如何找到图像的旋转角度?

9
我正在将位图图像输入到我的C#程序中,以执行OCR以识别图像中的字符。如果图像未旋转,我可以做得很好。然而,程序要求之一是程序自动确定图像是否已经旋转,并自动纠正这些旋转。
我尝试了一种简单的方法,其中跨越图像的线被跟踪,并记录接触字符的点,然后对线点执行简单的线性回归。这在某种程度上有效,但由于字符的曲率等原因,它并没有证明非常准确。
我想知道是否有更好的方法来解决这个问题?非常感谢! :)
6个回答

2
这是一个有趣的问题。我建议寻找一些易于判断旋转角度的字母,例如大写字母A、R或K,它们的下部分应该在同一水平面上。另一个方法是取那些无法识别的字母,将它们以不同的方式旋转并尝试重新识别它们。如果在旋转后无法识别的字母变得可识别了,那就是一个很大的线索。一旦确定了使无法识别的字符变成可识别字符的“校正”旋转角度,就可以将相同的旋转值应用于其他字符。

此外,如果你能找到一个字母"o",你可以在一个方向上径向延伸,并通过查看字母是否在你的线上来轻松确定方向。 - im so confused
最大的问题是在旋转之前难以分离字符,因为我需要在字符之间寻找垂直和水平的空白。如果图像被旋转,往往这些空白会被下一个字符打断。由于我无法分离字符,因此也就无法开始尝试识别它们。 - Mac Sigler
@MacSigler,强度足够的模糊是否可以使文本行至少混合在一起,从而进行边缘检测或者在霍夫变换中突出显示? - im so confused
@MacSigler 这篇文章或许有帮助:http://www.loni.ucla.edu/~ztu/publication/cvpr12_textdetection.pdf - im so confused
1
@AK4749 这篇论文确实很有趣,但每次我尝试阅读时都会感到困惑。 :P - Mac Sigler
我认为,隔离单个字母应该相对容易 —— 只需识别“白色”的阈值,并选择完全被其环绕的区域即可。 - Heather

2
如果它识别出文本行,则尝试模糊图像,使行大部分是实线,并找到线的方向(可以通过傅里叶变换或脊线检测进行分析)。

2

我在我的程序中使用了gmseDeskew算法来矫正图像的倾斜。它的效果非常好。


1
这个算法对我很有用。我在这里找到了一个很棒的C#实现。不幸的是,似乎这个算法写死了±20度。我尝试更改代码行,例如double cAlphaStart = -20;改为-45,以搜索±45度和其他一些行,但不可避免地会出现问题。如果有更灵活的算法,或者有人可以解释如何调整算法使其更灵活而不破坏结果,我很乐意听取建议。 - Mac Sigler
1
我也试过了,它正常工作。@MacSigler 要将角度“范围”增加到(-45,+45),似乎只需要更改以下行:double cAlphaStart = -45; int cSteps = 90 * 5; 我进行了快速测试,看起来没问题。 - AFract

1

如果文本格式像印刷文件(列和行的文本),那么您可以利用这一点。

我经常看到的处理文档文本的方法是进行投影剖面:

  1. 在特定方向上扫描文档,并总结每个扫描线上的“黑色”像素数量(创建一个计数的1D数组,每个索引表示Y坐标,即剖面)。
  2. 计算计数(剖面)的方差。
  3. 以多个角度重复此过程(可以通过二进制搜索方式减少处理量)。
  4. 导致最大方差的角度是正确的角度(由于文本行从印刷文本中创建大峰值,而由于行之间的文本缺失而产生低谷)

然后,在找到这个角度之后,您可以相应地调整图像并进行出色的OCR。


0
我们之前遇到过类似的问题,寻找了一个简单快捷的解决方案,最终使用了商业工具包(leadtools)。您可以使用它在OCR之前对图像进行自动处理。您可以查看此帮助主题以了解如何使用此工具包来处理和扫描图像。

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分(以及为什么它实际上回答了关于旋转角度的问题),并提供参考链接。如果链接页面更改,仅有链接的答案可能会变得无效(并被投票降低)。请参阅如何回答以了解其重要性。 - Be Brave Be Like Ukraine

0

可能更容易找到与文本相邻的垂直线(即左边距)。对于每个扫描线,记录第一个黑色像素。将所有这些放入线性回归中,您应该会得到一条接近垂直的线。从真正的垂直线测量其角度,您应该能够旋转文本。您也可以想象对顶部、底部和右侧进行相同的操作,并取平均值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接