利用MSER算法提取图像区域(车牌区域)的OpenCV代码~

图像处理开发需求、图像处理接私活挣零花钱,请加微信/QQ 2487872782
图像处理开发资料、图像处理技术交流请加QQ群,群号 271891601

我的博客中前面已经写了两种方法来实现车牌区域的提取了,大家可以参看下面这篇博文

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

MSER的全称是maximally stable extremal region,翻译过来为“最稳定极值区域”,extremal 意思的极值的意思。

下面说下这种方法的大致思路,如果要学习具体的原理,可以参考论文J.Matas. “Robust Wide Baseline Stereo from Maximally Stable Extremal Regions”,BMVC2002。

MSER提取过程
1.使用一系列灰度阈值对图像进行二值化处理
2.对于每个阈值得到的二值图像,得到相应的黑色区域与白色区域
3.在比较宽的灰度阈值范围内保持形状稳定的区域就是MSER,判断标准为dA/dt
David Nister等人于2008年在论文“Linera Time Maximally Stable Extermal Regions”对J.Matas提出的MSER算法进行了改进,使其在时间复杂度方面比原算法要小得多,OpenCV中提供的MSER模块算法就是利用该算法实现的。David Nister等人提出的算法思路如下(下面所列的每一步具体是怎么回事,请参看原论文):

①像素点排序→②极值区域生成→③稳定区域判定→④区域拟合→⑤区域归一化

下面分享利用MSER算法提取车牌区域的OpenCV代码~希望对大家有帮助,代码先使用MSER算法提取出图像的区域,然后对这些区域进行形态学闭操作,使其成较为完整的区域,再对这些区域求外接矩形,根据外接矩形的参数去判断是否是车牌区域。

代码如下(代码中用到的图像下载链接分别为 http://pan.baidu.com/s/1c2cBnFE car2.jpg_免费高速下载|百度网盘-分享无限制):

注意:OpenCV版本我从3.0.0换到了2.4.13,原因是因为最近我在实现SIFT算法时,发现3.0.0中没有nonfree模块!而SIFT和SURT都是包含在nonfree模块中的!

//OpenCV版本opencv2.4.13
//图像处理开发需求、图像处理接私活挣零花钱,请加微信/QQ 2487872782
//图像处理开发资料、图像处理技术交流请加QQ群,群号 271891601

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
// Mser车牌目标检测
std::vector<cv::Rect> mserGetPlate(cv::Mat srcImage)
{
   // HSV空间转换
	cv::Mat gray, gray_neg;
	cv::Mat hsi;
	cv::cvtColor(srcImage, hsi, CV_BGR2HSV);
    // 通道分离
	std::vector<cv::Mat> channels;
	cv::split(hsi, channels);
	// 提取h通道
	gray = channels[1];
	// 灰度转换 
	cv::cvtColor(srcImage, gray, CV_BGR2GRAY);
   // 取反值灰度
	gray_neg = 255 - gray;
	std::vector<std::vector<cv::Point> > regContours;
	std::vector<std::vector<cv::Point> > charContours;
	// MSER+操作 
	//如果要了解初始化参数的含义,请参看类定义和MSER原理文档
	cv::MSER(2, 10, 5000, 0.5, 0.3)(gray, regContours);
	// MSER-操作
	//如果要了解初始化参数的含义,请参看类定义和MSER原理文档
	cv::MSER(2, 2, 400, 0.1, 0.3)(gray_neg, charContours);
	cv::Mat mserMapMat = 
		cv::Mat::zeros(srcImage.size(), CV_8UC1);
	cv::Mat mserNegMapMat = 
		cv::Mat::zeros(srcImage.size(), CV_8UC1);
	// MSER+ 检测
	for(int i = (int)regContours.size()-1; i >= 0; i--) 
	{
		// 根据检测区域点生成mser+结果
		const std::vector<cv::Point>& r = regContours[i];
		for (int j = 0; j < (int)r.size(); j++ )
		{
			cv::Point pt = r[j];
			mserMapMat.at<unsigned char>(pt) = 255;
		}
	}
	// MSER- 检测
	for(int i = (int)charContours.size()-1; i >= 0; i--) 
	{
		// 根据检测区域点生成mser-结果
		const std::vector<cv::Point>& r = charContours[i];
		for (int j = 0; j < (int)r.size(); j++ )
		{
			cv::Point pt = r[j];
			mserNegMapMat.at<unsigned char>(pt) = 255;
		}
	}
	// mser结果输出
	cv::Mat mserResMat;
	// mser+与mser-位与操作
	mserResMat= mserMapMat & mserNegMapMat;
	cv::imshow("mserMapMat", mserMapMat);
	cv::imshow("mserNegMapMat", mserNegMapMat);
	cv::imshow("mserResMat", mserResMat);
	// 闭操作连接缝隙
	cv::Mat mserClosedMat;
	//根据不同的mserResMat图像,适当调整闭操作窗大小,才能得到车牌区域
	cv::morphologyEx(mserResMat, mserClosedMat,
	cv::MORPH_CLOSE, cv::Mat::ones(1, 20, CV_8UC1));
	cv::imshow("mserClosedMat", mserClosedMat);
	cv::waitKey();
	// 寻找外部轮廓
	std::vector<std::vector<cv::Point> > plate_contours;
	cv::findContours(mserClosedMat, plate_contours, 
		CV_RETR_EXTERNAL,
		CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
	// 候选车牌区域判断输出
	std::vector<cv::Rect> candidates;
	for (size_t i = 0; i != plate_contours.size(); ++i)  
	{
		// 求解最小外界矩形
		cv::Rect rect = cv::boundingRect(plate_contours[i]);
		// 宽高比例
		double wh_ratio = rect.width / double(rect.height);
		// 不符合尺寸条件判断
		if (rect.height > 20 && wh_ratio > 4 && wh_ratio < 7)
			candidates.push_back(rect);
	}
	
	
		return  candidates;
	}
int main() 
{
	cv::Mat srcImage = 
		cv::imread("car.jpg");
	if(srcImage .empty())
		return-1;
	// 候选车牌区域检测
	std::vector<cv::Rect> candidates;
	candidates = mserGetPlate(srcImage);
   // 车牌区域显示
	for (int i = 0; i < candidates.size(); ++i) {
		cv::imshow("rect", srcImage(candidates[i]));
		cv::waitKey();
	}
	return 0;
}

运行结果如下图所示

值得注意的是,在进行形态学闭操作时,一定要根据具体的图像来调整矩形窗的大小,比如下面这幅图,就需要把窗的大小由(1,20)调整到(1,30)才能检测出结果,相关运行截图如下:

图像处理开发需求、图像处理接私活挣零花钱,请加微信/QQ 2487872782
图像处理开发资料、图像处理技术交流请加QQ群,群号 271891601

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值