Перейти к содержимому
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 ); //Освобождение памяти

}

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


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

Удачи :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Чет не пойму...опробовал функцию 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 переводить..может можно вообще как-то проще по пикселям обрабатывать...что-то я совсем запутался(((

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Загружаемое из файла изображение 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]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Правда назрел еще один вопрос...Пытаюсь средствами 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, выводится почему-то пустое серое окно.... А если не вызывать до этого окно поиска файла то все отображается отлично... Вот такие вот странности)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Большое спасибо!Разобрался)

Правда назрел еще один вопрос...Пытаюсь средствами 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)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Подкиньте теорию, плз.

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Я новичок.

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Доброе время суток!

Я новичок.

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

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

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

2q9b6ux.jpg

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Необходимо распознавать данные с изображений такого вида:

2q9b6ux.jpg

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Добрый день.

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

Написал прогу, которая должна находить контуры 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;

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×