MSER代码编译:
matlabroot
%如果是VS2010则解压VS2010MEX支持文件到MATLAB根目录
unzip('E:\Software\develop Tools\VS2010MEXSupport.zip',matlabroot)
mex -setup
%设置代码文件夹编译路径
cd('E:\Koder Quelle\Image process Package\mser-0.5')
mser_compile
%生成PDB文件供调试用
mex -g mser.mex.c -output 'mser.mex.pdb' 
%编译MEX文件
mex -g mser.mex.c -output 'mser'
mex -g erfill.mex.c -output 'erfill'
 
MSER的原理介绍:

图像I为一个映射  . 极值区域在图像上的定义为:
1. S是全序的,例如存在满足自反性,反对称性和传递性的二元关系“小于等于”。论文里考虑到的范围仅是S={0,1,2,...,255},但是极值区域可以被定义在实值图像上(S=R)。

2.邻域关系的定义为(备注,这里集合的乘积为笛卡尔积),这里只用到了4邻域,例如是相邻的(用表示),那么当且仅当满足的时候它们才是邻域关系。
区域Q是D的连续子集,例如 对每个这里存在一个序列并且
这个性质表示区域Q为单连通的。
 
区域的边界(外部的),例如Q的边界是这样一个像素集合,它至少有一个像素是属于Q的邻域像素但是不属于区域Q。
 
极值区域是这样的一个区域:对于所有[最大亮度区域]或者[最小亮度区域]。
 
 
最大稳定极值区域(MSER)。令为嵌套的极值区域,例如,当且仅当时存在局部最小值,极值区域才是最大稳定的(|.|表示集合的势,对于离散图像来说就是像素面积),属于方法参数
 
Component Tree原理
当前元素和所有周围邻近当前区域的元素并且小于当前元素的区域都属于该区域
从最小值Xi像素开始建立一个region,如果Xi的邻域亮度值等于该像素的亮度值,则将Xi合并进邻域像素所在的region(且父节点是邻域像素父节点),如果Xi邻域的像素值小于Xi的像素值,则将邻域像素归入当前region,并将当前region作为邻域像素region的根节点(且邻域像素父节点指向当前像素的父节点),直到遍历完所有像素为止。
 
Component Tree 代码解读:
4    4    4    4    4    4    4
4    2    2    4    2    1    4
4    2    2    4    1    2    4
4    3    3    4    3    3    4
4    2    2    4    4    3    4
4    1    1        4    3    4
4    4    4    4    4    4    4
 
Extremal regions: 8

ner: 0. value:1,area: 2, parent: 3
ner: 1. value:1,area: 2, parent: 4
ner: 2. value:2,area: 4, parent: 5
ner: 3. value:2,area: 5, parent: 5
ner: 4. value:2,area: 4, parent: 6
ner: 5. value:3,area: 11, parent: 7
ner: 6. value:3,area: 8, parent: 7
ner: 7. value:4,area: 49, parent: 7

 
从像素值是1的像素开始:
节点0,1属于节点3
节点2,3属于节点5
节点4属于节点6
节点5,6属于节点7
 
反之则有:
1   1   1   1   1   1   1
1   3   3   2   3   4   1
1   3   3   2   3   4   1
1   1   1   1   1   3   1
1   3   4   2   1   1   1
1   4   3   2   2   2   1
1   1   1   1   1   1   1 
 
ner: 0. value:1,area: 30, parent: 1
ner: 1. value:2,area: 36, parent: 2
ner: 2. value:3,area: 45, parent: 3
ner: 3. value:4,area: 49, parent: 3
 
从像素值是1的像素开始,刚开始只有节点0一个区域,将像素2的区域并入0后形成节点1,将像素3并入节点1后形成节点2,最后全部合并形成整个区域作为父节点.
 
 
Component Tree的步骤:
1.在计算开始之前首先对所有像素按照亮度大小进行排序。
 
