试图了解仿射变换

时间:2012-05-19 18:27:46

标签: opencv

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

要设置问题,我使用的程序是第一个定义扭曲矩阵,然后进行变换。

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

cvGetAffineTransorm(srcTri, dstTri, warp_matrix);
cvWarpAffine(src, dst, warp_mat);

要定义扭曲矩阵,srcTridstTri定义为:

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[]的映射代表什么?

1 个答案:

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

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

    1,0,10
    0,1,1
    0,0,1
    

    如果你看到正常的班次比一切都好,但如果出现狗屎而不是将矩阵转置为:

    1,0,0
    0,1,0
    10,1,1