10

我正在尝试对图像执行倾斜,就像这里显示的那样


(来源:microsoft.com

我有一组代表我的图像的像素,我不确定如何处理它们。

4

3 回答 3

55

一个更好的方法是通过逆映射。

本质上,您想“扭曲”图像,对吗?这意味着源图像中的每个像素都会到达一个预定义的点——预定义是一个变换矩阵,它告诉你如何旋转、缩放、平移、剪切等。图像本质上是(x,y)在你的图像上获取一些坐标并说, “好的,这个像素的新位置是(f(x),g(y)).

这基本上就是“翘曲”的作用。

现在,考虑缩放图像……比如说,缩放到十倍。所以这意味着,像素点(1,1)变成了像素点(10,10)- 然后下一个像素点(1,2)变成(10,20)了新图像中的像素点。但是,如果您继续这样做,您将没有像素值,(13,13)因为(1.3,1.3)原始图像中没有定义,并且您的新图像中将有一堆孔 - 您必须使用四个插值该值新图像中它周围的像素,即(10,10) , (10,20), (20,10), (200,2)- 这称为双线性插值

但这是另一个问题,假设您的转换不是简单的缩放并且是仿射的(就像您发布的示例图像) - 然后(1,1)会变成这样(2.34,4.21),然后您必须在输出图像中将它们四舍五入(2,4)然后您d 必须对新图像进行双线性插值以填充孔或更复杂的插值 - 很乱吧?

现在,没有办法摆脱插值,但我们可以只做一次双线性插值。如何?简单的逆映射。

不要将其视为将源图像转到新图像,而应考虑新图像的数据将来自源图像中的何处!所以,(1,1)在新的图像中会来自源图像中的一些反向映射,比如说,(3.4, 2.1)然后对源图像做双线性插值,找出对应的值!

变换矩阵

好的,那么如何为仿射变换定义变换矩阵呢?这个网站告诉你如何通过组合不同的变换矩阵来实现旋转、剪切等。

转换:

替代文字

合成:

替代文字

最终矩阵可以通过按顺序合成每个矩阵来实现,然后将其反转以获得逆映射 - 使用它计算源图像中像素的位置并进行插值。

于 2010-03-15T15:03:24.007 回答
3

如果您不想重新发明轮子,请查看 OpenCV 库。它实现了许多有用的图像处理功能,包括透视变换。查看我用来轻松完成此任务的cvWarpPerspective 。

于 2010-03-15T16:36:37.417 回答
2

正如 KennyTM 所评论的,您只需要一个仿射变换,它是通过将每个像素乘以矩阵M并将结果添加到平移向量V获得的线性映射。这是简单的数学

end_pixel_position = M*start_pixel_position + V

其中M是简单变换(如旋转或缩放)的组合,V是一个向量,它通过向每个像素添加固定系数来转换图像的每个点。

例如,如果要旋转图像,可以将旋转矩阵定义为:

    | cos(a) -sin(a) |
M = |                |
    | sin(a)  cos(a) |

a您要旋转图像的角度在哪里。

缩放使用以下形式的矩阵:

    | s1   0 |
M = |        |
    | 0   s2 |

其中s1s2是两个轴上的比例因子。

对于翻译,你只有向量V

    | t1 |
V = |    |
    | t2 |

添加t1t2到像素坐标。

然后,您将矩阵组合在一个单一的转换中,例如,如果您有缩放、旋转和平移,您最终会得到如下结果:

| x2 |             | x1 |
|    | = M1 * M2 * |    | + T
| y2 |             | y1 |

在哪里:

  • x1并且y1是应用变换之前的像素坐标,
  • x2是变换后y2的像素,
  • M1并且M2是用于缩放和旋转的矩阵(请记住:矩阵的组合不是可交换的!通常M1 * M2 * Vect != M2 * M1 * Vect),
  • T是用于平移每个像素的平移向量。
于 2010-03-15T14:28:58.143 回答