车牌定位算法在车牌识别技术中占有很重要地位,一个车牌识别系统的识别率往往取决于车牌定位的成功率及准确度。
车牌定位有很多种算法,从最简单的来,车牌在图像中一般被认为是长方形,由于图像摄取角度不同也可能是四边形。我们可以使用OpenCV中的实例: C:\\Program Files\\OpenCV\\samples\\c.squares.c 这是一个搜索图片中矩形的一个算法。我们只要稍微修改一下就可以实现定位车牌。
在这个实例中使用了canny算法进行边缘检测,然后二值化,接着用
cvFindContours搜索轮廓,最后从找到的轮廓中根据角点的个数,角的度数和轮廓大小确定,矩形位置。以下是效果图:
这个算法可以找到一些车牌位置,但在复杂噪声背景下,或者车牌图像灰度与背景相差不大就很难定位车牌
所以我们需要寻找更好的定位算法。下面是squares的代码: 1. 2.
#ifdef _CH_
#pragma package
3. #endif 4.
5. #ifndef _EiC 6. #include \
7. #include \8. #include
13. int thresh = 50; 14. IplImage* img = 0; 15. IplImage* img0 = 0;
16. CvMemStorage* storage = 0; 17. CvPoint pt[4];
18. const char* wndname = \19.
20. // helper function:
21. // finds a cosine of angle between vectors 22. // from pt0->pt1 and from pt0->pt2
23. double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 ) 24. {
25. double dx1 = pt1->x - pt0->x; 26. double dy1 = pt1->y - pt0->y; 27. double dx2 = pt2->x - pt0->x; 28. double dy2 = pt2->y - pt0->y;
29. return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); 30. } 31.
32. // returns sequence of squares detected on the image.
33. // the sequence is stored in the specified memory storage 34. CvSeq* findSquares4( IplImage* img, CvMemStorage* storage ) 35. {
36. CvSeq* contours; 37. int i, c, l, N = 11;
38. CvSize sz = cvSize( img->width & -2, img->height & -2 );
39. IplImage* timg = cvCloneImage( img ); // make a copy of input image
40. IplImage* gray = cvCreateImage( sz, 8, 1 );
41. IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );
42. IplImage* tgray;
43. CvSeq* result; 44. double s, t;
45. // create empty sequence that will contain points - 46. // 4 points per square (the square's vertices)
47. CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage ); 48.
49. // select the maximum ROI in the image
50. // with the width and height divisible by 2
51. cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height )); 52.
53. // down-scale and upscale the image to filter out the noise
54. cvPyrDown( timg, pyr, 7 ); 55. cvPyrUp( pyr, timg, 7 );
56. tgray = cvCreateImage( sz, 8, 1 ); 57.
58. // find squares in every color plane of the image 59. for( c = 0; c < 3; c++ ) 60. {
61. // extract the c-th color plane 62. cvSetImageCOI( timg, c+1 ); 63. cvCopy( timg, tgray, 0 ); 64.
65. // try several threshold levels 66. for( l = 0; l < N; l++ ) 67. {
68. // hack: use Canny instead of zero threshold level.
69. // Canny helps to catch squares with gradient shading 70. if( l == 0 ) 71. {
72. // apply Canny. Take the upper threshold from slider 73. // and set the lower to 0 (which forces edges merging) 74. cvCanny( tgray, gray,60, 180, 3 );
75. // dilate canny output to remove potential 76. // holes between edge segments 77. cvDilate( gray, gray, 0, 1 ); 78. } 79. else 80. {
81. //apply threshold if l!=0:
82. //tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
83. //cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );
84. cvThreshold( tgray, gray, 50, 255, CV_THRESH_BINARY ); 85. } 86.
87. // find contours and store them all as a list
88. cvFindContours( gray, storage, &contours, sizeof(CvContour),
89. CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) ); 90. 91.
92. // test each contour 93. while( contours ) 94. {
95. // approximate contour with accuracy proportional 96. // to the contour perimeter 97.
result = cvApproxPoly( contours, sizeof(CvContour), storage, 98. CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );
99. // square contours should have 4 vertices after approximation
100. // relatively large area (to filter out noisy contours) 101. // and be convex.
102. // Note: absolute value of an area is used because
103. // area may be positive or negative - in accordance with the
104. // contour orientation 105. if( result->total == 4 &&
106. fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 && 107. cvCheckContourConvexity(result) ) 108. {
109. s = 0; 110.
111. for( i = 0; i < 5; i++ ) 112. {
113. // find minimum angle between joint 114. // edges (maximum of cosine) 115. if( i >= 2 ) 116. {
117. t = fabs(angle(
118. (CvPoint*)cvGetSeqElem( result, i ), 119. (CvPoint*)cvGetSeqElem( result, i-2 ), 120. (CvPoint*)cvGetSeqElem( result, i-1 )));
121. s = s > t ? s : t; 122. } 123. } 124. 125.
126. // if cosines of all angles are small 127. // (all angles are ~90 degree) then write quandrange
128. // vertices to resultant sequence 129. if( s < 0.3 )
130. for( i = 0; i < 4; i++ ) 131. cvSeqPush( squares,
132. (CvPoint*)cvGetSeqElem( result, i ));
133. } 134.
135. // take the next contour 136. contours = contours->h_next; 137. } 138. } 139. } 140.
141. // release all the temporary images 142. cvReleaseImage( &gray ); 143. cvReleaseImage( &pyr ); 144. cvReleaseImage( &tgray ); 145. cvReleaseImage( &timg ); 146.
147. return squares; 148. } 149. 150.
151. // the function draws all the squares in the image 152. void drawSquares( IplImage* img, CvSeq* squares ) 153. {
154. CvSeqReader reader;
155. IplImage* cpy = cvCloneImage( img ); 156. int i; 157.
158. // initialize reader of the sequence 159. cvStartReadSeq( squares, &reader, 0 ); 160.
161. // read 4 sequence elements at a time (all vertices of a square)
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库OpenCV下车牌定位算法实现代码(一)在线全文阅读。
相关推荐: