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

Viv*_*nem 3 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)
Run Code Online (Sandbox Code Playgroud)

我得到的全球xy非常关闭.我在某处做错了吗?

alk*_*asm 7

答案很长

Homographies是3x3矩阵,点只是对,2x1所以没有办法将这些映射到一起.相反,使用齐次坐标,使3x1矢量相乘.但是,同一点可以在表示同一点时进行缩放; 也就是说,在齐次坐标中,(kx,ky,k)(x,y,1)是相同的点.从齐次坐标维基百科页面:

给定欧几里德平面上的点(x,y),对于任何非零实数Z,三元组(xZ,yZ,Z)被称为该点的一组齐次坐标.通过这个定义,将三个齐次坐标乘以一个共同的非零因子,为同一点提供一组新的齐次坐标.特别地,(x,y,1)是点(x,y)的均匀坐标系统.例如,笛卡尔点(1,2)可以在齐次坐标中表示为( 1,2,1 )(2,4,2).通过将前两个位置除以第三个位置来恢复原始笛卡尔坐标.因此,与笛卡尔坐标不同,单个点可以由无限多个齐次坐标表示.

显然,在笛卡尔坐标系中,这种缩放并不成立; 除非Z = 0Z = 1 ,否则(x,y)(xZ,yZ)不同.因此,我们需要一种方法来映射这些齐次坐标,这些坐标可以无限多种方式表示,直到笛卡尔坐标,只能用一种方式表示.幸运的是,这很简单,只需缩放齐次坐标,使三元组中的最后一个数字为1.

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

简短的回答

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

sx'       x
sy' = H * y
s         1
Run Code Online (Sandbox Code Playgroud)

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

答案越短

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