从轮廓中取得四肢与头部的算法

来源:互联网 发布:热力学第二定律知乎 编辑:程序博客网 时间:2024/04/29 16:09

从轮廓中取得四肢与头部的算法

实现了取得四肢与头部的算法,即取得五个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;
}