【问题标题】:trouble getting cv.transform to work无法让 cv.transform 正常工作
【发布时间】:2017-11-06 18:25:08
【问题描述】:

我想在某些单独的 (x,y) 点上使用与使用 cv2.warpAffine 的图像相同的仿射矩阵 M。看来 cv2.transform 是要走的路。当我尝试发送一个 Nx2 点矩阵时,我被否定了(

   src = np.array([
        [x1,y1],[x2,y2],[x3,y3],[x4,y4]],  dtype = "float32")
    print('source shape '+str(src.shape))
    dst=cv2.transform(src,M)

cv2.error: /home/jeremy/sw/opencv-3.1.0/modules/core/src/matmul.cpp:1947: error: (-215) scn == m.cols || scn + 1 == m.cols in function transform

我可以使用 numpy 算术得到我想要的转换:

    dst = np.dot(src,M[:,0:2]) +M[:,2]
    print('dest:{}'.format(dst))

但想了解发生了什么。文档说 cv2.transform 想要的通道数等于 M 中的列数,但我不清楚通道是什么 - 可能是“x”通道和“y”通道,但第三个通道会是,不同的行表示什么?

【问题讨论】:

  • OpenCV 通常会以np.array([ [[x1, y1]], [[x2, y2]], ... ]) 的形式期望他们喜欢的点。他们通常希望将其用于点变换——单个列或行向量,其长度为点数,通道数等于坐标数。第三个坐标可以是三维坐标——变换矩阵毕竟不只是用于二维变换。
  • 谢谢你成功了,我在心里把维度顺序倒过来了,chw 而不是 hwc,caffe 太多了跨度>
  • 与问题本身无关,但 numpy 等效代码可以正常运行,但不是您想要的正确转换。 cv2.transform 的 numpy 等效值为 (np.dot(M[:,:2], a.T)+M[:,2].reshape(2,1)).T

标签: python opencv numpy affinetransform


【解决方案1】:

Python 上的 OpenCV 经常需要表单中的点

np.array([ [[x1, y1]], ..., [[xn, yn]] ])

这在documentation for cv2.transform() 中并不清楚,但在使用点的其他函数的文档中更清楚,例如cv2.perspectiveTransform(),他们提到坐标位于不同的通道上:

src – 输入两通道或三通道浮点数组

变换也可以在 3D 中使用(使用 4x4 透视变换矩阵),因此可以解释在 cv2.transform() 中使用两个三通道数组的能力。

【讨论】:

  • 对于上述用例(点的 Nx2 矩阵的 2D 变换),一种简写是 dst = cv2.transform( np.array([src]),M)[0]
【解决方案2】:

通道是源数组的最后一个维度。让我们阅读开头的 cv2.transform() 的文档。


问题

由于该函数是从参数src中转换每个元素,所以src的维度需要大于2。

import cv2
import numpy as np

rotation_mat = np.array([[0.8660254, 0.5, -216.41978046], [-0.5, 0.8660254, 264.31038357]]) # 2x3

rotate_box = np.array([[410, 495], [756, 295], [956, 642], [610, 842]]) # 2x2
result_box = cv2.transform(rotate_box, rotation_mat) # error: (-215:Assertion failed) scn == m.cols || scn + 1 == m.cols in function 'transform'

原因是rotate_box每个元素的维度是(2,)。无法进行矩阵乘法变换。

换一个答案: 只要最后一个维度合适,其他维度都无所谓。继续上面的sn-p:

rotate_box_1 = np.array([rotate_box]) # 1x4x2
result_box = cv2.transform(rotate_box_1, rotation_mat) # 1x4x2

rotate_box_2 = np.array([[[410, 495]], [[756, 295]], [[956, 642]], [[610, 842]]]) # 4x1x2
result_box = cv2.transform(rotate_box_2, rotation_mat) # 4x1x2

致读者: 请注意cv2.transform() 返回的形状与src 相同。

【讨论】:

    猜你喜欢
    • 2012-09-05
    • 2011-09-06
    • 1970-01-01
    • 2023-03-10
    • 2020-10-16
    • 2014-01-15
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多