机器视觉项目一:小孔判定与最短距识别

版权声明:本文为博主原创文章,未经博主允许不得转载。欢迎交流,QQ:896922782,微信:15058133936 https://blog.csdn.net/zhubenfulovepoem/article/details/6802937

Question:以下两幅图像,判断出哪个有孔,并计算出图中勺子的最窄处的宽度?

代码下载:http://www.pudn.com/downloads386/sourcecode/graph/texture_mapping/detail1655727.html


我用vc++编写的识别框架如下:

1.运行界面打开图像:

2.点击区域分割与提取:


3.进行多次中值滤波,然后进行一次一阶微分运算,运算结果放大两倍,然后去25二值化得到边界图:


然后计算最后操那个图的像素总值,2.bmp显示结果为接近6000;求得最短就离为31个像素点,利用length=nmin/28.346这个即可求出距离。


关键代码:

/*----Threshold----二值化处理------------------------

image_in 输入图像数据指针

image_out 输出图像数据指针

xsize   图像宽度

ysize   图像高度

thresh  阈值(0-255)

mode    处理方法(1,2)

--------------------------------------------------*/

void Threshold(BYTE *image_in,BYTE*image_out,int xsize,int ysize,int thresh,int mode)

       {

              inti,j;

              for(j=0;j<ysize;j++)

              {

                     for(i=0;i<xsize;i++)

                     {

                            switch(mode)

                            {

                            case2:

                                   if(*(image_in+i+j*xsize)<=thresh)

                                          *(image_out+i+j*xsize)=HIGH;

                                   else

                                          *(image_out+i+j*xsize)=LOW;

                                   break;

                            default:

                                   if(*(image_in+i+j*xsize)>=thresh)

                                          *(image_out+i+j*xsize)=HIGH;

                                   else

                                          *(image_out+i+j*xsize)=LOW;

                                   break;

                            }

                     }    

              }

       }

//中值子函数

int median_value(BYTE c[9])

{

       inti,j,buf;

       for(j=0;j<8;j++){

              for(i=0;i<8;i++){

                     if(c[i+1]<c[i]){

                            buf=c[i+1];

                            c[i+1]=c[i];

                            c[i]=buf;

                     }

              }

       }

       returnc[4];

}

//中值滤波

void Median(BYTE *image_in, BYTE*image_out, int xsize, int ysize)

{

       inti,j;

       unsignedchar c[9];

       for(i=1;i<ysize-1;i++){

              for(j=1;j<xsize-1;j++){

              c[0]=*(image_in+(i-1)*xsize+j-1);

              c[1]=*(image_in+(i-1)*xsize+j);

              c[2]=*(image_in+(i-1)*xsize+j+1);

              c[3]=*(image_in+i*xsize+j-1);

              c[4]=*(image_in+i*xsize+j);

              c[5]=*(image_in+i*xsize+j+1);

              c[6]=*(image_in+(i+1)*xsize+j-1);

              c[7]=*(image_in+(i+1)*xsize+j);

              c[8]=*(image_in+(i+1)*xsize+j+1);

              *(image_out+i*xsize+j)=median_value(c);

              }

       }

}

/*--------------------------提取轮廓-----------------------------*

//1阶微分边沿检出(梯度算子)

amp    //输出像素值倍数

roberts算子:g(x,y)=abs(f(x,y)-f(x+1,y+1))+abs(f(x,y+1)-f(x+1,y))

Roberts边缘检测算子是一种利用局部差分算子寻找边缘的算子,Robert算子图像处理后结果边缘不是很平滑。

经分析,由于Robert算子通常会在图像边缘附近的区域内 产生较宽的响应,

故采用上述算子检测的边缘图像常需做细化处理,边缘定位的精度不是很高。

卷积运算:可看作是加权求和的过程,使用到的图像区域中的每个像素

分别于卷积核(权矩阵)的每个元素对应相乘,所有乘积之和作为区域中心像素的新值。

连续空间的卷积定义是f(x)与g(x)的卷积是 f(t-x)g(x) 在t从负无穷到正无穷的积分值.t-x要在f(x)定义域内

所以看上去很大的积分实际上还是在一定范围的

把积分符号换成求和就是离散空间的卷积定义了.那么在图像中卷积卷积地是什么意思呢,

就是图像就是图像f(x),模板是g(x),然后将模版g(x)在模版中移动,每到一个位置,

就把f(x)与g(x)的定义域相交的元素进行乘积并且求和,得出新的图像一点,就是被卷积后的图像.

------------------------------------------------------------------*/

void Differential(BYTE *image_in, BYTE*image_out, int xsize, int ysize, float amp)

{

       staticint cx[9]={0,0,0,0,1,0,0,0,-1};  //算子X(roberts)

       staticint cy[9]={0,0,0,0,0,1,0,-1,0};  //算子y(roberts)

       intd[9];

       inti,j,dat;

       floatxx,yy,zz;

       for(j=1;j<ysize-1;j++)

       {

              for(i=1;i<xsize;i++)

              {

                     d[0]=*(image_in+(j-1)*xsize+i-1);

                     d[1]=*(image_in+(j-1)*xsize+i);

                     d[2]=*(image_in+(j-1)*xsize+i+1);

                     d[3]=*(image_in+j*xsize+i-1);

                     d[4]=*(image_in+j*xsize+i);

                     d[5]=*(image_in+j*xsize+i+1);

                     d[6]=*(image_in+(j+1)*xsize+i-1);

                     d[7]=*(image_in+(j+1)*xsize+i);

                     d[8]=*(image_in+(j+1)*xsize+i+1);//在图像上取出3*3的像素值

                     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*xsize+i)=dat;

              }

       }

}

//膨胀

void Dilation(BYTE *image_in, BYTE*image_out, int xsize, int ysize)

{

       inti,j;

       for(j=1;j<ysize-1;j++){

              for(i=1;i<xsize-1;i++){

                     *(image_out+j*xsize+i)=*(image_in+j*xsize+i);

                     if(*(image_in+(j-1)*xsize+i-1)==HIGH)

                     *(image_out+j*xsize+i)=HIGH;

                     if(*(image_in+(j-1)*xsize+i)==HIGH)

                     *(image_out+j*xsize+i)=HIGH;

                     if(*(image_in+(j-1)*xsize+i+1)==HIGH)

                     *(image_out+j*xsize+i+1)=HIGH;

                     if(*(image_in+j*xsize+i-1)==HIGH)

                     *(image_out+j*xsize+i)=HIGH;

                     if(*(image_in+j*xsize+i+1)==HIGH)

                     *(image_out+j*xsize+i)=HIGH;

                     if(*(image_in+j*xsize+i)==HIGH)

                     *(image_out+j*xsize+i)=HIGH;

                     if(*(image_in+(j+1)*xsize+i-1)==HIGH)

                     *(image_out+j*xsize+i)=HIGH;

                     if(*(image_in+(j+1)*xsize+i+1)==HIGH)

                     *(image_out+j*xsize+i)=HIGH;

                     if(*(image_in+(j+1)*xsize+i)==HIGH)

                     *(image_out+j*xsize+i)=HIGH;

              }

       }

}

//腐蚀

void Erodible(BYTE *image_in, BYTE*image_out, int xsize, int ysize)

{

       inti,j;

       for(j=1;j<ysize-1;j++){

              for(i=1;i<xsize-1;i++){

                     *(image_out+j*xsize+i)=*(image_in+j*xsize+i);

                     if(*(image_in+(j-1)*xsize+i-1)==LOW)

                     *(image_out+j*xsize+i)=LOW;

                     if(*(image_in+(j-1)*xsize+i)==LOW)

                     *(image_out+j*xsize+i)=LOW;

                     if(*(image_in+(j-1)*xsize+i+1)==LOW)

                     *(image_out+j*xsize+i+1)=LOW;

                     if(*(image_in+j*xsize+i-1)==LOW)

                     *(image_out+j*xsize+i)=LOW;

                     if(*(image_in+j*xsize+i+1)==LOW)

                     *(image_out+j*xsize+i)=LOW;

                     if(*(image_in+j*xsize+i)==LOW)

                     *(image_out+j*xsize+i)=LOW;

                     if(*(image_in+(j+1)*xsize+i-1)==LOW)

                     *(image_out+j*xsize+i)=LOW;

                     if(*(image_in+(j+1)*xsize+i+1)==LOW)

                     *(image_out+j*xsize+i)=LOW;

                     if(*(image_in+(j+1)*xsize+i)==LOW)

                     *(image_out+j*xsize+i)=LOW;

              }

       }

}

/********************************************************************/

//求像素总和

int i,j;

       for(j=1;j<m_nysize-1;j++){

              for(i=1;i<m_nxsize-1;i++){

                     *(m_pImage_out+j*m_nxsize+i)=*(m_pImage_in+j*m_nxsize+i);

                     if(*(m_pImage_in+j*m_nxsize+i-1)==HIGH)

                            m_nSum++;

              }

       }

       SetDlgItemInt(IDC_SUM,m_nSum,TRUE);

/**********************************************************************/

求最短距离

int i,j;

       intxx,yy;

       intjj=0;

       intii=0;

       intsumiy[429]={0};

       intsumjy[429]={0};

       intsum[429]={1};

       intiy[116]={0};

       intjy[116]={0};

       intnmin=100;//最短距离初值

       for(j=1;j<m_nysize-1;j++)

       {

              for(i=1;i<m_nxsize-1;i++)//求出某一行在横坐标方向上的左起像素岂起始点

              {

                     //*(m_pImage_out+j*m_nxsize+i)=*(m_pImage_in+j*m_nxsize+i);

                     if(*(m_pImage_in+j*m_nxsize+i-1)==HIGH)

                            xx=1;

                     if(xx==1)

                     {

                            iy[jj]=i;

                            jj++;

                     }

              }

              sumiy[j]=iy[1];

      

              for(i=m_nxsize-1;i>1;i--)//求出某一行在横坐标方向上的右起像素岂起始点

              {

                     if(*(m_pImage_in+j*m_nxsize+i-1)==HIGH)

                            yy=1;

                     if(ii==1)

                     {

                            jy[ii]=i;

                            ii++;

                     }

              }

              sumjy[j]=jy[1];

              sum[j]=abs(sumjy[j]-sumiy[j]);//求出某一行在横坐标方向上的像素区间

       }

       for(j=1;j<427;j++)

       {

        //求出所有行中在在横坐标方向像素区间最小的距离

              if((sum[j]>30) && (sum[j]<100))//排除错误成分

                     {

                            if( sum[j]<nmin )

                            {

                                   nmin=sum[j];

                            }

                     }

       }

       SetDlgItemInt(IDC_MIN,nmin,TRUE);


猜你喜欢

转载自blog.csdn.net/zhubenfulovepoem/article/details/6802937