Ok.. Here is what I came up with:
First I'll explain the opencv specific variables:
CvSeq = A struct containing my contour, from which i can extract CvPoint objects
CvPoint = A struct containing int x and int y
Prototype of function for extracting CvPoints from CvSeq:
CVAPI(schar*) cvGetSeqElem( const CvSeq* seq, int index );
Here is my function:
Code:
CvPoint *findCorners( CvSeq *contour, int max_corners, int min_angle, int min_distance )
{
CvPoint *ret = malloc( sizeof( CvPoint ) * max_corners );
CvPoint *p1, *p2, *p3;
double prevAngle = 0;
double distance = 0;
int cc = 0;
for( int i = 0; i < (contour->total + 3); i++ )
{
if( i > 2 )
{
if( i - contour->total < 0 ) //Handle the overlapping steps of the loop
{
p1 = (CvPoint *)cvGetSeqElem( contour, i - 2 );
p2 = (CvPoint *)cvGetSeqElem( contour, i - 1 );
p3 = (CvPoint *)cvGetSeqElem( contour, i );
}
else if( i - contour->total == 0 )
{
p1 = (CvPoint *)cvGetSeqElem( contour, i - 2 );
p2 = (CvPoint *)cvGetSeqElem( contour, i - 1 );
p3 = (CvPoint *)cvGetSeqElem( contour, 0 );
}
else if( i - contour->total == 1 )
{
p1 = (CvPoint *)cvGetSeqElem( contour, i - 2 );
p2 = (CvPoint *)cvGetSeqElem( contour, 0 );
p3 = (CvPoint *)cvGetSeqElem( contour, 1 );
}
else
{
p1 = (CvPoint *)cvGetSeqElem( contour, i - contour->total - 2 );
p2 = (CvPoint *)cvGetSeqElem( contour, i - contour->total - 1 );
p3 = (CvPoint *)cvGetSeqElem( contour, i - contour->total );
}
//Calculate angle between points 1 and 3
double currAngle = atan2( p1->y - p3->y, p1->x - p3->x ) * 180 / PI;
if( currAngle < 0 )
currAngle = (currAngle * -1);
if( i > 3 )
{
//calculate the difference between this angle and the previous one
double diffAngle = prevAngle - currAngle;
if( diffAngle < 0 ) //Make sure sign is positive
diffAngle = (diffAngle * -1);
//Add point to return array if angle diff is above threshold
if( diffAngle > min_angle )
{
//Ignore points that are closer than "min_distance pixels" to the previous point
if( cc > 0 )
{
double dx;
if(p1->x > ret[cc - 1].x)
dx = (double)(p1->x - ret[cc - 1].x);
else
dx = (double)(ret[cc - 1].x - p1->x);
double dy;
if(p1->y > ret[cc - 1].y)
dy = p1->y - ret[cc - 1].y;
else
dy = ret[cc - 1].y - p1->y;
distance = sqrtf( (dx * dx) + (dy * dy) );
if( distance >= min_distance )
{
ret[cc] = *p1;
cc++;
}
}
else
{
ret[cc] = *p1;
cc++;
}
if( cc > max_corners )
break;
}
}
prevAngle = currAngle;
}
}
if( cc < max_corners )
fprintf( stderr, "Find corners: found %d of %d corners\n", cc, max_corners );
return ret;
}
I would appreciate any feedback on this function. Not only on its functionality, but also general mistakes or bad behaviors in my coding.
Thanks
//John