From 85009800b3d98ec0370ab718a2afa32f2991b29b Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sun, 7 Mar 2021 04:26:49 +0000 Subject: [PATCH 01/15] videoio(docs): fixes --- doc/tutorials/videoio/video-write/video_write.markdown | 2 +- modules/videoio/doc/videoio_overview.markdown | 4 ++-- modules/videoio/include/opencv2/videoio.hpp | 6 +++++- samples/cpp/videocapture_gstreamer_pipeline.cpp | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/tutorials/videoio/video-write/video_write.markdown b/doc/tutorials/videoio/video-write/video_write.markdown index 29b6cf6f4e..9377780f3d 100644 --- a/doc/tutorials/videoio/video-write/video_write.markdown +++ b/doc/tutorials/videoio/video-write/video_write.markdown @@ -59,7 +59,7 @@ extension, its first version. A direct limitation of this is that you cannot sav larger than 2 GB. Furthermore you can only create and expand a single video track inside the container. No audio or other track editing support here. Nevertheless, any video codec present on your system might work. If you encounter some of these limitations you will need to look into more -specialized video writing libraries such as *FFMpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As +specialized video writing libraries such as *FFmpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As an alternative, create the video track with OpenCV and expand it with sound tracks or convert it to other formats by using video manipulation programs such as *VirtualDub* or *AviSynth*. diff --git a/modules/videoio/doc/videoio_overview.markdown b/modules/videoio/doc/videoio_overview.markdown index 13602fade0..26930ce87b 100644 --- a/modules/videoio/doc/videoio_overview.markdown +++ b/modules/videoio/doc/videoio_overview.markdown @@ -15,7 +15,7 @@ I/O APIs used as backend. ![Video I/O with OpenCV](pics/videoio_overview.svg) -Some backends such as (DSHOW) Direct Show, Video For Windows (VFW), Microsoft Media Foundation (MSMF), +Some backends such as Direct Show (DSHOW), Video For Windows (VFW), Microsoft Media Foundation (MSMF), Video 4 Linux (V4L), etc... are interfaces to the video I/O library provided by the operating system. Some others backends like OpenNI2 for Kinect, Intel Perceptual Computing SDK, GStreamer, @@ -87,7 +87,7 @@ The FFmpeg library OpenCV can use the FFmpeg library (http://ffmpeg.org/) as backend to record, convert and stream audio and video. FFmpeg is a complete, cross-reference solution. If you enable FFmpeg while configuring OpenCV than CMake will download and install the binaries in `OPENCV_SOURCE_CODE/3rdparty/ffmpeg/`. To use -FFmpeg at runtime, you must deploy the FFMepg binaries with your application. +FFmpeg at runtime, you must deploy the FFmpeg binaries with your application. @note FFmpeg is licensed under the GNU Lesser General Public License (LGPL) version 2.1 or later. See `OPENCV_SOURCE_CODE/3rdparty/ffmpeg/readme.txt` and http://ffmpeg.org/legal.html for details and diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index df1d18118f..ba9c18bd97 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -500,7 +500,6 @@ enum { CAP_PROP_XI_DOWNSAMPLING = 400, //!< Chan //! @} XIMEA /** @name AVFoundation framework for iOS - OS X Lion will have the same API @{ */ @@ -512,6 +511,9 @@ enum { CAP_PROP_IOS_DEVICE_FOCUS = 9001, CAP_PROP_IOS_DEVICE_TORCH = 9005 }; +//! @} AVFoundation framework for iOS + + /** @name Smartek Giganetix GigEVisionSDK @{ */ @@ -990,8 +992,10 @@ protected: Size frameSize, bool isColor = true); }; +//! @cond IGNORED template<> CV_EXPORTS void DefaultDeleter::operator ()(CvCapture* obj) const; template<> CV_EXPORTS void DefaultDeleter::operator ()(CvVideoWriter* obj) const; +//! @endcond IGNORED //! @} videoio diff --git a/samples/cpp/videocapture_gstreamer_pipeline.cpp b/samples/cpp/videocapture_gstreamer_pipeline.cpp index 9507eb3c90..ed9d6fd334 100644 --- a/samples/cpp/videocapture_gstreamer_pipeline.cpp +++ b/samples/cpp/videocapture_gstreamer_pipeline.cpp @@ -223,7 +223,7 @@ inline Ptr createWriter(const string &backend, const string &file_n } else if (backend == "ffmpeg") { - cout << "Created FFMpeg writer ( " << file_name << ", FPS=" << fps << ", Size=" << sz << " )" << endl; + cout << "Created FFmpeg writer ( " << file_name << ", FPS=" << fps << ", Size=" << sz << " )" << endl; return makePtr(file_name, CAP_FFMPEG, getValue(fourccByCodec(), codec, "Invalid codec"), fps, sz, true); } return Ptr(); From 31f66766b7b179f67fa81e3f489a0a3f2a9a3437 Mon Sep 17 00:00:00 2001 From: Dan Ben-Yosef Date: Sun, 7 Mar 2021 19:06:08 +0200 Subject: [PATCH 02/15] Merge pull request #19685 from danbey:setting_stereoBMImpl_in_init_list Init params (StereoBMParams) in StereoBMImpl constructor initialization list * Init StereoBMImpl in initialization list To improve preformence it is better to init the params (StereoBMImpl) in the initialization list. * coding style * drop useless copy/move ctor Co-authored-by: Alexander Alekhin --- modules/calib3d/src/stereobm.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 96c8d0662d..f58aa5e400 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -1148,13 +1148,15 @@ class StereoBMImpl CV_FINAL : public StereoBM { public: StereoBMImpl() + : params() { - params = StereoBMParams(); + // nothing } StereoBMImpl( int _numDisparities, int _SADWindowSize ) + : params(_numDisparities, _SADWindowSize) { - params = StereoBMParams(_numDisparities, _SADWindowSize); + // nothing } void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) CV_OVERRIDE From 4c48f1eed2b1c96c4237ff0e69b9f1e16efb14ad Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 4 Mar 2021 17:05:15 +0300 Subject: [PATCH 03/15] Removed unused variables found by pylint. --- samples/dnn/virtual_try_on.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/samples/dnn/virtual_try_on.py b/samples/dnn/virtual_try_on.py index e4f2e518ec..f10e6c601a 100644 --- a/samples/dnn/virtual_try_on.py +++ b/samples/dnn/virtual_try_on.py @@ -112,7 +112,7 @@ class BilinearFilter(object): out[yy] = np.round(np.sum(img[ymin : ymin + ymax, 0:out.shape[1]] * k[:, np.newaxis], axis=0)) def imaging_resample(self, img, xsize, ysize): - height, width, *args = img.shape + height, width = img.shape[0:2] bounds_horiz, kk_horiz, ksize_horiz = self._precompute_coeffs(width, xsize) bounds_vert, kk_vert, ksize_vert = self._precompute_coeffs(height, ysize) @@ -232,7 +232,6 @@ class CpVton(object): return Li def _prepare_to_transform(self, out_h=256, out_w=192, grid_size=5): - grid = np.zeros([out_h, out_w, 3], dtype=np.float32) grid_X, grid_Y = np.meshgrid(np.linspace(-1, 1, out_w), np.linspace(-1, 1, out_h)) grid_X = np.expand_dims(np.expand_dims(grid_X, axis=0), axis=3) grid_Y = np.expand_dims(np.expand_dims(grid_Y, axis=0), axis=3) @@ -397,7 +396,7 @@ class CorrelationLayer(object): def getMemoryShapes(self, inputs): fetureAShape = inputs[0] - b, c, h, w = fetureAShape + b, _, h, w = fetureAShape return [[b, h * w, h, w]] def forward(self, inputs): From 65b51e15380a45094f8c1ab0d35fd15ce864af8f Mon Sep 17 00:00:00 2001 From: Daniel Playfair Cal Date: Wed, 10 Mar 2021 02:09:08 +1100 Subject: [PATCH 04/15] Merge pull request #19690 from hedgepigdaniel:fix/calibration_fisheye * fix(samples/camera_calibration): set new camera matrix for fisheye * fix(camera_calibration): ignore inapplicable flags for fisheye --- .../calib3d/camera_calibration/camera_calibration.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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 a6f87f41e8..38961ec63e 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp @@ -391,7 +391,12 @@ int main(int argc, char* argv[]) { Mat temp = view.clone(); if (s.useFisheye) - cv::fisheye::undistortImage(temp, view, cameraMatrix, distCoeffs); + { + Mat newCamMat; + fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix, distCoeffs, imageSize, + Matx33d::eye(), newCamMat, 1); + cv::fisheye::undistortImage(temp, view, cameraMatrix, distCoeffs, newCamMat); + } else undistort(temp, view, cameraMatrix, distCoeffs); } @@ -519,7 +524,7 @@ static bool runCalibration( Settings& s, Size& imageSize, Mat& cameraMatrix, Mat { //! [fixed_aspect] cameraMatrix = Mat::eye(3, 3, CV_64F); - if( s.flag & CALIB_FIX_ASPECT_RATIO ) + if( !s.useFisheye && s.flag & CALIB_FIX_ASPECT_RATIO ) cameraMatrix.at(0,0) = s.aspectRatio; //! [fixed_aspect] if (s.useFisheye) { @@ -586,7 +591,7 @@ static void saveCameraParams( Settings& s, Size& imageSize, Mat& cameraMatrix, M fs << "board_height" << s.boardSize.height; fs << "square_size" << s.squareSize; - if( s.flag & CALIB_FIX_ASPECT_RATIO ) + if( !s.useFisheye && s.flag & CALIB_FIX_ASPECT_RATIO ) fs << "fix_aspect_ratio" << s.aspectRatio; if (s.flag) From 84fcc4ab9b6e4dee5f8e64d8a04ec601713636ee Mon Sep 17 00:00:00 2001 From: Sayed Adel Date: Mon, 8 Mar 2021 19:13:12 +0000 Subject: [PATCH 05/15] core:ppc64 fix the build with the newer versions of Eigen on IBM/Power It also fixes the build when universal intrinsics is disabled via `-DDCV_ENABLE_INTRINSICS=OFF`. --- modules/core/include/opencv2/core/fast_math.hpp | 3 +++ modules/core/include/opencv2/core/vsx_utils.hpp | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/fast_math.hpp b/modules/core/include/opencv2/core/fast_math.hpp index 0f53cf5c1b..eb4fbe213b 100644 --- a/modules/core/include/opencv2/core/fast_math.hpp +++ b/modules/core/include/opencv2/core/fast_math.hpp @@ -76,6 +76,9 @@ #if defined __PPC64__ && defined __GNUC__ && defined _ARCH_PWR8 \ && !defined(OPENCV_SKIP_INCLUDE_ALTIVEC_H) #include + #undef vector + #undef bool + #undef pixel #endif #if defined(CV_INLINE_ROUND_FLT) diff --git a/modules/core/include/opencv2/core/vsx_utils.hpp b/modules/core/include/opencv2/core/vsx_utils.hpp index d7962517df..68863ffb36 100644 --- a/modules/core/include/opencv2/core/vsx_utils.hpp +++ b/modules/core/include/opencv2/core/vsx_utils.hpp @@ -497,11 +497,13 @@ VSX_IMPL_CONV_EVEN_2_4(vec_uint4, vec_double2, vec_ctu, vec_ctuo) VSX_FINLINE(rt) fnm(const rg& a, int only_truncate) \ { \ assert(only_truncate == 0); \ - CV_UNUSED(only_truncate); \ + CV_UNUSED(only_truncate); \ return fn2(a); \ } VSX_IMPL_CONV_2VARIANT(vec_int4, vec_float4, vec_cts, vec_cts) + VSX_IMPL_CONV_2VARIANT(vec_uint4, vec_float4, vec_ctu, vec_ctu) VSX_IMPL_CONV_2VARIANT(vec_float4, vec_int4, vec_ctf, vec_ctf) + VSX_IMPL_CONV_2VARIANT(vec_float4, vec_uint4, vec_ctf, vec_ctf) // define vec_cts for converting double precision to signed doubleword // which isn't compatible with xlc but its okay since Eigen only uses it for gcc VSX_IMPL_CONV_2VARIANT(vec_dword2, vec_double2, vec_cts, vec_ctsl) From 47337e219611646c2d50b37c6337d98be103ded1 Mon Sep 17 00:00:00 2001 From: Qoo Date: Wed, 24 Feb 2021 04:32:45 -0500 Subject: [PATCH 06/15] boost NMS performance --- modules/dnn/src/layers/detection_output_layer.cpp | 11 +++++++++-- modules/dnn/src/nms.inl.hpp | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/modules/dnn/src/layers/detection_output_layer.cpp b/modules/dnn/src/layers/detection_output_layer.cpp index 2dd6f5fb73..8374d74293 100644 --- a/modules/dnn/src/layers/detection_output_layer.cpp +++ b/modules/dnn/src/layers/detection_output_layer.cpp @@ -133,6 +133,12 @@ public: typedef std::map > LabelBBox; + inline int getNumOfTargetClasses() { + unsigned numBackground = + (_backgroundLabelId >= 0 && _backgroundLabelId < _numClasses) ? 1 : 0; + return (_numClasses - numBackground); + } + bool getParameterDict(const LayerParams ¶ms, const std::string ¶meterName, DictValue& result) @@ -584,12 +590,13 @@ public: LabelBBox::const_iterator label_bboxes = decodeBBoxes.find(label); if (label_bboxes == decodeBBoxes.end()) CV_Error_(cv::Error::StsError, ("Could not find location predictions for label %d", label)); + int limit = (getNumOfTargetClasses() == 1) ? _keepTopK : std::numeric_limits::max(); if (_bboxesNormalized) NMSFast_(label_bboxes->second, scores, _confidenceThreshold, _nmsThreshold, 1.0, _topK, - indices[c], util::caffe_norm_box_overlap); + indices[c], util::caffe_norm_box_overlap, limit); else NMSFast_(label_bboxes->second, scores, _confidenceThreshold, _nmsThreshold, 1.0, _topK, - indices[c], util::caffe_box_overlap); + indices[c], util::caffe_box_overlap, limit); numDetections += indices[c].size(); } if (_keepTopK > -1 && numDetections > (size_t)_keepTopK) diff --git a/modules/dnn/src/nms.inl.hpp b/modules/dnn/src/nms.inl.hpp index 89e3adfcf5..7b84839c02 100644 --- a/modules/dnn/src/nms.inl.hpp +++ b/modules/dnn/src/nms.inl.hpp @@ -62,12 +62,15 @@ inline void GetMaxScoreIndex(const std::vector& scores, const float thres // score_threshold: a threshold used to filter detection results. // nms_threshold: a threshold used in non maximum suppression. // top_k: if not > 0, keep at most top_k picked indices. +// limit: early terminate once the # of picked indices has reached it. // indices: the kept indices of bboxes after nms. template inline void NMSFast_(const std::vector& bboxes, const std::vector& scores, const float score_threshold, const float nms_threshold, const float eta, const int top_k, - std::vector& indices, float (*computeOverlap)(const BoxType&, const BoxType&)) + std::vector& indices, + float (*computeOverlap)(const BoxType&, const BoxType&), + int limit = std::numeric_limits::max()) { CV_Assert(bboxes.size() == scores.size()); @@ -86,8 +89,12 @@ inline void NMSFast_(const std::vector& bboxes, float overlap = computeOverlap(bboxes[idx], bboxes[kept_idx]); keep = overlap <= adaptive_threshold; } - if (keep) + if (keep) { indices.push_back(idx); + if (indices.size() >= limit) { + break; + } + } if (keep && eta < 1 && adaptive_threshold > 0.5) { adaptive_threshold *= eta; } From 63048812c7a7bfdc4c73326dd1deafa84594db5b Mon Sep 17 00:00:00 2001 From: Dan Ben Yosef Date: Wed, 10 Mar 2021 13:00:17 -0500 Subject: [PATCH 07/15] Init params (StereoSGBMParams) in StereoSGBMImpl constructor initialization list To improve preformence it is better to init the params (StereoSGBMParams) in the initialization list. --- modules/calib3d/src/stereosgbm.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index 7d5d23c18d..70eb3c658a 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -2186,19 +2186,21 @@ class StereoSGBMImpl CV_FINAL : public StereoSGBM { public: StereoSGBMImpl() + : params() { - params = StereoSGBMParams(); + // nothing } StereoSGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize, int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, int _mode ) + : params(_minDisparity, _numDisparities, _SADWindowSize, + _P1, _P2, _disp12MaxDiff, _preFilterCap, + _uniquenessRatio, _speckleWindowSize, _speckleRange, + _mode) { - params = StereoSGBMParams( _minDisparity, _numDisparities, _SADWindowSize, - _P1, _P2, _disp12MaxDiff, _preFilterCap, - _uniquenessRatio, _speckleWindowSize, _speckleRange, - _mode ); + // nothing } void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) CV_OVERRIDE From b995de4ff3f7e28e5d8f9d4f38e10ad1cbd87e21 Mon Sep 17 00:00:00 2001 From: Xinguang Bian Date: Fri, 12 Mar 2021 05:53:06 +0800 Subject: [PATCH 08/15] Merge pull request #19253 from mightbxg:bugfix_PnPRansac * fix unexpected Exception in solvePnPRansac caused by input points * calib3d: solvePnPRansac - keep minimal changes to handle DLT 6 points requirement Co-authored-by: Alexander Alekhin --- modules/calib3d/src/solvepnp.cpp | 34 ++++++++++++++--- modules/calib3d/test/test_solvepnp_ransac.cpp | 37 +++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/modules/calib3d/src/solvepnp.cpp b/modules/calib3d/src/solvepnp.cpp index cac04c4869..ad5c85b222 100644 --- a/modules/calib3d/src/solvepnp.cpp +++ b/modules/calib3d/src/solvepnp.cpp @@ -311,18 +311,42 @@ bool solvePnPRansac(InputArray _opoints, InputArray _ipoints, opoints_inliers.resize(npoints1); ipoints_inliers.resize(npoints1); - result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix, - distCoeffs, rvec, tvec, useExtrinsicGuess, - (flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1; + try + { + result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix, + distCoeffs, rvec, tvec, useExtrinsicGuess, + (flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1; + } + catch (const cv::Exception& e) + { + if (flags == SOLVEPNP_ITERATIVE && + npoints1 == 5 && + e.what() && + std::string(e.what()).find("DLT algorithm needs at least 6 points") != std::string::npos + ) + { + CV_LOG_INFO(NULL, "solvePnPRansac(): solvePnP stage to compute the final pose using points " + "in the consensus set raised DLT 6 points exception, use result from MSS (Minimal Sample Sets) stage instead."); + rvec = _local_model.col(0); // output rotation vector + tvec = _local_model.col(1); // output translation vector + result = 1; + } + else + { + // raise other exceptions + throw; + } + } - if( result <= 0 ) + if (result <= 0) { _rvec.assign(_local_model.col(0)); // output rotation vector _tvec.assign(_local_model.col(1)); // output translation vector - if( _inliers.needed() ) + if (_inliers.needed()) _inliers.release(); + CV_LOG_DEBUG(NULL, "solvePnPRansac(): solvePnP stage to compute the final pose using points in the consensus set failed. Return false"); return false; } else diff --git a/modules/calib3d/test/test_solvepnp_ransac.cpp b/modules/calib3d/test/test_solvepnp_ransac.cpp index fb0e2965e6..43b90dff92 100644 --- a/modules/calib3d/test/test_solvepnp_ransac.cpp +++ b/modules/calib3d/test/test_solvepnp_ransac.cpp @@ -837,6 +837,43 @@ TEST(Calib3d_SolvePnPRansac, double_support) EXPECT_LE(cvtest::norm(t, Mat_(tF), NORM_INF), 1e-3); } +TEST(Calib3d_SolvePnPRansac, bad_input_points_19253) +{ + // with this specific data + // when computing the final pose using points in the consensus set with SOLVEPNP_ITERATIVE and solvePnP() + // an exception is thrown from solvePnP because there are 5 non-coplanar 3D points and the DLT algorithm needs at least 6 non-coplanar 3D points + // with PR #19253 we choose to return true, with the pose estimated from the MSS stage instead of throwing the exception + + float pts2d_[] = { + -5.38358629e-01f, -5.09638414e-02f, + -5.07192254e-01f, -2.20743284e-01f, + -5.43107152e-01f, -4.90474701e-02f, + -5.54325163e-01f, -1.86715424e-01f, + -5.59334219e-01f, -4.01909500e-02f, + -5.43504596e-01f, -4.61776406e-02f + }; + Mat pts2d(6, 2, CV_32FC1, pts2d_); + + float pts3d_[] = { + -3.01153604e-02f, -1.55665115e-01f, 4.50000018e-01f, + 4.27827090e-01f, 4.28645730e-01f, 1.08600008e+00f, + -3.14165242e-02f, -1.52656138e-01f, 4.50000018e-01f, + -1.46217480e-01f, 5.57961613e-02f, 7.17000008e-01f, + -4.89348806e-02f, -1.38795510e-01f, 4.47000027e-01f, + -3.13065052e-02f, -1.52636901e-01f, 4.51000035e-01f + }; + Mat pts3d(6, 3, CV_32FC1, pts3d_); + + Mat camera_mat = Mat::eye(3, 3, CV_64FC1); + Mat rvec, tvec; + vector inliers; + + // solvePnPRansac will return true with 5 inliers, which means the result is from MSS stage. + bool result = solvePnPRansac(pts3d, pts2d, camera_mat, noArray(), rvec, tvec, false, 100, 4.f / 460.f, 0.99, inliers); + EXPECT_EQ(inliers.size(), size_t(5)); + EXPECT_TRUE(result); +} + TEST(Calib3d_SolvePnP, input_type) { Matx33d intrinsics(5.4794130238156129e+002, 0., 2.9835545700043139e+002, 0., From f8181fbef85854739f7a3e96f4981083b110b16c Mon Sep 17 00:00:00 2001 From: Sayed Adel Date: Fri, 12 Mar 2021 02:02:31 +0000 Subject: [PATCH 09/15] core:ppc64 fix detecting CPU features when optimization is off --- modules/core/src/system.cpp | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index ad688a6c68..d0412a36e5 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -128,11 +128,14 @@ void* allocSingletonNewBuffer(size_t size) { return malloc(size); } #endif -#if CV_VSX && defined __linux__ +#if (defined __ppc64__ || defined __PPC64__) && defined __linux__ # include "sys/auxv.h" # ifndef AT_HWCAP2 # define AT_HWCAP2 26 # endif +# ifndef PPC_FEATURE2_ARCH_2_07 +# define PPC_FEATURE2_ARCH_2_07 0x80000000 +# endif # ifndef PPC_FEATURE2_ARCH_3_00 # define PPC_FEATURE2_ARCH_3_00 0x00800000 # endif @@ -587,14 +590,25 @@ struct HWFeatures #ifdef __mips_msa have[CV_CPU_MSA] = true; #endif - // there's no need to check VSX availability in runtime since it's always available on ppc64le CPUs - have[CV_CPU_VSX] = (CV_VSX); - // TODO: Check VSX3 availability in runtime for other platforms - #if CV_VSX && defined __linux__ - uint64 hwcap2 = getauxval(AT_HWCAP2); - have[CV_CPU_VSX3] = (hwcap2 & PPC_FEATURE2_ARCH_3_00); + + #if (defined __ppc64__ || defined __PPC64__) && defined __linux__ + unsigned int hwcap = getauxval(AT_HWCAP); + if (hwcap & PPC_FEATURE_HAS_VSX) { + hwcap = getauxval(AT_HWCAP2); + if (hwcap & PPC_FEATURE2_ARCH_3_00) { + have[CV_CPU_VSX] = have[CV_CPU_VSX3] = true; + } else { + have[CV_CPU_VSX] = (hwcap & PPC_FEATURE2_ARCH_2_07) != 0; + } + } #else - have[CV_CPU_VSX3] = (CV_VSX3); + // TODO: AIX, FreeBSD + #if CV_VSX || defined _ARCH_PWR8 || defined __POWER9_VECTOR__ + have[CV_CPU_VSX] = true; + #endif + #if CV_VSX3 || defined __POWER9_VECTOR__ + have[CV_CPU_VSX3] = true; + #endif #endif bool skip_baseline_check = false; From 95ab9468c12be3a627be41f60150def047a90151 Mon Sep 17 00:00:00 2001 From: Liubov Batanina Date: Fri, 12 Mar 2021 12:00:59 +0300 Subject: [PATCH 10/15] Added ngraph::op::v4::Interpolation --- modules/dnn/src/layers/resize_layer.cpp | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/modules/dnn/src/layers/resize_layer.cpp b/modules/dnn/src/layers/resize_layer.cpp index a41e20a666..2527ad1190 100644 --- a/modules/dnn/src/layers/resize_layer.cpp +++ b/modules/dnn/src/layers/resize_layer.cpp @@ -257,6 +257,7 @@ public: { auto& ieInpNode = nodes[0].dynamicCast()->node; +#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2021_2) ngraph::op::InterpolateAttrs attrs; attrs.pads_begin.push_back(0); attrs.pads_end.push_back(0); @@ -275,6 +276,36 @@ public: std::vector shape = {outHeight, outWidth}; auto out_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, shape.data()); auto interp = std::make_shared(ieInpNode, out_shape, attrs); +#else + ngraph::op::v4::Interpolate::InterpolateAttrs attrs; + + if (interpolation == "nearest") { + attrs.mode = ngraph::op::v4::Interpolate::InterpolateMode::nearest; + attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::half_pixel; + } else if (interpolation == "bilinear") { + attrs.mode = ngraph::op::v4::Interpolate::InterpolateMode::linear_onnx; + attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::asymmetric; + } else { + CV_Error(Error::StsNotImplemented, "Unsupported interpolation: " + interpolation); + } + attrs.shape_calculation_mode = ngraph::op::v4::Interpolate::ShapeCalcMode::sizes; + + if (alignCorners) { + attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::align_corners; + } + + attrs.nearest_mode = ngraph::op::v4::Interpolate::NearestMode::round_prefer_floor; + + std::vector shape = {outHeight, outWidth}; + auto out_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, shape.data()); + + auto& input_shape = ieInpNode->get_shape(); + std::vector scales = {static_cast(outHeight) / input_shape[2], static_cast(outHeight) / input_shape[2]}; + auto scales_shape = std::make_shared(ngraph::element::f32, ngraph::Shape{2}, scales.data()); + + auto axes = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{2, 3}); + auto interp = std::make_shared(ieInpNode, out_shape, scales_shape, axes, attrs); +#endif return Ptr(new InfEngineNgraphNode(interp)); } #endif // HAVE_DNN_NGRAPH From 8d29a902e4ac038b248eed161f1e18950036a5c3 Mon Sep 17 00:00:00 2001 From: Liubov Batanina Date: Fri, 12 Mar 2021 16:33:16 +0300 Subject: [PATCH 11/15] Added ngraph::op::v6::MVN --- modules/dnn/src/layers/mvn_layer.cpp | 8 ++++++++ modules/dnn/src/layers/resize_layer.cpp | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/dnn/src/layers/mvn_layer.cpp b/modules/dnn/src/layers/mvn_layer.cpp index 386446e18f..8f06216df1 100644 --- a/modules/dnn/src/layers/mvn_layer.cpp +++ b/modules/dnn/src/layers/mvn_layer.cpp @@ -394,7 +394,15 @@ public: const std::vector >& nodes) CV_OVERRIDE { auto& ieInpNode = nodes[0].dynamicCast()->node; +#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2021_2) auto mvn = std::make_shared(ieInpNode, acrossChannels, normVariance, eps); +#else + int64_t start_axis = acrossChannels ? 1 : 2; + std::vector axes_v(ieInpNode->get_shape().size() - start_axis); + std::iota(axes_v.begin(), axes_v.end(), start_axis); + auto axes = std::make_shared(ngraph::element::i64, ngraph::Shape{axes_v.size()}, axes_v.data()); + auto mvn = std::make_shared(ieInpNode, axes, normVariance, eps, ngraph::op::MVNEpsMode::INSIDE_SQRT); +#endif return Ptr(new InfEngineNgraphNode(mvn)); } #endif // HAVE_DNN_NGRAPH diff --git a/modules/dnn/src/layers/resize_layer.cpp b/modules/dnn/src/layers/resize_layer.cpp index 2527ad1190..40c7351984 100644 --- a/modules/dnn/src/layers/resize_layer.cpp +++ b/modules/dnn/src/layers/resize_layer.cpp @@ -286,7 +286,7 @@ public: attrs.mode = ngraph::op::v4::Interpolate::InterpolateMode::linear_onnx; attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::asymmetric; } else { - CV_Error(Error::StsNotImplemented, "Unsupported interpolation: " + interpolation); + CV_Error(Error::StsNotImplemented, format("Unsupported interpolation: %s", interpolation.c_str())); } attrs.shape_calculation_mode = ngraph::op::v4::Interpolate::ShapeCalcMode::sizes; @@ -300,7 +300,8 @@ public: auto out_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, shape.data()); auto& input_shape = ieInpNode->get_shape(); - std::vector scales = {static_cast(outHeight) / input_shape[2], static_cast(outHeight) / input_shape[2]}; + CV_Assert_N(input_shape[2] != 0, input_shape[3] != 0); + std::vector scales = {static_cast(outHeight) / input_shape[2], static_cast(outWidth) / input_shape[3]}; auto scales_shape = std::make_shared(ngraph::element::f32, ngraph::Shape{2}, scales.data()); auto axes = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{2, 3}); From d4d805cb3e7a4fb3d41a4d5dbb494827cbd79c26 Mon Sep 17 00:00:00 2001 From: Dan Ben Yosef Date: Fri, 12 Mar 2021 14:17:11 -0500 Subject: [PATCH 12/15] Avoiding copy by passing param by reference It is best to pass bad_value_ param by reference to avoid copy. --- modules/core/src/system.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index d0412a36e5..6e882e1dde 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1938,7 +1938,7 @@ class ParseError { std::string bad_value; public: - ParseError(const std::string bad_value_) :bad_value(bad_value_) {} + ParseError(const std::string &bad_value_) :bad_value(bad_value_) {} std::string toString(const std::string ¶m) const { std::ostringstream out; From cbe236652b6b95a8e0e5c38e69884196d192dbc5 Mon Sep 17 00:00:00 2001 From: Dale Phurrough Date: Mon, 1 Mar 2021 22:42:13 +0100 Subject: [PATCH 13/15] noexcept def construct Mat, UMat, Mat_, MatSize, MatStep original commit: 1b0f781b7cc18562b59ef60fb303ce0f9cea9f78 --- modules/core/include/opencv2/core/mat.hpp | 24 +++++++++---------- modules/core/include/opencv2/core/mat.inl.hpp | 18 +++++++------- modules/core/src/matrix.cpp | 4 ++-- modules/core/src/umatrix.cpp | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 6fedeaa974..d0ce61e123 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -583,24 +583,24 @@ struct CV_EXPORTS UMatData struct CV_EXPORTS MatSize { - explicit MatSize(int* _p); - int dims() const; + explicit MatSize(int* _p) CV_NOEXCEPT; + int dims() const CV_NOEXCEPT; Size operator()() const; const int& operator[](int i) const; int& operator[](int i); - operator const int*() const; // TODO OpenCV 4.0: drop this - bool operator == (const MatSize& sz) const; - bool operator != (const MatSize& sz) const; + operator const int*() const CV_NOEXCEPT; // TODO OpenCV 4.0: drop this + bool operator == (const MatSize& sz) const CV_NOEXCEPT; + bool operator != (const MatSize& sz) const CV_NOEXCEPT; int* p; }; struct CV_EXPORTS MatStep { - MatStep(); - explicit MatStep(size_t s); - const size_t& operator[](int i) const; - size_t& operator[](int i); + MatStep() CV_NOEXCEPT; + explicit MatStep(size_t s) CV_NOEXCEPT; + const size_t& operator[](int i) const CV_NOEXCEPT; + size_t& operator[](int i) CV_NOEXCEPT; operator size_t() const; MatStep& operator = (size_t s); @@ -819,7 +819,7 @@ public: The constructed matrix can further be assigned to another matrix or matrix expression or can be allocated with Mat::create . In the former case, the old content is de-referenced. */ - Mat(); + Mat() CV_NOEXCEPT; /** @overload @param rows Number of rows in a 2D array. @@ -2220,7 +2220,7 @@ public: typedef MatConstIterator_<_Tp> const_iterator; //! default constructor - Mat_(); + Mat_() CV_NOEXCEPT; //! equivalent to Mat(_rows, _cols, DataType<_Tp>::type) Mat_(int _rows, int _cols); //! constructor that sets each matrix element to specified value @@ -2420,7 +2420,7 @@ class CV_EXPORTS UMat { public: //! default constructor - UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT); + UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT) CV_NOEXCEPT; //! constructs 2D matrix of the specified size and type // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index c1d5261b8c..49357555de 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -1218,11 +1218,11 @@ Mat& Mat::operator = (Mat&& m) ///////////////////////////// MatSize //////////////////////////// inline -MatSize::MatSize(int* _p) +MatSize::MatSize(int* _p) CV_NOEXCEPT : p(_p) {} inline -int MatSize::dims() const +int MatSize::dims() const CV_NOEXCEPT { return (p - 1)[0]; } @@ -1255,13 +1255,13 @@ int& MatSize::operator[](int i) } inline -MatSize::operator const int*() const +MatSize::operator const int*() const CV_NOEXCEPT { return p; } inline -bool MatSize::operator != (const MatSize& sz) const +bool MatSize::operator != (const MatSize& sz) const CV_NOEXCEPT { return !(*this == sz); } @@ -1271,25 +1271,25 @@ bool MatSize::operator != (const MatSize& sz) const ///////////////////////////// MatStep //////////////////////////// inline -MatStep::MatStep() +MatStep::MatStep() CV_NOEXCEPT { p = buf; p[0] = p[1] = 0; } inline -MatStep::MatStep(size_t s) +MatStep::MatStep(size_t s) CV_NOEXCEPT { p = buf; p[0] = s; p[1] = 0; } inline -const size_t& MatStep::operator[](int i) const +const size_t& MatStep::operator[](int i) const CV_NOEXCEPT { return p[i]; } inline -size_t& MatStep::operator[](int i) +size_t& MatStep::operator[](int i) CV_NOEXCEPT { return p[i]; } @@ -1312,7 +1312,7 @@ inline MatStep& MatStep::operator = (size_t s) ////////////////////////////// Mat_<_Tp> //////////////////////////// template inline -Mat_<_Tp>::Mat_() +Mat_<_Tp>::Mat_() CV_NOEXCEPT : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | traits::Type<_Tp>::value; diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 178e291d3f..4db7c7a89e 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -204,7 +204,7 @@ MatAllocator* Mat::getStdAllocator() //================================================================================================== -bool MatSize::operator==(const MatSize& sz) const +bool MatSize::operator==(const MatSize& sz) const CV_NOEXCEPT { int d = dims(); int dsz = sz.dims(); @@ -337,7 +337,7 @@ void finalizeHdr(Mat& m) //======================================= Mat ====================================================== -Mat::Mat() +Mat::Mat() CV_NOEXCEPT : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0) {} diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index 936348f779..94f828ba60 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -230,7 +230,7 @@ UMatDataAutoLock::~UMatDataAutoLock() //////////////////////////////// UMat //////////////////////////////// -UMat::UMat(UMatUsageFlags _usageFlags) +UMat::UMat(UMatUsageFlags _usageFlags) CV_NOEXCEPT : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows) {} From 87e607a19b385f29b22dd62817d9899652d1d430 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sat, 13 Mar 2021 05:56:40 +0000 Subject: [PATCH 14/15] core(ocl): skip SPIR test on AMD devices if problem detected --- modules/core/test/ocl/test_opencl.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/core/test/ocl/test_opencl.cpp b/modules/core/test/ocl/test_opencl.cpp index 27cd82d424..275dc0f3cd 100644 --- a/modules/core/test/ocl/test_opencl.cpp +++ b/modules/core/test/ocl/test_opencl.cpp @@ -120,6 +120,11 @@ TEST(OpenCL, support_SPIR_programs) cv::ocl::ProgramSource src = cv::ocl::ProgramSource::fromSPIR(module_name, "simple_spir", (uchar*)&program_binary_code[0], program_binary_code.size(), ""); cv::String errmsg; cv::ocl::Program program(src, "", errmsg); + if (program.ptr() == NULL && device.isAMD()) + { + // https://community.amd.com/t5/opencl/spir-support-in-new-drivers-lost/td-p/170165 + throw cvtest::SkipTestException("Bypass AMD OpenCL runtime bug: 'cl_khr_spir' extension is declared, but it doesn't really work"); + } ASSERT_TRUE(program.ptr() != NULL); k.create("test_kernel", program); } From 960f501cc18bed647c3718c4d62fc94a4819ab1c Mon Sep 17 00:00:00 2001 From: Ziachnix <76476871+Ziachnix@users.noreply.github.com> Date: Sat, 13 Mar 2021 13:52:44 +0100 Subject: [PATCH 15/15] Merge pull request #19284 from Ziachnix:feature/js-qr-code-detector Add QRCodeDetector to JavaScript Build * ADD: js support for qrCodeDetector - cherry picked commit to solve rebase error * CHG. Revert haarcascade path * FIX: Tests without images * ADD: decodeCurved * js(docs): don't require OPENCV_TEST_DATA_PATH Co-authored-by: Alexander Alekhin --- .../js_setup/js_setup/js_setup.markdown | 7 ++++ modules/js/generator/embindgen.py | 7 ++-- modules/js/test/test_objdetect.js | 41 +++++++++++++++++++ platforms/js/build_js.py | 2 +- platforms/js/opencv_js.config.py | 3 +- 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/doc/js_tutorials/js_setup/js_setup/js_setup.markdown b/doc/js_tutorials/js_setup/js_setup/js_setup.markdown index 7fd7fe05c3..43bffc9653 100644 --- a/doc/js_tutorials/js_setup/js_setup/js_setup.markdown +++ b/doc/js_tutorials/js_setup/js_setup/js_setup.markdown @@ -138,6 +138,7 @@ Building OpenCV.js from Source python ./platforms/js/build_js.py build_js --cmake_option="-DOPENCV_EXTRA_MODULES_PATH=opencv_contrib/modules" @endcode + Running OpenCV.js Tests --------------------------------------- @@ -303,6 +304,12 @@ The example uses latest version of emscripten. If the build fails you should try docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk:2.0.10 emcmake python3 ./platforms/js/build_js.py build_js @endcode +In Windows use the following PowerShell command: + +@code{.bash} +docker run --rm --workdir /src -v "$(get-location):/src" "emscripten/emsdk:2.0.10" emcmake python3 ./platforms/js/build_js.py build_js +@endcode + ### Building the documentation with Docker To build the documentation `doxygen` needs to be installed. Create a file named `Dockerfile` with the following content: diff --git a/modules/js/generator/embindgen.py b/modules/js/generator/embindgen.py index a11309a551..dc7a001df1 100644 --- a/modules/js/generator/embindgen.py +++ b/modules/js/generator/embindgen.py @@ -119,6 +119,7 @@ type_dict = { 'InputOutputArray': 'cv::Mat&', 'InputArrayOfArrays': 'const std::vector&', 'OutputArrayOfArrays': 'std::vector&', + 'string': 'std::string', 'String': 'std::string', 'const String&':'const std::string&' } @@ -462,8 +463,7 @@ class JSWrapperGenerator(object): ret_type = type_dict[ptr_type] for key in type_dict: if key in ret_type: - ret_type = ret_type.replace(key, type_dict[key]) - + ret_type = re.sub('(^|[^\w])' + key + '($|[^\w])', type_dict[key], ret_type) arg_types = [] unwrapped_arg_types = [] for arg in variant.args: @@ -567,7 +567,7 @@ class JSWrapperGenerator(object): # consider the default parameter variants args_num = len(variant.args) - j if args_num in class_info.constructor_arg_num: - # FIXME: workaournd for constructor overload with same args number + # FIXME: workaround for constructor overload with same args number # e.g. DescriptorMatcher continue class_info.constructor_arg_num.add(args_num) @@ -627,7 +627,6 @@ class JSWrapperGenerator(object): ret_type = 'void' if variant.rettype.strip() == '' else variant.rettype ret_type = ret_type.strip() - if ret_type.startswith('Ptr'): #smart pointer ptr_type = ret_type.replace('Ptr<', '').replace('>', '') if ptr_type in type_dict: diff --git a/modules/js/test/test_objdetect.js b/modules/js/test/test_objdetect.js index 79c357ae2f..dc863d682f 100644 --- a/modules/js/test/test_objdetect.js +++ b/modules/js/test/test_objdetect.js @@ -159,3 +159,44 @@ QUnit.test('Cascade classification', function(assert) { locations.delete(); } }); +QUnit.test('QR code detect and decode', function (assert) { + { + const detector = new cv.QRCodeDetector(); + let mat = cv.Mat.ones(800, 600, cv.CV_8U); + assert.ok(mat); + + // test detect + let points = new cv.Mat(); + let qrCodeFound = detector.detect(mat, points); + assert.equal(points.rows, 0) + assert.equal(points.cols, 0) + assert.equal(qrCodeFound, false); + + // test detectMult + qrCodeFound = detector.detectMulti(mat, points); + assert.equal(points.rows, 0) + assert.equal(points.cols, 0) + assert.equal(qrCodeFound, false); + + // test decode (with random numbers) + let decodeTestPoints = cv.matFromArray(1, 4, cv.CV_32FC2, [10, 20, 30, 40, 60, 80, 90, 100]); + let qrCodeContent = detector.decode(mat, decodeTestPoints); + assert.equal(typeof qrCodeContent, 'string'); + assert.equal(qrCodeContent, ''); + + //test detectAndDecode + qrCodeContent = detector.detectAndDecode(mat); + assert.equal(typeof qrCodeContent, 'string'); + assert.equal(qrCodeContent, ''); + + // test decodeCurved + qrCodeContent = detector.decodeCurved(mat, decodeTestPoints); + assert.equal(typeof qrCodeContent, 'string'); + assert.equal(qrCodeContent, ''); + + decodeTestPoints.delete(); + points.delete(); + mat.delete(); + + } +}); \ No newline at end of file diff --git a/platforms/js/build_js.py b/platforms/js/build_js.py index 7f9ce3ea8b..c9a451643f 100644 --- a/platforms/js/build_js.py +++ b/platforms/js/build_js.py @@ -114,7 +114,7 @@ class Builder: "-DWITH_GPHOTO2=OFF", "-DWITH_LAPACK=OFF", "-DWITH_ITT=OFF", - "-DWITH_QUIRC=OFF", + "-DWITH_QUIRC=ON", "-DBUILD_ZLIB=ON", "-DBUILD_opencv_apps=OFF", "-DBUILD_opencv_calib3d=ON", diff --git a/platforms/js/opencv_js.config.py b/platforms/js/opencv_js.config.py index 749624be88..86551ae4d9 100644 --- a/platforms/js/opencv_js.config.py +++ b/platforms/js/opencv_js.config.py @@ -22,7 +22,8 @@ imgproc = {'': ['Canny', 'GaussianBlur', 'Laplacian', 'HoughLines', 'HoughLinesP objdetect = {'': ['groupRectangles'], 'HOGDescriptor': ['load', 'HOGDescriptor', 'getDefaultPeopleDetector', 'getDaimlerPeopleDetector', 'setSVMDetector', 'detectMultiScale'], - 'CascadeClassifier': ['load', 'detectMultiScale2', 'CascadeClassifier', 'detectMultiScale3', 'empty', 'detectMultiScale']} + 'CascadeClassifier': ['load', 'detectMultiScale2', 'CascadeClassifier', 'detectMultiScale3', 'empty', 'detectMultiScale'], + 'QRCodeDetector': ['QRCodeDetector', 'decode', 'decodeCurved', 'detect', 'detectAndDecode', 'detectMulti', 'setEpsX', 'setEpsY']} video = {'': ['CamShift', 'calcOpticalFlowFarneback', 'calcOpticalFlowPyrLK', 'createBackgroundSubtractorMOG2', \ 'findTransformECC', 'meanShift'],