From e19b0ebc5c26fae3005336a1d3b3ed949ecd16e0 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Wed, 27 May 2026 16:06:51 +0300 Subject: [PATCH] Merge pull request #28804 from asmorkalov:as/calib_boards_migration Migrated chessboard and circles grid detectors to objdetect #28804 OpenCV Contrib: https://github.com/opencv/opencv_contrib/pull/4125 OpenCV Extra: https://github.com/opencv/opencv_extra/pull/1375 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/calib/CMakeLists.txt | 2 +- modules/calib/include/opencv2/calib.hpp | 268 -------------- modules/calib/misc/java/gen_dict.json | 4 +- modules/calib/misc/java/test/CalibTest.java | 80 ----- modules/calib/misc/objc/gen_dict.json | 5 - modules/calib/misc/objc/test/CalibTest.swift | 83 ----- modules/calib/src/precomp.hpp | 2 - modules/calib/test/test_cameracalibration.cpp | 1 + .../test_cameracalibration_artificial.cpp | 1 + modules/objdetect/CMakeLists.txt | 1 + .../objdetect/include/opencv2/objdetect.hpp | 264 ++++++++++++++ modules/objdetect/misc/java/gen_dict.json | 4 + .../misc/java/test/ObjdetectTest.java | 100 ++++++ modules/objdetect/misc/objc/gen_dict.json | 5 + .../misc/objc/test/ObjdetectTest.swift | 88 +++++ .../perf/perf_cicrlesGrid.cpp | 0 .../{calib => objdetect}/src/calibinit.cpp | 1 + .../src/checkchessboard.cpp | 0 .../{calib => objdetect}/src/chessboard.cpp | 1 + .../{calib => objdetect}/src/chessboard.hpp | 0 .../{calib => objdetect}/src/circlesgrid.cpp | 2 + .../{calib => objdetect}/src/circlesgrid.hpp | 0 modules/objdetect/src/precomp.hpp | 8 + .../{calib => objdetect}/src/quadsubpix.cpp | 0 .../test/test_chessboardgenerator.cpp | 331 ++++++++++++++++++ .../test/test_chessboardgenerator.hpp | 43 +++ .../test/test_chesscorners.cpp | 19 +- .../test/test_chesscorners_badarg.cpp | 0 .../test/test_chesscorners_timing.cpp | 2 +- .../test/test_cornerssubpix.cpp | 0 modules/objdetect/test/test_precomp.hpp | 1 + .../cameracalibration/CameraCalibrator.java | 7 +- samples/cpp/3calibration.cpp | 1 + samples/cpp/calibration.cpp | 5 +- samples/cpp/select3dobj.cpp | 1 + samples/cpp/stereo_calib.cpp | 1 + .../camera_calibration/camera_calibration.cpp | 1 + .../Homography/decompose_homography.cpp | 1 + .../homography_from_camera_displacement.cpp | 1 + .../Homography/perspective_correction.cpp | 1 + .../Homography/pose_from_homography.cpp | 1 + 41 files changed, 880 insertions(+), 456 deletions(-) create mode 100644 modules/objdetect/misc/java/test/ObjdetectTest.java create mode 100644 modules/objdetect/misc/objc/test/ObjdetectTest.swift rename modules/{calib => objdetect}/perf/perf_cicrlesGrid.cpp (100%) rename modules/{calib => objdetect}/src/calibinit.cpp (99%) rename modules/{calib => objdetect}/src/checkchessboard.cpp (100%) rename modules/{calib => objdetect}/src/chessboard.cpp (99%) rename modules/{calib => objdetect}/src/chessboard.hpp (100%) rename modules/{calib => objdetect}/src/circlesgrid.cpp (99%) rename modules/{calib => objdetect}/src/circlesgrid.hpp (100%) rename modules/{calib => objdetect}/src/quadsubpix.cpp (100%) create mode 100644 modules/objdetect/test/test_chessboardgenerator.cpp create mode 100644 modules/objdetect/test/test_chessboardgenerator.hpp rename modules/{calib => objdetect}/test/test_chesscorners.cpp (98%) rename modules/{calib => objdetect}/test/test_chesscorners_badarg.cpp (100%) rename modules/{calib => objdetect}/test/test_chesscorners_timing.cpp (98%) rename modules/{calib => objdetect}/test/test_cornerssubpix.cpp (100%) diff --git a/modules/calib/CMakeLists.txt b/modules/calib/CMakeLists.txt index fee5499d5c..2af9a78e45 100644 --- a/modules/calib/CMakeLists.txt +++ b/modules/calib/CMakeLists.txt @@ -4,6 +4,6 @@ set(debug_modules "") if(DEBUG_opencv_calib) list(APPEND debug_modules opencv_highgui) endif() -ocv_define_module(calib opencv_imgproc opencv_features opencv_flann opencv_3d opencv_stereo ${debug_modules} +ocv_define_module(calib opencv_imgproc opencv_objdetect opencv_flann opencv_3d opencv_stereo ${debug_modules} WRAP java objc python js ) diff --git a/modules/calib/include/opencv2/calib.hpp b/modules/calib/include/opencv2/calib.hpp index fd7b8bb1e2..176c3212fe 100644 --- a/modules/calib/include/opencv2/calib.hpp +++ b/modules/calib/include/opencv2/calib.hpp @@ -7,7 +7,6 @@ #include "opencv2/core.hpp" #include "opencv2/core/types.hpp" -#include "opencv2/features.hpp" #include "opencv2/core/affine.hpp" /** @@ -487,22 +486,6 @@ namespace cv { //! @addtogroup calib //! @{ -enum { CALIB_CB_ADAPTIVE_THRESH = 1, - CALIB_CB_NORMALIZE_IMAGE = 2, - CALIB_CB_FILTER_QUADS = 4, - CALIB_CB_FAST_CHECK = 8, - CALIB_CB_EXHAUSTIVE = 16, - CALIB_CB_ACCURACY = 32, - CALIB_CB_LARGER = 64, - CALIB_CB_MARKER = 128, - CALIB_CB_PLAIN = 256 - }; - -enum { CALIB_CB_SYMMETRIC_GRID = 1, - CALIB_CB_ASYMMETRIC_GRID = 2, - CALIB_CB_CLUSTERING = 4 - }; - #define CALIB_NINTRINSIC 18 //!< Maximal size of camera internal parameters (initrinsics) vector enum CameraModel { @@ -577,257 +560,6 @@ CV_EXPORTS_W Mat initCameraMatrix2D( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, Size imageSize, double aspectRatio = 1.0 ); -/** @brief Finds the positions of internal corners of the chessboard. - -@param image Source chessboard view. It must be an 8-bit grayscale or color image. -@param patternSize Number of inner corners per a chessboard row and column -( patternSize = cv::Size(points_per_row,points_per_column) = cv::Size(columns,rows) ). -@param corners Output array of detected corners. -@param flags Various operation flags that can be zero or a combination of the following values: -- @ref CALIB_CB_ADAPTIVE_THRESH Use adaptive thresholding to convert the image to black -and white, rather than a fixed threshold level (computed from the average image brightness). -- @ref CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with equalizeHist before -applying fixed or adaptive thresholding. -- @ref CALIB_CB_FILTER_QUADS Use additional criteria (like contour area, perimeter, -square-like shape) to filter out false quads extracted at the contour retrieval stage. -- @ref CALIB_CB_FAST_CHECK Run a fast check on the image that looks for chessboard corners, -and shortcut the call if none is found. This can drastically speed up the call in the -degenerate condition when no chessboard is observed. -- @ref CALIB_CB_PLAIN All other flags are ignored. The input image is taken as is. -No image processing is done to improve to find the checkerboard. This has the effect of speeding up the -execution of the function but could lead to not recognizing the checkerboard if the image -is not previously binarized in the appropriate manner. - -The function attempts to determine whether the input image is a view of the chessboard pattern and -locate the internal chessboard corners. The function returns a non-zero value if all of the corners -are found and they are placed in a certain order (row by row, left to right in every row). -Otherwise, if the function fails to find all the corners or reorder them, it returns 0. For example, -a regular chessboard has 8 x 8 squares and 7 x 7 internal corners, that is, points where the black -squares touch each other. The detected coordinates are approximate, and to determine their positions -more accurately, the function calls #cornerSubPix. You also may use the function #cornerSubPix with -different parameters if returned coordinates are not accurate enough. - -Sample usage of detecting and drawing chessboard corners: : -@code - Size patternsize(8,6); //interior number of corners - Mat gray = ....; //source image - vector corners; //this will be filled by the detected corners - - //CALIB_CB_FAST_CHECK saves a lot of time on images - //that do not contain any chessboard corners - bool patternfound = findChessboardCorners(gray, patternsize, corners, - CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE - + CALIB_CB_FAST_CHECK); - - if(patternfound) - cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1), - TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1)); - - drawChessboardCorners(img, patternsize, Mat(corners), patternfound); -@endcode -@note The function requires white space (like a square-thick border, the wider the better) around -the board to make the detection more robust in various environments. Otherwise, if there is no -border and the background is dark, the outer black squares cannot be segmented properly and so the -square grouping and ordering algorithm fails. - -Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) -to create the desired checkerboard pattern. - */ -CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, - int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE ); - -/* - Checks whether the image contains chessboard of the specific size or not. - If yes, nonzero value is returned. -*/ -CV_EXPORTS_W bool checkChessboard(InputArray img, Size size); - -/** @brief Finds the positions of internal corners of the chessboard using a sector based approach. - -@param image Source chessboard view. It must be an 8-bit grayscale or color image. -@param patternSize Number of inner corners per a chessboard row and column -( patternSize = cv::Size(points_per_row,points_per_column) = cv::Size(columns,rows) ). -@param corners Output array of detected corners. -@param flags Various operation flags that can be zero or a combination of the following values: -- @ref CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with equalizeHist before detection. -- @ref CALIB_CB_EXHAUSTIVE Run an exhaustive search to improve detection rate. -- @ref CALIB_CB_ACCURACY Up sample input image to improve sub-pixel accuracy due to aliasing effects. -- @ref CALIB_CB_LARGER The detected pattern is allowed to be larger than patternSize (see description). -- @ref CALIB_CB_MARKER The detected pattern must have a marker (see description). -This should be used if an accurate camera calibration is required. -@param meta Optional output array of detected corners (CV_8UC1 and size = cv::Size(columns,rows)). -Each entry stands for one corner of the pattern and can have one of the following values: -- 0 = no meta data attached -- 1 = left-top corner of a black cell -- 2 = left-top corner of a white cell -- 3 = left-top corner of a black cell with a white marker dot -- 4 = left-top corner of a white cell with a black marker dot (pattern origin in case of markers otherwise first corner) - -The function is analog to #findChessboardCorners but uses a localized radon -transformation approximated by box filters being more robust to all sort of -noise, faster on larger images and is able to directly return the sub-pixel -position of the internal chessboard corners. The Method is based on the paper -@cite duda2018 "Accurate Detection and Localization of Checkerboard Corners for -Calibration" demonstrating that the returned sub-pixel positions are more -accurate than the one returned by cornerSubPix allowing a precise camera -calibration for demanding applications. - -In the case, the flags @ref CALIB_CB_LARGER or @ref CALIB_CB_MARKER are given, -the result can be recovered from the optional meta array. Both flags are -helpful to use calibration patterns exceeding the field of view of the camera. -These oversized patterns allow more accurate calibrations as corners can be -utilized, which are as close as possible to the image borders. For a -consistent coordinate system across all images, the optional marker (see image -below) can be used to move the origin of the board to the location where the -black circle is located. - -@note The function requires a white boarder with roughly the same width as one -of the checkerboard fields around the whole board to improve the detection in -various environments. In addition, because of the localized radon -transformation it is beneficial to use round corners for the field corners -which are located on the outside of the board. The following figure illustrates -a sample checkerboard optimized for the detection. However, any other checkerboard -can be used as well. - -Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) -to create the corresponding checkerboard pattern: -\image html pics/checkerboard_radon.png width=60% - */ -CV_EXPORTS_AS(findChessboardCornersSBWithMeta) -bool findChessboardCornersSB(InputArray image,Size patternSize, OutputArray corners, - int flags,OutputArray meta); -/** @overload */ -CV_EXPORTS_W inline -bool findChessboardCornersSB(InputArray image, Size patternSize, OutputArray corners, - int flags = 0) -{ - return findChessboardCornersSB(image, patternSize, corners, flags, noArray()); -} - -/** @brief Estimates the sharpness of a detected chessboard. - -Image sharpness, as well as brightness, are a critical parameter for accuracte -camera calibration. For accessing these parameters for filtering out -problematic calibraiton images, this method calculates edge profiles by traveling from -black to white chessboard cell centers. Based on this, the number of pixels is -calculated required to transit from black to white. This width of the -transition area is a good indication of how sharp the chessboard is imaged -and should be below ~3.0 pixels. - -@param image Gray image used to find chessboard corners -@param patternSize Size of a found chessboard pattern -@param corners Corners found by #findChessboardCornersSB -@param rise_distance Rise distance 0.8 means 10% ... 90% of the final signal strength -@param vertical By default edge responses for horizontal lines are calculated -@param sharpness Optional output array with a sharpness value for calculated edge responses (see description) - -The optional sharpness array is of type CV_32FC1 and has for each calculated -profile one row with the following five entries: -* 0 = x coordinate of the underlying edge in the image -* 1 = y coordinate of the underlying edge in the image -* 2 = width of the transition area (sharpness) -* 3 = signal strength in the black cell (min brightness) -* 4 = signal strength in the white cell (max brightness) - -@return Scalar(average sharpness, average min brightness, average max brightness,0) -*/ -CV_EXPORTS_W Scalar estimateChessboardSharpness(InputArray image, Size patternSize, InputArray corners, - float rise_distance=0.8F,bool vertical=false, - OutputArray sharpness=noArray()); - - -//! finds subpixel-accurate positions of the chessboard corners -CV_EXPORTS_W bool find4QuadCornerSubpix( InputArray img, InputOutputArray corners, Size region_size ); - -/** @brief Renders the detected chessboard corners. - -@param image Destination image. It must be an 8-bit color image. -@param patternSize Number of inner corners per a chessboard row and column -(patternSize = cv::Size(points_per_row,points_per_column)). -@param corners Array of detected corners, the output of #findChessboardCorners. -@param patternWasFound Parameter indicating whether the complete board was found or not. The -return value of #findChessboardCorners should be passed here. - -The function draws individual chessboard corners detected either as red circles if the board was not -found, or as colored corners connected with lines if the board was found. - */ -CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize, - InputArray corners, bool patternWasFound ); - -struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters -{ - CV_WRAP CirclesGridFinderParameters(); - CV_PROP_RW cv::Size2f densityNeighborhoodSize; - CV_PROP_RW float minDensity; - CV_PROP_RW int kmeansAttempts; - CV_PROP_RW int minDistanceToAddKeypoint; - CV_PROP_RW int keypointScale; - CV_PROP_RW float minGraphConfidence; - CV_PROP_RW float vertexGain; - CV_PROP_RW float vertexPenalty; - CV_PROP_RW float existingVertexGain; - CV_PROP_RW float edgeGain; - CV_PROP_RW float edgePenalty; - CV_PROP_RW float convexHullFactor; - CV_PROP_RW float minRNGEdgeSwitchDist; - - enum GridType - { - SYMMETRIC_GRID, ASYMMETRIC_GRID - }; - CV_PROP_RW GridType gridType; - - CV_PROP_RW float squareSize; //!< Distance between two adjacent points. Used by CALIB_CB_CLUSTERING. - CV_PROP_RW float maxRectifiedDistance; //!< Max deviation from prediction. Used by CALIB_CB_CLUSTERING. -}; - -#ifndef DISABLE_OPENCV_3_COMPATIBILITY -typedef CirclesGridFinderParameters CirclesGridFinderParameters2; -#endif - -/** @brief Finds centers in the grid of circles. - -@param image grid view of input circles; it must be an 8-bit grayscale or color image. -@param patternSize number of circles per row and column -( patternSize = Size(points_per_row, points_per_column) ). -@param centers output array of detected centers. -@param flags various operation flags that can be one of the following values: -- @ref CALIB_CB_SYMMETRIC_GRID uses symmetric pattern of circles. -- @ref CALIB_CB_ASYMMETRIC_GRID uses asymmetric pattern of circles. -- @ref CALIB_CB_CLUSTERING uses a special algorithm for grid detection. It is more robust to -perspective distortions but much more sensitive to background clutter. -@param blobDetector feature detector that finds blobs like dark circles on light background. - If `blobDetector` is NULL then `image` represents Point2f array of candidates. -@param parameters struct for finding circles in a grid pattern. - -The function attempts to determine whether the input image contains a grid of circles. If it is, the -function locates centers of the circles. The function returns a non-zero value if all of the centers -have been found and they have been placed in a certain order (row by row, left to right in every -row). Otherwise, if the function fails to find all the corners or reorder them, it returns 0. - -Sample usage of detecting and drawing the centers of circles: : -@code - Size patternsize(7,7); //number of centers - Mat gray = ...; //source image - vector centers; //this will be filled by the detected centers - - bool patternfound = findCirclesGrid(gray, patternsize, centers); - - drawChessboardCorners(img, patternsize, Mat(centers), patternfound); -@endcode -@note The function requires white space (like a square-thick border, the wider the better) around -the board to make the detection more robust in various environments. - */ -CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, - OutputArray centers, int flags, - const Ptr &blobDetector, - const CirclesGridFinderParameters& parameters); - -/** @overload */ -CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, - OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID, - const Ptr &blobDetector = SimpleBlobDetector::create()); - /** @brief Finds the camera intrinsic and extrinsic parameters from several views of a calibration pattern. diff --git a/modules/calib/misc/java/gen_dict.json b/modules/calib/misc/java/gen_dict.json index e7e2e50970..7a75f91f18 100644 --- a/modules/calib/misc/java/gen_dict.json +++ b/modules/calib/misc/java/gen_dict.json @@ -7,8 +7,6 @@ }, "func_arg_fix" : { "initCameraMatrix2D" : { "objectPoints" : {"ctype" : "vector_vector_Point3f"}, - "imagePoints" : {"ctype" : "vector_vector_Point2f"} }, - "findChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} }, - "drawChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} } + "imagePoints" : {"ctype" : "vector_vector_Point2f"} } } } diff --git a/modules/calib/misc/java/test/CalibTest.java b/modules/calib/misc/java/test/CalibTest.java index 11c968e4de..065f1d76b8 100644 --- a/modules/calib/misc/java/test/CalibTest.java +++ b/modules/calib/misc/java/test/CalibTest.java @@ -18,86 +18,6 @@ import org.opencv.imgproc.Imgproc; public class CalibTest extends OpenCVTestCase { - Size size; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - size = new Size(3, 3); - } - - public void testFindChessboardCornersMatSizeMat() { - Size patternSize = new Size(9, 6); - MatOfPoint2f corners = new MatOfPoint2f(); - Calib.findChessboardCorners(grayChess, patternSize, corners); - assertFalse(corners.empty()); - } - - public void testFindChessboardCornersMatSizeMatInt() { - Size patternSize = new Size(9, 6); - MatOfPoint2f corners = new MatOfPoint2f(); - Calib.findChessboardCorners(grayChess, patternSize, corners, Calib.CALIB_CB_ADAPTIVE_THRESH + Calib.CALIB_CB_NORMALIZE_IMAGE - + Calib.CALIB_CB_FAST_CHECK); - assertFalse(corners.empty()); - } - - public void testFind4QuadCornerSubpix() { - Size patternSize = new Size(9, 6); - MatOfPoint2f corners = new MatOfPoint2f(); - Size region_size = new Size(5, 5); - Calib.findChessboardCorners(grayChess, patternSize, corners); - Calib.find4QuadCornerSubpix(grayChess, corners, region_size); - assertFalse(corners.empty()); - } - - public void testFindCirclesGridMatSizeMat() { - int size = 300; - Mat img = new Mat(size, size, CvType.CV_8U); - img.setTo(new Scalar(255)); - Mat centers = new Mat(); - - assertFalse(Calib.findCirclesGrid(img, new Size(5, 5), centers)); - - for (int i = 0; i < 5; i++) - for (int j = 0; j < 5; j++) { - Point pt = new Point(size * (2 * i + 1) / 10, size * (2 * j + 1) / 10); - Imgproc.circle(img, pt, 10, new Scalar(0), -1); - } - - assertTrue(Calib.findCirclesGrid(img, new Size(5, 5), centers)); - - assertEquals(1, centers.rows()); - assertEquals(25, centers.cols()); - assertEquals(CvType.CV_32FC2, centers.type()); - } - - public void testFindCirclesGridMatSizeMatInt() { - int size = 300; - Mat img = new Mat(size, size, CvType.CV_8U); - img.setTo(new Scalar(255)); - Mat centers = new Mat(); - - assertFalse(Calib.findCirclesGrid(img, new Size(3, 5), centers, Calib.CALIB_CB_CLUSTERING - | Calib.CALIB_CB_ASYMMETRIC_GRID)); - - int step = size * 2 / 15; - int offsetx = size / 6; - int offsety = (size - 4 * step) / 2; - for (int i = 0; i < 3; i++) - for (int j = 0; j < 5; j++) { - Point pt = new Point(offsetx + (2 * i + j % 2) * step, offsety + step * j); - Imgproc.circle(img, pt, 10, new Scalar(0), -1); - } - - assertTrue(Calib.findCirclesGrid(img, new Size(3, 5), centers, Calib.CALIB_CB_CLUSTERING - | Calib.CALIB_CB_ASYMMETRIC_GRID)); - - assertEquals(1, centers.rows()); - assertEquals(15, centers.cols()); - assertEquals(CvType.CV_32FC2, centers.type()); - } - public void testConstants() { // calib3d.hpp: some constants have conflict with constants from 'fisheye' namespace diff --git a/modules/calib/misc/objc/gen_dict.json b/modules/calib/misc/objc/gen_dict.json index 15cc9f4de3..713fc99f6d 100644 --- a/modules/calib/misc/objc/gen_dict.json +++ b/modules/calib/misc/objc/gen_dict.json @@ -1,10 +1,5 @@ { "namespaces_dict": { "cv.fisheye": "fisheye" - }, - "func_arg_fix" : { - "Calib" : { - "findCirclesGrid" : { "blobDetector" : {"defval" : "cv::SimpleBlobDetector::create()"} } - } } } diff --git a/modules/calib/misc/objc/test/CalibTest.swift b/modules/calib/misc/objc/test/CalibTest.swift index c8f249d7ad..352c6435af 100644 --- a/modules/calib/misc/objc/test/CalibTest.swift +++ b/modules/calib/misc/objc/test/CalibTest.swift @@ -9,89 +9,6 @@ import OpenCV class CalibTest: OpenCVTestCase { - var size = Size() - - override func setUp() { - super.setUp() - size = Size(width: 3, height: 3) - } - - override func tearDown() { - super.tearDown() - } - - func testFindChessboardCornersMatSizeMat() { - let patternSize = Size(width: 9, height: 6) - let corners = MatOfPoint2f() - Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners) - XCTAssertFalse(corners.empty()) - } - - func testFindChessboardCornersMatSizeMatInt() { - let patternSize = Size(width: 9, height: 6) - let corners = MatOfPoint2f() - Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners, flags: Calib.CALIB_CB_ADAPTIVE_THRESH + Calib.CALIB_CB_NORMALIZE_IMAGE + Calib.CALIB_CB_FAST_CHECK) - XCTAssertFalse(corners.empty()) - } - - func testFind4QuadCornerSubpix() { - let patternSize = Size(width: 9, height: 6) - let corners = MatOfPoint2f() - let region_size = Size(width: 5, height: 5) - Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners) - Calib.find4QuadCornerSubpix(img: grayChess, corners: corners, region_size: region_size) - XCTAssertFalse(corners.empty()) - } - - func testFindCirclesGridMatSizeMat() { - let size = 300 - let img = Mat(rows:Int32(size), cols:Int32(size), type:CvType.CV_8U) - img.setTo(scalar: Scalar(255)) - let centers = Mat() - - XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 5, height: 5), centers: centers)) - - for i in 0..<5 { - for j in 0..<5 { - let x = Int32(size * (2 * i + 1) / 10) - let y = Int32(size * (2 * j + 1) / 10) - let pt = Point(x: x, y: y) - Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1) - } - } - - XCTAssert(Calib.findCirclesGrid(image: img, patternSize:Size(width:5, height:5), centers:centers)) - - XCTAssertEqual(25, centers.rows()) - XCTAssertEqual(1, centers.cols()) - XCTAssertEqual(CvType.CV_32FC2, centers.type()) - } - - func testFindCirclesGridMatSizeMatInt() { - let size:Int32 = 300 - let img = Mat(rows:size, cols: size, type: CvType.CV_8U) - img.setTo(scalar: Scalar(255)) - let centers = Mat() - - XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID)) - - let step = size * 2 / 15 - let offsetx = size / 6 - let offsety = (size - 4 * step) / 2 - for i:Int32 in 0...2 { - for j:Int32 in 0...4 { - let pt = Point(x: offsetx + (2 * i + j % 2) * step, y: offsety + step * j) - Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1) - } - } - - XCTAssert(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID)) - - XCTAssertEqual(15, centers.rows()) - XCTAssertEqual(1, centers.cols()) - XCTAssertEqual(CvType.CV_32FC2, centers.type()) - } - func testConstants() { // calib3d.hpp: some constants have conflict with constants from 'fisheye' namespace diff --git a/modules/calib/src/precomp.hpp b/modules/calib/src/precomp.hpp index ef90fec63b..dc4cc5722e 100644 --- a/modules/calib/src/precomp.hpp +++ b/modules/calib/src/precomp.hpp @@ -134,8 +134,6 @@ static inline bool haveCollinearPoints( const Mat& m, int count ) return false; } -int checkChessboardBinary(const Mat & img, const Size & size); - } // namespace cv #endif diff --git a/modules/calib/test/test_cameracalibration.cpp b/modules/calib/test/test_cameracalibration.cpp index a9e8bd3df7..7fcc41f991 100644 --- a/modules/calib/test/test_cameracalibration.cpp +++ b/modules/calib/test/test_cameracalibration.cpp @@ -41,6 +41,7 @@ #include "test_precomp.hpp" #include "opencv2/stereo.hpp" +#include "opencv2/objdetect.hpp" namespace opencv_test { namespace { diff --git a/modules/calib/test/test_cameracalibration_artificial.cpp b/modules/calib/test/test_cameracalibration_artificial.cpp index f2f1be2baa..16245eeea0 100644 --- a/modules/calib/test/test_cameracalibration_artificial.cpp +++ b/modules/calib/test/test_cameracalibration_artificial.cpp @@ -42,6 +42,7 @@ #include "test_precomp.hpp" #include "test_chessboardgenerator.hpp" +#include "opencv2/objdetect.hpp" namespace opencv_test { namespace { diff --git a/modules/objdetect/CMakeLists.txt b/modules/objdetect/CMakeLists.txt index b770d31125..f16b26d034 100644 --- a/modules/objdetect/CMakeLists.txt +++ b/modules/objdetect/CMakeLists.txt @@ -2,6 +2,7 @@ set(the_description "Object Detection") ocv_define_module(objdetect opencv_core opencv_imgproc + opencv_features opencv_3d OPTIONAL opencv_dnn diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index 95cb874135..b71af5cb66 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -45,6 +45,7 @@ #define OPENCV_OBJDETECT_HPP #include "opencv2/core.hpp" +#include "opencv2/features.hpp" #include "opencv2/objdetect/aruco_detector.hpp" #include "opencv2/objdetect/graphical_code_detector.hpp" #include "opencv2/objdetect/mcc_checker_detector.hpp" @@ -316,6 +317,269 @@ public: CV_WRAP void setArucoParameters(const aruco::DetectorParameters& params); }; +enum { CALIB_CB_ADAPTIVE_THRESH = 1, + CALIB_CB_NORMALIZE_IMAGE = 2, + CALIB_CB_FILTER_QUADS = 4, + CALIB_CB_FAST_CHECK = 8, + CALIB_CB_EXHAUSTIVE = 16, + CALIB_CB_ACCURACY = 32, + CALIB_CB_LARGER = 64, + CALIB_CB_MARKER = 128, + CALIB_CB_PLAIN = 256 + }; + +enum { CALIB_CB_SYMMETRIC_GRID = 1, + CALIB_CB_ASYMMETRIC_GRID = 2, + CALIB_CB_CLUSTERING = 4 + }; + +/** @brief Finds the positions of internal corners of the chessboard. + +@param image Source chessboard view. It must be an 8-bit grayscale or color image. +@param patternSize Number of inner corners per a chessboard row and column +( patternSize = cv::Size(points_per_row,points_per_column) = cv::Size(columns,rows) ). +@param corners Output array of detected corners. +@param flags Various operation flags that can be zero or a combination of the following values: +- @ref CALIB_CB_ADAPTIVE_THRESH Use adaptive thresholding to convert the image to black +and white, rather than a fixed threshold level (computed from the average image brightness). +- @ref CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with equalizeHist before +applying fixed or adaptive thresholding. +- @ref CALIB_CB_FILTER_QUADS Use additional criteria (like contour area, perimeter, +square-like shape) to filter out false quads extracted at the contour retrieval stage. +- @ref CALIB_CB_FAST_CHECK Run a fast check on the image that looks for chessboard corners, +and shortcut the call if none is found. This can drastically speed up the call in the +degenerate condition when no chessboard is observed. +- @ref CALIB_CB_PLAIN All other flags are ignored. The input image is taken as is. +No image processing is done to improve to find the checkerboard. This has the effect of speeding up the +execution of the function but could lead to not recognizing the checkerboard if the image +is not previously binarized in the appropriate manner. + +The function attempts to determine whether the input image is a view of the chessboard pattern and +locate the internal chessboard corners. The function returns a non-zero value if all of the corners +are found and they are placed in a certain order (row by row, left to right in every row). +Otherwise, if the function fails to find all the corners or reorder them, it returns 0. For example, +a regular chessboard has 8 x 8 squares and 7 x 7 internal corners, that is, points where the black +squares touch each other. The detected coordinates are approximate, and to determine their positions +more accurately, the function calls #cornerSubPix. You also may use the function #cornerSubPix with +different parameters if returned coordinates are not accurate enough. + +Sample usage of detecting and drawing chessboard corners: : +@code + Size patternsize(8,6); //interior number of corners + Mat gray = ....; //source image + vector corners; //this will be filled by the detected corners + + //CALIB_CB_FAST_CHECK saves a lot of time on images + //that do not contain any chessboard corners + bool patternfound = findChessboardCorners(gray, patternsize, corners, + CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + + CALIB_CB_FAST_CHECK); + + if(patternfound) + cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1), + TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1)); + + drawChessboardCorners(img, patternsize, Mat(corners), patternfound); +@endcode +@note The function requires white space (like a square-thick border, the wider the better) around +the board to make the detection more robust in various environments. Otherwise, if there is no +border and the background is dark, the outer black squares cannot be segmented properly and so the +square grouping and ordering algorithm fails. + +Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) +to create the desired checkerboard pattern. + */ +CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, + int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE ); + +/* + Checks whether the image contains chessboard of the specific size or not. + If yes, nonzero value is returned. +*/ +CV_EXPORTS_W bool checkChessboard(InputArray img, Size size); + +/** @brief Finds the positions of internal corners of the chessboard using a sector based approach. + +@param image Source chessboard view. It must be an 8-bit grayscale or color image. +@param patternSize Number of inner corners per a chessboard row and column +( patternSize = cv::Size(points_per_row,points_per_column) = cv::Size(columns,rows) ). +@param corners Output array of detected corners. +@param flags Various operation flags that can be zero or a combination of the following values: +- @ref CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with equalizeHist before detection. +- @ref CALIB_CB_EXHAUSTIVE Run an exhaustive search to improve detection rate. +- @ref CALIB_CB_ACCURACY Up sample input image to improve sub-pixel accuracy due to aliasing effects. +- @ref CALIB_CB_LARGER The detected pattern is allowed to be larger than patternSize (see description). +- @ref CALIB_CB_MARKER The detected pattern must have a marker (see description). +This should be used if an accurate camera calibration is required. +@param meta Optional output array of detected corners (CV_8UC1 and size = cv::Size(columns,rows)). +Each entry stands for one corner of the pattern and can have one of the following values: +- 0 = no meta data attached +- 1 = left-top corner of a black cell +- 2 = left-top corner of a white cell +- 3 = left-top corner of a black cell with a white marker dot +- 4 = left-top corner of a white cell with a black marker dot (pattern origin in case of markers otherwise first corner) + +The function is analog to #findChessboardCorners but uses a localized radon +transformation approximated by box filters being more robust to all sort of +noise, faster on larger images and is able to directly return the sub-pixel +position of the internal chessboard corners. The Method is based on the paper +@cite duda2018 "Accurate Detection and Localization of Checkerboard Corners for +Calibration" demonstrating that the returned sub-pixel positions are more +accurate than the one returned by cornerSubPix allowing a precise camera +calibration for demanding applications. + +In the case, the flags @ref CALIB_CB_LARGER or @ref CALIB_CB_MARKER are given, +the result can be recovered from the optional meta array. Both flags are +helpful to use calibration patterns exceeding the field of view of the camera. +These oversized patterns allow more accurate calibrations as corners can be +utilized, which are as close as possible to the image borders. For a +consistent coordinate system across all images, the optional marker (see image +below) can be used to move the origin of the board to the location where the +black circle is located. + +@note The function requires a white boarder with roughly the same width as one +of the checkerboard fields around the whole board to improve the detection in +various environments. In addition, because of the localized radon +transformation it is beneficial to use round corners for the field corners +which are located on the outside of the board. The following figure illustrates +a sample checkerboard optimized for the detection. However, any other checkerboard +can be used as well. + +Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) +to create the corresponding checkerboard pattern: +\image html pics/checkerboard_radon.png width=60% + */ +CV_EXPORTS_AS(findChessboardCornersSBWithMeta) +bool findChessboardCornersSB(InputArray image,Size patternSize, OutputArray corners, + int flags,OutputArray meta); +/** @overload */ +CV_EXPORTS_W inline +bool findChessboardCornersSB(InputArray image, Size patternSize, OutputArray corners, + int flags = 0) +{ + return findChessboardCornersSB(image, patternSize, corners, flags, noArray()); +} + +/** @brief Estimates the sharpness of a detected chessboard. + +Image sharpness, as well as brightness, are a critical parameter for accuracte +camera calibration. For accessing these parameters for filtering out +problematic calibraiton images, this method calculates edge profiles by traveling from +black to white chessboard cell centers. Based on this, the number of pixels is +calculated required to transit from black to white. This width of the +transition area is a good indication of how sharp the chessboard is imaged +and should be below ~3.0 pixels. + +@param image Gray image used to find chessboard corners +@param patternSize Size of a found chessboard pattern +@param corners Corners found by #findChessboardCornersSB +@param rise_distance Rise distance 0.8 means 10% ... 90% of the final signal strength +@param vertical By default edge responses for horizontal lines are calculated +@param sharpness Optional output array with a sharpness value for calculated edge responses (see description) + +The optional sharpness array is of type CV_32FC1 and has for each calculated +profile one row with the following five entries: +* 0 = x coordinate of the underlying edge in the image +* 1 = y coordinate of the underlying edge in the image +* 2 = width of the transition area (sharpness) +* 3 = signal strength in the black cell (min brightness) +* 4 = signal strength in the white cell (max brightness) + +@return Scalar(average sharpness, average min brightness, average max brightness,0) +*/ +CV_EXPORTS_W Scalar estimateChessboardSharpness(InputArray image, Size patternSize, InputArray corners, + float rise_distance=0.8F,bool vertical=false, + OutputArray sharpness=noArray()); + + +//! finds subpixel-accurate positions of the chessboard corners +CV_EXPORTS_W bool find4QuadCornerSubpix( InputArray img, InputOutputArray corners, Size region_size ); + +/** @brief Renders the detected chessboard corners. + +@param image Destination image. It must be an 8-bit color image. +@param patternSize Number of inner corners per a chessboard row and column +(patternSize = cv::Size(points_per_row,points_per_column)). +@param corners Array of detected corners, the output of #findChessboardCorners. +@param patternWasFound Parameter indicating whether the complete board was found or not. The +return value of #findChessboardCorners should be passed here. + +The function draws individual chessboard corners detected either as red circles if the board was not +found, or as colored corners connected with lines if the board was found. + */ +CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize, + InputArray corners, bool patternWasFound ); + +struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters +{ + CV_WRAP CirclesGridFinderParameters(); + CV_PROP_RW cv::Size2f densityNeighborhoodSize; + CV_PROP_RW float minDensity; + CV_PROP_RW int kmeansAttempts; + CV_PROP_RW int minDistanceToAddKeypoint; + CV_PROP_RW int keypointScale; + CV_PROP_RW float minGraphConfidence; + CV_PROP_RW float vertexGain; + CV_PROP_RW float vertexPenalty; + CV_PROP_RW float existingVertexGain; + CV_PROP_RW float edgeGain; + CV_PROP_RW float edgePenalty; + CV_PROP_RW float convexHullFactor; + CV_PROP_RW float minRNGEdgeSwitchDist; + + enum GridType + { + SYMMETRIC_GRID, ASYMMETRIC_GRID + }; + CV_PROP_RW GridType gridType; + + CV_PROP_RW float squareSize; //!< Distance between two adjacent points. Used by CALIB_CB_CLUSTERING. + CV_PROP_RW float maxRectifiedDistance; //!< Max deviation from prediction. Used by CALIB_CB_CLUSTERING. +}; + +/** @brief Finds centers in the grid of circles. + +@param image grid view of input circles; it must be an 8-bit grayscale or color image. +@param patternSize number of circles per row and column +( patternSize = Size(points_per_row, points_per_column) ). +@param centers output array of detected centers. +@param flags various operation flags that can be one of the following values: +- @ref CALIB_CB_SYMMETRIC_GRID uses symmetric pattern of circles. +- @ref CALIB_CB_ASYMMETRIC_GRID uses asymmetric pattern of circles. +- @ref CALIB_CB_CLUSTERING uses a special algorithm for grid detection. It is more robust to +perspective distortions but much more sensitive to background clutter. +@param blobDetector feature detector that finds blobs like dark circles on light background. + If `blobDetector` is NULL then `image` represents Point2f array of candidates. +@param parameters struct for finding circles in a grid pattern. + +The function attempts to determine whether the input image contains a grid of circles. If it is, the +function locates centers of the circles. The function returns a non-zero value if all of the centers +have been found and they have been placed in a certain order (row by row, left to right in every +row). Otherwise, if the function fails to find all the corners or reorder them, it returns 0. + +Sample usage of detecting and drawing the centers of circles: : +@code + Size patternsize(7,7); //number of centers + Mat gray = ...; //source image + vector centers; //this will be filled by the detected centers + + bool patternfound = findCirclesGrid(gray, patternsize, centers); + + drawChessboardCorners(img, patternsize, Mat(centers), patternfound); +@endcode +@note The function requires white space (like a square-thick border, the wider the better) around +the board to make the detection more robust in various environments. + */ +CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, + OutputArray centers, int flags, + const Ptr &blobDetector, + const CirclesGridFinderParameters& parameters); + +/** @overload */ +CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, + OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID, + const Ptr &blobDetector = cv::SimpleBlobDetector::create()); + //! @} } diff --git a/modules/objdetect/misc/java/gen_dict.json b/modules/objdetect/misc/java/gen_dict.json index 376c7ad920..142b5f7efe 100644 --- a/modules/objdetect/misc/java/gen_dict.json +++ b/modules/objdetect/misc/java/gen_dict.json @@ -65,5 +65,9 @@ "suffix": "Ljava_util_List", "v_type": "vector_NativeByteArray" } + }, + "func_arg_fix" : { + "findChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} }, + "drawChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} } } } diff --git a/modules/objdetect/misc/java/test/ObjdetectTest.java b/modules/objdetect/misc/java/test/ObjdetectTest.java new file mode 100644 index 0000000000..8d62eed711 --- /dev/null +++ b/modules/objdetect/misc/java/test/ObjdetectTest.java @@ -0,0 +1,100 @@ +package org.opencv.test.objdetect; + +import java.util.ArrayList; + +import org.opencv.cv3d.Cv3d; +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDouble; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.MatOfPoint3f; +import org.opencv.core.Point; +import org.opencv.core.Scalar; +import org.opencv.core.Size; +import org.opencv.objdetect.Objdetect; +import org.opencv.test.OpenCVTestCase; +import org.opencv.imgproc.Imgproc; + +public class ObjdetectTest extends OpenCVTestCase { + + Size size; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + size = new Size(3, 3); + } + + public void testFindChessboardCornersMatSizeMat() { + Size patternSize = new Size(9, 6); + MatOfPoint2f corners = new MatOfPoint2f(); + Objdetect.findChessboardCorners(grayChess, patternSize, corners); + assertFalse(corners.empty()); + } + + public void testFindChessboardCornersMatSizeMatInt() { + Size patternSize = new Size(9, 6); + MatOfPoint2f corners = new MatOfPoint2f(); + Objdetect.findChessboardCorners(grayChess, patternSize, corners, Objdetect.CALIB_CB_ADAPTIVE_THRESH + Objdetect.CALIB_CB_NORMALIZE_IMAGE + + Objdetect.CALIB_CB_FAST_CHECK); + assertFalse(corners.empty()); + } + + public void testFind4QuadCornerSubpix() { + Size patternSize = new Size(9, 6); + MatOfPoint2f corners = new MatOfPoint2f(); + Size region_size = new Size(5, 5); + Objdetect.findChessboardCorners(grayChess, patternSize, corners); + Objdetect.find4QuadCornerSubpix(grayChess, corners, region_size); + assertFalse(corners.empty()); + } + + public void testFindCirclesGridMatSizeMat() { + int size = 300; + Mat img = new Mat(size, size, CvType.CV_8U); + img.setTo(new Scalar(255)); + Mat centers = new Mat(); + + assertFalse(Objdetect.findCirclesGrid(img, new Size(5, 5), centers)); + + for (int i = 0; i < 5; i++) + for (int j = 0; j < 5; j++) { + Point pt = new Point(size * (2 * i + 1) / 10, size * (2 * j + 1) / 10); + Imgproc.circle(img, pt, 10, new Scalar(0), -1); + } + + assertTrue(Objdetect.findCirclesGrid(img, new Size(5, 5), centers)); + + assertEquals(1, centers.rows()); + assertEquals(25, centers.cols()); + assertEquals(CvType.CV_32FC2, centers.type()); + } + + public void testFindCirclesGridMatSizeMatInt() { + int size = 300; + Mat img = new Mat(size, size, CvType.CV_8U); + img.setTo(new Scalar(255)); + Mat centers = new Mat(); + + assertFalse(Objdetect.findCirclesGrid(img, new Size(3, 5), centers, Objdetect.CALIB_CB_CLUSTERING + | Objdetect.CALIB_CB_ASYMMETRIC_GRID)); + + int step = size * 2 / 15; + int offsetx = size / 6; + int offsety = (size - 4 * step) / 2; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 5; j++) { + Point pt = new Point(offsetx + (2 * i + j % 2) * step, offsety + step * j); + Imgproc.circle(img, pt, 10, new Scalar(0), -1); + } + + assertTrue(Objdetect.findCirclesGrid(img, new Size(3, 5), centers, Objdetect.CALIB_CB_CLUSTERING + | Objdetect.CALIB_CB_ASYMMETRIC_GRID)); + + assertEquals(1, centers.rows()); + assertEquals(15, centers.cols()); + assertEquals(CvType.CV_32FC2, centers.type()); + } +} diff --git a/modules/objdetect/misc/objc/gen_dict.json b/modules/objdetect/misc/objc/gen_dict.json index 0311e1e5d6..f11d265e48 100644 --- a/modules/objdetect/misc/objc/gen_dict.json +++ b/modules/objdetect/misc/objc/gen_dict.json @@ -3,5 +3,10 @@ "QRCodeDetectorAruco": { "getDetectorParameters": { "declaration" : [""], "implementation" : [""] } } + }, + "func_arg_fix" : { + "Calib" : { + "findCirclesGrid" : { "blobDetector" : {"defval" : "cv::SimpleBlobDetector::create()"} } + } } } diff --git a/modules/objdetect/misc/objc/test/ObjdetectTest.swift b/modules/objdetect/misc/objc/test/ObjdetectTest.swift new file mode 100644 index 0000000000..c56f92e9d8 --- /dev/null +++ b/modules/objdetect/misc/objc/test/ObjdetectTest.swift @@ -0,0 +1,88 @@ +import XCTest +import OpenCV + +class ObjdetectTest: OpenCVTestCase { + + var size = Size() + + override func setUp() { + super.setUp() + size = Size(width: 3, height: 3) + } + + override func tearDown() { + super.tearDown() + } + + func testFindChessboardCornersMatSizeMat() { + let patternSize = Size(width: 9, height: 6) + let corners = MatOfPoint2f() + Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners) + XCTAssertFalse(corners.empty()) + } + + func testFindChessboardCornersMatSizeMatInt() { + let patternSize = Size(width: 9, height: 6) + let corners = MatOfPoint2f() + Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners, flags: Calib.CALIB_CB_ADAPTIVE_THRESH + Calib.CALIB_CB_NORMALIZE_IMAGE + Calib.CALIB_CB_FAST_CHECK) + XCTAssertFalse(corners.empty()) + } + + func testFind4QuadCornerSubpix() { + let patternSize = Size(width: 9, height: 6) + let corners = MatOfPoint2f() + let region_size = Size(width: 5, height: 5) + Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners) + Calib.find4QuadCornerSubpix(img: grayChess, corners: corners, region_size: region_size) + XCTAssertFalse(corners.empty()) + } + + func testFindCirclesGridMatSizeMat() { + let size = 300 + let img = Mat(rows:Int32(size), cols:Int32(size), type:CvType.CV_8U) + img.setTo(scalar: Scalar(255)) + let centers = Mat() + + XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 5, height: 5), centers: centers)) + + for i in 0..<5 { + for j in 0..<5 { + let x = Int32(size * (2 * i + 1) / 10) + let y = Int32(size * (2 * j + 1) / 10) + let pt = Point(x: x, y: y) + Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1) + } + } + + XCTAssert(Calib.findCirclesGrid(image: img, patternSize:Size(width:5, height:5), centers:centers)) + + XCTAssertEqual(25, centers.rows()) + XCTAssertEqual(1, centers.cols()) + XCTAssertEqual(CvType.CV_32FC2, centers.type()) + } + + func testFindCirclesGridMatSizeMatInt() { + let size:Int32 = 300 + let img = Mat(rows:size, cols: size, type: CvType.CV_8U) + img.setTo(scalar: Scalar(255)) + let centers = Mat() + + XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID)) + + let step = size * 2 / 15 + let offsetx = size / 6 + let offsety = (size - 4 * step) / 2 + for i:Int32 in 0...2 { + for j:Int32 in 0...4 { + let pt = Point(x: offsetx + (2 * i + j % 2) * step, y: offsety + step * j) + Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1) + } + } + + XCTAssert(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID)) + + XCTAssertEqual(15, centers.rows()) + XCTAssertEqual(1, centers.cols()) + XCTAssertEqual(CvType.CV_32FC2, centers.type()) + } +} diff --git a/modules/calib/perf/perf_cicrlesGrid.cpp b/modules/objdetect/perf/perf_cicrlesGrid.cpp similarity index 100% rename from modules/calib/perf/perf_cicrlesGrid.cpp rename to modules/objdetect/perf/perf_cicrlesGrid.cpp diff --git a/modules/calib/src/calibinit.cpp b/modules/objdetect/src/calibinit.cpp similarity index 99% rename from modules/calib/src/calibinit.cpp rename to modules/objdetect/src/calibinit.cpp index 5c9232f89e..5a651506ec 100644 --- a/modules/calib/src/calibinit.cpp +++ b/modules/objdetect/src/calibinit.cpp @@ -71,6 +71,7 @@ #include "precomp.hpp" #include "circlesgrid.hpp" +#include "opencv2/3d.hpp" #include "opencv2/flann.hpp" #include diff --git a/modules/calib/src/checkchessboard.cpp b/modules/objdetect/src/checkchessboard.cpp similarity index 100% rename from modules/calib/src/checkchessboard.cpp rename to modules/objdetect/src/checkchessboard.cpp diff --git a/modules/calib/src/chessboard.cpp b/modules/objdetect/src/chessboard.cpp similarity index 99% rename from modules/calib/src/chessboard.cpp rename to modules/objdetect/src/chessboard.cpp index 8ac01ee3a8..279745c3c4 100644 --- a/modules/calib/src/chessboard.cpp +++ b/modules/objdetect/src/chessboard.cpp @@ -4,6 +4,7 @@ #include "precomp.hpp" #include "opencv2/flann.hpp" +#include "opencv2/3d.hpp" #include "chessboard.hpp" #include "math.h" diff --git a/modules/calib/src/chessboard.hpp b/modules/objdetect/src/chessboard.hpp similarity index 100% rename from modules/calib/src/chessboard.hpp rename to modules/objdetect/src/chessboard.hpp diff --git a/modules/calib/src/circlesgrid.cpp b/modules/objdetect/src/circlesgrid.cpp similarity index 99% rename from modules/calib/src/circlesgrid.cpp rename to modules/objdetect/src/circlesgrid.cpp index 77e45719ad..d1a38ad8e6 100644 --- a/modules/calib/src/circlesgrid.cpp +++ b/modules/objdetect/src/circlesgrid.cpp @@ -57,6 +57,8 @@ # endif #endif +#include "opencv2/3d.hpp" + namespace cv { #ifdef DEBUG_CIRCLES diff --git a/modules/calib/src/circlesgrid.hpp b/modules/objdetect/src/circlesgrid.hpp similarity index 100% rename from modules/calib/src/circlesgrid.hpp rename to modules/objdetect/src/circlesgrid.hpp diff --git a/modules/objdetect/src/precomp.hpp b/modules/objdetect/src/precomp.hpp index 82ecec2751..9546892bda 100644 --- a/modules/objdetect/src/precomp.hpp +++ b/modules/objdetect/src/precomp.hpp @@ -48,6 +48,7 @@ #include "opencv2/objdetect/barcode.hpp" #include "opencv2/imgproc.hpp" +#include #include "opencv2/core/utility.hpp" #include "opencv2/core/ocl.hpp" #include "opencv2/core/private.hpp" @@ -56,4 +57,11 @@ #include #include +namespace cv { + +int checkChessboardBinary(const Mat & img, const Size & size); + + +} + #endif diff --git a/modules/calib/src/quadsubpix.cpp b/modules/objdetect/src/quadsubpix.cpp similarity index 100% rename from modules/calib/src/quadsubpix.cpp rename to modules/objdetect/src/quadsubpix.cpp diff --git a/modules/objdetect/test/test_chessboardgenerator.cpp b/modules/objdetect/test/test_chessboardgenerator.cpp new file mode 100644 index 0000000000..da7cd8e094 --- /dev/null +++ b/modules/objdetect/test/test_chessboardgenerator.cpp @@ -0,0 +1,331 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// + // + // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. + // + // By downloading, copying, installing or using the software you agree to this license. + // If you do not agree to this license, do not download, install, + // copy or use the software. + // + // + // License Agreement + // For Open Source Computer Vision Library + // + // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. + // Copyright (C) 2009, Willow Garage Inc., all rights reserved. + // Third party copyrights are property of their respective owners. + // + // Redistribution and use in source and binary forms, with or without modification, + // are permitted provided that the following conditions are met: + // + // * Redistribution's of source code must retain the above copyright notice, + // this list of conditions and the following disclaimer. + // + // * Redistribution's in binary form must reproduce the above copyright notice, + // this list of conditions and the following disclaimer in the documentation + // and/or other materials provided with the distribution. + // + // * The name of the copyright holders may not be used to endorse or promote products + // derived from this software without specific prior written permission. + // + // This software is provided by the copyright holders and contributors "as is" and + // any express or implied warranties, including, but not limited to, the implied + // warranties of merchantability and fitness for a particular purpose are disclaimed. + // In no event shall the Intel Corporation or contributors be liable for any direct, + // indirect, incidental, special, exemplary, or consequential damages + // (including, but not limited to, procurement of substitute goods or services; + // loss of use, data, or profits; or business interruption) however caused + // and on any theory of liability, whether in contract, strict liability, + // or tort (including negligence or otherwise) arising in any way out of + // the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "test_precomp.hpp" +#include "test_chessboardgenerator.hpp" + +namespace cv { + +ChessBoardGenerator::ChessBoardGenerator(const Size& _patternSize) : sensorWidth(32), sensorHeight(24), + squareEdgePointsNum(200), min_cos(std::sqrt(3.f)*0.5f), cov(0.5), + patternSize(_patternSize), rendererResolutionMultiplier(4), tvec(Mat::zeros(1, 3, CV_32F)) +{ + rvec.create(3, 1, CV_32F); + Rodrigues(Mat::eye(3, 3, CV_32F), rvec); +} + +void ChessBoardGenerator::generateEdge(const Point3f& p1, const Point3f& p2, vector& out) const +{ + Point3f step = (p2 - p1) * (1.f/squareEdgePointsNum); + for(size_t n = 0; n < squareEdgePointsNum; ++n) + out.push_back( p1 + step * (float)n); +} + +Size ChessBoardGenerator::cornersSize() const +{ + return Size(patternSize.width-1, patternSize.height-1); +} + +struct Mult +{ + float m; + Mult(int mult) : m((float)mult) {} + Point2f operator()(const Point2f& p)const { return p * m; } +}; + +void ChessBoardGenerator::generateBasis(Point3f& pb1, Point3f& pb2) const +{ + RNG& rng = theRNG(); + + Vec3f n; + for(;;) + { + n[0] = rng.uniform(-1.f, 1.f); + n[1] = rng.uniform(-1.f, 1.f); + n[2] = rng.uniform(0.0f, 1.f); + float len = (float)norm(n); + if (len < 1e-3) + continue; + n[0]/=len; + n[1]/=len; + n[2]/=len; + + if (n[2] > min_cos) + break; + } + + Vec3f n_temp = n; n_temp[0] += 100; + Vec3f b1 = n.cross(n_temp); + Vec3f b2 = n.cross(b1); + float len_b1 = (float)norm(b1); + float len_b2 = (float)norm(b2); + + pb1 = Point3f(b1[0]/len_b1, b1[1]/len_b1, b1[2]/len_b1); + pb2 = Point3f(b2[0]/len_b1, b2[1]/len_b2, b2[2]/len_b2); +} + + +Mat ChessBoardGenerator::generateChessBoard(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, + const Point3f& zero, const Point3f& pb1, const Point3f& pb2, + float sqWidth, float sqHeight, const vector& whole, + vector& corners) const +{ + vector< vector > squares_black; + for(int i = 0; i < patternSize.width; ++i) + for(int j = 0; j < patternSize.height; ++j) + if ( (i % 2 == 0 && j % 2 == 0) || (i % 2 != 0 && j % 2 != 0) ) + { + vector pts_square3d; + vector pts_square2d; + + Point3f p1 = zero + (i + 0) * sqWidth * pb1 + (j + 0) * sqHeight * pb2; + Point3f p2 = zero + (i + 1) * sqWidth * pb1 + (j + 0) * sqHeight * pb2; + Point3f p3 = zero + (i + 1) * sqWidth * pb1 + (j + 1) * sqHeight * pb2; + Point3f p4 = zero + (i + 0) * sqWidth * pb1 + (j + 1) * sqHeight * pb2; + generateEdge(p1, p2, pts_square3d); + generateEdge(p2, p3, pts_square3d); + generateEdge(p3, p4, pts_square3d); + generateEdge(p4, p1, pts_square3d); + + projectPoints(pts_square3d, rvec, tvec, camMat, distCoeffs, pts_square2d); + squares_black.resize(squares_black.size() + 1); + vector temp; + approxPolyDP(pts_square2d, temp, 1.0, true); + transform(temp.begin(), temp.end(), back_inserter(squares_black.back()), Mult(rendererResolutionMultiplier)); + } + + /* calculate corners */ + corners3d.clear(); + for(int j = 0; j < patternSize.height - 1; ++j) + for(int i = 0; i < patternSize.width - 1; ++i) + corners3d.push_back(zero + (i + 1) * sqWidth * pb1 + (j + 1) * sqHeight * pb2); + corners.clear(); + projectPoints(corners3d, rvec, tvec, camMat, distCoeffs, corners); + + vector whole3d; + vector whole2d; + generateEdge(whole[0], whole[1], whole3d); + generateEdge(whole[1], whole[2], whole3d); + generateEdge(whole[2], whole[3], whole3d); + generateEdge(whole[3], whole[0], whole3d); + projectPoints(whole3d, rvec, tvec, camMat, distCoeffs, whole2d); + vector temp_whole2d; + approxPolyDP(whole2d, temp_whole2d, 1.0, true); + + vector< vector > whole_contour(1); + transform(temp_whole2d.begin(), temp_whole2d.end(), + back_inserter(whole_contour.front()), Mult(rendererResolutionMultiplier)); + + Mat result; + if (rendererResolutionMultiplier == 1) + { + result = bg.clone(); + drawContours(result, whole_contour, -1, Scalar::all(255), FILLED, LINE_AA); + drawContours(result, squares_black, -1, Scalar::all(0), FILLED, LINE_AA); + } + else + { + Mat tmp; + resize(bg, tmp, bg.size() * rendererResolutionMultiplier, 0, 0, INTER_LINEAR_EXACT); + drawContours(tmp, whole_contour, -1, Scalar::all(255), FILLED, LINE_AA); + drawContours(tmp, squares_black, -1, Scalar::all(0), FILLED, LINE_AA); + resize(tmp, result, bg.size(), 0, 0, INTER_AREA); + } + + return result; +} + +Mat ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, vector& corners) const +{ + cov = std::min(cov, 0.8); + double fovx, fovy, focalLen; + Point2d principalPoint; + double aspect; + calibrationMatrixValues( camMat, bg.size(), sensorWidth, sensorHeight, + fovx, fovy, focalLen, principalPoint, aspect); + + RNG& rng = theRNG(); + + float d1 = static_cast(rng.uniform(0.1, 10.0)); + float ah = static_cast(rng.uniform(-fovx/2 * cov, fovx/2 * cov) * CV_PI / 180); + float av = static_cast(rng.uniform(-fovy/2 * cov, fovy/2 * cov) * CV_PI / 180); + + Point3f p; + p.z = std::cos(ah) * d1; + p.x = std::sin(ah) * d1; + p.y = p.z * std::tan(av); + + Point3f pb1, pb2; + generateBasis(pb1, pb2); + + float cbHalfWidth = static_cast(norm(p) * std::sin( std::min(fovx, fovy) * 0.5 * CV_PI / 180)); + float cbHalfHeight = cbHalfWidth * patternSize.height / patternSize.width; + + float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width; + float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height; + + vector pts3d(4); + vector pts2d(4); + for(;;) + { + pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2; + pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2; + pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2; + pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2; + + /* can remake with better perf */ + projectPoints(pts3d, rvec, tvec, camMat, distCoeffs, pts2d); + + bool inrect1 = pts2d[0].x < bg.cols && pts2d[0].y < bg.rows && pts2d[0].x > 0 && pts2d[0].y > 0; + bool inrect2 = pts2d[1].x < bg.cols && pts2d[1].y < bg.rows && pts2d[1].x > 0 && pts2d[1].y > 0; + bool inrect3 = pts2d[2].x < bg.cols && pts2d[2].y < bg.rows && pts2d[2].x > 0 && pts2d[2].y > 0; + bool inrect4 = pts2d[3].x < bg.cols && pts2d[3].y < bg.rows && pts2d[3].x > 0 && pts2d[3].y > 0; + + if (inrect1 && inrect2 && inrect3 && inrect4) + break; + + cbHalfWidth*=0.8f; + cbHalfHeight = cbHalfWidth * patternSize.height / patternSize.width; + + cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width; + cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height; + } + + Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2; + float sqWidth = 2 * cbHalfWidth/patternSize.width; + float sqHeight = 2 * cbHalfHeight/patternSize.height; + + return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2, sqWidth, sqHeight, pts3d, corners); +} + + +Mat ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, + const Size2f& squareSize, vector& corners) const +{ + cov = std::min(cov, 0.8); + double fovx, fovy, focalLen; + Point2d principalPoint; + double aspect; + calibrationMatrixValues( camMat, bg.size(), sensorWidth, sensorHeight, + fovx, fovy, focalLen, principalPoint, aspect); + + RNG& rng = theRNG(); + + float d1 = static_cast(rng.uniform(0.1, 10.0)); + float ah = static_cast(rng.uniform(-fovx/2 * cov, fovx/2 * cov) * CV_PI / 180); + float av = static_cast(rng.uniform(-fovy/2 * cov, fovy/2 * cov) * CV_PI / 180); + + Point3f p; + p.z = std::cos(ah) * d1; + p.x = std::sin(ah) * d1; + p.y = p.z * std::tan(av); + + Point3f pb1, pb2; + generateBasis(pb1, pb2); + + float cbHalfWidth = squareSize.width * patternSize.width * 0.5f; + float cbHalfHeight = squareSize.height * patternSize.height * 0.5f; + + float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width; + float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height; + + vector pts3d(4); + vector pts2d(4); + for(;;) + { + pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2; + pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2; + pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2; + pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2; + + /* can remake with better perf */ + projectPoints(pts3d, rvec, tvec, camMat, distCoeffs, pts2d); + + bool inrect1 = pts2d[0].x < bg.cols && pts2d[0].y < bg.rows && pts2d[0].x > 0 && pts2d[0].y > 0; + bool inrect2 = pts2d[1].x < bg.cols && pts2d[1].y < bg.rows && pts2d[1].x > 0 && pts2d[1].y > 0; + bool inrect3 = pts2d[2].x < bg.cols && pts2d[2].y < bg.rows && pts2d[2].x > 0 && pts2d[2].y > 0; + bool inrect4 = pts2d[3].x < bg.cols && pts2d[3].y < bg.rows && pts2d[3].x > 0 && pts2d[3].y > 0; + + if ( inrect1 && inrect2 && inrect3 && inrect4) + break; + + p.z *= 1.1f; + } + + Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2; + + return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2, + squareSize.width, squareSize.height, pts3d, corners); +} + +Mat ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, + const Size2f& squareSize, const Point3f& pos, vector& corners) const +{ + cov = std::min(cov, 0.8); + Point3f p = pos; + Point3f pb1, pb2; + generateBasis(pb1, pb2); + + float cbHalfWidth = squareSize.width * patternSize.width * 0.5f; + float cbHalfHeight = squareSize.height * patternSize.height * 0.5f; + + float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width; + float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height; + + vector pts3d(4); + vector pts2d(4); + + pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2; + pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2; + pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2; + pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2; + + /* can remake with better perf */ + projectPoints(pts3d, rvec, tvec, camMat, distCoeffs, pts2d); + + Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2; + + return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2, + squareSize.width, squareSize.height, pts3d, corners); +} + +} // namespace diff --git a/modules/objdetect/test/test_chessboardgenerator.hpp b/modules/objdetect/test/test_chessboardgenerator.hpp new file mode 100644 index 0000000000..c416c6b05c --- /dev/null +++ b/modules/objdetect/test/test_chessboardgenerator.hpp @@ -0,0 +1,43 @@ +// 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 CV_CHESSBOARDGENERATOR_H143KJTVYM389YTNHKFDHJ89NYVMO3VLMEJNTBGUEIYVCM203P +#define CV_CHESSBOARDGENERATOR_H143KJTVYM389YTNHKFDHJ89NYVMO3VLMEJNTBGUEIYVCM203P + +namespace cv +{ + +using std::vector; + +class ChessBoardGenerator +{ +public: + double sensorWidth; + double sensorHeight; + size_t squareEdgePointsNum; + double min_cos; + mutable double cov; + Size patternSize; + int rendererResolutionMultiplier; + + ChessBoardGenerator(const Size& patternSize = Size(8, 6)); + Mat operator()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, std::vector& corners) const; + Mat operator()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, const Size2f& squareSize, std::vector& corners) const; + Mat operator()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, const Size2f& squareSize, const Point3f& pos, std::vector& corners) const; + Size cornersSize() const; + + mutable std::vector corners3d; +private: + void generateEdge(const Point3f& p1, const Point3f& p2, std::vector& out) const; + Mat generateChessBoard(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, + const Point3f& zero, const Point3f& pb1, const Point3f& pb2, + float sqWidth, float sqHeight, const std::vector& whole, std::vector& corners) const; + void generateBasis(Point3f& pb1, Point3f& pb2) const; + + Mat rvec, tvec; +}; + +} + + +#endif diff --git a/modules/calib/test/test_chesscorners.cpp b/modules/objdetect/test/test_chesscorners.cpp similarity index 98% rename from modules/calib/test/test_chesscorners.cpp rename to modules/objdetect/test/test_chesscorners.cpp index f391e42e6a..9570c22a6c 100644 --- a/modules/calib/test/test_chesscorners.cpp +++ b/modules/objdetect/test/test_chesscorners.cpp @@ -211,13 +211,13 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) case CHESSBOARD: case CHESSBOARD_SB: case CHESSBOARD_PLAIN: - folder = string(ts->get_data_path()) + "cv/cameracalibration/"; + folder = string(ts->get_data_path()) + "cameracalibration/"; break; case CIRCLES_GRID: - folder = string(ts->get_data_path()) + "cv/cameracalibration/circles/"; + folder = string(ts->get_data_path()) + "cameracalibration/circles/"; break; case ASYMMETRIC_CIRCLES_GRID: - folder = string(ts->get_data_path()) + "cv/cameracalibration/asymmetric_circles/"; + folder = string(ts->get_data_path()) + "cameracalibration/asymmetric_circles/"; break; } @@ -681,8 +681,9 @@ TEST(Calib3d_AsymmetricCirclesPatternDetectorWithClustering, accuracy) { CV_Ches TEST(Calib3d_ChessboardWithMarkers, regression_25806_white) { - const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/"; + const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cameracalibration/"; const cv::Mat image = cv::imread(dataDir + "checkerboard_marker_white.png"); + ASSERT_FALSE(image.empty()); std::vector corners; const bool success = cv::findChessboardCornersSB(image, Size(9, 14), corners, CALIB_CB_MARKER); @@ -691,8 +692,9 @@ TEST(Calib3d_ChessboardWithMarkers, regression_25806_white) TEST(Calib3d_ChessboardWithMarkers, regression_25806_black) { - const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/"; + const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cameracalibration/"; const cv::Mat image = cv::imread(dataDir + "checkerboard_marker_black.png"); + ASSERT_FALSE(image.empty()); std::vector corners; const bool success = cv::findChessboardCornersSB(image, Size(9, 14), corners, CALIB_CB_MARKER); @@ -701,7 +703,7 @@ TEST(Calib3d_ChessboardWithMarkers, regression_25806_black) TEST(Calib3d_CirclesPatternDetectorWithClustering, accuracy) { - cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/circles/"; + cv::String dataDir = string(TS::ptr()->get_data_path()) + "cameracalibration/circles/"; cv::Mat expected; FileStorage fs(dataDir + "circles_corners15.dat", FileStorage::READ); @@ -709,6 +711,7 @@ TEST(Calib3d_CirclesPatternDetectorWithClustering, accuracy) fs.release(); cv::Mat image = cv::imread(dataDir + "circles15.png"); + ASSERT_FALSE(image.empty()); std::vector centers; cv::findCirclesGrid(image, Size(10, 8), centers, CALIB_CB_SYMMETRIC_GRID | CALIB_CB_CLUSTERING); @@ -814,7 +817,7 @@ TEST(Calib3d_AsymmetricCirclesPatternDetector, regression_19498) TEST(Calib3d_RotatedCirclesPatternDetector, issue_24964) { - string path = cvtest::findDataFile("cv/cameracalibration/circles/circles_24964.png"); + string path = cvtest::findDataFile("cameracalibration/circles/circles_24964.png"); Mat image = cv::imread(path); ASSERT_FALSE(image.empty()) << "Can't read image: " << path; @@ -850,7 +853,7 @@ TEST(Calib3d_RotatedCirclesPatternDetector, issue_24964) } TEST(Calib3d_CornerOrdering, issue_26830) { - const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/"; + const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cameracalibration/"; const cv::Mat image = cv::imread(dataDir + "checkerboard_marker_white.png"); std::vector cornersMinimumSizeMatchesPatternSize; diff --git a/modules/calib/test/test_chesscorners_badarg.cpp b/modules/objdetect/test/test_chesscorners_badarg.cpp similarity index 100% rename from modules/calib/test/test_chesscorners_badarg.cpp rename to modules/objdetect/test/test_chesscorners_badarg.cpp diff --git a/modules/calib/test/test_chesscorners_timing.cpp b/modules/objdetect/test/test_chesscorners_timing.cpp similarity index 98% rename from modules/calib/test/test_chesscorners_timing.cpp rename to modules/objdetect/test/test_chesscorners_timing.cpp index 6c8ea6f0bf..c0154a2df8 100644 --- a/modules/calib/test/test_chesscorners_timing.cpp +++ b/modules/objdetect/test/test_chesscorners_timing.cpp @@ -72,7 +72,7 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) int idx, max_idx; int progress = 0; - filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() ); + filepath = cv::format("%scameracalibration/", ts->get_data_path().c_str() ); filename = cv::format("%schessboard_timing_list.dat", filepath.c_str() ); cv::FileStorage fs( filename, FileStorage::READ ); cv::FileNode board_list = fs["boards"]; diff --git a/modules/calib/test/test_cornerssubpix.cpp b/modules/objdetect/test/test_cornerssubpix.cpp similarity index 100% rename from modules/calib/test/test_cornerssubpix.cpp rename to modules/objdetect/test/test_cornerssubpix.cpp diff --git a/modules/objdetect/test/test_precomp.hpp b/modules/objdetect/test/test_precomp.hpp index 452a0d78d6..14b5befda5 100644 --- a/modules/objdetect/test/test_precomp.hpp +++ b/modules/objdetect/test/test_precomp.hpp @@ -5,6 +5,7 @@ #define __OPENCV_TEST_PRECOMP_HPP__ #include "opencv2/ts.hpp" +#include "opencv2/3d.hpp" #include "opencv2/objdetect.hpp" #include diff --git a/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrator.java b/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrator.java index caf351b758..670305b25e 100644 --- a/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrator.java +++ b/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrator.java @@ -15,6 +15,7 @@ import org.opencv.core.Point; import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.imgproc.Imgproc; +import org.opencv.objdetect.Objdetect; import android.util.Log; @@ -124,8 +125,8 @@ public class CameraCalibrator { } private void findPattern(Mat grayFrame) { - mPatternWasFound = Calib.findCirclesGrid(grayFrame, mPatternSize, - mCorners, Calib.CALIB_CB_ASYMMETRIC_GRID); + mPatternWasFound = Objdetect.findCirclesGrid(grayFrame, mPatternSize, + mCorners, Objdetect.CALIB_CB_ASYMMETRIC_GRID); } public void addCorners() { @@ -135,7 +136,7 @@ public class CameraCalibrator { } private void drawPoints(Mat rgbaFrame) { - Calib.drawChessboardCorners(rgbaFrame, mPatternSize, mCorners, mPatternWasFound); + Objdetect.drawChessboardCorners(rgbaFrame, mPatternSize, mCorners, mPatternWasFound); } private void renderFrame(Mat rgbaFrame) { diff --git a/samples/cpp/3calibration.cpp b/samples/cpp/3calibration.cpp index 1393af6a92..0dbe2d5df8 100644 --- a/samples/cpp/3calibration.cpp +++ b/samples/cpp/3calibration.cpp @@ -8,6 +8,7 @@ #include "opencv2/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" +#include "opencv2/objdetect.hpp" #include "opencv2/core/utility.hpp" #include diff --git a/samples/cpp/calibration.cpp b/samples/cpp/calibration.cpp index cc48399924..7e32c5b881 100644 --- a/samples/cpp/calibration.cpp +++ b/samples/cpp/calibration.cpp @@ -1,12 +1,13 @@ #include "opencv2/core.hpp" -#include +#include "opencv2/core/utility.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/3d.hpp" #include "opencv2/calib.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" -#include +#include "opencv2/objdetect.hpp" +#include "opencv2/objdetect/charuco_detector.hpp" #include #include diff --git a/samples/cpp/select3dobj.cpp b/samples/cpp/select3dobj.cpp index c86a6578c4..7366626bcd 100644 --- a/samples/cpp/select3dobj.cpp +++ b/samples/cpp/select3dobj.cpp @@ -14,6 +14,7 @@ #include "opencv2/3d.hpp" #include "opencv2/calib.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/objdetect.hpp" #include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" diff --git a/samples/cpp/stereo_calib.cpp b/samples/cpp/stereo_calib.cpp index 5968e84554..ecd6739ed0 100644 --- a/samples/cpp/stereo_calib.cpp +++ b/samples/cpp/stereo_calib.cpp @@ -26,6 +26,7 @@ #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/objdetect.hpp" #include "opencv2/objdetect/charuco_detector.hpp" #include diff --git a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp index 4ae2418779..3f8e5d61ec 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "opencv2/objdetect/charuco_detector.hpp" using namespace cv; diff --git a/samples/cpp/tutorial_code/features/Homography/decompose_homography.cpp b/samples/cpp/tutorial_code/features/Homography/decompose_homography.cpp index 8ed6908a67..8e9872a835 100644 --- a/samples/cpp/tutorial_code/features/Homography/decompose_homography.cpp +++ b/samples/cpp/tutorial_code/features/Homography/decompose_homography.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace std; using namespace cv; diff --git a/samples/cpp/tutorial_code/features/Homography/homography_from_camera_displacement.cpp b/samples/cpp/tutorial_code/features/Homography/homography_from_camera_displacement.cpp index 85cdec073d..d1167361e4 100644 --- a/samples/cpp/tutorial_code/features/Homography/homography_from_camera_displacement.cpp +++ b/samples/cpp/tutorial_code/features/Homography/homography_from_camera_displacement.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include using namespace std; diff --git a/samples/cpp/tutorial_code/features/Homography/perspective_correction.cpp b/samples/cpp/tutorial_code/features/Homography/perspective_correction.cpp index ade1d52739..9180dc719a 100644 --- a/samples/cpp/tutorial_code/features/Homography/perspective_correction.cpp +++ b/samples/cpp/tutorial_code/features/Homography/perspective_correction.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include using namespace std; diff --git a/samples/cpp/tutorial_code/features/Homography/pose_from_homography.cpp b/samples/cpp/tutorial_code/features/Homography/pose_from_homography.cpp index 807f0d2972..6a379f1fa0 100644 --- a/samples/cpp/tutorial_code/features/Homography/pose_from_homography.cpp +++ b/samples/cpp/tutorial_code/features/Homography/pose_from_homography.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include using namespace std;