2.
for (i = 0; i < pixel_numbers; i++)
{
     1.弹出当前像素的索引和值
     2.将邻结点的索引指向当前索引
     3.将当前像素结点插入到树中
     4.while(依次处理以该像素为中心的8邻域像素)
       {
          a.邻域像素在图像边界以内
          b.邻域像素不是自身
          c.邻域像素已经在树中了,也就是说这个像素已经被处理过了
          if(满足a,b,c)
          {
               1.将当前此节点,以及当前此节点的上一层父节点,..., 直到根节点的所有链路节点的shortcut都置为根节点
               2.将此邻域节点,以及此邻域节点的上一层父节点,..., 直到根节点的所有链路节点的shortcut都置为根节点
              
               i.  如果当前节点的根节点等于邻域像素的根节点,这种情况下两个树已经加入了同一个树当中了
               ii. 如果当前节点的根节点的亮度等于邻域像素的根节点的亮度,此种情况索引将被扩展到具有相同亮度的一个极值区域,因为邻域像素的根节点不会是整个图像的一个极值区域;当前索引的根节点能够安全的被添加到邻域像素的根节点作为邻域像素的孩子结点。
               iii.如果当前节点的根节点的亮度大于邻域像素的根节点的亮度并且当前节点是一个极值区域,这时仅仅增加它的层数。这种情况下邻域像素根节点将会是最终整个图像的一个极值区域并且只有唯一的可能性作为添加到当前像素所属的树中当前像素的孩子

}
       }
}

MSER区域的椭圆拟合(注意! 这里是二值图像):
X,X   correlation[X,X]
X,Y   correlation[X,Y]
Y,Y   correlation[Y,Y]
 
 
 
 
 
 
 
其中E(x),E(y)分别为拟合椭圆的中心点坐标,D(x),D(y),COV(x,y)分别为该区域内所有点的横坐标方差,纵坐标方差和横纵坐标协方差
 
椭圆拟合的代码:
   /* -----------------------------------------------------------------
* Fit ellipses
* -------------------------------------------------------------- */
ell_pt = ;
if (nout >= ) {
int midx = ;
int d, index, j ; verbose && mexPrintf("Fitting ellipses...\n") ; /* enumerate maxstable regions */
for(i = ; i < ner ; ++i) {
if(! regions_pt [i].maxstable) continue ;
regions_pt [i].maxstable = midx++ ;
} /* allocate space */
acc_pt = mxMalloc(sizeof(acc_t) * nel) ;
ell_pt = mxMalloc(sizeof(acc_t) * gdl * nmer) ; /* clear accumulators */
memset(ell_pt, , sizeof(int) * gdl * nmer) ;
for(index = ; index < nel ; ++ index){
mexPrintf("%d\t",joins_pt[index]) ;
if( == (index+)%dims[]) mexPrintf("\n");
} for(index = ; index < nel ; ++ index){
mexPrintf("%d\t",forest_pt [ index ].parent) ;
if( == (index+)%dims[]) mexPrintf("\n");
} /* for each gdl */
for(d = ; d < gdl ; ++d) {
/* initalize parameter */
memset(subs_pt, , sizeof(int) * ndims) ; //注意这里的0和1下标不是0阶矩和1阶矩,而是表示X和Y之间的均值,相关系数
//例如(0,0)表示corr(X,X), (0,1)表示corr(X,Y),(1,0)表示corr(Y,X),(1,1)表示corr(Y,Y)不要搞混!!! by frisch
if(d < ndims) {
//图像每个像素的行[0], 列坐标[1]坐标, x方向和y方向的均值,by frisch
verbose && mexPrintf(" mean %d\n",d) ;
for(index = ; index < nel ; ++ index) {
acc_pt[index] = subs_pt[d] ;
adv(dims, ndims, subs_pt) ; } } else { //图像每个像素的行[0], 列坐标[1]的相关度计算, by frisch
//corr[0,0](行与行), corr[1,0](行与列), corr[0,1](列与行), corr[1,1](列与列), by frisch
/* decode d-ndims into a (i,j) pair */
i = d-ndims ;
j = ;
while(i > j) {
i -= j + ;
j ++ ;
} verbose && mexPrintf(" corr (%d,%d)\n",i,j) ; /* add x_i * x_j */
//计算相关值,将其放入二维数组
for(index = ; index < nel ; ++ index){
acc_pt[index] = subs_pt[i]*subs_pt[j] ;
mexPrintf("(%d\t%d\t)",subs_pt[i],subs_pt[j]) ;
if( == (index+)%dims[]) mexPrintf("\n");
adv(dims, ndims, subs_pt) ;
}
} for(index = ; index < nel ; ++ index){
mexPrintf("%d\t",acc_pt[index]) ;
if( == (index+)%dims[]) mexPrintf("\n");
} /* integrate parameter */
//对每个区域进行均值或者相关值积分,by frisch
for(i = ; i < njoins ; ++i) {
idx_t index = joins_pt[i] ;
idx_t parent = forest_pt [ index ].parent ;
acc_pt[parent] += acc_pt[index] ;
} /* save back to ellpises */
//保存椭圆参数, 五个参数(包含椭圆的中心点,长短轴幅值,方向向量) by frisch
for(i = ; i < ner ; ++i) {
idx_t region = regions_pt [i].maxstable ; /* skip if not extremal region */
if(region-- == ) continue ;
ell_pt [d + gdl*region] = acc_pt [ regions_pt[i].index ] ;
} /* next gdl */
}
mxFree(acc_pt) ;
}
reference:
椭圆拟合部分参考《多通道图像MSER局部不变特征》 国防科技大学,柳涛
 
 

MSER算法介绍的更多相关文章

  1. 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍

    考虑到知识的复杂性,连续性,将本算法及应用分为3篇文章,请关注,将在本月逐步发表. 1.机器学习之PageRank算法应用与C#实现(1)算法介绍 2.机器学习之PageRank算法应用与C#实现(2 ...

  2. KNN算法介绍

    KNN算法全名为k-Nearest Neighbor,就是K最近邻的意思. 算法描述 KNN是一种分类算法,其基本思想是采用测量不同特征值之间的距离方法进行分类. 算法过程如下: 1.准备样本数据集( ...

  3. ISP基本框架及算法介绍

    什么是ISP,他的工作原理是怎样的? ISP是Image Signal Processor的缩写,全称是影像处理器.在相机成像的整个环节中,它负责接收感光元件(Sensor)的原始信号数据,可以理解为 ...

  4. Python之常见算法介绍

    一.算法介绍 1. 算法是什么 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时间内获得所要求的输 ...

  5. RETE算法介绍

    RETE算法介绍一. rete概述Rete算法是一种前向规则快速匹配算法,其匹配速度与规则数目无关.Rete是拉丁文,对应英文是net,也就是网络.Rete算法通过形成一个rete网络进行模式匹配,利 ...

  6. H2O中的随机森林算法介绍及其项目实战(python实现)

    H2O中的随机森林算法介绍及其项目实战(python实现) 包的引入:from h2o.estimators.random_forest import H2ORandomForestEstimator ...

  7. STL 算法介绍

    STL 算法介绍 算法概述 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成.        <algorithm ...

  8. Levenshtein字符串距离算法介绍

    Levenshtein字符串距离算法介绍 文/开发部 Dimmacro KMP完全匹配算法和 Levenshtein相似度匹配算法是模糊查找匹配字符串中最经典的算法,配合近期技术栏目关于算法的探讨,上 ...

  9. 机器学习概念之特征选择(Feature selection)之RFormula算法介绍

    不多说,直接上干货! RFormula算法介绍: RFormula通过R模型公式来选择列.支持R操作中的部分操作,包括‘~’, ‘.’, ‘:’, ‘+’以及‘-‘,基本操作如下: 1. ~分隔目标和 ...

随机推荐

  1. php 画图片2

    <?php // 使用php操作gd库做图 // 1. 创建一个画布资源 $im = imagecreatetruecolor(200, 50); // 2. 创建背景色 // 2.1 得到背景 ...

  2. Best Coder Round#25 1001 依赖检测

    原题大致上就是检测一系列进程之间是否存在循环依赖的问题,形如: a->b->c->a,  a->a ,都行成了循环依赖,事实上可以视为“检测链表中是否存在环” AC代码: #i ...

  3. 配置和创建一个hibernate简单应用

    1.配置 到http://hibernate.org/orm/下载hibernate包然后解压 在eclipse中新建一个java project,如名为hibernate_test 再所建工程中新建 ...

  4. Mac下用brew安装nginx

    1. nginx nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TC ...

  5. 浅谈JavaScript的作用域

    前段时间学了下JavaScript作用域,这个东西在JavaScript非常重要,也是JavaScript很基础的东西,正如少林里面基础武功,有了基础,才能学绝世武功. 作用域的作用是啥?一套设计良好 ...

  6. Kmeans++算是DONet实现

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  7. Unattend.xml应答文件制作(WISM)

    将制作好的应答文件unattend.xml拷贝到模板机sysprep目录下,然后在cmd下运行 (unattend.xml文件可自定义名称)   sysprep /generalize /oobe / ...

  8. 与考试相关的JS方法

    var IsChange = 0;var ensure = 0;var timeCounter = (function () {//考试剩余时间 倒计时 var int; //var total = ...

  9. php + sqlserver

    Dbconn <?php class DbConn{ private $conn; private $rs; private function __construct(){ $serverNam ...

  10. c语言数据结构之 堆排序

    算法:先生成随机数,赋值到数组,将数组第一个元素a[0]设置为哨兵,函数调用数组和随机数个数n,再设定n/2的根结点与孩子结点进行比较操作,若右孩子存在,则选出三个数里最小的数赋值给根节点,如果右孩子 ...