Я пытаюсь написать программу для программного определения угла наклона или угла поворота на произвольном изображении.
Изображения имеют следующие свойства:
- Состоит из темного текста на светлом фоне.
- Иногда содержат горизонтальные или вертикальные линии, которые пересекаются только под углом 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);
}
Это хорошо работает на некоторых изображениях, а не на других, и на медленном.
Есть ли более эффективный и надежный способ определения наклона изображения?