Программа для распознавания букв на C#

В этом учебном семестре у меня появился довольно интересный предмет «Методы распознавания образов».

Существуют такие предметы или явления, для которых характерно такое свойство, что ознакомившись с конечным представителем этих предметов или явлений люди оказываются способными узнавать сколь угодно большое число других представителей этих предметов или явлений. Предметы и явления — образы, а их отдельные представители — объекты. Воспринимая окружаюший мир, мы всегда проводим классификацию явлений, т.е. разбиваем все явления на группы похожих. Для принятия решения необходимо выполнить распознавание, т.е. отнести незнакомый объект (ситуацию) к классу (образу, группе) ранее известных и классифицированных.

Моим первым практическое задание, заключалось в написании программы, которая могла бы распознать буквы Y, R, N. Для этого нужно немножко окунуться в теорию. Распознавание выполняется попиксельно. Каждый пискель имеет 8 соседей.

Тип пикселя определяется из количества и вида его соедей, т.е. с точки зрения связности. Для определения типа пикселя введены понятия связности и характеристичесие числа

  • количество единичных элементов по 4-х свзяности A4(аij) = ∑ а2k-1, k=1..4
  • количество единичных элементов по 8-ми свзяности A8(аij) = ∑ аk, k=1..8
  • количество единичных двоек  B8(аij) = ∑ аkk+1, k=1..8
  • количество единичных двоек в окреснтности пикселя Cn(аij) = A8(аij) -B8(аij)

Изолированный пиксель имеет А8=0, конечный писксель A8=1,

Cn=0 – изолированный пиксель, Сn=1 – конечный пиксель, Сn=2 – связующий пиксель, Сn≥3 – пиксель ветвления.

Помимо этого, мне нужно было осуществить возможность подгружать изображения, и выводить схему буквы. На данный момент программа распознаёт три буквы (Y, R, N), нарисованные однопиксельной кистью.

Приведу несколько строк из кода:
Метод, который определяет закрашенность пикселя (чёрный или белый)
[cpp] public int pixel_value(int X, int Y)
{
Color clr; byte val;
clr = (pictureBox1.Image as Bitmap).GetPixel(X, Y);
if ((clr.R.Equals(0)) && (clr.G.Equals(0)) && (clr.B.Equals(0))) val = 1;
else val = 0;
return val;
}

[/cpp] Подсветка количества соседей у пикселя в ReachTextBox
[cpp] static void Highlight(RichTextBox box, string phrase, Color color)
{
int pos = box.SelectionStart;
string s = box.Text;
for (int ix = 0; ; )
{
int jx = s.IndexOf(phrase, ix, StringComparison.CurrentCultureIgnoreCase);
if (jx < 0) break;
box.SelectionStart = jx;
box.SelectionLength = phrase.Length;
box.SelectionColor = color;
ix = jx + 1;
}
box.SelectionStart = pos;
box.SelectionLength = 0;
}
[/cpp]

 
Обработка события нажатия кнопки Распознать
[cpp] private void button1_Click(object sender, EventArgs e)
{
int pX, pY, A4 = 0, A8 = 0, B8 = 0, C8 = 0, NC4 = 0, CN = 0, pxKon = 0, pxNor = 0, pxVet = 0;
Color clr;
for (pY = 0; pY < pictureBox1.Height; pY++)
{
for (pX = 0; pX < pictureBox1.Width; pX++)
{
pictureBox1.Refresh();
clr = (pictureBox1.Image as Bitmap).GetPixel(pX, pY);
if ((clr.R.Equals(0)) && (clr.G.Equals(0)) && (clr.B.Equals(0)))
{
A4 = 0; A8 = 0;
A4 = pixel_value(pX — 1, pY) + pixel_value(pX + 1, pY) + pixel_value(pX, pY — 1) + pixel_value(pX, pY + 1);
A8 = A4 + pixel_value(pX + 1, pY — 1) + pixel_value(pX — 1, pY — 1) + pixel_value(pX — 1, pY + 1) + pixel_value(pX + 1, pY + 1);
B8 = pixel_value(pX + 1, pY) * pixel_value(pX + 1, pY — 1) + pixel_value(pX + 1, pY — 1) * pixel_value(pX, pY — 1) + pixel_value(pX, pY — 1) * pixel_value(pX — 1, pY — 1) + pixel_value(pX — 1, pY — 1) * pixel_value(pX — 1, pY) + pixel_value(pX — 1, pY) * pixel_value(pX — 1, pY — 1) + pixel_value(pX — 1, pY + 1) * pixel_value(pX, pY + 1) + pixel_value(pX, pY + 1) * pixel_value(pX + 1, pY + 1) + pixel_value(pX + 1, pY + 1) * pixel_value(pX + 1, pY);
C8 = pixel_value(pX + 1, pY) * pixel_value(pX + 1, pY — 1) * pixel_value(pX, pY — 1) + pixel_value(pX, pY — 1) * pixel_value(pX — 1, pY — 1) * pixel_value(pX — 1, pY) + pixel_value(pX — 1, pY) * pixel_value(pX — 1, pY + 1) * pixel_value(pX, pY + 1) + pixel_value(pX, pY + 1) * pixel_value(pX + 1, pY + 1) * pixel_value(pX + 1, pY);
NC4 = A4 — C8;
CN = A8 — B8;
if (A8 == 1) pxKon++;
if (A8 == 2) pxNor++;
if (A8 > 2) pxVet++;
pCount++;
}
if (pixel_value(pX, pY) == 1)
richTextBox1.Text += A8;
else richTextBox1.Text += "_";
progressBar1.Value += 1;
}
richTextBox1.Text += "\n";
}
if (/*(pxVet == 1) && */(pxKon == 3)) MessageBox.Show("Y", "Ваша буква", MessageBoxButtons.OK, MessageBoxIcon.Information);
if ((pxVet > 4) && (pxKon == 2)) MessageBox.Show("R", "Ваша буква", MessageBoxButtons.OK, MessageBoxIcon.Information);
if ((pxVet > 1) && (pxVet < 5) && (pxKon == 2)) MessageBox.Show("N", "Ваша буква", MessageBoxButtons.OK, MessageBoxIcon.Information);
Highlight(richTextBox1, "_", Color.LightGray);
Highlight(richTextBox1, "1", Color.White);
Highlight(richTextBox1, "1", Color.Green);
Highlight(richTextBox1, "2", Color.Orange);
Highlight(richTextBox1, "3", Color.OrangeRed);
Highlight(richTextBox1, "4", Color.Firebrick);
richTextBox1.Visible = true;
label3.Text = "Количество чёрных пикселей: " + pCount;
pCount = 0;
progressBar1.Value = 0;
}
[/cpp]

