如何旋转图像?

时间:2009-03-29 18:21:56

标签: math image-processing

  

另请参阅:Why is my image rotation algorithm not working?

这个问题不是语言特定的,而且是一个数学问题。然而,我将使用一些C ++代码来解释我需要什么,因为我对数学不太热。

以下是图像的组成方式:

ImageMatrix image;
image[0][0][0] = 1;
image[0][1][0] = 2;
image[0][2][0] = 1;
image[1][0][0] = 0;
image[1][1][0] = 0;
image[1][2][0] = 0;
image[2][0][0] = -1;
image[2][1][0] = -2;
image[2][2][0] = -1;

这是我正在尝试创建的函数的原型:

ImageMatrix rotateImage(ImageMatrix image, double angle);

我想只旋转前两个索引(行和列),而不是通道。

4 个答案:

答案 0 :(得分:28)

解决这个问题的通常方法是向后做。您可以计算输出图像中每个像素在输入图像中的位置(通过在另一个方向上旋转相同的量 ,而不是计算输入图像中每个像素的最终位置。这样,您可以确保输出图像中的所有像素都具有值。

output = new Image(input.size())

for each pixel in input:
{
  p2 = rotate(pixel, -angle);
  value = interpolate(input, p2)
  output(pixel) = value
}

有不同的插值方法。对于旋转公式,我认为你应该检查https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions

但是为了好看,这里是(点(x,y)角度/弧度的旋转):

 newX = cos(angle)*x - sin(angle)*y
 newY = sin(angle)*x + cos(angle)*y

答案 1 :(得分:2)

请注意除了旋转矩阵之外还有另一种解决方案,即不会通过锯齿丢失图像信息。 您可以将2D图像旋转分离为skews and scalings,从而保持图像质量。

Here's a simpler explanation

答案 2 :(得分:2)

要旋转图像,您需要创建3个点:

A----B 
|
|
C

并围绕A旋转。要获得新的旋转图像,请执行以下操作:

  • 在2D中围绕A旋转ABC,因此这是单个euler旋转
  • 从A到B的旋转状态进行遍历。对于每个像素,您也会在原始图像的水平线上从左到右遍历。因此,如果图像是宽度为100,高度为50的图像,则您将以100步从A到B,以50步从A到C,在ABC旋转状态下在ABC形成的区域中绘制50行100像素。

这可能听起来很复杂,但事实并非如此。请看一下我前面写的这个C#代码: rotoZoomer by me

绘图时,我稍微改变源指针以获得类似橡胶的效果,但是如果禁用它,您将看到代码旋转图像没有问题。当然,在某些角度你会得到一个看起来有点扭曲的图像。源代码包含正在进行的注释,因此您应该能够轻松地获取其背后的数学/逻辑。

如果你更喜欢Java,我也已经制作了一个java版本,大约14年前;) - > http://www.xs4all.nl/~perseus/zoom/zoom.java

答案 3 :(得分:0)

您提供的示例似乎是一些边缘检测内核。因此,如果您想要检测不同角度的边缘,您最好选择一些连续函数(在您的情况下可能是x1的参数化高斯乘以x2),然后根据kigurai提供的公式旋转它。因此,您可以更有效地生成磁盘内核而不会出现锯齿。