Opencv单应性从像素xy坐标中找到全局xy坐标

mwecs4sa  于 2023-06-24  发布在  其他
关注(0)|答案(2)|浏览(154)

我试图找到变换矩阵H,以便我可以乘以(x,y)像素坐标并获得(x,y)真实世界坐标。下面是我的代码:

import cv2
import numpy as np
from numpy.linalg import inv
if __name__ == '__main__' :
D=[159.1,34.2]
I=[497.3,37.5]
G=[639.3,479.7]
A=[0,478.2]
# Read source image.
im_src = cv2.imread('/home/vivek/june_14.png')
# Four corners of the book in source image
pts_src = np.array([D,I,G,A])

# Read destination image.
im_dst = cv2.imread('/home/vivek/june_14.png')

# Four corners of the book in destination image.
print "img1 shape:",im_dst.shape
scale=1
O=[0.0,0.0]
X=[134.0*scale,0]
Y=[0.0,184.0*scale]
P=[134.0*scale,184.0*scale]
# lx = 75.5 * scale
# ly = 154.0 * scale
pts_dst = np.array([O,X,P,Y])

# Calculate Homography
h, status = cv2.findHomography(pts_src, pts_dst)

print "homography:",h
print "inv of H:",inv(h)
print "position of the blob on the ground xy plane:",np.dot(np.dot(h,np.array([[323.0],[120.0],[1.0]])),scale)

# Warp source image to destination based on homography

im_out = cv2.warpPerspective(im_src, h, (im_dst.shape[1],im_dst.shape[0]))

# Display images
cv2.imshow("Source Image", im_src)
cv2.imshow("Destination Image", im_dst)
cv2.imshow("Warped Source Image", im_out)
cv2.imwrite("im_out.jpg", im_out)
cv2.waitKey(0)

我得到的全局xy非常不对劲。我在哪里做错了吗?

z31licg0

z31licg01#

冗长的答案

同应性是3x3矩阵,点是对,2x1,所以没有办法把它们Map到一起。相反,使用齐次坐标,给出3x1向量相乘。然而,同质点可以在表示相同点的同时被缩放;也就是说,在齐次坐标中,(kx,ky,k)(x,y,1) 是同一点。关于Wikipedia page on homogeneous coordinates
给定欧几里得平面上的一个点 (x,y),对于任何非零实数 * Z ,三元组 (xZ,yZ,Z) 被称为该点的齐次坐标集。根据该定义,将三个齐次坐标乘以公共的非零因子给出同一点的一组新的齐次坐标。特别地,(x,y,1)* 是点 (x,y) 的齐次坐标系。例如,笛卡尔点 (1,2) 可以在齐次坐标中表示为 (1,2,1)(2,4,2)。通过将前两个位置除以第三个位置来恢复原始笛卡尔坐标。因此,与笛卡尔坐标不同,一个点可以由无限多个齐次坐标表示。
显然,在笛卡尔坐标系中,这种比例并不成立;* (x,y)* 与 (xZ,yZ) 不是同一个点,除非 * Z = 0 * 或 * Z = 1 *。所以我们需要一种方法来Map这些齐次坐标,可以用无数种方式来表示,到笛卡尔坐标,只能用一种方式来表示。幸运的是,这非常简单,只需缩放齐次坐标,使三元组中的最后一个数字是 * 1 *。
单应性将齐次坐标相乘并返回齐次坐标。所以为了将它们Map回笛卡尔世界,你只需要除以最后一个坐标来缩放它们,然后去掉前两个数字。

简短的回答

当将齐次坐标乘以单应性时,需要缩放它们:

sx'       x
sy' = H * y
s         1

因此,为了回到笛卡尔坐标,将新的齐次坐标除以 * s (sx',sy',s)/s =(x',y',1)* 然后 (x',y') 就是你想要的点。

简短的回答

使用内置的OpenCV函数convertPointsFromHomogeneous()将点从齐次3-向量转换为笛卡尔2-向量。

t98cgbkg

t98cgbkg2#

# convert to world coordinates
    def toworld(x,y):
        imagepoint = [x, y, 1]
        worldpoint = np.array(np.dot(inversehomographymatrix,imagepoint))
        scalar = worldpoint[0,2]
        xworld = int((worldpoint[0][0]/scalar)*10 +p.x_buffer_width*10)
        yworld = int((worldpoint[0][1]/scalar)*10 +p.y_buffer_width*10) #in 10demm 
        return xworld, yworld

相关问题