我正在使用OpenCV中的仿射变换,我无法直观地理解它的工作原理,更具体地说,我如何指定地图矩阵的参数,以便获得特定的预期结果。 / p>
要设置问题,我使用的程序是第一个定义扭曲矩阵,然后进行变换。
在OpenCV中,有两个例程(我在Bradski& Kaehler的优秀书籍OpenCV中使用了一个例子):
cvGetAffineTransorm(srcTri, dstTri, warp_matrix);
cvWarpAffine(src, dst, warp_mat);
要定义扭曲矩阵,srcTri
和dstTri
定义为:
CvPoint2D32f srcTri[3], dstTri[3];
srcTri[3]
填充如下:
srcTri[0].x = 0;
srcTri[0].y = 0;
srcTri[1].x = src->width - 1;
srcTri[1].y = 0;
srcTri[2].x = 0;
srcTri[2].y = src->height -1;
这基本上是矩阵起点的图像的左上角,右上角和左下角。这部分对我有意义。
但是dstTri[3]
的值只是令人困惑,至少,当我改变一个点时,我得不到我期望的结果。
例如,如果我对dstTri[3]
使用以下内容:
dstTri[0].x = 0;
dstTri[0].y = 0;
dstTri[1].x = src->width - 1;
dstTri[1].y = 0;
dstTri[2].x = 0;
dstTri[2].y = 100;
似乎src和dst点之间的唯一区别是左下角的点向右移动了100个像素。直观地说,我觉得图像的底部应该向右移动100个像素,但事实并非如此。
另外,如果我使用dstTri[3]
的{{1}}完全相同的值,我会认为变换会生成完全相同的图像 - 但事实并非如此。
显然,我不明白这里发生了什么。那么,从srcTri[3]
到srcTri[]
的映射代表什么?
答案 0 :(得分:11)
这是仿射变换的数学解释: 这是一个大小为3x3的矩阵,它在2D矢量上应用了愚蠢的变换:X轴缩放,缩放,旋转,倾斜,x轴和y平移。 这些是6个转换,因此您的3x3矩阵中有6个元素。底行始终为[0 0 1]。 为什么?因为底行表示轴x和y的透视变换,仿射变换不包括透视变换。 (如果你想应用透视变形使用单应性:也是3x3矩阵)
您插入到仿射矩阵中的6个值与它所做的6个转换之间的关系是什么?让我们看看像
这样的3x3矩阵e*Zx*cos(a), -q1*sin(a) , dx,
e*q2*sin(a), Z y*cos(a), dy,
0 , 0 , 1
以上解释是数学的。它假设您将矩阵乘以右侧的列向量。据我所知,Matlab使用反向乘法(左侧的行向量),因此您需要转置此矩阵。我很确定openCV使用常规乘法,但你需要检查它。 只输入平移矩阵(x移动10个像素,y移1)。
1,0,10
0,1,1
0,0,1
如果你看到正常的班次比一切都好,但如果出现狗屎而不是将矩阵转置为:
1,0,0
0,1,0
10,1,1