从轮廓中取得四肢与头部的算法
实现了取得四肢与头部的算法,即取得五个U形的端点.
算法如下:
int SegmentBody(CvSeq* contour)
{
float StandBodyLength = 10.0;
float StandArc = 40;
float lk,l1,l2=0;
CvPoint pt1,pt2,pt0;
double total_arc = 0; //内旋角度
double rarc12= 0;
double arc12= 0;
bool Haslkvec = false; //是否存在先前记录的矢量
CvSeqReader reader;
CvSeqReader subReader;
int N = contour->total;
int i;
CvPoint pt;
CvPoint pre_pt;
CvPoint pre_pre_pt;
//CvFont font;
//cvInitFont( &font, CV_FONT_HERSHEY_SIMPLEX, 0.3, 0.3, 0.0, 1, CV_AA );
cvStartReadSeq(contour, &reader);
for (i= 0; i < N; i++)
{
CV_READ_SEQ_ELEM(pt, reader);
//printf("%d,%d \n",pt.x,pt.y);
pre_pt = pre_pre_pt = pt;
//draw_cross( pt, CV_RGB(255,255,255), 3 );
if(i==9)
draw_cross( pt, CV_RGB(240,222,240), 3 );
//cvLine( dst, pt,pre_pt,CV_RGB(0,255,0),2,CV_AA, 0 );
//计算两点之间的距离
subReader = reader ;
Haslkvec = false;
total_arc =0;
//printf("------------------ \n");
//printf("%d,%d \n",pt.x,pt.y);
for(int j=0;j<5;j++)
{
//printf("in sub %d,%d \n",pt.x,pt.y);
l1=calc_2Point_Magnitude(pt,pre_pt);
if (l1>StandBodyLength)
{
//是否存在先前记录的点,如果有,检查角度范围
if(Haslkvec)
{
Vector3f vt1 = Vector3f (pre_pre_pt.x-pre_pt.x,pre_pre_pt.y-pre_pt.y,0);
Vector3f vt2 = Vector3f (pre_pt.x-pt.x,pre_pt.y-pt.y,0);
arc12 = AngleBetweenVectors(vt1,vt2);
rarc12 = 180*arc12/pi;
Vector3f vtnor=Cross(vt1,vt2); //使用叉集检查矢量是内旋还是外旋。
if(vtnor.z >0) total_arc += rarc12;
else total_arc -= rarc12;
//检查角度范围合理 -200 -160
if (abs(total_arc+180)<StandArc)
{
//检查平行线之间构成四边形是否在同一轴线上,相似度判断
if(Is_Closed_Vectors(pt,pre_pt,pt1,pt2))
{
//匹配成功,完成一个搜索
//记录两个矢量,清空标记
Haslkvec = false;
total_arc = 0;
//绘出位置
draw_2Points(pt,pre_pt,pt1,pt2);
//跳过已经成形的点,好处是减少计算,二是避免歧异点
for(int k=0;k<j;k++)
{
CV_READ_SEQ_ELEM(pt, reader);
pre_pt = pre_pre_pt = pt;
}
}
//cvShowImage( "Components", dst );
//cvWaitKey(0);
break;
}
}
else
{
//记录两个点
pt1=pt;
pt2=pre_pt;
Haslkvec = true;
}
}
//对于短线段忽略,并且跳过其检测点,将加快检测速度。
else
{
pt = pre_pt;
pre_pt = pre_pre_pt;
}
pre_pre_pt = pre_pt;
pre_pt= pt;
CV_READ_SEQ_ELEM(pt, subReader);
}
}
return 0;
}