opencv MSER(最大极值稳定区域)
2017-06-08 14:55
716 查看
最大极值稳定区域,是一种类似分水岭图像的分割与匹配算法。它具有SIFT SURF及 ORB等特征不具备的仿射不变性,近年来广泛应用于图像分割与匹配领域。
详细算法原理介绍可参见链接 http://blog.csdn.net/zhaocj/article/details/40742191
创建MSER类
[cpp]
view plain
copy
//开发环境 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为稳定区域的最小变换量
申明输出参数
[cpp]
view plain
copy
std::vector<std::vector<cv::Point> > regContours;
std::vector<cv::Rect> bboxes1;
MSER检测
[cpp]
view plain
copy
mesr1->detectRegions(gray, regContours, bboxes1);//gray为处理的图像,为单通道灰度图
保存检测到的结果
[cpp]
view plain
copy
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-
下面贴上Mser车牌目标检测示例 完整的C++代码 示例图片可到 此处下载
[cpp]
view plain
copy
#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;
}
,其中Qi表示第i个连通区域的面积,Δ表示微小的阈值变化(注水),当vi小于给定阈值时认为该区域为MSER。
显然,这样检测得到的MSER内部灰度值是小于边界的,想象一副黑色背景白色区域的图片,显然这个区域是检测不到的。因此对原图进行一次MSER检测后需要将其反转,再做一次MSER检测,两次操作又称MSER+和MSER-
以下算法步骤基于改进的分水岭算法:注水的地方固定,只有当该处的沟壑水漫出来后才能注入到另一个沟壑
此外,为方便编程,面积变化的计算方式也从双边改为单边检测,即
原文地址:http://blog.csdn.net/hust_bochu_xuchao/article/details/52230694
http://www.cnblogs.com/jkmiao/p/6797252.html
详细算法原理介绍可参见链接 http://blog.csdn.net/zhaocj/article/details/40742191
创建MSER类
[cpp]
view plain
copy
//开发环境 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为稳定区域的最小变换量
申明输出参数
[cpp]
view plain
copy
std::vector<std::vector<cv::Point> > regContours;
std::vector<cv::Rect> bboxes1;
MSER检测
[cpp]
view plain
copy
mesr1->detectRegions(gray, regContours, bboxes1);//gray为处理的图像,为单通道灰度图
保存检测到的结果
[cpp]
view plain
copy
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-
下面贴上Mser车牌目标检测示例 完整的C++代码 示例图片可到 此处下载
[cpp]
view plain
copy
#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;
}
opencv mser算法框出图片文字区域
MSER(Maximally Stable Extrernal Regions)是区域检测中影响最大的算法1. 原理
MSER基于分水岭的概念:对图像进行二值化,二值化阈值取[0, 255],这样二值化图像就经历一个从全黑到全白的过程(就像水位不断上升的俯瞰图)。在这个过程中,有些连通区域面积随阈值上升的变化很小,这种区域就叫MSER。,其中Qi表示第i个连通区域的面积,Δ表示微小的阈值变化(注水),当vi小于给定阈值时认为该区域为MSER。
显然,这样检测得到的MSER内部灰度值是小于边界的,想象一副黑色背景白色区域的图片,显然这个区域是检测不到的。因此对原图进行一次MSER检测后需要将其反转,再做一次MSER检测,两次操作又称MSER+和MSER-
2. 算法步骤
从上节可以看到,MSER的基本思路很简单,但编码实现是很需要算法和编程技巧的以下算法步骤基于改进的分水岭算法:注水的地方固定,只有当该处的沟壑水漫出来后才能注入到另一个沟壑
此外,为方便编程,面积变化的计算方式也从双边改为单边检测,即
import sys sys.path.append('/usr/local/lib/python2.7/dist-packages/') from PIL import Image import numpy as np import cv2 import matplotlib.pyplot as plt img = cv2.imread('img/origin2/31.jpg') mser = cv2.MSER_create(_min_area=300) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) regions, boxes = mser.detectRegions(gray) for box in boxes: x, y, w, h = box cv2.rectangle(img, (x,y),(x+w, y+h), (255, 0, 0), 2) plt.imshow(img,'brg') plt.show()
原文地址:http://blog.csdn.net/hust_bochu_xuchao/article/details/52230694
http://www.cnblogs.com/jkmiao/p/6797252.html
相关文章推荐
- opencv MSER(最大极值稳定区域)
- opencv MSER(最大极值稳定区域)
- MSER最大稳定极值区域
- Matlab mser(最大极值稳定区域)
- 最大稳定极值区域(MSER)检测
- 图像检索服务器编写问题记录——MSER最大稳定极值区域检测
- Matlab mser(最大极值稳定区域)
- opencv MSER(最大极值稳定区域)
- < openCV > 最大稳定极值区域(MSER-Maximally Stable Extremal Regions)
- OpenCV-利用颜色、形态学和最大稳定极值区域MSER实现车牌区域检测
- OpenCV-最大极值稳定区域MSER分析
- matlab实现MSER(最大极值稳定区域)来进行文本定位
- 最大稳定极值区域(MSER)检测
- matlab实现MSER(最大极值稳定区域)来进行文本定位
- 最大稳定极值区域MSERs
- matlab实现MSER(最大极值稳定区域)来进行文本定位
- mser 最大稳定极值区域(文字区域定位)算法 附完整C代码
- mser 最大稳定极值区域(文字区域定位)算法 附完整C代码
- 基于最大稳定区域的图像分割算法
- MSER最稳定极值区域源码分析