Merge pull request #317 from vpisarev:c2cpp_refactor_imgproc

This commit is contained in:
Andrey Kamaev 2013-01-24 13:03:33 +04:00 committed by OpenCV Buildbot
commit 0487067964
17 changed files with 1890 additions and 2343 deletions

View File

@ -109,6 +109,8 @@ template<typename _Tp> class CV_EXPORTS MatIterator_;
template<typename _Tp> class CV_EXPORTS MatConstIterator_;
template<typename _Tp> class CV_EXPORTS MatCommaInitializer_;
template<typename _Tp, size_t fixed_size = 1024/sizeof(_Tp)+8> class CV_EXPORTS AutoBuffer;
CV_EXPORTS string format( const char* fmt, ... );
CV_EXPORTS string tempfile( const char* suffix CV_DEFAULT(0));
@ -2061,7 +2063,8 @@ CV_EXPORTS void swap(Mat& a, Mat& b);
//! converts array (CvMat or IplImage) to cv::Mat
CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData=false,
bool allowND=true, int coiMode=0);
bool allowND=true, int coiMode=0,
AutoBuffer<double>* buf=0);
//! extracts Channel of Interest from CvMat or IplImage and makes cv::Mat out of it.
CV_EXPORTS void extractImageCOI(const CvArr* arr, OutputArray coiimg, int coi=-1);
//! inserts single-channel cv::Mat into a multi-channel CvMat or IplImage
@ -3081,7 +3084,7 @@ public:
\code
void my_func(const cv::Mat& m)
{
cv::AutoBuffer<float, 1000> buf; // create automatic buffer containing 1000 floats
cv::AutoBuffer<float> buf; // create automatic buffer containing 1000 floats
buf.allocate(m.rows); // if m.rows <= 1000, the pre-allocated buffer is used,
// otherwise the buffer of "m.rows" floats will be allocated
@ -3090,16 +3093,21 @@ public:
}
\endcode
*/
template<typename _Tp, size_t fixed_size=4096/sizeof(_Tp)+8> class CV_EXPORTS AutoBuffer
template<typename _Tp, size_t fixed_size> class CV_EXPORTS AutoBuffer
{
public:
typedef _Tp value_type;
enum { buffer_padding = (int)((16 + sizeof(_Tp) - 1)/sizeof(_Tp)) };
//! the default contructor
AutoBuffer();
//! constructor taking the real buffer size
AutoBuffer(size_t _size);
//! the copy constructor
AutoBuffer(const AutoBuffer<_Tp, fixed_size>& buf);
//! the assignment operator
AutoBuffer<_Tp, fixed_size>& operator = (const AutoBuffer<_Tp, fixed_size>& buf);
//! destructor. calls deallocate()
~AutoBuffer();
@ -3107,6 +3115,10 @@ public:
void allocate(size_t _size);
//! deallocates the buffer if it was dynamically allocated
void deallocate();
//! resizes the buffer and preserves the content
void resize(size_t _size);
//! returns the current buffer size
size_t size() const;
//! returns pointer to the real buffer, stack-allocated or head-allocated
operator _Tp* ();
//! returns read-only pointer to the real buffer, stack-allocated or head-allocated
@ -3116,9 +3128,9 @@ protected:
//! pointer to the real buffer, can point to buf if the buffer is small enough
_Tp* ptr;
//! size of the real buffer
size_t size;
size_t sz;
//! pre-allocated buffer
_Tp buf[fixed_size+buffer_padding];
_Tp buf[fixed_size];
};
/////////////////////////// multi-dimensional dense matrix //////////////////////////
@ -4314,7 +4326,6 @@ public:
int index;
};
class CV_EXPORTS Algorithm;
class CV_EXPORTS AlgorithmInfo;
struct CV_EXPORTS AlgorithmInfoData;

View File

@ -2534,48 +2534,109 @@ inline Point LineIterator::pos() const
/////////////////////////////// AutoBuffer ////////////////////////////////////////
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::AutoBuffer()
template<typename _Tp, size_t fixed_size> inline
AutoBuffer<_Tp, fixed_size>::AutoBuffer()
{
ptr = buf;
size = fixed_size;
sz = fixed_size;
}
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size)
template<typename _Tp, size_t fixed_size> inline
AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size)
{
ptr = buf;
size = fixed_size;
sz = fixed_size;
allocate(_size);
}
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::~AutoBuffer()
template<typename _Tp, size_t fixed_size> inline
AutoBuffer<_Tp, fixed_size>::AutoBuffer(const AutoBuffer<_Tp, fixed_size>& abuf )
{
ptr = buf;
sz = fixed_size;
allocate(abuf.size);
for( size_t i = 0; i < sz; i++ )
ptr[i] = abuf.ptr[i];
}
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>&
AutoBuffer<_Tp, fixed_size>::operator = (const AutoBuffer<_Tp, fixed_size>& abuf)
{
if( this != &abuf )
{
deallocate();
allocate(abuf.size);
for( size_t i = 0; i < sz; i++ )
ptr[i] = abuf.ptr[i];
}
return *this;
}
template<typename _Tp, size_t fixed_size> inline
AutoBuffer<_Tp, fixed_size>::~AutoBuffer()
{ deallocate(); }
template<typename _Tp, size_t fixed_size> inline void AutoBuffer<_Tp, fixed_size>::allocate(size_t _size)
template<typename _Tp, size_t fixed_size> inline void
AutoBuffer<_Tp, fixed_size>::allocate(size_t _size)
{
if(_size <= size)
if(_size <= sz)
{
sz = _size;
return;
}
deallocate();
if(_size > fixed_size)
{
ptr = cv::allocate<_Tp>(_size);
size = _size;
ptr = new _Tp[_size];
sz = _size;
}
}
template<typename _Tp, size_t fixed_size> inline void AutoBuffer<_Tp, fixed_size>::deallocate()
template<typename _Tp, size_t fixed_size> inline void
AutoBuffer<_Tp, fixed_size>::deallocate()
{
if( ptr != buf )
{
cv::deallocate<_Tp>(ptr, size);
delete[] ptr;
ptr = buf;
size = fixed_size;
sz = fixed_size;
}
}
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::operator _Tp* ()
template<typename _Tp, size_t fixed_size> inline void
AutoBuffer<_Tp, fixed_size>::resize(size_t _size)
{
if(_size <= sz)
{
sz = _size;
return;
}
size_t i, prevsize = sz, minsize = MIN(prevsize, _size);
_Tp* prevptr = ptr;
ptr = _size > fixed_size ? new _Tp[_size] : buf;
sz = _size;
if( ptr != prevptr )
for( i = 0; i < minsize; i++ )
ptr[i] = prevptr[i];
for( i = prevsize; i < _size; i++ )
ptr[i] = _Tp();
if( prevptr != buf )
delete[] prevptr;
}
template<typename _Tp, size_t fixed_size> inline size_t
AutoBuffer<_Tp, fixed_size>::size() const
{ return sz; }
template<typename _Tp, size_t fixed_size> inline
AutoBuffer<_Tp, fixed_size>::operator _Tp* ()
{ return ptr; }
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::operator const _Tp* () const
template<typename _Tp, size_t fixed_size> inline
AutoBuffer<_Tp, fixed_size>::operator const _Tp* () const
{ return ptr; }

View File

@ -1314,7 +1314,7 @@ cvMixChannels( const CvArr** src, int src_count,
CvArr** dst, int dst_count,
const int* from_to, int pair_count )
{
cv::AutoBuffer<cv::Mat, 32> buf(src_count + dst_count);
cv::AutoBuffer<cv::Mat> buf(src_count + dst_count);
int i;
for( i = 0; i < src_count; i++ )

View File

@ -669,7 +669,7 @@ void Mat::push_back(const Mat& elems)
Mat cvarrToMat(const CvArr* arr, bool copyData,
bool /*allowND*/, int coiMode)
bool /*allowND*/, int coiMode, AutoBuffer<double>* abuf )
{
if( !arr )
return Mat();
@ -687,10 +687,21 @@ Mat cvarrToMat(const CvArr* arr, bool copyData,
if( CV_IS_SEQ(arr) )
{
CvSeq* seq = (CvSeq*)arr;
CV_Assert(seq->total > 0 && CV_ELEM_SIZE(seq->flags) == seq->elem_size);
int total = seq->total, type = CV_MAT_TYPE(seq->flags), esz = seq->elem_size;
if( total == 0 )
return Mat();
CV_Assert(total > 0 && CV_ELEM_SIZE(seq->flags) == esz);
if(!copyData && seq->first->next == seq->first)
return Mat(seq->total, 1, CV_MAT_TYPE(seq->flags), seq->first->data);
Mat buf(seq->total, 1, CV_MAT_TYPE(seq->flags));
return Mat(total, 1, type, seq->first->data);
if( abuf )
{
abuf->allocate(((size_t)total*esz + sizeof(double)-1)/sizeof(double));
double* bufdata = *abuf;
cvCvtSeqToArray(seq, bufdata, CV_WHOLE_SEQ);
return Mat(total, 1, type, bufdata);
}
Mat buf(total, 1, type);
cvCvtSeqToArray(seq, buf.data, CV_WHOLE_SEQ);
return buf;
}
@ -830,7 +841,7 @@ int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) con
{
return (depth() == _depth || _depth <= 0) &&
(isContinuous() || !_requireContinuous) &&
((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) || (cols == _elemChannels))) ||
((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) || (cols == _elemChannels && channels() == 1))) ||
(dims == 3 && channels() == 1 && size.p[2] == _elemChannels && (size.p[0] == 1 || size.p[1] == 1) &&
(isContinuous() || step.p[1] == step.p[2]*size.p[2])))
? (int)(total()*channels()/_elemChannels) : -1;

View File

@ -202,9 +202,9 @@ bool PxMDecoder::readData( Mat& img )
if( m_offset < 0 || !m_strm.isOpened())
return false;
AutoBuffer<uchar,1024> _src(src_pitch + 32);
AutoBuffer<uchar> _src(src_pitch + 32);
uchar* src = _src;
AutoBuffer<uchar,1024> _gray_palette;
AutoBuffer<uchar> _gray_palette;
uchar* gray_palette = _gray_palette;
// create LUT for converting colors

View File

