opencv MSER(最大極值穩定區域)

最大極值穩定區域,是一種相似分水嶺圖像的分割與匹配算法。它具備SIFT SURF及 ORB等特徵不具有的仿射不變性,近年來普遍應用於圖像分割與匹配領域。ios

詳細算法原理介紹可參見連接   http://blog.csdn.net/zhaocj/article/details/40742191算法

建立MSER類ui

//開發環境 vs2013+opencv3.1.0
// 建立MSER對象
cv::Ptr<cv::MSER> mesr1 = cv::MSER::create(2, 10, 5000, 0.5, 0.3);
//若是想要了解各參數的含義,首先須要經過以上連接瞭解算法原理。2表示灰度值的變化量,10和5000表示檢測到的組塊面積的範圍,0.5爲最大的變化率,0.3爲穩定區域的最小變換量

申明輸出參數.net

std::vector<std::vector<cv::Point> > regContours;
std::vector<cv::Rect> bboxes1;

MSER檢測code

mesr1->detectRegions(gray, regContours, bboxes1);//gray爲處理的圖像,爲單通道灰度圖

保存檢測到的結果對象

cv::Mat mserMapMat =cv::Mat::zeros(gray.size(), CV_8UC1);
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根據須要檢測的白色區域和黑色區域,又分爲MSER+和MSER-blog

下面貼上Mser車牌目標檢測示例 完整的C++代碼   示例圖片可到圖片

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
// 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對象
	cv::Ptr<cv::MSER> mesr1 = cv::MSER::create(2, 10, 5000, 0.5, 0.3);
	cv::Ptr<cv::MSER> mesr2 = cv::MSER::create(2, 2, 400, 0.1, 0.3);


	std::vector<cv::Rect> bboxes1;
	std::vector<cv::Rect> bboxes2;
	// MSER+ 檢測
	mesr1->detectRegions(gray, regContours, bboxes1);
	// MSER-操做
	mesr2->detectRegions(gray_neg, charContours, bboxes2);

	cv::Mat mserMapMat =cv::Mat::zeros(srcImage.size(), CV_8UC1);
	cv::Mat mserNegMapMat =cv::Mat::zeros(srcImage.size(), CV_8UC1);

	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;
	cv::morphologyEx(mserResMat, mserClosedMat,
		cv::MORPH_CLOSE, cv::Mat::ones(1, 20, CV_8UC1));
	cv::imshow("mserClosedMat", mserClosedMat);
	// 尋找外部輪廓
	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;
	cv::imshow("src Image", srcImage);
	// 候選車牌區域檢測
	std::vector<cv::Rect> candidates;
	candidates = mserGetPlate(srcImage);
	// 車牌區域顯示
	for (int i = 0; i < candidates.size(); ++i) 
	{
		cv::imshow("rect", srcImage(candidates[i]));
		cv::waitKey();
	}
	cv::waitKey(0);
	return 0;
}
相關文章
相關標籤/搜索