Детектирование автомобильных номеров в OpenCV на основе контурного анализа / OpenCV / Recog.ru - Распознавание образов для программистов


Детектирование автомобильных номеров в OpenCV на основе контурного анализа

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

void FoFindBox( IplImage* img, float max_ratio, float min_ratio, int max_area, int min_area, int Min_Lenght_Fo, 
			   CvBox2D* boxes, CvRect *Rects, double* areas, int* all_boxes )
{
	const float Min_Fill_Area = 0.4f;
	 CvMemStorage* storage = cvCreateMemStorage(0);

	 CvSeq* contours = 0;
	 cvFindContours( img, storage, &contours, sizeof(CvContour),
                    CV_RETR_LIST  , CV_CHAIN_APPROX_NONE, cvPoint(0,0) );

	 int all = 0;	 
	 for( CvSeq* c=contours; c!=NULL; c=c->h_next)
	 {
		  CvBox2D b = cvMinAreaRect2( c );		  		  
		  if ( b.size.height < Min_Lenght_Fo || b.size.width < Min_Lenght_Fo || 
			   (b.size.width*b.size.height) < min_area || (b.size.width*b.size.height) > max_area ) continue;		  
		  if ( fabs( cvContourArea( c ) ) / (b.size.width*b.size.height) < Min_Fill_Area ) continue;
		  float ratio = ( (b.size.width < b.size.height)?
                  (float)b.size.width /b.size.height:
                  (float)b.size.height/b.size.width);   
		  if ( ratio < min_ratio || ratio > max_ratio ) continue;
		  

		  boxes[all] = b;
		  Rects[all] = cvBoundingRect( c );
		  ratio = (float) Rects[all].height / Rects[all].width;
		  if ( ratio < min_ratio || ratio > max_ratio ) continue;
		  if ( areas != NULL) areas[all] = cvContourArea©;
		  all++;
		  if ( all >= (*all_boxes) ) {			  
			   break;
		  }
	 }

	 (*all_boxes) = all;

	 cvReleaseMemStorage( &storage); 
}

Вызывать эту функцию в программе будем следующим образом:
IplImage* Img=cvLoadImage(buf,CV_LOAD_IMAGE_GRAYSCALE); // buf – буфер с именем файла
IplImage* Img2=cvCreateImage( cvGetSize(Img), 8, 1);	
IplImage*ImgOut=cvLoadImage(buf);
cvAdaptiveThreshold( Img, Img2, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,15, 0 );
CvBox2D b[1000];
CvRect r[1000];
double a[1000];
int all = 1000;
FoFindBox( Img2, 0.5f, 0.15f, 25000, 500, 5, b, r, a, &all );
for(j=0;j<all;j++)
	if ( r[j].width > r[j].height )
	cvRectangle(ImgOut,cvPoint(r[j].x,r[j].y),cvPoint(r[j].x+r[j].width,r[j].y+r[j].height),	CV_RGB(255,255,0), 2);

Результат можно посмотреть на следующих картинках:



Однако есть и проблемы:

В этом случае нужно после распознавания буквы и цифр (6 в сумме) продлить границы номера.
После детектирование для каждого кандидата на номер необходимо вызвать функцию распознавания.
В целом использование этой простейшей функции позволяет детектировать 70-80% автомобильных номеров, что однако при построении действующей системы распознавания автомобильных номеров является неудовлетворительным, поэтому необходимо усложнить функцию и/или добавить другой метод детектирования номера.
Одним из явных преимуществ контурного анализа является четко выделенная граница автомобильного номера.
  • 0
  • 14 марта 2013, 09:53
  • vidikon

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

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

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