1

我正在尝试为一种算法制作一个原型,以找到一个球在盘子上的坐标,我想让它尽可能高效,因为我必须在 FPGA 中实现它。球和盘子的图片并不总是在同一方向,所以我需要根据盘子角的坐标移动球中心的坐标。

要理解我的意思,请参见下图,其中白纸代表盘子。

在此处输入图像描述

现在我已经找到了一种方法来确定球在图片上的坐标,以及图片中盘子的角坐标,但是我想找出球在盘子上的位置。

我尝试用 getPerspectiveTransform() 和 wrapPerspective() 做一些事情并且它起作用了,但这涉及大量矩阵计算,我认为当我只想移动一个像素的坐标时这有点矫枉过正(中心球)。

您知道如何确定球在板上的中心像素坐标的更有效方法吗?

4

2 回答 2

0

我通过使用下面帖子的 morotspaj 和 Matlab 的答案解决了这个问题。

在MATLAB中从4个点计算一个2D齐次透视变换矩阵

ui 和 vi 是已知的(它们等于图片的分辨率),所以我将它们填充到 8x8 矩阵中并得到以下结果:

/ x0 y0  1  0  0  0     0          0    \ /m00\ /  0  \
| x1 y1  1  0  0  0 -x1*RES_H -y1*RES_H | |m01| |RES_H|
| x2 y2  1  0  0  0     0          0    | |m02| |  0  |
| x3 y3  1  0  0  0 -x3*RES_H -y3*RES_H |.|m10|=|RES_H|
|  0  0  0 x0 y0  1     0          0    | |m11| |  0  |
|  0  0  0 x1 y1  1     0          0    | |m12| |  0  |
|  0  0  0 x2 y2  1 -x2*RES_V -y2*RES_V | |m20| |RES_V|
\  0  0  0 x3 y3  1 -x3*RES_V -y3*RES_V / \m21/ \RES_V/

其中 RES_H = (640 - 1) 和 RES_V = (480 - 1)。这个方程可以看作是Ax = b。我将A矩阵 (8x8) 和b向量 (8x1) 放入 Matlab 并使用 linsolve( A , b ) 求解线性系统:

syms x0 x1 x2 x3 y0 y1 y2 y3 RES_H RES_V;
A = [ x0 y0 1 0 0 0 0 0 ; x1 y1 1 0 0 0 -x1*RES_H -y1*RES_H ; x2 y2 1 0 0 0 0 0 ; x3 y3 1  0 0 0 -x3*RES_H -y3*RES_H ; 0 0 0 x0 y0 1 0 0 ; 0 0 0 x1 y1 1 0 0 ; 0 0 0 x2 y2 1 -x2*RES_V -y2*RES_V ; 0 0 0 x3 y3 1 -x3*RES_V -y3*RES_V ];
b = [ 0 ; RES_H ; 0 ; RES_H ; 0 ; 0 ; RES_V ; RES_V ];
simplify(linsolve(A,B))

结果如下:

