您的位置:首页 > 编程语言

利用颜色和形态学两种方法进行车牌区域提取的OpenCV代码

2016-07-18 10:32 639 查看
本文参考了《OpenCV图像处理编程实例》

2016-7-28日:用MSER算法也实现了车牌区域的检测 详情利用MSER算法提取图像区域(车牌区域)的OpenCV代码~

要想提取车牌号,首先你要定位车牌区域嘛,本文分别两种方法用,即颜色和形态学的方法,对车牌区域进行判定。说得是两种方法,其实两种方法并无多大的区别,只是有一步的判断标准不一样而已,你看了下面整理出的的思路就知道两者的区别真的很小了。

方法一:利用颜色提取车牌区域的思路:

①求得原图像的sobel边缘sobelMat

②在HSV空间内利用车牌颜色阈值对图像进行二值化处理,得到图像bw_blue→

③由下面的判别标准得到图像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.height = 3;
rct.width = 3;
if ((sobelMat.at<uchar>(k, l) == 255) && (cv::countNonZero(bw_blue(rct)) >= 1))
bw_blue_edge.at<uchar>(k, l) = 255;
}
}


④对bw_blue_edge进行形态学闭操作,将那些小洞,小孔之类的连接起来,进而使图形中矩形更像矩形

⑤对连通区域的轮廓进行检测,如果有车牌,车牌肯定占一个轮廓撒

⑥对每一个轮廓求其外接矩形,并进行检测,从而把最像车牌的区域检测出来,按下面的标准进行检测:

for (size_t n = 0; n != region_contours.size(); ++n)
{
// 去除高度宽度不符合条件区域
cv::Rect rect = cv::boundingRect(region_contours
);
int sub = cv::countNonZero(morph(rect));
double ratio = double(sub) / rect.area();
double wh_ratio = double(rect.width) / rect.height;
if (ratio > 0.5 && wh_ratio > 2 && wh_ratio < 5 &&
rect.height > 12 && rect.width > 60)
{
cv::Mat small = bw_blue_edge(rect);
result = srcImage(rect);
cv::imshow("rect", srcImage(rect));
cv::waitKey(0);
}
}


从上面的过程来看,具体的应用中,如下语句中涉汲到的参数是需要调整的,如果设置不当,很有可能会提取出错误的车牌区域或是提取不出车牌区域。很明显的一个例子,离车牌远近不同拍摄出来的照片车牌区域的大小肯定不一样,那么rect.height > 12 && rect.width > 60之类的语句肯定要随时要调调才行,所以,如果解决不好这类的问题,这个程序是不具备通用性的,这也是这个程序最大的缺陷之一。

cv::countNonZero(bw_blue(rct)) >= 1//‘1’是需要根据据体的应用场景调整的
ratio > 0.5 && wh_ratio > 2 && wh_ratio < 5 &&ect.height > 12 && rect.width > 60)//这里面的参数也需要根据据体的应用场景调整的


方法二:利用形态学原理进行车牌提取的方法:

①利用形态学梯度的方法进行图像的边缘检测

②根据不同的图形大小选取不同的形态学闭操作窗口进行形态学水平方向和垂直方向的闭操作

③对连通区域的轮廓进行检测,如果有车牌,车牌肯定占一个轮廓撒

④对每一个轮廓求其外接矩形,并进行检测,从而把最像车牌的区域检测出来,按下面的标准进行检测:

for (size_t i = 0; i != blue_contours.size(); ++i)
{
cv::Rect rect = cv::boundingRect(blue_contours[i]);
double wh_ratio = double(rect.width) / rect.height;
int sub = cv::countNonZero(result(rect));
double ratio = double(sub) / rect.area();
if (wh_ratio > 2 && wh_ratio < 8 && rect.height >
12 &&rect.width > 60 && ratio > 0.4)
{
//blue_rect.push_back(rect);
cv::imshow("rect", srcGray(rect));
cv::waitKey(0);
}
}


同方法一一样,方法二下面的这句语句中的参数也需要根据实际的应用进行设置,如果设置不当,很有可能会提取出错误的车牌区域或是提取不出车牌区域。很明显的一个例子,离车牌远近不同拍摄出来的照片车牌区域的大小肯定不一样,那么rect.height > 12 &&rect.width > 60之类的语句肯定要随时要调调才行,所以,如果解决不好这类的问题,这个程序是不具备通用性的,这也是这个程序最大的缺陷之一。

wh_ratio > 2 && wh_ratio < 8 && rect.height > 12 &&rect.width > 60 && ratio > 0.4


对比一下两种方法:

两种方法都要先对图像作预处理,以去除多余信息,去除多余信息后,进行形态学闭操作,以凸显出目标轮廓,求得轮廓后,再求轮廓的外接矩形,利用车牌的矩形特征去检测这些外接矩形,符合车牌特征的即是车牌区域。两种方法都不能自适应因拍摄距离远近不同导致的车牌在图形中的大小不同。

两种方法不同的部分是:①方法一采用sobel提取边缘,方法二采用形态学梯度的方法提取边缘;②方法一在提取边缘后还利用车牌的颜色对图像作了阈值限制,方法二则没有。③方法一在作形态学闭操作时,没有根据图形的尺寸选取不同的窗,而方法二则做了这样的处理。

下面附两种方法的源码即运行结果:

方法一的源码:(代码中用到的图像下载链接为 http://pan.baidu.com/s/1c2cBnFE)
//OpenCV版本3.0.0
//交流QQ2487872782

2016-8-4注:很报歉,此代码目前不能公开发表在博客上,已经删除,希望大家能理解!  


方法一的运行结果:



方法二的源码:(代码中用到的图像下载链接为 http://pan.baidu.com/s/1c2cBnFE

//OpenCV版本3.0.0
//交流QQ2487872782

2016-8-4注:很报歉,此代码目前不能公开发表在博客上,已经删除,希望大家能理解!  


方法二的运行结果:



-------------------------------------------

欢迎大家加入图像识别技术交流群:271891601,另外,特别欢迎成都从事图像识别工作的朋友交流,我的QQ号2487872782
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: