【问题标题】:Opencv homography to find global xy coordinates from pixel xy coordinatesOpencv单应性从像素xy坐标中找到全局xy坐标
【发布时间】:2017-11-18 14:51:15
【问题描述】:

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

【问题讨论】:

  • 抱歉,D,I,G,A,O,X,P,Y 的变量是什么?这些应该代表什么?无论如何,在您计算“真实世界”(x,y) 坐标的地方,您将得到 homogenous 点,它们在缩放时是等效的——换句话说,它们可能会被缩放并且仍然是认为同一点。但是您需要x,y 点,而不是缩放点,因此您需要除以比例。三向量都按相同的量缩放,因此您可以使用最后一个条目作为缩放因子。你应该先pts = scale*np.dot(h,np.array([[323.0],[120.0],[1.0]])) 然后pts = pts/pts[-1]。
  • OXPY 是真实的字点(O 原点,右侧 X-134 英寸,右侧 P-134 英寸和向下 184 英寸,向下 Y-184 英寸)和 DIGA 是各自的像素图像平面上的坐标。
  • 对不起。我没有完全理解缩放部分。
  • 我想我明白你的意思了。让我检查一下我是否得到了正确的值。
  • 快速试用代码,看看它是否能解决您的问题——如果能,我会添加更详细的答案。基本上,[x', y', 1] = H*[x, y, 1] 是不正确的;它是[sx', sy', s] = H*[x, y, 1]。但是你需要以1结尾的齐次点等于x,y坐标,所以你需要从齐次坐标中除以s。

标签: python opencv homography


【解决方案1】:

长答案

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。

单应性乘以齐次坐标并返回齐次坐标。所以为了将它们映射回笛卡尔世界,你只需要除以最后一个坐标来缩放它们,然后去掉前两个数字。

简短的回答

当你将齐次坐标乘以一个单应性时,你需要对它们进行缩放:

sx'       x
sy' = H * y
s         1

所以要回到笛卡尔坐标,用新的齐次坐标除以s:(sx', sy', s)/s = (x', y', 1) 然后 (x', y') 是你想要的点。

简短的答案

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

【讨论】:

    【解决方案2】:
        # 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
    

    【讨论】:

    • 刚试过这个答案,很有帮助,更正的版本是def toworld(x,y):imagepoint = [x, y, 1];worldpoint = np.array(np.dot(inversehomographymatrix,imagepoint));scalar = worldpoint[2];xworld = worldpoint[0]/scalar;yworld = worldpoint[1]/scalar;return xworld, yworld
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    相关资源
    最近更新 更多