一阶微分算子首先出现就是
Proberts算子,是一个2x2的算子,检测精度比后面的算子要高,但是和高斯算子一样具有对噪声敏感的特性,所以。。。。后来出现了
Prewitt算子,这个算子是3x3的,但是对噪声也比较敏感。
Sobel算子使用了3x3的模板,但是对中心点的权重增加所以对噪声具有一定的抵抗能力,可以很好的检测到边缘,所以现在使用的比较多。前面几种算子对都是提供2个或者4个模板来检测一个区域,取其中响应最大的那个方向来作为该点的输出。
一些资料l:
边缘检测算子的分析比较.PDF

一种ROBERTS自适应边缘检测方法.PDF

资料网上很多;
代码很长,打包了:https://static.assets-stash.eet-china.com/album/old-resources/2009/3/13/75f8b7b5-d4f4-4844-aa89-76bf46209b15.rar
/****************************************************************
利用算子进行边缘检测
EDGE_ROBERT
-1 | 0
--------|-------
0 | 1
1 | 0
--------|-------
0 | -1
Roberts边缘检测算子是一种利用局部差分算子寻找边缘的算子,Robert算子图像处理后结果边缘不是很平滑。
经分析,由于Robert算子通常会在图像边缘附近的区域内 产生较宽的响应,故采用上述算子检测的边缘图像
常需做细化处理,边缘定位的精度不是很高。
*****************************************************************/
BOOL ImgEdge_Robert(BITMAPINFO* pbmpinfo,BYTE* pbmpdata)
{
LONG imagewidth=(int)pbmpinfo->bmiHeader.biWidth;
LONG imageheigth=(int)pbmpinfo->bmiHeader.biHeight;
//image size
LONG Linebyte =( pbmpinfo->bmiHeader.biBitCount * imagewidth +31)/32*4;
LONG ImageSize=Linebyte * imageheigth;
//data is not null
if (pbmpdata == NULL)
{
return FALSE;
}
//color must be gray
if (pbmpinfo->bmiHeader.biBitCount != 8)
{
AfxMessageBox("只对灰度图像进行操作!");
return FALSE;
}
//copy
BYTE *pNewbmpdata=(BYTE*)malloc(ImageSize);
if (pNewbmpdata == NULL)
{
return FALSE;
}
memcpy(pNewbmpdata,pbmpdata,ImageSize);
//注意数组不要越界,不对右边和下边的数据进行处理
LONG width=0,heigth=0;
BYTE *psrc=NULL;
BYTE *pdest=NULL;
BYTE template_box[4]={0};
BYTE result=0;
for (heigth = 0; heigth < imageheigth -1 ; heigth++)
{
for (width=0; width < imagewidth-1; width++)
{
psrc = pbmpdata+ImageSize- Linebyte*heigth - Linebyte + width;
pdest = pNewbmpdata+ImageSize- Linebyte*heigth - Linebyte + width;
template_box[0]= *psrc;
template_box[1]= *(psrc+1);
template_box[2]= *(psrc-Linebyte);
template_box[3]= *(psrc-Linebyte+1);
result = 2*(unsigned char)sqrt( (template_box[3]-template_box[0])*(template_box[3]-template_box[0])+\
(template_box[0]-template_box[3])*(template_box[0]-template_box[3]) );
//将2个模板的平方的和的sprt
if (result>255)
{
result=255;
}
*pdest=result;
}
}
memcpy(pbmpdata,pNewbmpdata,ImageSize);
free(pNewbmpdata);
return TRUE;
}
/***********************************************************************
SOBLE算子
边沿检测中,常用的一种模板是Sobel 算子。Sobel 算子有两个,一个是检测水平边沿的 ;另一个是检测垂直平边沿的 。与 和
相比,Sobel算子对于象素的位置的影响做了加权,因此效果更好。
Sobel算子另一种形式是各向同性Sobel(Isotropic Sobel)算子,也有两个,一个是检测水平边沿的 ,另一个是检测垂直平边沿的。
各向同性Sobel算子和普通Sobel算子相比,它的位置加权系数更为准确,在检测不同方向的边沿时梯度的幅度一致。由于建筑物图
像的特殊性,我们可以发现,处理该类型图像轮廓时,并不需要对梯度方向进行运算,
所以程序并没有给出各向同性Sobel算子的处理方法。
由于Sobel算子是滤波算子的形式,用于提取边缘,可以利用快速卷积函数,简单有效,因此应用广泛。美中不足的是,Sobel算子
并没有将图像的主体与背景严格地区分开来,换言之就是Sobel算子没有基于图像灰度进行处理,由于Sobel算子没有严格地模拟人
的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。
***********************************************************************/
BOOL ImgEdge_Soble(BITMAPINFO* pbmpinfo,BYTE* pbmpdata)
{
LONG imagewidth=(int)pbmpinfo->bmiHeader.biWidth;
LONG imageheigth=(int)pbmpinfo->bmiHeader.biHeight;
//image size
LONG Linebyte =( pbmpinfo->bmiHeader.biBitCount * imagewidth +31)/32*4;
LONG ImageSize=Linebyte * imageheigth;
//data is not null
if (pbmpdata == NULL)
{
return FALSE;
}
//color must be gray
if (pbmpinfo->bmiHeader.biBitCount != 8)
{
AfxMessageBox("只对灰度图像进行操作!");
return FALSE;
}
//copy
BYTE *pNewbmpdata=(BYTE*)malloc(ImageSize);
if (pNewbmpdata == NULL)
{
return FALSE;
}
memcpy(pNewbmpdata,pbmpdata,ImageSize);
//memset(pNewbmpdata,255,ImageSize);
//注意数组不要越界,不对右边和下边的数据进行处理
LONG width=0,heigth=0;
BYTE *psrc=NULL;
BYTE *pdest=NULL;
int temp_horizon=0;
int temp_vetical=0;
int result=0;
int temp[9]={0};
int maxnum=0;
for (heigth = 1; heigth < imageheigth -1 ; heigth++)
{
for (width=1; width < imagewidth-1; width++)
{
psrc = pbmpdata + ImageSize- Linebyte*heigth - Linebyte + width;
pdest = pNewbmpdata+ImageSize- Linebyte*heigth - Linebyte + width;
//这里没有使用模板来做,减少寻址的次数
temp_horizon = ( *(psrc-Linebyte+1) )- ( *(psrc-Linebyte-1) ) +\
( *(psrc+1) )*2 - ( *(psrc-1) )*2 +\
( *(psrc+Linebyte+1) )- ( *(psrc+Linebyte-1) );
temp_vetical = ( *(psrc - Linebyte-1) ) - ( *(psrc + Linebyte-1) )+\
( *(psrc - Linebyte) ) *2 - ( *(psrc + Linebyte)) *2+\
( *(psrc - Linebyte+1) ) - ( *(psrc + Linebyte+1) );
result=(int)sqrt(temp_horizon*temp_horizon + temp_vetical*temp_vetical);
if (result>255)
{
result=255;
}
*pdest= result;
}
}
memcpy(pbmpdata,pNewbmpdata,ImageSize);
free(pNewbmpdata);
return TRUE;
}
/*****************************************************************************
Sobel算子和Prewitt算子具有平滑作用,能滤除一些噪声,去掉部分伪边缘,但同时也平滑了真正的边缘;
定位精度不高
******************************************************************************/
BOOL ImgEdge_Prewitt(BITMAPINFO* pbmpinfo,BYTE* pbmpdata)
{
LONG imagewidth=(int)pbmpinfo->bmiHeader.biWidth;
LONG imageheigth=(int)pbmpinfo->bmiHeader.biHeight;
//image size
LONG Linebyte =( pbmpinfo->bmiHeader.biBitCount * imagewidth +31)/32*4;
LONG ImageSize=Linebyte * imageheigth;
//data is not null
if (pbmpdata == NULL)
{
return FALSE;
}
//color must be gray
if (pbmpinfo->bmiHeader.biBitCount != 8)
{
AfxMessageBox("只对灰度图像进行操作!");
return FALSE;
}
//copy
BYTE *pNewbmpdata=(BYTE*)malloc(ImageSize);
if (pNewbmpdata == NULL)
{
return FALSE;
}
memcpy(pNewbmpdata,pbmpdata,ImageSize);
//memset(pNewbmpdata,255,ImageSize);
//注意数组不要越界,不对右边和下边的数据进行处理
LONG width=0,heigth=0;
BYTE *psrc=NULL;
BYTE *pdest=NULL;
// BYTE template_box_vertical[9]={-1,-2,-1,0,0,0,1,2,1};
// BYTE template_box_horizon[9]={-1,0,1,-2,0,2,-1,0,1};
// unsigned char temp_horizon=0;
// unsigned char temp_vetical=0;
int temp_horizon=0;
int temp_vetical=0;
int result=0;
for (heigth = 1; heigth < imageheigth -1 ; heigth++)
{
for (width=1; width < imagewidth-1; width++)
{
psrc = pbmpdata + ImageSize- Linebyte*heigth - Linebyte + width;
pdest = pNewbmpdata+ImageSize- Linebyte*heigth - Linebyte + width;
//这里没有使用模板来做,减少寻址的次数
temp_horizon = ( *(psrc-Linebyte+1) )- ( *(psrc-Linebyte-1) ) +\
( *(psrc+1) ) - ( *(psrc-1) ) +\
( *(psrc+Linebyte+1) )- ( *(psrc+Linebyte-1) );
temp_vetical = ( *(psrc - Linebyte-1) ) - ( *(psrc + Linebyte-1) )+\
( *(psrc - Linebyte) ) - ( *(psrc + Linebyte)) +\
( *(psrc - Linebyte+1) ) - ( *(psrc + Linebyte+1) );
result=(int)sqrt(temp_horizon*temp_horizon + temp_vetical*temp_vetical);
//result=abs(temp_horizon) + abs(temp_vetical*temp_vetical);
//将2个模板的平方的和的sprt
if (result>255)
{
result=255;
}
//可以对阈值进行处理
/* if (result<50)
{
result=0;
}*/
*pdest= result;
}
}
memcpy(pbmpdata,pNewbmpdata,ImageSize);
free(pNewbmpdata);
return TRUE;
}
文章评论(0条评论)
登录后参与讨论