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

    技术2022-07-11  86

    这一节讲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());  }

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

    Processed: 0.035, SQL: 9