试图了解仿射变换

And*_*lez 7 opencv

我正在使用OpenCV中的仿射变换,我无法直观地理解它的工作原理,更具体地说,我如何指定地图矩阵的参数,以便获得特定的期望结果.

要设置问题,我使用的过程是第一个定义warp矩阵,然后进行转换.

在OpenCV中,有两个例程(我在Bradski&Kaehler的优秀书籍OpenCV中使用了一个例子):

cvGetAffineTransorm(srcTri, dstTri, warp_matrix);
cvWarpAffine(src, dst, warp_mat);
Run Code Online (Sandbox Code Playgroud)

为了限定该经矩阵,srcTri并且dstTri定义如下:

CvPoint2D32f srcTri[3], dstTri[3];
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

这基本上是矩阵起点的图像的左上角,右上角和左下角.这部分对我有意义.

但是,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;
Run Code Online (Sandbox Code Playgroud)

似乎src和dst点之间的唯一区别是左下角点向右移动了100个像素.直觉上,我觉得图像的底部应该向右移动100个像素,但事实并非如此.

另外,如果我使用了完全相同的值dstTri[3],我使用的srcTri[3],我认为转换会产生完全相同的图像-但事实并非如此.

显然,我不明白这里发生了什么.那么,从代表srcTri[]dstTri[]代表的映射是什么?

Dan*_*HsH 12

以下是仿射变换的数学解释:这是一个大小为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
Run Code Online (Sandbox Code Playgroud)
  1. dx和
  2. dy元素是x和y轴的平移(只需向左,向下移动图片).
  3. Zx是您在X轴上应用于图像的相对比例(缩放).
  4. 对于y轴,Zy与上述相同
  5. a是图像的旋转角度.这很棘手,因为当您想要通过'a'旋转时,您必须在矩阵的4个不同位置插入sin(),cos().
  6. 'q'是偏斜参数.它很少使用.它会导致图像在侧面倾斜(q1导致y轴影响x轴,q2导致x轴影响y轴)
  7. 额外奖励:'e'参数实际上不是转换.它可以具有值1,-1.如果它是1而不是没有发生,但如果它是-1,则图像被水平翻转.您也可以使用它来垂直翻转图像,但很少使用这种类型的转换.

非常重要的注意!!!!!

以上解释是数学的.它假设您将矩阵乘以右侧的列向量.据我所知,Matlab使用反向乘法(左侧的行向量),因此您需要转置此矩阵.我很确定openCV使用常规乘法,但你需要检查它.只输入平移矩阵(x移动10个像素,y移1).

1,0,10
0,1,1
0,0,1
Run Code Online (Sandbox Code Playgroud)

如果你看到正常的移位比一切都好,但是如果出现shit而不是将矩阵转置为:

1,0,0
0,1,0
10,1,1
Run Code Online (Sandbox Code Playgroud)