|
Распознавание графических символов |
Если проводилось сохранение обучения, то можно не обучать. Для распознавания в таком случае надо делать следующие: открываешь распознаваемое изображение, нажимаешь "Сегментация", нажимаешь "загрузить", нажимаешь "распознать".- В записке в графической части нужно вставить некоторые свои данные, я их отметил красным.- путь к EXE-шнику: \WordSearcher\WordSearcher\bin\Debug\ WordSearcher.exeЕсли будут какие-то баги или вопросы, сообщай - исправлю.С уважением, Свирко ЮрийMail: sv1r4.sd@gmail.comPhone: 8-033-63-123-60ЛИСТИНГ ПРОГРАММЫusing System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;namespace WordSearcher{public partial class FormMain : Form{/// <summary>/// Флаг разрешения распознавания/// </summary>bool enableRecognize = false;/// <summary>/// Размер битмапа со словом "Указ"/// к этому размеру подгоняются все отсалдьные распознаваемые битмапы/// </summary>private static Size imSize = new Size(65, 25);/// <summary>/// Состояние формы/// </summary>private FormState formState = FormState.Empty;/// <summary>/// Масив битмапов сос словами текста/// </summary>private List<Bitmap> words;/// <summary>/// Объект класса для распознавания(персептрон)/// </summary>private Recognizer r = new Recognizer(imSize, 750, 2);/// <summary>/// Метод для делания активными неактивными кнопок управления/// в зависимости от этапа обработк изображения/// </summary>/// <param name="fs">текущее состояние</param>private void ButtonsEnabled(FormState fs){formState = fs;switch (fs){case FormState.Empty:buttonOpen.Enabled = true;buttonSegment.Enabled = false;buttonRecognize.Enabled = false;buttonTeach.Enabled = false;buttonLoadTeaching.Enabled = false;buttonSaveTeaching.Enabled = false;pictureBoxMain.Image = null;dataGridViewSegments.Rows.Clear();break;case FormState.Open:buttonOpen.Enabled = true;buttonSegment.Enabled = true;buttonRecognize.Enabled = false;buttonTeach.Enabled = false;buttonLoadTeaching.Enabled = false;buttonSaveTeaching.Enabled = false;dataGridViewSegments.Rows.Clear();break;case FormState.Segmented:buttonOpen.Enabled = true;buttonSegment.Enabled = true;if (enableRecognize)buttonRecognize.Enabled = true;elsebuttonRecognize.Enabled = false;buttonTeach.Enabled = true;buttonLoadTeaching.Enabled = true;buttonSaveTeaching.Enabled = false;break;case FormState.Teached:buttonOpen.Enabled = true;buttonSegment.Enabled = false;buttonRecognize.Enabled = true;buttonTeach.Enabled = false;buttonLoadTeaching.Enabled = false;buttonSaveTeaching.Enabled = true;enableRecognize = true;break;case FormState.Deserialized:buttonOpen.Enabled = true;buttonSegment.Enabled = false;buttonRecognize.Enabled = true;buttonTeach.Enabled = false;buttonLoadTeaching.Enabled = false;buttonSaveTeaching.Enabled = true;enableRecognize = true;break;case FormState.Recognized:buttonOpen.Enabled = true;buttonSegment.Enabled = false;buttonRecognize.Enabled = true;buttonTeach.Enabled = false;buttonLoadTeaching.Enabled = true;buttonSaveTeaching.Enabled = true;break;}}public FormMain(){InitializeComponent();}private void buttonOpen_Click(object sender, EventArgs e){try{Bitmap b;if (openFileDialog1.ShowDialog() == DialogResult.OK)else{this.ButtonsEnabled(FormState.Empty);}}catch (Exception ex){MessageBox.Show(ex.Message);}}private void buttonSegment_Click(object sender, EventArgs e){//Получаем набор битмапов соответствующих словам текстаwords = Segmentation.GetWords((Bitmap)pictureBoxMain.Image);dataGridViewSegments.RowCount = words.Count;int i =0;//Перебираем слов и отображаем в таблицеforeach (Bitmap word in words){dataGridViewSegments.Rows[i].Cells[0].Value = word;i++;}ButtonsEnabled(FormState.Segmented);}private void buttonRecognize_Click(object sender, EventArgs e){int i = 0;foreach (Bitmap word in words){dataGridViewSegments.Rows[i].Cells[1].Value = r.Recognize(Recognizer.NormalizeBitmap(word,imSize));i++;}ButtonsEnabled(FormState.Recognized);}private void buttonTeach_Click(object sender, EventArgs e){//Перебираем слова и обучаем ими//т.к. класса для распознаваня два то//первый класс обучаем просто изображение слова//а второй обучаем противопорложным изображение(т.е инвертируем цвета исходного изображения)for (int i = 0; i < 5; i++){foreach (Bitmap word in words){r.Teach(Recognizer.NormalizeBitmap(word, imSize), 0);r.Teach(Recognizer.InverseBitmap(Recognizer.NormalizeBitmap(word, imSize)), 1);}}ButtonsEnabled(FormState.Teached);}private void buttonSaveTeaching_Click(object sender, EventArgs e){r.SerializeParams();ButtonsEnabled(FormState.Serialized);}private void buttonLoadTeaching_Click(object sender, EventArgs e){r.DeserializeParams();ButtonsEnabled(FormState.Deserialized);}private void FormMain_Load(object sender, EventArgs e){this.ButtonsEnabled(FormState.Empty);}}// <summary>/// Состояния изображения/// </summary>enum FormState{/// <summary>/// изображение не открыто/// </summary>Empty,/// <summary>/// Изображение открыто/// </summary>Open,/// <summary>/// Сегментировано/// </summary>Segmented,/// <summary>/// Персептрон обучен/// </summary>Teached,/// <summary>/// Параметры персептрона сохранены/// </summary>Serialized,/// <summary>/// Параметры персептрона загружены/// </summary>Deserialized,/// <summary>/// Распознано/// </summary>Recognized}}using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Drawing;using System.Windows.Forms;using System.IO;using System.Runtime.Serialization.Formatters.Binary;namespace WordSearcher{/// <summary>/// Реализует распозноание изображений/// на базе персептрона/// </summary>class Recognizer{/// <summary>/// матрица знаков входов персептрона/// </summary>private int[,] xa;/// <summary>/// Массив лямд/// </summary>private int[,] l;/// <summary>/// Массив имен классов/// </summary>private string[] classes = {"Указ","Не указ"};/// <summary>/// Массив имен классов/// </summary>public string[] ClassesList{get { return classes; }}/// <summary>/// Инициализирует xa-матрицу/// </summary>/// <param name="sz">размер изображения</param>/// <param name="aCount">количесвто а-элементов</param>/// <param name="lCount">количесвто классов</param>public Recognizer(Size sz, int aCount, int lCount){Random r = new Random();//Создание матрцы хаxa = new int[sz.Height * sz.Width, aCount];//Создание матрицы лямдl = new int[lCount,aCount];//Первоначальная//иницализация лямд еденицамиfor (int i = 0; i < l.GetLength(0); i++){for (int j = 0; j < l.GetLength(1); j++){l[i, j] = 1;}}//заполнение матрицы//для каждого рецептора(строчки)//назначаетя только один а-элемент(столбец) со знаком + или -for (int i = 0; i < xa.GetLength(0); i++){xa[i, r.Next(aCount)] = (int)Math.Pow(-1, r.Next(1, 3));}}/// <summary>/// Обучение персептрона/// </summary>/// <param name="b">битмап для обучения</param>/// <param name="classindex">имя класса к ккоторому относиться изображение</param>public void Teach(Bitmap b, int classindex){int[] x = new int[b.Height * b.Width];int k = 0;//Инициализация входных рецепторовfor (int i = 0; i < b.Width; i++){for (int j = 0; j < b.Height; j++){if (b.GetPixel(i, j) == Color.FromArgb(0, 0, 0))x[k] = 1;k++;}}//Вектор сумм рецепторовint[] sumx = new int[xa.GetLength(1)];//Вектор выходов А-элементовint[] outa = new int[xa.GetLength(1)];//суммирование сигналов от рецепторовfor (int i = 0; i < xa.GetLength(1); i++){for (int j = 0; j < xa.GetLength(0); j++){sumx[i] += x[j] * xa[j, i];}//Если сумма больше нуля выход а элемента 1if (sumx[i] > 0)outa[i] = 1;}//изменение коэфициетов лямдаfor (int i = 0; i < outa.Length; i++){//Если а-элемент возбужден то изменяем лямдыif (outa[i] == 1){//перебор всех классовfor (int j = 0; j < l.GetLength(0); j++){//Увеличение на 1 лямд для класса который обучается//и уменьшение для всех осатльныхif (classindex == j)l[j, i]++;elsel[j, i]--;}}}}/// <summary>/// Распознавание изобржения/// </summary>/// <param name="b">битмап изображения</param>/// <returns>имя класса к которому отнесено изображение</returns>public string Recognize(Bitmap b){int[] x = new int[b.Height * b.Width];int k = 0;//Инициализация входных рецепторовfor (int i = 0; i < b.Width; i++){for (int j = 0; j < b.Height; j++){if (b.GetPixel(i, j) == Color.FromArgb(0, 0, 0))x[k] = 1;k++;}}//Вектор суммрецепторовint[] sumx = new int[xa.GetLength(1)];//Вектор выходов А-элементовint[] outa = new int[xa.GetLength(1)];//суммирование сигналов от рецепторовfor (int i = 0; i < xa.GetLength(1); i++){for (int j = 0; j < xa.GetLength(0); j++){sumx[i] += x[j] * xa[j, i];}//Если сумма больше нуля выход а элемента 1if (sumx[i] > 0)outa[i] = 1;}//Создание масива значений сумматоров//каждый для отдельного классаint[] sum = new int[l.GetLength(0)];//Нахождение значений сумматоров для каждого классаfor (int i = 0; i < sum.Length; i++){for (int j = 0; j < xa.GetLength(1); j++){sum[i] += outa[j] * l[i, j];}}//нахождение максимального значения сумматор//именно оно соответствует распознанному классуint max = sum[0];int maxindex = 0;for (int i = 1; i < sum.Length; i++){if (max < sum[i]){max = sum[i];maxindex = i;}}//Возвращается имя класса с максимальным значением сумматораreturn classes[maxindex];}/// <summary>/// Сериализация массива лямд(сохранение в файл) для сохранения обученяи персептрона/// </summary>public void SerializeParams(){try{BinaryFormatter bf = new BinaryFormatter();FileStream fs = new FileStream("l.dat", FileMode.Create);bf.Serialize(fs, l);fs.Close();bf = new BinaryFormatter();fs = new FileStream("xa.dat", FileMode.Create);bf.Serialize(fs, xa);fs.Close();}catch (Exception ex){MessageBox.Show(ex.Message);}}/// <summary>/// Десериализация массива лямд(чтение из файла)/// </summary>public void DeserializeParams(){try{BinaryFormatter bf = new BinaryFormatter();FileStream fs = new FileStream("l.dat", FileMode.Open);l = (int[,])bf.Deserialize(fs);fs.Close();bf = new BinaryFormatter();fs = new FileStream("xa.dat", FileMode.Open);xa = (int[,])bf.Deserialize(fs);fs.Close();}catch (Exception ex){MessageBox.Show(ex.Message);}}/// <summary>/// Подгонка битмапа по размеру и его бинаризация/// </summary>/// <param name="b">входной битмап</param>/// <param name="sz">новый размер битмапа</param>/// <returns>нормализованный битмап</returns>public static Bitmap NormalizeBitmap(Bitmap b, Size sz){//Подгонка размераBitmap inImg = new Bitmap(b, sz);//Создание выходного битмапа на основе подогнанногоBitmap outImg = new Bitmap(inImg);//находим среднее значение яркостиint sum = 0;for (int i = 0; i < outImg.Width; i++){for (int j = 0; j < outImg.Height; j++){Color cl = ((Bitmap)inImg).GetPixel(i,j);sum += (cl.R + cl.G + cl.B) / 3;}}int sredn = sum / (inImg.Width * inImg.Height);//Просматриваем изображнеи и бинаризуем егоfor (int i = 0; i < outImg.Width; i++){for (int j = 0; j < outImg.Height; j++){Color cl = ((Bitmap)inImg).GetPixel(i,j);int gray = (cl.R + cl.G + cl.B) / 3;if (gray > sredn)outImg.SetPixel(i, j, Color.FromArgb(255, 255, 255));elseoutImg.SetPixel(i, j, Color.FromArgb(0, 0, 0));}}return outImg;}/// <summary>/// Инверсия цвета битмапа/// </summary>/// <param name="b"></param>/// <returns></returns>public static Bitmap InverseBitmap(Bitmap b){Bitmap outImg = new Bitmap(b.Width, b.Height);for (int i = 0; i < b.Width; i++){for (int j = 0; j < b.Height; j++){Color c = b.GetPixel(i,j);outImg.SetPixel(i, j, Color.FromArgb(255 - c.R, 255 - c.G, 255 - c.B));}}return outImg;}}}using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Drawing;namespace WordSearcher{class Segmentation{/// <summary>/// Разбиение битмапа с текстоми на строки/// </summary>/// <param name="b">исходный битмап</param>/// <returns>коллекция строк</returns>public static List<Bitmap> GetStrings(Bitmap text){List<Bitmap> strs = new List<Bitmap>();List<int> whiteLineIndexes = new List<int>();//Находим все белые горзонатльные линии на ихображении//и запоминаем их индексыfor (int j = 0; j < text.Height; j++){bool whiteLineFound = true;for (int i = 0; i < text.Width; i++){if (text.GetPixel(i, j) != Color.FromArgb(255, 255, 255)){whiteLineFound = false;break;}}if (whiteLineFound)whiteLineIndexes.Add(j);}//Выделение строк между белыми несоседними линиямиfor (int i = 0; i < whiteLineIndexes.Count-1; i++){if (whiteLineIndexes[i + 1] - whiteLineIndexes[i] > 4){strs.Add(text.Clone(new Rectangle(0,whiteLineIndexes[i],text.Width,whiteLineIndexes[i + 1] - whiteLineIndexes[i]+1),System.Drawing.Imaging.PixelFormat.Format24bppRgb));}}return strs;}/// <summary>/// Получить список слов отдельной строки/// </summary>/// <param name="str">битмап со строкой текста</param>/// <returns>спсиок слов строки</returns>public static List<Bitmap> GetStringWords(Bitmap str){List<Bitmap> words = new List<Bitmap>();List<int> whiteLineIndexes = new List<int>();//Находим все белые вертикальные линии на изображении//и запоминаем их индексыfor (int i = 0; i < str.Width; i++){bool whiteLineFound = true;for (int j = 0; j < str.Height; j++){if (str.GetPixel(i, j).R < 100){whiteLineFound = false;break;}}if (whiteLineFound)whiteLineIndexes.Add(i);}//Ширина пробелаint spaceWidth = 0;int sum = 0;int n = 0;//Вычисление ширины пробелаfor (int i = 0; i < whiteLineIndexes.Count - 1; i++){int d = whiteLineIndexes[i + 1] - whiteLineIndexes[i];if (d > 1){sum += d;n++;}}//Ширина пробела необходимо при дальнейшем выделении слов//коэф. подобран вручнуюspaceWidth = (int)Math.Round(sum * 0.45 / n + 0.1);//начальная координата словаint wordBegin = 0;//конечная координат словаint wordEnd = 0;//флаг указывающий на то найденно ли начало слова или нет//перволдится обратно в фолс после нахождения конца словаbool wordFound = false;//Счетчик ширины белой полоскиint whiteWidth = 0;//Выделение словfor (int i = 0; i < whiteLineIndexes.Count - 1; i++){//если линии не соседние и флаг wordFound фолс т.е.//слово еще не найдено//запоминаем координату певрой линии это будет//координатой началом словаif ((whiteLineIndexes[i + 1] - whiteLineIndexes[i] > 1) &&!wordFound){//обнуление счетчика идущих подряд белыхз линийwhiteWidth = 0;//флаг найденного слова в труwordFound = true;//инициализируем начальную координату словаwordBegin = whiteLineIndexes[i];}//инициализируем конечную координату слова//если найдены не сосдение линии//но не обрезаем битмап и не добавлям его в коллекцию//т.к. необходисмо зделать проверку на ширину пробелаif ((whiteLineIndexes[i + 1] - whiteLineIndexes[i] > 1) &&wordFound){whiteWidth = 0;wordEnd = whiteLineIndexes[i + 1];}//Если найденны соседние белые линии//инкремируем счетчик белых линий и сравниваем ширину идущих подрд белых линий//с ранее высчитаной средней шириной пробелаif (whiteLineIndexes[i + 1] - whiteLineIndexes[i] == 1){whiteWidth++;if ((whiteWidth >= spaceWidth) &&(wordEnd - wordBegin > 1)){//Обрезаем и добавляем слово в коллекциюwords.Add(TrimBitmap(str.Clone(new Rectangle(wordBegin,0,wordEnd - wordBegin + 1,str.Height),System.Drawing.Imaging.PixelFormat.Format24bppRgb)));//обнуляем счетчики//и флагиwhiteWidth = 0;wordFound = false;wordBegin = 0;wordEnd = 0;}}}return words;}/// <summary>/// Получить битмапы всех слов в тексте/// </summary>/// <param name="text">битмап с текстом</param>/// <returns>коллекция всех слов в тексте</returns>public static List<Bitmap> GetWords(Bitmap text){List<Bitmap> strs = GetStrings(text);List<Bitmap> words = new List<Bitmap>();foreach (Bitmap str in strs){foreach (Bitmap word in GetStringWords(str)){words.Add(word);}}return words;}/// <summary>/// Обрезка белых полей вокруг изображения на битмапе/// </summary>/// <param name="bmp"></param>/// <returns></returns>public static Bitmap TrimBitmap(Bitmap bmp){int left = 0;int right = 0;int top = 0;int bottom = 0;bool go = true;//проход сверхуfor (int j = 0; (j < bmp.Height) && go; j++){for (int i = 0; (i < bmp.Width) && go; i++){if (bmp.GetPixel(i, j) != Color.FromArgb(255, 255, 255)){go = false;top = j;}}}go = true;//проход снизуfor (int j = bmp.Height - 1; (j >= 0) && go; j--){for (int i = 0; (i < bmp.Width) && go; i++){if (bmp.GetPixel(i, j) != Color.FromArgb(255, 255, 255)){go = false;bottom = j;}}}go = true;//проход слеваfor (int i = 0; (i < bmp.Width) && go; i++){for (int j = 0; (j < bmp.Height) && go; j++){if (bmp.GetPixel(i, j) != Color.FromArgb(255, 255, 255)){go = false;left = i;}}}go = true;//проход спарваfor (int i = bmp.Width - 1; (i >= 0) && go; i--){for (int j = 0; (j < bmp.Height) && go; j++){if (bmp.GetPixel(i, j) != Color.FromArgb(255, 255, 255)){go = false;right = i;}}}return bmp.Clone(new Rectangle(left, top, right - left + 1, bottom - top + 1), System.Drawing.Imaging.PixelFormat.Format24bppRgb);}}}ОПИСЬ ЛИСТОВ ГРАФИЧЕСКОЙ ЧАСТИЛист 1 - Схема приложенияФункциональная схема приложения Лист 2 - Диаграмма классовЛист 3 - Результаты работы программы.Лист 4 - Схема алгоритма сегментации текста.
Страницы: 1, 2
|
|
|
© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент. |
|
|