Распознавание текста с использованием шаблонов / Оптическое распознавание символов / Recog.ru - Распознавание образов для программистов


Распознавание текста с использованием шаблонов

Здесь показано, как распознавать текст с использованием контуров. Однако в случае зашумления и искажения контуров данный метод работает неудовлетворительно. Конечно, известны методы распознавание текста на базе нейронных сетей, но существует ещё более простой метод (в плане обучения), основанный на сравнении с эталоном (шаблоном). В ряде случае сравнение с шаблоном будет достаточно для распознавания текста, например, при распознавании автомобильных номеров.
Предположим на некотором изображении есть текст:


И нам естественно необходимо его распознать. Но первоначально необходимо найти местонахождение букв и цифр. Для этого изображение надо предварительно обработать, а именно – привести изображение к монохромному. В библиотеке OpenCV есть для этого несколько функций: cvThreshold(), cvAdaptiveThreshold(). Данные функции не раз использовались в http://blog.vidikon.com, поэтому не будем останавливаться на них подробнее. Здесь однако стоит отметить, что при работе с изображениями данного типа (с текстом) стоит использовать не адаптивную функцию, а обычную cvThreshold(), впрочем выбирая оптимальный порог, например, используя метод Отсу.
Далее можно выделить контуры с использованием функции cvFindContours() — http://blog.vidikon.com/?p=59. В большинстве случаев будет много всякого шума, но его частично можно удалить, зная приблизительны размеры букв.

После удаления ненужных контуров похожим образом, как показано здесь, останутся нужные контура находимых букв. Используя функцию cvBoundingRect(), получае области нахождения символов.
После этого можно приступать к анализу найденных областей символов, но для этого необходимо составить шаблоны образов. Шаблоны составляются в виде массива, например, как представлено ниже:
-1 ,  1  ,  1  ,  1  ,  -1
1  ,  -1 ,  -1 ,  -1 ,  1
1  ,  -1 ,  -2 ,  -1 ,  -1
1  ,  -1 ,  -2 ,  -2 ,  -2
1  ,  -1 ,  -2 ,  -1 ,  -1
1  ,  -1 ,  -1 ,  -1 ,  1
-1 ,  1  ,  1  ,  1  ,  -1

Как вы уже догадались, это шаблон буквы «C». Для того, чтобы сравнить область изображения с символом необходимо привести эту область к размеру шаблона или наоборот – шаблон к размеру области. Можно просто использовать известные методы увеличения, или написать самому. Ниже представлен листинг, в котором осуществляется приведение к размеру шаблона (в данном случае 5 на 7).
double a[5*7];
double a1[4];
uchar* ptr = (uchar*) (Image->imageData);
int x,y;
int x1,y1;
double x1_,y1_;
int x2,y2;
double x2_,y2_;
...
memset(a,0,5*7*sizeof(double));
for(y=0;y<Rect.height;y++)
	for(x=0;x<Rect.width;x++){
		if (ptr[x+Rect.x+(y+Rect.y)* Image->widthStep]==0) continue;
		memset(a1,0,4*sizeof(double));
		x1_=(double)x*ratioW;
		y1_=(double)y*ratioH;
		x1=int(x1_);y1=int(y1_);
		x2_=(double)(x+1)*ratioW;
		y2_=(double)(y+1)*ratioH;
		x2=int(x2_);y2=int(y2_);
		if (x2==x1) { a1[0]=1;a1[1]=0;}
		else {
			a1[0]=(double)(x1+1-x1_)/(x2_-x1_);
			a1[1]=(double)(x2_-x2)/(x2_-x1_);
		}
		if (y2!=y1){
			a1[2]=(double)a1[0]*(y2_-y2)/(y2_-y1_);
			a1[3]=(double)a1[1]*(y2_-y2)/(y2_-y1_);
			a1[0]=(double)a1[0]*(y1+1-y1_)/(y2_-y1_);
			a1[1]=(double)a1[1]*(y1+1-y1_)/(y2_-y1_);
		}
		a[x1+y1*7]+=a1[0];
		if (x1<4)
			a[x1+1+y1*7]+=a1[1];
		if (y1<6)
			a[x1+(y1+1)*7]+=a1[2];
		if (x1<4 && y1<6)
			a[x1+1+(y1+1)*7]+=a1[3];
	}

В листинге перебираются каждые точки, относящиеся к символу, после чего происходит их отнесение к той или иной ячейки изображения, причем не всегда полностью, но и частично – часть пикселя в одну ячейку, часть в другую. Далее можно сравнить полученный результат с каждым из эталонов, просто перемножив соответствующие элементы матрицы. И по наибольшему совпадению выбрать эталон.
  • 0
  • 14 апреля 2011, 19:30
  • vidikon

Комментарии (0)

RSS свернуть / развернуть

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.