设为首页 加入收藏

TOP

Visual C++ 实现数字化图像的分割(三)
2012-11-04 15:25:27 来源: 作者: 【 】 浏览:892
Tags:Visual 实现 数字化 图像 分割
  Kirsch算子实现起来相对来说稍微麻烦一些,它采用8个模板对图像上的每一个像素点进行卷积求导数,这8个模板代表8个方向,对图像上的8个特定边缘方向作出最大响应,运算中取最大值作为图像的边缘输出(上述算法中用到的8个模板在下面的实现代码中给出)。为了便于读者理解该算法的实现,这里我们给出实现该算法的函数代码,读者可以稍加改动应用到自己的项目中去。

BOOL Kirsch(BYTE *pData,int Width,int Height)
{//定义实现Kirsch算法的8个模板;
int i,j,s,t,k,max,sum[8];
static a[3][3]={{+5,+5,+5},{-3,0,-3},{-3,-3,-3}};
static a1[3][3]={{-3,+5,+5},{-3,0,+5},{-3,-3,-3}};
static a2[3][3]={{-3,-3,+5},{-3,0,+5},{-3,-3,+5}};
static a3[3][3]={{-3,-3,-3},{-3,0,+5},{-3,+5,+5}};
static a4[3][3]={{-3,-3,-3},{-3,0,-3},{+5,+5,+5}};
static a5[3][3]={{-3,-3,-3},{+5,0,-3},{+5,+5,-3}};
static a6[3][3]={{+5,-3,-3},{+5,0,-3},{+5,-3,-3}};
static a7[3][3]={{+5,+5,-3},{+5,0,-3},{-3,-3,-3}};
BYTE *pData1;
if(pData==NULL)
{
AfxMessageBox("图像数据为空,请读取图像数据!");
return FALSE;
}
pData1=(BYTE*)new char[Width*Height];
if(pData1==NULL)
{
AfxMessageBox("图像缓冲数据区申请失败,请重新申请图像数据缓冲区!");
return FALSE ;
}
memcpy(pData1,pData, Width*8*Height);
//kirsch算子处理,对每一像素点求取八个方向的导数;;
for(i=1;i<Height-1;i++)
for(j=1;j<Width-1;j++)
{
sum[1]=sum[2]=sum[3]=sum[4]=sum[5]=sum[6]=sum[7]=sum[8]=0;
for(t=-1;t<2;t++)
{
for(s=-1;s<2;s++)
{ sum[1]+=*(pData+WIDTHBYTES(Width*8)*(i+t)+j+s)*a[1+t][1+s];
sum[2]+=*(pData+WIDTHBYTES(Width*8)*(i+t)+j+s)*a1[1+t][1+s]; sum[3]+=*(pData+WIDTHBYTES(Width*8)*(i+t)+j+s)*a2[1+t][1+s]; sum[4]+=*(pData+WIDTHBYTES(Width*8)*(i+t)+j+s)*a3[1+t][1+s]; sum[5]+=*(pData+WIDTHBYTES(Width*8)*(i+t)+j+s)*a4[1+t][1+s]; sum[6]+=*(pData+WIDTHBYTES(Width*8)*(i+t)+j+s)*a5[1+t][1+s]; sum[7]+=*(pData+WIDTHBYTES(Width*8)*(i+t)+j+s)*a6[1+t][1+s]; sum[8]+=*(pData+WIDTHBYTES(Width*8)*(i+t)+j+s)*a7[1+t][1+s];
}
}
//取最大方向的导数;
for(k=0;k<8;k++)
{
max=0;
if(max<sum[k])
max=sum[k];
}
if(max<0)
max=0;
if(max>255)
max=255;
*(pData1+ Width*8*i+j)=max;
}
memcpy(pData,pData1, Width*8*Height);
delete pData1;
return TRUE;
}

  另外还有一种称为拉普拉斯的算子是不依赖于边缘方向的二阶微分算子,其表示式 ,对于数字图像来说拉普拉斯算子可以简单表示为:G[I,j]=|f[i+1,j]+f[i-1,j]+f(i,j+1)+f[i,j-1]-4f[i,j]|;它是一个标量而不是向量,具有旋转不变,既各向同性的性质,它常常用在图像处理的过程中。

  梯度算子和拉普拉斯算子对噪声敏感,它们都使噪声成份加强,因此在处理含有较大噪声的图像时,常常先对图像进行平滑操作,然后再进行二阶微分,这就产生了所谓的LOG(又称为Marr方法)边缘检测方法。它先用高斯函数对图像进行平滑,然后再用拉普拉斯算子进行运算。

  总的来说,传统的边缘检测算子的噪声平滑能力和边缘定位能力是矛盾的,为了克服这个不足,正确地得到图像的边缘信息,人们提出了很多方法,如多尺度空间滤波、Facet模型检测边缘、模板匹配、Hough变换、小波变换、人工神经网络、模糊推理等算法。但这些方法绝大多数没有经典的算法精简,要么难以获得合理的计算复杂度,要么需要人为的调节各种参数,有时甚至难以实时运行。因为传统边缘的定义为图像中灰度的突变,所以这样定义边缘既失去了边缘的部分信息,又把噪声的影响包含在了边缘中。其实,边缘往往具有以下特征:

  1)灰度突变;

  2)是不同区域的边界;

  3)具有方向性;

  根据边缘的这三个特征,可以判断所关心的区域其特征是否存在差异来判断是否存在边缘的可能性。如果特征没有差异,则认为是平滑区;如果特征有差异,则判断为边缘点。算法的具体实现步骤如下:

  1) 设置四个3x3模板如图三所示,显而易见,四个模板分别按0、45、90、135以(x,y)点为中心将3x3的区域分成两个部分,按照这四个模板分别对图像中的每一像素点进行卷积求和操作。

  2)对图像中每一像素点求的四个结果求绝对值,将每个结果分别与一个阈值比较,如果其中任意一结果大于或等于阈值T,则该模板的中心点所对应的图像像素点的灰度值为255,否则为0。

 
图三 边缘提取模板

  对于有噪声的图像,由于噪声是随机分布的,因此不论(x,y)是有效边界点还是处于平坦区域内部,沿边缘方向划分的两个区域R1和R2的噪声分布和噪声强度,在概率上相同。从四个模板的结构可以看出,噪声的影响基本上被相应的抵消,不会对边缘提取产生太大的影响,因此该算法具有较好的抗噪能力,克服了传统的边界提取仅考虑灰度突变的情况的局限。经实验证明该方法有较强的抗噪声性能。为了更好的对比各种算法进行边缘检测的效果,我们对一幅汽车图像进行了处理,下图中的a、b、c、d是分别通过LOG算子、Sober算子、Kirsch算子和使用上述算法检测得到的边缘。


(a) 原始图像

(b)LOG算子

(c) Sober算子

(d) Kirsch算子

(e) 模板检测法
 
  图四 图像的边缘检测

  从上面的处理后的效果图来说,只有最后一种算法处理后肉眼看不出有噪声点,所以从去噪和提取边缘的综合效果来看,我们上述介绍的模板检测算法还是比较另人满意的。

首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇VC通用控件编程之CProgress控件 下一篇VC编程轻松获取局域网连接通知

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: