mirror of
https://github.com/opencv/opencv.git
synced 2024-11-28 13:10:12 +08:00
refactored approxpoly
This commit is contained in:
parent
867ddebe07
commit
e3941d0965
@ -3107,6 +3107,10 @@ public:
|
|||||||
void allocate(size_t _size);
|
void allocate(size_t _size);
|
||||||
//! deallocates the buffer if it was dynamically allocated
|
//! deallocates the buffer if it was dynamically allocated
|
||||||
void deallocate();
|
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
|
//! returns pointer to the real buffer, stack-allocated or head-allocated
|
||||||
operator _Tp* ();
|
operator _Tp* ();
|
||||||
//! returns read-only pointer to the real buffer, stack-allocated or head-allocated
|
//! returns read-only pointer to the real buffer, stack-allocated or head-allocated
|
||||||
@ -3116,7 +3120,7 @@ protected:
|
|||||||
//! pointer to the real buffer, can point to buf if the buffer is small enough
|
//! pointer to the real buffer, can point to buf if the buffer is small enough
|
||||||
_Tp* ptr;
|
_Tp* ptr;
|
||||||
//! size of the real buffer
|
//! size of the real buffer
|
||||||
size_t size;
|
size_t sz;
|
||||||
//! pre-allocated buffer
|
//! pre-allocated buffer
|
||||||
_Tp buf[fixed_size+buffer_padding];
|
_Tp buf[fixed_size+buffer_padding];
|
||||||
};
|
};
|
||||||
|
@ -2537,13 +2537,13 @@ inline Point LineIterator::pos() const
|
|||||||
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;
|
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;
|
ptr = buf;
|
||||||
size = fixed_size;
|
sz = fixed_size;
|
||||||
allocate(_size);
|
allocate(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2552,13 +2552,16 @@ template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::~A
|
|||||||
|
|
||||||
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;
|
return;
|
||||||
|
}
|
||||||
deallocate();
|
deallocate();
|
||||||
if(_size > fixed_size)
|
if(_size > fixed_size)
|
||||||
{
|
{
|
||||||
ptr = cv::allocate<_Tp>(_size);
|
ptr = new _Tp[_size];
|
||||||
size = _size;
|
sz = _size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2566,12 +2569,38 @@ template<typename _Tp, size_t fixed_size> inline void AutoBuffer<_Tp, fixed_size
|
|||||||
{
|
{
|
||||||
if( ptr != buf )
|
if( ptr != buf )
|
||||||
{
|
{
|
||||||
cv::deallocate<_Tp>(ptr, size);
|
delete[] ptr;
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
size = fixed_size;
|
sz = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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* ()
|
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::operator _Tp* ()
|
||||||
{ return ptr; }
|
{ return ptr; }
|
||||||
|
|
||||||
|
@ -469,48 +469,59 @@ cvApproxChains( CvSeq* src_seq,
|
|||||||
|
|
||||||
/* Ramer-Douglas-Peucker algorithm for polygon simplification */
|
/* Ramer-Douglas-Peucker algorithm for polygon simplification */
|
||||||
|
|
||||||
/* the version for integer point coordinates */
|
namespace cv
|
||||||
template<typename T> static CvSeq*
|
|
||||||
icvApproxPolyDP( CvSeq* src_contour, int header_size,
|
|
||||||
CvMemStorage* storage, double eps )
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
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;
|
typedef cv::Point_<T> PT;
|
||||||
int init_iters = 3;
|
int init_iters = 3;
|
||||||
CvSlice slice = {0, 0}, right_slice = {0, 0};
|
Range slice(0, 0), right_slice(0, 0);
|
||||||
CvSeqReader reader, reader2;
|
PT start_pt((T)-1000000, (T)-1000000), end_pt(0, 0), pt(0,0);
|
||||||
CvSeqWriter writer;
|
int i = 0, j, pos = 0, wpos, count = count0, new_count=0;
|
||||||
PT start_pt(-1000000, -1000000), end_pt(0, 0), pt(0,0);
|
int is_closed = is_closed0;
|
||||||
int i = 0, j, count = src_contour->total, new_count;
|
|
||||||
int is_closed = CV_IS_SEQ_CLOSED( src_contour );
|
|
||||||
bool le_eps = false;
|
bool le_eps = false;
|
||||||
CvMemStorage* temp_storage = 0;
|
size_t top = 0, stacksz = _stack->size();
|
||||||
CvSeq* stack = 0;
|
Range* stack = *_stack;
|
||||||
CvSeq* dst_contour;
|
|
||||||
|
|
||||||
assert( CV_SEQ_ELTYPE(src_contour) == cv::DataType<PT>::type );
|
if( count == 0 )
|
||||||
cvStartWriteSeq( src_contour->flags, header_size, sizeof(pt), storage, &writer );
|
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;
|
eps *= eps;
|
||||||
cvStartReadSeq( src_contour, &reader, 0 );
|
|
||||||
|
|
||||||
if( !is_closed )
|
if( !is_closed )
|
||||||
{
|
{
|
||||||
right_slice.start_index = count;
|
right_slice.start = count;
|
||||||
end_pt = *(PT*)(reader.ptr);
|
end_pt = src_contour[0];
|
||||||
start_pt = *(PT*)cvGetSeqElem( src_contour, -1 );
|
start_pt = src_contour[count-1];
|
||||||
|
|
||||||
if( start_pt.x != end_pt.x || start_pt.y != end_pt.y )
|
if( start_pt.x != end_pt.x || start_pt.y != end_pt.y )
|
||||||
{
|
{
|
||||||
slice.start_index = 0;
|
slice.start = 0;
|
||||||
slice.end_index = count - 1;
|
slice.end = count - 1;
|
||||||
cvSeqPush( stack, &slice );
|
PUSH_SLICE(slice);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -521,20 +532,20 @@ icvApproxPolyDP( CvSeq* src_contour, int header_size,
|
|||||||
|
|
||||||
if( is_closed )
|
if( is_closed )
|
||||||
{
|
{
|
||||||
/* 1. Find approximately two farthest points of the contour */
|
// 1. Find approximately two farthest points of the contour
|
||||||
right_slice.start_index = 0;
|
right_slice.start = 0;
|
||||||
|
|
||||||
for( i = 0; i < init_iters; i++ )
|
for( i = 0; i < init_iters; i++ )
|
||||||
{
|
{
|
||||||
double dist, max_dist = 0;
|
double dist, max_dist = 0;
|
||||||
cvSetSeqReaderPos( &reader, right_slice.start_index, 1 );
|
pos = (pos + right_slice.start) % count;
|
||||||
CV_READ_SEQ_ELEM( start_pt, reader ); /* read the first point */
|
READ_PT(start_pt, pos);
|
||||||
|
|
||||||
for( j = 1; j < count; j++ )
|
for( j = 1; j < count; j++ )
|
||||||
{
|
{
|
||||||
double dx, dy;
|
double dx, dy;
|
||||||
|
|
||||||
CV_READ_SEQ_ELEM( pt, reader );
|
READ_PT(pt, pos);
|
||||||
dx = pt.x - start_pt.x;
|
dx = pt.x - start_pt.x;
|
||||||
dy = pt.y - start_pt.y;
|
dy = pt.y - start_pt.y;
|
||||||
|
|
||||||
@ -543,43 +554,35 @@ icvApproxPolyDP( CvSeq* src_contour, int header_size,
|
|||||||
if( dist > max_dist )
|
if( dist > max_dist )
|
||||||
{
|
{
|
||||||
max_dist = dist;
|
max_dist = dist;
|
||||||
right_slice.start_index = j;
|
right_slice.start = j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
le_eps = max_dist <= eps;
|
le_eps = max_dist <= eps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. initialize the stack */
|
// 2. initialize the stack
|
||||||
if( !le_eps )
|
if( !le_eps )
|
||||||
{
|
{
|
||||||
slice.start_index = cvGetSeqReaderPos( &reader );
|
right_slice.end = slice.start = pos % count;
|
||||||
slice.end_index = right_slice.start_index += slice.start_index;
|
slice.end = right_slice.start = (right_slice.start + slice.start) % count;
|
||||||
|
|
||||||
right_slice.start_index -= right_slice.start_index >= count ? count : 0;
|
PUSH_SLICE(right_slice);
|
||||||
right_slice.end_index = slice.start_index;
|
PUSH_SLICE(slice);
|
||||||
if( right_slice.end_index < right_slice.start_index )
|
|
||||||
right_slice.end_index += count;
|
|
||||||
|
|
||||||
cvSeqPush( stack, &right_slice );
|
|
||||||
cvSeqPush( stack, &slice );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CV_WRITE_SEQ_ELEM( start_pt, writer );
|
WRITE_PT(start_pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3. run recursive process */
|
// 3. run recursive process
|
||||||
while( stack->total != 0 )
|
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 );
|
if( pos != slice.end )
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
double dx, dy, dist, max_dist = 0;
|
double dx, dy, dist, max_dist = 0;
|
||||||
|
|
||||||
@ -588,15 +591,15 @@ icvApproxPolyDP( CvSeq* src_contour, int header_size,
|
|||||||
|
|
||||||
assert( dx != 0 || dy != 0 );
|
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);
|
dist = fabs((pt.y - start_pt.y) * dx - (pt.x - start_pt.x) * dy);
|
||||||
|
|
||||||
if( dist > max_dist )
|
if( dist > max_dist )
|
||||||
{
|
{
|
||||||
max_dist = 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
|
else
|
||||||
{
|
{
|
||||||
assert( slice.end_index > slice.start_index );
|
|
||||||
le_eps = true;
|
le_eps = true;
|
||||||
/* read starting point */
|
// read starting point
|
||||||
cvSetSeqReaderPos( &reader, slice.start_index );
|
start_pt = src_contour[slice.start];
|
||||||
CV_READ_SEQ_ELEM( start_pt, reader );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( le_eps )
|
if( le_eps )
|
||||||
{
|
{
|
||||||
CV_WRITE_SEQ_ELEM( start_pt, writer );
|
WRITE_PT(start_pt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
right_slice.end_index = slice.end_index;
|
right_slice.end = slice.end;
|
||||||
slice.end_index = right_slice.start_index;
|
slice.end = right_slice.start;
|
||||||
cvSeqPush( stack, &right_slice );
|
PUSH_SLICE(right_slice);
|
||||||
cvSeqPush( stack, &slice );
|
PUSH_SLICE(slice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is_closed = CV_IS_SEQ_CLOSED( src_contour );
|
|
||||||
if( !is_closed )
|
if( !is_closed )
|
||||||
CV_WRITE_SEQ_ELEM( end_pt, writer );
|
WRITE_PT( src_contour[count-1] );
|
||||||
|
|
||||||
dst_contour = cvEndWriteSeq( &writer );
|
|
||||||
|
|
||||||
// last stage: do final clean-up of the approximated contour -
|
// last stage: do final clean-up of the approximated contour -
|
||||||
// remove extra points on the [almost] stright lines.
|
// 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++ )
|
for( i = !is_closed; i < count - !is_closed && new_count > 2; i++ )
|
||||||
{
|
{
|
||||||
double dx, dy, dist, successive_inner_product;
|
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;
|
dx = end_pt.x - start_pt.x;
|
||||||
dy = end_pt.y - start_pt.y;
|
dy = end_pt.y - start_pt.y;
|
||||||
dist = fabs((pt.x - start_pt.x)*dy - (pt.y - start_pt.y)*dx);
|
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) +
|
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 &&
|
if( dist * dist <= 0.5*eps*(dx*dx + dy*dy) && dx != 0 && dy != 0 &&
|
||||||
successive_inner_product >= 0 )
|
successive_inner_product >= 0 )
|
||||||
{
|
{
|
||||||
new_count--;
|
new_count--;
|
||||||
*((PT*)reader2.ptr) = start_pt = end_pt;
|
dst_contour[wpos] = start_pt = end_pt;
|
||||||
CV_NEXT_SEQ_ELEM( sizeof(pt), reader2 );
|
if(++wpos >= count) wpos = 0;
|
||||||
CV_READ_SEQ_ELEM( pt, reader );
|
READ_DST_PT(pt, pos);
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*((PT*)reader2.ptr) = start_pt = pt;
|
dst_contour[wpos] = start_pt = pt;
|
||||||
CV_NEXT_SEQ_ELEM( sizeof(pt), reader2 );
|
if(++wpos >= count) wpos = 0;
|
||||||
pt = end_pt;
|
pt = end_pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !is_closed )
|
if( !is_closed )
|
||||||
*((PT*)reader2.ptr) = pt;
|
dst_contour[wpos] = pt;
|
||||||
|
|
||||||
if( new_count < count )
|
return new_count;
|
||||||
cvSeqPopMulti( dst_contour, 0, count - 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*
|
CV_IMPL CvSeq*
|
||||||
cvApproxPoly( const void* array, int header_size,
|
cvApproxPoly( const void* array, int header_size,
|
||||||
CvMemStorage* storage, int method,
|
CvMemStorage* storage, int method,
|
||||||
double parameter, int parameter2 )
|
double parameter, int parameter2 )
|
||||||
{
|
{
|
||||||
|
cv::AutoBuffer<cv::Point> _buf;
|
||||||
|
cv::AutoBuffer<cv::Range> stack(100);
|
||||||
CvSeq* dst_seq = 0;
|
CvSeq* dst_seq = 0;
|
||||||
CvSeq *prev_contour = 0, *parent = 0;
|
CvSeq *prev_contour = 0, *parent = 0;
|
||||||
CvContour contour_header;
|
CvContour contour_header;
|
||||||
@ -703,8 +728,8 @@ cvApproxPoly( const void* array, int header_size,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
src_seq = cvPointSeqFromMat(
|
src_seq = cvPointSeqFromMat(
|
||||||
CV_SEQ_KIND_CURVE | (parameter2 ? CV_SEQ_FLAG_CLOSED : 0),
|
CV_SEQ_KIND_CURVE | (parameter2 ? CV_SEQ_FLAG_CLOSED : 0),
|
||||||
array, &contour_header, &block );
|
array, &contour_header, &block );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !storage )
|
if( !storage )
|
||||||
@ -712,7 +737,7 @@ cvApproxPoly( const void* array, int header_size,
|
|||||||
|
|
||||||
if( header_size < 0 )
|
if( header_size < 0 )
|
||||||
CV_Error( CV_StsOutOfRange, "header_size is negative. "
|
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 )
|
if( header_size == 0 )
|
||||||
header_size = src_seq->header_size;
|
header_size = src_seq->header_size;
|
||||||
@ -722,7 +747,7 @@ cvApproxPoly( const void* array, int header_size,
|
|||||||
if( CV_IS_SEQ_CHAIN( src_seq ))
|
if( CV_IS_SEQ_CHAIN( src_seq ))
|
||||||
{
|
{
|
||||||
CV_Error( CV_StsBadArg, "Input curves are not polygonal. "
|
CV_Error( CV_StsBadArg, "Input curves are not polygonal. "
|
||||||
"Use cvApproxChains first" );
|
"Use cvApproxChains first" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -749,13 +774,34 @@ cvApproxPoly( const void* array, int header_size,
|
|||||||
if( parameter < 0 )
|
if( parameter < 0 )
|
||||||
CV_Error( CV_StsOutOfRange, "Accuracy must be non-negative" );
|
CV_Error( CV_StsOutOfRange, "Accuracy must be non-negative" );
|
||||||
|
|
||||||
if( CV_SEQ_ELTYPE(src_seq) == CV_32SC2 )
|
CV_Assert( CV_SEQ_ELTYPE(src_seq) == CV_32SC2 ||
|
||||||
contour = icvApproxPolyDP<int>( src_seq, header_size, storage, parameter );
|
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
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
|
||||||
CV_Error( CV_StsBadArg, "Invalid approximation method" );
|
CV_Error( CV_StsBadArg, "Invalid approximation method" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1753,23 +1753,6 @@ void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours,
|
|||||||
findContours(_image, _contours, noArray(), mode, method, offset);
|
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 )
|
double cv::arcLength( InputArray _curve, bool closed )
|
||||||
{
|
{
|
||||||
Mat curve = _curve.getMat();
|
Mat curve = _curve.getMat();
|
||||||
|
Loading…
Reference in New Issue
Block a user