机器视觉入门之路(三四,经典canny边缘检测(计算机视觉里程碑))

这一节讲traceedge函数,从字面翻译,显然和边缘痕迹相关,也有人叫他染色嵌套函数,借用别人的指点,这种编程方法对图像中具有相同性质(灰度值等)的联通区域进行染色操作是很有用的。

是的,正是这个traceedge函数的启示,我领悟了找斑函数(findblob),因为我爷爷辈是染布的,后来自己的找斑函数就命名为染色函数,以兹纪念。

以下都是我调试成功,久经考验的函数:

网上traceedge函数的第一种表达(c++),

void TraceEdge(int y, int x, int nThrLow, BYTE *pResult, int *pMag, SIZE sz)  
{   //TraceEdge(i(h),  j(w),        dThrLow,     N,               M,        sz);sz.cx=w;sz.cy=h
    //对8邻域像素进行查询   
    int xNum[8] = {1,1,0,-1,-1,-1,0,1};  
    int yNum[8] = {0,1,1,1,0,-1,-1,-1};  
    LONG yy,xx,k;  
    for(int k=0;k<8;k++)  
    {  
        yy = y+yNum[k];  
        xx = x+xNum[k];  
        if(pResult[(yy*sz.cx+xx)*4]==128 && pMag[yy*sz.cx+xx]>=nThrLow )  
        {  
            //该点设为边界点   
            pResult[(yy*sz.cx+xx)*4] = 255;
                        pResult[(yy*sz.cx+xx)*4+1] = 255;
            pResult[(yy*sz.cx+xx)*4+2] = 255;
            pResult[(yy*sz.cx+xx)*4+3] = 255;
            //以该点为中心再进行跟踪   
            TraceEdge(yy,xx,nThrLow,pResult,pMag,sz);  
        }  
    }  
}  

网上traceedge函数的第二种表达(c++),

void TraceEdge(int y, int x, int nThrLow, BYTE *pResult, int *pMag, SIZE sz)  
{   //TraceEdge(i(h),  j(w),        dThrLow,     N,               M,        sz);sz.cx=w;sz.cy=h
    //癸8綟办琩т  
    //int xNum[8] = {1,1,0,-1,-1,-1,0,1};  
    //int yNum[8] = {0,1,1,1,0,-1,-1,-1};  
    //LONG yy,xx/*,k*/;  
    //for(int k=0;k<8;k++)  
    //{  
    //    yy = y+yNum[k];  
    //    xx = x+xNum[k];  
    //    if(pResult[(yy*sz.cx+xx)]==128 && pMag[yy*sz.cx+xx]>=nThrLow )  
    //    {  
    //        pResult[(yy*sz.cx+xx)] = 255;
    //        TraceEdge(yy,xx,nThrLow,pResult,pMag,sz);  
    //    }  
    //} 
    int i,j;//2013.8.29
   for(i=-1;i<2;i++)
   for(j=-1;j<2;j++)//这里没考虑图像4边界情况,因为边界灰度都事先设为0。不可能是128
    if(pResult[(y+i)*sz.cx+x+j]==128&&pMag[(y+i)*sz.cx+x+j]>nThrLow)
    {
     pResult[(y+i)*sz.cx+x+j]=255;
     TraceEdge(y+i,x+j,nThrLow,pResult,pMag,sz);
    }
}

这是我c#的改进算法:以上使用嵌套递归,这里使用堆栈

   private void TraceEdge(int y, int x, int nThrLow, ref byte[,] pResult, ref int[,] pMag)
         {
             Point start = new Point(x, y);
             Stack<Point> s = new Stack<Point>();
             int[] xNum = new int[8] { 1, 1, 0, -1, -1, -1, 0, 1 };
             int[] yNum = new int[8] { 0, 1, 1, 1, 0, -1, -1, -1 };
             long xx = 0, yy = 0;
             s.Push(start);
             do
             {
                 //Point pt1 = s.ElementAt(0); 
                 Point pt1 = s.Peek();
                 s.Pop();
                 for (int k = 0; k < 8; k++)
                 {
                     yy = y + yNum[k];
                     xx = x + xNum[k];
                     if (pResult[yy, xx] == 128 && pMag[yy, xx] >= nThrLow)
                     {
                         pResult[yy, xx] = 255;
                         Point pt = new Point((int)xx, (int)yy);
                         s.Push(pt);
                     }
                 }
             } while (s.Count != 0);

         }

以下是我的发展而来的findblob(找斑)函数(c++),C#博文中已经存在(染色函数),此处略去,但可以对比着看

void CBufferBase::FindBlob(BYTE *tempImage,int w,int h)//process binary image.8 bits one pixel.
 {
     for(int i=0;i<h;i++)
         for(int j=0;j<w;j++)
         {
             if(tempImage[i*w+j]>128)
             {
                 tempImage[i*w+j]=0;
             }
             else
             {
                 tempImage[i*w+j]=128;
             }
         }
         CPoint start;
         for(int m=0;m<h;m++)
             for(int n=0;n<w;n++)
             {
                 if(tempImage[m*w+n]==128)
                 {
                     start.x=n;
                     start.y=m;
                     break;
                 }
             }
      stack<CPoint> s;
            //癸8綟办琩т  
    int xNum[8] = {1,1,0,-1,-1,-1,0,1};  
    int yNum[8] = {0,1,1,1,0,-1,-1,-1};  
    LONG yy=0,xx=0;  

    tempImage[ start.y*w+start.x ]=255;
     

      s.push(start);

      do{
          CPoint pt1=s.top();
          s.pop();

          for(int k=0;k<8;k++)  
          {  
              yy = pt1.y+yNum[k];  
              xx =pt1. x+xNum[k];  
              if(tempImage[(yy*w+xx)]==128)  
              {  
                  tempImage[(yy*w+xx)] = 255;
                  CPoint pt(xx,yy);
                  s.push(pt);
              }  
          } 
      }while(!s.empty());
 }

没有谁能一次成功,只是跟着遛弯久了,自然就通透了。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页