微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何确定在cv2.getPerspectiveTransform中应该给出的点?

如何解决如何确定在cv2.getPerspectiveTransform中应该给出的点?

我正在尝试对以下图像进行变形,以便获得大墙的正面平行视图,该大墙位于图像的左侧。但是,我无法决定应在函数cv2.getPerspectiveTransform()中给出哪些点,这样我就可以得到矩阵,如果应用该矩阵将产生期望的结果。

the input image

我使用的代码是:

import cv2
import numpy as np

circles = np.zeros((4,2),np.int)
counter = 0

def mousePoints(event,x,y,flags,params):
    global counter
    if event == cv2.EVENT_LBUTTONDOWN:

        circles[counter] = x,y
        counter = counter + 1
        print(circles)

img = cv2.imread("DSC_0273.JPG")

img = cv2.resize(img,(1500,1000))
q = 0
while True:

    if counter == 4:
        q = q+1

        height1,width1 = 1080,1920
        pts1 = np.float32([circles[0],circles[1],circles[2],circles[3]])
        width = np.sqrt((circles[1][0] - circles[0][0])**2 + (circles[1][1] - circles[0][1])**2)
        height =  np.sqrt((circles[2][1] - circles[0][1])**2 + (circles[2][0] - circles[0][0])**2)
        width = int(np.round(width))
        height = int(np.round(height))
        x1,y1 = circles[0]
    
        pts2 = np.float32([[x1,y1],[(x1+width),(y1+height)],[x1,(y1+height)]])
        matrix = cv2.getPerspectiveTransform(pts1,pts2)

        if q == 1:
            print(matrix.shape)
            print(matrix)
        imgOutput = cv2.warpPerspective(img,matrix,(width1,height1))
        cv2.imshow("Output Image ",imgOutput)


for x in range (0,4):
    cv2.circle(img,(circles[x][0],circles[x][1]),3,(0,255,0),cv2.FILLED)

cv2.imshow("Original Image ",img)
cv2.setMouseCallback("Original Image ",mousePoints)
cv2.waitKey(1)

因此,基本上,我单击4个点,我的代码将找到变形矩阵,以便将这4个点中包含的区域映射到一个矩形,这样我给出的第一个点将映射到相同的像素位置,并且调整其他4个点,使包围的部分变成矩形。为了推断这一点,我在整个图像上应用了相同的矩阵。 我尝试的一组要点(通过鼠标单击给出的4个要点)是: [[349,445],[396,415],[388,596],[338,610]] 我得到的结果是:

The output image

解决方法

我无法使您的代码正常工作,坦率地说,当所讨论的代码不是最小的可重现示例时,这是一个真正的痛苦,因为我对这个问题感兴趣,所以我坚持不懈-我不明白您的代码如何应该收集四次鼠标单击,然后处理透视图,但是您的缩进是垃圾。

每次运行都必须点击分数的一个问题是很难获得可比的运行-因此,我只收集了一次点击,然后使用这些点击来进行检查。

我遇到的一个问题是点击的顺序。 AFAICT进行工作变换的正确顺序是左上,右上,左下,右下。令人困惑的是,您在问题中列出的分数顺序不是按此顺序排列的。我必须交换pts2中的最后两个值以对应正确的顺序。也许两个交换可以互相补偿,我力不从心地猜测您的无效代码。

您的观点相对接近-我认为随着传播点的扩大,您将获得更好的结果。注意“更好”而不是“完美”-我认为您尝试做的事情没有“完美”,因为透视畸变非常大,并且WarpPerspective无法神奇地重新投影图像的不同深度。 / p>

将输出与输入进行比较也很困难,因为单击位置在输入或输出上不可见。

我不确定的另一件事是,如果1500宽乘1000高,则调整我下载的寺庙的源图像的大小。忽略这个。

说了这么多,我认为您所得到的几乎就是您应该得到的。是的,它是非常扭曲的,但是翘曲透视图是一个简单的2D操作,不需要声明会造成镜头失真的重新投影。

这是我的代码的简化版本,它使用四个固定点-转换前已将它们覆盖在源图像上,因此它们在输出图像中可见-您还可以在输入图像上覆盖网格线,然后查看这些看起来像在输出图像中。是的,输出确实包含四个绿点,由于转换,右侧的两个非常小。例如,您可以检查一下弓的尖端是否对齐-显然其中的3D内容看起来很奇怪,但是正如我说的那样,没有魔杖。

import cv2
import numpy as np

circles = np.zeros((4,2),np.int)

circles = [(349,473),(903,158),(336,713),(918,758) ]

img = cv2.imread("temple.JPG")

for x in range (0,4):
    cv2.circle(img,(circles[x][0],circles[x][1]),3,(0,255,0),cv2.FILLED)

cv2.imshow("Original Image ",img)

cv2.waitKey(-1)
    
height1,width1 = 1080,1920

pts1 = np.float32([circles[0],circles[1],circles[2],circles[3]])
width = np.sqrt((circles[1][0] - circles[0][0])**2 + (circles[1][1] - circles[0][1])**2)
height =  np.sqrt((circles[2][1] - circles[0][1])**2 + (circles[2][0] - circles[0][0])**2)
width = int(np.round(width))
height = int(np.round(height))
x1,y1 = circles[0]

print( f"{x1=} {y1=} {width=} {height=}")

# NOTE the third and fourth values are swapped from the original code
pts2 = np.float32([[x1,y1],[(x1+width),[x1,(y1+height)],(y1+height)]])
matrix = cv2.getPerspectiveTransform(pts1,pts2)

print(matrix.shape)
print(matrix)

imgOutput = cv2.warpPerspective(img,matrix,(width1,height1))
cv2.imshow("Output Image ",imgOutput)

cv2.waitKey(-1)

输入点重叠的输入图像:

full input image with green dots on selected points

输出图像的裁剪部分:

cropper part of output image

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。