Jump to content
Compvision.ru
K0rG

Распознавание номерного знака, расп. текста.

Recommended Posts

Привет народ!) Разрабатываю систему распознавания автомобильных номерных знаков, использую библиотеку OpenCV.

Алгоритм пока, что прост)...

1. Программа находит все прямоугольные элементы на фотографии (за основу взят стандартный пример из сэмплов по обнаружению парямоугольников)

2. Бинаризация изображений (т.е бинаризуются все найденые прямоугольные области функцией Threeshold)

3. Анализ каждого прямоугольника на кол-во белого цвета (Таким способом выявляется прямоугольник с номерным знаком)

4. Сегментация прямоугольника с номером

5. Распознавание символов.

Итак вопросы следующие:

1. Как можно обращаться к бинаризованному изображению попиксельно?...никак не могу въехать(

2. Прямоугольники, которые были получены, хранятся в CvSeq*.Как можно вывести изображения находящееся в области каждого прямоугольника?

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

void SearchNumber( IplImage* img, CvSeq* squares ) // CvSeq хранит данные о контуре 

{

   char* NameWnd2 = "Nomer";

   cvNamedWindow( "Nomer", CV_WINDOW_AUTOSIZE );

	CvSeqReader reader;

	IplImage* cpy = cvCloneImage( img );

	int i,j;

   CvPoint pt1;

   CvFont font;

   CvSize text_size;

   pt1.x = 100;

   pt1.y = 100;

   cvInitFont( &font, CV_FONT_HERSHEY_COMPLEX, 0.5, 0.5, 0.0, 0, CV_AA );

   cvGetTextSize( "1", &font, &text_size, 0 );

	// initialize reader of the sequence

	cvStartReadSeq( squares, &reader, 0 );

  //  cvSeqRemove( squares, 10);

	// читать 4 последовательности элементов (все вершины)

	for( i = 0; i < squares->total; i += 4 )

	{

		CvPoint pt[4], *rect = pt; // Массив точек массива контура

		int count = 4;


		// Читать 4 вершины

		CV_READ_SEQ_ELEM( pt[0], reader ); //

		CV_READ_SEQ_ELEM( pt[1], reader ); // Считывание точек вершин

		CV_READ_SEQ_ELEM( pt[2], reader ); //

		CV_READ_SEQ_ELEM( pt[3], reader ); //


 //Поиск вершин по которым будут строится новый квадрат изображения

	  int c,gip,max,min;

	  max=0;

	  min=10000;

	  CvPoint MaxPoint;

	  CvPoint MinPoint;

	  MaxPoint.x=1; MaxPoint.y=1;

	  MinPoint.x=1; MinPoint.y=1;


////Далее собсно идет мой алгоритм поиска двух вершин по которым будет строится область ROI ....

////Алгоритм крив и косячен до ужоса >_<   Может есть какая-то функция заменяющая весь этот ужс???)


		   for( j=0; j<4; j++ )

		 {		 

			 gip= (int)sqrt ((double)((pt[j].x)*(pt[j].x)+(pt[j].y)*(pt[j].y)));


			   if ((gip > max)&&((pt[j].y)>(MaxPoint.y))) 

			{

			   max = gip;

			   MaxPoint = pt[j];

			} 


			if ((gip < min)&&((pt[j].y)<(MaxPoint.y)))

			{

			   min = gip;

			   MinPoint = pt[j];

			}

			printf("(%d,%d)\n", pt[j].x, pt[j].y );

			printf("Gipotinuza =   %d,\n",gip);

		}


		  printf("MaX =  %d,%d\n",MaxPoint.x,MaxPoint.y);

				printf("MiN =  %d,%d\n",MinPoint.x,MinPoint.y);


		 cvSetImageROI(img, cvRect(MinPoint.x,MinPoint.y,MaxPoint.x,MaxPoint.y));


						 ////Запись квадрата в память как JPG вайл

			char buffer[50];										  

			itoa(i,buffer,10);	   

			strcat(buffer,".jpg");

			printf("Imia Faila: %s\n", buffer);	

			 if(!cvSaveImage(buffer, img))	  

			 {

			   printf("Невозможно записать файл изображения\n");

			 }


		 cvShowImage( NameWnd2, img );

		 cvResetImageROI(img);


		  printf("************************\n");


		 /////Вывод номеров вершин

		 for( j=0; j<4; j++ ) 

		 {		 

		 char buffer[50];										  

		 itoa(j+1,buffer,10);	   

		 cvPutText(cpy, buffer, pt[j], &font, CV_RGB(255,1,1));

		 }

   }


	// Вывод изображения

	cvShowImage( wndname, cpy );

	cvReleaseImage( &cpy ); //Освобождение памяти

}

Очень надеюсь на вашу помощ... :(

Share this post


Link to post
Share on other sites

Для начала гляньте топик "Картинка в картинке". И вопрос, а для чего попиксельный доступ?

В другом топике есть такое (не проверял): "Удобно использовать макросы: CV_IMAGE_ELEM(img, uchar, i, j) "

И пара моих заметок:

Лучше координаты точек перед вычислением диагоналей присвоить переменным типа double, а не приводить типы, во всяком случае, не так как у Вас (может быть переполнение).

Для определения диагонали sqrt можно не брать.

Share this post


Link to post
Share on other sites

Большое спасибо за быстрый и грамотный ответ!) "Картинку в картинке" вечером обязательно изучу, думаю это то что надо)Попиксельная обработка мне нужна для того чтобы реализовать распознавание символов, распознавание решил сделать на основе нейронной сети обратного распространения ошибки т.к. есть небольшой опыт работы с ней.... Может быть есть какие-то способы попроще организовать распознавание, средствами OpenCV ??? Использование нескольких способов распознавания мне не повредит)