m00 = -(RES_H*(y0 - y2)*(x0*y1 - x1*y0 - x0*y3 + x3*y0 + x1*y3 - x3*y1)*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2))/(- x0*x0*x1*y1*y2*y2 + 2*x0*x0*x1*y1*y2*y3 - x0*x0*x1*y1*y3*y3 + x0*x0*x2*y1*y1*y2 - 2*x0*x0*x2*y1*y2*y3 + x0*x0*x2*y2*y3*y3 - 2*x0*x0*x3*y1*y1*y2 + x0*x0*x3*y1*y1*y3 + 2*x0*x0*x3*y1*y2*y2 - x0*x0*x3*y2*y2*y3 + x0*x1*x1*y0*y2*y2 - 2*x0*x1*x1*y0*y2*y3 + x0*x1*x1*y0*y3*y3 - 2*x0*x1*x2*y0*y1*y3 + 2*x0*x1*x2*y0*y2*y3 + 2*x0*x1*x2*y1*y3*y3 - 2*x0*x1*x2*y2*y3*y3 + 2*x0*x1*x3*y0*y1*y2 - 2*x0*x1*x3*y0*y2*y2 - 2*x0*x1*x3*y1*y2*y3 + 2*x0*x1*x3*y2*y2*y3 - x0*x2*x2*y0*y1*y1 + 2*x0*x2*x2*y0*y1*y3 - x0*x2*x2*y0*y3*y3 + 2*x0*x2*x3*y0*y1*y1 - 2*x0*x2*x3*y0*y1*y2 - 2*x0*x2*x3*y1*y1*y3 + 2*x0*x2*x3*y1*y2*y3 - x0*x3*x3*y0*y1*y1 + x0*x3*x3*y0*y2*y2 + 2*x0*x3*x3*y1*y1*y2 - 2*x0*x3*x3*y1*y2*y2 - x1*x1*x2*y0*y0*y2 + 2*x1*x1*x2*y0*y0*y3 - 2*x1*x1*x2*y0*y3*y3 + x1*x1*x2*y2*y3*y3 - x1*x1*x3*y0*y0*y3 + 2*x1*x1*x3*y0*y2*y3 - x1*x1*x3*y2*y2*y3 + x1*x2*x2*y0*y0*y1 - 2*x1*x2*x2*y0*y0*y3 + 2*x1*x2*x2*y0*y3*y3 - x1*x2*x2*y1*y3*y3 - 2*x1*x2*x3*y0*y0*y1 + 2*x1*x2*x3*y0*y0*y2 + 2*x1*x2*x3*y0*y1*y3 - 2*x1*x2*x3*y0*y2*y3 + x1*x3*x3*y0*y0*y1 - 2*x1*x3*x3*y0*y1*y2 + x1*x3*x3*y1*y2*y2 + x2*x2*x3*y0*y0*y3 - 2*x2*x2*x3*y0*y1*y3 + x2*x2*x3*y1*y1*y3 - x2*x3*x3*y0*y0*y2 + 2*x2*x3*x3*y0*y1*y2 - x2*x3*x3*y1*y1*y2);
m01 = (RES_H*(x0 - x2)*(x0*y1 - x1*y0 - x0*y3 + x3*y0 + x1*y3 - x3*y1)*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2))/(- x0*x0*x1*y1*y2*y2 + 2*x0*x0*x1*y1*y2*y3 - x0*x0*x1*y1*y3*y3 + x0*x0*x2*y1*y1*y2 - 2*x0*x0*x2*y1*y2*y3 + x0*x0*x2*y2*y3*y3 - 2*x0*x0*x3*y1*y1*y2 + x0*x0*x3*y1*y1*y3 + 2*x0*x0*x3*y1*y2*y2 - x0*x0*x3*y2*y2*y3 + x0*x1*x1*y0*y2*y2 - 2*x0*x1*x1*y0*y2*y3 + x0*x1*x1*y0*y3*y3 - 2*x0*x1*x2*y0*y1*y3 + 2*x0*x1*x2*y0*y2*y3 + 2*x0*x1*x2*y1*y3*y3 - 2*x0*x1*x2*y2*y3*y3 + 2*x0*x1*x3*y0*y1*y2 - 2*x0*x1*x3*y0*y2*y2 - 2*x0*x1*x3*y1*y2*y3 + 2*x0*x1*x3*y2*y2*y3 - x0*x2*x2*y0*y1*y1 + 2*x0*x2*x2*y0*y1*y3 - x0*x2*x2*y0*y3*y3 + 2*x0*x2*x3*y0*y1*y1 - 2*x0*x2*x3*y0*y1*y2 - 2*x0*x2*x3*y1*y1*y3 + 2*x0*x2*x3*y1*y2*y3 - x0*x3*x3*y0*y1*y1 + x0*x3*x3*y0*y2*y2 + 2*x0*x3*x3*y1*y1*y2 - 2*x0*x3*x3*y1*y2*y2 - x1*x1*x2*y0*y0*y2 + 2*x1*x1*x2*y0*y0*y3 - 2*x1*x1*x2*y0*y3*y3 + x1*x1*x2*y2*y3*y3 - x1*x1*x3*y0*y0*y3 + 2*x1*x1*x3*y0*y2*y3 - x1*x1*x3*y2*y2*y3 + x1*x2*x2*y0*y0*y1 - 2*x1*x2*x2*y0*y0*y3 + 2*x1*x2*x2*y0*y3*y3 - x1*x2*x2*y1*y3*y3 - 2*x1*x2*x3*y0*y0*y1 + 2*x1*x2*x3*y0*y0*y2 + 2*x1*x2*x3*y0*y1*y3 - 2*x1*x2*x3*y0*y2*y3 + x1*x3*x3*y0*y0*y1 - 2*x1*x3*x3*y0*y1*y2 + x1*x3*x3*y1*y2*y2 + x2*x2*x3*y0*y0*y3 - 2*x2*x2*x3*y0*y1*y3 + x2*x2*x3*y1*y1*y3 - x2*x3*x3*y0*y0*y2 + 2*x2*x3*x3*y0*y1*y2 - x2*x3*x3*y1*y1*y2);
m02 = -(RES_H*(x0*y2 - x2*y0)*(x0*y1 - x1*y0 - x0*y3 + x3*y0 + x1*y3 - x3*y1)*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2))/(- x0*x0*x1*y1*y2*y2 + 2*x0*x0*x1*y1*y2*y3 - x0*x0*x1*y1*y3*y3 + x0*x0*x2*y1*y1*y2 - 2*x0*x0*x2*y1*y2*y3 + x0*x0*x2*y2*y3*y3 - 2*x0*x0*x3*y1*y1*y2 + x0*x0*x3*y1*y1*y3 + 2*x0*x0*x3*y1*y2*y2 - x0*x0*x3*y2*y2*y3 + x0*x1*x1*y0*y2*y2 - 2*x0*x1*x1*y0*y2*y3 + x0*x1*x1*y0*y3*y3 - 2*x0*x1*x2*y0*y1*y3 + 2*x0*x1*x2*y0*y2*y3 + 2*x0*x1*x2*y1*y3*y3 - 2*x0*x1*x2*y2*y3*y3 + 2*x0*x1*x3*y0*y1*y2 - 2*x0*x1*x3*y0*y2*y2 - 2*x0*x1*x3*y1*y2*y3 + 2*x0*x1*x3*y2*y2*y3 - x0*x2*x2*y0*y1*y1 + 2*x0*x2*x2*y0*y1*y3 - x0*x2*x2*y0*y3*y3 + 2*x0*x2*x3*y0*y1*y1 - 2*x0*x2*x3*y0*y1*y2 - 2*x0*x2*x3*y1*y1*y3 + 2*x0*x2*x3*y1*y2*y3 - x0*x3*x3*y0*y1*y1 + x0*x3*x3*y0*y2*y2 + 2*x0*x3*x3*y1*y1*y2 - 2*x0*x3*x3*y1*y2*y2 - x1*x1*x2*y0*y0*y2 + 2*x1*x1*x2*y0*y0*y3 - 2*x1*x1*x2*y0*y3*y3 + x1*x1*x2*y2*y3*y3 - x1*x1*x3*y0*y0*y3 + 2*x1*x1*x3*y0*y2*y3 - x1*x1*x3*y2*y2*y3 + x1*x2*x2*y0*y0*y1 - 2*x1*x2*x2*y0*y0*y3 + 2*x1*x2*x2*y0*y3*y3 - x1*x2*x2*y1*y3*y3 - 2*x1*x2*x3*y0*y0*y1 + 2*x1*x2*x3*y0*y0*y2 + 2*x1*x2*x3*y0*y1*y3 - 2*x1*x2*x3*y0*y2*y3 + x1*x3*x3*y0*y0*y1 - 2*x1*x3*x3*y0*y1*y2 + x1*x3*x3*y1*y2*y2 + x2*x2*x3*y0*y0*y3 - 2*x2*x2*x3*y0*y1*y3 + x2*x2*x3*y1*y1*y3 - x2*x3*x3*y0*y0*y2 + 2*x2*x3*x3*y0*y1*y2 - x2*x3*x3*y1*y1*y2);
m10 = -(RES_V*(y0 - y1)*(x0*y2 - x2*y0 - x0*y3 + x3*y0 + x2*y3 - x3*y2)*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2))/(- x0*x0*x1*y1*y2*y2 + 2*x0*x0*x1*y1*y2*y3 - x0*x0*x1*y1*y3*y3 + x0*x0*x2*y1*y1*y2 - 2*x0*x0*x2*y1*y2*y3 + x0*x0*x2*y2*y3*y3 - 2*x0*x0*x3*y1*y1*y2 + x0*x0*x3*y1*y1*y3 + 2*x0*x0*x3*y1*y2*y2 - x0*x0*x3*y2*y2*y3 + x0*x1*x1*y0*y2*y2 - 2*x0*x1*x1*y0*y2*y3 + x0*x1*x1*y0*y3*y3 - 2*x0*x1*x2*y0*y1*y3 + 2*x0*x1*x2*y0*y2*y3 + 2*x0*x1*x2*y1*y3*y3 - 2*x0*x1*x2*y2*y3*y3 + 2*x0*x1*x3*y0*y1*y2 - 2*x0*x1*x3*y0*y2*y2 - 2*x0*x1*x3*y1*y2*y3 + 2*x0*x1*x3*y2*y2*y3 - x0*x2*x2*y0*y1*y1 + 2*x0*x2*x2*y0*y1*y3 - x0*x2*x2*y0*y3*y3 + 2*x0*x2*x3*y0*y1*y1 - 2*x0*x2*x3*y0*y1*y2 - 2*x0*x2*x3*y1*y1*y3 + 2*x0*x2*x3*y1*y2*y3 - x0*x3*x3*y0*y1*y1 + x0*x3*x3*y0*y2*y2 + 2*x0*x3*x3*y1*y1*y2 - 2*x0*x3*x3*y1*y2*y2 - x1*x1*x2*y0*y0*y2 + 2*x1*x1*x2*y0*y0*y3 - 2*x1*x1*x2*y0*y3*y3 + x1*x1*x2*y2*y3*y3 - x1*x1*x3*y0*y0*y3 + 2*x1*x1*x3*y0*y2*y3 - x1*x1*x3*y2*y2*y3 + x1*x2*x2*y0*y0*y1 - 2*x1*x2*x2*y0*y0*y3 + 2*x1*x2*x2*y0*y3*y3 - x1*x2*x2*y1*y3*y3 - 2*x1*x2*x3*y0*y0*y1 + 2*x1*x2*x3*y0*y0*y2 + 2*x1*x2*x3*y0*y1*y3 - 2*x1*x2*x3*y0*y2*y3 + x1*x3*x3*y0*y0*y1 - 2*x1*x3*x3*y0*y1*y2 + x1*x3*x3*y1*y2*y2 + x2*x2*x3*y0*y0*y3 - 2*x2*x2*x3*y0*y1*y3 + x2*x2*x3*y1*y1*y3 - x2*x3*x3*y0*y0*y2 + 2*x2*x3*x3*y0*y1*y2 - x2*x3*x3*y1*y1*y2);
m11 = (RES_V*(x0 - x1)*(x0*y2 - x2*y0 - x0*y3 + x3*y0 + x2*y3 - x3*y2)*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2))/(- x0*x0*x1*y1*y2*y2 + 2*x0*x0*x1*y1*y2*y3 - x0*x0*x1*y1*y3*y3 + x0*x0*x2*y1*y1*y2 - 2*x0*x0*x2*y1*y2*y3 + x0*x0*x2*y2*y3*y3 - 2*x0*x0*x3*y1*y1*y2 + x0*x0*x3*y1*y1*y3 + 2*x0*x0*x3*y1*y2*y2 - x0*x0*x3*y2*y2*y3 + x0*x1*x1*y0*y2*y2 - 2*x0*x1*x1*y0*y2*y3 + x0*x1*x1*y0*y3*y3 - 2*x0*x1*x2*y0*y1*y3 + 2*x0*x1*x2*y0*y2*y3 + 2*x0*x1*x2*y1*y3*y3 - 2*x0*x1*x2*y2*y3*y3 + 2*x0*x1*x3*y0*y1*y2 - 2*x0*x1*x3*y0*y2*y2 - 2*x0*x1*x3*y1*y2*y3 + 2*x0*x1*x3*y2*y2*y3 - x0*x2*x2*y0*y1*y1 + 2*x0*x2*x2*y0*y1*y3 - x0*x2*x2*y0*y3*y3 + 2*x0*x2*x3*y0*y1*y1 - 2*x0*x2*x3*y0*y1*y2 - 2*x0*x2*x3*y1*y1*y3 + 2*x0*x2*x3*y1*y2*y3 - x0*x3*x3*y0*y1*y1 + x0*x3*x3*y0*y2*y2 + 2*x0*x3*x3*y1*y1*y2 - 2*x0*x3*x3*y1*y2*y2 - x1*x1*x2*y0*y0*y2 + 2*x1*x1*x2*y0*y0*y3 - 2*x1*x1*x2*y0*y3*y3 + x1*x1*x2*y2*y3*y3 - x1*x1*x3*y0*y0*y3 + 2*x1*x1*x3*y0*y2*y3 - x1*x1*x3*y2*y2*y3 + x1*x2*x2*y0*y0*y1 - 2*x1*x2*x2*y0*y0*y3 + 2*x1*x2*x2*y0*y3*y3 - x1*x2*x2*y1*y3*y3 - 2*x1*x2*x3*y0*y0*y1 + 2*x1*x2*x3*y0*y0*y2 + 2*x1*x2*x3*y0*y1*y3 - 2*x1*x2*x3*y0*y2*y3 + x1*x3*x3*y0*y0*y1 - 2*x1*x3*x3*y0*y1*y2 + x1*x3*x3*y1*y2*y2 + x2*x2*x3*y0*y0*y3 - 2*x2*x2*x3*y0*y1*y3 + x2*x2*x3*y1*y1*y3 - x2*x3*x3*y0*y0*y2 + 2*x2*x3*x3*y0*y1*y2 - x2*x3*x3*y1*y1*y2);
m12 = -(RES_V*(x0*y1 - x1*y0)*(x0*y2 - x2*y0 - x0*y3 + x3*y0 + x2*y3 - x3*y2)*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2))/(- x0*x0*x1*y1*y2*y2 + 2*x0*x0*x1*y1*y2*y3 - x0*x0*x1*y1*y3*y3 + x0*x0*x2*y1*y1*y2 - 2*x0*x0*x2*y1*y2*y3 + x0*x0*x2*y2*y3*y3 - 2*x0*x0*x3*y1*y1*y2 + x0*x0*x3*y1*y1*y3 + 2*x0*x0*x3*y1*y2*y2 - x0*x0*x3*y2*y2*y3 + x0*x1*x1*y0*y2*y2 - 2*x0*x1*x1*y0*y2*y3 + x0*x1*x1*y0*y3*y3 - 2*x0*x1*x2*y0*y1*y3 + 2*x0*x1*x2*y0*y2*y3 + 2*x0*x1*x2*y1*y3*y3 - 2*x0*x1*x2*y2*y3*y3 + 2*x0*x1*x3*y0*y1*y2 - 2*x0*x1*x3*y0*y2*y2 - 2*x0*x1*x3*y1*y2*y3 + 2*x0*x1*x3*y2*y2*y3 - x0*x2*x2*y0*y1*y1 + 2*x0*x2*x2*y0*y1*y3 - x0*x2*x2*y0*y3*y3 + 2*x0*x2*x3*y0*y1*y1 - 2*x0*x2*x3*y0*y1*y2 - 2*x0*x2*x3*y1*y1*y3 + 2*x0*x2*x3*y1*y2*y3 - x0*x3*x3*y0*y1*y1 + x0*x3*x3*y0*y2*y2 + 2*x0*x3*x3*y1*y1*y2 - 2*x0*x3*x3*y1*y2*y2 - x1*x1*x2*y0*y0*y2 + 2*x1*x1*x2*y0*y0*y3 - 2*x1*x1*x2*y0*y3*y3 + x1*x1*x2*y2*y3*y3 - x1*x1*x3*y0*y0*y3 + 2*x1*x1*x3*y0*y2*y3 - x1*x1*x3*y2*y2*y3 + x1*x2*x2*y0*y0*y1 - 2*x1*x2*x2*y0*y0*y3 + 2*x1*x2*x2*y0*y3*y3 - x1*x2*x2*y1*y3*y3 - 2*x1*x2*x3*y0*y0*y1 + 2*x1*x2*x3*y0*y0*y2 + 2*x1*x2*x3*y0*y1*y3 - 2*x1*x2*x3*y0*y2*y3 + x1*x3*x3*y0*y0*y1 - 2*x1*x3*x3*y0*y1*y2 + x1*x3*x3*y1*y2*y2 + x2*x2*x3*y0*y0*y3 - 2*x2*x2*x3*y0*y1*y3 + x2*x2*x3*y1*y1*y3 - x2*x3*x3*y0*y0*y2 + 2*x2*x3*x3*y0*y1*y2 - x2*x3*x3*y1*y1*y2);

