1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 15:23:05 +04:00

Merge branch '4.x' into '5.x'

This commit is contained in:
Maksim Shabunin
2024-06-11 19:38:59 +03:00
573 changed files with 72922 additions and 7355 deletions
+76 -88
View File
@@ -39,6 +39,7 @@
//
//M*/
#include "precomp.hpp"
using namespace cv;
namespace cv
{
@@ -2143,35 +2144,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, std::vector<CvSeq>& seq,
std::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.ptr() : 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 = (0 <= h_next && h_next < (int)ncontours) ? &seq[h_next] : 0;
seq[i].h_prev = (0 <= h_prev && h_prev < (int)ncontours) ? &seq[h_prev] : 0;
seq[i].v_next = (0 <= v_next && v_next < (int)ncontours) ? &seq[v_next] : 0;
seq[i].v_prev = (0 <= v_prev && v_prev < (int)ncontours) ? &seq[v_prev] : 0;
if( v_next >= 0 )
addChildContour(contours, ncontours, hierarchy, v_next, seq, block);
}
}
}
void
cvDrawContours( void* _img, CvSeq* contour,
@@ -2185,83 +2157,99 @@ void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours,
int maxLevel, Point offset )
{
CV_INSTRUMENT_REGION();
Mat image = _image.getMat(), hierarchy = _hierarchy.getMat();
CvMat _cimage = cvMat(image);
size_t ncontours = _contours.total();
size_t i = 0, first = 0, last = ncontours;
std::vector<CvSeq> seq;
std::vector<CvSeqBlock> block;
if( !last )
CV_Assert( thickness <= MAX_THICKNESS );
const size_t ncontours = _contours.total();
if (!ncontours)
return;
CV_Assert(ncontours <= (size_t)std::numeric_limits<int>::max());
if (lineType == cv::LINE_AA && _image.depth() != CV_8U)
lineType = 8;
Mat image = _image.getMat(), hierarchy = _hierarchy.getMat();
seq.resize(last);
block.resize(last);
for( i = first; i < last; i++ )
seq[i].first = 0;
if( contourIdx >= 0 )
if (thickness >= 0) // contour lines
{
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.ptr(), npoints, &seq[i], &block[i] );
}
if( hierarchy.empty() || maxLevel == 0 )
for( i = first; i < last; i++ )
double color_buf[4] {};
scalarToRawData(color, color_buf, _image.type(), 0 );
int i = 0, end = (int)ncontours;
if (contourIdx >= 0)
{
seq[i].h_next = i < last-1 ? &seq[i+1] : 0;
seq[i].h_prev = i > first ? &seq[i-1] : 0;
i = contourIdx;
end = i + 1;
}
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 < end; ++i)
{
for( i = first; i < last; i++ )
Mat cnt = _contours.getMat(i);
if (cnt.empty())
continue;
const int npoints = cnt.checkVector(2, CV_32S);
CV_Assert(npoints > 0);
for (int j = 0; j < npoints; ++j)
{
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;
const bool isLastIter = j == npoints - 1;
const Point pt1 = cnt.at<Point>(j);
const Point pt2 = cnt.at<Point>(isLastIter ? 0 : j + 1);
cv::ThickLine(image, pt1 + offset, pt2 + offset, color_buf, thickness, lineType, 2, 0);
}
}
}
else // filled polygons
{
int i = 0, end = (int)ncontours;
if (contourIdx >= 0)
{
i = contourIdx;
end = i + 1;
}
std::vector<int> indexesToFill;
if (hierarchy.empty() || maxLevel == 0)
{
for (; i != end; ++i)
indexesToFill.push_back(i);
}
else
{
int child = h[first][2];
if( child >= 0 )
std::stack<int> indexes;
for (; i != end; ++i)
{
addChildContour(_contours, ncontours, h, child, seq, block);
seq[first].v_next = &seq[child];
// either all from the top level or a single contour
if (hierarchy.at<Vec4i>(i)[3] < 0 || contourIdx >= 0)
indexes.push(i);
}
while (!indexes.empty())
{
// get current element
const int cur = indexes.top();
indexes.pop();
// check current element depth
int curLevel = -1;
int par = cur;
while (par >= 0)
{
par = hierarchy.at<Vec4i>(par)[3]; // parent
++curLevel;
}
if (curLevel <= maxLevel)
{
indexesToFill.push_back(cur);
}
int next = hierarchy.at<Vec4i>(cur)[2]; // first child
while (next > 0)
{
indexes.push(next);
next = hierarchy.at<Vec4i>(next)[0]; // next sibling
}
}
}
std::vector<Mat> contoursToFill;
for (const int & idx : indexesToFill)
contoursToFill.push_back(_contours.getMat(idx));
fillPoly(image, contoursToFill, color, lineType, 0, offset);
}
cvDrawContours( &_cimage, &seq[first], cvScalar(color), cvScalar(color), contourIdx >= 0 ?
-maxLevel : maxLevel, thickness, lineType, cvPoint(offset) );
}
static const int CodeDeltas[8][2] =
{ {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };