9

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

为了设置这个问题,我使用的过程是首先定义一个扭曲矩阵,然后进行变换。

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

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

定义warp矩阵,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;

这本质上是图像的左上点、右上点和左下点作为矩阵的起点。这部分对我来说很有意义。

但是 just 的值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]此外,如果我使用与for完全相同的值srcTri[3],我会认为转换会产生完全相同的图像——但事实并非如此。

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

4

1 回答 1

15

这是仿射变换的数学解释:这是一个大小为 3x3 的矩阵,它在 2D 向量上应用了愚蠢的变换:X 轴缩放、Y 轴缩放、旋转、倾斜、x 轴平移和 y。这些是 6 个转换,因此您的 3x3 矩阵中有六个元素。底行始终为 [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' 是偏斜参数。它很少使用。它会导致您的图像偏斜(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

如果您看到正常的转变,则一切正常,但是如果出现狗屎,则将矩阵转置为:

1,0,0
0,1,0
10,1,1
于 2012-05-21T06:27:36.277 回答