Return drawContours back to imgproc

This partly reverts commit 6ca618277c.
This commit is contained in:
Andrey Kamaev
2012-10-15 18:12:33 +04:00
parent dbd30d4fba
commit 58f31819cc
6 changed files with 299 additions and 300 deletions

View File

@@ -483,88 +483,6 @@ Draws several polygonal curves.
The function ``polylines`` draws one or more polygonal curves.
drawContours
----------------
Draws contours outlines or filled contours.
.. ocv:function:: void drawContours( InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )
.. ocv:pyfunction:: cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]) -> None
.. ocv:cfunction:: void cvDrawContours( CvArr * img, CvSeq* contour, CvScalar external_color, CvScalar hole_color, int max_level, int thickness=1, int line_type=8, CvPoint offset=cvPoint(0,0) )
.. ocv:pyoldfunction:: cv.DrawContours(img, contour, external_color, hole_color, max_level, thickness=1, lineType=8, offset=(0, 0))-> None
:param image: Destination image.
:param contours: All the input contours. Each contour is stored as a point vector.
:param contourIdx: Parameter indicating a contour to draw. If it is negative, all the contours are drawn.
:param color: Color of the contours.
:param thickness: Thickness of lines the contours are drawn with. If it is negative (for example, ``thickness=CV_FILLED`` ), the contour interiors are
drawn.
:param lineType: Line connectivity. See :ocv:func:`line` for details.
:param hierarchy: Optional information about hierarchy. It is only needed if you want to draw only some of the contours (see ``maxLevel`` ).
:param maxLevel: Maximal level for drawn contours. If it is 0, only
the specified contour is drawn. If it is 1, the function draws the contour(s) and all the nested contours. If it is 2, the function draws the contours, all the nested contours, all the nested-to-nested contours, and so on. This parameter is only taken into account when there is ``hierarchy`` available.
:param offset: Optional contour shift parameter. Shift all the drawn contours by the specified :math:`\texttt{offset}=(dx,dy)` .
:param contour: Pointer to the first contour.
:param external_color: Color of external contours.
:param hole_color: Color of internal contours (holes).
The function draws contour outlines in the image if
:math:`\texttt{thickness} \ge 0` or fills the area bounded by the contours if
:math:`\texttt{thickness}<0` . The example below shows how to retrieve connected components from the binary image and label them: ::
#include "cv.h"
#include "highgui.h"
using namespace cv;
int main( int argc, char** argv )
{
Mat src;
// the first command-line parameter must be a filename of the binary
// (black-n-white) image
if( argc != 2 || !(src=imread(argv[1], 0)).data)
return -1;
Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);
src = src > 1;
namedWindow( "Source", 1 );
imshow( "Source", src );
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( src, contours, hierarchy,
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
// iterate through all the top-level contours,
// draw each connected component with its own random color
int idx = 0;
for( ; idx >= 0; idx = hierarchy[idx][0] )
{
Scalar color( rand()&255, rand()&255, rand()&255 );
drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );
}
namedWindow( "Components", 1 );
imshow( "Components", dst );
waitKey(0);
}
putText
-----------

View File

@@ -2578,13 +2578,6 @@ CV_EXPORTS_W void polylines(InputOutputArray img, InputArrayOfArrays pts,
bool isClosed, const Scalar& color,
int thickness=1, int lineType=8, int shift=0 );
//! draws contours in the image
CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours,
int contourIdx, const Scalar& color,
int thickness=1, int lineType=8,
InputArray hierarchy=noArray(),
int maxLevel=INT_MAX, Point offset=Point() );
//! clips the line segment by the rectangle Rect(0, 0, imgSize.width, imgSize.height)
CV_EXPORTS bool clipLine(Size imgSize, CV_IN_OUT Point& pt1, CV_IN_OUT Point& pt2);

View File

@@ -140,11 +140,11 @@ bool clipLine( Rect img_rect, Point& pt1, Point& pt2 )
pt1 -= tl; pt2 -= tl;
bool inside = clipLine(img_rect.size(), pt1, pt2);
pt1 += tl; pt2 += tl;
return inside;
}
/*
/*
Initializes line iterator.
Returns number of points on the line or negative number if error.
*/
@@ -195,7 +195,7 @@ LineIterator::LineIterator(const Mat& img, Point pt1, Point pt2,
istep = (istep ^ s) - s;
s = dy > dx ? -1 : 0;
/* conditional swaps */
dx ^= dy & s;
dy ^= dx & s;
@@ -208,7 +208,7 @@ LineIterator::LineIterator(const Mat& img, Point pt1, Point pt2,
if( connectivity == 8 )
{
assert( dx >= 0 && dy >= 0 );
err = dx - (dy + dy);
plusDelta = dx + dx;
minusDelta = -(dy + dy);
@@ -219,7 +219,7 @@ LineIterator::LineIterator(const Mat& img, Point pt1, Point pt2,
else /* connectivity == 4 */
{
assert( dx >= 0 && dy >= 0 );
err = 0;
plusDelta = (dx + dx) + (dy + dy);
minusDelta = -(dy + dy);
@@ -227,7 +227,7 @@ LineIterator::LineIterator(const Mat& img, Point pt1, Point pt2,
minusStep = bt_pix;
count = dx + dy + 1;
}
this->ptr0 = img.data;
this->step = (int)img.step;
this->elemSize = bt_pix0;
@@ -621,10 +621,10 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color )
tptr[1] = (uchar)cg; \
tptr[2] = (uchar)cr; \
}
ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT,
(pt2.y + (XY_ONE >> 1)) >> XY_SHIFT);
(pt2.y + (XY_ONE >> 1)) >> XY_SHIFT);
if( ax > ay )
{
pt1.x >>= XY_SHIFT;
@@ -640,7 +640,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color )
else
{
pt1.y >>= XY_SHIFT;
while( ecount >= 0 )
{
ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y);
@@ -664,8 +664,8 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color )
}
ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT,
(pt2.y + (XY_ONE >> 1)) >> XY_SHIFT);
(pt2.y + (XY_ONE >> 1)) >> XY_SHIFT);
if( ax > ay )
{
pt1.x >>= XY_SHIFT;
@@ -681,7 +681,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color )
else
{
pt1.y >>= XY_SHIFT;
while( ecount >= 0 )
{
ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y);
@@ -690,7 +690,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color )
ecount--;
}
}
#undef ICV_PUT_POINT
}
else
@@ -706,12 +706,12 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color )
}
ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT,
(pt2.y + (XY_ONE >> 1)) >> XY_SHIFT);
(pt2.y + (XY_ONE >> 1)) >> XY_SHIFT);
if( ax > ay )
{
pt1.x >>= XY_SHIFT;
while( ecount >= 0 )
{
ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT);
@@ -723,7 +723,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color )
else
{
pt1.y >>= XY_SHIFT;
while( ecount >= 0 )
{
ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y);
@@ -732,7 +732,7 @@ Line2( Mat& img, Point pt1, Point pt2, const void* color )
ecount--;
}
}
#undef ICV_PUT_POINT
}
}
@@ -830,7 +830,7 @@ sincos( int angle, float& cosval, float& sinval )
cosval = SinTable[450 - angle];
}
/*
/*
constructs polygon that represents elliptic arc.
*/
void ellipse2Poly( Point center, Size axes, int angle,
@@ -880,7 +880,7 @@ void ellipse2Poly( Point center, Size axes, int angle,
angle = arc_end;
if( angle < 0 )
angle += 360;
x = size_a * SinTable[450-angle];
y = size_b * SinTable[angle];
Point pt;
@@ -922,7 +922,7 @@ EllipseEx( Mat& img, Point center, Size axes,
/****************************************************************************************\
* Polygons filling *
* Polygons filling *
\****************************************************************************************/
/* helper macros: filling horizontal row */
@@ -1010,7 +1010,7 @@ FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_
LineAA( img, p0, p, color );
p0 = p;
}
xmin = (xmin + delta) >> shift;
xmax = (xmax + delta) >> shift;
ymin = (ymin + delta) >> shift;
@@ -1118,7 +1118,7 @@ CollectPolyEdges( Mat& img, const Point* v, int count, vector<PolyEdge>& edges,
{
Point t0, t1;
PolyEdge edge;
pt1 = v[i];
pt1.x = (pt1.x + offset.x) << (XY_SHIFT - shift);
pt1.y = (pt1.y + delta) >> shift;
@@ -1337,7 +1337,7 @@ Circle( Mat& img, Point center, int radius, const void* color, int fill )
{
uchar *tptr0 = ptr + y11 * step;
uchar *tptr1 = ptr + y12 * step;
if( !fill )
{
ICV_PUT_POINT( tptr0, x11 );
@@ -1374,7 +1374,7 @@ Circle( Mat& img, Point center, int radius, const void* color, int fill )
x11 = std::max( x11, 0 );
x12 = MIN( x12, size.width - 1 );
}
if( (unsigned)y11 < (unsigned)size.height )
{
uchar *tptr = ptr + y11 * step;
@@ -1523,7 +1523,7 @@ ThickLine( Mat& img, Point p0, Point p1, const void* color,
Point center;
center.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
center.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
Circle( img, center, (thickness + (XY_ONE>>1)) >> XY_SHIFT, color, 1 );
Circle( img, center, (thickness + (XY_ONE>>1)) >> XY_SHIFT, color, 1 );
}
else
{
@@ -1544,7 +1544,7 @@ PolyLine( Mat& img, const Point* v, int count, bool is_closed,
{
if( !v || count <= 0 )
return;
int i = is_closed ? count - 1 : 0;
int flags = 2 + !is_closed;
Point p0;
@@ -1575,7 +1575,7 @@ void line( Mat& img, Point pt1, Point pt2, const Scalar& color,
double buf[4];
scalarToRawData( color, buf, img.type(), 0 );
ThickLine( img, pt1, pt2, buf, thickness, line_type, 3, shift );
ThickLine( img, pt1, pt2, buf, thickness, line_type, 3, shift );
}
void rectangle( Mat& img, Point pt1, Point pt2,
@@ -1606,7 +1606,7 @@ void rectangle( Mat& img, Point pt1, Point pt2,
FillConvexPoly( img, pt, 4, buf, lineType, shift );
}
void rectangle( Mat& img, Rect rec,
const Scalar& color, int thickness,
int lineType, int shift )
@@ -1617,7 +1617,7 @@ void rectangle( Mat& img, Rect rec,
color, thickness, lineType, shift );
}
void circle( Mat& img, Point center, int radius,
const Scalar& color, int thickness, int line_type, int shift )
{
@@ -1667,25 +1667,25 @@ void ellipse( Mat& img, Point center, Size axes,
EllipseEx( img, center, axes, _angle, _start_angle,
_end_angle, buf, thickness, line_type );
}
void ellipse(Mat& img, const RotatedRect& box, const Scalar& color,
int thickness, int lineType)
{
if( lineType == CV_AA && img.depth() != CV_8U )
lineType = 8;
CV_Assert( box.size.width >= 0 && box.size.height >= 0 &&
thickness <= 255 );
double buf[4];
scalarToRawData(color, buf, img.type(), 0);
int _angle = cvRound(box.angle);
Point center(cvRound(box.center.x*(1 << XY_SHIFT)),
cvRound(box.center.y*(1 << XY_SHIFT)));
Size axes(cvRound(box.size.width*(1 << (XY_SHIFT - 1))),
cvRound(box.size.height*(1 << (XY_SHIFT - 1))));
EllipseEx( img, center, axes, _angle, 0, 360, buf, thickness, lineType );
EllipseEx( img, center, axes, _angle, 0, 360, buf, thickness, lineType );
}
void fillConvexPoly( Mat& img, const Point* pts, int npts,
@@ -1875,12 +1875,12 @@ static const int HersheyScriptComplex[] = {
2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676,
2225, 2229, 2226, 2246 };
static const int* getFontData(int fontFace)
{
bool isItalic = (fontFace & FONT_ITALIC) != 0;
const int* ascii = 0;
switch( fontFace & 15 )
{
case FONT_HERSHEY_SIMPLEX:
@@ -1912,15 +1912,15 @@ static const int* getFontData(int fontFace)
}
return ascii;
}
void putText( Mat& img, const string& text, Point org,
int fontFace, double fontScale, Scalar color,
int thickness, int line_type, bool bottomLeftOrigin )
{
const int* ascii = getFontData(fontFace);
double buf[4];
scalarToRawData(color, buf, img.type(), 0);
@@ -1959,7 +1959,7 @@ void putText( Mat& img, const string& text, Point org,
if( *ptr == ' ' || !*ptr )
{
if( pts.size() > 1 )
PolyLine( img, &pts[0], (int)pts.size(), false, buf, thickness, line_type, XY_SHIFT );
PolyLine( img, &pts[0], (int)pts.size(), false, buf, thickness, line_type, XY_SHIFT );
if( !*ptr++ )
break;
pts.resize(0);
@@ -2030,7 +2030,7 @@ void cv::fillPoly(InputOutputArray _img, InputArrayOfArrays pts,
AutoBuffer<int> _npts(ncontours);
Point** ptsptr = _ptsptr;
int* npts = _npts;
for( i = 0; i < ncontours; i++ )
{
Mat p = pts.getMat(i);
@@ -2056,7 +2056,7 @@ void cv::polylines(InputOutputArray _img, InputArrayOfArrays pts,
AutoBuffer<int> _npts(ncontours);
Point** ptsptr = _ptsptr;
int* npts = _npts;
for( i = 0; i < ncontours; i++ )
{
Mat p = pts.getMat(manyContours ? i : -1);
@@ -2069,116 +2069,6 @@ void cv::polylines(InputOutputArray _img, InputArrayOfArrays pts,
polylines(img, (const Point**)ptsptr, npts, (int)ncontours, isClosed, color, thickness, lineType, shift);
}
namespace
{
using namespace cv;
static void addChildContour(InputArrayOfArrays contours,
size_t ncontours,
const Vec4i* hierarchy,
int i, vector<CvSeq>& seq,
vector<CvSeqBlock>& block)
{
for( ; i >= 0; i = hierarchy[i][0] )
{
Mat ci = contours.getMat(i);
cvMakeSeqHeaderForArray(CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point),
!ci.empty() ? (void*)ci.data : 0, (int)ci.total(),
&seq[i], &block[i] );
int h_next = hierarchy[i][0], h_prev = hierarchy[i][1],
v_next = hierarchy[i][2], v_prev = hierarchy[i][3];
seq[i].h_next = (size_t)h_next < ncontours ? &seq[h_next] : 0;
seq[i].h_prev = (size_t)h_prev < ncontours ? &seq[h_prev] : 0;
seq[i].v_next = (size_t)v_next < ncontours ? &seq[v_next] : 0;
seq[i].v_prev = (size_t)v_prev < ncontours ? &seq[v_prev] : 0;
if( v_next >= 0 )
addChildContour(contours, ncontours, hierarchy, v_next, seq, block);
}
}
}
void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours,
int contourIdx, const Scalar& color, int thickness,
int lineType, InputArray _hierarchy,
int maxLevel, Point offset )
{
Mat image = _image.getMat(), hierarchy = _hierarchy.getMat();
CvMat _cimage = image;
size_t ncontours = _contours.total();
size_t i = 0, first = 0, last = ncontours;
vector<CvSeq> seq;
vector<CvSeqBlock> block;
if( !last )
return;
seq.resize(last);
block.resize(last);
for( i = first; i < last; i++ )
seq[i].first = 0;
if( contourIdx >= 0 )
{
CV_Assert( 0 <= contourIdx && contourIdx < (int)last );
first = contourIdx;
last = contourIdx + 1;
}
for( i = first; i < last; i++ )
{
Mat ci = _contours.getMat((int)i);
if( ci.empty() )
continue;
int npoints = ci.checkVector(2, CV_32S);
CV_Assert( npoints > 0 );
cvMakeSeqHeaderForArray( CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point),
ci.data, npoints, &seq[i], &block[i] );
}
if( hierarchy.empty() || maxLevel == 0 )
for( i = first; i < last; i++ )
{
seq[i].h_next = i < last-1 ? &seq[i+1] : 0;
seq[i].h_prev = i > first ? &seq[i-1] : 0;
}
else
{
size_t count = last - first;
CV_Assert(hierarchy.total() == ncontours && hierarchy.type() == CV_32SC4 );
const Vec4i* h = hierarchy.ptr<Vec4i>();
if( count == ncontours )
{
for( i = first; i < last; i++ )
{
int h_next = h[i][0], h_prev = h[i][1],
v_next = h[i][2], v_prev = h[i][3];
seq[i].h_next = (size_t)h_next < count ? &seq[h_next] : 0;
seq[i].h_prev = (size_t)h_prev < count ? &seq[h_prev] : 0;
seq[i].v_next = (size_t)v_next < count ? &seq[v_next] : 0;
seq[i].v_prev = (size_t)v_prev < count ? &seq[v_prev] : 0;
}
}
else
{
int child = h[first][2];
if( child >= 0 )
{
addChildContour(_contours, ncontours, h, child, seq, block);
seq[first].v_next = &seq[child];
}
}
}
cvDrawContours( &_cimage, &seq[first], color, color, contourIdx >= 0 ?
-maxLevel : maxLevel, thickness, lineType, offset );
}
static const int CodeDeltas[8][2] =
{ {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };
@@ -2188,7 +2078,7 @@ static const int CodeDeltas[8][2] =
CV_IMPL void
cvDrawContours( void* _img, CvSeq* contour,
CvScalar _externalColor, CvScalar _holeColor,
CvScalar _externalColor, CvScalar _holeColor,
int maxLevel, int thickness,
int line_type, CvPoint _offset )
{
@@ -2214,7 +2104,7 @@ cvDrawContours( void* _img, CvSeq* contour,
maxLevel = MAX(maxLevel, INT_MIN+2);
maxLevel = MIN(maxLevel, INT_MAX-1);
if( maxLevel < 0 )
{
h_next = contour->h_next;
@@ -2258,7 +2148,7 @@ cvDrawContours( void* _img, CvSeq* contour,
pts.push_back(pt);
prev_pt = pt;
}
pt.x += CodeDeltas[(int)code][0];
pt.y += CodeDeltas[(int)code][1];
}
@@ -2276,7 +2166,7 @@ cvDrawContours( void* _img, CvSeq* contour,
CV_Assert( elem_type == CV_32SC2 );
cv::Point pt1, pt2;
int shift = 0;
count -= !CV_IS_SEQ_CLOSED(contour);
CV_READ_SEQ_ELEM( pt1, reader );
pt1 += offset;
@@ -2328,7 +2218,7 @@ CV_IMPL CvScalar
cvColorToScalar( double packed_color, int type )
{
CvScalar scalar;
if( CV_MAT_DEPTH( type ) == CV_8U )
{
int icolor = cvRound( packed_color );