Share this post


Link to post
Share on other sites
Большое спасибо за быстрый и грамотный ответ!) "Картинку в картинке" вечером обязательно изучу, думаю это то что надо)Попиксельная обработка мне нужна для того чтобы реализовать распознавание символов, распознавание решил сделать на основе нейронной сети обратного распространения ошибки т.к. есть небольшой опыт работы с ней.... Может быть есть какие-то способы попроще организовать распознавание, средствами OpenCV ??? Использование нескольких способов распознавания мне не повредит)

Здесь пример на OpenCV (практически Ваша задача :( ): OpenCV OCR

Документ с задачей аналогичной Вашей здесь (нейросети): Распознавание образов (букв)

Посмотрите вот это еще: Метод распознавания лиц, думаю что для данной задачи его можно приспособить. Не знаю насколько он применяется для этого, но думаю что должен работать.

Share this post


Link to post
Share on other sites

Большущее спасибо, буду изучать!!!)Как только закончу обязательно выложу исходники)Надеюсь кому-то пригодятся)

Share this post


Link to post
Share on other sites
Большущее спасибо, буду изучать!!!)Как только закончу обязательно выложу исходники)Надеюсь кому-то пригодятся)

Удачи :(

Share this post


Link to post
Share on other sites

Чет не пойму...опробовал функцию CV_IMAGE_ELEM(img, uchar, y, x)

#include "stdafx.h"

#include <cxcore.h>

#include <cv.h>

#include <highgui.h>


int main(int argc, char** argv)

{

IplImage* img = cvLoadImage("BlonD.jpg");


char* NameWnd1 = "IMAGE";


cvNamedWindow( "IMAGE", CV_WINDOW_AUTOSIZE );


for (int y=0; y<30; y++)

 {

	for (int x=0; x<30; x++)

	 {


		printf("%d ",CV_IMAGE_ELEM(img, uchar, y, x));


	 }

 printf("\n");

 }


cvShowImage( NameWnd1, img );

cvWaitKey(0);

cvDestroyWindow(NameWnd1);

return 0;

}

Опробовал на двухцветном изображении (ЧБ), считывал только участок 30 на 30... выдает только значение 255.....Может я что - то не так понял...может нужно в CvMat переводить..может можно вообще как-то проще по пикселям обрабатывать...что-то я совсем запутался(((

Share this post


Link to post
Share on other sites

Загружаемое из файла изображение 3х канальное

I(x,y)blue ~ CV_IMAGE_ELEM( img, uchar, y, x*3);

I(x,y)green ~ CV_IMAGE_ELEM( img, uchar, y, x*3+1);

I(x,y)red ~ CV_IMAGE_ELEM( img, uchar, y, x*3+2);

Если не заработает, то так:

I(x,y)blue ~ ((uchar*)(img->imageData + img->widthStep*y))[x*3]

I(x,y)green ~ ((uchar*)(img->imageData + img->widthStep*y))[x*3+1]

I(x,y)red ~ ((uchar*)(img->imageData + img->widthStep*y))[x*3+2]

или так:

uchar *data;

cvGetRawData(img, (uchar**)&data);

I(x, y) = data[x*img->Width + y]

Share this post


Link to post
Share on other sites

Большое спасибо!Разобрался)

Правда назрел еще один вопрос...Пытаюсь средствами MFC осуществить поиск и выбор файла, выглядит это примерно так:

CString fname;  //Переменная для хранения имени файла

  CFile file;		//обьект класса CFile		


	CFileDialog dlgOpen(TRUE, L"txt",L"", 

	OFN_HIDEREADONLY, L" JPEG(*.JPG;*.JPEG;*.JPE)| *.jpg|BMP(*.BMP;*.RLE;*.DIB)| *.bmp| PNG(*.PNG)|*.png| TIFF(*.TIF;*.TIFF)|*.tif| ALL	 

		Formats(*.*)|*.*|", this);


	if(dlgOpen.DoModal()==IDOK)

	{

		  fname = dlgOpen.GetPathName();

	}

	else

	return;


char* FailDir = fname;   //Проблемная строка

Выдает ошибку: cannot convert from 'CString' to 'char *'

Мало того даже если убрать проблемную строчку и написать char* FailDir = "Имя файла.жпег"; и вызвать, заранее написанную функцию, вывода изображения средствами OpenCV, выводится почему-то пустое серое окно.... А если не вызывать до этого окно поиска файла то все отображается отлично... Вот такие вот странности)

Share this post


Link to post
Share on other sites
Большое спасибо!Разобрался)

Правда назрел еще один вопрос...Пытаюсь средствами MFC осуществить поиск и выбор файла, выглядит это примерно так:

CString fname;  //Переменная для хранения имени файла
CFile file; //обьект класса CFile

CFileDialog dlgOpen(TRUE, L"txt",L"",
OFN_HIDEREADONLY, L" JPEG(*.JPG;*.JPEG;*.JPE)| *.jpg|BMP(*.BMP;*.RLE;*.DIB)| *.bmp| PNG(*.PNG)|*.png| TIFF(*.TIF;*.TIFF)|*.tif| ALL
Formats(*.*)|*.*|", this);

if(dlgOpen.DoModal()==IDOK)
{
fname = dlgOpen.GetPathName();
}
else
return;

char* FailDir = fname; //Проблемная строка[/code]

Выдает ошибку: cannot convert from 'CString' to 'char *'

Мало того даже если убрать проблемную строчку и написать char* FailDir = "Имя файла.жпег"; и вызвать, заранее написанную функцию, вывода изображения средствами OpenCV, выводится почему-то пустое серое окно.... А если не вызывать до этого окно поиска файла то все отображается отлично... Вот такие вот странности)

Мне кажется, проблема в том, что при вызове окна fname = dlgOpen.GetPathName(); заносит в fname строку типа w_char (два байта на символ), а не char, может нужно просто преобразовать в char? Я не спец по MFC, но вроде там есть функция, типа OEMToChar, или что то в этом роде.

Посмотрел. Есть функция wctomb(char,t_wchar)

Share this post


Link to post
Share on other sites
Подкиньте теорию, плз.

Вот есть ссылочка OpenCV OCR

а тут посерьезнее материальчик: OCR_Systems.pdf

Share this post


Link to post
Share on other sites

Доброе время суток!

Я новичок.

Есть задача: распознать регистрационный номер автомобиля.

Следует ли распознавать сначала саму табличку с номером (распознавание прямоугольников), а потом уже по цвету и пропорциям подбирать нужный прямоугольник. И уже потом разбирать цифры номера.

А если скажем попадется такое - на лобовом стекле: белая бумажка и на нем текст крупными буквами и прочее?

Какие алгоритмы посоветуете? Реализуема ли задача распознавания текста под любым углом?

PS есть ли русская документация по библиотеке opencv? хотя это не критично.

Share this post


Link to post
Share on other sites
Доброе время суток!

Я новичок.

Есть задача: распознать регистрационный номер автомобиля.

Следует ли распознавать сначала саму табличку с номером (распознавание прямоугольников), а потом уже по цвету и пропорциям подбирать нужный прямоугольник. И уже потом разбирать цифры номера.

А если скажем попадется такое - на лобовом стекле: белая бумажка и на нем текст крупными буквами и прочее?

Какие алгоритмы посоветуете? Реализуема ли задача распознавания текста под любым углом?

PS есть ли русская документация по библиотеке opencv? хотя это не критично.

Русский перевод пока застрял :) есть только то что на этом сайте.

В разделе википедии. И в разных постах по чуть-чуть.

Основной кусок перевода здесь: http://www.compvision.ru/forum/index.php?showtopic=7

Share this post


Link to post
Share on other sites

Спасибо, за ссылки!

Как это я не догадался воспользоваться поиском слова "распознавание номера"!? Голова опухла от информации походу...

Share this post


Link to post
Share on other sites

Необходимо распознавать данные с изображений такого вида:

2q9b6ux.jpg

(цифры от 0-9 или одно из значений "lo","hi").

Освещенность и наклон изображения может меняться в небольших пределах.

Думаю делать как написано в вики с ипользованием классификаторов Хаара.

Но может есть способ лучше и надежнее?

Share this post


Link to post
Share on other sites
Необходимо распознавать данные с изображений такого вида:

2q9b6ux.jpg

(цифры от 0-9 или одно из значений "lo","hi").

Освещенность и наклон изображения может меняться в небольших пределах.

Думаю делать как написано в вики с ипользованием классификаторов Хаара.

Но может есть способ лучше и надежнее?

Неплохо бы в кадр и рамку индикатора брать.

Индикатор прямоугольный (во всяком случае его форму мы знаем), зная угловые точки (можно найти в кадре).

По конфигурации трапеции, в которую превратился наш прямоугольник находим преобразование к прямоугольнику с заданными размерами.

Делается при помощи cvFindHomography. описание здесь.

Или, если вариации наклона не сильные, просто преобразовывать масштаб к заданному размеру.

Можно наверное использовать пример с калибровкой камеры.

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

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

Выясняем что написано на индикаторе.

PS: Можно просто перед началом работы включить все сегменты и указать (мышкой) точки для контроля цвета на каждом сегменте :), но это слишком просто :)

Share this post


Link to post
Share on other sites

Как будешь получать изображения? Камера будет висеть на дисплеем?

Для начала я бы сделал картинки с изображением каждой цифры.

Share this post


Link to post
Share on other sites

Если положение дисплея не сильн изменяется, то действительно, определив углы можно преобразовать изображение к прямугольному. А поскольку символы по дисплею не перемещаются то можно разделить полученный прямоуольник на сегменты, содержащие по одноу символу. В каждом сегменте можно выделить по семь областей, соответствующих каждому элементу символа. И простым расчётом среднего значения по области можно определить горит ли данный элемент. А выяснев какие элементы горят а какие нет можно по таблице найти изображённый символ.

По крайней мере почтовые коды с конвертов так читаются без проблем.

Share this post


Link to post
Share on other sites

Добрый день.

В общем прочитал статейку одну про распознавание текста с помощью инвариантных моментов и решил попробовать сделать.

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

Беру 2 изображения.

e100ee22.jpg

86219012.jpg

#include "stdafx.h"

#include <stdio.h>

#include "cv.h"

#include "highgui.h"



int main()

{

CvMemStorage* image_storage = cvCreateMemStorage(0);

CvMemStorage* nomer_storage = cvCreateMemStorage(0);

CvSeq* nomer_contours;

CvSeq* image_contours;


IplImage *image = 0;

image = cvLoadImage( "ex.jpg", 1 );

IplImage *image_gray = cvCreateImage(cvSize(24,42), IPL_DEPTH_8U, 1);

cvCvtColor( image, image_gray, CV_BGR2GRAY );

IplImage *image_canny = cvCreateImage(cvSize(24,42), IPL_DEPTH_8U, 1);

cvCanny( image_gray, image_canny, 50, 255, 3 );


IplImage *nomer = 0;

nomer = cvLoadImage( "E100EE22.jpg", 1 );

IplImage *nomer_gray = cvCreateImage(cvSize(24,42), IPL_DEPTH_8U, 1);

cvCvtColor( nomer, nomer_gray, CV_BGR2GRAY );

IplImage *nomer_canny = cvCreateImage(cvSize(24,42), IPL_DEPTH_8U, 1);

cvCanny( nomer_gray, nomer_canny, 50, 255, 3 );



cvFindContours( nomer_canny, image_storage, &nomer_contours, sizeof(CvContour), CV_RETR_TREE,

			   CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));