@ -469,7 +469,7 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const vector<int>& /*params*/)
// row buffer, because TIFFWriteScanline modifies the original data!
size_t scanlineSize = TIFFScanlineSize(pTiffHandle);
AutoBuffer<uchar,1024> _buffer(scanlineSize+32);
AutoBuffer<uchar> _buffer(scanlineSize+32);
uchar* buffer = _buffer;
if (!buffer)
{
@ -577,9 +577,9 @@ bool TiffEncoder::write( const Mat& img, const vector<int>& /*params*/)
#endif*/
int directoryOffset = 0;
AutoBuffer<int,1024> stripOffsets(stripCount);
AutoBuffer<short,1024> stripCounts(stripCount);
AutoBuffer<uchar,1024> _buffer(fileStep+32);
AutoBuffer<int> stripOffsets(stripCount);
AutoBuffer<short> stripCounts(stripCount);
AutoBuffer<uchar> _buffer(fileStep+32);
uchar* buffer = _buffer;
int stripOffsetsOffset = 0;
int stripCountsOffset = 0;

View File

@ -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. */
CvSeq* icvApproximateChainTC89( CvChain* chain, int header_size, CvMemStorage* storage, int method );

View File

@ -469,48 +469,59 @@ cvApproxChains( CvSeq* src_seq,
/* Ramer-Douglas-Peucker algorithm for polygon simplification */
/* the version for integer point coordinates */
template<typename T> static CvSeq*
icvApproxPolyDP( CvSeq* src_contour, int header_size,
CvMemStorage* storage, double eps )
namespace cv
{
template<typename T> static int
approxPolyDP_( const Point_<T>* src_contour, int count0, Point_<T>* dst_contour,
bool is_closed0, double eps, AutoBuffer<Range>* _stack )
{
#define PUSH_SLICE(slice) \
if( top >= stacksz ) \
{ \
_stack->resize(stacksz*3/2); \
stack = *_stack; \
stacksz = _stack->size(); \
} \
stack[top++] = slice
#define READ_PT(pt, pos) \
pt = src_contour[pos]; \
if( ++pos >= count ) pos = 0
#define READ_DST_PT(pt, pos) \
pt = dst_contour[pos]; \
if( ++pos >= count ) pos = 0
#define WRITE_PT(pt) \
dst_contour[new_count++] = pt
typedef cv::Point_<T> PT;
int init_iters = 3;
CvSlice slice = {0, 0}, right_slice = {0, 0};
CvSeqReader reader, reader2;
CvSeqWriter writer;
PT start_pt(-1000000, -1000000), end_pt(0, 0), pt(0,0);
int i = 0, j, count = src_contour->total, new_count;
int is_closed = CV_IS_SEQ_CLOSED( src_contour );
Range slice(0, 0), right_slice(0, 0);
PT start_pt((T)-1000000, (T)-1000000), end_pt(0, 0), pt(0,0);
int i = 0, j, pos = 0, wpos, count = count0, new_count=0;
int is_closed = is_closed0;
bool le_eps = false;
CvMemStorage* temp_storage = 0;
CvSeq* stack = 0;
CvSeq* dst_contour;
size_t top = 0, stacksz = _stack->size();
Range* stack = *_stack;
assert( CV_SEQ_ELTYPE(src_contour) == cv::DataType<PT>::type );
cvStartWriteSeq( src_contour->flags, header_size, sizeof(pt), storage, &writer );
if( count == 0 )
return 0;
if( src_contour->total == 0 )
return cvEndWriteSeq( &writer );
temp_storage = cvCreateChildMemStorage( storage );
assert( src_contour->first != 0 );
stack = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvSlice), temp_storage );
eps *= eps;
cvStartReadSeq( src_contour, &reader, 0 );
if( !is_closed )
{
right_slice.start_index = count;
end_pt = *(PT*)(reader.ptr);
start_pt = *(PT*)cvGetSeqElem( src_contour, -1 );
right_slice.start = count;
end_pt = src_contour[0];
start_pt = src_contour[count-1];
if( start_pt.x != end_pt.x || start_pt.y != end_pt.y )
{
slice.start_index = 0;
slice.end_index = count - 1;
cvSeqPush( stack, &slice );
slice.start = 0;
slice.end = count - 1;
PUSH_SLICE(slice);
}
else
{
@ -521,20 +532,20 @@ icvApproxPolyDP( CvSeq* src_contour, int header_size,
if( is_closed )
{
/* 1. Find approximately two farthest points of the contour */
right_slice.start_index = 0;
// 1. Find approximately two farthest points of the contour
right_slice.start = 0;
for( i = 0; i < init_iters; i++ )
{
double dist, max_dist = 0;
cvSetSeqReaderPos( &reader, right_slice.start_index, 1 );
CV_READ_SEQ_ELEM( start_pt, reader ); /* read the first point */
pos = (pos + right_slice.start) % count;
READ_PT(start_pt, pos);
for( j = 1; j < count; j++ )
{
double dx, dy;
CV_READ_SEQ_ELEM( pt, reader );
READ_PT(pt, pos);
dx = pt.x - start_pt.x;
dy = pt.y - start_pt.y;
@ -543,43 +554,35 @@ icvApproxPolyDP( CvSeq* src_contour, int header_size,
if( dist > max_dist )
{
max_dist = dist;
right_slice.start_index = j;
right_slice.start = j;
}
}
le_eps = max_dist <= eps;
}
/* 2. initialize the stack */
// 2. initialize the stack
if( !le_eps )
{
slice.start_index = cvGetSeqReaderPos( &reader );
slice.end_index = right_slice.start_index += slice.start_index;
right_slice.end = slice.start = pos % count;
slice.end = right_slice.start = (right_slice.start + slice.start) % count;
right_slice.start_index -= right_slice.start_index >= count ? count : 0;
right_slice.end_index = slice.start_index;
if( right_slice.end_index < right_slice.start_index )
right_slice.end_index += count;
cvSeqPush( stack, &right_slice );
cvSeqPush( stack, &slice );
PUSH_SLICE(right_slice);
PUSH_SLICE(slice);
}
else
CV_WRITE_SEQ_ELEM( start_pt, writer );
WRITE_PT(start_pt);
}
/* 3. run recursive process */
while( stack->total != 0 )
// 3. run recursive process
while( top > 0 )
{
cvSeqPop( stack, &slice );
slice = stack[--top];
end_pt = src_contour[slice.end];
pos = slice.start;
READ_PT(start_pt, pos);
cvSetSeqReaderPos( &reader, slice.end_index );
CV_READ_SEQ_ELEM( end_pt, reader );
cvSetSeqReaderPos( &reader, slice.start_index );
CV_READ_SEQ_ELEM( start_pt, reader );
if( slice.end_index > slice.start_index + 1 )
if( pos != slice.end )
{
double dx, dy, dist, max_dist = 0;
@ -588,15 +591,15 @@ icvApproxPolyDP( CvSeq* src_contour, int header_size,
assert( dx != 0 || dy != 0 );
for( i = slice.start_index + 1; i < slice.end_index; i++ )
while( pos != slice.end )
{
CV_READ_SEQ_ELEM( pt, reader );
READ_PT(pt, pos);
dist = fabs((pt.y - start_pt.y) * dx - (pt.x - start_pt.x) * dy);
if( dist > max_dist )
{
max_dist = dist;
right_slice.start_index = i;
right_slice.start = (pos+count-1)%count;
}
}
@ -604,84 +607,106 @@ icvApproxPolyDP( CvSeq* src_contour, int header_size,
}
else
{
assert( slice.end_index > slice.start_index );
le_eps = true;
/* read starting point */
cvSetSeqReaderPos( &reader, slice.start_index );
CV_READ_SEQ_ELEM( start_pt, reader );
// read starting point
start_pt = src_contour[slice.start];
}
if( le_eps )
{
CV_WRITE_SEQ_ELEM( start_pt, writer );
WRITE_PT(start_pt);
}
else
{
right_slice.end_index = slice.end_index;
slice.end_index = right_slice.start_index;
cvSeqPush( stack, &right_slice );
cvSeqPush( stack, &slice );
right_slice.end = slice.end;
slice.end = right_slice.start;
PUSH_SLICE(right_slice);
PUSH_SLICE(slice);
}
}
is_closed = CV_IS_SEQ_CLOSED( src_contour );
if( !is_closed )
CV_WRITE_SEQ_ELEM( end_pt, writer );
dst_contour = cvEndWriteSeq( &writer );
WRITE_PT( src_contour[count-1] );
// last stage: do final clean-up of the approximated contour -
// remove extra points on the [almost] stright lines.
is_closed = is_closed0;
count = new_count;
pos = is_closed ? count - 1 : 0;
READ_DST_PT(start_pt, pos);
wpos = pos;
READ_DST_PT(pt, pos);
cvStartReadSeq( dst_contour, &reader, is_closed );
CV_READ_SEQ_ELEM( start_pt, reader );
reader2 = reader;
CV_READ_SEQ_ELEM( pt, reader );
new_count = count = dst_contour->total;
for( i = !is_closed; i < count - !is_closed && new_count > 2; i++ )
{
double dx, dy, dist, successive_inner_product;
CV_READ_SEQ_ELEM( end_pt, reader );
READ_DST_PT( end_pt, pos );
dx = end_pt.x - start_pt.x;
dy = end_pt.y - start_pt.y;
dist = fabs((pt.x - start_pt.x)*dy - (pt.y - start_pt.y)*dx);
successive_inner_product = (pt.x - start_pt.x) * (end_pt.x - pt.x) +
(pt.y - start_pt.y) * (end_pt.y - pt.y);
(pt.y - start_pt.y) * (end_pt.y - pt.y);
if( dist * dist <= 0.5*eps*(dx*dx + dy*dy) && dx != 0 && dy != 0 &&
successive_inner_product >= 0 )
successive_inner_product >= 0 )
{
new_count--;
*((PT*)reader2.ptr) = start_pt = end_pt;
CV_NEXT_SEQ_ELEM( sizeof(pt), reader2 );
CV_READ_SEQ_ELEM( pt, reader );
dst_contour[wpos] = start_pt = end_pt;
if(++wpos >= count) wpos = 0;
READ_DST_PT(pt, pos);
i++;
continue;
}
*((PT*)reader2.ptr) = start_pt = pt;
CV_NEXT_SEQ_ELEM( sizeof(pt), reader2 );
dst_contour[wpos] = start_pt = pt;
if(++wpos >= count) wpos = 0;
pt = end_pt;
}
if( !is_closed )
*((PT*)reader2.ptr) = pt;
dst_contour[wpos] = pt;
if( new_count < count )
cvSeqPopMulti( dst_contour, 0, count - new_count );
return new_count;
}
cvReleaseMemStorage( &temp_storage );
return dst_contour;
}
void cv::approxPolyDP( InputArray _curve, OutputArray _approxCurve,
double epsilon, bool closed )
{
Mat curve = _curve.getMat();
int npoints = curve.checkVector(2), depth = curve.depth();
CV_Assert( npoints >= 0 && (depth == CV_32S || depth == CV_32F));
if( npoints == 0 )
{
_approxCurve.release();
return;
}
AutoBuffer<Point> _buf(npoints);
AutoBuffer<Range> _stack(npoints);
Point* buf = _buf;
int nout = 0;
if( depth == CV_32S )
nout = approxPolyDP_(curve.ptr<Point>(), npoints, buf, closed, epsilon, &_stack);
else if( depth == CV_32F )
nout = approxPolyDP_(curve.ptr<Point2f>(), npoints, (Point2f*)buf, closed, epsilon, &_stack);
else
CV_Error( CV_StsUnsupportedFormat, "" );
Mat(nout, 1, CV_MAKETYPE(depth, 2), buf).copyTo(_approxCurve);
}
CV_IMPL CvSeq*
cvApproxPoly( const void* array, int header_size,
CvMemStorage* storage, int method,
double parameter, int parameter2 )
cvApproxPoly( const void* array, int header_size,
CvMemStorage* storage, int method,
double parameter, int parameter2 )
{
cv::AutoBuffer<cv::Point> _buf;
cv::AutoBuffer<cv::Range> stack(100);
CvSeq* dst_seq = 0;
CvSeq *prev_contour = 0, *parent = 0;
CvContour contour_header;
@ -703,8 +728,8 @@ cvApproxPoly( const void* array, int header_size,
else
{
src_seq = cvPointSeqFromMat(
CV_SEQ_KIND_CURVE | (parameter2 ? CV_SEQ_FLAG_CLOSED : 0),
array, &contour_header, &block );
CV_SEQ_KIND_CURVE | (parameter2 ? CV_SEQ_FLAG_CLOSED : 0),
array, &contour_header, &block );
}
if( !storage )
@ -712,7 +737,7 @@ cvApproxPoly( const void* array, int header_size,
if( header_size < 0 )
CV_Error( CV_StsOutOfRange, "header_size is negative. "
"Pass 0 to make the destination header_size == input header_size" );
"Pass 0 to make the destination header_size == input header_size" );
if( header_size == 0 )
header_size = src_seq->header_size;
@ -722,7 +747,7 @@ cvApproxPoly( const void* array, int header_size,
if( CV_IS_SEQ_CHAIN( src_seq ))
{
CV_Error( CV_StsBadArg, "Input curves are not polygonal. "
"Use cvApproxChains first" );
"Use cvApproxChains first" );
}
else
{
@ -749,13 +774,34 @@ cvApproxPoly( const void* array, int header_size,
if( parameter < 0 )
CV_Error( CV_StsOutOfRange, "Accuracy must be non-negative" );
if( CV_SEQ_ELTYPE(src_seq) == CV_32SC2 )
contour = icvApproxPolyDP<int>( src_seq, header_size, storage, parameter );
CV_Assert( CV_SEQ_ELTYPE(src_seq) == CV_32SC2 ||
CV_SEQ_ELTYPE(src_seq) == CV_32FC2 );
{
int npoints = src_seq->total, nout = 0;
_buf.allocate(npoints*2);
cv::Point *src = _buf, *dst = src + npoints;
bool closed = CV_IS_SEQ_CLOSED(src_seq);
if( src_seq->first->next == src_seq->first )
src = (cv::Point*)src_seq->first->data;
else
contour = icvApproxPolyDP<float>( src_seq, header_size, storage, parameter );
cvCvtSeqToArray(src_seq, src);
if( CV_SEQ_ELTYPE(src_seq) == CV_32SC2 )
nout = cv::approxPolyDP_(src, npoints, dst, closed, parameter, &stack);
else if( CV_SEQ_ELTYPE(src_seq) == CV_32FC2 )
nout = cv::approxPolyDP_((cv::Point2f*)src, npoints,
(cv::Point2f*)dst, closed, parameter, &stack);
else
CV_Error( CV_StsUnsupportedFormat, "" );
contour = cvCreateSeq( src_seq->flags, header_size,
src_seq->elem_size, storage );
cvSeqPushMulti(contour, dst, nout);
}
break;
default:
assert(0);
CV_Error( CV_StsBadArg, "Invalid approximation method" );
}

View File

@ -1753,195 +1753,4 @@ void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours,
findContours(_image, _contours, noArray(), mode, method, offset);
}
void cv::approxPolyDP( InputArray _curve, OutputArray _approxCurve,
double epsilon, bool closed )
{
Mat curve = _curve.getMat();
int npoints = curve.checkVector(2), depth = curve.depth();
CV_Assert( npoints >= 0 && (depth == CV_32S || depth == CV_32F));
CvMat _ccurve = curve;
MemStorage storage(cvCreateMemStorage());
CvSeq* result = cvApproxPoly(&_ccurve, sizeof(CvContour), storage, CV_POLY_APPROX_DP, epsilon, closed);
if( result->total > 0 )
{
_approxCurve.create(result->total, 1, CV_MAKETYPE(curve.depth(), 2), -1, true);
cvCvtSeqToArray(result, _approxCurve.getMat().data );
}
}
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);
}
void cv::convexHull( InputArray _points, OutputArray _hull, bool clockwise, bool returnPoints )
{
Mat points = _points.getMat();
int nelems = points.checkVector(2), depth = points.depth();
CV_Assert(nelems >= 0 && (depth == CV_32F || depth == CV_32S));
if( nelems == 0 )
{
_hull.release();
return;
}
returnPoints = !_hull.fixedType() ? returnPoints : _hull.type() != CV_32S;
Mat hull(nelems, 1, returnPoints ? CV_MAKETYPE(depth, 2) : CV_32S);
CvMat _cpoints = points, _chull = hull;
cvConvexHull2(&_cpoints, &_chull, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, returnPoints);
_hull.create(_chull.rows, 1, hull.type(), -1, true);
Mat dhull = _hull.getMat(), shull(dhull.size(), dhull.type(), hull.data);
shull.copyTo(dhull);
}
void cv::convexityDefects( InputArray _points, InputArray _hull, OutputArray _defects )
{
Mat points = _points.getMat();
int ptnum = points.checkVector(2, CV_32S);
CV_Assert( ptnum > 3 );
Mat hull = _hull.getMat();
CV_Assert( hull.checkVector(1, CV_32S) > 2 );
Ptr<CvMemStorage> storage = cvCreateMemStorage();
CvMat c_points = points, c_hull = hull;
CvSeq* seq = cvConvexityDefects(&c_points, &c_hull, storage);
int i, n = seq->total;
if( n == 0 )
{
_defects.release();
return;
}
_defects.create(n, 1, CV_32SC4);
Mat defects = _defects.getMat();
SeqIterator<CvConvexityDefect> it = Seq<CvConvexityDefect>(seq).begin();
CvPoint* ptorg = (CvPoint*)points.data;
for( i = 0; i < n; i++, ++it )
{
CvConvexityDefect& d = *it;
int idx0 = (int)(d.start - ptorg);
int idx1 = (int)(d.end - ptorg);
int idx2 = (int)(d.depth_point - ptorg);
CV_Assert( 0 <= idx0 && idx0 < ptnum );
CV_Assert( 0 <= idx1 && idx1 < ptnum );
CV_Assert( 0 <= idx2 && idx2 < ptnum );
CV_Assert( d.depth >= 0 );
int idepth = cvRound(d.depth*256);
defects.at<Vec4i>(i) = Vec4i(idx0, idx1, idx2, idepth);
}
}
bool cv::isContourConvex( InputArray _contour )
{
Mat contour = _contour.getMat();
CV_Assert(contour.checkVector(2) >= 0 &&
(contour.depth() == CV_32F || contour.depth() == CV_32S));
CvMat c = Mat(contour);
return cvCheckContourConvexity(&c) > 0;
}
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);
}
void cv::fitLine( InputArray _points, OutputArray _line, int distType,
double param, double reps, double aeps )
{
Mat points = _points.getMat();
bool is3d = points.checkVector(3) >= 0;
bool is2d = points.checkVector(2) >= 0;
CV_Assert( (is2d || is3d) && (points.depth() == CV_32F || points.depth() == CV_32S) );
CvMat _cpoints = points.reshape(2 + (int)is3d);
float line[6];
cvFitLine(&_cpoints, distType, param, reps, aeps, &line[0]);
int out_size = (is2d)?( (is3d)? (points.channels() * points.rows * 2) : 4 ): 6;
_line.create(out_size, 1, CV_32F, -1, true);
Mat l = _line.getMat();
CV_Assert( l.isContinuous() );
memcpy( l.data, line, out_size * sizeof(line[0]) );
}
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. */

View File

@ -40,18 +40,22 @@
//M*/
#include "precomp.hpp"
#include <iostream>
static int
icvSklansky_32s( CvPoint** array, int start, int end, int* stack, int nsign, int sign2 )
namespace cv
{
template<typename _Tp>
static int Sklansky_( Point_<_Tp>** array, int start, int end, int* stack, int nsign, int sign2 )
{
int incr = end > start ? 1 : -1;
/* prepare first triangle */
// prepare first triangle
int pprev = start, pcur = pprev + incr, pnext = pcur + incr;
int stacksize = 3;
if( start == end ||
(array[start]->x == array[end]->x &&
array[start]->y == array[end]->y) )
(array[start]->x == array[end]->x &&
array[start]->y == array[end]->y) )
{
stack[0] = start;
return 1;
@ -61,94 +65,21 @@ icvSklansky_32s( CvPoint** array, int start, int end, int* stack, int nsign, int
stack[1] = pcur;
stack[2] = pnext;
end += incr; /* make end = afterend */
end += incr; // make end = afterend
while( pnext != end )
{
/* check the angle p1,p2,p3 */
int cury = array[pcur]->y;
int nexty = array[pnext]->y;
int by = nexty - cury;
if( CV_SIGN(by) != nsign )
{
int ax = array[pcur]->x - array[pprev]->x;
int bx = array[pnext]->x - array[pcur]->x;
int ay = cury - array[pprev]->y;
int convexity = ay*bx - ax*by;/* if >0 then convex angle */
if( CV_SIGN(convexity) == sign2 && (ax != 0 || ay != 0) )
{
pprev = pcur;
pcur = pnext;
pnext += incr;
stack[stacksize] = pnext;
stacksize++;
}
else
{
if( pprev == start )
{
pcur = pnext;
stack[1] = pcur;
pnext += incr;
stack[2] = pnext;
}
else
{
stack[stacksize-2] = pnext;
pcur = pprev;
pprev = stack[stacksize-4];
stacksize--;
}
}
}
else
{
pnext += incr;
stack[stacksize-1] = pnext;
}
}
return --stacksize;
}
static int
icvSklansky_32f( CvPoint2D32f** array, int start, int end, int* stack, int nsign, int sign2 )
{
int incr = end > start ? 1 : -1;
/* prepare first triangle */
int pprev = start, pcur = pprev + incr, pnext = pcur + incr;
int stacksize = 3;
if( start == end ||
(array[start]->x == array[end]->x &&
array[start]->y == array[end]->y) )
{
stack[0] = start;
return 1;
}
stack[0] = pprev;
stack[1] = pcur;
stack[2] = pnext;
end += incr; /* make end = afterend */
while( pnext != end )
{
/* check the angle p1,p2,p3 */
float cury = array[pcur]->y;
float nexty = array[pnext]->y;
float by = nexty - cury;
// check the angle p1,p2,p3
_Tp cury = array[pcur]->y;
_Tp nexty = array[pnext]->y;
_Tp by = nexty - cury;
if( CV_SIGN( by ) != nsign )
{
float ax = array[pcur]->x - array[pprev]->x;
float bx = array[pnext]->x - array[pcur]->x;
float ay = cury - array[pprev]->y;
float convexity = ay*bx - ax*by;/* if >0 then convex angle */
_Tp ax = array[pcur]->x - array[pprev]->x;
_Tp bx = array[pnext]->x - array[pcur]->x;
_Tp ay = cury - array[pprev]->y;
_Tp convexity = ay*bx - ax*by; // if >0 then convex angle
if( CV_SIGN( convexity ) == sign2 && (ax != 0 || ay != 0) )
{
@ -166,7 +97,6 @@ icvSklansky_32f( CvPoint2D32f** array, int start, int end, int* stack, int nsign
stack[1] = pcur;
pnext += incr;
stack[2] = pnext;
}
else
{
@ -183,69 +113,297 @@ icvSklansky_32f( CvPoint2D32f** array, int start, int end, int* stack, int nsign
stack[stacksize-1] = pnext;
}
}
return --stacksize;
}
typedef int (*sklansky_func)( CvPoint** points, int start, int end,
int* stack, int sign, int sign2 );
#define cmp_pts( pt1, pt2 ) \
((pt1)->x < (pt2)->x || ((pt1)->x <= (pt2)->x && (pt1)->y < (pt2)->y))
static CV_IMPLEMENT_QSORT( icvSortPointsByPointers_32s, CvPoint*, cmp_pts )
static CV_IMPLEMENT_QSORT( icvSortPointsByPointers_32f, CvPoint2D32f*, cmp_pts )
static void
icvCalcAndWritePtIndices( CvPoint** pointer, int* stack, int start, int end,
CvSeq* ptseq, CvSeqWriter* writer )
template<typename _Tp>
struct CHullCmpPoints
{
int i, incr = start < end ? 1 : -1;
int idx, first_idx = ptseq->first->start_index;
bool operator()(const Point_<_Tp>* p1, const Point_<_Tp>* p2) const
{ return p1->x < p2->x || (p1->x == p2->x && p1->y < p2->y); }
};
for( i = start; i != end; i += incr )
void convexHull( InputArray _points, OutputArray _hull, bool clockwise, bool returnPoints )
{
Mat points = _points.getMat();
int i, total = points.checkVector(2), depth = points.depth(), nout = 0;
int miny_ind = 0, maxy_ind = 0;
CV_Assert(total >= 0 && (depth == CV_32F || depth == CV_32S));
if( total == 0 )
{
CvPoint* ptr = (CvPoint*)pointer[stack[i]];
CvSeqBlock* block = ptseq->first;
while( (unsigned)(idx = (int)(ptr - (CvPoint*)block->data)) >= (unsigned)block->count )
_hull.release();
return;
}
returnPoints = !_hull.fixedType() ? returnPoints : _hull.type() != CV_32S;
bool is_float = depth == CV_32F;
AutoBuffer<Point*> _pointer(total);
AutoBuffer<int> _stack(total + 2), _hullbuf(total);
Point** pointer = _pointer;
Point2f** pointerf = (Point2f**)pointer;
Point* data0 = (Point*)points.data;
int* stack = _stack;
int* hullbuf = _hullbuf;
CV_Assert(points.isContinuous());
for( i = 0; i < total; i++ )
pointer[i] = &data0[i];
// sort the point set by x-coordinate, find min and max y
if( !is_float )
{
std::sort(pointer, pointer + total, CHullCmpPoints<int>());
for( i = 1; i < total; i++ )
{
block = block->next;
if( block == ptseq->first )
CV_Error( CV_StsError, "Internal error" );
int y = pointer[i]->y;
if( pointer[miny_ind]->y > y )
miny_ind = i;
if( pointer[maxy_ind]->y < y )
maxy_ind = i;
}
idx += block->start_index - first_idx;
CV_WRITE_SEQ_ELEM( idx, *writer );
}
else
{
std::sort(pointerf, pointerf + total, CHullCmpPoints<float>());
for( i = 1; i < total; i++ )
{
float y = pointerf[i]->y;
if( pointerf[miny_ind]->y > y )
miny_ind = i;
if( pointerf[maxy_ind]->y < y )
maxy_ind = i;
}
}
if( pointer[0]->x == pointer[total-1]->x &&
pointer[0]->y == pointer[total-1]->y )
{
hullbuf[nout++] = 0;
}
else
{
// upper half
int *tl_stack = stack;
int tl_count = !is_float ?
Sklansky_( pointer, 0, maxy_ind, tl_stack, -1, 1) :
Sklansky_( pointerf, 0, maxy_ind, tl_stack, -1, 1);
int *tr_stack = stack + tl_count;
int tr_count = !is_float ?
Sklansky_( pointer, total-1, maxy_ind, tr_stack, -1, -1) :
Sklansky_( pointerf, total-1, maxy_ind, tr_stack, -1, -1);
// gather upper part of convex hull to output
if( !clockwise )
{
std::swap( tl_stack, tr_stack );
std::swap( tl_count, tr_count );
}
for( i = 0; i < tl_count-1; i++ )
hullbuf[nout++] = pointer[tl_stack[i]] - data0;
for( i = tr_count - 1; i > 0; i-- )
hullbuf[nout++] = pointer[tr_stack[i]] - data0;
int stop_idx = tr_count > 2 ? tr_stack[1] : tl_count > 2 ? tl_stack[tl_count - 2] : -1;
// lower half
int *bl_stack = stack;
int bl_count = !is_float ?
Sklansky_( pointer, 0, miny_ind, bl_stack, 1, -1) :
Sklansky_( pointerf, 0, miny_ind, bl_stack, 1, -1);
int *br_stack = stack + bl_count;
int br_count = !is_float ?
Sklansky_( pointer, total-1, miny_ind, br_stack, 1, 1) :
Sklansky_( pointerf, total-1, miny_ind, br_stack, 1, 1);
if( clockwise )
{
std::swap( bl_stack, br_stack );
std::swap( bl_count, br_count );
}
if( stop_idx >= 0 )
{
int check_idx = bl_count > 2 ? bl_stack[1] :
bl_count + br_count > 2 ? br_stack[2-bl_count] : -1;
if( check_idx == stop_idx || (check_idx >= 0 &&
pointer[check_idx]->x == pointer[stop_idx]->x &&
pointer[check_idx]->y == pointer[stop_idx]->y) )
{
// if all the points lie on the same line, then
// the bottom part of the convex hull is the mirrored top part
// (except the exteme points).
bl_count = MIN( bl_count, 2 );
br_count = MIN( br_count, 2 );
}
}
for( i = 0; i < bl_count-1; i++ )
hullbuf[nout++] = pointer[bl_stack[i]] - data0;
for( i = br_count-1; i > 0; i-- )
hullbuf[nout++] = pointer[br_stack[i]] - data0;
}
if( !returnPoints )
Mat(nout, 1, CV_32S, hullbuf).copyTo(_hull);
else
{
_hull.create(nout, 1, CV_MAKETYPE(depth, 2));
Mat hull = _hull.getMat();
size_t step = !hull.isContinuous() ? hull.step[0] : sizeof(Point);
for( i = 0; i < nout; i++ )
*(Point*)(hull.data + i*step) = data0[hullbuf[i]];
}
}
void convexityDefects( InputArray _points, InputArray _hull, OutputArray _defects )
{
Mat points = _points.getMat();
int i, j = 0, npoints = points.checkVector(2, CV_32S);
CV_Assert( npoints >= 0 );
if( npoints <= 3 )
{
_defects.release();
return;
}
Mat hull = _hull.getMat();
int hpoints = hull.checkVector(1, CV_32S);
CV_Assert( hpoints > 2 );
const Point* ptr = (const Point*)points.data;
const int* hptr = hull.ptr<int>();
vector<Vec4i> defects;
// 1. recognize co-orientation of the contour and its hull
bool rev_orientation = ((hptr[1] > hptr[0]) + (hptr[2] > hptr[1]) + (hptr[0] > hptr[2])) != 2;
// 2. cycle through points and hull, compute defects
int hcurr = hptr[rev_orientation ? 0 : hpoints-1];
CV_Assert( 0 <= hcurr && hcurr < npoints );
for( i = 0; i < hpoints; i++ )
{
int hnext = hptr[rev_orientation ? hpoints - i - 1 : i];
CV_Assert( 0 <= hnext && hnext < npoints );
Point pt0 = ptr[hcurr], pt1 = ptr[hnext];
double dx0 = pt1.x - pt0.x;
double dy0 = pt1.y - pt0.y;
double scale = dx0 == 0 && dy0 == 0 ? 0. : 1./sqrt(dx0*dx0 + dy0*dy0);
int defect_deepest_point = -1;
double defect_depth = 0;
bool is_defect = false;
for(;;)
{
// go through points to achieve next hull point
j++;
j &= j >= npoints ? 0 : -1;
if( j == hnext )
break;
// compute distance from current point to hull edge
double dx = ptr[j].x - pt0.x;
double dy = ptr[j].y - pt0.y;
double dist = fabs(-dy0*dx + dx0*dy) * scale;
if( dist > defect_depth )
{
defect_depth = dist;
defect_deepest_point = j;
is_defect = true;
}
}
if( is_defect )
{
int idepth = cvRound(defect_depth*256);
defects.push_back(Vec4i(hcurr, hnext, defect_deepest_point, idepth));
}
hcurr = hnext;
}
Mat(defects).copyTo(_defects);
}
template<typename _Tp>
static bool isContourConvex_( const Point_<_Tp>* p, int n )
{
Point_<_Tp> prev_pt = p[(n-2+n) % n];
Point_<_Tp> cur_pt = p[n-1];
_Tp dx0 = cur_pt.x - prev_pt.x;
_Tp dy0 = cur_pt.y - prev_pt.y;
int orientation = 0;
for( int i = 0; i < n-1; i++ )
{
_Tp dxdy0, dydx0;
_Tp dx, dy;
prev_pt = cur_pt;
cur_pt = p[i];
dx = cur_pt.x - prev_pt.x;
dy = cur_pt.y - prev_pt.y;
dxdy0 = dx * dy0;
dydx0 = dy * dx0;
// find orientation
// orient = -dy0 * dx + dx0 * dy;
// orientation |= (orient > 0) ? 1 : 2;
orientation |= (dydx0 > dxdy0) ? 1 : ((dydx0 < dxdy0) ? 2 : 3);
if( orientation == 3 )
return false;
dx0 = dx;
dy0 = dy;
}
return true;
}
bool isContourConvex( InputArray _contour )
{
Mat contour = _contour.getMat();
int total = contour.checkVector(2), depth = contour.depth();
CV_Assert(total >= 0 && (depth == CV_32F || depth == CV_32S));
if( total == 0 )
return false;
return depth == CV_32S ?
isContourConvex_((const Point*)contour.data, total ) :
isContourConvex_((const Point2f*)contour.data, total );
}
}
CV_IMPL CvSeq*
cvConvexHull2( const CvArr* array, void* hull_storage,
int orientation, int return_points )
{
union { CvContour* c; CvSeq* s; } hull;
cv::AutoBuffer<CvPoint*> _pointer;
CvPoint** pointer;
CvPoint2D32f** pointerf = 0;
cv::AutoBuffer<int> _stack;
int* stack;
hull.s = 0;
CvMat* mat = 0;
CvSeqReader reader;
CvSeqWriter writer;
CvContour contour_header;
union { CvContour c; CvSeq s; } hull_header;
CvSeqBlock block, hullblock;
CvSeq* ptseq = 0;
CvSeq* hullseq = 0;
int is_float;
int* t_stack;
int t_count;
int i, miny_ind = 0, maxy_ind = 0, total;
int hulltype;
int stop_idx;
sklansky_func sklansky;
if( CV_IS_SEQ( array ))
{
@ -264,17 +422,16 @@ cvConvexHull2( const CvArr* array, void* hull_storage,
{
if( return_points )
{
hullseq = cvCreateSeq(
CV_SEQ_KIND_CURVE|CV_SEQ_ELTYPE(ptseq)|
CV_SEQ_FLAG_CLOSED|CV_SEQ_FLAG_CONVEX,
sizeof(CvContour), sizeof(CvPoint),(CvMemStorage*)hull_storage );
hullseq = cvCreateSeq(CV_SEQ_KIND_CURVE|CV_SEQ_ELTYPE(ptseq)|
CV_SEQ_FLAG_CLOSED|CV_SEQ_FLAG_CONVEX,
sizeof(CvContour), sizeof(CvPoint),(CvMemStorage*)hull_storage );
}
else
{
hullseq = cvCreateSeq(
CV_SEQ_KIND_CURVE|CV_SEQ_ELTYPE_PPOINT|
CV_SEQ_FLAG_CLOSED|CV_SEQ_FLAG_CONVEX,
sizeof(CvContour), sizeof(CvPoint*), (CvMemStorage*)hull_storage );
CV_SEQ_KIND_CURVE|CV_SEQ_ELTYPE_PPOINT|
CV_SEQ_FLAG_CLOSED|CV_SEQ_FLAG_CONVEX,
sizeof(CvContour), sizeof(CvPoint*), (CvMemStorage*)hull_storage );
}
}
else
@ -286,192 +443,50 @@ cvConvexHull2( const CvArr* array, void* hull_storage,
if( (mat->cols != 1 && mat->rows != 1) || !CV_IS_MAT_CONT(mat->type))
CV_Error( CV_StsBadArg,
"The hull matrix should be continuous and have a single row or a single column" );
"The hull matrix should be continuous and have a single row or a single column" );
if( mat->cols + mat->rows - 1 < ptseq->total )
CV_Error( CV_StsBadSize, "The hull matrix size might be not enough to fit the hull" );
if( CV_MAT_TYPE(mat->type) != CV_SEQ_ELTYPE(ptseq) &&
CV_MAT_TYPE(mat->type) != CV_32SC1 )
CV_MAT_TYPE(mat->type) != CV_32SC1 )
CV_Error( CV_StsUnsupportedFormat,
"The hull matrix must have the same type as input or 32sC1 (integers)" );
"The hull matrix must have the same type as input or 32sC1 (integers)" );
hullseq = cvMakeSeqHeaderForArray(
CV_SEQ_KIND_CURVE|CV_MAT_TYPE(mat->type)|CV_SEQ_FLAG_CLOSED,
sizeof(contour_header), CV_ELEM_SIZE(mat->type), mat->data.ptr,
mat->cols + mat->rows - 1, &hull_header.s, &hullblock );
CV_SEQ_KIND_CURVE|CV_MAT_TYPE(mat->type)|CV_SEQ_FLAG_CLOSED,
sizeof(contour_header), CV_ELEM_SIZE(mat->type), mat->data.ptr,
mat->cols + mat->rows - 1, &hull_header.s, &hullblock );
cvClearSeq( hullseq );
}
total = ptseq->total;
int hulltype = CV_SEQ_ELTYPE(hullseq);
int total = ptseq->total;
if( total == 0 )
{
if( mat )
CV_Error( CV_StsBadSize,
"Point sequence can not be empty if the output is matrix" );
"Point sequence can not be empty if the output is matrix" );
return hull.s;
}
cvStartAppendToSeq( hullseq, &writer );
cv::AutoBuffer<double> _ptbuf;
cv::Mat h0;
cv::convexHull(cv::cvarrToMat(ptseq, false, false, 0, &_ptbuf), h0,
orientation == CV_CLOCKWISE, CV_MAT_CN(hulltype) == 2);
is_float = CV_SEQ_ELTYPE(ptseq) == CV_32FC2;
hulltype = CV_SEQ_ELTYPE(hullseq);
sklansky = !is_float ? (sklansky_func)icvSklansky_32s :
(sklansky_func)icvSklansky_32f;
_pointer.allocate( ptseq->total );
_stack.allocate( ptseq->total + 2);
pointer = _pointer;
pointerf = (CvPoint2D32f**)pointer;
stack = _stack;
cvStartReadSeq( ptseq, &reader );
for( i = 0; i < total; i++ )
if( hulltype == CV_SEQ_ELTYPE_PPOINT )
{
pointer[i] = (CvPoint*)reader.ptr;
CV_NEXT_SEQ_ELEM( ptseq->elem_size, reader );
}
// sort the point set by x-coordinate, find min and max y
if( !is_float )
{
icvSortPointsByPointers_32s( pointer, total, 0 );
for( i = 1; i < total; i++ )
const int* idx = h0.ptr<int>();
int ctotal = (int)h0.total();
for( int i = 0; i < ctotal; i++ )
{
int y = pointer[i]->y;
if( pointer[miny_ind]->y > y )
miny_ind = i;
if( pointer[maxy_ind]->y < y )
maxy_ind = i;
void* ptr = cvGetSeqElem(ptseq, idx[i]);
cvSeqPush( hullseq, &ptr );
}
}
else
{
icvSortPointsByPointers_32f( pointerf, total, 0 );
for( i = 1; i < total; i++ )
{
float y = pointerf[i]->y;
if( pointerf[miny_ind]->y > y )
miny_ind = i;
if( pointerf[maxy_ind]->y < y )
maxy_ind = i;
}
}
if( pointer[0]->x == pointer[total-1]->x &&
pointer[0]->y == pointer[total-1]->y )
{
if( hulltype == CV_SEQ_ELTYPE_PPOINT )
{
CV_WRITE_SEQ_ELEM( pointer[0], writer );
}
else if( hulltype == CV_SEQ_ELTYPE_INDEX )
{
int index = 0;
CV_WRITE_SEQ_ELEM( index, writer );
}
else
{
CvPoint pt = pointer[0][0];
CV_WRITE_SEQ_ELEM( pt, writer );
}
goto finish_hull;
}
/*upper half */
{
int *tl_stack = stack;
int tl_count = sklansky( pointer, 0, maxy_ind, tl_stack, -1, 1 );
int *tr_stack = tl_stack + tl_count;
int tr_count = sklansky( pointer, ptseq->total - 1, maxy_ind, tr_stack, -1, -1 );
/* gather upper part of convex hull to output */
if( orientation == CV_COUNTER_CLOCKWISE )
{
CV_SWAP( tl_stack, tr_stack, t_stack );
CV_SWAP( tl_count, tr_count, t_count );
}
if( hulltype == CV_SEQ_ELTYPE_PPOINT )
{
for( i = 0; i < tl_count - 1; i++ )
CV_WRITE_SEQ_ELEM( pointer[tl_stack[i]], writer );
for( i = tr_count - 1; i > 0; i-- )
CV_WRITE_SEQ_ELEM( pointer[tr_stack[i]], writer );
}
else if( hulltype == CV_SEQ_ELTYPE_INDEX )
{
icvCalcAndWritePtIndices( pointer, tl_stack, 0, tl_count-1, ptseq, &writer );
icvCalcAndWritePtIndices( pointer, tr_stack, tr_count-1, 0, ptseq, &writer );
}
else
{
for( i = 0; i < tl_count - 1; i++ )
CV_WRITE_SEQ_ELEM( pointer[tl_stack[i]][0], writer );
for( i = tr_count - 1; i > 0; i-- )
CV_WRITE_SEQ_ELEM( pointer[tr_stack[i]][0], writer );
}
stop_idx = tr_count > 2 ? tr_stack[1] : tl_count > 2 ? tl_stack[tl_count - 2] : -1;
}
/* lower half */
{
int *bl_stack = stack;
int bl_count = sklansky( pointer, 0, miny_ind, bl_stack, 1, -1 );
int *br_stack = stack + bl_count;
int br_count = sklansky( pointer, ptseq->total - 1, miny_ind, br_stack, 1, 1 );
if( orientation != CV_COUNTER_CLOCKWISE )
{
CV_SWAP( bl_stack, br_stack, t_stack );
CV_SWAP( bl_count, br_count, t_count );
}
if( stop_idx >= 0 )
{
int check_idx = bl_count > 2 ? bl_stack[1] :
bl_count + br_count > 2 ? br_stack[2-bl_count] : -1;
if( check_idx == stop_idx || (check_idx >= 0 &&
pointer[check_idx]->x == pointer[stop_idx]->x &&
pointer[check_idx]->y == pointer[stop_idx]->y) )
{
/* if all the points lie on the same line, then
the bottom part of the convex hull is the mirrored top part
(except the exteme points).*/
bl_count = MIN( bl_count, 2 );
br_count = MIN( br_count, 2 );
}
}
if( hulltype == CV_SEQ_ELTYPE_PPOINT )
{
for( i = 0; i < bl_count - 1; i++ )
CV_WRITE_SEQ_ELEM( pointer[bl_stack[i]], writer );
for( i = br_count - 1; i > 0; i-- )
CV_WRITE_SEQ_ELEM( pointer[br_stack[i]], writer );
}
else if( hulltype == CV_SEQ_ELTYPE_INDEX )
{
icvCalcAndWritePtIndices( pointer, bl_stack, 0, bl_count-1, ptseq, &writer );
icvCalcAndWritePtIndices( pointer, br_stack, br_count-1, 0, ptseq, &writer );
}
else
{
for( i = 0; i < bl_count - 1; i++ )
CV_WRITE_SEQ_ELEM( pointer[bl_stack[i]][0], writer );
for( i = br_count - 1; i > 0; i-- )
CV_WRITE_SEQ_ELEM( pointer[br_stack[i]][0], writer );
}
}
finish_hull:
cvEndWriteSeq( &writer );
cvSeqPushMulti(hullseq, h0.data, (int)h0.total());
if( mat )
{
@ -484,13 +499,10 @@ finish_hull:
{
hull.s = hullseq;
hull.c->rect = cvBoundingRect( ptseq,
ptseq->header_size < (int)sizeof(CvContour) ||
&ptseq->flags == &contour_header.flags );
/*if( ptseq != (CvSeq*)&contour_header )
hullseq->v_prev = ptseq;*/
ptseq->header_size < (int)sizeof(CvContour) ||
&ptseq->flags == &contour_header.flags );
}
return hull.s;
}
@ -498,8 +510,8 @@ finish_hull:
/* contour must be a simple polygon */
/* it must have more than 3 points */
CV_IMPL CvSeq* cvConvexityDefects( const CvArr* array,
const CvArr* hullarray,
CvMemStorage* storage )
const CvArr* hullarray,
CvMemStorage* storage )
{
CvSeq* defects = 0;
@ -523,7 +535,7 @@ CV_IMPL CvSeq* cvConvexityDefects( const CvArr* array,
{
if( !CV_IS_SEQ_POINT_SET( ptseq ))
CV_Error( CV_StsUnsupportedFormat,
"Input sequence is not a sequence of points" );
"Input sequence is not a sequence of points" );
if( !storage )
storage = ptseq->storage;
}
@ -540,8 +552,8 @@ CV_IMPL CvSeq* cvConvexityDefects( const CvArr* array,
int hulltype = CV_SEQ_ELTYPE( hull );
if( hulltype != CV_SEQ_ELTYPE_PPOINT && hulltype != CV_SEQ_ELTYPE_INDEX )
CV_Error( CV_StsUnsupportedFormat,
"Convex hull must represented as a sequence "
"of indices or sequence of pointers" );
"Convex hull must represented as a sequence "
"of indices or sequence of pointers" );
if( !storage )
storage = hull->storage;
}
@ -553,17 +565,17 @@ CV_IMPL CvSeq* cvConvexityDefects( const CvArr* array,
CV_Error(CV_StsBadArg, "Convex hull is neither sequence nor matrix");
if( (mat->cols != 1 && mat->rows != 1) ||
!CV_IS_MAT_CONT(mat->type) || CV_MAT_TYPE(mat->type) != CV_32SC1 )
!CV_IS_MAT_CONT(mat->type) || CV_MAT_TYPE(mat->type) != CV_32SC1 )
CV_Error( CV_StsBadArg,
"The matrix should be 1-dimensional and continuous array of int's" );
"The matrix should be 1-dimensional and continuous array of int's" );
if( mat->cols + mat->rows - 1 > ptseq->total )
CV_Error( CV_StsBadSize, "Convex hull is larger than the point sequence" );
hull = cvMakeSeqHeaderForArray(
CV_SEQ_KIND_CURVE|CV_MAT_TYPE(mat->type)|CV_SEQ_FLAG_CLOSED,
sizeof(CvContour), CV_ELEM_SIZE(mat->type), mat->data.ptr,
mat->cols + mat->rows - 1, &hull_header.s, &hullblock );
CV_SEQ_KIND_CURVE|CV_MAT_TYPE(mat->type)|CV_SEQ_FLAG_CLOSED,
sizeof(CvContour), CV_ELEM_SIZE(mat->type), mat->data.ptr,
mat->cols + mat->rows - 1, &hull_header.s, &hullblock );
}
is_index = CV_SEQ_ELTYPE(hull) == CV_SEQ_ELTYPE_INDEX;
@ -701,11 +713,6 @@ CV_IMPL CvSeq* cvConvexityDefects( const CvArr* array,
CV_IMPL int
cvCheckContourConvexity( const CvArr* array )
{
int flag = -1;
int i;
int orientation = 0;
CvSeqReader reader;
CvContour contour_header;
CvSeqBlock block;
CvSeq* contour = (CvSeq*)array;
@ -714,102 +721,19 @@ cvCheckContourConvexity( const CvArr* array )
{
if( !CV_IS_SEQ_POINT_SET(contour))
CV_Error( CV_StsUnsupportedFormat,
"Input sequence must be polygon (closed 2d curve)" );
"Input sequence must be polygon (closed 2d curve)" );
}
else
{
contour = cvPointSeqFromMat(CV_SEQ_KIND_CURVE|CV_SEQ_FLAG_CLOSED, array, &contour_header, &block );
contour = cvPointSeqFromMat(CV_SEQ_KIND_CURVE|
CV_SEQ_FLAG_CLOSED, array, &contour_header, &block );
}
if( contour->total == 0 )
return -1;
cvStartReadSeq( contour, &reader, 0 );
flag = 1;
if( CV_SEQ_ELTYPE( contour ) == CV_32SC2 )
{
CvPoint *prev_pt = (CvPoint*)reader.prev_elem;
CvPoint *cur_pt = (CvPoint*)reader.ptr;
int dx0 = cur_pt->x - prev_pt->x;
int dy0 = cur_pt->y - prev_pt->y;
for( i = 0; i < contour->total; i++ )
{
int dxdy0, dydx0;
int dx, dy;
/*int orient; */
CV_NEXT_SEQ_ELEM( sizeof(CvPoint), reader );
prev_pt = cur_pt;
cur_pt = (CvPoint *) reader.ptr;
dx = cur_pt->x - prev_pt->x;
dy = cur_pt->y - prev_pt->y;
dxdy0 = dx * dy0;
dydx0 = dy * dx0;
/* find orientation */
/*orient = -dy0 * dx + dx0 * dy;
orientation |= (orient > 0) ? 1 : 2;
*/
orientation |= (dydx0 > dxdy0) ? 1 : ((dydx0 < dxdy0) ? 2 : 3);
if( orientation == 3 )
{
flag = 0;
break;
}
dx0 = dx;
dy0 = dy;
}
}
else
{
CV_Assert( CV_SEQ_ELTYPE(contour) == CV_32FC2 );
CvPoint2D32f *prev_pt = (CvPoint2D32f*)reader.prev_elem;
CvPoint2D32f *cur_pt = (CvPoint2D32f*)reader.ptr;
float dx0 = cur_pt->x - prev_pt->x;
float dy0 = cur_pt->y - prev_pt->y;
for( i = 0; i < contour->total; i++ )
{
float dxdy0, dydx0;
float dx, dy;
/*int orient; */
CV_NEXT_SEQ_ELEM( sizeof(CvPoint2D32f), reader );
prev_pt = cur_pt;
cur_pt = (CvPoint2D32f*) reader.ptr;
dx = cur_pt->x - prev_pt->x;
dy = cur_pt->y - prev_pt->y;
dxdy0 = dx * dy0;
dydx0 = dy * dx0;
/* find orientation */
/*orient = -dy0 * dx + dx0 * dy;
orientation |= (orient > 0) ? 1 : 2;
*/
orientation |= (dydx0 > dxdy0) ? 1 : ((dydx0 < dxdy0) ? 2 : 3);
if( orientation == 3 )
{
flag = 0;
break;
}
dx0 = dx;
dy0 = dy;
}
}
return flag;
cv::AutoBuffer<double> _buf;
return cv::isContourConvex(cv::cvarrToMat(contour, false, false, 0, &_buf)) ? 1 : 0;
}
/* End of file. */

View File

@ -92,97 +92,38 @@ cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] )
}
int
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 cv::pointPolygonTest( InputArray _contour, Point2f pt, bool measureDist )
{
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;
CvContour header;
CvSeq* contour = (CvSeq*)_contour;
CvSeqReader reader;
int i, total, counter = 0;
int is_float;
bool is_float = depth == CV_32F;
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) )
{
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" );
if( total == 0 )
return measureDist ? -DBL_MAX : -1;
total = contour->total;
is_float = CV_SEQ_ELTYPE(contour) == CV_32FC2;
cvStartReadSeq( contour, &reader, -1 );
const Point* cnt = (const Point*)contour.data;
const Point2f* cntf = (const Point2f*)cnt;
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
CvPoint v0, v;
CV_READ_SEQ_ELEM( v, reader );
// the fastest "purely integer" branch
Point v0, v = cnt[total-1];
for( i = 0; i < total; i++ )
{
int dist;
v0 = v;
CV_READ_SEQ_ELEM( v, reader );
v = cnt[i];
if( (v0.y <= ip.y && v.y <= ip.y) ||
(v0.y > ip.y && v.y > ip.y) ||
(v0.x < ip.x && v.x < ip.x) )
(v0.y > ip.y && v.y > ip.y) ||
(v0.x < ip.x && v.x < ip.x) )
{
if( ip.y == v.y && (ip.x == v.x || (ip.y == v0.y &&
((v0.x <= ip.x && ip.x <= v.x) || (v.x <= ip.x && ip.x <= v0.x)))) )
@ -202,38 +143,32 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
}
else
{
CvPoint2D32f v0, v;
CvPoint iv;
Point2f v0, v;
Point iv;
if( is_float )
{
CV_READ_SEQ_ELEM( v, reader );
v = cntf[total-1];
}
else
{
CV_READ_SEQ_ELEM( iv, reader );
v = cvPointTo32f( iv );
v = cnt[total-1];
}
if( !measure_dist )
if( !measureDist )
{
for( i = 0; i < total; i++ )
{
double dist;
v0 = v;
if( is_float )
{
CV_READ_SEQ_ELEM( v, reader );
}
v = cntf[i];
else
{
CV_READ_SEQ_ELEM( iv, reader );
v = cvPointTo32f( iv );
}
v = cnt[i];
if( (v0.y <= pt.y && v.y <= pt.y) ||
(v0.y > pt.y && v.y > pt.y) ||
(v0.x < pt.x && v.x < pt.x) )
(v0.y > pt.y && v.y > pt.y) ||
(v0.x < pt.x && v.x < pt.x) )
{
if( pt.y == v.y && (pt.x == v.x || (pt.y == v0.y &&
((v0.x <= pt.x && pt.x <= v.x) || (v.x <= pt.x && pt.x <= v0.x)))) )
@ -259,14 +194,9 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
v0 = v;
if( is_float )
{
CV_READ_SEQ_ELEM( v, reader );
}
v = cntf[i];
else
{
CV_READ_SEQ_ELEM( iv, reader );
v = cvPointTo32f( iv );
}
v = cnt[i];
dx = v.x - v0.x; dy = v.y - v0.y;
dx1 = pt.x - v0.x; dy1 = pt.y - v0.y;
@ -292,8 +222,8 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
}
if( (v0.y <= pt.y && v.y <= pt.y) ||
(v0.y > pt.y && v.y > pt.y) ||
(v0.x < pt.x && v.x < pt.x) )
(v0.y > pt.y && v.y > pt.y) ||
(v0.x < pt.x && v.x < pt.x) )
continue;
dist_num = dy1*dx - dx1*dy;
@ -301,17 +231,25 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
dist_num = -dist_num;
counter += dist_num > 0;
}
result = sqrt(min_dist_num/min_dist_denom);
if( counter % 2 == 0 )
result = -result;
}
}
return result;
}
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),
Chapter 7. It is not written to be comprehensible without the

View File

@ -40,19 +40,19 @@
//M*/
#include "precomp.hpp"
namespace cv
{
static const double eps = 1e-6;
static CvStatus
icvFitLine2D_wods( CvPoint2D32f * points, int _count, float *weights, float *line )
static void fitLine2D_wods( const Point2f* points, int count, float *weights, float *line )
{
double x = 0, y = 0, x2 = 0, y2 = 0, xy = 0, w = 0;
double dx2, dy2, dxy;
int i;
int count = _count;
float t;
/* Calculating the average of x and y... */
// Calculating the average of x and y...
if( weights == 0 )
{
for( i = 0; i < count; i += 1 )
@ -94,12 +94,9 @@ icvFitLine2D_wods( CvPoint2D32f * points, int _count, float *weights, float *lin
line[2] = (float) x;
line[3] = (float) y;
return CV_NO_ERR;
}
static CvStatus
icvFitLine3D_wods( CvPoint3D32f * points, int count, float *weights, float *line )
static void fitLine3D_wods( const Point3f * points, int count, float *weights, float *line )
{
int i;
float w0 = 0;
@ -184,25 +181,13 @@ icvFitLine3D_wods( CvPoint3D32f * points, int count, float *weights, float *line
det[7] = det[5];
det[8] = dy2 + dx2;
/* Searching for a eigenvector of det corresponding to the minimal eigenvalue */
#if 1
{
CvMat _det = cvMat( 3, 3, CV_32F, det );
CvMat _evc = cvMat( 3, 3, CV_32F, evc );
CvMat _evl = cvMat( 3, 1, CV_32F, evl );
cvEigenVV( &_det, &_evc, &_evl, 0 );
// Searching for a eigenvector of det corresponding to the minimal eigenvalue
Mat _det( 3, 3, CV_32F, det );
Mat _evc( 3, 3, CV_32F, evc );
Mat _evl( 3, 1, CV_32F, evl );
eigen( _det, _evl, _evc );
i = evl[0] < evl[1] ? (evl[0] < evl[2] ? 0 : 2) : (evl[1] < evl[2] ? 1 : 2);
}
#else
{
CvMat _det = cvMat( 3, 3, CV_32F, det );
CvMat _evc = cvMat( 3, 3, CV_32F, evc );
CvMat _evl = cvMat( 1, 3, CV_32F, evl );
cvSVD( &_det, &_evl, &_evc, 0, CV_SVD_MODIFY_A+CV_SVD_U_T );
}
i = 2;
#endif
v = &evc[i * 3];
n = (float) sqrt( (double)v[0] * v[0] + (double)v[1] * v[1] + (double)v[2] * v[2] );
n = (float)MAX(n, eps);
@ -212,12 +197,9 @@ icvFitLine3D_wods( CvPoint3D32f * points, int count, float *weights, float *line
line[3] = x0;
line[4] = y0;
line[5] = z0;
return CV_NO_ERR;
}
static double
icvCalcDist2D( CvPoint2D32f * points, int count, float *_line, float *dist )
static double calcDist2D( const Point2f* points, int count, float *_line, float *dist )
{
int j;
float px = _line[2], py = _line[3];
@ -238,8 +220,7 @@ icvCalcDist2D( CvPoint2D32f * points, int count, float *_line, float *dist )
return sum_dist;
}
static double
icvCalcDist3D( CvPoint3D32f * points, int count, float *_line, float *dist )
static double calcDist3D( const Point3f* points, int count, float *_line, float *dist )
{
int j;
float px = _line[3], py = _line[4], pz = _line[5];
@ -266,8 +247,7 @@ icvCalcDist3D( CvPoint3D32f * points, int count, float *_line, float *dist )
return sum_dist;
}
static void
icvWeightL1( float *d, int count, float *w )
static void weightL1( float *d, int count, float *w )
{
int i;
@ -278,8 +258,7 @@ icvWeightL1( float *d, int count, float *w )
}
}
static void
icvWeightL12( float *d, int count, float *w )
static void weightL12( float *d, int count, float *w )
{
int i;
@ -290,8 +269,7 @@ icvWeightL12( float *d, int count, float *w )
}
static void
icvWeightHuber( float *d, int count, float *w, float _c )
static void weightHuber( float *d, int count, float *w, float _c )
{
int i;
const float c = _c <= 0 ? 1.345f : _c;
@ -306,8 +284,7 @@ icvWeightHuber( float *d, int count, float *w, float _c )
}
static void
icvWeightFair( float *d, int count, float *w, float _c )
static void weightFair( float *d, int count, float *w, float _c )
{
int i;
const float c = _c == 0 ? 1 / 1.3998f : 1 / _c;
@ -318,76 +295,72 @@ icvWeightFair( float *d, int count, float *w, float _c )
}
}
static void
icvWeightWelsch( float *d, int count, float *w, float _c )
static void weightWelsch( float *d, int count, float *w, float _c )
{
int i;
const float c = _c == 0 ? 1 / 2.9846f : 1 / _c;
for( i = 0; i < count; i++ )
{
w[i] = (float) exp( -d[i] * d[i] * c * c );
w[i] = (float) std::exp( -d[i] * d[i] * c * c );
}
}
/* Takes an array of 2D points, type of distance (including user-defined
distance specified by callbacks, fills the array of four floats with line
parameters A, B, C, D, where (A, B) is the normalized direction vector,
(C, D) is the point that belongs to the line. */
distance specified by callbacks, fills the array of four floats with line
parameters A, B, C, D, where (A, B) is the normalized direction vector,
(C, D) is the point that belongs to the line. */
static CvStatus icvFitLine2D( CvPoint2D32f * points, int count, int dist,
float _param, float reps, float aeps, float *line )
static void fitLine2D( const Point2f * points, int count, int dist,
float _param, float reps, float aeps, float *line )
{
double EPS = count*FLT_EPSILON;
void (*calc_weights) (float *, int, float *) = 0;
void (*calc_weights_param) (float *, int, float *, float) = 0;
float *w; /* weights */
float *r; /* square distances */
int i, j, k;
float _line[6], _lineprev[6];
float rdelta = reps != 0 ? reps : 1.0f;
float adelta = aeps != 0 ? aeps : 0.01f;
double min_err = DBL_MAX, err = 0;
CvRNG rng = cvRNG(-1);
RNG rng((uint64)-1);
memset( line, 0, 4*sizeof(line[0]) );
switch (dist)
{
case CV_DIST_L2:
return icvFitLine2D_wods( points, count, 0, line );
return fitLine2D_wods( points, count, 0, line );
case CV_DIST_L1:
calc_weights = icvWeightL1;
calc_weights = weightL1;
break;
case CV_DIST_L12:
calc_weights = icvWeightL12;
calc_weights = weightL12;
break;
case CV_DIST_FAIR:
calc_weights_param = icvWeightFair;
calc_weights_param = weightFair;
break;
case CV_DIST_WELSCH:
calc_weights_param = icvWeightWelsch;
calc_weights_param = weightWelsch;
break;
case CV_DIST_HUBER:
calc_weights_param = icvWeightHuber;
calc_weights_param = weightHuber;
break;
/*case CV_DIST_USER:
calc_weights = (void ( * )(float *, int, float *)) _PFP.fp;
break;*/
/*case DIST_USER:
calc_weights = (void ( * )(float *, int, float *)) _PFP.fp;
break;*/
default:
return CV_BADFACTOR_ERR;
CV_Error(CV_StsBadArg, "Unknown distance type");
}
w = (float *) cvAlloc( count * sizeof( float ));
r = (float *) cvAlloc( count * sizeof( float ));
AutoBuffer<float> wr(count*2);
float *w = wr, *r = w + count;
for( k = 0; k < 20; k++ )
{
@ -397,7 +370,7 @@ static CvStatus icvFitLine2D( CvPoint2D32f * points, int count, int dist,
for( i = 0; i < MIN(count,10); )
{
j = cvRandInt(&rng) % count;
j = rng.uniform(0, count);
if( w[j] < FLT_EPSILON )
{
w[j] = 1.f;
@ -405,7 +378,7 @@ static CvStatus icvFitLine2D( CvPoint2D32f * points, int count, int dist,
}
}
icvFitLine2D_wods( points, count, w, _line );
fitLine2D_wods( points, count, w, _line );
for( i = 0; i < 30; i++ )
{
double sum_w = 0;
@ -432,7 +405,7 @@ static CvStatus icvFitLine2D( CvPoint2D32f * points, int count, int dist,
}
}
/* calculate distances */
err = icvCalcDist2D( points, count, _line, r );
err = calcDist2D( points, count, _line, r );
if( err < EPS )
break;
@ -461,7 +434,7 @@ static CvStatus icvFitLine2D( CvPoint2D32f * points, int count, int dist,
memcpy( _lineprev, _line, 4 * sizeof( float ));
/* Run again... */
icvFitLine2D_wods( points, count, w, _line );
fitLine2D_wods( points, count, w, _line );
}
if( err < min_err )
@ -472,70 +445,57 @@ static CvStatus icvFitLine2D( CvPoint2D32f * points, int count, int dist,
break;
}
}
cvFree( &w );
cvFree( &r );
return CV_OK;
}
/* Takes an array of 3D points, type of distance (including user-defined
distance specified by callbacks, fills the array of four floats with line
parameters A, B, C, D, E, F, where (A, B, C) is the normalized direction vector,
(D, E, F) is the point that belongs to the line. */
static CvStatus
icvFitLine3D( CvPoint3D32f * points, int count, int dist,
float _param, float reps, float aeps, float *line )
distance specified by callbacks, fills the array of four floats with line
parameters A, B, C, D, E, F, where (A, B, C) is the normalized direction vector,
(D, E, F) is the point that belongs to the line. */
static void fitLine3D( Point3f * points, int count, int dist,
float _param, float reps, float aeps, float *line )
{
double EPS = count*FLT_EPSILON;
void (*calc_weights) (float *, int, float *) = 0;
void (*calc_weights_param) (float *, int, float *, float) = 0;
float *w; /* weights */
float *r; /* square distances */
int i, j, k;
float _line[6]={0,0,0,0,0,0}, _lineprev[6]={0,0,0,0,0,0};
float rdelta = reps != 0 ? reps : 1.0f;
float adelta = aeps != 0 ? aeps : 0.01f;
double min_err = DBL_MAX, err = 0;
CvRNG rng = cvRNG(-1);
RNG rng((uint64)-1);
switch (dist)
{
case CV_DIST_L2:
return icvFitLine3D_wods( points, count, 0, line );
return fitLine3D_wods( points, count, 0, line );
case CV_DIST_L1:
calc_weights = icvWeightL1;
calc_weights = weightL1;
break;
case CV_DIST_L12:
calc_weights = icvWeightL12;
calc_weights = weightL12;
break;
case CV_DIST_FAIR:
calc_weights_param = icvWeightFair;
calc_weights_param = weightFair;
break;
case CV_DIST_WELSCH:
calc_weights_param = icvWeightWelsch;
calc_weights_param = weightWelsch;
break;
case CV_DIST_HUBER:
calc_weights_param = icvWeightHuber;
calc_weights_param = weightHuber;
break;
/*case CV_DIST_USER:
_PFP.p = param;
calc_weights = (void ( * )(float *, int, float *)) _PFP.fp;
break;*/
default:
return CV_BADFACTOR_ERR;
CV_Error(CV_StsBadArg, "Unknown distance");
}
w = (float *) cvAlloc( count * sizeof( float ));
r = (float *) cvAlloc( count * sizeof( float ));
AutoBuffer<float> buf(count*2);
float *w = buf, *r = w + count;
for( k = 0; k < 20; k++ )
{
@ -545,7 +505,7 @@ icvFitLine3D( CvPoint3D32f * points, int count, int dist,
for( i = 0; i < MIN(count,10); )
{
j = cvRandInt(&rng) % count;
j = rng.uniform(0, count);
if( w[j] < FLT_EPSILON )
{
w[j] = 1.f;
@ -553,7 +513,7 @@ icvFitLine3D( CvPoint3D32f * points, int count, int dist,
}
}
icvFitLine3D_wods( points, count, w, _line );
fitLine3D_wods( points, count, w, _line );
for( i = 0; i < 30; i++ )
{
double sum_w = 0;
@ -587,8 +547,9 @@ icvFitLine3D( CvPoint3D32f * points, int count, int dist,
}
}
/* calculate distances */
if( icvCalcDist3D( points, count, _line, r ) < FLT_EPSILON*count )
break;
err = calcDist3D( points, count, _line, r );
//if( err < FLT_EPSILON*count )
// break;
/* calculate weights */
if( calc_weights )
@ -610,14 +571,14 @@ icvFitLine3D( CvPoint3D32f * points, int count, int dist,
for( j = 0; j < count; j++ )
w[j] = 1.f;
}
/* save the line parameters */
memcpy( _lineprev, _line, 6 * sizeof( float ));
/* Run again... */
icvFitLine3D_wods( points, count, w, _line );
fitLine3D_wods( points, count, w, _line );
}
if( err < min_err )
{
min_err = err;
@ -626,11 +587,36 @@ icvFitLine3D( CvPoint3D32f * points, int count, int dist,
break;
}
}
}
// Return...
cvFree( &w );
cvFree( &r );
return CV_OK;
}
void cv::fitLine( InputArray _points, OutputArray _line, int distType,
double param, double reps, double aeps )
{
Mat points = _points.getMat();
float linebuf[6]={0.f};
int npoints2 = points.checkVector(2, -1, false);
int npoints3 = points.checkVector(3, -1, false);
CV_Assert( npoints2 >= 0 || npoints3 >= 0 );
if( points.depth() != CV_32F || !points.isContinuous() )
{
Mat temp;
points.convertTo(temp, CV_32F);
points = temp;
}
if( npoints2 >= 0 )
fitLine2D( points.ptr<Point2f>(), npoints2, distType,
(float)param, (float)reps, (float)aeps, linebuf);
else
fitLine3D( points.ptr<Point3f>(), npoints3, distType,
(float)param, (float)reps, (float)aeps, linebuf);
Mat(npoints2 >= 0 ? 4 : 6, 1, CV_32F, linebuf).copyTo(_line);
}
@ -638,82 +624,13 @@ CV_IMPL void
cvFitLine( const CvArr* array, int dist, double param,
double reps, double aeps, float *line )
{
cv::AutoBuffer<schar> buffer;
CV_Assert(line != 0);
schar* points = 0;
union { CvContour contour; CvSeq seq; } header;
CvSeqBlock block;
CvSeq* ptseq = (CvSeq*)array;
int type;
cv::AutoBuffer<double> buf;
cv::Mat points = cv::cvarrToMat(array, false, false, 0, &buf);
cv::Mat linemat(points.checkVector(2) >= 0 ? 4 : 6, 1, CV_32F, line);
if( !line )
CV_Error( CV_StsNullPtr, "NULL pointer to line parameters" );
if( CV_IS_SEQ(ptseq) )
{
type = CV_SEQ_ELTYPE(ptseq);
if( ptseq->total == 0 )
CV_Error( CV_StsBadSize, "The sequence has no points" );
if( (type!=CV_32FC2 && type!=CV_32FC3 && type!=CV_32SC2 && type!=CV_32SC3) ||
CV_ELEM_SIZE(type) != ptseq->elem_size )
CV_Error( CV_StsUnsupportedFormat,
"Input sequence must consist of 2d points or 3d points" );
}
else
{
CvMat* mat = (CvMat*)array;
type = CV_MAT_TYPE(mat->type);
if( !CV_IS_MAT(mat))
CV_Error( CV_StsBadArg, "Input array is not a sequence nor matrix" );
if( !CV_IS_MAT_CONT(mat->type) ||
(type!=CV_32FC2 && type!=CV_32FC3 && type!=CV_32SC2 && type!=CV_32SC3) ||
(mat->width != 1 && mat->height != 1))
CV_Error( CV_StsBadArg,
"Input array must be 1d continuous array of 2d or 3d points" );
ptseq = cvMakeSeqHeaderForArray(
CV_SEQ_KIND_GENERIC|type, sizeof(CvContour), CV_ELEM_SIZE(type), mat->data.ptr,
mat->width + mat->height - 1, &header.seq, &block );
}
if( reps < 0 || aeps < 0 )
CV_Error( CV_StsOutOfRange, "Both reps and aeps must be non-negative" );
if( CV_MAT_DEPTH(type) == CV_32F && ptseq->first->next == ptseq->first )
{
/* no need to copy data in this case */
points = ptseq->first->data;
}
else
{
buffer.allocate(ptseq->total*CV_ELEM_SIZE(type));
points = buffer;
cvCvtSeqToArray( ptseq, points, CV_WHOLE_SEQ );
if( CV_MAT_DEPTH(type) != CV_32F )
{
int i, total = ptseq->total*CV_MAT_CN(type);
assert( CV_MAT_DEPTH(type) == CV_32S );
for( i = 0; i < total; i++ )
((float*)points)[i] = (float)((int*)points)[i];
}
}
if( dist == CV_DIST_USER )
CV_Error( CV_StsBadArg, "User-defined distance is not allowed" );
if( CV_MAT_CN(type) == 2 )
{
IPPI_CALL( icvFitLine2D( (CvPoint2D32f*)points, ptseq->total,
dist, (float)param, (float)reps, (float)aeps, line ));
}
else
{
IPPI_CALL( icvFitLine3D( (CvPoint3D32f*)points, ptseq->total,
dist, (float)param, (float)reps, (float)aeps, line ));
}
cv::fitLine(points, linemat, dist, param, reps, aeps);
}
/* End of file. */

View File

@ -40,159 +40,122 @@
//M*/
#include "precomp.hpp"
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvMatchContours
// 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*/ )
double cv::matchShapes(InputArray contour1, InputArray contour2, int method, double)
{
CvMoments moments;
CvHuMoments huMoments;
double ma[7], mb[7];
int i, sma, smb;
double eps = 1.e-5;
double mmm;
double result = 0;
if( !contour1 || !contour2 )
CV_Error( CV_StsNullPtr, "" );
// 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;
HuMoments( moments(contour1), ma );
HuMoments( moments(contour2), mb );
switch (method)
{
case 1:
for( i = 0; i < 7; i++ )
{
for( i = 0; i < 7; i++ )
double ama = fabs( ma[i] );
double amb = fabs( mb[i] );
if( ma[i] > 0 )
sma = 1;
else if( ma[i] < 0 )
sma = -1;
else
sma = 0;
if( mb[i] > 0 )
smb = 1;
else if( mb[i] < 0 )
smb = -1;
else
smb = 0;
if( ama > eps && amb > eps )
{
double ama = fabs( ma[i] );
double amb = fabs( mb[i] );
if( ma[i] > 0 )
sma = 1;
else if( ma[i] < 0 )
sma = -1;
else
sma = 0;
if( mb[i] > 0 )
smb = 1;
else if( mb[i] < 0 )
smb = -1;
else
smb = 0;
if( ama > eps && amb > eps )
{
ama = 1. / (sma * log10( ama ));
amb = 1. / (smb * log10( amb ));
result += fabs( -ama + amb );
}
ama = 1. / (sma * log10( ama ));
amb = 1. / (smb * log10( amb ));
result += fabs( -ama + amb );
}
break;
}
break;
case 2:
for( i = 0; i < 7; i++ )
{
for( i = 0; i < 7; i++ )
double ama = fabs( ma[i] );
double amb = fabs( mb[i] );
if( ma[i] > 0 )
sma = 1;
else if( ma[i] < 0 )
sma = -1;
else
sma = 0;
if( mb[i] > 0 )
smb = 1;
else if( mb[i] < 0 )
smb = -1;
else
smb = 0;
if( ama > eps && amb > eps )
{
double ama = fabs( ma[i] );
double amb = fabs( mb[i] );
if( ma[i] > 0 )
sma = 1;
else if( ma[i] < 0 )
sma = -1;
else
sma = 0;
if( mb[i] > 0 )
smb = 1;
else if( mb[i] < 0 )
smb = -1;
else
smb = 0;
if( ama > eps && amb > eps )
{
ama = sma * log10( ama );
amb = smb * log10( amb );
result += fabs( -ama + amb );
}
ama = sma * log10( ama );
amb = smb * log10( amb );
result += fabs( -ama + amb );
}
break;
}
break;
case 3:
for( i = 0; i < 7; i++ )
{
for( i = 0; i < 7; i++ )
double ama = fabs( ma[i] );
double amb = fabs( mb[i] );
if( ma[i] > 0 )
sma = 1;
else if( ma[i] < 0 )
sma = -1;
else
sma = 0;
if( mb[i] > 0 )
smb = 1;
else if( mb[i] < 0 )
smb = -1;
else
smb = 0;
if( ama > eps && amb > eps )
{
double ama = fabs( ma[i] );
double amb = fabs( mb[i] );
if( ma[i] > 0 )
sma = 1;
else if( ma[i] < 0 )
sma = -1;
else
sma = 0;
if( mb[i] > 0 )
smb = 1;
else if( mb[i] < 0 )
smb = -1;
else
smb = 0;
if( ama > eps && amb > eps )
{
ama = sma * log10( ama );
amb = smb * log10( amb );
mmm = fabs( (ama - amb) / ama );
if( result < mmm )
result = mmm;
}
ama = sma * log10( ama );
amb = smb * log10( amb );
mmm = fabs( (ama - amb) / ama );
if( result < mmm )
result = mmm;
}
break;
}
break;
default:
CV_Error( CV_StsBadArg, "Unknown comparison method" );
}
return result;
}
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. */

View File

@ -7,7 +7,7 @@
// copy or use the software.
//
//
// Intel License Agreement
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
@ -23,13 +23,13 @@
// this list of conditions and the following disclaimer in the documentation
// 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.
//
// 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
// 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
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
@ -40,7 +40,10 @@
//M*/
#include "precomp.hpp"
typedef struct
namespace cv
{
struct MinAreaState
{
int bottom;
int left;
@ -48,61 +51,58 @@ typedef struct
float width;
float base_a;
float base_b;
}
icvMinAreaState;
};
#define CV_CALIPERS_MAXHEIGHT 0
#define CV_CALIPERS_MINAREARECT 1
#define CV_CALIPERS_MAXDIST 2
enum { CALIPERS_MAXHEIGHT=0, CALIPERS_MINAREARECT=1, CALIPERS_MAXDIST=2 };
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvRotatingCalipers
// Purpose:
// Rotating calipers algorithm with some applications
//
// Context:
// Parameters:
// points - convex hull vertices ( any orientation )
// n - number of vertices
// mode - concrete application of algorithm
// can be CV_CALIPERS_MAXDIST or
// CV_CALIPERS_MINAREARECT
// left, bottom, right, top - indexes of extremal points
// out - output info.
// In case CV_CALIPERS_MAXDIST it points to float value -
// maximal height of polygon.
// In case CV_CALIPERS_MINAREARECT
// ((CvPoint2D32f*)out)[0] - corner
// ((CvPoint2D32f*)out)[1] - vector1
// ((CvPoint2D32f*)out)[0] - corner2
//
// ^
// |
// vector2 |
// |
// |____________\
// corner /
// vector1
//
// Returns:
// Notes:
//F*/
// Name: rotatingCalipers
// Purpose:
// Rotating calipers algorithm with some applications
//
// Context:
// Parameters:
// points - convex hull vertices ( any orientation )
// n - number of vertices
// mode - concrete application of algorithm
// can be CV_CALIPERS_MAXDIST or
// CV_CALIPERS_MINAREARECT
// left, bottom, right, top - indexes of extremal points
// out - output info.
// In case CV_CALIPERS_MAXDIST it points to float value -
// maximal height of polygon.
// In case CV_CALIPERS_MINAREARECT
// ((CvPoint2D32f*)out)[0] - corner
// ((CvPoint2D32f*)out)[1] - vector1
// ((CvPoint2D32f*)out)[0] - corner2
//
// ^
// |
// vector2 |
// |
// |____________\
// corner /
// vector1
//
// Returns:
// Notes:
//F*/
/* we will use usual cartesian coordinates */
static void
icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
static void rotatingCalipers( const Point2f* points, int n, int mode, float* out )
{
float minarea = FLT_MAX;
float max_dist = 0;
char buffer[32] = {};
int i, k;
CvPoint2D32f* vect = (CvPoint2D32f*)cvAlloc( n * sizeof(vect[0]) );
float* inv_vect_length = (float*)cvAlloc( n * sizeof(inv_vect_length[0]) );
AutoBuffer<float> abuf(n*3);
float* inv_vect_length = abuf;
Point2f* vect = (Point2f*)(inv_vect_length + n);
int left = 0, bottom = 0, right = 0, top = 0;
int seq[4] = { -1, -1, -1, -1 };
/* rotating calipers sides will always have coordinates
(a,b) (-b,a) (-a,-b) (b, -a)
(a,b) (-b,a) (-a,-b) (b, -a)
*/
/* this is a first base bector (a,b) initialized by (1,0) */
float orientation = 0;
@ -110,7 +110,7 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
float base_b = 0;
float left_x, right_x, top_y, bottom_y;
CvPoint2D32f pt0 = points[0];
Point2f pt0 = points[0];
left_x = right_x = pt0.x;
top_y = bottom_y = pt0.y;
@ -131,7 +131,7 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
if( pt0.y < bottom_y )
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;
dy = pt.y - pt0.y;
@ -143,9 +143,7 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
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 ay = vect[n-1].y;
@ -165,18 +163,18 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
ax = bx;
ay = by;
}
assert( orientation != 0 );
CV_Assert( orientation != 0 );
}
base_a = orientation;
/*****************************************************************************************/
/* init calipers position */
/*****************************************************************************************/
/* init calipers position */
seq[0] = bottom;
seq[1] = right;
seq[2] = top;
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 */
for( k = 0; k < n; k++ )
@ -229,190 +227,140 @@ icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
base_a = -lead_y;
base_b = lead_x;
break;
default: assert(0);
default:
CV_Error(CV_StsError, "main_element should be 0, 1, 2 or 3");
}
}
/* change base point of main edge */
seq[main_element] += 1;
seq[main_element] = (seq[main_element] == n) ? 0 : seq[main_element];
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 */
/* find opposite element i.e. transform */
/* 0->2, 1->3, 2->0, 3->1 */
int opposite_el = main_element ^ 2;
/* find opposite element i.e. transform */
/* 0->2, 1->3, 2->0, 3->1 */
int opposite_el = main_element ^ 2;
float dx = points[seq[opposite_el]].x - points[seq[main_element]].x;
float dy = points[seq[opposite_el]].y - points[seq[main_element]].y;
float dist;
float dx = points[seq[opposite_el]].x - points[seq[main_element]].x;
float dy = points[seq[opposite_el]].y - points[seq[main_element]].y;
float dist;
if( main_element & 1 )
dist = (float)fabs(dx * base_a + dy * base_b);
else
dist = (float)fabs(dx * (-base_b) + dy * base_a);
if( main_element & 1 )
dist = (float)fabs(dx * base_a + dy * base_b);
else
dist = (float)fabs(dx * (-base_b) + dy * base_a);
if( dist > max_dist )
max_dist = dist;
break;
if( dist > max_dist )
max_dist = dist;
}
case CV_CALIPERS_MINAREARECT:
break;
case CALIPERS_MINAREARECT:
/* find area of rectangle */
{
float height;
float area;
float height;
float area;
/* find vector left-right */
float dx = points[seq[1]].x - points[seq[3]].x;
float dy = points[seq[1]].y - points[seq[3]].y;
/* find vector left-right */
float dx = points[seq[1]].x - points[seq[3]].x;
float dy = points[seq[1]].y - points[seq[3]].y;
/* dotproduct */
float width = dx * base_a + dy * base_b;
/* dotproduct */
float width = dx * base_a + dy * base_b;
/* find vector left-right */
dx = points[seq[2]].x - points[seq[0]].x;
dy = points[seq[2]].y - points[seq[0]].y;
/* find vector left-right */
dx = points[seq[2]].x - points[seq[0]].x;
dy = points[seq[2]].y - points[seq[0]].y;
/* dotproduct */
height = -dx * base_b + dy * base_a;
/* dotproduct */
height = -dx * base_b + dy * base_a;
area = width * height;
if( area <= minarea )
{
float *buf = (float *) buffer;
area = width * height;
if( area <= minarea )
{
float *buf = (float *) buffer;
minarea = area;
/* leftist point */
((int *) buf)[0] = seq[3];
buf[1] = base_a;
buf[2] = width;
buf[3] = base_b;
buf[4] = height;
/* bottom point */
((int *) buf)[5] = seq[0];
buf[6] = area;
}
break;
minarea = area;
/* leftist point */
((int *) buf)[0] = seq[3];
buf[1] = base_a;
buf[2] = width;
buf[3] = base_b;
buf[4] = height;
/* bottom point */
((int *) buf)[5] = seq[0];
buf[6] = area;
}
}
break;
} /*switch */
} /* for */
switch (mode)
{
case CV_CALIPERS_MINAREARECT:
case CALIPERS_MINAREARECT:
{
float *buf = (float *) buffer;
float *buf = (float *) buffer;
float A1 = buf[1];
float B1 = buf[3];
float A1 = buf[1];
float B1 = buf[3];
float A2 = -buf[3];
float B2 = buf[1];
float A2 = -buf[3];
float B2 = buf[1];
float C1 = A1 * points[((int *) buf)[0]].x + points[((int *) buf)[0]].y * B1;
float C2 = A2 * points[((int *) buf)[5]].x + points[((int *) buf)[5]].y * B2;
float C1 = A1 * points[((int *) buf)[0]].x + points[((int *) buf)[0]].y * B1;
float C2 = A2 * points[((int *) buf)[5]].x + points[((int *) buf)[5]].y * B2;
float idet = 1.f / (A1 * B2 - A2 * B1);
float idet = 1.f / (A1 * B2 - A2 * B1);
float px = (C1 * B2 - C2 * B1) * idet;
float py = (A1 * C2 - A2 * C1) * idet;
float px = (C1 * B2 - C2 * B1) * idet;
float py = (A1 * C2 - A2 * C1) * idet;
out[0] = px;
out[1] = py;
out[2] = A1 * buf[2];
out[3] = B1 * buf[2];
out[4] = A2 * buf[4];
out[5] = B2 * buf[4];
out[0] = px;
out[1] = py;
out[2] = A1 * buf[2];
out[3] = B1 * buf[2];
out[4] = A2 * buf[4];
out[5] = B2 * buf[4];
}
break;
case CV_CALIPERS_MAXHEIGHT:
case CALIPERS_MAXHEIGHT:
{
out[0] = max_dist;
out[0] = max_dist;
}
break;
}
cvFree( &vect );
cvFree( &inv_vect_length );
}
}
CV_IMPL CvBox2D
cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
cv::RotatedRect cv::minAreaRect( InputArray _points )
{
cv::Ptr<CvMemStorage> temp_storage;
CvBox2D box;
cv::AutoBuffer<CvPoint2D32f> _points;
CvPoint2D32f* points;
memset(&box, 0, sizeof(box));
int i, n;
CvSeqReader reader;
CvContour contour_header;
CvSeqBlock block;
CvSeq* ptseq = (CvSeq*)array;
CvPoint2D32f out[3];
if( CV_IS_SEQ(ptseq) )
Mat hull;
Point2f out[3];
RotatedRect box;
convexHull(_points, hull, true, true);
if( hull.depth() != CV_32F )
{
if( !CV_IS_SEQ_POINT_SET(ptseq) &&
(CV_SEQ_KIND(ptseq) != CV_SEQ_KIND_CURVE ||
CV_SEQ_ELTYPE(ptseq) != CV_SEQ_ELTYPE_PPOINT ))
CV_Error( CV_StsUnsupportedFormat,
"Input sequence must consist of 2d points or pointers to 2d points" );
if( !storage )
storage = ptseq->storage;
Mat temp;
hull.convertTo(temp, CV_32F);
hull = temp;
}
else
{
ptseq = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block );
}
if( storage )
{
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 );
}
}
int n = hull.checkVector(2);
const Point2f* hpoints = (const Point2f*)hull.data;
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.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);
@ -421,10 +369,10 @@ cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
}
else if( n == 2 )
{
box.center.x = (points[0].x + points[1].x)*0.5f;
box.center.y = (points[0].y + points[1].y)*0.5f;
double dx = points[1].x - points[0].x;
double dy = points[1].y - points[0].y;
box.center.x = (hpoints[0].x + hpoints[1].x)*0.5f;
box.center.y = (hpoints[0].y + hpoints[1].y)*0.5f;
double dx = hpoints[1].x - hpoints[0].x;
double dy = hpoints[1].y - hpoints[0].y;
box.size.width = (float)sqrt(dx*dx + dy*dy);
box.size.height = 0;
box.angle = (float)atan2( dy, dx );
@ -432,10 +380,21 @@ cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
else
{
if( n == 1 )
box.center = points[0];
box.center = hpoints[0];
}
box.angle = (float)(box.angle*180/CV_PI);
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

View File

@ -395,8 +395,8 @@ FarnebackUpdateFlow_GaussianBlur( const Mat& _R0, const Mat& _R1,
double sigma = m*0.3, s = 1;
AutoBuffer<float> _vsum((width+m*2+2)*5 + 16), _hsum(width*5 + 16);
AutoBuffer<float, 4096> _kernel((m+1)*5 + 16);
AutoBuffer<float*, 1024> _srow(m*2+1);
AutoBuffer<float> _kernel((m+1)*5 + 16);
AutoBuffer<float*> _srow(m*2+1);
float *vsum = alignPtr((float*)_vsum + (m+1)*5, 16), *hsum = alignPtr((float*)_hsum, 16);
float* kernel = (float*)_kernel;
const float** srow = (const float**)&_srow[0];

View File

@ -13,7 +13,7 @@ static void help()
"Random points are generated and then enclosed.\n"
"Call:\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*/ )