MSER相关总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25458977/article/details/77984179

最近做项目用到了MSER,特地在这做总结。


以前提到字符检测首先会想到Tesseract,但是tesseact对图像的二值化要求过高,比较适合于白底黑字的字符识别,对于复杂情况就无能为力了;

于是就想到用轮廓检测,这种方法试验过后,对我的课题效果不太管用,或者说是适用性不太广泛,因此决定放弃;在阅读几篇论文之后,发现了MSER,这里首先说一下,我搜论文的时候用到了关键字:natural sence才搜到这几个论文,以前都是搜索character detection or recognition,应该把这两个关键字加在一起,才会有更多自然情况下字符检测的论文出来;


这里首先把这几个论文贴出来;

第一篇:ROBUST TEXT DETECTION IN NATURAL IMAGES WITH EDGE-ENHANCED MAXIMALLY STABLE EXTREMAL REGIONS ,Huizhong Chen 。相当好的一篇论文,将轮廓检测和MSER相结合;

第二篇:CHARACTER RECOGNITION IN NATURAL IMAGES;

三:Real-Time Scene Text Localization and Recognition。Luk´aˇs Neumann。这也是相当好的一篇文章,提到了对MSER的相关应用;


下边主要是我根据之前看过的博客,总结一个关于MSER的内容。

MSER基于分水岭的概念:对图像进行二值化,二值化阈值取[0, 255],这样二值化图像就经历一个从全黑到全白的过程(就像水位不断上升的俯瞰图)。在这个过程中,有些连通区域面积随阈值上升的变化很小,这种区域就叫MSER。
 检测连通区域的面积变化快慢可以用公式variation表示:
其中Qi表示第i个连通区域的面积,Δ表示微小的阈值变化(注水),当vi小于给定阈值时认为该区域为MSER。
 以下是PPT中的两个讲解图片,帮助理解以下:

具体过程通俗地讲是:拿到一张图片之后,MSER会首先去检测极值区域,就是ER,设定一个阈值,比如说为1,检测那些像素值小于等于1的区域作为ER区,这个区域内的所有值都小于这个阈值,这个区的所有边界都大于这个阈值,比如说上图中的10和12两个图片中黄色的区域属于两个ER区,有人问,为什么不能将他们合并呢。这是因为ER区必须得是联通的,所以,10和12属于两个ER。在程序中ER用栈保存,每个栈里存放的是ER的像素坐标值,比如ER10 存放(2,0),ER12存放(1,2);
上图这样的图片,可以被分成如上五个ER区域,想要知道这五个区域哪个是最稳定的,就要计算它的variation稳定值。

算完后,每个区域都会有一个自己的variation值,在opencv中,只要某个ER区的variation值小于0.27,就认为这个ER区是稳定的,那么这个函数就会被OpenCV中的MSER保存到regions中返回;

显然,这样检测得到的MSER内部灰度值是小于边界的,想象一副黑色背景白色区域的图片,显然这个区域是检测不到的。因此对原图进行一次MSER检测后需要将其反转,再做一次MSER检测,两次操作又称MSER+和MSER-

关于MSER的定义讲解,还有这篇文章:overview of mser

虽然是英文,但是很通俗易懂,这里把我认为很重要的摘抄出来:





Effect of Δ. We startwith a synthetic image which has an intensity profile as shown. The bumps have heights equal to 32, 64, 96, 128 and 160. As we increase Δ, fewer and fewer regions are detected until finally at Δ=160 there is no region R which is stable at R(+Δ).

The stability of an extremal region R is the inverse of the relative area variation of the region R when the intensity level is increased by Δ. Formally, the variation is defined as:

|R(+Δ) - R|
-----------
    |R|

where |R| denotes the area of the extremal region RR(+Δ) is the extremal region  levels up which contains R and |R(+Δ) - R| is the area difference of the two regions.

