converted few more comp. geometry functions to C++

This commit is contained in:
Vadim Pisarevsky 2013-01-22 16:54:31 +04:00
parent c2241dccc5
commit dc4d0398f3
7 changed files with 1381 additions and 1692 deletions

@ -52,16 +52,6 @@ CV_INLINE float icvDistanceL2_32f( CvPoint2D32f pt1, CvPoint2D32f pt2 )
} }
int icvIntersectLines( double x1, double dx1, double y1, double dy1,
double x2, double dx2, double y2, double dy2,
double* t2 );
void icvIntersectLines3( double* a0, double* b0, double* c0,
double* a1, double* b1, double* c1,
CvPoint2D32f* point );
/* curvature: 0 - 1-curvature, 1 - k-cosine curvature. */ /* curvature: 0 - 1-curvature, 1 - k-cosine curvature. */
CvSeq* icvApproximateChainTC89( CvChain* chain, int header_size, CvMemStorage* storage, int method ); CvSeq* icvApproximateChainTC89( CvChain* chain, int header_size, CvMemStorage* storage, int method );

@ -1753,85 +1753,4 @@ void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours,
findContours(_image, _contours, noArray(), mode, method, offset); findContours(_image, _contours, noArray(), mode, method, offset);
} }
double cv::arcLength( InputArray _curve, bool closed )
{
Mat curve = _curve.getMat();
CV_Assert(curve.checkVector(2) >= 0 && (curve.depth() == CV_32F || curve.depth() == CV_32S));
CvMat _ccurve = curve;
return cvArcLength(&_ccurve, CV_WHOLE_SEQ, closed);
}
cv::Rect cv::boundingRect( InputArray _points )
{
Mat points = _points.getMat();
CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S));
CvMat _cpoints = points;
return cvBoundingRect(&_cpoints, 0);
}
double cv::contourArea( InputArray _contour, bool oriented )
{
Mat contour = _contour.getMat();
CV_Assert(contour.checkVector(2) >= 0 && (contour.depth() == CV_32F || contour.depth() == CV_32S));
CvMat _ccontour = contour;
return cvContourArea(&_ccontour, CV_WHOLE_SEQ, oriented);
}
cv::RotatedRect cv::minAreaRect( InputArray _points )
{
Mat points = _points.getMat();
CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S));
CvMat _cpoints = points;
return cvMinAreaRect2(&_cpoints, 0);
}
void cv::minEnclosingCircle( InputArray _points,
Point2f& center, float& radius )
{
Mat points = _points.getMat();
CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S));
CvMat _cpoints = points;
cvMinEnclosingCircle( &_cpoints, (CvPoint2D32f*)&center, &radius );
}
double cv::matchShapes( InputArray _contour1,
InputArray _contour2,
int method, double parameter )
{
Mat contour1 = _contour1.getMat(), contour2 = _contour2.getMat();
CV_Assert(contour1.checkVector(2) >= 0 && contour2.checkVector(2) >= 0 &&
(contour1.depth() == CV_32F || contour1.depth() == CV_32S) &&
contour1.depth() == contour2.depth());
CvMat c1 = Mat(contour1), c2 = Mat(contour2);
return cvMatchShapes(&c1, &c2, method, parameter);
}
cv::RotatedRect cv::fitEllipse( InputArray _points )
{
Mat points = _points.getMat();
CV_Assert(points.checkVector(2) >= 0 &&
(points.depth() == CV_32F || points.depth() == CV_32S));
CvMat _cpoints = points;
return cvFitEllipse2(&_cpoints);
}
double cv::pointPolygonTest( InputArray _contour,
Point2f pt, bool measureDist )
{
Mat contour = _contour.getMat();
CV_Assert(contour.checkVector(2) >= 0 &&
(contour.depth() == CV_32F || contour.depth() == CV_32S));
CvMat c = Mat(contour);
return cvPointPolygonTest( &c, pt, measureDist );
}
/* End of file. */ /* End of file. */

