基于纹理边缘抑制的轮廓和边界检测(Contour and Boundary Detection)

kezunhai@gmail.com

http://blog.csdn.net/kezunhai


一幅复杂的自然场景图像中包含丰富的信息,视觉不可能对空间中的每一点赋予相同的关注程度。对人类视觉系统的实验表明:图像中的轮廓特征特别重要,它们在保留关于物体的边界有用的结构信息的同时,极大地降低了数据量,从而简化了信息的表达形式,使视觉能对各种瞬息万变的输入可以及时有效地处理。在很多情况下,根据画出了的物体轮廓就可以识别出物体。

轮廓在计算机视觉中属于中层视觉,它是基于形状目标识别的一个重要特征。形状与结构的视觉分析在人类的视觉感知中起着重要的作用,物体往往是通过它的形状大小、颜色信息和几何结构等特征来描述的。在许多视觉任务中,由于形状具有很强的鲁棒性,因此一般物体的识别主要是根据形状特征。轮廓检测的一个首要问题是如何处理通过简单边缘检测机制产生的大量的候选成分。由于许多的边缘仅仅是一种对比度的突变,它们可能不属于任何有意思的和相关物理轮廓。通过来自周边环境上下文的信息影响  边缘检测器的响应来增强对相关边缘的敏感性,并根据上下文的信息将孤立的边缘点连接起来,构成某一个物体在图像上形成的一个区域的完整边界线,去除那些不具有实际物理意义的背景纹理边缘。

本文根据Cosmin Grigorescu等人的论文“Contour and boundary detection improved by surround suppression of texture edges"的内容和自己的理解而成,如果对其中的细节感兴趣,敬请参考原文。   在Cosmin Grigorescu的论文中,提出了一个重要的计算环节(Computational Step),叫做环境抑制(Surround Suppression)来提高自然场景中图像的目标轮廓和区域边界的检测。该灵感主要是受到人的初级视皮层(Primary Visual Cortex)中的那些具有方向选择性的神经元(Orientation Selective Neurons)激发,这些细胞对周围的非经典感受野区域具有抑制作用,并且影响对边缘和线条的聚集的感知能力(Perception of  Group of Edges or Lines)。接下来,本文将详细的介绍下这篇论文的基本内容。

(1)计算梯度(Gradient Computation)

这里的操作类似Canny算子的第一步,也即首先将原图与一个高斯函数进行卷积,对图像进行平滑滤波,然后对滤波后的图像进行有限差分运算,求梯度。在Canny中,其计算公式如下:

然而,通过学者的研究得出,采用上面的公式来计算是病态的(ill-posed),因此,在该文中,采用如下的公式来计算梯度:

其中,是高斯函数的一阶微分。接着,进一步来计算X、Y方向的梯度,计算公式如下:

计算完梯度,那么就可以进一步得到幅值和方向,公式如下:

接着,沿着梯度方向采用非极大值抑制来对图像中的边缘像素进行定位,非极大值抑制可以参考博文:Canny算子中的非极大值抑制(Non-Maximum Suppression)分析

(2)环境抑制(Surround Suppression)

通过第一步的计算,可以得到边缘图像,在这一步,需要对检测到的边缘图像进行非轮廓边缘的抑制,非轮廓边缘包括背景纹理以及噪声等。在该文中,通过高斯差分来模拟人的初级视皮层细胞对环境抑制机制,DOG的表达式如下:

权重函数的定义如下:

对图像中的每一个点,采用上面的权重函数进行处理。根据处理方式的不同,可以分为各向同性抑制和各向异性抑制。下面来简单介绍下这两种抑制。

(3)各向同性抑制(Isotropic Surround Suppression)

通过前面的两步计算,各向同性抑制的准备工作已经就绪了。该种方式的抑制作用只考虑距离因素,因此其表达公式如下:

最后,可以得到轮廓检测算子,用公式表达如下:

其中,alpha是一个控制因子(control factor),H(*)是一个操作算子,类似于Canny算子的后处理部分,包括轮廓的细化、滞后阈值化以及轮廓连接等,具体的可以参考Canny算子。

(4)各向异性抑制(Anisotropic Surround Suppression)

各向异性抑制与各向同性抑制相比,增加了一个抑制因素,也即方向因素。对于两个点(x,y)和(x-u,y-v),其方向因素表示如下:

通过上式可知,如果这两个点的方向一致,那么抑制最用最大,因为cos(0)=1,随着夹角的增大,抑制作用逐渐减少,当两个点相互垂直时,抑制作用最小(cos(90)=0)。

增加了方向的环境抑制因素后,抑制作用表示如下:

公式中的符号与前面相同,不再介绍。

下面给出两段代码:

(1)非极大值抑制