A stable region has a small variation. The algorithm finds regions which are "maximally stable", meaning that they have a lower variation than the regions one level below or above. Note that due to the discrete nature of the image, the region below / above may be coincident with the actual region, in which case the region is still deemed(被认为) maximal.

However, even if an extremal region is maximally stable, it might be rejected if:

  • it is too big (see the parameter MaxArea);
  • it is too small (see the parameter MinArea);
  • it is too unstable (see the parameter MaxVariation);
  • it is too similar to its parent MSER (see the parameter MinDiversity).

By default, MSERs are extracted for both dark-on-bright regions and bright-on-dark regions. To control this, parmeters BrightOnDark and DarkOnBright which take values 0 or 1 to enable or disable the regions



以下是MSER的算法步骤,最好是看一下,对于理解MSER的定义和计算过程有帮助;

以下总结来自于博客:文字识别与检测--1.MSER

文章写的很长,但是分析的很清晰,建议静下心来自己在纸上画一遍;
2. 算法步骤
从上节可以看到,MSER的基本思路很简单,但编码实现是很需要算法和编程技巧的
以下算法步骤基于改进的分水岭算法:注水的地方固定,只有当该处的沟壑水漫出来后才能注入到另一个沟壑
此外,为方便编程,面积变化的计算方式也从双边改为单边检测,即
具体步骤(摘自Opencv2.4.9源码分析——MSER)
1、初始化栈和堆,栈用于存储组块(组块就是区域,就相当于水面,水漫过的地方就会出现水面,水面的高度就是图像的灰度值,因此用灰度值来表示组块的值),堆用于存储组块的边界像素,相当于水域的岸边,岸边要高于水面的,因此边界像素的灰度值一定不小于它所包围的区域(即组块)的灰度值。首先向栈内放入一个虚假的组块,当该组块被弹出时意味着程序的结束;
2、把图像中的任意一个像素(一般选取图像的左上角像素)作为源像素,标注该像素为已访问过,并且把该像素的灰度值作为当前值。这一步相当于往源像素这一地点注水;
3、向栈内放入一个空组块,该组块的值是当前值;
4、按照顺序搜索当前值的4-领域内剩余的边缘,对于每一个邻域,检查它是否已经被访问过,如果没有,则标注它为已访问过并检索它的灰度值,如果灰度值不小于当前值,则把它放入用于存放边界像素的堆中。另一方面,如果领域灰度值小于当前值,则把当前值放入堆中,而把领域值作为当前值,并回到步骤3;
5、累计栈顶组块的像素个数,即计算区域面积,这是通过循环累计得到的,这一步相当于水面的饱和;
6、弹出堆中的边界像素。如果堆是空的,则程序结束;如果弹出的边界像素的灰度值等于当前值,则回到步骤4;
7、从堆中得到的像素值会大于当前值,因此我们需要处理栈中所有的组块,直到栈中的组块的灰度值大于当前边界像素灰度值为止。然后回到步骤4。
至于如何处理组块,则需要进入处理栈子模块中,传入该子模块的值为步骤7中从堆中提取得到的边界像素灰度值。子模块的具体步骤为:
1)、处理栈顶的组块,即根据公式2计算最大稳定区域,判断其是否为极值区域;
2)、如果边界像素灰度值小于距栈顶第二个组块的灰度值,那么设栈顶组块的灰度值为边界像素灰度值,并退出该子模块。之所以会出现这种情况,是因为在栈顶组块和第二个组块之间还有组块没有被检测处理,因此我们需要改变栈顶组块的灰度值为边界像素灰度值(相当于这两层的组块进行了合并),并回到主程序,再次搜索组块;
3)、弹出栈顶组块,并与目前栈顶组块合并;
4)、如果边界像素灰度值大于栈顶组块的灰度值,则回到步骤1。
最后附上一张图片,就是我想要检测的物体:
 就是检测这个积木块上的字母









猜你喜欢

转载自blog.csdn.net/qq_25458977/article/details/77984179