diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index f6f39a17ed..728a40c305 100644 --- a/3rdparty/libpng/CMakeLists.txt +++ b/3rdparty/libpng/CMakeLists.txt @@ -278,6 +278,7 @@ endif(PNG_HARDWARE_OPTIMIZATIONS) if(MSVC) add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + ocv_warnings_disable(CMAKE_C_FLAGS /wd4146) endif(MSVC) add_library(${PNG_LIBRARY} STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL} ${lib_srcs} ${lib_hdrs}) diff --git a/apps/interactive-calibration/main.cpp b/apps/interactive-calibration/main.cpp index 709fa4ed3e..1d67514601 100644 --- a/apps/interactive-calibration/main.cpp +++ b/apps/interactive-calibration/main.cpp @@ -53,7 +53,7 @@ const char* keys = "DICT_4X4_50, DICT_4X4_100, DICT_4X4_250, DICT_4X4_1000, DICT_5X5_50, DICT_5X5_100, DICT_5X5_250, " "DICT_5X5_1000, DICT_6X6_50, DICT_6X6_100, DICT_6X6_250, DICT_6X6_1000, DICT_7X7_50, DICT_7X7_100, " "DICT_7X7_250, DICT_7X7_1000, DICT_ARUCO_ORIGINAL, DICT_APRILTAG_16h5, DICT_APRILTAG_25h9, " - "DICT_APRILTAG_36h10, DICT_APRILTAG_36h11 }" + "DICT_APRILTAG_36h10, DICT_APRILTAG_36h11, DICT_ARUCO_MIP_36h12 }" "{fad | None | name of file with ArUco dictionary}" "{of | cameraParameters.xml | Output file name}" "{ft | true | Auto tuning of calibration flags}" diff --git a/apps/interactive-calibration/parametersController.cpp b/apps/interactive-calibration/parametersController.cpp index 48639a2bdb..66fd769fbb 100644 --- a/apps/interactive-calibration/parametersController.cpp +++ b/apps/interactive-calibration/parametersController.cpp @@ -175,6 +175,7 @@ bool calib::parametersController::loadFromParser(cv::CommandLineParser &parser) else if (arucoDictName == "DICT_APRILTAG_25h9") { mCapParams.charucoDictName = cv::aruco::DICT_APRILTAG_25h9; } else if (arucoDictName == "DICT_APRILTAG_36h10") { mCapParams.charucoDictName = cv::aruco::DICT_APRILTAG_36h10; } else if (arucoDictName == "DICT_APRILTAG_36h11") { mCapParams.charucoDictName = cv::aruco::DICT_APRILTAG_36h11; } + else if (arucoDictName == "DICT_ARUCO_MIP_36h12") { mCapParams.charucoDictName = cv::aruco::DICT_ARUCO_MIP_36h12; } else { std::cout << "incorrect name of aruco dictionary \n"; return false; diff --git a/apps/pattern-tools/DICT_ARUCO_MIP_36h12.json.gz b/apps/pattern-tools/DICT_ARUCO_MIP_36h12.json.gz new file mode 100644 index 0000000000..60734621e6 Binary files /dev/null and b/apps/pattern-tools/DICT_ARUCO_MIP_36h12.json.gz differ diff --git a/apps/pattern-tools/svgfig.py b/apps/pattern-tools/svgfig.py index 73a91ce134..323ed420c0 100644 --- a/apps/pattern-tools/svgfig.py +++ b/apps/pattern-tools/svgfig.py @@ -489,9 +489,9 @@ class SVG: f.close() else: - f = codecs.open(fileName, "w", encoding=encoding) - f.write(self.standalone_xml(encoding=encoding)) - f.close() + with open(fileName, "w", encoding=encoding) as f: + f.write(self.standalone_xml(encoding=encoding)) + def inkview(self, fileName=None, encoding="utf-8"): """View in "inkview", assuming that program is available on your system. diff --git a/apps/pattern-tools/test_charuco_board.py b/apps/pattern-tools/test_charuco_board.py index 4f783c26f9..c53d1eb10f 100644 --- a/apps/pattern-tools/test_charuco_board.py +++ b/apps/pattern-tools/test_charuco_board.py @@ -18,10 +18,10 @@ class aruco_objdetect_test(NewOpenCVTests): square_size = 100 aruco_type = [cv.aruco.DICT_4X4_1000, cv.aruco.DICT_5X5_1000, cv.aruco.DICT_6X6_1000, cv.aruco.DICT_7X7_1000, cv.aruco.DICT_ARUCO_ORIGINAL, cv.aruco.DICT_APRILTAG_16h5, - cv.aruco.DICT_APRILTAG_25h9, cv.aruco.DICT_APRILTAG_36h10, cv.aruco.DICT_APRILTAG_36h11] + cv.aruco.DICT_APRILTAG_25h9, cv.aruco.DICT_APRILTAG_36h10, cv.aruco.DICT_APRILTAG_36h11, cv.aruco.DICT_ARUCO_MIP_36h12] aruco_type_str = ['DICT_4X4_1000','DICT_5X5_1000', 'DICT_6X6_1000', 'DICT_7X7_1000', 'DICT_ARUCO_ORIGINAL', 'DICT_APRILTAG_16h5', - 'DICT_APRILTAG_25h9', 'DICT_APRILTAG_36h10', 'DICT_APRILTAG_36h11'] + 'DICT_APRILTAG_25h9', 'DICT_APRILTAG_36h10', 'DICT_APRILTAG_36h11', 'DICT_ARUCO_MIP_36h12'] marker_size = 0.8*square_size board_width = cols*square_size board_height = rows*square_size diff --git a/doc/tutorials/objdetect/aruco_detection/aruco_detection.markdown b/doc/tutorials/objdetect/aruco_detection/aruco_detection.markdown index edd43866e7..dd4ae483df 100644 --- a/doc/tutorials/objdetect/aruco_detection/aruco_detection.markdown +++ b/doc/tutorials/objdetect/aruco_detection/aruco_detection.markdown @@ -144,7 +144,7 @@ Error correction techniques are employed when necessary. Consider the following image: -![Image with an assortment of markers](images/singlemarkerssource.jpg) +![Image with an assortment of markers](images/singlemarkerssource.jpg) { width=70% } And a printout of this image in a photo: diff --git a/doc/tutorials/tutorials.markdown b/doc/tutorials/tutorials.markdown index aaf621b8e6..dcf20fa727 100644 --- a/doc/tutorials/tutorials.markdown +++ b/doc/tutorials/tutorials.markdown @@ -6,7 +6,7 @@ OpenCV Tutorials {#tutorial_root} - @subpage tutorial_table_of_content_imgproc - image processing functions - @subpage tutorial_table_of_content_app - application utils (GUI, image/video input/output) - @subpage tutorial_table_of_content_calib3d - extract 3D world information from 2D images -- @subpage tutorial_table_of_content_objdetect - INSERT OBJDETECT MODULE INFO +- @subpage tutorial_table_of_content_objdetect - detect ArUco markers and other calibration boards - @subpage tutorial_table_of_content_features - feature detectors, descriptors and matching framework - @subpage tutorial_table_of_content_dnn - infer neural networks using built-in _dnn_ module - @subpage tutorial_table_of_content_other - other modules (stitching, video) diff --git a/hal/ipp/include/ipp_hal_imgproc.hpp b/hal/ipp/include/ipp_hal_imgproc.hpp index 28ab1cd042..1e37326881 100644 --- a/hal/ipp/include/ipp_hal_imgproc.hpp +++ b/hal/ipp/include/ipp_hal_imgproc.hpp @@ -19,6 +19,8 @@ int ipp_hal_warpAffine(int src_type, const uchar *src_data, size_t src_step, int //#define cv_hal_warpAffine ipp_hal_warpAffine #endif +#if IPP_VERSION_X100 >= 202600 + int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, uchar *dst_data, size_t dst_step, int dst_width, int dst_height, const double M[9], int interpolation, int borderType, const double borderValue[4]); @@ -26,6 +28,8 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step //#undef cv_hal_warpPerspective //#define cv_hal_warpPerspective ipp_hal_warpPerspective +#endif // IPP_VERSION_X100 >= 202600 + int ipp_hal_remap32f(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, uchar *dst_data, size_t dst_step, int dst_width, int dst_height, float* mapx, size_t mapx_step, float* mapy, size_t mapy_step, diff --git a/hal/ipp/src/warp_ipp.cpp b/hal/ipp/src/warp_ipp.cpp index fb059a82ea..7736b884fb 100644 --- a/hal/ipp/src/warp_ipp.cpp +++ b/hal/ipp/src/warp_ipp.cpp @@ -8,153 +8,13 @@ #include #include "precomp_ipp.hpp" +#include // Uncomment to enforce IPP calls for all supported by IPP configurations // #define IPP_CALLS_ENFORCED -#define CV_IPP_SAFE_CALL(pFunc, pFlag, ...) if (pFunc(__VA_ARGS__) != ippStsNoErr) {*pFlag = false; return;} #define CV_TYPE(src_type) (src_type & (CV_DEPTH_MAX - 1)) -#ifdef HAVE_IPP_IW -// Warp affine section - -#include "iw++/iw.hpp" - -class ipp_warpAffineParallel: public cv::ParallelLoopBody -{ -public: - ipp_warpAffineParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, IppiInterpolationType _inter, double (&_coeffs)[2][3], ::ipp::IwiBorderType _borderType, IwTransDirection _iwTransDirection, bool *_ok):m_src(src), m_dst(dst) - { - ok = _ok; - - inter = _inter; - borderType = _borderType; - iwTransDirection = _iwTransDirection; - - for( int i = 0; i < 2; i++ ) - for( int j = 0; j < 3; j++ ) - coeffs[i][j] = _coeffs[i][j]; - - *ok = true; - } - ~ipp_warpAffineParallel() {} - - virtual void operator() (const cv::Range& range) const CV_OVERRIDE - { - //CV_INSTRUMENT_REGION_IPP(); - if(*ok == false) - return; - - try - { - ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start); - CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, m_src, m_dst, coeffs, iwTransDirection, inter, ::ipp::IwiWarpAffineParams(), borderType, tile); - } - catch(const ::ipp::IwException &) - { - *ok = false; - return; - } - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); - } -private: - ::ipp::IwiImage &m_src; - ::ipp::IwiImage &m_dst; - - IppiInterpolationType inter; - double coeffs[2][3]; - ::ipp::IwiBorderType borderType; - IwTransDirection iwTransDirection; - - bool *ok; - const ipp_warpAffineParallel& operator= (const ipp_warpAffineParallel&); -}; - -int ipp_hal_warpAffine(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, uchar *dst_data, size_t dst_step, int dst_width, - int dst_height, const double M[6], int interpolation, int borderType, const double borderValue[4]) -{ - CV_HAL_CHECK_USE_IPP(); - //CV_INSTRUMENT_REGION_IPP(); - - IppiInterpolationType ippInter = ippiGetInterpolation(interpolation); - if((int)ippInter < 0 || interpolation > 2) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - -#if defined(IPP_CALLS_ENFORCED) - /* C1 C2 C3 C4 */ - char impl[CV_DEPTH_MAX][4][3]={{{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //8U - {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8S - {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //16U - {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //16S - {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //32S - {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //32F - {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}}; //64F -#else // IPP_CALLS_ENFORCED is not defined, results are strictly aligned to OpenCV implementation - /* C1 C2 C3 C4 */ - char impl[CV_DEPTH_MAX][4][3]={{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8U - {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8S - {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 0, 0}}, //16U - {{1, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 0}}, //16S - {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //32S - {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //32F - {{1, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 0}}}; //64F -#endif - - if(impl[CV_TYPE(src_type)][CV_MAT_CN(src_type)-1][interpolation] == 0) - { - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - // Acquire data and begin processing - try - { - ::ipp::IwiImage iwSrc; - iwSrc.Init({src_width, src_height}, ippiGetDataType(src_type), CV_MAT_CN(src_type), NULL, src_data, IwSize(src_step)); - ::ipp::IwiImage iwDst({dst_width, dst_height}, ippiGetDataType(src_type), CV_MAT_CN(src_type), NULL, dst_data, dst_step); - ::ipp::IwiBorderType ippBorder(ippiGetBorderType(borderType), {borderValue[0], borderValue[1], borderValue[2], borderValue[3]}); - IwTransDirection iwTransDirection = iwTransInverse; - - if((int)ippBorder == -1) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - double coeffs[2][3]; - for( int i = 0; i < 2; i++ ) - for( int j = 0; j < 3; j++ ) - coeffs[i][j] = M[i*3 + j]; - - int min_payload = 1 << 16; // 64KB shall be minimal per thread to maximize scalability for warping functions - const int threads = ippiSuggestRowThreadsNum(iwDst, min_payload); - - if (threads > 1) - { - bool ok = true; - cv::Range range(0, (int)iwDst.m_size.height); - ipp_warpAffineParallel invoker(iwSrc, iwDst, ippInter, coeffs, ippBorder, iwTransDirection, &ok); - if(!ok) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - parallel_for_(range, invoker, threads); - - if(!ok) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - else - { - CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, iwSrc, iwDst, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpAffineParams(), ippBorder); - } - } - catch (const ::ipp::IwException &) - { - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - return CV_HAL_ERROR_OK; -} - -#endif // HAVE_IPP_IW - -// End of Warp affine section - typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize); template @@ -214,168 +74,143 @@ static bool IPPSet(const double value[4], void *dataPointer, int step, IppiSize return false; } -// Warp perspective section +#ifdef HAVE_IPP_IW -typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveFunc)(const Ipp8u*, int, Ipp8u*, int,IppiPoint, IppiSize, const IppiWarpSpec*,Ipp8u*); -typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveInitFunc)(IppiSize, IppiRect, IppiSize, IppDataType,const double [3][3], IppiWarpDirection, int, IppiBorderType, const Ipp64f *, int, IppiWarpSpec*); +#include "iw++/iw.hpp" -class IPPWarpPerspectiveInvoker : - public cv::ParallelLoopBody +int ipp_hal_warpAffine(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, uchar *dst_data, size_t dst_step, + int dst_width, int dst_height, const double M[6], int interpolation, int borderType, const double borderValue[4]) { - // Mem object ot simplify IPP memory lifetime control - struct IPPWarpPerspectiveMem + //CV_INSTRUMENT_REGION_IPP(); + + IppiInterpolationType ippInter = ippiGetInterpolation(interpolation); + if((int)ippInter < 0 || interpolation > 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + +#if defined(IPP_CALLS_ENFORCED) + /* C1 C2 C3 C4 */ + char impl[CV_DEPTH_MAX][4][3]={{{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //8U + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8S + {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //16U + {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //16S + {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //32S + {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //32F + {{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}}; //64F +#else // IPP_CALLS_ENFORCED is not defined, results are strictly aligned to OpenCV implementation + /* C1 C2 C3 C4 */ + char impl[CV_DEPTH_MAX][4][3]={{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8U + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8S + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 0, 0}}, //16U + {{1, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 0}}, //16S + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //32S + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //32F + {{1, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 0}}}; //64F +#endif + + if(impl[CV_TYPE(src_type)][CV_MAT_CN(src_type)-1][interpolation] == 0) { - IppiWarpSpec* pSpec = nullptr; - Ipp8u* pBuffer = nullptr; - - IPPWarpPerspectiveMem() = default; - IPPWarpPerspectiveMem (const IPPWarpPerspectiveMem&) = delete; - IPPWarpPerspectiveMem& operator= (const IPPWarpPerspectiveMem&) = delete; - - void AllocateSpec(int size) - { - pSpec = (IppiWarpSpec*)ippMalloc_L(size); - } - - void AllocateBuffer(int size) - { - pBuffer = (Ipp8u*)ippMalloc_L(size); - } - - ~IPPWarpPerspectiveMem() - { - if (nullptr != pSpec) ippFree(pSpec); - if (nullptr != pBuffer) ippFree(pBuffer); - } - }; -public: - IPPWarpPerspectiveInvoker(int _src_type, cv::Mat &_src, size_t _src_step, cv::Mat &_dst, size_t _dst_step, IppiInterpolationType _interpolation, - double (&_coeffs)[3][3], int &_borderType, const double _borderValue[4], ippiWarpPerspectiveFunc _func, ippiWarpPerspectiveInitFunc _initFunc, - bool *_ok) : - ParallelLoopBody(), src_type(_src_type), src(_src), src_step(_src_step), dst(_dst), dst_step(_dst_step), inter(_interpolation), coeffs(_coeffs), - borderType(_borderType), func(_func), initFunc(_initFunc), ok(_ok) - { - memcpy(this->borderValue, _borderValue, sizeof(this->borderValue)); - *ok = true; + return CV_HAL_ERROR_NOT_IMPLEMENTED; } - virtual void operator() (const cv::Range& range) const CV_OVERRIDE + // Acquire data and begin processing + double coeffs[2][3]; + for( int i = 0; i < 2; i++ ) + for( int j = 0; j < 3; j++ ) + coeffs[i][j] = M[i*3 + j]; + + try { - //CV_INSTRUMENT_REGION_IPP(); - if (*ok == false) - return; + std::atomic_bool ok{true}; + cv::Range cv_range(0, dst_height); + ::ipp::IwiImage iwSrc; + iwSrc.Init(IwiSize{src_width, src_height}, ippiGetDataType(src_type), CV_MAT_CN(src_type), IwiBorderSize(), src_data, IwSize(src_step)); + ::ipp::IwiImage iwDst(IwiSize{dst_width, dst_height}, ippiGetDataType(src_type), CV_MAT_CN(src_type), IwiBorderSize(), dst_data, IwSize(dst_step)); + ::ipp::IwiBorderType ippBorder(ippiGetBorderType(borderType), {borderValue, 4}); + // OpenCV inverts the affine matrix before calling the HAL (lines 2401-2411 of imgwarp.cpp), so the HAL receives the inverse transform. + IwTransDirection iwTransDirection = iwTransInverse; - IPPWarpPerspectiveMem mem; - - int specSize = 0, initSize = 0, bufSize = 0; - - IppiWarpDirection direction = ippWarpBackward; //fixed for IPP - const Ipp32u numChannels = CV_MAT_CN(src_type); - - IppiSize srcsize = {src.cols, src.rows}; - IppiSize dstsize = {dst.cols, dst.rows}; - IppiRect srcroi = {0, 0, src.cols, src.rows}; - - /* Spec and init buffer sizes */ - CV_IPP_SAFE_CALL(ippiWarpPerspectiveGetSize, ok, srcsize, srcroi, dstsize, ippiGetDataType(src_type), coeffs, inter, ippWarpBackward, ippiGetBorderType(borderType), &specSize, &initSize); - - mem.AllocateSpec(specSize); - - CV_IPP_SAFE_CALL(initFunc, ok, srcsize, srcroi, dstsize, ippiGetDataType(src_type), coeffs, direction, numChannels, ippiGetBorderType(borderType), - borderValue, 0, mem.pSpec); - - CV_IPP_SAFE_CALL(ippiWarpGetBufferSize, ok, mem.pSpec, dstsize, &bufSize); - - mem.AllocateBuffer(bufSize); - - IppiPoint dstRoiOffset = {0, range.start}; - IppiSize dstRoiSize = {dst.cols, range.size()}; - auto* pDst = dst.ptr(range.start); - if (borderType == cv::BorderTypes::BORDER_CONSTANT && - !IPPSet(borderValue, pDst, (int)dst_step, dstRoiSize, src.channels(), src.depth())) + if ((int)ippBorder == -1) { - *ok = false; - return; + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + // The lambda function is used to invoke IPP warping function in parallel for different image stripes. + // The function is exception safe and sets the 'ok' flag to false if any exception occurs during processing. + // The 'ok' flag is checked before and after parallel processing to determine if the operation was successful or + // if it should fall back to a non-IPP implementation. + auto IPPWarpAffineInvokerLambda = [&iwSrc, &iwDst, dst_width, ippInter, &coeffs, ippBorder, iwTransDirection, &ok](const cv::Range& range) + { + //CV_INSTRUMENT_REGION_IPP(); + if (!ok.load(std::memory_order_relaxed)) + { + return; + } + + try + { + ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, dst_width, range.end - range.start); + CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, iwSrc, iwDst, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpAffineParams(), ippBorder, tile); + } + catch (const ::ipp::IwException &) + { + ok.store(false, std::memory_order_relaxed); + return; + } + CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); + }; + + int min_payload = 1 << 16; // 64KB shall be minimal per thread to maximize scalability for warping functions + const int num_threads = ippiSuggestRowThreadsNum(iwDst, min_payload); + + if (num_threads > 1) + { + parallel_for_(cv_range, IPPWarpAffineInvokerLambda, num_threads); + } + else + { + CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, iwSrc, iwDst, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpAffineParams(), ippBorder); } - if (ippStsNoErr != CV_INSTRUMENT_FUN_IPP(func, src.ptr(), (int)src_step, pDst, (int)dst_step, dstRoiOffset, dstRoiSize, mem.pSpec, mem.pBuffer)) + if (!ok) { - *ok = false; - return; + return CV_HAL_ERROR_NOT_IMPLEMENTED; } - - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); } -private: - int src_type; - cv::Mat &src; - size_t src_step; - cv::Mat &dst; - size_t dst_step; - IppiInterpolationType inter; - double (&coeffs)[3][3]; - int borderType; - double borderValue[4]; - ippiWarpPerspectiveFunc func; - ippiWarpPerspectiveInitFunc initFunc; - bool *ok; - const IPPWarpPerspectiveInvoker& operator= (const IPPWarpPerspectiveInvoker&); -}; + catch (const ::ipp::IwException &) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + return CV_HAL_ERROR_OK; +} + +#if IPP_VERSION_X100 >= 202600 int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, uchar * dst_data, size_t dst_step, int dst_width, int dst_height, const double M[9], int interpolation, int borderType, const double borderValue[4]) { - CV_HAL_CHECK_USE_IPP(); //CV_INSTRUMENT_REGION_IPP(); + IppiInterpolationType ippInter = ippiGetInterpolation(interpolation); + if (src_height <= 1 || src_width <= 1) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } - ippiWarpPerspectiveFunc ippFunc = nullptr; - ippiWarpPerspectiveInitFunc ippInitFunc = nullptr; + int mode = + interpolation == cv::InterpolationFlags::INTER_NEAREST ? IPPI_INTER_NN : + interpolation == cv::InterpolationFlags::INTER_LINEAR ? IPPI_INTER_LINEAR : 0; - if (interpolation == cv::InterpolationFlags::INTER_NEAREST) - { - ippInitFunc = ippiWarpPerspectiveNearestInit; - ippFunc = - src_type == CV_8UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_8u_C1R : - src_type == CV_8UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_8u_C3R : - src_type == CV_8UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_8u_C4R : - src_type == CV_16UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16u_C1R : - src_type == CV_16UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16u_C3R : - src_type == CV_16UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16u_C4R : - src_type == CV_16SC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16s_C1R : - src_type == CV_16SC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16s_C3R : - src_type == CV_16SC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16s_C4R : - src_type == CV_32FC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_32f_C1R : - src_type == CV_32FC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_32f_C3R : - src_type == CV_32FC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_32f_C4R : nullptr; - } - else if (interpolation == cv::InterpolationFlags::INTER_LINEAR) - { - ippInitFunc = ippiWarpPerspectiveLinearInit; - ippFunc = - src_type == CV_8UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_8u_C1R : - src_type == CV_8UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_8u_C3R : - src_type == CV_8UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_8u_C4R : - src_type == CV_16UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16u_C1R : - src_type == CV_16UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16u_C3R : - src_type == CV_16UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16u_C4R : - src_type == CV_16SC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16s_C1R : - src_type == CV_16SC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16s_C3R : - src_type == CV_16SC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16s_C4R : - src_type == CV_32FC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_32f_C1R : - src_type == CV_32FC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_32f_C3R : - src_type == CV_32FC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_32f_C4R : nullptr; - } - else + if (mode == 0) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } - if (ippFunc == nullptr) + // Unsupported source type + if (src_type != CV_8UC1 && src_type != CV_8UC3 && src_type != CV_8UC4 && + src_type != CV_16UC1 && src_type != CV_16UC3 && src_type != CV_16UC4 && + src_type != CV_16SC1 && src_type != CV_16SC3 && src_type != CV_16SC4 && + src_type != CV_32FC1 && src_type != CV_32FC3 && src_type != CV_32FC4) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } @@ -396,46 +231,90 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step {{0, 0}, {0, 0}, {0, 1}, {0, 1}}, //16U {{1, 1}, {0, 0}, {1, 1}, {1, 1}}, //16S {{1, 1}, {0, 0}, {1, 0}, {1, 1}}, //32S - {{0, 0}, {0, 0}, {0, 0}, {1, 0}}, //32F + {{1, 0}, {0, 0}, {0, 0}, {1, 0}}, //32F {{0, 0}, {0, 0}, {0, 0}, {0, 0}}}; //64F #endif - const char type_size[CV_DEPTH_MAX] = {1,1,2,2,4,4,8}; - if(impl[CV_TYPE(src_type)][CV_MAT_CN(src_type)-1][interpolation] == 0) + if (impl[CV_TYPE(src_type)][CV_MAT_CN(src_type)-1][interpolation] == 0) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + + // Acquire data and begin processing double coeffs[3][3]; for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) coeffs[i][j] = M[i*3 + j]; - bool ok = true; - cv::Range range(0, dst_height); - cv::Mat src(cv::Size(src_width, src_height), src_type, const_cast(src_data), src_step); - cv::Mat dst(cv::Size(dst_width, dst_height), src_type, dst_data, dst_step); - IppiInterpolationType ippInter = ippiGetInterpolation(interpolation); - - int min_payload = 1 << 16; // 64KB shall be minimal per thread to maximize scalability for warping functions - int num_threads = ippiSuggestRowThreadsNum(dst_width, dst_height, type_size[CV_TYPE(src_type)]*CV_MAT_CN(src_type), min_payload); - - IPPWarpPerspectiveInvoker invoker(src_type, src, src_step, dst, dst_step, ippInter, coeffs, borderType, borderValue, ippFunc, ippInitFunc, &ok); - - (num_threads > 1) ? parallel_for_(range, invoker, num_threads) : invoker(range); - - if (ok) + try { - CV_IMPL_ADD(CV_IMPL_IPP | CV_IMPL_MT); - return CV_HAL_ERROR_OK; + std::atomic_bool ok{true}; + cv::Range cv_range(0, dst_height); + ::ipp::IwiImage iwSrc; // src_data is const pointer. So, we need to call an init function + iwSrc.Init(IwiSize{src_width, src_height}, ippiGetDataType(src_type), CV_MAT_CN(src_type), IwiBorderSize(), src_data, IwSize(src_step)); + ::ipp::IwiImage iwDst(IwiSize{dst_width, dst_height}, ippiGetDataType(src_type), CV_MAT_CN(src_type), IwiBorderSize(), dst_data, IwSize(dst_step)); + ::ipp::IwiBorderType ippBorder(ippiGetBorderType(borderType), {borderValue, 4}); + IwTransDirection iwTransDirection = iwTransInverse; //fixed for IPP + if ((int)ippBorder == -1) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + // The lambda function is used to invoke IPP warping function in parallel for different image stripes. + // The function is exception safe and sets the 'ok' flag to false if any exception occurs during processing. + // The 'ok' flag is checked before and after parallel processing to determine + // if the operation was successful or if it should fall back to a non-IPP implementation. + auto IPPWarpPerspectiveInvokerLambda = [&iwSrc, &iwDst, dst_width, ippInter, &coeffs, ippBorder, iwTransDirection, &ok](const cv::Range& range) + { + //CV_INSTRUMENT_REGION_IPP(); + if (!ok.load(std::memory_order_relaxed)) + { + return; + } + + try + { + ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, dst_width, range.end - range.start); + CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpPerspective, iwSrc, iwDst, ippRectInfinite, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpPerspectiveParams(), ippBorder, tile); + } + catch (const ::ipp::IwException &) + { + ok.store(false, std::memory_order_relaxed); + return; + } + CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); + }; + + int min_payload = 1 << 16; // 64KB shall be minimal per thread to maximize scalability for warping functions + const char type_size[CV_DEPTH_MAX] = {1,1,2,2,4,4,8}; + const int num_threads = ippiSuggestRowThreadsNum(dst_width, dst_height, type_size[CV_TYPE(src_type)]*CV_MAT_CN(src_type), min_payload); + + if (num_threads > 1) + { + parallel_for_(cv_range, IPPWarpPerspectiveInvokerLambda, num_threads); + } + else + { + CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpPerspective, iwSrc, iwDst, ippRectInfinite, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpPerspectiveParams(), ippBorder); + } + + if (!ok) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + } + catch (const ::ipp::IwException &) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; } - return CV_HAL_ERROR_NOT_IMPLEMENTED; + return CV_HAL_ERROR_OK; } +#endif // IPP_VERSION_X100 >= 202600 -// End of Warp perspective section +#endif // HAVE_IPP_IW // Remap section - typedef IppStatus(CV_STDCALL *ippiRemap)(const void *pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi, const Ipp32f *pxMap, int xMapStep, const Ipp32f *pyMap, int yMapStep, void *pDst, int dstStep, IppiSize dstRoiSize, int interpolation); @@ -445,20 +324,18 @@ class IPPRemapInvoker : public cv::ParallelLoopBody public: IPPRemapInvoker(int _src_type, const uchar *_src_data, size_t _src_step, int _src_width, int _src_height, uchar *_dst_data, size_t _dst_step, int _dst_width, float *_mapx, size_t _mapx_step, float *_mapy, - size_t _mapy_step, ippiRemap _ippFunc, int _ippInterpolation, int _borderType, const double _borderValue[4], bool *_ok) : - ParallelLoopBody(), + size_t _mapy_step, ippiRemap _ippFunc, int _ippInterpolation, int _borderType, const double _borderValue[4], std::atomic_bool *_ok) : src_type(_src_type), src(_src_data), src_step(_src_step), src_width(_src_width), src_height(_src_height), dst(_dst_data), dst_step(_dst_step), dst_width(_dst_width), mapx(_mapx), mapx_step(_mapx_step), mapy(_mapy), mapy_step(_mapy_step), ippFunc(_ippFunc), ippInterpolation(_ippInterpolation), borderType(_borderType), ok(_ok) { memcpy(this->borderValue, _borderValue, sizeof(this->borderValue)); - *ok = true; } virtual void operator()(const cv::Range &range) const { //CV_INSTRUMENT_REGION_IPP(); - if (*ok == false) + if(!ok->load(std::memory_order_relaxed)) return; IppiRect srcRoiRect = {0, 0, src_width, src_height}; @@ -469,7 +346,7 @@ public: if (borderType == cv::BORDER_CONSTANT && !IPPSet(borderValue, dst_roi_data, (int)dst_step, dstRoiSize, cn, depth)) { - *ok = false; + ok->store(false, std::memory_order_relaxed); return; } @@ -477,7 +354,7 @@ public: mapx, (int)mapx_step, mapy, (int)mapy_step, dst_roi_data, (int)dst_step, dstRoiSize, ippInterpolation)) { - *ok = false; + ok->store(false, std::memory_order_relaxed); return; } @@ -499,7 +376,7 @@ private: ippiRemap ippFunc; int ippInterpolation, borderType; double borderValue[4]; - bool *ok; + std::atomic_bool *ok; }; int ipp_hal_remap32f(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, @@ -507,7 +384,6 @@ int ipp_hal_remap32f(int src_type, const uchar *src_data, size_t src_step, int s float *mapx, size_t mapx_step, float *mapy, size_t mapy_step, int interpolation, int border_type, const double border_value[4]) { - CV_HAL_CHECK_USE_IPP(); if (!((interpolation == cv::INTER_LINEAR || interpolation == cv::INTER_CUBIC || interpolation == cv::INTER_NEAREST) && (border_type == cv::BORDER_CONSTANT || border_type == cv::BORDER_TRANSPARENT))) { @@ -555,7 +431,7 @@ int ipp_hal_remap32f(int src_type, const uchar *src_data, size_t src_step, int s if (ippFunc) { - bool ok = true; + std::atomic_bool ok{true}; IPPRemapInvoker invoker(src_type, src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, mapx, mapx_step, mapy, mapy_step, ippFunc, ippInterpolation, border_type, border_value, &ok); diff --git a/hal/kleidicv/kleidicv.cmake b/hal/kleidicv/kleidicv.cmake index 4ea691f97a..61c398b3e2 100644 --- a/hal/kleidicv/kleidicv.cmake +++ b/hal/kleidicv/kleidicv.cmake @@ -1,8 +1,8 @@ function(download_kleidicv root_var) set(${root_var} "" PARENT_SCOPE) - ocv_update(KLEIDICV_SRC_COMMIT "0.7.0") - ocv_update(KLEIDICV_SRC_HASH "e8f94e427bd78a745afa5c8cd073b416") + ocv_update(KLEIDICV_SRC_COMMIT "26.03") + ocv_update(KLEIDICV_SRC_HASH "b85a745bfe0e87e67e30be9533eb6b24") set(THE_ROOT "${OpenCV_BINARY_DIR}/3rdparty/kleidicv") ocv_download(FILENAME "kleidicv-${KLEIDICV_SRC_COMMIT}.tar.gz" diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 79add3cad1..240e77702e 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -708,9 +708,15 @@ __CV_ENUM_FLAGS_BITWISE_XOR_EQ (EnumType, EnumType) #endif #if defined(__clang__) || defined(__GNUC__) - #define CV_DISABLE_UBSAN __attribute__((no_sanitize("undefined"))) -#else - #define CV_DISABLE_UBSAN +# if defined(__has_attribute) +# if __has_attribute(no_sanitize) +# define CV_DISABLE_UBSAN __attribute__((no_sanitize("undefined"))) +# endif +# endif +#endif + +#ifndef CV_DISABLE_UBSAN +# define CV_DISABLE_UBSAN #endif /****************************************************************************************\ diff --git a/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp b/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp index 8fd2257171..7abfad01df 100644 --- a/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp @@ -2620,23 +2620,25 @@ inline v_float32 v_matmul(const v_float32& v, const v_float32& mat0, const v_float32& mat1, const v_float32& mat2, const v_float32& mat3) { - vfloat32m2_t res; - res = __riscv_vfmul_vf_f32m2(mat0, v_extract_n(v, 0), VTraits::vlanes()); - res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v, 1), mat1, VTraits::vlanes()); - res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v, 2), mat2, VTraits::vlanes()); - res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v, 3), mat3, VTraits::vlanes()); - return res; + const int vl = VTraits::vlanes(); + vuint32m2_t idx = __riscv_vand(__riscv_vid_v_u32m2(vl), 0xfffffffc, vl); + v_float32 v0 = __riscv_vrgather(v, idx, vl); + v_float32 v1 = __riscv_vrgather(v, __riscv_vadd(idx, 1, vl), vl); + v_float32 v2 = __riscv_vrgather(v, __riscv_vadd(idx, 2, vl), vl); + v_float32 v3 = __riscv_vrgather(v, __riscv_vadd(idx, 3, vl), vl); + return v_fma(v0, mat0, v_fma(v1, mat1, v_fma(v2, mat2, v_mul(v3, mat3)))); } -// TODO: only 128 bit now. inline v_float32 v_matmuladd(const v_float32& v, const v_float32& mat0, const v_float32& mat1, const v_float32& mat2, const v_float32& a) { - vfloat32m2_t res = __riscv_vfmul_vf_f32m2(mat0, v_extract_n(v,0), VTraits::vlanes()); - res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v,1), mat1, VTraits::vlanes()); - res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v,2), mat2, VTraits::vlanes()); - return __riscv_vfadd(res, a, VTraits::vlanes()); + const int vl = VTraits::vlanes(); + vuint32m2_t idx = __riscv_vand(__riscv_vid_v_u32m2(vl), 0xfffffffc, vl); + v_float32 v0 = __riscv_vrgather(v, idx, vl); + v_float32 v1 = __riscv_vrgather(v, __riscv_vadd(idx, 1, vl), vl); + v_float32 v2 = __riscv_vrgather(v, __riscv_vadd(idx, 2, vl), vl); + return v_fma(v0, mat0, v_fma(v1, mat1, v_fma(v2, mat2, a))); } inline void v_cleanup() {} diff --git a/modules/core/misc/java/test/CoreTest.java b/modules/core/misc/java/test/CoreTest.java index 62d72b706f..8d6b731616 100644 --- a/modules/core/misc/java/test/CoreTest.java +++ b/modules/core/misc/java/test/CoreTest.java @@ -1820,12 +1820,18 @@ public class CoreTest extends OpenCVTestCase { assertGE(1e-6, Math.abs(Core.solvePoly(coeffs, roots))); - truth = new Mat(3, 1, CvType.CV_32FC2) { + List rootsReIm = new ArrayList(); + Core.split(roots, rootsReIm); + Core.sort(rootsReIm.get(0), dst, Core.SORT_EVERY_COLUMN); + + Mat truthRe = new Mat(3, 1, CvType.CV_32F) { { - put(0, 0, 1, 0, 2, 0, 3, 0); + put(0, 0, 1, 2, 3); } }; - assertMatEqual(truth, roots, EPS); + Mat truthIm = Mat.zeros(3, 1, CvType.CV_32F); + assertMatEqual(truthRe, dst, EPS); + assertMatEqual(truthIm, rootsReIm.get(1), EPS); } public void testSolvePolyMatMatInt() { @@ -1836,14 +1842,20 @@ public class CoreTest extends OpenCVTestCase { }; Mat roots = new Mat(); - assertEquals(10.198039027185569, Core.solvePoly(coeffs, roots, 1)); + assertGE(1e-6, Core.solvePoly(coeffs, roots, 10)); - truth = new Mat(3, 1, CvType.CV_32FC2) { + List rootsReIm = new ArrayList(); + Core.split(roots, rootsReIm); + Core.sort(rootsReIm.get(0), dst, Core.SORT_EVERY_COLUMN); + + Mat truthRe = new Mat(3, 1, CvType.CV_32F) { { - put(0, 0, 1, 0, -1, 2, -2, 12); + put(0, 0, 1, 2, 3); } }; - assertMatEqual(truth, roots, EPS); + Mat truthIm = Mat.zeros(3, 1, CvType.CV_32F); + assertMatEqual(truthRe, dst, EPS); + assertMatEqual(truthIm, rootsReIm.get(1), EPS); } public void testSort() { diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index c42171aa77..8b927f79b1 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -1585,7 +1585,40 @@ double cv::solvePoly( InputArray _coeffs0, OutputArray _roots0, int maxIters ) break; } - C p(1, 0), r(1, 1); + // Related issue: https://github.com/opencv/opencv/issues/23644, + // This the initialization scheme of "Initial approximations in Durand-Kerner's root finding method" by Guggenheimer. + // https://link.springer.com/article/10.1007/BF01935059 + // We put the initial points equidistantly on a circle on the complex plane. This code computes the circle radius as in the paper. + Mat absCoeffs(n + 1, 1, CV_64F); + for( i = 0; i <= n; i++ ) + absCoeffs.at(i) = abs(coeffs[i]); + + int nonZeroCoeffs = 0; + Mat u(n, 1, CV_64F, Scalar(0)), v(n, 1, CV_64F, Scalar(0)); + for( i = 0; i <= n; i++ ) + { + double coeff = absCoeffs.at(i); + if( coeff > DBL_EPSILON ) + { + if( i != n ) + u.at(i) = 2.0 * pow(coeff / absCoeffs.at(n), 1.0 / (n - i)); + if( i != 0 ) + v.at(i - 1) = 0.5 * pow(absCoeffs.at(0) / coeff, 1.0 / i); + nonZeroCoeffs++; + } + } + double scale = 1; + if( nonZeroCoeffs > 2 ) + { + Point maxU, minV; + minMaxLoc(u, nullptr, nullptr, nullptr, &maxU); + minMaxLoc(v, nullptr, nullptr, &minV); + u.at(maxU) = 0; + v.at(minV) = 0; + scale = (sum(u).val[0] + sum(v).val[0]) / (2 * nonZeroCoeffs - 2); + } + + C p(scale, 0), r(cos(CV_2PI / n), sin(CV_2PI / n)); for( i = 0; i < n; i++ ) { diff --git a/modules/core/src/matmul.simd.hpp b/modules/core/src/matmul.simd.hpp index 7f53f5583d..8781ab1626 100644 --- a/modules/core/src/matmul.simd.hpp +++ b/modules/core/src/matmul.simd.hpp @@ -1596,8 +1596,7 @@ static void transform_32f( const float* src, float* dst, const float* m, int len, int scn, int dcn ) { // Disabled for RISC-V Vector (scalable), because of: -// 1. v_matmuladd for RVV is 128-bit only but not scalable, this will fail the test `Core_Transform.accuracy`. -// 2. Both gcc and clang can autovectorize this, with better performance than using Universal intrinsic. +// 1. Both gcc and clang can autovectorize this, with better performance than using Universal intrinsic. #if (CV_SIMD || CV_SIMD_SCALABLE) && !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) && !(CV_TRY_RVV && CV_RVV) int x = 0; if( scn == 3 && dcn == 3 ) diff --git a/modules/core/src/norm.simd.hpp b/modules/core/src/norm.simd.hpp index a13a19e090..d5fd51cfda 100644 --- a/modules/core/src/norm.simd.hpp +++ b/modules/core/src/norm.simd.hpp @@ -1283,7 +1283,7 @@ struct MaskedNormInf_SIMD { v_float32 acc = vx_setzero_f32(); for (; i <= len - vstep; i += vstep) { - v_uint32 m = v_reinterpret_as_u32(vx_load_expand(mask + i)); + v_uint32 m = vx_load_expand_q(mask + i); v_uint32 cmp = v_gt(m, vx_setzero_u32()); v_float32 s = vx_load(src + i); s = v_abs(s); diff --git a/modules/core/test/test_intrin_utils.hpp b/modules/core/test/test_intrin_utils.hpp index 8bb44624b2..ea94f98f1f 100644 --- a/modules/core/test/test_intrin_utils.hpp +++ b/modules/core/test/test_intrin_utils.hpp @@ -1570,9 +1570,8 @@ template struct TheTest R v = dataV, a = dataA, b = dataB, c = dataC, d = dataD; Data res = v_matmul(v, a, b, c, d); - // for (int i = 0; i < VTraits::vlanes(); i += 4) - // { - int i = 0; + for (int i = 0; i < VTraits::vlanes(); i += 4) + { for (int j = i; j < i + 4; ++j) { SCOPED_TRACE(cv::format("i=%d j=%d", i, j)); @@ -1582,12 +1581,11 @@ template struct TheTest + dataV[i + 3] * dataD[j]; EXPECT_COMPARE_EQ(val, res[j]); } - // } + } Data resAdd = v_matmuladd(v, a, b, c, d); - // for (int i = 0; i < VTraits::vlanes(); i += 4) - // { - i = 0; + for (int i = 0; i < VTraits::vlanes(); i += 4) + { for (int j = i; j < i + 4; ++j) { SCOPED_TRACE(cv::format("i=%d j=%d", i, j)); @@ -1597,7 +1595,7 @@ template struct TheTest + dataD[j]; EXPECT_COMPARE_EQ(val, resAdd[j]); } - // } + } return *this; } diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index 70d03a23b9..37c27ca801 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -1978,6 +1978,93 @@ TEST(Core_SolvePoly, regression_5599) } } +TEST(Core_SolvePoly, regression_23644) +{ + // x^2 - 2x - 3 = 0, roots: 3, -1 + cv::Mat coefs = (cv::Mat_(1,3) << -3, -2, 1 ); + cv::Mat r; + double prec; + prec = cv::solvePoly(coefs, r); + EXPECT_LE(prec, 1e-6); + EXPECT_EQ(2u, r.total()); + ASSERT_EQ(CV_32FC2, r.type()); + checkRoot(r, 3, 0); + checkRoot(r, -1, 0); +} + +TEST(Core_SolvePoly, degree_2_polynomials) +{ + cv::Mat_ coefs(1,3); + cv::Mat r; + double prec; + for (float c0 = -20; c0 <= 20; c0++) + { + coefs.at(0) = c0; + for (float c1 = -20; c1 <= 20; c1++) + { + coefs.at(1) = c1; + for (float c2 = -20; c2 <= 20; c2++) + { + coefs.at(2) = c2; + prec = cv::solvePoly(coefs, r); + EXPECT_LE(prec, 1e-6); + } + } + } +} + +TEST(Core_SolvePoly, degree_4_polynomials) +{ + applyTestTag(CV_TEST_TAG_VERYLONG); + + cv::Mat_ coefs(1,5); + cv::Mat r; + double prec; + for (float c0 = -10; c0 <= 10; c0++) + { + coefs.at(0) = c0; + for (float c1 = -10; c1 <= 10; c1++) + { + coefs.at(1) = c1; + for (float c2 = -10; c2 <= 10; c2++) + { + coefs.at(2) = c2; + for (float c3 = -10; c3 <= 10; c3++) + { + coefs.at(3) = c3; + for (float c4 = -10; c4 <= 10; c4++) + { + coefs.at(4) = c4; + prec = cv::solvePoly(coefs, r); + EXPECT_LE(prec, 1e-3); + } + } + } + } + } +} + +TEST(Core_SolvePoly, different_magnitudes_polynomials) +{ + cv::Mat_ coefs(1,3); + cv::Mat r; + double prec; + for (float i = -10; i < 10; i++) + { + coefs.at(0) = pow(2.f, i); + for (float j = -10; j < 10; j++) + { + coefs.at(1) = pow(2.f, j); + for (float k = -10; k < 10; k++) + { + coefs.at(2) = pow(2.f, k); + prec = cv::solvePoly(coefs, r); + EXPECT_LE(prec, 1e-6); + } + } + } +} + class Core_PhaseTest : public cvtest::BaseTest { int t; diff --git a/modules/dnn/misc/python/test/test_dnn.py b/modules/dnn/misc/python/test/test_dnn.py index 7343b5b6be..b4aa46750b 100755 --- a/modules/dnn/misc/python/test/test_dnn.py +++ b/modules/dnn/misc/python/test/test_dnn.py @@ -231,7 +231,7 @@ class dnn_test(NewOpenCVTests): iouDiff = 0.05 confThreshold = 0.0001 nmsThreshold = 0 - scoreDiff = 1e-3 + scoreDiff = 1.1e-3 classIds, confidences, boxes = model.detect(frame, confThreshold, nmsThreshold) diff --git a/modules/dnn/test/test_caffe_importer.cpp b/modules/dnn/test/test_caffe_importer.cpp index ed8f91f026..6bc7689346 100644 --- a/modules/dnn/test/test_caffe_importer.cpp +++ b/modules/dnn/test/test_caffe_importer.cpp @@ -278,7 +278,7 @@ TEST(Reproducibility_FCN, Accuracy) int shape[] = {1, 21, 500, 500}; Mat ref(4, shape, CV_32FC1, refData.data); - normAssert(ref, out); + normAssert(ref, out, "", 0.013, 0.17); } TEST(Reproducibility_SSD, Accuracy) diff --git a/modules/dnn/test/test_common.impl.hpp b/modules/dnn/test/test_common.impl.hpp index ad77db95fc..74e1ce14aa 100644 --- a/modules/dnn/test/test_common.impl.hpp +++ b/modules/dnn/test/test_common.impl.hpp @@ -138,6 +138,8 @@ void normAssertDetections( const char *comment /*= ""*/, double confThreshold /*= 0.0*/, double scores_diff /*= 1e-5*/, double boxes_iou_diff /*= 1e-4*/) { + scores_diff = std::max(0.022, scores_diff); + boxes_iou_diff = std::max(0.019, boxes_iou_diff); ASSERT_FALSE(testClassIds.empty()) << "No detections"; std::vector matchedRefBoxes(refBoxes.size(), false); std::vector refBoxesIoUDiff(refBoxes.size(), 1.0); diff --git a/modules/dnn/test/test_int8_layers.cpp b/modules/dnn/test/test_int8_layers.cpp index b74d64144f..88013f78bd 100644 --- a/modules/dnn/test/test_int8_layers.cpp +++ b/modules/dnn/test/test_int8_layers.cpp @@ -979,7 +979,7 @@ TEST_P(Test_Int8_nets, MobileNet_v1_SSD) Mat blob = blobFromImage(inp, 1.0, Size(300, 300), Scalar(), true, false); Mat ref = blobFromNPY(_tf("tensorflow/ssd_mobilenet_v1_coco_2017_11_17.detection_out.npy")); - float confThreshold = 0.5, scoreDiff = 0.034, iouDiff = 0.13; + float confThreshold = 0.5, scoreDiff = 0.034, iouDiff = 0.14; testDetectionNet(net, blob, ref, confThreshold, scoreDiff, iouDiff); } @@ -997,7 +997,7 @@ TEST_P(Test_Int8_nets, MobileNet_v1_SSD_PPN) Mat blob = blobFromImage(inp, 1.0, Size(300, 300), Scalar(), true, false); Mat ref = blobFromNPY(_tf("tensorflow/ssd_mobilenet_v1_ppn_coco.detection_out.npy")); - float confThreshold = 0.51, scoreDiff = 0.05, iouDiff = 0.06; + float confThreshold = 0.51, scoreDiff = 0.05, iouDiff = 0.07; testDetectionNet(net, blob, ref, confThreshold, scoreDiff, iouDiff); } @@ -1259,7 +1259,7 @@ TEST_P(Test_Int8_nets, YOLOv3) std::string model_file = "yolov3.onnx"; - double scoreDiff = 0.08, iouDiff = 0.21, confThreshold = 0.25; + double scoreDiff = 0.08, iouDiff = 0.21, confThreshold = 0.28; { SCOPED_TRACE("batch size 1"); testYOLOModel(model_file, ref.rowRange(0, N0), scoreDiff, iouDiff, confThreshold); @@ -1285,7 +1285,7 @@ TEST_P(Test_Int8_nets, YOLOv4) applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL); const int N0 = 3; - const int N1 = 7; + const int N1 = 5; static const float ref_[/* (N0 + N1) * 7 */] = { 0, 16, 0.992194f, 0.172375f, 0.402458f, 0.403918f, 0.932801f, 0, 1, 0.988326f, 0.166708f, 0.228236f, 0.737208f, 0.735803f, @@ -1296,8 +1296,6 @@ TEST_P(Test_Int8_nets, YOLOv4) 1, 2, 0.98233f, 0.452007f, 0.462217f, 0.495612f, 0.521687f, 1, 9, 0.919195f, 0.374642f, 0.316524f, 0.398126f, 0.393714f, 1, 9, 0.856303f, 0.666842f, 0.372215f, 0.685539f, 0.44141f, -1, 9, 0.313516f, 0.656791f, 0.374734f, 0.671959f, 0.438371f, -1, 9, 0.256625f, 0.940232f, 0.326931f, 0.967586f, 0.374002f, }; Mat ref(N0 + N1, 7, CV_32FC1, (void*)ref_); @@ -1305,13 +1303,13 @@ TEST_P(Test_Int8_nets, YOLOv4) double scoreDiff = 0.15, iouDiff = 0.2; { SCOPED_TRACE("batch size 1"); - testYOLOModel(model_file, ref.rowRange(0, N0), scoreDiff, iouDiff); + testYOLOModel(model_file, ref.rowRange(0, N0), scoreDiff, iouDiff, 0.5); } { SCOPED_TRACE("batch size 2"); - testYOLOModel(model_file, ref, scoreDiff, iouDiff); + testYOLOModel(model_file, ref, scoreDiff, iouDiff, 0.5); } } diff --git a/modules/dnn/test/test_model.cpp b/modules/dnn/test/test_model.cpp index 4ef3022672..b0531fa5e1 100644 --- a/modules/dnn/test/test_model.cpp +++ b/modules/dnn/test/test_model.cpp @@ -460,7 +460,7 @@ TEST_P(Test_Model, Keypoints_face) bool swapRB = false; // Ref. Range: [-1.1784188, 1.7758257] - float norm = 1e-4; + float norm = 2e-3; if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16) norm = 5e-3; if (target == DNN_TARGET_MYRIAD) diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index d43fe21717..5073dfcb1d 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -2432,7 +2432,7 @@ TEST_P(Test_ONNX_nets, RAFT) // and output 12006 is calculated from 12007 so checking 12007 is sufficient. std::string ref_12700_path = _tf("data/output_optical_flow_estimation_raft_2023aug.npy"); auto ref0 = blobFromNPY(ref_12700_path); - normAssert(ref0, outs[0], "", 1e-5, 1.8e-4); + normAssert(ref0, outs[0], "", 1.5e-3, 3.2e-2); } TEST_P(Test_ONNX_nets, Squeezenet) @@ -3503,9 +3503,9 @@ TEST_P(Test_ONNX_nets, VitTrack) { auto ref_output2 = blobFromNPY(_tf("data/output_object_tracking_vittrack_2023sep_1.npy")); auto ref_output3 = blobFromNPY(_tf("data/output_object_tracking_vittrack_2023sep_2.npy")); - normAssert(ref_output1, outputs[0], "VitTrack output1"); - normAssert(ref_output2, outputs[1], "VitTrack output2"); - normAssert(ref_output3, outputs[2], "VitTrack output3"); + normAssert(ref_output1, outputs[0], "VitTrack output1", 3e-5, 3e-4); + normAssert(ref_output2, outputs[1], "VitTrack output2", 3e-5, 2e-4); + normAssert(ref_output3, outputs[2], "VitTrack output3", 3e-4, 9e-4); } TEST_P(Test_ONNX_layers, LayerNormNoFusion) { diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index 4e0e5bd734..4e5e464274 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -70,7 +70,7 @@ TEST(Test_TensorFlow, inception_accuracy) Mat ref = blobFromNPY(_tf("tf_inception_prob.npy")); - normAssert(ref, out); + normAssert(ref, out, "", 5e-5, 0.02); } static std::string path(const std::string& file) @@ -937,16 +937,12 @@ TEST_P(Test_TensorFlow_nets, MobileNet_SSD) net.setInput(inp); Mat out = net.forward(); - double scoreDiff = default_l1, iouDiff = default_lInf; + double scoreDiff = default_l1, iouDiff = 0.04; if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16) { scoreDiff = 0.01; iouDiff = 0.1; } - else if (target == DNN_TARGET_CUDA_FP16) - { - iouDiff = 0.04; - } normAssertDetections(ref, out, "", 0.2, scoreDiff, iouDiff); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE >= 2019010000 diff --git a/modules/dnn/test/test_tflite_importer.cpp b/modules/dnn/test/test_tflite_importer.cpp index c6259927c1..c361c2ad96 100644 --- a/modules/dnn/test/test_tflite_importer.cpp +++ b/modules/dnn/test/test_tflite_importer.cpp @@ -94,7 +94,7 @@ TEST_P(Test_TFLite, face_landmark) { if (backend == DNN_BACKEND_CUDA && target == DNN_TARGET_CUDA_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16); - double l1 = 2.2e-5, lInf = 2e-4; + double l1 = 0.066, lInf = 0.21; if (target == DNN_TARGET_CPU_FP16 || target == DNN_TARGET_CUDA_FP16 || target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)) { @@ -120,7 +120,7 @@ TEST_P(Test_TFLite, face_detection_short_range) // https://google.github.io/mediapipe/solutions/selfie_segmentation TEST_P(Test_TFLite, selfie_segmentation) { - double l1 = 0, lInf = 0; + double l1 = 0.002, lInf = 0.24; if (target == DNN_TARGET_CPU_FP16 || target == DNN_TARGET_CUDA_FP16 || target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)) { diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp index 499036cedf..a2520179b8 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.cpp +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp @@ -825,10 +825,12 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) if( (channels > 1) && ( sampling_factor != 0 ) ) { - cinfo.comp_info[0].v_samp_factor = (sampling_factor >> 16 ) & 0xF; cinfo.comp_info[0].h_samp_factor = (sampling_factor >> 20 ) & 0xF; - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = (sampling_factor >> 16 ) & 0xF; + cinfo.comp_info[1].h_samp_factor = (sampling_factor >> 12 ) & 0xF; + cinfo.comp_info[1].v_samp_factor = (sampling_factor >> 8 ) & 0xF; + cinfo.comp_info[2].h_samp_factor = (sampling_factor >> 4 ) & 0xF; + cinfo.comp_info[2].v_samp_factor = (sampling_factor >> 0 ) & 0xF; } if (luma_quality >= 0 && chroma_quality >= 0) @@ -843,6 +845,8 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; + cinfo.comp_info[2].v_samp_factor = 1; + cinfo.comp_info[2].h_samp_factor = 1; } jpeg_default_qtables( &cinfo, TRUE ); #else diff --git a/modules/imgproc/test/test_connectedcomponents.cpp b/modules/imgproc/test/test_connectedcomponents.cpp index 7d58f714e0..42ee000497 100644 --- a/modules/imgproc/test/test_connectedcomponents.cpp +++ b/modules/imgproc/test/test_connectedcomponents.cpp @@ -240,7 +240,7 @@ TEST(Imgproc_ConnectedComponents, missing_background_pixels) TEST(Imgproc_ConnectedComponents, spaghetti_bbdt_sauf_stats) { - cv::Mat1b img({16, 16}, { + cv::Mat1b img({16, 16}, { (unsigned char) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, @@ -361,8 +361,8 @@ TEST(Imgproc_ConnectedComponents, spaghetti_bbdt_sauf_stats) TEST(Imgproc_ConnectedComponents, chessboard_even) { - const auto size = {16, 16}; - cv::Mat1b input(size, { + auto size = {16, 16}; + cv::Mat1b input(size, { (unsigned char) 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, @@ -445,8 +445,8 @@ TEST(Imgproc_ConnectedComponents, chessboard_even) TEST(Imgproc_ConnectedComponents, chessboard_odd) { - const auto size = {15, 15}; - cv::Mat1b input(size, { + auto size = {15, 15}; + cv::Mat1b input(size, { (unsigned char) 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, @@ -526,8 +526,8 @@ TEST(Imgproc_ConnectedComponents, chessboard_odd) TEST(Imgproc_ConnectedComponents, maxlabels_8conn_even) { - const auto size = {16, 16}; - cv::Mat1b input(size, { + auto size = {16, 16}; + cv::Mat1b input(size, { (unsigned char) 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, @@ -607,8 +607,8 @@ TEST(Imgproc_ConnectedComponents, maxlabels_8conn_even) TEST(Imgproc_ConnectedComponents, maxlabels_8conn_odd) { - const auto size = {15, 15}; - cv::Mat1b input(size, { + auto size = {15, 15}; + cv::Mat1b input(size, { (unsigned char) 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, @@ -685,7 +685,7 @@ TEST(Imgproc_ConnectedComponents, maxlabels_8conn_odd) TEST(Imgproc_ConnectedComponents, single_row) { - const auto size = {1, 15}; + auto size = {1, 15}; cv::Mat1b input(size, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}); cv::Mat1i output_8c(size, {1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8}); cv::Mat1i output_4c(size, {1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8}); @@ -715,8 +715,8 @@ TEST(Imgproc_ConnectedComponents, single_row) TEST(Imgproc_ConnectedComponents, single_column) { - const auto size = {15, 1}; - cv::Mat1b input(size, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}); + auto size = {15, 1}; + cv::Mat1b input(size, {(unsigned char)1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}); cv::Mat1i output_8c(size, {1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8}); cv::Mat1i output_4c(size, {1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8}); diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index 9ffe6701ad..0ccfb77227 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -3,7 +3,6 @@ import sys, re, os.path, errno, fnmatch import json import logging -import codecs from shutil import copyfile from pprint import pformat from string import Template @@ -601,7 +600,7 @@ class JavaWrapperGenerator(object): content = f.read() if content == buf: return - with codecs.open(path, "w", "utf-8") as f: + with open(path, "w", encoding="utf-8") as f: f.write(buf) updated_files += 1 diff --git a/modules/objc/generator/gen_objc.py b/modules/objc/generator/gen_objc.py index 39cbf73581..78fe9454bc 100755 --- a/modules/objc/generator/gen_objc.py +++ b/modules/objc/generator/gen_objc.py @@ -4,7 +4,6 @@ from __future__ import print_function, unicode_literals import sys, re, os.path, errno, fnmatch import json import logging -import codecs import io from shutil import copyfile from pprint import pformat @@ -903,7 +902,7 @@ class ObjectiveCWrapperGenerator(object): content = f.read() if content == buf: return - with codecs.open(path, "w", "utf-8") as f: + with open(path, "w", encoding="utf-8") as f: f.write(buf) updated_files += 1 @@ -1531,7 +1530,7 @@ typedef NS_ENUM(int, {1}) {{ body = file.read() body = body.replace("import OpenCV", "import " + framework_name) body = body.replace("#import ", "#import <" + framework_name + "/" + framework_name + ".h>") - with codecs.open(filepath, "w", "utf-8") as file: + with open(filepath, "w", encoding="utf-8") as file: file.write(body) diff --git a/modules/objdetect/doc/pics/AprilTag_corners_comparison_opencv_april.png b/modules/objdetect/doc/pics/AprilTag_corners_comparison_opencv_april.png new file mode 100644 index 0000000000..3e794fe148 Binary files /dev/null and b/modules/objdetect/doc/pics/AprilTag_corners_comparison_opencv_april.png differ diff --git a/modules/objdetect/doc/pics/AprilTag_family.png b/modules/objdetect/doc/pics/AprilTag_family.png new file mode 100644 index 0000000000..cb9127a85a Binary files /dev/null and b/modules/objdetect/doc/pics/AprilTag_family.png differ diff --git a/modules/objdetect/doc/pics/ArUco_family.png b/modules/objdetect/doc/pics/ArUco_family.png new file mode 100644 index 0000000000..0bdca9c32d Binary files /dev/null and b/modules/objdetect/doc/pics/ArUco_family.png differ diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index 22c3810292..95cb874135 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -78,6 +78,65 @@ @sa @cite Aruco2014 This code has been originally developed by Sergio Garrido-Jurado as a project for Google Summer of Code 2015 (GSoC 15). + +
+ + @warning In OpenCV, the order of the returned corners locations for the AprilTag family is not aligned with the ArUco one.\n + Note that this order is also different from the convention adopted by the official [AprilTag library](https://github.com/AprilRobotics/apriltag/). + ![](pics/AprilTag_corners_comparison_opencv_april.png) { width=80% } + +
+ + An overview of the supported ArUco markers family is visible in the following image: + ![](pics/ArUco_family.png) { width=80% } + +
+ + An overview of the supported AprilTag markers family is visible in the following image: + ![](pics/AprilTag_family.png) { width=80% } + + @note The generated images (in the above picture) using @ref aruco::generateImageMarker for the AprilTag markers have been + rotated by 180 degree in order to match the official AprilTag images. + When using the @ref aruco::generateImageMarker function, it will output by default a different image from the official AprilTag convention, + see the [AprilRobotics/apriltag-imgs](https://github.com/AprilRobotics/apriltag-imgs) repository. + This is the reason why you see a different corners order between ArUco and AprilTag in the above image. + +
+ + For the ArUco marker family, the recommended family is the DICT_ARUCO_MIP_36h12 one, [see](https://stackoverflow.com/a/51511558). + In general, a smaller marker family (e.g. `4x4` vs `6x6`) should give you a better detection rate with respect to the camera distance, + at the expense of having more probability to have issues with false detection or marker id decoding error. + The number of marker ids in a family is also something to take into account with respect to the application use case and the ability + to correct wrong bits during the marker id decoding process. + + You can download some pregenerated MIP_36h12 ArUco marker images from: + - https://sourceforge.net/projects/aruco/files/ + - or use the `samples/cpp/tutorial_code/objectDetection/create_marker.cpp` sample to generate the marker image for your + desired marker family (which uses the @ref aruco::generateImageMarker function) + + For the AprilTag family, you can find some pregenerated marker images in the + [AprilRobotics/apriltag-imgs](https://github.com/AprilRobotics/apriltag-imgs) repository. + + @note For accurate corners location extraction, a white border (to have a strong gradient between white and black transition) around the marker is important. + This is necessary to precisely extract the marker contour in difficult conditions such as bad illumination, confusing color background, etc. + +
+ + There are multiple parameters which can be tweaked to improve the marker detection rate or to be adapted to your use case (e.g. image resolution). + Please refer to the: + - @ref aruco::DetectorParameters + - "Detector Parameters" section in the @ref tutorial_aruco_detection tutorial or in the @ref tutorial_aruco_faq page + - [ArUco Library Documentation](https://drive.google.com/file/d/1OiavRVYVJ-WH88sQg1LUsh8CuJZUQyrX) for additional information from the ArUco library + + The corner refinement method can be changed according to the @ref aruco::CornerRefineMethod to improve the corners location accuracy + at the expense of more computation time. + +
+ + To estimate the marker pose with respect to the camera frame, we recommend you to look at the following sources of information: + - @ref tutorial_aruco_detection for a tutorial about ArUco markers detection + - @ref calib for some theoretical background about the pinhole camera model and the @ref calib3d_solvePnP page + - @ref solvePnP, @ref solvePnPGeneric, @ref solveP3P for the relevant pose estimation methods @} @} diff --git a/modules/videoio/src/cap_mjpeg_encoder.cpp b/modules/videoio/src/cap_mjpeg_encoder.cpp index 41cbcb6c83..d51cb9d07c 100644 --- a/modules/videoio/src/cap_mjpeg_encoder.cpp +++ b/modules/videoio/src/cap_mjpeg_encoder.cpp @@ -161,7 +161,7 @@ public: inline void put_bits(unsigned bits, int len) { CV_Assert(len >=0 && len < 32); - if((m_pos == (data.size() - 1) && len > bits_free) || m_pos == data.size()) + if((m_pos == (data.size() - 1) && len >= bits_free) || m_pos == data.size()) { resize(int(2*data.size())); } diff --git a/modules/videoio/test/test_video_io.cpp b/modules/videoio/test/test_video_io.cpp index e75efe2b33..98159edafe 100644 --- a/modules/videoio/test/test_video_io.cpp +++ b/modules/videoio/test/test_video_io.cpp @@ -1278,4 +1278,21 @@ VideoCaptureAPIs seekable_backeinds[] = {CAP_FFMPEG, CAP_MSMF, CAP_AVFOUNDATION} INSTANTIATE_TEST_CASE_P(videoio, PreciseSeekingTest, testing::ValuesIn(seekable_backeinds), safe_capture_name_printer); +// Regression test for heap-buffer-overflow in mjpeg_buffer::put_bits (GitHub issue #29112). +// When len == bits_free the old guard used strict '>' and skipped the resize, causing +// an out-of-bounds write after '++m_pos' advanced past data.size(). +TEST(Videoio_MJPEG, put_bits_no_heap_overflow) +{ + const std::string filename = cv::tempfile(".avi"); + cv::Mat frame(1, 1, CV_8UC1, cv::Scalar::all(255)); + int fourcc = cv::VideoWriter::fourcc('M', 'J', 'P', 'G'); + { + cv::VideoWriter writer; + ASSERT_NO_THROW(writer.open(filename, CAP_OPENCV_MJPEG, fourcc, 25.0, cv::Size(1, 1), false)); + ASSERT_TRUE(writer.isOpened()); + EXPECT_NO_THROW(writer.write(frame)); + } + remove(filename.c_str()); +} + } // namespace diff --git a/platforms/ios/build_framework.py b/platforms/ios/build_framework.py index e2befffa54..e1345aa608 100755 --- a/platforms/ios/build_framework.py +++ b/platforms/ios/build_framework.py @@ -32,7 +32,7 @@ Adding --dynamic parameter will build {framework_name}.framework as App Store dy """ from __future__ import print_function, unicode_literals -import glob, os, os.path, shutil, string, sys, argparse, traceback, multiprocessing, codecs, io +import glob, os, os.path, shutil, string, sys, argparse, traceback, multiprocessing, io from subprocess import check_call, check_output, CalledProcessError if sys.version_info >= (3, 8): # Python 3.8+ @@ -190,7 +190,7 @@ class Builder: body = body[:insert_pos] + "import " + self.framework_name + "\n" + body[insert_pos:] else: body = "import " + self.framework_name + "\n\n" + body - with codecs.open(os.path.join(swift_sources_dir, file), "w", "utf-8") as file_out: + with open(os.path.join(swift_sources_dir, file), "w", encoding="utf-8") as file_out: file_out.write(body) def build(self, outdir): @@ -380,7 +380,7 @@ class Builder: framework = self.framework_name, hosting_base_path = self.hosting_base_path ) - with codecs.open(os.path.join(docs_dir, "HOWTO.md"), "w", "utf-8") as file: + with open(os.path.join(docs_dir, "HOWTO.md"), "w", encoding="utf-8") as file: file.write(howto) self.docs_built = True execute(["cmake", "-DBUILD_TYPE=%s" % self.getConfiguration(), "-DCMAKE_INSTALL_PREFIX=%s" % (builddir + "/install"), "-P", "cmake_install.cmake"], cwd = framework_build_dir) @@ -473,11 +473,11 @@ class Builder: for dirname, dirs, files in os.walk(os.path.join(dstdir, "Headers")): for filename in files: filepath = os.path.join(dirname, filename) - with codecs.open(filepath, "r", "utf-8") as file: + with open(filepath, "r", encoding="utf-8") as file: body = file.read() body = body.replace("include \"opencv2/", "include \"" + name + "/") body = body.replace("include 0 && markerSize > 0) { FileStorage fs(outputFile, FileStorage::WRITE); if (checkFlippedMarkers) - dictionary = generateCustomAsymmetricDictionary(nMarkers, markerSize, aruco::Dictionary(), 0); + dictionary = generateCustomAsymmetricDictionary(nMarkers, markerSize, dictionary, 0); else - dictionary = aruco::extendDictionary(nMarkers, markerSize, aruco::Dictionary(), 0); + dictionary = aruco::extendDictionary(nMarkers, markerSize, dictionary, 0); dictionary.writeDictionary(fs); } diff --git a/samples/cpp/calibration.cpp b/samples/cpp/calibration.cpp index 1f8ff2b7d3..cc48399924 100644 --- a/samples/cpp/calibration.cpp +++ b/samples/cpp/calibration.cpp @@ -67,7 +67,7 @@ static void help(char** argv) "DICT_4X4_1000, DICT_5X5_50, DICT_5X5_100, DICT_5X5_250, DICT_5X5_1000, " "DICT_6X6_50, DICT_6X6_100, DICT_6X6_250, DICT_6X6_1000, DICT_7X7_50, " "DICT_7X7_100, DICT_7X7_250, DICT_7X7_1000, DICT_ARUCO_ORIGINAL, " - "DICT_APRILTAG_16h5, DICT_APRILTAG_25h9, DICT_APRILTAG_36h10, DICT_APRILTAG_36h11\n" + "DICT_APRILTAG_16h5, DICT_APRILTAG_25h9, DICT_APRILTAG_36h10, DICT_APRILTAG_36h11, DICT_ARUCO_MIP_36h12\n" " [-adf=] # Custom aruco dictionary file for ChArUco board\n" " [-o=] # the output filename for intrinsic [and extrinsic] parameters\n" " [-op] # write detected feature points\n" @@ -459,6 +459,7 @@ int main( int argc, char** argv ) else if (arucoDictName == "DICT_APRILTAG_25h9") { arucoDict = cv::aruco::DICT_APRILTAG_25h9; } else if (arucoDictName == "DICT_APRILTAG_36h10") { arucoDict = cv::aruco::DICT_APRILTAG_36h10; } else if (arucoDictName == "DICT_APRILTAG_36h11") { arucoDict = cv::aruco::DICT_APRILTAG_36h11; } + else if (arucoDictName == "DICT_ARUCO_MIP_36h12") { arucoDict = cv::aruco::DICT_ARUCO_MIP_36h12; } else { cout << "Incorrect Aruco dictionary name " << arucoDictName << std::endl; return 1; diff --git a/samples/cpp/stereo_calib.cpp b/samples/cpp/stereo_calib.cpp index 1294f66314..5968e84554 100644 --- a/samples/cpp/stereo_calib.cpp +++ b/samples/cpp/stereo_calib.cpp @@ -60,7 +60,7 @@ static int print_help(char** argv) << "DICT_4X4_1000, DICT_5X5_50, DICT_5X5_100, DICT_5X5_250, DICT_5X5_1000, " << "DICT_6X6_50, DICT_6X6_100, DICT_6X6_250, DICT_6X6_1000, DICT_7X7_50, " << "DICT_7X7_100, DICT_7X7_250, DICT_7X7_1000, DICT_ARUCO_ORIGINAL, " - << "DICT_APRILTAG_16h5, DICT_APRILTAG_25h9, DICT_APRILTAG_36h10, DICT_APRILTAG_36h11\n"; + << "DICT_APRILTAG_16h5, DICT_APRILTAG_25h9, DICT_APRILTAG_36h10, DICT_APRILTAG_36h11, DICT_ARUCO_MIP_36h12\n"; return 0; } @@ -437,6 +437,7 @@ int main(int argc, char** argv) else if (arucoDictName == "DICT_APRILTAG_25h9") { arucoDict = cv::aruco::DICT_APRILTAG_25h9; } else if (arucoDictName == "DICT_APRILTAG_36h10") { arucoDict = cv::aruco::DICT_APRILTAG_36h10; } else if (arucoDictName == "DICT_APRILTAG_36h11") { arucoDict = cv::aruco::DICT_APRILTAG_36h11; } + else if (arucoDictName == "DICT_ARUCO_MIP_36h12") { arucoDict = cv::aruco::DICT_ARUCO_MIP_36h12; } else { cout << "incorrect name of aruco dictionary \n"; return 1; 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 38daacffa5..4ae2418779 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp @@ -340,6 +340,7 @@ int main(int argc, char* argv[]) else if (s.arucoDictName == "DICT_APRILTAG_25h9") { arucoDict = cv::aruco::DICT_APRILTAG_25h9; } else if (s.arucoDictName == "DICT_APRILTAG_36h10") { arucoDict = cv::aruco::DICT_APRILTAG_36h10; } else if (s.arucoDictName == "DICT_APRILTAG_36h11") { arucoDict = cv::aruco::DICT_APRILTAG_36h11; } + else if (s.arucoDictName == "DICT_ARUCO_MIP_36h12") { arucoDict = cv::aruco::DICT_ARUCO_MIP_36h12; } else { cout << "incorrect name of aruco dictionary \n"; return 1; diff --git a/samples/cpp/tutorial_code/objectDetection/calibrate_camera.cpp b/samples/cpp/tutorial_code/objectDetection/calibrate_camera.cpp index b415477019..5662a84124 100644 --- a/samples/cpp/tutorial_code/objectDetection/calibrate_camera.cpp +++ b/samples/cpp/tutorial_code/objectDetection/calibrate_camera.cpp @@ -25,7 +25,8 @@ const char* keys = "{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," - "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" + "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{cd | | Input file with custom dictionary }" "{@outfile |cam.yml| Output file with calibrated camera parameters }" "{v | | Input from video file, if ommited, input comes from camera }" diff --git a/samples/cpp/tutorial_code/objectDetection/calibrate_camera_charuco.cpp b/samples/cpp/tutorial_code/objectDetection/calibrate_camera_charuco.cpp index 5bea807db9..dcb2c8aa21 100644 --- a/samples/cpp/tutorial_code/objectDetection/calibrate_camera_charuco.cpp +++ b/samples/cpp/tutorial_code/objectDetection/calibrate_camera_charuco.cpp @@ -23,7 +23,8 @@ const char* keys = "{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," - "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" + "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{cd | | Input file with custom dictionary }" "{@outfile |cam.yml| Output file with calibrated camera parameters }" "{v | | Input from video file, if ommited, input comes from camera }" diff --git a/samples/cpp/tutorial_code/objectDetection/create_board.cpp b/samples/cpp/tutorial_code/objectDetection/create_board.cpp index b1864ffc19..4af6f18da4 100644 --- a/samples/cpp/tutorial_code/objectDetection/create_board.cpp +++ b/samples/cpp/tutorial_code/objectDetection/create_board.cpp @@ -16,7 +16,8 @@ const char* keys = "{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," - "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" + "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{cd | | Input file with custom dictionary }" "{m | | Margins size (in pixels). Default is marker separation (-s) }" "{bb | 1 | Number of bits in marker borders }" diff --git a/samples/cpp/tutorial_code/objectDetection/create_board_charuco.cpp b/samples/cpp/tutorial_code/objectDetection/create_board_charuco.cpp index b76708817a..e07bd670ec 100644 --- a/samples/cpp/tutorial_code/objectDetection/create_board_charuco.cpp +++ b/samples/cpp/tutorial_code/objectDetection/create_board_charuco.cpp @@ -17,7 +17,8 @@ const char* keys = "{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," - "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" + "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{cd | | Input file with custom dictionary }" "{m | | Margins size (in pixels). Default is (squareLength-markerLength) }" "{bb | 1 | Number of bits in marker borders }" diff --git a/samples/cpp/tutorial_code/objectDetection/create_diamond.cpp b/samples/cpp/tutorial_code/objectDetection/create_diamond.cpp index 0db00e7e02..07effaca57 100644 --- a/samples/cpp/tutorial_code/objectDetection/create_diamond.cpp +++ b/samples/cpp/tutorial_code/objectDetection/create_diamond.cpp @@ -17,7 +17,8 @@ const char* keys = "{d | 10 | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," - "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" + "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{ids |0, 1, 2, 3 | Four ids for the ChArUco marker: id1,id2,id3,id4 }" "{m | 0 | Margins size (in pixels) }" "{bb | 1 | Number of bits in marker borders }" diff --git a/samples/cpp/tutorial_code/objectDetection/create_marker.cpp b/samples/cpp/tutorial_code/objectDetection/create_marker.cpp index 560e51c974..1ed78e4fe2 100644 --- a/samples/cpp/tutorial_code/objectDetection/create_marker.cpp +++ b/samples/cpp/tutorial_code/objectDetection/create_marker.cpp @@ -6,7 +6,7 @@ using namespace cv; namespace { -const char* about = "Create an ArUco marker image"; +const char* about = "Create an ArUco/AprilTag marker image"; //! [aruco_create_markers_keys] const char* keys = @@ -14,7 +14,8 @@ const char* keys = "{d | 0 | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," - "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" + "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{cd | | Input file with custom dictionary }" "{id | 0 | Marker id in the dictionary }" "{ms | 200 | Marker size in pixels }" diff --git a/samples/cpp/tutorial_code/objectDetection/detect_board.cpp b/samples/cpp/tutorial_code/objectDetection/detect_board.cpp index a9c74f2fdc..c7ed7ca7c0 100644 --- a/samples/cpp/tutorial_code/objectDetection/detect_board.cpp +++ b/samples/cpp/tutorial_code/objectDetection/detect_board.cpp @@ -19,7 +19,8 @@ const char* keys = "{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," - "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" + "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{cd | | Input file with custom dictionary }" "{c | | Output file with calibrated camera parameters }" "{v | | Input from video or image file, if omitted, input comes from camera }" diff --git a/samples/cpp/tutorial_code/objectDetection/detect_board_charuco.cpp b/samples/cpp/tutorial_code/objectDetection/detect_board_charuco.cpp index c02318d6eb..7c4b5a6f50 100644 --- a/samples/cpp/tutorial_code/objectDetection/detect_board_charuco.cpp +++ b/samples/cpp/tutorial_code/objectDetection/detect_board_charuco.cpp @@ -19,7 +19,8 @@ const char* keys = "{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," - "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" + "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{cd | | Input file with custom dictionary }" "{c | | Output file with calibrated camera parameters }" "{v | | Input from video or image file, if ommited, input comes from camera }" diff --git a/samples/cpp/tutorial_code/objectDetection/detect_diamonds.cpp b/samples/cpp/tutorial_code/objectDetection/detect_diamonds.cpp index f6a6236b2a..37097d87e9 100644 --- a/samples/cpp/tutorial_code/objectDetection/detect_diamonds.cpp +++ b/samples/cpp/tutorial_code/objectDetection/detect_diamonds.cpp @@ -16,7 +16,8 @@ const char* keys = "{d | 10 | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," - "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" + "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{cd | | Input file with custom dictionary }" "{c | | Output file with calibrated camera parameters }" "{as | | Automatic scale. The provided number is multiplied by the last" diff --git a/samples/cpp/tutorial_code/objectDetection/detect_markers.cpp b/samples/cpp/tutorial_code/objectDetection/detect_markers.cpp index f220b84565..06aa6221c4 100644 --- a/samples/cpp/tutorial_code/objectDetection/detect_markers.cpp +++ b/samples/cpp/tutorial_code/objectDetection/detect_markers.cpp @@ -15,7 +15,7 @@ const char* keys = "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16," - "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20}" + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}" "{cd | | Input file with custom dictionary }" "{v | | Input from video or image file, if ommited, input comes from camera }" "{ci | 0 | Camera id if input doesnt come from video (-v) }" diff --git a/samples/python/aruco_detect_board_charuco.py b/samples/python/aruco_detect_board_charuco.py index ffb5ac677d..58ba5a899f 100644 --- a/samples/python/aruco_detect_board_charuco.py +++ b/samples/python/aruco_detect_board_charuco.py @@ -36,7 +36,8 @@ def main(): parser.add_argument("-d", help="dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2, DICT_4X4_1000=3," "DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, DICT_6X6_50=8," "DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12, DICT_7X7_100=13," - "DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}", + "DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16," + "DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}", default="0", action="store", dest="d", type=int) parser.add_argument("-ci", help="Camera id if input doesnt come from video (-v)", default="0", action="store", dest="ci", type=int) diff --git a/samples/python/calibrate.py b/samples/python/calibrate.py index 33c87b6a52..19c0ab0d66 100755 --- a/samples/python/calibrate.py +++ b/samples/python/calibrate.py @@ -100,7 +100,8 @@ def main(): 'DICT_APRILTAG_16h5': cv.aruco.DICT_APRILTAG_16h5, 'DICT_APRILTAG_25h9': cv.aruco.DICT_APRILTAG_25h9, 'DICT_APRILTAG_36h10': cv.aruco.DICT_APRILTAG_36h10, - 'DICT_APRILTAG_36h11': cv.aruco.DICT_APRILTAG_36h11 + 'DICT_APRILTAG_36h11': cv.aruco.DICT_APRILTAG_36h11, + 'DICT_ARUCO_MIP_36h12': cv.aruco.DICT_ARUCO_MIP_36h12 } if (aruco_dict_name not in set(aruco_dicts.keys())):