【问题标题】:cv2.perspectiveTransform() not accepting homography matrixcv2.perspectiveTransform() 不接受单应矩阵
【发布时间】:2018-02-13 06:06:06
【问题描述】:

下面是bookhomography-example-1.jpg,然后是bookhomography-example-2.jpg,来自popular OpenCV blogpost,关于单应性。

我可以进行单应性和扭曲图像,但是当我尝试使用 cv2.perspectiveTransform(pts, h)cv2.perspectiveTransform(pts, h[0]) 时,hh[0] 不起作用。我还尝试将二维数组h[0] 转换为元组的元组,但没有变化。这可能很简单,但我想不通。

错误信息:

Traceback(最近一次通话最后一次):

文件“bookhomography stackexchange v00.py”,第 36 行,在 T_dst = cv2.perspectiveTransform(pts_dst, h) TypeError: m is not a numeric tuple

注意:False 设置为True 以诱导失败。两条变换线之一是错误的方向,但都失败了。

import numpy as np
import matplotlib.pyplot as plt
import cv2

im_src = cv2.imread("bookhomography-example-2.jpg")
im_dst = cv2.imread("bookhomography-example-1.jpg")

im_srcrgb = cv2.cvtColor(im_src, cv2.COLOR_BGR2RGB)
im_dstrgb = cv2.cvtColor(im_dst, cv2.COLOR_BGR2RGB)

pts_src = np.float32([52, 376, 240, 528, 413, 291, 217, 266]).reshape(4, -1)
pts_dst = np.float32([56, 478, 387, 497, 376, 124, 148, 218]).reshape(4, -1)

h       = cv2.findHomography(pts_src, pts_dst)

print "type(h): ", type(h)
print "len(h): ", len(h)

print "type(h[0]): ", type(h[0])
print "len(h[0]): ", len(h[0])
print "h[0].shape: ", h[0].shape

shape   = im_src.shape[:2][::-1]

print h[0]

print "pts_src:"
print pts_src

print "pts_dst:"
print pts_dst

if False:
    T_dst = cv2.perspectiveTransform(pts_dst, h)
    T_src = cv2.perspectiveTransform(pts_src, h)

    print "T_src:"
    print T_src

    print "T_dst:"
    print T_dst

im_fin  = cv2.warpPerspective(im_src, h[0], shape)
im_finrgb  = cv2.cvtColor(im_fin, cv2.COLOR_BGR2RGB)

plt.figure()
plt.subplot(1, 3, 1)
plt.imshow(im_srcrgb)
x, y = pts_src.T
plt.plot(x, y, 'or', ms=8)
plt.subplot(1, 3, 2)
plt.imshow(im_dstrgb)
x, y = pts_dst.T
plt.plot(x, y, 'or', ms=8)
plt.subplot(1, 3, 3)
plt.imshow(im_finrgb)
x, y = pts_dst.T
plt.plot(x, y, 'or', ms=8)
plt.show()

【问题讨论】:

  • 我以为有一个问题:“我可以进行单应性和扭曲图像,但是当我尝试使用 cv2.perspectiveTransform(pts, h)cv2.perspectiveTransform(pts, h[0]) 时,hh[0] 不起作用。” 注意:False 设置为True 以诱导失败。
  • 当您在perspectiveTransform() 中使用hh[0] 时会出现不同的错误消息,因此您应该同时包含这两个。
  • @AlexanderReynolds 好的,我现在就检查一下,以及另一个问题;再给我大约 10 分钟,谢谢!
  • 别担心,我已经回答了。我只是让你知道:)

标签: python-2.7 opencv cv2


【解决方案1】:

请参阅我的回答 here 以获得快速修复。 TL:博士; OpenCV 函数 perspectiveTransform() 采用以奇数格式指定的点,而 findHomography() 使用您拥有的格式。


首先注意findHomography()返回两个值;单应矩阵和mask。来自docs

