BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / ml-dm / #3034同步于 2008/9/1
该镜像源已超过 30 天没有更新,可能在源站已被删除。
ML_DM机器人发帖

[求助]轮廓(边界)追踪的算法

grepf
2008/9/1镜像同步1 回复
我自己写的纯c代码,貌似有问题,因下图的追踪结果显然不对,恳请大牛指点一下错误所在. 附件(17.4KB) t1out.bmp /* * calc_length -- 求周长 * image_label: 标签图像数组 * label: 标签序号 */ float calc_length(unsigned char * image_label, int x_size, int y_size, int label) { int i, j; // 位图数据大小试验 int nPitch = ( (x_size * 8 + 31) >> 5 )<< 2; for (i = 0; i < y_size; i++) for (j = 0; j < x_size; j++) if (*(image_label + i*nPitch + j) == label) { //return trace(image_label, x_size, y_size, j-1, i); return trace(image_label, x_size, y_size, j, i); } return 0; } /* * nextpoint -- 追踪轮廓线:选择最合适的下一个点 * image_label: 标签图像数组 * label: 当前标签 * p[6]: 由 起始位置、当前点位置、下一点位置所组成的4点坐标数组,每个点格式为(x,y) */ bool nextpoint(unsigned char * image_label, int x_size, int y_size, int label, int p[6], float * l, int * vec) { int startx, starty, curx, cury, nextx, nexty; int x, y; int d[8]; /*右、右上、上、左上、左、左下、下、右下*/ // 位图数据大小试验 int nPitch = ((x_size * 8 + 31) >> 5) << 2; startx = p[0]; starty = p[1]; curx = p[2]; cury = p[3]; x = curx; y = cury; if (curx == startx && cury == starty) // 当前点是起始点 { // 开始追踪轮廓 if (curx == 0 || cury == 0) { if (curx == 0) { if (cury == 0) // x,y同时为0 { d[0] = *(image_label + y*nPitch + x+1); // 右 d[6] = *(image_label + (y+1)*nPitch + x); // 下 d[7] = *(image_label + (y+1)*nPitch + x+1); // 右下 if (d[6] == label || d[7] == label || d[0] == label) { if (d[6] == label) { *vec = 6; return true; } if (d[7] == label) { *vec = 7; return true; } if (d[0] == label) { *vec = 0; return true; } } else return false; } else { // x为0,而y不为0 d[0] = *(image_label + y*nPitch + x+1); // 右,缺少1方向 d[1] = *(image_label + (y-1)*nPitch + x+1); // 右上 d[2] = *(image_label + (y-1)*nPitch + x); // 上 d[6] = *(image_label + (y+1)*nPitch + x); // 下 d[7] = *(image_label + (y+1)*nPitch + x+1); // 右下 if (d[6] == label || d[7] == label || d[0] == label) { if (d[6] == label) { *vec = 6; return true; } if (d[7] == label) { *vec = 7; return true; } if (d[0] == label) { *vec = 0; return true; } if (d[1] == label) { *vec = 1; return true; } if (d[2] == label) { *vec = 2; return true; } } else return false; } } // x不为0,而y为0 if (cury == 0) { d[0] = *(image_label + y*nPitch + x+1); // 右 d[4] = *(image_label + y*nPitch + x-1); // 左 d[5] = *(image_label + (y+1)*nPitch + x-1); // 左下 d[6] = *(image_label + (y+1)*nPitch + x); // 下 d[7] = *(image_label + (y+1)*nPitch + x+1); // 右下 if (d[4] == label || d[5] == label || d[6] == label || d[7] == label || d[0] == label) { if (d[4] == label) { *vec = 4; return true; } if (d[5] == label) { *vec = 5; return true; } if (d[6] == label) { *vec = 6; return true; } if (d[7] == label) { *vec = 7; return true; } if (d[0] == label) { *vec = 0; return true; } } else return false; } } else { // 起始点非图像边界点 // 因是正常的点,其周围8个点都存在,取出其值进行研究 d[0] = *(image_label + y*nPitch + x+1); d[1] = *(image_label + (y-1)*nPitch + x+1); d[2] = *(image_label + (y-1)*nPitch + x); d[3] = *(image_label + (y-1)*nPitch + x-1); d[4] = *(image_label + y*nPitch + x-1); d[5] = *(image_label + (y+1)*nPitch + x-1); d[6] = *(image_label + (y+1)*nPitch + x); d[7] = *(image_label + (y+1)*nPitch + x+1); int total= 0; total = d[0] + d[1] + d[2] + d[3] + d[4] + d[5] + d[6] + d[7]; if (total == 0) { return false; } if (d[2] == label) { // 上 *vec = 2; return true; } if (d[3] == label) { // 左上 *vec = 3; return true; } if (d[4] == label) { // 左 *vec = 4; return true; } if (d[5] == label) { // 左下 *vec = 5; return true; } if (d[6] == label) { // 下 *vec = 6; return true; } if (d[7] == label) { // 右下 *vec = 7; return true; } if (d[0] == label) { // 右 *vec = 0; return true; } if (d[1] == label) { // 右上 *vec = 1; return true; } } } else { // 当前点非是起始点 // 开始追踪轮廓 if (curx == 0 || cury == 0) { if (curx == 0) { if (cury == 0) // x,y同时为0 { d[0] = *(image_label + y*nPitch + x+1); // 右 d[6] = *(image_label + (y+1)*nPitch + x); // 下 d[7] = *(image_label + (y+1)*nPitch + x+1); // 右下 if (d[6] == label || d[7] == label || d[0] == label) { if (d[6] == label) { *vec = 6; return true; } if (d[7] == label) { *vec = 7; return true; } if (d[0] == label) { *vec = 0; return true; } } else return false; } else { // x为0,而y不为0 d[0] = *(image_label + y*nPitch + x+1); // 右,缺少1方向 d[1] = *(image_label + (y-1)*nPitch + x+1); // 右上 d[2] = *(image_label + (y-1)*nPitch + x); // 上 d[6] = *(image_label + (y+1)*nPitch + x); // 下 d[7] = *(image_label + (y+1)*nPitch + x+1); // 右下 if (d[6] == label || d[7] == label || d[0] == label|| d[1] == label || d[2] == label) { if (d[2] == label) { *vec = 2; return true; } if (d[6] == label) { *vec = 6; return true; } if (d[7] == label) { *vec = 7; return true; } if (d[0] == label) { *vec = 0; return true; } if (d[1] == label) { *vec = 1; return true; } } else return false; } } // x不为0,而y为0 if (cury == 0) { d[0] = *(image_label + y*nPitch + x+1); // 右 d[4] = *(image_label + y*nPitch + x-1); // 左 d[5] = *(image_label + (y+1)*nPitch + x-1); // 左下 d[6] = *(image_label + (y+1)*nPitch + x); // 下 d[7] = *(image_label + (y+1)*nPitch + x+1); // 右下 if (d[4] == label || d[5] == label || d[6] == label || d[7] == label || d[0] == label) { if (d[4] == label) { *vec = 4; return true; } if (d[5] == label) { *vec = 5; return true; } if (d[6] == label) { *vec = 6; return true; } if (d[7] == label) { *vec = 7; return true; } if (d[0] == label) { *vec = 0; return true; } } else return false; } } // 因是正常的点,其周围8个点都存在,取出其值进行研究 d[0] = *(image_label + y*nPitch + x+1); d[1] = *(image_label + (y-1)*nPitch + x+1); d[2] = *(image_label + (y-1)*nPitch + x); d[3] = *(image_label + (y-1)*nPitch + x-1); d[4] = *(image_label + y*nPitch + x-1); d[5] = *(image_label + (y+1)*nPitch + x-1); d[6] = *(image_label + (y+1)*nPitch + x); d[7] = *(image_label + (y+1)*nPitch + x+1); int total= 0; total = d[0] + d[1] + d[2] + d[3] + d[4] + d[5] + d[6] + d[7]; if (total == 0) { return false; } if (d[2] == label) { // 上 *vec = 2; return true; } if (d[3] == label) { // 左上 *vec = 3; return true; } if (d[4] == label) { // 左 *vec = 4; return true; } if (d[5] == label) { // 左下 *vec = 5; return true; } if (d[6] == label) { // 下 *vec = 6; return true; } if (d[7] == label) { // 右下 *vec = 7; return true; } if (d[0] == label) { // 右 *vec = 0; return true; } if (d[1] == label) { // 右上 *vec = 1; return true; } // 特殊情况,即轮廓最后应回到原点的算法 if (curx == startx+1 && cury == starty) { *vec = 4; return true; } if (curx == startx+1 && cury == starty+1) { *vec = 3; return true; } // 上述条件均不满足,则返回false return false; } return false; } /* * trace -- 追踪轮廓线 * image_label: 标签图像数组 * xs, ys: 开始位置 */ float trace(unsigned char * image_label, int x_size, int y_size, int xs, int ys) { int x, y, no, vec; float l; int p[8]; /* 起始位置(x,y)、当前点位置(x,y)、下一点位置(x,y)、前一点位置(x,y) */ // 位图数据大小试验 int nPitch = ((x_size * 8 + 31) >> 5) << 2; l = 0; x = xs; y = ys; //no = *(image_label + y*nPitch + x+1); // 正关注的分界点 no = *(image_label + y*nPitch + x); // 正关注的分界点 //vec = 5; p[0] = xs; p[1] = ys; p[2] = xs; p[3] = ys; p[4] = xs; p[5] = ys; p[6] = xs; p[7] = ys; for(;;) { if (x == xs && y == ys && l != 0) return l; *(image_label + y*nPitch + x) = HIGH; p[6] = p[2]; // 更新前一点的位置 p[7] = p[3]; p[2] = p[4]; // 更新当前点的位置 p[3] = p[5]; if (nextpoint(image_label, x_size, y_size, no, p, &l, &vec)) { switch(vec) { case 0: p[4] = p[2]+1; // 右 p[5] = p[3]; l += 1; break; case 1: p[4] = p[2]+1; // 右上 p[5] = p[3]-1; l += ROOT2; break; case 2: p[4] = p[2]; p[5] = p[3]-1; l += 1; break; case 3: p[4] = p[2]-1; p[5] = p[3]-1; l += ROOT2; break; case 4: p[4] = p[2]-1; p[5] = p[3]; l += 1; break; case 5: p[4] = p[2]-1; p[5] = p[3]+1; l += ROOT2; break; case 6: p[4] = p[2]; // 下 p[5] = p[3]+1; l++; break; case 7: p[4] = p[2]+1; p[5] = p[3]+1; l += ROOT2; break; } x = p[4]; y = p[5]; if (x == p[6] && y == p[7]) // 前一点与当前点重合了 return l; continue; } else if (p[2] == p[6] && p[3] == p[7]) return l; /* switch(vec) { case 3: // 左上 if (y-1 < 0 || x+1 > x_size) continue; if (*(image_label + y*nPitch + x+1) != no && *(image_label + (y-1)*nPitch + x+1) == no) { x = x + 1; y = y; l++; vec = 0; continue; } case 4: // 左 if (y-1 < 0 || x+1 > x_size) continue; if (*(image_label + (y-1)*nPitch + x+1) != no && *(image_label + (y-1)*nPitch + x) == no) { x = x + 1; y = y - 1; l += ROOT2; vec = 1; continue; } case 5: // 左下 if (y-1 < 0 || x-1 < 0) { vec = 6; continue; } if (*(image_label + (y-1)*nPitch + x) != no && *(image_label + (y-1)*nPitch + x-1) == no) { x = x; y = y - 1; l++; vec = 2; continue; } case 6: // 下 if (y-1 < 0 || x-1 < 0 || x+1 > x_size) continue; if (*(image_label + (y-1)*nPitch + x+1) != no && *(image_label + y*nPitch + x-1) == no) { x = x - 1; y = y - 1; l += ROOT2; vec = 3; continue; } case 7: // 右下 if (x-1 < 0 || y+1 >= y_size) continue; if (*(image_label + y*nPitch + x-1) != no && *(image_label + (y+1)*nPitch + x-1) == no) { x = x - 1; y = y; l++; vec = 4; continue; } case 0: // 右 if (x-1 < 0 || y+1 >= y_size) continue; if (*(image_label + (y+1)*nPitch + x-1) != no && *(image_label + (y+1)*nPitch + x) == no) { x = x - 1; y = y + 1; l += ROOT2; vec = 5; continue; } case 1: // 右上 if (y+1 >= y_size || x+1 >= x_size) continue; if (*(image_label + (y+1)*nPitch + x) != no && *(image_label + (y+1)*nPitch + x+1) == no) { x = x; y = y + 1; l++; vec = 6; continue; } case 2: // 上 if (y+1 >= y_size || x+1 >= x_size) continue; if (*(image_label + (y+1)*nPitch + x+1) != no && *(image_label + y*nPitch + x+1) == no) { x = x + 1; y = y + 1; l += ROOT2; vec = 7; continue; } vec = 3; } */ } }
订阅后,新回复会通过你的通知中心匿名送达。
1 条回复
cryppie机器人#1 · 2008/9/1
我觉得这个问题,最好自己去想办法解决。 【 在 grepf 的大作中提到: 】 : 我自己写的纯c代码,貌似有问题,因下图的追踪结果显然不对,恳请大牛指点一下错误所在. : /* : * calc_length -- 求周长 : ...................