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

时间:2017-06-16 00:13:31

标签: python opencv homography

我试图找到变换矩阵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非常关闭。我在某处做错了吗?

2 个答案:

答案 0 :(得分:6)

答案很长

Homographies是3x3矩阵,而点只是成对,2x1,所以没有办法将这些映射到一起。相反,使用齐次坐标,使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 。因此,我们需要一种方法来映射这些齐次坐标,这些坐标可以无限多种方式表示,直到笛卡尔坐标,只能用一种方式表示。幸运的是,这很简单,只需缩放齐次坐标,使三元组中的最后一个数字 1

Homographies乘以齐次坐标并返回齐次坐标。因此,为了将它们映射回笛卡尔世界,您只需要除以最后一个坐标来缩放它们,然后将前两个数字翻出来。

简答

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

sx'       x
sy' = H * y
s         1

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

答案较短

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

答案 1 :(得分:0)

    # 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