Я хочу автоматически разделить изображение древнего рукописного текста по строкам (и по словам в будущем).
Я просто использую простую оцифровку (на основе яркости пикселя). После этого я сохраняю данные в двумерном массиве.
Мой первый алгоритм был довольно простым - если в строке массива больше черных пикселей, чем среднеквадратическое значение максимального и минимального значения , то эта строка является частью строки.
После формирования списка строк я вырезал строки с высотой , которая меньше средней. В итоге получилась какая-то линейная регрессии, пытаясь свести к минимуму разницу между пустыми строками и текстовыми строками. (я предполагал этот факт)
Моя вторая попытка - я пытался использовать GA несколько раз подряд функции. Хромосома содержала 3 значения - xo, x1, x2. xo [-1; 0] x1 [0; 0,5] x2 [0; 0,5]
Функция, которая определяет идентичность строки к строке (xo + α1 x1 + α2 x2)> 0 , где α1 - это масштабированная сумма черных пикселей в строке, α2 - среднее значение диапазонов между крайними черными пикселями в строке.(a1, a2 [0,1]) Еще одна функция, которую я пробовал, - это (x1 α2) и (1 / xo + [a1 x1] / [a2 x2])> 0 Последняя функция является наиболее эффективной. Фитнес-функция - ( 1 / (HeigthRange + SpacesRange)
Где диапазон - это разница между максимумом и минимумом. Он представляет однородность текста. Глобальный оптимум этой функции - наиболее плавный способ разделить изображение на линии.
Я использую C # с моим самокодирующимся GA (классический, с двухточечным кроссовером, хромосомы с серым кодом, максимальная популяция 40, частота мутаций 0,05)
Теперь у меня закончились идеи, как разделить это изображение на строки с ~ 100 % точности.
Какой эффективный алгоритм для этого?
ОБНОВЛЕНИЕ: Исходное изображение Исходное изображение в формате BMP (1,3 МБ)
ОБНОВЛЕНИЕ2: Улучшенные результаты на этот текст на 100%
Как я это сделал:
Проблема:
GA неожиданно не смог распознать эту строку. Я посмотрел на отладочные данные функции «find rages» и обнаружил, что в «нераспознанном» месте слишком много шума. Код функции ниже:
public double[] Ranges()
{
var ranges = new double[_original.Height];
for (int y = 0; y < _original.Height; y++ )
{
ranges[y] = 0;
var dx = new List();
int last = 0;
int x = 0;
while (last == 0 && x<_original.Width)
{
if (_bit[x, y])
last = x;
x++;
}
if (last == 0)
{
ranges[y] = 0;
continue;
}
for (x = last; x<_original.Width; x++)
{
if (!_bit[x, y]) continue;
if (last != x - 1)
{
dx.Add((x-last)+1);
}
last = x;
}
if (dx.Count > 2)
{
dx.Sort();
ranges[y] = dx[dx.Count / 2];
//ranges[y] = dx.Average();
}
else
ranges[y] = 0;
}
var maximum = ranges.Max();
for (int i = 0; i < ranges.Length; i++)
{
if (Math.Abs(ranges[i] - 0) < 0.9)
ranges[i] = maximum;
}
return ranges;
}
Я использую некоторые хаки в этом коде. Основная причина - я хочу минимизировать интервал между ближайшими черными пикселями, но если пикселей нет, значение становится «0», и решить эту проблему с поиском оптимумов становится невозможно.Вторая причина - этот код меняется слишком часто. Я постараюсь полностью изменить этот код, но понятия не имею, как это сделать.
Q: