简体   繁体   English

在OpenCV C ++中将车牌标准化为OCR

[英]Normalize car plate for OCR in OpenCV C++

I'm doing some simple OCR car plate recognition system. 我正在做一些简单的OCR车牌识别系统。 I'm using HaarCascades to find car plate, and next i need to normalize this plate, to put it into my OCR module. 我正在使用HaarCascades找到车牌,然后我需要将这个盘子标准化,将其放入我的OCR模块中。 I'm using floodfill to find main contours of a car plate, and then i perform Hough transform, to find upper and lower boarders of a car plate: 我正在使用填充物找到汽车板的主要轮廓,然后我执行霍夫变换,找到汽车板的上下边界:

floodfill

踝关节

Here's a part of code, where i perform Hough transform^ 这是代码的一部分,我执行Hough变换^

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 picture along this two lines. 现在我需要沿着这两条线切割和旋转这张照片。 How can i do this? 我怎样才能做到这一点? i understand that i need to use point Point(lines[i][0])..Point(lines i ), but what i should do with them? 我明白我需要使用点Point(lines [i] [0]).. Point(第i行),但是我应该用它们做什么?

So basically, i need to get something like that: 基本上,我需要得到类似的东西:

  1. Image, that i got using HaarCascades 图像,我使用HaarCascades

在此输入图像描述

  1. After some transformation i need to get something like this: 经过一些转变,我需要得到这样的东西: 在此输入图像描述

So at the first step i need to cut only upper and lower boarders. 所以在第一步我只需要削减上下边界。

You need to use affine transformations, here there is tutorial . 你需要使用仿射变换,这里有教程 In your situation you need to choose some size of car plate, for example 20x100 . 在您的情况下,您需要选择一些尺寸的车牌,例如20x100 Your destination points will be 3 corners of non rotated rectangle of choosen size and source points will be 3 corners of founded car plate. 您的目标点将是选择大小的非旋转矩形的3个角,源点将是已建立的汽车板的3个角。 I hope it is clear, if it is'not, let me know - i will make some example. 我希望很清楚,如果不是,请告诉我 - 我会举一些例子。

*\\\\EDIT: *\\\\编辑:
Ok, i've made some example. 好的,我已经做了一些例子。 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 results: 结果:
在此输入图像描述
在此输入图像描述
If you will use the code without any modification you will get the first result, if you comment second line and uncomment third line you will get second result (i think that's what you wanted). 如果您将使用代码而不进行任何修改,您将获得第一个结果,如果您评论第二行并取消注释第三行,您将获得第二个结果(我认为这是您想要的)。 To get the second result you just need to find the points where upper and lower lines cross the image border. 要获得第二个结果,您只需要找到上下线穿过图像边界的点。 I've marked it here: 我在这里标记了它:
在此输入图像描述
So basically you need to use red points. 所以基本上你需要使用红点。 To calculate their positions you just need to find where blue lines (which if i understand correct you already have) cross the image border. 要计算它们的位置,你只需要找到蓝线(如果我理解你已经有的话)穿过图像边框。

Here is a solution with EmguCv: 这是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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM