1.概述
边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。 这些包括(i)深度上的不连续、(ii)表面方向不连续、(iii)物质属性变化和(iv)场景照明变化。 边缘检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。
图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。有许多方法用于边缘检测,它们的绝大部分可以划分为两类:基于查找一类和基于零穿越的一类。基于查找的方法通过寻找图像一阶导数中的最大和最小值来检测边界,通常是将边界定位在梯度最大的方向。基于零穿越的方法通过寻找图像二阶导数零穿越来寻找边界,通常是Laplacian过零点或者非线性差分表示的过零点。
1.1 梯度算子
梯度对应一阶导数,对于一个连续图像函数f(x,y),它在点f(x,y)处的梯度是一个矢量,定义为
式中 和 分别为沿x方向和y方向的梯度。梯度的幅度| |和方向角分别为
由上式可知,梯度的数值就是f(x,y)在其最大变化率方向上的单位距离所增加的量。对于数字图像而言,梯度是由差分代替微分来实现的,所以上式可以写为
式中各像素的位置如图6-6b所示这种梯度法又称为水平垂直差分法。另一种梯度法如图a所示,是交叉地进行差分计算,称为罗伯特梯度法,表示为
以上各式中的偏导数需对每个像素进行运算,在实际中常用小区模板进行卷积来近似计算。
由梯度的计算可知,在图像中灰度变化较大的边缘区域其梯度值较大,在灰度变化平缓的区域其梯度值较小,而在灰度均匀的区域其梯度值为零。
1.2 拉普拉斯算子
拉普拉斯算子是常用的边缘检测算子,它在各个同向性的二阶导数
经边缘检测的图像g(x,y)为
式中,系数K与扩散效应有关。图像f(x,y)经拉普拉斯运算后得到检测出边缘的图像g(x,y)。需要注意的是,对系数K的选择要合理,太大会使图像中的边缘产生过冲,太小则边缘不明显。对数字图像来讲,f(x,y)的二阶偏导数可以表示为
2.调试
2.1 matlab调试结果及代码
MATLAB代码
I=imread('D:\\Administrator\\My Pictures\\Lenagray.bmp');
BW_sobel = edge(I,'sobel');
BW_prewitt = edge(I,'prewitt');
BW_roberts = edge(I,'roberts');
BW_laplace = edge(I,'log');
figure(1);
subplot(2,3,1),imshow(I),xlabel('ÔʼͼÏñ');
subplot(2,3,2),imshow(BW_sobel),xlabel('sobel¼ì²â');
subplot(2,3,3),imshow(BW_prewitt),xlabel('prewitt¼ì²â');
subplot(2,3,4),imshow(BW_roberts),xlabel('roberts¼ì²â');
subplot(2,3,5),imshow(BW_laplace),xlabel('laplace¼ì²â');
2.2 ccs调试结果及代码
2.2.1 边缘检测
测试结果
拉普拉斯算子处理:
Prewitt算子处理:
Sobel算子处理:
Robert算子处理:
CCS测试代码
#include
#include
#define IMAGEWIDTH 256
#define IMAGEHEIGHT 256
#define Uint8 unsigned char
#pragma DATA_SECTION(grey1,"my_sect")
void ReadImage(char *cFileName);
void bmpDataPart(FILE* fpbmp);
void EdgeDetection();
unsigned char grey[IMAGEHEIGHT][IMAGEWIDTH];
unsigned char grey1[IMAGEHEIGHT][IMAGEWIDTH];
void main()
{
ReadImage("D:\\Administrator\\My Pictures\\Lenagray.bmp");
EdgeDetection();
while (1) ;
}
void ReadImage(char *cFileName)
{
FILE *fp;
if ( fp=fopen(cFileName,"rb" ) )
{
bmpDataPart(fp);
fclose(fp);
}
}
void bmpDataPart(FILE* fpbmp)
{
int i, j=0;
unsigned char* pix=NULL;
fseek(fpbmp, 54L, SEEK_SET);
pix=(unsigned char*)malloc(256);
for(j=0;j
{
fread(pix, 1, 256, fpbmp);
for(i=0;i
{
grey[IMAGEHEIGHT-1-j][i] =pix[i];
grey1[IMAGEHEIGHT-1-j][i] =pix[i];
}
}
}
void EdgeDetection(int choose)
{
int i,j;
int greytemp_x,greytemp_y;
// int Kx[2][2]={{1,0},{0,-1}}; // Robert算子
// int Ky[2][2]={{0,1},{-1,0}};
// int Kx[3][3]={{-1,0,1},{-1,0,1},{-1,0,1}}; //Prewitt算子
// int Ky[3][3]={{1,1,1},{0,0,0},{-1,-1,-1}};
int Kx[3][3]={{-1,0,1},{-2,0,2},{-1,0,1}}; // Sobel算子
int Ky[3][3]={{1,2,1},{0,0,0},{-1,-2,-1}};
// int K[3][3]={{0,1,0},{1,-4,1},{0,1,0}}; //拉普拉斯算子
for(i=1;i
{
for(j=1;j
{
greytemp_x = (
Kx[0][0]*grey[i-1][j-1] +
Kx[0][1]*grey[i-1][j] +
Kx[0][2]*grey[i-1][j+1] +
Kx[1][0]*grey[i][j-1] +
Kx[1][1]*grey[i][j]+
Kx[1][2]*grey[i][j+1] +
Kx[2][0]*grey[i+1][j-1] +
Kx[2][1]*grey[i+1][j] +
Kx[2][2]*grey[i+1][j+1]
);
greytemp_y = (
Ky[0][0]*grey[i-1][j-1] +
Ky[0][1]*grey[i-1][j] +
Ky[0][2]*grey[i-1][j+1] +
Ky[1][0]*grey[i][j-1] +
Ky[1][1]*grey[i][j]+
Ky[1][2]*grey[i][j+1] +
Ky[2][0]*grey[i+1][j-1] +
Ky[2][1]*grey[i+1][j] +
Ky[2][2]*grey[i+1][j+1]
);
grey1[i][j] = sqrt(greytemp_x*greytemp_x+greytemp_y*greytemp_y);
}
}
}