使用 m00、m01、m02、m10、m11 和 m12,我构造了一个 M 矩阵。我省略了 m20、m21 和 m22,因为它们对 x 和 y 的结果没有影响。

最后,我使用这个 M 矩阵来移动球的坐标:

x_shifted = m00*x + m01*y + m02;
y_shifted = m10*x + m11*y + m12;

这是基于此:

在此处输入图像描述

如您所见,Matlab 产生的解导致方程非常长。偶然地,我发现当你在A矩阵中将 xi 与 ui 和 yi 与 vi 交换时,你将得到 m00、m01、m02、m10、m11、m12 的变换矩阵M的逆,但系数是用计算的方式更短的方程。

/   0     0     1     0     0     0     0         0     \ /m00\ /x0\
| RES_H   0     1     0     0     0 -RES_H*x1     0     | |m01| |x1|
|   0   RES_V   1     0     0     0     0     -RES_V*x2 | |m02| |x2|
| RES_H RES_V   1     0     0     0 -RES_H*x3 -RES_V*x3 |.|m10|=|x3|
|   0     0     0     0     0     1     0         0     | |m11| |y0|
|   0     0     0   RES_H   0     1 -RES_H*y1     0     | |m12| |y1|
|   0     0     0     0   RES_V   1     0     -RES_V*y2 | |m20| |y2|
\   0     0     0   RES_H RES_V   1 -RES_H*y3 -RES_V*y3 / \m21/ \y3/

