Вопрос

I'm doing some head tracking and I'm trying to estimate the roll angel by useing openCV to fit an ellipse to the head contour. That all works fine and the cvFitEllipse2 returns a CvBox2D. I would like to use the angle of the box to calculate the roll angle, i.e. the angle between the y axis of the image and the long axis of the ellipse.

They say that the box angle is the angle between the horizonal axis and the first side (i.e length), but the results that I get are somewhat strange.

  • The angel is 180° in case my head is upward.
  • When I tilt to the right the angle decreases to around 135° normally and then jumps suddenly to around 315°.
  • When I tilt to the left the angle rises to around 260° without any strange changes.

Here's short video of this: cvBox2D angle

Any idea what's going on and how I could calculate the roll angle?

And here is my code:

  CvBox2D box;
  CvPoint center;
  CvSize size;
  int count = largest_contour->total;

  CvMat* points_f = cvCreateMat( 1, count, CV_32FC2 );
  CvMat points_i = cvMat( 1, count, CV_32SC2, points_f->data.ptr );
  cvCvtSeqToArray(largest_contour, points_f->data.ptr, CV_WHOLE_SEQ );
  cvConvert( &points_i, points_f );

  box = cvFitEllipse2(points_f);
  center = cvPointFrom32f(box.center);
  size.width = cvRound(box.size.width*0.5);
  size.height = cvRound(box.size.height*0.5);

  cvEllipse(dst,center,size,box.angle,0,360,cvScalar(0,255,0),2,8,0); 

  float newAngle = (box.angle > 90 ? 180 - box.angle : -1*(box.angle));
Это было полезно?

Решение

So, I have found the answer to my problem.

If you look at the source code for the cvFitEllipse2 function that you can find in ...\modules\imgproc\src file: "shapedescr.cpp", you will see that there are two different algorithms for doing ellipse fitting. By default only one is used in the openCV231 version I'm using.

icvFitEllipse_F is the function that caused my problem, but there is also a part of the algorithm that is not used because the following statement is in the code of the cvFitEllipse2 function:

#if 1
    icvFitEllipse_F( ptseq, &box );
#else
/*
 *  New fitellipse algorithm, contributed by Dr. Daniel Weiss
 */

so the new fitellipse algorithm is not compiled.

By changing #if 1 to #if 0 the other algorithm is compiled and used instead of icvFitEllipse_F and everything works fine now.

Другие советы

I have been using CAMShift tracking on several head tracking applications with the calculation below, after simply modifying the CAMShift demo from OpenCV:

float newAngle = (trackBox.angle > 90 ? 180 - trackBox.angle : -1*(trackBox.angle));

If this does not work, please post your code for extracting the roll angle so that we can have a look at the numbers.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top