我正在尝试编写一个程序,以编程方式确定任意图像的倾斜或旋转角度。
图像具有以下属性:
- 由浅色背景上的深色文本组成
- 偶尔包含仅以90度角交叉的水平或垂直线条。
- 倾斜角度在-45到45度之间。
- 请参考此图片(它被倾斜了2.8度)。
到目前为止,我想出了这个策略:从左到右绘制路径,始终选择最近的白色像素。可以预期,从左到右的路径将更喜欢沿图像的倾斜线路跟随文本行之间的路径。
下面是我的代码:
private bool IsWhite(Color c) { return c.GetBrightness() >= 0.5 || c == Color.Transparent; }
private bool IsBlack(Color c) { return !IsWhite(c); }
private double ToDegrees(decimal slope) { return (180.0 / Math.PI) * Math.Atan(Convert.ToDouble(slope)); }
private void GetSkew(Bitmap image, out double minSkew, out double maxSkew)
{
decimal minSlope = 0.0M;
decimal maxSlope = 0.0M;
for (int start_y = 0; start_y < image.Height; start_y++)
{
int end_y = start_y;
for (int x = 1; x < image.Width; x++)
{
int above_y = Math.Max(end_y - 1, 0);
int below_y = Math.Min(end_y + 1, image.Height - 1);
Color center = image.GetPixel(x, end_y);
Color above = image.GetPixel(x, above_y);
Color below = image.GetPixel(x, below_y);
if (IsWhite(center)) { /* no change to end_y */ }
else if (IsWhite(above) && IsBlack(below)) { end_y = above_y; }
else if (IsBlack(above) && IsWhite(below)) { end_y = below_y; }
}
decimal slope = (Convert.ToDecimal(start_y) - Convert.ToDecimal(end_y)) / Convert.ToDecimal(image.Width);
minSlope = Math.Min(minSlope, slope);
maxSlope = Math.Max(maxSlope, slope);
}
minSkew = ToDegrees(minSlope);
maxSkew = ToDegrees(maxSlope);
}
这在一些图像上效果很好,在另一些图像上效果不佳,而且速度较慢。
是否有更高效、更可靠的方法来确定图像的倾斜?
decimal
?它对计算斜率的精度没有太大帮助,而且在传递给atan
方法时还必须将其强制转换回double
。 - Cecil Has a Name