From ab11b17d4bd8bd263faf3dc6bba61387b76c4a1d Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 31 May 2018 15:56:29 +0300 Subject: [PATCH 01/26] experimental version++ --- modules/dnn/include/opencv2/dnn/dnn.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index 193b096be3..f65f503529 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -46,9 +46,9 @@ #include #if !defined CV_DOXYGEN && !defined CV_DNN_DONT_ADD_EXPERIMENTAL_NS -#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_v4 { +#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_v5 { #define CV__DNN_EXPERIMENTAL_NS_END } -namespace cv { namespace dnn { namespace experimental_dnn_v4 { } using namespace experimental_dnn_v4; }} +namespace cv { namespace dnn { namespace experimental_dnn_v5 { } using namespace experimental_dnn_v5; }} #else #define CV__DNN_EXPERIMENTAL_NS_BEGIN #define CV__DNN_EXPERIMENTAL_NS_END From d69a327d6da5608ca1c0545670279970de5e8df8 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 31 May 2018 16:00:53 +0300 Subject: [PATCH 02/26] OpenCV version++ OpenCV 3.4.2 --- doc/tutorials/dnn/dnn_android/dnn_android.markdown | 2 +- .../cross_referencing/tutorial_cross_referencing.markdown | 4 ++-- modules/core/include/opencv2/core/version.hpp | 4 ++-- platforms/android/build_sdk.py | 2 +- platforms/android/service/engine/AndroidManifest.xml | 4 ++-- .../engine/src/org/opencv/engine/OpenCVEngineService.java | 2 +- platforms/android/service/readme.txt | 2 +- platforms/maven/opencv-it/pom.xml | 2 +- platforms/maven/opencv/pom.xml | 2 +- platforms/maven/pom.xml | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/tutorials/dnn/dnn_android/dnn_android.markdown b/doc/tutorials/dnn/dnn_android/dnn_android.markdown index 8ddb324ee9..0fed10e487 100644 --- a/doc/tutorials/dnn/dnn_android/dnn_android.markdown +++ b/doc/tutorials/dnn/dnn_android/dnn_android.markdown @@ -12,7 +12,7 @@ Tutorial was written for the following versions of corresponding software: - Download and install Android Studio from https://developer.android.com/studio. -- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases and unpack it (for example, `opencv-3.4.1-android-sdk.zip`). +- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases and unpack it (for example, `opencv-3.4.2-android-sdk.zip`). - Download MobileNet object detection model from https://github.com/chuanqi305/MobileNet-SSD. We need a configuration file `MobileNetSSD_deploy.prototxt` and weights `MobileNetSSD_deploy.caffemodel`. diff --git a/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown b/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown index 36267cd521..ce6c868165 100644 --- a/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown +++ b/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown @@ -36,14 +36,14 @@ Open your Doxyfile using your favorite text editor and search for the key `TAGFILES`. Change it as follows: @code -TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.1 +TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.2 @endcode If you had other definitions already, you can append the line using a `\`: @code TAGFILES = ./docs/doxygen-tags/libstdc++.tag=https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen \ - ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.1 + ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.2 @endcode Doxygen can now use the information from the tag file to link to the OpenCV diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index 28cf598964..28a25eeddf 100644 --- a/modules/core/include/opencv2/core/version.hpp +++ b/modules/core/include/opencv2/core/version.hpp @@ -7,8 +7,8 @@ #define CV_VERSION_MAJOR 3 #define CV_VERSION_MINOR 4 -#define CV_VERSION_REVISION 1 -#define CV_VERSION_STATUS "-dev" +#define CV_VERSION_REVISION 2 +#define CV_VERSION_STATUS "" #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) diff --git a/platforms/android/build_sdk.py b/platforms/android/build_sdk.py index ba44ecc09e..bfd0be79f4 100755 --- a/platforms/android/build_sdk.py +++ b/platforms/android/build_sdk.py @@ -206,7 +206,7 @@ class Builder: # Add extra data apkxmldest = check_dir(os.path.join(apkdest, "res", "xml"), create=True) apklibdest = check_dir(os.path.join(apkdest, "libs", abi.name), create=True) - for ver, d in self.extra_packs + [("3.4.1", os.path.join(self.libdest, "lib"))]: + for ver, d in self.extra_packs + [("3.4.2", os.path.join(self.libdest, "lib"))]: r = ET.Element("library", attrib={"version": ver}) log.info("Adding libraries from %s", d) diff --git a/platforms/android/service/engine/AndroidManifest.xml b/platforms/android/service/engine/AndroidManifest.xml index 38ab1ea215..f094417235 100644 --- a/platforms/android/service/engine/AndroidManifest.xml +++ b/platforms/android/service/engine/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="342@ANDROID_PLATFORM_ID@" + android:versionName="3.42"> diff --git a/platforms/android/service/engine/src/org/opencv/engine/OpenCVEngineService.java b/platforms/android/service/engine/src/org/opencv/engine/OpenCVEngineService.java index 4c6b9b2be7..c2c3950e47 100644 --- a/platforms/android/service/engine/src/org/opencv/engine/OpenCVEngineService.java +++ b/platforms/android/service/engine/src/org/opencv/engine/OpenCVEngineService.java @@ -137,7 +137,7 @@ public class OpenCVEngineService extends Service { @Override public int getEngineVersion() throws RemoteException { - int version = 3410; + int version = 3420; try { version = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; } catch (NameNotFoundException e) { diff --git a/platforms/android/service/readme.txt b/platforms/android/service/readme.txt index f26b467070..45fbe43d9f 100644 --- a/platforms/android/service/readme.txt +++ b/platforms/android/service/readme.txt @@ -12,7 +12,7 @@ manually using adb tool: adb install /apk/OpenCV__Manager__.apk -Example: OpenCV_3.4.1-dev_Manager_3.41_armeabi-v7a.apk +Example: OpenCV_3.4.2-dev_Manager_3.42_armeabi-v7a.apk Use the list of platforms below to determine proper OpenCV Manager package for your device: diff --git a/platforms/maven/opencv-it/pom.xml b/platforms/maven/opencv-it/pom.xml index dcba9ceb21..6722142487 100644 --- a/platforms/maven/opencv-it/pom.xml +++ b/platforms/maven/opencv-it/pom.xml @@ -4,7 +4,7 @@ org.opencv opencv-parent - 3.4.1 + 3.4.2 org.opencv opencv-it diff --git a/platforms/maven/opencv/pom.xml b/platforms/maven/opencv/pom.xml index 46c28034c9..0599d5b8d2 100644 --- a/platforms/maven/opencv/pom.xml +++ b/platforms/maven/opencv/pom.xml @@ -4,7 +4,7 @@ org.opencv opencv-parent - 3.4.1 + 3.4.2 org.opencv opencv diff --git a/platforms/maven/pom.xml b/platforms/maven/pom.xml index 617e4260d9..f3044a8a80 100644 --- a/platforms/maven/pom.xml +++ b/platforms/maven/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.opencv opencv-parent - 3.4.1 + 3.4.2 pom OpenCV Parent POM From 49886ebae3d5be2701495442713ac34e658642cd Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 31 May 2018 16:06:01 +0300 Subject: [PATCH 03/26] OpenCV version '-openvino' --- modules/core/include/opencv2/core/version.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index 28a25eeddf..8a28faa2ca 100644 --- a/modules/core/include/opencv2/core/version.hpp +++ b/modules/core/include/opencv2/core/version.hpp @@ -8,7 +8,7 @@ #define CV_VERSION_MAJOR 3 #define CV_VERSION_MINOR 4 #define CV_VERSION_REVISION 2 -#define CV_VERSION_STATUS "" +#define CV_VERSION_STATUS "-openvino" #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) From 481af5c469eb28b07edfa73b07974df2e0d18bcd Mon Sep 17 00:00:00 2001 From: catree Date: Mon, 2 Jul 2018 14:59:00 +0200 Subject: [PATCH 04/26] Add Java and Python code for AKAZE local features matching tutorial. Fix incorrect uses of Mat.mul() in Java code. Uniform Lowe's ratio test in the code. --- .../akaze_matching/akaze_matching.markdown | 198 +++++++++++------- .../table_of_content_features2d.markdown | 2 + .../tutorial_code/features2D/AKAZE_match.cpp | 23 +- .../SURF_FLANN_matching_Demo.cpp | 2 +- .../SURF_FLANN_matching_homography_Demo.cpp | 2 +- .../ImageSegmentationDemo.java | 16 +- .../akaze_matching/AKAZEMatchDemo.java | 163 ++++++++++++++ .../SURFFLANNMatchingDemo.java | 4 +- .../SURFFLANNMatchingHomographyDemo.java | 4 +- .../photo/hdr_imaging/HDRImagingDemo.java | 7 +- .../features2D/akaze_matching/AKAZE_match.py | 81 +++++++ .../SURF_FLANN_matching_Demo.py | 2 +- .../SURF_FLANN_matching_homography_Demo.py | 2 +- 13 files changed, 405 insertions(+), 101 deletions(-) create mode 100644 samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java create mode 100644 samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py diff --git a/doc/tutorials/features2d/akaze_matching/akaze_matching.markdown b/doc/tutorials/features2d/akaze_matching/akaze_matching.markdown index b9f55d6573..d0f772439b 100644 --- a/doc/tutorials/features2d/akaze_matching/akaze_matching.markdown +++ b/doc/tutorials/features2d/akaze_matching/akaze_matching.markdown @@ -7,8 +7,7 @@ Introduction In this tutorial we will learn how to use AKAZE @cite ANB13 local features to detect and match keypoints on two images. We will find keypoints on a pair of images with given homography matrix, match them and count the - -number of inliers (i. e. matches that fit in the given homography). +number of inliers (i.e. matches that fit in the given homography). You can find expanded version of this example here: @@ -16,7 +15,7 @@ You can find expanded version of this example here: Data ---- -We are going to use images 1 and 3 from *Graffity* sequence of Oxford dataset. +We are going to use images 1 and 3 from *Graffiti* sequence of [Oxford dataset](http://www.robots.ox.ac.uk/~vgg/data/data-aff.html). ![](images/graf.png) @@ -27,107 +26,148 @@ Homography is given by a 3 by 3 matrix: 3.4663091e-04 -1.4364524e-05 1.0000000e+00 @endcode You can find the images (*graf1.png*, *graf3.png*) and homography (*H1to3p.xml*) in -*opencv/samples/cpp*. +*opencv/samples/data/*. ### Source Code -@include cpp/tutorial_code/features2D/AKAZE_match.cpp +@add_toggle_cpp +- **Downloadable code**: Click + [here](https://raw.githubusercontent.com/opencv/opencv/3.4/samples/cpp/tutorial_code/features2D/AKAZE_match.cpp) + +- **Code at glance:** + @include samples/cpp/tutorial_code/features2D/AKAZE_match.cpp +@end_toggle + +@add_toggle_java +- **Downloadable code**: Click + [here](https://raw.githubusercontent.com/opencv/opencv/3.4/samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java) + +- **Code at glance:** + @include samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java +@end_toggle + +@add_toggle_python +- **Downloadable code**: Click + [here](https://raw.githubusercontent.com/opencv/opencv/3.4/samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py) + +- **Code at glance:** + @include samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py +@end_toggle ### Explanation --# **Load images and homography** - @code{.cpp} - Mat img1 = imread("graf1.png", IMREAD_GRAYSCALE); - Mat img2 = imread("graf3.png", IMREAD_GRAYSCALE); +- **Load images and homography** - Mat homography; - FileStorage fs("H1to3p.xml", FileStorage::READ); - fs.getFirstTopLevelNode() >> homography; - @endcode - We are loading grayscale images here. Homography is stored in the xml created with FileStorage. +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/features2D/AKAZE_match.cpp load +@end_toggle --# **Detect keypoints and compute descriptors using AKAZE** - @code{.cpp} - vector kpts1, kpts2; - Mat desc1, desc2; +@add_toggle_java +@snippet samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java load +@end_toggle - AKAZE akaze; - akaze(img1, noArray(), kpts1, desc1); - akaze(img2, noArray(), kpts2, desc2); - @endcode - We create AKAZE object and use it's *operator()* functionality. Since we don't need the *mask* - parameter, *noArray()* is used. +@add_toggle_python +@snippet samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py load +@end_toggle --# **Use brute-force matcher to find 2-nn matches** - @code{.cpp} - BFMatcher matcher(NORM_HAMMING); - vector< vector > nn_matches; - matcher.knnMatch(desc1, desc2, nn_matches, 2); - @endcode - We use Hamming distance, because AKAZE uses binary descriptor by default. +We are loading grayscale images here. Homography is stored in the xml created with FileStorage. --# **Use 2-nn matches to find correct keypoint matches** - @code{.cpp} - for(size_t i = 0; i < nn_matches.size(); i++) { - DMatch first = nn_matches[i][0]; - float dist1 = nn_matches[i][0].distance; - float dist2 = nn_matches[i][1].distance; +- **Detect keypoints and compute descriptors using AKAZE** - if(dist1 < nn_match_ratio * dist2) { - matched1.push_back(kpts1[first.queryIdx]); - matched2.push_back(kpts2[first.trainIdx]); - } - } - @endcode - If the closest match is *ratio* closer than the second closest one, then the match is correct. +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/features2D/AKAZE_match.cpp AKAZE +@end_toggle --# **Check if our matches fit in the homography model** - @code{.cpp} - for(int i = 0; i < matched1.size(); i++) { - Mat col = Mat::ones(3, 1, CV_64F); - col.at(0) = matched1[i].pt.x; - col.at(1) = matched1[i].pt.y; +@add_toggle_java +@snippet samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java AKAZE +@end_toggle - col = homography * col; - col /= col.at(2); - float dist = sqrt( pow(col.at(0) - matched2[i].pt.x, 2) + - pow(col.at(1) - matched2[i].pt.y, 2)); +@add_toggle_python +@snippet samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py AKAZE +@end_toggle - if(dist < inlier_threshold) { - int new_i = inliers1.size(); - inliers1.push_back(matched1[i]); - inliers2.push_back(matched2[i]); - good_matches.push_back(DMatch(new_i, new_i, 0)); - } - } - @endcode - If the distance from first keypoint's projection to the second keypoint is less than threshold, - then it it fits in the homography. +We create AKAZE and detect and compute AKAZE keypoints and descriptors. Since we don't need the *mask* +parameter, *noArray()* is used. - We create a new set of matches for the inliers, because it is required by the drawing function. +- **Use brute-force matcher to find 2-nn matches** --# **Output results** - @code{.cpp} - Mat res; - drawMatches(img1, inliers1, img2, inliers2, good_matches, res); - imwrite("res.png", res); - ... - @endcode - Here we save the resulting image and print some statistics. +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/features2D/AKAZE_match.cpp 2-nn matching +@end_toggle -### Results +@add_toggle_java +@snippet samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java 2-nn matching +@end_toggle -Found matches -------------- +@add_toggle_python +@snippet samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py 2-nn matching +@end_toggle + +We use Hamming distance, because AKAZE uses binary descriptor by default. + +- **Use 2-nn matches and ratio criterion to find correct keypoint matches** +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/features2D/AKAZE_match.cpp ratio test filtering +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java ratio test filtering +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py ratio test filtering +@end_toggle + +If the closest match distance is significantly lower than the second closest one, then the match is correct (match is not ambiguous). + +- **Check if our matches fit in the homography model** + +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/features2D/AKAZE_match.cpp homography check +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java homography check +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py homography check +@end_toggle + +If the distance from first keypoint's projection to the second keypoint is less than threshold, +then it fits the homography model. + +We create a new set of matches for the inliers, because it is required by the drawing function. + +- **Output results** + +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/features2D/AKAZE_match.cpp draw final matches +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java draw final matches +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py draw final matches +@end_toggle + +Here we save the resulting image and print some statistics. + +Results +------- + +### Found matches ![](images/res.png) -A-KAZE Matching Results ------------------------ +Depending on your OpenCV version, you should get results coherent with: + @code{.none} Keypoints 1: 2943 Keypoints 2: 3511 Matches: 447 Inliers: 308 - Inlier Ratio: 0.689038} + Inlier Ratio: 0.689038 @endcode diff --git a/doc/tutorials/features2d/table_of_content_features2d.markdown b/doc/tutorials/features2d/table_of_content_features2d.markdown index 37e4e41a1d..1f941f9d01 100644 --- a/doc/tutorials/features2d/table_of_content_features2d.markdown +++ b/doc/tutorials/features2d/table_of_content_features2d.markdown @@ -98,6 +98,8 @@ OpenCV. - @subpage tutorial_akaze_matching + *Languages:* C++, Java, Python + *Compatibility:* \> OpenCV 3.0 *Author:* Fedor Morozov diff --git a/samples/cpp/tutorial_code/features2D/AKAZE_match.cpp b/samples/cpp/tutorial_code/features2D/AKAZE_match.cpp index 1eb1df6a10..b5b1b9229e 100755 --- a/samples/cpp/tutorial_code/features2D/AKAZE_match.cpp +++ b/samples/cpp/tutorial_code/features2D/AKAZE_match.cpp @@ -6,11 +6,12 @@ using namespace std; using namespace cv; -const float inlier_threshold = 2.5f; // Distance threshold to identify inliers +const float inlier_threshold = 2.5f; // Distance threshold to identify inliers with homography check const float nn_match_ratio = 0.8f; // Nearest neighbor matching ratio int main(int argc, char* argv[]) { + //! [load] CommandLineParser parser(argc, argv, "{@img1 | ../data/graf1.png | input image 1}" "{@img2 | ../data/graf3.png | input image 2}" @@ -21,20 +22,25 @@ int main(int argc, char* argv[]) Mat homography; FileStorage fs(parser.get("@homography"), FileStorage::READ); fs.getFirstTopLevelNode() >> homography; + //! [load] + //! [AKAZE] vector kpts1, kpts2; Mat desc1, desc2; Ptr akaze = AKAZE::create(); akaze->detectAndCompute(img1, noArray(), kpts1, desc1); akaze->detectAndCompute(img2, noArray(), kpts2, desc2); + //! [AKAZE] + //! [2-nn matching] BFMatcher matcher(NORM_HAMMING); vector< vector > nn_matches; matcher.knnMatch(desc1, desc2, nn_matches, 2); + //! [2-nn matching] - vector matched1, matched2, inliers1, inliers2; - vector good_matches; + //! [ratio test filtering] + vector matched1, matched2; for(size_t i = 0; i < nn_matches.size(); i++) { DMatch first = nn_matches[i][0]; float dist1 = nn_matches[i][0].distance; @@ -45,8 +51,12 @@ int main(int argc, char* argv[]) matched2.push_back(kpts2[first.trainIdx]); } } + //! [ratio test filtering] - for(unsigned i = 0; i < matched1.size(); i++) { + //! [homography check] + vector good_matches; + vector inliers1, inliers2; + for(size_t i = 0; i < matched1.size(); i++) { Mat col = Mat::ones(3, 1, CV_64F); col.at(0) = matched1[i].pt.x; col.at(1) = matched1[i].pt.y; @@ -63,12 +73,14 @@ int main(int argc, char* argv[]) good_matches.push_back(DMatch(new_i, new_i, 0)); } } + //! [homography check] + //! [draw final matches] Mat res; drawMatches(img1, inliers1, img2, inliers2, good_matches, res); imwrite("akaze_result.png", res); - double inlier_ratio = inliers1.size() * 1.0 / matched1.size(); + double inlier_ratio = inliers1.size() / (double) matched1.size(); cout << "A-KAZE Matching Results" << endl; cout << "*******************************" << endl; cout << "# Keypoints 1: \t" << kpts1.size() << endl; @@ -80,6 +92,7 @@ int main(int argc, char* argv[]) imshow("result", res); waitKey(); + //! [draw final matches] return 0; } diff --git a/samples/cpp/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.cpp b/samples/cpp/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.cpp index e22155f471..1724709828 100755 --- a/samples/cpp/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.cpp +++ b/samples/cpp/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.cpp @@ -46,7 +46,7 @@ int main( int argc, char* argv[] ) std::vector good_matches; for (size_t i = 0; i < knn_matches.size(); i++) { - if (knn_matches[i].size() > 1 && knn_matches[i][0].distance / knn_matches[i][1].distance <= ratio_thresh) + if (knn_matches[i][0].distance < ratio_thresh * knn_matches[i][1].distance) { good_matches.push_back(knn_matches[i][0]); } diff --git a/samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp b/samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp index 68b1d2a720..231cda887d 100755 --- a/samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp +++ b/samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp @@ -48,7 +48,7 @@ int main( int argc, char* argv[] ) std::vector good_matches; for (size_t i = 0; i < knn_matches.size(); i++) { - if (knn_matches[i].size() > 1 && knn_matches[i][0].distance / knn_matches[i][1].distance <= ratio_thresh) + if (knn_matches[i][0].distance < ratio_thresh * knn_matches[i][1].distance) { good_matches.push_back(knn_matches[i][0]); } diff --git a/samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java b/samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java index 1a26092f64..8f44a378fb 100644 --- a/samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java +++ b/samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java @@ -103,8 +103,9 @@ class ImageSegmentation { // Normalize the distance image for range = {0.0, 1.0} // so we can visualize and threshold it - Core.normalize(dist, dist, 0, 1., Core.NORM_MINMAX); - Mat distDisplayScaled = dist.mul(dist, 255); + Core.normalize(dist, dist, 0.0, 1.0, Core.NORM_MINMAX); + Mat distDisplayScaled = new Mat(); + Core.multiply(dist, new Scalar(255), distDisplayScaled); Mat distDisplay = new Mat(); distDisplayScaled.convertTo(distDisplay, CvType.CV_8U); HighGui.imshow("Distance Transform Image", distDisplay); @@ -113,14 +114,14 @@ class ImageSegmentation { //! [peaks] // Threshold to obtain the peaks // This will be the markers for the foreground objects - Imgproc.threshold(dist, dist, .4, 1., Imgproc.THRESH_BINARY); + Imgproc.threshold(dist, dist, 0.4, 1.0, Imgproc.THRESH_BINARY); // Dilate a bit the dist image Mat kernel1 = Mat.ones(3, 3, CvType.CV_8U); Imgproc.dilate(dist, dist, kernel1); Mat distDisplay2 = new Mat(); dist.convertTo(distDisplay2, CvType.CV_8U); - distDisplay2 = distDisplay2.mul(distDisplay2, 255); + Core.multiply(distDisplay2, new Scalar(255), distDisplay2); HighGui.imshow("Peaks", distDisplay2); //! [peaks] @@ -144,11 +145,14 @@ class ImageSegmentation { } // Draw the background marker - Imgproc.circle(markers, new Point(5, 5), 3, new Scalar(255, 255, 255), -1); - Mat markersScaled = markers.mul(markers, 10000); + Mat markersScaled = new Mat(); + markers.convertTo(markersScaled, CvType.CV_32F); + Core.normalize(markersScaled, markersScaled, 0.0, 255.0, Core.NORM_MINMAX); + Imgproc.circle(markersScaled, new Point(5, 5), 3, new Scalar(255, 255, 255), -1); Mat markersDisplay = new Mat(); markersScaled.convertTo(markersDisplay, CvType.CV_8U); HighGui.imshow("Markers", markersDisplay); + Imgproc.circle(markers, new Point(5, 5), 3, new Scalar(255, 255, 255), -1); //! [seeds] //! [watershed] diff --git a/samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java b/samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java new file mode 100644 index 0000000000..33e3c38bfc --- /dev/null +++ b/samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java @@ -0,0 +1,163 @@ +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.DMatch; +import org.opencv.core.KeyPoint; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDMatch; +import org.opencv.core.MatOfKeyPoint; +import org.opencv.core.Scalar; +import org.opencv.features2d.AKAZE; +import org.opencv.features2d.DescriptorMatcher; +import org.opencv.features2d.Features2d; +import org.opencv.highgui.HighGui; +import org.opencv.imgcodecs.Imgcodecs; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +class AKAZEMatch { + public void run(String[] args) { + //! [load] + String filename1 = args.length > 2 ? args[0] : "../data/graf1.png"; + String filename2 = args.length > 2 ? args[1] : "../data/graf3.png"; + String filename3 = args.length > 2 ? args[2] : "../data/H1to3p.xml"; + Mat img1 = Imgcodecs.imread(filename1, Imgcodecs.IMREAD_GRAYSCALE); + Mat img2 = Imgcodecs.imread(filename2, Imgcodecs.IMREAD_GRAYSCALE); + if (img1.empty() || img2.empty()) { + System.err.println("Cannot read images!"); + System.exit(0); + } + + File file = new File(filename3); + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder; + Document document; + Mat homography = new Mat(3, 3, CvType.CV_64F); + double[] homographyData = new double[(int) (homography.total()*homography.channels())]; + try { + documentBuilder = documentBuilderFactory.newDocumentBuilder(); + document = documentBuilder.parse(file); + String homographyStr = document.getElementsByTagName("data").item(0).getTextContent(); + String[] splited = homographyStr.split("\\s+"); + int idx = 0; + for (String s : splited) { + if (!s.isEmpty()) { + homographyData[idx] = Double.parseDouble(s); + idx++; + } + } + } catch (ParserConfigurationException e) { + e.printStackTrace(); + System.exit(0); + } catch (SAXException e) { + e.printStackTrace(); + System.exit(0); + } catch (IOException e) { + e.printStackTrace(); + System.exit(0); + } + homography.put(0, 0, homographyData); + //! [load] + + //! [AKAZE] + AKAZE akaze = AKAZE.create(); + MatOfKeyPoint kpts1 = new MatOfKeyPoint(), kpts2 = new MatOfKeyPoint(); + Mat desc1 = new Mat(), desc2 = new Mat(); + akaze.detectAndCompute(img1, new Mat(), kpts1, desc1); + akaze.detectAndCompute(img2, new Mat(), kpts2, desc2); + //! [AKAZE] + + //! [2-nn matching] + DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); + List knnMatches = new ArrayList<>(); + matcher.knnMatch(desc1, desc2, knnMatches, 2); + //! [2-nn matching] + + //! [ratio test filtering] + float ratioThreshold = 0.8f; // Nearest neighbor matching ratio + List listOfMatched1 = new ArrayList<>(); + List listOfMatched2 = new ArrayList<>(); + List listOfKeypoints1 = kpts1.toList(); + List listOfKeypoints2 = kpts2.toList(); + for (int i = 0; i < knnMatches.size(); i++) { + DMatch[] matches = knnMatches.get(i).toArray(); + float dist1 = matches[0].distance; + float dist2 = matches[1].distance; + if (dist1 < ratioThreshold * dist2) { + listOfMatched1.add(listOfKeypoints1.get(matches[0].queryIdx)); + listOfMatched2.add(listOfKeypoints2.get(matches[0].trainIdx)); + } + } + //! [ratio test filtering] + + //! [homography check] + double inlierThreshold = 2.5; // Distance threshold to identify inliers with homography check + List listOfInliers1 = new ArrayList<>(); + List listOfInliers2 = new ArrayList<>(); + List listOfGoodMatches = new ArrayList<>(); + for (int i = 0; i < listOfMatched1.size(); i++) { + Mat col = new Mat(3, 1, CvType.CV_64F); + double[] colData = new double[(int) (col.total() * col.channels())]; + colData[0] = listOfMatched1.get(i).pt.x; + colData[1] = listOfMatched1.get(i).pt.y; + colData[2] = 1.0; + col.put(0, 0, colData); + + Mat colRes = new Mat(); + Core.gemm(homography, col, 1.0, new Mat(), 0.0, colRes); + colRes.get(0, 0, colData); + Core.multiply(colRes, new Scalar(1.0 / colData[2]), col); + col.get(0, 0, colData); + + double dist = Math.sqrt(Math.pow(colData[0] - listOfMatched2.get(i).pt.x, 2) + + Math.pow(colData[1] - listOfMatched2.get(i).pt.y, 2)); + + if (dist < inlierThreshold) { + listOfGoodMatches.add(new DMatch(listOfInliers1.size(), listOfInliers2.size(), 0)); + listOfInliers1.add(listOfMatched1.get(i)); + listOfInliers2.add(listOfMatched2.get(i)); + } + } + //! [homography check] + + //! [draw final matches] + Mat res = new Mat(); + MatOfKeyPoint inliers1 = new MatOfKeyPoint(listOfInliers1.toArray(new KeyPoint[listOfInliers1.size()])); + MatOfKeyPoint inliers2 = new MatOfKeyPoint(listOfInliers2.toArray(new KeyPoint[listOfInliers2.size()])); + MatOfDMatch goodMatches = new MatOfDMatch(listOfGoodMatches.toArray(new DMatch[listOfGoodMatches.size()])); + Features2d.drawMatches(img1, inliers1, img2, inliers2, goodMatches, res); + Imgcodecs.imwrite("akaze_result.png", res); + + double inlierRatio = listOfInliers1.size() / (double) listOfMatched1.size(); + System.out.println("A-KAZE Matching Results"); + System.out.println("*******************************"); + System.out.println("# Keypoints 1: \t" + listOfKeypoints1.size()); + System.out.println("# Keypoints 2: \t" + listOfKeypoints2.size()); + System.out.println("# Matches: \t" + listOfMatched1.size()); + System.out.println("# Inliers: \t" + listOfInliers1.size()); + System.out.println("# Inliers Ratio: \t" + inlierRatio); + + HighGui.imshow("result", res); + HighGui.waitKey(); + //! [draw final matches] + + System.exit(0); + } +} + +public class AKAZEMatchDemo { + public static void main(String[] args) { + // Load the native OpenCV library + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + + new AKAZEMatch().run(args); + } +} diff --git a/samples/java/tutorial_code/features2D/feature_flann_matcher/SURFFLANNMatchingDemo.java b/samples/java/tutorial_code/features2D/feature_flann_matcher/SURFFLANNMatchingDemo.java index e02af9cadb..365c0c7ee2 100644 --- a/samples/java/tutorial_code/features2D/feature_flann_matcher/SURFFLANNMatchingDemo.java +++ b/samples/java/tutorial_code/features2D/feature_flann_matcher/SURFFLANNMatchingDemo.java @@ -42,12 +42,12 @@ class SURFFLANNMatching { matcher.knnMatch(descriptors1, descriptors2, knnMatches, 2); //-- Filter matches using the Lowe's ratio test - float ratio_thresh = 0.7f; + float ratioThresh = 0.7f; List listOfGoodMatches = new ArrayList<>(); for (int i = 0; i < knnMatches.size(); i++) { if (knnMatches.get(i).rows() > 1) { DMatch[] matches = knnMatches.get(i).toArray(); - if (matches[0].distance / matches[1].distance <= ratio_thresh) { + if (matches[0].distance < ratioThresh * matches[1].distance) { listOfGoodMatches.add(matches[0]); } } diff --git a/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java b/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java index 1a5cbe7f30..44367dd966 100644 --- a/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java +++ b/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java @@ -48,12 +48,12 @@ class SURFFLANNMatchingHomography { matcher.knnMatch(descriptorsObject, descriptorsScene, knnMatches, 2); //-- Filter matches using the Lowe's ratio test - float ratio_thresh = 0.75f; + float ratioThresh = 0.75f; List listOfGoodMatches = new ArrayList<>(); for (int i = 0; i < knnMatches.size(); i++) { if (knnMatches.get(i).rows() > 1) { DMatch[] matches = knnMatches.get(i).toArray(); - if (matches[0].distance / matches[1].distance <= ratio_thresh) { + if (matches[0].distance < ratioThresh * matches[1].distance) { listOfGoodMatches.add(matches[0]); } } diff --git a/samples/java/tutorial_code/photo/hdr_imaging/HDRImagingDemo.java b/samples/java/tutorial_code/photo/hdr_imaging/HDRImagingDemo.java index 9d96d85f2f..ea201399b8 100644 --- a/samples/java/tutorial_code/photo/hdr_imaging/HDRImagingDemo.java +++ b/samples/java/tutorial_code/photo/hdr_imaging/HDRImagingDemo.java @@ -7,6 +7,7 @@ import java.util.List; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; +import org.opencv.core.Scalar; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.photo.CalibrateDebevec; import org.opencv.photo.MergeDebevec; @@ -70,7 +71,7 @@ class HDRImaging { //! [Tonemap HDR image] Mat ldr = new Mat(); - TonemapDurand tonemap = Photo.createTonemapDurand(); + TonemapDurand tonemap = Photo.createTonemapDurand(2.2f, 4.0f, 1.0f, 2.0f, 2.0f); tonemap.process(hdr, ldr); //! [Tonemap HDR image] @@ -81,8 +82,8 @@ class HDRImaging { //! [Perform exposure fusion] //! [Write results] - fusion = fusion.mul(fusion, 255); - ldr = ldr.mul(ldr, 255); + Core.multiply(fusion, new Scalar(255,255,255), fusion); + Core.multiply(ldr, new Scalar(255,255,255), ldr); Imgcodecs.imwrite("fusion.png", fusion); Imgcodecs.imwrite("ldr.png", ldr); Imgcodecs.imwrite("hdr.hdr", hdr); diff --git a/samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py b/samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py new file mode 100644 index 0000000000..0d9818a3c1 --- /dev/null +++ b/samples/python/tutorial_code/features2D/akaze_matching/AKAZE_match.py @@ -0,0 +1,81 @@ +from __future__ import print_function +import cv2 as cv +import numpy as np +import argparse +from math import sqrt + +## [load] +parser = argparse.ArgumentParser(description='Code for AKAZE local features matching tutorial.') +parser.add_argument('--input1', help='Path to input image 1.', default='../data/graf1.png') +parser.add_argument('--input2', help='Path to input image 2.', default='../data/graf3.png') +parser.add_argument('--homography', help='Path to the homography matrix.', default='../data/H1to3p.xml') +args = parser.parse_args() + +img1 = cv.imread(args.input1, cv.IMREAD_GRAYSCALE) +img2 = cv.imread(args.input2, cv.IMREAD_GRAYSCALE) +if img1 is None or img2 is None: + print('Could not open or find the images!') + exit(0) + +fs = cv.FileStorage(args.homography, cv.FILE_STORAGE_READ) +homography = fs.getFirstTopLevelNode().mat() +## [load] + +## [AKAZE] +akaze = cv.AKAZE_create() +kpts1, desc1 = akaze.detectAndCompute(img1, None) +kpts2, desc2 = akaze.detectAndCompute(img2, None) +## [AKAZE] + +## [2-nn matching] +matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE_HAMMING) +nn_matches = matcher.knnMatch(desc1, desc2, 2) +## [2-nn matching] + +## [ratio test filtering] +matched1 = [] +matched2 = [] +nn_match_ratio = 0.8 # Nearest neighbor matching ratio +for m, n in nn_matches: + if m.distance < nn_match_ratio * n.distance: + matched1.append(kpts1[m.queryIdx]) + matched2.append(kpts2[m.trainIdx]) +## [ratio test filtering] + +## [homography check] +inliers1 = [] +inliers2 = [] +good_matches = [] +inlier_threshold = 2.5 # Distance threshold to identify inliers with homography check +for i, m in enumerate(matched1): + col = np.ones((3,1), dtype=np.float64) + col[0:2,0] = m.pt + + col = np.dot(homography, col) + col /= col[2,0] + dist = sqrt(pow(col[0,0] - matched2[i].pt[0], 2) +\ + pow(col[1,0] - matched2[i].pt[1], 2)) + + if dist < inlier_threshold: + good_matches.append(cv.DMatch(len(inliers1), len(inliers2), 0)) + inliers1.append(matched1[i]) + inliers2.append(matched2[i]) +## [homography check] + +## [draw final matches] +res = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8) +cv.drawMatches(img1, inliers1, img2, inliers2, good_matches, res) +cv.imwrite("akaze_result.png", res) + +inlier_ratio = len(inliers1) / float(len(matched1)) +print('A-KAZE Matching Results') +print('*******************************') +print('# Keypoints 1: \t', len(kpts1)) +print('# Keypoints 2: \t', len(kpts2)) +print('# Matches: \t', len(matched1)) +print('# Inliers: \t', len(inliers1)) +print('# Inliers Ratio: \t', inlier_ratio) + +cv.imshow('result', res) +cv.waitKey() +## [draw final matches] diff --git a/samples/python/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.py b/samples/python/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.py index 1a65d324fd..fbe35675d7 100644 --- a/samples/python/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.py +++ b/samples/python/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.py @@ -29,7 +29,7 @@ knn_matches = matcher.knnMatch(descriptors1, descriptors2, 2) ratio_thresh = 0.7 good_matches = [] for m,n in knn_matches: - if m.distance / n.distance <= ratio_thresh: + if m.distance < ratio_thresh * n.distance: good_matches.append(m) #-- Draw matches diff --git a/samples/python/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.py b/samples/python/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.py index 5172b4f303..8ef500e7af 100644 --- a/samples/python/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.py +++ b/samples/python/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.py @@ -29,7 +29,7 @@ knn_matches = matcher.knnMatch(descriptors_obj, descriptors_scene, 2) ratio_thresh = 0.75 good_matches = [] for m,n in knn_matches: - if m.distance / n.distance <= ratio_thresh: + if m.distance < ratio_thresh * n.distance: good_matches.append(m) #-- Draw matches From 7ed5d85f2557917daedceb90f8673df55f8dfeb9 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Tue, 3 Jul 2018 08:26:43 +0300 Subject: [PATCH 05/26] Add Reshape layer tests --- modules/dnn/src/layers/reshape_layer.cpp | 11 ++++++- modules/dnn/src/tensorflow/tf_importer.cpp | 38 ++++++++++++++-------- modules/dnn/src/torch/torch_importer.cpp | 4 +-- modules/dnn/test/test_layers.cpp | 7 ++++ modules/dnn/test/test_tf_importer.cpp | 1 + 5 files changed, 44 insertions(+), 17 deletions(-) diff --git a/modules/dnn/src/layers/reshape_layer.cpp b/modules/dnn/src/layers/reshape_layer.cpp index 65a81c7820..c9e632dd29 100644 --- a/modules/dnn/src/layers/reshape_layer.cpp +++ b/modules/dnn/src/layers/reshape_layer.cpp @@ -82,17 +82,26 @@ static void computeShapeByReshapeMask(const MatShape &srcShape, { if (matched) { - if (i == 0 || total(srcShape, i, srcRange.end) != maskTotal) + if (total(srcShape, i, srcRange.end) != maskTotal) { srcRange.start = i + 1; break; } + else if (i == 0) + { + srcRange.start = 0; + break; + } } else { matched = total(srcShape, i, srcRange.end) == maskTotal; } } + while (total(srcShape, srcRange.start, srcRange.end) != maskTotal && srcRange.start > 0) + { + srcRange.start -= 1; + } CV_Assert(total(srcShape, srcRange.start, srcRange.end) == maskTotal); } diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index 1faa7fba4d..7d7d300386 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -262,6 +262,18 @@ static int getDataLayout(const tensorflow::NodeDef& layer) return DATA_LAYOUT_UNKNOWN; } +static inline std::string getNodeName(const std::string& tensorName) +{ + return tensorName.substr(0, tensorName.rfind(':')); +} + +static inline int getDataLayout(const std::string& layerName, + const std::map& data_layouts) +{ + std::map::const_iterator it = data_layouts.find(getNodeName(layerName)); + return it != data_layouts.end() ? it->second : DATA_LAYOUT_UNKNOWN; +} + void setStrides(LayerParams &layerParams, const tensorflow::NodeDef &layer) { if (hasLayerAttr(layer, "strides")) @@ -604,11 +616,6 @@ static void addConstNodes(tensorflow::GraphDef& net, std::map& cons } } -static inline std::string getNodeName(const std::string& tensorName) -{ - return tensorName.substr(0, tensorName.rfind(':')); -} - // If all inputs of specific layer have the same data layout we can say that // this layer's output has this data layout too. Returns DATA_LAYOUT_UNKNOWN otherwise. static int predictOutputDataLayout(const tensorflow::GraphDef& net, @@ -830,7 +837,8 @@ void TFImporter::populateNet(Net dstNet) // one input only connect(layer_id, dstNet, parsePin(input), id, 0); - if (data_layouts[name] == DATA_LAYOUT_UNKNOWN) + + if (getDataLayout(name, data_layouts) == DATA_LAYOUT_UNKNOWN) data_layouts[name] = DATA_LAYOUT_NHWC; } else if (type == "BiasAdd" || type == "Add") @@ -956,7 +964,8 @@ void TFImporter::populateNet(Net dstNet) Pin inpId = parsePin(layer.input(0)); Mat newShape = getTensorContent(getConstBlob(layer, value_id, 1)); - if (newShape.total() != 4 && data_layouts[layer.input(0)] == DATA_LAYOUT_NHWC) + int inpLayout = getDataLayout(layer.input(0), data_layouts); + if (newShape.total() != 4 && inpLayout == DATA_LAYOUT_NHWC) { LayerParams permLP; int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC. @@ -969,7 +978,7 @@ void TFImporter::populateNet(Net dstNet) connect(layer_id, dstNet, inpId, permId, 0); inpId = Pin(permName); } - else if (newShape.total() == 4 && data_layouts[layer.input(0)] == DATA_LAYOUT_NHWC) + else if (newShape.total() == 4 && inpLayout == DATA_LAYOUT_NHWC) { // NHWC->NCHW std::swap(*newShape.ptr(0, 2), *newShape.ptr(0, 3)); @@ -987,7 +996,7 @@ void TFImporter::populateNet(Net dstNet) else if (type == "Flatten" || type == "Squeeze") { Pin inpId = parsePin(layer.input(0)); - int inpLayout = data_layouts[layer.input(0)]; + int inpLayout = getDataLayout(layer.input(0), data_layouts); if (type == "Squeeze") { CV_Assert(hasLayerAttr(layer, "squeeze_dims")); @@ -1032,7 +1041,8 @@ void TFImporter::populateNet(Net dstNet) { // Only NHWC <-> NCHW permutations are allowed. OpenCV is always // keep NCHW layout this way. - if (data_layouts[layer.input(0)] == DATA_LAYOUT_NHWC) + int inpLayout = getDataLayout(layer.input(0), data_layouts); + if (inpLayout == DATA_LAYOUT_NHWC) { if (permData[0] == 0 && permData[1] == 3 && permData[2] == 1 && permData[3] == 2) { @@ -1049,7 +1059,7 @@ void TFImporter::populateNet(Net dstNet) else CV_Error(Error::StsParseError, "Only NHWC <-> NCHW permutations are allowed."); } - else if (data_layouts[layer.input(0)] == DATA_LAYOUT_NCHW) + else if (inpLayout == DATA_LAYOUT_NCHW) { if (permData[0] == 0 && permData[1] == 2 && permData[2] == 3 && permData[3] == 1) { @@ -1112,7 +1122,7 @@ void TFImporter::populateNet(Net dstNet) int axisId = (type == "Concat" ? 0 : layer.input_size() - 1); int axis = getConstBlob(layer, value_id, axisId).int_val().Get(0); - if (data_layouts[name] == DATA_LAYOUT_NHWC) + if (getDataLayout(name, data_layouts) == DATA_LAYOUT_NHWC) axis = toNCHW(axis); layerParams.set("axis", axis); @@ -1197,7 +1207,7 @@ void TFImporter::populateNet(Net dstNet) CV_Assert(!begins.empty(), !sizes.empty(), begins.type() == CV_32SC1, sizes.type() == CV_32SC1); - if (begins.total() == 4 && data_layouts[name] == DATA_LAYOUT_NHWC) + if (begins.total() == 4 && getDataLayout(name, data_layouts) == DATA_LAYOUT_NHWC) { // Swap NHWC parameters' order to NCHW. std::swap(*begins.ptr(0, 2), *begins.ptr(0, 3)); @@ -1597,7 +1607,7 @@ void TFImporter::populateNet(Net dstNet) CV_Assert(reductionIndices.type() == CV_32SC1); const int numAxes = reductionIndices.total(); - if (data_layouts[name] == DATA_LAYOUT_NHWC) + if (getDataLayout(name, data_layouts) == DATA_LAYOUT_NHWC) for (int i = 0; i < numAxes; ++i) reductionIndices.at(i) = toNCHW(reductionIndices.at(i)); diff --git a/modules/dnn/src/torch/torch_importer.cpp b/modules/dnn/src/torch/torch_importer.cpp index 3607e6c08e..88779e9977 100644 --- a/modules/dnn/src/torch/torch_importer.cpp +++ b/modules/dnn/src/torch/torch_importer.cpp @@ -592,8 +592,8 @@ struct TorchImporter DictValue dimParam = scalarParams.get("size"); layerParams.set("dim", dimParam); - if (scalarParams.has("batchMode") && scalarParams.get("batchMode")) - layerParams.set("axis", 1); + int axis = (int)scalarParams.get("batchMode", true); + layerParams.set("axis", axis); curModule->modules.push_back(newModule); } diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index 720447afb9..963206bd73 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -201,6 +201,13 @@ TEST(Layer_Test_Reshape, Accuracy) testReshape(MatShape(inp, inp + 4), MatShape(out, out + 2), 0, -1, MatShape(mask, mask + 2)); } + { + int inp[] = {1, 2, 3}; + int out[] = {3, 1, 2}; + int mask[] = {3, 1, 2}; + testReshape(MatShape(inp, inp + 3), MatShape(out, out + 3), 0, -1, + MatShape(mask, mask + 3)); + } } TEST(Layer_Test_BatchNorm, Accuracy) diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index d4ffc94399..408782233c 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -198,6 +198,7 @@ TEST_P(Test_TensorFlow_layers, reshape) { int targetId = GetParam(); runTensorFlowNet("shift_reshape_no_reorder", targetId); + runTensorFlowNet("reshape_no_reorder", targetId); runTensorFlowNet("reshape_reduce", targetId); runTensorFlowNet("flatten", targetId, true); runTensorFlowNet("unfused_flatten", targetId); From 0c4328fbf3da0da57a91b2133578c5100370b867 Mon Sep 17 00:00:00 2001 From: ilovezfs Date: Tue, 3 Jul 2018 06:31:39 +0000 Subject: [PATCH 06/26] Python 3.7 compatability The result of PyUnicode_AsUTF8() is now of type const char * rather of char *. --- modules/python/src2/cv2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index e16fcbacf2..5a6bf7ef62 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -916,7 +916,7 @@ bool pyopencv_to(PyObject* obj, String& value, const char* name) (void)name; if(!obj || obj == Py_None) return true; - char* str = PyString_AsString(obj); + const char* str = PyString_AsString(obj); if(!str) return false; value = String(str); From b3578710cf918a9cd865d4bf137422f7e4ac3418 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 3 Jul 2018 15:28:55 +0300 Subject: [PATCH 07/26] videoio(MSMF): fix 32-bit build crash --- modules/videoio/src/cap_msmf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp index 61240bdf3c..beed7420d3 100644 --- a/modules/videoio/src/cap_msmf.cpp +++ b/modules/videoio/src/cap_msmf.cpp @@ -86,7 +86,7 @@ // MFCreateDXGIDeviceManager() is available since Win8 only. // To avoid OpenCV loading failure on Win7 use dynamic detection of this symbol. // Details: https://github.com/opencv/opencv/issues/11858 -typedef HRESULT (*FN_MFCreateDXGIDeviceManager)(UINT *resetToken, IMFDXGIDeviceManager **ppDeviceManager); +typedef HRESULT (WINAPI *FN_MFCreateDXGIDeviceManager)(UINT *resetToken, IMFDXGIDeviceManager **ppDeviceManager); static bool pMFCreateDXGIDeviceManager_initialized = false; static FN_MFCreateDXGIDeviceManager pMFCreateDXGIDeviceManager = NULL; static void init_MFCreateDXGIDeviceManager() From 203f95d3be6a490cc24ffe2933b3723d3ea718e9 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 3 Jul 2018 15:44:53 +0300 Subject: [PATCH 08/26] samples: videocapture_camera use VideoCapture with 0 index Not all backends support -1 index. --- samples/cpp/videocapture_camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/cpp/videocapture_camera.cpp b/samples/cpp/videocapture_camera.cpp index 4d5a341657..ca39b2093b 100644 --- a/samples/cpp/videocapture_camera.cpp +++ b/samples/cpp/videocapture_camera.cpp @@ -11,7 +11,7 @@ int main(int, char**) { Mat frame; cout << "Opening camera..." << endl; - VideoCapture capture(-1); // open the first available camera + VideoCapture capture(0); // open the first camera if (!capture.isOpened()) { cerr << "ERROR: Can't initialize camera capture" << endl; From f545aee66d76adb635c950f60c5df5593e197744 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 3 Jul 2018 15:54:45 +0300 Subject: [PATCH 09/26] videoio(VFW): lower priority (after DSHOW) --- modules/videoio/src/videoio_registry.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/videoio/src/videoio_registry.cpp b/modules/videoio/src/videoio_registry.cpp index 1f990b11c0..9f0abc512b 100644 --- a/modules/videoio/src/videoio_registry.cpp +++ b/modules/videoio/src/videoio_registry.cpp @@ -75,12 +75,12 @@ static const struct VideoBackendInfo builtin_backends[] = #ifdef HAVE_MSMF DECLARE_BACKEND(CAP_MSMF, "MSMF", MODE_CAPTURE_ALL | MODE_WRITER), #endif -#ifdef HAVE_VFW - DECLARE_BACKEND(CAP_VFW, "VFW", MODE_CAPTURE_ALL | MODE_WRITER), -#endif #ifdef HAVE_DSHOW DECLARE_BACKEND(CAP_DSHOW, "DSHOW", MODE_CAPTURE_BY_INDEX), #endif +#ifdef HAVE_VFW + DECLARE_BACKEND(CAP_VFW, "VFW", MODE_CAPTURE_ALL | MODE_WRITER), +#endif // Linux, some Unix #if defined HAVE_CAMV4L2 From 36288eebe7a75a047dd983cb60ff1c1ab705f602 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Wed, 4 Jul 2018 11:53:24 +0300 Subject: [PATCH 10/26] Nearest neighbor resize from Keras --- .../src/tensorflow/tf_graph_simplifier.cpp | 45 +++++++++++++++++++ modules/dnn/test/test_tf_importer.cpp | 1 + 2 files changed, 46 insertions(+) diff --git a/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp b/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp index a537358a1f..3d8a97f240 100644 --- a/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp +++ b/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp @@ -571,6 +571,50 @@ public: } }; +// In case of resizing by factor. +class UpsamplingKerasSubgraph : public Subgraph +{ +public: + UpsamplingKerasSubgraph() + { + int input = addNodeToMatch(""); + int shape = addNodeToMatch("Shape", input); + int stack = addNodeToMatch("Const"); + int stack_1 = addNodeToMatch("Const"); + int stack_2 = addNodeToMatch("Const"); + int strided_slice = addNodeToMatch("StridedSlice", shape, stack, stack_1, stack_2); + int factors = addNodeToMatch("Const"); + int mul = addNodeToMatch("Mul", strided_slice, factors); + addNodeToMatch("ResizeNearestNeighbor", input, mul); + setFusedNode("ResizeNearestNeighbor", input, factors); + } + + virtual void finalize(tensorflow::GraphDef& net, tensorflow::NodeDef* fusedNode, + std::vector& inputNodes) CV_OVERRIDE + { + Mat factorsMat = getTensorContent(inputNodes[1]->attr().at("value").tensor()); + CV_Assert(factorsMat.total() == 2, factorsMat.type() == CV_32SC1); + + // Height scale factor + tensorflow::TensorProto* factorY = inputNodes[1]->mutable_attr()->at("value").mutable_tensor(); + factorY->clear_int_val(); + factorY->clear_tensor_content(); + factorY->add_int_val(factorsMat.at(0, 0)); + + // Width scale factor. + tensorflow::NodeDef* factorXNode = net.add_node(); + factorXNode->set_op("Const"); + factorXNode->set_name(fusedNode->name() + "/factor_y"); + + tensorflow::AttrValue factorX; + factorX.mutable_tensor()->set_dtype(tensorflow::DT_INT32); + factorX.mutable_tensor()->add_int_val(factorsMat.at(0, 1)); + factorXNode->mutable_attr()->insert(MapPair("value", factorX)); + + fusedNode->add_input(factorXNode->name()); + } +}; + void simplifySubgraphs(tensorflow::GraphDef& net) { std::vector > subgraphs; @@ -585,6 +629,7 @@ void simplifySubgraphs(tensorflow::GraphDef& net) subgraphs.push_back(Ptr(new DeconvolutionValidKerasSubgraph())); subgraphs.push_back(Ptr(new DeconvolutionSameKerasSubgraph())); subgraphs.push_back(Ptr(new ResizeBilinearSubgraph())); + subgraphs.push_back(Ptr(new UpsamplingKerasSubgraph())); int numNodes = net.node_size(); std::vector matchedNodesIds; diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index d4ffc94399..bb60d46d6f 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -402,6 +402,7 @@ TEST(Test_TensorFlow, split) TEST(Test_TensorFlow, resize_nearest_neighbor) { runTensorFlowNet("resize_nearest_neighbor"); + runTensorFlowNet("keras_upsampling2d"); } TEST(Test_TensorFlow, slice) From f25a01bb5a3a1ca4950f0d496fc70164b0627e59 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Wed, 4 Jul 2018 15:50:39 +0300 Subject: [PATCH 11/26] Disable fusion to output layers --- modules/dnn/src/dnn.cpp | 7 ++++--- modules/dnn/test/test_layers.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 0177b31a47..bffcee39d3 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -2075,7 +2075,8 @@ Mat Net::forward(const String& outputName) if (layerName.empty()) layerName = getLayerNames().back(); - impl->setUpNet(); + std::vector pins(1, impl->getPinByAlias(layerName)); + impl->setUpNet(pins); impl->forwardToLayer(impl->getLayerData(layerName)); return impl->getBlob(layerName); @@ -2085,13 +2086,13 @@ void Net::forward(OutputArrayOfArrays outputBlobs, const String& outputName) { CV_TRACE_FUNCTION(); - impl->setUpNet(); - String layerName = outputName; if (layerName.empty()) layerName = getLayerNames().back(); + std::vector pins(1, impl->getPinByAlias(layerName)); + impl->setUpNet(pins); impl->forwardToLayer(impl->getLayerData(layerName)); LayerPin pin = impl->getPinByAlias(layerName); diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index 963206bd73..fd52cae73e 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -1240,4 +1240,36 @@ INSTANTIATE_TEST_CASE_P(/**/, Layer_Test_ShuffleChannel, Combine( /*group*/ Values(1, 2, 3, 6) )); +// Check if relu is not fused to convolution if we requested it's output +TEST(Layer_Test_Convolution, relu_fusion) +{ + Net net; + { + LayerParams lp; + lp.set("kernel_size", 1); + lp.set("num_output", 1); + lp.set("bias_term", false); + lp.type = "Convolution"; + lp.name = "testConv"; + + int weightsShape[] = {1, 1, 1, 1}; + Mat weights(4, &weightsShape[0], CV_32F, Scalar(1)); + lp.blobs.push_back(weights); + net.addLayerToPrev(lp.name, lp.type, lp); + } + { + LayerParams lp; + lp.type = "ReLU"; + lp.name = "testReLU"; + net.addLayerToPrev(lp.name, lp.type, lp); + } + int sz[] = {1, 1, 2, 3}; + Mat input(4, &sz[0], CV_32F); + randu(input, -1.0, -0.1); + net.setInput(input); + net.setPreferableBackend(DNN_BACKEND_OPENCV); + Mat output = net.forward("testConv"); + normAssert(input, output); +} + }} // namespace From 135ea264ef3ab940feb72ff13bfb944ba1ee4bf8 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 8 Jun 2018 05:55:57 +0000 Subject: [PATCH 12/26] core: align cv::AutoBuffer API with std::vector/std::array - added .data() methods - added operator[] (int i) - extend checks support to generic and debug-only cases - deprecate existed operator* () --- modules/core/include/opencv2/core/check.hpp | 26 +++++++++++++++++-- modules/core/include/opencv2/core/utility.hpp | 24 ++++++++++------- modules/core/src/check.cpp | 8 ++++++ 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/modules/core/include/opencv2/core/check.hpp b/modules/core/include/opencv2/core/check.hpp index 92d114dfab..bf441383e8 100644 --- a/modules/core/include/opencv2/core/check.hpp +++ b/modules/core/include/opencv2/core/check.hpp @@ -66,6 +66,7 @@ struct CheckContext { { CV__CHECK_FUNCTION, CV__CHECK_FILENAME, __LINE__, testOp, message, p1_str, p2_str } CV_EXPORTS void CV_NORETURN check_failed_auto(const int v1, const int v2, const CheckContext& ctx); +CV_EXPORTS void CV_NORETURN check_failed_auto(const size_t v1, const size_t v2, const CheckContext& ctx); CV_EXPORTS void CV_NORETURN check_failed_auto(const float v1, const float v2, const CheckContext& ctx); CV_EXPORTS void CV_NORETURN check_failed_auto(const double v1, const double v2, const CheckContext& ctx); CV_EXPORTS void CV_NORETURN check_failed_MatDepth(const int v1, const int v2, const CheckContext& ctx); @@ -73,6 +74,7 @@ CV_EXPORTS void CV_NORETURN check_failed_MatType(const int v1, const int v2, con CV_EXPORTS void CV_NORETURN check_failed_MatChannels(const int v1, const int v2, const CheckContext& ctx); CV_EXPORTS void CV_NORETURN check_failed_auto(const int v, const CheckContext& ctx); +CV_EXPORTS void CV_NORETURN check_failed_auto(const size_t v, const CheckContext& ctx); CV_EXPORTS void CV_NORETURN check_failed_auto(const float v, const CheckContext& ctx); CV_EXPORTS void CV_NORETURN check_failed_auto(const double v, const CheckContext& ctx); CV_EXPORTS void CV_NORETURN check_failed_MatDepth(const int v, const CheckContext& ctx); @@ -120,15 +122,35 @@ CV_EXPORTS void CV_NORETURN check_failed_MatChannels(const int v, const CheckCon #define CV_CheckChannelsEQ(c1, c2, msg) CV__CHECK(_, EQ, MatChannels, c1, c2, #c1, #c2, msg) - /// Example: type == CV_8UC1 || type == CV_8UC3 #define CV_CheckType(t, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, MatType, t, (test_expr), #t, #test_expr, msg) /// Example: depth == CV_32F || depth == CV_64F #define CV_CheckDepth(t, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, MatDepth, t, (test_expr), #t, #test_expr, msg) +/// Example: v == A || v == B +#define CV_Check(v, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, auto, v, (test_expr), #v, #test_expr, msg) + /// Some complex conditions: CV_Check(src2, src2.empty() || (src2.type() == src1.type() && src2.size() == src1.size()), "src2 should have same size/type as src1") -// TODO define pretty-printers: #define CV_Check(v, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, auto, v, (test_expr), #v, #test_expr, msg) +// TODO define pretty-printers + +#ifndef NDEBUG +#define CV_DbgCheck(v, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, auto, v, (test_expr), #v, #test_expr, msg) +#define CV_DbgCheckEQ(v1, v2, msg) CV__CHECK(_, EQ, auto, v1, v2, #v1, #v2, msg) +#define CV_DbgCheckNE(v1, v2, msg) CV__CHECK(_, NE, auto, v1, v2, #v1, #v2, msg) +#define CV_DbgCheckLE(v1, v2, msg) CV__CHECK(_, LE, auto, v1, v2, #v1, #v2, msg) +#define CV_DbgCheckLT(v1, v2, msg) CV__CHECK(_, LT, auto, v1, v2, #v1, #v2, msg) +#define CV_DbgCheckGE(v1, v2, msg) CV__CHECK(_, GE, auto, v1, v2, #v1, #v2, msg) +#define CV_DbgCheckGT(v1, v2, msg) CV__CHECK(_, GT, auto, v1, v2, #v1, #v2, msg) +#else +#define CV_DbgCheck(v, test_expr, msg) do { } while (0) +#define CV_DbgCheckEQ(v1, v2, msg) do { } while (0) +#define CV_DbgCheckNE(v1, v2, msg) do { } while (0) +#define CV_DbgCheckLE(v1, v2, msg) do { } while (0) +#define CV_DbgCheckLT(v1, v2, msg) do { } while (0) +#define CV_DbgCheckGE(v1, v2, msg) do { } while (0) +#define CV_DbgCheckGT(v1, v2, msg) do { } while (0) +#endif } // namespace diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index 8ee82b82cf..4888eae5cf 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -143,9 +143,21 @@ public: //! returns the current buffer size size_t size() const; //! returns pointer to the real buffer, stack-allocated or heap-allocated - operator _Tp* (); + inline _Tp* data() { return ptr; } //! returns read-only pointer to the real buffer, stack-allocated or heap-allocated - operator const _Tp* () const; + inline const _Tp* data() const { return ptr; } + +#if !defined(OPENCV_DISABLE_DEPRECATED_COMPATIBILITY) // use to .data() calls instead + //! returns pointer to the real buffer, stack-allocated or heap-allocated + operator _Tp* () { return ptr; } + //! returns read-only pointer to the real buffer, stack-allocated or heap-allocated + operator const _Tp* () const { return ptr; } +#else + //! returns a reference to the element at specified location. No bounds checking is performed in Release builds. + inline _Tp& operator[] (size_t i) { CV_DbgCheckLT(i, sz, "out of range"); return ptr[i]; } + //! returns a reference to the element at specified location. No bounds checking is performed in Release builds. + inline const _Tp& operator[] (size_t i) const { CV_DbgCheckLT(i, sz, "out of range"); return ptr[i]; } +#endif protected: //! pointer to the real buffer, can point to buf if the buffer is small enough @@ -1064,14 +1076,6 @@ template inline size_t AutoBuffer<_Tp, fixed_size>::size() const { return sz; } -template inline -AutoBuffer<_Tp, fixed_size>::operator _Tp* () -{ return ptr; } - -template inline -AutoBuffer<_Tp, fixed_size>::operator const _Tp* () const -{ return ptr; } - template<> inline std::string CommandLineParser::get(int index, bool space_delete) const { return get(index, space_delete); diff --git a/modules/core/src/check.cpp b/modules/core/src/check.cpp index 966d2cad20..ebaa294385 100644 --- a/modules/core/src/check.cpp +++ b/modules/core/src/check.cpp @@ -101,6 +101,10 @@ void check_failed_auto(const int v1, const int v2, const CheckContext& ctx) { check_failed_auto_(v1, v2, ctx); } +void check_failed_auto(const size_t v1, const size_t v2, const CheckContext& ctx) +{ + check_failed_auto_(v1, v2, ctx); +} void check_failed_auto(const float v1, const float v2, const CheckContext& ctx) { check_failed_auto_(v1, v2, ctx); @@ -147,6 +151,10 @@ void check_failed_auto(const int v, const CheckContext& ctx) { check_failed_auto_(v, ctx); } +void check_failed_auto(const size_t v, const CheckContext& ctx) +{ + check_failed_auto_(v, ctx); +} void check_failed_auto(const float v, const CheckContext& ctx) { check_failed_auto_(v, ctx); From b09a4a98d44adbe30031c59efa4d5487f3aa3118 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sun, 10 Jun 2018 22:42:00 +0000 Subject: [PATCH 13/26] opencv: Use cv::AutoBuffer<>::data() --- apps/createsamples/utility.cpp | 2 +- apps/traincascade/HOGfeatures.cpp | 4 +- apps/traincascade/boost.cpp | 12 ++-- apps/traincascade/old_ml_boost.cpp | 22 +++---- apps/traincascade/old_ml_tree.cpp | 48 +++++++-------- modules/calib3d/src/calibinit.cpp | 2 +- modules/calib3d/src/ptsetreg.cpp | 2 +- modules/calib3d/src/stereosgbm.cpp | 2 +- modules/core/include/opencv2/core/cvdef.h | 1 + modules/core/src/arithm.cpp | 14 ++--- modules/core/src/batch_distance.cpp | 2 +- modules/core/src/channels.cpp | 6 +- modules/core/src/conjugate_gradient.cpp | 2 +- modules/core/src/copy.cpp | 12 ++-- modules/core/src/dxt.cpp | 60 +++++++++---------- modules/core/src/kmeans.cpp | 6 +- modules/core/src/lapack.cpp | 22 +++---- modules/core/src/mathfuncs.cpp | 8 +-- modules/core/src/matmul.cpp | 33 +++++----- modules/core/src/matrix.cpp | 4 +- modules/core/src/matrix_c.cpp | 2 +- modules/core/src/matrix_decomp.cpp | 2 +- modules/core/src/matrix_operations.cpp | 17 +++--- modules/core/src/mean.cpp | 4 +- modules/core/src/merge.cpp | 2 +- modules/core/src/ocl.cpp | 38 ++++++------ modules/core/src/persistence_cpp.cpp | 4 +- modules/core/src/rand.cpp | 8 +-- modules/core/src/split.cpp | 2 +- modules/core/src/sum.cpp | 2 +- modules/core/src/system.cpp | 4 +- modules/core/src/umatrix.cpp | 4 +- modules/core/src/utils/filesystem.cpp | 8 +-- modules/core/test/test_rand.cpp | 6 +- modules/dnn/src/layers/convolution_layer.cpp | 2 +- .../dnn/src/layers/fully_connected_layer.cpp | 2 +- modules/dnn/src/layers/lrn_layer.cpp | 2 +- modules/dnn/src/torch/torch_importer.cpp | 6 +- modules/features2d/src/fast.cpp | 2 +- modules/features2d/src/orb.cpp | 2 +- .../include/opencv2/flann/kmeans_index.h | 8 +-- modules/imgcodecs/src/grfmt_bmp.cpp | 2 +- modules/imgcodecs/src/grfmt_exr.cpp | 2 +- modules/imgcodecs/src/grfmt_jpeg.cpp | 2 +- modules/imgcodecs/src/grfmt_pam.cpp | 11 +--- modules/imgcodecs/src/grfmt_png.cpp | 4 +- modules/imgcodecs/src/grfmt_pxm.cpp | 8 +-- modules/imgcodecs/src/grfmt_sunras.cpp | 2 +- modules/imgcodecs/src/grfmt_tiff.cpp | 4 +- modules/imgproc/src/approx.cpp | 26 ++++---- modules/imgproc/src/canny.cpp | 8 +-- modules/imgproc/src/clahe.cpp | 2 +- modules/imgproc/src/color_lab.cpp | 2 +- modules/imgproc/src/convhull.cpp | 6 +- modules/imgproc/src/corner.cpp | 2 +- modules/imgproc/src/demosaicing.cpp | 2 +- modules/imgproc/src/distransform.cpp | 6 +- modules/imgproc/src/drawing.cpp | 8 +-- modules/imgproc/src/emd.cpp | 2 +- modules/imgproc/src/filter.cpp | 2 +- modules/imgproc/src/geometry.cpp | 2 +- modules/imgproc/src/hough.cpp | 12 ++-- modules/imgproc/src/imgwarp.cpp | 2 +- modules/imgproc/src/linefit.cpp | 4 +- modules/imgproc/src/phasecorr.cpp | 2 +- modules/imgproc/src/pyramids.cpp | 8 +-- modules/imgproc/src/resize.cpp | 42 ++++++------- modules/imgproc/src/rotcalipers.cpp | 2 +- modules/imgproc/src/shapedescr.cpp | 2 +- modules/imgproc/src/smooth.cpp | 4 +- modules/imgproc/src/sumpixels.cpp | 2 +- modules/imgproc/test/test_convhull.cpp | 2 +- modules/ml/src/ann_mlp.cpp | 4 +- modules/ml/src/boost.cpp | 2 +- modules/ml/src/data.cpp | 2 +- modules/ml/src/kdtree.cpp | 6 +- modules/ml/src/knearest.cpp | 2 +- modules/ml/src/nbayes.cpp | 4 +- modules/ml/src/svm.cpp | 4 +- modules/ml/src/tree.cpp | 24 ++++---- modules/objdetect/src/cascadedetect.cpp | 2 +- modules/objdetect/src/hog.cpp | 6 +- modules/objdetect/test/test_cascadeandhog.cpp | 4 +- modules/python/src2/cv2.cpp | 2 +- modules/ts/src/ts_perf.cpp | 2 +- modules/video/src/bgfg_gaussmix2.cpp | 2 +- modules/video/src/lkpyramid.cpp | 6 +- modules/video/src/optflowgf.cpp | 14 ++--- modules/videoio/src/cap_mfx_common.cpp | 2 +- modules/videoio/src/cap_msmf.cpp | 8 +-- 90 files changed, 333 insertions(+), 339 deletions(-) diff --git a/apps/createsamples/utility.cpp b/apps/createsamples/utility.cpp index 9d59284d3d..bae9a9acac 100644 --- a/apps/createsamples/utility.cpp +++ b/apps/createsamples/utility.cpp @@ -1372,7 +1372,7 @@ int icvGetTraininDataFromVec( Mat& img, CvVecFile& userdata ) size_t elements_read = fread( &tmp, sizeof( tmp ), 1, userdata.input ); CV_Assert(elements_read == 1); - elements_read = fread( vector, sizeof( short ), userdata.vecsize, userdata.input ); + elements_read = fread(vector.data(), sizeof(short), userdata.vecsize, userdata.input); CV_Assert(elements_read == (size_t)userdata.vecsize); if( feof( userdata.input ) || userdata.last++ >= userdata.count ) diff --git a/apps/traincascade/HOGfeatures.cpp b/apps/traincascade/HOGfeatures.cpp index 908c87bdd9..0707f936d5 100644 --- a/apps/traincascade/HOGfeatures.cpp +++ b/apps/traincascade/HOGfeatures.cpp @@ -165,7 +165,7 @@ void CvHOGEvaluator::integralHistogram(const Mat &img, vector &histogram, M Mat qangle(gradSize, CV_8U); AutoBuffer mapbuf(gradSize.width + gradSize.height + 4); - int* xmap = (int*)mapbuf + 1; + int* xmap = mapbuf.data() + 1; int* ymap = xmap + gradSize.width + 2; const int borderType = (int)BORDER_REPLICATE; @@ -177,7 +177,7 @@ void CvHOGEvaluator::integralHistogram(const Mat &img, vector &histogram, M int width = gradSize.width; AutoBuffer _dbuf(width*4); - float* dbuf = _dbuf; + float* dbuf = _dbuf.data(); Mat Dx(1, width, CV_32F, dbuf); Mat Dy(1, width, CV_32F, dbuf + width); Mat Mag(1, width, CV_32F, dbuf + width*2); diff --git a/apps/traincascade/boost.cpp b/apps/traincascade/boost.cpp index 7b1f1fcb9e..993d6885fd 100644 --- a/apps/traincascade/boost.cpp +++ b/apps/traincascade/boost.cpp @@ -383,7 +383,7 @@ CvDTreeNode* CvCascadeBoostTrainData::subsample_data( const CvMat* _subsample_id int ci = get_var_type(vi); CV_Assert( ci < 0 ); - int *src_idx_buf = (int*)(uchar*)inn_buf; + int *src_idx_buf = (int*)inn_buf.data(); float *src_val_buf = (float*)(src_idx_buf + sample_count); int* sample_indices_buf = (int*)(src_val_buf + sample_count); const int* src_idx = 0; @@ -423,7 +423,7 @@ CvDTreeNode* CvCascadeBoostTrainData::subsample_data( const CvMat* _subsample_id } // subsample cv_lables - const int* src_lbls = get_cv_labels(data_root, (int*)(uchar*)inn_buf); + const int* src_lbls = get_cv_labels(data_root, (int*)inn_buf.data()); if (is_buf_16u) { unsigned short* udst = (unsigned short*)(buf->data.s + root->buf_idx*get_length_subbuf() + @@ -440,7 +440,7 @@ CvDTreeNode* CvCascadeBoostTrainData::subsample_data( const CvMat* _subsample_id } // subsample sample_indices - const int* sample_idx_src = get_sample_indices(data_root, (int*)(uchar*)inn_buf); + const int* sample_idx_src = get_sample_indices(data_root, (int*)inn_buf.data()); if (is_buf_16u) { unsigned short* sample_idx_dst = (unsigned short*)(buf->data.s + root->buf_idx*get_length_subbuf() + @@ -815,7 +815,7 @@ struct FeatureIdxOnlyPrecalc : ParallelLoopBody void operator()( const Range& range ) const { cv::AutoBuffer valCache(sample_count); - float* valCachePtr = (float*)valCache; + float* valCachePtr = valCache.data(); for ( int fi = range.start; fi < range.end; fi++) { for( int si = 0; si < sample_count; si++ ) @@ -1084,7 +1084,7 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node ) CvMat* buf = data->buf; size_t length_buf_row = data->get_length_subbuf(); cv::AutoBuffer inn_buf(n*(3*sizeof(int)+sizeof(float))); - int* tempBuf = (int*)(uchar*)inn_buf; + int* tempBuf = (int*)inn_buf.data(); bool splitInputData; complete_node_dir(node); @@ -1398,7 +1398,7 @@ void CvCascadeBoost::update_weights( CvBoostTree* tree ) int inn_buf_size = ((params.boost_type == LOGIT) || (params.boost_type == GENTLE) ? n*sizeof(int) : 0) + ( !tree ? n*sizeof(int) : 0 ); cv::AutoBuffer inn_buf(inn_buf_size); - uchar* cur_inn_buf_pos = (uchar*)inn_buf; + uchar* cur_inn_buf_pos = inn_buf.data(); if ( (params.boost_type == LOGIT) || (params.boost_type == GENTLE) ) { step = CV_IS_MAT_CONT(data->responses_copy->type) ? diff --git a/apps/traincascade/old_ml_boost.cpp b/apps/traincascade/old_ml_boost.cpp index fae3d60806..c887c77b92 100644 --- a/apps/traincascade/old_ml_boost.cpp +++ b/apps/traincascade/old_ml_boost.cpp @@ -168,7 +168,7 @@ CvBoostTree::try_split_node( CvDTreeNode* node ) // store the responses for the corresponding training samples double* weak_eval = ensemble->get_weak_response()->data.db; cv::AutoBuffer inn_buf(node->sample_count); - const int* labels = data->get_cv_labels( node, (int*)inn_buf ); + const int* labels = data->get_cv_labels(node, inn_buf.data()); int i, count = node->sample_count; double value = node->value; @@ -191,7 +191,7 @@ CvBoostTree::calc_node_dir( CvDTreeNode* node ) if( data->get_var_type(vi) >= 0 ) // split on categorical var { cv::AutoBuffer inn_buf(n); - const int* cat_labels = data->get_cat_var_data( node, vi, (int*)inn_buf ); + const int* cat_labels = data->get_cat_var_data(node, vi, inn_buf.data()); const int* subset = node->split->subset; double sum = 0, sum_abs = 0; @@ -210,7 +210,7 @@ CvBoostTree::calc_node_dir( CvDTreeNode* node ) else // split on ordered var { cv::AutoBuffer inn_buf(2*n*sizeof(int)+n*sizeof(float)); - float* values_buf = (float*)(uchar*)inn_buf; + float* values_buf = (float*)inn_buf.data(); int* sorted_indices_buf = (int*)(values_buf + n); int* sample_indices_buf = sorted_indices_buf + n; const float* values = 0; @@ -260,7 +260,7 @@ CvBoostTree::find_split_ord_class( CvDTreeNode* node, int vi, float init_quality cv::AutoBuffer inn_buf; if( !_ext_buf ) inn_buf.allocate(n*(3*sizeof(int)+sizeof(float))); - uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf; + uchar* ext_buf = _ext_buf ? _ext_buf : inn_buf.data(); float* values_buf = (float*)ext_buf; int* sorted_indices_buf = (int*)(values_buf + n); int* sample_indices_buf = sorted_indices_buf + n; @@ -369,7 +369,7 @@ CvBoostTree::find_split_cat_class( CvDTreeNode* node, int vi, float init_quality cv::AutoBuffer inn_buf((2*mi+3)*sizeof(double) + mi*sizeof(double*)); if( !_ext_buf) inn_buf.allocate( base_size + 2*n*sizeof(int) ); - uchar* base_buf = (uchar*)inn_buf; + uchar* base_buf = inn_buf.data(); uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size; int* cat_labels_buf = (int*)ext_buf; @@ -490,7 +490,7 @@ CvBoostTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init_quality, cv::AutoBuffer inn_buf; if( !_ext_buf ) inn_buf.allocate(2*n*(sizeof(int)+sizeof(float))); - uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf; + uchar* ext_buf = _ext_buf ? _ext_buf : inn_buf.data(); float* values_buf = (float*)ext_buf; int* indices_buf = (int*)(values_buf + n); @@ -559,7 +559,7 @@ CvBoostTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init_quality, cv::AutoBuffer inn_buf(base_size); if( !_ext_buf ) inn_buf.allocate(base_size + n*(2*sizeof(int) + sizeof(float))); - uchar* base_buf = (uchar*)inn_buf; + uchar* base_buf = inn_buf.data(); uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size; int* cat_labels_buf = (int*)ext_buf; @@ -652,7 +652,7 @@ CvBoostTree::find_surrogate_split_ord( CvDTreeNode* node, int vi, uchar* _ext_bu cv::AutoBuffer inn_buf; if( !_ext_buf ) inn_buf.allocate(n*(2*sizeof(int)+sizeof(float))); - uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf; + uchar* ext_buf = _ext_buf ? _ext_buf : inn_buf.data(); float* values_buf = (float*)ext_buf; int* indices_buf = (int*)(values_buf + n); int* sample_indices_buf = indices_buf + n; @@ -733,7 +733,7 @@ CvBoostTree::find_surrogate_split_cat( CvDTreeNode* node, int vi, uchar* _ext_bu cv::AutoBuffer inn_buf(base_size); if( !_ext_buf ) inn_buf.allocate(base_size + n*sizeof(int)); - uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf; + uchar* ext_buf = _ext_buf ? _ext_buf : inn_buf.data(); int* cat_labels_buf = (int*)ext_buf; const int* cat_labels = data->get_cat_var_data(node, vi, cat_labels_buf); @@ -797,7 +797,7 @@ CvBoostTree::calc_node_value( CvDTreeNode* node ) int i, n = node->sample_count; const double* weights = ensemble->get_weights()->data.db; cv::AutoBuffer inn_buf(n*(sizeof(int) + ( data->is_classifier ? sizeof(int) : sizeof(int) + sizeof(float)))); - int* labels_buf = (int*)(uchar*)inn_buf; + int* labels_buf = (int*)inn_buf.data(); const int* labels = data->get_cv_labels(node, labels_buf); double* subtree_weights = ensemble->get_subtree_weights()->data.db; double rcw[2] = {0,0}; @@ -1147,7 +1147,7 @@ CvBoost::update_weights( CvBoostTree* tree ) _buf_size += data->get_length_subbuf()*(sizeof(float)+sizeof(uchar)); } inn_buf.allocate(_buf_size); - uchar* cur_buf_pos = (uchar*)inn_buf; + uchar* cur_buf_pos = inn_buf.data(); if ( (params.boost_type == LOGIT) || (params.boost_type == GENTLE) ) { diff --git a/apps/traincascade/old_ml_tree.cpp b/apps/traincascade/old_ml_tree.cpp index 832330d24f..ed6b6eed45 100644 --- a/apps/traincascade/old_ml_tree.cpp +++ b/apps/traincascade/old_ml_tree.cpp @@ -780,7 +780,7 @@ CvDTreeNode* CvDTreeTrainData::subsample_data( const CvMat* _subsample_idx ) if( ci >= 0 || vi >= var_count ) { int num_valid = 0; - const int* src = CvDTreeTrainData::get_cat_var_data( data_root, vi, (int*)(uchar*)inn_buf ); + const int* src = CvDTreeTrainData::get_cat_var_data(data_root, vi, (int*)inn_buf.data()); if (is_buf_16u) { @@ -810,7 +810,7 @@ CvDTreeNode* CvDTreeTrainData::subsample_data( const CvMat* _subsample_idx ) } else { - int *src_idx_buf = (int*)(uchar*)inn_buf; + int *src_idx_buf = (int*)inn_buf.data(); float *src_val_buf = (float*)(src_idx_buf + sample_count); int* sample_indices_buf = (int*)(src_val_buf + sample_count); const int* src_idx = 0; @@ -870,7 +870,7 @@ CvDTreeNode* CvDTreeTrainData::subsample_data( const CvMat* _subsample_idx ) } } // sample indices subsampling - const int* sample_idx_src = get_sample_indices(data_root, (int*)(uchar*)inn_buf); + const int* sample_idx_src = get_sample_indices(data_root, (int*)inn_buf.data()); if (is_buf_16u) { unsigned short* sample_idx_dst = (unsigned short*)(buf->data.s + root->buf_idx*get_length_subbuf() + @@ -943,7 +943,7 @@ void CvDTreeTrainData::get_vectors( const CvMat* _subsample_idx, { float* dst = values + vi; uchar* m = missing ? missing + vi : 0; - const int* src = get_cat_var_data(data_root, vi, (int*)(uchar*)inn_buf); + const int* src = get_cat_var_data(data_root, vi, (int*)inn_buf.data()); for( i = 0; i < count; i++, dst += var_count ) { @@ -962,7 +962,7 @@ void CvDTreeTrainData::get_vectors( const CvMat* _subsample_idx, float* dst = values + vi; uchar* m = missing ? missing + vi : 0; int count1 = data_root->get_num_valid(vi); - float *src_val_buf = (float*)(uchar*)inn_buf; + float *src_val_buf = (float*)inn_buf.data(); int* src_idx_buf = (int*)(src_val_buf + sample_count); int* sample_indices_buf = src_idx_buf + sample_count; const float *src_val = 0; @@ -999,7 +999,7 @@ void CvDTreeTrainData::get_vectors( const CvMat* _subsample_idx, { if( is_classifier ) { - const int* src = get_class_labels(data_root, (int*)(uchar*)inn_buf); + const int* src = get_class_labels(data_root, (int*)inn_buf.data()); for( i = 0; i < count; i++ ) { int idx = sidx ? sidx[i] : i; @@ -1010,7 +1010,7 @@ void CvDTreeTrainData::get_vectors( const CvMat* _subsample_idx, } else { - float* val_buf = (float*)(uchar*)inn_buf; + float* val_buf = (float*)inn_buf.data(); int* sample_idx_buf = (int*)(val_buf + sample_count); const float* _values = get_ord_responses(data_root, val_buf, sample_idx_buf); for( i = 0; i < count; i++ ) @@ -1780,7 +1780,7 @@ double CvDTree::calc_node_dir( CvDTreeNode* node ) if( data->get_var_type(vi) >= 0 ) // split on categorical var { cv::AutoBuffer inn_buf(n*(!data->have_priors ? 1 : 2)); - int* labels_buf = (int*)inn_buf; + int* labels_buf = inn_buf.data(); const int* labels = data->get_cat_var_data( node, vi, labels_buf ); const int* subset = node->split->subset; if( !data->have_priors ) @@ -1824,7 +1824,7 @@ double CvDTree::calc_node_dir( CvDTreeNode* node ) int split_point = node->split->ord.split_point; int n1 = node->get_num_valid(vi); cv::AutoBuffer inn_buf(n*(sizeof(int)*(data->have_priors ? 3 : 2) + sizeof(float))); - float* val_buf = (float*)(uchar*)inn_buf; + float* val_buf = (float*)inn_buf.data(); int* sorted_buf = (int*)(val_buf + n); int* sample_idx_buf = sorted_buf + n; const float* val = 0; @@ -1929,16 +1929,16 @@ void DTreeBestSplitFinder::operator()(const BlockedRange& range) if( data->is_classifier ) { if( ci >= 0 ) - res = tree->find_split_cat_class( node, vi, bestSplit->quality, split, (uchar*)inn_buf ); + res = tree->find_split_cat_class( node, vi, bestSplit->quality, split, inn_buf.data() ); else - res = tree->find_split_ord_class( node, vi, bestSplit->quality, split, (uchar*)inn_buf ); + res = tree->find_split_ord_class( node, vi, bestSplit->quality, split, inn_buf.data() ); } else { if( ci >= 0 ) - res = tree->find_split_cat_reg( node, vi, bestSplit->quality, split, (uchar*)inn_buf ); + res = tree->find_split_cat_reg( node, vi, bestSplit->quality, split, inn_buf.data() ); else - res = tree->find_split_ord_reg( node, vi, bestSplit->quality, split, (uchar*)inn_buf ); + res = tree->find_split_ord_reg( node, vi, bestSplit->quality, split, inn_buf.data() ); } if( res && bestSplit->quality < split->quality ) @@ -1982,7 +1982,7 @@ CvDTreeSplit* CvDTree::find_split_ord_class( CvDTreeNode* node, int vi, cv::AutoBuffer inn_buf(base_size); if( !_ext_buf ) inn_buf.allocate(base_size + n*(3*sizeof(int)+sizeof(float))); - uchar* base_buf = (uchar*)inn_buf; + uchar* base_buf = inn_buf.data(); uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size; float* values_buf = (float*)ext_buf; int* sorted_indices_buf = (int*)(values_buf + n); @@ -2096,7 +2096,7 @@ void CvDTree::cluster_categories( const int* vectors, int n, int m, int iters = 0, max_iters = 100; int i, j, idx; cv::AutoBuffer buf(n + k); - double *v_weights = buf, *c_weights = buf + n; + double *v_weights = buf.data(), *c_weights = buf.data() + n; bool modified = true; RNG* r = data->rng; @@ -2201,7 +2201,7 @@ CvDTreeSplit* CvDTree::find_split_cat_class( CvDTreeNode* node, int vi, float in cv::AutoBuffer inn_buf(base_size); if( !_ext_buf ) inn_buf.allocate(base_size + 2*n*sizeof(int)); - uchar* base_buf = (uchar*)inn_buf; + uchar* base_buf = inn_buf.data(); uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size; int* lc = (int*)base_buf; @@ -2383,7 +2383,7 @@ CvDTreeSplit* CvDTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init cv::AutoBuffer inn_buf; if( !_ext_buf ) inn_buf.allocate(2*n*(sizeof(int) + sizeof(float))); - uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf; + uchar* ext_buf = _ext_buf ? _ext_buf : inn_buf.data(); float* values_buf = (float*)ext_buf; int* sorted_indices_buf = (int*)(values_buf + n); int* sample_indices_buf = sorted_indices_buf + n; @@ -2443,7 +2443,7 @@ CvDTreeSplit* CvDTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init cv::AutoBuffer inn_buf(base_size); if( !_ext_buf ) inn_buf.allocate(base_size + n*(2*sizeof(int) + sizeof(float))); - uchar* base_buf = (uchar*)inn_buf; + uchar* base_buf = inn_buf.data(); uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size; int* labels_buf = (int*)ext_buf; const int* labels = data->get_cat_var_data(node, vi, labels_buf); @@ -2534,7 +2534,7 @@ CvDTreeSplit* CvDTree::find_surrogate_split_ord( CvDTreeNode* node, int vi, ucha cv::AutoBuffer inn_buf; if( !_ext_buf ) inn_buf.allocate( n*(sizeof(int)*(data->have_priors ? 3 : 2) + sizeof(float)) ); - uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf; + uchar* ext_buf = _ext_buf ? _ext_buf : inn_buf.data(); float* values_buf = (float*)ext_buf; int* sorted_indices_buf = (int*)(values_buf + n); int* sample_indices_buf = sorted_indices_buf + n; @@ -2658,7 +2658,7 @@ CvDTreeSplit* CvDTree::find_surrogate_split_cat( CvDTreeNode* node, int vi, ucha cv::AutoBuffer inn_buf(base_size); if( !_ext_buf ) inn_buf.allocate(base_size + n*(sizeof(int) + (data->have_priors ? sizeof(int) : 0))); - uchar* base_buf = (uchar*)inn_buf; + uchar* base_buf = inn_buf.data(); uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size; int* labels_buf = (int*)ext_buf; @@ -2758,7 +2758,7 @@ void CvDTree::calc_node_value( CvDTreeNode* node ) int base_size = data->is_classifier ? m*cv_n*sizeof(int) : 2*cv_n*sizeof(double)+cv_n*sizeof(int); int ext_size = n*(sizeof(int) + (data->is_classifier ? sizeof(int) : sizeof(int)+sizeof(float))); cv::AutoBuffer inn_buf(base_size + ext_size); - uchar* base_buf = (uchar*)inn_buf; + uchar* base_buf = inn_buf.data(); uchar* ext_buf = base_buf + base_size; int* cv_labels_buf = (int*)ext_buf; @@ -2961,7 +2961,7 @@ void CvDTree::complete_node_dir( CvDTreeNode* node ) if( data->get_var_type(vi) >= 0 ) // split on categorical var { - int* labels_buf = (int*)(uchar*)inn_buf; + int* labels_buf = (int*)inn_buf.data(); const int* labels = data->get_cat_var_data(node, vi, labels_buf); const int* subset = split->subset; @@ -2980,7 +2980,7 @@ void CvDTree::complete_node_dir( CvDTreeNode* node ) } else // split on ordered var { - float* values_buf = (float*)(uchar*)inn_buf; + float* values_buf = (float*)inn_buf.data(); int* sorted_indices_buf = (int*)(values_buf + n); int* sample_indices_buf = sorted_indices_buf + n; const float* values = 0; @@ -3042,7 +3042,7 @@ void CvDTree::split_node_data( CvDTreeNode* node ) CvMat* buf = data->buf; size_t length_buf_row = data->get_length_subbuf(); cv::AutoBuffer inn_buf(n*(3*sizeof(int) + sizeof(float))); - int* temp_buf = (int*)(uchar*)inn_buf; + int* temp_buf = (int*)inn_buf.data(); complete_node_dir(node); diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index 7eade39b40..feaaf4a73a 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -1264,7 +1264,7 @@ icvCleanFoundConnectedQuads( int quad_count, CvCBQuad **quad_group, CvSize patte // get bounding rectangle CvPoint2D32f temp = centers[skip]; // temporarily make index 'skip' the same as centers[skip] = center; // pattern center (so it is not counted for convex hull) - CvMat pointMat = cvMat(1, quad_count, CV_32FC2, centers); + CvMat pointMat = cvMat(1, quad_count, CV_32FC2, centers.data()); CvSeq *hull = cvConvexHull2( &pointMat, temp_storage, CV_CLOCKWISE, 1 ); centers[skip] = temp; double hull_area = fabs(cvContourArea(hull, CV_WHOLE_SEQ)); diff --git a/modules/calib3d/src/ptsetreg.cpp b/modules/calib3d/src/ptsetreg.cpp index 1ed98756ec..fdf2776bf0 100644 --- a/modules/calib3d/src/ptsetreg.cpp +++ b/modules/calib3d/src/ptsetreg.cpp @@ -104,7 +104,7 @@ public: int maxAttempts=1000 ) const { cv::AutoBuffer _idx(modelPoints); - int* idx = _idx; + int* idx = _idx.data(); int i = 0, j, k, iters = 0; int d1 = m1.channels() > 1 ? m1.channels() : m1.cols; int d2 = m2.channels() > 1 ? m2.channels() : m2.cols; diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index b6489bf0e2..374d7353d9 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -2451,7 +2451,7 @@ void cv::validateDisparity( InputOutputArray _disp, InputArray _cost, int minDis int minD = minDisparity, maxD = minDisparity + numberOfDisparities; int x, minX1 = std::max(maxD, 0), maxX1 = cols + std::min(minD, 0); AutoBuffer _disp2buf(cols*2); - int* disp2buf = _disp2buf; + int* disp2buf = _disp2buf.data(); int* disp2cost = disp2buf + cols; const int DISP_SHIFT = 4, DISP_SCALE = 1 << DISP_SHIFT; int INVALID_DISP = minD - 1, INVALID_DISP_SCALED = INVALID_DISP*DISP_SCALE; diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 4ab72b34cc..6959c6fa52 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -255,6 +255,7 @@ Cv64suf; #ifdef __OPENCV_BUILD # define DISABLE_OPENCV_24_COMPATIBILITY +# define OPENCV_DISABLE_DEPRECATED_COMPATIBILITY #endif #ifdef CVAPI_EXPORTS diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index dbbe6895ed..5ea596ffc6 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -282,7 +282,7 @@ static void binary_op( InputArray _src1, InputArray _src2, OutputArray _dst, { blocksize = std::min(blocksize, blocksize0); _buf.allocate(blocksize*esz); - maskbuf = _buf; + maskbuf = _buf.data(); } for( size_t i = 0; i < it.nplanes; i++, ++it ) @@ -312,7 +312,7 @@ static void binary_op( InputArray _src1, InputArray _src2, OutputArray _dst, size_t total = it.size, blocksize = std::min(total, blocksize0); _buf.allocate(blocksize*(haveMask ? 2 : 1)*esz + 32); - scbuf = _buf; + scbuf = _buf.data(); maskbuf = alignPtr(scbuf + blocksize*esz, 16); convertAndUnrollScalar( src2, src1.type(), scbuf, blocksize); @@ -754,7 +754,7 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, blocksize = std::min(blocksize, blocksize0); _buf.allocate(bufesz*blocksize + 64); - buf = _buf; + buf = _buf.data(); if( cvtsrc1 ) buf1 = buf, buf = alignPtr(buf + blocksize*wsz, 16); if( cvtsrc2 ) @@ -818,7 +818,7 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, size_t total = it.size, blocksize = std::min(total, blocksize0); _buf.allocate(bufesz*blocksize + 64); - buf = _buf; + buf = _buf.data(); if( cvtsrc1 ) buf1 = buf, buf = alignPtr(buf + blocksize*wsz, 16); buf2 = buf; buf = alignPtr(buf + blocksize*wsz, 16); @@ -1309,7 +1309,7 @@ void cv::compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op) size_t total = it.size, blocksize = std::min(total, blocksize0); AutoBuffer _buf(blocksize*esz); - uchar *buf = _buf; + uchar *buf = _buf.data(); if( depth1 > CV_32S ) convertAndUnrollScalar( src2, depth1, buf, blocksize ); @@ -1700,7 +1700,7 @@ static bool ocl_inRange( InputArray _src, InputArray _lowerb, size_t blocksize = 36; AutoBuffer _buf(blocksize*(((int)lbScalar + (int)ubScalar)*esz + cn) + 2*cn*sizeof(int) + 128); - uchar *buf = alignPtr(_buf + blocksize*cn, 16); + uchar *buf = alignPtr(_buf.data() + blocksize*cn, 16); if( ldepth != sdepth && sdepth < CV_32S ) { @@ -1806,7 +1806,7 @@ void cv::inRange(InputArray _src, InputArray _lowerb, size_t total = it.size, blocksize = std::min(total, blocksize0); AutoBuffer _buf(blocksize*(((int)lbScalar + (int)ubScalar)*esz + cn) + 2*cn*sizeof(int) + 128); - uchar *buf = _buf, *mbuf = buf, *lbuf = 0, *ubuf = 0; + uchar *buf = _buf.data(), *mbuf = buf, *lbuf = 0, *ubuf = 0; buf = alignPtr(buf + blocksize*cn, 16); if( lbScalar && ubScalar ) diff --git a/modules/core/src/batch_distance.cpp b/modules/core/src/batch_distance.cpp index 807b7f0285..1fd088dd5e 100644 --- a/modules/core/src/batch_distance.cpp +++ b/modules/core/src/batch_distance.cpp @@ -179,7 +179,7 @@ struct BatchDistInvoker : public ParallelLoopBody void operator()(const Range& range) const CV_OVERRIDE { AutoBuffer buf(src2->rows); - int* bufptr = buf; + int* bufptr = buf.data(); for( int i = range.start; i < range.end; i++ ) { diff --git a/modules/core/src/channels.cpp b/modules/core/src/channels.cpp index 065651f26d..8e88c7d82c 100644 --- a/modules/core/src/channels.cpp +++ b/modules/core/src/channels.cpp @@ -104,7 +104,7 @@ void cv::mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, cons int depth = dst[0].depth(); AutoBuffer buf((nsrcs + ndsts + 1)*(sizeof(Mat*) + sizeof(uchar*)) + npairs*(sizeof(uchar*)*2 + sizeof(int)*6)); - const Mat** arrays = (const Mat**)(uchar*)buf; + const Mat** arrays = (const Mat**)(uchar*)buf.data(); uchar** ptrs = (uchar**)(arrays + nsrcs + ndsts); const uchar** srcs = (const uchar**)(ptrs + nsrcs + ndsts + 1); uchar** dsts = (uchar**)(srcs + npairs); @@ -294,7 +294,7 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, CV_Assert(nsrc > 0 && ndst > 0); cv::AutoBuffer _buf(nsrc + ndst); - Mat* buf = _buf; + Mat* buf = _buf.data(); for( i = 0; i < nsrc; i++ ) buf[i] = src.getMat(src_is_mat ? -1 : i); for( i = 0; i < ndst; i++ ) @@ -327,7 +327,7 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, CV_Assert(fromTo.size()%2 == 0 && nsrc > 0 && ndst > 0); cv::AutoBuffer _buf(nsrc + ndst); - Mat* buf = _buf; + Mat* buf = _buf.data(); for( i = 0; i < nsrc; i++ ) buf[i] = src.getMat(src_is_mat ? -1 : i); for( i = 0; i < ndst; i++ ) diff --git a/modules/core/src/conjugate_gradient.cpp b/modules/core/src/conjugate_gradient.cpp index 400a5ab3a8..fecf0be156 100644 --- a/modules/core/src/conjugate_gradient.cpp +++ b/modules/core/src/conjugate_gradient.cpp @@ -52,7 +52,7 @@ namespace cv double eps = getGradientEps(); int i, n = getDims(); AutoBuffer x_buf(n); - double* x_ = x_buf; + double* x_ = x_buf.data(); for( i = 0; i < n; i++ ) x_[i] = x[i]; for( i = 0; i < n; i++ ) diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index e67e58b98e..b8a52f2f5a 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -531,7 +531,7 @@ Mat& Mat::setTo(InputArray _value, InputArray _mask) int blockSize0 = std::min(totalsz, (int)((BLOCK_SIZE + esz-1)/esz)); blockSize0 -= blockSize0 % mcn; // must be divisible without remainder for unrolling and advancing AutoBuffer _scbuf(blockSize0*esz + 32); - uchar* scbuf = alignPtr((uchar*)_scbuf, (int)sizeof(double)); + uchar* scbuf = alignPtr((uchar*)_scbuf.data(), (int)sizeof(double)); convertAndUnrollScalar( value, type(), scbuf, blockSize0/mcn ); for( size_t i = 0; i < it.nplanes; i++, ++it ) @@ -559,7 +559,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, { int i, j, limit = (int)(((size.width + 1)/2)*esz); AutoBuffer _tab(size.width*esz); - int* tab = _tab; + int* tab = _tab.data(); for( i = 0; i < size.width; i++ ) for( size_t k = 0; k < esz; k++ ) @@ -960,7 +960,7 @@ void copyMakeBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi, } cv::AutoBuffer _tab((dstroi.width - srcroi.width)*cn); - int* tab = _tab; + int* tab = _tab.data(); int right = dstroi.width - srcroi.width - left; int bottom = dstroi.height - srcroi.height - top; @@ -1031,7 +1031,7 @@ void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi, { int i, j; cv::AutoBuffer _constBuf(dstroi.width*cn); - uchar* constBuf = _constBuf; + uchar* constBuf = _constBuf.data(); int right = dstroi.width - srcroi.width - left; int bottom = dstroi.height - srcroi.height - top; @@ -1224,10 +1224,10 @@ void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom, CV_Assert( value[0] == value[1] && value[0] == value[2] && value[0] == value[3] ); cn1 = 1; } - scalarToRawData(value, buf, CV_MAKETYPE(src.depth(), cn1), cn); + scalarToRawData(value, buf.data(), CV_MAKETYPE(src.depth(), cn1), cn); copyMakeConstBorder_8u( src.ptr(), src.step, src.size(), dst.ptr(), dst.step, dst.size(), - top, left, (int)src.elemSize(), (uchar*)(double*)buf ); + top, left, (int)src.elemSize(), (uchar*)buf.data() ); } } diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index a161f86885..e7af47ba93 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -908,7 +908,7 @@ DFT(const OcvDftOptions & c, const Complex* src, Complex* dst) int p, q, factor2 = (factor - 1)/2; int d, dd, dw_f = c.tab_size/factor; AutoBuffer > buf(factor2 * 2); - Complex* a = buf; + Complex* a = buf.data(); Complex* b = a + factor2; for( i = 0; i < c.n; i += n ) @@ -2895,7 +2895,7 @@ protected: uchar* dptr = dptr0; if( needBufferA ) - dptr = tmp_bufA; + dptr = tmp_bufA.data(); contextA->apply(sptr, dptr); @@ -2921,12 +2921,12 @@ protected: const uchar* sptr0 = src_data; uchar* dptr0 = dst_data; - dbuf0 = buf0, dbuf1 = buf1; + dbuf0 = buf0.data(), dbuf1 = buf1.data(); if( needBufferB ) { - dbuf1 = tmp_bufB; - dbuf0 = buf1; + dbuf1 = tmp_bufB.data(); + dbuf0 = buf1.data(); } if( real_transform ) @@ -2937,42 +2937,42 @@ protected: b = (count+1)/2; if( !inv ) { - memset( buf0, 0, len*complex_elem_size ); - CopyColumn( sptr0, src_step, buf0, complex_elem_size, len, elem_size ); + memset( buf0.data(), 0, len*complex_elem_size ); + CopyColumn( sptr0, src_step, buf0.data(), complex_elem_size, len, elem_size ); sptr0 += stage_dst_channels*elem_size; if( even ) { - memset( buf1, 0, len*complex_elem_size ); + memset( buf1.data(), 0, len*complex_elem_size ); CopyColumn( sptr0 + (count-2)*elem_size, src_step, - buf1, complex_elem_size, len, elem_size ); + buf1.data(), complex_elem_size, len, elem_size ); } } else if( stage_src_channels == 1 ) { - CopyColumn( sptr0, src_step, buf0, elem_size, len, elem_size ); - ExpandCCS( buf0, len, elem_size ); + CopyColumn( sptr0, src_step, buf0.data(), elem_size, len, elem_size ); + ExpandCCS( buf0.data(), len, elem_size ); if( even ) { CopyColumn( sptr0 + (count-1)*elem_size, src_step, - buf1, elem_size, len, elem_size ); - ExpandCCS( buf1, len, elem_size ); + buf1.data(), elem_size, len, elem_size ); + ExpandCCS( buf1.data(), len, elem_size ); } sptr0 += elem_size; } else { - CopyColumn( sptr0, src_step, buf0, complex_elem_size, len, complex_elem_size ); + CopyColumn( sptr0, src_step, buf0.data(), complex_elem_size, len, complex_elem_size ); if( even ) { CopyColumn( sptr0 + b*complex_elem_size, src_step, - buf1, complex_elem_size, len, complex_elem_size ); + buf1.data(), complex_elem_size, len, complex_elem_size ); } sptr0 += complex_elem_size; } if( even ) - contextB->apply(buf1, dbuf1); - contextB->apply(buf0, dbuf0); + contextB->apply(buf1.data(), dbuf1); + contextB->apply(buf0.data(), dbuf0); if( stage_dst_channels == 1 ) { @@ -3019,13 +3019,13 @@ protected: { if( i+1 < b ) { - CopyFrom2Columns( sptr0, src_step, buf0, buf1, len, complex_elem_size ); - contextB->apply(buf1, dbuf1); + CopyFrom2Columns( sptr0, src_step, buf0.data(), buf1.data(), len, complex_elem_size ); + contextB->apply(buf1.data(), dbuf1); } else - CopyColumn( sptr0, src_step, buf0, complex_elem_size, len, complex_elem_size ); + CopyColumn( sptr0, src_step, buf0.data(), complex_elem_size, len, complex_elem_size ); - contextB->apply(buf0, dbuf0); + contextB->apply(buf0.data(), dbuf0); if( i+1 < b ) CopyTo2Columns( dbuf0, dbuf1, dptr0, dst_step, len, complex_elem_size ); @@ -3134,9 +3134,9 @@ public: if (len != prev_len || (!inplace_transform && opt.isInverse && real_transform)) { wave_buf.allocate(opt.n*complex_elem_size); - opt.wave = wave_buf; + opt.wave = wave_buf.data(); itab_buf.allocate(opt.n); - opt.itab = itab_buf; + opt.itab = itab_buf.data(); DFTInit( opt.n, opt.nf, opt.factors, opt.itab, complex_elem_size, opt.wave, stage == 0 && opt.isInverse && real_transform ); } @@ -4152,31 +4152,31 @@ public: bool inplace_transform = opt.factors[0] == opt.factors[opt.nf-1]; wave_buf.allocate(len*complex_elem_size); - opt.wave = wave_buf; + opt.wave = wave_buf.data(); itab_buf.allocate(len); - opt.itab = itab_buf; + opt.itab = itab_buf.data(); DFTInit( len, opt.nf, opt.factors, opt.itab, complex_elem_size, opt.wave, isInverse ); dct_wave.allocate((len/2 + 1)*complex_elem_size); src_buf.allocate(len*elem_size); - src_dft_buf = src_buf; + src_dft_buf = src_buf.data(); if(!inplace_transform) { dst_buf.allocate(len*elem_size); - dst_dft_buf = dst_buf; + dst_dft_buf = dst_buf.data(); } else { - dst_dft_buf = src_buf; + dst_dft_buf = src_buf.data(); } - DCTInit( len, complex_elem_size, dct_wave, isInverse); + DCTInit( len, complex_elem_size, dct_wave.data(), isInverse); prev_len = len; } // otherwise reuse the tables calculated on the previous stage for(unsigned i = 0; i < static_cast(count); i++ ) { dct_func( opt, sptr + i*sstep0, sstep1, src_dft_buf, dst_dft_buf, - dptr + i*dstep0, dstep1, dct_wave); + dptr + i*dstep0, dstep1, dct_wave.data()); } src = dst; src_step = dst_step; diff --git a/modules/core/src/kmeans.cpp b/modules/core/src/kmeans.cpp index 6b1a110c1f..c34e254953 100644 --- a/modules/core/src/kmeans.cpp +++ b/modules/core/src/kmeans.cpp @@ -330,7 +330,7 @@ double cv::kmeans( InputArray _data, int K, else { for (int k = 0; k < K; k++) - generateRandomCenter(dims, box, centers.ptr(k), rng); + generateRandomCenter(dims, box.data(), centers.ptr(k), rng); } } else @@ -429,14 +429,14 @@ double cv::kmeans( InputArray _data, int K, if (isLastIter) { // don't re-assign labels to avoid creation of empty clusters - parallel_for_(Range(0, N), KMeansDistanceComputer(dists, labels, data, centers), (double)divUp((size_t)(dims * N), CV_KMEANS_PARALLEL_GRANULARITY)); + parallel_for_(Range(0, N), KMeansDistanceComputer(dists.data(), labels, data, centers), (double)divUp((size_t)(dims * N), CV_KMEANS_PARALLEL_GRANULARITY)); compactness = sum(Mat(Size(N, 1), CV_64F, &dists[0]))[0]; break; } else { // assign labels - parallel_for_(Range(0, N), KMeansDistanceComputer(dists, labels, data, centers), (double)divUp((size_t)(dims * N * K), CV_KMEANS_PARALLEL_GRANULARITY)); + parallel_for_(Range(0, N), KMeansDistanceComputer(dists.data(), labels, data, centers), (double)divUp((size_t)(dims * N * K), CV_KMEANS_PARALLEL_GRANULARITY)); } } diff --git a/modules/core/src/lapack.cpp b/modules/core/src/lapack.cpp index 8fdbddad6e..2ec808a7a6 100644 --- a/modules/core/src/lapack.cpp +++ b/modules/core/src/lapack.cpp @@ -401,7 +401,7 @@ JacobiSVDImpl_(_Tp* At, size_t astep, _Tp* _W, _Tp* Vt, size_t vstep, { VBLAS<_Tp> vblas; AutoBuffer Wbuf(n); - double* W = Wbuf; + double* W = Wbuf.data(); int i, j, k, iter, max_iter = std::max(m, 30); _Tp c, s; double sd; @@ -778,7 +778,7 @@ double cv::determinant( InputArray _mat ) { size_t bufSize = rows*rows*sizeof(float); AutoBuffer buffer(bufSize); - Mat a(rows, rows, CV_32F, (uchar*)buffer); + Mat a(rows, rows, CV_32F, buffer.data()); mat.copyTo(a); result = hal::LU32f(a.ptr(), a.step, rows, 0, 0, 0); @@ -801,7 +801,7 @@ double cv::determinant( InputArray _mat ) { size_t bufSize = rows*rows*sizeof(double); AutoBuffer buffer(bufSize); - Mat a(rows, rows, CV_64F, (uchar*)buffer); + Mat a(rows, rows, CV_64F, buffer.data()); mat.copyTo(a); result = hal::LU64f(a.ptr(), a.step, rows, 0, 0, 0); @@ -846,7 +846,7 @@ double cv::invert( InputArray _src, OutputArray _dst, int method ) int nm = std::min(m, n); AutoBuffer _buf((m*nm + nm + nm*n)*esz + sizeof(double)); - uchar* buf = alignPtr((uchar*)_buf, (int)esz); + uchar* buf = alignPtr((uchar*)_buf.data(), (int)esz); Mat u(m, nm, type, buf); Mat w(nm, 1, type, u.ptr() + m*nm*esz); Mat vt(nm, n, type, w.ptr() + nm*esz); @@ -865,7 +865,7 @@ double cv::invert( InputArray _src, OutputArray _dst, int method ) if( method == DECOMP_EIG ) { AutoBuffer _buf((n*n*2 + n)*esz + sizeof(double)); - uchar* buf = alignPtr((uchar*)_buf, (int)esz); + uchar* buf = alignPtr((uchar*)_buf.data(), (int)esz); Mat u(n, n, type, buf); Mat w(n, 1, type, u.ptr() + n*n*esz); Mat vt(n, n, type, w.ptr() + n*esz); @@ -1063,7 +1063,7 @@ double cv::invert( InputArray _src, OutputArray _dst, int method ) int elem_size = CV_ELEM_SIZE(type); AutoBuffer buf(n*n*elem_size); - Mat src1(n, n, type, (uchar*)buf); + Mat src1(n, n, type, buf.data()); src.copyTo(src1); setIdentity(dst); @@ -1267,7 +1267,7 @@ bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int meth bufsize += n*5*esz + n*vstep + nb*sizeof(double) + 32; buffer.allocate(bufsize); - uchar* ptr = alignPtr((uchar*)buffer, 16); + uchar* ptr = alignPtr(buffer.data(), 16); Mat a(m_, n, type, ptr, astep); @@ -1445,7 +1445,7 @@ bool cv::eigen( InputArray _src, OutputArray _evals, OutputArray _evects ) size_t elemSize = src.elemSize(), astep = alignSize(n*elemSize, 16); AutoBuffer buf(n*astep + n*5*elemSize + 32); - uchar* ptr = alignPtr((uchar*)buf, 16); + uchar* ptr = alignPtr(buf.data(), 16); Mat a(n, n, type, ptr, astep), w(n, 1, type, ptr + astep*n); ptr += astep*n + elemSize*n; src.copyTo(a); @@ -1489,7 +1489,7 @@ static void _SVDcompute( InputArray _aarr, OutputArray _w, int urows = full_uv ? m : n; size_t esz = src.elemSize(), astep = alignSize(m*esz, 16), vstep = alignSize(n*esz, 16); AutoBuffer _buf(urows*astep + n*vstep + n*esz + 32); - uchar* buf = alignPtr((uchar*)_buf, 16); + uchar* buf = alignPtr(_buf.data(), 16); Mat temp_a(n, m, type, buf, astep); Mat temp_w(n, 1, type, buf + urows*astep); Mat temp_u(urows, m, type, buf, astep), temp_v; @@ -1568,11 +1568,11 @@ void SVD::backSubst( InputArray _w, InputArray _u, InputArray _vt, if( type == CV_32F ) SVBkSb(m, n, w.ptr(), wstep, u.ptr(), u.step, false, vt.ptr(), vt.step, true, rhs.ptr(), rhs.step, nb, - dst.ptr(), dst.step, buffer); + dst.ptr(), dst.step, buffer.data()); else if( type == CV_64F ) SVBkSb(m, n, w.ptr(), wstep, u.ptr(), u.step, false, vt.ptr(), vt.step, true, rhs.ptr(), rhs.step, nb, - dst.ptr(), dst.step, buffer); + dst.ptr(), dst.step, buffer.data()); else CV_Error( CV_StsUnsupportedFormat, "" ); } diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index be6e7de3a2..9154db6bcb 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -586,7 +586,7 @@ void polarToCart( InputArray src1, InputArray src2, if( depth == CV_64F ) { _buf.allocate(blockSize*2); - buf[0] = _buf; + buf[0] = _buf.data(); buf[1] = buf[0] + blockSize; } @@ -1278,8 +1278,8 @@ void pow( InputArray _src, double power, OutputArray _dst ) if( src.ptr() == dst.ptr() ) { buf.allocate(blockSize*esz1); - fbuf = (float*)(uchar*)buf; - dbuf = (double*)(uchar*)buf; + fbuf = (float*)buf.data(); + dbuf = (double*)buf.data(); } for( size_t i = 0; i < it.nplanes; i++, ++it ) @@ -1901,7 +1901,7 @@ double cv::solvePoly( InputArray _coeffs0, OutputArray _roots0, int maxIters ) Mat roots0 = _roots0.getMat(); AutoBuffer buf(n*2+2); - C *coeffs = buf, *roots = coeffs + n + 1; + C *coeffs = buf.data(), *roots = coeffs + n + 1; Mat coeffs1(coeffs0.size(), CV_MAKETYPE(CV_64F, coeffs0.channels()), coeffs0.channels() == 2 ? coeffs : roots); coeffs0.convertTo(coeffs1, coeffs1.type()); if( coeffs0.channels() == 1 ) diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index f67a301086..7f624b5f76 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -165,7 +165,7 @@ GEMMSingleMul( const T* a_data, size_t a_step, if( a_step > 1 && n > 1 ) { _a_buf.allocate(n); - a_buf = _a_buf; + a_buf = _a_buf.data(); } } @@ -177,7 +177,7 @@ GEMMSingleMul( const T* a_data, size_t a_step, if( a_step > 1 && a_size.height > 1 ) { _a_buf.allocate(drows); - a_buf = _a_buf; + a_buf = _a_buf.data(); for( k = 0; k < drows; k++ ) a_buf[k] = a_data[a_step*k]; a_data = a_buf; @@ -186,7 +186,7 @@ GEMMSingleMul( const T* a_data, size_t a_step, if( b_step > 1 ) { _b_buf.allocate(d_size.width); - b_buf = _b_buf; + b_buf = _b_buf.data(); for( j = 0; j < d_size.width; j++ ) b_buf[j] = b_data[j*b_step]; b_data = b_buf; @@ -326,7 +326,7 @@ GEMMSingleMul( const T* a_data, size_t a_step, else { cv::AutoBuffer _d_buf(m); - WT* d_buf = _d_buf; + WT* d_buf = _d_buf.data(); for( i = 0; i < drows; i++, _a_data += a_step0, _c_data += c_step0, d_data += d_step ) { @@ -404,7 +404,7 @@ GEMMBlockMul( const T* a_data, size_t a_step, CV_SWAP( a_step0, a_step1, t_step ); n = a_size.height; _a_buf.allocate(n); - a_buf = _a_buf; + a_buf = _a_buf.data(); } if( flags & GEMM_2_T ) @@ -1354,7 +1354,7 @@ static void gemmImpl( Mat A, Mat B, double alpha, } buf.allocate(d_buf_size + b_buf_size + a_buf_size); - d_buf = (uchar*)buf; + d_buf = buf.data(); b_buf = d_buf + d_buf_size; if( is_a_t ) @@ -2098,7 +2098,7 @@ void cv::transform( InputArray _src, OutputArray _dst, InputArray _mtx ) if( !m.isContinuous() || m.type() != mtype || m.cols != scn + 1 ) { _mbuf.allocate(dcn*(scn+1)); - mbuf = (double*)_mbuf; + mbuf = _mbuf.data(); Mat tmp(dcn, scn+1, mtype, mbuf); memset(tmp.ptr(), 0, tmp.total()*tmp.elemSize()); if( m.cols == scn+1 ) @@ -2273,17 +2273,16 @@ void cv::perspectiveTransform( InputArray _src, OutputArray _dst, InputArray _mt const int mtype = CV_64F; AutoBuffer _mbuf; - double* mbuf = _mbuf; + double* mbuf = m.ptr(); if( !m.isContinuous() || m.type() != mtype ) { _mbuf.allocate((dcn+1)*(scn+1)); - Mat tmp(dcn+1, scn+1, mtype, (double*)_mbuf); + mbuf = _mbuf.data(); + Mat tmp(dcn+1, scn+1, mtype, mbuf); m.convertTo(tmp, mtype); m = tmp; } - else - mbuf = m.ptr(); TransformFunc func = depth == CV_32F ? (TransformFunc)perspectiveTransform_32f : @@ -2612,7 +2611,7 @@ double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar ) const float* src2 = v2.ptr(); size_t step1 = v1.step/sizeof(src1[0]); size_t step2 = v2.step/sizeof(src2[0]); - double* diff = buf; + double* diff = buf.data(); const float* mat = icovar.ptr(); size_t matstep = icovar.step/sizeof(mat[0]); @@ -2622,7 +2621,7 @@ double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar ) diff[i] = src1[i] - src2[i]; } - diff = buf; + diff = buf.data(); for( i = 0; i < len; i++, mat += matstep ) { double row_sum = 0; @@ -2643,7 +2642,7 @@ double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar ) const double* src2 = v2.ptr(); size_t step1 = v1.step/sizeof(src1[0]); size_t step2 = v2.step/sizeof(src2[0]); - double* diff = buf; + double* diff = buf.data(); const double* mat = icovar.ptr(); size_t matstep = icovar.step/sizeof(mat[0]); @@ -2653,7 +2652,7 @@ double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar ) diff[i] = src1[i] - src2[i]; } - diff = buf; + diff = buf.data(); for( i = 0; i < len; i++, mat += matstep ) { double row_sum = 0; @@ -2705,7 +2704,7 @@ MulTransposedR( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scal buf_size *= 5; } buf.allocate(buf_size); - col_buf = (dT*)(uchar*)buf; + col_buf = (dT*)buf.data(); if( delta && delta_cols < size.width ) { @@ -2834,7 +2833,7 @@ MulTransposedL( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scal dT delta_buf[4]; int delta_shift = delta_cols == size.width ? 4 : 0; AutoBuffer buf(size.width*sizeof(dT)); - dT* row_buf = (dT*)(uchar*)buf; + dT* row_buf = (dT*)buf.data(); for( i = 0; i < size.height; i++, tdst += dststep ) { diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index a003fd4b01..65ac200463 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -410,7 +410,7 @@ Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange) rs[1] = _colRange; for( int i = 2; i < m.dims; i++ ) rs[i] = Range::all(); - *this = m(rs); + *this = m(rs.data()); return; } @@ -897,7 +897,7 @@ Mat Mat::reshape(int _cn, int _newndims, const int* _newsz) const Mat hdr = *this; hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((_cn-1) << CV_CN_SHIFT); - setSize(hdr, _newndims, (int*)newsz_buf, NULL, true); + setSize(hdr, _newndims, newsz_buf.data(), NULL, true); return hdr; } diff --git a/modules/core/src/matrix_c.cpp b/modules/core/src/matrix_c.cpp index 6d299f7531..a4efd4ccf3 100644 --- a/modules/core/src/matrix_c.cpp +++ b/modules/core/src/matrix_c.cpp @@ -169,7 +169,7 @@ Mat cvarrToMat(const CvArr* arr, bool copyData, if( abuf ) { abuf->allocate(((size_t)total*esz + sizeof(double)-1)/sizeof(double)); - double* bufdata = *abuf; + double* bufdata = abuf->data(); cvCvtSeqToArray(seq, bufdata, CV_WHOLE_SEQ); return Mat(total, 1, type, bufdata); } diff --git a/modules/core/src/matrix_decomp.cpp b/modules/core/src/matrix_decomp.cpp index 4bcc61a1be..7eeb47a16a 100644 --- a/modules/core/src/matrix_decomp.cpp +++ b/modules/core/src/matrix_decomp.cpp @@ -206,7 +206,7 @@ QRImpl(_Tp* A, size_t astep, int m, int n, int k, _Tp* b, size_t bstep, _Tp* hFa cv::AutoBuffer<_Tp> buffer; size_t buf_size = m ? m + n : hFactors != NULL; buffer.allocate(buf_size); - _Tp* vl = buffer; + _Tp* vl = buffer.data(); if (hFactors == NULL) hFactors = vl + m; diff --git a/modules/core/src/matrix_operations.cpp b/modules/core/src/matrix_operations.cpp index c501c88bb5..74d289b683 100644 --- a/modules/core/src/matrix_operations.cpp +++ b/modules/core/src/matrix_operations.cpp @@ -606,7 +606,7 @@ reduceR_( const Mat& srcmat, Mat& dstmat ) Size size = srcmat.size(); size.width *= srcmat.channels(); AutoBuffer buffer(size.width); - WT* buf = buffer; + WT* buf = buffer.data(); ST* dst = dstmat.ptr(); const T* src = srcmat.ptr(); size_t srcstep = srcmat.step/sizeof(src[0]); @@ -1125,7 +1125,6 @@ namespace cv template static void sort_( const Mat& src, Mat& dst, int flags ) { AutoBuffer buf; - T* bptr; int n, len; bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW; bool inplace = src.data == dst.data; @@ -1138,7 +1137,7 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) n = src.cols, len = src.rows; buf.allocate(len); } - bptr = (T*)buf; + T* bptr = buf.data(); for( int i = 0; i < n; i++ ) { @@ -1223,7 +1222,7 @@ static bool ipp_sort(const Mat& src, Mat& dst, int flags) for(int i = 0; i < dst.rows; i++) { - if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)dst.ptr(i), dst.cols, buffer) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)dst.ptr(i), dst.cols, buffer.data()) < 0) return false; } } @@ -1248,7 +1247,7 @@ static bool ipp_sort(const Mat& src, Mat& dst, int flags) dstSub = Mat(dst, subRect); srcSub.copyTo(row); - if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)row.ptr(), dst.rows, buffer) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)row.ptr(), dst.rows, buffer.data()) < 0) return false; row = row.reshape(1, dstSub.rows); @@ -1286,8 +1285,8 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) buf.allocate(len); ibuf.allocate(len); } - T* bptr = (T*)buf; - int* _iptr = (int*)ibuf; + T* bptr = buf.data(); + int* _iptr = ibuf.data(); for( int i = 0; i < n; i++ ) { @@ -1365,7 +1364,7 @@ static bool ipp_sortIdx( const Mat& src, Mat& dst, int flags ) for(int i = 0; i < src.rows; i++) { - if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (const void*)src.ptr(i), (Ipp32s)src.step[1], (Ipp32s*)dst.ptr(i), src.cols, buffer) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (const void*)src.ptr(i), (Ipp32s)src.step[1], (Ipp32s*)dst.ptr(i), src.cols, buffer.data()) < 0) return false; } } @@ -1388,7 +1387,7 @@ static bool ipp_sortIdx( const Mat& src, Mat& dst, int flags ) subRect.x = i; dstSub = Mat(dst, subRect); - if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (const void*)src.ptr(0, i), srcStep, (Ipp32s*)dstRow.ptr(), src.rows, buffer) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (const void*)src.ptr(0, i), srcStep, (Ipp32s*)dstRow.ptr(), src.rows, buffer.data()) < 0) return false; dstRow = dstRow.reshape(1, dstSub.rows); diff --git a/modules/core/src/mean.cpp b/modules/core/src/mean.cpp index 9a7afaa71a..d0029b3cbc 100644 --- a/modules/core/src/mean.cpp +++ b/modules/core/src/mean.cpp @@ -135,7 +135,7 @@ cv::Scalar cv::mean( InputArray _src, InputArray _mask ) intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15); blockSize = std::min(blockSize, intSumBlockSize); _buf.allocate(cn); - buf = _buf; + buf = _buf.data(); for( k = 0; k < cn; k++ ) buf[k] = 0; @@ -789,7 +789,7 @@ void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, Input int total = (int)it.size, blockSize = total, intSumBlockSize = 0; int j, count = 0, nz0 = 0; AutoBuffer _buf(cn*4); - double *s = (double*)_buf, *sq = s + cn; + double *s = (double*)_buf.data(), *sq = s + cn; int *sbuf = (int*)s, *sqbuf = (int*)sq; bool blockSum = depth <= CV_16S, blockSqSum = depth <= CV_8S; size_t esz = 0; diff --git a/modules/core/src/merge.cpp b/modules/core/src/merge.cpp index 6f44b1b9a8..e1fe6ad1e9 100644 --- a/modules/core/src/merge.cpp +++ b/modules/core/src/merge.cpp @@ -496,7 +496,7 @@ void cv::merge(const Mat* mv, size_t n, OutputArray _dst) size_t esz = dst.elemSize(), esz1 = dst.elemSize1(); size_t blocksize0 = (int)((BLOCK_SIZE + esz-1)/esz); AutoBuffer _buf((cn+1)*(sizeof(Mat*) + sizeof(uchar*)) + 16); - const Mat** arrays = (const Mat**)(uchar*)_buf; + const Mat** arrays = (const Mat**)_buf.data(); uchar** ptrs = (uchar**)alignPtr(arrays + cn + 1, 16); arrays[0] = &dst; diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 59b649feaa..cc6feacbbb 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -617,12 +617,12 @@ public: if (fileSourceSignatureSize == sourceSignatureSize_) { cv::AutoBuffer fileSourceSignature(fileSourceSignatureSize + 1); - f.read((char*)fileSourceSignature, fileSourceSignatureSize); + f.read(fileSourceSignature.data(), fileSourceSignatureSize); if (f.eof()) { CV_LOG_ERROR(NULL, "Unexpected EOF"); } - else if (memcmp(sourceSignature, (const char*)fileSourceSignature, fileSourceSignatureSize) == 0) + else if (memcmp(sourceSignature, fileSourceSignature.data(), fileSourceSignatureSize) == 0) { isValid = true; } @@ -696,10 +696,10 @@ public: { if (entry.keySize > 0) { - f.read((char*)fileKey, entry.keySize); + f.read(fileKey.data(), entry.keySize); CV_Assert(!f.fail()); } - if (memcmp((const char*)fileKey, key.c_str(), entry.keySize) == 0) + if (memcmp(fileKey.data(), key.c_str(), entry.keySize) == 0) { buf.resize(entry.dataSize); f.read(&buf[0], entry.dataSize); @@ -786,10 +786,10 @@ public: { if (entry.keySize > 0) { - f.read((char*)fileKey, entry.keySize); + f.read(fileKey.data(), entry.keySize); CV_Assert(!f.fail()); } - if (0 == memcmp((const char*)fileKey, key.c_str(), entry.keySize)) + if (0 == memcmp(fileKey.data(), key.c_str(), entry.keySize)) { // duplicate CV_LOG_VERBOSE(NULL, 0, "Duplicate key ignored: " << fileName_); @@ -1634,7 +1634,7 @@ inline cl_int getStringInfo(Functor f, ObjectType obj, cl_uint name, std::string if (required > 0) { AutoBuffer buf(required + 1); - char* ptr = (char*)buf; // cleanup is not needed + char* ptr = buf.data(); // cleanup is not needed err = f(obj, name, required, ptr, NULL); if (err != CL_SUCCESS) return err; @@ -2002,7 +2002,7 @@ struct Context::Impl CV_OCL_DBG_CHECK(clGetDeviceIDs(pl, dtype, 0, 0, &nd0)); AutoBuffer dlistbuf(nd0*2+1); - cl_device_id* dlist = (cl_device_id*)(void**)dlistbuf; + cl_device_id* dlist = (cl_device_id*)dlistbuf.data(); cl_device_id* dlist_new = dlist + nd0; CV_OCL_DBG_CHECK(clGetDeviceIDs(pl, dtype, nd0, dlist, &nd0)); String name0; @@ -2465,12 +2465,12 @@ static void get_platform_name(cl_platform_id id, String& name) // get platform name string AutoBuffer buf(sz + 1); - CV_OCL_CHECK(clGetPlatformInfo(id, CL_PLATFORM_NAME, sz, buf, 0)); + CV_OCL_CHECK(clGetPlatformInfo(id, CL_PLATFORM_NAME, sz, buf.data(), 0)); // just in case, ensure trailing zero for ASCIIZ string buf[sz] = 0; - name = (const char*)buf; + name = buf.data(); } /* @@ -3654,7 +3654,7 @@ struct Program::Impl { buffer.resize(retsz + 16); log_retval = clGetProgramBuildInfo(handle, deviceList[0], - CL_PROGRAM_BUILD_LOG, retsz+1, (char*)buffer, &retsz); + CL_PROGRAM_BUILD_LOG, retsz+1, buffer.data(), &retsz); if (log_retval == CL_SUCCESS) { if (retsz < buffer.size()) @@ -3668,7 +3668,7 @@ struct Program::Impl } } - errmsg = String(buffer); + errmsg = String(buffer.data()); printf("OpenCL program build log: %s/%s\nStatus %d: %s\n%s\n%s\n", sourceModule_.c_str(), sourceName_.c_str(), result, getOpenCLErrorString(result), @@ -3701,7 +3701,7 @@ struct Program::Impl { size_t n = ctx.ndevices(); AutoBuffer deviceListBuf(n + 1); - cl_device_id* deviceList = deviceListBuf; + cl_device_id* deviceList = deviceListBuf.data(); for (size_t i = 0; i < n; i++) { deviceList[i] = (cl_device_id)(ctx.device(i).ptr()); @@ -3770,9 +3770,9 @@ struct Program::Impl AutoBuffer binaryPtrs_(ndevices); AutoBuffer binarySizes_(ndevices); - cl_device_id* devices = devices_; - const uchar** binaryPtrs = binaryPtrs_; - size_t* binarySizes = binarySizes_; + cl_device_id* devices = devices_.data(); + const uchar** binaryPtrs = binaryPtrs_.data(); + size_t* binarySizes = binarySizes_.data(); for (size_t i = 0; i < ndevices; i++) { devices[i] = (cl_device_id)ctx.device(i).ptr(); @@ -3781,7 +3781,7 @@ struct Program::Impl } cl_int result = 0; - handle = clCreateProgramWithBinary((cl_context)ctx.ptr(), (cl_uint)ndevices, (cl_device_id*)devices_, + handle = clCreateProgramWithBinary((cl_context)ctx.ptr(), (cl_uint)ndevices, devices_.data(), binarySizes, binaryPtrs, NULL, &result); if (result != CL_SUCCESS) { @@ -3798,7 +3798,7 @@ struct Program::Impl } // call clBuildProgram() { - result = clBuildProgram(handle, (cl_uint)ndevices, (cl_device_id*)devices_, buildflags.c_str(), 0, 0); + result = clBuildProgram(handle, (cl_uint)ndevices, devices_.data(), buildflags.c_str(), 0, 0); CV_OCL_DBG_CHECK_RESULT(result, cv::format("clBuildProgram(binary: %s/%s)", sourceModule_.c_str(), sourceName_.c_str()).c_str()); if (result != CL_SUCCESS) { @@ -6318,7 +6318,7 @@ struct Image2D::Impl AutoBuffer formats(numFormats); err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, numFormats, - formats, NULL); + formats.data(), NULL); CV_OCL_DBG_CHECK_RESULT(err, "clGetSupportedImageFormats(CL_MEM_OBJECT_IMAGE2D, formats)"); for (cl_uint i = 0; i < numFormats; ++i) { diff --git a/modules/core/src/persistence_cpp.cpp b/modules/core/src/persistence_cpp.cpp index 9b1e6bd82d..ab1b1f09e8 100644 --- a/modules/core/src/persistence_cpp.cpp +++ b/modules/core/src/persistence_cpp.cpp @@ -222,7 +222,7 @@ String FileStorage::getDefaultObjectName(const String& _filename) if( ptr == ptr2 ) CV_Error( CV_StsBadArg, "Invalid filename" ); - char* name = name_buf; + char* name = name_buf.data(); // name must start with letter or '_' if( !cv_isalpha(*ptr) && *ptr!= '_' ){ @@ -237,7 +237,7 @@ String FileStorage::getDefaultObjectName(const String& _filename) *name++ = c; } *name = '\0'; - name = name_buf; + name = name_buf.data(); if( strcmp( name, "_" ) == 0 ) strcpy( name, stubname ); return String(name); diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index cac5166ff6..7b7f8ed9b6 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -542,7 +542,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, if( disttype == UNIFORM ) { _parambuf.allocate(cn*8 + n1 + n2); - double* parambuf = _parambuf; + double* parambuf = _parambuf.data(); double* p1 = _param1.ptr(); double* p2 = _param2.ptr(); @@ -651,7 +651,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, else if( disttype == CV_RAND_NORMAL ) { _parambuf.allocate(MAX(n1, cn) + MAX(n2, cn)); - double* parambuf = _parambuf; + double* parambuf = _parambuf.data(); int ptype = depth == CV_64F ? CV_64F : CV_32F; int esz = (int)CV_ELEM_SIZE(ptype); @@ -701,7 +701,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, if( disttype == UNIFORM ) { buf.allocate(blockSize*cn*4); - param = (uchar*)(double*)buf; + param = (uchar*)(double*)buf.data(); if( depth <= CV_32S ) { @@ -738,7 +738,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, else { buf.allocate((blockSize*cn+1)/2); - nbuf = (float*)(double*)buf; + nbuf = (float*)(double*)buf.data(); } for( size_t i = 0; i < it.nplanes; i++, ++it ) diff --git a/modules/core/src/split.cpp b/modules/core/src/split.cpp index 0452941871..43896455e1 100644 --- a/modules/core/src/split.cpp +++ b/modules/core/src/split.cpp @@ -485,7 +485,7 @@ void cv::split(const Mat& src, Mat* mv) size_t esz = src.elemSize(), esz1 = src.elemSize1(); size_t blocksize0 = (BLOCK_SIZE + esz-1)/esz; AutoBuffer _buf((cn+1)*(sizeof(Mat*) + sizeof(uchar*)) + 16); - const Mat** arrays = (const Mat**)(uchar*)_buf; + const Mat** arrays = (const Mat**)_buf.data(); uchar** ptrs = (uchar**)alignPtr(arrays + cn + 1, 16); arrays[0] = &src; diff --git a/modules/core/src/sum.cpp b/modules/core/src/sum.cpp index 76dec2f4a8..f965823889 100644 --- a/modules/core/src/sum.cpp +++ b/modules/core/src/sum.cpp @@ -617,7 +617,7 @@ cv::Scalar cv::sum( InputArray _src ) intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15); blockSize = std::min(blockSize, intSumBlockSize); _buf.allocate(cn); - buf = _buf; + buf = _buf.data(); for( k = 0; k < cn; k++ ) buf[k] = 0; diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 49f9cc09ba..41a589ea3a 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -807,7 +807,7 @@ String format( const char* fmt, ... ) va_list va; va_start(va, fmt); int bsize = static_cast(buf.size()); - int len = cv_vsnprintf((char *)buf, bsize, fmt, va); + int len = cv_vsnprintf(buf.data(), bsize, fmt, va); va_end(va); CV_Assert(len >= 0 && "Check format string for errors"); @@ -817,7 +817,7 @@ String format( const char* fmt, ... ) continue; } buf[bsize - 1] = 0; - return String((char *)buf, len); + return String(buf.data(), len); } } diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index f89f777b52..f61126b3d9 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -502,7 +502,7 @@ UMat::UMat(const UMat& m, const Range& _rowRange, const Range& _colRange) rs[1] = _colRange; for( int i = 2; i < m.dims; i++ ) rs[i] = Range::all(); - *this = m(rs); + *this = m(rs.data()); return; } @@ -805,7 +805,7 @@ UMat UMat::reshape(int _cn, int _newndims, const int* _newsz) const UMat hdr = *this; hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((_cn-1) << CV_CN_SHIFT); - setSize(hdr, _newndims, (int*)newsz_buf, NULL, true); + setSize(hdr, _newndims, newsz_buf.data(), NULL, true); return hdr; } diff --git a/modules/core/src/utils/filesystem.cpp b/modules/core/src/utils/filesystem.cpp index d7eeffce23..23bed074f7 100644 --- a/modules/core/src/utils/filesystem.cpp +++ b/modules/core/src/utils/filesystem.cpp @@ -158,13 +158,13 @@ cv::String getcwd() #else DWORD sz = GetCurrentDirectoryA(0, NULL); buf.allocate((size_t)sz); - sz = GetCurrentDirectoryA((DWORD)buf.size(), (char*)buf); - return cv::String((char*)buf, (size_t)sz); + sz = GetCurrentDirectoryA((DWORD)buf.size(), buf.data()); + return cv::String(buf.data(), (size_t)sz); #endif #elif defined __linux__ || defined __APPLE__ || defined __HAIKU__ for(;;) { - char* p = ::getcwd((char*)buf, buf.size()); + char* p = ::getcwd(buf.data(), buf.size()); if (p == NULL) { if (errno == ERANGE) @@ -176,7 +176,7 @@ cv::String getcwd() } break; } - return cv::String((char*)buf, (size_t)strlen((char*)buf)); + return cv::String(buf.data(), (size_t)strlen(buf.data())); #else return cv::String(); #endif diff --git a/modules/core/test/test_rand.cpp b/modules/core/test/test_rand.cpp index baccbc9b59..82bb6104a9 100644 --- a/modules/core/test/test_rand.cpp +++ b/modules/core/test/test_rand.cpp @@ -374,9 +374,9 @@ TEST(Core_Rand, Regression_Stack_Corruption) int bufsz = 128; //enough for 14 doubles AutoBuffer buffer(bufsz); size_t offset = 0; - cv::Mat_ x(2, 3, (cv::Point2d*)(buffer+offset)); offset += x.total()*x.elemSize(); - double& param1 = *(double*)(buffer+offset); offset += sizeof(double); - double& param2 = *(double*)(buffer+offset); offset += sizeof(double); + cv::Mat_ x(2, 3, (cv::Point2d*)(buffer.data()+offset)); offset += x.total()*x.elemSize(); + double& param1 = *(double*)(buffer.data()+offset); offset += sizeof(double); + double& param2 = *(double*)(buffer.data()+offset); offset += sizeof(double); param1 = -9; param2 = 2; cv::theRNG().fill(x, cv::RNG::NORMAL, param1, param2); diff --git a/modules/dnn/src/layers/convolution_layer.cpp b/modules/dnn/src/layers/convolution_layer.cpp index 27818e5e7c..2958d6634b 100644 --- a/modules/dnn/src/layers/convolution_layer.cpp +++ b/modules/dnn/src/layers/convolution_layer.cpp @@ -586,7 +586,7 @@ public: float* data_out0_ = output_->ptr(); size_t rowbufsz = (size_t)karea*BLK_SIZE_CN*BLK_SIZE; AutoBuffer rowbuf0_(rowbufsz + valign); - float* rowbuf0 = alignPtr((float*)rowbuf0_, (int)(valign*sizeof(float))); + float* rowbuf0 = alignPtr(rowbuf0_.data(), (int)(valign*sizeof(float))); // we clear the buffer once; ultimately, it lets us to avoid // tail processing after running the unrolled/vectorized loop. diff --git a/modules/dnn/src/layers/fully_connected_layer.cpp b/modules/dnn/src/layers/fully_connected_layer.cpp index 499f672918..dfaa58c7ed 100644 --- a/modules/dnn/src/layers/fully_connected_layer.cpp +++ b/modules/dnn/src/layers/fully_connected_layer.cpp @@ -182,7 +182,7 @@ public: size_t stripeEnd = r.end == nstripes ? total : std::min(r.end*stripeSize, total); size_t wstep = weights->step1(); AutoBuffer srcbuf(vecsize_aligned + valign); - float* sptr = alignPtr((float*)srcbuf, (int)(valign*sizeof(float))); + float* sptr = alignPtr(srcbuf.data(), (int)(valign*sizeof(float))); for( k = vecsize; k < vecsize_aligned; k++ ) sptr[k] = 0.f; diff --git a/modules/dnn/src/layers/lrn_layer.cpp b/modules/dnn/src/layers/lrn_layer.cpp index cfa95e96e8..8ff8390bea 100644 --- a/modules/dnn/src/layers/lrn_layer.cpp +++ b/modules/dnn/src/layers/lrn_layer.cpp @@ -211,7 +211,7 @@ public: int k, channels = channels_, ksize = ksize_; AutoBuffer buf_((channels + ksize + 1)*2); - float* acc = (float*)buf_; + float* acc = buf_.data(); float* buf = acc + channels + ksize + 1; for( k = 0; k <= ksize; k++ ) buf[-k-1] = buf[channels + k] = 0.f; diff --git a/modules/dnn/src/torch/torch_importer.cpp b/modules/dnn/src/torch/torch_importer.cpp index 88779e9977..049c83f606 100644 --- a/modules/dnn/src/torch/torch_importer.cpp +++ b/modules/dnn/src/torch/torch_importer.cpp @@ -370,8 +370,8 @@ struct TorchImporter int ndims = readInt(); AutoBuffer sizes(ndims); AutoBuffer steps(ndims); - THFile_readLongRaw(file, sizes, ndims); - THFile_readLongRaw(file, steps, ndims); + THFile_readLongRaw(file, sizes.data(), ndims); + THFile_readLongRaw(file, steps.data(), ndims); long offset = readLong() - 1; //read Storage @@ -411,7 +411,7 @@ struct TorchImporter } //allocate Blob - Mat srcMat(ndims, (int*)isizes, typeTensor , storages[indexStorage].ptr() + offset*CV_ELEM_SIZE(typeTensor), (size_t*)ssteps); + Mat srcMat(ndims, isizes.data(), typeTensor , storages[indexStorage].ptr() + offset*CV_ELEM_SIZE(typeTensor), ssteps.data()); int dstType = CV_32F; Mat blob; diff --git a/modules/features2d/src/fast.cpp b/modules/features2d/src/fast.cpp index e34fa8f9d0..4a7071bc98 100644 --- a/modules/features2d/src/fast.cpp +++ b/modules/features2d/src/fast.cpp @@ -83,7 +83,7 @@ void FAST_t(InputArray _img, std::vector& keypoints, int threshold, bo AutoBuffer _buf((img.cols+16)*3*(sizeof(int) + sizeof(uchar)) + 128); uchar* buf[3]; - buf[0] = _buf; buf[1] = buf[0] + img.cols; buf[2] = buf[1] + img.cols; + buf[0] = _buf.data(); buf[1] = buf[0] + img.cols; buf[2] = buf[1] + img.cols; int* cpbuf[3]; cpbuf[0] = (int*)alignPtr(buf[2] + img.cols, sizeof(int)) + 1; cpbuf[1] = cpbuf[0] + img.cols + 1; diff --git a/modules/features2d/src/orb.cpp b/modules/features2d/src/orb.cpp index 453ddf420d..dc9664e548 100644 --- a/modules/features2d/src/orb.cpp +++ b/modules/features2d/src/orb.cpp @@ -143,7 +143,7 @@ HarrisResponses(const Mat& img, const std::vector& layerinfo, float scale_sq_sq = scale * scale * scale * scale; AutoBuffer ofsbuf(blockSize*blockSize); - int* ofs = ofsbuf; + int* ofs = ofsbuf.data(); for( int i = 0; i < blockSize; i++ ) for( int j = 0; j < blockSize; j++ ) ofs[i*blockSize + j] = (int)(i*step + j); diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index 2f48e40785..09d5bd2370 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -726,7 +726,7 @@ private: } cv::AutoBuffer centers_idx_buf(branching); - int* centers_idx = (int*)centers_idx_buf; + int* centers_idx = centers_idx_buf.data(); int centers_length; (this->*chooseCenters)(branching, indices, indices_length, centers_idx, centers_length); @@ -739,7 +739,7 @@ private: cv::AutoBuffer dcenters_buf(branching*veclen_); - Matrix dcenters((double*)dcenters_buf,branching,veclen_); + Matrix dcenters(dcenters_buf.data(), branching, veclen_); for (int i=0; i radiuses(branching); cv::AutoBuffer count_buf(branching); - int* count = (int*)count_buf; + int* count = count_buf.data(); for (int i=0; i belongs_to_buf(indices_length); - int* belongs_to = (int*)belongs_to_buf; + int* belongs_to = belongs_to_buf.data(); for (int i=0; i& params ) if( channels > 1 ) _buffer.allocate(width*channels); - buffer = _buffer; + buffer = _buffer.data(); for( int y = 0; y < height; y++ ) { diff --git a/modules/imgcodecs/src/grfmt_pam.cpp b/modules/imgcodecs/src/grfmt_pam.cpp index e300d33ff4..9c9aa9e79e 100644 --- a/modules/imgcodecs/src/grfmt_pam.cpp +++ b/modules/imgcodecs/src/grfmt_pam.cpp @@ -496,9 +496,7 @@ bool PAMDecoder::readData( Mat& img ) /* setting buffer to max data size so scaling up is possible */ AutoBuffer _src(src_elems_per_row * 2); - uchar* src = _src; - AutoBuffer _gray_palette; - uchar* gray_palette = _gray_palette; + uchar* src = _src.data(); if( m_offset < 0 || !m_strm.isOpened()) return false; @@ -544,10 +542,7 @@ bool PAMDecoder::readData( Mat& img ) if (bit_mode) { if( target_channels == 1 ) { - _gray_palette.allocate(2); - gray_palette = _gray_palette; - gray_palette[0] = 0; - gray_palette[1] = 255; + uchar gray_palette[2] = {0, 255}; for( y = 0; y < m_height; y++, data += imp_stride ) { m_strm.getBytes( src, src_stride ); @@ -683,7 +678,7 @@ bool PAMEncoder::write( const Mat& img, const std::vector& params ) bufsize = tmp; AutoBuffer _buffer(bufsize); - char* buffer = _buffer; + char* buffer = _buffer.data(); /* write header */ tmp = 0; diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index 06df9858ad..36324c2e6c 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -225,7 +225,7 @@ bool PngDecoder::readData( Mat& img ) { volatile bool result = false; AutoBuffer _buffer(m_height); - uchar** buffer = _buffer; + uchar** buffer = _buffer.data(); int color = img.channels() > 1; png_structp png_ptr = (png_structp)m_png_ptr; @@ -426,7 +426,7 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) for( y = 0; y < height; y++ ) buffer[y] = img.data + y*img.step; - png_write_image( png_ptr, buffer ); + png_write_image( png_ptr, buffer.data() ); png_write_end( png_ptr, info_ptr ); result = true; diff --git a/modules/imgcodecs/src/grfmt_pxm.cpp b/modules/imgcodecs/src/grfmt_pxm.cpp index b7186ce223..7c5c9910be 100644 --- a/modules/imgcodecs/src/grfmt_pxm.cpp +++ b/modules/imgcodecs/src/grfmt_pxm.cpp @@ -245,7 +245,7 @@ bool PxMDecoder::readData( Mat& img ) if( !m_binary ) { AutoBuffer _src(m_width); - uchar* src = _src; + uchar* src = _src.data(); for (int y = 0; y < m_height; y++, data += img.step) { @@ -261,7 +261,7 @@ bool PxMDecoder::readData( Mat& img ) else { AutoBuffer _src(src_pitch); - uchar* src = _src; + uchar* src = _src.data(); for (int y = 0; y < m_height; y++, data += img.step) { @@ -281,7 +281,7 @@ bool PxMDecoder::readData( Mat& img ) case 24: { AutoBuffer _src(std::max(width3*2, src_pitch)); - uchar* src = _src; + uchar* src = _src.data(); for (int y = 0; y < m_height; y++, data += img.step) { @@ -463,7 +463,7 @@ bool PxMEncoder::write(const Mat& img, const std::vector& params) bufferSize = lineLength; AutoBuffer _buffer(bufferSize); - char* buffer = _buffer; + char* buffer = _buffer.data(); // write header; const int code = ((mode == PXM_TYPE_PBM) ? 1 : (mode == PXM_TYPE_PGM) ? 2 : 3) diff --git a/modules/imgcodecs/src/grfmt_sunras.cpp b/modules/imgcodecs/src/grfmt_sunras.cpp index b419b7795a..ec17685850 100644 --- a/modules/imgcodecs/src/grfmt_sunras.cpp +++ b/modules/imgcodecs/src/grfmt_sunras.cpp @@ -174,7 +174,7 @@ bool SunRasterDecoder::readData( Mat& img ) return false; AutoBuffer _src(src_pitch + 32); - uchar* src = _src; + uchar* src = _src.data(); if( !color && m_maptype == RMT_EQUAL_RGB ) CvtPaletteToGray( m_palette, gray_palette, 1 << m_bpp ); diff --git a/modules/imgcodecs/src/grfmt_tiff.cpp b/modules/imgcodecs/src/grfmt_tiff.cpp index 901bfce17a..8dcbe5b672 100644 --- a/modules/imgcodecs/src/grfmt_tiff.cpp +++ b/modules/imgcodecs/src/grfmt_tiff.cpp @@ -355,7 +355,7 @@ bool TiffDecoder::readData( Mat& img ) } const size_t buffer_size = (bpp/bitsPerByte) * ncn * tile_height0 * tile_width0; AutoBuffer _buffer( buffer_size ); - uchar* buffer = _buffer; + uchar* buffer = _buffer.data(); ushort* buffer16 = (ushort*)buffer; float* buffer32 = (float*)buffer; double* buffer64 = (double*)buffer; @@ -834,7 +834,7 @@ bool TiffEncoder::writeLibTiff( const std::vector& img_vec, const std::vect // row buffer, because TIFFWriteScanline modifies the original data! size_t scanlineSize = TIFFScanlineSize(pTiffHandle); AutoBuffer _buffer(scanlineSize + 32); - uchar* buffer = _buffer; + uchar* buffer = _buffer.data(); if (!buffer) { TIFFClose(pTiffHandle); diff --git a/modules/imgproc/src/approx.cpp b/modules/imgproc/src/approx.cpp index 49b77551a1..0af613d666 100644 --- a/modules/imgproc/src/approx.cpp +++ b/modules/imgproc/src/approx.cpp @@ -63,7 +63,7 @@ CvSeq* icvApproximateChainTC89( CvChain* chain, int header_size, cv::AutoBuffer<_CvPtInfo> buf(chain->total + 8); _CvPtInfo temp; - _CvPtInfo *array = buf, *first = 0, *current = 0, *prev_current = 0; + _CvPtInfo *array = buf.data(), *first = 0, *current = 0, *prev_current = 0; int i, j, i1, i2, s, len; int count = chain->total; @@ -475,14 +475,14 @@ namespace cv template static int approxPolyDP_( const Point_* src_contour, int count0, Point_* dst_contour, - bool is_closed0, double eps, AutoBuffer* _stack ) + bool is_closed0, double eps, AutoBuffer& _stack ) { #define PUSH_SLICE(slice) \ if( top >= stacksz ) \ { \ - _stack->resize(stacksz*3/2); \ - stack = *_stack; \ - stacksz = _stack->size(); \ + _stack.resize(stacksz*3/2); \ + stack = _stack.data(); \ + stacksz = _stack.size(); \ } \ stack[top++] = slice @@ -504,8 +504,8 @@ approxPolyDP_( const Point_* src_contour, int count0, Point_* dst_contour, int i = 0, j, pos = 0, wpos, count = count0, new_count=0; int is_closed = is_closed0; bool le_eps = false; - size_t top = 0, stacksz = _stack->size(); - Range* stack = *_stack; + size_t top = 0, stacksz = _stack.size(); + Range* stack = _stack.data(); if( count == 0 ) return 0; @@ -689,13 +689,13 @@ void cv::approxPolyDP( InputArray _curve, OutputArray _approxCurve, AutoBuffer _buf(npoints); AutoBuffer _stack(npoints); - Point* buf = _buf; + Point* buf = _buf.data(); int nout = 0; if( depth == CV_32S ) - nout = approxPolyDP_(curve.ptr(), npoints, buf, closed, epsilon, &_stack); + nout = approxPolyDP_(curve.ptr(), npoints, buf, closed, epsilon, _stack); else if( depth == CV_32F ) - nout = approxPolyDP_(curve.ptr(), npoints, (Point2f*)buf, closed, epsilon, &_stack); + nout = approxPolyDP_(curve.ptr(), npoints, (Point2f*)buf, closed, epsilon, _stack); else CV_Error( CV_StsUnsupportedFormat, "" ); @@ -783,7 +783,7 @@ cvApproxPoly( const void* array, int header_size, { int npoints = src_seq->total, nout = 0; _buf.allocate(npoints*2); - cv::Point *src = _buf, *dst = src + npoints; + cv::Point *src = _buf.data(), *dst = src + npoints; bool closed = CV_IS_SEQ_CLOSED(src_seq); if( src_seq->first->next == src_seq->first ) @@ -792,10 +792,10 @@ cvApproxPoly( const void* array, int header_size, cvCvtSeqToArray(src_seq, src); if( CV_SEQ_ELTYPE(src_seq) == CV_32SC2 ) - nout = cv::approxPolyDP_(src, npoints, dst, closed, parameter, &stack); + nout = cv::approxPolyDP_(src, npoints, dst, closed, parameter, stack); else if( CV_SEQ_ELTYPE(src_seq) == CV_32FC2 ) nout = cv::approxPolyDP_((cv::Point2f*)src, npoints, - (cv::Point2f*)dst, closed, parameter, &stack); + (cv::Point2f*)dst, closed, parameter, stack); else CV_Error( CV_StsUnsupportedFormat, "" ); diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 1d413726b8..eaea6b2f8f 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -390,21 +390,21 @@ public: { dxMax.allocate(2 * dx.cols); dyMax.allocate(2 * dy.cols); - _dx_a = (short*)dxMax; + _dx_a = dxMax.data(); _dx_n = _dx_a + dx.cols; - _dy_a = (short*)dyMax; + _dy_a = dyMax.data(); _dy_n = _dy_a + dy.cols; } // _mag_p: previous row, _mag_a: actual row, _mag_n: next row #if CV_SIMD128 AutoBuffer buffer(3 * (mapstep * cn + CV_MALLOC_SIMD128)); - _mag_p = alignPtr((int*)buffer + 1, CV_MALLOC_SIMD128); + _mag_p = alignPtr(buffer.data() + 1, CV_MALLOC_SIMD128); _mag_a = alignPtr(_mag_p + mapstep * cn, CV_MALLOC_SIMD128); _mag_n = alignPtr(_mag_a + mapstep * cn, CV_MALLOC_SIMD128); #else AutoBuffer buffer(3 * (mapstep * cn)); - _mag_p = (int*)buffer + 1; + _mag_p = buffer.data() + 1; _mag_a = _mag_p + mapstep * cn; _mag_n = _mag_a + mapstep * cn; #endif diff --git a/modules/imgproc/src/clahe.cpp b/modules/imgproc/src/clahe.cpp index fffc194ff7..84ea287193 100644 --- a/modules/imgproc/src/clahe.cpp +++ b/modules/imgproc/src/clahe.cpp @@ -230,7 +230,7 @@ namespace src_(src), dst_(dst), lut_(lut), tileSize_(tileSize), tilesX_(tilesX), tilesY_(tilesY) { buf.allocate(src.cols << 2); - ind1_p = (int *)buf; + ind1_p = buf.data(); ind2_p = ind1_p + src.cols; xa_p = (float *)(ind2_p + src.cols); xa1_p = xa_p + src.cols; diff --git a/modules/imgproc/src/color_lab.cpp b/modules/imgproc/src/color_lab.cpp index 61e30a9dac..10640d5e0c 100644 --- a/modules/imgproc/src/color_lab.cpp +++ b/modules/imgproc/src/color_lab.cpp @@ -1398,7 +1398,7 @@ static LABLUVLUT_s16_t initLUTforLABLUVs16(const softfloat & un, const softfloat for (int p_ = 0; p_ < 2; ++p_) for (int q_ = 0; q_ < 2; ++q_) for (int r_ = 0; r_ < 2; ++r_) - fill_one(RGB2LabLUT_s16, RGB2Labprev, RGB2LuvLUT_s16, RGB2Luvprev, p, q, r, p_, q_, r_); + fill_one(RGB2LabLUT_s16, RGB2Labprev.data(), RGB2LuvLUT_s16, RGB2Luvprev.data(), p, q, r, p_, q_, r_); LABLUVLUT_s16_t res; res.RGB2LabLUT_s16 = RGB2LabLUT_s16; res.RGB2LuvLUT_s16 = RGB2LuvLUT_s16; diff --git a/modules/imgproc/src/convhull.cpp b/modules/imgproc/src/convhull.cpp index 5f816efe84..e1db7164d1 100644 --- a/modules/imgproc/src/convhull.cpp +++ b/modules/imgproc/src/convhull.cpp @@ -147,11 +147,11 @@ void convexHull( InputArray _points, OutputArray _hull, bool clockwise, bool ret bool is_float = depth == CV_32F; AutoBuffer _pointer(total); AutoBuffer _stack(total + 2), _hullbuf(total); - Point** pointer = _pointer; + Point** pointer = _pointer.data(); Point2f** pointerf = (Point2f**)pointer; Point* data0 = points.ptr(); - int* stack = _stack; - int* hullbuf = _hullbuf; + int* stack = _stack.data(); + int* hullbuf = _hullbuf.data(); CV_Assert(points.isContinuous()); diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index e784fa2403..8d1857fa3d 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -542,7 +542,7 @@ static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockS if (ok >= 0) { AutoBuffer buffer(bufferSize); - ok = CV_INSTRUMENT_FUN_IPP(ippiMinEigenVal_C1R, src.ptr(), (int) src.step, dst.ptr(), (int) dst.step, srcRoi, kerType, kerSize, blockSize, buffer); + ok = CV_INSTRUMENT_FUN_IPP(ippiMinEigenVal_C1R, src.ptr(), (int) src.step, dst.ptr(), (int) dst.step, srcRoi, kerType, kerSize, blockSize, buffer.data()); CV_SUPPRESS_DEPRECATED_START if (ok >= 0) ok = CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1IR, norm_coef, dst.ptr(), (int) dst.step, srcRoi); CV_SUPPRESS_DEPRECATED_END diff --git a/modules/imgproc/src/demosaicing.cpp b/modules/imgproc/src/demosaicing.cpp index 05920d2150..f70f3e8dfa 100644 --- a/modules/imgproc/src/demosaicing.cpp +++ b/modules/imgproc/src/demosaicing.cpp @@ -976,7 +976,7 @@ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code ) int N = size.width, N2 = N*2, N3 = N*3, N4 = N*4, N5 = N*5, N6 = N*6, N7 = N*7; int i, bufstep = N7*bcn; cv::AutoBuffer _buf(bufstep*brows); - ushort* buf = (ushort*)_buf; + ushort* buf = _buf.data(); bayer += bstep*2; diff --git a/modules/imgproc/src/distransform.cpp b/modules/imgproc/src/distransform.cpp index 8e7774ae48..b91f9b88ff 100644 --- a/modules/imgproc/src/distransform.cpp +++ b/modules/imgproc/src/distransform.cpp @@ -458,7 +458,7 @@ struct DTColumnInvoker : ParallelLoopBody int m = src->rows; size_t sstep = src->step, dstep = dst->step/sizeof(float); AutoBuffer _d(m); - int* d = _d; + int* d = _d.data(); for( i = i1; i < i2; i++ ) { @@ -503,7 +503,7 @@ struct DTRowInvoker : ParallelLoopBody int i, i1 = range.start, i2 = range.end; int n = dst->cols; AutoBuffer _buf((n+2)*2*sizeof(float) + (n+2)*sizeof(int)); - float* f = (float*)(uchar*)_buf; + float* f = (float*)_buf.data(); float* z = f + n; int* v = alignPtr((int*)(z + n + 1), sizeof(int)); @@ -564,7 +564,7 @@ trueDistTrans( const Mat& src, Mat& dst ) cv::AutoBuffer _buf(std::max(m*2*sizeof(float) + (m*3+1)*sizeof(int), n*2*sizeof(float))); // stage 1: compute 1d distance transform of each column - float* sqr_tab = (float*)(uchar*)_buf; + float* sqr_tab = (float*)_buf.data(); int* sat_tab = cv::alignPtr((int*)(sqr_tab + m*2), sizeof(int)); int shift = m*2; diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index 05a9150d77..b71b9209c5 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -2398,8 +2398,8 @@ void cv::fillPoly(InputOutputArray _img, InputArrayOfArrays pts, return; AutoBuffer _ptsptr(ncontours); AutoBuffer _npts(ncontours); - Point** ptsptr = _ptsptr; - int* npts = _npts; + Point** ptsptr = _ptsptr.data(); + int* npts = _npts.data(); for( i = 0; i < ncontours; i++ ) { @@ -2426,8 +2426,8 @@ void cv::polylines(InputOutputArray _img, InputArrayOfArrays pts, return; AutoBuffer _ptsptr(ncontours); AutoBuffer _npts(ncontours); - Point** ptsptr = _ptsptr; - int* npts = _npts; + Point** ptsptr = _ptsptr.data(); + int* npts = _npts.data(); for( i = 0; i < ncontours; i++ ) { diff --git a/modules/imgproc/src/emd.cpp b/modules/imgproc/src/emd.cpp index a87c440111..0b985a066e 100644 --- a/modules/imgproc/src/emd.cpp +++ b/modules/imgproc/src/emd.cpp @@ -359,7 +359,7 @@ static int icvInitEMD( const float* signature1, int size1, /* allocate buffers */ _buffer.allocate(buffer_size); - state->buffer = buffer = _buffer; + state->buffer = buffer = _buffer.data(); buffer_end = buffer + buffer_size; state->idx1 = (int*) buffer; diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index d83c2a03ac..23c560736a 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -1444,7 +1444,7 @@ private: return 0; } AutoBuffer buf(bufsz + 64); - uchar* bufptr = alignPtr((uchar*)buf, 32); + uchar* bufptr = alignPtr(buf.data(), 32); int step = (int)(width*sizeof(dst[0])*cn); float borderValue[] = {0.f, 0.f, 0.f}; // here is the trick. IPP needs border type and extrapolates the row. We did it already. diff --git a/modules/imgproc/src/geometry.cpp b/modules/imgproc/src/geometry.cpp index e2ace817b4..421fa64ed3 100644 --- a/modules/imgproc/src/geometry.cpp +++ b/modules/imgproc/src/geometry.cpp @@ -524,7 +524,7 @@ float cv::intersectConvexConvex( InputArray _p1, InputArray _p2, OutputArray _p1 } AutoBuffer _result(n*2 + m*2 + 1); - Point2f *fp1 = _result, *fp2 = fp1 + n; + Point2f *fp1 = _result.data(), *fp2 = fp1 + n; Point2f* result = fp2 + m; int orientation = 0; diff --git a/modules/imgproc/src/hough.cpp b/modules/imgproc/src/hough.cpp index 1f61146193..18c532253f 100644 --- a/modules/imgproc/src/hough.cpp +++ b/modules/imgproc/src/hough.cpp @@ -165,11 +165,11 @@ HoughLinesStandard( InputArray src, OutputArray lines, int type, AutoBuffer _tabSin(numangle); AutoBuffer _tabCos(numangle); int *accum = _accum.ptr(); - float *tabSin = _tabSin, *tabCos = _tabCos; + float *tabSin = _tabSin.data(), *tabCos = _tabCos.data(); // create sin and cos table createTrigTable( numangle, min_theta, theta, - irho, tabSin, tabCos ); + irho, tabSin, tabCos); // stage 1. fill accumulator for( i = 0; i < height; i++ ) @@ -963,7 +963,7 @@ void HoughLinesPointSet( InputArray _point, OutputArray _lines, int lines_max, i AutoBuffer _tabSin(numangle); AutoBuffer _tabCos(numangle); int *accum = _accum.ptr(); - float *tabSin = _tabSin, *tabCos = _tabCos; + float *tabSin = _tabSin.data(), *tabCos = _tabCos.data(); // create sin and cos table createTrigTable( numangle, min_theta, theta_step, @@ -1408,8 +1408,8 @@ protected: int nBins = cvRound((maxRadius - minRadius)/dr*nBinsPerDr); AutoBuffer bins(nBins); AutoBuffer distBuf(nzSz), distSqrtBuf(nzSz); - float *ddata = distBuf; - float *dSqrtData = distSqrtBuf; + float *ddata = distBuf.data(); + float *dSqrtData = distSqrtBuf.data(); bool singleThread = (boundaries == Range(0, centerSz)); int i = boundaries.start; @@ -1434,7 +1434,7 @@ protected: Mat_ distSqrtMat(1, nzCount, dSqrtData); sqrt(distMat, distSqrtMat); - memset(bins, 0, sizeof(bins[0])*bins.size()); + memset(bins.data(), 0, sizeof(bins[0])*bins.size()); for(int k = 0; k < nzCount; k++) { int bin = std::max(0, std::min(nBins-1, cvRound((dSqrtData[k] - minRadius)/dr*nBinsPerDr))); diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index adc201acbe..9e069bc84d 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -228,7 +228,7 @@ static const void* initInterTab2D( int method, bool fixpt ) { AutoBuffer _tab(8*INTER_TAB_SIZE); int i, j, k1, k2; - initInterTab1D(method, _tab, INTER_TAB_SIZE); + initInterTab1D(method, _tab.data(), INTER_TAB_SIZE); for( i = 0; i < INTER_TAB_SIZE; i++ ) for( j = 0; j < INTER_TAB_SIZE; j++, tab += ksize*ksize, itab += ksize*ksize ) { diff --git a/modules/imgproc/src/linefit.cpp b/modules/imgproc/src/linefit.cpp index c073e26cb0..246d693586 100644 --- a/modules/imgproc/src/linefit.cpp +++ b/modules/imgproc/src/linefit.cpp @@ -360,7 +360,7 @@ static void fitLine2D( const Point2f * points, int count, int dist, } AutoBuffer wr(count*2); - float *w = wr, *r = w + count; + float *w = wr.data(), *r = w + count; for( k = 0; k < 20; k++ ) { @@ -495,7 +495,7 @@ static void fitLine3D( Point3f * points, int count, int dist, } AutoBuffer buf(count*2); - float *w = buf, *r = w + count; + float *w = buf.data(), *r = w + count; for( k = 0; k < 20; k++ ) { diff --git a/modules/imgproc/src/phasecorr.cpp b/modules/imgproc/src/phasecorr.cpp index 71299bbb36..52aeb9208a 100644 --- a/modules/imgproc/src/phasecorr.cpp +++ b/modules/imgproc/src/phasecorr.cpp @@ -607,7 +607,7 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type) int rows = dst.rows, cols = dst.cols; AutoBuffer _wc(cols); - double * const wc = (double *)_wc; + double* const wc = _wc.data(); double coeff0 = 2.0 * CV_PI / (double)(cols - 1), coeff1 = 2.0f * CV_PI / (double)(rows - 1); for(int j = 0; j < cols; j++) diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index 7ece7f5537..def3dc1d68 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -860,10 +860,10 @@ pyrDown_( const Mat& _src, Mat& _dst, int borderType ) int cn = _src.channels(); int bufstep = (int)alignSize(dsize.width*cn, 16); AutoBuffer _buf(bufstep*PD_SZ + 16); - WT* buf = alignPtr((WT*)_buf, 16); + WT* buf = alignPtr((WT*)_buf.data(), 16); int tabL[CV_CN_MAX*(PD_SZ+2)], tabR[CV_CN_MAX*(PD_SZ+2)]; AutoBuffer _tabM(dsize.width*cn); - int* tabM = _tabM; + int* tabM = _tabM.data(); WT* rows[PD_SZ]; CastOp castOp; VecOp vecOp; @@ -984,9 +984,9 @@ pyrUp_( const Mat& _src, Mat& _dst, int) int cn = _src.channels(); int bufstep = (int)alignSize((dsize.width+1)*cn, 16); AutoBuffer _buf(bufstep*PU_SZ + 16); - WT* buf = alignPtr((WT*)_buf, 16); + WT* buf = alignPtr((WT*)_buf.data(), 16); AutoBuffer _dtab(ssize.width*cn); - int* dtab = _dtab; + int* dtab = _dtab.data(); WT* rows[PU_SZ]; T* dsts[2]; CastOp castOp; diff --git a/modules/imgproc/src/resize.cpp b/modules/imgproc/src/resize.cpp index 0d57e1a933..016fff03d9 100644 --- a/modules/imgproc/src/resize.cpp +++ b/modules/imgproc/src/resize.cpp @@ -686,18 +686,18 @@ public: { last_eval = 1 - interp_y_len; evalbuf_start = 1; - hResize((ET*)src, cn, xoffsets, xcoeffs, (fixedpoint*)linebuf, min_x, max_x, dst_width); + hResize((ET*)src, cn, xoffsets, xcoeffs, linebuf.data(), min_x, max_x, dst_width); } int dy = range.start; for (; dy < rmin_y; dy++) - vlineSet((fixedpoint*)linebuf, (ET*)(dst + dst_step * dy), dst_width*cn); + vlineSet(linebuf.data(), (ET*)(dst + dst_step * dy), dst_width*cn); for (; dy < rmax_y; dy++) { int &iy = yoffsets[dy]; int i; for (i = max(iy, last_eval + interp_y_len); i < min(iy + interp_y_len, src_height); i++, evalbuf_start = (evalbuf_start + 1) % interp_y_len) - hResize((ET*)(src + i * src_step), cn, xoffsets, xcoeffs, (fixedpoint*)linebuf + evalbuf_start*(dst_width * cn), min_x, max_x, dst_width); + hResize((ET*)(src + i * src_step), cn, xoffsets, xcoeffs, linebuf.data() + evalbuf_start*(dst_width * cn), min_x, max_x, dst_width); evalbuf_start = (evalbuf_start + max(iy, src_height - interp_y_len) - max(last_eval, src_height - interp_y_len)) % interp_y_len; last_eval = iy; @@ -707,9 +707,9 @@ public: for (; i < interp_y_len; i++) curcoeffs[i] = ycoeffs[ dy*interp_y_len - evalbuf_start + i]; - vlineResize((fixedpoint*)linebuf, dst_width*cn, curcoeffs, (ET*)(dst + dst_step * dy), dst_width*cn); + vlineResize(linebuf.data(), dst_width*cn, curcoeffs, (ET*)(dst + dst_step * dy), dst_width*cn); } - fixedpoint *endline = (fixedpoint*)linebuf; + fixedpoint *endline = linebuf.data(); if (last_eval + interp_y_len > src_height) endline += dst_width*cn*((evalbuf_start + src_height - 1 - last_eval) % interp_y_len); else @@ -757,7 +757,7 @@ void resize_bitExact(const uchar* src, size_t src_step, int src_width, int src_h dst_height * sizeof(int) + dst_width * interp_x.len*sizeof(fixedpoint) + dst_height * interp_y.len * sizeof(fixedpoint) ); - int* xoffsets = (int*)((uchar*)buf); + int* xoffsets = (int*)buf.data(); int* yoffsets = xoffsets + dst_width; fixedpoint* xcoeffs = (fixedpoint*)(yoffsets + dst_height); fixedpoint* ycoeffs = xcoeffs + dst_width * interp_x.len; @@ -950,7 +950,7 @@ resizeNN( const Mat& src, Mat& dst, double fx, double fy ) { Size ssize = src.size(), dsize = dst.size(); AutoBuffer _x_ofs(dsize.width); - int* x_ofs = _x_ofs; + int* x_ofs = _x_ofs.data(); int pix_size = (int)src.elemSize(); int pix_size4 = (int)(pix_size / sizeof(int)); double ifx = 1./fx, ify = 1./fy; @@ -2226,7 +2226,7 @@ public: for(int k = 0; k < ksize; k++ ) { prev_sy[k] = -1; - rows[k] = (WT*)_buffer + bufstep*k; + rows[k] = _buffer.data() + bufstep*k; } const AT* beta = _beta + ksize * range.start; @@ -3039,7 +3039,7 @@ public: AutoBuffer _buffer(dsize.width*2); const DecimateAlpha* xtab = xtab0; int xtab_size = xtab_size0; - WT *buf = _buffer, *sum = buf + dsize.width; + WT *buf = _buffer.data(), *sum = buf + dsize.width; int j_start = tabofs[range.start], j_end = tabofs[range.end], j, k, dx, prev_dy = ytab[j_start].di; for( dx = 0; dx < dsize.width; dx++ ) @@ -3322,7 +3322,7 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, if (depth == CV_8U && ((void)0, 0)) { AutoBuffer _buffer((dsize.width + dsize.height)*(sizeof(int) + sizeof(short)*2)); - int* xofs = (int*)(uchar*)_buffer, * yofs = xofs + dsize.width; + int* xofs = (int*)_buffer.data(), * yofs = xofs + dsize.width; short* ialpha = (short*)(yofs + dsize.height), * ibeta = ialpha + dsize.width*2; float fxx, fyy; int sx, sy; @@ -3357,7 +3357,7 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, int wdepth = std::max(depth, CV_32S), wtype = CV_MAKETYPE(wdepth, cn); UMat coeffs; - Mat(1, static_cast(_buffer.size()), CV_8UC1, (uchar *)_buffer).copyTo(coeffs); + Mat(1, static_cast(_buffer.size()), CV_8UC1, _buffer.data()).copyTo(coeffs); k.create("resizeLN", ocl::imgproc::resize_oclsrc, format("-D INTER_LINEAR_INTEGER -D depth=%d -D T=%s -D T1=%s " @@ -3440,17 +3440,17 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, AutoBuffer _xymap_tab(xytab_size), _xyofs_tab(tabofs_size); AutoBuffer _xyalpha_tab(xytab_size); - int * xmap_tab = _xymap_tab, * ymap_tab = _xymap_tab + (ssize.width << 1); - float * xalpha_tab = _xyalpha_tab, * yalpha_tab = _xyalpha_tab + (ssize.width << 1); - int * xofs_tab = _xyofs_tab, * yofs_tab = _xyofs_tab + dsize.width + 1; + int * xmap_tab = _xymap_tab.data(), * ymap_tab = _xymap_tab.data() + (ssize.width << 1); + float * xalpha_tab = _xyalpha_tab.data(), * yalpha_tab = _xyalpha_tab.data() + (ssize.width << 1); + int * xofs_tab = _xyofs_tab.data(), * yofs_tab = _xyofs_tab.data() + dsize.width + 1; ocl_computeResizeAreaTabs(ssize.width, dsize.width, inv_fx, xmap_tab, xalpha_tab, xofs_tab); ocl_computeResizeAreaTabs(ssize.height, dsize.height, inv_fy, ymap_tab, yalpha_tab, yofs_tab); // loading precomputed arrays to GPU - Mat(1, xytab_size, CV_32FC1, (void *)_xyalpha_tab).copyTo(alphaOcl); - Mat(1, xytab_size, CV_32SC1, (void *)_xymap_tab).copyTo(mapOcl); - Mat(1, tabofs_size, CV_32SC1, (void *)_xyofs_tab).copyTo(tabofsOcl); + Mat(1, xytab_size, CV_32FC1, _xyalpha_tab.data()).copyTo(alphaOcl); + Mat(1, xytab_size, CV_32SC1, _xymap_tab.data()).copyTo(mapOcl); + Mat(1, tabofs_size, CV_32SC1, _xyofs_tab.data()).copyTo(tabofsOcl); } ocl::KernelArg srcarg = ocl::KernelArg::ReadOnly(src), dstarg = ocl::KernelArg::WriteOnly(dst); @@ -3856,7 +3856,7 @@ void resize(int src_type, int area = iscale_x*iscale_y; size_t srcstep = src_step / src.elemSize1(); AutoBuffer _ofs(area + dsize.width*cn); - int* ofs = _ofs; + int* ofs = _ofs.data(); int* xofs = ofs + area; ResizeAreaFastFunc func = areafast_tab[depth]; CV_Assert( func != 0 ); @@ -3881,13 +3881,13 @@ void resize(int src_type, CV_Assert( func != 0 && cn <= 4 ); AutoBuffer _xytab((src_width + src_height)*2); - DecimateAlpha* xtab = _xytab, *ytab = xtab + src_width*2; + DecimateAlpha* xtab = _xytab.data(), *ytab = xtab + src_width*2; int xtab_size = computeResizeAreaTab(src_width, dsize.width, cn, scale_x, xtab); int ytab_size = computeResizeAreaTab(src_height, dsize.height, 1, scale_y, ytab); AutoBuffer _tabofs(dsize.height + 1); - int* tabofs = _tabofs; + int* tabofs = _tabofs.data(); for( k = 0, dy = 0; k < ytab_size; k++ ) { if( k == 0 || ytab[k].di != ytab[k-1].di ) @@ -3922,7 +3922,7 @@ void resize(int src_type, CV_Assert( func != 0 ); AutoBuffer _buffer((width + dsize.height)*(sizeof(int) + sizeof(float)*ksize)); - int* xofs = (int*)(uchar*)_buffer; + int* xofs = (int*)_buffer.data(); int* yofs = xofs + width; float* alpha = (float*)(yofs + dsize.height); short* ialpha = (short*)alpha; diff --git a/modules/imgproc/src/rotcalipers.cpp b/modules/imgproc/src/rotcalipers.cpp index 28b854ac9b..487e1d6243 100644 --- a/modules/imgproc/src/rotcalipers.cpp +++ b/modules/imgproc/src/rotcalipers.cpp @@ -96,7 +96,7 @@ static void rotatingCalipers( const Point2f* points, int n, int mode, float* out char buffer[32] = {}; int i, k; AutoBuffer abuf(n*3); - float* inv_vect_length = abuf; + float* inv_vect_length = abuf.data(); Point2f* vect = (Point2f*)(inv_vect_length + n); int left = 0, bottom = 0, right = 0, top = 0; int seq[4] = { -1, -1, -1, -1 }; diff --git a/modules/imgproc/src/shapedescr.cpp b/modules/imgproc/src/shapedescr.cpp index bac5f75c81..460a61f9f5 100644 --- a/modules/imgproc/src/shapedescr.cpp +++ b/modules/imgproc/src/shapedescr.cpp @@ -318,7 +318,7 @@ cv::RotatedRect cv::fitEllipse( InputArray _points ) const Point2f* ptsf = points.ptr(); AutoBuffer _Ad(n*5), _bd(n); - double *Ad = _Ad, *bd = _bd; + double *Ad = _Ad.data(), *bd = _bd.data(); // first fit for parameters A - E Mat A( n, 5, CV_64F, Ad ); diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 9ac01b7172..2bcc4b2789 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -3614,9 +3614,9 @@ public: virtual void operator() (const Range& range) const CV_OVERRIDE { AutoBuffer _buf(width*cn*kylen); - FT* buf = _buf; + FT* buf = _buf.data(); AutoBuffer _ptrs(kylen*2); - FT** ptrs = _ptrs; + FT** ptrs = _ptrs.data(); if (kylen == 1) { diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index 40918da527..4122b1ae54 100755 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -216,7 +216,7 @@ void integral_( const T* src, size_t _srcstep, ST* sum, size_t _sumstep, else { AutoBuffer _buf(width+cn); - ST* buf = _buf; + ST* buf = _buf.data(); ST s; QT sq; for( k = 0; k < cn; k++, src++, sum++, tilted++, buf++ ) diff --git a/modules/imgproc/test/test_convhull.cpp b/modules/imgproc/test/test_convhull.cpp index 1fb34f5831..7ad2f5fff7 100644 --- a/modules/imgproc/test/test_convhull.cpp +++ b/modules/imgproc/test/test_convhull.cpp @@ -1584,7 +1584,7 @@ int CV_FitLineTest::prepare_test_case( int test_case_idx ) void CV_FitLineTest::run_func() { if(!test_cpp) - cvFitLine( points, dist_type, 0, reps, aeps, line ); + cvFitLine( points, dist_type, 0, reps, aeps, line.data()); else if(dims == 2) cv::fitLine(cv::cvarrToMat(points), (cv::Vec4f&)line[0], dist_type, 0, reps, aeps); else diff --git a/modules/ml/src/ann_mlp.cpp b/modules/ml/src/ann_mlp.cpp index 156a0440ba..a83c615578 100644 --- a/modules/ml/src/ann_mlp.cpp +++ b/modules/ml/src/ann_mlp.cpp @@ -434,7 +434,7 @@ public: } cv::AutoBuffer _buf(buf_sz+noutputs); - double* buf = _buf; + double* buf = _buf.data(); if( !_outputs.needed() ) { @@ -996,7 +996,7 @@ public: _idx[i] = i; AutoBuffer _buf(max_lsize*2); - double* buf[] = { _buf, (double*)_buf + max_lsize }; + double* buf[] = { _buf.data(), _buf.data() + max_lsize }; const double* sw = _sw.empty() ? 0 : _sw.ptr(); diff --git a/modules/ml/src/boost.cpp b/modules/ml/src/boost.cpp index 66e87f6e1c..b3e8c2724a 100644 --- a/modules/ml/src/boost.cpp +++ b/modules/ml/src/boost.cpp @@ -205,7 +205,7 @@ public: int nvars = (int)varIdx.size(); double sumw = 0., C = 1.; cv::AutoBuffer buf(n + nvars); - double* result = buf; + double* result = buf.data(); float* sbuf = (float*)(result + n); Mat sample(1, nvars, CV_32F, sbuf); int predictFlags = bparams.boostType == Boost::DISCRETE ? (PREDICT_MAX_VOTE | RAW_OUTPUT) : PREDICT_SUM; diff --git a/modules/ml/src/data.cpp b/modules/ml/src/data.cpp index cbd1c3fde5..852d5c6a5b 100644 --- a/modules/ml/src/data.cpp +++ b/modules/ml/src/data.cpp @@ -335,7 +335,7 @@ public: CatMapHash ofshash; AutoBuffer buf(nsamples); - Mat non_missing(layout == ROW_SAMPLE ? Size(1, nsamples) : Size(nsamples, 1), CV_8U, (uchar*)buf); + Mat non_missing(layout == ROW_SAMPLE ? Size(1, nsamples) : Size(nsamples, 1), CV_8U, buf.data()); bool haveMissing = !missing.empty(); if( haveMissing ) { diff --git a/modules/ml/src/kdtree.cpp b/modules/ml/src/kdtree.cpp index 9ab61e4d6b..1ab8400936 100644 --- a/modules/ml/src/kdtree.cpp +++ b/modules/ml/src/kdtree.cpp @@ -285,13 +285,13 @@ int KDTree::findNearest(InputArray _vec, int K, int emax, CV_Assert(K > 0 && (normType == NORM_L2 || normType == NORM_L1)); AutoBuffer _buf((K+1)*(sizeof(float) + sizeof(int))); - int* idx = (int*)(uchar*)_buf; + int* idx = (int*)_buf.data(); float* dist = (float*)(idx + K + 1); int i, j, ncount = 0, e = 0; int qsize = 0, maxqsize = 1 << 10; AutoBuffer _pqueue(maxqsize*sizeof(PQueueElem)); - PQueueElem* pqueue = (PQueueElem*)(uchar*)_pqueue; + PQueueElem* pqueue = (PQueueElem*)_pqueue.data(); emax = std::max(emax, 1); for( e = 0; e < emax; ) @@ -433,7 +433,7 @@ void KDTree::findOrthoRange(InputArray _lowerBound, std::vector idx; AutoBuffer _stack(MAX_TREE_DEPTH*2 + 1); - int* stack = _stack; + int* stack = _stack.data(); int top = 0; stack[top++] = 0; diff --git a/modules/ml/src/knearest.cpp b/modules/ml/src/knearest.cpp index 30a0951bf3..d608012dfb 100644 --- a/modules/ml/src/knearest.cpp +++ b/modules/ml/src/knearest.cpp @@ -149,7 +149,7 @@ public: int k = std::min(k0, nsamples); AutoBuffer buf(testcount*k*2); - float* dbuf = buf; + float* dbuf = buf.data(); float* rbuf = dbuf + testcount*k; const float* rptr = responses.ptr(); diff --git a/modules/ml/src/nbayes.cpp b/modules/ml/src/nbayes.cpp index 2b6467a6fe..baa46d8f0a 100644 --- a/modules/ml/src/nbayes.cpp +++ b/modules/ml/src/nbayes.cpp @@ -241,8 +241,8 @@ public: } // allocate memory and initializing headers for calculating cv::AutoBuffer _buffer(nvars*2); - double* _diffin = _buffer; - double* _diffout = _buffer + nvars; + double* _diffin = _buffer.data(); + double* _diffout = _buffer.data() + nvars; Mat diffin( 1, nvars, CV_64FC1, _diffin ); Mat diffout( 1, nvars, CV_64FC1, _diffout ); diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index d6518ef013..330831c0dc 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -1579,7 +1579,7 @@ public: return; AutoBuffer vbuf(var_count); - double* v = vbuf; + double* v = vbuf.data(); Mat new_sv(df_count, var_count, CV_32F); vector new_df; @@ -1914,7 +1914,7 @@ public: int class_count = !svm->class_labels.empty() ? (int)svm->class_labels.total() : svmType == ONE_CLASS ? 1 : 0; AutoBuffer _buffer(sv_total + (class_count+1)*2); - float* buffer = _buffer; + float* buffer = _buffer.data(); int i, j, dfi, k, si; diff --git a/modules/ml/src/tree.cpp b/modules/ml/src/tree.cpp index 6a596551ea..da76a81f87 100644 --- a/modules/ml/src/tree.cpp +++ b/modules/ml/src/tree.cpp @@ -417,7 +417,7 @@ int DTreesImpl::findBestSplit( const vector& _sidx ) int splitidx = -1; int vi_, nv = (int)activeVars.size(); AutoBuffer buf(w->maxSubsetSize*2); - int *subset = buf, *best_subset = subset + w->maxSubsetSize; + int *subset = buf.data(), *best_subset = subset + w->maxSubsetSize; WSplit split, best_split; best_split.quality = 0.; @@ -488,7 +488,7 @@ void DTreesImpl::calcValue( int nidx, const vector& _sidx ) // misclassified samples with cv_labels(*)==j. // compute the number of instances of each class - double* cls_count = buf; + double* cls_count = buf.data(); double* cv_cls_count = cls_count + m; double max_val = -1, total_weight = 0; @@ -592,7 +592,7 @@ void DTreesImpl::calcValue( int nidx, const vector& _sidx ) } else { - double *cv_sum = buf, *cv_sum2 = cv_sum + cv_n; + double *cv_sum = buf.data(), *cv_sum2 = cv_sum + cv_n; double* cv_count = (double*)(cv_sum2 + cv_n); for( j = 0; j < cv_n; j++ ) @@ -646,7 +646,7 @@ DTreesImpl::WSplit DTreesImpl::findSplitOrdClass( int vi, const vector& _si const int* sidx = &_sidx[0]; const int* responses = &w->cat_responses[0]; const double* weights = &w->sample_weights[0]; - double* lcw = (double*)(uchar*)buf; + double* lcw = (double*)buf.data(); double* rcw = lcw + m; float* values = (float*)(rcw + m); int* sorted_idx = (int*)(values + n); @@ -717,7 +717,7 @@ void DTreesImpl::clusterCategories( const double* vectors, int n, int m, double* int iters = 0, max_iters = 100; int i, j, idx; cv::AutoBuffer buf(n + k); - double *v_weights = buf, *c_weights = buf + n; + double *v_weights = buf.data(), *c_weights = buf.data() + n; bool modified = true; RNG r((uint64)-1); @@ -819,12 +819,12 @@ DTreesImpl::WSplit DTreesImpl::findSplitCatClass( int vi, const vector& _si base_size += mi; AutoBuffer buf(base_size + n); - double* lc = (double*)buf; + double* lc = buf.data(); double* rc = lc + m; double* _cjk = rc + m*2, *cjk = _cjk; double* c_weights = cjk + m*mi; - int* labels = (int*)(buf + base_size); + int* labels = (int*)(buf.data() + base_size); w->data->getNormCatValues(vi, _sidx, labels); const int* responses = &w->cat_responses[0]; const double* weights = &w->sample_weights[0]; @@ -991,7 +991,7 @@ DTreesImpl::WSplit DTreesImpl::findSplitOrdReg( int vi, const vector& _sidx AutoBuffer buf(n*(sizeof(int) + sizeof(float))); - float* values = (float*)(uchar*)buf; + float* values = (float*)buf.data(); int* sorted_idx = (int*)(values + n); w->data->getValues(vi, _sidx, values); const double* responses = &w->ord_responses[0]; @@ -1053,7 +1053,7 @@ DTreesImpl::WSplit DTreesImpl::findSplitCatReg( int vi, const vector& _sidx int mi = getCatCount(vi); AutoBuffer buf(3*mi + 3 + n); - double* sum = (double*)buf + 1; + double* sum = buf.data() + 1; double* counts = sum + mi + 1; double** sum_ptr = (double**)(counts + mi); int* cat_labels = (int*)(sum_ptr + mi); @@ -1148,7 +1148,7 @@ int DTreesImpl::calcDir( int splitidx, const vector& _sidx, if( mi <= 0 ) // split on an ordered variable { float c = split.c; - float* values = buf; + float* values = buf.data(); w->data->getValues(vi, _sidx, values); for( i = 0; i < n; i++ ) @@ -1169,7 +1169,7 @@ int DTreesImpl::calcDir( int splitidx, const vector& _sidx, else { const int* subset = &w->wsubsets[split.subsetOfs]; - int* cat_labels = (int*)(float*)buf; + int* cat_labels = (int*)buf.data(); w->data->getNormCatValues(vi, _sidx, cat_labels); for( i = 0; i < n; i++ ) @@ -1372,7 +1372,7 @@ float DTreesImpl::predictTrees( const Range& range, const Mat& sample, int flags int i, ncats = (int)catOfs.size(), nclasses = (int)classLabels.size(); int catbufsize = ncats > 0 ? nvars : 0; AutoBuffer buf(nclasses + catbufsize + 1); - int* votes = buf; + int* votes = buf.data(); int* catbuf = votes + nclasses; const int* cvidx = (flags & (COMPRESSED_INPUT|PREPROCESSED_INPUT)) == 0 && !varIdx.empty() ? &compVarIdx[0] : 0; const uchar* vtype = &varType[0]; diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index 6c98eb9299..6d76ba5e4e 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -1346,7 +1346,7 @@ void CascadeClassifierImpl::detectMultiScaleNoGrouping( InputArray _image, std:: size_t i, nscales = scales.size(); cv::AutoBuffer stripeSizeBuf(nscales); - int* stripeSizes = stripeSizeBuf; + int* stripeSizes = stripeSizeBuf.data(); const FeatureEvaluator::ScaleData* s = &featureEvaluator->getScaleData(0); Size szw = s->getWorkingSize(data.origWinSize); int nstripes = cvCeil(szw.width/32.); diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index 23b710b385..8fc18f467f 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -297,7 +297,7 @@ void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, #endif AutoBuffer mapbuf(gradsize.width + gradsize.height + 4); - int* xmap = (int*)mapbuf + 1; + int* xmap = mapbuf.data() + 1; int* ymap = xmap + gradsize.width + 2; const int borderType = (int)BORDER_REFLECT_101; @@ -312,7 +312,7 @@ void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, // x- & y- derivatives for the whole row int width = gradsize.width; AutoBuffer _dbuf(width*4); - float* const dbuf = _dbuf; + float* const dbuf = _dbuf.data(); Mat Dx(1, width, CV_32F, dbuf); Mat Dy(1, width, CV_32F, dbuf + width); Mat Mag(1, width, CV_32F, dbuf + width*2); @@ -656,7 +656,7 @@ void HOGCache::init(const HOGDescriptor* _descriptor, { AutoBuffer di(blockSize.height), dj(blockSize.width); - float* _di = (float*)di, *_dj = (float*)dj; + float* _di = di.data(), *_dj = dj.data(); float bh = blockSize.height * 0.5f, bw = blockSize.width * 0.5f; i = 0; diff --git a/modules/objdetect/test/test_cascadeandhog.cpp b/modules/objdetect/test/test_cascadeandhog.cpp index 3f5681dc6b..fffb23b396 100644 --- a/modules/objdetect/test/test_cascadeandhog.cpp +++ b/modules/objdetect/test/test_cascadeandhog.cpp @@ -1193,7 +1193,7 @@ void HOGDescriptorTester::computeGradient(const Mat& img, Mat& grad, Mat& qangle _lut(0,i) = (float)i; AutoBuffer mapbuf(gradsize.width + gradsize.height + 4); - int* xmap = (int*)mapbuf + 1; + int* xmap = mapbuf.data() + 1; int* ymap = xmap + gradsize.width + 2; const int borderType = (int)BORDER_REFLECT_101; @@ -1208,7 +1208,7 @@ void HOGDescriptorTester::computeGradient(const Mat& img, Mat& grad, Mat& qangle // x- & y- derivatives for the whole row int width = gradsize.width; AutoBuffer _dbuf(width*4); - float* dbuf = _dbuf; + float* dbuf = _dbuf.data(); Mat Dx(1, width, CV_32F, dbuf); Mat Dy(1, width, CV_32F, dbuf + width); Mat Mag(1, width, CV_32F, dbuf + width*2); diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 5a6bf7ef62..179bf678b2 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -189,7 +189,7 @@ public: _sizes[i] = sizes[i]; if( cn > 1 ) _sizes[dims++] = cn; - PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum); + PyObject* o = PyArray_SimpleNew(dims, _sizes.data(), typenum); if(!o) CV_Error_(Error::StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims)); return allocate(o, dims0, sizes, type, step); diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp index 259c289d67..7bf60af716 100644 --- a/modules/ts/src/ts_perf.cpp +++ b/modules/ts/src/ts_perf.cpp @@ -2166,7 +2166,7 @@ void perf::sort(std::vector& pts, cv::InputOutputArray descriptors for (int i = 0; i < desc.rows; ++i) idxs[i] = i; - std::sort((int*)idxs, (int*)idxs + desc.rows, KeypointComparator(pts)); + std::sort(idxs.data(), idxs.data() + desc.rows, KeypointComparator(pts)); std::vector spts(pts.size()); cv::Mat sdesc(desc.size(), desc.type()); diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index f338b6c3ff..96ae0299ec 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -575,7 +575,7 @@ public: for( int y = y0; y < y1; y++ ) { - const float* data = buf; + const float* data = buf.data(); if( src->depth() != CV_32F ) src->row(y).convertTo(Mat(1, ncols, CV_32FC(nchannels), (void*)data), CV_32F); else diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 353e356102..94704681ef 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -67,7 +67,7 @@ static void calcSharrDeriv(const cv::Mat& src, cv::Mat& dst) int x, y, delta = (int)alignSize((cols + 2)*cn, 16); AutoBuffer _tempBuf(delta*2 + 64); - deriv_type *trow0 = alignPtr(_tempBuf + cn, 16), *trow1 = alignPtr(trow0 + delta, 16); + deriv_type *trow0 = alignPtr(_tempBuf.data() + cn, 16), *trow1 = alignPtr(trow0 + delta, 16); #if CV_SIMD128 v_int16x8 c3 = v_setall_s16(3), c10 = v_setall_s16(10); @@ -191,8 +191,8 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const cv::AutoBuffer _buf(winSize.area()*(cn + cn2)); int derivDepth = DataType::depth; - Mat IWinBuf(winSize, CV_MAKETYPE(derivDepth, cn), (deriv_type*)_buf); - Mat derivIWinBuf(winSize, CV_MAKETYPE(derivDepth, cn2), (deriv_type*)_buf + winSize.area()*cn); + Mat IWinBuf(winSize, CV_MAKETYPE(derivDepth, cn), _buf.data()); + Mat derivIWinBuf(winSize, CV_MAKETYPE(derivDepth, cn2), _buf.data() + winSize.area()*cn); for( int ptidx = range.start; ptidx < range.end; ptidx++ ) { diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index 448dea2bb8..68edf4ca4e 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -121,10 +121,10 @@ FarnebackPolyExp( const Mat& src, Mat& dst, int n, double sigma ) int width = src.cols; int height = src.rows; AutoBuffer kbuf(n*6 + 3), _row((width + n*2)*3); - float* g = kbuf + n; + float* g = kbuf.data() + n; float* xg = g + n*2 + 1; float* xxg = xg + n*2 + 1; - float *row = (float*)_row + n*3; + float *row = _row.data() + n*3; double ig11, ig03, ig33, ig55; FarnebackPrepareGaussian(n, sigma, g, xg, xxg, ig11, ig03, ig33, ig55); @@ -322,7 +322,7 @@ FarnebackUpdateFlow_Blur( const Mat& _R0, const Mat& _R1, double scale = 1./(block_size*block_size); AutoBuffer _vsum((width+m*2+2)*5); - double* vsum = _vsum + (m+1)*5; + double* vsum = _vsum.data() + (m+1)*5; // init vsum const float* srow0 = matM.ptr(); @@ -416,10 +416,10 @@ FarnebackUpdateFlow_GaussianBlur( const Mat& _R0, const Mat& _R1, AutoBuffer _vsum((width+m*2+2)*5 + 16), _hsum(width*5 + 16); AutoBuffer _kernel((m+1)*5 + 16); - AutoBuffer _srow(m*2+1); - float *vsum = alignPtr((float*)_vsum + (m+1)*5, 16), *hsum = alignPtr((float*)_hsum, 16); - float* kernel = (float*)_kernel; - const float** srow = (const float**)&_srow[0]; + AutoBuffer _srow(m*2+1); + float *vsum = alignPtr(_vsum.data() + (m+1)*5, 16), *hsum = alignPtr(_hsum.data(), 16); + float* kernel = _kernel.data(); + const float** srow = _srow.data(); kernel[0] = (float)s; for( i = 1; i <= m; i++ ) diff --git a/modules/videoio/src/cap_mfx_common.cpp b/modules/videoio/src/cap_mfx_common.cpp index 9c02d6d7bf..705d180687 100644 --- a/modules/videoio/src/cap_mfx_common.cpp +++ b/modules/videoio/src/cap_mfx_common.cpp @@ -96,7 +96,7 @@ SurfacePool::SurfacePool(ushort width_, ushort height_, ushort count, const mfxF for(int i = 0; i < count; ++i) { mfxFrameSurface1 &surface = surfaces[i]; - uint8_t * dataPtr = buffers + oneSize * i; + uint8_t * dataPtr = buffers.data() + oneSize * i; memset(&surface, 0, sizeof(mfxFrameSurface1)); surface.Info = frameInfo; surface.Data.Y = dataPtr; diff --git a/modules/videoio/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp index beed7420d3..35043ee535 100644 --- a/modules/videoio/src/cap_msmf.cpp +++ b/modules/videoio/src/cap_msmf.cpp @@ -1029,8 +1029,8 @@ bool CvCapture_MSMF::open(const cv::String& _filename) srAttr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, D3DMgr.Get()); #endif cv::AutoBuffer unicodeFileName(_filename.length() + 1); - MultiByteToWideChar(CP_ACP, 0, _filename.c_str(), -1, unicodeFileName, (int)_filename.length() + 1); - if (SUCCEEDED(MFCreateSourceReaderFromURL(unicodeFileName, srAttr.Get(), &videoFileSource))) + MultiByteToWideChar(CP_ACP, 0, _filename.c_str(), -1, unicodeFileName.data(), (int)_filename.length() + 1); + if (SUCCEEDED(MFCreateSourceReaderFromURL(unicodeFileName.data(), srAttr.Get(), &videoFileSource))) { isOpen = true; sampleTime = 0; @@ -2081,8 +2081,8 @@ bool CvVideoWriter_MSMF::open( const cv::String& filename, int fourcc, { // Create the sink writer cv::AutoBuffer unicodeFileName(filename.length() + 1); - MultiByteToWideChar(CP_ACP, 0, filename.c_str(), -1, unicodeFileName, (int)filename.length() + 1); - HRESULT hr = MFCreateSinkWriterFromURL(unicodeFileName, NULL, spAttr.Get(), &sinkWriter); + MultiByteToWideChar(CP_ACP, 0, filename.c_str(), -1, unicodeFileName.data(), (int)filename.length() + 1); + HRESULT hr = MFCreateSinkWriterFromURL(unicodeFileName.data(), NULL, spAttr.Get(), &sinkWriter); if (SUCCEEDED(hr)) { // Configure the sink writer and tell it start to start accepting data From c7fc563dc0ac2d21ad2bd618e741227c0a4b4f76 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 23 May 2018 17:44:12 +0300 Subject: [PATCH 14/26] calib3d: chessboard detector - replace OpenCV C API --- modules/calib3d/src/calib3d_c_api.cpp | 47 + modules/calib3d/src/calibinit.cpp | 1744 ++++++++--------- modules/calib3d/src/precomp.hpp | 8 +- .../calib3d/test/test_cameracalibration.cpp | 3 +- modules/core/include/opencv2/core/types_c.h | 24 + modules/ts/src/ts.cpp | 12 +- 6 files changed, 911 insertions(+), 927 deletions(-) create mode 100644 modules/calib3d/src/calib3d_c_api.cpp diff --git a/modules/calib3d/src/calib3d_c_api.cpp b/modules/calib3d/src/calib3d_c_api.cpp new file mode 100644 index 0000000000..284c8a074b --- /dev/null +++ b/modules/calib3d/src/calib3d_c_api.cpp @@ -0,0 +1,47 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// This file contains wrappers for legacy OpenCV C API + +#include "precomp.hpp" +#include "opencv2/calib3d/calib3d_c.h" + +using namespace cv; + +CV_IMPL void +cvDrawChessboardCorners(CvArr* _image, CvSize pattern_size, + CvPoint2D32f* corners, int count, int found) +{ + CV_Assert(corners != NULL); //CV_CheckNULL(corners, "NULL is not allowed for 'corners' parameter"); + Mat image = cvarrToMat(_image); + CV_StaticAssert(sizeof(CvPoint2D32f) == sizeof(Point2f), ""); + drawChessboardCorners(image, pattern_size, Mat(1, count, traits::Type::value, corners), found != 0); +} + +CV_IMPL int +cvFindChessboardCorners(const void* arr, CvSize pattern_size, + CvPoint2D32f* out_corners_, int* out_corner_count, + int flags) +{ + if (!out_corners_) + CV_Error( CV_StsNullPtr, "Null pointer to corners" ); + + Mat image = cvarrToMat(arr); + std::vector out_corners; + + if (out_corner_count) + *out_corner_count = 0; + + bool res = cv::findChessboardCorners(image, pattern_size, out_corners, flags); + + int corner_count = (int)out_corners.size(); + if (out_corner_count) + *out_corner_count = corner_count; + CV_CheckLE(corner_count, Size(pattern_size).area(), "Unexpected number of corners"); + for (int i = 0; i < corner_count; ++i) + { + out_corners_[i] = cvPoint2D32f(out_corners[i]); + } + return res ? 1 : 0; +} diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index feaaf4a73a..3e31550240 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -70,36 +70,29 @@ \************************************************************************************/ #include "precomp.hpp" -#include "opencv2/imgproc/imgproc_c.h" -#include "opencv2/calib3d/calib3d_c.h" #include "circlesgrid.hpp" -#include -#include -#include "opencv2/core/utility.hpp" -#include +#include //#define ENABLE_TRIM_COL_ROW //#define DEBUG_CHESSBOARD +#define DEBUG_CHESSBOARD_TIMEOUT 0 // 0 - wait for 'q' +#include //#undef CV_LOG_STRIP_LEVEL //#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1 #include #ifdef DEBUG_CHESSBOARD -static int PRINTF( const char* fmt, ... ) -{ - va_list args; - va_start(args, fmt); - return vprintf(fmt, args); -} +#include "opencv2/highgui.hpp" +#include "opencv2/imgproc.hpp" +#define DPRINTF(...) CV_LOG_INFO(NULL, cv::format("calib3d: " __VA_ARGS__)) #else -#define PRINTF(...) +#define DPRINTF(...) #endif -using namespace cv; -using namespace std; +namespace cv { //===================================================================================== // Implementation for the enhanced calibration object detection @@ -120,6 +113,11 @@ struct QuadCountour { } }; #else + +} // namespace +#include "opencv2/imgproc/imgproc_c.h" +namespace cv { + struct CvContourEx { CV_CONTOUR_FIELDS() @@ -127,41 +125,41 @@ struct CvContourEx }; #endif -//===================================================================================== -/// Corner info structure /** This structure stores information about the chessboard corner.*/ -struct CvCBCorner +struct ChessBoardCorner { - CvPoint2D32f pt; // Coordinates of the corner + cv::Point2f pt; // Coordinates of the corner int row; // Board row index int count; // Number of neighbor corners - struct CvCBCorner* neighbors[4]; // Neighbor corners + struct ChessBoardCorner* neighbors[4]; // Neighbor corners - float meanDist(int *_n) const + ChessBoardCorner(const cv::Point2f& pt_ = cv::Point2f()) : + pt(pt_), row(0), count(0) + { + neighbors[0] = neighbors[1] = neighbors[2] = neighbors[3] = NULL; + } + + float sumDist(int& n_) const { float sum = 0; int n = 0; - for( int i = 0; i < 4; i++ ) + for (int i = 0; i < 4; ++i) { - if( neighbors[i] ) + if (neighbors[i]) { - float dx = neighbors[i]->pt.x - pt.x; - float dy = neighbors[i]->pt.y - pt.y; - sum += sqrt(dx*dx + dy*dy); + sum += sqrt(normL2Sqr(neighbors[i]->pt - pt)); n++; } } - if(_n) - *_n = n; - return sum/MAX(n,1); + n_ = n; + return sum; } }; -//===================================================================================== -/// Quadrangle contour info structure -/** This structure stores information about the chessboard quadrange.*/ -struct CvCBQuad + +/** This structure stores information about the chessboard quadrangle.*/ +struct ChessBoardQuad { int count; // Number of quad neighbors int group_idx; // quad group ID @@ -169,140 +167,179 @@ struct CvCBQuad bool ordered; // true if corners/neighbors are ordered counter-clockwise float edge_len; // quad edge len, in pix^2 // neighbors and corners are synced, i.e., neighbor 0 shares corner 0 - CvCBCorner *corners[4]; // Coordinates of quad corners - struct CvCBQuad *neighbors[4]; // Pointers of quad neighbors + ChessBoardCorner *corners[4]; // Coordinates of quad corners + struct ChessBoardQuad *neighbors[4]; // Pointers of quad neighbors + + ChessBoardQuad(int group_idx_ = -1) : + count(0), + group_idx(group_idx_), + row(0), col(0), + ordered(0), + edge_len(0) + { + corners[0] = corners[1] = corners[2] = corners[3] = NULL; + neighbors[0] = neighbors[1] = neighbors[2] = neighbors[3] = NULL; + } }; -//===================================================================================== + #ifdef DEBUG_CHESSBOARD -#include "opencv2/highgui.hpp" -#include "opencv2/imgproc.hpp" static void SHOW(const std::string & name, Mat & img) { imshow(name, img); +#if DEBUG_CHESSBOARD_TIMEOUT + waitKey(DEBUG_CHESSBOARD_TIMEOUT); +#else while ((uchar)waitKey(0) != 'q') {} +#endif } -static void SHOW_QUADS(const std::string & name, const Mat & img_, CvCBQuad * quads, int quads_count) +static void SHOW_QUADS(const std::string & name, const Mat & img_, ChessBoardQuad * quads, int quads_count) { Mat img = img_.clone(); if (img.channels() == 1) cvtColor(img, img, COLOR_GRAY2BGR); for (int i = 0; i < quads_count; ++i) { - CvCBQuad & quad = quads[i]; + ChessBoardQuad & quad = quads[i]; for (int j = 0; j < 4; ++j) { - line(img, quad.corners[j]->pt, quad.corners[(j + 1) % 4]->pt, Scalar(0, 240, 0), 1, LINE_AA); + line(img, quad.corners[j]->pt, quad.corners[(j + 1) & 3]->pt, Scalar(0, 240, 0), 1, LINE_AA); } } imshow(name, img); +#if DEBUG_CHESSBOARD_TIMEOUT + waitKey(DEBUG_CHESSBOARD_TIMEOUT); +#else while ((uchar)waitKey(0) != 'q') {} +#endif } #else #define SHOW(...) #define SHOW_QUADS(...) #endif -//===================================================================================== -static int icvGenerateQuads( CvCBQuad **quads, CvCBCorner **corners, - CvMemStorage *storage, const Mat &image_, int flags, int *max_quad_buf_size); -static bool processQuads(CvCBQuad *quads, int quad_count, CvSize pattern_size, int max_quad_buf_size, - CvMemStorage * storage, CvCBCorner *corners, CvPoint2D32f *out_corners, int *out_corner_count, int & prev_sqr_size); +class ChessBoardDetector +{ +public: + cv::Mat binarized_image; + Size pattern_size; -/*static int -icvGenerateQuadsEx( CvCBQuad **out_quads, CvCBCorner **out_corners, - CvMemStorage *storage, CvMat *image, CvMat *thresh_img, int dilation, int flags );*/ + cv::AutoBuffer all_quads; + cv::AutoBuffer all_corners; -static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count ); + int all_quads_count; -static int icvFindConnectedQuads( CvCBQuad *quads, int quad_count, - CvCBQuad **quad_group, int group_idx, - CvMemStorage* storage ); + ChessBoardDetector(const Size& pattern_size_) : + pattern_size(pattern_size_), + all_quads_count(0) + { + } -static int icvCheckQuadGroup( CvCBQuad **quad_group, int count, - CvCBCorner **out_corners, CvSize pattern_size ); + void reset() + { + all_quads.deallocate(); + all_corners.deallocate(); + all_quads_count = 0; + } -static int icvCleanFoundConnectedQuads( int quad_count, - CvCBQuad **quads, CvSize pattern_size ); + void generateQuads(const cv::Mat& image_, int flags); -static int icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, - int *all_count, CvCBQuad **all_quads, CvCBCorner **corners, - CvSize pattern_size, int max_quad_buf_size, CvMemStorage* storage ); + bool processQuads(std::vector& out_corners, int &prev_sqr_size); -static void icvOrderQuad(CvCBQuad *quad, CvCBCorner *corner, int common); + void findQuadNeighbors(); + + void findConnectedQuads(std::vector& out_group, int group_idx); + + int checkQuadGroup(std::vector& quad_group, std::vector& out_corners); + + int cleanFoundConnectedQuads(std::vector& quad_group); + + int orderFoundConnectedQuads(std::vector& quads); + + void orderQuad(ChessBoardQuad& quad, ChessBoardCorner& corner, int common); #ifdef ENABLE_TRIM_COL_ROW -static int icvTrimCol(CvCBQuad **quads, int count, int col, int dir); - -static int icvTrimRow(CvCBQuad **quads, int count, int row, int dir); + void trimCol(std::vector& quads, int col, int dir); + void trimRow(std::vector& quads, int row, int dir); #endif -static int icvAddOuterQuad(CvCBQuad *quad, CvCBQuad **quads, int quad_count, - CvCBQuad **all_quads, int all_count, CvCBCorner **corners, int max_quad_buf_size); + int addOuterQuad(ChessBoardQuad& quad, std::vector& quads); -static void icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0); + void removeQuadFromGroup(std::vector& quads, ChessBoardQuad& q0); -static int icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size ); + bool checkBoardMonotony(const std::vector& corners); +}; /***************************************************************************************************/ //COMPUTE INTENSITY HISTOGRAM OF INPUT IMAGE -static int icvGetIntensityHistogram( const Mat & img, std::vector& piHist ) +template +static void icvGetIntensityHistogram256(const Mat& img, ArrayContainer& piHist) { + for (int i = 0; i < 256; i++) + piHist[i] = 0; // sum up all pixel in row direction and divide by number of columns - for ( int j=0; j(j); + for (int i = 0; i < img.cols; i++) { piHist[row[i]]++; } } - return 0; } /***************************************************************************************************/ //SMOOTH HISTOGRAM USING WINDOW OF SIZE 2*iWidth+1 -static int icvSmoothHistogram( const std::vector& piHist, std::vector& piHistSmooth, int iWidth ) +template +static void icvSmoothHistogram256(const ArrayContainer& piHist, ArrayContainer& piHistSmooth, int iWidth = 0) { - int iIdx; - for ( int i=0; i<256; i++) + CV_DbgAssert(iWidth_ == 0 || (iWidth == iWidth_ || iWidth == 0)); + iWidth = (iWidth_ != 0) ? iWidth_ : iWidth; + CV_Assert(iWidth > 0); + CV_DbgAssert(piHist.size() == 256); + CV_DbgAssert(piHistSmooth.size() == 256); + for (int i = 0; i < 256; ++i) { + int iIdx_min = std::max(0, i - iWidth); + int iIdx_max = std::min(255, i + iWidth); int iSmooth = 0; - for ( int ii=-iWidth; ii<=iWidth; ii++) + for (int iIdx = iIdx_min; iIdx <= iIdx_max; ++iIdx) { - iIdx = i+ii; - if (iIdx >= 0 && iIdx < 256) - { - iSmooth += piHist[iIdx]; - } + CV_DbgAssert(iIdx >= 0 && iIdx < 256); + iSmooth += piHist[iIdx]; } piHistSmooth[i] = iSmooth/(2*iWidth+1); } - return 0; } /***************************************************************************************************/ //COMPUTE FAST HISTOGRAM GRADIENT -static int icvGradientOfHistogram( const std::vector& piHist, std::vector& piHistGrad ) +template +static void icvGradientOfHistogram256(const ArrayContainer& piHist, ArrayContainer& piHistGrad) { + CV_DbgAssert(piHist.size() == 256); + CV_DbgAssert(piHistGrad.size() == 256); piHistGrad[0] = 0; - for ( int i=1; i<255; i++) + int prev_grad = 0; + for (int i = 1; i < 255; ++i) { - piHistGrad[i] = piHist[i-1] - piHist[i+1]; - if ( abs(piHistGrad[i]) < 100 ) + int grad = piHist[i-1] - piHist[i+1]; + if (std::abs(grad) < 100) { - if ( piHistGrad[i-1] == 0) - piHistGrad[i] = -100; + if (prev_grad == 0) + grad = -100; else - piHistGrad[i] = piHistGrad[i-1]; + grad = prev_grad; } + piHistGrad[i] = grad; + prev_grad = grad; } - return 0; + piHistGrad[255] = 0; } /***************************************************************************************************/ //PERFORM SMART IMAGE THRESHOLDING BASED ON ANALYSIS OF INTENSTY HISTOGRAM -static bool icvBinarizationHistogramBased( Mat & img ) +static void icvBinarizationHistogramBased(Mat & img) { CV_Assert(img.channels() == 1 && img.depth() == CV_8U); int iCols = img.cols; @@ -310,65 +347,62 @@ static bool icvBinarizationHistogramBased( Mat & img ) int iMaxPix = iCols*iRows; int iMaxPix1 = iMaxPix/100; const int iNumBins = 256; - std::vector piHistIntensity(iNumBins, 0); - std::vector piHistSmooth(iNumBins, 0); - std::vector piHistGrad(iNumBins, 0); - std::vector piAccumSum(iNumBins, 0); - std::vector piMaxPos; piMaxPos.reserve(20); - int iThresh = 0; - int iIdx; - int iWidth = 1; + const int iMaxPos = 20; + cv::AutoBuffer piHistIntensity(iNumBins); + cv::AutoBuffer piHistSmooth(iNumBins); + cv::AutoBuffer piHistGrad(iNumBins); + cv::AutoBuffer piMaxPos(iMaxPos); - icvGetIntensityHistogram( img, piHistIntensity ); + icvGetIntensityHistogram256(img, piHistIntensity); +#if 0 // get accumulated sum starting from bright + cv::AutoBuffer piAccumSum(iNumBins); piAccumSum[iNumBins-1] = piHistIntensity[iNumBins-1]; - for ( int i=iNumBins-2; i>=0; i-- ) + for (int i = iNumBins - 2; i >= 0; --i) { piAccumSum[i] = piHistIntensity[i] + piAccumSum[i+1]; } +#endif // first smooth the distribution - icvSmoothHistogram( piHistIntensity, piHistSmooth, iWidth ); + //const int iWidth = 1; + icvSmoothHistogram256<1>(piHistIntensity, piHistSmooth); // compute gradient - icvGradientOfHistogram( piHistSmooth, piHistGrad ); + icvGradientOfHistogram256(piHistSmooth, piHistGrad); // check for zeros - int iCntMaxima = 0; - for ( int i=iNumBins-2; (i>2) && (iCntMaxima<20); i--) + unsigned iCntMaxima = 0; + for (int i = iNumBins-2; (i > 2) && (iCntMaxima < iMaxPos); --i) { - if ( (piHistGrad[i-1] < 0) && (piHistGrad[i] > 0) ) + if ((piHistGrad[i-1] < 0) && (piHistGrad[i] > 0)) { - piMaxPos.push_back(i); - iCntMaxima++; + int iSumAroundMax = piHistSmooth[i-1] + piHistSmooth[i] + piHistSmooth[i+1]; + if (!(iSumAroundMax < iMaxPix1 && i < 64)) + { + piMaxPos[iCntMaxima++] = i; + } } } - iIdx = 0; - int iSumAroundMax = 0; - for ( int i=0; i 0 ? piMaxPos[0] : -1, + iCntMaxima > 1 ? piMaxPos[1] : -1, + iCntMaxima > 2 ? piMaxPos[2] : -1); - CV_Assert((size_t)iCntMaxima == piMaxPos.size()); + int iThresh = 0; - PRINTF("HIST: MAXIMA COUNT: %d (%d, %d, %d, ...)\n", iCntMaxima, + CV_Assert((size_t)iCntMaxima <= piMaxPos.size()); + + DPRINTF("HIST: MAXIMA COUNT: %d (%d, %d, %d, ...)", iCntMaxima, iCntMaxima > 0 ? piMaxPos[0] : -1, iCntMaxima > 1 ? piMaxPos[1] : -1, iCntMaxima > 2 ? piMaxPos[2] : -1); if (iCntMaxima == 0) { - // no any maxima inside (except 0 and 255 which are not handled above) + // no any maxima inside (only 0 and 255 which are not counted above) // Does image black-write already? const int iMaxPix2 = iMaxPix / 2; for (int sum = 0, i = 0; i < 256; ++i) // select mean intensity @@ -376,8 +410,8 @@ static bool icvBinarizationHistogramBased( Mat & img ) sum += piHistIntensity[i]; if (sum > iMaxPix2) { - iThresh = i; - break; + iThresh = i; + break; } } } @@ -385,7 +419,7 @@ static bool icvBinarizationHistogramBased( Mat & img ) { iThresh = piMaxPos[0]/2; } - else if ( iCntMaxima == 2) + else if (iCntMaxima == 2) { iThresh = (piMaxPos[0] + piMaxPos[1])/2; } @@ -393,7 +427,7 @@ static bool icvBinarizationHistogramBased( Mat & img ) { // CHECKING THRESHOLD FOR WHITE int iIdxAccSum = 0, iAccum = 0; - for (int i=iNumBins-1; i>0; i--) + for (int i = iNumBins - 1; i > 0; --i) { iAccum += piHistIntensity[i]; // iMaxPix/18 is about 5,5%, minimum required number of pixels required for white part of chessboard @@ -404,12 +438,12 @@ static bool icvBinarizationHistogramBased( Mat & img ) } } - int iIdxBGMax = 0; + unsigned iIdxBGMax = 0; int iBrightMax = piMaxPos[0]; // printf("iBrightMax = %d\n", iBrightMax); - for ( int n=0; n= 250 && iIdxBGMax + 1 < iCntMaxima ) + if (piMaxPos[iIdxBGMax] >= 250 && iIdxBGMax + 1 < iCntMaxima) { iIdxBGMax++; iMaxVal = piHistIntensity[piMaxPos[iIdxBGMax]]; } - for ( int n=iIdxBGMax + 1; n= iMaxVal ) + if (piHistIntensity[piMaxPos[n]] >= iMaxVal) { iMaxVal = piHistIntensity[piMaxPos[n]]; iIdxBGMax = n; @@ -439,70 +473,58 @@ static bool icvBinarizationHistogramBased( Mat & img ) //SETTING THRESHOLD FOR BINARIZATION int iDist2 = (iBrightMax - piMaxPos[iIdxBGMax])/2; iThresh = iBrightMax - iDist2; - PRINTF("THRESHOLD SELECTED = %d, BRIGHTMAX = %d, DARKMAX = %d\n", iThresh, iBrightMax, piMaxPos[iIdxBGMax]); + DPRINTF("THRESHOLD SELECTED = %d, BRIGHTMAX = %d, DARKMAX = %d", iThresh, iBrightMax, piMaxPos[iIdxBGMax]); } - - if ( iThresh > 0 ) + if (iThresh > 0) { - for ( int jj=0; jj= iThresh); } - - return true; } -CV_IMPL -int cvFindChessboardCorners( const void* arr, CvSize pattern_size, - CvPoint2D32f* out_corners, int* out_corner_count, - int flags ) +bool findChessboardCorners(InputArray image_, Size pattern_size, + OutputArray corners_, int flags) { - int found = 0; - CvCBQuad *quads = 0; - CvCBCorner *corners = 0; + CV_INSTRUMENT_REGION() - cv::Ptr storage; + DPRINTF("==== findChessboardCorners(img=%dx%d, pattern=%dx%d, flags=%d)", + image_.cols(), image_.rows(), pattern_size.width, pattern_size.height, flags); + + bool found = false; - CV_TRY - { - int k = 0; const int min_dilations = 0; const int max_dilations = 7; - if( out_corner_count ) - *out_corner_count = 0; + int type = image_.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + Mat img = image_.getMat(); - Mat img = cvarrToMat((CvMat*)arr).clone(); + CV_CheckType(type, depth == CV_8U && (cn == 1 || cn == 3 || cn == 4), + "Only 8-bit grayscale or color images are supported"); - if( img.depth() != CV_8U || (img.channels() != 1 && img.channels() != 3 && img.channels() != 4) ) - CV_Error( CV_StsUnsupportedFormat, "Only 8-bit grayscale or color images are supported" ); + if (pattern_size.width <= 2 || pattern_size.height <= 2) + CV_Error(Error::StsOutOfRange, "Both width and height of the pattern should have bigger than 2"); - if( pattern_size.width <= 2 || pattern_size.height <= 2 ) - CV_Error( CV_StsOutOfRange, "Both width and height of the pattern should have bigger than 2" ); + if (!corners_.needed()) + CV_Error(Error::StsNullPtr, "Null pointer to corners"); - if( !out_corners ) - CV_Error( CV_StsNullPtr, "Null pointer to corners" ); + std::vector out_corners; if (img.channels() != 1) { cvtColor(img, img, COLOR_BGR2GRAY); } + else + { + img.clone(); + } + int prev_sqr_size = 0; Mat thresh_img_new = img.clone(); - icvBinarizationHistogramBased( thresh_img_new ); // process image in-place + icvBinarizationHistogramBased(thresh_img_new); // process image in-place SHOW("New binarization", thresh_img_new); - if( flags & CV_CALIB_CB_FAST_CHECK) + if (flags & CALIB_CB_FAST_CHECK) { //perform new method for checking chessboard using a binary image. //image is binarised using a threshold dependent on the image histogram @@ -510,24 +532,20 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, { if (checkChessboard(img, pattern_size) <= 0) { - return found; + corners_.release(); + return false; } } } - storage.reset(cvCreateMemStorage(0)); - - int prev_sqr_size = 0; + ChessBoardDetector detector(pattern_size); // Try our standard "1" dilation, but if the pattern is not found, iterate the whole procedure with higher dilations. // This is necessary because some squares simply do not separate properly with a single dilation. However, // we want to use the minimum number of dilations possible since dilations cause the squares to become smaller, // making it difficult to detect smaller squares. - for( int dilations = min_dilations; dilations <= max_dilations; dilations++ ) + for (int dilations = min_dilations; dilations <= max_dilations; dilations++) { - if (found) - break; // already found it - //USE BINARY IMAGE COMPUTED USING icvBinarizationHistogramBased METHOD dilate( thresh_img_new, thresh_img_new, Mat(), Point(-1, -1), 1 ); @@ -535,58 +553,58 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // Otherwise FindContours will miss those clipped rectangle contours. // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... rectangle( thresh_img_new, Point(0,0), Point(thresh_img_new.cols-1, thresh_img_new.rows-1), Scalar(255,255,255), 3, LINE_8); - int max_quad_buf_size = 0; - cvFree(&quads); - cvFree(&corners); + + detector.reset(); + #ifdef USE_CV_FINDCONTOURS Mat binarized_img = thresh_img_new; #else Mat binarized_img = thresh_img_new.clone(); // make clone because cvFindContours modifies the source image #endif - int quad_count = icvGenerateQuads( &quads, &corners, storage, binarized_img, flags, &max_quad_buf_size ); - PRINTF("Quad count: %d/%d\n", quad_count, (pattern_size.width/2+1)*(pattern_size.height/2+1)); - SHOW_QUADS("New quads", thresh_img_new, quads, quad_count); - if (processQuads(quads, quad_count, pattern_size, max_quad_buf_size, storage, corners, out_corners, out_corner_count, prev_sqr_size)) - found = 1; + detector.generateQuads(binarized_img, flags); + DPRINTF("Quad count: %d/%d", detector.all_quads_count, (pattern_size.width/2+1)*(pattern_size.height/2+1)); + SHOW_QUADS("New quads", thresh_img_new, &detector.all_quads[0], detector.all_quads_count); + if (detector.processQuads(out_corners, prev_sqr_size)) + { + found = true; + break; + } } - PRINTF("Chessboard detection result 0: %d\n", found); + DPRINTF("Chessboard detection result 0: %d", (int)found); // revert to old, slower, method if detection failed if (!found) { - if( flags & CV_CALIB_CB_NORMALIZE_IMAGE ) + if (flags & CALIB_CB_NORMALIZE_IMAGE) { - equalizeHist( img, img ); + equalizeHist(img, img); } Mat thresh_img; prev_sqr_size = 0; - PRINTF("Fallback to old algorithm\n"); - const bool useAdaptive = flags & CV_CALIB_CB_ADAPTIVE_THRESH; + DPRINTF("Fallback to old algorithm"); + const bool useAdaptive = flags & CALIB_CB_ADAPTIVE_THRESH; if (!useAdaptive) { // empiric threshold level // thresholding performed here and not inside the cycle to save processing time double mean = cv::mean(img).val[0]; - int thresh_level = MAX(cvRound( mean - 10 ), 10); - threshold( img, thresh_img, thresh_level, 255, THRESH_BINARY ); + int thresh_level = std::max(cvRound(mean - 10), 10); + threshold(img, thresh_img, thresh_level, 255, THRESH_BINARY); } - //if flag CV_CALIB_CB_ADAPTIVE_THRESH is not set it doesn't make sense to iterate over k + //if flag CALIB_CB_ADAPTIVE_THRESH is not set it doesn't make sense to iterate over k int max_k = useAdaptive ? 6 : 1; - for( k = 0; k < max_k; k++ ) + for (int k = 0; k < max_k && !found; k++) { - for( int dilations = min_dilations; dilations <= max_dilations; dilations++ ) + for (int dilations = min_dilations; dilations <= max_dilations; dilations++) { - if (found) - break; // already found it - // convert the input grayscale image to binary (black-n-white) if (useAdaptive) { int block_size = cvRound(prev_sqr_size == 0 - ? MIN(img.cols, img.rows) * (k % 2 == 0 ? 0.2 : 0.1) + ? std::min(img.cols, img.rows) * (k % 2 == 0 ? 0.2 : 0.1) : prev_sqr_size * 2); block_size = block_size | 1; // convert to binary @@ -605,80 +623,74 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // Otherwise FindContours will miss those clipped rectangle contours. // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... rectangle( thresh_img, Point(0,0), Point(thresh_img.cols-1, thresh_img.rows-1), Scalar(255,255,255), 3, LINE_8); - int max_quad_buf_size = 0; - cvFree(&quads); - cvFree(&corners); + + detector.reset(); + #ifdef USE_CV_FINDCONTOURS Mat binarized_img = thresh_img; #else Mat binarized_img = (useAdaptive) ? thresh_img : thresh_img.clone(); // make clone because cvFindContours modifies the source image #endif - int quad_count = icvGenerateQuads( &quads, &corners, storage, binarized_img, flags, &max_quad_buf_size); - PRINTF("Quad count: %d/%d\n", quad_count, (pattern_size.width/2+1)*(pattern_size.height/2+1)); - SHOW_QUADS("Old quads", thresh_img, quads, quad_count); - if (processQuads(quads, quad_count, pattern_size, max_quad_buf_size, storage, corners, out_corners, out_corner_count, prev_sqr_size)) + detector.generateQuads(binarized_img, flags); + DPRINTF("Quad count: %d/%d", detector.all_quads_count, (pattern_size.width/2+1)*(pattern_size.height/2+1)); + SHOW_QUADS("Old quads", thresh_img, &detector.all_quads[0], detector.all_quads_count); + if (detector.processQuads(out_corners, prev_sqr_size)) + { found = 1; + break; + } } } } - PRINTF("Chessboard detection result 1: %d\n", found); + DPRINTF("Chessboard detection result 1: %d", (int)found); - if( found ) - found = icvCheckBoardMonotony( out_corners, pattern_size ); + if (found) + found = detector.checkBoardMonotony(out_corners); - PRINTF("Chessboard detection result 2: %d\n", found); + DPRINTF("Chessboard detection result 2: %d", (int)found); // check that none of the found corners is too close to the image boundary - if( found ) + if (found) { const int BORDER = 8; - for( k = 0; k < pattern_size.width*pattern_size.height; k++ ) + for (int k = 0; k < pattern_size.width*pattern_size.height; ++k) { if( out_corners[k].x <= BORDER || out_corners[k].x > img.cols - BORDER || out_corners[k].y <= BORDER || out_corners[k].y > img.rows - BORDER ) + { + found = false; break; + } } - - found = k == pattern_size.width*pattern_size.height; } - PRINTF("Chessboard detection result 3: %d\n", found); + DPRINTF("Chessboard detection result 3: %d", (int)found); - if( found ) + if (found) { - if ( pattern_size.height % 2 == 0 && pattern_size.width % 2 == 0 ) + if ((pattern_size.height & 1) == 0 && (pattern_size.width & 1) == 0 ) { int last_row = (pattern_size.height-1)*pattern_size.width; double dy0 = out_corners[last_row].y - out_corners[0].y; - if( dy0 < 0 ) + if (dy0 < 0) { int n = pattern_size.width*pattern_size.height; for(int i = 0; i < n/2; i++ ) { - CvPoint2D32f temp; - CV_SWAP(out_corners[i], out_corners[n-i-1], temp); + std::swap(out_corners[i], out_corners[n-i-1]); } } } - int wsize = 2; - CvMat old_img(img); - cvFindCornerSubPix( &old_img, out_corners, pattern_size.width*pattern_size.height, - cvSize(wsize, wsize), cvSize(-1,-1), - cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 15, 0.1)); + cv::cornerSubPix(img, out_corners, Size(2, 2), Size(-1,-1), + cv::TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 15, 0.1)); } - } - CV_CATCH_ALL - { - cvFree(&quads); - cvFree(&corners); - CV_RETHROW(); - } - cvFree(&quads); - cvFree(&corners); + + Mat(out_corners).copyTo(corners_); return found; } + // // Checks that each board row and column is pretty much monotonous curve: // It analyzes each row and each column of the chessboard as following: @@ -689,35 +701,33 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // This function has been created as temporary workaround for the bug in current implementation // of cvFindChessboardCornes that produces absolutely unordered sets of corners. // - -static int -icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size ) +bool ChessBoardDetector::checkBoardMonotony(const std::vector& corners) { - int i, j, k; - - for( k = 0; k < 2; k++ ) + for (int k = 0; k < 2; ++k) { - for( i = 0; i < (k == 0 ? pattern_size.height : pattern_size.width); i++ ) + int max_i = (k == 0 ? pattern_size.height : pattern_size.width); + int max_j = (k == 0 ? pattern_size.width: pattern_size.height) - 1; + for (int i = 0; i < max_i; ++i) { - CvPoint2D32f a = k == 0 ? corners[i*pattern_size.width] : corners[i]; - CvPoint2D32f b = k == 0 ? corners[(i+1)*pattern_size.width-1] : - corners[(pattern_size.height-1)*pattern_size.width + i]; - float prevt = 0, dx0 = b.x - a.x, dy0 = b.y - a.y; - if( fabs(dx0) + fabs(dy0) < FLT_EPSILON ) - return 0; - for( j = 1; j < (k == 0 ? pattern_size.width : pattern_size.height) - 1; j++ ) + cv::Point2f a = k == 0 ? corners[i*pattern_size.width] : corners[i]; + cv::Point2f b = k == 0 ? corners[(i+1)*pattern_size.width-1] + : corners[(pattern_size.height-1)*pattern_size.width + i]; + float dx0 = b.x - a.x, dy0 = b.y - a.y; + if (fabs(dx0) + fabs(dy0) < FLT_EPSILON) + return false; + float prevt = 0; + for (int j = 1; j < max_j; ++j) { - CvPoint2D32f c = k == 0 ? corners[i*pattern_size.width + j] : - corners[j*pattern_size.width + i]; + cv::Point2f c = k == 0 ? corners[i*pattern_size.width + j] + : corners[j*pattern_size.width + i]; float t = ((c.x - a.x)*dx0 + (c.y - a.y)*dy0)/(dx0*dx0 + dy0*dy0); - if( t < prevt || t > 1 ) - return 0; + if (t < prevt || t > 1) + return false; prevt = t; } } } - - return 1; + return true; } // @@ -731,18 +741,16 @@ icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size ) // can change the number of quads in the group // can add quads, so we need to have quad/corner arrays passed in // - -static int -icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, - int *all_count, CvCBQuad **all_quads, CvCBCorner **corners, - CvSize pattern_size, int max_quad_buf_size, CvMemStorage* storage ) +int ChessBoardDetector::orderFoundConnectedQuads(std::vector& quads) { - cv::Ptr temp_storage(cvCreateChildMemStorage( storage )); - CvSeq* stack = cvCreateSeq( 0, sizeof(*stack), sizeof(void*), temp_storage ); + const int max_quad_buf_size = (int)all_quads.size(); + int quad_count = (int)quads.size(); + + std::stack stack; // first find an interior quad - CvCBQuad *start = NULL; - for (int i=0; icount == 4) { @@ -760,7 +768,7 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, std::map col_hist; std::map row_hist; - cvSeqPush(stack, &start); + stack.push(start); start->row = 0; start->col = 0; start->ordered = true; @@ -768,10 +776,10 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, // Recursively order the quads so that all position numbers (e.g., // 0,1,2,3) are in the at the same relative corner (e.g., lower right). - while( stack->total ) + while (!stack.empty()) { - CvCBQuad* q; - cvSeqPop( stack, &q ); + ChessBoardQuad* q = stack.top(); stack.pop(); CV_Assert(q); + int col = q->col; int row = q->row; col_hist[col]++; @@ -783,9 +791,9 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, if (col > col_max) col_max = col; if (col < col_min) col_min = col; - for(int i = 0; i < 4; i++ ) + for (int i = 0; i < 4; i++) { - CvCBQuad *neighbor = q->neighbors[i]; + ChessBoardQuad *neighbor = q->neighbors[i]; switch(i) // adjust col, row for this quad { // start at top left, go clockwise case 0: @@ -801,18 +809,21 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, // just do inside quads if (neighbor && neighbor->ordered == false && neighbor->count == 4) { - PRINTF("col: %d row: %d\n", col, row); - icvOrderQuad(neighbor, q->corners[i], (i+2)%4); // set in order + DPRINTF("col: %d row: %d", col, row); + CV_Assert(q->corners[i]); + orderQuad(*neighbor, *(q->corners[i]), (i+2)&3); // set in order neighbor->ordered = true; neighbor->row = row; neighbor->col = col; - cvSeqPush( stack, &neighbor ); + stack.push(neighbor); } } } - for (int i=col_min; i<=col_max; i++) - PRINTF("HIST[%d] = %d\n", i, col_hist[i]); +#ifdef DEBUG_CHESSBOARD + for (int i = col_min; i <= col_max; i++) + DPRINTF("HIST[%d] = %d", i, col_hist[i]); +#endif // analyze inner quad structure int w = pattern_size.width - 1; @@ -828,62 +839,67 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, w = pattern_size.height - 1; } - PRINTF("Size: %dx%d Pattern: %dx%d\n", dcol, drow, w, h); + DPRINTF("Size: %dx%d Pattern: %dx%d", dcol, drow, w, h); // check if there are enough inner quads if (dcol < w || drow < h) // found enough inner quads? { - PRINTF("Too few inner quad rows/cols\n"); + DPRINTF("Too few inner quad rows/cols"); return 0; // no, return } #ifdef ENABLE_TRIM_COL_ROW // too many columns, not very common if (dcol == w+1) // too many, trim { - PRINTF("Trimming cols\n"); + DPRINTF("Trimming cols"); if (col_hist[col_max] > col_hist[col_min]) { - PRINTF("Trimming left col\n"); - quad_count = icvTrimCol(quads,quad_count,col_min,-1); + DPRINTF("Trimming left col"); + trimCol(quads, col_min, -1); } else { - PRINTF("Trimming right col\n"); - quad_count = icvTrimCol(quads,quad_count,col_max,+1); + DPRINTF("Trimming right col"); + trimCol(quads, col_max, +1); } } // too many rows, not very common if (drow == h+1) // too many, trim { - PRINTF("Trimming rows\n"); + DPRINTF("Trimming rows"); if (row_hist[row_max] > row_hist[row_min]) { - PRINTF("Trimming top row\n"); - quad_count = icvTrimRow(quads,quad_count,row_min,-1); + DPRINTF("Trimming top row"); + trimRow(quads, row_min, -1); } else { - PRINTF("Trimming bottom row\n"); - quad_count = icvTrimRow(quads,quad_count,row_max,+1); + DPRINTF("Trimming bottom row"); + trimRow(quads, row_max, +1); } } + + quad_count = (int)quads.size(); // update after icvTrimCol/icvTrimRow #endif // check edges of inner quads // if there is an outer quad missing, fill it in // first order all inner quads int found = 0; - for (int i=0; icount == 4) + ChessBoardQuad& q = *quads[i]; + if (q.count != 4) + continue; + { // ok, look at neighbors - int col = quads[i]->col; - int row = quads[i]->row; - for (int j=0; j<4; j++) + int col = q.col; + int row = q.row; + for (int j = 0; j < 4; j++) { switch(j) // adjust col, row for this quad - { // start at top left, go clockwise + { // start at top left, go clockwise case 0: row--; col--; break; case 1: @@ -893,15 +909,16 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, case 3: col -= 2; break; } - CvCBQuad *neighbor = quads[i]->neighbors[j]; + ChessBoardQuad *neighbor = q.neighbors[j]; if (neighbor && !neighbor->ordered && // is it an inner quad? col <= col_max && col >= col_min && row <= row_max && row >= row_min) { // if so, set in order - PRINTF("Adding inner: col: %d row: %d\n", col, row); + DPRINTF("Adding inner: col: %d row: %d", col, row); found++; - icvOrderQuad(neighbor, quads[i]->corners[j], (j+2)%4); + CV_Assert(q.corners[j]); + orderQuad(*neighbor, *q.corners[j], (j+2)&3); neighbor->ordered = true; neighbor->row = row; neighbor->col = col; @@ -914,18 +931,18 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, // which are missing if (found > 0) { - PRINTF("Found %d inner quads not connected to outer quads, repairing\n", found); - for (int i=0; icount < 4 && quads[i]->ordered) + ChessBoardQuad& q = *quads[i]; + if (q.count < 4 && q.ordered) { - int added = icvAddOuterQuad(quads[i],quads,quad_count,all_quads,*all_count,corners, max_quad_buf_size); - *all_count += added; + int added = addOuterQuad(q, quads); quad_count += added; } } - if (*all_count >= max_quad_buf_size) + if (all_quads_count >= max_quad_buf_size) return 0; } @@ -933,29 +950,27 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, // final trimming of outer quads if (dcol == w && drow == h) // found correct inner quads { - PRINTF("Inner bounds ok, check outer quads\n"); - int rcount = quad_count; - for (int i=quad_count-1; i>=0; i--) // eliminate any quad not connected to - // an ordered quad + DPRINTF("Inner bounds ok, check outer quads"); + for (int i = quad_count - 1; i >= 0; i--) // eliminate any quad not connected to an ordered quad { - if (quads[i]->ordered == false) + ChessBoardQuad& q = *quads[i]; + if (q.ordered == false) { bool outer = false; for (int j=0; j<4; j++) // any neighbors that are ordered? { - if (quads[i]->neighbors[j] && quads[i]->neighbors[j]->ordered) + if (q.neighbors[j] && q.neighbors[j]->ordered) outer = true; } if (!outer) // not an outer quad, eliminate { - PRINTF("Removing quad %d\n", i); - icvRemoveQuadFromGroup(quads,rcount,quads[i]); - rcount--; + DPRINTF("Removing quad %d", i); + removeQuadFromGroup(quads, q); } } } - return rcount; + return (int)quads.size(); } return 0; @@ -966,69 +981,63 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, // looks for the neighbor of that isn't present, // tries to add it in. // is ordered - -static int -icvAddOuterQuad( CvCBQuad *quad, CvCBQuad **quads, int quad_count, - CvCBQuad **all_quads, int all_count, CvCBCorner **corners, int max_quad_buf_size ) - +int ChessBoardDetector::addOuterQuad(ChessBoardQuad& quad, std::vector& quads) { int added = 0; - for (int i=0; i<4 && all_count < max_quad_buf_size; i++) // find no-neighbor corners + int max_quad_buf_size = (int)all_quads.size(); + + for (int i = 0; i < 4 && all_quads_count < max_quad_buf_size; i++) // find no-neighbor corners { - if (!quad->neighbors[i]) // ok, create and add neighbor + if (!quad.neighbors[i]) // ok, create and add neighbor { - int j = (i+2)%4; - PRINTF("Adding quad as neighbor 2\n"); - CvCBQuad *q = &(*all_quads)[all_count]; - memset( q, 0, sizeof(*q) ); + int j = (i+2)&3; + DPRINTF("Adding quad as neighbor 2"); + int q_index = all_quads_count++; + ChessBoardQuad& q = all_quads[q_index]; + q = ChessBoardQuad(0); added++; - quads[quad_count] = q; - quad_count++; + quads.push_back(&q); // set neighbor and group id - quad->neighbors[i] = q; - quad->count += 1; - q->neighbors[j] = quad; - q->group_idx = quad->group_idx; - q->count = 1; // number of neighbors - q->ordered = false; - q->edge_len = quad->edge_len; + quad.neighbors[i] = &q; + quad.count += 1; + q.neighbors[j] = &quad; + q.group_idx = quad.group_idx; + q.count = 1; // number of neighbors + q.ordered = false; + q.edge_len = quad.edge_len; // make corners of new quad // same as neighbor quad, but offset - CvPoint2D32f pt = quad->corners[i]->pt; - CvCBCorner* corner; - float dx = pt.x - quad->corners[j]->pt.x; - float dy = pt.y - quad->corners[j]->pt.y; - for (int k=0; k<4; k++) + const cv::Point2f pt_offset = quad.corners[i]->pt - quad.corners[j]->pt; + for (int k = 0; k < 4; k++) { - corner = &(*corners)[all_count*4+k]; - pt = quad->corners[k]->pt; - memset( corner, 0, sizeof(*corner) ); - corner->pt = pt; - q->corners[k] = corner; - corner->pt.x += dx; - corner->pt.y += dy; + ChessBoardCorner& corner = (ChessBoardCorner&)all_corners[q_index * 4 + k]; + const cv::Point2f& pt = quad.corners[k]->pt; + corner = ChessBoardCorner(pt); + q.corners[k] = &corner; + corner.pt += pt_offset; } // have to set exact corner - q->corners[j] = quad->corners[i]; + q.corners[j] = quad.corners[i]; // now find other neighbor and add it, if possible - if (quad->neighbors[(i+3)%4] && - quad->neighbors[(i+3)%4]->ordered && - quad->neighbors[(i+3)%4]->neighbors[i] && - quad->neighbors[(i+3)%4]->neighbors[i]->ordered ) + int next_i = (i + 1) & 3; + int prev_i = (i + 3) & 3; // equal to (j + 1) & 3 + ChessBoardQuad* quad_prev = quad.neighbors[prev_i]; + if (quad_prev && + quad_prev->ordered && + quad_prev->neighbors[i] && + quad_prev->neighbors[i]->ordered ) { - CvCBQuad *qn = quad->neighbors[(i+3)%4]->neighbors[i]; - q->count = 2; - q->neighbors[(j+1)%4] = qn; - qn->neighbors[(i+1)%4] = q; + ChessBoardQuad* qn = quad_prev->neighbors[i]; + q.count = 2; + q.neighbors[prev_i] = qn; + qn->neighbors[next_i] = &q; qn->count += 1; // have to set exact corner - q->corners[(j+1)%4] = qn->corners[(i+1)%4]; + q.corners[prev_i] = qn->corners[next_i]; } - - all_count++; } } return added; @@ -1037,151 +1046,141 @@ icvAddOuterQuad( CvCBQuad *quad, CvCBQuad **quads, int quad_count, // trimming routines #ifdef ENABLE_TRIM_COL_ROW -static int -icvTrimCol(CvCBQuad **quads, int count, int col, int dir) +void ChessBoardDetector::trimCol(std::vector& quads, int col, int dir) { - int rcount = count; + std::vector quads_(quads); // find the right quad(s) - for (int i=0; iordered) - PRINTF("index: %d cur: %d\n", col, quads[i]->col); + if (q.ordered) + DPRINTF("i: %d index: %d cur: %d", (int)i, col, q.col); #endif - if (quads[i]->ordered && quads[i]->col == col) + if (q.ordered && q.col == col) { if (dir == 1) { - if (quads[i]->neighbors[1]) + if (q.neighbors[1]) { - icvRemoveQuadFromGroup(quads,rcount,quads[i]->neighbors[1]); - rcount--; + removeQuadFromGroup(quads, *q.neighbors[1]); } - if (quads[i]->neighbors[2]) + if (q.neighbors[2]) { - icvRemoveQuadFromGroup(quads,rcount,quads[i]->neighbors[2]); - rcount--; + removeQuadFromGroup(quads, *q.neighbors[2]); } } else { - if (quads[i]->neighbors[0]) + if (q.neighbors[0]) { - icvRemoveQuadFromGroup(quads,rcount,quads[i]->neighbors[0]); - rcount--; + removeQuadFromGroup(quads, *q.neighbors[0]); } - if (quads[i]->neighbors[3]) + if (q.neighbors[3]) { - icvRemoveQuadFromGroup(quads,rcount,quads[i]->neighbors[3]); - rcount--; + removeQuadFromGroup(quads, *q.neighbors[3]); } } - } } - return rcount; } -static int -icvTrimRow(CvCBQuad **quads, int count, int row, int dir) +void ChessBoardDetector::trimRow(std::vector& quads, int row, int dir) { - int i, rcount = count; + std::vector quads_(quads); // find the right quad(s) - for (i=0; iordered) - PRINTF("index: %d cur: %d\n", row, quads[i]->row); + if (q.ordered) + DPRINTF("i: %d index: %d cur: %d", (int)i, row, q.row); #endif - if (quads[i]->ordered && quads[i]->row == row) + if (q.ordered && q.row == row) { if (dir == 1) // remove from bottom { - if (quads[i]->neighbors[2]) + if (q.neighbors[2]) { - icvRemoveQuadFromGroup(quads,rcount,quads[i]->neighbors[2]); - rcount--; + removeQuadFromGroup(quads, *q.neighbors[2]); } - if (quads[i]->neighbors[3]) + if (q.neighbors[3]) { - icvRemoveQuadFromGroup(quads,rcount,quads[i]->neighbors[3]); - rcount--; + removeQuadFromGroup(quads, *q.neighbors[3]); } } else // remove from top { - if (quads[i]->neighbors[0]) + if (q.neighbors[0]) { - icvRemoveQuadFromGroup(quads,rcount,quads[i]->neighbors[0]); - rcount--; + removeQuadFromGroup(quads, *q.neighbors[0]); } - if (quads[i]->neighbors[1]) + if (q.neighbors[1]) { - icvRemoveQuadFromGroup(quads,rcount,quads[i]->neighbors[1]); - rcount--; + removeQuadFromGroup(quads, *q.neighbors[1]); } } } } - return rcount; } #endif // // remove quad from quad group // - -static void -icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0) +void ChessBoardDetector::removeQuadFromGroup(std::vector& quads, ChessBoardQuad& q0) { - int i, j; + const int count = (int)quads.size(); + + int self_idx = -1; + // remove any references to this quad as a neighbor - for(i = 0; i < count; i++ ) + for (int i = 0; i < count; ++i) { - CvCBQuad *q = quads[i]; - for(j = 0; j < 4; j++ ) + ChessBoardQuad* q = quads[i]; + if (q == &q0) + self_idx = i; + for (int j = 0; j < 4; j++) { - if( q->neighbors[j] == q0 ) + if (q->neighbors[j] == &q0) { - q->neighbors[j] = 0; + q->neighbors[j] = NULL; q->count--; - for(int k = 0; k < 4; k++ ) - if( q0->neighbors[k] == q ) + for (int k = 0; k < 4; ++k) + { + if (q0.neighbors[k] == q) { - q0->neighbors[k] = 0; - q0->count--; + q0.neighbors[k] = 0; + q0.count--; +#ifndef _DEBUG break; +#endif } + } break; } } } + CV_Assert(self_idx >= 0); // item itself should be found // remove the quad - for(i = 0; i < count; i++ ) - { - CvCBQuad *q = quads[i]; - if (q == q0) - { - quads[i] = quads[count-1]; - break; - } - } + if (self_idx != count-1) + quads[self_idx] = quads[count-1]; + quads.resize(count - 1); } // // put quad into correct order, where has value // - -static void -icvOrderQuad(CvCBQuad *quad, CvCBCorner *corner, int common) +void ChessBoardDetector::orderQuad(ChessBoardQuad& quad, ChessBoardCorner& corner, int common) { + CV_DbgAssert(common >= 0 && common <= 3); + // find the corner - int tc; - for (tc=0; tc<4; tc++) - if (quad->corners[tc]->pt.x == corner->pt.x && - quad->corners[tc]->pt.y == corner->pt.y) + int tc = 0;; + for (; tc < 4; ++tc) + if (quad.corners[tc]->pt == corner.pt) break; // set corner order @@ -1189,62 +1188,52 @@ icvOrderQuad(CvCBQuad *quad, CvCBCorner *corner, int common) while (tc != common) { // shift by one - CvCBCorner *tempc; - CvCBQuad *tempq; - tempc = quad->corners[3]; - tempq = quad->neighbors[3]; - for (int i=3; i>0; i--) + ChessBoardCorner *tempc = quad.corners[3]; + ChessBoardQuad *tempq = quad.neighbors[3]; + for (int i = 3; i > 0; --i) { - quad->corners[i] = quad->corners[i-1]; - quad->neighbors[i] = quad->neighbors[i-1]; + quad.corners[i] = quad.corners[i-1]; + quad.neighbors[i] = quad.neighbors[i-1]; } - quad->corners[0] = tempc; - quad->neighbors[0] = tempq; - tc++; - tc = tc%4; + quad.corners[0] = tempc; + quad.neighbors[0] = tempq; + tc = (tc + 1) & 3; } } // if we found too many connect quads, remove those which probably do not belong. -static int -icvCleanFoundConnectedQuads( int quad_count, CvCBQuad **quad_group, CvSize pattern_size ) +int ChessBoardDetector::cleanFoundConnectedQuads(std::vector& quad_group) { - CvPoint2D32f center; - int i, j, k; // number of quads this pattern should contain int count = ((pattern_size.width + 1)*(pattern_size.height + 1) + 1)/2; // if we have more quadrangles than we should, // try to eliminate duplicates or ones which don't belong to the pattern rectangle... - if( quad_count <= count ) + int quad_count = (int)quad_group.size(); + if (quad_count <= count) return quad_count; + CV_DbgAssert(quad_count > 0); // create an array of quadrangle centers - cv::AutoBuffer centers( quad_count ); - cv::Ptr temp_storage(cvCreateMemStorage(0)); + cv::AutoBuffer centers(quad_count); - for( i = 0; i < quad_count; i++ ) + cv::Point2f center; + for (int i = 0; i < quad_count; ++i) { - CvPoint2D32f ci; - CvCBQuad* q = quad_group[i]; + ChessBoardQuad* q = quad_group[i]; - for( j = 0; j < 4; j++ ) - { - CvPoint2D32f pt = q->corners[j]->pt; - ci.x += pt.x; - ci.y += pt.y; - } - - ci.x *= 0.25f; - ci.y *= 0.25f; + const cv::Point2f ci = ( + q->corners[0]->pt + + q->corners[1]->pt + + q->corners[2]->pt + + q->corners[3]->pt + ) * 0.25f; centers[i] = ci; - center.x += ci.x; - center.y += ci.y; + center += ci; } - center.x /= quad_count; - center.y /= quad_count; + center.x *= (1.0f / quad_count); // If we still have more quadrangles than we should, // we try to eliminate bad ones based on minimizing the bounding box. @@ -1253,50 +1242,52 @@ icvCleanFoundConnectedQuads( int quad_count, CvCBQuad **quad_group, CvSize patte // (since we want the rectangle to be as small as possible) // remove the quadrange that causes the biggest reduction // in pattern size until we have the correct number - for( ; quad_count > count; quad_count-- ) + for (; quad_count > count; quad_count--) { double min_box_area = DBL_MAX; - int skip, min_box_area_index = -1; + int min_box_area_index = -1; // For each point, calculate box area without that point - for( skip = 0; skip < quad_count; skip++ ) + for (int skip = 0; skip < quad_count; ++skip) { // get bounding rectangle - CvPoint2D32f temp = centers[skip]; // temporarily make index 'skip' the same as + cv::Point2f temp = centers[skip]; // temporarily make index 'skip' the same as centers[skip] = center; // pattern center (so it is not counted for convex hull) - CvMat pointMat = cvMat(1, quad_count, CV_32FC2, centers.data()); - CvSeq *hull = cvConvexHull2( &pointMat, temp_storage, CV_CLOCKWISE, 1 ); + std::vector hull; + Mat points(1, quad_count, CV_32FC2, ¢ers[0]); + cv::convexHull(points, hull, true); centers[skip] = temp; - double hull_area = fabs(cvContourArea(hull, CV_WHOLE_SEQ)); + double hull_area = contourArea(hull, true); // remember smallest box area - if( hull_area < min_box_area ) + if (hull_area < min_box_area) { min_box_area = hull_area; min_box_area_index = skip; } - cvClearMemStorage( temp_storage ); } - CvCBQuad *q0 = quad_group[min_box_area_index]; + ChessBoardQuad *q0 = quad_group[min_box_area_index]; // remove any references to this quad as a neighbor - for( i = 0; i < quad_count; i++ ) + for (int i = 0; i < quad_count; ++i) { - CvCBQuad *q = quad_group[i]; - for( j = 0; j < 4; j++ ) + ChessBoardQuad *q = quad_group[i]; + for (int j = 0; j < 4; ++j) { - if( q->neighbors[j] == q0 ) + if (q->neighbors[j] == q0) { q->neighbors[j] = 0; q->count--; - for( k = 0; k < 4; k++ ) - if( q0->neighbors[k] == q ) + for (int k = 0; k < 4; ++k) + { + if (q0->neighbors[k] == q) { q0->neighbors[k] = 0; q0->count--; break; } + } break; } } @@ -1311,111 +1302,108 @@ icvCleanFoundConnectedQuads( int quad_count, CvCBQuad **quad_group, CvSize patte return quad_count; } -//===================================================================================== -static int -icvFindConnectedQuads( CvCBQuad *quad, int quad_count, CvCBQuad **out_group, - int group_idx, CvMemStorage* storage ) + +void ChessBoardDetector::findConnectedQuads(std::vector& out_group, int group_idx) { - cv::Ptr temp_storage(cvCreateChildMemStorage( storage )); - CvSeq* stack = cvCreateSeq( 0, sizeof(*stack), sizeof(void*), temp_storage ); - int i, count = 0; + out_group.clear(); - // Scan the array for a first unlabeled quad - for( i = 0; i < quad_count; i++ ) - { - if( quad[i].count > 0 && quad[i].group_idx < 0) - break; - } + std::stack stack; - // Recursively find a group of connected quads starting from the seed quad[i] - if( i < quad_count ) + int i = 0; + for (; i < all_quads_count; i++) { - CvCBQuad* q = &quad[i]; - cvSeqPush( stack, &q ); - out_group[count++] = q; + ChessBoardQuad* q = (ChessBoardQuad*)&all_quads[i]; + + // Scan the array for a first unlabeled quad + if (q->count <= 0 || q->group_idx >= 0) continue; + + // Recursively find a group of connected quads starting from the seed all_quads[i] + stack.push(q); + out_group.push_back(q); q->group_idx = group_idx; q->ordered = false; - while( stack->total ) + while (!stack.empty()) { - cvSeqPop( stack, &q ); - for( i = 0; i < 4; i++ ) + q = stack.top(); CV_Assert(q); + stack.pop(); + for (int k = 0; k < 4; k++ ) { - CvCBQuad *neighbor = q->neighbors[i]; - if( neighbor && neighbor->count > 0 && neighbor->group_idx < 0 ) + ChessBoardQuad *neighbor = q->neighbors[k]; + if (neighbor && neighbor->count > 0 && neighbor->group_idx < 0 ) { - cvSeqPush( stack, &neighbor ); - out_group[count++] = neighbor; + stack.push(neighbor); + out_group.push_back(neighbor); neighbor->group_idx = group_idx; neighbor->ordered = false; } } } + break; } - - return count; } -//===================================================================================== - -static int -icvCheckQuadGroup( CvCBQuad **quad_group, int quad_count, - CvCBCorner **out_corners, CvSize pattern_size ) +int ChessBoardDetector::checkQuadGroup(std::vector& quad_group, std::vector& out_corners) { const int ROW1 = 1000000; const int ROW2 = 2000000; const int ROW_ = 3000000; - int result = 0; - int i, out_corner_count = 0, corner_count = 0; - std::vector corners(quad_count*4); - int j, k, kk; + int quad_count = (int)quad_group.size(); + + std::vector corners(quad_count*4); + int corner_count = 0; + int result = 0; + int width = 0, height = 0; int hist[5] = {0,0,0,0,0}; - CvCBCorner* first = 0, *first2 = 0, *right, *cur, *below, *c; + //ChessBoardCorner* first = 0, *first2 = 0, *right, *cur, *below, *c; // build dual graph, which vertices are internal quad corners // and two vertices are connected iff they lie on the same quad edge - for( i = 0; i < quad_count; i++ ) + for (int i = 0; i < quad_count; ++i) { - CvCBQuad* q = quad_group[i]; + ChessBoardQuad* q = quad_group[i]; /*CvScalar color = q->count == 0 ? cvScalar(0,255,255) : q->count == 1 ? cvScalar(0,0,255) : q->count == 2 ? cvScalar(0,255,0) : q->count == 3 ? cvScalar(255,255,0) : cvScalar(255,0,0);*/ - for( j = 0; j < 4; j++ ) + for (int j = 0; j < 4; ++j) { //cvLine( debug_img, cvPointFrom32f(q->corners[j]->pt), cvPointFrom32f(q->corners[(j+1)&3]->pt), color, 1, CV_AA, 0 ); - if( q->neighbors[j] ) + if (q->neighbors[j]) { - CvCBCorner *a = q->corners[j], *b = q->corners[(j+1)&3]; + int next_j = (j + 1) & 3; + ChessBoardCorner *a = q->corners[j], *b = q->corners[next_j]; // mark internal corners that belong to: // - a quad with a single neighbor - with ROW1, // - a quad with two neighbors - with ROW2 // make the rest of internal corners with ROW_ int row_flag = q->count == 1 ? ROW1 : q->count == 2 ? ROW2 : ROW_; - if( a->row == 0 ) + if (a->row == 0) { corners[corner_count++] = a; a->row = row_flag; } - else if( a->row > row_flag ) - a->row = row_flag; - - if( q->neighbors[(j+1)&3] ) + else if (a->row > row_flag) { - if( a->count >= 4 || b->count >= 4 ) + a->row = row_flag; + } + + if (q->neighbors[next_j]) + { + if (a->count >= 4 || b->count >= 4) goto finalize; - for( k = 0; k < 4; k++ ) + for (int k = 0; k < 4; ++k) { - if( a->neighbors[k] == b ) + if (a->neighbors[k] == b) goto finalize; - if( b->neighbors[k] == a ) + if (b->neighbors[k] == a) goto finalize; } a->neighbors[a->count++] = b; @@ -1425,19 +1413,21 @@ icvCheckQuadGroup( CvCBQuad **quad_group, int quad_count, } } - if( corner_count != pattern_size.width*pattern_size.height ) + if (corner_count != pattern_size.width*pattern_size.height) goto finalize; - for( i = 0; i < corner_count; i++ ) +{ + ChessBoardCorner* first = NULL, *first2 = NULL; + for (int i = 0; i < corner_count; ++i) { int n = corners[i]->count; - assert( 0 <= n && n <= 4 ); + CV_DbgAssert(0 <= n && n <= 4); hist[n]++; - if( !first && n == 2 ) + if (!first && n == 2) { - if( corners[i]->row == ROW1 ) + if (corners[i]->row == ROW1) first = corners[i]; - else if( !first2 && corners[i]->row == ROW2 ) + else if (!first2 && corners[i]->row == ROW2) first2 = corners[i]; } } @@ -1451,18 +1441,19 @@ icvCheckQuadGroup( CvCBQuad **quad_group, int quad_count, hist[3] != (pattern_size.width + pattern_size.height)*2 - 8 ) goto finalize; - cur = first; - right = below = 0; - out_corners[out_corner_count++] = cur; + ChessBoardCorner* cur = first; + ChessBoardCorner* right = NULL; + ChessBoardCorner* below = NULL; + out_corners.push_back(cur); - for( k = 0; k < 4; k++ ) + for (int k = 0; k < 4; ++k) { - c = cur->neighbors[k]; - if( c ) + ChessBoardCorner* c = cur->neighbors[k]; + if (c) { - if( !right ) + if (!right) right = c; - else if( !below ) + else if (!below) below = c; } } @@ -1475,28 +1466,30 @@ icvCheckQuadGroup( CvCBQuad **quad_group, int quad_count, //cvCircle( debug_img, cvPointFrom32f(cur->pt), 3, cvScalar(0,255,0), -1, 8, 0 ); first = below; // remember the first corner in the next row + // find and store the first row (or column) - for(j=1;;j++) + for (int j = 1; ; ++j) { right->row = 0; - out_corners[out_corner_count++] = right; + out_corners.push_back(right); //cvCircle( debug_img, cvPointFrom32f(right->pt), 3, cvScalar(0,255-j*10,0), -1, 8, 0 ); if( right->count == 2 ) break; - if( right->count != 3 || out_corner_count >= MAX(pattern_size.width,pattern_size.height) ) + if( right->count != 3 || (int)out_corners.size() >= std::max(pattern_size.width,pattern_size.height) ) goto finalize; cur = right; - for( k = 0; k < 4; k++ ) + for (int k = 0; k < 4; ++k) { - c = cur->neighbors[k]; - if( c && c->row > 0 ) + ChessBoardCorner* c = cur->neighbors[k]; + if (c && c->row > 0) { - for( kk = 0; kk < 4; kk++ ) + int kk = 0; + for (; kk < 4; ++kk) { - if( c->neighbors[kk] == below ) + if (c->neighbors[kk] == below) break; } - if( kk < 4 ) + if (kk < 4) below = c; else right = c; @@ -1504,109 +1497,114 @@ icvCheckQuadGroup( CvCBQuad **quad_group, int quad_count, } } - width = out_corner_count; - if( width == pattern_size.width ) + width = (int)out_corners.size(); + if (width == pattern_size.width) height = pattern_size.height; - else if( width == pattern_size.height ) + else if (width == pattern_size.height) height = pattern_size.width; else goto finalize; // find and store all the other rows - for( i = 1; ; i++ ) + for (int i = 1; ; ++i) { if( !first ) break; cur = first; first = 0; - for( j = 0;; j++ ) + int j = 0; + for (; ; ++j) { cur->row = i; - out_corners[out_corner_count++] = cur; + out_corners.push_back(cur); //cvCircle( debug_img, cvPointFrom32f(cur->pt), 3, cvScalar(0,0,255-j*10), -1, 8, 0 ); - if( cur->count == 2 + (i < height-1) && j > 0 ) + if (cur->count == 2 + (i < height-1) && j > 0) break; right = 0; // find a neighbor that has not been processed yet // and that has a neighbor from the previous row - for( k = 0; k < 4; k++ ) + for (int k = 0; k < 4; ++k) { - c = cur->neighbors[k]; - if( c && c->row > i ) + ChessBoardCorner* c = cur->neighbors[k]; + if (c && c->row > i) { - for( kk = 0; kk < 4; kk++ ) + int kk = 0; + for (; kk < 4; ++kk) { - if( c->neighbors[kk] && c->neighbors[kk]->row == i-1 ) + if (c->neighbors[kk] && c->neighbors[kk]->row == i-1) break; } - if( kk < 4 ) + if(kk < 4) { right = c; - if( j > 0 ) + if (j > 0) break; } - else if( j == 0 ) + else if (j == 0) first = c; } } - if( !right ) + if (!right) goto finalize; cur = right; } - if( j != width - 1 ) + if (j != width - 1) goto finalize; } - if( out_corner_count != corner_count ) + if ((int)out_corners.size() != corner_count) goto finalize; // check if we need to transpose the board - if( width != pattern_size.width ) + if (width != pattern_size.width) { - CV_SWAP( width, height, k ); + std::swap(width, height); - memcpy( &corners[0], out_corners, corner_count*sizeof(corners[0]) ); - for( i = 0; i < height; i++ ) - for( j = 0; j < width; j++ ) - out_corners[i*width + j] = corners[j*height + i]; + std::vector tmp(out_corners); + for (int i = 0; i < height; ++i) + for (int j = 0; j < width; ++j) + out_corners[i*width + j] = tmp[j*height + i]; } // check if we need to revert the order in each row { - CvPoint2D32f p0 = out_corners[0]->pt, p1 = out_corners[pattern_size.width-1]->pt, - p2 = out_corners[pattern_size.width]->pt; + cv::Point2f p0 = out_corners[0]->pt, + p1 = out_corners[pattern_size.width-1]->pt, + p2 = out_corners[pattern_size.width]->pt; if( (p1.x - p0.x)*(p2.y - p1.y) - (p1.y - p0.y)*(p2.x - p1.x) < 0 ) { - if( width % 2 == 0 ) + if (width % 2 == 0) { - for( i = 0; i < height; i++ ) - for( j = 0; j < width/2; j++ ) - CV_SWAP( out_corners[i*width+j], out_corners[i*width+width-j-1], c ); + for (int i = 0; i < height; ++i) + for (int j = 0; j < width/2; ++j) + std::swap(out_corners[i*width+j], out_corners[i*width+width-j-1]); } else { - for( j = 0; j < width; j++ ) - for( i = 0; i < height/2; i++ ) - CV_SWAP( out_corners[i*width+j], out_corners[(height - i - 1)*width+j], c ); + for (int j = 0; j < width; ++j) + for (int i = 0; i < height/2; ++i) + std::swap(out_corners[i*width+j], out_corners[(height - i - 1)*width+j]); } } } result = corner_count; +} finalize: - - if( result <= 0 ) + if (result <= 0) { - corner_count = MIN( corner_count, pattern_size.width*pattern_size.height ); - for( i = 0; i < corner_count; i++ ) + corner_count = std::min(corner_count, pattern_size.area()); + out_corners.resize(corner_count); + for (int i = 0; i < corner_count; i++) out_corners[i] = corners[i]; + result = -corner_count; - if (result == -pattern_size.width*pattern_size.height) + if (result == -pattern_size.area()) result = -result; } @@ -1615,19 +1613,13 @@ finalize: - -//===================================================================================== - -static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count ) +void ChessBoardDetector::findQuadNeighbors() { const float thresh_scale = 1.f; - int idx, i, k, j; - float dx, dy, dist; - // find quad neighbors - for( idx = 0; idx < quad_count; idx++ ) + for (int idx = 0; idx < all_quads_count; idx++) { - CvCBQuad* cur_quad = &quads[idx]; + ChessBoardQuad& cur_quad = (ChessBoardQuad&)all_quads[idx]; // choose the points of the current quadrangle that are close to // some points of the other quadrangles @@ -1635,151 +1627,141 @@ static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count ) // checker board). Search only in other quadrangles! // for each corner of this quadrangle - for( i = 0; i < 4; i++ ) + for (int i = 0; i < 4; i++) { - CvPoint2D32f pt; - float min_dist = FLT_MAX; - int closest_corner_idx = -1; - CvCBQuad *closest_quad = 0; - CvCBCorner *closest_corner = 0; - - if( cur_quad->neighbors[i] ) + if (cur_quad.neighbors[i]) continue; - pt = cur_quad->corners[i]->pt; + float min_dist = FLT_MAX; + int closest_corner_idx = -1; + ChessBoardQuad *closest_quad = 0; + + cv::Point2f pt = cur_quad.corners[i]->pt; // find the closest corner in all other quadrangles - for( k = 0; k < quad_count; k++ ) + for (int k = 0; k < all_quads_count; k++) { - if( k == idx ) + if (k == idx) continue; - for( j = 0; j < 4; j++ ) + ChessBoardQuad& q_k = all_quads[k]; + + for (int j = 0; j < 4; j++) { - if( quads[k].neighbors[j] ) + if (q_k.neighbors[j]) continue; - dx = pt.x - quads[k].corners[j]->pt.x; - dy = pt.y - quads[k].corners[j]->pt.y; - dist = dx * dx + dy * dy; - - if( dist < min_dist && - dist <= cur_quad->edge_len*thresh_scale && - dist <= quads[k].edge_len*thresh_scale ) + float dist = normL2Sqr(pt - q_k.corners[j]->pt); + if (dist < min_dist && + dist <= cur_quad.edge_len*thresh_scale && + dist <= q_k.edge_len*thresh_scale ) { // check edge lengths, make sure they're compatible // edges that are different by more than 1:4 are rejected - float ediff = cur_quad->edge_len - quads[k].edge_len; - if (ediff > 32*cur_quad->edge_len || - ediff > 32*quads[k].edge_len) + float ediff = cur_quad.edge_len - q_k.edge_len; + if (ediff > 32*cur_quad.edge_len || + ediff > 32*q_k.edge_len) { - PRINTF("Incompatible edge lengths\n"); + DPRINTF("Incompatible edge lengths"); continue; } closest_corner_idx = j; - closest_quad = &quads[k]; + closest_quad = &q_k; min_dist = dist; } } } // we found a matching corner point? - if( closest_corner_idx >= 0 && min_dist < FLT_MAX ) + if (closest_corner_idx >= 0 && min_dist < FLT_MAX) { + CV_Assert(closest_quad); + + if (cur_quad.count >= 4 || closest_quad->count >= 4) + continue; + // If another point from our current quad is closer to the found corner // than the current one, then we don't count this one after all. // This is necessary to support small squares where otherwise the wrong // corner will get matched to closest_quad; - closest_corner = closest_quad->corners[closest_corner_idx]; + ChessBoardCorner& closest_corner = *closest_quad->corners[closest_corner_idx]; - for( j = 0; j < 4; j++ ) + int j = 0; + for (; j < 4; j++) { - if( cur_quad->neighbors[j] == closest_quad ) + if (cur_quad.neighbors[j] == closest_quad) break; - dx = closest_corner->pt.x - cur_quad->corners[j]->pt.x; - dy = closest_corner->pt.y - cur_quad->corners[j]->pt.y; - - if( dx * dx + dy * dy < min_dist ) + if (normL2Sqr(closest_corner.pt - cur_quad.corners[j]->pt) < min_dist) break; } - - if( j < 4 || cur_quad->count >= 4 || closest_quad->count >= 4 ) + if (j < 4) continue; // Check that each corner is a neighbor of different quads - for( j = 0; j < closest_quad->count; j++ ) + for(j = 0; j < closest_quad->count; j++ ) { - if( closest_quad->neighbors[j] == cur_quad ) + if (closest_quad->neighbors[j] == &cur_quad) break; } - if( j < closest_quad->count ) + if (j < closest_quad->count) continue; // check whether the closest corner to closest_corner // is different from cur_quad->corners[i]->pt - for( k = 0; k < quad_count; k++ ) + for (j = 0; j < all_quads_count; j++ ) { - CvCBQuad* q = &quads[k]; - if( k == idx || q == closest_quad ) + ChessBoardQuad* q = &const_cast(all_quads[j]); + if (j == idx || q == closest_quad) continue; - for( j = 0; j < 4; j++ ) - if( !q->neighbors[j] ) + int k = 0; + for (; k < 4; k++ ) + { + if (!q->neighbors[k]) { - dx = closest_corner->pt.x - q->corners[j]->pt.x; - dy = closest_corner->pt.y - q->corners[j]->pt.y; - dist = dx*dx + dy*dy; - if( dist < min_dist ) + if (normL2Sqr(closest_corner.pt - q->corners[k]->pt) < min_dist) break; } - if( j < 4 ) + } + if (k < 4) break; } - - if( k < quad_count ) + if (j < all_quads_count) continue; - closest_corner->pt.x = (pt.x + closest_corner->pt.x) * 0.5f; - closest_corner->pt.y = (pt.y + closest_corner->pt.y) * 0.5f; + closest_corner.pt = (pt + closest_corner.pt) * 0.5f; // We've found one more corner - remember it - cur_quad->count++; - cur_quad->neighbors[i] = closest_quad; - cur_quad->corners[i] = closest_corner; + cur_quad.count++; + cur_quad.neighbors[i] = closest_quad; + cur_quad.corners[i] = &closest_corner; closest_quad->count++; - closest_quad->neighbors[closest_corner_idx] = cur_quad; + closest_quad->neighbors[closest_corner_idx] = &cur_quad; } } } } -//===================================================================================== // returns corners in clockwise order // corners don't necessarily start at same position on quad (e.g., // top left corner) - -static int -icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, - CvMemStorage *storage, const cv::Mat & image_, int flags, int *max_quad_buf_size ) +void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags) { + binarized_image = image_; // save for debug purposes + int quad_count = 0; - cv::Ptr temp_storage; - if( out_quads ) - *out_quads = 0; - - if( out_corners ) - *out_corners = 0; + all_quads.deallocate(); + all_corners.deallocate(); // empiric bound for minimal allowed perimeter for squares int min_size = 25; //cvRound( image->cols * image->rows * .03 * 0.01 * 0.92 ); bool filterQuads = (flags & CALIB_CB_FILTER_QUADS) != 0; #ifdef USE_CV_FINDCONTOURS // use cv::findContours - CV_UNUSED(storage); std::vector > contours; std::vector hierarchy; @@ -1789,8 +1771,7 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, if (contours.empty()) { CV_LOG_DEBUG(NULL, "calib3d(chessboard): cv::findContours() returns no contours"); - *max_quad_buf_size = 0; - return 0; + return; } std::vector contour_child_counter(contours.size(), 0); @@ -1863,65 +1844,55 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, } size_t total = contour_quads.size(); - *max_quad_buf_size = (int)std::max((size_t)2, total * 3); - *out_quads = (CvCBQuad*)cvAlloc(*max_quad_buf_size * sizeof((*out_quads)[0])); - *out_corners = (CvCBCorner*)cvAlloc(*max_quad_buf_size * 4 * sizeof((*out_corners)[0])); + size_t max_quad_buf_size = std::max((size_t)2, total * 3); + all_quads.allocate(max_quad_buf_size); + all_corners.allocate(max_quad_buf_size * 4); // Create array of quads structures - for(int idx = 0; idx < (int)contour_quads.size(); idx++ ) + for (size_t idx = 0; idx < total; ++idx) { - CvCBQuad* q = &(*out_quads)[quad_count]; - QuadCountour& qc = contour_quads[idx]; if (filterQuads && qc.parent_contour != boardIdx) continue; - // reset group ID - memset(q, 0, sizeof(*q)); - q->group_idx = -1; - for (int i = 0; i < 4; ++i) - { - CvCBCorner* corner = &(*out_corners)[quad_count*4 + i]; + int quad_idx = quad_count++; + ChessBoardQuad& q = all_quads[quad_idx]; - memset(corner, 0, sizeof(*corner)); - corner->pt = qc.pt[i]; - q->corners[i] = corner; - } - q->edge_len = FLT_MAX; + // reset group ID + q = ChessBoardQuad(); for (int i = 0; i < 4; ++i) { - // TODO simplify with normL2Sqr() - float dx = q->corners[i]->pt.x - q->corners[(i+1)&3]->pt.x; - float dy = q->corners[i]->pt.y - q->corners[(i+1)&3]->pt.y; - float d = dx*dx + dy*dy; - if (q->edge_len > d) - q->edge_len = d; + Point2f pt(qc.pt[i]); + ChessBoardCorner& corner = all_corners[quad_idx * 4 + i]; + + corner = ChessBoardCorner(pt); + q.corners[i] = &corner; + } + q.edge_len = FLT_MAX; + for (int i = 0; i < 4; ++i) + { + float d = normL2Sqr(q.corners[i]->pt - q.corners[(i+1)&3]->pt); + q.edge_len = std::min(q.edge_len, d); } - quad_count++; } #else // use legacy API: cvStartFindContours / cvFindNextContour / cvEndFindContours - CvMat image_old(image_), *image = &image_old; + CvMat image_old = cvMat(image_), *image = &image_old; - CvSeq *src_contour = 0; - CvSeq *root; CvContourEx* board = 0; - CvContourScanner scanner; - int i, idx; - - CV_Assert( out_corners && out_quads ); // create temporary storage for contours and the sequence of pointers to found quadrangles - temp_storage.reset(cvCreateChildMemStorage( storage )); - root = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvSeq*), temp_storage ); + cv::Ptr temp_storage(cvCreateMemStorage(0)); + CvSeq *root = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvSeq*), temp_storage); // initialize contour retrieving routine - scanner = cvStartFindContours( image, temp_storage, sizeof(CvContourEx), - CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); + CvContourScanner scanner = cvStartFindContours(image, temp_storage, sizeof(CvContourEx), + CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); // get all the contours one by one - while( (src_contour = cvFindNextContour( scanner )) != 0 ) + CvSeq* src_contour = NULL; + while ((src_contour = cvFindNextContour(scanner)) != NULL) { CvSeq *dst_contour = 0; CvRect rect = ((CvContour*)src_contour)->rect; @@ -1930,8 +1901,7 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, if( CV_IS_SEQ_HOLE(src_contour) && rect.width*rect.height >= min_size ) { const int min_approx_level = 1, max_approx_level = MAX_CONTOUR_APPROX; - int approx_level; - for( approx_level = min_approx_level; approx_level <= max_approx_level; approx_level++ ) + for (int approx_level = min_approx_level; approx_level <= max_approx_level; approx_level++ ) { dst_contour = cvApproxPoly( src_contour, sizeof(CvContour), temp_storage, CV_POLY_APPROX_DP, (float)approx_level ); @@ -1950,31 +1920,21 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, // reject non-quadrangles if( dst_contour->total == 4 && cvCheckContourConvexity(dst_contour) ) { - CvPoint pt[4]; - double d1, d2, p = cvContourPerimeter(dst_contour); + cv::Point2i pt[4]; + double p = cvContourPerimeter(dst_contour); double area = fabs(cvContourArea(dst_contour, CV_WHOLE_SEQ)); - double dx, dy; - for( i = 0; i < 4; i++ ) + for (int i = 0; i < 4; ++i) pt[i] = *(CvPoint*)cvGetSeqElem(dst_contour, i); + CV_LOG_VERBOSE(NULL, 9, "... contours(" << root->total << " added):" << pt[0] << " " << pt[1] << " " << pt[2] << " " << pt[3]); - dx = pt[0].x - pt[2].x; - dy = pt[0].y - pt[2].y; - d1 = sqrt(dx*dx + dy*dy); - - dx = pt[1].x - pt[3].x; - dy = pt[1].y - pt[3].y; - d2 = sqrt(dx*dx + dy*dy); + double d1 = sqrt(normL2Sqr(pt[0] - pt[2])); + double d2 = sqrt(normL2Sqr(pt[1] - pt[3])); // philipg. Only accept those quadrangles which are more square // than rectangular and which are big enough - double d3, d4; - dx = pt[0].x - pt[1].x; - dy = pt[0].y - pt[1].y; - d3 = sqrt(dx*dx + dy*dy); - dx = pt[1].x - pt[2].x; - dy = pt[1].y - pt[2].y; - d4 = sqrt(dx*dx + dy*dy); + double d3 = sqrt(normL2Sqr(pt[0] - pt[1])); + double d4 = sqrt(normL2Sqr(pt[1] - pt[2])); if (!filterQuads || (d3*4 > d4 && d4*4 > d3 && d3*d4 < area*1.5 && area > min_size && d1 >= 0.15 * p && d2 >= 0.15 * p)) @@ -1996,156 +1956,151 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, // allocate quad & corner buffers int total = root->total; - *max_quad_buf_size = MAX(1, (total + total / 2)) * 2; - *out_quads = (CvCBQuad*)cvAlloc(*max_quad_buf_size * sizeof((*out_quads)[0])); - *out_corners = (CvCBCorner*)cvAlloc(*max_quad_buf_size * 4 * sizeof((*out_corners)[0])); + size_t max_quad_buf_size = std::max((size_t)2, (size_t)total * 3); + all_quads.allocate(max_quad_buf_size); + all_corners.allocate(max_quad_buf_size * 4); // Create array of quads structures - for( idx = 0; idx < root->total; idx++ ) + for (int idx = 0; idx < total; ++idx) { - CvCBQuad* q = &(*out_quads)[quad_count]; - src_contour = *(CvSeq**)cvGetSeqElem( root, idx ); + /* CvSeq* */src_contour = *(CvSeq**)cvGetSeqElem(root, idx); if (filterQuads && src_contour->v_prev != (CvSeq*)board) continue; - // reset group ID - memset( q, 0, sizeof(*q) ); - q->group_idx = -1; - assert( src_contour->total == 4 ); - for( i = 0; i < 4; i++ ) - { - CvPoint * onePoint = (CvPoint*)cvGetSeqElem(src_contour, i); - CV_Assert(onePoint != NULL); - CvPoint2D32f pt = cvPointTo32f(*onePoint); - CvCBCorner* corner = &(*out_corners)[quad_count*4 + i]; + int quad_idx = quad_count++; + ChessBoardQuad& q = all_quads[quad_idx]; - memset( corner, 0, sizeof(*corner) ); - corner->pt = pt; - q->corners[i] = corner; - } - q->edge_len = FLT_MAX; - for( i = 0; i < 4; i++ ) + // reset group ID + q = ChessBoardQuad(); + CV_Assert(src_contour->total == 4); + for (int i = 0; i < 4; i++) { - float dx = q->corners[i]->pt.x - q->corners[(i+1)&3]->pt.x; - float dy = q->corners[i]->pt.y - q->corners[(i+1)&3]->pt.y; - float d = dx*dx + dy*dy; - if( q->edge_len > d ) - q->edge_len = d; + Point* onePoint = (Point*)cvGetSeqElem(src_contour, i); + CV_Assert(onePoint != NULL); + Point2f pt(*onePoint); + ChessBoardCorner& corner = all_corners[quad_idx*4 + i]; + + corner = ChessBoardCorner(pt); + q.corners[i] = &corner; + } + q.edge_len = FLT_MAX; + for (int i = 0; i < 4; ++i) + { + float d = normL2Sqr(q.corners[i]->pt - q.corners[(i+1)&3]->pt); + q.edge_len = std::min(q.edge_len, d); } - quad_count++; } #endif - CV_LOG_VERBOSE(NULL, 3, "Total quad contours: " << total); - CV_LOG_VERBOSE(NULL, 3, "max_quad_buf_size=" << *max_quad_buf_size); - CV_LOG_VERBOSE(NULL, 3, "filtered quad_count=" << quad_count); + all_quads_count = quad_count; - return quad_count; + CV_LOG_VERBOSE(NULL, 3, "Total quad contours: " << total); + CV_LOG_VERBOSE(NULL, 3, "max_quad_buf_size=" << max_quad_buf_size); + CV_LOG_VERBOSE(NULL, 3, "filtered quad_count=" << quad_count); } -static bool processQuads(CvCBQuad *quads, int quad_count, CvSize pattern_size, int max_quad_buf_size, - CvMemStorage * storage, CvCBCorner *corners, CvPoint2D32f *out_corners, int *out_corner_count, int & prev_sqr_size) +bool ChessBoardDetector::processQuads(std::vector& out_corners, int &prev_sqr_size) { - if( quad_count <= 0 ) + out_corners.resize(0); + if (all_quads_count <= 0) return false; - bool found = false; + size_t max_quad_buf_size = all_quads.size(); // Find quad's neighbors - icvFindQuadNeighbors( quads, quad_count ); + findQuadNeighbors(); - // allocate extra for adding in icvOrderFoundQuads - CvCBQuad **quad_group = 0; - CvCBCorner **corner_group = 0; + // allocate extra for adding in orderFoundQuads + std::vector quad_group; + std::vector corner_group; corner_group.reserve(max_quad_buf_size * 4); - quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size); - corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 ); - - for( int group_idx = 0; ; group_idx++ ) + for (int group_idx = 0; ; group_idx++) { - int count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage ); - - if( count == 0 ) + findConnectedQuads(quad_group, group_idx); + if (quad_group.empty()) break; + int count = (int)quad_group.size(); + // order the quad corners globally // maybe delete or add some - PRINTF("Starting ordering of inner quads (%d)\n", count); - count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, - pattern_size, max_quad_buf_size, storage ); - PRINTF("Finished ordering of inner quads (%d)\n", count); + DPRINTF("Starting ordering of inner quads (%d)", count); + count = orderFoundConnectedQuads(quad_group); + DPRINTF("Finished ordering of inner quads (%d)", count); if (count == 0) continue; // haven't found inner quads // If count is more than it should be, this will remove those quads // which cause maximum deviation from a nice square pattern. - count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size ); - PRINTF("Connected group: %d, count: %d\n", group_idx, count); + count = cleanFoundConnectedQuads(quad_group); + DPRINTF("Connected group: %d, count: %d", group_idx, count); - count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size ); - PRINTF("Connected group: %d, count: %d\n", group_idx, count); + count = checkQuadGroup(quad_group, corner_group); + DPRINTF("Connected group: %d, count: %d", group_idx, count); int n = count > 0 ? pattern_size.width * pattern_size.height : -count; - n = MIN( n, pattern_size.width * pattern_size.height ); + n = std::min(n, pattern_size.width * pattern_size.height); float sum_dist = 0; int total = 0; for(int i = 0; i < n; i++ ) { int ni = 0; - float avgi = corner_group[i]->meanDist(&ni); - sum_dist += avgi*ni; + float sum = corner_group[i]->sumDist(ni); + sum_dist += sum; total += ni; } - prev_sqr_size = cvRound(sum_dist/MAX(total, 1)); + prev_sqr_size = cvRound(sum_dist/std::max(total, 1)); - if( count > 0 || (out_corner_count && -count > *out_corner_count) ) + if (count > 0 || (-count > (int)out_corners.size())) { // copy corners to output array - for(int i = 0; i < n; i++ ) - out_corners[i] = corner_group[i]->pt; + out_corners.reserve(n); + for (int i = 0; i < n; ++i) + out_corners.push_back(corner_group[i]->pt); - if( out_corner_count ) - *out_corner_count = n; - - if( count == pattern_size.width*pattern_size.height - && icvCheckBoardMonotony( out_corners, pattern_size )) + if (count == pattern_size.width*pattern_size.height + && checkBoardMonotony(out_corners)) { - found = true; - break; + return true; } } } - cvFree(&quad_group); - cvFree(&corner_group); - - return found; + return false; } -//================================================================================================== -CV_IMPL void -cvDrawChessboardCorners( CvArr* _image, CvSize pattern_size, - CvPoint2D32f* corners, int count, int found ) + +void drawChessboardCorners( InputOutputArray image, Size patternSize, + InputArray _corners, + bool patternWasFound ) { + CV_INSTRUMENT_REGION(); + + int type = image.type(); + int cn = CV_MAT_CN(type); + CV_CheckType(type, cn == 1 || cn == 3 || cn == 4, + "Number of channels must be 1, 3 or 4" ); + + int depth = CV_MAT_DEPTH(type); + CV_CheckType(type, depth == CV_8U || depth == CV_16U || depth == CV_32F, + "Only 8-bit, 16-bit or floating-point 32-bit images are supported"); + + if (_corners.empty()) + return; + Mat corners = _corners.getMat(); + const Point2f* corners_data = corners.ptr(0); + int nelems = corners.checkVector(2, CV_32F, true); + CV_Assert(nelems >= 0); + const int shift = 0; const int radius = 4; const int r = radius*(1 << shift); - int i; - CvMat stub, *image; + double scale = 1; - int type, cn, line_type; - - image = cvGetMat( _image, &stub ); - - type = CV_MAT_TYPE(image->type); - cn = CV_MAT_CN(type); - if( cn != 1 && cn != 3 && cn != 4 ) - CV_Error( CV_StsUnsupportedFormat, "Number of channels must be 1, 3 or 4" ); - - switch( CV_MAT_DEPTH(image->type) ) + switch (depth) { case CV_8U: scale = 1; @@ -2156,140 +2111,90 @@ cvDrawChessboardCorners( CvArr* _image, CvSize pattern_size, case CV_32F: scale = 1./255; break; - default: - CV_Error( CV_StsUnsupportedFormat, - "Only 8-bit, 16-bit or floating-point 32-bit images are supported" ); } - line_type = type == CV_8UC1 || type == CV_8UC3 ? CV_AA : 8; + int line_type = (type == CV_8UC1 || type == CV_8UC3) ? LINE_AA : LINE_8; - if( !found ) + if (!patternWasFound) { - CvScalar color(0,0,255,0); - if( cn == 1 ) - color = cvScalarAll(200); - color.val[0] *= scale; - color.val[1] *= scale; - color.val[2] *= scale; - color.val[3] *= scale; + Scalar color(0,0,255,0); + if (cn == 1) + color = Scalar::all(200); + color *= scale; - for( i = 0; i < count; i++ ) + for (int i = 0; i < nelems; i++ ) { - CvPoint pt; - pt.x = cvRound(corners[i].x*(1 << shift)); - pt.y = cvRound(corners[i].y*(1 << shift)); - cvLine( image, cvPoint( pt.x - r, pt.y - r ), - cvPoint( pt.x + r, pt.y + r ), color, 1, line_type, shift ); - cvLine( image, cvPoint( pt.x - r, pt.y + r), - cvPoint( pt.x + r, pt.y - r), color, 1, line_type, shift ); - cvCircle( image, pt, r+(1< tmpcorners(count+1); - Mat image = _image.getMat(); CvMat c_image = image; - bool ok = cvFindChessboardCorners(&c_image, patternSize, - (CvPoint2D32f*)&tmpcorners[0], &count, flags ) > 0; - if( count > 0 ) - { - tmpcorners.resize(count); - Mat(tmpcorners).copyTo(corners); - } - else - corners.release(); - return ok; + return 0; } -namespace -{ -int quiet_error(int /*status*/, const char* /*func_name*/, - const char* /*err_msg*/, const char* /*file_name*/, - int /*line*/, void* /*userdata*/ ) -{ - return 0; -} -} - -void cv::drawChessboardCorners( InputOutputArray _image, Size patternSize, - InputArray _corners, - bool patternWasFound ) -{ - CV_INSTRUMENT_REGION() - - Mat corners = _corners.getMat(); - if( corners.empty() ) - return; - Mat image = _image.getMat(); CvMat c_image = image; - int nelems = corners.checkVector(2, CV_32F, true); - CV_Assert(nelems >= 0); - cvDrawChessboardCorners( &c_image, patternSize, corners.ptr(), - nelems, patternWasFound ); -} - -bool cv::findCirclesGrid( InputArray image, Size patternSize, - OutputArray centers, int flags, - const Ptr &blobDetector, - CirclesGridFinderParameters parameters) +bool findCirclesGrid(InputArray image, Size patternSize, + OutputArray centers, int flags, + const Ptr &blobDetector, + CirclesGridFinderParameters parameters) { CirclesGridFinderParameters2 parameters2; *((CirclesGridFinderParameters*)¶meters2) = parameters; return cv::findCirclesGrid2(image, patternSize, centers, flags, blobDetector, parameters2); } -bool cv::findCirclesGrid2( InputArray _image, Size patternSize, - OutputArray _centers, int flags, const Ptr &blobDetector, - CirclesGridFinderParameters2 parameters) +bool findCirclesGrid2(InputArray _image, Size patternSize, + OutputArray _centers, int flags, const Ptr &blobDetector, + CirclesGridFinderParameters2 parameters) { CV_INSTRUMENT_REGION() @@ -2332,7 +2237,7 @@ bool cv::findCirclesGrid2( InputArray _image, Size patternSize, #define BE_QUIET 1 #if BE_QUIET void* oldCbkData; - ErrorCallback oldCbk = redirectError(quiet_error, 0, &oldCbkData); + ErrorCallback oldCbk = redirectError(quiet_error, 0, &oldCbkData); // FIXIT not thread safe #endif CV_TRY { @@ -2356,7 +2261,7 @@ bool cv::findCirclesGrid2( InputArray _image, Size patternSize, boxFinder.getAsymmetricHoles(centers); break; default: - CV_Error(CV_StsBadArg, "Unknown pattern type"); + CV_Error(Error::StsBadArg, "Unknown pattern type"); } if (i != 0) @@ -2381,10 +2286,11 @@ bool cv::findCirclesGrid2( InputArray _image, Size patternSize, return false; } -bool cv::findCirclesGrid( InputArray _image, Size patternSize, - OutputArray _centers, int flags, const Ptr &blobDetector) +bool findCirclesGrid(InputArray _image, Size patternSize, + OutputArray _centers, int flags, const Ptr &blobDetector) { return cv::findCirclesGrid2(_image, patternSize, _centers, flags, blobDetector, CirclesGridFinderParameters2()); } +} // namespace /* End of file. */ diff --git a/modules/calib3d/src/precomp.hpp b/modules/calib3d/src/precomp.hpp index 753c46ae54..329692eb01 100644 --- a/modules/calib3d/src/precomp.hpp +++ b/modules/calib3d/src/precomp.hpp @@ -42,13 +42,15 @@ #ifndef __OPENCV_PRECOMP_H__ #define __OPENCV_PRECOMP_H__ -#include "opencv2/calib3d.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/features2d.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/core/private.hpp" +#include "opencv2/calib3d.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/features2d.hpp" + + #include "opencv2/core/ocl.hpp" #ifdef HAVE_TEGRA_OPTIMIZATION diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index 3534c324fe..d8f6cd2e03 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -1618,7 +1618,8 @@ void CV_StereoCalibrationTest::run( int ) bool found2 = findChessboardCorners(right, patternSize, imgpt2[i]); if(!found1 || !found2) { - ts->printf( cvtest::TS::LOG, "The function could not detect boards on the images %s and %s, testcase %d\n", + ts->printf( cvtest::TS::LOG, "The function could not detect boards (%d x %d) on the images %s and %s, testcase %d\n", + patternSize.width, patternSize.height, imglist[i*2].c_str(), imglist[i*2+1].c_str(), testcase ); ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); return; diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index 65f354e070..81b24f0cc7 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -409,6 +409,11 @@ IplConvKernelFP; #define CV_MAT_MAGIC_VAL 0x42420000 #define CV_TYPE_NAME_MAT "opencv-matrix" +#ifdef __cplusplus +typedef struct CvMat CvMat; +CV_INLINE CvMat cvMat(const cv::Mat& m); +#endif + /** Matrix elements are stored row by row. Element (i, j) (i - 0-based row index, j - 0-based column index) of a matrix can be retrieved or modified using CV_MAT_ELEM macro: @@ -531,6 +536,16 @@ inline CvMat::CvMat(const cv::Mat& m) step = (int)m.step[0]; type = (type & ~cv::Mat::CONTINUOUS_FLAG) | (m.flags & cv::Mat::CONTINUOUS_FLAG); } + +inline CvMat cvMat(const cv::Mat& m) +{ + CvMat self; + CV_DbgAssert(m.dims <= 2); + self = cvMat(m.rows, m.dims == 1 ? 1 : m.cols, m.type(), m.data); + self.step = (int)m.step[0]; + self.type = (self.type & ~cv::Mat::CONTINUOUS_FLAG) | (m.flags & cv::Mat::CONTINUOUS_FLAG); + return self; +} #endif @@ -916,6 +931,15 @@ CV_INLINE CvPoint2D32f cvPoint2D32f( double x, double y ) return p; } +#ifdef __cplusplus +template +CvPoint2D32f cvPoint2D32f(const cv::Point_<_Tp>& pt) +{ + CvPoint2D32f p((float)pt.x, (float)pt.y); + return p; +} +#endif + /** converts CvPoint to CvPoint2D32f. */ CV_INLINE CvPoint2D32f cvPointTo32f( CvPoint point ) { diff --git a/modules/ts/src/ts.cpp b/modules/ts/src/ts.cpp index ee823a54a9..06f9118a28 100644 --- a/modules/ts/src/ts.cpp +++ b/modules/ts/src/ts.cpp @@ -255,8 +255,9 @@ void BaseTest::safe_run( int start_from ) const char* errorStr = cvErrorStr(exc.code); char buf[1 << 16]; - sprintf( buf, "OpenCV Error:\n\t%s (%s) in %s, file %s, line %d", - errorStr, exc.err.c_str(), exc.func.size() > 0 ? + const char* delim = exc.err.find('\n') == cv::String::npos ? "" : "\n"; + sprintf( buf, "OpenCV Error:\n\t%s (%s%s) in %s, file %s, line %d", + errorStr, delim, exc.err.c_str(), exc.func.size() > 0 ? exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line ); ts->printf(TS::LOG, "%s\n", buf); @@ -384,7 +385,9 @@ int BadArgTest::run_test_case( int expected_code, const string& _descr ) catch(const cv::Exception& e) { thrown = true; - if( e.code != expected_code ) + if (e.code != expected_code && + e.code != cv::Error::StsError && e.code != cv::Error::StsAssert // Exact error codes support will be dropped. Checks should provide proper text messages intead. + ) { ts->printf(TS::LOG, "%s (test case #%d): the error code %d is different from the expected %d\n", descr, test_case_idx, e.code, expected_code); @@ -471,7 +474,8 @@ string TS::str_from_code( const TS::FailureCode code ) static int tsErrorCallback( int status, const char* func_name, const char* err_msg, const char* file_name, int line, TS* ts ) { - ts->printf(TS::LOG, "OpenCV Error:\n\t%s (%s) in %s, file %s, line %d\n", cvErrorStr(status), err_msg, func_name[0] != 0 ? func_name : "unknown function", file_name, line); + const char* delim = std::string(err_msg).find('\n') == std::string::npos ? "" : "\n"; + ts->printf(TS::LOG, "OpenCV Error:\n\t%s (%s%s) in %s, file %s, line %d\n", cvErrorStr(status), delim, err_msg, func_name[0] != 0 ? func_name : "unknown function", file_name, line); return 0; } From 4bc080dc50ae8c58deff35b3db7650eff532d078 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 5 Jul 2018 13:54:42 +0300 Subject: [PATCH 15/26] fix function signatures, drop invalid casts --- modules/highgui/src/window_gtk.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 9d107fbd4f..ea3f4541ca 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -447,8 +447,9 @@ cvImageWidget_destroy (GtkObject *object) #endif //GTK_VERSION3 } -static void cvImageWidget_class_init (CvImageWidgetClass * klass) +static void cvImageWidget_class_init (gpointer g_class, gpointer /*class_data*/) { + CvImageWidgetClass* klass = (CvImageWidgetClass*)g_class; #if defined (GTK_VERSION3) GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); #else @@ -478,8 +479,9 @@ static void cvImageWidget_class_init (CvImageWidgetClass * klass) } static void -cvImageWidget_init (CvImageWidget *image_widget) +cvImageWidget_init(GTypeInstance* instance, gpointer /*g_class*/) { + CvImageWidget* image_widget = (CvImageWidget*)instance; image_widget->original_image=0; image_widget->scaled_image=0; image_widget->flags=0; @@ -494,9 +496,9 @@ GType cvImageWidget_get_type (void){ GTK_TYPE_WIDGET, (gchar*) "CvImageWidget", sizeof(CvImageWidgetClass), - (GClassInitFunc) cvImageWidget_class_init, + cvImageWidget_class_init, sizeof(CvImageWidget), - (GInstanceInitFunc) cvImageWidget_init, + cvImageWidget_init, (GTypeFlags)0 ); } @@ -590,7 +592,7 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da #ifdef HAVE_GTHREAD int thread_started=0; -static gpointer icvWindowThreadLoop(); +static gpointer icvWindowThreadLoop(gpointer data); GMutex* last_key_mutex = NULL; GCond* cond_have_key = NULL; GMutex* window_mutex = NULL; @@ -640,10 +642,10 @@ CV_IMPL int cvStartWindowThread(){ #if !GLIB_CHECK_VERSION(2, 32, 0) // this is the window update thread - window_thread = g_thread_create((GThreadFunc) icvWindowThreadLoop, + window_thread = g_thread_create(icvWindowThreadLoop, NULL, TRUE, NULL); #else - window_thread = g_thread_new("OpenCV window update", (GThreadFunc)icvWindowThreadLoop, NULL); + window_thread = g_thread_new("OpenCV window update", icvWindowThreadLoop, NULL); #endif } thread_started = window_thread!=NULL; @@ -654,7 +656,7 @@ CV_IMPL int cvStartWindowThread(){ } #ifdef HAVE_GTHREAD -gpointer icvWindowThreadLoop() +gpointer icvWindowThreadLoop(gpointer /*data*/) { while(1){ g_mutex_lock(window_mutex); From 019c2f21151e2d1cfb050ab10501d339d8d52331 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Wed, 27 Jun 2018 16:34:36 +0300 Subject: [PATCH 16/26] Enable more deep learning tests --- modules/dnn/src/dnn.cpp | 4 +- modules/dnn/src/layers/convolution_layer.cpp | 16 +- modules/dnn/src/layers/eltwise_layer.cpp | 4 +- modules/dnn/src/layers/reorg_layer.cpp | 21 +- modules/dnn/src/layers/resize_layer.cpp | 21 ++ modules/dnn/src/layers/slice_layer.cpp | 16 +- modules/dnn/test/test_backends.cpp | 41 +-- modules/dnn/test/test_darknet_importer.cpp | 202 ++++++------ modules/dnn/test/test_halide_layers.cpp | 328 ++++++++++++------- modules/dnn/test/test_layers.cpp | 244 +++++++------- modules/dnn/test/test_precomp.hpp | 87 +++++ modules/dnn/test/test_tf_importer.cpp | 294 +++++++++-------- modules/dnn/test/test_torch_importer.cpp | 1 - 13 files changed, 761 insertions(+), 518 deletions(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 0177b31a47..469951cccf 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -2729,9 +2729,9 @@ void Layer::applyHalideScheduler(Ptr& node, const std::vector } else if (targetId == DNN_TARGET_OPENCL) { - int c_split = outC > 8 ? (outC > 16 ? 8 : 4) : outC; if (outW == 1 && outH == 1) { + int c_split = outC > 8 ? (outC > 16 ? 8 : 4) : outC; top.split(c, co, ci, c_split) .fuse(x, y, tile).fuse(co, tile, tile).fuse(n, tile, tile) .gpu_blocks(tile) @@ -2741,6 +2741,8 @@ void Layer::applyHalideScheduler(Ptr& node, const std::vector { int x_split = outW > 8 ? (outW >= 32 ? 16 : 8) : outW; int y_split = outH > 8 ? (outH >= 32 ? 16 : 8) : outH; + // Supported vectorization widths: 2, 3, 4, 8, 16 + int c_split = outC > 8 ? (outC > 16 ? 8 : 4) : std::min(4, outC); top.split(x, xo, xi, x_split).split(y, yo, yi, y_split) .split(c, co, ci, c_split) .gpu_blocks(xo, yo, co) diff --git a/modules/dnn/src/layers/convolution_layer.cpp b/modules/dnn/src/layers/convolution_layer.cpp index 27818e5e7c..61489e741e 100644 --- a/modules/dnn/src/layers/convolution_layer.cpp +++ b/modules/dnn/src/layers/convolution_layer.cpp @@ -82,7 +82,21 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { if (backendId == DNN_BACKEND_INFERENCE_ENGINE) - return preferableTarget != DNN_TARGET_MYRIAD || type != "Deconvolution" || adjustPad == Size(); + { + if (type == "Convolution") + return preferableTarget != DNN_TARGET_MYRIAD || dilation.width == dilation.height; + else + { + CV_Assert(type == "Deconvolution"); + const int outGroupCn = blobs[0].size[1]; // Weights are in IOHW layout + const int group = numOutput / outGroupCn; + if (group != 1) + return false; + if (preferableTarget == DNN_TARGET_OPENCL || preferableTarget == DNN_TARGET_OPENCL_FP16) + return dilation.width == 1 && dilation.height == 1; + return true; + } + } else return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE; } diff --git a/modules/dnn/src/layers/eltwise_layer.cpp b/modules/dnn/src/layers/eltwise_layer.cpp index 07a7f60228..8eb3ff4a68 100644 --- a/modules/dnn/src/layers/eltwise_layer.cpp +++ b/modules/dnn/src/layers/eltwise_layer.cpp @@ -97,8 +97,8 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || - backendId == DNN_BACKEND_HALIDE && haveHalide() || - backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine(); + backendId == DNN_BACKEND_HALIDE || + backendId == DNN_BACKEND_INFERENCE_ENGINE && (op != SUM || coeffs.empty()); } bool getMemoryShapes(const std::vector &inputs, diff --git a/modules/dnn/src/layers/reorg_layer.cpp b/modules/dnn/src/layers/reorg_layer.cpp index 102f29874a..89b6f1d85b 100644 --- a/modules/dnn/src/layers/reorg_layer.cpp +++ b/modules/dnn/src/layers/reorg_layer.cpp @@ -41,9 +41,9 @@ //M*/ #include "../precomp.hpp" +#include "../op_inf_engine.hpp" #include #include -#include #ifdef HAVE_OPENCL #include "opencl_kernels_dnn.hpp" @@ -85,6 +85,11 @@ public: return false; } + virtual bool supportBackend(int backendId) CV_OVERRIDE + { + return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_INFERENCE_ENGINE; + } + #ifdef HAVE_OPENCL bool forward_ocl(InputArrayOfArrays inps, OutputArrayOfArrays outs, OutputArrayOfArrays internals) { @@ -169,6 +174,20 @@ public: } } + virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE + { +#ifdef HAVE_INF_ENGINE + InferenceEngine::LayerParams lp; + lp.name = name; + lp.type = "ReorgYolo"; + lp.precision = InferenceEngine::Precision::FP32; + std::shared_ptr ieLayer(new InferenceEngine::CNNLayer(lp)); + ieLayer->params["stride"] = format("%d", reorgStride); + return Ptr(new InfEngineBackendNode(ieLayer)); +#endif // HAVE_INF_ENGINE + return Ptr(); + } + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/resize_layer.cpp b/modules/dnn/src/layers/resize_layer.cpp index 358ee8dd99..4bf7b506a5 100644 --- a/modules/dnn/src/layers/resize_layer.cpp +++ b/modules/dnn/src/layers/resize_layer.cpp @@ -192,6 +192,11 @@ public: return (outputs[0][2] == inputs[0][2]) && (outputs[0][3] == inputs[0][3]); } + virtual bool supportBackend(int backendId) CV_OVERRIDE + { + return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_INFERENCE_ENGINE; + } + virtual void finalize(const std::vector& inputs, std::vector &outputs) CV_OVERRIDE { if (!outWidth && !outHeight) @@ -204,6 +209,22 @@ public: scaleHeight = (outHeight > 1) ? (static_cast(inpHeight - 1) / (outHeight - 1)) : 0.f; scaleWidth = (outWidth > 1) ? (static_cast(inpWidth - 1) / (outWidth - 1)) : 0.f; } + + virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE + { +#ifdef HAVE_INF_ENGINE + InferenceEngine::LayerParams lp; + lp.name = name; + lp.type = "Interp"; + lp.precision = InferenceEngine::Precision::FP32; + + std::shared_ptr ieLayer(new InferenceEngine::CNNLayer(lp)); + ieLayer->params["pad_beg"] = "0"; + ieLayer->params["pad_end"] = "0"; + return Ptr(new InfEngineBackendNode(ieLayer)); +#endif // HAVE_INF_ENGINE + return Ptr(); + } }; Ptr InterpLayer::create(const LayerParams& params) diff --git a/modules/dnn/src/layers/slice_layer.cpp b/modules/dnn/src/layers/slice_layer.cpp index f6f4109c61..e4c723e3bf 100644 --- a/modules/dnn/src/layers/slice_layer.cpp +++ b/modules/dnn/src/layers/slice_layer.cpp @@ -266,7 +266,21 @@ public: std::shared_ptr ieLayer(new InferenceEngine::CropLayer(lp)); CV_Assert(sliceRanges.size() == 1); - for (int i = sliceRanges[0].size() - 1; i >= 0; --i) + + int from, to, step; + if (preferableTarget == DNN_TARGET_MYRIAD) + { + from = 1; + to = sliceRanges[0].size() + 1; + step = 1; + } + else + { + from = sliceRanges[0].size() - 1; + to = -1; + step = -1; + } + for (int i = from; i != to; i += step) { ieLayer->axis.push_back(i); ieLayer->offset.push_back(sliceRanges[0][i].start); diff --git a/modules/dnn/test/test_backends.cpp b/modules/dnn/test/test_backends.cpp index 48fe765224..ad7eb0917e 100644 --- a/modules/dnn/test/test_backends.cpp +++ b/modules/dnn/test/test_backends.cpp @@ -10,18 +10,9 @@ namespace opencv_test { namespace { -class DNNTestNetwork : public TestWithParam > +class DNNTestNetwork : public DNNTestLayer { public: - dnn::Backend backend; - dnn::Target target; - - DNNTestNetwork() - { - backend = (dnn::Backend)(int)get<0>(GetParam()); - target = (dnn::Target)(int)get<1>(GetParam()); - } - void processNet(const std::string& weights, const std::string& proto, Size inpSize, const std::string& outputLayer = "", const std::string& halideScheduler = "", @@ -40,32 +31,10 @@ public: std::string halideScheduler = "", double l1 = 0.0, double lInf = 0.0, double detectionConfThresh = 0.2) { - if (backend == DNN_BACKEND_OPENCV && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) - { -#ifdef HAVE_OPENCL - if (!cv::ocl::useOpenCL()) -#endif - { - throw SkipTestException("OpenCL is not available/disabled in OpenCV"); - } - } - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - { - if (!checkMyriadTarget()) - { - throw SkipTestException("Myriad is not available/disabled in OpenCV"); - } - } - if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) - { - l1 = l1 == 0.0 ? 4e-3 : l1; - lInf = lInf == 0.0 ? 2e-2 : lInf; - } - else - { - l1 = l1 == 0.0 ? 1e-5 : l1; - lInf = lInf == 0.0 ? 1e-4 : lInf; - } + checkBackend(); + l1 = l1 ? l1 : default_l1; + lInf = lInf ? lInf : default_lInf; + weights = findDataFile(weights, false); if (!proto.empty()) proto = findDataFile(proto, false); diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index 2232aa4ff3..682213b791 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -65,76 +65,84 @@ TEST(Test_Darknet, read_yolo_voc) ASSERT_FALSE(net.empty()); } -// Test object detection network from Darknet framework. -static void testDarknetModel(const std::string& cfg, const std::string& weights, - const std::vector& outNames, - const std::vector& refClassIds, - const std::vector& refConfidences, - const std::vector& refBoxes, - int backendId, int targetId, float scoreDiff = 0.0, - float iouDiff = 0.0, float confThreshold = 0.24) +class Test_Darknet_layers : public DNNTestLayer { - if (backendId == DNN_BACKEND_OPENCV && targetId == DNN_TARGET_OPENCL) +public: + void testDarknetLayer(const std::string& name, bool hasWeights = false) { - #ifdef HAVE_OPENCL - if (!cv::ocl::useOpenCL()) - #endif - { - throw SkipTestException("OpenCL is not available/disabled in OpenCV"); - } + std::string cfg = findDataFile("dnn/darknet/" + name + ".cfg", false); + std::string model = ""; + if (hasWeights) + model = findDataFile("dnn/darknet/" + name + ".weights", false); + Mat inp = blobFromNPY(findDataFile("dnn/darknet/" + name + "_in.npy", false)); + Mat ref = blobFromNPY(findDataFile("dnn/darknet/" + name + "_out.npy", false)); + + checkBackend(&inp, &ref); + + Net net = readNet(cfg, model); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); + net.setInput(inp); + Mat out = net.forward(); + normAssert(out, ref, "", default_l1, default_lInf); } - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD) +}; + +class Test_Darknet_nets : public DNNTestLayer +{ +public: + // Test object detection network from Darknet framework. + void testDarknetModel(const std::string& cfg, const std::string& weights, + const std::vector& outNames, + const std::vector& refClassIds, + const std::vector& refConfidences, + const std::vector& refBoxes, + double scoreDiff, double iouDiff, float confThreshold = 0.24) { - if (!checkMyriadTarget()) + checkBackend(); + + Mat sample = imread(_tf("dog416.png")); + Mat inp = blobFromImage(sample, 1.0/255, Size(416, 416), Scalar(), true, false); + + Net net = readNet(findDataFile("dnn/" + cfg, false), + findDataFile("dnn/" + weights, false)); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); + net.setInput(inp); + std::vector outs; + net.forward(outs, outNames); + + std::vector classIds; + std::vector confidences; + std::vector boxes; + for (int i = 0; i < outs.size(); ++i) { - throw SkipTestException("Myriad is not available/disabled in OpenCV"); + Mat& out = outs[i]; + for (int j = 0; j < out.rows; ++j) + { + Mat scores = out.row(j).colRange(5, out.cols); + double confidence; + Point maxLoc; + minMaxLoc(scores, 0, &confidence, 0, &maxLoc); + + float* detection = out.ptr(j); + double centerX = detection[0]; + double centerY = detection[1]; + double width = detection[2]; + double height = detection[3]; + boxes.push_back(Rect2d(centerX - 0.5 * width, centerY - 0.5 * height, + width, height)); + confidences.push_back(confidence); + classIds.push_back(maxLoc.x); + } } + normAssertDetections(refClassIds, refConfidences, refBoxes, classIds, + confidences, boxes, "", confThreshold, scoreDiff, iouDiff); } - Mat sample = imread(_tf("dog416.png")); - Mat inp = blobFromImage(sample, 1.0/255, Size(416, 416), Scalar(), true, false); - - Net net = readNet(findDataFile("dnn/" + cfg, false), - findDataFile("dnn/" + weights, false)); - net.setPreferableBackend(backendId); - net.setPreferableTarget(targetId); - net.setInput(inp); - std::vector outs; - net.forward(outs, outNames); - - std::vector classIds; - std::vector confidences; - std::vector boxes; - for (int i = 0; i < outs.size(); ++i) - { - Mat& out = outs[i]; - for (int j = 0; j < out.rows; ++j) - { - Mat scores = out.row(j).colRange(5, out.cols); - double confidence; - Point maxLoc; - minMaxLoc(scores, 0, &confidence, 0, &maxLoc); - - float* detection = out.ptr(j); - double centerX = detection[0]; - double centerY = detection[1]; - double width = detection[2]; - double height = detection[3]; - boxes.push_back(Rect2d(centerX - 0.5 * width, centerY - 0.5 * height, - width, height)); - confidences.push_back(confidence); - classIds.push_back(maxLoc.x); - } - } - normAssertDetections(refClassIds, refConfidences, refBoxes, classIds, - confidences, boxes, "", confThreshold, scoreDiff, iouDiff); -} - -typedef testing::TestWithParam > Test_Darknet_nets; +}; TEST_P(Test_Darknet_nets, YoloVoc) { - int backendId = get<0>(GetParam()); - int targetId = get<1>(GetParam()); std::vector outNames(1, "detection_out"); std::vector classIds(3); @@ -143,34 +151,28 @@ TEST_P(Test_Darknet_nets, YoloVoc) classIds[0] = 6; confidences[0] = 0.750469f; boxes[0] = Rect2d(0.577374, 0.127391, 0.325575, 0.173418); // a car classIds[1] = 1; confidences[1] = 0.780879f; boxes[1] = Rect2d(0.270762, 0.264102, 0.461713, 0.48131); // a bicycle classIds[2] = 11; confidences[2] = 0.901615f; boxes[2] = Rect2d(0.1386, 0.338509, 0.282737, 0.60028); // a dog - double scoreDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 1e-2 : 8e-5; - double iouDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 0.013 : 3e-5; + double scoreDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-2 : 8e-5; + double iouDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.013 : 3e-5; testDarknetModel("yolo-voc.cfg", "yolo-voc.weights", outNames, - classIds, confidences, boxes, backendId, targetId, scoreDiff, iouDiff); + classIds, confidences, boxes, scoreDiff, iouDiff); } TEST_P(Test_Darknet_nets, TinyYoloVoc) { - int backendId = get<0>(GetParam()); - int targetId = get<1>(GetParam()); std::vector outNames(1, "detection_out"); std::vector classIds(2); std::vector confidences(2); std::vector boxes(2); classIds[0] = 6; confidences[0] = 0.761967f; boxes[0] = Rect2d(0.579042, 0.159161, 0.31544, 0.160779); // a car classIds[1] = 11; confidences[1] = 0.780595f; boxes[1] = Rect2d(0.129696, 0.386467, 0.315579, 0.534527); // a dog - double scoreDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 8e-3 : 8e-5; - double iouDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 8e-3 : 3e-5; + double scoreDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 8e-3 : 8e-5; + double iouDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 8e-3 : 3e-5; testDarknetModel("tiny-yolo-voc.cfg", "tiny-yolo-voc.weights", outNames, - classIds, confidences, boxes, backendId, targetId, scoreDiff, iouDiff); + classIds, confidences, boxes, scoreDiff, iouDiff); } TEST_P(Test_Darknet_nets, YOLOv3) { - int backendId = get<0>(GetParam()); - int targetId = get<1>(GetParam()); - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD) - throw SkipTestException(""); std::vector outNames(3); outNames[0] = "yolo_82"; outNames[1] = "yolo_94"; @@ -182,55 +184,41 @@ TEST_P(Test_Darknet_nets, YOLOv3) classIds[0] = 7; confidences[0] = 0.952983f; boxes[0] = Rect2d(0.614622, 0.150257, 0.286747, 0.138994); // a truck classIds[1] = 1; confidences[1] = 0.987908f; boxes[1] = Rect2d(0.150913, 0.221933, 0.591342, 0.524327); // a bicycle classIds[2] = 16; confidences[2] = 0.998836f; boxes[2] = Rect2d(0.160024, 0.389964, 0.257861, 0.553752); // a dog (COCO) - double scoreDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 4e-3 : 8e-5; - double iouDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 0.011 : 3e-5; + double scoreDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 4e-3 : 8e-5; + double iouDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.011 : 3e-5; testDarknetModel("yolov3.cfg", "yolov3.weights", outNames, - classIds, confidences, boxes, backendId, targetId, scoreDiff, iouDiff); + classIds, confidences, boxes, scoreDiff, iouDiff); } -const tuple testCases[] = { -#ifdef HAVE_INF_ENGINE - tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU), - tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL), - tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16), - tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD), -#endif - tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU), - tuple(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL), - tuple(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL_FP16) -}; +INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_nets, dnnBackendsAndTargets()); -INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_nets, testing::ValuesIn(testCases)); - -static void testDarknetLayer(const std::string& name, bool hasWeights = false) -{ - std::string cfg = findDataFile("dnn/darknet/" + name + ".cfg", false); - std::string model = ""; - if (hasWeights) - model = findDataFile("dnn/darknet/" + name + ".weights", false); - Mat inp = blobFromNPY(findDataFile("dnn/darknet/" + name + "_in.npy", false)); - Mat ref = blobFromNPY(findDataFile("dnn/darknet/" + name + "_out.npy", false)); - - Net net = readNet(cfg, model); - net.setPreferableBackend(DNN_BACKEND_OPENCV); - net.setInput(inp); - Mat out = net.forward(); - normAssert(out, ref); -} - -TEST(Test_Darknet, shortcut) +TEST_P(Test_Darknet_layers, shortcut) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_CPU) + throw SkipTestException(""); testDarknetLayer("shortcut"); } -TEST(Test_Darknet, upsample) +TEST_P(Test_Darknet_layers, upsample) { testDarknetLayer("upsample"); } -TEST(Test_Darknet, avgpool_softmax) +TEST_P(Test_Darknet_layers, avgpool_softmax) { testDarknetLayer("avgpool_softmax"); } +TEST_P(Test_Darknet_layers, region) +{ + testDarknetLayer("region"); +} + +TEST_P(Test_Darknet_layers, reorg) +{ + testDarknetLayer("reorg"); +} + +INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_layers, dnnBackendsAndTargets()); + }} // namespace diff --git a/modules/dnn/test/test_halide_layers.cpp b/modules/dnn/test/test_halide_layers.cpp index 2d137c5eda..b21ae85800 100644 --- a/modules/dnn/test/test_halide_layers.cpp +++ b/modules/dnn/test/test_halide_layers.cpp @@ -12,32 +12,60 @@ namespace opencv_test { namespace { -#ifdef HAVE_HALIDE using namespace cv; using namespace cv::dnn; using namespace testing; -static void test(LayerParams& params, Mat& input) +static void test(Mat& input, Net& net, int backendId, int targetId) { + DNNTestLayer::checkBackend(backendId, targetId); randu(input, -1.0f, 1.0f); - Net net; - int lid = net.addLayer(params.name, params.type, params); - net.connect(0, 0, lid, 0); - net.setInput(input); net.setPreferableBackend(DNN_BACKEND_OPENCV); - Mat outputDefault = net.forward(params.name).clone(); + Mat outputDefault = net.forward().clone(); - net.setPreferableBackend(DNN_BACKEND_HALIDE); - Mat outputHalide = net.forward(params.name).clone(); - normAssert(outputDefault, outputHalide); + net.setPreferableBackend(backendId); + net.setPreferableTarget(targetId); + Mat outputHalide = net.forward().clone(); + + double l1, lInf; + DNNTestLayer::getDefaultThresholds(backendId, targetId, &l1, &lInf); + normAssert(outputDefault, outputHalide, "", l1, lInf); } +static void test(LayerParams& params, Mat& input, int backendId, int targetId) +{ + Net net; + net.addLayerToPrev(params.name, params.type, params); + test(input, net, backendId, targetId); +} + +static testing::internal::ParamGenerator > dnnBackendsAndTargetsWithHalide() +{ + static const tuple testCases[] = { +#ifdef HAVE_HALIDE + tuple(DNN_BACKEND_HALIDE, DNN_TARGET_CPU), + tuple(DNN_BACKEND_HALIDE, DNN_TARGET_OPENCL), +#endif +#ifdef HAVE_INF_ENGINE + tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU), + tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL), + tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16), + tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD), +#endif + tuple(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL), + tuple(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL_FP16) + }; + return testing::ValuesIn(testCases); +} + +class Test_Halide_layers : public DNNTestLayer {}; + //////////////////////////////////////////////////////////////////////////////// // Padding //////////////////////////////////////////////////////////////////////////////// -TEST(Padding_Halide, Accuracy) +TEST_P(Test_Halide_layers, Padding) { static const int kNumRuns = 10; std::vector paddings(8); @@ -52,15 +80,16 @@ TEST(Padding_Halide, Accuracy) lp.type = "Padding"; lp.name = "testLayer"; - Mat input({1 + rng(10), 1 + rng(10), 1 + rng(10), 1 + rng(10)}, CV_32F); - test(lp, input); + int sz[] = {1 + (int)rng(10), 1 + (int)rng(10), 1 + (int)rng(10), 1 + (int)rng(10)}; + Mat input(4, &sz[0], CV_32F); + test(lp, input, backend, target); } } //////////////////////////////////////////////////////////////////////////////// // Convolution //////////////////////////////////////////////////////////////////////////////// -typedef TestWithParam > Convolution; +typedef TestWithParam > > Convolution; TEST_P(Convolution, Accuracy) { int inChannels = get<0>(GetParam())[0]; @@ -72,8 +101,15 @@ TEST_P(Convolution, Accuracy) Size pad = get<4>(GetParam()); Size dilation = get<5>(GetParam()); bool hasBias = get<6>(GetParam()); + int backendId = get<0>(get<7>(GetParam())); + int targetId = get<1>(get<7>(GetParam())); - Mat weights({outChannels, inChannels / group, kernel.height, kernel.width}, CV_32F); + if ((backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD) || + (backendId == DNN_BACKEND_OPENCV && targetId == DNN_TARGET_OPENCL_FP16)) + throw SkipTestException(""); + + int sz[] = {outChannels, inChannels / group, kernel.height, kernel.width}; + Mat weights(4, &sz[0], CV_32F); randu(weights, -1.0f, 1.0f); LayerParams lp; @@ -93,12 +129,13 @@ TEST_P(Convolution, Accuracy) lp.blobs.push_back(weights); if (hasBias) { - Mat bias({outChannels}, CV_32F); + Mat bias(1, outChannels, CV_32F); randu(bias, -1.0f, 1.0f); lp.blobs.push_back(bias); } - Mat input({1, inChannels, inSize.height, inSize.width}, CV_32F); - test(lp, input); + int inpSz[] = {1, inChannels, inSize.height, inSize.width}; + Mat input(4, &inpSz[0], CV_32F); + test(lp, input, backendId, targetId); } INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Convolution, Combine( @@ -110,13 +147,14 @@ INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Convolution, Combine( /*stride*/ Values(Size(1, 1), Size(2, 2)), /*pad*/ Values(Size(1, 0), Size(0, 1)), /*dilation*/ Values(Size(1, 1), Size(2, 2)), -/*has bias*/ Bool() +/*has bias*/ Bool(), + dnnBackendsAndTargetsWithHalide() )); //////////////////////////////////////////////////////////////////////////////// // Deconvolution //////////////////////////////////////////////////////////////////////////////// -typedef TestWithParam > Deconvolution; +typedef TestWithParam > > Deconvolution; TEST_P(Deconvolution, Accuracy) { int inChannels = get<0>(GetParam())[0]; @@ -129,8 +167,14 @@ TEST_P(Deconvolution, Accuracy) Size stride = Size(get<5>(GetParam())[0], get<5>(GetParam())[1]); Size adjPad = Size(get<5>(GetParam())[2], get<5>(GetParam())[3]); bool hasBias = get<6>(GetParam()); + int backendId = get<0>(get<7>(GetParam())); + int targetId = get<1>(get<7>(GetParam())); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_CPU && + dilation.width == 2 && dilation.height == 2) + throw SkipTestException(""); - Mat weights({inChannels, outChannels / group, kernel.height, kernel.width}, CV_32F); + int sz[] = {inChannels, outChannels / group, kernel.height, kernel.width}; + Mat weights(4, &sz[0], CV_32F); randu(weights, -1.0f, 1.0f); LayerParams lp; @@ -152,12 +196,13 @@ TEST_P(Deconvolution, Accuracy) lp.blobs.push_back(weights); if (hasBias) { - Mat bias({outChannels}, CV_32F); + Mat bias(1, outChannels, CV_32F); randu(bias, -1.0f, 1.0f); lp.blobs.push_back(bias); } - Mat input({1, inChannels, inSize.height, inSize.width}, CV_32F); - test(lp, input); + int inpSz[] = {1, inChannels, inSize.height, inSize.width}; + Mat input(4, &inpSz[0], CV_32F); + test(lp, input, backendId, targetId); } INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Deconvolution, Combine( @@ -168,13 +213,14 @@ INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Deconvolution, Combine( /*pad*/ Values(Size(1, 0), Size(0, 1)), /*dilation*/ Values(Size(1, 1), Size(2, 2)), /*stride, adj. pad*/ Values(Vec4i(1,1, 0,0), Vec4i(2,2, 1,0), Vec4i(1,2, 0,1)), -/*has bias*/ Bool() +/*has bias*/ Bool(), + dnnBackendsAndTargetsWithHalide() )); //////////////////////////////////////////////////////////////////////////////// // LRN //////////////////////////////////////////////////////////////////////////////// -typedef TestWithParam > LRN; +typedef TestWithParam > > LRN; TEST_P(LRN, Accuracy) { int inChannels = get<0>(GetParam())[0]; @@ -185,6 +231,10 @@ TEST_P(LRN, Accuracy) float bias = get<2>(GetParam())[2]; bool normBySize = get<3>(GetParam()); std::string nrmType = get<4>(GetParam()); + int backendId = get<0>(get<5>(GetParam())); + int targetId = get<1>(get<5>(GetParam())); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + throw SkipTestException(""); LayerParams lp; lp.set("norm_region", nrmType); @@ -196,8 +246,9 @@ TEST_P(LRN, Accuracy) lp.type = "LRN"; lp.name = "testLayer"; - Mat input({1, inChannels, inSize.height, inSize.width}, CV_32F); - test(lp, input); + int sz[] = {1, inChannels, inSize.height, inSize.width}; + Mat input(4, &sz[0], CV_32F); + test(lp, input, backendId, targetId); } INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, LRN, Combine( @@ -207,19 +258,24 @@ INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, LRN, Combine( /*alpha, beta,*/ Vec3f(1.0f, 0.9f, 1.1f), Vec3f(1.0f, 1.1f, 0.9f), /*bias */ Vec3f(1.1f, 0.9f, 1.0f), Vec3f(1.1f, 1.0f, 0.9f)), /*norm_by_size*/ Bool(), -/*norm_type*/ Values("ACROSS_CHANNELS", "WITHIN_CHANNEL") +/*norm_type*/ Values("ACROSS_CHANNELS", "WITHIN_CHANNEL"), + dnnBackendsAndTargetsWithHalide() )); //////////////////////////////////////////////////////////////////////////////// // Average pooling //////////////////////////////////////////////////////////////////////////////// -typedef TestWithParam > AvePooling; +typedef TestWithParam > > AvePooling; TEST_P(AvePooling, Accuracy) { int inChannels = get<0>(GetParam()); Size outSize = get<1>(GetParam());; // Input size will be computed from parameters. Size kernel = get<2>(GetParam()); Size stride = get<3>(GetParam()); + int backendId = get<0>(get<4>(GetParam())); + int targetId = get<1>(get<4>(GetParam())); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD) + throw SkipTestException(""); const int inWidth = (outSize.width - 1) * stride.width + kernel.width; const int inHeight = (outSize.height - 1) * stride.height + kernel.height; @@ -233,21 +289,23 @@ TEST_P(AvePooling, Accuracy) lp.type = "Pooling"; lp.name = "testLayer"; - Mat input({1, inChannels, inHeight, inWidth}, CV_32F); - test(lp, input); + int sz[] = {1, inChannels, inHeight, inWidth}; + Mat input(4, &sz[0], CV_32F); + test(lp, input, backendId, targetId); } INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, AvePooling, Combine( /*in channels*/ Values(3, 4), /*out size*/ Values(Size(1, 1), Size(2, 2), Size(3, 2), Size(4, 7)), /*kernel*/ Values(Size(1, 1), Size(2, 2), Size(3, 3), Size(3, 2)), -/*stride*/ Values(Size(1, 1), Size(2, 2), Size(3, 2)) +/*stride*/ Values(Size(1, 1), Size(2, 2), Size(3, 2)), + dnnBackendsAndTargetsWithHalide() )); //////////////////////////////////////////////////////////////////////////////// // Maximum pooling //////////////////////////////////////////////////////////////////////////////// -typedef TestWithParam > MaxPooling; +typedef TestWithParam > > MaxPooling; TEST_P(MaxPooling, Accuracy) { int inChannels = get<0>(GetParam()); @@ -255,6 +313,8 @@ TEST_P(MaxPooling, Accuracy) Size kernel = get<2>(GetParam()); Size stride = get<3>(GetParam()); Size pad = get<4>(GetParam()); + int backendId = get<0>(get<5>(GetParam())); + int targetId = get<1>(get<5>(GetParam())); LayerParams lp; lp.set("pool", "max"); @@ -267,8 +327,9 @@ TEST_P(MaxPooling, Accuracy) lp.type = "Pooling"; lp.name = "testLayer"; - Mat input({1, inChannels, inSize.height, inSize.width}, CV_32F); - test(lp, input); + int sz[] = {1, inChannels, inSize.height, inSize.width}; + Mat input(4, &sz[0], CV_32F); + test(lp, input, backendId, targetId); } INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, MaxPooling, Combine( @@ -276,19 +337,25 @@ INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, MaxPooling, Combine( /*in size*/ Values(Size(5, 5), Size(7, 6)), /*kernel*/ Values(Size(2, 2), Size(3, 3), Size(3, 2)), /*stride*/ Values(Size(1, 1), Size(2, 2), Size(3, 2)), -/*pad*/ Values(Size(0, 0), Size(1, 1), Size(0, 1)) +/*pad*/ Values(Size(0, 0), Size(1, 1), Size(0, 1)), + dnnBackendsAndTargetsWithHalide() )); //////////////////////////////////////////////////////////////////////////////// // Fully-connected //////////////////////////////////////////////////////////////////////////////// -typedef TestWithParam > FullyConnected; +typedef TestWithParam > > FullyConnected; TEST_P(FullyConnected, Accuracy) { int inChannels = get<0>(GetParam()); Size inSize = get<1>(GetParam()); int outChannels = get<2>(GetParam()); bool hasBias = get<3>(GetParam()); + int backendId = get<0>(get<4>(GetParam())); + int targetId = get<1>(get<4>(GetParam())); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE || + (backendId == DNN_BACKEND_OPENCV && targetId == DNN_TARGET_OPENCL_FP16)) + throw SkipTestException(""); Mat weights(outChannels, inChannels * inSize.height * inSize.width, CV_32F); randu(weights, -1.0f, 1.0f); @@ -304,39 +371,50 @@ TEST_P(FullyConnected, Accuracy) lp.type = "InnerProduct"; lp.name = "testLayer"; - Mat input({1, inChannels, inSize.height, inSize.width}, CV_32F); - test(lp, input); + int sz[] = {1, inChannels, inSize.height, inSize.width}; + Mat input(4, &sz[0], CV_32F); + test(lp, input, backendId, targetId); } INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, FullyConnected, Combine( /*in channels*/ Values(3, 4), /*in size*/ Values(Size(5, 4), Size(4, 5), Size(1, 1)), /*out channels*/ Values(3, 4), -/*has bias*/ Bool() +/*has bias*/ Bool(), + dnnBackendsAndTargetsWithHalide() )); //////////////////////////////////////////////////////////////////////////////// // SoftMax //////////////////////////////////////////////////////////////////////////////// -typedef TestWithParam > SoftMax; +typedef TestWithParam > > SoftMax; TEST_P(SoftMax, Accuracy) { int inChannels = get<0>(GetParam()); + int backendId = get<0>(get<1>(GetParam())); + int targetId = get<1>(get<1>(GetParam())); LayerParams lp; lp.type = "SoftMax"; lp.name = "testLayer"; - Mat input({1, inChannels, 1, 1}, CV_32F); - test(lp, input); + int sz[] = {1, inChannels, 1, 1}; + Mat input(4, &sz[0], CV_32F); + test(lp, input, backendId, targetId); } -INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, SoftMax, Values(3, 4, 5, 1024)); +INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, SoftMax, Combine( + Values(3, 4, 5, 1024), + dnnBackendsAndTargetsWithHalide() +)); ////////////////////////////////////////////////////////////////////////////// // Max pooling - unpooling ////////////////////////////////////////////////////////////////////////////// -TEST(MaxPoolUnpool_Halide, Accuracy) +TEST_P(Test_Halide_layers, MaxPoolUnpool) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE) + throw SkipTestException(""); + LayerParams pool; pool.set("pool", "max"); pool.set("kernel_w", 2); @@ -366,16 +444,9 @@ TEST(MaxPoolUnpool_Halide, Accuracy) net.connect(poolId, 0, unpoolId, 0); net.connect(poolId, 1, unpoolId, 1); - Mat input({1, 1, 4, 4}, CV_32F); - randu(input, -1.0f, 1.0f); - net.setInput(input); - net.setPreferableBackend(DNN_BACKEND_OPENCV); - Mat outputDefault = net.forward("testUnpool").clone(); - - net.setPreferableBackend(DNN_BACKEND_HALIDE); - net.setInput(input); - Mat outputHalide = net.forward("testUnpool").clone(); - normAssert(outputDefault, outputHalide); + int sz[] = {1, 1, 4, 4}; + Mat input(4, &sz[0], CV_32F); + test(input, net, backend, target); } //////////////////////////////////////////////////////////////////////////////// @@ -383,7 +454,7 @@ TEST(MaxPoolUnpool_Halide, Accuracy) //////////////////////////////////////////////////////////////////////////////// static const int kNumChannels = 3; -void testInPlaceActivation(LayerParams& lp) +void testInPlaceActivation(LayerParams& lp, int backendId, int targetId) { EXPECT_FALSE(lp.name.empty()); @@ -400,24 +471,19 @@ void testInPlaceActivation(LayerParams& lp) net.connect(0, 0, poolId, 0); net.addLayerToPrev(lp.name, lp.type, lp); - Mat input({1, kNumChannels, 10, 10}, CV_32F); - randu(input, -1.0f, 1.0f); - net.setInput(input); - net.setPreferableBackend(DNN_BACKEND_OPENCV); - Mat outputDefault = net.forward(lp.name).clone(); - - net.setInput(input); - net.setPreferableBackend(DNN_BACKEND_HALIDE); - Mat outputHalide = net.forward(lp.name).clone(); - normAssert(outputDefault, outputHalide); + int sz[] = {1, kNumChannels, 10, 10}; + Mat input(4, &sz[0], CV_32F); + test(input, net, backendId, targetId); } -typedef TestWithParam > BatchNorm; +typedef TestWithParam > > BatchNorm; TEST_P(BatchNorm, Accuracy) { bool hasWeights = get<0>(GetParam()); bool hasBias = get<1>(GetParam()); float epsilon = get<2>(GetParam()); + int backendId = get<0>(get<3>(GetParam())); + int targetId = get<1>(get<3>(GetParam())); LayerParams lp; lp.set("has_weight", hasWeights); @@ -428,56 +494,66 @@ TEST_P(BatchNorm, Accuracy) lp.blobs.reserve(4); for (int i = 0; i < 3; ++i) - lp.blobs.push_back(Mat({kNumChannels}, CV_32F)); + lp.blobs.push_back(Mat(1, kNumChannels, CV_32F)); if (hasBias || hasWeights) - lp.blobs.push_back(Mat({kNumChannels}, CV_32F)); + lp.blobs.push_back(Mat(1, kNumChannels, CV_32F)); - for (Mat& m : lp.blobs) - randu(m, 0.0f, 1.0f); + for (int i = 0; i < lp.blobs.size(); ++i) + randu(lp.blobs[i], 0.0f, 1.0f); - testInPlaceActivation(lp); + testInPlaceActivation(lp, backendId, targetId); } INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, BatchNorm, Combine( /*has weights*/ Bool(), /*has bias*/ Bool(), -/*epsilon*/ Values(1e-3f, 1e-5f) +/*epsilon*/ Values(1e-3f, 1e-5f), + dnnBackendsAndTargetsWithHalide() )); -typedef TestWithParam > ReLU; +typedef TestWithParam > > ReLU; TEST_P(ReLU, Accuracy) { float negativeSlope = get<0>(GetParam()); + int backendId = get<0>(get<1>(GetParam())); + int targetId = get<1>(get<1>(GetParam())); LayerParams lp; lp.set("negative_slope", negativeSlope); lp.type = "ReLU"; lp.name = "testLayer"; - testInPlaceActivation(lp); + testInPlaceActivation(lp, backendId, targetId); } -INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, ReLU, Values( -/*negative slope*/ 2.0f, 0.3f, -0.1f, 0.0f +INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, ReLU, Combine( +/*negative slope*/ Values(2.0f, 0.3f, -0.1f, 0.0f), + dnnBackendsAndTargetsWithHalide() )); -typedef TestWithParam > NoParamActivation; +typedef TestWithParam > > NoParamActivation; TEST_P(NoParamActivation, Accuracy) { + int backendId = get<0>(get<1>(GetParam())); + int targetId = get<1>(get<1>(GetParam())); + LayerParams lp; lp.type = get<0>(GetParam()); lp.name = "testLayer"; - testInPlaceActivation(lp); + testInPlaceActivation(lp, backendId, targetId); } -INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, NoParamActivation, Values( -/*type*/ "TanH", "Sigmoid", "AbsVal", "BNLL" +INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, NoParamActivation, Combine( +/*type*/ Values("TanH", "Sigmoid", "AbsVal", "BNLL"), + dnnBackendsAndTargetsWithHalide() )); -typedef TestWithParam > Power; +typedef TestWithParam > > Power; TEST_P(Power, Accuracy) { float power = get<0>(GetParam())[0]; float scale = get<0>(GetParam())[1]; float shift = get<0>(GetParam())[2]; + int backendId = get<0>(get<1>(GetParam())); + int targetId = get<1>(get<1>(GetParam())); LayerParams lp; lp.set("power", power); @@ -485,46 +561,52 @@ TEST_P(Power, Accuracy) lp.set("shift", shift); lp.type = "Power"; lp.name = "testLayer"; - testInPlaceActivation(lp); + testInPlaceActivation(lp, backendId, targetId); } -INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Power, +INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Power, Combine( /*power, scale, shift*/ Values(Vec3f(0.9f, 1.0f, 1.1f), Vec3f(0.9f, 1.1f, 1.0f), Vec3f(1.0f, 0.9f, 1.1f), Vec3f(1.0f, 1.1f, 0.9f), - Vec3f(1.1f, 0.9f, 1.0f), Vec3f(1.1f, 1.0f, 0.9f)) -); + Vec3f(1.1f, 0.9f, 1.0f), Vec3f(1.1f, 1.0f, 0.9f)), + dnnBackendsAndTargetsWithHalide() +)); -TEST(ChannelsPReLU, Accuracy) +TEST_P(Test_Halide_layers, ChannelsPReLU) { LayerParams lp; lp.type = "ChannelsPReLU"; lp.name = "testLayer"; - lp.blobs.push_back(Mat({kNumChannels}, CV_32F)); + lp.blobs.push_back(Mat(1, kNumChannels, CV_32F)); randu(lp.blobs[0], -1.0f, 1.0f); - testInPlaceActivation(lp); + testInPlaceActivation(lp, backend, target); } -typedef TestWithParam > Scale; +typedef TestWithParam > > Scale; TEST_P(Scale, Accuracy) { bool hasBias = get<0>(GetParam()); + int backendId = get<0>(get<1>(GetParam())); + int targetId = get<1>(get<1>(GetParam())); LayerParams lp; lp.set("bias_term", hasBias); lp.type = "Scale"; lp.name = "testLayer"; - lp.blobs.push_back(Mat({kNumChannels}, CV_32F)); + lp.blobs.push_back(Mat(1, kNumChannels, CV_32F)); randu(lp.blobs[0], -1.0f, 1.0f); if (hasBias) { - lp.blobs.push_back(Mat({kNumChannels}, CV_32F)); + lp.blobs.push_back(Mat(1, kNumChannels, CV_32F)); randu(lp.blobs[1], -1.0f, 1.0f); } - testInPlaceActivation(lp); + testInPlaceActivation(lp, backendId, targetId); } -INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Scale, Values(true, false)); +INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Scale, Combine( + Bool(), + dnnBackendsAndTargetsWithHalide() +)); //////////////////////////////////////////////////////////////////////////////// // Concat layer @@ -534,11 +616,13 @@ INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Scale, Values(true, false)); // `--- conv ----^ ^ ^ // `---- ... ------' ' // `-----------------' -typedef TestWithParam > Concat; +typedef TestWithParam > > Concat; TEST_P(Concat, Accuracy) { Vec3i inSize = get<0>(GetParam()); Vec3i numChannels = get<1>(GetParam()); + int backendId = get<0>(get<2>(GetParam())); + int targetId = get<1>(get<2>(GetParam())); Net net; @@ -549,7 +633,8 @@ TEST_P(Concat, Accuracy) if (!numChannels[i]) break; - Mat weights({numChannels[i], inSize[0], 1, 1}, CV_32F); + int sz[] = {numChannels[i], inSize[0], 1, 1}; + Mat weights(4, &sz[0], CV_32F); randu(weights, -1.0f, 1.0f); LayerParams convParam; @@ -578,21 +663,15 @@ TEST_P(Concat, Accuracy) net.connect(convLayerIds[i], 0, concatId, i + 1); } - Mat input({1, inSize[0], inSize[1], inSize[2]}, CV_32F); - randu(input, -1.0f, 1.0f); - - net.setInput(input); - net.setPreferableBackend(DNN_BACKEND_OPENCV); - Mat outputDefault = net.forward(concatParam.name).clone(); - - net.setPreferableBackend(DNN_BACKEND_HALIDE); - Mat outputHalide = net.forward(concatParam.name).clone(); - normAssert(outputDefault, outputHalide); + int sz[] = {1, inSize[0], inSize[1], inSize[2]}; + Mat input(4, &sz[0], CV_32F); + test(input, net, backendId, targetId); } INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Concat, Combine( /*input size*/ Values(Vec3i(1, 4, 5), Vec3i(2, 8, 6)), -/*channels*/ Values(Vec3i(2, 0, 0), Vec3i(3, 4, 0), Vec3i(1, 6, 2)) +/*channels*/ Values(Vec3i(2, 0, 0), Vec3i(3, 4, 0), Vec3i(1, 6, 2)), + dnnBackendsAndTargetsWithHalide() )); //////////////////////////////////////////////////////////////////////////////// @@ -603,20 +682,27 @@ INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Concat, Combine( // `--- conv ----^ ^ ^ // `---- ... ------' ' // `-----------------' -typedef TestWithParam > Eltwise; +typedef TestWithParam > > Eltwise; TEST_P(Eltwise, Accuracy) { Vec3i inSize = get<0>(GetParam()); std::string op = get<1>(GetParam()); int numConv = get<2>(GetParam()); bool weighted = get<3>(GetParam()); + int backendId = get<0>(get<4>(GetParam())); + int targetId = get<1>(get<4>(GetParam())); + + if (backendId == DNN_BACKEND_OPENCV && + (targetId == DNN_TARGET_OPENCL || targetId == DNN_TARGET_OPENCL_FP16)) + throw SkipTestException(""); Net net; std::vector convLayerIds(numConv); for (int i = 0; i < numConv; ++i) { - Mat weights({inSize[0], inSize[0], 1, 1}, CV_32F); + int sz[] = {inSize[0], inSize[0], 1, 1}; + Mat weights(4, &sz[0], CV_32F); randu(weights, -1.0f, 1.0f); LayerParams convParam; @@ -655,28 +741,23 @@ TEST_P(Eltwise, Accuracy) net.connect(convLayerIds[i], 0, eltwiseId, i + 1); } - Mat input({1, inSize[0], inSize[1], inSize[2]}, CV_32F); - randu(input, -1.0f, 1.0f); - - net.setInput(input); - net.setPreferableBackend(DNN_BACKEND_OPENCV); - Mat outputDefault = net.forward(eltwiseParam.name).clone(); - - net.setPreferableBackend(DNN_BACKEND_HALIDE); - Mat outputHalide = net.forward(eltwiseParam.name).clone(); - normAssert(outputDefault, outputHalide); + int sz[] = {1, inSize[0], inSize[1], inSize[2]}; + Mat input(4, &sz[0], CV_32F); + test(input, net, backendId, targetId); } INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, Eltwise, Combine( /*input size*/ Values(Vec3i(1, 4, 5), Vec3i(2, 8, 6)), /*operation*/ Values("prod", "sum", "max"), /*num convs*/ Values(1, 2, 3), -/*weighted(for sum only)*/ Bool() +/*weighted(for sum only)*/ Bool(), + dnnBackendsAndTargetsWithHalide() )); //////////////////////////////////////////////////////////////////////////// // Mixed backends //////////////////////////////////////////////////////////////////////////// +#ifdef HAVE_HALIDE TEST(MixedBackends_Halide_Default_Halide, Accuracy) { // Just a layer that supports Halide backend. @@ -700,7 +781,8 @@ TEST(MixedBackends_Halide_Default_Halide, Accuracy) net.addLayerToPrev(mvn.name, mvn.type, mvn); net.addLayerToPrev(lrn2.name, lrn2.type, lrn2); - Mat input({4, 3, 5, 6}, CV_32F); + int sz[] = {4, 3, 5, 6}; + Mat input(4, &sz[0], CV_32F); randu(input, -1.0f, 1.0f); net.setInput(input); net.setPreferableBackend(DNN_BACKEND_OPENCV); @@ -718,4 +800,6 @@ TEST(MixedBackends_Halide_Default_Halide, Accuracy) } #endif // HAVE_HALIDE +INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_Halide_layers, dnnBackendsAndTargetsWithHalide()); + }} // namespace diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index 963206bd73..798ab8449f 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -92,75 +92,84 @@ void runLayer(Ptr layer, std::vector &inpBlobs, std::vector &ou outBlobs[i] = outp[i]; } - -void testLayerUsingCaffeModels(String basename, int targetId = DNN_TARGET_CPU, - bool useCaffeModel = false, bool useCommonInputBlob = true) +class Test_Caffe_layers : public DNNTestLayer { - String prototxt = _tf(basename + ".prototxt"); - String caffemodel = _tf(basename + ".caffemodel"); +public: + void testLayerUsingCaffeModels(const String& basename, bool useCaffeModel = false, + bool useCommonInputBlob = true, double l1 = 0.0, + double lInf = 0.0) + { + String prototxt = _tf(basename + ".prototxt"); + String caffemodel = _tf(basename + ".caffemodel"); - String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy"); - String outfile = _tf(basename + ".npy"); + String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy"); + String outfile = _tf(basename + ".npy"); - Net net = readNetFromCaffe(prototxt, (useCaffeModel) ? caffemodel : String()); - ASSERT_FALSE(net.empty()); + Mat inp = blobFromNPY(inpfile); + Mat ref = blobFromNPY(outfile); + checkBackend(&inp, &ref); - net.setPreferableBackend(DNN_BACKEND_OPENCV); - net.setPreferableTarget(targetId); + Net net = readNetFromCaffe(prototxt, (useCaffeModel) ? caffemodel : String()); + ASSERT_FALSE(net.empty()); - Mat inp = blobFromNPY(inpfile); - Mat ref = blobFromNPY(outfile); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); - net.setInput(inp, "input"); - Mat out = net.forward("output"); + net.setInput(inp, "input"); + Mat out = net.forward("output"); - normAssert(ref, out); -} + normAssert(ref, out, "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf); + } +}; -typedef testing::TestWithParam Test_Caffe_layers; TEST_P(Test_Caffe_layers, Softmax) { - testLayerUsingCaffeModels("layer_softmax", GetParam()); + testLayerUsingCaffeModels("layer_softmax"); } TEST_P(Test_Caffe_layers, LRN_spatial) { - testLayerUsingCaffeModels("layer_lrn_spatial", GetParam()); + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + throw SkipTestException(""); + testLayerUsingCaffeModels("layer_lrn_spatial"); } TEST_P(Test_Caffe_layers, LRN_channels) { - testLayerUsingCaffeModels("layer_lrn_channels", GetParam()); + testLayerUsingCaffeModels("layer_lrn_channels"); } TEST_P(Test_Caffe_layers, Convolution) { - testLayerUsingCaffeModels("layer_convolution", GetParam(), true); + testLayerUsingCaffeModels("layer_convolution", true); } TEST_P(Test_Caffe_layers, DeConvolution) { - testLayerUsingCaffeModels("layer_deconvolution", GetParam(), true, false); + testLayerUsingCaffeModels("layer_deconvolution", true, false); } TEST_P(Test_Caffe_layers, InnerProduct) { - testLayerUsingCaffeModels("layer_inner_product", GetParam(), true); + if (backend == DNN_BACKEND_INFERENCE_ENGINE || + (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)) + throw SkipTestException(""); + testLayerUsingCaffeModels("layer_inner_product", true); } TEST_P(Test_Caffe_layers, Pooling_max) { - testLayerUsingCaffeModels("layer_pooling_max", GetParam()); + testLayerUsingCaffeModels("layer_pooling_max"); } TEST_P(Test_Caffe_layers, Pooling_ave) { - testLayerUsingCaffeModels("layer_pooling_ave", GetParam()); + testLayerUsingCaffeModels("layer_pooling_ave"); } TEST_P(Test_Caffe_layers, MVN) { - testLayerUsingCaffeModels("layer_mvn", GetParam()); + testLayerUsingCaffeModels("layer_mvn"); } void testReshape(const MatShape& inputShape, const MatShape& targetShape, @@ -210,33 +219,38 @@ TEST(Layer_Test_Reshape, Accuracy) } } -TEST(Layer_Test_BatchNorm, Accuracy) +TEST_P(Test_Caffe_layers, BatchNorm) { - testLayerUsingCaffeModels("layer_batch_norm", DNN_TARGET_CPU, true); -} - -TEST(Layer_Test_BatchNorm, local_stats) -{ - testLayerUsingCaffeModels("layer_batch_norm_local_stats", DNN_TARGET_CPU, true, false); + if (backend == DNN_BACKEND_INFERENCE_ENGINE) + throw SkipTestException(""); + testLayerUsingCaffeModels("layer_batch_norm", true); + testLayerUsingCaffeModels("layer_batch_norm_local_stats", true, false); } TEST_P(Test_Caffe_layers, ReLU) { - testLayerUsingCaffeModels("layer_relu", GetParam()); + testLayerUsingCaffeModels("layer_relu"); } -TEST(Layer_Test_Dropout, Accuracy) +TEST_P(Test_Caffe_layers, Dropout) { testLayerUsingCaffeModels("layer_dropout"); } TEST_P(Test_Caffe_layers, Concat) { - testLayerUsingCaffeModels("layer_concat", GetParam()); + testLayerUsingCaffeModels("layer_concat"); + testLayerUsingCaffeModels("layer_concat_optim", true, false); + testLayerUsingCaffeModels("layer_concat_shared_input", true, false); } -TEST(Layer_Test_Fused_Concat, Accuracy) +TEST_P(Test_Caffe_layers, Fused_Concat) { + if ((backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_CPU) || + (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL)) + throw SkipTestException(""); + checkBackend(); + // Test case // input // | @@ -267,28 +281,32 @@ TEST(Layer_Test_Fused_Concat, Accuracy) randu(input, 0.0f, 1.0f); // [0, 1] to make AbsVal an identity transformation. net.setInput(input); - net.setPreferableBackend(DNN_BACKEND_OPENCV); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); Mat out = net.forward(); - normAssert(slice(out, Range::all(), Range(0, 2), Range::all(), Range::all()), input); - normAssert(slice(out, Range::all(), Range(2, 4), Range::all(), Range::all()), input); - - // - - testLayerUsingCaffeModels("layer_concat_optim", DNN_TARGET_CPU, true, false); - testLayerUsingCaffeModels("layer_concat_shared_input", DNN_TARGET_CPU, true, false); + normAssert(slice(out, Range::all(), Range(0, 2), Range::all(), Range::all()), input, "", default_l1, default_lInf); + normAssert(slice(out, Range::all(), Range(2, 4), Range::all(), Range::all()), input, "", default_l1, default_lInf); } TEST_P(Test_Caffe_layers, Eltwise) { - testLayerUsingCaffeModels("layer_eltwise", GetParam()); + if (backend == DNN_BACKEND_INFERENCE_ENGINE) + throw SkipTestException(""); + testLayerUsingCaffeModels("layer_eltwise"); } TEST_P(Test_Caffe_layers, PReLU) { - int targetId = GetParam(); - testLayerUsingCaffeModels("layer_prelu", targetId, true); - testLayerUsingCaffeModels("layer_prelu_fc", targetId, true, false); + testLayerUsingCaffeModels("layer_prelu", true); +} + +// TODO: fix an unstable test case +TEST_P(Test_Caffe_layers, layer_prelu_fc) +{ + if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) + throw SkipTestException(""); + testLayerUsingCaffeModels("layer_prelu_fc", true, false); } //template @@ -311,13 +329,16 @@ TEST_P(Test_Caffe_layers, PReLU) // ); //} -static void test_Reshape_Split_Slice_layers(int targetId) +TEST_P(Test_Caffe_layers, Reshape_Split_Slice) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE) + throw SkipTestException(""); + Net net = readNetFromCaffe(_tf("reshape_and_slice_routines.prototxt")); ASSERT_FALSE(net.empty()); - net.setPreferableBackend(DNN_BACKEND_OPENCV); - net.setPreferableTarget(targetId); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); Mat input(6, 12, CV_32F); RNG rng(0); @@ -326,15 +347,10 @@ static void test_Reshape_Split_Slice_layers(int targetId) net.setInput(input, "input"); Mat output = net.forward("output"); - normAssert(input, output); + normAssert(input, output, "", default_l1, default_lInf); } -TEST_P(Test_Caffe_layers, Reshape_Split_Slice) -{ - test_Reshape_Split_Slice_layers(GetParam()); -} - -TEST(Layer_Conv_Elu, Accuracy) +TEST_P(Test_Caffe_layers, Conv_Elu) { Net net = readNetFromTensorflow(_tf("layer_elu_model.pb")); ASSERT_FALSE(net.empty()); @@ -343,10 +359,11 @@ TEST(Layer_Conv_Elu, Accuracy) Mat ref = blobFromNPY(_tf("layer_elu_out.npy")); net.setInput(inp, "input"); - net.setPreferableBackend(DNN_BACKEND_OPENCV); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); Mat out = net.forward(); - normAssert(ref, out); + normAssert(ref, out, "", default_l1, default_lInf); } class Layer_LSTM_Test : public ::testing::Test @@ -496,37 +513,6 @@ TEST_F(Layer_RNN_Test, get_set_test) EXPECT_EQ(shape(outputs[1]), shape(nT, nS, nH)); } -void testLayerUsingDarknetModels(String basename, bool useDarknetModel = false, bool useCommonInputBlob = true) -{ - String cfg = _tf(basename + ".cfg"); - String weights = _tf(basename + ".weights"); - - String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy"); - String outfile = _tf(basename + ".npy"); - - Net net = readNetFromDarknet(cfg, (useDarknetModel) ? weights : String()); - ASSERT_FALSE(net.empty()); - - Mat inp = blobFromNPY(inpfile); - Mat ref = blobFromNPY(outfile); - - net.setInput(inp, "data"); - net.setPreferableBackend(DNN_BACKEND_OPENCV); - Mat out = net.forward(); - - normAssert(ref, out); -} - -TEST(Layer_Test_Region, Accuracy) -{ - testLayerUsingDarknetModels("region", false, false); -} - -TEST(Layer_Test_Reorg, Accuracy) -{ - testLayerUsingDarknetModels("reorg", false, false); -} - TEST(Layer_Test_ROIPooling, Accuracy) { Net net = readNetFromCaffe(_tf("net_roi_pooling.prototxt")); @@ -546,8 +532,10 @@ TEST(Layer_Test_ROIPooling, Accuracy) TEST_P(Test_Caffe_layers, FasterRCNN_Proposal) { + if ((backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) || + backend == DNN_BACKEND_INFERENCE_ENGINE) + throw SkipTestException(""); Net net = readNetFromCaffe(_tf("net_faster_rcnn_proposal.prototxt")); - net.setPreferableTarget(GetParam()); Mat scores = blobFromNPY(_tf("net_faster_rcnn_proposal.scores.npy")); Mat deltas = blobFromNPY(_tf("net_faster_rcnn_proposal.deltas.npy")); @@ -558,7 +546,8 @@ TEST_P(Test_Caffe_layers, FasterRCNN_Proposal) net.setInput(imInfo, "im_info"); std::vector outs; - net.setPreferableBackend(DNN_BACKEND_OPENCV); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); net.forward(outs, "output"); for (int i = 0; i < 2; ++i) @@ -573,7 +562,6 @@ TEST_P(Test_Caffe_layers, FasterRCNN_Proposal) EXPECT_EQ(countNonZero(outs[i].rowRange(numDets, outs[i].size[0])), 0); } } -INSTANTIATE_TEST_CASE_P(/**/, Test_Caffe_layers, availableDnnTargets()); typedef testing::TestWithParam > Scale_untrainable; TEST_P(Scale_untrainable, Accuracy) @@ -739,8 +727,10 @@ INSTANTIATE_TEST_CASE_P(Layer_Test, Crop, Combine( // Check that by default average pooling layer should not count zero padded values // into the normalization area. -TEST(Layer_Test_Average_pooling_kernel_area, Accuracy) +TEST_P(Test_Caffe_layers, Average_pooling_kernel_area) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + throw SkipTestException(""); LayerParams lp; lp.name = "testAvePool"; lp.type = "Pooling"; @@ -755,17 +745,21 @@ TEST(Layer_Test_Average_pooling_kernel_area, Accuracy) // ----+-- // 7 8 | 9 Mat inp = (Mat_(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9); - Mat target = (Mat_(2, 2) << (1 + 2 + 4 + 5) / 4.f, (3 + 6) / 2.f, (7 + 8) / 2.f, 9); + Mat ref = (Mat_(2, 2) << (1 + 2 + 4 + 5) / 4.f, (3 + 6) / 2.f, (7 + 8) / 2.f, 9); Mat tmp = blobFromImage(inp); net.setInput(blobFromImage(inp)); - net.setPreferableBackend(DNN_BACKEND_OPENCV); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); Mat out = net.forward(); - normAssert(out, blobFromImage(target)); + normAssert(out, blobFromImage(ref)); } // Test PriorBoxLayer in case of no aspect ratios (just squared proposals). -TEST(Layer_PriorBox, squares) +TEST_P(Test_Caffe_layers, PriorBox_squares) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE || + (backend == DNN_BACKEND_OPENCV && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))) + throw SkipTestException(""); LayerParams lp; lp.name = "testPriorBox"; lp.type = "PriorBox"; @@ -783,14 +777,15 @@ TEST(Layer_PriorBox, squares) Mat inp(1, 2, CV_32F); randu(inp, -1, 1); net.setInput(blobFromImage(inp)); - net.setPreferableBackend(DNN_BACKEND_OPENCV); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); Mat out = net.forward(); - Mat target = (Mat_(4, 4) << 0.0, 0.0, 0.75, 1.0, + Mat ref = (Mat_(4, 4) << 0.0, 0.0, 0.75, 1.0, 0.25, 0.0, 1.0, 1.0, 0.1f, 0.1f, 0.2f, 0.2f, 0.1f, 0.1f, 0.2f, 0.2f); - normAssert(out.reshape(1, 4), target); + normAssert(out.reshape(1, 4), ref); } typedef TestWithParam > Layer_Test_DWconv_Prelu; @@ -1056,19 +1051,19 @@ TEST(Test_DLDT, multiple_networks) #endif // HAVE_INF_ENGINE // Test a custom layer. -class InterpLayer CV_FINAL : public Layer +class CustomInterpLayer CV_FINAL : public Layer { public: - InterpLayer(const LayerParams ¶ms) : Layer(params) + CustomInterpLayer(const LayerParams ¶ms) : Layer(params) { zoomFactor = params.get("zoom_factor", 0); outWidth = params.get("width", 0); outHeight = params.get("height", 0); } - static Ptr create(LayerParams& params) + static Ptr create(LayerParams& params) { - return Ptr(new InterpLayer(params)); + return Ptr(new CustomInterpLayer(params)); } virtual bool getMemoryShapes(const std::vector > &inputs, @@ -1142,23 +1137,40 @@ public: } } - virtual void forward(InputArrayOfArrays, OutputArrayOfArrays, OutputArrayOfArrays) CV_OVERRIDE {} + void forward(InputArrayOfArrays inputs, OutputArrayOfArrays outputs, OutputArrayOfArrays internals) CV_OVERRIDE + { + CV_TRACE_FUNCTION(); + CV_TRACE_ARG_VALUE(name, "name", name.c_str()); + + Layer::forward_fallback(inputs, outputs, internals); + } private: int outWidth, outHeight, zoomFactor; }; -TEST(Layer_Test_Interp_custom, Accuracy) +TEST_P(Test_Caffe_layers, Interp) { - CV_DNN_REGISTER_LAYER_CLASS(Interp, InterpLayer); - testLayerUsingCaffeModels("layer_interp", DNN_TARGET_CPU, false, false); + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + throw SkipTestException(""); + // Test a cusom layer. + CV_DNN_REGISTER_LAYER_CLASS(Interp, CustomInterpLayer); + try + { + testLayerUsingCaffeModels("layer_interp", false, false); + } + catch (...) + { + LayerFactory::unregisterLayer("Interp"); + throw; + } LayerFactory::unregisterLayer("Interp"); + + // Test an implemented layer. + testLayerUsingCaffeModels("layer_interp", false, false); } -TEST(Layer_Test_Interp, Accuracy) -{ - testLayerUsingCaffeModels("layer_interp", DNN_TARGET_CPU, false, false); -} +INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_Caffe_layers, dnnBackendsAndTargets()); TEST(Layer_Test_PoolingIndices, Accuracy) { diff --git a/modules/dnn/test/test_precomp.hpp b/modules/dnn/test/test_precomp.hpp index 7ca1b985ad..16f1e5c846 100644 --- a/modules/dnn/test/test_precomp.hpp +++ b/modules/dnn/test/test_precomp.hpp @@ -69,6 +69,93 @@ static testing::internal::ParamGenerator availableDnnTargets() return testing::ValuesIn(targets); } +static testing::internal::ParamGenerator > dnnBackendsAndTargets() +{ + static const tuple testCases[] = { + #ifdef HAVE_INF_ENGINE + tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU), + tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL), + tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16), + tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD), + #endif + tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU), + tuple(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL), + tuple(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL_FP16) + }; + return testing::ValuesIn(testCases); +} + +class DNNTestLayer : public TestWithParam > +{ +public: + dnn::Backend backend; + dnn::Target target; + double default_l1, default_lInf; + + DNNTestLayer() + { + backend = (dnn::Backend)(int)get<0>(GetParam()); + target = (dnn::Target)(int)get<1>(GetParam()); + getDefaultThresholds(backend, target, &default_l1, &default_lInf); + } + + static void getDefaultThresholds(int backend, int target, double* l1, double* lInf) + { + if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) + { + *l1 = 4e-3; + *lInf = 2e-2; + } + else + { + *l1 = 1e-5; + *lInf = 1e-4; + } + } + + static void checkBackend(int backend, int target, Mat* inp = 0, Mat* ref = 0) + { + if (backend == DNN_BACKEND_OPENCV && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) + { +#ifdef HAVE_OPENCL + if (!cv::ocl::useOpenCL()) +#endif + { + throw SkipTestException("OpenCL is not available/disabled in OpenCV"); + } + } + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + { + if (!checkMyriadTarget()) + { + throw SkipTestException("Myriad is not available/disabled in OpenCV"); + } + if (inp && ref && inp->size[0] != 1) + { + // Myriad plugin supports only batch size 1. Slice a single sample. + if (inp->size[0] == ref->size[0]) + { + std::vector range(inp->dims, Range::all()); + range[0] = Range(0, 1); + *inp = inp->operator()(range); + + range = std::vector(ref->dims, Range::all()); + range[0] = Range(0, 1); + *ref = ref->operator()(range); + } + else + throw SkipTestException("Myriad plugin supports only batch size 1"); + } + } + } + +protected: + void checkBackend(Mat* inp = 0, Mat* ref = 0) + { + checkBackend(backend, target, inp, ref); + } +}; + }} #endif diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index 408782233c..ff1d0b3200 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -78,141 +78,170 @@ static std::string path(const std::string& file) return findDataFile("dnn/tensorflow/" + file, false); } -static void runTensorFlowNet(const std::string& prefix, int targetId = DNN_TARGET_CPU, bool hasText = false, - double l1 = 1e-5, double lInf = 1e-4, - bool memoryLoad = false) +class Test_TensorFlow_layers : public DNNTestLayer { - std::string netPath = path(prefix + "_net.pb"); - std::string netConfig = (hasText ? path(prefix + "_net.pbtxt") : ""); - std::string inpPath = path(prefix + "_in.npy"); - std::string outPath = path(prefix + "_out.npy"); - - Net net; - if (memoryLoad) +public: + void runTensorFlowNet(const std::string& prefix, bool hasText = false, + double l1 = 0.0, double lInf = 0.0, bool memoryLoad = false) { - // Load files into a memory buffers - string dataModel; - ASSERT_TRUE(readFileInMemory(netPath, dataModel)); + std::string netPath = path(prefix + "_net.pb"); + std::string netConfig = (hasText ? path(prefix + "_net.pbtxt") : ""); + std::string inpPath = path(prefix + "_in.npy"); + std::string outPath = path(prefix + "_out.npy"); - string dataConfig; - if (hasText) - ASSERT_TRUE(readFileInMemory(netConfig, dataConfig)); + cv::Mat input = blobFromNPY(inpPath); + cv::Mat ref = blobFromNPY(outPath); + checkBackend(&input, &ref); - net = readNetFromTensorflow(dataModel.c_str(), dataModel.size(), - dataConfig.c_str(), dataConfig.size()); + Net net; + if (memoryLoad) + { + // Load files into a memory buffers + string dataModel; + ASSERT_TRUE(readFileInMemory(netPath, dataModel)); + + string dataConfig; + if (hasText) + ASSERT_TRUE(readFileInMemory(netConfig, dataConfig)); + + net = readNetFromTensorflow(dataModel.c_str(), dataModel.size(), + dataConfig.c_str(), dataConfig.size()); + } + else + net = readNetFromTensorflow(netPath, netConfig); + + ASSERT_FALSE(net.empty()); + + net.setPreferableBackend(backend); + net.setPreferableTarget(target); + net.setInput(input); + cv::Mat output = net.forward(); + normAssert(ref, output, "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf); } - else - net = readNetFromTensorflow(netPath, netConfig); - - ASSERT_FALSE(net.empty()); - - net.setPreferableBackend(DNN_BACKEND_OPENCV); - net.setPreferableTarget(targetId); - - cv::Mat input = blobFromNPY(inpPath); - cv::Mat target = blobFromNPY(outPath); - - net.setInput(input); - cv::Mat output = net.forward(); - normAssert(target, output, "", l1, lInf); -} - -typedef testing::TestWithParam Test_TensorFlow_layers; +}; TEST_P(Test_TensorFlow_layers, conv) { - int targetId = GetParam(); - runTensorFlowNet("single_conv", targetId); - runTensorFlowNet("atrous_conv2d_valid", targetId); - runTensorFlowNet("atrous_conv2d_same", targetId); - runTensorFlowNet("depthwise_conv2d", targetId); - runTensorFlowNet("keras_atrous_conv2d_same", targetId); - runTensorFlowNet("conv_pool_nchw", targetId); + runTensorFlowNet("single_conv"); + runTensorFlowNet("atrous_conv2d_valid"); + runTensorFlowNet("atrous_conv2d_same"); + runTensorFlowNet("depthwise_conv2d"); + runTensorFlowNet("keras_atrous_conv2d_same"); + runTensorFlowNet("conv_pool_nchw"); } TEST_P(Test_TensorFlow_layers, padding) { - int targetId = GetParam(); - runTensorFlowNet("padding_same", targetId); - runTensorFlowNet("padding_valid", targetId); - runTensorFlowNet("spatial_padding", targetId); + runTensorFlowNet("padding_same"); + runTensorFlowNet("padding_valid"); + runTensorFlowNet("spatial_padding"); } TEST_P(Test_TensorFlow_layers, eltwise_add_mul) { - runTensorFlowNet("eltwise_add_mul", GetParam()); + runTensorFlowNet("eltwise_add_mul"); } -TEST_P(Test_TensorFlow_layers, concat) +TEST_P(Test_TensorFlow_layers, pad_and_concat) { - runTensorFlowNet("pad_and_concat", GetParam()); - runTensorFlowNet("concat_axis_1", GetParam()); + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + throw SkipTestException(""); + runTensorFlowNet("pad_and_concat"); +} + +TEST_P(Test_TensorFlow_layers, concat_axis_1) +{ + runTensorFlowNet("concat_axis_1"); } TEST_P(Test_TensorFlow_layers, batch_norm) { - int targetId = GetParam(); - runTensorFlowNet("batch_norm", targetId); - runTensorFlowNet("fused_batch_norm", targetId); - runTensorFlowNet("batch_norm_text", targetId, true); - runTensorFlowNet("mvn_batch_norm", targetId); - runTensorFlowNet("mvn_batch_norm_1x1", targetId); - runTensorFlowNet("unfused_batch_norm", targetId); - runTensorFlowNet("fused_batch_norm_no_gamma", targetId); - runTensorFlowNet("unfused_batch_norm_no_gamma", targetId); + runTensorFlowNet("batch_norm"); + runTensorFlowNet("batch_norm", false, 0.0, 0.0, true); + runTensorFlowNet("fused_batch_norm"); + runTensorFlowNet("fused_batch_norm", false, 0.0, 0.0, true); + runTensorFlowNet("batch_norm_text", true); + runTensorFlowNet("batch_norm_text", true, 0.0, 0.0, true); + runTensorFlowNet("unfused_batch_norm"); + runTensorFlowNet("fused_batch_norm_no_gamma"); + runTensorFlowNet("unfused_batch_norm_no_gamma"); +} + +TEST_P(Test_TensorFlow_layers, mvn_batch_norm) +{ + if (backend == DNN_BACKEND_INFERENCE_ENGINE) + throw SkipTestException(""); + runTensorFlowNet("mvn_batch_norm"); + runTensorFlowNet("mvn_batch_norm_1x1"); } TEST_P(Test_TensorFlow_layers, pooling) { - int targetId = GetParam(); - cv::ocl::Device d = cv::ocl::Device::getDefault(); - bool loosenFlag = targetId == DNN_TARGET_OPENCL && d.isIntel() && d.type() == cv::ocl::Device::TYPE_CPU; - runTensorFlowNet("max_pool_even", targetId); - runTensorFlowNet("max_pool_odd_valid", targetId); - runTensorFlowNet("ave_pool_same", targetId); - runTensorFlowNet("max_pool_odd_same", targetId, false, loosenFlag ? 3e-5 : 1e-5, loosenFlag ? 3e-4 : 1e-4); - runTensorFlowNet("reduce_mean", targetId); // an average pooling over all spatial dimensions. + runTensorFlowNet("max_pool_even"); + runTensorFlowNet("max_pool_odd_valid"); + runTensorFlowNet("max_pool_odd_same"); + runTensorFlowNet("reduce_mean"); // an average pooling over all spatial dimensions. +} + +// TODO: fix tests and replace to pooling +TEST_P(Test_TensorFlow_layers, ave_pool_same) +{ + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + throw SkipTestException(""); + runTensorFlowNet("ave_pool_same"); } TEST_P(Test_TensorFlow_layers, deconvolution) { - int targetId = GetParam(); - runTensorFlowNet("deconvolution", targetId); - runTensorFlowNet("deconvolution_same", targetId); - runTensorFlowNet("deconvolution_stride_2_same", targetId); - runTensorFlowNet("deconvolution_adj_pad_valid", targetId); - runTensorFlowNet("deconvolution_adj_pad_same", targetId); - runTensorFlowNet("keras_deconv_valid", targetId); - runTensorFlowNet("keras_deconv_same", targetId); + runTensorFlowNet("deconvolution"); + runTensorFlowNet("deconvolution_same"); + runTensorFlowNet("deconvolution_stride_2_same"); + runTensorFlowNet("deconvolution_adj_pad_valid"); + runTensorFlowNet("deconvolution_adj_pad_same"); + runTensorFlowNet("keras_deconv_valid"); + runTensorFlowNet("keras_deconv_same"); } TEST_P(Test_TensorFlow_layers, matmul) { - int targetId = GetParam(); - runTensorFlowNet("matmul", targetId); - runTensorFlowNet("nhwc_reshape_matmul", targetId); - runTensorFlowNet("nhwc_transpose_reshape_matmul", targetId); + if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) + throw SkipTestException(""); + runTensorFlowNet("matmul"); + runTensorFlowNet("nhwc_reshape_matmul"); + runTensorFlowNet("nhwc_transpose_reshape_matmul"); } TEST_P(Test_TensorFlow_layers, reshape) { - int targetId = GetParam(); - runTensorFlowNet("shift_reshape_no_reorder", targetId); - runTensorFlowNet("reshape_no_reorder", targetId); - runTensorFlowNet("reshape_reduce", targetId); - runTensorFlowNet("flatten", targetId, true); - runTensorFlowNet("unfused_flatten", targetId); - runTensorFlowNet("unfused_flatten_unknown_batch", targetId); + if (backend == DNN_BACKEND_INFERENCE_ENGINE) + throw SkipTestException(""); + runTensorFlowNet("shift_reshape_no_reorder"); + runTensorFlowNet("reshape_no_reorder"); + runTensorFlowNet("reshape_reduce"); +} + +TEST_P(Test_TensorFlow_layers, flatten) +{ + if (backend == DNN_BACKEND_INFERENCE_ENGINE && + (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) + throw SkipTestException(""); + runTensorFlowNet("flatten", true); + runTensorFlowNet("unfused_flatten"); + runTensorFlowNet("unfused_flatten_unknown_batch"); } TEST_P(Test_TensorFlow_layers, l2_normalize) { - int targetId = GetParam(); - runTensorFlowNet("l2_normalize", targetId); - runTensorFlowNet("l2_normalize_3d", targetId); + runTensorFlowNet("l2_normalize"); } -INSTANTIATE_TEST_CASE_P(/**/, Test_TensorFlow_layers, availableDnnTargets()); +// TODO: fix it and add to l2_normalize +TEST_P(Test_TensorFlow_layers, l2_normalize_3d) +{ + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + throw SkipTestException(""); + runTensorFlowNet("l2_normalize_3d"); +} typedef testing::TestWithParam Test_TensorFlow_nets; @@ -359,90 +388,95 @@ TEST_P(Test_TensorFlow_nets, EAST_text_detection) INSTANTIATE_TEST_CASE_P(/**/, Test_TensorFlow_nets, availableDnnTargets()); -typedef testing::TestWithParam Test_TensorFlow_fp16; - -TEST_P(Test_TensorFlow_fp16, tests) +TEST_P(Test_TensorFlow_layers, fp16_weights) { - int targetId = GetParam(); - const float l1 = 7e-4; - const float lInf = 1e-2; - runTensorFlowNet("fp16_single_conv", targetId, false, l1, lInf); - runTensorFlowNet("fp16_deconvolution", targetId, false, l1, lInf); - runTensorFlowNet("fp16_max_pool_odd_same", targetId, false, l1, lInf); - runTensorFlowNet("fp16_padding_valid", targetId, false, l1, lInf); - runTensorFlowNet("fp16_eltwise_add_mul", targetId, false, l1, lInf); - runTensorFlowNet("fp16_max_pool_odd_valid", targetId, false, l1, lInf); - runTensorFlowNet("fp16_pad_and_concat", targetId, false, l1, lInf); - runTensorFlowNet("fp16_max_pool_even", targetId, false, l1, lInf); - runTensorFlowNet("fp16_padding_same", targetId, false, l1, lInf); + const float l1 = 0.00071; + const float lInf = 0.012; + runTensorFlowNet("fp16_single_conv", false, l1, lInf); + runTensorFlowNet("fp16_deconvolution", false, l1, lInf); + runTensorFlowNet("fp16_max_pool_odd_same", false, l1, lInf); + runTensorFlowNet("fp16_padding_valid", false, l1, lInf); + runTensorFlowNet("fp16_eltwise_add_mul", false, l1, lInf); + runTensorFlowNet("fp16_max_pool_odd_valid", false, l1, lInf); + runTensorFlowNet("fp16_max_pool_even", false, l1, lInf); + runTensorFlowNet("fp16_padding_same", false, l1, lInf); } -INSTANTIATE_TEST_CASE_P(/**/, Test_TensorFlow_fp16, - Values(DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16)); +// TODO: fix pad_and_concat and add this test case to fp16_weights +TEST_P(Test_TensorFlow_layers, fp16_pad_and_concat) +{ + const float l1 = 0.00071; + const float lInf = 0.012; + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + throw SkipTestException(""); + runTensorFlowNet("fp16_pad_and_concat", false, l1, lInf); +} -TEST(Test_TensorFlow, defun) +TEST_P(Test_TensorFlow_layers, defun) { runTensorFlowNet("defun_dropout"); } -TEST(Test_TensorFlow, quantized) +TEST_P(Test_TensorFlow_layers, quantized) { runTensorFlowNet("uint8_single_conv"); } -TEST(Test_TensorFlow, lstm) +TEST_P(Test_TensorFlow_layers, lstm) { - runTensorFlowNet("lstm", DNN_TARGET_CPU, true); + if (backend == DNN_BACKEND_INFERENCE_ENGINE || + (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)) + throw SkipTestException(""); + runTensorFlowNet("lstm", true); + runTensorFlowNet("lstm", true, 0.0, 0.0, true); } -TEST(Test_TensorFlow, split) +TEST_P(Test_TensorFlow_layers, split) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE) + throw SkipTestException(""); runTensorFlowNet("split_equals"); } -TEST(Test_TensorFlow, resize_nearest_neighbor) +TEST_P(Test_TensorFlow_layers, resize_nearest_neighbor) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_MYRIAD) + throw SkipTestException(""); runTensorFlowNet("resize_nearest_neighbor"); } -TEST(Test_TensorFlow, slice) +TEST_P(Test_TensorFlow_layers, slice) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE && + (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) + throw SkipTestException(""); runTensorFlowNet("slice_4d"); } -TEST(Test_TensorFlow, softmax) +TEST_P(Test_TensorFlow_layers, softmax) { runTensorFlowNet("keras_softmax"); } -TEST(Test_TensorFlow, relu6) +TEST_P(Test_TensorFlow_layers, relu6) { runTensorFlowNet("keras_relu6"); - runTensorFlowNet("keras_relu6", DNN_TARGET_CPU, /*hasText*/ true); + runTensorFlowNet("keras_relu6", /*hasText*/ true); } -TEST(Test_TensorFlow, keras_mobilenet_head) +TEST_P(Test_TensorFlow_layers, keras_mobilenet_head) { runTensorFlowNet("keras_mobilenet_head"); } -TEST(Test_TensorFlow, memory_read) -{ - double l1 = 1e-5; - double lInf = 1e-4; - runTensorFlowNet("lstm", DNN_TARGET_CPU, true, l1, lInf, true); - - runTensorFlowNet("batch_norm", DNN_TARGET_CPU, false, l1, lInf, true); - runTensorFlowNet("fused_batch_norm", DNN_TARGET_CPU, false, l1, lInf, true); - runTensorFlowNet("batch_norm_text", DNN_TARGET_CPU, true, l1, lInf, true); -} - -TEST(Test_TensorFlow, resize_bilinear) +TEST_P(Test_TensorFlow_layers, resize_bilinear) { runTensorFlowNet("resize_bilinear"); runTensorFlowNet("resize_bilinear_factor"); } +INSTANTIATE_TEST_CASE_P(/**/, Test_TensorFlow_layers, dnnBackendsAndTargets()); + TEST(Test_TensorFlow, two_inputs) { Net net = readNet(path("two_inputs_net.pbtxt")); diff --git a/modules/dnn/test/test_torch_importer.cpp b/modules/dnn/test/test_torch_importer.cpp index 5fe3fe121b..c1abdc930d 100644 --- a/modules/dnn/test/test_torch_importer.cpp +++ b/modules/dnn/test/test_torch_importer.cpp @@ -296,7 +296,6 @@ TEST_P(Test_Torch_nets, FastNeuralStyle_accuracy) Mat inputBlob = blobFromImage(img, 1.0, Size(), Scalar(103.939, 116.779, 123.68), false); net.setInput(inputBlob); - net.setPreferableBackend(DNN_BACKEND_OPENCV); Mat out = net.forward(); // Deprocessing. From 06fc77610b53df024fb67033302f0592b8dc4090 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 6 Jul 2018 12:41:59 +0300 Subject: [PATCH 17/26] core(hal): eliminate build warnings --- .../include/opencv2/core/hal/intrin_sse.hpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/core/include/opencv2/core/hal/intrin_sse.hpp b/modules/core/include/opencv2/core/hal/intrin_sse.hpp index 22c0668642..8c61f44f4a 100644 --- a/modules/core/include/opencv2/core/hal/intrin_sse.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_sse.hpp @@ -296,15 +296,15 @@ namespace hal_sse_internal to_sse_type v_sse_reinterpret_as(const from_sse_type& a) \ { return sse_cast_intrin(a); } - OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128i, __m128i, OPENCV_HAL_NOP); - OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128i, __m128, _mm_castps_si128); - OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128i, __m128d, _mm_castpd_si128); - OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128, __m128i, _mm_castsi128_ps); - OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128, __m128, OPENCV_HAL_NOP); - OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128, __m128d, _mm_castpd_ps); - OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128d, __m128i, _mm_castsi128_pd); - OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128d, __m128, _mm_castps_pd); - OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128d, __m128d, OPENCV_HAL_NOP); + OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128i, __m128i, OPENCV_HAL_NOP) + OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128i, __m128, _mm_castps_si128) + OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128i, __m128d, _mm_castpd_si128) + OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128, __m128i, _mm_castsi128_ps) + OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128, __m128, OPENCV_HAL_NOP) + OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128, __m128d, _mm_castpd_ps) + OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128d, __m128i, _mm_castsi128_pd) + OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128d, __m128, _mm_castps_pd) + OPENCV_HAL_IMPL_SSE_REINTERPRET_RAW(__m128d, __m128d, OPENCV_HAL_NOP) } #define OPENCV_HAL_IMPL_SSE_INITVEC(_Tpvec, _Tp, suffix, zsuffix, ssuffix, _Tps, cast) \ @@ -988,8 +988,8 @@ inline _Tpvec operator == (const _Tpvec& a, const _Tpvec& b) \ inline _Tpvec operator != (const _Tpvec& a, const _Tpvec& b) \ { return cast(v_reinterpret_as_f64(a) != v_reinterpret_as_f64(b)); } -OPENCV_HAL_IMPL_SSE_64BIT_CMP_OP(v_uint64x2, v_reinterpret_as_u64); -OPENCV_HAL_IMPL_SSE_64BIT_CMP_OP(v_int64x2, v_reinterpret_as_s64); +OPENCV_HAL_IMPL_SSE_64BIT_CMP_OP(v_uint64x2, v_reinterpret_as_u64) +OPENCV_HAL_IMPL_SSE_64BIT_CMP_OP(v_int64x2, v_reinterpret_as_s64) OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_uint8x16, v_add_wrap, _mm_add_epi8) OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_int8x16, v_add_wrap, _mm_add_epi8) From fc59498b2b3fee27d7dbcb6be7f19090a50024ed Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 6 Jul 2018 15:31:25 +0300 Subject: [PATCH 18/26] cuda: fix build use cv::AutoBuffer::data() to get data pointer --- modules/cudaimgproc/src/hough_circles.cpp | 4 ++-- modules/cudastereo/src/stereocsbp.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/cudaimgproc/src/hough_circles.cpp b/modules/cudaimgproc/src/hough_circles.cpp index b706967671..2a5c025d43 100644 --- a/modules/cudaimgproc/src/hough_circles.cpp +++ b/modules/cudaimgproc/src/hough_circles.cpp @@ -215,8 +215,8 @@ namespace AutoBuffer newBuf_(centersCount); int newCount = 0; - ushort2* oldBuf = oldBuf_; - ushort2* newBuf = newBuf_; + ushort2* oldBuf = oldBuf_.data(); + ushort2* newBuf = newBuf_.data(); cudaSafeCall( cudaMemcpy(oldBuf, centers, centersCount * sizeof(ushort2), cudaMemcpyDeviceToHost) ); diff --git a/modules/cudastereo/src/stereocsbp.cpp b/modules/cudastereo/src/stereocsbp.cpp index ded5fa20e1..bc5a230f63 100644 --- a/modules/cudastereo/src/stereocsbp.cpp +++ b/modules/cudastereo/src/stereocsbp.cpp @@ -172,7 +172,7 @@ namespace // compute sizes AutoBuffer buf(levels_ * 3); - int* cols_pyr = buf; + int* cols_pyr = buf.data(); int* rows_pyr = cols_pyr + levels_; int* nr_plane_pyr = rows_pyr + levels_; From aa0c6ddb4cc09adcabcdcba807b2eba27759bcfa Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 6 Jul 2018 16:17:49 +0300 Subject: [PATCH 19/26] highgui: fix GTK issues with external UI thread --- modules/highgui/src/window_gtk.cpp | 47 ++++++++++++++++++------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index ea3f4541ca..07e683de39 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -40,9 +40,6 @@ //M*/ #include "precomp.hpp" -#include "opencv2/imgproc.hpp" - -using namespace cv; #ifndef _WIN32 @@ -66,6 +63,11 @@ using namespace cv; #include #endif +#include +#include "opencv2/imgproc.hpp" + +using namespace cv; + #ifndef BIT_ALLIN #define BIT_ALLIN(x,y) ( ((x)&(y)) == (y) ) #endif @@ -1705,18 +1707,19 @@ static gboolean icvOnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer us code |= event->state << 16; #ifdef HAVE_GTHREAD - if(thread_started) g_mutex_lock(last_key_mutex); -#endif - - last_key = code; - -#ifdef HAVE_GTHREAD - if(thread_started){ + if(thread_started) + { + g_mutex_lock(last_key_mutex); + last_key = code; // signal any waiting threads g_cond_broadcast(cond_have_key); g_mutex_unlock(last_key_mutex); } + else #endif + { + last_key = code; + } return FALSE; } @@ -1886,10 +1889,12 @@ static gboolean icvAlarm( gpointer user_data ) CV_IMPL int cvWaitKey( int delay ) { #ifdef HAVE_GTHREAD - if(thread_started && g_thread_self()!=window_thread){ - gboolean expired; + if (thread_started && g_thread_self() != window_thread) + { + gboolean expired = true; int my_last_key; + g_mutex_lock(last_key_mutex); // wait for signal or timeout if delay > 0 if(delay>0){ GTimeVal timer; @@ -1898,8 +1903,15 @@ CV_IMPL int cvWaitKey( int delay ) expired = !g_cond_timed_wait(cond_have_key, last_key_mutex, &timer); } else{ - g_cond_wait(cond_have_key, last_key_mutex); - expired=false; + if (g_windows.empty()) + { + CV_LOG_WARNING(NULL, "cv::waitKey() is called without timeout and missing active windows. Ignoring"); + } + else + { + g_cond_wait(cond_have_key, last_key_mutex); + expired=false; + } } my_last_key = last_key; g_mutex_unlock(last_key_mutex); @@ -1908,21 +1920,20 @@ CV_IMPL int cvWaitKey( int delay ) } return my_last_key; } - else{ + else #endif + { int expired = 0; guint timer = 0; if( delay > 0 ) timer = g_timeout_add( delay, icvAlarm, &expired ); last_key = -1; - while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && !g_windows.empty()) + while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && (delay > 0 || !g_windows.empty())) ; if( delay > 0 && !expired ) g_source_remove(timer); -#ifdef HAVE_GTHREAD } -#endif return last_key; } From 81325a3fa0af9748c7a62e056d3ddec2cc6f78d9 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 6 Jul 2018 17:06:01 +0300 Subject: [PATCH 20/26] highgui(gtk): use recursive cv::Mutex for 'window_mutex' variable --- modules/highgui/src/window_gtk.cpp | 64 ++++++++++++++---------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 07e683de39..5ab7de86ab 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -597,10 +597,15 @@ int thread_started=0; static gpointer icvWindowThreadLoop(gpointer data); GMutex* last_key_mutex = NULL; GCond* cond_have_key = NULL; -GMutex* window_mutex = NULL; GThread* window_thread = NULL; #endif +static cv::Mutex& getWindowMutex() +{ + static cv::Mutex* g_window_mutex = new cv::Mutex(); + return *g_window_mutex; +} + static int last_key = -1; static std::vector< Ptr > g_windows; @@ -627,28 +632,28 @@ CV_IMPL int cvInitSystem( int argc, char** argv ) CV_IMPL int cvStartWindowThread(){ #ifdef HAVE_GTHREAD cvInitSystem(0,NULL); - if (!thread_started) { - if (!g_thread_supported ()) { - /* the GThread system wasn't inited, so init it */ - g_thread_init(NULL); - } + if (!thread_started) + { + if (!g_thread_supported ()) { + /* the GThread system wasn't inited, so init it */ + g_thread_init(NULL); + } - // this mutex protects the window resources - window_mutex = g_mutex_new(); + (void)getWindowMutex(); // force mutex initialization - // protects the 'last key pressed' variable - last_key_mutex = g_mutex_new(); + // protects the 'last key pressed' variable + last_key_mutex = g_mutex_new(); - // conditional that indicates a key has been pressed - cond_have_key = g_cond_new(); + // conditional that indicates a key has been pressed + cond_have_key = g_cond_new(); -#if !GLIB_CHECK_VERSION(2, 32, 0) - // this is the window update thread - window_thread = g_thread_create(icvWindowThreadLoop, - NULL, TRUE, NULL); -#else - window_thread = g_thread_new("OpenCV window update", icvWindowThreadLoop, NULL); -#endif + #if !GLIB_CHECK_VERSION(2, 32, 0) + // this is the window update thread + window_thread = g_thread_create(icvWindowThreadLoop, + NULL, TRUE, NULL); + #else + window_thread = g_thread_new("OpenCV window update", icvWindowThreadLoop, NULL); + #endif } thread_started = window_thread!=NULL; return thread_started; @@ -661,9 +666,10 @@ CV_IMPL int cvStartWindowThread(){ gpointer icvWindowThreadLoop(gpointer /*data*/) { while(1){ - g_mutex_lock(window_mutex); - gtk_main_iteration_do(FALSE); - g_mutex_unlock(window_mutex); + { + cv::AutoLock lock(getWindowMutex()); + gtk_main_iteration_do(FALSE); + } // little sleep g_usleep(500); @@ -673,20 +679,10 @@ gpointer icvWindowThreadLoop(gpointer /*data*/) return NULL; } - -class GMutexLock { - GMutex* mutex_; -public: - GMutexLock(GMutex* mutex) : mutex_(mutex) { if (mutex_) g_mutex_lock(mutex_); } - ~GMutexLock() { if (mutex_) g_mutex_unlock(mutex_); mutex_ = NULL; } -}; - -#define CV_LOCK_MUTEX() GMutexLock lock(window_mutex); - -#else -#define CV_LOCK_MUTEX() #endif +#define CV_LOCK_MUTEX() cv::AutoLock lock(getWindowMutex()) + static CvWindow* icvFindWindowByName( const char* name ) { for(size_t i = 0; i < g_windows.size(); ++i) From e14b2ba43cf2e3cb7f454bd3d9145749281284f2 Mon Sep 17 00:00:00 2001 From: berak Date: Sat, 7 Jul 2018 16:56:40 +0200 Subject: [PATCH 21/26] objdetect: validate input in qrcode --- modules/objdetect/src/qrcode.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/objdetect/src/qrcode.cpp b/modules/objdetect/src/qrcode.cpp index f7c40a744f..e3c8d559ae 100644 --- a/modules/objdetect/src/qrcode.cpp +++ b/modules/objdetect/src/qrcode.cpp @@ -71,8 +71,11 @@ bool QRDecode::localization() Point begin, end; std::vector list_lines_x = searchVerticalLines(); + if (list_lines_x.empty()) return false; std::vector list_lines_y = separateHorizontalLines(list_lines_x); + if (list_lines_y.empty()) return false; std::vector result_point = pointClustering(list_lines_y); + if (result_point.empty()) return false; for (int i = 0; i < 3; i++) { localization_points.push_back( From 45677819e88d794f0c4416ef0cec55efbf270bfc Mon Sep 17 00:00:00 2001 From: berak Date: Sun, 8 Jul 2018 09:51:06 +0200 Subject: [PATCH 22/26] core: fix autobuffer usage in opengl.cpp --- modules/core/src/opengl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/src/opengl.cpp b/modules/core/src/opengl.cpp index 08cfb4ed90..6661b669a4 100644 --- a/modules/core/src/opengl.cpp +++ b/modules/core/src/opengl.cpp @@ -1624,12 +1624,12 @@ Context& initializeContextFromGL() if (status == CL_SUCCESS) { extensionStr.allocate(extensionSize+1); - status = clGetPlatformInfo(platforms[i], CL_PLATFORM_EXTENSIONS, extensionSize, (char*)extensionStr, NULL); + status = clGetPlatformInfo(platforms[i], CL_PLATFORM_EXTENSIONS, extensionSize, (char*)extensionStr.data(), NULL); } if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get platform extension string"); - if (!strstr((const char*)extensionStr, "cl_khr_gl_sharing")) + if (!strstr((const char*)extensionStr.data(), "cl_khr_gl_sharing")) continue; } From 362d4f53950aa385253b7f146d83dae15dcaa571 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 9 Jul 2018 14:35:54 +0300 Subject: [PATCH 23/26] Replace convertFp16 from dnn::Net::setInput() --- modules/dnn/src/dnn.cpp | 107 +++++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 34 deletions(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 080de30d21..011631f54e 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -409,8 +409,44 @@ struct LayerData struct DataLayer : public Layer { void finalize(const std::vector&, std::vector&) CV_OVERRIDE {} - void forward(std::vector&, std::vector&, std::vector &) CV_OVERRIDE {} - void forward(InputArrayOfArrays inputs, OutputArrayOfArrays outputs, OutputArrayOfArrays internals) CV_OVERRIDE {} + + void forward(InputArrayOfArrays inputs, OutputArrayOfArrays outputs, OutputArrayOfArrays internals) CV_OVERRIDE + { + CV_TRACE_FUNCTION(); + CV_TRACE_ARG_VALUE(name, "name", name.c_str()); + + CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget), + forward_ocl(inputs, outputs, internals)); + + Layer::forward_fallback(inputs, outputs, internals); + } + + void forward(std::vector&, std::vector& outputs, std::vector &) CV_OVERRIDE + { + for (int i = 0; i < inputsData.size(); ++i) + { + if (inputsData[i].type() == CV_32F && outputs[i].type() == CV_16S) + { + convertFp16(inputsData[i], outputs[i]); + } + } + } + +#ifdef HAVE_OPENCL + bool forward_ocl(InputArrayOfArrays, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_) + { + if (outputs_.depth() == CV_16S) + { + std::vector outputs; + outputs_.getUMatVector(outputs); + for (int i = 0; i < inputsData.size(); ++i) + { + convertFp16(inputsData[i], outputs[i]); + } + } + return true; + } +#endif int outputNameToIndex(const String& tgtName) CV_OVERRIDE { @@ -434,6 +470,7 @@ struct DataLayer : public Layer } std::vector outNames; + std::vector inputsData; }; struct BlobManager @@ -848,9 +885,6 @@ struct Net::Impl poolingLayer->computeMaxIdx = true; } } - it = layers.find(0); - CV_Assert(it != layers.end()); - it->second.skip = true; layersTimings.clear(); } @@ -1355,15 +1389,27 @@ struct Net::Impl allocateLayer(*i, layersShapes); //bind inputs - ld.inputBlobs.resize(ninputs); - ld.inputBlobsWrappers.resize(ninputs); - for (size_t i = 0; i < ninputs; i++) + if (ld.id == 0) // DataLayer { - LayerPin from = ld.inputBlobsId[i]; - CV_Assert(from.valid()); - CV_DbgAssert(layers.count(from.lid) && (int)layers[from.lid].outputBlobs.size() > from.oid); - ld.inputBlobs[i] = &layers[from.lid].outputBlobs[from.oid]; - ld.inputBlobsWrappers[i] = layers[from.lid].outputBlobsWrappers[from.oid]; + ninputs = netInputLayer->inputsData.size(); + ld.inputBlobsWrappers.resize(ninputs); + for (size_t i = 0; i < ninputs; i++) + { + ld.inputBlobsWrappers[i] = wrap(netInputLayer->inputsData[i]); + } + } + else + { + ld.inputBlobs.resize(ninputs); + ld.inputBlobsWrappers.resize(ninputs); + for (size_t i = 0; i < ninputs; i++) + { + LayerPin from = ld.inputBlobsId[i]; + CV_Assert(from.valid()); + CV_DbgAssert(layers.count(from.lid) && (int)layers[from.lid].outputBlobs.size() > from.oid); + ld.inputBlobs[i] = &layers[from.lid].outputBlobs[from.oid]; + ld.inputBlobsWrappers[i] = layers[from.lid].outputBlobsWrappers[from.oid]; + } } LayersShapesMap::const_iterator layerShapesIt = layersShapes.find(lid); @@ -1731,15 +1777,14 @@ struct Net::Impl ShapesVec inputShapes; for(int i = 0; i < layers[0].outputBlobs.size(); i++) { - CV_Assert(layers[0].outputBlobs[i].total()); - if (layers[0].outputBlobs[i].depth() == CV_32F && - preferableBackend == DNN_BACKEND_OPENCV && + Mat& inp = layers[0].outputBlobs[i]; + CV_Assert(inp.total()); + if (preferableBackend == DNN_BACKEND_OPENCV && preferableTarget == DNN_TARGET_OPENCL_FP16) { - Mat mat = layers[0].outputBlobs[i].clone(); - convertFp16(mat, layers[0].outputBlobs[i]); + layers[0].outputBlobs[i].create(inp.dims, inp.size, CV_16S); } - inputShapes.push_back(shape(layers[0].outputBlobs[i])); + inputShapes.push_back(shape(inp)); } LayersShapesMap layersShapes; getLayersShapes(inputShapes, layersShapes); @@ -2271,28 +2316,22 @@ void Net::setInput(InputArray blob, const String& name) CV_Error(Error::StsObjectNotFound, "Requested blob \"" + name + "\" not found"); LayerData &ld = impl->layers[pin.lid]; - ld.outputBlobs.resize( std::max(pin.oid+1, (int)ld.requiredOutputs.size()) ); - ld.outputBlobsWrappers.resize(ld.outputBlobs.size()); - MatShape prevShape = shape(ld.outputBlobs[pin.oid]); - Mat blob_; - if (impl->preferableBackend == DNN_BACKEND_OPENCV && - impl->preferableTarget == DNN_TARGET_OPENCL_FP16) - { - Mat blob_mat = blob.getMat(); - convertFp16(blob_mat, blob_); - } - else - { - blob_ = blob.getMat(); - } + const int numInputs = std::max(pin.oid+1, (int)ld.requiredOutputs.size()); + ld.outputBlobs.resize(numInputs); + ld.outputBlobsWrappers.resize(numInputs); + impl->netInputLayer->inputsData.resize(numInputs); + + MatShape prevShape = shape(impl->netInputLayer->inputsData[pin.oid]); + Mat blob_ = blob.getMat(); bool oldShape = prevShape == shape(blob_); if (oldShape) { - blob_.copyTo(ld.outputBlobs[pin.oid]); + blob_.copyTo(impl->netInputLayer->inputsData[pin.oid]); } else { ld.outputBlobs[pin.oid] = blob_.clone(); + impl->netInputLayer->inputsData[pin.oid] = ld.outputBlobs[pin.oid]; } if (!ld.outputBlobsWrappers[pin.oid].empty()) From 52b151dcebff448d052d5e8546bb2a1e87ed9e8c Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 9 Jul 2018 16:20:46 +0300 Subject: [PATCH 24/26] dnn(test): use checkMyriadTarget() in Test_Caffe_layers.Conv_Elu test --- modules/dnn/test/test_layers.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index 3d20df5346..8c3d72fb49 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -352,6 +352,12 @@ TEST_P(Test_Caffe_layers, Reshape_Split_Slice) TEST_P(Test_Caffe_layers, Conv_Elu) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + { + if (!checkMyriadTarget()) + throw SkipTestException("Myriad is not available/disabled in OpenCV"); + } + Net net = readNetFromTensorflow(_tf("layer_elu_model.pb")); ASSERT_FALSE(net.empty()); From e2b5d112909b9dfd764f14833b82e38e4bc2f81f Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 9 Jul 2018 17:19:35 +0300 Subject: [PATCH 25/26] dnn: allow to use external protobuf "custom layers" feature will not work properly in these builds. --- modules/dnn/CMakeLists.txt | 4 ++++ modules/dnn/src/caffe/caffe_io.cpp | 4 ++++ modules/dnn/test/test_layers.cpp | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt index e306dde188..a2f741cda1 100644 --- a/modules/dnn/CMakeLists.txt +++ b/modules/dnn/CMakeLists.txt @@ -48,6 +48,10 @@ if(ANDROID) add_definitions(-DDISABLE_POSIX_MEMALIGN -DTH_DISABLE_HEAP_TRACKING) endif() +if(NOT BUILD_PROTOBUF) + add_definitions(-DOPENCV_DNN_EXTERNAL_PROTOBUF=1) +endif() + add_definitions(-DHAVE_PROTOBUF=1) #suppress warnings in autogenerated caffe.pb.* files diff --git a/modules/dnn/src/caffe/caffe_io.cpp b/modules/dnn/src/caffe/caffe_io.cpp index 730c752cef..9f4e31c7b0 100644 --- a/modules/dnn/src/caffe/caffe_io.cpp +++ b/modules/dnn/src/caffe/caffe_io.cpp @@ -1120,7 +1120,11 @@ bool ReadProtoFromTextFile(const char* filename, Message* proto) { std::ifstream fs(filename, std::ifstream::in); CHECK(fs.is_open()) << "Can't open \"" << filename << "\""; IstreamInputStream input(&fs); +#ifndef OPENCV_DNN_EXTERNAL_PROTOBUF return google::protobuf::TextFormat::Parser(true).Parse(&input, proto); +#else + return google::protobuf::TextFormat::Parser().Parse(&input, proto); +#endif } bool ReadProtoFromBinaryFile(const char* filename, Message* proto) { diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index 3d20df5346..1a6aad0d62 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -1149,7 +1149,11 @@ private: int outWidth, outHeight, zoomFactor; }; +#ifndef OPENCV_DNN_EXTERNAL_PROTOBUF TEST_P(Test_Caffe_layers, Interp) +#else +TEST_P(Test_Caffe_layers, DISABLED_Interp) // requires patched protobuf (available in OpenCV source tree only) +#endif { if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) throw SkipTestException(""); From b6255ab9e797c62be0b4cdde836d4436e21decd4 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 9 Jul 2018 18:02:20 +0300 Subject: [PATCH 26/26] dnn(ocl4dnn): fix args for 'max_pool_forward' kernel --- modules/dnn/src/ocl4dnn/src/ocl4dnn_pool.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/dnn/src/ocl4dnn/src/ocl4dnn_pool.cpp b/modules/dnn/src/ocl4dnn/src/ocl4dnn_pool.cpp index b74bf4d8e8..8b74248b64 100644 --- a/modules/dnn/src/ocl4dnn/src/ocl4dnn_pool.cpp +++ b/modules/dnn/src/ocl4dnn/src/ocl4dnn_pool.cpp @@ -132,9 +132,10 @@ bool OCL4DNNPool::Forward(const UMat& bottom, width_, pooled_height_, pooled_width_, - ocl::KernelArg::PtrWriteOnly(top), - ocl::KernelArg::PtrWriteOnly(top_mask) + ocl::KernelArg::PtrWriteOnly(top) ); + if (computeMaxIdx) + oclk_max_pool_forward.set(8, ocl::KernelArg::PtrWriteOnly(top_mask)); // TODO remove magic number. Extend cv::ocl::Kernel API ret = oclk_max_pool_forward.run(1, global, local, false); }