Normalize car label for OCR in OpenCV C ++

I am making a simple OCR car sign recognition system. I use HaarCascades to search for a car plate, and then I need to normalize this plate to put it in my OCR module. I use fill to find the main contours of the car plate, and then I perform a Hough transform to find the upper and lower borders of the car plate:

floodfill

Hough

Here's the piece of code where I do the Hough transform ^

HoughLinesP(canny_img, lines, 1, CV_PI/180, 80, 80, 30 ); for ( size_t i = 0; i < lines.size(); i++ ) { line (output, Point(lines[i][0], lines[i][3]), Point(lines[i][4], lines[i][5]), Scalar(0,0,255), 1, 8 ); } 

Now I need to cut and rotate this image along these two lines. How can i do this? I understand that I need to use point Point (strings [i] [0]). Point (lines i ), but what should I do with them?

Basically, I need to get something like this:

  • The image I got with HaarCascades

enter image description here

  1. After some conversion, I need to get something like this: enter image description here

So, in the first stage, I need to cut only the upper and lower boundaries.

+6
source share
2 answers

You need to use affine transformations, here is tutorial . In your situation, you need to choose some size of the car plate, for example 20x100 . Your destinations will have 3 corners without turning a rectangle of the selected size, and the starting points will be 3 corners of the car plate based. I hope this is clear, if it is not, let me know - I will give an example.

* \\ EDIT:
Ok, I made some examples. Here is the code:

 cv::Mat img = cv::imread("D:\\temp\\car_plate.jpg"); cv::Point2f a1(25, 18), b1(279, 27), c1(279, 79), a2(0, 0), b2(img.size().width, 0), c2(img.size().width, img.size().height); //cv::Point2f a1(0, 16), b1(303, 28), c1(303, 81), a2(0, 0), b2(img.size().width, 0), c2(img.size().width, img.size().height); cv::Point2f src[] = {a1, b1, c1}; cv::Point2f dst[] = {a2, b2, c2}; cv::Mat warpMat = cv::getAffineTransform(src, dst); cv::warpAffine(img, img, warpMat, img.size()); cv::imshow("result", img); cv::waitKey(-1); return 0; 

And the results:
enter image description here
enter image description here
If you use the code without any changes, you will get the first result, if you comment on the second line and uncomment the third line, you will get the second result (I think you wanted). To get the second result, you just need to find the points where the upper and lower lines intersect the border of the image. I noted this here:
enter image description here
So basically you need to use red glasses. To calculate their positions, you just need to find where the blue lines (which, if I understand what you already have) cross the border of the image.

+5
source

Here is the solution with EmguCv:

 var src = new[] { new PointF(approxContour[0].X, approxContour[0].Y), new PointF(approxContour[1].X, approxContour[1].Y), new PointF(approxContour[2].X, approxContour[2].Y), new PointF(approxContour[3].X, approxContour[3].Y) }; var dst = new[] { new PointF(0, 0), new PointF(0, 400), new PointF(400, 400), new PointF(400, 0) }; var tmp = new UMat(); var matrix = CvInvoke.GetPerspectiveTransform(src, dst); CvInvoke.WarpPerspective(imageRGB, tmp, matrix, new Size(400, 400)); viewer.Image = tmp; 
0
source

Source: https://habr.com/ru/post/982077/


All Articles