这一部分我们来谈一谈如何检测车牌,即是车牌定位。
在上文部分,我讲了车牌定位的四种方法:
(1)基于颜色的分割方法;
(2)基于纹理的分割方法;
(3)基于边缘检测的分割方法;
(4)基于数学形态法的分割方法。
这里面我要具体介绍的检测车牌方法的步骤如下:
Mat img_gray;
cvtColor(input, img_gray, CV_BGR2GRAY);
blur(img_gray, img_gray, Size(5,5));
// 突出垂直边缘
Mat img_sobel;
Sobel(img_gray, img_sobel, CV_8U, 1, 0, 3, 1, 0, BORDER_DEFAULT);
if(showSteps)
imshow("Sobel", img_sobel);
// 阈值化处理
Mat img_threshold;
threshold(img_sobel, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);
if(showSteps)
imshow("Threshold", img_threshold);
// 形态学close处理(先膨胀再腐蚀,填充内部空隙)
Mat element = getStructuringElement(MORPH_RECT, Size(17, 3) );
morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element);
if(showSteps)
imshow("Close", img_threshold);
// 利用findContours函数寻找车牌可能的轮廓
vector< vector< Point> > contours;
findContours(img_threshold,
contours, // 轮廓的数组
CV_RETR_EXTERNAL, // 获取外轮廓
CV_CHAIN_APPROX_NONE); // 获取每个轮廓的每个像素
// 排除非车牌的可能轮廓
vector<vector<Point> >::iterator itc= contours.begin();
vector<RotatedRect> rects;
while (itc!=contours.end()) {
// minAreaRect函数计算最小包围旋转矩形
RotatedRect mr= minAreaRect(Mat(*itc));
if( !verifySizes(mr)){
itc= contours.erase(itc);
}else{
++itc;
rects.push_back(mr);
}
}
// 画出轮廓
cv::Mat result;
input.copyTo(result);
cv::drawContours(result,contours,
-1, // draw all contours
cv::Scalar(255,0,0), // in blue
1); // with a thickness of 1
for(int i = 0; i < rects.size(); i++){
// 现在进一步利用车牌的颜色信息,运用floodfill算法。
// flood fill 算法是从一个区域中提取若干个连通的点与其他相邻区域分开的经典算法。它接收三个参数:起始结点,
// 目标颜色和替换颜色。
circle(result, rects[i].center, 3, Scalar(0,255,0), -1);
//get the min size between width and height
float minSize = (rects[i].size.width < rects[i].size.height)? rects[i].size.width : rects[i].size.height;
minSize=minSize-minSize*0.5;
//initialize rand and get 5 points around center for floodfill algorithm
srand ( time(NULL) );
//Initialize floodfill parameters and variables
Mat mask;
mask.create(input.rows + 2, input.cols + 2, CV_8UC1);
mask= Scalar::all(0);
int loDiff = 30;
int upDiff = 30;
int connectivity = 4;
int newMaskVal = 255;
int NumSeeds = 10;
Rect ccomp;
int flags = connectivity + (newMaskVal << 8 ) + CV_FLOODFILL_FIXED_RANGE + CV_FLOODFILL_MASK_ONLY;
for(int j=0; j<NumSeeds; j++){
Point seed;
seed.x=rects[i].center.x+rand()%(int)minSize-(minSize/2);
seed.y=rects[i].center.y+rand()%(int)minSize-(minSize/2);
circle(result, seed, 1, Scalar(0,255,255), -1);
int area = floodFill(input, mask, seed, Scalar(255,0,0), &ccomp, Scalar(loDiff, loDiff, loDiff), Scalar(upDiff, upDiff, upDiff), flags);
}
if(showSteps)
imshow("MASK", mask);
//cvWaitKey(0);
更多图像处理、机器视觉资源请关注 博客:LinJM-机器视觉 微博:林建民-机器视觉
车牌识别系统开发记录(二) 车牌定位,布布扣,bubuko.com
原文:http://blog.csdn.net/linj_m/article/details/23281403