// non-maximum suppression
void NonMaxSuppress(float*pMag, float* pGradX, float*pGradY, Size sz, unsigned char* pNSRst)
{
long x,y;
int nPos;
// the component of the gradient
float gx,gy;
// the temp varialbe
float g1,g2,g3,g4;
float weight;
float dTemp,dTemp1,dTemp2;
//设置图像边缘为不可能的分界点
for(x=0;x<sz.width;x++)
{
pNSRst[x] = 0;
pNSRst[(sz.height-1)*sz.width+x] = 0;
}
for(y=0;y<sz.height;y++)
{
pNSRst[y*sz.width] = 0;
pNSRst[y*sz.width + sz.width-1] = 0;
} for (y=1;y<sz.height-1;y++)
{
for (x=1;x<sz.width-1;x++)
{
nPos=y*sz.width+x;
// if pMag[nPos]==0, then nPos is not the edge point
if (pMag[nPos]==0)
{
pNSRst[nPos]=0;
}
else
{
// the gradient of current point
dTemp=pMag[nPos];
// x,y 方向导数
gx=pGradX[nPos];
gy=pGradY[nPos];
//如果方向导数y分量比x分量大,说明导数方向趋向于y分量
if (fabs(gy)>fabs(gx))
{
// calculate the factor of interplation
weight=fabs(gx)/fabs(gy);
g2 = pMag[nPos-sz.width]; // 上一行
g4 = pMag[nPos+sz.width]; // 下一行
//如果x,y两个方向导数的符号相同
//C 为当前像素,与g1-g4 的位置关系为:
//g1 g2
// C
// g4 g3
if(gx*gy>0)
{
g1 = pMag[nPos-sz.width-1];
g3 = pMag[nPos+sz.width+1];
}
//如果x,y两个方向的方向导数方向相反
//C是当前像素,与g1-g4的关系为:
// g2 g1
// C
// g3 g4
else
{
g1 = pMag[nPos-sz.width+1];
g3 = pMag[nPos+sz.width-1];
}
}
else
{
//插值比例
weight = fabs(gy)/fabs(gx);
g2 = pMag[nPos+1]; //后一列
g4 = pMag[nPos-1]; // 前一列
//如果x,y两个方向的方向导数符号相同
//当前像素C与 g1-g4的关系为
// g3
// g4 C g2
// g1
if(gx * gy > 0)
{
g1 = pMag[nPos+sz.width+1];
g3 = pMag[nPos-sz.width-1];
} //如果x,y两个方向导数的方向相反
// C与g1-g4的关系为
// g1
// g4 C g2
// g3
else
{
g1 = pMag[nPos-sz.width+1];
g3 = pMag[nPos+sz.width-1];
}
}
dTemp1 = weight*g1 + (1-weight)*g2;
dTemp2 = weight*g3 + (1-weight)*g4;
//当前像素的梯度是局部的最大值
//该点可能是边界点
if(dTemp>=dTemp1 && dTemp>=dTemp2)
pNSRst[nPos] = 128;
else
//不可能是边界点
pNSRst[nPos] = 0;
}
}
}
}

(2)高斯差分DoG

// sigma2 = 4*sigma1
void getDoGKernel( Mat& kernel, int kSize, double sigma1, double sigma2)
{
double sigma1x = sigma1*sigma1;
double sigma2x = sigma2*sigma2;
Mat mkernel (kSize, kSize, CV_64F);
int center = (kSize-1)/2;
int i,j;
double dsum = 0; for ( i=0; i<kSize; ++i )
{
double* data = (double*)(mkernel.data+ mkernel.step[0]*i);
int di = (i-center);
for ( j=0; j<kSize; ++j )
{
int dj = (j-center);
double d1 = (1.0/sigma1x)*exp(-(di*di+dj*dj)/(2*sigma1x));
double d2 = (1.0/sigma2x)*exp(-(di*di+dj*dj)/(2*sigma2x));
double dis = d2 - d1;
if ( dis>0.0)
data[j] = dis;
else
data[j]=0.0;
dsum += fabs(dis);
}
}
// 归一化
mkernel = mkernel/dsum;
mkernel.copyTo( kernel);
return;
}

最后,再附上一小节代码:

Sobel( gray, sobelX, CV_32F, 1, 0, 3);
Sobel( gray, sobelY, CV_32F, 0, 1, 3);
magnitude( sobelX, sobelY, mag);
//cartToPolar( sobelX, sobelY, mag, dir, true);
// 非极大值值抑制
filter2D( mag, mag, mag.depth(), kernel); // 环境抑制 surround suppression

另外,推荐几篇相关论文:

1、Cosmin Grigorescu.  contour detection based on nonclassical receptive field inhibition(2003 TIP).

2、唐奇伶. 基于初级视皮层感知机制的轮廓与边界检测(2007华中科技大学博士论文)

作者:kezunhai出处:http://blog.csdn.net/kezunhai欢迎转载或分享,但请务必声明文章出处。

基于纹理边缘抑制的轮廓和边界检测(Contour and Boundary Detection)的更多相关文章

  1. 基于纹理的图片检索及demo(未启动)

    基于纹理的图片检索及demo(未启动)

  2. opencv::轮廓发现(find contour in your image)

    轮廓发现(find contour) 轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法. 所以边缘提取的阈值选定会影响最终轮廓发现结果 //发现轮廓 cv::findContours( InputO ...

  3. Halcon编程-基于纹理的mara检测

    表面瑕疵检测是机器视觉领域非常重要的一个应用.机器视觉是集光学.机电和计算机三个领域的一门不算新的技术.但目前表面瑕疵检测在学界主要是计算机专业或者控制专业瞄准图像处理方向在做,而视觉光学系统这一块主 ...

  4. 每天进步一点点------Sobel算子(3)基于彩色图像边缘差分的运动目标检测算法

    摘  要: 针对目前常用的运动目标提取易受到噪声影响.易出现阴影和误检漏检等情况,提出了一种基于Sobel算子的彩色边缘图像检测和帧差分相结合的检测方法.首先用Sobel算子提取视频流中连续4帧图像的 ...

  5. 基于纹理内存的CUDA热传导模拟

    原文链接 项目中有三个,第一个是全局内存,其余两个分别是基于1d和2d纹理内存.项目打包下载. 纹理内存是只读内存,与常量内存相同的是,纹理内存也缓存在芯片中,因此某些情况下,它能减少对内存的请求并提 ...

  6. 基于Qt的FreeType字体轮廓解析

    一.本文目的 以前的文档中.详细的介绍了FreeType开源字体引擎库的基础知识.基本用法.但并未详细的阐明在TurboCG中.是如何解析出一个文字的轮廓的,本文集中阐述.怎么样使用FreeType开 ...

  7. 基于图像二维熵的视频信号丢失检测(Signal Loss Detection)

    1 图像二维熵 ​图像二维熵作为一种特征评价尺度能够反映出整个图像所含平均信息量的高低,熵值(H)越大则代表图像所包含的信息越多,反之熵值(H)越小,则图像包含的信息越少.对于图像信息量,可以简单地认 ...

  8. Image Processing and Analysis_8_Edge Detection:Edge and line oriented contour detection State of the art ——2011

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  9. Canny边缘检測算法原理及其VC实现具体解释(一)

    图象的边缘是指图象局部区域亮度变化显著的部分,该区域的灰度剖面一般能够看作是一个阶跃,既从一个灰度值在非常小的缓冲区域内急剧变化到还有一个灰度相差较大的灰度值.图象的边缘部分集中了图象的大部分信息,图 ...

随机推荐

  1. Linux基本操作 2-----Linux文件系统基本结构

    Linux的文件系统结构             Linux文件系统为一个倒转的单根树状结构 文件系统的根为"/" 文件系统严格区分大小写 路径使用“/”来分割,在windows使 ...

  2. HttpServletRequest对象请求转发和HttpServletResponse对象请求重定向之间的区别

    HttpServletRequest对象request代表浏览器请求对象,HttpServletResponse对象代表服务器响应对象,当用浏览器访问web服务器,发出请求时,Servlet调用ser ...

  3. [Python学习笔记][Python内置函数]

    Python 常用内建函数 比较基础的列表 abs(x) 求绝对值 pow(x,y) 返回x的y次方,等同于x**y round(x[,小数位数]) 对x进行四舍五入,若不指定位数,则返回整数 chr ...

  4. openssl 对称加密算法enc命令详解

    1.对称加密算法概述 openssl的加密算法库提供了丰富的对称加密算法,我们可以通过openssl提供的对称加密算法指令的方式使用,也可以通过调用openssl提供的API的方式使用. openss ...

  5. studio中集成.so文件的两种方式

    .so文件作为NDK的开发包,如果不进行依赖使用将会报错所以,需要.so的一定要配置 注:如果没有引用so文件,可能会在程序执行的时候加载类库失败,有类似如下的DEBUG提示:    java.lan ...

  6. Adnroid Studio使用技巧

    官方第一条提示:所有的使用技巧都可以通过Help→Tips of the Day查看. 下面摘抄一些比较有用的技巧: 1.Esc把活动窗口从工具窗口指向编辑窗口.F12把编辑窗口指向上一次活动的工具窗 ...

  7. 关闭显卡快捷键 CTRL+ALT+方向键

    eclipse中的CTRL+ALT+方向键  会和电脑的快捷键进行冲突,按照以下的方法就可以解决了 打开控制面板,找到“显示”(图中圈划的),点击进入        找到”更改显示器设置“,点击进入 ...

  8. (原创)ubuntu 12.04 安装 apache ant

    1. go to the websie to download the newest version of ant (search google by "Apache Ant"). ...

  9. (原创) mac 10.9.2 eclipse 的 CDT 的 异常的修复

    测试平台:macbook air 2012 , os x 10.9.2 , eclipse 4.3   在升级了 10.9 之后,eclipse 的CDT 无法正常使用了   异常表现:   1. 文 ...

  10. 解决MySQL中文乱码的问题

    遇到中文乱码问题,首先用status命令检查数据库的配置,如下: 上图会显示数据库配置的各项信息. 还可以用 show create database XXX,来显示创建数据库的时候的编码设置. 一般 ...