From 80342bccc8fb2e0bb09fe539e8951330e1a571fa Mon Sep 17 00:00:00 2001 From: Rok Mandeljc Date: Thu, 31 Dec 2015 17:37:10 +0100 Subject: [PATCH 01/15] opencv_text: src/erfilter.cpp: replaced bit and/or with their logical counterparts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variables p2-p9 are booleans, so combination of logical negation and use of bit and/or operations in lines 2823 and 2824 results in the following warning from gcc: warning: suggest parentheses around operand of ‘!’ or change ‘&’ to ‘&&’ or ‘!’ to ‘~’ [-Wparentheses] --- modules/text/src/erfilter.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/text/src/erfilter.cpp b/modules/text/src/erfilter.cpp index b5f58b76c..02056af1f 100644 --- a/modules/text/src/erfilter.cpp +++ b/modules/text/src/erfilter.cpp @@ -2820,12 +2820,12 @@ bool guo_hall_thinning(const Mat1b & img, Mat& skeleton) p8 = (skeleton.data[row * skeleton.cols + col-1]) > 0; p9 = (skeleton.data[(row-1) * skeleton.cols + col-1]) > 0; - int C = (!p2 & (p3 | p4)) + (!p4 & (p5 | p6)) + - (!p6 & (p7 | p8)) + (!p8 & (p9 | p2)); - int N1 = (p9 | p2) + (p3 | p4) + (p5 | p6) + (p7 | p8); - int N2 = (p2 | p3) + (p4 | p5) + (p6 | p7) + (p8 | p9); + int C = (!p2 && (p3 || p4)) + (!p4 && (p5 || p6)) + + (!p6 && (p7 || p8)) + (!p8 && (p9 || p2)); + int N1 = (p9 || p2) + (p3 || p4) + (p5 || p6) + (p7 || p8); + int N2 = (p2 || p3) + (p4 || p5) + (p6 || p7) + (p8 || p9); int N = N1 < N2 ? N1 : N2; - int m = iter == 0 ? ((p6 | p7 | !p9) & p8) : ((p2 | p3 | !p5) & p4); + int m = iter == 0 ? ((p6 || p7 || !p9) && p8) : ((p2 || p3 || !p5) && p4); if ((C == 1) && (N >= 2) && (N <= 3) && (m == 0)) { From bf6254a6e6548f36ea7772cadec887b4574a9150 Mon Sep 17 00:00:00 2001 From: lych77 Date: Tue, 26 Apr 2016 12:16:53 +0800 Subject: [PATCH 02/15] Fix building waldboost_detector with opencv_world Itseez/opencv_contrib#497 --- modules/xobjdetect/tools/waldboost_detector/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/xobjdetect/tools/waldboost_detector/CMakeLists.txt b/modules/xobjdetect/tools/waldboost_detector/CMakeLists.txt index 40424180e..8ed7eb6db 100644 --- a/modules/xobjdetect/tools/waldboost_detector/CMakeLists.txt +++ b/modules/xobjdetect/tools/waldboost_detector/CMakeLists.txt @@ -19,7 +19,7 @@ file(GLOB ${the_target}_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) add_executable(${the_target} ${${the_target}_SOURCES}) -target_link_libraries(${the_target} ${OPENCV_${the_target}_DEPS}) +ocv_target_link_libraries(${the_target} ${OPENCV_${the_target}_DEPS}) set_target_properties(${the_target} PROPERTIES DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" From 4889ec5cdf940855605f271a00e6c053102e595b Mon Sep 17 00:00:00 2001 From: berak Date: Mon, 2 May 2016 09:55:55 +0200 Subject: [PATCH 03/15] structured_light: python / java bindings --- modules/structured_light/CMakeLists.txt | 2 +- .../opencv2/structured_light/graycodepattern.hpp | 11 ++++++----- modules/structured_light/src/graycodepattern.cpp | 10 ++++++++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/modules/structured_light/CMakeLists.txt b/modules/structured_light/CMakeLists.txt index 66bcc2756..de3a07382 100644 --- a/modules/structured_light/CMakeLists.txt +++ b/modules/structured_light/CMakeLists.txt @@ -1,2 +1,2 @@ set(the_description "Structured Light API") -ocv_define_module(structured_light opencv_core opencv_calib3d opencv_imgproc opencv_highgui opencv_features2d opencv_rgbd OPTIONAL opencv_viz) +ocv_define_module(structured_light opencv_core opencv_calib3d opencv_imgproc opencv_highgui opencv_features2d opencv_rgbd OPTIONAL opencv_viz WRAP python java) diff --git a/modules/structured_light/include/opencv2/structured_light/graycodepattern.hpp b/modules/structured_light/include/opencv2/structured_light/graycodepattern.hpp index cf01f70d3..55b39af0f 100644 --- a/modules/structured_light/include/opencv2/structured_light/graycodepattern.hpp +++ b/modules/structured_light/include/opencv2/structured_light/graycodepattern.hpp @@ -43,6 +43,7 @@ #define __OPENCV_GRAY_CODE_PATTERN_HPP__ #include "opencv2/core.hpp" +#include "opencv2/structured_light/structured_light.hpp" namespace cv { namespace structured_light { @@ -72,22 +73,22 @@ class CV_EXPORTS_W GrayCodePattern : public StructuredLightPattern * @param width Projector's width. Default value is 1024. * @param height Projector's height. Default value is 768. */ - struct CV_EXPORTS_W_SIMPLE Params + struct CV_EXPORTS Params { - CV_WRAP Params(); - CV_PROP_RW int width; - CV_PROP_RW int height; }; /** @brief Constructor @param parameters GrayCodePattern parameters GrayCodePattern::Params: the width and the height of the projector. */ - CV_WRAP static Ptr create( const GrayCodePattern::Params ¶meters = GrayCodePattern::Params() ); + // alias for scripting + CV_WRAP + static Ptr create( int width, int height ); + /** @brief Get the number of pattern images needed for the graycode pattern. * * @return The number of pattern images needed for the graycode pattern. diff --git a/modules/structured_light/src/graycodepattern.cpp b/modules/structured_light/src/graycodepattern.cpp index d3df7aa2a..ff56a027d 100644 --- a/modules/structured_light/src/graycodepattern.cpp +++ b/modules/structured_light/src/graycodepattern.cpp @@ -471,5 +471,15 @@ Ptr GrayCodePattern::create( const GrayCodePattern::Params& par return makePtr( params ); } +// Creates the GrayCodePattern instance +// alias for scripting +Ptr GrayCodePattern::create( int width, int height ) +{ + Params params; + params.width = width; + params.height = height; + return makePtr( params ); +} + } } From 55e53ea86b6c8029a7720e924658514ccc901051 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Sun, 22 May 2016 14:46:12 +0300 Subject: [PATCH 04/15] fix for width&height problem in haarcascade_mcs_xxx.xml files --- modules/face/data/cascades/haarcascade_mcs_eyepair_big.xml | 4 ++-- modules/face/data/cascades/haarcascade_mcs_eyepair_small.xml | 4 ++-- modules/face/data/cascades/haarcascade_mcs_leftear.xml | 4 ++-- modules/face/data/cascades/haarcascade_mcs_lefteye.xml | 4 ++-- modules/face/data/cascades/haarcascade_mcs_mouth.xml | 4 ++-- modules/face/data/cascades/haarcascade_mcs_nose.xml | 4 ++-- modules/face/data/cascades/haarcascade_mcs_rightear.xml | 4 ++-- modules/face/data/cascades/haarcascade_mcs_righteye.xml | 4 ++-- modules/face/data/cascades/haarcascade_mcs_upperbody.xml | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/face/data/cascades/haarcascade_mcs_eyepair_big.xml b/modules/face/data/cascades/haarcascade_mcs_eyepair_big.xml index c3ac7a1ba..56598de32 100644 --- a/modules/face/data/cascades/haarcascade_mcs_eyepair_big.xml +++ b/modules/face/data/cascades/haarcascade_mcs_eyepair_big.xml @@ -122,8 +122,8 @@ Section 8 – Interpretation. BOOST HAAR - 45 - 11 + 11 + 45 85 diff --git a/modules/face/data/cascades/haarcascade_mcs_eyepair_small.xml b/modules/face/data/cascades/haarcascade_mcs_eyepair_small.xml index 6e22b44ea..9828a879b 100644 --- a/modules/face/data/cascades/haarcascade_mcs_eyepair_small.xml +++ b/modules/face/data/cascades/haarcascade_mcs_eyepair_small.xml @@ -121,8 +121,8 @@ Section 8 – Interpretation. BOOST HAAR - 22 - 5 + 5 + 22 133 diff --git a/modules/face/data/cascades/haarcascade_mcs_leftear.xml b/modules/face/data/cascades/haarcascade_mcs_leftear.xml index 359851516..f6849764e 100644 --- a/modules/face/data/cascades/haarcascade_mcs_leftear.xml +++ b/modules/face/data/cascades/haarcascade_mcs_leftear.xml @@ -120,8 +120,8 @@ Section 8 – Interpretation. BOOST HAAR - 12 - 20 + 20 + 12 65 diff --git a/modules/face/data/cascades/haarcascade_mcs_lefteye.xml b/modules/face/data/cascades/haarcascade_mcs_lefteye.xml index d745e0593..525c6006b 100644 --- a/modules/face/data/cascades/haarcascade_mcs_lefteye.xml +++ b/modules/face/data/cascades/haarcascade_mcs_lefteye.xml @@ -121,8 +121,8 @@ Section 8 – Interpretation. BOOST HAAR - 18 - 12 + 12 + 18 279 diff --git a/modules/face/data/cascades/haarcascade_mcs_mouth.xml b/modules/face/data/cascades/haarcascade_mcs_mouth.xml index 277a2eb67..d4dc0536e 100644 --- a/modules/face/data/cascades/haarcascade_mcs_mouth.xml +++ b/modules/face/data/cascades/haarcascade_mcs_mouth.xml @@ -122,8 +122,8 @@ Section 8 – Interpretation. BOOST HAAR - 25 - 15 + 15 + 25 218 diff --git a/modules/face/data/cascades/haarcascade_mcs_nose.xml b/modules/face/data/cascades/haarcascade_mcs_nose.xml index d196df130..49e0b8700 100644 --- a/modules/face/data/cascades/haarcascade_mcs_nose.xml +++ b/modules/face/data/cascades/haarcascade_mcs_nose.xml @@ -121,8 +121,8 @@ Section 8 – Interpretation. BOOST HAAR - 18 - 15 + 15 + 18 377 diff --git a/modules/face/data/cascades/haarcascade_mcs_rightear.xml b/modules/face/data/cascades/haarcascade_mcs_rightear.xml index 61adf1692..8c028c2ab 100644 --- a/modules/face/data/cascades/haarcascade_mcs_rightear.xml +++ b/modules/face/data/cascades/haarcascade_mcs_rightear.xml @@ -121,8 +121,8 @@ Section 8 – Interpretation. BOOST HAAR - 12 - 20 + 20 + 12 61 diff --git a/modules/face/data/cascades/haarcascade_mcs_righteye.xml b/modules/face/data/cascades/haarcascade_mcs_righteye.xml index 8db288d26..12bbc79ae 100644 --- a/modules/face/data/cascades/haarcascade_mcs_righteye.xml +++ b/modules/face/data/cascades/haarcascade_mcs_righteye.xml @@ -121,8 +121,8 @@ Section 8 – Interpretation. BOOST HAAR - 18 - 12 + 12 + 18 415 diff --git a/modules/face/data/cascades/haarcascade_mcs_upperbody.xml b/modules/face/data/cascades/haarcascade_mcs_upperbody.xml index 76ba9ceef..ba66ca94c 100644 --- a/modules/face/data/cascades/haarcascade_mcs_upperbody.xml +++ b/modules/face/data/cascades/haarcascade_mcs_upperbody.xml @@ -119,8 +119,8 @@ Section 8 – Interpretation. BOOST HAAR - 22 - 20 + 20 + 22 334 From 395db9e7211d58473beafa6a9643d3cd49ad4eb4 Mon Sep 17 00:00:00 2001 From: Gregory Kramida Date: Mon, 23 May 2016 12:56:39 -0400 Subject: [PATCH 05/15] Fix sign() macro redefinition compile-time error --- modules/tracking/include/opencv2/tracking/onlineMIL.hpp | 2 -- modules/tracking/src/onlineMIL.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/tracking/include/opencv2/tracking/onlineMIL.hpp b/modules/tracking/include/opencv2/tracking/onlineMIL.hpp index b6fc25b0c..78e1372f8 100644 --- a/modules/tracking/include/opencv2/tracking/onlineMIL.hpp +++ b/modules/tracking/include/opencv2/tracking/onlineMIL.hpp @@ -54,8 +54,6 @@ namespace cv //TODO based on the original implementation //http://vision.ucsd.edu/~bbabenko/project_miltrack.shtml -#define sign(s) ((s > 0 ) ? 1 : ((s<0) ? -1 : 0)) - class ClfOnlineStump; class CV_EXPORTS ClfMilBoost diff --git a/modules/tracking/src/onlineMIL.cpp b/modules/tracking/src/onlineMIL.cpp index 4fcfb548f..29fa9fe34 100644 --- a/modules/tracking/src/onlineMIL.cpp +++ b/modules/tracking/src/onlineMIL.cpp @@ -42,6 +42,8 @@ #include "precomp.hpp" #include "opencv2/tracking/onlineMIL.hpp" +#define sign(s) ((s > 0 ) ? 1 : ((s<0) ? -1 : 0)) + template class SortableElementRev { public: From 9481d44b4490457c160ff9de84785121792d73b1 Mon Sep 17 00:00:00 2001 From: Wu Jiang Date: Wed, 25 May 2016 22:59:04 -0400 Subject: [PATCH 06/15] Fix a typo `lenght` --> `length` --- modules/aruco/samples/calibrate_camera_charuco.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/aruco/samples/calibrate_camera_charuco.cpp b/modules/aruco/samples/calibrate_camera_charuco.cpp index 5df699707..7c346fbf0 100644 --- a/modules/aruco/samples/calibrate_camera_charuco.cpp +++ b/modules/aruco/samples/calibrate_camera_charuco.cpp @@ -57,8 +57,8 @@ const char* about = const char* keys = "{w | | Number of squares in X direction }" "{h | | Number of squares in Y direction }" - "{sl | | Square side lenght (in pixels) }" - "{ml | | Marker side lenght (in pixels) }" + "{sl | | Square side length (in pixels) }" + "{ml | | Marker side length (in pixels) }" "{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," From f5deefefe21febf9e43095db42897cdd6a579c2d Mon Sep 17 00:00:00 2001 From: Gary Bradski Date: Sun, 27 Mar 2016 17:31:51 -0700 Subject: [PATCH 07/15] Extensive changes to master README.md Extensive changes to README.md opencv_contrib file to bring it up to date. --- modules/README.md | 70 +++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/modules/README.md b/modules/README.md index 0f245bee2..d42fea6b5 100644 --- a/modules/README.md +++ b/modules/README.md @@ -1,59 +1,71 @@ -An overview of the contrib modules and a small explanation ----------------------------------------------------------- +An overview of the opencv_contrib modules +----------------------------------------- This list gives an overview of all modules available inside the contrib repository. -These are also the correct names for disabling the building of a specific module by adding +To turn off building one of these module repositories, set the names in bold below to ``` -$ cmake -D OPENCV_EXTRA_MODULES_PATH=/modules -D BUILD_opencv_reponame=OFF +$ cmake -D OPENCV_EXTRA_MODULES_PATH=/modules -D BUILD_opencv_=OFF ``` -1. **opencv_adas**: Advanced Driver Assistance Systems module with Forward Collision Warning. +1. **aruco**: ArUco and ChArUco Markers -- Augmented reality ArUco marker and "ChARUco" markers where ArUco markers embedded inside the white areas of the checker board. -2. **opencv_bgsegm**: Improved Adaptive Background Mixture Model for Real-time Tracking / Visual Tracking of Human Visitors under Variable-Lighting Conditions. +2. **bgsegm**: Background Segmentation -- Improved Adaptive Background Mixture Model and use for real time human tracking under Variable-Lighting Conditions. -3. **opencv_bioinspired**: Biologically inspired vision models and derivated tools. +3. **bioinspired**: Biological Vision -- Biologically inspired vision model: minimize noise and luminance variance, transient event segmentation, high dynamic range tone mapping methods. -4. **opencv_ ccalib**: Custom Calibration Pattern for 3D reconstruction. +4. **ccalib**: Custom Calibration -- Patterns for 3D reconstruction, omnidirectional camera calibration, random pattern calibration and multi-camera calibration. -5. **opencv_cvv**: GUI for Interactive Visual Debugging of Computer Vision Programs. +5. **cnn_3dobj**: Deep Object Recognition and Pose -- Uses Caffe Deep Neural Net library to build, train and test a CNN model of visual object recognition and pose. -6. **opencv_datasets**: Interface for interfacing with existing computer vision databases. +6. **contrib_world**: opencv_contrib holder -- contrib_world is the module that when built, contains all other opencv_contrib modules. It may be used for the more convenient redistribution of opencv binaries. -7. **opencv_datasettools**: Tools for working with different datasets. +7. **cvv**: Computer Vision Debugger -- Simple code that you can add to your program that pops up a GUI allowing you to interactively and visually debug computer vision programs. -8. **opencv_face**: Recently added face recognition software which is not yet stabilized. +8. **datasets**: Datasets Reader -- Code for reading existing computer vision databases and samples of using the readers to train, test and run using that dataset's data. -9. **opencv_latentsvm**: Implementation of the LatentSVM detector algorithm. +9. **dnn**: Deep Neural Networks (DNNs) -- This module can read in image recogniton networks trained in the Caffe neural netowrk library and run them efficiently on CPU. -10. **opencv_line_descriptor**: Binary descriptors for lines extracted from an image. +10. **dnns_easily_fooled**: Subvert DNNs -- This code can use the activations in a network to fool the networks into recognizing something else. -11. **opencv_matlab**: OpenCV Matlab Code Generator. +11. **dpm**: Deformable Part Model -- Felzenszwalb's Cascade with deformable parts object recognition code. -12. **opencv_optflow**: Optical Flow Algorithms for tracking points. +12. **face**: Face Recognition -- Face recognition techniques: Eigen, Fisher and Local Binary Pattern Histograms LBPH methods. -13. **opencv_reg**: Image Registration module. +13. **fuzzy**: Fuzzy Logic in Vision -- Fuzzy logic image transform and inverse; Fuzzy image processing. -14. **opencv_rgbd**: RGB-Depth Processing module. +14. **hdf**: Hierarchical Data Storage -- This module contains I/O routines for Hierarchical Data Format: https://en.m.wikipedia.org/wiki/Hierarchical_Data_Format meant to store large amounts of data. -15. **opencv_saliency**: Saliency API, understanding where humans focus given a scene. +15. **line_descriptor**: Line Segment Extract and Match -- Methods of extracting, describing and latching line segments using binary descriptors. -16. **opencv_surface_matching**: Surface Matching Algorithm Through 3D Features. +16. **matlab**: Matlab Interface -- OpenCV Matlab Mex wrapper code generator for certain opencv core modules. -17. **opencv_text**: Scene Text Detection and Recognition in Natural Scene Images. +17. **optflow**: Optical Flow -- Algorithms for running and evaluating deepflow, simpleflow, sparsetodenseflow and motion templates (silhouette flow). -18. **opencv_tracking**: Long-term optical tracking API. +18. **plot**: Plotting -- The plot module allows you to easily plot data in 1D or 2D. -19. **opencv_xfeatures2d**: Extra 2D Features Framework containing experimental and non-free 2D feature algorithms. +19. **reg**: Image Registration -- Pixels based image registration for precise alignment. Follows the paper "Image Alignment and Stitching: A Tutorial", by Richard Szeliski. -20. **opencv_ximgproc**: Extended Image Processing: Structured Forests / Domain Transform Filter / Guided Filter / Adaptive Manifold Filter / Joint Bilateral Filter / Superpixels. +20. **rgbd**: RGB-Depth Processing module -- Linemod 3D object recognition; Fast surface normals and 3D plane finding. 3D visual odometry -21. **opencv_xobjdetect**: Integral Channel Features Detector Framework. +21. **saliency**: Saliency API -- Where humans would look in a scene. Has routines for static, motion and "objectness" saliency. -22. **opencv_xphoto**: Additional photo processing algorithms: Color balance / Denoising / Inpainting. +22. **sfm**: Structure from Motion -- This module contains algorithms to perform 3d reconstruction from 2d images. The core of the module is a light version of Libmv. -23. **opencv_stereo**: Stereo Correspondence done with different descriptors: Census / CS-Census / MCT / BRIEF / MV. +23. **stereo**: Stereo Correspondence -- Stereo matching done with different descriptors: Census / CS-Census / MCT / BRIEF / MV. -24. **opencv_hdf**: Hierarchical Data Format I/O. +24. **structured_light**: Structured Light Use -- How to generate and project gray code patterns and use them to find dense depth in a scene. -25. **opencv_fuzzy**: New module focused on the fuzzy image processing. +25. **surface_matching**: Point Pair Features -- Implements 3d object detection and localization using multimodal point pair features. + +26. **text**: Visual Text Matching -- In a visual scene, detect text, segment words and recognise the text. + +27. **tracking**: Vision Based Object Tracking -- Use and/or evaluate one of 5 different visual object tracking techniques. + +28. **xfeatures2d**: Features2D extra -- Extra 2D Features Framework containing experimental and non-free 2D feature detector/descriptor algorithms. SURF, SIFT, BRIEF, Censure, Freak, LUCID, Daisy, Self-similar. + +29. **ximgproc**: Extended Image Processing -- Structured Forests / Domain Transform Filter / Guided Filter / Adaptive Manifold Filter / Joint Bilateral Filter / Superpixels. + +30. **xobjdetect**: Boosted 2D Object Detection -- Uses a Waldboost cascade and local binary patterns computed as integral features for 2D object detection. + +31. **xphoto**: Extra Computational Photography -- Additional photo processing algorithms: Color balance / Denoising / Inpainting. From fd6355e00a0fa904aacf230502702879299adcaf Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Fri, 3 Jun 2016 10:33:01 +0300 Subject: [PATCH 08/15] aruco: fixed rejectedCorners input type to generate correct python signature --- modules/aruco/include/opencv2/aruco.hpp | 2 +- modules/aruco/src/aruco.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/aruco/include/opencv2/aruco.hpp b/modules/aruco/include/opencv2/aruco.hpp index 88d400335..b650ec597 100644 --- a/modules/aruco/include/opencv2/aruco.hpp +++ b/modules/aruco/include/opencv2/aruco.hpp @@ -374,7 +374,7 @@ CV_EXPORTS_W int estimatePoseBoard(InputArrayOfArrays corners, InputArray ids, P */ CV_EXPORTS_W void refineDetectedMarkers( InputArray image, Ptr &board, InputOutputArrayOfArrays detectedCorners, - InputOutputArray detectedIds, InputOutputArray rejectedCorners, + InputOutputArray detectedIds, InputOutputArrayOfArrays rejectedCorners, InputArray cameraMatrix = noArray(), InputArray distCoeffs = noArray(), float minRepDistance = 10.f, float errorCorrectionRate = 3.f, bool checkAllOrders = true, OutputArray recoveredIdxs = noArray(), const Ptr ¶meters = DetectorParameters::create()); diff --git a/modules/aruco/src/aruco.cpp b/modules/aruco/src/aruco.cpp index bb98778a4..91a236f19 100644 --- a/modules/aruco/src/aruco.cpp +++ b/modules/aruco/src/aruco.cpp @@ -1099,7 +1099,7 @@ static void _projectUndetectedMarkers(Ptr &_board, InputOutputArrayOfArra */ void refineDetectedMarkers(InputArray _image, Ptr &_board, InputOutputArrayOfArrays _detectedCorners, InputOutputArray _detectedIds, - InputOutputArray _rejectedCorners, InputArray _cameraMatrix, + InputOutputArrayOfArrays _rejectedCorners, InputArray _cameraMatrix, InputArray _distCoeffs, float minRepDistance, float errorCorrectionRate, bool checkAllOrders, OutputArray _recoveredIdxs, const Ptr &_params) { From d4df727d380887fdd880fdb5430cf4680a4ad19b Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Sat, 11 Jun 2016 17:51:46 +0200 Subject: [PATCH 09/15] fix overflow issue when computing diagonal - with big images the int multiplication can overflow --- modules/xfeatures2d/src/sift.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/xfeatures2d/src/sift.cpp b/modules/xfeatures2d/src/sift.cpp index 9634fbbf0..efd0b2f3a 100644 --- a/modules/xfeatures2d/src/sift.cpp +++ b/modules/xfeatures2d/src/sift.cpp @@ -579,7 +579,7 @@ static void calcSIFTDescriptor( const Mat& img, Point2f ptf, float ori, float sc float hist_width = SIFT_DESCR_SCL_FCTR * scl; int radius = cvRound(hist_width * 1.4142135623730951f * (d + 1) * 0.5f); // Clip the radius to the diagonal of the image to avoid autobuffer too large exception - radius = std::min(radius, (int) sqrt((double) img.cols*img.cols + img.rows*img.rows)); + radius = std::min(radius, (int) sqrt(((double) img.cols)*img.cols + ((double) img.rows)*img.rows)); cos_t /= hist_width; sin_t /= hist_width; From f63c28a61558bff439f69bf22d2a1078f06116b4 Mon Sep 17 00:00:00 2001 From: Sarthak Ahuja Date: Mon, 16 May 2016 02:45:29 +0530 Subject: [PATCH 10/15] [Aruco] detector_params YAML updated [Aruco] Fixed the spelling of Length in Samples replaced images to 6x6_250 Updated README [Aruco] Updated Charuco Diamond Detection Tutorial Readme [Aruco] Updated Charuco Board Detection Tutorial Readme [Aruco] Updated Aruco Tutorials Readme [Aruco] Updated Aruco Tutorials Readme Added a new line at the end of file. Update aruco_board_detection.markdown Update aruco_calibration.markdown Update aruco_detection.markdown Update charuco_detection.markdown Update charuco_diamond_detection.markdown Update README.md Update charuco_detection.markdown --- README.md | 7 +++++-- modules/aruco/samples/calibrate_camera.cpp | 2 +- .../samples/calibrate_camera_charuco.cpp | 4 ++-- modules/aruco/samples/create_board.cpp | 2 +- .../aruco/samples/create_board_charuco.cpp | 4 ++-- modules/aruco/samples/create_diamond.cpp | 4 ++-- .../aruco/samples/detect_board_charuco.cpp | 4 ++-- modules/aruco/samples/detect_diamonds.cpp | 4 ++-- modules/aruco/samples/detector_params.yml | 7 +++++++ .../aruco_board_detection.markdown | 11 +++++++++++ .../aruco_board_detection/images/board.jpg | Bin 81038 -> 10914 bytes .../aruco_calibration.markdown | 10 ++++++++++ .../aruco_detection/aruco_detection.markdown | 15 +++++++++++++++ .../aruco_detection/images/marker23.jpg | Bin 4777 -> 1163 bytes .../charuco_detection.markdown | 15 +++++++++++++++ .../charuco_detection/images/board.jpg | Bin 0 -> 31536 bytes .../charuco_detection/images/charucoboard.jpg | Bin 28375 -> 0 bytes .../charuco_diamond_detection.markdown | 13 +++++++++++++ 18 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 modules/aruco/tutorials/charuco_detection/images/board.jpg delete mode 100644 modules/aruco/tutorials/charuco_detection/images/charucoboard.jpg diff --git a/README.md b/README.md index c3456233c..e7690419d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ provides production quality support for this module. ### How to build OpenCV with extra modules -You can build OpenCV, so it will include the modules from this repository. +You can build OpenCV, so it will include the modules from this repository. Contrib modules are under constant development and it is recommended to use them alongside the master branch or latest releases of OpenCV. + Here is the CMake command for you: ``` @@ -46,10 +47,12 @@ If you prefer using the gui version of cmake (cmake-gui), then, you can add `ope 7. build the `opencv` core with the method you chose (make and make install if you chose Unix makfile at step 6) +8. to run, linker flags to contrib modules will need to be added to use them in your code/IDE. For example to use the aruco module, "-lopencv_aruco" flag will be added. + ### Update the repository documentation In order to keep a clean overview containing all contributed modules the following files need to be created/adapted. 1. Update the README.md file under the modules folder. Here you add your model with a single line description. -2. Add a README.md inside your own module folder. This README explains which functionality (seperate functions) is available, links to the corresponding samples and explains in somewhat more detail what the module is expected to do. If any extra requirements are needed to build the module without problems, add them here also. \ No newline at end of file +2. Add a README.md inside your own module folder. This README explains which functionality (seperate functions) is available, links to the corresponding samples and explains in somewhat more detail what the module is expected to do. If any extra requirements are needed to build the module without problems, add them here also. diff --git a/modules/aruco/samples/calibrate_camera.cpp b/modules/aruco/samples/calibrate_camera.cpp index 0ffbc8acd..f732967ea 100644 --- a/modules/aruco/samples/calibrate_camera.cpp +++ b/modules/aruco/samples/calibrate_camera.cpp @@ -58,7 +58,7 @@ const char* about = const char* keys = "{w | | Number of squares in X direction }" "{h | | Number of squares in Y direction }" - "{l | | Marker side lenght (in meters) }" + "{l | | Marker side length (in meters) }" "{s | | Separation between two consecutive markers in the grid (in meters) }" "{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, " diff --git a/modules/aruco/samples/calibrate_camera_charuco.cpp b/modules/aruco/samples/calibrate_camera_charuco.cpp index 7c346fbf0..0b2934919 100644 --- a/modules/aruco/samples/calibrate_camera_charuco.cpp +++ b/modules/aruco/samples/calibrate_camera_charuco.cpp @@ -57,8 +57,8 @@ const char* about = const char* keys = "{w | | Number of squares in X direction }" "{h | | Number of squares in Y direction }" - "{sl | | Square side length (in pixels) }" - "{ml | | Marker side length (in pixels) }" + "{sl | | Square side length (in meters) }" + "{ml | | Marker side length (in meters) }" "{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," diff --git a/modules/aruco/samples/create_board.cpp b/modules/aruco/samples/create_board.cpp index f599bb6a1..937fe5b5f 100644 --- a/modules/aruco/samples/create_board.cpp +++ b/modules/aruco/samples/create_board.cpp @@ -48,7 +48,7 @@ const char* keys = "{@outfile | | Output image }" "{w | | Number of markers in X direction }" "{h | | Number of markers in Y direction }" - "{l | | Marker side lenght (in pixels) }" + "{l | | Marker side length (in pixels) }" "{s | | Separation between two consecutive markers in the grid (in pixels)}" "{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, " diff --git a/modules/aruco/samples/create_board_charuco.cpp b/modules/aruco/samples/create_board_charuco.cpp index f21b90bbf..113138201 100644 --- a/modules/aruco/samples/create_board_charuco.cpp +++ b/modules/aruco/samples/create_board_charuco.cpp @@ -48,8 +48,8 @@ const char* keys = "{@outfile | | Output image }" "{w | | Number of squares in X direction }" "{h | | Number of squares in Y direction }" - "{sl | | Square side lenght (in pixels) }" - "{ml | | Marker side lenght (in pixels) }" + "{sl | | Square side length (in pixels) }" + "{ml | | Marker side length (in pixels) }" "{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," diff --git a/modules/aruco/samples/create_diamond.cpp b/modules/aruco/samples/create_diamond.cpp index 4534fe2d2..66aec2274 100644 --- a/modules/aruco/samples/create_diamond.cpp +++ b/modules/aruco/samples/create_diamond.cpp @@ -49,8 +49,8 @@ namespace { const char* about = "Create a ChArUco marker image"; const char* keys = "{@outfile | | Output image }" - "{sl | | Square side lenght (in pixels) }" - "{ml | | Marker side lenght (in pixels) }" + "{sl | | Square side length (in pixels) }" + "{ml | | Marker side length (in pixels) }" "{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," diff --git a/modules/aruco/samples/detect_board_charuco.cpp b/modules/aruco/samples/detect_board_charuco.cpp index b537e45de..57f0c0d2f 100644 --- a/modules/aruco/samples/detect_board_charuco.cpp +++ b/modules/aruco/samples/detect_board_charuco.cpp @@ -51,8 +51,8 @@ const char* about = "Pose estimation using a ChArUco board"; const char* keys = "{w | | Number of squares in X direction }" "{h | | Number of squares in Y direction }" - "{sl | | Square side lenght (in pixels) }" - "{ml | | Marker side lenght (in pixels) }" + "{sl | | Square side length (in meters) }" + "{ml | | Marker side length (in meters) }" "{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," diff --git a/modules/aruco/samples/detect_diamonds.cpp b/modules/aruco/samples/detect_diamonds.cpp index f60b70699..eda0dfc19 100644 --- a/modules/aruco/samples/detect_diamonds.cpp +++ b/modules/aruco/samples/detect_diamonds.cpp @@ -49,8 +49,8 @@ using namespace cv; namespace { const char* about = "Detect ChArUco markers"; const char* keys = - "{sl | | Square side lenght (in pixels) }" - "{ml | | Marker side lenght (in pixels) }" + "{sl | | Square side length (in meters) }" + "{ml | | Marker side length (in meters) }" "{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," diff --git a/modules/aruco/samples/detector_params.yml b/modules/aruco/samples/detector_params.yml index 764c717d5..ab94c03cf 100644 --- a/modules/aruco/samples/detector_params.yml +++ b/modules/aruco/samples/detector_params.yml @@ -1,5 +1,8 @@ %YAML:1.0 nmarkers: 1024 +adaptiveThreshWinSizeMin: 3 +adaptiveThreshWinSizeMax: 23 +adaptiveThreshWinSizeStep: 10 adaptiveThreshWinSize: 21 adaptiveThreshConstant: 7 minMarkerPerimeterRate: 0.03 @@ -8,6 +11,8 @@ polygonalApproxAccuracyRate: 0.05 minCornerDistance: 10.0 minDistanceToBorder: 3 minMarkerDistance: 10.0 +minMarkerDistanceRate: 0.05 +doCornerRefinement: false cornerRefinementWinSize: 5 cornerRefinementMaxIterations: 30 cornerRefinementMinAccuracy: 0.1 @@ -15,3 +20,5 @@ markerBorderBits: 1 perspectiveRemovePixelPerCell: 8 perspectiveRemoveIgnoredMarginPerCell: 0.13 maxErroneousBitsInBorderRate: 0.04 +minOtsuStdDev: 5.0 +errorCorrectionRate: 0.6 diff --git a/modules/aruco/tutorials/aruco_board_detection/aruco_board_detection.markdown b/modules/aruco/tutorials/aruco_board_detection/aruco_board_detection.markdown index 0760feb23..2ec5ef9dd 100644 --- a/modules/aruco/tutorials/aruco_board_detection/aruco_board_detection.markdown +++ b/modules/aruco/tutorials/aruco_board_detection/aruco_board_detection.markdown @@ -155,6 +155,11 @@ The output image will be something like this: A full working example of board creation is included in the ```create_board.cpp``` inside the module samples folder. +Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like +``` c++ + "_output path_/aboard.png" -w=5 -h=7 -l=100 -s=10 -d=10 +``` + Finally, a full example of board detection: ``` c++ @@ -204,6 +209,12 @@ Sample video: A full working example is included in the ```detect_board.cpp``` inside the module samples folder. +Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like +``` c++ + -c="_path_"/calib.txt" "_path_/aboard.png" -w=5 -h=7 -l=100 -s=10 -d=10 +``` + + Refine marker detection ----- diff --git a/modules/aruco/tutorials/aruco_board_detection/images/board.jpg b/modules/aruco/tutorials/aruco_board_detection/images/board.jpg index 2edc06fc3dda33abd2a6b0512efcdc4a8ebc0844..0f2c25b55954c31236437bfa3dd241fd86894e65 100644 GIT binary patch literal 10914 zcmb_>bzIcV+V=trtaJ#{-MOT6NH+@7v2=$tNF!3xA&p8(=TZ_&h)PN~g0g^!G}1gj z@B6&xJ!^gsY+~{{RF+g@Qn6I1r!# zWdE?|BM5}E>>wwnts*B!r|scp>)>ny0vSXW>th<|yeG{!P8lN#NGB2-$6+&7Ey74L z1K*FKPm+P~p`+B%$8om!5F+Ydy<&@_4(or4j_rimj@`z_w!Ow7%;iQDYv8kT(dm0Q z+;NlVIg%@8=L*tZhoYm>V1eF!iHi)ofAoa?R*derDII2G7=JD12lWhPnZ#&FBv)ub zzg>h|wf+t$S*m7EW#&BNy5MTzhg8=OI<1ax9@`u+ zF}AI06WPc|b(cyuc0nVzSo^C9cJ27C3ZwQ?on1}H`lLWFSWx$i*rFro^V#1=7t1+g zKhh|N(ve#7M!R`1$v%)k0jYB)5)JfA$@4JOecAgyjW@N!{!}ZqvZj8I#RNo9 zEwQ7`>;1#-M{E-uf!82g*?W1P1~wui@y-?4Y~rl1dwlP;XA(0GXEB20iR+*&j$^`> z>Ku1NQ67Q%M5!#aCtq~+6{6->j=@dnYVVix-s)YvE)Os>uuO@p|UJgy7pn*RAEVR_)!EN(K1h;$wAr_H+zX5kfRh? zhv~k1AK}s4pqqrcj=5gsWR0K?O08bt&auMXYKZEcaTibOzKgdR>4hhsDjVg@f;s>E zRzat`9;$-_LE}rqk3yNROyS<0up;GFbUI6zBhk$UIdpGKMIp3 z_VJovRvLlF7gX`NOZmCQ+Ue1JwV-YCk7C&KV)GXt_bC!qZ?Q2y-Ids+4`GvHupfTR zmdeL;m0rMk#H5ERyH&6J_NbhYvkbk5++@0VJ?JK-$*pN2D7ks>qc?p;TAJHe)UOOC z%qA?0tR|Scrv>lH1NFqEd1(QCWj;Zk}WSQ~XV9eR#n%$zx* zgDF>w2KAC32&{hk;3v;`mMX*b^oMR%X6f{huvmWCmcApXU9**0~{9Yg&OZPUKEJh-?a}JpSL%r zTW5z;h(Do5P}C|`l4!3QGy0%9CB3AmymftYB^Oy5RN7Na(o0cp&;C$CSEtY^#LIfC z@D=kqZG!u`^yKztY_jdQkOuoBF>@dA$%d&CU$Ka`@@=PB;z&(dwzqp5%KKsO(k$=Y zDz=w%BzNwz6=Nm%QB!Cfwekxgv;vck`_t=<7UImK?rN(IwFGI$pjHJk1BB&>1Vr}~Ckaja zAbd*B1WJ7*`}Z!BwVAL~WKxm^pCl?L1zHn62(P^NA(>lQs2<-zMw4zMiSr$I5%HGn zwc_$ivhpX6FEGl`#qhipw(KDk5t?!nV}|xLM$tTSgJY_V7*%pwFYb&9H=+f_o>+l& z`Wm5DLwKJ3fpzX&glhdyW+f`gIQu#3jAqe{YMl%)r{g;MV_L*C`*&cZ5qk!?k)u5u zt7`imfvjdx1wA#Zd49Cl$ucaP#LkfKUh%nZmNkvZ<7bl!BCgaO-O<-R70Hua zlb2HuCb6dA<$1b~%MxDalwXuLOx}6zrXyXoTr4|TI|;Kda!RwmeD&ylp_Yz@XSi*y zZGvqil5iN0TYd0e+{^w6qv|H}3e)X8c$lzhPF06|yWU0liBle*n3R}vo@Jh-n2Xr1 z*Xy?HHu5%3Z~X1$iQePNV}@hfZI^NJsu^)bt7ijb)0u007XypaO2<{lg-08kZc}bk zyLX|25J3X6%DW;CV@_o@n^u{wEpPYAEE1F3lAjaK*vEh5D`eHx;K=(>m~mh0{>8K7 z_=soBZ;hYvQs8GAWcOv?&iuyLYF7^X>X_}=_O@}ZadhaNbG>2boNL1Z@&H+lq&oCQ zawBWFxwzN3NsX!CoAAjxYXhX=claA81^59x+vcHzcM#X3%I(=_b(8~UaK);;O3`VO z>F3Vcly;QW!-_eaaIo=R<4%|29b9o{@itTVl54x>W9|#>3)G9=lhL(lf7QPx>?nAWV|YDsF_gmr1Z z=CCGhu4!)MNYjWUk1fx89!e9}7RMIF79MZOZAJH-FTyKT?{})&8`@`sx-QIVd}zpN z+9ldpjWn&b7KQg;md3D7c*fa9-I?N?+qSF0bF*?Q@h$#=MypeByMUu$;Hd7%D**Ru zj%l80wMZ`2?4s>r9QTcVHCix1b(dcE8D-PQSLkF4Sb$WFvvq+KkmZFxgEi?PU z`xR^ACC_sBeLqBkJHW2@f*9EOcZa-QdB`ld zSXI>LVfOVSkD%7|#f>f5t(*ySyC-(v-ktWvZS1^H8&n^0{#3Cqa9UcA)8J8G4RHo5 zgeMq&ZMI`=egzCJS2x4&Yh81@d{qOtVR#R_TkYr$gJCIMm0i|hd+;7 zyCXzOahr!N@Ko*-etR67LeDG8I7w2sYr>o4i_iVcpPyHnAJmByp9bElDr)?4^IOnEz%ImOPrF%h@gX&t{+ zoHN5-nOeEchRt1J?gkI;KmW0wdjOABA$csk>1I&Bdi*vmUjOcybNP~UZL9TRdqJ!8 z$|6xqarOACdN0mLPAAh!3v2KuXWu0=(_;OH4~{J`LzD(a%JNFfP0K5Mw|0#>DVMnC zmUL2eJsVSHqYl_>(k((k-h==P%d9ig=o< zccB~ZNFhf4W+Zfqo>X7Kt<36w zeP3~(yT{-olVJX1l^GqxMA-5x>4!IqdqZF65M6=SjypNyGsh;UmlG>$=9`_f`yM@m z$m{6qiyD4&+&4VIg%`FP#xu>_yK5_wG?`cVN1fk#XYu1{<)oIc($2OfLO|T6dsKm5 zVVxililKw9ftP`Xx|o%l3y+1ho23nppNsp?R0t&DCkFgkhBpD1ewCUvBJZ$KMcm#Q%3{qHhbaWCP*0y2~!Z0z7UWcD#I|qN2P|eqMflZlDLZr@yP0g&()8C*z-!{GWN`Z9J_!9NfJe z++68?&TC=m=ItfP!0=PiKR#FjV4atC*ID zgAJhh=loK95`XmkUv2-;Bf^G$0miP-ot7L0#Q+@$jj>b zq3q=Cq)@hc$SWmWT-P`!eh;9?(y-RI$SJzlw@*v*m00ARy%ItGam~%uS_s`3>z?$L zEKNVqo)*iZxjPT9P=qd+o^_xxW~oXuJtH|>L%qfA79CHTP<$<-qW7byjl)m*{B2- ztf8=6%!+VOI6H{Y2Nm+x|34MT1gOQ@oG-rE<*xhWk3z}q(pwQ_otZU1d-!qYc@Z~W zt%Dw?BsV*6r9|nKJl9f*Lm#Siao5ch({bGJ9Yq*y8cd)*9F0RC3Ik)(bh5TvMw21sduR{@qsw>BWI}-(}@Gqek6Hg z9R;8ljfg!06i&`n`#V4;AaL>rdr%5R`fl^MlvfS!+|(fEY_*G#Si?gv(s?1_siLto zUUg8!V@(iZsPz*rp!mN9bREq78&CZyFA_CN(l*U$rq4zt-#VNjn09(ETO~9lQ1vbv ztCcQN2{C7d8fOQxcWN*=t6^H$Yg0Q2E+h#h;KnRgQZH) z!FMM-GSJ5>HwRmUL;Up}*aSn%Ke_?~zzxrwcTvF&KdyKSXb^ujWa6`xv-PMkpA+|9 zY`#BcfyA)pRZ7G`B;Q*u4pc}9gZv_dj;t5)iXjxnaj!2P6wXKWYl7|?yDNoUZ=3x( z@M%xrx2aAf41yFgk%n`IpUqYT4I>DKoLYjN^}&aA`WM*|^qDj6SF_a+q*cv{5T+co zX7#+zlyGRkY{v<&B*gY0MOsb7oEr_izI#)g|f(vy) zk{a=?I<)_gF;fB7UdoucL{jS)3~qop|L_7gw4;)aCc;R=cJdQoKKk8jXU7gQYKgS@ zU3pb2`AssELW3RFohgJ>+{5jGDmgk&z0(`N?B;6BdyQ*}2V8l0hXh)fg|N~Jp&$Y$ zy*sa=5ajVQX-CxXv$E~LD+_|5ZSs&wF!=EP%-MM_UFM9yb=fTlvatH_I7${;V|RI< zm|#fBbYmMo0%kUPTF63|nb7GEf1IQw9|9Z-TI+Q+s^=DXpYQES_mwba5p^VO&tH{$T6gd@hE4n=Loqr~Uh~mNVc}a}^;*{wJVt zLb6OD!0-ha}QkO`p3v@7U1pgjDlH8ig} zKkF%X7!^!e6{PRt#FWE-W2sY-o?jZFI%7hwLOnrI9Nxl={miiw8iB3{P@01bgAIYq z?*fD1z{b0;kKWh>SCFO7aBsJnUF%r5ID5it8w=)-L#j&COQUh&3gxwMtB;Xtdnqv7WJk%K>-@FJ$&^t zXuBY*^12_zmnbfrvGx$_Q_dFCT@16+W@P-4<#K?oeuUj;G+7*Bunhy^EK z=cNXxyE4bqXGkqBp;W~tTThJNQam5zT8L8jpU)TvwZrvNz9sNJ>+Y_+MVFaPNPZ85 zfZz;egTh~vC)0xoep!$~OKYrURmC*dZ>+Ik68JdIxc(s18|*Ao;nT53c7hSXJ48tr zG7bSBsx+THZJ^7%D|1~$2tlU09^%@`Lft|yRTv3|SeKBLBjK=R&{?V?U8Yvs@ZDT= z#2b_Y)_56cfme>32zIzX+7~T~FqqVq@QQoJ`oO?*>G*X_F-mS{k4Pq5fhN%_`cfdg zAS>+T{&^FkCk;}#E1&D)c=83^zP6e|>pbnreOcEDSRv0ofdp{j?HDR~fg@0p0FQzR zhO!{rYN!w-5k5iy1?db)nk~(lzce!HXw8tcr`A8Xrkl;sn0yb^ZP5;~I({l-_t(-}P_f=zL1C7RX10m~s zKYi+AJA9{{aL7kLc()sZr0M!CaDM7nLp)_n@Cm!2Ur2g434-+JYTkSTgSQ|zsEH5~ ziR+|!1Vf}Vmv7`4GB@fLUlE7Ttz{SZDuWLtGK{_ML5)og5Aj~##JB&r?m(URzO=TF zDZY#T{tj}v$wfaN25&!jjHw9yar&!Zx)f!{>vHdMr*S1;=mq*5{2=#)xDKUiz8_2N zCM)2~&FRi_YFpWb0Zzr)&^bJszhgna}O3bC|zqQD~1&=sRV;al1a8+4&CyxU~d z0P)Jjmck%kRX_hCNiX3^|9*p z2x*mG2zg?^9$`a*OhxGpTgYTEC2v;AVk(Un# zqJCAhUlS-NCT179J=_9{~nAfO^sbI;V_&|C&Z}E2!h0TL#;;mOW@p&C0?4pg>S21e7~1} z;yXg(PjCKs25u@8KKK2@E;Siq@pJPp0)qmK2c@5tHlx6258Kj@#y-(1RX3q#*J3=?#=!;#RqKru4*qPPu&oRXb%8`uA-VHjh`}~oQ&n*s!b}bmTfE#{BkLcnC zEHE;rh!(icQQ#Xma05wMQi6dmTB6GZz#fb;mCpfY`2P&t+P}Y2bhPwU4NY2u<{HRt zIVhovc4}?HoFmlN?Qo+l|8py)7=!*sy9stlEfRLiLY?u~`mK#6?BY0|u~S1=3xJEK z!zDtD0#1GR=@-GzYab#B54{Y`y>xItQX8E}Jbo~)ni42frH9sGhhNds0JR){cVdUF z@-&7sUH)>8{ z>av5E2pR21{yoXYpVdzAja{6IJFg?M{!JW7}-N+;Bl#}5riTDw2x10mzDfGdI2sV)%+H}BHtD4P<~ zaE^#SD||Z3IJZm;how$Ka$Tb!Av8nVfK;I_kp!*I#rQ=jE5TQsBiN(L8|%Rr0Ys^k4@<=uV|7ds+^YCZ1*B#>>)z{%aD@oXKjQTje-puKys%;;X~L8-Z?${z%u}5{F2Zn1a7C zmmL3W}+513ERd9Fm zZAnKcwP5<}H3dna1(C|74shbJ=yrfZCnEnX0GR)d1_w#ValNHKwKCebbS~z|lML7R zdkF4k+}e-uByv6a>x8U;fGW*eEK~cGw8Ou{FqPd@R+(SAp03~orP^OUKk*2dSFE=G zUaQ$an34}?Vs|VN&OXEwcUicMA3limA8-j8!vP=4K0iw+q|5ZxzJ5UtK}PT#QY*EzLV{zP}jJ4}i}KVkm0;O?Abe zZ$&j&>`9mLl76Zc_W=zw6(%{1O8fQuK!KmQrr_-zmI+pVAV6c$cDDg47!CBl1-g## sb3G^sA(wKYyf~`=nh*TDSGya`D~aHxr||QLpAW7o3YzlO_h8}w13UTKtN;K2 literal 81038 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 bL(hx&`XDoY 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 diff --git a/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown b/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown index 959ba715f..1d6697033 100644 --- a/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown +++ b/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown @@ -78,6 +78,11 @@ The output image will be something like this: A full working example is included in the ```create_board_charuco.cpp``` inside the module samples folder. +Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like +``` c++ + "_ output path_/chboard.png" -w=5 -h=7 -sl=200 -ml=120 -d=10 +``` + ChArUco Board Detection ------ @@ -240,6 +245,11 @@ Sample video: A full working example is included in the ```detect_board_charuco.cpp``` inside the module samples folder. +Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like +``` c++ + -c="_path_/calib.txt" -dp="_path_/detector_params.yml" -w=5 -h=7 -sl=0.04 -ml=0.02 -d=10 +``` + ChArUco Pose Estimation ------ @@ -312,3 +322,8 @@ A full example of ChArUco detection with pose estimation: ``` A full working example is included in the ```detect_board_charuco.cpp``` inside the module samples folder. + +Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like +``` c++ + "_path_/calib.txt" -dp="_path_/detector_params.yml" -w=5 -h=7 -sl=0.04 -ml=0.02 -d=10 +``` diff --git a/modules/aruco/tutorials/charuco_detection/images/board.jpg b/modules/aruco/tutorials/charuco_detection/images/board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eda7c86ca3247df317073382d01d3b7bf5563433 GIT binary patch literal 31536 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 literal 0 HcmV?d00001 diff --git a/modules/aruco/tutorials/charuco_detection/images/charucoboard.jpg b/modules/aruco/tutorials/charuco_detection/images/charucoboard.jpg deleted file mode 100644 index c0e7a85fc5508b21cd7373bab670bbfd6d351165..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28375 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 diff --git a/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown b/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown index 479d59dce..9f56cc2e9 100644 --- a/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown +++ b/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown @@ -60,6 +60,10 @@ The image produced will be: A full working example is included in the ```create_diamond.cpp``` inside the module samples folder. +Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like +``` c++ + "_path_/mydiamond.png" -sl=200 -ml=120 -d=10 -ids=45,68,28,74 +``` ChArUco Diamond Detection ------ @@ -116,6 +120,10 @@ The result is the same that the one produced by ```drawDetectedMarkers()```, but A full working example is included in the ```detect_diamonds.cpp``` inside the module samples folder. +Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like +``` c++ + -c="_path_/calib.txt" -dp="_path_/detector_params.yml" -sl=0.04 -ml=0.02 -d=10 +``` ChArUco Diamond Pose Estimation ------ @@ -159,3 +167,8 @@ Sample video: @endhtmlonly A full working example is included in the ```detect_diamonds.cpp``` inside the module samples folder. + +Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like +``` c++ + -c="_output path_/calib.txt" -dp="_path_/detector_params.yml" -sl=0.04 -ml=0.02 -d=10 +``` From 63584d77cb4032ee7f1134512aa7affe6926f7ce Mon Sep 17 00:00:00 2001 From: Dikay900 Date: Tue, 31 May 2016 19:53:21 +0200 Subject: [PATCH 11/15] add issue and pull request template --- .github/ISSUE_TEMPLATE.md | 30 ++++++++++++++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 9 +++++++++ 2 files changed, 39 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..4f1453a2f --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,30 @@ + + +##### System information (version) + + +- OpenCV => :grey_question: +- Operating System / Platform => :grey_question: +- Compiler => :grey_question: + +##### Detailed description + + + +##### Steps to reproduce + + \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..210a25311 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ + + +### This pullrequest changes + + From 823dea726f260e07b47fb1faf446f4e35a255a6f Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 16 Jun 2016 18:21:26 +0300 Subject: [PATCH 12/15] migration: github.com/opencv/opencv_contrib --- .github/ISSUE_TEMPLATE.md | 2 +- .travis.yml | 2 +- CONTRIBUTING.md | 2 +- modules/dnn/tutorials/tutorial_dnn_build.markdown | 8 ++++---- modules/text/include/opencv2/text.hpp | 2 +- modules/text/include/opencv2/text/erfilter.hpp | 2 +- modules/text/include/opencv2/text/ocr.hpp | 14 +++++++------- modules/text/src/ocr_hmm_decoder.cpp | 2 +- .../tutorial_introduction_to_tracker.markdown | 4 ++-- .../ximgproc/samples/structured_edge_detection.cpp | 2 +- .../tutorials/disparity_filtering.markdown | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 4f1453a2f..e72c70d8c 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,6 @@ diff --git a/.travis.yml b/.travis.yml index 23b3aba4e..5c603efde 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ compiler: - clang before_script: - cd ../ - - git clone https://github.com/Itseez/opencv.git + - git clone https://github.com/opencv/opencv.git - mkdir build-opencv - cd build-opencv - cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules ../opencv diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1e13c8996..318e9ac8f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,3 @@ ## Contributing guidelines -All guidelines for contributing to the OpenCV repository can be found at [`How to contribute guideline`](https://github.com/Itseez/opencv/wiki/How_to_contribute). +All guidelines for contributing to the OpenCV repository can be found at [`How to contribute guideline`](https://github.com/opencv/opencv/wiki/How_to_contribute). diff --git a/modules/dnn/tutorials/tutorial_dnn_build.markdown b/modules/dnn/tutorials/tutorial_dnn_build.markdown index d5fbc7f6a..36f0fecbf 100644 --- a/modules/dnn/tutorials/tutorial_dnn_build.markdown +++ b/modules/dnn/tutorials/tutorial_dnn_build.markdown @@ -3,7 +3,7 @@ Build opencv_contrib with dnn module {#tutorial_dnn_build} Introduction ------------ -opencv_dnn module is placed in the secondary [opencv_contrib](https://github.com/Itseez/opencv_contrib) repository, +opencv_dnn module is placed in the secondary [opencv_contrib](https://github.com/opencv/opencv_contrib) repository, which isn't distributed in binary form, therefore you need to build it manually. To do this you need to have installed: [CMake](http://www.cmake.org/download), git, and build system (*gcc* with *make* for Linux or *MS Visual Studio* for Windows) @@ -12,12 +12,12 @@ Steps ----- -# Make any directory, for example **opencv_root** --# Clone [opencv](https://github.com/Itseez/opencv) and [opencv_contrib](https://github.com/Itseez/opencv_contrib) repos to the **opencv_root**. +-# Clone [opencv](https://github.com/opencv/opencv) and [opencv_contrib](https://github.com/opencv/opencv_contrib) repos to the **opencv_root**. You can do it in terminal like here: @code cd opencv_root -git clone https://github.com/Itseez/opencv -git clone https://github.com/Itseez/opencv_contrib +git clone https://github.com/opencv/opencv +git clone https://github.com/opencv/opencv_contrib @endcode -# Run [CMake-gui] and set source and build directories: diff --git a/modules/text/include/opencv2/text.hpp b/modules/text/include/opencv2/text.hpp index 591424cb4..945194a16 100644 --- a/modules/text/include/opencv2/text.hpp +++ b/modules/text/include/opencv2/text.hpp @@ -92,7 +92,7 @@ grouping horizontally aligned text, and the method proposed by Lluis Gomez and D in [Gomez13][Gomez14] for grouping arbitrary oriented text (see erGrouping). To see the text detector at work, have a look at the textdetection demo: - + @defgroup text_recognize Scene Text Recognition @} diff --git a/modules/text/include/opencv2/text/erfilter.hpp b/modules/text/include/opencv2/text/erfilter.hpp index d17ac8879..9303e128f 100644 --- a/modules/text/include/opencv2/text/erfilter.hpp +++ b/modules/text/include/opencv2/text/erfilter.hpp @@ -345,7 +345,7 @@ single vector\, the function separates them in two different vectors (th ERStats where extracted from two different channels). An example of MSERsToERStats in use can be found in the text detection webcam_demo: - + */ CV_EXPORTS void MSERsToERStats(InputArray image, std::vector > &contours, std::vector > ®ions); diff --git a/modules/text/include/opencv2/text/ocr.hpp b/modules/text/include/opencv2/text/ocr.hpp index 651934b0c..1261046cd 100644 --- a/modules/text/include/opencv2/text/ocr.hpp +++ b/modules/text/include/opencv2/text/ocr.hpp @@ -81,10 +81,10 @@ Notice that it is compiled only when tesseract-ocr is correctly installed. @note - (C++) An example of OCRTesseract recognition combined with scene text detection can be found at the end_to_end_recognition demo: - + - (C++) Another example of OCRTesseract recognition combined with scene text detection can be found at the webcam_demo: - + */ class CV_EXPORTS_W OCRTesseract : public BaseOCR { @@ -152,7 +152,7 @@ enum decoder_mode @note - (C++) An example on using OCRHMMDecoder recognition combined with scene text detection can be found at the webcam_demo sample: - + */ class CV_EXPORTS_W OCRHMMDecoder : public BaseOCR { @@ -165,7 +165,7 @@ public: The default character classifier and feature extractor can be loaded using the utility funtion loadOCRHMMClassifierNM and KNN model provided in - . + . */ class CV_EXPORTS_W ClassifierCallback { @@ -321,7 +321,7 @@ CV_EXPORTS_W Ptr loadOCRHMMClassifierCNN(cons * The function calculate frequency statistics of character pairs from the given lexicon and fills the output transition_probabilities_table with them. The transition_probabilities_table can be used as input in the OCRHMMDecoder::create() and OCRBeamSearchDecoder::create() methods. * @note * - (C++) An alternative would be to load the default generic language transition table provided in the text module samples folder (created from ispell 42869 english words list) : - * + * **/ CV_EXPORTS void createOCRHMMTransitionsTable(std::string& vocabulary, std::vector& lexicon, OutputArray transition_probabilities_table); @@ -335,7 +335,7 @@ CV_EXPORTS_W Mat createOCRHMMTransitionsTable(const String& vocabulary, std::vec @note - (C++) An example on using OCRBeamSearchDecoder recognition combined with scene text detection can be found at the demo sample: - + */ class CV_EXPORTS_W OCRBeamSearchDecoder : public BaseOCR { @@ -348,7 +348,7 @@ public: The default character classifier and feature extractor can be loaded using the utility funtion loadOCRBeamSearchClassifierCNN with all its parameters provided in - . + . */ class CV_EXPORTS_W ClassifierCallback { diff --git a/modules/text/src/ocr_hmm_decoder.cpp b/modules/text/src/ocr_hmm_decoder.cpp index 1076475f1..5b7a5aa31 100644 --- a/modules/text/src/ocr_hmm_decoder.cpp +++ b/modules/text/src/ocr_hmm_decoder.cpp @@ -1206,7 +1206,7 @@ the output transition_probabilities_table with them. The transition_probabilities_table can be used as input in the OCRHMMDecoder::create() and OCRBeamSearchDecoder::create() methods. @note - (C++) An alternative would be to load the default generic language transition table provided in the text module samples folder (created from ispell 42869 english words list) : - + */ void createOCRHMMTransitionsTable(string& vocabulary, vector& lexicon, OutputArray _transitions) { diff --git a/modules/tracking/tutorials/tutorial_introduction_to_tracker.markdown b/modules/tracking/tutorials/tutorial_introduction_to_tracker.markdown index 500df0c1c..9e2b6eb89 100644 --- a/modules/tracking/tutorials/tutorial_introduction_to_tracker.markdown +++ b/modules/tracking/tutorials/tutorial_introduction_to_tracker.markdown @@ -28,8 +28,8 @@ Explanation as shown in help. In the help, it means that the image files are numbered with 4 digits (e.g. the file naming will be 0001.jpg, 0002.jpg, and so on). - You can find video samples in Itseez/opencv_extra/testdata/cv/tracking - + You can find video samples in opencv_extra/testdata/cv/tracking + -# **Declares the required variables** diff --git a/modules/ximgproc/samples/structured_edge_detection.cpp b/modules/ximgproc/samples/structured_edge_detection.cpp index 4c20d01a5..a11e9f102 100644 --- a/modules/ximgproc/samples/structured_edge_detection.cpp +++ b/modules/ximgproc/samples/structured_edge_detection.cpp @@ -1,7 +1,7 @@ /************************************************************************************** The structered edge demo requires you to provide a model. This model can be found at the opencv_extra repository on Github on the following link: -https://github.com/Itseez/opencv_extra/blob/master/testdata/cv/ximgproc/model.yml.gz +https://github.com/opencv/opencv_extra/blob/master/testdata/cv/ximgproc/model.yml.gz ***************************************************************************************/ #include diff --git a/modules/ximgproc/tutorials/disparity_filtering.markdown b/modules/ximgproc/tutorials/disparity_filtering.markdown index 4ca559f83..0248c6db4 100644 --- a/modules/ximgproc/tutorials/disparity_filtering.markdown +++ b/modules/ximgproc/tutorials/disparity_filtering.markdown @@ -27,7 +27,7 @@ Source Stereoscopic Image Source Code ----------- -We will be using snippets from the example application, that can be downloaded [here ](https://github.com/Itseez/opencv_contrib/blob/master/modules/ximgproc/samples/disparity_filtering.cpp). +We will be using snippets from the example application, that can be downloaded [here ](https://github.com/opencv/opencv_contrib/blob/master/modules/ximgproc/samples/disparity_filtering.cpp). Explanation ----------- From 42640a33af3f5915f89d79a5243bce169fe94bf8 Mon Sep 17 00:00:00 2001 From: LaurentBerger Date: Sun, 5 Jun 2016 20:41:50 +0200 Subject: [PATCH 13/15] Paillou filter Paillou Filter comment : english tab and assert Mat(instead of new) InputArray and ptr() Outputarrays OutputArray as argument Update doc --- modules/ximgproc/README.md | 1 + modules/ximgproc/doc/ximgproc.bib | 10 + modules/ximgproc/include/opencv2/ximgproc.hpp | 2 + .../opencv2/ximgproc/paillou_filter.hpp | 67 +++ modules/ximgproc/samples/paillou_demo.cpp | 107 ++++ modules/ximgproc/src/paillou_filter.cpp | 486 ++++++++++++++++++ 6 files changed, 673 insertions(+) create mode 100644 modules/ximgproc/include/opencv2/ximgproc/paillou_filter.hpp create mode 100644 modules/ximgproc/samples/paillou_demo.cpp create mode 100644 modules/ximgproc/src/paillou_filter.cpp diff --git a/modules/ximgproc/README.md b/modules/ximgproc/README.md index b566aa354..1afdd610b 100644 --- a/modules/ximgproc/README.md +++ b/modules/ximgproc/README.md @@ -9,3 +9,4 @@ Extended Image Processing 6. Superpixels 7. Graph segmentation 8. Selective search from segmentation +10. Paillou Filter diff --git a/modules/ximgproc/doc/ximgproc.bib b/modules/ximgproc/doc/ximgproc.bib index 3de1724c9..0fbbb374b 100644 --- a/modules/ximgproc/doc/ximgproc.bib +++ b/modules/ximgproc/doc/ximgproc.bib @@ -166,3 +166,13 @@ year={2014}, organization={IEEE} } + +@article{paillou1997detecting, + title={Detecting step edges in noisy SAR images: a new linear operator}, + author={Paillou, Philippe}, + journal={IEEE transactions on geoscience and remote sensing}, + volume={35}, + number={1}, + pages={191--196}, + year={1997} +} diff --git a/modules/ximgproc/include/opencv2/ximgproc.hpp b/modules/ximgproc/include/opencv2/ximgproc.hpp index 84015b910..b803ce3ef 100644 --- a/modules/ximgproc/include/opencv2/ximgproc.hpp +++ b/modules/ximgproc/include/opencv2/ximgproc.hpp @@ -48,6 +48,8 @@ #include "ximgproc/weighted_median_filter.hpp" #include "ximgproc/slic.hpp" #include "ximgproc/lsc.hpp" +#include "ximgproc/paillou_filter.hpp" + /** @defgroup ximgproc Extended Image Processing @{ diff --git a/modules/ximgproc/include/opencv2/ximgproc/paillou_filter.hpp b/modules/ximgproc/include/opencv2/ximgproc/paillou_filter.hpp new file mode 100644 index 000000000..e58b609d5 --- /dev/null +++ b/modules/ximgproc/include/opencv2/ximgproc/paillou_filter.hpp @@ -0,0 +1,67 @@ +/* + * By downloading, copying, installing or using the software you agree to this license. + * If you do not agree to this license, do not download, install, + * copy or use the software. + * + * + * License Agreement + * For Open Source Computer Vision Library + * (3 - clause BSD License) + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met : + * + * *Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and / or other materials provided with the distribution. + * + * * Neither the names of the copyright holders nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided by the copyright holders and contributors "as is" and + * any express or implied warranties, including, but not limited to, the implied + * warranties of merchantability and fitness for a particular purpose are disclaimed. + * In no event shall copyright holders or contributors be liable for any direct, + * indirect, incidental, special, exemplary, or consequential damages + * (including, but not limited to, procurement of substitute goods or services; + * loss of use, data, or profits; or business interruption) however caused + * and on any theory of liability, whether in contract, strict liability, + * or tort(including negligence or otherwise) arising in any way out of + * the use of this software, even if advised of the possibility of such damage. + */ + +#ifndef __OPENCV_PAILLOUFILTER_HPP__ +#define __OPENCV_PAILLOUFILTER_HPP__ +#ifdef __cplusplus + +#include + +namespace cv { +namespace ximgproc { + +//! @addtogroup ximgproc_filters +//! @{ + +/** +* @brief Applies Paillou filter to an image. +* +* For more details about this implementation, please see @cite paillou1997detecting +* +* @param op Source 8-bit or 16bit image, 1-channel or 3-channel image. +* @param _dst result CV_32F image with same numeber of channel than op. +* @param omega double see paper +* @param alpha double see paper +* +* @sa GradientPaillouX, GradientPaillouY +*/ +CV_EXPORTS void GradientPaillouY(InputArray op, OutputArray _dst, double alpha, double omega); +CV_EXPORTS void GradientPaillouX(InputArray op, OutputArray _dst, double alpha, double omega); + +} +} +#endif +#endif diff --git a/modules/ximgproc/samples/paillou_demo.cpp b/modules/ximgproc/samples/paillou_demo.cpp new file mode 100644 index 000000000..7ac98b682 --- /dev/null +++ b/modules/ximgproc/samples/paillou_demo.cpp @@ -0,0 +1,107 @@ +/* + * By downloading, copying, installing or using the software you agree to this license. + * If you do not agree to this license, do not download, install, + * copy or use the software. + * + * + * License Agreement + * For Open Source Computer Vision Library + * (3 - clause BSD License) + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met : + * + * *Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and / or other materials provided with the distribution. + * + * * Neither the names of the copyright holders nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided by the copyright holders and contributors "as is" and + * any express or implied warranties, including, but not limited to, the implied + * warranties of merchantability and fitness for a particular purpose are disclaimed. + * In no event shall copyright holders or contributors be liable for any direct, + * indirect, incidental, special, exemplary, or consequential damages + * (including, but not limited to, procurement of substitute goods or services; + * loss of use, data, or profits; or business interruption) however caused + * and on any theory of liability, whether in contract, strict liability, + * or tort(including negligence or otherwise) arising in any way out of + * the use of this software, even if advised of the possibility of such damage. + */ + +#include +#include +#include +#include +#include "opencv2/ximgproc/paillou_filter.hpp" + +using namespace cv; +using namespace cv::ximgproc; + +#include +using namespace std; + +int aa = 100, ww = 10; +Mat dx, dy; +UMat img; +const char* window_name = "Gradient Modulus"; + +static void DisplayImage(Mat x,string s) +{ + vector sx; + split(x, sx); + vector minVal(3), maxVal(3); + for (int i = 0; i < static_cast(sx.size()); i++) + { + minMaxLoc(sx[i], &minVal[i], &maxVal[i]); + } + maxVal[0] = *max_element(maxVal.begin(), maxVal.end()); + minVal[0] = *min_element(minVal.begin(), minVal.end()); + Mat uc; + x.convertTo(uc, CV_8U,255/(maxVal[0]-minVal[0]),-255*minVal[0]/(maxVal[0]-minVal[0])); + imshow(s, uc); +} + + +/** + * @function paillouFilter + * @brief Trackbar callback + */ +static void PaillouFilter(int, void*) +{ + Mat dst; + double a=aa/100.0,w=ww/100.0; + Mat rx,ry; + GradientPaillouX(img,rx,a,w); + GradientPaillouY(img,ry,a,w); + DisplayImage(rx, "Gx"); + DisplayImage(ry, "Gy"); + add(rx.mul(rx),ry.mul(ry),dst); + sqrt(dst,dst); + DisplayImage(dst, window_name ); +} + + +int main(int argc, char* argv[]) +{ + if (argc==2) + imread(argv[1]).copyTo(img); + if (img.empty()) + { + cout << "File not found or empty image\n"; + } + imshow("Original",img); + namedWindow( window_name, WINDOW_AUTOSIZE ); + + /// Create a Trackbar for user to enter threshold + createTrackbar( "a:",window_name, &aa, 400, PaillouFilter ); + createTrackbar( "w:", window_name, &ww, 400, PaillouFilter ); + PaillouFilter(0,NULL); + waitKey(); + return 0; +} \ No newline at end of file diff --git a/modules/ximgproc/src/paillou_filter.cpp b/modules/ximgproc/src/paillou_filter.cpp new file mode 100644 index 000000000..a82158051 --- /dev/null +++ b/modules/ximgproc/src/paillou_filter.cpp @@ -0,0 +1,486 @@ +#include "precomp.hpp" +#include "opencv2/highgui.hpp" +#include +#include +#include + +namespace cv { +namespace ximgproc { + +/* +If you use this code please cite this @cite paillou1997detecting +Detecting step edges in noisy SAR images: a new linear operator IEEE Transactions on Geoscience and Remote Sensing (Volume:35 , Issue: 1 ) 1997 +*/ + + +class ParallelGradientPaillouYCols: public ParallelLoopBody +{ +private: + Mat &img; + Mat &dst; + double a; + double w; + bool verbose; +public: + ParallelGradientPaillouYCols(Mat& imgSrc, Mat &d,double aa,double ww): + img(imgSrc), + dst(d), + a(aa), + w(ww), + verbose(false) + {} + void Verbose(bool b){verbose=b;} + virtual void operator()(const Range& range) const + { + CV_Assert(img.depth()==CV_8UC1 || img.depth()==CV_16SC1 || img.depth()==CV_16UC1); + CV_Assert(dst.depth()==CV_32FC1); + if (verbose) + std::cout << getThreadNum()<<"# :Start from row " << range.start << " to " << range.end-1<<" ("<img.cols)?img.rows:img.cols; + Mat matYp(1,tailleSequence,CV_64FC1), matYm(1,tailleSequence,CV_64FC1); + double *yp=matYp.ptr(0), *ym=matYm.ptr(0); + int rows=img.rows,cols=img.cols; + + // Equation 12 p193 + double b1=-2*exp(-a)*cosh(w); + double a1=2*exp(-a)*cosh(w)-exp(-2*a)-1; + double b2=exp(-2*a); + + switch(img.depth()){ + case CV_8U : + for (int j=range.start;j(0)+j; + double border=*c1; + yp[0] = *c1 ; + c1+=cols; + yp[1] = *c1 - b1*yp[0]-b2*border; + c1+=cols; + for (int i=2;i=0;i--,c1-=cols) + ym[i]=*c1-b1*ym[i+1]-b2*ym[i+2]; + // Equation 25 p193 + for (int i=0;i(0) + j; + f2 = dst.ptr(0) + j; + double border = *c1; + yp[0] = *c1; + c1 += cols; + yp[1] = *c1 - b1*yp[0] - b2*border; + c1 += cols; + for (int i = 2; i(rows - 1) + j; + border = *c1; + ym[rows - 1] = *c1; + c1 -= cols; + ym[rows - 2] = *c1 - b1*ym[rows - 1]; + c1 -= cols; + for (int i = rows - 3; i >= 0; i--, c1 -= cols) + ym[i] = *c1 - b1*ym[i + 1] - b2*ym[i + 2]; + // Equation 25 p193 + for (int i = 0; i(0) + j; + f2 = dst.ptr(0) + j; + double border = *c1; + yp[0] = *c1; + c1 += cols; + yp[1] = *c1 - b1*yp[0] - b2*border; + c1 += cols; + for (int i = 2; i(rows - 1) + j; + border = *c1; + ym[rows - 1] = *c1; + c1 -= cols; + ym[rows - 2] = *c1 - b1*ym[rows - 1]; + c1 -= cols; + for (int i = rows - 3; i >= 0; i--, c1 -= cols) + ym[i] = *c1 - b1*ym[i + 1] - b2*ym[i + 2]; + // Equation 25 p193 + for (int i = 0; iimg.cols)?img.rows:img.cols; + Mat matIym(1,tailleSequence,CV_64FC1), matIyp(1,tailleSequence,CV_64FC1); + double *iym=matIym.ptr(0), *iyp=matIyp.ptr(0); + int cols=img.cols; + + // Equation 13 p193 + double d=(1-2*exp(-a)*cosh(w)+exp(-2*a))/(2*a*exp(-a)*sinh(w)+w*(1-exp(-2*a))); + double c1=a*d; + double c2=w*d; + // Equation 12 p193 + double b1=-2*exp(-a)*cosh(w); + double b2=exp(-2*a); + // Equation 14 p193 + double a0p=c2; + double a1p=(c1*sinh(w)-c2*cosh(w))*exp(-a); + double a1m=a1p-c2*b1; + double a2m=-c2*b2; + + for (int i=range.start;i(i); + int j=0; + iyp[0] = a0p*iy0[0] ; + iyp[1] = a0p*iy0[1] + a1p*iy0[0] - b1*iyp[0]; + iy0 += 2; + for (j=2;j(i)+cols-1; + iym[cols-1] = 0; + iy0--; + iym[cols-2] = a1m*iy0[1] - b1*iym[cols-1]; + iy0--; + for (j=cols-3;j>=0;j--,iy0--) + iym[j] = a1m*iy0[1] + a2m*iy0[2] - b1*iym[j+1] - b2*iym[j+2]; + iy = dst.ptr(i); + for (j=0;jimg.cols) ? img.rows : img.cols; + Mat matIym(1,tailleSequence,CV_64FC1), matIyp(1,tailleSequence,CV_64FC1); + double *iym=matIym.ptr(0), *iyp=matIyp.ptr(0); + int rows = img.rows,cols=img.cols; + + // Equation 13 p193 + double d = (1 - 2 * exp(-a)*cosh(w) + exp(-2 * a)) / (2 * a*exp(-a)*sinh(w) + w*(1 - exp(-2 * a))); + double c1 = a*d; + double c2 = w*d; + // Equation 12 p193 + double b1 = -2 * exp(-a)*cosh(w); + double b2 = exp(-2 * a); + // Equation 14 p193 + double a0p = c2; + double a1p = (c1*sinh(w) - c2*cosh(w))*exp(-a); + double a1m = a1p - c2*b1; + double a2m = -c2*b2; + + for (int j = range.start; j(0)+j; + iyp[0] = a0p*iy0[0]; + iy0 +=cols; + iyp[1] = a0p*iy0[0] + a1p*iy0[-cols] - b1*iyp[0]; + iy0 +=cols; + for (int i = 2; i(rows-1) + j; + iym[rows - 1] = 0; + iy0 -=cols; + iym[rows - 2] = a1m*iy0[cols] - b1*iym[rows-1]; + iy0-=cols; + for (int i = rows - 3; i >= 0; i--, iy0-=cols) + iym[i] = a1m*iy0[cols] + a2m*iy0[2*cols] - b1*iym[i + 1] - b2*iym[i + 2]; + iy = dst.ptr(0)+j; + for (int i = 0; iimg.cols) ? img.rows : img.cols; + Mat matYp(1,tailleSequence,CV_64FC1), matYm(1,tailleSequence,CV_64FC1); + double *yp=matYp.ptr(0), *ym=matYm.ptr(0); + int cols = img.cols; + + // Equation 12 p193 + double b1 = -2 * exp(-a)*cosh(w); + double a1 = 2 * exp(-a)*cosh(w) - exp(-2 * a) - 1; + double b2 = exp(-2 * a); + + switch(img.depth()){ + case CV_8U : + for (int i = range.start; i= 0; j--, c1--) + ym[j] = *c1 - b1*ym[j + 1] - b2*ym[j + 2]; + // Equation 25 p193 + f2 = im1.ptr(i); + for (int j = 0; j(i); + double border = *c1; + yp[0] = *c1; + c1++; + yp[1] = *c1 - b1*yp[0] - b2*border; + c1++; + for (int j = 2; j(i)+cols-1; + border = *c1; + ym[cols - 1] = *c1; + c1--; + ym[cols - 2] = *c1 - b1*ym[cols - 1]; + c1--; + for (int j = cols - 3; j >= 0; j--, c1--) + ym[j] = *c1 - b1*ym[j + 1] - b2*ym[j + 2]; + // Equation 25 p193 + f2 = im1.ptr(i); + for (int j = 0; j(i); + f2 = im1.ptr(i); + double border = *c1; + yp[0] = *c1; + c1++; + yp[1] = *c1 - b1*yp[0] - b2*border; + c1++; + for (int j = 2; j(i) + cols - 1; + border = *c1; + ym[cols - 1] = *c1; + c1--; + ym[cols - 2] = *c1 - b1*ym[cols - 1]; + c1--; + for (int j = cols - 3; j >= 0; j--, c1--) + ym[j] = *c1 - b1*ym[j + 1] - b2*ym[j + 2]; + // Equation 25 p193 + for (int j = 0; j(i); + f2 = im1.ptr(i); + double border = *c1; + yp[0] = *c1; + c1++; + yp[1] = *c1 - b1*yp[0] - b2*border; + c1++; + for (int j = 2; j(i) + cols - 1; + border = *c1; + ym[cols - 1] = *c1; + c1--; + ym[cols - 2] = *c1 - b1*ym[cols - 1]; + c1--; + for (int j = cols - 3; j >= 0; j--, c1--) + ym[j] = *c1 - b1*ym[j + 1] - b2*ym[j + 2]; + // Equation 25 p193 + for (int j = 0; j planSrc; + split(opSrc,planSrc); + std::vector planTmp; + split(tmp,planTmp); + std::vector planDst; + split(_dst,planDst); + for (int i = 0; i < static_cast(planSrc.size()); i++) + { + if (planSrc[i].isContinuous() && planTmp[i].isContinuous() && planDst[i].isContinuous()) + { + ParallelGradientPaillouYCols x(planSrc[i],planTmp[i],alpha,omega); + parallel_for_(Range(0,opSrc.cols), x,getNumThreads()); + ParallelGradientPaillouYRows xr(planTmp[i],planDst[i],alpha,omega); + parallel_for_(Range(0,opSrc.rows), xr,getNumThreads()); + + } + else + std::cout << "PB"; + } + merge(planDst,_dst); +} + +void GradientPaillouX(InputArray _op, OutputArray _dst, double alpha, double omega) +{ + Mat tmp(_op.size(),CV_32FC(_op.channels())); + _dst.create( _op.size(),CV_32FC(tmp.channels()) ); + Mat opSrc = _op.getMat(); + std::vector planSrc; + split(opSrc,planSrc); + std::vector planTmp; + split(tmp,planTmp); + std::vector planDst; + split(_dst,planDst); + for (int i = 0; i < static_cast(planSrc.size()); i++) + { + if (planSrc[i].isContinuous() && planTmp[i].isContinuous() && planDst[i].isContinuous()) + { + ParallelGradientPaillouXRows x(planSrc[i],planTmp[i],alpha,omega); + parallel_for_(Range(0,opSrc.rows), x,getNumThreads()); + ParallelGradientPaillouXCols xr(planTmp[i],planDst[i],alpha,omega); + parallel_for_(Range(0,opSrc.cols), xr,getNumThreads()); + } + else + std::cout << "PB"; + } + merge(planDst,_dst); +} +} +} From 5a1fd4c8734d4070ba8505741a9fa7a07aec6adc Mon Sep 17 00:00:00 2001 From: vbystricky Date: Fri, 15 Jul 2016 11:25:46 +0300 Subject: [PATCH 14/15] Add methods for get/set weights of variational refiment part of DISFlow method --- modules/optflow/include/opencv2/optflow.hpp | 19 +++++++++++++++++++ modules/optflow/src/dis_flow.cpp | 20 +++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/modules/optflow/include/opencv2/optflow.hpp b/modules/optflow/include/opencv2/optflow.hpp index 23c40ddaf..2cfd3dc64 100644 --- a/modules/optflow/include/opencv2/optflow.hpp +++ b/modules/optflow/include/opencv2/optflow.hpp @@ -302,6 +302,25 @@ public: /** @copybrief getGradientDescentIterations @see getGradientDescentIterations */ CV_WRAP virtual void setVariationalRefinementIterations(int val) = 0; + /** @brief Weight of the smoothness term + @see setVariationalRefinementAlpha */ + CV_WRAP virtual float getVariationalRefinementAlpha() const = 0; + /** @copybrief getVariationalRefinementAlpha @see getVariationalRefinementAlpha */ + CV_WRAP virtual void setVariationalRefinementAlpha(float val) = 0; + + /** @brief Weight of the color constancy term + @see setVariationalRefinementDelta */ + CV_WRAP virtual float getVariationalRefinementDelta() const = 0; + /** @copybrief getVariationalRefinementDelta @see getVariationalRefinementDelta */ + CV_WRAP virtual void setVariationalRefinementDelta(float val) = 0; + + /** @brief Weight of the gradient constancy term + @see setVariationalRefinementGamma */ + CV_WRAP virtual float getVariationalRefinementGamma() const = 0; + /** @copybrief getVariationalRefinementGamma @see getVariationalRefinementGamma */ + CV_WRAP virtual void setVariationalRefinementGamma(float val) = 0; + + /** @brief Whether to use mean-normalization of patches when computing patch distance. It is turned on by default as it typically provides a noticeable quality boost because of increased robustness to illumanition variations. Turn it off if you are certain that your sequence does't contain any changes diff --git a/modules/optflow/src/dis_flow.cpp b/modules/optflow/src/dis_flow.cpp index fed97439f..15b3133e9 100644 --- a/modules/optflow/src/dis_flow.cpp +++ b/modules/optflow/src/dis_flow.cpp @@ -65,6 +65,9 @@ class DISOpticalFlowImpl : public DISOpticalFlow int patch_stride; int grad_descent_iter; int variational_refinement_iter; + float variational_refinement_alpha; + float variational_refinement_gamma; + float variational_refinement_delta; bool use_mean_normalization; bool use_spatial_propagation; @@ -84,6 +87,13 @@ class DISOpticalFlowImpl : public DISOpticalFlow void setGradientDescentIterations(int val) { grad_descent_iter = val; } int getVariationalRefinementIterations() const { return variational_refinement_iter; } void setVariationalRefinementIterations(int val) { variational_refinement_iter = val; } + float getVariationalRefinementAlpha() const { return variational_refinement_alpha; } + void setVariationalRefinementAlpha(float val) { variational_refinement_alpha = val; } + float getVariationalRefinementDelta() const { return variational_refinement_delta; } + void setVariationalRefinementDelta(float val) { variational_refinement_delta = val; } + float getVariationalRefinementGamma() const { return variational_refinement_gamma; } + void setVariationalRefinementGamma(float val) { variational_refinement_gamma = val; } + bool getUseMeanNormalization() const { return use_mean_normalization; } void setUseMeanNormalization(bool val) { use_mean_normalization = val; } bool getUseSpatialPropagation() const { return use_spatial_propagation; } @@ -161,6 +171,10 @@ DISOpticalFlowImpl::DISOpticalFlowImpl() patch_stride = 4; grad_descent_iter = 16; variational_refinement_iter = 5; + variational_refinement_alpha = 20.f; + variational_refinement_gamma = 10.f; + variational_refinement_delta = 5.f; + border_size = 16; use_mean_normalization = true; use_spatial_propagation = true; @@ -234,9 +248,9 @@ void DISOpticalFlowImpl::prepareBuffers(Mat &I0, Mat &I1) spatialGradient(I0s[i], I0xs[i], I0ys[i]); Ux[i].create(cur_rows, cur_cols); Uy[i].create(cur_rows, cur_cols); - variational_refinement_processors[i]->setAlpha(20.0f); - variational_refinement_processors[i]->setDelta(5.0f); - variational_refinement_processors[i]->setGamma(10.0f); + variational_refinement_processors[i]->setAlpha(variational_refinement_alpha); + variational_refinement_processors[i]->setDelta(variational_refinement_delta); + variational_refinement_processors[i]->setGamma(variational_refinement_gamma); variational_refinement_processors[i]->setSorIterations(5); variational_refinement_processors[i]->setFixedPointIterations(variational_refinement_iter); } From 38ece115a04bd0baf1f280c1a3f9d492abb6b800 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 5 Jul 2016 19:20:42 +0300 Subject: [PATCH 15/15] disable dnn for aarch64 platform --- modules/dnn/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt index 4e06d566e..2bdfe2902 100644 --- a/modules/dnn/CMakeLists.txt +++ b/modules/dnn/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.8) -if(APPLE_FRAMEWORK OR WINRT) +if(APPLE_FRAMEWORK OR WINRT + OR AARCH64 # protobuf doesn't know this platform +) ocv_module_disable(dnn) endif()