cv2.findHomography(srcPoints, dstPoints[, method[, ransacReprojThreshold[, mask]]]) → retval, mask

第二个返回值不是单应性,因此为什么应该使用h[0]。或者你可以写:

h, mask = cv2.findHomography(srcPoints, dstPoints)

h = cv2.findHomography(srcPoints, dstPoints)[0]

以便h 持有单应性以减少混淆。请注意,使用您指定的 hh[0] 会给您不同的错误消息:

使用h:

>>> T_dst = cv2.perspectiveTransform(pts_dst, h)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: m is not a numerical tuple

使用h[0]

>>> T_dst = cv2.perspectiveTransform(pts_dst, h[0])
OpenCV Error: Assertion failed (scn + 1 == m.cols) in perspectiveTransform, file .../opencv/modules/core/src/matmul.cpp, line 2299
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
cv2.error: .../opencv/modules/core/src/matmul.cpp:2299: error: (-215) scn + 1 == m.cols in function perspectiveTransform

不幸的是,这里的错误消息对您并没有真正的帮助,因为实际的问题是指定点的方式。这在技术上是用户错误,但文档(和函数本身)可能应该更改。


无论如何,解决方法:将频道添加到您的 pts 向量中。看看区别:

>>> np.float32([52, 376, 240, 528, 413, 291, 217, 266]).reshape(4, -1)
array([[  52.,  376.],
       [ 240.,  528.],
       [ 413.,  291.],
       [ 217.,  266.]], dtype=float32)
>>> np.float32([52, 376, 240, 528, 413, 291, 217, 266]).reshape(4, 1, -1)
array([[[  52.,  376.]],

       [[ 240.,  528.]],

       [[ 413.,  291.]],

       [[ 217.,  266.]]], dtype=float32)

幸运的是,findHomography() 也可以使用这种格式,因此您不必根据所使用的功能使用两种不同的格式。为了安全起见,对于 OpenCV 函数,请始终以这种格式放置点。

>>> pts_src = np.float32([52, 376, 240, 528, 413, 291, 217, 266]).reshape(4, 1, -1)
>>> pts_dst = np.float32([56, 478, 387, 497, 376, 124, 148, 218]).reshape(4, 1, -1)
>>> h = cv2.findHomography(pts_src, pts_dst)[0]
>>> T_dst = cv2.perspectiveTransform(pts_dst, h)
>>> T_src = cv2.perspectiveTransform(pts_src, h)
>>> T_src
array([[[  56.,  478.]],

       [[ 387.,  497.]],

       [[ 376.,  124.]],

       [[ 148.,  218.]]], dtype=float32)
>>> T_dst
array([[[ 157.78089905,  588.9598999 ]],

       [[ 495.96539307,  365.68994141]],

       [[ 200.45231628,  -69.54611206]],

       [[  15.72697926,  204.0632019 ]]], dtype=float32)

以上没有错误。

【讨论】:

  • 伊皮!好的,我完全理解你的解释,谢谢你花时间把它说得这么清楚。事实上,我现在得到了数字,应该正确的数字确实是正确的 - 反向转换有效。
  • 您认为这应该与其他问答重复,还是保持原样?
  • 嗯,问题和解决方案是重复的,但您的标题可能会在搜索中出现更多。社区应该决定,但 OpenCV 标签没有很多用户,所以我们会看看它是否会被标记为骗子。
  • @AlexanderReynolds 标记为重复的问题不会自动删除。由于您给出的原因,它们被保留为重复项,因此更多的搜索词将导致正确的答案。我会继续并建议将此作为您链接的问题的副本。
  • 刚才让我很困惑,这是我找到的最清晰的答案,也是我找到的使用这两个功能的最佳示例之一。 (- 谢谢!)我强烈支持保留这个答案将其中的至少一部分移到 OpenCV Python 文档/教程中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-18
  • 2019-07-30
  • 1970-01-01
  • 2019-12-16
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
相关资源
最近更新 更多