cvFindContours( image_canny, nomer_storage, &image_contours, sizeof(CvContour), CV_RETR_TREE,

			   CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));


double match = cvMatchShapes( nomer_contours, image_contours, CV_CONTOURS_MATCH_I3))


cvReleaseImage( &nomer );

cvReleaseImage( &nomer_gray );

cvReleaseImage( &nomer_canny );

cvReleaseImage( &image );

cvReleaseImage( &image_gray );

cvReleaseImage( &image_canny );

cvClearMemStorage( image_storage );

cvClearMemStorage( nomer_storage );

return 0;

}

Share this post


Link to post
Share on other sites

Думается что инвариантные моменты не самый подходящий инструмент для распознавания текста,из-за своей инвариантности к повороту, отражению, и т.д.

Например даже цифры 6 и 9 будут иметь одинаковые характеристики, также Ш, Е , И, N и т.д.

Share this post


Link to post
Share on other sites

Дело в том что я хочу применить этот метод для распознавания автомобильного номерного знака. Насколько я помню в номерном знаке могут присутствовать цифры от 0 до 9 и буквы(А, В, Е, К, М, Н, О, Р, С, Т, У, Х). Проблема возникает тут тока с цифрами 6 и 9, 0 и о. Хотелось бы еще узнать, есть ли какие нить другие методы реализации данной задачи с помощью OpenCV и без использования нейронных сетей.

Share this post


Link to post
Share on other sites
Дело в том что я хочу применить этот метод для распознавания автомобильного номерного знака. Насколько я помню в номерном знаке могут присутствовать цифры от 0 до 9 и буквы(А, В, Е, К, М, Н, О, Р, С, Т, У, Х). Проблема возникает тут тока с цифрами 6 и 9, 0 и о. Хотелось бы еще узнать, есть ли какие нить другие методы реализации данной задачи с помощью OpenCV и без использования нейронных сетей.

Тут может подойти функция cvMatchTemplate.

Тут она используется в детекторе глаз: http://nashruddin.com/Real_Time_Eye_Tracki...Blink_Detection

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

×