您的位置:首页 > 运维架构

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;  


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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: