图像八领域c语言,八领域边界追踪算法

void edgeTracing( const unsigned char* _Binary, contour** _TracingPtr, const int _Width, const int _Height )

{

unsigned char* _Mark = NULL;//标记矩阵

int direction[8][2] = { 0,-1, -1,-1, -1,0, -1,1, 0,1, 1,1, 1,0, 1,-1 };//方向数组

int i = 0, j = 0;//行、列计数

int start_I = 0, start_J = 0;//轮廓的起始点

int rec_I = 0, rec_J = 0;//待检测轮廓点坐标

int mov_I = 0, mov_J = 0;//待检测轮廓点周围8领域逆时针旋转点

int tmp_I = 0, tmp_J = 0;//临时点保存

int point_Count = 0;//轮廓点计数

int direc_Count = 0;//方向转次数计数

int rot_Direct = 0;//方向数组计数

int stepWidth = (_Width + 3) & ~3;//灰度图行步长

int contour_Succe_Flag = 0;//轮廓寻找成功标志位

int contour_Point_Now = 0;//现已开辟轮廓空间点数量

int contour_Point_Add = 0;//需要增加的轮廓空间点数量

contour* ptr_Contour_First = NULL;//轮廓点数组首地址

contour_Point_Now = 4 * (_Width+_Height);

contour_Point_Add = _Width + _Height;

*_TracingPtr = ( contour *)malloc( contour_Point_Now * sizeof( contour) );//为储存轮廓点创建内存块

ptr_Contour_First = *_TracingPtr;

_Mark = ( unsigned char*)malloc( stepWidth*_Height );//轮廓标记矩阵

memset(_Mark, 0, stepWidth*_Height);//轮廓标记矩阵清零

for ( i = 0; i < _Height; i ++ )

{

for ( j = 1; j < _Width; j ++ )

{

if ( 255 == _Binary[ i*stepWidth + j - 1] && 0 == _Binary[ i*stepWidth + j] && 0 == _Mark[i*stepWidth + j] )

{

direc_Count = 0;//方向计数置零

rot_Direct = 0;//旋转方向计数置零

start_I = i;//保存每个轮廓的起始点

start_J = j;

rec_I = i;//存储第一个b点的行坐标

rec_J = j;//存储第一个b点的列坐标

mov_I = i;//存储第一个c点的行坐标

mov_J = j-1;//存储第一个c点的列坐标

while ( direc_Count < 8 && mov_I > 0 && mov_I < _Height && mov_J > 0 && mov_J < _Width )

{

direc_Count ++;

rot_Direct ++;//顺时针方向转45°

if ( 8 == rot_Direct) rot_Direct = 0;//使方向循环且不溢出

mov_I = rec_I + direction[rot_Direct][0];//转完之后c点的行坐标

mov_J = rec_J + direction[rot_Direct][1];//转完之后c点的列坐标

if ( 0 == _Binary[ mov_I*stepWidth + mov_J]

&& mov_I > 0 && mov_I < _Height

&& mov_J > 0 && mov_J < _Width

&& ( start_I != mov_I || start_J != mov_J ) )

{

if ( 0 == rot_Direct ) rot_Direct = 7;//方向回到上一个角度

else rot_Direct --;

tmp_I = rec_I;//记录变换前b点行坐标

tmp_J = rec_J;//记录变换前b点列坐标

rec_I = mov_I;//新的c点坐标赋值给b点

rec_J = mov_J;

mov_I = tmp_I + direction[rot_Direct][0];//将上一个c点坐标赋值给新c点坐标

mov_J = tmp_J + direction[rot_Direct][1];

direc_Count = 0;//方向次数计数清零

if ( rec_I > mov_I )//计算现在c点相对b点的方位

rot_Direct = 2;

else if ( rec_I < mov_I )

rot_Direct = 6;

else if ( rec_J > mov_J )

rot_Direct = 0;

else if ( rec_J < mov_J )

rot_Direct = 4;

}

else if ( start_I == mov_I && start_J == mov_J )

{

//如果等于起始点,则重新遍历该轮廓,标记轮廓并储存轮廓点

if ( point_Count > contour_Point_Now-1 )

{

//若轮廓空间点超出范围,则加入额外轮廓空间点

ptr_Contour_First = ( contour *)malloc( contour_Point_Now * sizeof( contour) );

memcpy( ptr_Contour_First, *_TracingPtr, contour_Point_Now * sizeof( contour) );

*_TracingPtr = ( contour *)malloc( (contour_Point_Now + contour_Point_Add) * sizeof( contour) );

memcpy( *_TracingPtr, ptr_Contour_First, contour_Point_Now * sizeof( contour) );

contour_Point_Now += contour_Point_Add;

free( ptr_Contour_First);

ptr_Contour_First = NULL;

ptr_Contour_First = *_TracingPtr;

}

ptr_Contour_First[ point_Count].height = start_I;//储存起始点

ptr_Contour_First[ point_Count].width = start_J;

ptr_Contour_First[ point_Count].stateFlag = 1;//状态标志位stateFlag:

//1为起始点,0为普通边缘点,2为结束点

_Mark[ start_I*stepWidth + start_J] = 255;//标记为已搜索过的点

direc_Count = 0;//方向计数置零

rot_Direct = 0;//旋转方向计数置零

rec_I = start_I;//存储b点的行坐标

rec_J = start_J;//存储b点的列坐标

mov_I = start_I;//存储 c点的行坐标

mov_J = start_J-1;//存储c点的列坐标

while ( direc_Count < 8 && mov_I > 0 && mov_I < _Height && mov_J > 0 && mov_J < _Width )

{

direc_Count ++;

rot_Direct ++;//顺时针方向转45°

if ( 8 == rot_Direct) rot_Direct = 0;//使方向循环且不溢出

mov_I = rec_I + direction[rot_Direct][0];//转完之后c点的行坐标

mov_J = rec_J + direction[rot_Direct][1];//转完之后c点的列坐标

if ( 0 == _Binary[ mov_I*stepWidth + mov_J]

&& mov_I > 0 && mov_I < _Height

&& mov_J > 0 && mov_J < _Width

&& ( start_I != mov_I || start_J != mov_J ) )

{

if ( 0 == rot_Direct ) rot_Direct = 7;//方向回到上一个角度

else rot_Direct --;

tmp_I = rec_I;//记录变换前b点行坐标

tmp_J = rec_J;//记录变换前b点列坐标

rec_I = mov_I;//新的c点坐标赋值给b点

rec_J = mov_J;

mov_I = tmp_I + direction[rot_Direct][0];//将上一个c点坐标赋值给新c点坐标

mov_J = tmp_J + direction[rot_Direct][1];

direc_Count = 0;//方向次数计数清零

if ( rec_I > mov_I )//计算现在c点相对b点的方位

rot_Direct = 2;

else if ( rec_I < mov_I )

rot_Direct = 6;

else if ( rec_J > mov_J )

rot_Direct = 0;

else if ( rec_J < mov_J )

rot_Direct = 4;

point_Count ++;//压入新点之前,轮廓计数自加

if ( point_Count > contour_Point_Now-1 )

{

//若轮廓空间点超出范围,则加入额外轮廓空间点

ptr_Contour_First = ( contour *)malloc( contour_Point_Now * sizeof( contour) );

memcpy( ptr_Contour_First, *_TracingPtr, contour_Point_Now * sizeof( contour) );

*_TracingPtr = ( contour *)malloc( (contour_Point_Now + contour_Point_Add) * sizeof( contour) );

memcpy( *_TracingPtr, ptr_Contour_First, contour_Point_Now * sizeof( contour) );

contour_Point_Now += contour_Point_Add;

free( ptr_Contour_First);

ptr_Contour_First = NULL;

ptr_Contour_First = *_TracingPtr;

}

ptr_Contour_First[ point_Count].height = rec_I;//储存新轮廓点

ptr_Contour_First[ point_Count].width = rec_J;

ptr_Contour_First[ point_Count].stateFlag = 0;//状态标志位stateFlag:

//1为起始点,0为普通边缘点,2为结束点

_Mark[ rec_I*stepWidth + rec_J] = 255;//标记为已搜索过的点

}

else if ( start_I == mov_I && start_J == mov_J )

{

//如果等于起始点,则把之前最后一个点改为终点,跳出开始新的搜索

ptr_Contour_First[ point_Count].stateFlag = 2;//状态标志位stateFlag:

//1为起始点,0为普通边缘点,2为结束点

contour_Succe_Flag = 1;//轮廓完整,标志位置一

point_Count ++;//为下一个轮廓开辟一个新点

break;

}

}

}

if ( contour_Succe_Flag )//如果一个轮廓搜索并储存成功,则开始找新的起始点

{

contour_Succe_Flag = 0;//轮廓搜索成功标志位置零

break;

}

}

}

}

}

ptr_Contour_First[0].stateFlag = point_Count;//将轮廓点数量保存在第一个空间点的状态位

}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值