【问题标题】:How do I rotate an image?如何旋转图像?
【发布时间】:2017-03-05 06:12:31
【问题描述】:

另请参阅: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);

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

【问题讨论】:

  • 旋转多少?任意角度或 90 度的倍数?
  • @shoosh:正如原型所暗示的(双角度),这必须使用任何值的双精度类型。

标签: math image-processing


【解决方案1】:

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

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

【讨论】:

【解决方案2】:

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

A----B 
|
|
C

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

  • 在二维中围绕 A 旋转 ABC,所以这是一次欧拉旋转
  • 在旋转状态下从 A 遍历到 B。对于每个像素,您还从左到右遍历原始图像中的水平线。因此,如果图像是宽度为 100、高度为 50 的图像,您将在 100 步中从 A 遍历到 B,从 A 到 C 以 50 步遍历,在 ABC 旋转状态下形成的区域中绘制 50 条 100 像素的线.

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

在绘图时,我稍微改变了源指针以获得类似橡胶的效果,但如果禁用它,您会看到代码旋转图像没有问题。当然,在某些角度上,您会得到看起来略微失真的图像。源代码包含 cmets 正在发生的事情,因此您应该能够轻松掌握其背后的数学/逻辑。

如果你更喜欢 Java,我也做过一次 Java 版本,大约 14 年前 ;) -> http://www.xs4all.nl/~perseus/zoom/zoom.java

【讨论】:

    【解决方案3】:

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

    Here's a simpler explanation

    【讨论】:

    • 很有趣,但我不明白大多数数学术语,如“奈奎斯特频率”或“图像频谱”。你能指点我阅读背景信息的材料吗?这是我可以自己探索的东西,还是我需要真正的数学教育? (我是去年数学高中的学生。)
    • @Iraimbilanja:信号处理理论是 EE 的第二或第三年的东西。首先知道如何进行积分会有所帮助。
    • 总有维基百科:en.wikipedia.org/wiki/Nyquist_frequency 将频率视为图像的频谱图:它相当于音频播放器的图形分析仪的输出,只是二维的。它显示了图像中哪个频率可见度最高,以及在哪个方向上。
    • 论文可能过于复杂,该方法实际上是基于左右移动行或上下移动列(剪切),我将在一个更简单的示例中进行编辑。
    • 多重倾斜方法是唯一的高质量索引图像旋转,它可以防止 rgba 图像软化这个答案需要投票到顶部。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-30
      • 2011-10-30
      相关资源
      最近更新 更多