Посоветуйте алгоритм распознавания символов с матричного изображения

Приветы. Пишу на C# распознавание символов с изображения (OCR). Есть например такая матрица

введите сюда описание изображения

и надо написать алгоритм который выделит с этого группы связанных пикселей, т.е. символы и получить в таком виде

введите сюда описание изображения

Никак не могу придумать как это элегантно написать, помогите пожалуйста, хотя бы идеи подкиньте. Спасибо.


Ответы (2 шт):

Автор решения: Space Researcher

Цифра прерывается, если вокруг неё нее, нет ни одной единицы, тогда вам следует искать по матрице первую единицу. Как только нашли, смотреть вокруг нее остальные в следующем порядке(0 это ваша единица):

781
602
543

именно так потому, что мы пишем слева-напрво сверху вниз

Второй алгоритм, находить первую единицу и просто отслеживать всю цепочку единиц, что стоят рядом с ней. Как только цепь закончилась, из цепи выбираете самый левый-нижний элемент(с наибольшими индексами он будет) и отсекаете из этой точки к ближайшим краям матрицы

→ Ссылка
Автор решения: Ant0hin

Я написал такой код. Каждому пикселю присваивается группа, затем в рекурсии проверяются все соседние и им присваивается та же группа. Таким образом в результате получается список отдельных групп пикселей. Это работает хорошо, пока размер изображение не становится значительнее больше. Тогда возникает ошибка переполнения стека, т.е. в стеке заканчивается память потому что рекурсивный метод был вызван слишком много раз. Посоветуйте может как то можно переделать отказавшись от рекурсии.

List<PixelGroup> groupList = new List<PixelGroup>();
for (int y = 0; y < height - 1; y++)
{
    string line = lines[y];
    for (int x = 0; x < width; x++)
    {
        if (pixArray[x, y].active && pixArray[x, y].group == null)
        {
            PixelGroup group = new PixelGroup();
            group.left = x;
            group.top = y;
            groupList.Add(group);
            SetPixelGroupRecursion(ref pixArray, x, y, ref group, 0);
        }
    }
}

void SetPixelGroupRecursion(ref Pixel[,] pixArray, int x, int y, ref PixelGroup group, int recursionDepth)
{
    int width = pixArray.GetLength(0);
    int height = pixArray.GetLength(1);
    pixArray[x, y].group = group;
    if (x < group.left)
        group.left = x;
    if (x > group.right)
        group.right = x;
    if (y < group.top)
        group.top = y;
    if (y > group.bottom)
        group.bottom = y;
    recursionDepth += 1;   

    if (x > 0 && y < height-1 && pixArray[x - 1, y + 1].active && pixArray[x - 1, y + 1].group == null)
        SetPixelGroupRecursion(ref pixArray, x - 1, y + 1, ref group, recursionDepth);
    if (x > 0 && pixArray[x - 1, y].active && pixArray[x - 1, y].group == null)
        SetPixelGroupRecursion(ref pixArray, x - 1, y, ref group, recursionDepth);
    if (x > 0 && y > 0 && pixArray[x - 1, y - 1].active && pixArray[x - 1, y - 1].group == null)
        SetPixelGroupRecursion(ref pixArray, x - 1, y - 1, ref group, recursionDepth);
    if (y > 0&& pixArray[x, y - 1].active && pixArray[x, y - 1].group == null)
        SetPixelGroupRecursion(ref pixArray, x, y - 1, ref group, recursionDepth);
    if (x < width -1 && y > 0 && pixArray[x + 1, y - 1].active && pixArray[x + 1, y - 1].group == null)
        SetPixelGroupRecursion(ref pixArray, x + 1, y - 1, ref group, recursionDepth);
    if (x < width -1 && pixArray[x + 1, y].active && pixArray[x + 1, y].group == null)
        SetPixelGroupRecursion(ref pixArray, x + 1, y, ref group, recursionDepth);
    if (x < width -1 && y < height - 1  && pixArray[x + 1, y + 1].active && pixArray[x + 1, y + 1].group == null)
        SetPixelGroupRecursion(ref pixArray, x + 1, y + 1, ref group, recursionDepth);
    if (y < height - 1  && pixArray[x, y + 1].active && pixArray[x, y + 1].group == null)
        SetPixelGroupRecursion(ref pixArray, x, y + 1, ref group, recursionDepth);         
}
→ Ссылка