@ -92,93 +92,34 @@ cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] )
} }
int double cv::pointPolygonTest( InputArray _contour, Point2f pt, bool measureDist )
icvIntersectLines( double x1, double dx1, double y1, double dy1,
double x2, double dx2, double y2, double dy2, double *t2 )
{
double d = dx1 * dy2 - dx2 * dy1;
int result = -1;
if( d != 0 )
{
*t2 = ((x2 - x1) * dy1 - (y2 - y1) * dx1) / d;
result = 0;
}
return result;
}
void
icvIntersectLines3( double *a0, double *b0, double *c0,
double *a1, double *b1, double *c1, CvPoint2D32f * point )
{
double det = a0[0] * b1[0] - a1[0] * b0[0];
if( det != 0 )
{
det = 1. / det;
point->x = (float) ((b0[0] * c1[0] - b1[0] * c0[0]) * det);
point->y = (float) ((a1[0] * c0[0] - a0[0] * c1[0]) * det);
}
else
{
point->x = point->y = FLT_MAX;
}
}
CV_IMPL double
cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
{ {
double result = 0; double result = 0;
Mat contour = _contour.getMat();
int i, total = contour.checkVector(2), counter = 0;
int depth = contour.depth();
CV_Assert( total >= 0 && (depth == CV_32S || depth == CV_32F));
CvSeqBlock block; bool is_float = depth == CV_32F;
CvContour header;
CvSeq* contour = (CvSeq*)_contour;
CvSeqReader reader;
int i, total, counter = 0;
int is_float;
double min_dist_num = FLT_MAX, min_dist_denom = 1; double min_dist_num = FLT_MAX, min_dist_denom = 1;
CvPoint ip = {0,0}; Point ip(cvRound(pt.x), cvRound(pt.y));
if( !CV_IS_SEQ(contour) ) if( total == 0 )
{ return measureDist ? -DBL_MAX : -1;
contour = cvPointSeqFromMat( CV_SEQ_KIND_CURVE + CV_SEQ_FLAG_CLOSED,
_contour, &header, &block );
}
else if( CV_IS_SEQ_POINT_SET(contour) )
{
if( contour->header_size == sizeof(CvContour) && !measure_dist )
{
CvRect r = ((CvContour*)contour)->rect;
if( pt.x < r.x || pt.y < r.y ||
pt.x >= r.x + r.width || pt.y >= r.y + r.height )
return -1;
}
}
else if( CV_IS_SEQ_CHAIN(contour) )
{
CV_Error( CV_StsBadArg,
"Chains are not supported. Convert them to polygonal representation using cvApproxChains()" );
}
else
CV_Error( CV_StsBadArg, "Input contour is neither a valid sequence nor a matrix" );
total = contour->total; const Point* cnt = (const Point*)contour.data;
is_float = CV_SEQ_ELTYPE(contour) == CV_32FC2; const Point2f* cntf = (const Point2f*)cnt;
cvStartReadSeq( contour, &reader, -1 );
if( !is_float && !measure_dist && (ip.x = cvRound(pt.x)) == pt.x && (ip.y = cvRound(pt.y)) == pt.y ) if( !is_float && !measureDist && ip.x == pt.x && ip.y == pt.y )
{ {
// the fastest "pure integer" branch // the fastest "purely integer" branch
CvPoint v0, v; Point v0, v = cnt[total-1];
CV_READ_SEQ_ELEM( v, reader );
for( i = 0; i < total; i++ ) for( i = 0; i < total; i++ )
{ {
int dist; int dist;
v0 = v; v0 = v;
CV_READ_SEQ_ELEM( v, reader ); v = cnt[i];
if( (v0.y <= ip.y && v.y <= ip.y) || if( (v0.y <= ip.y && v.y <= ip.y) ||
(v0.y > ip.y && v.y > ip.y) || (v0.y > ip.y && v.y > ip.y) ||
@ -202,34 +143,28 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
} }
else else
{ {
CvPoint2D32f v0, v; Point2f v0, v;
CvPoint iv; Point iv;
if( is_float ) if( is_float )
{ {
CV_READ_SEQ_ELEM( v, reader ); v = cntf[total-1];
} }
else else
{ {
CV_READ_SEQ_ELEM( iv, reader ); v = cnt[total-1];
v = cvPointTo32f( iv );
} }
if( !measure_dist ) if( !measureDist )
{ {
for( i = 0; i < total; i++ ) for( i = 0; i < total; i++ )
{ {
double dist; double dist;
v0 = v; v0 = v;
if( is_float ) if( is_float )
{ v = cntf[i];
CV_READ_SEQ_ELEM( v, reader );
}
else else
{ v = cnt[i];
CV_READ_SEQ_ELEM( iv, reader );
v = cvPointTo32f( iv );
}
if( (v0.y <= pt.y && v.y <= pt.y) || if( (v0.y <= pt.y && v.y <= pt.y) ||
(v0.y > pt.y && v.y > pt.y) || (v0.y > pt.y && v.y > pt.y) ||
@ -259,14 +194,9 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
v0 = v; v0 = v;
if( is_float ) if( is_float )
{ v = cntf[i];
CV_READ_SEQ_ELEM( v, reader );
}
else else
{ v = cnt[i];
CV_READ_SEQ_ELEM( iv, reader );
v = cvPointTo32f( iv );
}
dx = v.x - v0.x; dy = v.y - v0.y; dx = v.x - v0.x; dy = v.y - v0.y;
dx1 = pt.x - v0.x; dy1 = pt.y - v0.y; dx1 = pt.x - v0.x; dy1 = pt.y - v0.y;
@ -312,6 +242,14 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
} }
CV_IMPL double
cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
{
cv::AutoBuffer<double> abuf;
cv::Mat contour = cv::cvarrToMat(_contour, false, false, 0, &abuf);
return cv::pointPolygonTest(contour, pt, measure_dist != 0);
}
/* /*
This code is described in "Computational Geometry in C" (Second Edition), This code is described in "Computational Geometry in C" (Second Edition),
Chapter 7. It is not written to be comprehensible without the Chapter 7. It is not written to be comprehensible without the

@ -40,64 +40,21 @@
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvMatchContours double cv::matchShapes(InputArray contour1, InputArray contour2, int method, double)
// Purpose:
// Calculates matching of the two contours
// Context:
// Parameters:
// contour_1 - pointer to the first input contour object.
// contour_2 - pointer to the second input contour object.
// method - method for the matching calculation
// (now CV_IPPI_CONTOURS_MATCH_I1, CV_CONTOURS_MATCH_I2 or
// CV_CONTOURS_MATCH_I3 only )
// rezult - output calculated measure
//
//F*/
CV_IMPL double
cvMatchShapes( const void* contour1, const void* contour2,
int method, double /*parameter*/ )
{ {
CvMoments moments;
CvHuMoments huMoments;
double ma[7], mb[7]; double ma[7], mb[7];
int i, sma, smb; int i, sma, smb;
double eps = 1.e-5; double eps = 1.e-5;
double mmm; double mmm;
double result = 0; double result = 0;
if( !contour1 || !contour2 ) HuMoments( moments(contour1), ma );
CV_Error( CV_StsNullPtr, "" ); HuMoments( moments(contour2), mb );
// calculate moments of the first shape
cvMoments( contour1, &moments );
cvGetHuMoments( &moments, &huMoments );
ma[0] = huMoments.hu1;
ma[1] = huMoments.hu2;
ma[2] = huMoments.hu3;
ma[3] = huMoments.hu4;
ma[4] = huMoments.hu5;
ma[5] = huMoments.hu6;
ma[6] = huMoments.hu7;
// calculate moments of the second shape
cvMoments( contour2, &moments );
cvGetHuMoments( &moments, &huMoments );
mb[0] = huMoments.hu1;
mb[1] = huMoments.hu2;
mb[2] = huMoments.hu3;
mb[3] = huMoments.hu4;
mb[4] = huMoments.hu5;
mb[5] = huMoments.hu6;
mb[6] = huMoments.hu7;
switch (method) switch (method)
{ {
case 1: case 1:
{
for( i = 0; i < 7; i++ ) for( i = 0; i < 7; i++ )
{ {
double ama = fabs( ma[i] ); double ama = fabs( ma[i] );
@ -124,10 +81,8 @@ cvMatchShapes( const void* contour1, const void* contour2,
} }
} }
break; break;
}
case 2: case 2:
{
for( i = 0; i < 7; i++ ) for( i = 0; i < 7; i++ )
{ {
double ama = fabs( ma[i] ); double ama = fabs( ma[i] );
@ -154,10 +109,8 @@ cvMatchShapes( const void* contour1, const void* contour2,
} }
} }
break; break;
}
case 3: case 3:
{
for( i = 0; i < 7; i++ ) for( i = 0; i < 7; i++ )
{ {
double ama = fabs( ma[i] ); double ama = fabs( ma[i] );
@ -186,7 +139,6 @@ cvMatchShapes( const void* contour1, const void* contour2,
} }
} }
break; break;
}
default: default:
CV_Error( CV_StsBadArg, "Unknown comparison method" ); CV_Error( CV_StsBadArg, "Unknown comparison method" );
} }
@ -195,4 +147,15 @@ cvMatchShapes( const void* contour1, const void* contour2,
} }
CV_IMPL double
cvMatchShapes( const void* _contour1, const void* _contour2,
int method, double parameter )
{
cv::AutoBuffer<double> abuf1, abuf2;
cv::Mat contour1 = cv::cvarrToMat(_contour1, false, false, 0, &abuf1);
cv::Mat contour2 = cv::cvarrToMat(_contour2, false, false, 0, &abuf2);
return cv::matchShapes(contour1, contour2, method, parameter);
}
/* End of file. */ /* End of file. */

@ -1,103 +1,103 @@
/*M/////////////////////////////////////////////////////////////////////////////////////// /*M///////////////////////////////////////////////////////////////////////////////////////
// //
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
// //
// By downloading, copying, installing or using the software you agree to this license. // By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install, // If you do not agree to this license, do not download, install,
// copy or use the software. // copy or use the software.
// //
// //
// Intel License Agreement // License Agreement
// For Open Source Computer Vision Library // For Open Source Computer Vision Library
// //
// Copyright (C) 2000, Intel Corporation, all rights reserved. // Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners. // Third party copyrights are property of their respective owners.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// * Redistribution's of source code must retain the above copyright notice, // * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// * Redistribution's in binary form must reproduce the above copyright notice, // * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation // this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. // and/or other materials provided with the distribution.
// //
// * The name of Intel Corporation may not be used to endorse or promote products // * The name of OpenCV Foundation may not be used to endorse or promote products
// derived from this software without specific prior written permission. // derived from this software without specific prior written permission.
// //
// This software is provided by the copyright holders and contributors "as is" and // This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied // any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed. // warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct, // In no event shall the OpenCV Foundation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages // indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services; // (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused // loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability, // and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of // or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage. // the use of this software, even if advised of the possibility of such damage.
// //
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
typedef struct namespace cv
{ {
struct MinAreaState
{
int bottom; int bottom;
int left; int left;
float height; float height;
float width; float width;
float base_a; float base_a;
float base_b; float base_b;
} };
icvMinAreaState;
#define CV_CALIPERS_MAXHEIGHT 0 enum { CALIPERS_MAXHEIGHT=0, CALIPERS_MINAREARECT=1, CALIPERS_MAXDIST=2 };
#define CV_CALIPERS_MINAREARECT 1
#define CV_CALIPERS_MAXDIST 2
/*F/////////////////////////////////////////////////////////////////////////////////////// /*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvRotatingCalipers // Name: rotatingCalipers
// Purpose: // Purpose:
// Rotating calipers algorithm with some applications // Rotating calipers algorithm with some applications
// //
// Context: // Context:
// Parameters: // Parameters:
// points - convex hull vertices ( any orientation ) // points - convex hull vertices ( any orientation )
// n - number of vertices // n - number of vertices
// mode - concrete application of algorithm // mode - concrete application of algorithm
// can be CV_CALIPERS_MAXDIST or // can be CV_CALIPERS_MAXDIST or
// CV_CALIPERS_MINAREARECT // CV_CALIPERS_MINAREARECT
// left, bottom, right, top - indexes of extremal points // left, bottom, right, top - indexes of extremal points
// out - output info. // out - output info.
// In case CV_CALIPERS_MAXDIST it points to float value - // In case CV_CALIPERS_MAXDIST it points to float value -
// maximal height of polygon. // maximal height of polygon.
// In case CV_CALIPERS_MINAREARECT // In case CV_CALIPERS_MINAREARECT
// ((CvPoint2D32f*)out)[0] - corner // ((CvPoint2D32f*)out)[0] - corner
// ((CvPoint2D32f*)out)[1] - vector1 // ((CvPoint2D32f*)out)[1] - vector1
// ((CvPoint2D32f*)out)[0] - corner2 // ((CvPoint2D32f*)out)[0] - corner2
// //
// ^ // ^
// | // |
// vector2 | // vector2 |
// | // |
// |____________\ // |____________\
// corner / // corner /
// vector1 // vector1
// //
// Returns: // Returns:
// Notes: // Notes:
//F*/ //F*/
/* we will use usual cartesian coordinates */ /* we will use usual cartesian coordinates */
static void static void rotatingCalipers( const Point2f* points, int n, int mode, float* out )
icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out ) {
{
float minarea = FLT_MAX; float minarea = FLT_MAX;
float max_dist = 0; float max_dist = 0;
char buffer[32] = {}; char buffer[32] = {};
int i, k; int i, k;
CvPoint2D32f* vect = (CvPoint2D32f*)cvAlloc( n * sizeof(vect[0]) ); AutoBuffer<float> buf(n*3);
float* inv_vect_length = (float*)cvAlloc( n * sizeof(inv_vect_length[0]) ); float* inv_vect_length = buf;
Point2f* vect = (Point2f*)(inv_vect_length + n);
int left = 0, bottom = 0, right = 0, top = 0; int left = 0, bottom = 0, right = 0, top = 0;
int seq[4] = { -1, -1, -1, -1 }; int seq[4] = { -1, -1, -1, -1 };
@ -110,7 +110,7 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
float base_b = 0; float base_b = 0;
float left_x, right_x, top_y, bottom_y; float left_x, right_x, top_y, bottom_y;
CvPoint2D32f pt0 = points[0]; Point2f pt0 = points[0];
left_x = right_x = pt0.x; left_x = right_x = pt0.x;
top_y = bottom_y = pt0.y; top_y = bottom_y = pt0.y;
@ -131,7 +131,7 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
if( pt0.y < bottom_y ) if( pt0.y < bottom_y )
bottom_y = pt0.y, bottom = i; bottom_y = pt0.y, bottom = i;
CvPoint2D32f pt = points[(i+1) & (i+1 < n ? -1 : 0)]; Point2f pt = points[(i+1) & (i+1 < n ? -1 : 0)];
dx = pt.x - pt0.x; dx = pt.x - pt0.x;
dy = pt.y - pt0.y; dy = pt.y - pt0.y;
@ -143,9 +143,7 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
pt0 = pt; pt0 = pt;
} }
//cvbInvSqrt( inv_vect_length, inv_vect_length, n ); // find convex hull orientation
/* find convex hull orientation */
{ {
double ax = vect[n-1].x; double ax = vect[n-1].x;
double ay = vect[n-1].y; double ay = vect[n-1].y;
@ -165,18 +163,18 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
ax = bx; ax = bx;
ay = by; ay = by;
} }
assert( orientation != 0 ); CV_Assert( orientation != 0 );
} }
base_a = orientation; base_a = orientation;
/*****************************************************************************************/ /*****************************************************************************************/
/* init calipers position */ /* init calipers position */
seq[0] = bottom; seq[0] = bottom;
seq[1] = right; seq[1] = right;
seq[2] = top; seq[2] = top;
seq[3] = left; seq[3] = left;
/*****************************************************************************************/ /*****************************************************************************************/
/* Main loop - evaluate angles and rotate calipers */ /* Main loop - evaluate angles and rotate calipers */
/* all of edges will be checked while rotating calipers by 90 degrees */ /* all of edges will be checked while rotating calipers by 90 degrees */
for( k = 0; k < n; k++ ) for( k = 0; k < n; k++ )
@ -229,17 +227,17 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
base_a = -lead_y; base_a = -lead_y;
base_b = lead_x; base_b = lead_x;
break; break;
default: assert(0); default:
CV_Error(CV_StsError, "main_element should be 0, 1, 2 or 3");
} }
} }
/* change base point of main edge */ /* change base point of main edge */
seq[main_element] += 1; seq[main_element] += 1;
seq[main_element] = (seq[main_element] == n) ? 0 : seq[main_element]; seq[main_element] = (seq[main_element] == n) ? 0 : seq[main_element];
switch (mode) switch (mode)
{ {
case CV_CALIPERS_MAXHEIGHT: case CALIPERS_MAXHEIGHT:
{ {
/* now main element lies on edge alligned to calipers side */ /* now main element lies on edge alligned to calipers side */
@ -261,7 +259,7 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
break; break;
} }
case CV_CALIPERS_MINAREARECT: case CALIPERS_MINAREARECT:
/* find area of rectangle */ /* find area of rectangle */
{ {
float height; float height;
@ -304,7 +302,7 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
switch (mode) switch (mode)
{ {
case CV_CALIPERS_MINAREARECT: case CALIPERS_MINAREARECT:
{ {
float *buf = (float *) buffer; float *buf = (float *) buffer;
@ -332,87 +330,38 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
out[5] = B2 * buf[4]; out[5] = B2 * buf[4];
} }
break; break;
case CV_CALIPERS_MAXHEIGHT: case CALIPERS_MAXHEIGHT:
{ {
out[0] = max_dist; out[0] = max_dist;
} }
break; break;
} }
}
cvFree( &vect );
cvFree( &inv_vect_length );
} }
CV_IMPL CvBox2D cv::RotatedRect cv::minAreaRect( InputArray _points )
cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
{ {
cv::Ptr<CvMemStorage> temp_storage; Mat hull;
CvBox2D box; Point2f out[3];
cv::AutoBuffer<CvPoint2D32f> _points; RotatedRect box;
CvPoint2D32f* points;
memset(&box, 0, sizeof(box)); convexHull(_points, hull, true, true);
int i, n; if( hull.depth() != CV_32F )
CvSeqReader reader;
CvContour contour_header;
CvSeqBlock block;
CvSeq* ptseq = (CvSeq*)array;
CvPoint2D32f out[3];
if( CV_IS_SEQ(ptseq) )
{ {
if( !CV_IS_SEQ_POINT_SET(ptseq) && Mat temp;
(CV_SEQ_KIND(ptseq) != CV_SEQ_KIND_CURVE || hull.convertTo(temp, CV_32F);
CV_SEQ_ELTYPE(ptseq) != CV_SEQ_ELTYPE_PPOINT )) hull = temp;
CV_Error( CV_StsUnsupportedFormat,
"Input sequence must consist of 2d points or pointers to 2d points" );
if( !storage )
storage = ptseq->storage;
}
else
{
ptseq = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block );
} }
if( storage ) int n = hull.checkVector(2);
{ const Point2f* hpoints = (const Point2f*)hull.data;
temp_storage = cvCreateChildMemStorage( storage );
}
else
{
temp_storage = cvCreateMemStorage(1 << 10);
}
ptseq = cvConvexHull2( ptseq, temp_storage, CV_CLOCKWISE, 1 );
n = ptseq->total;
_points.allocate(n);
points = _points;
cvStartReadSeq( ptseq, &reader );
if( CV_SEQ_ELTYPE( ptseq ) == CV_32SC2 )
{
for( i = 0; i < n; i++ )
{
CvPoint pt;
CV_READ_SEQ_ELEM( pt, reader );
points[i].x = (float)pt.x;
points[i].y = (float)pt.y;
}
}
else
{
for( i = 0; i < n; i++ )
{
CV_READ_SEQ_ELEM( points[i], reader );
}
}
if( n > 2 ) if( n > 2 )
{ {
icvRotatingCalipers( points, n, CV_CALIPERS_MINAREARECT, (float*)out ); rotatingCalipers( hpoints, n, CALIPERS_MINAREARECT, (float*)out );
box.center.x = out[0].x + (out[1].x + out[2].x)*0.5f; box.center.x = out[0].x + (out[1].x + out[2].x)*0.5f;
box.center.y = out[0].y + (out[1].y + out[2].y)*0.5f; box.center.y = out[0].y + (out[1].y + out[2].y)*0.5f;
box.size.width = (float)sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y); box.size.width = (float)sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y);
@ -421,10 +370,10 @@ cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
} }
else if( n == 2 ) else if( n == 2 )
{ {
box.center.x = (points[0].x + points[1].x)*0.5f; box.center.x = (hpoints[0].x + hpoints[1].x)*0.5f;
box.center.y = (points[0].y + points[1].y)*0.5f; box.center.y = (hpoints[0].y + hpoints[1].y)*0.5f;
double dx = points[1].x - points[0].x; double dx = hpoints[1].x - hpoints[0].x;
double dy = points[1].y - points[0].y; double dy = hpoints[1].y - hpoints[0].y;
box.size.width = (float)sqrt(dx*dx + dy*dy); box.size.width = (float)sqrt(dx*dx + dy*dy);
box.size.height = 0; box.size.height = 0;
box.angle = (float)atan2( dy, dx ); box.angle = (float)atan2( dy, dx );
@ -432,10 +381,21 @@ cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
else else
{ {
if( n == 1 ) if( n == 1 )
box.center = points[0]; box.center = hpoints[0];
} }
box.angle = (float)(box.angle*180/CV_PI); box.angle = (float)(box.angle*180/CV_PI);
return box; return box;
} }
CV_IMPL CvBox2D
cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
{
cv::AutoBuffer<double> abuf;
cv::Mat points = cv::cvarrToMat(array, false, false, 0, &abuf);
cv::RotatedRect rr = cv::minAreaRect(points);
return (CvBox2D)rr;
}

File diff suppressed because it is too large Load Diff

@ -13,7 +13,7 @@ static void help()
"Random points are generated and then enclosed.\n" "Random points are generated and then enclosed.\n"
"Call:\n" "Call:\n"
"./minarea\n" "./minarea\n"
"Using OpenCV version %s\n" << CV_VERSION << "\n" << endl; "Using OpenCV v" << CV_VERSION << "\n" << endl;
} }
int main( int /*argc*/, char** /*argv*/ ) int main( int /*argc*/, char** /*argv*/ )