The OPENCV code of license plate region extraction using color and morphology two methods

Source: Internet
Author: User
Tags scalar

To get the license plate number , first you have to locate the license plate area , the two methods used in this paper, namely, color and morphology of the method, to determine the license plate area. Said is two methods, in fact, there is no big difference between the two methods, but there is a step to judge the standard is not the same, you see the following the idea of sorting out to know that the difference is really very small.

method One: Using color to extract the car license area of the idea :

① obtains the Sobel edge of the original image Sobelmat

② uses the license plate color threshold to binary image processing in HSV space, and obtains the image bw_blue→

③ from the following criteria to obtain the image Bw_blue_edge

for (int k = 1; k! = Height-2; ++k) {for (int l = 1; L! = width-2; ++l) {Cv::rect rct;rct.x = L-1;rct.y = k-1;rct.he ight = 3;rct.width = 3;if ((sobelmat.at<uchar> (k, l) = = 255) && (Cv::countnonzero (RCT) Bw_blue 1)) >= Blue_edge.at<uchar> (k, l) = 255;}}

④ the morphological closure of the Bw_blue_edge, connecting those small holes, holes, and so on, so that the rectangles in the graph are more like rectangles

⑤ the contour of the connected area to detect, if there is a license plate, the license plate must occupy a contour scatter

⑥ for each contour of the outside of the rectangle, and to detect, so that the most like the area of the license plate detection, according to the following criteria for detection:

for (size_t n = 0; n! = Region_contours.size (); ++n) {//Remove height width does not match the condition area cv::rect Rect = Cv::boundingrect (Region_contours[n]); int sub = Cv::countnonzero (Morph (rect));d ouble ratio = Double (sub)/Rect.area ();d ouble wh_ratio = double (rect.width)/RE Ct.height;if (ratio > 0.5 && wh_ratio > 2 && wh_ratio < 5 &&rect.height > && ; Rect.width >) {cv::mat small = Bw_blue_edge (rect); result = Srcimage (rect); Cv::imshow ("Rect", Srcimage (rect)); CV:: Waitkey (0);}}

From the above process, the specific application, the following statements in the parameters involved in the need to adjust, if not properly set, it is possible to extract the wrong license plate area or can not extract the license plate area. Obviously an example, from the distance between the license plate is different from the size of the license plate area, then rect.height > && rect.width > 60 Such statements must be at any time to tune the line, so, If the problem is not good, this program is not universal, which is one of the biggest flaws of the program.

Cv::countnonzero (Bw_blue (RCT)) >= 1//' 1 ' is a need to adjust according to the application scenario of the body ratio > 0.5 && wh_ratio > 2 && wh_ratio & Lt 5 &&ect.height > && rect.width > 60)//The parameters in this also need to be adjusted according to the application scenario of the body

method Two: The method of license plate extraction using morphological principle :

① Image edge detection using morphological gradient method

② selecting different morphological closed operation Windows according to different graphic sizes closed operations of morphological horizontal and vertical direction

③ the contour of the connected area to detect, if there is a license plate, the license plate must occupy a contour scatter

④ for each contour of the outside of the rectangle, and to detect, so that the most like the area of the license plate detection, according to the following criteria for detection:

for (size_t i = 0; I! = Blue_contours.size (); ++i) {Cv::rect Rect = Cv::boundingrect (Blue_contours[i]);d ouble wh_ratio = do Uble (rect.width)/rect.height;int sub = Cv::countnonzero (Result (rect));d ouble ratio = Double (sub)/Rect.area (); if (wh_r Atio > 2 && wh_ratio < 8 && rect.height > &&rect.width > 0 && ratio > .4) {//blue_rect.push_back (rect); Cv::imshow ("Rect", Srcgray (Rect)); Cv::waitkey (0);}}

As with method one, the parameters in the following sentence of method two also need to be set according to the actual application, if improperly set, it is possible to extract the wrong license plate area or to extract the license plate area. A very obvious example, from the distance between the license plate is different from the size of the license plate area, then rect.height > &&rect.width > 60 and other statements must be at any time to tune the line, so, If the problem is not good, this program is not universal, which is one of the biggest flaws of the program.

Wh_ratio > 2 && wh_ratio < 8 && rect.height > &&rect.width > $ && ratio &G T 0.4

Compare the two methods :

Two methods must first pre-processing the image, in order to remove redundant information, the removal of redundant information, the morphological closed operation, to highlight the target contour, after the contour, then the contour of the external rectangle, the use of the rectangular features of the license plate to detect these external rectangles, in line with the license plate feature is the license plate area. Neither of the two methods can be adaptively adapted to the size of the license plate in the graph due to the distance between shooting distances.

two methods the different parts are : ① method One uses the Sobel to extract the edge, the method two uses the morphological gradient method to extract the edge; The ② method uses the color of the license plate to limit the image after extracting the edge, and the method two does not. ③ method One in the morphological closed operation, not according to the size of the graph to choose a different window, and method two did such a treatment.

the following two methods of the source code is running results :

method One of the source code :

OPENCV version 3.0.0//AC QQ2487872782 #include <iostream> #include <vector> #include <stdint.h> #include " Opencv2/core/core.hpp "#include" opencv2/highgui/highgui.hpp "#include" opencv2/imgproc/imgproc.hpp "#include" OPENCV2/FEATURES2D/FEATURES2D.HPP "//Extract vertical Sobel edge bool Sobelveredge (Cv::mat srcimage, cv::mat& resultimage) {CV_ Assert (srcimage.channels () = = 1); Srcimage.convertto (Srcimage, CV_32FC1);//Sobel operator in horizontal direction cv::mat Sobelx = (cv::mat_< Float> (3, 3) << -0.125, 0, 0.125,-0.25, 0, 0.25,-0.125, 0, 0.125); Cv::mat conresmat;//convolution Operation Cv::filter2d (srcimage , Conresmat, Srcimage.type (), sobelx);//Calculate the amplitude of the gradient Cv::mat gramagmat;cv::multiply (Conresmat, Conresmat, graMagMat);// Set the threshold value int scaleval = 4;double Thresh = scaleval * Cv::mean (Gramagmat) according to the gradient amplitude and parameters. Val[0];cv::mat Resulttempmat = Cv::mat::zero S (gramagmat.size (), Gramagmat.type ()), float* Pdatamag = (float*) gramagmat.data;float* pdatares = (float*) resulttempmat.data;const int nRows = conresmat.rows;const int nCols = conresmat.cols;for (int i = 1; I! = nRows-1; ++i) {for (int j = 1; J! = NCols-1; ++j) {//calculates this point gradient compared to horizontal or vertical gradient values bool B1 = (Pdatama  G[i * nCols + j] > Pdatamag[i *ncols + j-1]); bool B2 = (Pdatamag[i * nCols + j] > Pdatamag[i *ncols + j + 1]); bool B3 = (Pdatamag[i * nCols + j] > pdatamag[(i-1) * nCols + j]); bool B4 = (Pdatamag[i * nCols + j] > pdatamag[(i + 1) * NCols + j]);//Determine if the neighborhood gradient is greater than the horizontal or vertical gradient//and binary according to the adaptive threshold parameter Pdatares[i * nCols + j] = 255 * ((Pdatamag[i *ncols + j] > Thresh ) && ((B1 && b2) | | (B3 && b4));}} Resulttempmat.convertto (Resulttempmat, cv_8uc1); resultimage = Resulttempmat.clone (); return true;} Suspected area extraction Cv::mat Getplatearea (Cv::mat srcimage, Cv::mat sobelmat) {//Convert to HSV Cv::mat Img_h, img_s, Img_v, Imghsv;std::vect Or<cv::mat> Hsv_vec;cv::cvtcolor (Srcimage, IMGHSV, CV_BGR2HSV); Cv::imshow ("HSV", IMGHSV); Cv::waitKey (0);// The HSV-scoped element extracts Cv::mat bw_blue;cv::inrange (Imghsv,cv::scalar (81,38,63), Cv::scalar (135,255,255), bw_blue); int height = Bw_blue.rOws;int width = Bw_blue.cols;cv::mat Bw_blue_edge = Cv::mat::zeros (Bw_blue.size (), Bw_blue.type ()); Cv::imshow ("Bw_ Blue ", bw_blue); Cv::waitkey (0);//license plate suspected area extraction for (int k = 1; k! = Height-2; ++k) {for (int l = 1; L! = width-2; ++l) {Cv::r ECT rct;rct.x = L-1;rct.y = K-1;rct.height = 3;rct.width = 3;if ((sobelmat.at<uchar> (k, l) = = 255) && (c V::countnonzero (Bw_blue (RCT)) >= 1)) bw_blue_edge.at<uchar> (k, l) = 255;}} Morphological closed Operation Cv::mat Morph;cv::morphologyex (Bw_blue_edge, Morph, Cv::morph_close,cv::mat::ones (2, CV_8UC1)); CV:: Imshow ("Bw_blue_edge", Bw_blue_edge); Cv::waitkey (0);//connectivity Area Contour detection cv::imshow ("morph", morph); STD::VECTOR&LT;STD:: VECTOR&LT;CV::P oint> > Region_contours;cv::findcontours (Morph.clone (), region_contours,cv_retr_external, CV_ Chain_approx_simple, CV::P oint (0, 0)), Cv::mat result;for (size_t n = 0; n! = Region_contours.size (); ++n) {//Remove height width does not match the condition area Cv::rect Rect = Cv::boundingrect (Region_contours[n]), int sub = Cv::countnonzero (Morph (Rect));d ouble RATio = Double (sub)/Rect.area ();d ouble wh_ratio = double (rect.width)/rect.height;if (ratio > 0.5 && wh_ratio > 2 && wh_ratio < 5 &&rect.height > && rect.width >) {cv::mat small = Bw_blue_edg E (rect); result = Srcimage (rect); Cv::imshow ("Rect", Srcimage (Rect)); Cv::waitkey (0);}} return result;} int main () {Cv::mat srcimage = Cv::imread ("car.jpg"), if (!srcimage.data) return 1;cv::mat Srcgray;cv::cvtcolor (srcImage , Srcgray, Cv_rgb2gray); Cv::imshow ("Srcimage", srcimage);//Sobel Extract Edge Cv::mat Sobelmat;//sobel (Srcgray, Sobelmat, CV_ 16S, 1, 0, 3, 1, 0, 4);//convertscaleabs (Sobelmat, Sobelmat); Sobelveredge (Srcgray, Sobelmat); Cv::imshow ("Sobel", Sobelmat);//cv::waitkey (0);//suspect area extraction cv::mat result = Getplatearea (Srcimage, Sobelmat); return 0;}

operation result of method one :


method Two of the source code :

OPENCV version 3.0.0//AC QQ2487872782 #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp > #include <opencv2/imgproc/imgproc.hpp> #include <iostream>using namespace Cv;cv::mat getplate (int width, int height, Cv::mat srcgray) {cv::mat result;//morphological gradient detection edge Morphologyex (srcgray, result, Morph_gradient, Mat (1, 2, CV _8u, Scalar (1))); Cv::imshow ("1result", result);//threshold threshold (result, result, 255 * (0.1), 255, thresh_binary); CV:: Imshow ("2result", result);//horizontal direction closed operation if (width >= && width <) Morphologyex (result, result, Morph_clos E, Mat (1, cv_8u, Scalar (1))), else if (width >= && width <) Morphologyex (result, result, Morph_clo SE, Mat (1, cv_8u, Scalar (1))), else if (width >=) morphologyex (result, result, Morph_close, Mat (1,, cv_8u, Sca Lar (1))); Elsemorphologyex (result, result, Morph_close, Mat (1, 1, cv_8u, Scalar));//Vertical closed operation if (height >= & & Height < Morphologyex (result, result, MORph_close, Mat (8, 1, cv_8u, Scalar (1))), else if (height >= && height <) Morphologyex (result, result, Morph_close, Mat (6, 1, cv_8u, Scalar (1))), else if (height >=) Morphologyex (result, result, Morph_close, Mat (Ten, 1, C v_8u, scalar (1))); Elsemorphologyex (result, result, Morph_close, Mat (4, 1, cv_8u, Scalar (1))); return result; int main () {Cv::mat srcimage = Cv::imread ("car.jpg"), if (!srcimage.data) return 1;cv::mat Srcgray;cv::cvtcolor (srcImage , Srcgray, Cv_rgb2gray), Cv::imshow ("Srcgray", Srcgray), cv::mat result = Getplate (+, Srcgray);//connectivity Area Contour Detection std:: VECTOR&LT;STD::VECTOR&LT;CV::P oint> > Blue_contours;std::vector<cv::rect> blue_rect;cv::findContours ( Result.clone (), Blue_contours, Cv_retr_external, Cv_chain_approx_simple, CV::P oint (0, 0));//connected domain Traversal license plate target extraction for (size_t i = 0; I! = Blue_contours.size (); ++i) {Cv::rect Rect = Cv::boundingrect (Blue_contours[i]);d ouble wh_ratio = double (rect.width)/rect.height;int sub = CV:: Countnonzero (Result (rect));d ouble ratio = Double (sub)/Rect.area (); if (Wh_ratio > 2 && wh_ratio < 8 && rect.height > && Amp;rect.width > && Ratio > 0.4) {//blue_rect.push_back (rect); Cv::imshow ("Rect", Srcgray (rect)); CV:: Waitkey (0);}} Cv::imshow ("result", result); Cv::waitkey (0); return 0;}

operation result of method two :


-------------------------------------------
Welcome everyone to join the image recognition technology Exchange Group: 271891601, in addition, the special welcome Chengdu engaged in image recognition work of friends, my QQ number 2487872782


The OPENCV code of license plate region extraction using color and morphology two methods

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.