这一节讲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()); }
没有谁能一次成功,只是跟着遛弯久了,自然就通透了。