diff --git a/3rdparty/quirc/include/quirc_internal.h b/3rdparty/quirc/include/quirc_internal.h index 56f5d28bfa..21cd5610f5 100644 --- a/3rdparty/quirc/include/quirc_internal.h +++ b/3rdparty/quirc/include/quirc_internal.h @@ -32,8 +32,10 @@ #define QUIRC_PERSPECTIVE_PARAMS 8 #if QUIRC_MAX_REGIONS < UINT8_MAX +#define QUIRC_PIXEL_ALIAS_IMAGE 1 typedef uint8_t quirc_pixel_t; #elif QUIRC_MAX_REGIONS < UINT16_MAX +#define QUIRC_PIXEL_ALIAS_IMAGE 0 typedef uint16_t quirc_pixel_t; #else #error "QUIRC_MAX_REGIONS > 65534 is not supported" @@ -77,7 +79,6 @@ struct quirc_grid { struct quirc { uint8_t *image; quirc_pixel_t *pixels; - int *row_average; /* used by threshold() */ int w; int h; diff --git a/3rdparty/quirc/src/decode.c b/3rdparty/quirc/src/decode.c index f556097b65..894b5067d8 100644 --- a/3rdparty/quirc/src/decode.c +++ b/3rdparty/quirc/src/decode.c @@ -874,7 +874,7 @@ static quirc_decode_error_t decode_payload(struct quirc_data *data, done: /* Add nul terminator to all payloads */ - if ((unsigned)data->payload_len >= sizeof(data->payload)) + if (data->payload_len >= (int) sizeof(data->payload)) data->payload_len--; data->payload[data->payload_len] = 0; diff --git a/3rdparty/quirc/src/quirc.c b/3rdparty/quirc/src/quirc.c index a1418b2b26..2499f8df7e 100644 --- a/3rdparty/quirc/src/quirc.c +++ b/3rdparty/quirc/src/quirc.c @@ -27,10 +27,7 @@ struct quirc *quirc_new(void) { struct quirc *q = malloc(sizeof(*q)); - if (!q) - return NULL; - - memset(q, 0, sizeof(*q)); + memset(q, 0, sizeof(*q)); return q; } @@ -39,9 +36,8 @@ void quirc_destroy(struct quirc *q) free(q->image); /* q->pixels may alias q->image when their type representation is of the same size, so we need to be careful here to avoid a double free */ - if (sizeof(*q->image) != sizeof(*q->pixels)) + if (!QUIRC_PIXEL_ALIAS_IMAGE) free(q->pixels); - free(q->row_average); free(q); } @@ -49,7 +45,6 @@ int quirc_resize(struct quirc *q, int w, int h) { uint8_t *image = NULL; quirc_pixel_t *pixels = NULL; - int *row_average = NULL; /* * XXX: w and h should be size_t (or at least unsigned) as negatives @@ -82,35 +77,27 @@ int quirc_resize(struct quirc *q, int w, int h) (void)memcpy(image, q->image, min); /* alloc a new buffer for q->pixels if needed */ - if (sizeof(*q->image) != sizeof(*q->pixels)) { + if (!QUIRC_PIXEL_ALIAS_IMAGE) { pixels = calloc(newdim, sizeof(quirc_pixel_t)); if (!pixels) goto fail; } - /* alloc a new buffer for q->row_average */ - row_average = calloc(w, sizeof(int)); - if (!row_average) - goto fail; - /* alloc succeeded, update `q` with the new size and buffers */ q->w = w; q->h = h; free(q->image); q->image = image; - if (sizeof(*q->image) != sizeof(*q->pixels)) { + if (!QUIRC_PIXEL_ALIAS_IMAGE) { free(q->pixels); q->pixels = pixels; } - free(q->row_average); - q->row_average = row_average; return 0; /* NOTREACHED */ fail: free(image); free(pixels); - free(row_average); return -1; } @@ -133,6 +120,10 @@ static const char *const error_table[] = { const char *quirc_strerror(quirc_decode_error_t err) { - if ((int)err < 8) { return error_table[err]; } - else { return "Unknown error"; } + if ((int) err >= 0) { + if ((unsigned long) err < (unsigned long) (sizeof(error_table) / sizeof(error_table[0]))) + return error_table[err]; + } + + return "Unknown error"; } diff --git a/3rdparty/quirc/src/version_db.c b/3rdparty/quirc/src/version_db.c index 9c77e63d47..4242aee298 100644 --- a/3rdparty/quirc/src/version_db.c +++ b/3rdparty/quirc/src/version_db.c @@ -17,16 +17,7 @@ #include const struct quirc_version_info quirc_version_db[QUIRC_MAX_VERSION + 1] = { - { /* 0 */ - .data_bytes = 0, - .apat = {0}, - .ecc = { - {.bs = 0, .dw = 0, .ns = 0}, - {.bs = 0, .dw = 0, .ns = 0}, - {.bs = 0, .dw = 0, .ns = 0}, - {.bs = 0, .dw = 0, .ns = 0} - } - }, + {0}, { /* Version 1 */ .data_bytes = 26, .apat = {0}, diff --git a/doc/tutorials/calib3d/camera_calibration/camera_calibration.markdown b/doc/tutorials/calib3d/camera_calibration/camera_calibration.markdown index 85515d99bb..e30642f702 100644 --- a/doc/tutorials/calib3d/camera_calibration/camera_calibration.markdown +++ b/doc/tutorials/calib3d/camera_calibration/camera_calibration.markdown @@ -1,6 +1,10 @@ Camera calibration With OpenCV {#tutorial_camera_calibration} ============================== +@prev_tutorial{tutorial_camera_calibration_square_chess} +@next_tutorial{tutorial_real_time_pose} + + Cameras have been around for a long-long time. However, with the introduction of the cheap *pinhole* cameras in the late 20th century, they became a common occurrence in our everyday life. Unfortunately, this cheapness comes with its price: significant distortion. Luckily, these are diff --git a/doc/tutorials/calib3d/camera_calibration_pattern/camera_calibration_pattern.markdown b/doc/tutorials/calib3d/camera_calibration_pattern/camera_calibration_pattern.markdown index 80c63cb157..d6df8a8b5e 100644 --- a/doc/tutorials/calib3d/camera_calibration_pattern/camera_calibration_pattern.markdown +++ b/doc/tutorials/calib3d/camera_calibration_pattern/camera_calibration_pattern.markdown @@ -1,6 +1,9 @@ Create calibration pattern {#tutorial_camera_calibration_pattern} ========================================= +@next_tutorial{tutorial_camera_calibration_square_chess} + + The goal of this tutorial is to learn how to create calibration pattern. You can find a chessboard pattern in https://github.com/opencv/opencv/blob/master/doc/pattern.png diff --git a/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.markdown b/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.markdown index bf1eadca1f..51b0a5eac7 100644 --- a/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.markdown +++ b/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.markdown @@ -1,6 +1,10 @@ Camera calibration with square chessboard {#tutorial_camera_calibration_square_chess} ========================================= +@prev_tutorial{tutorial_camera_calibration_pattern} +@next_tutorial{tutorial_camera_calibration} + + The goal of this tutorial is to learn how to calibrate a camera given a set of chessboard images. *Test data*: use images in your data/chess folder. diff --git a/doc/tutorials/calib3d/interactive_calibration/interactive_calibration.markdown b/doc/tutorials/calib3d/interactive_calibration/interactive_calibration.markdown index 8280262cdd..36e19e0754 100644 --- a/doc/tutorials/calib3d/interactive_calibration/interactive_calibration.markdown +++ b/doc/tutorials/calib3d/interactive_calibration/interactive_calibration.markdown @@ -1,6 +1,9 @@ Interactive camera calibration application {#tutorial_interactive_calibration} ============================== +@prev_tutorial{tutorial_real_time_pose} + + According to classical calibration technique user must collect all data first and when run @ref cv::calibrateCamera function to obtain camera parameters. If average re-projection error is huge or if estimated parameters seems to be wrong, process of selection or collecting data and starting of @ref cv::calibrateCamera repeats. diff --git a/doc/tutorials/calib3d/real_time_pose/real_time_pose.markdown b/doc/tutorials/calib3d/real_time_pose/real_time_pose.markdown index f61fa7a8b4..98a44b232b 100644 --- a/doc/tutorials/calib3d/real_time_pose/real_time_pose.markdown +++ b/doc/tutorials/calib3d/real_time_pose/real_time_pose.markdown @@ -1,6 +1,10 @@ Real Time pose estimation of a textured object {#tutorial_real_time_pose} ============================================== +@prev_tutorial{tutorial_camera_calibration} +@next_tutorial{tutorial_interactive_calibration} + + Nowadays, augmented reality is one of the top research topic in computer vision and robotics fields. The most elemental problem in augmented reality is the estimation of the camera pose respect of an object in the case of computer vision area to do later some 3D rendering or in the case of robotics diff --git a/doc/tutorials/dnn/dnn_android/dnn_android.markdown b/doc/tutorials/dnn/dnn_android/dnn_android.markdown index 5de2c0fa0d..86ed81cf48 100644 --- a/doc/tutorials/dnn/dnn_android/dnn_android.markdown +++ b/doc/tutorials/dnn/dnn_android/dnn_android.markdown @@ -1,5 +1,8 @@ # How to run deep networks on Android device {#tutorial_dnn_android} +@prev_tutorial{tutorial_dnn_halide_scheduling} +@next_tutorial{tutorial_dnn_yolo} + ## Introduction In this tutorial you'll know how to run deep learning networks on Android device using OpenCV deep learning module. diff --git a/doc/tutorials/dnn/dnn_custom_layers/dnn_custom_layers.md b/doc/tutorials/dnn/dnn_custom_layers/dnn_custom_layers.md index f367946620..c0cd4a3a99 100644 --- a/doc/tutorials/dnn/dnn_custom_layers/dnn_custom_layers.md +++ b/doc/tutorials/dnn/dnn_custom_layers/dnn_custom_layers.md @@ -1,5 +1,7 @@ # Custom deep learning layers support {#tutorial_dnn_custom_layers} +@prev_tutorial{tutorial_dnn_javascript} + ## Introduction Deep learning is a fast growing area. The new approaches to build neural networks usually introduce new types of layers. They could be modifications of existing diff --git a/doc/tutorials/dnn/dnn_googlenet/dnn_googlenet.markdown b/doc/tutorials/dnn/dnn_googlenet/dnn_googlenet.markdown index aadb251644..f6040dce1c 100644 --- a/doc/tutorials/dnn/dnn_googlenet/dnn_googlenet.markdown +++ b/doc/tutorials/dnn/dnn_googlenet/dnn_googlenet.markdown @@ -1,6 +1,8 @@ Load Caffe framework models {#tutorial_dnn_googlenet} =========================== +@next_tutorial{tutorial_dnn_halide} + Introduction ------------ diff --git a/doc/tutorials/dnn/dnn_halide/dnn_halide.markdown b/doc/tutorials/dnn/dnn_halide/dnn_halide.markdown index fe82f05816..0500d25150 100644 --- a/doc/tutorials/dnn/dnn_halide/dnn_halide.markdown +++ b/doc/tutorials/dnn/dnn_halide/dnn_halide.markdown @@ -1,5 +1,8 @@ # How to enable Halide backend for improve efficiency {#tutorial_dnn_halide} +@prev_tutorial{tutorial_dnn_googlenet} +@next_tutorial{tutorial_dnn_halide_scheduling} + ## Introduction This tutorial guidelines how to run your models in OpenCV deep learning module using Halide language backend. Halide is an open-source project that let us diff --git a/doc/tutorials/dnn/dnn_halide_scheduling/dnn_halide_scheduling.markdown b/doc/tutorials/dnn/dnn_halide_scheduling/dnn_halide_scheduling.markdown index a43ab63e05..b825da7922 100644 --- a/doc/tutorials/dnn/dnn_halide_scheduling/dnn_halide_scheduling.markdown +++ b/doc/tutorials/dnn/dnn_halide_scheduling/dnn_halide_scheduling.markdown @@ -1,5 +1,8 @@ # How to schedule your network for Halide backend {#tutorial_dnn_halide_scheduling} +@prev_tutorial{tutorial_dnn_halide} +@next_tutorial{tutorial_dnn_android} + ## Introduction Halide code is the same for every device we use. But for achieving the satisfied efficiency we should schedule computations properly. In this tutorial we describe diff --git a/doc/tutorials/dnn/dnn_javascript/dnn_javascript.markdown b/doc/tutorials/dnn/dnn_javascript/dnn_javascript.markdown index 0a9caeae35..9ad632fbc8 100644 --- a/doc/tutorials/dnn/dnn_javascript/dnn_javascript.markdown +++ b/doc/tutorials/dnn/dnn_javascript/dnn_javascript.markdown @@ -1,5 +1,8 @@ # How to run deep networks in browser {#tutorial_dnn_javascript} +@prev_tutorial{tutorial_dnn_yolo} +@next_tutorial{tutorial_dnn_custom_layers} + ## Introduction This tutorial will show us how to run deep learning models using OpenCV.js right in a browser. Tutorial refers a sample of face detection and face recognition diff --git a/doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown b/doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown index 968b3faaca..1552d4e654 100644 --- a/doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown +++ b/doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown @@ -1,6 +1,9 @@ YOLO DNNs {#tutorial_dnn_yolo} =============================== +@prev_tutorial{tutorial_dnn_android} +@next_tutorial{tutorial_dnn_javascript} + Introduction ------------ diff --git a/doc/tutorials/features2d/akaze_matching/akaze_matching.markdown b/doc/tutorials/features2d/akaze_matching/akaze_matching.markdown index b2350f84c4..0635dfc4f6 100644 --- a/doc/tutorials/features2d/akaze_matching/akaze_matching.markdown +++ b/doc/tutorials/features2d/akaze_matching/akaze_matching.markdown @@ -1,6 +1,9 @@ AKAZE local features matching {#tutorial_akaze_matching} ============================= +@prev_tutorial{tutorial_detection_of_planar_objects} +@next_tutorial{tutorial_akaze_tracking} + Introduction ------------ diff --git a/doc/tutorials/features2d/akaze_tracking/akaze_tracking.markdown b/doc/tutorials/features2d/akaze_tracking/akaze_tracking.markdown index 518cada76a..58071ffd42 100644 --- a/doc/tutorials/features2d/akaze_tracking/akaze_tracking.markdown +++ b/doc/tutorials/features2d/akaze_tracking/akaze_tracking.markdown @@ -1,6 +1,9 @@ AKAZE and ORB planar tracking {#tutorial_akaze_tracking} ============================= +@prev_tutorial{tutorial_akaze_matching} +@next_tutorial{tutorial_homography} + Introduction ------------ diff --git a/doc/tutorials/features2d/detection_of_planar_objects/detection_of_planar_objects.markdown b/doc/tutorials/features2d/detection_of_planar_objects/detection_of_planar_objects.markdown index 4112b18738..9febdb7acd 100644 --- a/doc/tutorials/features2d/detection_of_planar_objects/detection_of_planar_objects.markdown +++ b/doc/tutorials/features2d/detection_of_planar_objects/detection_of_planar_objects.markdown @@ -1,6 +1,10 @@ Detection of planar objects {#tutorial_detection_of_planar_objects} =========================== +@prev_tutorial{tutorial_feature_homography} +@next_tutorial{tutorial_akaze_matching} + + The goal of this tutorial is to learn how to use *features2d* and *calib3d* modules for detecting known planar objects in scenes. diff --git a/doc/tutorials/features2d/feature_description/feature_description.markdown b/doc/tutorials/features2d/feature_description/feature_description.markdown index ec3cd0e4c5..70a30096f5 100644 --- a/doc/tutorials/features2d/feature_description/feature_description.markdown +++ b/doc/tutorials/features2d/feature_description/feature_description.markdown @@ -1,6 +1,9 @@ Feature Description {#tutorial_feature_description} =================== +@prev_tutorial{tutorial_feature_detection} +@next_tutorial{tutorial_feature_flann_matcher} + Goal ---- diff --git a/doc/tutorials/features2d/feature_detection/feature_detection.markdown b/doc/tutorials/features2d/feature_detection/feature_detection.markdown index d0996512ef..a22ef90520 100644 --- a/doc/tutorials/features2d/feature_detection/feature_detection.markdown +++ b/doc/tutorials/features2d/feature_detection/feature_detection.markdown @@ -1,6 +1,9 @@ Feature Detection {#tutorial_feature_detection} ================= +@prev_tutorial{tutorial_corner_subpixels} +@next_tutorial{tutorial_feature_description} + Goal ---- diff --git a/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown b/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown index cb05f3dd48..2e5f12c922 100644 --- a/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown +++ b/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown @@ -1,6 +1,9 @@ Feature Matching with FLANN {#tutorial_feature_flann_matcher} =========================== +@prev_tutorial{tutorial_feature_description} +@next_tutorial{tutorial_feature_homography} + Goal ---- diff --git a/doc/tutorials/features2d/feature_homography/feature_homography.markdown b/doc/tutorials/features2d/feature_homography/feature_homography.markdown index c4f0c00e55..b2d23435eb 100644 --- a/doc/tutorials/features2d/feature_homography/feature_homography.markdown +++ b/doc/tutorials/features2d/feature_homography/feature_homography.markdown @@ -1,6 +1,9 @@ Features2D + Homography to find a known object {#tutorial_feature_homography} ============================================== +@prev_tutorial{tutorial_feature_flann_matcher} +@next_tutorial{tutorial_detection_of_planar_objects} + Goal ---- diff --git a/doc/tutorials/features2d/homography/homography.markdown b/doc/tutorials/features2d/homography/homography.markdown index b8af35d60f..960511dd3d 100644 --- a/doc/tutorials/features2d/homography/homography.markdown +++ b/doc/tutorials/features2d/homography/homography.markdown @@ -1,6 +1,8 @@ Basic concepts of the homography explained with code {#tutorial_homography} ==================================================== +@prev_tutorial{tutorial_akaze_tracking} + @tableofcontents Introduction {#tutorial_homography_Introduction} diff --git a/doc/tutorials/features2d/trackingmotion/corner_subpixels/corner_subpixels.markdown b/doc/tutorials/features2d/trackingmotion/corner_subpixels/corner_subpixels.markdown index 82b33dd256..a9316b732d 100644 --- a/doc/tutorials/features2d/trackingmotion/corner_subpixels/corner_subpixels.markdown +++ b/doc/tutorials/features2d/trackingmotion/corner_subpixels/corner_subpixels.markdown @@ -1,6 +1,9 @@ Detecting corners location in subpixels {#tutorial_corner_subpixels} ======================================= +@prev_tutorial{tutorial_generic_corner_detector} +@next_tutorial{tutorial_feature_detection} + Goal ---- diff --git a/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown b/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown index f10d3efe4e..6082b9b91d 100644 --- a/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown +++ b/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown @@ -1,6 +1,10 @@ Creating your own corner detector {#tutorial_generic_corner_detector} ================================= +@prev_tutorial{tutorial_good_features_to_track} +@next_tutorial{tutorial_corner_subpixels} + + Goal ---- diff --git a/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown b/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown index 70d25ab9e2..7e8cf1157e 100644 --- a/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown +++ b/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown @@ -1,6 +1,9 @@ Shi-Tomasi corner detector {#tutorial_good_features_to_track} ========================== +@prev_tutorial{tutorial_harris_detector} +@next_tutorial{tutorial_generic_corner_detector} + Goal ---- diff --git a/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown b/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown index bbf4fdbd5b..f0b32683ce 100644 --- a/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown +++ b/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown @@ -1,6 +1,8 @@ Harris corner detector {#tutorial_harris_detector} ====================== +@next_tutorial{tutorial_good_features_to_track} + Goal ---- diff --git a/doc/tutorials/gpu/gpu-basics-similarity/gpu_basics_similarity.markdown b/doc/tutorials/gpu/gpu-basics-similarity/gpu_basics_similarity.markdown index d8f71de212..74840efbc2 100644 --- a/doc/tutorials/gpu/gpu-basics-similarity/gpu_basics_similarity.markdown +++ b/doc/tutorials/gpu/gpu-basics-similarity/gpu_basics_similarity.markdown @@ -3,6 +3,8 @@ Similarity check (PNSR and SSIM) on the GPU {#tutorial_gpu_basics_similarity} =========================================== @todo update this tutorial +@next_tutorial{tutorial_gpu_thrust_interop} + Goal ---- diff --git a/doc/tutorials/gpu/gpu-thrust-interop/gpu_thrust_interop.markdown b/doc/tutorials/gpu/gpu-thrust-interop/gpu_thrust_interop.markdown index 9e47f095b5..c930f883a3 100644 --- a/doc/tutorials/gpu/gpu-thrust-interop/gpu_thrust_interop.markdown +++ b/doc/tutorials/gpu/gpu-thrust-interop/gpu_thrust_interop.markdown @@ -2,6 +2,8 @@ Using a cv::cuda::GpuMat with thrust {#tutorial_gpu_thrust_interop} =========================================== +@prev_tutorial{tutorial_gpu_basics_similarity} + Goal ---- diff --git a/doc/tutorials/introduction/android_binary_package/O4A_SDK.markdown b/doc/tutorials/introduction/android_binary_package/O4A_SDK.markdown index 219bc86b21..f1216c0948 100644 --- a/doc/tutorials/introduction/android_binary_package/O4A_SDK.markdown +++ b/doc/tutorials/introduction/android_binary_package/O4A_SDK.markdown @@ -1,6 +1,10 @@ OpenCV4Android SDK {#tutorial_O4A_SDK} ================== +@prev_tutorial{tutorial_android_dev_intro} +@next_tutorial{tutorial_dev_with_OCV_on_Android} + + This tutorial was designed to help you with installation and configuration of OpenCV4Android SDK. This guide was written with MS Windows 7 in mind, though it should work with GNU Linux and Apple Mac diff --git a/doc/tutorials/introduction/android_binary_package/android_dev_intro.markdown b/doc/tutorials/introduction/android_binary_package/android_dev_intro.markdown index a614081926..9b6ba5a929 100644 --- a/doc/tutorials/introduction/android_binary_package/android_dev_intro.markdown +++ b/doc/tutorials/introduction/android_binary_package/android_dev_intro.markdown @@ -1,6 +1,10 @@ Introduction into Android Development {#tutorial_android_dev_intro} ===================================== +@prev_tutorial{tutorial_clojure_dev_intro} +@next_tutorial{tutorial_O4A_SDK} + + This guide was designed to help you in learning Android development basics and setting up your working environment quickly. It was written with Windows 7 in mind, though it would work with Linux (Ubuntu), Mac OS X and any other OS supported by Android SDK. diff --git a/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown b/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown index b41f91b241..70ce3130be 100644 --- a/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown +++ b/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown @@ -1,6 +1,10 @@ Use OpenCL in Android camera preview based CV application {#tutorial_android_ocl_intro} ===================================== +@prev_tutorial{tutorial_dev_with_OCV_on_Android} +@next_tutorial{tutorial_macos_install} + + This guide was designed to help you in use of [OpenCL ™](https://www.khronos.org/opencl/) in Android camera preview based CV application. It was written for [Eclipse-based ADT tools](http://developer.android.com/tools/help/adt.html) (deprecated by Google now), but it easily can be reproduced with [Android Studio](http://developer.android.com/tools/studio/index.html). diff --git a/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.markdown b/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.markdown index cd24514f26..6f9e6bdb90 100644 --- a/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.markdown +++ b/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.markdown @@ -1,6 +1,10 @@ Android Development with OpenCV {#tutorial_dev_with_OCV_on_Android} =============================== +@prev_tutorial{tutorial_O4A_SDK} +@next_tutorial{tutorial_android_ocl_intro} + + This tutorial has been created to help you use OpenCV library within your Android project. This guide was written with Windows 7 in mind, though it should work with any other OS supported by diff --git a/doc/tutorials/introduction/building_tegra_cuda/building_tegra_cuda.markdown b/doc/tutorials/introduction/building_tegra_cuda/building_tegra_cuda.markdown index fcee70c3c1..983d012aef 100644 --- a/doc/tutorials/introduction/building_tegra_cuda/building_tegra_cuda.markdown +++ b/doc/tutorials/introduction/building_tegra_cuda/building_tegra_cuda.markdown @@ -1,6 +1,10 @@ Building OpenCV for Tegra with CUDA {#tutorial_building_tegra_cuda} =================================== +@prev_tutorial{tutorial_arm_crosscompile_with_cmake} +@next_tutorial{tutorial_display_image} + + @tableofcontents OpenCV with CUDA for Tegra diff --git a/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.markdown b/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.markdown index f8b121cc72..dc1bd32022 100644 --- a/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.markdown +++ b/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.markdown @@ -1,6 +1,10 @@ Introduction to OpenCV Development with Clojure {#tutorial_clojure_dev_intro} =============================================== +@prev_tutorial{tutorial_java_eclipse} +@next_tutorial{tutorial_android_dev_intro} + + As of OpenCV 2.4.4, OpenCV supports desktop Java development using nearly the same interface as for Android development. diff --git a/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown b/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown index 7a52fe12bf..e2d7d27afa 100644 --- a/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown +++ b/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown @@ -1,6 +1,9 @@ Cross referencing OpenCV from other Doxygen projects {#tutorial_cross_referencing} ==================================================== +@prev_tutorial{tutorial_transition_guide} + + Cross referencing OpenCV ------------------------ diff --git a/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.markdown b/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.markdown index 3ef08f8a39..8d9c666b3d 100644 --- a/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.markdown +++ b/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.markdown @@ -1,6 +1,10 @@ Cross compilation for ARM based Linux systems {#tutorial_arm_crosscompile_with_cmake} ============================================= +@prev_tutorial{tutorial_ios_install} +@next_tutorial{tutorial_building_tegra_cuda} + + This steps are tested on Ubuntu Linux 12.04, but should work for other Linux distributions. I case of other distributions package names and names of cross compilation tools may differ. There are several popular EABI versions that are used on ARM platform. This tutorial is written for *gnueabi* diff --git a/doc/tutorials/introduction/desktop_java/java_dev_intro.markdown b/doc/tutorials/introduction/desktop_java/java_dev_intro.markdown index c6e8c06f7c..8511304f93 100644 --- a/doc/tutorials/introduction/desktop_java/java_dev_intro.markdown +++ b/doc/tutorials/introduction/desktop_java/java_dev_intro.markdown @@ -1,6 +1,10 @@ Introduction to Java Development {#tutorial_java_dev_intro} ================================ +@prev_tutorial{tutorial_windows_visual_studio_image_watch} +@next_tutorial{tutorial_java_eclipse} + + As of OpenCV 2.4.4, OpenCV supports desktop Java development using nearly the same interface as for Android development. This guide will help you to create your first Java (or Scala) application using OpenCV. We will use either [Apache Ant](http://ant.apache.org/) or [Simple Build Tool diff --git a/doc/tutorials/introduction/display_image/display_image.markdown b/doc/tutorials/introduction/display_image/display_image.markdown index 72635a3229..18e5e90bf6 100644 --- a/doc/tutorials/introduction/display_image/display_image.markdown +++ b/doc/tutorials/introduction/display_image/display_image.markdown @@ -1,6 +1,9 @@ Getting Started with Images {#tutorial_display_image} =========================== +@prev_tutorial{tutorial_building_tegra_cuda} +@next_tutorial{tutorial_documentation} + Goal ---- diff --git a/doc/tutorials/introduction/documenting_opencv/documentation_tutorial.markdown b/doc/tutorials/introduction/documenting_opencv/documentation_tutorial.markdown index 058f392afe..6b9a14b0ab 100644 --- a/doc/tutorials/introduction/documenting_opencv/documentation_tutorial.markdown +++ b/doc/tutorials/introduction/documenting_opencv/documentation_tutorial.markdown @@ -1,6 +1,10 @@ Writing documentation for OpenCV {#tutorial_documentation} ================================ +@prev_tutorial{tutorial_display_image} +@next_tutorial{tutorial_transition_guide} + + @tableofcontents Doxygen overview {#tutorial_documentation_overview} @@ -47,6 +51,9 @@ Generate documentation {#tutorial_documentation_generate} @code{.sh} make check_pylint @endcode +@note [Pylint](https://www.pylint.org/#install) must be installed before running cmake to be +able to test Python code. You can install using your system's package manager, or with pip: +@code{.sh} pip install pylint @endcode Quick start {#tutorial_documentation_quick_start} =========== diff --git a/doc/tutorials/introduction/ios_install/ios_install.markdown b/doc/tutorials/introduction/ios_install/ios_install.markdown index 1aaec1fd2d..f893c7ff83 100644 --- a/doc/tutorials/introduction/ios_install/ios_install.markdown +++ b/doc/tutorials/introduction/ios_install/ios_install.markdown @@ -1,6 +1,9 @@ Installation in iOS {#tutorial_ios_install} =================== +@prev_tutorial{tutorial_macos_install} +@next_tutorial{tutorial_arm_crosscompile_with_cmake} + Required Packages ----------------- diff --git a/doc/tutorials/introduction/java_eclipse/java_eclipse.markdown b/doc/tutorials/introduction/java_eclipse/java_eclipse.markdown index ed1f527217..f9ef84f740 100644 --- a/doc/tutorials/introduction/java_eclipse/java_eclipse.markdown +++ b/doc/tutorials/introduction/java_eclipse/java_eclipse.markdown @@ -1,6 +1,10 @@ Using OpenCV Java with Eclipse {#tutorial_java_eclipse} ============================== +@prev_tutorial{tutorial_java_dev_intro} +@next_tutorial{tutorial_clojure_dev_intro} + + Since version 2.4.4 [OpenCV supports Java](http://opencv.org/opencv-java-api.html). In this tutorial I will explain how to setup development environment for using OpenCV Java with Eclipse in **Windows**, so you can enjoy the benefits of garbage collected, very refactorable (rename variable, diff --git a/doc/tutorials/introduction/linux_eclipse/linux_eclipse.markdown b/doc/tutorials/introduction/linux_eclipse/linux_eclipse.markdown index 4aca7ee260..66ca510efb 100644 --- a/doc/tutorials/introduction/linux_eclipse/linux_eclipse.markdown +++ b/doc/tutorials/introduction/linux_eclipse/linux_eclipse.markdown @@ -1,6 +1,9 @@ Using OpenCV with Eclipse (plugin CDT) {#tutorial_linux_eclipse} ====================================== +@prev_tutorial{tutorial_linux_gcc_cmake} +@next_tutorial{tutorial_windows_install} + Prerequisites ------------- Two ways, one by forming a project directly, and another by CMake Prerequisites diff --git a/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.markdown b/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.markdown index fd447307a7..0f4d1c8cce 100644 --- a/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.markdown +++ b/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.markdown @@ -1,6 +1,10 @@ Using OpenCV with gcc and CMake {#tutorial_linux_gcc_cmake} =============================== +@prev_tutorial{tutorial_linux_install} +@next_tutorial{tutorial_linux_eclipse} + + @note We assume that you have successfully installed OpenCV in your workstation. - The easiest way of using OpenCV in your code is to use [CMake](http://www.cmake.org/). A few diff --git a/doc/tutorials/introduction/linux_install/linux_install.markdown b/doc/tutorials/introduction/linux_install/linux_install.markdown index b5dff7fede..4911cd65f4 100644 --- a/doc/tutorials/introduction/linux_install/linux_install.markdown +++ b/doc/tutorials/introduction/linux_install/linux_install.markdown @@ -1,6 +1,9 @@ Installation in Linux {#tutorial_linux_install} ===================== +@next_tutorial{tutorial_linux_gcc_cmake} + + The following steps have been tested for Ubuntu 10.04 but should work with other distros as well. Required Packages diff --git a/doc/tutorials/introduction/macos_install/macos_install.markdown b/doc/tutorials/introduction/macos_install/macos_install.markdown index 016e32ae5d..8321897a15 100644 --- a/doc/tutorials/introduction/macos_install/macos_install.markdown +++ b/doc/tutorials/introduction/macos_install/macos_install.markdown @@ -1,6 +1,10 @@ Installation in MacOS {#tutorial_macos_install} ===================== +@prev_tutorial{tutorial_android_ocl_intro} +@next_tutorial{tutorial_ios_install} + + The following steps have been tested for MacOSX (Mavericks) but should work with other versions as well. Required Packages @@ -35,6 +39,8 @@ Installing CMake cmake --version @endcode +@note You can use [Homebrew](https://brew.sh/) to install CMake with @code{.bash} brew install cmake @endcode + Getting OpenCV Source Code -------------------------- diff --git a/doc/tutorials/introduction/transition_guide/transition_guide.markdown b/doc/tutorials/introduction/transition_guide/transition_guide.markdown index 2151e7b2d4..8dda4c8ac3 100644 --- a/doc/tutorials/introduction/transition_guide/transition_guide.markdown +++ b/doc/tutorials/introduction/transition_guide/transition_guide.markdown @@ -1,6 +1,10 @@ Transition guide {#tutorial_transition_guide} ================ +@prev_tutorial{tutorial_documentation} +@next_tutorial{tutorial_cross_referencing} + + @tableofcontents Changes overview {#tutorial_transition_overview} diff --git a/doc/tutorials/introduction/windows_install/windows_install.markdown b/doc/tutorials/introduction/windows_install/windows_install.markdown index b30085cbbd..8eca5293a9 100644 --- a/doc/tutorials/introduction/windows_install/windows_install.markdown +++ b/doc/tutorials/introduction/windows_install/windows_install.markdown @@ -1,6 +1,10 @@ Installation in Windows {#tutorial_windows_install} ======================= +@prev_tutorial{tutorial_linux_eclipse} +@next_tutorial{tutorial_windows_visual_studio_opencv} + + The description here was tested on Windows 7 SP1. Nevertheless, it should also work on any other relatively modern version of Windows OS. If you encounter errors after following the steps described below, feel free to contact us via our [OpenCV Q&A forum](http://answers.opencv.org). We'll do our diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.markdown b/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.markdown index 8bc2b32fff..770a9c3479 100644 --- a/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.markdown +++ b/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.markdown @@ -1,6 +1,10 @@ Image Watch: viewing in-memory images in the Visual Studio debugger {#tutorial_windows_visual_studio_image_watch} =================================================================== +@prev_tutorial{tutorial_windows_visual_studio_opencv} +@next_tutorial{tutorial_java_dev_intro} + + Image Watch is a plug-in for Microsoft Visual Studio that lets you to visualize in-memory images (*cv::Mat* or *IplImage_* objects, for example) while debugging an application. This can be helpful for tracking down bugs, or for simply understanding what a given piece of code is doing. diff --git a/doc/tutorials/introduction/windows_visual_studio_opencv/windows_visual_studio_opencv.markdown b/doc/tutorials/introduction/windows_visual_studio_opencv/windows_visual_studio_opencv.markdown index e8ef112b02..6f8aa2477c 100644 --- a/doc/tutorials/introduction/windows_visual_studio_opencv/windows_visual_studio_opencv.markdown +++ b/doc/tutorials/introduction/windows_visual_studio_opencv/windows_visual_studio_opencv.markdown @@ -1,6 +1,10 @@ How to build applications with OpenCV inside the "Microsoft Visual Studio" {#tutorial_windows_visual_studio_opencv} ========================================================================== +@prev_tutorial{tutorial_windows_install} +@next_tutorial{tutorial_windows_visual_studio_image_watch} + + Everything I describe here will apply to the `C\C++` interface of OpenCV. I start out from the assumption that you have read and completed with success the @ref tutorial_windows_install tutorial. Therefore, before you go any further make sure you have an OpenCV directory that contains the OpenCV diff --git a/doc/tutorials/ios/hello/hello.markdown b/doc/tutorials/ios/hello/hello.markdown index 44f14adb12..fc6992cc70 100644 --- a/doc/tutorials/ios/hello/hello.markdown +++ b/doc/tutorials/ios/hello/hello.markdown @@ -1,6 +1,8 @@ OpenCV iOS Hello {#tutorial_hello} ================ +@next_tutorial{tutorial_image_manipulation} + Goal ---- diff --git a/doc/tutorials/ios/image_manipulation/image_manipulation.markdown b/doc/tutorials/ios/image_manipulation/image_manipulation.markdown index 42fefa5ae9..61590d8f77 100644 --- a/doc/tutorials/ios/image_manipulation/image_manipulation.markdown +++ b/doc/tutorials/ios/image_manipulation/image_manipulation.markdown @@ -1,6 +1,9 @@ OpenCV iOS - Image Processing {#tutorial_image_manipulation} ============================= +@prev_tutorial{tutorial_hello} +@next_tutorial{tutorial_video_processing} + Goal ---- diff --git a/doc/tutorials/ios/video_processing/video_processing.markdown b/doc/tutorials/ios/video_processing/video_processing.markdown index 43b0b96338..04bdd14e89 100644 --- a/doc/tutorials/ios/video_processing/video_processing.markdown +++ b/doc/tutorials/ios/video_processing/video_processing.markdown @@ -1,6 +1,9 @@ OpenCV iOS - Video Processing {#tutorial_video_processing} ============================= +@prev_tutorial{tutorial_image_manipulation} + + This tutorial explains how to process video frames using the iPhone's camera and OpenCV. Prerequisites: diff --git a/doc/tutorials/ml/introduction_to_pca/introduction_to_pca.markdown b/doc/tutorials/ml/introduction_to_pca/introduction_to_pca.markdown index 02f2d16ea9..c1c6c53a99 100644 --- a/doc/tutorials/ml/introduction_to_pca/introduction_to_pca.markdown +++ b/doc/tutorials/ml/introduction_to_pca/introduction_to_pca.markdown @@ -1,6 +1,8 @@ Introduction to Principal Component Analysis (PCA) {#tutorial_introduction_to_pca} ======================================= +@prev_tutorial{tutorial_non_linear_svms} + Goal ---- diff --git a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown index f7fca1520a..1340061228 100644 --- a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown +++ b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown @@ -1,6 +1,8 @@ Introduction to Support Vector Machines {#tutorial_introduction_to_svm} ======================================= +@next_tutorial{tutorial_non_linear_svms} + Goal ---- diff --git a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown index 7d7788e1a3..025ae0cda1 100644 --- a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown +++ b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown @@ -1,6 +1,9 @@ Support Vector Machines for Non-Linearly Separable Data {#tutorial_non_linear_svms} ======================================================= +@prev_tutorial{tutorial_introduction_to_svm} +@next_tutorial{tutorial_introduction_to_pca} + Goal ---- diff --git a/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown b/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown index 43fa143748..be942bdbdd 100644 --- a/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown +++ b/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown @@ -1,6 +1,8 @@ Cascade Classifier {#tutorial_cascade_classifier} ================== +@next_tutorial{tutorial_traincascade} + Goal ---- diff --git a/doc/tutorials/objdetect/traincascade.markdown b/doc/tutorials/objdetect/traincascade.markdown index a312340852..042aaccdc9 100644 --- a/doc/tutorials/objdetect/traincascade.markdown +++ b/doc/tutorials/objdetect/traincascade.markdown @@ -1,6 +1,8 @@ Cascade Classifier Training {#tutorial_traincascade} =========================== +@prev_tutorial{tutorial_cascade_classifier} + Introduction ------------ diff --git a/doc/tutorials/video/background_subtraction/background_subtraction.markdown b/doc/tutorials/video/background_subtraction/background_subtraction.markdown index bac6110467..c95cd4173d 100644 --- a/doc/tutorials/video/background_subtraction/background_subtraction.markdown +++ b/doc/tutorials/video/background_subtraction/background_subtraction.markdown @@ -1,6 +1,8 @@ How to Use Background Subtraction Methods {#tutorial_background_subtraction} ========================================= +@next_tutorial{tutorial_meanshift} + - Background subtraction (BS) is a common and widely used technique for generating a foreground mask (namely, a binary image containing the pixels belonging to moving objects in the scene) by using static cameras. diff --git a/doc/tutorials/video/meanshift/meanshift.markdown b/doc/tutorials/video/meanshift/meanshift.markdown index c51b8fc181..6472570ead 100644 --- a/doc/tutorials/video/meanshift/meanshift.markdown +++ b/doc/tutorials/video/meanshift/meanshift.markdown @@ -1,6 +1,9 @@ Meanshift and Camshift {#tutorial_meanshift} ====================== +@prev_tutorial{tutorial_background_subtraction} +@next_tutorial{tutorial_optical_flow} + Goal ---- diff --git a/doc/tutorials/video/optical_flow/optical_flow.markdown b/doc/tutorials/video/optical_flow/optical_flow.markdown index 8dc86d9a7e..bcf88f7af1 100644 --- a/doc/tutorials/video/optical_flow/optical_flow.markdown +++ b/doc/tutorials/video/optical_flow/optical_flow.markdown @@ -1,6 +1,8 @@ Optical Flow {#tutorial_optical_flow} ============ +@prev_tutorial{tutorial_meanshift} + Goal ---- diff --git a/doc/tutorials/videoio/intelperc.markdown b/doc/tutorials/videoio/intelperc.markdown index 6077a64a4e..8348d8663a 100644 --- a/doc/tutorials/videoio/intelperc.markdown +++ b/doc/tutorials/videoio/intelperc.markdown @@ -1,6 +1,8 @@ Using Creative Senz3D and other Intel Perceptual Computing SDK compatible depth sensors {#tutorial_intelperc} ======================================================================================= +@prev_tutorial{tutorial_kinect_openni} + **Note**: this tutorial is partially obsolete since PerC SDK has been replaced with RealSense SDK Depth sensors compatible with Intel Perceptual Computing SDK are supported through VideoCapture diff --git a/doc/tutorials/videoio/kinect_openni.markdown b/doc/tutorials/videoio/kinect_openni.markdown index 0734ea6c58..dc1ee6eeaa 100644 --- a/doc/tutorials/videoio/kinect_openni.markdown +++ b/doc/tutorials/videoio/kinect_openni.markdown @@ -1,6 +1,10 @@ Using Kinect and other OpenNI compatible depth sensors {#tutorial_kinect_openni} ====================================================== +@prev_tutorial{tutorial_video_write} +@next_tutorial{tutorial_intelperc} + + Depth sensors compatible with OpenNI (Kinect, XtionPRO, ...) are supported through VideoCapture class. Depth map, BGR image and some other formats of output can be retrieved by using familiar interface of VideoCapture. diff --git a/doc/tutorials/videoio/video-input-psnr-ssim/video_input_psnr_ssim.markdown b/doc/tutorials/videoio/video-input-psnr-ssim/video_input_psnr_ssim.markdown index 7e214e0962..e24f3cb71b 100644 --- a/doc/tutorials/videoio/video-input-psnr-ssim/video_input_psnr_ssim.markdown +++ b/doc/tutorials/videoio/video-input-psnr-ssim/video_input_psnr_ssim.markdown @@ -1,6 +1,8 @@ Video Input with OpenCV and similarity measurement {#tutorial_video_input_psnr_ssim} ================================================== +@next_tutorial{tutorial_video_write} + Goal ---- diff --git a/doc/tutorials/videoio/video-write/video_write.markdown b/doc/tutorials/videoio/video-write/video_write.markdown index 9781a7075d..624b2d1db6 100644 --- a/doc/tutorials/videoio/video-write/video_write.markdown +++ b/doc/tutorials/videoio/video-write/video_write.markdown @@ -1,6 +1,9 @@ Creating a video with OpenCV {#tutorial_video_write} ============================ +@prev_tutorial{tutorial_video_input_psnr_ssim} +@next_tutorial{tutorial_kinect_openni} + Goal ---- diff --git a/modules/dnn/include/opencv2/dnn/all_layers.hpp b/modules/dnn/include/opencv2/dnn/all_layers.hpp index 0969ba6c62..f574cc19be 100644 --- a/modules/dnn/include/opencv2/dnn/all_layers.hpp +++ b/modules/dnn/include/opencv2/dnn/all_layers.hpp @@ -556,6 +556,30 @@ CV__DNN_INLINE_NS_BEGIN static Ptr create(const LayerParams& params); }; + class CV_EXPORTS DataAugmentationLayer : public Layer + { + public: + static Ptr create(const LayerParams& params); + }; + + class CV_EXPORTS CorrelationLayer : public Layer + { + public: + static Ptr create(const LayerParams& params); + }; + + class CV_EXPORTS AccumLayer : public Layer + { + public: + static Ptr create(const LayerParams& params); + }; + + class CV_EXPORTS FlowWarpLayer : public Layer + { + public: + static Ptr create(const LayerParams& params); + }; + class CV_EXPORTS PriorBoxLayer : public Layer { public: diff --git a/modules/dnn/src/caffe/caffe_importer.cpp b/modules/dnn/src/caffe/caffe_importer.cpp index 8ceee2e587..05f94e6dc9 100644 --- a/modules/dnn/src/caffe/caffe_importer.cpp +++ b/modules/dnn/src/caffe/caffe_importer.cpp @@ -465,6 +465,35 @@ public: net.mutable_layer(li)->mutable_bottom()->RemoveLast(); type = "Eltwise"; } + else if (type == "Resample") + { + CV_Assert(layer.bottom_size() == 1 || layer.bottom_size() == 2); + type = "Resize"; + String interp = toLowerCase(layerParams.get("type")); + layerParams.set("interpolation", interp == "linear" ? "bilinear" : interp); + + if (layerParams.has("factor")) + { + float factor = layerParams.get("factor"); + CV_Assert(layer.bottom_size() != 2 || factor == 1.0); + layerParams.set("zoom_factor", factor); + + if ((interp == "linear" && factor != 1.0) || + (interp == "nearest" && factor < 1.0)) + CV_Error(Error::StsNotImplemented, "Unsupported Resample mode"); + } + } + else if ("Convolution" == type) + { + CV_Assert(layer.bottom_size() == layer.top_size()); + for (int i = 0; i < layer.bottom_size(); i++) + { + int conv_id = dstNet.addLayer(layer.top(i), type, layerParams); + addInput(layer.bottom(i), conv_id, 0, dstNet); + addedBlobs.push_back(BlobNote(layer.top(i), conv_id, 0)); + } + continue; + } else if ("ConvolutionDepthwise" == type) { type = "Convolution"; diff --git a/modules/dnn/src/init.cpp b/modules/dnn/src/init.cpp index e9bcfa6279..570a6ff665 100644 --- a/modules/dnn/src/init.cpp +++ b/modules/dnn/src/init.cpp @@ -132,6 +132,10 @@ void initializeLayerFactory() CV_DNN_REGISTER_LAYER_CLASS(Padding, PaddingLayer); CV_DNN_REGISTER_LAYER_CLASS(Proposal, ProposalLayer); CV_DNN_REGISTER_LAYER_CLASS(Scale, ScaleLayer); + CV_DNN_REGISTER_LAYER_CLASS(DataAugmentation, DataAugmentationLayer); + CV_DNN_REGISTER_LAYER_CLASS(Correlation, CorrelationLayer); + CV_DNN_REGISTER_LAYER_CLASS(Accum, AccumLayer); + CV_DNN_REGISTER_LAYER_CLASS(FlowWarp, FlowWarpLayer); CV_DNN_REGISTER_LAYER_CLASS(LSTM, LSTMLayer); } diff --git a/modules/dnn/src/layers/accum_layer.cpp b/modules/dnn/src/layers/accum_layer.cpp new file mode 100644 index 0000000000..72bbf04b87 --- /dev/null +++ b/modules/dnn/src/layers/accum_layer.cpp @@ -0,0 +1,141 @@ +// 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. + +// Copyright (C) 2020, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. + +#include "../precomp.hpp" +#include "layers_common.hpp" + + +namespace cv { namespace dnn { + +class AccumLayerImpl CV_FINAL : public AccumLayer +{ +public: + AccumLayerImpl(const LayerParams& params) + { + setParamsFrom(params); + top_height = params.get("top_height", 0); + top_width = params.get("top_width", 0); + divisor = params.get("size_divisible_by", 0); + have_reference = params.get("have_reference", "false") == "true"; + } + + virtual bool getMemoryShapes(const std::vector &inputs, + const int requiredOutputs, + std::vector &outputs, + std::vector &internals) const CV_OVERRIDE + { + std::vector outShape; + int batch = inputs[0][0]; + outShape.push_back(batch); + + if (have_reference) + { + CV_Assert(inputs.size() >= 2); + int totalchannels = 0; + for (int i = 0; i < inputs.size() - 1; i++) { + CV_Assert(inputs[i][0] == batch); + totalchannels += inputs[i][1]; + } + outShape.push_back(totalchannels); + + int height = inputs.back()[2]; + int width = inputs.back()[3]; + + outShape.push_back(height); + outShape.push_back(width); + } + else + { + int maxwidth = -1; + int maxheight = -1; + int totalchannels = 0; + + // Find largest blob size and count total channels + for (int i = 0; i < inputs.size(); ++i) + { + totalchannels += inputs[i][1]; + maxheight = std::max(maxheight, inputs[i][2]); + maxwidth = std::max(maxwidth, inputs[i][3]); + CV_Assert(inputs[i][0] == batch); + } + outShape.push_back(totalchannels); + + int out_h = divisor ? static_cast(ceil(maxheight / divisor) * divisor) : top_height; + int out_w = divisor ? static_cast(ceil(maxwidth / divisor) * divisor) : top_width; + + // Layer can specify custom top size which is larger than default + if (out_h <= maxheight || out_w <= maxwidth) + { + out_h = maxheight; + out_w = maxwidth; + } + + outShape.push_back(out_h); + outShape.push_back(out_w); + } + + outputs.assign(1, outShape); + return false; + } + + virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE + { + LayerParams resizeParams; + resizeParams.set("interpolation", "bilinear"); + resizeParams.set("align_corners", true); + resize = ResizeLayer::create(resizeParams); + } + + void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE + { + CV_TRACE_FUNCTION(); + CV_TRACE_ARG_VALUE(name, "name", name.c_str()); + + std::vector inputs, outputs; + inputs_arr.getMatVector(inputs); + outputs_arr.getMatVector(outputs); + + const int out_h = outputs[0].size[2]; + const int out_w = outputs[0].size[3]; + float* out_data = outputs[0].ptr(); + std::vector sizes(&outputs[0].size[0], &outputs[0].size[0] + outputs[0].size.dims()); + for (int i = 0; i < inputs.size() - have_reference; i++) + { + sizes[1] = inputs[i].size[1]; + Mat outSlice(sizes, CV_32F, out_data); + + if (out_h == inputs[i].size[2] && out_w == inputs[i].size[3]) + { + inputs[i].copyTo(outSlice); + } + else + { + std::vector inp_slices, out_slices; + inp_slices.push_back(inputs[i]); + out_slices.push_back(outSlice); + + resize->finalize(inp_slices, out_slices); + resize->forward(inp_slices, out_slices, internals_arr); + } + out_data += outSlice.total(1); + } + } + +private: + int top_height; + int top_width; + int divisor; + bool have_reference; + Ptr resize; +}; + +Ptr AccumLayer::create(const LayerParams& params) +{ + return Ptr(new AccumLayerImpl(params)); +} + +}} // namespace cv::dnn diff --git a/modules/dnn/src/layers/convolution_layer.cpp b/modules/dnn/src/layers/convolution_layer.cpp index a2889a77d1..1c2c85df09 100644 --- a/modules/dnn/src/layers/convolution_layer.cpp +++ b/modules/dnn/src/layers/convolution_layer.cpp @@ -1389,6 +1389,13 @@ public: CV_TRACE_FUNCTION(); CV_TRACE_ARG_VALUE(name, "name", name.c_str()); +#if CV_TRY_SSE + uint32_t ftzMode = _MM_GET_FLUSH_ZERO_MODE(); + uint32_t dazMode = _MM_GET_DENORMALS_ZERO_MODE(); + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); +#endif + CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget), forward_ocl(inputs_arr, outputs_arr, internals_arr)) @@ -1471,6 +1478,10 @@ public: ParallelConv::run(inputs[0], outputs[0], weightsMat, biasvec, reluslope, kernel_size, strides, pads_begin, pads_end, dilations, activ.get(), ngroups, nstripes); } +#if CV_TRY_SSE + _MM_SET_FLUSH_ZERO_MODE(ftzMode); + _MM_SET_DENORMALS_ZERO_MODE(dazMode); +#endif } #ifdef HAVE_CUDA diff --git a/modules/dnn/src/layers/correlation_layer.cpp b/modules/dnn/src/layers/correlation_layer.cpp new file mode 100644 index 0000000000..cfb3b8eefc --- /dev/null +++ b/modules/dnn/src/layers/correlation_layer.cpp @@ -0,0 +1,207 @@ +// 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. + +// Copyright (C) 2020, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. + +#include "../precomp.hpp" +#include "layers_common.hpp" + + +namespace cv { namespace dnn { + +class CorrelationLayerImpl CV_FINAL : public CorrelationLayer +{ +public: + CorrelationLayerImpl(const LayerParams& params) + { + setParamsFrom(params); + pad = params.get("pad", 0); + CV_Assert_N(params.has("kernel_size"), params.has("max_displacement")); + max_displacement = params.get("max_displacement"); + kernel = params.get("kernel_size"); + if (kernel % 2 == 0) + CV_Error(Error::StsNotImplemented, "Odd kernel size required."); + + stride_1 = params.get("stride_1", 1); + stride_2 = params.get("stride_2", 1); + } + + virtual bool getMemoryShapes(const std::vector &inputs, + const int requiredOutputs, + std::vector &outputs, + std::vector &internals) const CV_OVERRIDE + { + CV_Assert_N(inputs.size() == 2, inputs[0].size() == 4, inputs[1].size() == 4); + + int padded_height = inputs[0][2] + 2 * pad; + int padded_width = inputs[0][3] + 2 * pad; + + int kernel_radius = (kernel - 1) / 2; + int border_size = max_displacement + kernel_radius; + + int neighborhood_grid_radius = max_displacement / stride_2; + int neighborhood_grid_width = neighborhood_grid_radius * 2 + 1; + + std::vector outShape; + + int num = inputs[0][0]; + outShape.push_back(num); + + int out_c = neighborhood_grid_width * neighborhood_grid_width; + outShape.push_back(out_c); + + int out_h = ceil(static_cast(padded_height - border_size * 2) / stride_1); + int out_w = ceil(static_cast(padded_width - border_size * 2) / stride_1); + CV_Assert_N(out_h >= 1, out_w >= 1); + + outShape.push_back(out_h); + outShape.push_back(out_w); + outputs.assign(1, outShape); + return false; + } + + virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays) CV_OVERRIDE + { + std::vector inputs; + inputs_arr.getMatVector(inputs); + + int padded_height = inputs[0].size[2] + 2 * pad; + int padded_width = inputs[0].size[3] + 2 * pad; + + int size[] = {inputs[0].size[0], padded_height, padded_width, inputs[0].size[1]}; + rbot0 = Mat(4, &size[0], CV_32F, float(0)); + rbot1 = Mat(4, &size[0], CV_32F, float(0)); + } + + void blobRearrangeKernel2(const Mat& input, Mat& output) + { + const int num = input.size[0]; + const int channels = input.size[1]; + const int height = input.size[2]; + const int width = input.size[3]; + const int area = height * width; + const int pad_area = (width + 2 * pad) * (height + 2 * pad); + + const float* in = input.ptr(); + float* out = output.ptr(); + for (int n = 0; n < num; n++) + { + for (int ch = 0; ch < channels; ch++) + { + for (int xy = 0; xy < area; xy++) + { + float value = in[(n * channels + ch) * area + xy]; + int xpad = (xy % width + pad); + int ypad = (xy / width + pad); + int xypad = ypad * (width + 2 * pad) + xpad; + out[(n * pad_area + xypad) * channels + ch] = value; + } + } + } + } + + void correlationKernelSubtraction(const Mat& input0, const Mat& input1, Mat& output, int item) + { + const int inp_h = input0.size[1]; + const int inp_w = input0.size[2]; + const int inp_c = input0.size[3]; + + const int out_c = output.size[1]; + const int out_h = output.size[2]; + const int out_w = output.size[3]; + + int topcount = output.total(1); + int neighborhood_grid_radius = max_displacement / stride_2; + int neighborhood_grid_width = neighborhood_grid_radius * 2 + 1; + + const float* inp0_data = input0.ptr(); + const float* inp1_data = input1.ptr(); + float* out_data = output.ptr(); + int sumelems = kernel * kernel * inp_c; + std::vector patch_data(sumelems, 0); + for (int y = 0; y < out_h; y++) + { + for (int x = 0; x < out_w; x++) + { + int x1 = x * stride_1 + max_displacement; + int y1 = y * stride_1 + max_displacement; + + for (int j = 0; j < kernel; j++) + { + for (int i = 0; i < kernel; i++) + { + int ji_off = ((j * kernel) + i) * inp_c; + for (int ch = 0; ch < inp_c; ch++) + { + int idx1 = ((item * inp_h + y1 + j) * inp_w + x1 + i) * inp_c + ch; + int idxPatchData = ji_off + ch; + patch_data[idxPatchData] = inp0_data[idx1]; + } + } + } + + for (int out_ch = 0; out_ch < out_c; out_ch++) + { + float sum = 0; + int s2o = (out_ch % neighborhood_grid_width - neighborhood_grid_radius) * stride_2; + int s2p = (out_ch / neighborhood_grid_width - neighborhood_grid_radius) * stride_2; + + int x2 = x1 + s2o; + int y2 = y1 + s2p; + for (int j = 0; j < kernel; j++) + { + for (int i = 0; i < kernel; i++) + { + int ji_off = ((j * kernel) + i) * inp_c; + for (int ch = 0; ch < inp_c; ch++) + { + int idxPatchData = ji_off + ch; + int idx2 = ((item * inp_h + y2 + j) * inp_w + x2 + i) * inp_c + ch; + sum += patch_data[idxPatchData] * inp1_data[idx2]; + } + } + } + int index = ((out_ch * out_h + y) * out_w) + x; + out_data[index + item * topcount] = static_cast(sum) / sumelems; + } + } + } + } + + + void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE + { + CV_TRACE_FUNCTION(); + CV_TRACE_ARG_VALUE(name, "name", name.c_str()); + + std::vector inputs, outputs, internals; + inputs_arr.getMatVector(inputs); + outputs_arr.getMatVector(outputs); + internals_arr.getMatVector(internals); + + blobRearrangeKernel2(inputs[0], rbot0); + blobRearrangeKernel2(inputs[1], rbot1); + for (int i = 0; i < inputs[0].size[0]; i++) + { + correlationKernelSubtraction(rbot0, rbot1, outputs[0], i); + } + } + +private: + int pad; + int kernel; + int max_displacement; + int stride_1; + int stride_2; + Mat rbot0; + Mat rbot1; +}; + +Ptr CorrelationLayer::create(const LayerParams& params) +{ + return Ptr(new CorrelationLayerImpl(params)); +} + +}} // namespace cv::dnn diff --git a/modules/dnn/src/layers/flow_warp_layer.cpp b/modules/dnn/src/layers/flow_warp_layer.cpp new file mode 100644 index 0000000000..95dd6386fb --- /dev/null +++ b/modules/dnn/src/layers/flow_warp_layer.cpp @@ -0,0 +1,117 @@ +// 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. + +// Copyright (C) 2020, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. + +#include "../precomp.hpp" +#include "layers_common.hpp" + + +namespace cv { namespace dnn { + +class FlowWarpLayerImpl CV_FINAL : public FlowWarpLayer +{ +public: + FlowWarpLayerImpl(const LayerParams& params) + { + setParamsFrom(params); + String fill_string = toLowerCase(params.get("FillParameter", "ZERO")); + if (fill_string != "zero") + CV_Error(Error::StsNotImplemented, "Only zero filling supported."); + fill_value = 0; + } + + virtual bool getMemoryShapes(const std::vector &inputs, + const int requiredOutputs, + std::vector &outputs, + std::vector &internals) const CV_OVERRIDE + { + CV_Assert(inputs.size() == 2); + CV_Assert_N(inputs[0][0] == inputs[1][0], inputs[1][1] == 2, + inputs[0][2] == inputs[1][2], inputs[0][3] == inputs[1][3]); + + outputs.assign(1, inputs[0]); + return false; + } + + void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE + { + CV_TRACE_FUNCTION(); + CV_TRACE_ARG_VALUE(name, "name", name.c_str()); + + std::vector inputs, outputs; + inputs_arr.getMatVector(inputs); + outputs_arr.getMatVector(outputs); + + const int out_n = outputs[0].size[0]; + const int out_c = outputs[0].size[1]; + const int out_h = outputs[0].size[2]; + const int out_w = outputs[0].size[3]; + + const int area = out_w * out_h; + const int total = area * out_c; + + const float* image_data = inputs[0].ptr(); + const float* flow_data = inputs[1].ptr(); + float* out_data = outputs[0].ptr(); + + for (int n = 0; n < out_n; n++) + { + int off = total * n; + for (int x = 0; x < out_w; x++) + { + for (int y = 0; y < out_h; y++) + { + int idx = 2 * area * n + y * out_w + x; + float fx = flow_data[idx]; + float fy = flow_data[idx + area]; + + float x2 = x + fx; + float y2 = y + fy; + + if (x2 >= 0 && y2 >= 0 && x2 < out_w && y2 < out_h) + { + int ix2_L = x2; + float alpha = x2 - ix2_L; + + int iy2_T = y2; + float beta = y2 - iy2_T; + + int ix2_R = std::min(ix2_L + 1, out_w - 1); + int iy2_B = std::min(iy2_T + 1, out_h - 1); + + for (int c = 0; c < out_c; c++) + { + float TL = image_data[off + c * area + iy2_T * out_w + ix2_L]; + float TR = image_data[off + c * area + iy2_T * out_w + ix2_R]; + float BL = image_data[off + c * area + iy2_B * out_w + ix2_L]; + float BR = image_data[off + c * area + iy2_B * out_w + ix2_R]; + + out_data[off + c * area + y * out_w + x] = (1 - alpha) * (1 - beta) * TL + + (1 - alpha) * beta * BL + + alpha * (1 - beta) * TR + + alpha * beta * BR; + } + } + else + { + for (int c = 0; c < out_c; c++) + out_data[off + c * area + y * out_w + x] = fill_value; + } + } + } + } + } + +private: + float fill_value; +}; + +Ptr FlowWarpLayer::create(const LayerParams& params) +{ + return Ptr(new FlowWarpLayerImpl(params)); +} + +}} // namespace cv::dnn diff --git a/modules/dnn/src/layers/resize_layer.cpp b/modules/dnn/src/layers/resize_layer.cpp index 970bb9a55e..0c1f83b9d1 100644 --- a/modules/dnn/src/layers/resize_layer.cpp +++ b/modules/dnn/src/layers/resize_layer.cpp @@ -51,10 +51,15 @@ public: std::vector &outputs, std::vector &internals) const CV_OVERRIDE { - CV_Assert_N(inputs.size() == 1, inputs[0].size() == 4); + CV_Assert_N(inputs.size() == 1 || inputs.size() == 2, inputs[0].size() == 4); outputs.resize(1, inputs[0]); - outputs[0][2] = zoomFactorHeight > 0 ? (outputs[0][2] * zoomFactorHeight) : outHeight; - outputs[0][3] = zoomFactorWidth > 0 ? (outputs[0][3] * zoomFactorWidth) : outWidth; + if (inputs.size() == 1) { + outputs[0][2] = zoomFactorHeight > 0 ? (outputs[0][2] * zoomFactorHeight) : outHeight; + outputs[0][3] = zoomFactorWidth > 0 ? (outputs[0][3] * zoomFactorWidth) : outWidth; + } else { + outputs[0][2] = inputs[1][2]; + outputs[0][3] = inputs[1][3]; + } // We can work in-place (do nothing) if input shape == output shape. return (outputs[0][2] == inputs[0][2]) && (outputs[0][3] == inputs[0][3]); } diff --git a/modules/dnn/src/layers/scale_layer.cpp b/modules/dnn/src/layers/scale_layer.cpp index 71f54d8a21..7ec9ddc5f5 100644 --- a/modules/dnn/src/layers/scale_layer.cpp +++ b/modules/dnn/src/layers/scale_layer.cpp @@ -372,5 +372,118 @@ Ptr ShiftLayer::create(const LayerParams& params) return Ptr(new ScaleLayerImpl(scaleParams)); } +class DataAugmentationLayerImpl CV_FINAL : public DataAugmentationLayer +{ +public: + DataAugmentationLayerImpl(const LayerParams& params) + { + setParamsFrom(params); + recompute_mean = params.get("recompute_mean", 1); + CV_CheckGT(recompute_mean, 0, ""); + mean_per_pixel = params.get("mean_per_pixel", false); + } + + bool getMemoryShapes(const std::vector &inputs, + const int requiredOutputs, + std::vector &outputs, + std::vector &internals) const CV_OVERRIDE + { + CV_Assert_N(inputs.size() == 1, blobs.size() == 3); + CV_Assert_N(blobs[0].total() == 1, blobs[1].total() == total(inputs[0], 1), + blobs[2].total() == inputs[0][1]); + + outputs.assign(1, inputs[0]); + return true; + } + + void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE + { + CV_TRACE_FUNCTION(); + CV_TRACE_ARG_VALUE(name, "name", name.c_str()); + + std::vector inputs, outputs; + inputs_arr.getMatVector(inputs); + outputs_arr.getMatVector(outputs); + + CV_Assert_N(outputs.size() == 1, blobs.size() == 3, inputs.size() == 1); + int num_iter = 0; + + float* inpData = inputs[0].ptr(); + float* outData = outputs[0].ptr(); + + Mat data_mean_cpu = blobs[1].clone(); + Mat data_mean_per_channel_cpu = blobs[2].clone(); + + const int numWeights = data_mean_cpu.total(); + CV_Assert(numWeights != 0); + + ++num_iter; + if (num_iter <= recompute_mean) + { + data_mean_cpu *= (num_iter - 1); + const int batch = inputs[0].size[0]; + float alpha = 1.0 / batch; + + for (int i = 0; i < batch; ++i) + { + Mat inpSlice(1, numWeights, CV_32F, inpData); + inpSlice = alpha * inpSlice; + + add(data_mean_cpu.reshape(1, 1), inpSlice, data_mean_cpu.reshape(1, 1)); + inpData += numWeights; + } + data_mean_cpu *= (1.0 / num_iter); + + int newsize[] = {blobs[1].size[1], (int)blobs[1].total(2)}; + reduce(data_mean_cpu.reshape(1, 2, &newsize[0]), data_mean_per_channel_cpu, 1, REDUCE_SUM, CV_32F); + + int area = blobs[1].total(2); + data_mean_per_channel_cpu *= (1.0 / area); + } + + MatShape inpShape = shape(inputs[0]); + + inpData = inputs[0].ptr(); + if (mean_per_pixel) + { + int numSlices = inputs[0].size[0]; + for (int i = 0; i < numSlices; ++i) + { + Mat inpSlice(1, numWeights, CV_32F, inpData); + Mat outSlice(1, numWeights, CV_32F, outData); + + add(inpSlice, (-1) * data_mean_cpu, outSlice); + inpData += numWeights; + outData += numWeights; + } + } + else + { + int numSlices = inpShape[1]; + int count = numWeights / numSlices; + + for (int i = 0; i < numSlices; ++i) + { + Mat inpSlice(1, count, CV_32F, inpData); + Mat outSlice(1, count, CV_32F, outData); + float coeff = data_mean_per_channel_cpu.reshape(1, 1).at(0, i); + outSlice = inpSlice - coeff; + + inpData += count; + outData += count; + } + } + } + +private: + int recompute_mean; + bool mean_per_pixel; +}; + +Ptr DataAugmentationLayer::create(const LayerParams& params) +{ + return Ptr(new DataAugmentationLayerImpl(params)); +} + } // namespace dnn } // namespace cv diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index a0da23e200..2dce3e4fe4 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -97,29 +97,68 @@ class Test_Caffe_layers : public DNNTestLayer { public: void testLayerUsingCaffeModels(const String& basename, bool useCaffeModel = false, - bool useCommonInputBlob = true, double l1 = 0.0, - double lInf = 0.0) + bool useCommonInputBlob = true, double l1 = 0.0, double lInf = 0.0, + int numInps = 1, int numOuts = 1) { + CV_Assert_N(numInps >= 1, numInps <= 10, numOuts >= 1, numOuts <= 10); 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"); + std::vector inps, refs, outs; - Mat inp = blobFromNPY(inpfile); - Mat ref = blobFromNPY(outfile); - checkBackend(&inp, &ref); + if (numInps > 1) + { + for (int i = 0; i < numInps; i++) + { + String inpfile = _tf(basename + cv::format(".input_%d.npy", i)); + inps.push_back(blobFromNPY(inpfile)); + } + } + else + { + String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy"); + inps.push_back(blobFromNPY(inpfile)); + } + + if (numOuts > 1) + { + for (int i = 0; i < numOuts; i++) + { + String outfile = _tf(basename + cv::format("_%d.npy", i)); + refs.push_back(blobFromNPY(outfile)); + } + } + else + { + String outfile = _tf(basename + ".npy"); + refs.push_back(blobFromNPY(outfile)); + } Net net = readNetFromCaffe(prototxt, (useCaffeModel) ? caffemodel : String()); ASSERT_FALSE(net.empty()); + checkBackend(&inps[0], &refs[0]); net.setPreferableBackend(backend); net.setPreferableTarget(target); - net.setInput(inp, "input"); - Mat out = net.forward("output"); + String inp_name = "input"; + if (numInps > 1) + { + for (int i = 0; i < numInps; i++) + { + net.setInput(inps[i], inp_name + cv::format("_%d", i)); + } + } + else + { + net.setInput(inps.back(), inp_name); + } - normAssert(ref, out, "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf); + net.forward(outs); + for (int i = 0; i < refs.size(); i++) + { + normAssert(refs[i], outs[i], "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf); + } } }; @@ -579,6 +618,58 @@ TEST_F(Layer_RNN_Test, get_set_test) EXPECT_EQ(shape(outputs[1]), shape(nT, nS, nH)); } +TEST_P(Test_Caffe_layers, Accum) +{ + if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL, CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); + + testLayerUsingCaffeModels("accum", false, false, 0.0, 0.0, 2); + testLayerUsingCaffeModels("accum_ref", false, false, 0.0, 0.0, 2); +} + +TEST_P(Test_Caffe_layers, FlowWarp) +{ + if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) + applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); + + testLayerUsingCaffeModels("flow_warp", false, false, 0.0, 0.0, 2); +} + +TEST_P(Test_Caffe_layers, ChannelNorm) +{ + if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) + applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); + testLayerUsingCaffeModels("channel_norm", false, false); +} + +TEST_P(Test_Caffe_layers, DataAugmentation) +{ + if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) + applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); + testLayerUsingCaffeModels("data_augmentation", true, false); +} + +TEST_P(Test_Caffe_layers, Resample) +{ + if (backend != DNN_BACKEND_OPENCV) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); + testLayerUsingCaffeModels("nearest_2inps", false, false, 0.0, 0.0, 2); + testLayerUsingCaffeModels("nearest", false, false); +} + +TEST_P(Test_Caffe_layers, Correlation) +{ + if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, + CV_TEST_TAG_DNN_SKIP_OPENCL, CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); + testLayerUsingCaffeModels("correlation", false, false, 0.0, 0.0, 2); +} + +TEST_P(Test_Caffe_layers, Convolution2Inputs) +{ + testLayerUsingCaffeModels("conv_2_inps", true, false, 0.0, 0.0, 2); +} + TEST_P(Test_Caffe_layers, ROIPooling_Accuracy) { Net net = readNetFromCaffe(_tf("net_roi_pooling.prototxt")); diff --git a/modules/videoio/src/cap_avfoundation.mm b/modules/videoio/src/cap_avfoundation.mm index d7f7cc797b..8ac8d85d8d 100644 --- a/modules/videoio/src/cap_avfoundation.mm +++ b/modules/videoio/src/cap_avfoundation.mm @@ -392,7 +392,7 @@ int CvCaptureCAM::startCaptureDevice(int cameraNum) { [mCaptureDecompressedVideoOutput setVideoSettings:pixelBufferOptions]; mCaptureDecompressedVideoOutput.alwaysDiscardsLateVideoFrames = YES; -#if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) && !TARGET_OS_MACCATALYST +#if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) && (!defined(TARGET_OS_MACCATALYST) || !TARGET_OS_MACCATALYST) mCaptureDecompressedVideoOutput.minFrameDuration = CMTimeMake(1, 30); #endif diff --git a/modules/videoio/src/cap_ios_abstract_camera.mm b/modules/videoio/src/cap_ios_abstract_camera.mm index 1f698424d8..dd891242ff 100644 --- a/modules/videoio/src/cap_ios_abstract_camera.mm +++ b/modules/videoio/src/cap_ios_abstract_camera.mm @@ -299,7 +299,7 @@ } else { -#if !TARGET_OS_MACCATALYST +#if (!defined(TARGET_OS_MACCATALYST) || !TARGET_OS_MACCATALYST) // Deprecated in 6.0; here for backward compatibility if ([self.captureVideoPreviewLayer isOrientationSupported]) { diff --git a/samples/dnn/optical_flow.py b/samples/dnn/optical_flow.py new file mode 100644 index 0000000000..5d0d831cf3 --- /dev/null +++ b/samples/dnn/optical_flow.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +''' +This sample using FlowNet v2 model to calculate optical flow. +Original paper: https://arxiv.org/abs/1612.01925. +Original repo: https://github.com/lmb-freiburg/flownet2. + +Download the converted .caffemodel model from https://drive.google.com/open?id=16qvE9VNmU39NttpZwZs81Ga8VYQJDaWZ +and .prototxt from https://drive.google.com/open?id=19bo6SWU2p8ZKvjXqMKiCPdK8mghwDy9b. +Otherwise download original model from https://lmb.informatik.uni-freiburg.de/resources/binaries/flownet2/flownet2-models.tar.gz, +convert .h5 model to .caffemodel and modify original .prototxt using .prototxt from link above. +''' + +import argparse +import os.path +import numpy as np +import cv2 as cv + + +class OpticalFlow(object): + def __init__(self, proto, model, height, width): + self.net = cv.dnn.readNet(proto, model) + self.net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV) + self.height = height + self.width = width + + def compute_flow(self, first_img, second_img): + inp0 = cv.dnn.blobFromImage(first_img, size=(self.width, self.height)) + inp1 = cv.dnn.blobFromImage(second_img, size=(self.width, self.height)) + self.net.setInput(inp0, "img0") + self.net.setInput(inp1, "img1") + flow = self.net.forward() + output = self.motion_to_color(flow) + return output + + def motion_to_color(self, flow): + arr = np.arange(0, 255, dtype=np.uint8) + colormap = cv.applyColorMap(arr, cv.COLORMAP_HSV) + colormap = colormap.squeeze(1) + + flow = flow.squeeze(0) + fx, fy = flow[0, ...], flow[1, ...] + rad = np.sqrt(fx**2 + fy**2) + maxrad = rad.max() if rad.max() != 0 else 1 + + ncols = arr.size + rad = rad[..., np.newaxis] / maxrad + a = np.arctan2(-fy / maxrad, -fx / maxrad) / np.pi + fk = (a + 1) / 2.0 * (ncols - 1) + k0 = fk.astype(np.int) + k1 = (k0 + 1) % ncols + f = fk[..., np.newaxis] - k0[..., np.newaxis] + + col0 = colormap[k0] / 255.0 + col1 = colormap[k1] / 255.0 + col = (1 - f) * col0 + f * col1 + col = np.where(rad <= 1, 1 - rad * (1 - col), col * 0.75) + output = (255.0 * col).astype(np.uint8) + return output + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Use this script to calculate optical flow using FlowNetv2', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-input', '-i', required=True, help='Path to input video file. Skip this argument to capture frames from a camera.') + parser.add_argument('--height', default=320, help='Input height') + parser.add_argument('--width', default=448, help='Input width') + parser.add_argument('--proto', '-p', default='FlowNet2_deploy.prototxt', help='Path to prototxt.') + parser.add_argument('--model', '-m', default='FlowNet2_weights.caffemodel', help='Path to caffemodel.') + args, _ = parser.parse_known_args() + + if not os.path.isfile(args.model) or not os.path.isfile(args.proto): + raise OSError("Prototxt or caffemodel not exist") + + winName = 'Calculation optical flow in OpenCV' + cv.namedWindow(winName, cv.WINDOW_NORMAL) + cap = cv.VideoCapture(args.input if args.input else 0) + hasFrame, first_frame = cap.read() + opt_flow = OpticalFlow(args.proto, args.model, args.height, args.width) + while cv.waitKey(1) < 0: + hasFrame, second_frame = cap.read() + if not hasFrame: + break + flow = opt_flow.compute_flow(first_frame, second_frame) + first_frame = second_frame + cv.imshow(winName, flow)