原创 2.数字图像与C语言之轮廓提取

2011-1-26 02:58 6075 6 6 分类: 处理器与DSP

图像轮廓代表图像特征的线要素。在提取轮廓时,首先应当注重于浓度的变化。

图像的浓度急剧变化,称之为边界。提取出清晰漂亮的轮廓并非易事,不过有很多算法可以实现。

2.1 利用微分提取图像的轮廓。

由于轮廓产生于浓度值急剧变化的部分,因此可知,利用可以取出函数变化部分的微分运算就能抽出图像的轮廓。而微分又有一阶微分(斜率)与二阶微分(拉普拉斯算子),这两种微分可用于轮廓的提取。

(1)一阶微分(斜率,差分)

在x方向上的微分为 fx=f(x+1,y)-f(x,y)

在y方向上的微分为 fy=f(x,y+1)-f(x,y)

强度为fx和fy的平方和的开方根

或者为|fx|+|fy|

方向为(fx,fy)

求解公式是,第二条简单,但是,由轮廓浓度较暗处指向较明处。可以从梯度满意的检测出边界。

(2)二阶微分(拉普拉斯算子)

拉普拉斯算子又称为二阶微分L(x,y) 。由于他是把梯度,变化率再求一次微分,所以只用求出轮廓的强度(不求方向)。

数字图像以下式表示:

L(x,y)=4Xf(x,y)-{f(x,y-1)+f(x,y+1)+f(x-1,y)+f(x+1,y)}

在数字图像处理中,数据时以一定的间隔分开的,故无法实行本来意义上的微分运算,所以利用差分实现近似微分值。

 

为了对微分实行差分近似计算,需要采用表示相邻像素差值的系数组,称为微分算子。具体程序如下:

 

用一阶微分实现轮廓提取:

#include<math.h>
#include<Params.h>
/** 用一阶微分提取轮廓
image_in:输入图像数组
image_out:输出的图像数组
amp:输出图像的增益
**/
void gradient(unsigned char image_in[ysize][xsize],
              unsigned char image_out[ysize][xsize],float amp)
   {
   static int cx[9]={0,0,0,   /*算子的系数x(Roberts)*/
                     0,1,0,   /*采用其他请替换*/
                     0,0,-1
                    };
   static int cy[9]={0,0,0,   /*算子的系数y(Roberts)*/
                     0,0,1,   /*采用其他请替换*/
                     0,-1,0
                     };
    int d[9];
    int i,j,dat;
    float xx,yy,zz;
    for(i=1;i<ysize-1;i++){
       for(j=1;j<xsize-1;j++){
       d[0]=image_in[i-1][j-1];
       d[1]=image_in[i-1][j];
       d[2]=image_in[i-1][j+1];
       d[3]=image_in[j-1];
       d[4]=image_in[j];
       d[5]=image_in[j+1];
       d[6]=image_in[i+1][j-1];
       d[7]=image_in[i+1][j];
       d[8]=image_in[i+1][j+1];
      
       xx=(float)(cx[0]*d[0]+cx[1]*d[1]+cx[2]*d[2]+
                  cx[3]*d[3]+cx[4]*d[4]+cx[5]*d[5]+
                  cx[6]*d[6]+cx[7]*d[7]+cx[8]*d[8]
                 );
      yy=(float)(cy[0]*d[0]+cy[1]*d[1]+cy[2]*d[2]+
                 cy[3]*d[3]+cy[4]*d[4]+cy[5]*d[5]+
                  cy[6]*d[6]+cy[7]*d[7]+cy[8]*d[8]
                 );
       zz=(float)(amp*sqrt(xx*xx+yy*yy));
       dat=(int)zz;
       if(dat>255) dat=255;
       image_out[j]=(char)dat;
       }
    }
  
             
   }

2.用二阶微分提取轮廓

#include<math.h>
#include<Params.h>
/** 用二阶微分提取轮廓
image_in:输入图像数组
image_out:输出的图像数组
amp:输出图像的增益
**/
void lapacian(unsigned char image_in[ysize][xsize],
              unsigned char image_out[ysize][xsize],float amp)
{
  static int c[9]={-1,-1,-1,   /*算子的系数x(lalacian)*/
                   -1,8,-1,   /*采用其他请替换*/
                   -1,-1,-1
                   };           
    int d[9];
    int i,j,dat;
    float z,zz;
 for(i=1;i<ysize-1;i++){
       for(j=1;j<xsize-1;j++){
       d[0]=image_in[i-1][j-1];
       d[1]=image_in[i-1][j];
       d[2]=image_in[i-1][j+1];
       d[3]=image_in[j-1];
       d[4]=image_in[j];
       d[5]=image_in[j+1];
       d[6]=image_in[i+1][j-1];
       d[7]=image_in[i+1][j];
       d[8]=image_in[i+1][j+1];
       z=(float)(c[0]*d[0]+c[1]*d[1]+c[2]*d[2]+
                  c[3]*d[3]+c[4]*d[4]+c[5]*d[5]+
                  c[6]*d[6]+c[7]*d[7]+c[8]*d[8]
                 );  
        zzamp*z;
        dat=(int)(zz);
        if(dat<0) dat=-dat;
        if(dat>255)dat=255;
        image_out[j]=(char)dat;
        }
     }
 }

 

 

 

 

 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条