【发布时间】:2020-10-19 15:43:57
【问题描述】:
我只是试图摆脱图像的透视,换句话说,我试图从 2D 图像中获取鸟瞰图像,以便轻松计算图像中两点之间的距离。此时,使用OpenCV的cv2.warpPerspective方法得到的结果图像需要一个最终图像的大小作为参数,该参数是未知的,应该静态给出,结果是扭曲图像的裁剪图像。所以我用 cv2.getPerspective 方法计算源图像的角点,并用这些点计算一个新的单应性。在用这个单应矩阵和已知的最终图像大小生成一个新的扭曲图像后,我得到了没有任何裁剪的完整图像。我的大部分经验都非常成功,但在某些示例中却失败了。
这是我正在做的事情:
- 从相机图像中获取现实世界中已知矩形的 4 个点(点的顺序为:TL(左上)-> TR(右上)-> BR(右下)-> BL(下左))
- 计算这些点的边界框,并将其设置为通过上述步骤获得的源点的目的地。
- 计算单应性,得到单应性矩阵。
- 使用此矩阵,计算源图像的角,以便能够知道结果图像(变形图像)的大小。
- 由于我知道源图像角点的结果坐标,我计算一个新的单应矩阵并生成已知大小的结果图像。
成功的尝试如下所示。橙色点是真实世界矩形的点,红色矩形是目标点。
下图是我用上面的步骤计算出来的结果,效果不错。(调整为大图)
获得的新角点位置一致:
TL:(-385, -308), TR:(1397, -326), BR:(906, 778), BL:(97, 776)
但是在尝试不同的示例时,我遇到了一些失败的情况,如下所示:
生成的新角点如下,似乎不正确:TL: (5415, 2218), TR: (-1314, 4309), BR: (909, 360), BL: (318,第551章)
顺便说一下,单应矩阵似乎完全正确。我测试了它,问题出在结果图像上。并且图像内部没有与这些点(称为消失点)相交的线,可能会导致这种结果图像。
我将保留源图像和代码 sn-p 以重现下面的结果。有一个小东西我俯瞰但找不到它 2 天。提前致谢
来源图片:grid image
代码:
import numpy as np
import cv2
import imutils
def warpImage(image, src_pts):
height, width = image.shape[:2]
min_rect = cv2.boundingRect(np.array(src_pts))
dst = [[min_rect[0], min_rect[1]],
[min_rect[0] + min_rect[2], min_rect[1]],
[min_rect[0] + min_rect[2], min_rect[1] + min_rect[3]],
[min_rect[0], min_rect[1] + min_rect[3]]]
corners = [[0, 0], [width-1, 0], [width-1, height-1], [0, height-1]]
src_np = np.float32(src_pts)
dst_np = np.float32(dst)
M = cv2.getPerspectiveTransform(src_np, dst_np)
ptsss = np.float32([corners]).reshape(-1, 1, 2)
scene_corners = cv2.perspectiveTransform(ptsss, M)
min_col, min_row = 50000, 50000
max_col, max_row = 0, 0
i = 0
for corner in scene_corners:
if corner[0][0] > max_col:
max_col = corner[0][0]
if corner[0][1] > max_row:
max_row = corner[0][1]
if corner[0][0] < min_col:
min_col = corner[0][0]
if corner[0][1] < min_row:
min_row = corner[0][1]
i += 1
new_dst = []
for corner in scene_corners:
pt = [int(corner[0][0] - min_col), int(corner[0][1] - min_row)]
new_dst.append(pt)
src2_np = np.float32(corners)
dst2_np = np.float32(new_dst)
M2 = cv2.getPerspectiveTransform(src2_np, dst2_np)
warped_image = cv2.warpPerspective(image, M2, (max_col - min_col, max_row - min_row))
return warped_image
img = cv2.imread("grid.png", 1)
img2 = img.copy()
# first one that works good
src1 = [[262, 129], [695, 130], [770, 350], [171, 352]]
cv2.circle(img, (src1[0][0], src1[0][1]), 3, (5, 140, 205), 3, 20)
cv2.circle(img, (src1[1][0], src1[1][1]), 3, (5, 140, 205), 3, 20)
cv2.circle(img, (src1[2][0], src1[2][1]), 3, (5, 140, 205), 3, 20)
cv2.circle(img, (src1[3][0], src1[3][1]), 3, (5, 140, 205), 3, 20)
cv2.imshow("img", img)
warped_img_1 = warpImage(img, src1)
warped_img_1_height, warped_img_1_width = warped_img_1.shape[:2]
if warped_img_1_width > warped_img_1_height:
warped_img_1 = imutils.resize(warped_img_1, width=800)
else:
warped_img_1 = imutils.resize(warped_img_1, height=800)
cv2.imshow("warped1", warped_img_1)
# second one that does not work
src2 = [[263, 260], [450, 302], [364, 394], [142, 321]]
cv2.circle(img2, (src2[0][0], src2[0][1]), 3, (5, 140, 205), 3, 20)
cv2.circle(img2, (src2[1][0], src2[1][1]), 3, (5, 140, 205), 3, 20)
cv2.circle(img2, (src2[2][0], src2[2][1]), 3, (5, 140, 205), 3, 20)
cv2.circle(img2, (src2[3][0], src2[3][1]), 3, (5, 140, 205), 3, 20)
cv2.imshow("img2", img2)
warped_img_2 = warpImage(img2, src2)
warped_img_2_height, warped_img_2_width = warped_img_2.shape[:2]
if warped_img_2_width > warped_img_2_height:
warped_img_2 = imutils.resize(warped_img_2, width=800)
else:
warped_img_2 = imutils.resize(warped_img_2, height=800)
cv2.imshow("warped2", warped_img_2)
cv2.waitKey()
【问题讨论】:
标签: python opencv perspective homography