diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f56c0413c..7f24f655a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1505,7 +1505,7 @@ if(WITH_OPENEXR OR HAVE_OPENEXR) endif() if(WITH_GDAL OR HAVE_GDAL) - status(" GDAL:" HAVE_GDAL THEN "YES (${GDAL_LIBRARY})" ELSE "NO") + status(" GDAL:" HAVE_GDAL THEN "${GDAL_LIBRARY} (ver ${GDAL_VERSION})" ELSE "NO") endif() if(WITH_GDCM OR HAVE_GDCM) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index d7780f9592..3042db4ebc 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,6 +1,11 @@ add_definitions(-D__OPENCV_BUILD=1) add_definitions(-D__OPENCV_APPS=1) +if (NOT CMAKE_CROSSCOMPILING) + file(RELATIVE_PATH __loc_relative "${OpenCV_BINARY_DIR}" "${CMAKE_CURRENT_LIST_DIR}/pattern-tools\n") + file(APPEND "${OpenCV_BINARY_DIR}/opencv_apps_python_tests.cfg" "${__loc_relative}") +endif() + string(REPLACE "," ";" OPENCV_INSTALL_APPS_LIST "${OPENCV_INSTALL_APPS_LIST}") # support comma-separated list (,) too # Unified function for creating OpenCV applications: diff --git a/doc/pattern_tools/DICT_4X4_100.json.gz b/apps/pattern-tools/DICT_4X4_100.json.gz similarity index 100% rename from doc/pattern_tools/DICT_4X4_100.json.gz rename to apps/pattern-tools/DICT_4X4_100.json.gz diff --git a/doc/pattern_tools/DICT_4X4_1000.json.gz b/apps/pattern-tools/DICT_4X4_1000.json.gz similarity index 100% rename from doc/pattern_tools/DICT_4X4_1000.json.gz rename to apps/pattern-tools/DICT_4X4_1000.json.gz diff --git a/doc/pattern_tools/DICT_4X4_250.json.gz b/apps/pattern-tools/DICT_4X4_250.json.gz similarity index 100% rename from doc/pattern_tools/DICT_4X4_250.json.gz rename to apps/pattern-tools/DICT_4X4_250.json.gz diff --git a/doc/pattern_tools/DICT_4X4_50.json.gz b/apps/pattern-tools/DICT_4X4_50.json.gz similarity index 100% rename from doc/pattern_tools/DICT_4X4_50.json.gz rename to apps/pattern-tools/DICT_4X4_50.json.gz diff --git a/doc/pattern_tools/DICT_5X5_100.json.gz b/apps/pattern-tools/DICT_5X5_100.json.gz similarity index 100% rename from doc/pattern_tools/DICT_5X5_100.json.gz rename to apps/pattern-tools/DICT_5X5_100.json.gz diff --git a/doc/pattern_tools/DICT_5X5_1000.json.gz b/apps/pattern-tools/DICT_5X5_1000.json.gz similarity index 100% rename from doc/pattern_tools/DICT_5X5_1000.json.gz rename to apps/pattern-tools/DICT_5X5_1000.json.gz diff --git a/doc/pattern_tools/DICT_5X5_250.json.gz b/apps/pattern-tools/DICT_5X5_250.json.gz similarity index 100% rename from doc/pattern_tools/DICT_5X5_250.json.gz rename to apps/pattern-tools/DICT_5X5_250.json.gz diff --git a/doc/pattern_tools/DICT_5X5_50.json.gz b/apps/pattern-tools/DICT_5X5_50.json.gz similarity index 100% rename from doc/pattern_tools/DICT_5X5_50.json.gz rename to apps/pattern-tools/DICT_5X5_50.json.gz diff --git a/doc/pattern_tools/DICT_6X6_100.json.gz b/apps/pattern-tools/DICT_6X6_100.json.gz similarity index 100% rename from doc/pattern_tools/DICT_6X6_100.json.gz rename to apps/pattern-tools/DICT_6X6_100.json.gz diff --git a/doc/pattern_tools/DICT_6X6_1000.json.gz b/apps/pattern-tools/DICT_6X6_1000.json.gz similarity index 100% rename from doc/pattern_tools/DICT_6X6_1000.json.gz rename to apps/pattern-tools/DICT_6X6_1000.json.gz diff --git a/doc/pattern_tools/DICT_6X6_250.json.gz b/apps/pattern-tools/DICT_6X6_250.json.gz similarity index 100% rename from doc/pattern_tools/DICT_6X6_250.json.gz rename to apps/pattern-tools/DICT_6X6_250.json.gz diff --git a/doc/pattern_tools/DICT_6X6_50.json.gz b/apps/pattern-tools/DICT_6X6_50.json.gz similarity index 100% rename from doc/pattern_tools/DICT_6X6_50.json.gz rename to apps/pattern-tools/DICT_6X6_50.json.gz diff --git a/doc/pattern_tools/DICT_7X7_100.json.gz b/apps/pattern-tools/DICT_7X7_100.json.gz similarity index 100% rename from doc/pattern_tools/DICT_7X7_100.json.gz rename to apps/pattern-tools/DICT_7X7_100.json.gz diff --git a/doc/pattern_tools/DICT_7X7_1000.json.gz b/apps/pattern-tools/DICT_7X7_1000.json.gz similarity index 100% rename from doc/pattern_tools/DICT_7X7_1000.json.gz rename to apps/pattern-tools/DICT_7X7_1000.json.gz diff --git a/doc/pattern_tools/DICT_7X7_250.json.gz b/apps/pattern-tools/DICT_7X7_250.json.gz similarity index 100% rename from doc/pattern_tools/DICT_7X7_250.json.gz rename to apps/pattern-tools/DICT_7X7_250.json.gz diff --git a/doc/pattern_tools/DICT_7X7_50.json.gz b/apps/pattern-tools/DICT_7X7_50.json.gz similarity index 100% rename from doc/pattern_tools/DICT_7X7_50.json.gz rename to apps/pattern-tools/DICT_7X7_50.json.gz diff --git a/doc/pattern_tools/DICT_APRILTAG_16h5.json.gz b/apps/pattern-tools/DICT_APRILTAG_16h5.json.gz similarity index 100% rename from doc/pattern_tools/DICT_APRILTAG_16h5.json.gz rename to apps/pattern-tools/DICT_APRILTAG_16h5.json.gz diff --git a/doc/pattern_tools/DICT_APRILTAG_25h9.json.gz b/apps/pattern-tools/DICT_APRILTAG_25h9.json.gz similarity index 100% rename from doc/pattern_tools/DICT_APRILTAG_25h9.json.gz rename to apps/pattern-tools/DICT_APRILTAG_25h9.json.gz diff --git a/doc/pattern_tools/DICT_APRILTAG_36h10.json.gz b/apps/pattern-tools/DICT_APRILTAG_36h10.json.gz similarity index 100% rename from doc/pattern_tools/DICT_APRILTAG_36h10.json.gz rename to apps/pattern-tools/DICT_APRILTAG_36h10.json.gz diff --git a/doc/pattern_tools/DICT_APRILTAG_36h11.json.gz b/apps/pattern-tools/DICT_APRILTAG_36h11.json.gz similarity index 100% rename from doc/pattern_tools/DICT_APRILTAG_36h11.json.gz rename to apps/pattern-tools/DICT_APRILTAG_36h11.json.gz diff --git a/doc/pattern_tools/DICT_ARUCO_ORIGINAL.json.gz b/apps/pattern-tools/DICT_ARUCO_ORIGINAL.json.gz similarity index 100% rename from doc/pattern_tools/DICT_ARUCO_ORIGINAL.json.gz rename to apps/pattern-tools/DICT_ARUCO_ORIGINAL.json.gz diff --git a/doc/pattern_tools/README.txt b/apps/pattern-tools/README.txt similarity index 64% rename from doc/pattern_tools/README.txt rename to apps/pattern-tools/README.txt index dfe279022b..d099323f03 100644 --- a/doc/pattern_tools/README.txt +++ b/apps/pattern-tools/README.txt @@ -1,4 +1,4 @@ use -python gen_pattern.py --help +python generate_pattern.py --help to generate various calibration svg calibration patterns. diff --git a/doc/pattern_tools/gen_pattern.py b/apps/pattern-tools/generate_pattern.py similarity index 99% rename from doc/pattern_tools/gen_pattern.py rename to apps/pattern-tools/generate_pattern.py index 61d4e6839a..1123f5f116 100755 --- a/doc/pattern_tools/gen_pattern.py +++ b/apps/pattern-tools/generate_pattern.py @@ -1,8 +1,8 @@ #!/usr/bin/env python -"""gen_pattern.py +"""generate_pattern.py Usage example: -python gen_pattern.py -o out.svg -r 11 -c 8 -T circles -s 20.0 -R 5.0 -u mm -w 216 -h 279 +python generate_pattern.py -o out.svg -r 11 -c 8 -T circles -s 20.0 -R 5.0 -u mm -w 216 -h 279 -o, --output - output file (default out.svg) -r, --rows - pattern rows (default 11) -c, --columns - pattern columns (default 8) diff --git a/doc/pattern_tools/test_requirements.txt b/apps/pattern-tools/requirements-test.txt similarity index 100% rename from doc/pattern_tools/test_requirements.txt rename to apps/pattern-tools/requirements-test.txt diff --git a/doc/pattern_tools/svgfig.py b/apps/pattern-tools/svgfig.py similarity index 100% rename from doc/pattern_tools/svgfig.py rename to apps/pattern-tools/svgfig.py diff --git a/doc/pattern_tools/test_charuco_board.py b/apps/pattern-tools/test_charuco_board.py similarity index 96% rename from doc/pattern_tools/test_charuco_board.py rename to apps/pattern-tools/test_charuco_board.py index 31b90e67a5..447f2b387b 100644 --- a/doc/pattern_tools/test_charuco_board.py +++ b/apps/pattern-tools/test_charuco_board.py @@ -3,7 +3,7 @@ import os, tempfile, numpy as np import sys import cv2 as cv from tests_common import NewOpenCVTests -import gen_pattern +import generate_pattern class aruco_objdetect_test(NewOpenCVTests): @@ -42,7 +42,7 @@ class aruco_objdetect_test(NewOpenCVTests): try: basedir = os.path.abspath(os.path.dirname(__file__)) - pm = gen_pattern.PatternMaker(cols, rows, filesvg, "px", square_size, 0, board_width, + pm = generate_pattern.PatternMaker(cols, rows, filesvg, "px", square_size, 0, board_width, board_height, "charuco_checkboard", marker_size, os.path.join(basedir, aruco_type_str[aruco_type_i]+'.json.gz'), 0) pm.make_charuco_board() @@ -100,7 +100,7 @@ class aruco_objdetect_test(NewOpenCVTests): try: basedir = os.path.abspath(os.path.dirname(__file__)) - pm = gen_pattern.PatternMaker(cols, rows, filesvg, "px", square_size, 0, board_width, + pm = generate_pattern.PatternMaker(cols, rows, filesvg, "px", square_size, 0, board_width, board_height, "charuco_checkboard", marker_size, os.path.join(basedir, aruco_type_str+'.json.gz'), 0) pm.make_charuco_board() pm.save() diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 7736d922cc..603365964a 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,8 +1,3 @@ -if (NOT CMAKE_CROSSCOMPILING) - file(RELATIVE_PATH __loc_relative "${OpenCV_BINARY_DIR}" "${CMAKE_CURRENT_LIST_DIR}/pattern_tools\n") - file(APPEND "${OpenCV_BINARY_DIR}/opencv_apps_python_tests.cfg" "${__loc_relative}") -endif() - if(NOT BUILD_DOCS) return() endif() @@ -196,6 +191,7 @@ if(DOXYGEN_FOUND) list(APPEND CMAKE_DOXYGEN_HTML_FILES "${CMAKE_CURRENT_SOURCE_DIR}/opencv.ico") list(APPEND CMAKE_DOXYGEN_HTML_FILES "${CMAKE_CURRENT_SOURCE_DIR}/pattern.png") list(APPEND CMAKE_DOXYGEN_HTML_FILES "${CMAKE_CURRENT_SOURCE_DIR}/acircles_pattern.png") + list(APPEND CMAKE_DOXYGEN_HTML_FILES "${CMAKE_CURRENT_SOURCE_DIR}/charuco_board_pattern.png") list(APPEND CMAKE_DOXYGEN_HTML_FILES "${CMAKE_CURRENT_SOURCE_DIR}/bodybg.png") # list(APPEND CMAKE_DOXYGEN_HTML_FILES "${CMAKE_CURRENT_SOURCE_DIR}/mymath.sty") list(APPEND CMAKE_DOXYGEN_HTML_FILES "${CMAKE_CURRENT_SOURCE_DIR}/tutorial-utils.js") diff --git a/doc/tutorials/calib3d/camera_calibration_pattern/camera_calibration_pattern.markdown b/doc/tutorials/calib3d/camera_calibration_pattern/camera_calibration_pattern.markdown index 65a6db8820..94cb37e5b5 100644 --- a/doc/tutorials/calib3d/camera_calibration_pattern/camera_calibration_pattern.markdown +++ b/doc/tutorials/calib3d/camera_calibration_pattern/camera_calibration_pattern.markdown @@ -1,5 +1,5 @@ -Create calibration pattern {#tutorial_camera_calibration_pattern} -========================================= +Create Calibration Pattern {#tutorial_camera_calibration_pattern} +========================== @tableofcontents @@ -7,54 +7,165 @@ Create calibration pattern {#tutorial_camera_calibration_pattern} | | | | -: | :- | -| Original author | Laurent Berger | -| Compatibility | OpenCV >= 3.0 | +| Authors | Laurent Berger, Alexander Panov, Alexander Smorkalov | +| Compatibility | OpenCV > 4.12 | -The goal of this tutorial is to learn how to create a calibration pattern. +The tutorial describes all pattern supported by OpenCV for camera(s) calibration and pose estimation +with their strength, pitfalls and practical recommendations. -You can find a chessboard pattern in https://github.com/opencv/opencv/blob/5.x/doc/pattern.png +What is calibration pattern? why I need it? +------------------------------------------- -You can find a circleboard pattern in https://github.com/opencv/opencv/blob/5.x/doc/acircles_pattern.png +The flat printable pattern may be used: -You can find a ChAruco board pattern in https://github.com/opencv/opencv/blob/5.x/doc/charuco_board_pattern.png -(7X5 ChAruco board, square size: 30 mm , marker size: 15 mm, aruco dict: DICT_5X5_100, page width: 210 mm, page height: 297 mm) +1. For camera intrinsics (internal parameters) calibration. See @ref tutorial_camera_calibration. +2. For stereo or multi-camera system extrinsics (external parameters: rotation and translation + of each camera) calibration. See cv::stereoCalibrate for details. +3. Camera pose registration relative to well known point in 3d world. See @ref tutorial_multiview_camera_calibration -Create your own pattern ---------------- +Pattern Types +------------- -Now, if you want to create your own pattern, you will need python to use https://github.com/opencv/opencv/blob/5.x/doc/pattern_tools/gen_pattern.py +**Chessboard**. Classic calibration pattern of black and white squares. The all calibration algorithms +use internal chessboard corners as features. See cv::findChessboardCorners and cv::cornerSubPix to +detect the board and refine corners coordinates with sub-pixel accuracy. The board size is defined +as amount of internal corners, but not amount of black or white squares. Also pay attention, that +the board with even size is symmetric. If board has even amount of corners by one of direction then +its pose is defined up to 180 degrees (2 solutions). It the board is square with size N x N then its +pose is defined up to 90 degrees (4 solutions). The last two cases are not suitable for calibration. +Example code to generate features coordinates for calibration (object points): +``` + std::vector objectPoints; + for (int i = 0; i < boardSize.height; ++i) { + for (int j = 0; j < boardSize.width; ++j) { + objectPoints.push_back(Point3f(j*squareSize, i*squareSize, 0)); + } + } +``` +Printable chessboard pattern: https://github.com/opencv/opencv/blob/5.x/doc/pattern.png +(9x6 chessboard, page width: 210 mm, page height: 297 mm (A4)) -Example +**Circles Grid**. The circles grid is symmetric or asymmetric (each even row shifted) grid of black +circles on a white background or vice verse. See cv::findCirclesGrid function to detect the board +with OpenCV. The detector produces sub-pixel coordinates of the circle centers and does not require +additional refinement. The board size is defined as amount of circles in grid by x and y axis. +In case of asymmetric grid the shifted rows are taken into account too. The board is suitable for +intrinsics calibration. Symmetric grids suffer from the same issue as chessboard pattern with even +size. It's pose is defined up to 180 degrees. +Example code to generate features coordinates for calibration with symmetric grid (object points): +``` + std::vector objectPoints; + for (int i = 0; i < boardSize.height; ++i) { + for (int j = 0; j < boardSize.width; ++j) { + objectPoints.push_back(Point3f(j*squareSize, i*squareSize, 0)); + } + } +``` +Example code to generate features corrdinates for calibration with asymmetic grid (object points): +``` + std::vector objectPoints; + for (int i = 0; i < boardSize.height; i++) { + for (int j = 0; j < boardSize.width; j++) { + objectPoints.push_back(Point3f((2 * j + i % 2)*squareSize, i*squareSize, 0)); + } + } +``` +Printable asymmetric circles grid pattern: https://github.com/opencv/opencv/blob/5.x/doc/acircles_pattern.png +(11x4 asymmetric circles grid, page width: 210 mm, page height: 297 mm (A4)) + +**ChAruco board**. Chessboard unreached with ArUco markers. Each internal corner of the board is +described by 2 neighborhood ArUco markers that makes it unique. The board size is defined in number +of units, but not internal corners. ChAruco board of size N x M is equivalent to chessboard pattern +of size N-1 x M-1. OpenCV provides `cv::aruco::CharucoDetector` class for the board detection. +The detector algorithm finds ArUco markers first and them "assembles" the board using knowledge +about ArUco pairs. In opposite to the previous pattern partially occluded board may be used as all +corners are labeled. The board is rotation invariant, but set of ArUco markers and their order +should be known to detector apriori. It cannot detect ChAruco board with predefined size and random +set of markers. +Example code to generate features corrdinates for calibration (object points) for board size in units: +``` + std::vector objectPoints; + for (int i = 0; i < boardSize.height-1; ++i) { + for (int j = 0; j < boardSize.width-1; ++j) { + objectPoints.push_back(Point3f(j*squareSize, i*squareSize, 0)); + } + } +``` +Printable ChAruco board pattern: https://github.com/opencv/opencv/blob/5.x/doc/charuco_board_pattern.png +(7X5 ChAruco board, square size: 30 mm, marker size: 15 mm, ArUco dict: DICT_5X5_100, page width: +210 mm, page height: 297 mm (A4)) + +Create Your Own Pattern +----------------------- + +In case if ready pattern does not satisfy your requirements, you can generate your own. OpenCV +provides generate_pattern.py tool in `apps/pattern-tools` of source repository or your binary +distribution. The only requirement is Python 3. + +Examples: create a checkerboard pattern in file chessboard.svg with 9 rows, 6 columns and a square size of 20mm: - python gen_pattern.py -o chessboard.svg --rows 9 --columns 6 --type checkerboard --square_size 20 + python generate_pattern.py -o chessboard.svg --rows 9 --columns 6 --type checkerboard --square_size 20 create a circle board pattern in file circleboard.svg with 7 rows, 5 columns and a radius of 15 mm: - python gen_pattern.py -o circleboard.svg --rows 7 --columns 5 --type circles --square_size 15 + python generate_pattern.py -o circleboard.svg --rows 7 --columns 5 --type circles --square_size 15 -create a circle board pattern in file acircleboard.svg with 7 rows, 5 columns and a square size of 10mm and less spacing between circle: +create a circle board pattern in file acircleboard.svg with 7 rows, 5 columns and a square size of +10mm and less spacing between circle: - python gen_pattern.py -o acircleboard.svg --rows 7 --columns 5 --type acircles --square_size 10 --radius_rate 2 + python generate_pattern.py -o acircleboard.svg --rows 7 --columns 5 --type acircles --square_size 10 --radius_rate 2 create a radon checkerboard for findChessboardCornersSB() with markers in (7 4), (7 5), (8 5) cells: - python gen_pattern.py -o radon_checkerboard.svg --rows 10 --columns 15 --type radon_checkerboard -s 12.1 -m 7 4 7 5 8 5 + python generate_pattern.py -o radon_checkerboard.svg --rows 10 --columns 15 --type radon_checkerboard -s 12.1 -m 7 4 7 5 8 5 -create a ChAruco board pattern in charuco_board.svg with 7 rows, 5 columns, square size 30 mm, aruco marker size 15 mm and using DICT_5X5_100 as dictionary for aruco markers (it contains in DICT_ARUCO.json file): +create a ChAruco board pattern in charuco_board.svg with 7 rows, 5 columns, square size 30 mm, aruco +marker size 15 mm and using DICT_5X5_100 as dictionary for aruco markers (it contains in DICT_ARUCO.json file): - python gen_pattern.py -o charuco_board.svg --rows 7 --columns 5 -T charuco_board --square_size 30 --marker_size 15 -f DICT_5X5_100.json.gz + python generate_pattern.py -o charuco_board.svg --rows 7 --columns 5 -T charuco_board --square_size 30 --marker_size 15 -f DICT_5X5_100.json.gz If you want to change the measurement units, use the -u option (e.g. mm, inches, px, m) If you want to change the page size, use the -w (width) and -h (height) options -If you want to use your own dictionary for the ChAruco board, specify the name of your dictionary file. For example +If you want to use your own dictionary for the ChAruco board, specify the name of your dictionary +file. For example: - python gen_pattern.py -o charuco_board.svg --rows 7 --columns 5 -T charuco_board -f my_dictionary.json + python generate_pattern.py -o charuco_board.svg --rows 7 --columns 5 -T charuco_board -f my_dictionary.json -You can generate your dictionary in the file my_dictionary.json with 30 markers and a marker size of 5 bits using the utility provided in opencv/samples/cpp/aruco_dict_utils.cpp. +You can generate your dictionary in the file my_dictionary.json with 30 markers and a marker size of +5 bits using the utility provided in `samples/cpp/aruco_dict_utils.cpp`. bin/example_cpp_aruco_dict_utils.exe my_dict.json -nMarkers=30 -markerSize=5 + +Pattern Size +------------ + +Pattern is defined by it's physical board size, element (square or circle) physical size and amount +of elements. Factors that affect calibration quality: + +- **Amount of features**. Most of OpenCV functions that work with detected patterns use optimization +or some random consensus strategies inside. More features on board means more points for optimization +and better estimation quality. Calibration process requires several images. It means that in most +of cases lower amount of pattern features may be compensated by higher amount frames. + +- **Element size**. The physical size of elements depends on the distance and size in pixels. +Each detector defines some minimal size for reliable detection. For circles grid it's circle +radius, for chessboard it's square size, for ChAruco board it's ArUco marker element size. +General recommendation: larger elements (in frame pixels) reduces detection uncertainty. + +- **Board size**. The board should be fully visible, sharp and reliably detected by OpenCV algorithms. +So, the board size should satisfy previous items, if it's used with typical target distance. +Usually larger board is better, but smaller boards allow to calibrate corners better. + +Generic Recommendations +----------------------- + +1. The final pattern should be as flat as possible. It improves calibration accuracy. +2. Glance pattern is worse than matte. Blinks and shadows on glance surface degrades board detection +significantly. +3. Most of detection algorithms expect white (black) border around the markers. Please do not cut +them or cover them. diff --git a/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.markdown b/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.markdown index ddd7dbae79..2467704bc4 100644 --- a/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.markdown +++ b/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.markdown @@ -68,4 +68,4 @@ Answer: After obtaining the camera pose using solvePnP, the rotation (rvec) and // assuming 'point' is the 3D position of a chessboard corner in the camera coordinate system double distance = norm(point); -This is equivalent to applying the L2 norm on the 3D point’s coordinates (x, y, z). \ No newline at end of file +This is equivalent to applying the L2 norm on the 3D point’s coordinates (x, y, z). diff --git a/doc/tutorials/objdetect/aruco_board_detection/aruco_board_detection.markdown b/doc/tutorials/objdetect/aruco_board_detection/aruco_board_detection.markdown index 56eb1a75d1..400891dfaa 100644 --- a/doc/tutorials/objdetect/aruco_board_detection/aruco_board_detection.markdown +++ b/doc/tutorials/objdetect/aruco_board_detection/aruco_board_detection.markdown @@ -127,7 +127,7 @@ in ascending order starting on 0, so they will be 0, 1, 2, ..., 34. After creating a grid board, we probably want to print it and use it. There are two ways to do this: -1. By using the script `doc/patter_tools/gen_pattern.py `, see @subpage tutorial_camera_calibration_pattern. +1. By using the script `apps/pattern_tools/generate_pattern.py `, see @subpage tutorial_camera_calibration_pattern. 2. By using the function `cv::aruco::GridBoard::generateImage()`. The function `cv::aruco::GridBoard::generateImage()` is provided in cv::aruco::GridBoard class and diff --git a/doc/tutorials/objdetect/charuco_detection/charuco_detection.markdown b/doc/tutorials/objdetect/charuco_detection/charuco_detection.markdown index c1039376ea..40fc331000 100644 --- a/doc/tutorials/objdetect/charuco_detection/charuco_detection.markdown +++ b/doc/tutorials/objdetect/charuco_detection/charuco_detection.markdown @@ -77,7 +77,7 @@ through `board.ids`, like in the `cv::aruco::Board` parent class. Once we have our `cv::aruco::CharucoBoard` object, we can create an image to print it. There are two ways to do this: -1. By using the script `doc/patter_tools/gen_pattern.py `, see @subpage tutorial_camera_calibration_pattern. +1. By using the script `apps/pattern_tools/generate_pattern.py `, see @subpage tutorial_camera_calibration_pattern. 2. By using the function `cv::aruco::CharucoBoard::generateImage()`. The function `cv::aruco::CharucoBoard::generateImage()` is provided in cv::aruco::CharucoBoard class diff --git a/modules/calib/include/opencv2/calib.hpp b/modules/calib/include/opencv2/calib.hpp index b26d9c20c7..58aab94cfb 100644 --- a/modules/calib/include/opencv2/calib.hpp +++ b/modules/calib/include/opencv2/calib.hpp @@ -629,7 +629,7 @@ the board to make the detection more robust in various environments. Otherwise, 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 `gen_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) +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, @@ -688,7 +688,7 @@ 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 `gen_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) +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% */ diff --git a/modules/imgcodecs/src/grfmt_bmp.cpp b/modules/imgcodecs/src/grfmt_bmp.cpp index f0802211d9..4540d3cd93 100644 --- a/modules/imgcodecs/src/grfmt_bmp.cpp +++ b/modules/imgcodecs/src/grfmt_bmp.cpp @@ -633,7 +633,7 @@ bool BmpEncoder::write( const Mat& img, const std::vector& params ) // sRGB colorspace requires BITMAPV5HEADER. // See https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header bool useV5BitFields = true; - for(size_t i = 0 ; i < params.size(); i++) + for(size_t i = 0; i < params.size(); i+=2) { const int value = params[i+1]; switch(params[i]) diff --git a/modules/imgcodecs/src/grfmt_gdal.cpp b/modules/imgcodecs/src/grfmt_gdal.cpp index 2c09d3b62f..ec7f70a925 100644 --- a/modules/imgcodecs/src/grfmt_gdal.cpp +++ b/modules/imgcodecs/src/grfmt_gdal.cpp @@ -239,7 +239,7 @@ void write_pixel( const double& pixelValue, else if( image.depth() == CV_32S ){ image.ptr(row)[col] = Vec3i(newValue,newValue,newValue); } else if( image.depth() == CV_32F ){ image.ptr(row)[col] = Vec3f(newValue,newValue,newValue); } else if( image.depth() == CV_64F ){ image.ptr(row)[col] = Vec3d(newValue,newValue,newValue); } - else{ throw std::runtime_error("Unknown image depth, gdal:1, img: 3"); } + else{ throw std::runtime_error("Unknown image depth, gdal:1, img: 3"); } } // input: 3 channel, output: 1 channel diff --git a/modules/imgcodecs/src/grfmt_webp.cpp b/modules/imgcodecs/src/grfmt_webp.cpp index 932f08bec1..068be52b8b 100644 --- a/modules/imgcodecs/src/grfmt_webp.cpp +++ b/modules/imgcodecs/src/grfmt_webp.cpp @@ -389,33 +389,43 @@ bool WebPEncoder::write(const Mat& img, const std::vector& params) channels = 3; } - uint8_t *out = NULL; + uint8_t *encoder_out = NULL; size_t size = 0; if (comp_lossless) { if (channels == 3) { - size = WebPEncodeLosslessBGR(image->ptr(), width, height, (int)image->step, &out); + size = WebPEncodeLosslessBGR(image->ptr(), width, height, (int)image->step, &encoder_out); } else if (channels == 4) { - size = WebPEncodeLosslessBGRA(image->ptr(), width, height, (int)image->step, &out); + size = WebPEncodeLosslessBGRA(image->ptr(), width, height, (int)image->step, &encoder_out); } } else { if (channels == 3) { - size = WebPEncodeBGR(image->ptr(), width, height, (int)image->step, quality, &out); + size = WebPEncodeBGR(image->ptr(), width, height, (int)image->step, quality, &encoder_out); } else if (channels == 4) { - size = WebPEncodeBGRA(image->ptr(), width, height, (int)image->step, quality, &out); + size = WebPEncodeBGRA(image->ptr(), width, height, (int)image->step, quality, &encoder_out); } } - WebPData finalData = { out, size }; - if (!m_metadata.empty()) { +#if WEBP_DECODER_ABI_VERSION >= 0x0206 + Ptr out_cleaner(encoder_out, WebPFree); +#else + Ptr out_cleaner(encoder_out, free); +#endif + + uint8_t *out = encoder_out; + uint8_t *muxer_out = nullptr; + + if (!m_metadata.empty()) + { + WebPData muxerData; WebPMux* mux = WebPMuxNew(); WebPData imageData = { out, size }; @@ -442,8 +452,10 @@ bool WebPEncoder::write(const Mat& img, const std::vector& params) WebPMuxSetChunk(mux, "ICCP", &metadata, 1); } - if (WebPMuxAssemble(mux, &finalData) == WEBP_MUX_OK) { - size = finalData.size; + if (WebPMuxAssemble(mux, &muxerData) == WEBP_MUX_OK) { + size = muxerData.size; + muxer_out = const_cast(muxerData.bytes); + out = muxer_out; WebPMuxDelete(mux); } else { @@ -453,9 +465,9 @@ bool WebPEncoder::write(const Mat& img, const std::vector& params) } #if WEBP_DECODER_ABI_VERSION >= 0x0206 - Ptr out_cleaner(out, WebPFree); + Ptr muxer_cleaner(muxer_out, WebPFree); #else - Ptr out_cleaner(out, free); + Ptr muxer_cleaner(muxer_out, free); #endif CV_Assert(size > 0); @@ -463,7 +475,7 @@ bool WebPEncoder::write(const Mat& img, const std::vector& params) if (m_buf) { m_buf->resize(size); - memcpy(&(*m_buf)[0], finalData.bytes, size); + memcpy(&(*m_buf)[0], out, size); bytes_written = size; } else @@ -471,7 +483,7 @@ bool WebPEncoder::write(const Mat& img, const std::vector& params) FILE *fd = fopen(m_filename.c_str(), "wb"); if (fd != NULL) { - bytes_written = fwrite(finalData.bytes, sizeof(uint8_t), size, fd); + bytes_written = fwrite(out, sizeof(uint8_t), size, fd); if (size != bytes_written) { CV_LOG_ERROR(NULL, cv::format("Only %zu or %zu bytes are written\n",bytes_written, size)); diff --git a/modules/objdetect/src/qrcode.cpp b/modules/objdetect/src/qrcode.cpp index 923240292a..0e132db0db 100644 --- a/modules/objdetect/src/qrcode.cpp +++ b/modules/objdetect/src/qrcode.cpp @@ -2921,7 +2921,12 @@ std::string ImplContour::decode(InputArray in, InputArray points, OutputArray st vector src_points; points.copyTo(src_points); CV_Assert(src_points.size() == 4); - CV_CheckGT(contourArea(src_points), 0.0, "Invalid QR code source points"); + if (contourArea(src_points) <= 0.0) + { + if (straight_qrcode.needed()) + straight_qrcode.release(); + return std::string(); + } QRDecode qrdec(useAlignmentMarkers); qrdec.init(inarr, src_points); diff --git a/modules/objdetect/test/test_qrcode.cpp b/modules/objdetect/test/test_qrcode.cpp index c49480d38f..2912d39028 100644 --- a/modules/objdetect/test/test_qrcode.cpp +++ b/modules/objdetect/test/test_qrcode.cpp @@ -470,7 +470,7 @@ TEST(Objdetect_QRCode_basic, not_found_qrcode) QRCodeDetector qrcode; EXPECT_FALSE(qrcode.detect(zero_image, corners)); corners = std::vector(4); - EXPECT_ANY_THROW(qrcode.decode(zero_image, corners, straight_barcode)); + EXPECT_NO_THROW(qrcode.decode(zero_image, corners, straight_barcode)); } TEST(Objdetect_QRCode_detect, detect_regression_21287) diff --git a/modules/python/common.cmake b/modules/python/common.cmake index cd6c27984a..3c0c4febd7 100644 --- a/modules/python/common.cmake +++ b/modules/python/common.cmake @@ -14,7 +14,7 @@ ocv_module_include_directories( # try to use dynamic symbols linking with libpython.so set(OPENCV_FORCE_PYTHON_LIBS OFF CACHE BOOL "") -string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") +string(REGEX REPLACE "(^| )-Wl,--no-undefined( |$)" " " CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") if(NOT WIN32 AND NOT APPLE AND NOT OPENCV_PYTHON_SKIP_LINKER_EXCLUDE_LIBS) set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--exclude-libs=ALL") endif() @@ -59,11 +59,7 @@ endif() if(APPLE) set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") elseif(WIN32 OR OPENCV_FORCE_PYTHON_LIBS) - if(${PYTHON}_DEBUG_LIBRARIES AND NOT ${PYTHON}_LIBRARIES MATCHES "optimized.*debug") - ocv_target_link_libraries(${the_module} PRIVATE debug ${${PYTHON}_DEBUG_LIBRARIES} optimized ${${PYTHON}_LIBRARIES}) - else() - ocv_target_link_libraries(${the_module} PRIVATE ${${PYTHON}_LIBRARIES}) - endif() + ocv_target_link_libraries(${the_module} PRIVATE ${${PYTHON}_LIBRARIES}) endif() if(TARGET gen_opencv_python_source)