Ну, а вот и собственно исходник программы. Ах да, при запуске программы выскакивает окно, для выбора изображения из файла (3 файла изображения также в архиве с исходником), если хотите нарисовать букву самостоятельно, жмите отмена.

Надеюсь пригодилось?

Если вдруг Вы решили затеять ремонт, то Вам определённо стоит обратить внимание на металлопластиковые окна.

Stas Kuryan

Web developer. Перфекционист в написании кода.

18 комментариев

  1. burito     

    Вообще вещь!
    Спасибо. Пример очень кстати пришёлся)

  2. Alex     

    Мне бы не букв а целых слов… А так очень круто… Можешь сделать на целые слова…

    • Stafox        Автор

      Для целых слов — немного другой алгоритм, который потребует больших временных затрат. Это такой хороший курсовой проект получится. С радостью бы поделился, но тема моего проекта — распознавание рукописной подписи.

  3. sprintline     

    Очень интересно. Но думаю это забавы ради. Т.к. уже есть программы по распознаванию текста.

    • Stafox        Автор

      Программы может и есть, но вот проблема распознавания каптчи так и не решена окончательно.

      • Имя     

        А можеш привести код проги для распознавания капчи?

        • Stafox        Автор

          Не всякой каптчи, это раз. Ну и смотря какая сумма — это два. 🙂

  4. Sul     

    Привет.
    А можно обновить ссылку на исходный код, скачать не получается.

    • Stafox        Автор

      Привет. Обновил, можешь скачивать.

  5. Agra     

    Привет. Хотелось бы обсудить распознание капчи icq 9859685 цену обсудим

    • Stafox        Автор

      Приветствую. В силу загруженности, вынужден отказать.

  6. Uh     

    пример стоящий, но желательно, чтобы были подписаны переменные и процедуры с функциями) иначе выражаясь, описание кода, ведь делаете пример для других =))

    • Stafox        Автор

      Да, согласен. Было проще для усвоения. Но, это писалось мной на 3ем курсе университета, выложил потому, что в интернете очень мало информации по этой теме. Собираюсь еще выложить курсовой проект на тему: «Распознавание рукописной подписи» (применение систем с учителем). Да вот никак времени не найду.
      Поэтому, извиняйте, берите как есть.

  7. Uh     

    Спасибо и на том) буду ждать этой работы, тема интересная))

  8. Nika     

    В Visual Studio 2013 при нажатии на кнопку «Распознать» программа рушится и вылетает в обработчик прерываний (необработанное исключение типа «System.ArgumentOutOfRangeException» в System.Windows.Forms.dll.
    Значение «101» недопустимо для «Value». «Value»

    • Stafox        Автор

      C ходу не скажу в чем проблема. Думаю дело в подаваемых на вход изображениях. Если мне не изменяет память, то программа работает только с определенным размером изображений, примеры которых есть в архиве.

  9. Art     

    Привет
    Ваша программа распознает только три буквы
    Подскажите что на нужно чтоб она могла распознавать другие буквы английского алфавита к не только эти три буквы

    • Stafox        Автор

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *