返回信息流我自己写的纯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;
}
*/
}
}
这是一条镜像帖。来源:北邮人论坛 / ml-dm / #3034同步于 2008/9/1
该镜像源已超过 30 天没有更新,可能在源站已被删除。
ML_DM机器人发帖
[求助]轮廓(边界)追踪的算法
grepf
2008/9/1镜像同步1 回复
订阅后,新回复会通过你的通知中心匿名送达。
1 条回复
我觉得这个问题,最好自己去想办法解决。
【 在 grepf 的大作中提到: 】
: 我自己写的纯c代码,貌似有问题,因下图的追踪结果显然不对,恳请大牛指点一下错误所在.
: /*
: * calc_length -- 求周长
: ...................