您的位置:首页 > 其它

边缘检测之Sobel算子详谈

2013-05-22 15:38 239 查看
在边缘检测中,常用的一种模板是Sobel 算子。Sobel 算子有两个,一个是检测水平边缘的 ;另一个是检测垂直边缘的 。与Prewitt算子相比,Sobel算子对于象素的位置的影响做了加权,可以降低边缘模糊程度,因此效果更好。

Sobel算子另一种形式是各向同性Sobel(Isotropic Sobel)算子,也有两个,一个是检测水平边缘的 ,另一个是检测垂直边缘的 。各向同性Sobel算子和普通Sobel算子相比,它的位置加权系数更为准确,在检测不同方向的边沿时梯度的幅度一致。将Sobel算子矩阵中的所有2改为根号2,就能得到各向同性Sobel的矩阵。

由于Sobel算子是滤波算子的形式,用于提取边缘,可以利用快速卷积函数,
简单有效,因此应用广泛。美中不足的是,Sobel算子并没有将图像的主体与背景严格地区分开来,换言之就是Sobel算子没有基于图像灰度进行处理,由于Sobel算子没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。 在观测一幅图像的时候,我们往往首先注意的是图像与背景不同的部分,正是这个部分将主体突出显示,基于该理论,我们给出了下面阈值化轮廓提取算法,该算法已在数学上证明当像素点满足正态分布时所求解是最优的。


函数cvSobel

使用扩展 Sobel 算子计算一阶、二阶、三阶或混合图像差分
void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );


src输入图像.dst输出图像.xorderx 方向上的差分阶数yordery 方向上的差分阶数aperture_size扩展 Sobel 核的大小,必须是 1, 3, 5 或 7。 除了尺寸为 1, 其它情况下, aperture_size ×aperture_size 可分离内核将用来计算差分。对 aperture_size=1的情况, 使用 3x1 或 1x3 内核 (不进行高斯平滑操作)。这里有一个特殊变量 CV_SCHARR (=-1),对应 3x3 Scharr 滤波器,可以给出比 3x3 Sobel 滤波更精确的结果。Scharr
滤波器系数是:



对 x-方向 或矩阵转置后对 y-方向。

函数 cvSobel 通过对图像用相应的内核进行卷积操作来计算图像差分:



由于Sobel 算子结合了 Gaussian 平滑和微分,所以,其结果或多或少对噪声有一定的鲁棒性。通常情况,函数调用采用如下参数 (xorder=1, yorder=0, aperture_size=3) 或 (xorder=0, yorder=1, aperture_size=3) 来计算一阶 x- 或 y- 方向的图像差分。第一种情况对应:


核。

第二种对应:



或者



核的选则依赖于图像原点的定义 (origin 来自 IplImage 结构的定义)。由于该函数不进行图像尺度变换,所以和输入图像(数组)相比,输出图像(数组)的元素通常具有更大的绝对数值(译者注:即像素的位深)。为防止溢出,当输入图像是 8 位的,要求输出图像是 16 位的。当然可以用函数 cvConvertScale 或 cvConvertScaleAbs 把运算结果(dst)转换为 8 位的。除了8-位图像,函数也接受 32-位 浮点数图像。所有输入和输出图像都必须是单通道的,并且具有相同的图像尺寸或者ROI尺寸。

//  根据《基于OpenCV的计算机视觉技术实现》程序 6-1 改编

IplImage* pImage;
IplImage* pImgSobel = NULL;
IplImage* pImgPlanes[3] = {0,0,0};
int   i;

pImage = workImg;

pImgSobel= cvCreateImage(cvGetSize(pImage),
IPL_DEPTH_16S,1);   //  建立工作位图

if (workImg->nChannels==1) {            //  单通道图像处理
cvSobel(pImage,pImgSobel,1,1,3);
cvConvertScaleAbs(pImgSobel,pImage, 1, 0 );
}
else {                                  //  三通道图像处理
for (i=0;i<3;i++) {
pImgPlanes[i] = cvCreateImage(cvGetSize(pImage),
IPL_DEPTH_8U,1);    //  建立分量位图
}

cvCvtPixToPlane(pImage,pImgPlanes[0],
pImgPlanes[1],pImgPlanes[2],0);  //  取出各分量

for (i=0;i<3;i++) {                 //  各分量单独处理
cvSobel(pImgPlanes[i],pImgSobel,1,1,3);
cvConvertScaleAbs(pImgSobel,pImgPlanes[i], 1, 0 );
}

cvCvtPlaneToPix(pImgPlanes[0],pImgPlanes[1],
pImgPlanes[2],0,pImage);    //  由分量组装成彩色图像

for (i=0;i<3;i++) {
cvReleaseImage(&pImgPlanes[i]);  //  释放分量位图
}
}
cvReleaseImage(&pImgSobel);             //  释放工作位图
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