opencv MSER(最大极值稳定区域)

xiaoxiao2021-02-28  97

最大极值稳定区域,是一种类似分水岭图像的分割与匹配算法。它具有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

转载请注明原文地址: https://www.6miu.com/read-81993.html

最新回复(0)