当你让 Matlab 以同样的方式解决这个问题时,你会得到:

m00 = (x0*x2*y1 - x1*x2*y0 - x0*x3*y1 + x1*x3*y0 - x0*x2*y3 + x0*x3*y2 + x1*x2*y3 - x1*x3*y2)/(RES_H*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2));
m01 = -(x0*x1*y2 - x1*x2*y0 - x0*x1*y3 + x0*x3*y1 - x0*x3*y2 + x2*x3*y0 + x1*x2*y3 - x2*x3*y1)/(RES_V*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2));
m02 = x0;
m10 = (x0*y1*y2 - x1*y0*y2 - x0*y1*y3 + x1*y0*y3 - x2*y0*y3 + x3*y0*y2 + x2*y1*y3 - x3*y1*y2)/(RES_H*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2));
m11 = -(x0*y1*y2 - x2*y0*y1 - x1*y0*y3 + x3*y0*y1 - x0*y2*y3 + x2*y0*y3 + x1*y2*y3 - x3*y1*y2)/(RES_V*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2));
m12 = y0;
m20 = (x0*y2 - x2*y0 - x0*y3 - x1*y2 + x2*y1 + x3*y0 + x1*y3 - x3*y1)/(RES_H*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2));
m21 = -(x0*y1 - x1*y0 - x0*y3 + x1*y2 - x2*y1 + x3*y0 + x2*y3 - x3*y2)/(RES_V*(x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2));
m22 = 1.0;

当您将这些系数放入一个矩阵并反转该矩阵时,您将得到与第一种方法相同的结果 m00、m01、m02、m10、m11、m12。

我使用在这里找到的程序来反转矩阵: https ://codingtech2017.wordpress.com/2017/05/03/c-program-to-inverse-a-matrix3x3/

于 2021-02-24T10:53:46.427 回答
0

Opencv 的 getPerspectiveTransform 返回一个 3x3 的变换矩阵。所有 warpPerspective 所做的就是获取每个像素的 x,y 坐标并将其与该矩阵相乘(增加 [x,y] -> [x,y,1])。

如果您只想修改一个点 P [x,y,1],那么给定变换矩阵 M,您可以使用以下方法变换该点:

numpy.matmul(M, P);

这是一些示例代码,展示了它是如何工作的。我们制作了四个示例点,并表明使用 matmul 扭曲它们等同于使用 warpPerspective。

import cv2
import numpy as np

# test points
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]]);
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]]);

# transformation
M = cv2.getPerspectiveTransform(pts1,pts2);

# if our method works, then transforming each pts1 with M
# should result in pts2
transformed_points = [];
for p in pts1:
    # augment point
    point = np.array([p[0], p[1], 1], dtype = np.float32);

    # multiply
    transformed = np.matmul(M, point);

    # unpack and clean up
    x, y, scale = transformed;
    x /= scale;
    y /= scale;
    x = round(x, 5); # to clear out long floating points
    y = round(y, 5);
    transformed_points.append([x,y]);

# compare points
for a in range(len(pts2)):
    print("Target: " + str(pts2[a]));
    print("Transformed: " + str(transformed_points[a]));
于 2021-02-23T16:27:38.233 回答