1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 08:13:04 +04:00

Backport C-API cleanup (imgproc) from 5.x

This commit is contained in:
Maksim Shabunin
2023-01-16 23:29:50 +03:00
parent c63d79c5b1
commit c1e5c16ff3
34 changed files with 206 additions and 397 deletions
+2 -149
View File
@@ -101,8 +101,6 @@ namespace cv {
#define MAX_CONTOUR_APPROX 7
#define USE_CV_FINDCONTOURS // switch between cv::findContours() and legacy C API
#ifdef USE_CV_FINDCONTOURS
struct QuadCountour {
Point pt[4];
int parent_contour;
@@ -113,18 +111,6 @@ struct QuadCountour {
pt[0] = pt_[0]; pt[1] = pt_[1]; pt[2] = pt_[2]; pt[3] = pt_[3];
}
};
#else
} // namespace
#include "opencv2/imgproc/imgproc_c.h"
namespace cv {
struct CvContourEx
{
CV_CONTOUR_FIELDS()
int counter;
};
#endif
/** This structure stores information about the chessboard corner.*/
@@ -552,13 +538,7 @@ bool findChessboardCorners(InputArray image_, Size pattern_size,
rectangle( thresh_img_new, Point(0,0), Point(thresh_img_new.cols-1, thresh_img_new.rows-1), Scalar(255,255,255), 3, LINE_8);
detector.reset();
#ifdef USE_CV_FINDCONTOURS
Mat binarized_img = thresh_img_new;
#else
Mat binarized_img = thresh_img_new.clone(); // make clone because cvFindContours modifies the source image
#endif
detector.generateQuads(binarized_img, flags);
detector.generateQuads(thresh_img_new, flags);
DPRINTF("Quad count: %d/%d", detector.all_quads_count, (pattern_size.width/2+1)*(pattern_size.height/2+1));
SHOW_QUADS("New quads", thresh_img_new, &detector.all_quads[0], detector.all_quads_count);
if (detector.processQuads(out_corners, prev_sqr_size))
@@ -623,13 +603,7 @@ bool findChessboardCorners(InputArray image_, Size pattern_size,
rectangle( thresh_img, Point(0,0), Point(thresh_img.cols-1, thresh_img.rows-1), Scalar(255,255,255), 3, LINE_8);
detector.reset();
#ifdef USE_CV_FINDCONTOURS
Mat binarized_img = thresh_img;
#else
Mat binarized_img = (useAdaptive) ? thresh_img : thresh_img.clone(); // make clone because cvFindContours modifies the source image
#endif
detector.generateQuads(binarized_img, flags);
detector.generateQuads(thresh_img, flags);
DPRINTF("Quad count: %d/%d", detector.all_quads_count, (pattern_size.width/2+1)*(pattern_size.height/2+1));
SHOW_QUADS("Old quads", thresh_img, &detector.all_quads[0], detector.all_quads_count);
if (detector.processQuads(out_corners, prev_sqr_size))
@@ -1376,7 +1350,6 @@ int ChessBoardDetector::checkQuadGroup(std::vector<ChessBoardQuad*>& quad_group,
for (int j = 0; j < 4; ++j)
{
//cvLine( debug_img, cvPointFrom32f(q->corners[j]->pt), cvPointFrom32f(q->corners[(j+1)&3]->pt), color, 1, CV_AA, 0 );
if (q->neighbors[j])
{
int next_j = (j + 1) & 3;
@@ -1465,7 +1438,6 @@ int ChessBoardDetector::checkQuadGroup(std::vector<ChessBoardQuad*>& quad_group,
goto finalize;
cur->row = 0;
//cvCircle( debug_img, cvPointFrom32f(cur->pt), 3, cvScalar(0,255,0), -1, 8, 0 );
first = below; // remember the first corner in the next row
@@ -1474,7 +1446,6 @@ int ChessBoardDetector::checkQuadGroup(std::vector<ChessBoardQuad*>& quad_group,
{
right->row = 0;
out_corners.push_back(right);
//cvCircle( debug_img, cvPointFrom32f(right->pt), 3, cvScalar(0,255-j*10,0), -1, 8, 0 );
if( right->count == 2 )
break;
if( right->count != 3 || (int)out_corners.size() >= std::max(pattern_size.width,pattern_size.height) )
@@ -1519,7 +1490,6 @@ int ChessBoardDetector::checkQuadGroup(std::vector<ChessBoardQuad*>& quad_group,
{
cur->row = i;
out_corners.push_back(cur);
//cvCircle( debug_img, cvPointFrom32f(cur->pt), 3, cvScalar(0,0,255-j*10), -1, 8, 0 );
if (cur->count == 2 + (i < height-1) && j > 0)
break;
@@ -1764,7 +1734,6 @@ void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags)
int min_size = 25; //cvRound( image->cols * image->rows * .03 * 0.01 * 0.92 );
bool filterQuads = (flags & CALIB_CB_FILTER_QUADS) != 0;
#ifdef USE_CV_FINDCONTOURS // use cv::findContours
std::vector<std::vector<Point> > contours;
std::vector<Vec4i> hierarchy;
@@ -1879,122 +1848,6 @@ void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags)
}
}
#else // use legacy API: cvStartFindContours / cvFindNextContour / cvEndFindContours
CvMat image_old = cvMat(image_), *image = &image_old;
CvContourEx* board = 0;
// create temporary storage for contours and the sequence of pointers to found quadrangles
cv::Ptr<CvMemStorage> temp_storage(cvCreateMemStorage(0));
CvSeq *root = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvSeq*), temp_storage);
// initialize contour retrieving routine
CvContourScanner scanner = cvStartFindContours(image, temp_storage, sizeof(CvContourEx),
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
// get all the contours one by one
CvSeq* src_contour = NULL;
while ((src_contour = cvFindNextContour(scanner)) != NULL)
{
CvSeq *dst_contour = 0;
CvRect rect = ((CvContour*)src_contour)->rect;
// reject contours with too small perimeter
if( CV_IS_SEQ_HOLE(src_contour) && rect.width*rect.height >= min_size )
{
const int min_approx_level = 1, max_approx_level = MAX_CONTOUR_APPROX;
for (int approx_level = min_approx_level; approx_level <= max_approx_level; approx_level++ )
{
dst_contour = cvApproxPoly( src_contour, sizeof(CvContour), temp_storage,
CV_POLY_APPROX_DP, (float)approx_level );
if( dst_contour->total == 4 )
break;
// we call this again on its own output, because sometimes
// cvApproxPoly() does not simplify as much as it should.
dst_contour = cvApproxPoly( dst_contour, sizeof(CvContour), temp_storage,
CV_POLY_APPROX_DP, (float)approx_level );
if( dst_contour->total == 4 )
break;
}
// reject non-quadrangles
if( dst_contour->total == 4 && cvCheckContourConvexity(dst_contour) )
{
cv::Point2i pt[4];
double p = cvContourPerimeter(dst_contour);
double area = fabs(cvContourArea(dst_contour, CV_WHOLE_SEQ));
for (int i = 0; i < 4; ++i)
pt[i] = *(CvPoint*)cvGetSeqElem(dst_contour, i);
CV_LOG_VERBOSE(NULL, 9, "... contours(" << root->total << " added):" << pt[0] << " " << pt[1] << " " << pt[2] << " " << pt[3]);
double d1 = sqrt(normL2Sqr<double>(pt[0] - pt[2]));
double d2 = sqrt(normL2Sqr<double>(pt[1] - pt[3]));
// philipg. Only accept those quadrangles which are more square
// than rectangular and which are big enough
double d3 = sqrt(normL2Sqr<double>(pt[0] - pt[1]));
double d4 = sqrt(normL2Sqr<double>(pt[1] - pt[2]));
if (!filterQuads ||
(d3*4 > d4 && d4*4 > d3 && d3*d4 < area*1.5 && area > min_size &&
d1 >= 0.15 * p && d2 >= 0.15 * p))
{
CvContourEx* parent = (CvContourEx*)(src_contour->v_prev);
parent->counter++;
if( !board || board->counter < parent->counter )
board = parent;
dst_contour->v_prev = (CvSeq*)parent;
//for( i = 0; i < 4; i++ ) cvLine( debug_img, pt[i], pt[(i+1)&3], cvScalar(200,255,255), 1, CV_AA, 0 );
cvSeqPush( root, &dst_contour );
}
}
}
}
// finish contour retrieving
cvEndFindContours( &scanner );
// allocate quad & corner buffers
int total = root->total;
size_t max_quad_buf_size = std::max((size_t)2, (size_t)total * 3);
all_quads.allocate(max_quad_buf_size);
all_corners.allocate(max_quad_buf_size * 4);
// Create array of quads structures
for (int idx = 0; idx < total; ++idx)
{
/* CvSeq* */src_contour = *(CvSeq**)cvGetSeqElem(root, idx);
if (filterQuads && src_contour->v_prev != (CvSeq*)board)
continue;
int quad_idx = quad_count++;
ChessBoardQuad& q = all_quads[quad_idx];
// reset group ID
q = ChessBoardQuad();
CV_Assert(src_contour->total == 4);
for (int i = 0; i < 4; i++)
{
Point* onePoint = (Point*)cvGetSeqElem(src_contour, i);
CV_Assert(onePoint != NULL);
Point2f pt(*onePoint);
ChessBoardCorner& corner = all_corners[quad_idx*4 + i];
corner = ChessBoardCorner(pt);
q.corners[i] = &corner;
}
q.edge_len = FLT_MAX;
for (int i = 0; i < 4; ++i)
{
float d = normL2Sqr<float>(q.corners[i]->pt - q.corners[(i+1)&3]->pt);
q.edge_len = std::min(q.edge_len, d);
}
}
#endif
all_quads_count = quad_count;
CV_LOG_VERBOSE(NULL, 3, "Total quad contours: " << total);