Merge pull request #25146 from mshabunin:cpp-contours

Reworked findContours to reduce C-API usage #25146

What is done:
* rewritten `findContours` and `icvApproximateChainTC89` using C++ data structures
* extracted LINK_RUNS mode to separate new public functions - `findContoursLinkRuns` (it uses completely different algorithm)
* ~added new public `cv::approximateChainTC89`~ - ** decided to hide it**
* enabled chain code output (method = 0, no public enum value for this in C++ yet)
* kept old function as `findContours_old` (exported, but not exposed to user)
* added more tests for findContours (`test_contours_new.cpp`), some tests compare results of old function with new one. Following tests have been added:
  * contours of random rectangle
  * contours of many small (1-2px) blobs
  * contours of random noise
  * backport of old accuracy test
  * separate test for LINK RUNS variant

What is left to be done (can be done now or later):
* improve tests: 
  * some tests have limited verification (e.g. only verify contour sizes)
  * perhaps reference data can be collected and stored
  * maybe more test variants can be added (?)
* add enum value for chain code output and a method of returning starting points (e.g. first 8 elements of returned `vector<uchar>` can represent 2 int point coordinates)
* add documentation for new functions - **✔️ DONE**
* check and improve performance (my experiment showed 0.7x-1.1x some time ago)
* remove old functions completely (?)
* change contour return order (BFS) or allow to select it (?)
* return result tree as-is (?) (new data structures should be exposed, bindings should adapt)
This commit is contained in:
Maksim Shabunin
2024-04-09 09:37:49 +03:00
committed by GitHub
parent e5d530abae
commit a25132986a
10 changed files with 2417 additions and 3 deletions

View File

@@ -4040,6 +4040,19 @@ A program using pyramid scaling, Canny, contours and contour simplification to f
squares in the input image.
*/
//! @brief Find contours using link runs algorithm
//!
//! This function implements an algorithm different from cv::findContours:
//! - doesn't allocate temporary image internally, thus it has reduced memory consumption
//! - supports CV_8UC1 images only
//! - outputs 2-level hierarhy only (RETR_CCOMP mode)
//! - doesn't support approximation change other than CHAIN_APPROX_SIMPLE
//! In all other aspects this function is compatible with cv::findContours.
CV_EXPORTS_W void findContoursLinkRuns(InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy);
//! @overload
CV_EXPORTS_W void findContoursLinkRuns(InputArray image, OutputArrayOfArrays contours);
/** @brief Approximates a polygonal curve(s) with the specified precision.
The function cv::approxPolyDP approximates a curve or a polygon with another curve/polygon with less

View File

@@ -0,0 +1,30 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef OPENCV_IMGPROC_DETAIL_LEGACY_HPP
#define OPENCV_IMGPROC_DETAIL_LEGACY_HPP
#include "opencv2/imgproc.hpp"
namespace cv {
#ifdef __OPENCV_BUILD
CV_EXPORTS void findContours_legacy(InputArray _image,
OutputArrayOfArrays _contours,
OutputArray _hierarchy,
int mode,
int method,
Point offset = Point());
CV_EXPORTS void findContours_legacy(InputArray image,
OutputArrayOfArrays contours,
int mode,
int method,
Point offset = Point());
#endif
} // namespace cv
#endif // OPENCV_IMGPROC_DETAIL_LEGACY_HPP