Merge remote-tracking branch 'upstream/3.4' into merge-3.4

Revert "documentation: avoid links to 'master' branch from 3.4 maintenance branch"
This reverts commit 9ba9358ecb.

Revert "documentation: avoid links to 'master' branch from 3.4 maintenance branch (2)"
This reverts commit f185802489.
pull/11684/head
Alexander Alekhin 7 years ago
commit 45dd575ed2
  1. 20
      CMakeLists.txt
  2. 12
      cmake/FindCUDA.cmake
  3. 2
      cmake/OpenCVCompilerOptions.cmake
  4. 6
      cmake/OpenCVDetectInferenceEngine.cmake
  5. 2
      cmake/OpenCVFindLibsPerf.cmake
  6. 53
      cmake/OpenCVFindLibsVideo.cmake
  7. 6
      cmake/OpenCVModule.cmake
  8. 2
      cmake/OpenCVPCHSupport.cmake
  9. 34
      doc/opencv.bib
  10. 13
      doc/tools/html_functions.py
  11. 81
      doc/tutorials/features2d/feature_description/feature_description.markdown
  12. 75
      doc/tutorials/features2d/feature_detection/feature_detection.markdown
  13. 155
      doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown
  14. BIN
      doc/tutorials/features2d/feature_flann_matcher/images/Feature_FlannMatcher_Lowe_ratio_test.png
  15. BIN
      doc/tutorials/features2d/feature_flann_matcher/images/Feature_FlannMatcher_Result_ratio_test.jpg
  16. 125
      doc/tutorials/features2d/feature_homography/feature_homography.markdown
  17. BIN
      doc/tutorials/features2d/feature_homography/images/Feature_Homography_Result.jpg
  18. 28
      doc/tutorials/features2d/table_of_content_features2d.markdown
  19. 32
      doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.markdown
  20. 46
      doc/tutorials/features2d/trackingmotion/corner_subpixels/corner_subpixels.markdown
  21. 0
      doc/tutorials/features2d/trackingmotion/corner_subpixels/images/Corner_Subpixels_Original_Image.jpg
  22. 0
      doc/tutorials/features2d/trackingmotion/corner_subpixels/images/Corner_Subpixels_Result.jpg
  23. 24
      doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown
  24. 18
      doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown
  25. BIN
      doc/tutorials/features2d/trackingmotion/good_features_to_track/images/Feature_Detection_Result_a.jpg
  26. BIN
      doc/tutorials/features2d/trackingmotion/good_features_to_track/images/Feature_Detection_Result_b.jpg
  27. BIN
      doc/tutorials/features2d/trackingmotion/good_features_to_track/images/good_features_to_track_Shi_Tomasi.jpg
  28. 14
      doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown
  29. 2
      doc/tutorials/viz/launching_viz/launching_viz.markdown
  30. 183
      modules/calib3d/src/calibinit.cpp
  31. 16
      modules/calib3d/src/ptsetreg.cpp
  32. 68
      modules/calib3d/src/stereobm.cpp
  33. 8
      modules/calib3d/test/test_stereomatching.cpp
  34. 5
      modules/core/include/opencv2/core.hpp
  35. 14
      modules/core/include/opencv2/core/cvstd.inl.hpp
  36. 2
      modules/core/include/opencv2/core/mat.inl.hpp
  37. 14
      modules/core/include/opencv2/core/types.hpp
  38. 6
      modules/core/src/arithm.cpp
  39. 6
      modules/core/src/convert.cpp
  40. 11
      modules/core/src/copy.cpp
  41. 6
      modules/dnn/include/opencv2/dnn.hpp
  42. 22
      modules/dnn/include/opencv2/dnn/all_layers.hpp
  43. 23
      modules/dnn/include/opencv2/dnn/dnn.hpp
  44. 4
      modules/dnn/misc/quantize_face_detector.py
  45. 68
      modules/dnn/perf/perf_net.cpp
  46. 2
      modules/dnn/src/darknet/darknet_io.cpp
  47. 14
      modules/dnn/src/dnn.cpp
  48. 2
      modules/dnn/src/halide_scheduler.cpp
  49. 1
      modules/dnn/src/init.cpp
  50. 5
      modules/dnn/src/layers/convolution_layer.cpp
  51. 108
      modules/dnn/src/layers/crop_and_resize_layer.cpp
  52. 7
      modules/dnn/src/layers/detection_output_layer.cpp
  53. 13
      modules/dnn/src/layers/elementwise_layers.cpp
  54. 2
      modules/dnn/src/layers/eltwise_layer.cpp
  55. 47
      modules/dnn/src/layers/mvn_layer.cpp
  56. 3
      modules/dnn/src/layers/pooling_layer.cpp
  57. 39
      modules/dnn/src/layers/prior_box_layer.cpp
  58. 5
      modules/dnn/src/layers/region_layer.cpp
  59. 27
      modules/dnn/src/layers/resize_nearest_neighbor_layer.cpp
  60. 2
      modules/dnn/src/ocl4dnn/src/ocl4dnn_conv_spatial.cpp
  61. 85
      modules/dnn/src/op_inf_engine.cpp
  62. 5
      modules/dnn/src/op_inf_engine.hpp
  63. 15
      modules/dnn/src/opencl/mvn.cl
  64. 2
      modules/dnn/src/tensorflow/graph.proto
  65. 2
      modules/dnn/src/tensorflow/tf_graph_simplifier.cpp
  66. 40
      modules/dnn/src/tensorflow/tf_importer.cpp
  67. 6
      modules/dnn/src/torch/torch_importer.cpp
  68. 83
      modules/dnn/test/test_backends.cpp
  69. 22
      modules/dnn/test/test_common.hpp
  70. 67
      modules/dnn/test/test_darknet_importer.cpp
  71. 78
      modules/dnn/test/test_layers.cpp
  72. 6
      modules/dnn/test/test_precomp.hpp
  73. 21
      modules/dnn/test/test_tf_importer.cpp
  74. 2
      modules/dnn/test/test_torch_importer.cpp
  75. 6
      modules/features2d/src/agast.cpp
  76. 6
      modules/features2d/src/fast.cpp
  77. 6
      modules/features2d/src/gftt.cpp
  78. 224
      modules/imgproc/include/opencv2/imgproc.hpp
  79. 509
      modules/imgproc/src/color_hsv.cpp
  80. 4
      modules/imgproc/src/histogram.cpp
  81. 8
      modules/imgproc/src/hough.cpp
  82. 30
      modules/imgproc/test/test_histograms.cpp
  83. 68
      modules/python/src2/cv2.cpp
  84. 8
      modules/python/src2/gen2.py
  85. 6
      modules/python/test/test_misc.py
  86. 30
      modules/ts/include/opencv2/ts/ts_gtest.h
  87. 2
      modules/ts/src/ts_gtest.cpp
  88. 13
      modules/videoio/CMakeLists.txt
  89. 679
      modules/videoio/src/cap.cpp
  90. 92
      modules/videoio/src/cap_ffmpeg.cpp
  91. 22
      modules/videoio/src/cap_ffmpeg_api.hpp
  92. 27
      modules/videoio/src/cap_ffmpeg_impl.hpp
  93. 5
      modules/videoio/src/cap_mjpeg_encoder.cpp
  94. 1510
      modules/videoio/src/cap_v4l.cpp
  95. 7
      modules/videoio/src/precomp.hpp
  96. 152
      modules/videoio/src/videoio_c.cpp
  97. 644
      modules/videoio/src/videoio_registry.cpp
  98. 43
      modules/videoio/src/videoio_registry.hpp
  99. 14
      modules/videoio/test/test_ffmpeg.cpp
  100. 2
      modules/viz/CMakeLists.txt
  101. Some files were not shown because too many files have changed in this diff Show More

@ -32,7 +32,7 @@ endif()
option(ENABLE_PIC "Generate position independent code (necessary for shared libraries)" TRUE)
set(CMAKE_POSITION_INDEPENDENT_CODE ${ENABLE_PIC})
# Following block can break build in case of cross-compilng
# Following block can break build in case of cross-compiling
# but CMAKE_CROSSCOMPILING variable will be set only on project(OpenCV) command
# so we will try to detect cross-compiling by the presence of CMAKE_TOOLCHAIN_FILE
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
@ -43,17 +43,17 @@ if(NOT DEFINED CMAKE_INSTALL_PREFIX)
else()
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation Directory")
endif()
else(NOT CMAKE_TOOLCHAIN_FILE)
else()
#Android: set output folder to ${CMAKE_BINARY_DIR}
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are compiled to" )
set(LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are compiled to" )
# any cross-compiling
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory")
endif(NOT CMAKE_TOOLCHAIN_FILE)
endif()
endif()
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
set(WINRT TRUE)
endif(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
endif()
if(WINRT)
add_definitions(-DWINRT -DNO_GETENV)
@ -315,7 +315,7 @@ OCV_OPTION(INSTALL_TESTS "Install accuracy and performance test binar
# OpenCV build options
# ===================================================
OCV_OPTION(ENABLE_CCACHE "Use ccache" (UNIX AND NOT IOS AND (CMAKE_GENERATOR MATCHES "Makefile" OR CMAKE_GENERATOR MATCHES "Ninja")) )
OCV_OPTION(ENABLE_PRECOMPILED_HEADERS "Use precompiled headers" ON IF (NOT IOS AND NOT CMAKE_CROSSCOMPILING) )
OCV_OPTION(ENABLE_PRECOMPILED_HEADERS "Use precompiled headers" ON IF (MSVC OR (NOT IOS AND NOT CMAKE_CROSSCOMPILING) ) )
OCV_OPTION(ENABLE_SOLUTION_FOLDERS "Solution folder in Visual Studio or in other IDEs" (MSVC_IDE OR CMAKE_GENERATOR MATCHES Xcode) )
OCV_OPTION(ENABLE_PROFILING "Enable profiling in the GCC compiler (Add flags: -g -pg)" OFF IF CV_GCC )
OCV_OPTION(ENABLE_COVERAGE "Enable coverage collection with GCov" OFF IF CV_GCC )
@ -339,8 +339,8 @@ OCV_OPTION(CV_ENABLE_INTRINSICS "Use intrinsic-based optimized code" ON )
OCV_OPTION(CV_DISABLE_OPTIMIZATION "Disable explicit optimized code (dispatched code/intrinsics/loop unrolling/etc)" OFF )
OCV_OPTION(CV_TRACE "Enable OpenCV code trace" ON)
OCV_OPTION(ENABLE_PYLINT "Add target with Pylint checks" (${BUILD_DOCS} OR ${BUILD_EXAMPLES}) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )
OCV_OPTION(ENABLE_FLAKE8 "Add target with Python flake8 checker" (${BUILD_DOCS} OR ${BUILD_EXAMPLES}) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )
OCV_OPTION(ENABLE_PYLINT "Add target with Pylint checks" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )
OCV_OPTION(ENABLE_FLAKE8 "Add target with Python flake8 checker" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )
if(ENABLE_IMPL_COLLECTION)
add_definitions(-DCV_COLLECT_IMPL_DATA)
@ -1246,7 +1246,9 @@ if(WITH_1394 OR HAVE_DC1394)
endif()
if(WITH_FFMPEG OR HAVE_FFMPEG)
if(WIN32)
if(OPENCV_FFMPEG_USE_FIND_PACKAGE)
status(" FFMPEG:" HAVE_FFMPEG THEN "YES (find_package)" ELSE "NO (find_package)")
elseif(WIN32)
status(" FFMPEG:" HAVE_FFMPEG THEN "YES (prebuilt binaries)" ELSE NO)
else()
status(" FFMPEG:" HAVE_FFMPEG THEN YES ELSE NO)

@ -1042,7 +1042,7 @@ function(CUDA_COMPUTE_BUILD_PATH path build_path)
# Only deal with CMake style paths from here on out
file(TO_CMAKE_PATH "${path}" bpath)
if (IS_ABSOLUTE "${bpath}")
# Absolute paths are generally unnessary, especially if something like
# Absolute paths are generally unnecessary, especially if something like
# file(GLOB_RECURSE) is used to pick up the files.
string(FIND "${bpath}" "${CMAKE_CURRENT_BINARY_DIR}" _binary_dir_pos)
@ -1065,7 +1065,7 @@ function(CUDA_COMPUTE_BUILD_PATH path build_path)
# Avoid spaces
string(REPLACE " " "_" bpath "${bpath}")
# Strip off the filename. I wait until here to do it, since removin the
# Strip off the filename. I wait until here to do it, since removing the
# basename can make a path that looked like path/../basename turn into
# path/.. (notice the trailing slash).
get_filename_component(bpath "${bpath}" PATH)
@ -1362,7 +1362,7 @@ macro(CUDA_WRAP_SRCS cuda_target format generated_files)
# Bring in the dependencies. Creates a variable CUDA_NVCC_DEPEND #######
cuda_include_nvcc_dependencies(${cmake_dependency_file})
# Convience string for output ###########################################
# Convenience string for output ###########################################
if(CUDA_BUILD_EMULATION)
set(cuda_build_type "Emulation")
else()
@ -1563,7 +1563,7 @@ macro(CUDA_ADD_LIBRARY cuda_target)
${_cmake_options} ${_cuda_shared_flag}
OPTIONS ${_options} )
# Compute the file name of the intermedate link file used for separable
# Compute the file name of the intermediate link file used for separable
# compilation.
CUDA_COMPUTE_SEPARABLE_COMPILATION_OBJECT_FILE_NAME(link_file ${cuda_target} "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}")
@ -1607,7 +1607,7 @@ macro(CUDA_ADD_EXECUTABLE cuda_target)
# Create custom commands and targets for each file.
CUDA_WRAP_SRCS( ${cuda_target} OBJ _generated_files ${_sources} OPTIONS ${_options} )
# Compute the file name of the intermedate link file used for separable
# Compute the file name of the intermediate link file used for separable
# compilation.
CUDA_COMPUTE_SEPARABLE_COMPILATION_OBJECT_FILE_NAME(link_file ${cuda_target} "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}")
@ -1723,7 +1723,7 @@ endmacro()
###############################################################################
###############################################################################
macro(CUDA_BUILD_CLEAN_TARGET)
# Call this after you add all your CUDA targets, and you will get a convience
# Call this after you add all your CUDA targets, and you will get a convenience
# target. You should also make clean after running this target to get the
# build system to generate all the code again.

@ -1,5 +1,5 @@
if("${CMAKE_CXX_COMPILER};${CMAKE_C_COMPILER};${CMAKE_CXX_COMPILER_LAUNCHER}" MATCHES "ccache")
set(CMAKE_COMPILER_IS_CCACHE 1) # FIXIT Avoid setting of CMAKE_ variables
set(CMAKE_COMPILER_IS_CCACHE 1) # TODO: FIXIT Avoid setting of CMAKE_ variables
set(OPENCV_COMPILER_IS_CCACHE 1)
endif()
function(access_CMAKE_COMPILER_IS_CCACHE)

@ -38,8 +38,7 @@ set(INF_ENGINE_INCLUDE_DIRS "${INF_ENGINE_ROOT_DIR}/include" CACHE PATH "Path to
if(NOT INF_ENGINE_ROOT_DIR
OR NOT EXISTS "${INF_ENGINE_ROOT_DIR}"
OR NOT EXISTS "${INF_ENGINE_INCLUDE_DIRS}"
OR NOT EXISTS "${INF_ENGINE_INCLUDE_DIRS}/inference_engine.hpp"
OR NOT EXISTS "${INF_ENGINE_ROOT_DIR}/include/inference_engine.hpp"
)
ie_fail()
endif()
@ -49,10 +48,7 @@ set(INF_ENGINE_LIBRARIES "")
set(ie_lib_list inference_engine)
link_directories(
${INTEL_CVSDK_DIR}/external/mklml_lnx/lib
${INTEL_CVSDK_DIR}/inference_engine/external/mklml_lnx/lib
${INTEL_CVSDK_DIR}/inference_engine/external/mkltiny_lnx/lib
${INTEL_CVSDK_DIR}/external/cldnn/lib
${INTEL_CVSDK_DIR}/inference_engine/external/cldnn/lib
)

@ -43,7 +43,7 @@ endif(WITH_IPP_A)
if(WITH_CUDA)
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVDetectCUDA.cmake")
if(NOT HAVE_CUDA)
message(WARNING "OpenCV is not able to find/confidure CUDA SDK (required by WITH_CUDA).
message(WARNING "OpenCV is not able to find/configure CUDA SDK (required by WITH_CUDA).
CUDA support will be disabled in OpenCV build.
To eliminate this warning remove WITH_CUDA=ON CMake configuration option.
")

@ -212,12 +212,23 @@ endif(WITH_XIMEA)
# --- FFMPEG ---
ocv_clear_vars(HAVE_FFMPEG)
if(WITH_FFMPEG)
if(WIN32 AND NOT ARM)
if(WITH_FFMPEG) # try FFmpeg autodetection
if(OPENCV_FFMPEG_USE_FIND_PACKAGE)
if(OPENCV_FFMPEG_USE_FIND_PACKAGE STREQUAL "1" OR OPENCV_FFMPEG_USE_FIND_PACKAGE STREQUAL "ON")
set(OPENCV_FFMPEG_USE_FIND_PACKAGE "FFMPEG")
endif()
find_package(${OPENCV_FFMPEG_USE_FIND_PACKAGE}) # Required components: AVCODEC AVFORMAT AVUTIL SWSCALE
if(FFMPEG_FOUND OR FFmpeg_FOUND)
set(HAVE_FFMPEG TRUE)
else()
message(STATUS "Can't find FFmpeg via find_package(${OPENCV_FFMPEG_USE_FIND_PACKAGE})")
endif()
elseif(WIN32 AND NOT ARM AND NOT OPENCV_FFMPEG_SKIP_DOWNLOAD)
include("${OpenCV_SOURCE_DIR}/3rdparty/ffmpeg/ffmpeg.cmake")
download_win_ffmpeg(FFMPEG_CMAKE_SCRIPT)
if(FFMPEG_CMAKE_SCRIPT)
set(HAVE_FFMPEG TRUE)
set(HAVE_FFMPEG_WRAPPER 1)
include("${FFMPEG_CMAKE_SCRIPT}")
endif()
elseif(PKG_CONFIG_FOUND)
@ -226,27 +237,29 @@ if(WITH_FFMPEG)
if(FFMPEG_libavresample_FOUND)
ocv_append_build_options(FFMPEG FFMPEG_libavresample)
endif()
if(HAVE_FFMPEG)
try_compile(__VALID_FFMPEG
"${OpenCV_BINARY_DIR}"
"${OpenCV_SOURCE_DIR}/cmake/checks/ffmpeg_test.cpp"
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FFMPEG_INCLUDE_DIRS}"
"-DLINK_DIRECTORIES:STRING=${FFMPEG_LIBRARY_DIRS}"
"-DLINK_LIBRARIES:STRING=${FFMPEG_LIBRARIES}"
OUTPUT_VARIABLE TRY_OUT
)
if(NOT __VALID_FFMPEG)
#message(FATAL_ERROR "FFMPEG: test check build log:\n${TRY_OUT}")
message(STATUS "WARNING: Can't build ffmpeg test code")
set(HAVE_FFMPEG FALSE)
else()
ocv_append_build_options(VIDEOIO FFMPEG)
endif()
endif()
else()
message(STATUS "Can't find ffmpeg - 'pkg-config' utility is missing")
endif()
endif(WITH_FFMPEG)
endif()
if(HAVE_FFMPEG
AND NOT HAVE_FFMPEG_WRAPPER
)
try_compile(__VALID_FFMPEG
"${OpenCV_BINARY_DIR}"
"${OpenCV_SOURCE_DIR}/cmake/checks/ffmpeg_test.cpp"
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FFMPEG_INCLUDE_DIRS}"
"-DLINK_DIRECTORIES:STRING=${FFMPEG_LIBRARY_DIRS}"
"-DLINK_LIBRARIES:STRING=${FFMPEG_LIBRARIES}"
OUTPUT_VARIABLE TRY_OUT
)
if(NOT __VALID_FFMPEG)
#message(FATAL_ERROR "FFMPEG: test check build log:\n${TRY_OUT}")
message(STATUS "WARNING: Can't build ffmpeg test code")
set(HAVE_FFMPEG FALSE)
else()
ocv_append_build_options(VIDEOIO FFMPEG)
endif()
endif()
# --- VideoInput/DirectShow ---
if(WITH_DSHOW)

@ -455,7 +455,7 @@ function(__ocv_sort_modules_by_deps __lst)
set(${__lst} "${result};${result_extra}" PARENT_SCOPE)
endfunction()
# resolve dependensies
# resolve dependencies
function(__ocv_resolve_dependencies)
foreach(m ${OPENCV_MODULES_DISABLED_USER})
set(HAVE_${m} OFF CACHE INTERNAL "Module ${m} will not be built in current configuration")
@ -727,7 +727,7 @@ macro(ocv_set_module_sources)
endif()
endforeach()
# the hacky way to embeed any files into the OpenCV without modification of its build system
# the hacky way to embed any files into the OpenCV without modification of its build system
if(COMMAND ocv_get_module_external_sources)
ocv_get_module_external_sources()
endif()
@ -958,7 +958,7 @@ macro(_ocv_create_module)
target_compile_definitions(${the_module} PRIVATE CVAPI_EXPORTS)
endif()
# For dynamic link numbering convenions
# For dynamic link numbering conventions
if(NOT ANDROID)
# Android SDK build scripts can include only .so files into final .apk
# As result we should not set version properties for Android

@ -383,7 +383,7 @@ MACRO(ADD_NATIVE_PRECOMPILED_HEADER _targetName _input)
# For Xcode, cmake needs my patch to process
# GCC_PREFIX_HEADER and GCC_PRECOMPILE_PREFIX_HEADER as target properties
# When buiding out of the tree, precompiled may not be located
# When building out of the tree, precompiled may not be located
# Use full path instead.
GET_FILENAME_COMPONENT(fullPath ${_input} ABSOLUTE)

@ -20,6 +20,21 @@
volume = {34},
number = {7}
}
@INPROCEEDINGS{Arandjelovic:2012:TTE:2354409.2355123,
author = {Arandjelovic, Relja},
title = {Three Things Everyone Should Know to Improve Object Retrieval},
booktitle = {Proceedings of the 2012 IEEE Conference on Computer Vision and Pattern Recognition (CVPR)},
series = {CVPR '12},
year = {2012},
isbn = {978-1-4673-1226-4},
pages = {2911--2918},
numpages = {8},
url = {http://dl.acm.org/citation.cfm?id=2354409.2355123},
acmid = {2355123},
publisher = {IEEE Computer Society},
address = {Washington, DC, USA},
keywords = {Vectors,Visualization,Kernel,Standards,Support vector machines,Indexes,Euclidean distance},
}
@ARTICLE{BA83,
author = {Burt, Peter J and Adelson, Edward H},
title = {A multiresolution spline with application to image mosaics},
@ -515,6 +530,25 @@
volume = {1},
organization = {IEEE}
}
@ARTICLE{Lowe:2004:DIF:993451.996342,
author = {Lowe, David G.},
title = {Distinctive Image Features from Scale-Invariant Keypoints},
journal = {Int. J. Comput. Vision},
issue_date = {November 2004},
volume = {60},
number = {2},
month = nov,
year = {2004},
issn = {0920-5691},
pages = {91--110},
numpages = {20},
url = {https://doi.org/10.1023/B:VISI.0000029664.99615.94},
doi = {10.1023/B:VISI.0000029664.99615.94},
acmid = {996342},
publisher = {Kluwer Academic Publishers},
address = {Hingham, MA, USA},
keywords = {image matching, invariant features, object recognition, scale invariance},
}
@INPROCEEDINGS{Lucas81,
author = {Lucas, Bruce D and Kanade, Takeo and others},
title = {An iterative image registration technique with an application to stereo vision.},

@ -3,6 +3,7 @@ import sys
import logging
import os
import re
from pprint import pprint
import traceback
@ -17,12 +18,20 @@ except ImportError:
def load_html_file(file_dir):
""" Uses BeautifulSoup to load an html """
with open(file_dir, 'rb') as fp:
soup = BeautifulSoup(fp, 'html.parser')
data = fp.read()
if os.name == 'nt' or sys.version_info[0] == 3:
data = data.decode(encoding='utf-8', errors='strict')
data = re.sub(r'(\>)([ ]+)', lambda match: match.group(1) + ('!space!' * len(match.group(2))), data)
data = re.sub(r'([ ]+)(\<)', lambda match: ('!space!' * len(match.group(1))) + match.group(2), data)
if os.name == 'nt' or sys.version_info[0] == 3:
data = data.encode('utf-8', 'ignore')
soup = BeautifulSoup(data, 'html.parser')
return soup
def update_html(file, soup):
s = str(soup)
if os.name == 'nt' or sys.version_info[0] == 3: # if Windows
s = s.replace('!space!', ' ')
if os.name == 'nt' or sys.version_info[0] == 3:
s = s.encode('utf-8', 'ignore')
with open(file, 'wb') as f:
f.write(s)

@ -10,74 +10,35 @@ In this tutorial you will learn how to:
to the keypoints. Specifically:
- Use cv::xfeatures2d::SURF and its function cv::xfeatures2d::SURF::compute to perform the
required calculations.
- Use a @ref cv::BFMatcher to match the features vector
- Use a @ref cv::DescriptorMatcher to match the features vector
- Use the function @ref cv::drawMatches to draw the detected matches.
\warning You need the <a href="https://github.com/opencv/opencv_contrib">OpenCV contrib modules</a> to be able to use the SURF features
(alternatives are ORB, KAZE, ... features).
Theory
------
Code
----
This tutorial code's is shown lines below.
@code{.cpp}
#include <stdio.h>
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/xfeatures2d.hpp"
using namespace cv;
using namespace cv::xfeatures2d;
void readme();
/* @function main */
int main( int argc, char** argv )
{
if( argc != 3 )
{ return -1; }
Mat img_1 = imread( argv[1], IMREAD_GRAYSCALE );
Mat img_2 = imread( argv[2], IMREAD_GRAYSCALE );
if( !img_1.data || !img_2.data )
{ return -1; }
//-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
int minHessian = 400;
Ptr<SURF> detector = SURF::create();
detector->setHessianThreshold(minHessian);
std::vector<KeyPoint> keypoints_1, keypoints_2;
Mat descriptors_1, descriptors_2;
detector->detectAndCompute( img_1, Mat(), keypoints_1, descriptors_1 );
detector->detectAndCompute( img_2, Mat(), keypoints_2, descriptors_2 );
//-- Step 2: Matching descriptor vectors with a brute force matcher
BFMatcher matcher(NORM_L2);
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );
//-- Draw matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2, matches, img_matches );
//-- Show detected matches
imshow("Matches", img_matches );
waitKey(0);
return 0;
}
/* @function readme */
void readme()
{ std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
@endcode
@add_toggle_cpp
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/features2D/feature_description/SURF_matching_Demo.cpp)
@include samples/cpp/tutorial_code/features2D/feature_description/SURF_matching_Demo.cpp
@end_toggle
@add_toggle_java
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/features2D/feature_description/SURFMatchingDemo.java)
@include samples/java/tutorial_code/features2D/feature_description/SURFMatchingDemo.java
@end_toggle
@add_toggle_python
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/features2D/feature_description/SURF_matching_Demo.py)
@include samples/python/tutorial_code/features2D/feature_description/SURF_matching_Demo.py
@end_toggle
Explanation
-----------

@ -11,67 +11,32 @@ In this tutorial you will learn how to:
detection process
- Use the function @ref cv::drawKeypoints to draw the detected keypoints
\warning You need the <a href="https://github.com/opencv/opencv_contrib">OpenCV contrib modules</a> to be able to use the SURF features
(alternatives are ORB, KAZE, ... features).
Theory
------
Code
----
This tutorial code's is shown lines below.
@code{.cpp}
#include <stdio.h>
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/xfeatures2d.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
using namespace cv::xfeatures2d;
void readme();
/* @function main */
int main( int argc, char** argv )
{
if( argc != 3 )
{ readme(); return -1; }
Mat img_1 = imread( argv[1], IMREAD_GRAYSCALE );
Mat img_2 = imread( argv[2], IMREAD_GRAYSCALE );
if( !img_1.data || !img_2.data )
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; }
//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 400;
Ptr<SURF> detector = SURF::create( minHessian );
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector->detect( img_1, keypoints_1 );
detector->detect( img_2, keypoints_2 );
//-- Draw keypoints
Mat img_keypoints_1; Mat img_keypoints_2;
drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
drawKeypoints( img_2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
//-- Show detected (drawn) keypoints
imshow("Keypoints 1", img_keypoints_1 );
imshow("Keypoints 2", img_keypoints_2 );
waitKey(0);
@add_toggle_cpp
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/features2D/feature_detection/SURF_detection_Demo.cpp)
@include samples/cpp/tutorial_code/features2D/feature_detection/SURF_detection_Demo.cpp
@end_toggle
return 0;
}
@add_toggle_java
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/features2D/feature_detection/SURFDetectionDemo.java)
@include samples/java/tutorial_code/features2D/feature_detection/SURFDetectionDemo.java
@end_toggle
/* @function readme */
void readme()
{ std::cout << " Usage: ./SURF_detector <img1> <img2>" << std::endl; }
@endcode
@add_toggle_python
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/features2D/feature_detection/SURF_detection_Demo.py)
@include samples/python/tutorial_code/features2D/feature_detection/SURF_detection_Demo.py
@end_toggle
Explanation
-----------
@ -79,10 +44,10 @@ Explanation
Result
------
-# Here is the result of the feature detection applied to the first image:
-# Here is the result of the feature detection applied to the `box.png` image:
![](images/Feature_Detection_Result_a.jpg)
-# And here is the result for the second image:
-# And here is the result for the `box_in_scene.png` image:
![](images/Feature_Detection_Result_b.jpg)

@ -9,114 +9,57 @@ In this tutorial you will learn how to:
- Use the @ref cv::FlannBasedMatcher interface in order to perform a quick and efficient matching
by using the @ref flann module
\warning You need the <a href="https://github.com/opencv/opencv_contrib">OpenCV contrib modules</a> to be able to use the SURF features
(alternatives are ORB, KAZE, ... features).
Theory
------
Classical feature descriptors (SIFT, SURF, ...) are usually compared and matched using the Euclidean distance (or L2-norm).
Since SIFT and SURF descriptors represent the histogram of oriented gradient (of the Haar wavelet response for SURF)
in a neighborhood, alternatives of the Euclidean distance are histogram-based metrics (\f$ \chi^{2} \f$, Earth Mover’s Distance (EMD), ...).
Arandjelovic et al. proposed in @cite Arandjelovic:2012:TTE:2354409.2355123 to extend to the RootSIFT descriptor:
> a square root (Hellinger) kernel instead of the standard Euclidean distance to measure the similarity between SIFT descriptors
> leads to a dramatic performance boost in all stages of the pipeline.
Binary descriptors (ORB, BRISK, ...) are matched using the <a href="https://en.wikipedia.org/wiki/Hamming_distance">Hamming distance</a>.
This distance is equivalent to count the number of different elements for binary strings (population count after applying a XOR operation):
\f[ d_{hamming} \left ( a,b \right ) = \sum_{i=0}^{n-1} \left ( a_i \oplus b_i \right ) \f]
To filter the matches, Lowe proposed in @cite Lowe:2004:DIF:993451.996342 to use a distance ratio test to try to eliminate false matches.
The distance ratio between the two nearest matches of a considered keypoint is computed and it is a good match when this value is below
a thresold. Indeed, this ratio allows helping to discriminate between ambiguous matches (distance ratio between the two nearest neighbors is
close to one) and well discriminated matches. The figure below from the SIFT paper illustrates the probability that a match is correct
based on the nearest-neighbor distance ratio test.
![](images/Feature_FlannMatcher_Lowe_ratio_test.png)
Alternative or additional filterering tests are:
- cross check test (good match \f$ \left( f_a, f_b \right) \f$ if feature \f$ f_b \f$ is the best match for \f$ f_a \f$ in \f$ I_b \f$
and feature \f$ f_a \f$ is the best match for \f$ f_b \f$ in \f$ I_a \f$)
- geometric test (eliminate matches that do not fit to a geometric model, e.g. RANSAC or robust homography for planar objects)
Code
----
This tutorial code's is shown lines below.
@code{.cpp}
/*
* @file SURF_FlannMatcher
* @brief SURF detector + descriptor + FLANN Matcher
* @author A. Huaman
*/
#include <stdio.h>
#include <iostream>
#include <stdio.h>
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/xfeatures2d.hpp"
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
void readme();
/*
* @function main
* @brief Main function
*/
int main( int argc, char** argv )
{
if( argc != 3 )
{ readme(); return -1; }
Mat img_1 = imread( argv[1], IMREAD_GRAYSCALE );
Mat img_2 = imread( argv[2], IMREAD_GRAYSCALE );
if( !img_1.data || !img_2.data )
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; }
//-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
int minHessian = 400;
Ptr<SURF> detector = SURF::create();
detector->setHessianThreshold(minHessian);
std::vector<KeyPoint> keypoints_1, keypoints_2;
Mat descriptors_1, descriptors_2;
detector->detectAndCompute( img_1, Mat(), keypoints_1, descriptors_1 );
detector->detectAndCompute( img_2, Mat(), keypoints_2, descriptors_2 );
//-- Step 2: Matching descriptor vectors using FLANN matcher
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_1.rows; i++ )
{ double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
printf("-- Max dist : %f \n", max_dist );
printf("-- Min dist : %f \n", min_dist );
//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist,
//-- or a small arbitrary value ( 0.02 ) in the event that min_dist is very
//-- small)
//-- PS.- radiusMatch can also be used here.
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptors_1.rows; i++ )
{ if( matches[i].distance <= max(2*min_dist, 0.02) )
{ good_matches.push_back( matches[i]); }
}
//-- Draw only "good" matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//-- Show detected matches
imshow( "Good Matches", img_matches );
for( int i = 0; i < (int)good_matches.size(); i++ )
{ printf( "-- Good Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); }
waitKey(0);
return 0;
}
/*
* @function readme
*/
void readme()
{ std::cout << " Usage: ./SURF_FlannMatcher <img1> <img2>" << std::endl; }
@endcode
@add_toggle_cpp
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.cpp)
@include samples/cpp/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.cpp
@end_toggle
@add_toggle_java
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/features2D/feature_flann_matcher/SURFFLANNMatchingDemo.java)
@include samples/java/tutorial_code/features2D/feature_flann_matcher/SURFFLANNMatchingDemo.java
@end_toggle
@add_toggle_python
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.py)
@include samples/python/tutorial_code/features2D/feature_flann_matcher/SURF_FLANN_matching_Demo.py
@end_toggle
Explanation
-----------
@ -124,10 +67,6 @@ Explanation
Result
------
-# Here is the result of the feature detection applied to the first image:
![](images/Featur_FlannMatcher_Result.jpg)
-# Additionally, we get as console output the keypoints filtered:
- Here is the result of the SURF feature matching using the distance ratio test:
![](images/Feature_FlannMatcher_Keypoints_Result.jpg)
![](images/Feature_FlannMatcher_Result_ratio_test.jpg)

@ -9,125 +9,40 @@ In this tutorial you will learn how to:
- Use the function @ref cv::findHomography to find the transform between matched keypoints.
- Use the function @ref cv::perspectiveTransform to map the points.
\warning You need the <a href="https://github.com/opencv/opencv_contrib">OpenCV contrib modules</a> to be able to use the SURF features
(alternatives are ORB, KAZE, ... features).
Theory
------
Code
----
This tutorial code's is shown lines below.
@code{.cpp}
#include <stdio.h>
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/calib3d.hpp"
#include "opencv2/xfeatures2d.hpp"
using namespace cv;
using namespace cv::xfeatures2d;
void readme();
/* @function main */
int main( int argc, char** argv )
{
if( argc != 3 )
{ readme(); return -1; }
Mat img_object = imread( argv[1], IMREAD_GRAYSCALE );
Mat img_scene = imread( argv[2], IMREAD_GRAYSCALE );
if( !img_object.data || !img_scene.data )
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; }
//-- Step 1: Detect the keypoints and extract descriptors using SURF
int minHessian = 400;
Ptr<SURF> detector = SURF::create( minHessian );
std::vector<KeyPoint> keypoints_object, keypoints_scene;
Mat descriptors_object, descriptors_scene;
detector->detectAndCompute( img_object, Mat(), keypoints_object, descriptors_object );
detector->detectAndCompute( img_scene, Mat(), keypoints_scene, descriptors_scene );
//-- Step 2: Matching descriptor vectors using FLANN matcher
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_object, descriptors_scene, matches );
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_object.rows; i++ )
{ double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
printf("-- Max dist : %f \n", max_dist );
printf("-- Min dist : %f \n", min_dist );
//-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptors_object.rows; i++ )
{ if( matches[i].distance <= 3*min_dist )
{ good_matches.push_back( matches[i]); }
}
Mat img_matches;
drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//-- Localize the object
std::vector<Point2f> obj;
std::vector<Point2f> scene;
for( size_t i = 0; i < good_matches.size(); i++ )
{
//-- Get the keypoints from the good matches
obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
}
Mat H = findHomography( obj, scene, RANSAC );
//-- Get the corners from the image_1 ( the object to be "detected" )
std::vector<Point2f> obj_corners(4);
obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 );
obj_corners[2] = cvPoint( img_object.cols, img_object.rows ); obj_corners[3] = cvPoint( 0, img_object.rows );
std::vector<Point2f> scene_corners(4);
perspectiveTransform( obj_corners, scene_corners, H);
//-- Draw lines between the corners (the mapped object in the scene - image_2 )
line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0), scene_corners[1] + Point2f( img_object.cols, 0), Scalar(0, 255, 0), 4 );
line( img_matches, scene_corners[1] + Point2f( img_object.cols, 0), scene_corners[2] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
line( img_matches, scene_corners[2] + Point2f( img_object.cols, 0), scene_corners[3] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
line( img_matches, scene_corners[3] + Point2f( img_object.cols, 0), scene_corners[0] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
@add_toggle_cpp
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp)
@include samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp
@end_toggle
//-- Show detected matches
imshow( "Good Matches & Object detection", img_matches );
@add_toggle_java
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java)
@include samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java
@end_toggle
waitKey(0);
return 0;
}
@add_toggle_python
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.py)
@include samples/python/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.py
@end_toggle
/* @function readme */
void readme()
{ std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
@endcode
Explanation
-----------
Result
------
-# And here is the result for the detected object (highlighted in green)
- And here is the result for the detected object (highlighted in green). Note that since the homography is estimated with a RANSAC approach,
detected false matches will not impact the homography calculation.
![](images/Feature_Homography_Result.jpg)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 88 KiB

@ -6,39 +6,51 @@ OpenCV.
- @subpage tutorial_harris_detector
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán
Why is it a good idea to track corners? We learn to use the Harris method to detect
corners
Why is it a good idea to track corners? We learn how to use the Harris method to detect
corners.
- @subpage tutorial_good_features_to_track
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán
Where we use an improved method to detect corners more accuratelyI
Where we use an improved method to detect corners more accurately.
- @subpage tutorial_generic_corner_detector
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán
Here you will learn how to use OpenCV functions to make your personalized corner detector!
- @subpage tutorial_corner_subpixeles
*Languages:* C++, Java, Python
- @subpage tutorial_corner_subpixels
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán
Is pixel resolution enough? Here we learn a simple method to improve our accuracy.
Is pixel resolution enough? Here we learn a simple method to improve our corner location accuracy.
- @subpage tutorial_feature_detection
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán
@ -47,6 +59,8 @@ OpenCV.
- @subpage tutorial_feature_description
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán
@ -55,6 +69,8 @@ OpenCV.
- @subpage tutorial_feature_flann_matcher
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán
@ -63,6 +79,8 @@ OpenCV.
- @subpage tutorial_feature_homography
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán

@ -1,32 +0,0 @@
Detecting corners location in subpixeles {#tutorial_corner_subpixeles}
========================================
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function @ref cv::cornerSubPix to find more exact corner positions (more exact
than integer pixels).
Theory
------
Code
----
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp)
@include samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp
Explanation
-----------
Result
------
![](images/Corner_Subpixeles_Original_Image.jpg)
Here is the result:
![](images/Corner_Subpixeles_Result.jpg)

@ -0,0 +1,46 @@
Detecting corners location in subpixels {#tutorial_corner_subpixels}
=======================================
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function @ref cv::cornerSubPix to find more exact corner positions (more exact
than integer pixels).
Theory
------
Code
----
@add_toggle_cpp
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp)
@include samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp
@end_toggle
@add_toggle_java
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/TrackingMotion/corner_subpixels/CornerSubPixDemo.java)
@include samples/java/tutorial_code/TrackingMotion/corner_subpixels/CornerSubPixDemo.java
@end_toggle
@add_toggle_python
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/TrackingMotion/corner_subpixels/cornerSubPix_Demo.py)
@include samples/python/tutorial_code/TrackingMotion/corner_subpixels/cornerSubPix_Demo.py
@end_toggle
Explanation
-----------
Result
------
![](images/Corner_Subpixels_Original_Image.jpg)
Here is the result:
![](images/Corner_Subpixels_Result.jpg)

@ -1,5 +1,5 @@
Creating yor own corner detector {#tutorial_generic_corner_detector}
================================
Creating your own corner detector {#tutorial_generic_corner_detector}
=================================
Goal
----
@ -10,7 +10,7 @@ In this tutorial you will learn how to:
to determine if a pixel is a corner.
- Use the OpenCV function @ref cv::cornerMinEigenVal to find the minimum eigenvalues for corner
detection.
- To implement our own version of the Harris detector as well as the Shi-Tomasi detector, by using
- Implement our own version of the Harris detector as well as the Shi-Tomasi detector, by using
the two functions above.
Theory
@ -19,10 +19,26 @@ Theory
Code
----
@add_toggle_cpp
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp)
@include cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp
@include samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp
@end_toggle
@add_toggle_java
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/TrackingMotion/generic_corner_detector/CornerDetectorDemo.java)
@include samples/java/tutorial_code/TrackingMotion/generic_corner_detector/CornerDetectorDemo.java
@end_toggle
@add_toggle_python
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/TrackingMotion/generic_corner_detector/cornerDetector_Demo.py)
@include samples/python/tutorial_code/TrackingMotion/generic_corner_detector/cornerDetector_Demo.py
@end_toggle
Explanation
-----------

@ -6,7 +6,7 @@ Goal
In this tutorial you will learn how to:
- Use the function @ref cv::goodFeaturesToTrack to detect corners using the Shi-Tomasi method.
- Use the function @ref cv::goodFeaturesToTrack to detect corners using the Shi-Tomasi method (@cite Shi94).
Theory
------
@ -14,9 +14,23 @@ Theory
Code
----
@add_toggle_cpp
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp)
@include samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp
@end_toggle
@add_toggle_java
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/TrackingMotion/good_features_to_track/GoodFeaturesToTrackDemo.java)
@include samples/java/tutorial_code/TrackingMotion/good_features_to_track/GoodFeaturesToTrackDemo.java
@end_toggle
@add_toggle_python
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/TrackingMotion/good_features_to_track/goodFeaturesToTrack_Demo.py)
@include samples/python/tutorial_code/TrackingMotion/good_features_to_track/goodFeaturesToTrack_Demo.py
@end_toggle
Explanation
-----------
@ -24,4 +38,4 @@ Explanation
Result
------
![](images/Feature_Detection_Result_a.jpg)
![](images/good_features_to_track_Shi_Tomasi.jpg)

@ -118,9 +118,23 @@ In this tutorial we will study the *corner* features, specifically.
Code
----
@add_toggle_cpp
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp)
@include samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp
@end_toggle
@add_toggle_java
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/TrackingMotion/harris_detector/CornerHarrisDemo.java)
@include samples/java/tutorial_code/TrackingMotion/harris_detector/CornerHarrisDemo.java
@end_toggle
@add_toggle_python
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/TrackingMotion/harris_detector/cornerHarris_Demo.py)
@include samples/python/tutorial_code/TrackingMotion/harris_detector/cornerHarris_Demo.py
@end_toggle
Explanation
-----------

@ -37,7 +37,7 @@ Here is the general structure of the program:
the same with **myWindow**. If the name does not exist, a new window is created.
@code{.cpp}
/// Access window via its name
viz::Viz3d sameWindow = viz::get("Viz Demo");
viz::Viz3d sameWindow = viz::getWindowByName("Viz Demo");
@endcode
- Start a controlled event loop. Once it starts, **wasStopped** is set to false. Inside the while
loop, in each iteration, **spinOnce** is called to prevent event loop from completely stopping.

@ -76,13 +76,17 @@
#include <stdarg.h>
#include <vector>
using namespace cv;
using namespace std;
#include "opencv2/core/utility.hpp"
#include <opencv2/core/utils/logger.defines.hpp>
//#define ENABLE_TRIM_COL_ROW
//#define DEBUG_CHESSBOARD
//#undef CV_LOG_STRIP_LEVEL
//#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
#include <opencv2/core/utils/logger.hpp>
#ifdef DEBUG_CHESSBOARD
static int PRINTF( const char* fmt, ... )
{
@ -94,17 +98,34 @@ static int PRINTF( const char* fmt, ... )
#define PRINTF(...)
#endif
using namespace cv;
using namespace std;
//=====================================================================================
// Implementation for the enhanced calibration object detection
//=====================================================================================
#define MAX_CONTOUR_APPROX 7
#define USE_CV_FINDCONTOURS // switch between cv::findContours() and legacy C API
#ifdef USE_CV_FINDCONTOURS
struct QuadCountour {
Point pt[4];
int parent_contour;
QuadCountour(const Point pt_[4], int parent_contour_) :
parent_contour(parent_contour_)
{
pt[0] = pt_[0]; pt[1] = pt_[1]; pt[2] = pt_[2]; pt[3] = pt_[3];
}
};
#else
struct CvContourEx
{
CV_CONTOUR_FIELDS()
int counter;
};
#endif
//=====================================================================================
@ -517,7 +538,11 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
int max_quad_buf_size = 0;
cvFree(&quads);
cvFree(&corners);
#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);
@ -583,7 +608,11 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
int max_quad_buf_size = 0;
cvFree(&quads);
cvFree(&corners);
#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);
@ -1736,7 +1765,6 @@ static int
icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners,
CvMemStorage *storage, const cv::Mat & image_, int flags, int *max_quad_buf_size )
{
CvMat image_old(image_), *image = &image_old;
int quad_count = 0;
cv::Ptr<CvMemStorage> temp_storage;
@ -1746,17 +1774,144 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners,
if( out_corners )
*out_corners = 0;
// 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<std::vector<Point> > contours;
std::vector<Vec4i> hierarchy;
cv::findContours(image_, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
if (contours.empty())
{
CV_LOG_DEBUG(NULL, "calib3d(chessboard): cv::findContours() returns no contours");
*max_quad_buf_size = 0;
return 0;
}
std::vector<int> contour_child_counter(contours.size(), 0);
int boardIdx = -1;
std::vector<QuadCountour> contour_quads;
for (int idx = (int)(contours.size() - 1); idx >= 0; --idx)
{
int parentIdx = hierarchy[idx][3];
if (hierarchy[idx][2] != -1 || parentIdx == -1) // holes only (no child contours and with parent)
continue;
const std::vector<Point>& contour = contours[idx];
Rect contour_rect = boundingRect(contour);
if (contour_rect.area() < min_size)
continue;
std::vector<Point> approx_contour;
const int min_approx_level = 1, max_approx_level = MAX_CONTOUR_APPROX;
for (int approx_level = min_approx_level; approx_level <= max_approx_level; approx_level++ )
{
approxPolyDP(contour, approx_contour, (float)approx_level, true);
if (approx_contour.size() == 4)
break;
// we call this again on its own output, because sometimes
// approxPoly() does not simplify as much as it should.
std::vector<Point> approx_contour_tmp;
std::swap(approx_contour, approx_contour_tmp);
approxPolyDP(approx_contour_tmp, approx_contour, (float)approx_level, true);
if (approx_contour.size() == 4)
break;
}
// reject non-quadrangles
if (approx_contour.size() != 4)
continue;
if (!cv::isContourConvex(approx_contour))
continue;
cv::Point pt[4];
for (int i = 0; i < 4; ++i)
pt[i] = approx_contour[i];
CV_LOG_VERBOSE(NULL, 9, "... contours(" << contour_quads.size() << " added):" << pt[0] << " " << pt[1] << " " << pt[2] << " " << pt[3]);
if (filterQuads)
{
double p = cv::arcLength(approx_contour, true);
double area = cv::contourArea(approx_contour, false);
double d1 = sqrt(normL2Sqr<double>(pt[0] - pt[2]));
double d2 = sqrt(normL2Sqr<double>(pt[1] - pt[3]));
// philipg. Only accept those quadrangles which are more square
// than rectangular and which are big enough
double d3 = sqrt(normL2Sqr<double>(pt[0] - pt[1]));
double d4 = sqrt(normL2Sqr<double>(pt[1] - pt[2]));
if (!(d3*4 > d4 && d4*4 > d3 && d3*d4 < area*1.5 && area > min_size &&
d1 >= 0.15 * p && d2 >= 0.15 * p))
continue;
}
contour_child_counter[parentIdx]++;
if (boardIdx != parentIdx && (boardIdx < 0 || contour_child_counter[boardIdx] < contour_child_counter[parentIdx]))
boardIdx = parentIdx;
contour_quads.push_back(QuadCountour(pt, parentIdx));
}
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]));
// Create array of quads structures
for(int idx = 0; idx < (int)contour_quads.size(); 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];
memset(corner, 0, sizeof(*corner));
corner->pt = qc.pt[i];
q->corners[i] = corner;
}
q->edge_len = FLT_MAX;
for (int i = 0; i < 4; ++i)
{
// TODO simplify with normL2Sqr<float>()
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;
}
quad_count++;
}
#else // use legacy API: cvStartFindContours / cvFindNextContour / cvEndFindContours
CvMat image_old(image_), *image = &image_old;
CvSeq *src_contour = 0;
CvSeq *root;
CvContourEx* board = 0;
CvContourScanner scanner;
int i, idx, min_size;
int i, idx;
CV_Assert( out_corners && out_quads );
// empiric bound for minimal allowed perimeter for squares
min_size = 25; //cvRound( image->cols * image->rows * .03 * 0.01 * 0.92 );
// 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 );
@ -1820,9 +1975,9 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners,
dx = pt[1].x - pt[2].x;
dy = pt[1].y - pt[2].y;
d4 = sqrt(dx*dx + dy*dy);
if( !(flags & CV_CALIB_CB_FILTER_QUADS) ||
if (!filterQuads ||
(d3*4 > d4 && d4*4 > d3 && d3*d4 < area*1.5 && area > min_size &&
d1 >= 0.15 * p && d2 >= 0.15 * p) )
d1 >= 0.15 * p && d2 >= 0.15 * p))
{
CvContourEx* parent = (CvContourEx*)(src_contour->v_prev);
parent->counter++;
@ -1840,7 +1995,8 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners,
cvEndFindContours( &scanner );
// allocate quad & corner buffers
*max_quad_buf_size = MAX(1, (root->total+root->total / 2)) * 2;
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]));
@ -1849,7 +2005,7 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners,
{
CvCBQuad* q = &(*out_quads)[quad_count];
src_contour = *(CvSeq**)cvGetSeqElem( root, idx );
if( (flags & CV_CALIB_CB_FILTER_QUADS) && src_contour->v_prev != (CvSeq*)board )
if (filterQuads && src_contour->v_prev != (CvSeq*)board)
continue;
// reset group ID
@ -1878,6 +2034,11 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners,
}
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);
return quad_count;
}

@ -78,10 +78,7 @@ class RANSACPointSetRegistrator : public PointSetRegistrator
public:
RANSACPointSetRegistrator(const Ptr<PointSetRegistrator::Callback>& _cb=Ptr<PointSetRegistrator::Callback>(),
int _modelPoints=0, double _threshold=0, double _confidence=0.99, int _maxIters=1000)
: cb(_cb), modelPoints(_modelPoints), threshold(_threshold), confidence(_confidence), maxIters(_maxIters)
{
checkPartialSubsets = false;
}
: cb(_cb), modelPoints(_modelPoints), threshold(_threshold), confidence(_confidence), maxIters(_maxIters) {}
int findInliers( const Mat& m1, const Mat& m2, const Mat& model, Mat& err, Mat& mask, double thresh ) const
{
@ -143,17 +140,9 @@ public:
ms1ptr[i*esz1 + k] = m1ptr[idx_i*esz1 + k];
for( k = 0; k < esz2; k++ )
ms2ptr[i*esz2 + k] = m2ptr[idx_i*esz2 + k];
if( checkPartialSubsets && !cb->checkSubset( ms1, ms2, i+1 ))
{
// we may have selected some bad points;
// so, let's remove some of them randomly
i = rng.uniform(0, i+1);
iters++;
continue;
}
i++;
}
if( !checkPartialSubsets && i == modelPoints && !cb->checkSubset(ms1, ms2, i))
if( i == modelPoints && !cb->checkSubset(ms1, ms2, i) )
continue;
break;
}
@ -261,7 +250,6 @@ public:
Ptr<PointSetRegistrator::Callback> cb;
int modelPoints;
bool checkPartialSubsets;
double threshold;
double confidence;
int maxIters;

@ -284,7 +284,39 @@ prefilterXSobel( const Mat& src, Mat& dst, int ftzero )
static const int DISPARITY_SHIFT_16S = 4;
static const int DISPARITY_SHIFT_32S = 8;
template <typename T>
struct dispShiftTemplate
{ };
template<>
struct dispShiftTemplate<short>
{
enum { value = DISPARITY_SHIFT_16S };
};
template<>
struct dispShiftTemplate<int>
{
enum { value = DISPARITY_SHIFT_32S };
};
template <typename T>
inline T dispDescale(int /*v1*/, int /*v2*/, int /*d*/);
template<>
inline short dispDescale(int v1, int v2, int d)
{
return (short)((v1*256 + (d != 0 ? v2*256/d : 0) + 15) >> 4);
}
template <>
inline int dispDescale(int v1, int v2, int d)
{
return (int)(v1*256 + (d != 0 ? v2*256/d : 0)); // no need to add 127, this will be converted to float
}
#if CV_SIMD128
template <typename dType>
static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
Mat& disp, Mat& cost, StereoBMParams& state,
uchar* buf, int _dy0, int _dy1 )
@ -302,7 +334,8 @@ static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
int ftzero = state.preFilterCap;
int textureThreshold = state.textureThreshold;
int uniquenessRatio = state.uniquenessRatio;
short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT_16S);
const int disp_shift = dispShiftTemplate<dType>::value;
dType FILTERED = (dType)((mindisp - 1) << disp_shift);
ushort *sad, *hsad0, *hsad, *hsad_sub;
int *htext;
@ -310,7 +343,7 @@ static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
const uchar* lptr0 = left.ptr() + lofs;
const uchar* rptr0 = right.ptr() + rofs;
const uchar *lptr, *lptr_sub, *rptr;
short* dptr = disp.ptr<short>();
dType* dptr = disp.ptr<dType>();
int sstep = (int)left.step;
int dstep = (int)(disp.step/sizeof(dptr[0]));
int cstep = (height + dy0 + dy1)*ndisp;
@ -527,10 +560,10 @@ static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
{
int p = sad[mind+1], n = sad[mind-1];
d = p + n - 2*sad[mind] + std::abs(p - n);
dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*256/d : 0) + 15) >> 4);
dptr[y*dstep] = dispDescale<dType>(ndisp - mind - 1 + mindisp, p-n, d);
}
else
dptr[y*dstep] = (short)((ndisp - mind - 1 + mindisp)*16);
dptr[y*dstep] = dispDescale<dType>(ndisp - mind - 1 + mindisp, 0, 0);
costptr[y*coststep] = sad[mind];
}
}
@ -540,8 +573,8 @@ static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
template <typename mType>
static void
findStereoCorrespondenceBM( const Mat& left, const Mat& right,
Mat& disp, Mat& cost, const StereoBMParams& state,
uchar* buf, int _dy0, int _dy1, const int disp_shift )
Mat& disp, Mat& cost, const StereoBMParams& state,
uchar* buf, int _dy0, int _dy1 )
{
const int ALIGN = 16;
@ -557,6 +590,7 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
int ftzero = state.preFilterCap;
int textureThreshold = state.textureThreshold;
int uniquenessRatio = state.uniquenessRatio;
const int disp_shift = dispShiftTemplate<mType>::value;
mType FILTERED = (mType)((mindisp - 1) << disp_shift);
#if CV_SIMD128
@ -849,8 +883,8 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
sad[ndisp] = sad[ndisp-2];
int p = sad[mind+1], n = sad[mind-1];
d = p + n - 2*sad[mind] + std::abs(p - n);
dptr[y*dstep] = (mType)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*256/d : 0) + 15)
>> (DISPARITY_SHIFT_32S - disp_shift));
dptr[y*dstep] = dispDescale<mType>(ndisp - mind - 1 + mindisp, p-n, d);
costptr[y*coststep] = sad[mind];
}
}
@ -980,7 +1014,10 @@ struct FindStereoCorrespInvoker : public ParallelLoopBody
int _row0 = std::min(cvRound(range.start * rows / nstripes), rows);
int _row1 = std::min(cvRound(range.end * rows / nstripes), rows);
uchar *ptr = slidingSumBuf->ptr() + range.start * stripeBufSize;
int FILTERED = (state->minDisparity - 1)*16;
int dispShift = disp->type() == CV_16S ? DISPARITY_SHIFT_16S :
DISPARITY_SHIFT_32S;
int FILTERED = (state->minDisparity - 1) << dispShift;
Rect roi = validDisparityRect & Rect(0, _row0, cols, _row1 - _row0);
if( roi.height == 0 )
@ -1008,15 +1045,18 @@ struct FindStereoCorrespInvoker : public ParallelLoopBody
#if CV_SIMD128
if( useSIMD && useShorts )
{
findStereoCorrespondenceBM_SIMD( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
if( disp_i.type() == CV_16S)
findStereoCorrespondenceBM_SIMD<short>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
else
findStereoCorrespondenceBM_SIMD<int>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1);
}
else
#endif
{
if( disp_i.type() == CV_16S )
findStereoCorrespondenceBM<short>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1, DISPARITY_SHIFT_16S );
findStereoCorrespondenceBM<short>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
else
findStereoCorrespondenceBM<int>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1, DISPARITY_SHIFT_32S );
findStereoCorrespondenceBM<int>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
}
if( state->disp12MaxDiff >= 0 )
@ -1104,7 +1144,6 @@ public:
else
disp_shift = DISPARITY_SHIFT_32S;
int FILTERED = (params.minDisparity - 1) << disp_shift;
#ifdef HAVE_OPENCL
@ -1115,6 +1154,9 @@ public:
{
if(ocl_stereobm(left, right, disparr, &params))
{
disp_shift = DISPARITY_SHIFT_16S;
FILTERED = (params.minDisparity - 1) << disp_shift;
if( params.speckleRange >= 0 && params.speckleWindowSize > 0 )
filterSpeckles(disparr.getMat(), FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf);
if (dtype == CV_32F)

@ -556,7 +556,7 @@ int CV_StereoMatchingTest::processStereoMatchingResults( FileStorage& fs, int ca
assert( fs.isOpened() );
assert( trueLeftDisp.type() == CV_32FC1 );
assert( trueRightDisp.empty() || trueRightDisp.type() == CV_32FC1 );
assert( leftDisp.type() == CV_32FC1 && rightDisp.type() == CV_32FC1 );
assert( leftDisp.type() == CV_32FC1 && (rightDisp.empty() || rightDisp.type() == CV_32FC1) );
// get masks for unknown ground truth disparity values
Mat leftUnknMask, rightUnknMask;
@ -791,6 +791,12 @@ protected:
bm->compute( leftImg, rightImg, tempDisp );
tempDisp.convertTo(leftDisp, CV_32F, 1./StereoMatcher::DISP_SCALE);
//check for fixed-type disparity data type
Mat_<float> fixedFloatDisp;
bm->compute( leftImg, rightImg, fixedFloatDisp );
EXPECT_LT(cvtest::norm(fixedFloatDisp, leftDisp, cv::NORM_L2 | cv::NORM_RELATIVE),
0.005 + DBL_EPSILON);
if (params.mindisp != 0)
for (int y = 0; y < leftDisp.rows; y++)
for (int x = 0; x < leftDisp.cols; x++)

@ -532,8 +532,9 @@ CV_EXPORTS_W void convertScaleAbs(InputArray src, OutputArray dst,
/** @brief Converts an array to half precision floating number.
This function converts FP32 (single precision floating point) from/to FP16 (half precision floating point). The input array has to have type of CV_32F or
CV_16S to represent the bit depth. If the input array is neither of them, the function will raise an error.
This function converts FP32 (single precision floating point) from/to FP16 (half precision floating point). CV_16S format is used to represent FP16 data.
There are two use modes (src -> dst): CV_32F -> CV_16S and CV_16S -> CV_32F. The input array has to have type of CV_32F or
CV_16S to represent the bit depth. If the input array is neither of them, the function will raise an error.
The format of half precision floating point is defined in IEEE 754-2008.
@param src input array.

@ -77,11 +77,8 @@ inline
String::String(const std::string& str)
: cstr_(0), len_(0)
{
if (!str.empty())
{
size_t len = str.size();
if (len) memcpy(allocate(len), str.c_str(), len);
}
size_t len = str.size();
if (len) memcpy(allocate(len), str.c_str(), len);
}
inline
@ -99,11 +96,8 @@ inline
String& String::operator = (const std::string& str)
{
deallocate();
if (!str.empty())
{
size_t len = str.size();
if (len) memcpy(allocate(len), str.c_str(), len);
}
size_t len = str.size();
if (len) memcpy(allocate(len), str.c_str(), len);
return *this;
}

@ -1649,7 +1649,7 @@ Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m)
{
return (*this = m.reshape(DataType<_Tp>::channels, m.dims, 0));
}
CV_DbgAssert(DataType<_Tp>::channels == m.channels());
CV_Assert(DataType<_Tp>::channels == m.channels() || m.empty());
m.convertTo(*this, type());
return *this;
}

@ -1372,6 +1372,20 @@ Point_<_Tp> operator / (const Point_<_Tp>& a, double b)
}
template<typename _AccTp> static inline _AccTp normL2Sqr(const Point_<int>& pt);
template<typename _AccTp> static inline _AccTp normL2Sqr(const Point_<int64>& pt);
template<typename _AccTp> static inline _AccTp normL2Sqr(const Point_<float>& pt);
template<typename _AccTp> static inline _AccTp normL2Sqr(const Point_<double>& pt);
template<> inline int normL2Sqr<int>(const Point_<int>& pt) { return pt.dot(pt); }
template<> inline int64 normL2Sqr<int64>(const Point_<int64>& pt) { return pt.dot(pt); }
template<> inline float normL2Sqr<float>(const Point_<float>& pt) { return pt.dot(pt); }
template<> inline double normL2Sqr<double>(const Point_<int>& pt) { return pt.dot(pt); }
template<> inline double normL2Sqr<double>(const Point_<float>& pt) { return pt.ddot(pt); }
template<> inline double normL2Sqr<double>(const Point_<double>& pt) { return pt.ddot(pt); }
//////////////////////////////// 3D Point ///////////////////////////////

@ -1180,6 +1180,12 @@ void cv::compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op)
CV_Assert( op == CMP_LT || op == CMP_LE || op == CMP_EQ ||
op == CMP_NE || op == CMP_GE || op == CMP_GT );
if(_src1.empty() && _src2.empty())
{
_dst.release();
return;
}
bool haveScalar = false;
if ((_src1.isMatx() + _src2.isMatx()) == 1

@ -1304,6 +1304,12 @@ void cv::Mat::convertTo(OutputArray _dst, int _type, double alpha, double beta)
{
CV_INSTRUMENT_REGION()
if( empty() )
{
_dst.release();
return;
}
bool noScale = fabs(alpha-1) < DBL_EPSILON && fabs(beta) < DBL_EPSILON;
if( _type < 0 )

@ -246,13 +246,14 @@ void Mat::copyTo( OutputArray _dst ) const
return;
}
if( empty() )
{
_dst.release();
return;
}
if( _dst.isUMat() )
{
if( empty() )
{
_dst.release();
return;
}
_dst.create( dims, size.p, type() );
UMat dst = _dst.getUMat();
CV_Assert(dst.u != NULL);

@ -42,7 +42,7 @@
#ifndef OPENCV_DNN_HPP
#define OPENCV_DNN_HPP
// This is an umbrealla header to include into you project.
// This is an umbrella header to include into you project.
// We are free to change headers layout in dnn subfolder, so please include
// this header for future compatibility
@ -52,10 +52,10 @@
This module contains:
- API for new layers creation, layers are building bricks of neural networks;
- set of built-in most-useful Layers;
- API to constuct and modify comprehensive neural networks from layers;
- API to construct and modify comprehensive neural networks from layers;
- functionality for loading serialized networks models from different frameworks.
Functionality of this module is designed only for forward pass computations (i. e. network testing).
Functionality of this module is designed only for forward pass computations (i.e. network testing).
A network training is in principle not supported.
@}
*/

@ -58,7 +58,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
You can use both API, but factory API is less convenient for native C++ programming and basically designed for use inside importers (see @ref readNetFromCaffe(), @ref readNetFromTorch(), @ref readNetFromTensorflow()).
Built-in layers partially reproduce functionality of corresponding Caffe and Torch7 layers.
In partuclar, the following layers and Caffe importer were tested to reproduce <a href="http://caffe.berkeleyvision.org/tutorial/layers.html">Caffe</a> functionality:
In particular, the following layers and Caffe importer were tested to reproduce <a href="http://caffe.berkeleyvision.org/tutorial/layers.html">Caffe</a> functionality:
- Convolution
- Deconvolution
- Pooling
@ -108,13 +108,13 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
@f$W_{x?} \in R^{N_h \times N_x}@f$, @f$W_{h?} \in R^{N_h \times N_h}@f$, @f$b_? \in R^{N_h}@f$.
For simplicity and performance purposes we use @f$ W_x = [W_{xi}; W_{xf}; W_{xo}, W_{xg}] @f$
(i.e. @f$W_x@f$ is vertical contacentaion of @f$ W_{x?} @f$), @f$ W_x \in R^{4N_h \times N_x} @f$.
(i.e. @f$W_x@f$ is vertical concatenation of @f$ W_{x?} @f$), @f$ W_x \in R^{4N_h \times N_x} @f$.
The same for @f$ W_h = [W_{hi}; W_{hf}; W_{ho}, W_{hg}], W_h \in R^{4N_h \times N_h} @f$
and for @f$ b = [b_i; b_f, b_o, b_g]@f$, @f$b \in R^{4N_h} @f$.
@param Wh is matrix defining how previous output is transformed to internal gates (i.e. according to abovemtioned notation is @f$ W_h @f$)
@param Wx is matrix defining how current input is transformed to internal gates (i.e. according to abovemtioned notation is @f$ W_x @f$)
@param b is bias vector (i.e. according to abovemtioned notation is @f$ b @f$)
@param Wh is matrix defining how previous output is transformed to internal gates (i.e. according to above mentioned notation is @f$ W_h @f$)
@param Wx is matrix defining how current input is transformed to internal gates (i.e. according to above mentioned notation is @f$ W_x @f$)
@param b is bias vector (i.e. according to above mentioned notation is @f$ b @f$)
*/
CV_DEPRECATED virtual void setWeights(const Mat &Wh, const Mat &Wx, const Mat &b) = 0;
@ -148,7 +148,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* If setUseTimstampsDim() is set to true then @p input[0] should has at least two dimensions with the following shape: [`T`, `N`, `[data dims]`],
* where `T` specifies number of timestamps, `N` is number of independent streams (i.e. @f$ x_{t_0 + t}^{stream} @f$ is stored inside @p input[0][t, stream, ...]).
*
* If setUseTimstampsDim() is set to fase then @p input[0] should contain single timestamp, its shape should has form [`N`, `[data dims]`] with at least one dimension.
* If setUseTimstampsDim() is set to false then @p input[0] should contain single timestamp, its shape should has form [`N`, `[data dims]`] with at least one dimension.
* (i.e. @f$ x_{t}^{stream} @f$ is stored inside @p input[0][stream, ...]).
*/
@ -550,7 +550,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* dst(x, y, c) = \frac{ src(x, y, c) }{norm(c)}
* @f]
*
* Where `x, y` - spatial cooridnates, `c` - channel.
* Where `x, y` - spatial coordinates, `c` - channel.
*
* An every sample in the batch is normalized separately. Optionally,
* output is scaled by the trained parameters.
@ -565,7 +565,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
};
/**
* @brief Resize input 4-dimensional blob by nearest neghbor strategy.
* @brief Resize input 4-dimensional blob by nearest neighbor strategy.
*
* Layer is used to support TensorFlow's resize_nearest_neighbor op.
*/
@ -581,6 +581,12 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
static Ptr<ProposalLayer> create(const LayerParams& params);
};
class CV_EXPORTS CropAndResizeLayer : public Layer
{
public:
static Ptr<Layer> create(const LayerParams& params);
};
//! @}
//! @}
CV__DNN_EXPERIMENTAL_NS_END

@ -81,12 +81,13 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
{
DNN_TARGET_CPU,
DNN_TARGET_OPENCL,
DNN_TARGET_OPENCL_FP16
DNN_TARGET_OPENCL_FP16,
DNN_TARGET_MYRIAD
};
/** @brief This class provides all data needed to initialize layer.
*
* It includes dictionary with scalar params (which can be readed by using Dict interface),
* It includes dictionary with scalar params (which can be read by using Dict interface),
* blob params #blobs and optional meta information: #name and #type of layer instance.
*/
class CV_EXPORTS LayerParams : public Dict
@ -137,7 +138,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* Initialize wrapper from another one. It'll wrap the same host CPU
* memory and mustn't allocate memory on device(i.e. GPU). It might
* has different shape. Use in case of CPU memory reusing for reuse
* associented memory on device too.
* associated memory on device too.
*/
BackendWrapper(const Ptr<BackendWrapper>& base, const MatShape& shape);
@ -345,7 +346,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
/** @brief Create a network from Intel's Model Optimizer intermediate representation.
* @param[in] xml XML configuration file with network's topology.
* @param[in] bin Binary file with trained weights.
* Networks imported from Intel's Model Optimizer are lauched in Intel's Inference Engine
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
* backend.
*/
CV_WRAP static Net readFromModelOptimizer(const String& xml, const String& bin);
@ -401,8 +402,8 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
/** @brief Connects #@p outNum output of the first layer to #@p inNum input of the second layer.
* @param outLayerId identifier of the first layer
* @param inpLayerId identifier of the second layer
* @param outNum number of the first layer output
* @param inpLayerId identifier of the second layer
* @param inpNum number of the second layer input
*/
void connect(int outLayerId, int outNum, int inpLayerId, int inpNum);
@ -563,7 +564,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
*/
CV_WRAP int getLayersCount(const String& layerType) const;
/** @brief Computes bytes number which are requered to store
/** @brief Computes bytes number which are required to store
* all weights and intermediate blobs for model.
* @param netInputShapes vector of shapes for all net inputs.
* @param weights output parameter to store resulting bytes for weights.
@ -583,7 +584,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
const MatShape& netInputShape,
CV_OUT size_t& weights, CV_OUT size_t& blobs) const;
/** @brief Computes bytes number which are requered to store
/** @brief Computes bytes number which are required to store
* all weights and intermediate blobs for each layer.
* @param netInputShapes vector of shapes for all net inputs.
* @param layerIds output vector to save layer IDs.
@ -700,13 +701,13 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* * `*.pb` (TensorFlow, https://www.tensorflow.org/)
* * `*.t7` | `*.net` (Torch, http://torch.ch/)
* * `*.weights` (Darknet, https://pjreddie.com/darknet/)
* * `*.bin` (DLDT, https://software.seek.intel.com/deep-learning-deployment)
* * `*.bin` (DLDT, https://software.intel.com/openvino-toolkit)
* @param[in] config Text file contains network configuration. It could be a
* file with the following extensions:
* * `*.prototxt` (Caffe, http://caffe.berkeleyvision.org/)
* * `*.pbtxt` (TensorFlow, https://www.tensorflow.org/)
* * `*.cfg` (Darknet, https://pjreddie.com/darknet/)
* * `*.xml` (DLDT, https://software.seek.intel.com/deep-learning-deployment)
* * `*.xml` (DLDT, https://software.intel.com/openvino-toolkit)
* @param[in] framework Explicit framework name tag to determine a format.
* @returns Net object.
*
@ -726,7 +727,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* @param[in] xml XML configuration file with network's topology.
* @param[in] bin Binary file with trained weights.
* @returns Net object.
* Networks imported from Intel's Model Optimizer are lauched in Intel's Inference Engine
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
* backend.
*/
CV_EXPORTS_W Net readNetFromModelOptimizer(const String &xml, const String &bin);
@ -744,7 +745,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* @details if @p crop is true, input image is resized so one side after resize is equal to corresponding
* dimension in @p size and another one is equal or larger. Then, crop from the center is performed.
* If @p crop is false, direct resize without cropping and preserving aspect ratio is performed.
* @returns 4-dimansional Mat with NCHW dimensions order.
* @returns 4-dimensional Mat with NCHW dimensions order.
*/
CV_EXPORTS_W Mat blobFromImage(InputArray image, double scalefactor=1.0, const Size& size = Size(),
const Scalar& mean = Scalar(), bool swapRB=true, bool crop=true);

@ -223,9 +223,9 @@ with tf.Session() as sess:
# By default, float16 weights are stored in repeated tensor's field called
# `half_val`. It has type int32 with leading zeros for unused bytes.
# This type is encoded by Varint that means only 7 bits are used for value
# This type is encoded by Variant that means only 7 bits are used for value
# representation but the last one is indicated the end of encoding. This way
# float16 might takes 1 or 2 or 3 bytes depends on value. To impove compression,
# float16 might takes 1 or 2 or 3 bytes depends on value. To improve compression,
# we replace all `half_val` values to `tensor_content` using only 2 bytes for everyone.
for node in graph_def.node:
if 'value' in node.attr:

@ -13,7 +13,7 @@
namespace opencv_test {
CV_ENUM(DNNBackend, DNN_BACKEND_DEFAULT, DNN_BACKEND_HALIDE, DNN_BACKEND_INFERENCE_ENGINE)
CV_ENUM(DNNTarget, DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16)
CV_ENUM(DNNTarget, DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16, DNN_TARGET_MYRIAD)
class DNNTestNetwork : public ::perf::TestBaseWithParam< tuple<DNNBackend, DNNTarget> >
{
@ -29,6 +29,28 @@ public:
target = (dnn::Target)(int)get<1>(GetParam());
}
static bool checkMyriadTarget()
{
#ifndef HAVE_INF_ENGINE
return false;
#endif
cv::dnn::Net net;
cv::dnn::LayerParams lp;
net.addLayerToPrev("testLayer", "Identity", lp);
net.setPreferableBackend(cv::dnn::DNN_BACKEND_INFERENCE_ENGINE);
net.setPreferableTarget(cv::dnn::DNN_TARGET_MYRIAD);
net.setInput(cv::Mat::zeros(1, 1, CV_32FC1));
try
{
net.forward();
}
catch(...)
{
return false;
}
return true;
}
void processNet(std::string weights, std::string proto, std::string halide_scheduler,
const Mat& input, const std::string& outputLayer = "")
{
@ -41,6 +63,13 @@ public:
throw cvtest::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");
}
}
randu(input, 0.0f, 1.0f);
@ -87,8 +116,6 @@ public:
PERF_TEST_P_(DNNTestNetwork, AlexNet)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
throw SkipTestException("");
processNet("dnn/bvlc_alexnet.caffemodel", "dnn/bvlc_alexnet.prototxt",
"alexnet.yml", Mat(cv::Size(227, 227), CV_32FC3));
}
@ -130,7 +157,6 @@ PERF_TEST_P_(DNNTestNetwork, ENet)
PERF_TEST_P_(DNNTestNetwork, SSD)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE) throw SkipTestException("");
processNet("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel", "dnn/ssd_vgg16.prototxt", "disabled",
Mat(cv::Size(300, 300), CV_32FC3));
}
@ -146,18 +172,17 @@ PERF_TEST_P_(DNNTestNetwork, OpenFace)
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_Caffe)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
processNet("dnn/MobileNetSSD_deploy.caffemodel", "dnn/MobileNetSSD_deploy.prototxt", "",
Mat(cv::Size(300, 300), CV_32FC3));
}
// TODO: update MobileNet model.
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_TensorFlow)
{
if (backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL ||
backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE)
throw SkipTestException("");
processNet("dnn/ssd_mobilenet_v1_coco.pb", "ssd_mobilenet_v1_coco.pbtxt", "",
Mat(cv::Size(300, 300), CV_32FC3));
@ -166,7 +191,8 @@ PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_TensorFlow)
PERF_TEST_P_(DNNTestNetwork, DenseNet_121)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16)
backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL_FP16 ||
target == DNN_TARGET_MYRIAD))
throw SkipTestException("");
processNet("dnn/DenseNet_121.caffemodel", "dnn/DenseNet_121.prototxt", "",
Mat(cv::Size(224, 224), CV_32FC3));
@ -174,21 +200,27 @@ PERF_TEST_P_(DNNTestNetwork, DenseNet_121)
PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_coco)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
processNet("dnn/openpose_pose_coco.caffemodel", "dnn/openpose_pose_coco.prototxt", "",
Mat(cv::Size(368, 368), CV_32FC3));
}
PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi.prototxt", "",
Mat(cv::Size(368, 368), CV_32FC3));
}
PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
// The same .caffemodel but modified .prototxt
// See https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/src/openpose/pose/poseParameters.cpp
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi_faster_4_stages.prototxt", "",
@ -197,8 +229,7 @@ PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
PERF_TEST_P_(DNNTestNetwork, opencv_face_detector)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
processNet("dnn/opencv_face_detector.caffemodel", "dnn/opencv_face_detector.prototxt", "",
Mat(cv::Size(300, 300), CV_32FC3));
@ -207,7 +238,8 @@ PERF_TEST_P_(DNNTestNetwork, opencv_face_detector)
PERF_TEST_P_(DNNTestNetwork, Inception_v2_SSD_TensorFlow)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL) ||
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16))
throw SkipTestException("");
processNet("dnn/ssd_inception_v2_coco_2017_11_17.pb", "ssd_inception_v2_coco_2017_11_17.pbtxt", "",
Mat(cv::Size(300, 300), CV_32FC3));
@ -215,7 +247,8 @@ PERF_TEST_P_(DNNTestNetwork, Inception_v2_SSD_TensorFlow)
PERF_TEST_P_(DNNTestNetwork, YOLOv3)
{
if (backend != DNN_BACKEND_DEFAULT)
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/dog416.png", false));
Mat inp;
@ -232,6 +265,7 @@ const tuple<DNNBackend, DNNTarget> testCases[] = {
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD),
#endif
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL),

@ -288,7 +288,7 @@ namespace cv {
permute_params.set("order", paramOrder);
darknet::LayerParameter lp;
std::string layer_name = cv::format("premute_%d", layer_id);
std::string layer_name = cv::format("permute_%d", layer_id);
lp.layer_name = layer_name;
lp.layer_type = permute_params.type;
lp.layerParams = permute_params;

@ -541,7 +541,7 @@ public:
{
// if dst already has been allocated with total(shape) elements,
// it won't be recrreated and pointer of dst.data remains the same.
// it won't be recreated and pointer of dst.data remains the same.
dst.create(shape, use_half ? CV_16S : CV_32F);
addHost(lp, dst);
}
@ -1132,7 +1132,7 @@ struct Net::Impl
if (layerNet != ieInpNode->net)
{
// layerNet is empty or nodes are from different graphs.
ieInpNode->net->addOutput(inpLd.name);
ieInpNode->net->addOutput(ieInpNode->layer->name);
}
}
}
@ -1182,7 +1182,9 @@ struct Net::Impl
for (it = layers.begin(); it != layers.end(); ++it)
{
LayerData &ld = it->second;
bool fused = ld.skip && ld.id != 0;
if (ld.id == 0)
continue;
bool fused = ld.skip;
Ptr<Layer> layer = ld.layerInstance;
if (!layer->supportBackend(preferableBackend))
@ -1259,7 +1261,7 @@ struct Net::Impl
CV_Assert(!ieNode.empty());
ieNode->net = net;
if (preferableTarget == DNN_TARGET_OPENCL_FP16 && !fused)
if ((preferableTarget == DNN_TARGET_OPENCL_FP16 || preferableTarget == DNN_TARGET_MYRIAD) && !fused)
{
ieNode->layer->precision = InferenceEngine::Precision::FP16;
auto weightableLayer = std::dynamic_pointer_cast<InferenceEngine::WeightableLayer>(ieNode->layer);
@ -1518,7 +1520,7 @@ struct Net::Impl
}
}
// fuse convlution layer followed by eltwise + relu
// fuse convolution layer followed by eltwise + relu
if ( IS_DNN_OPENCL_TARGET(preferableTarget) )
{
Ptr<EltwiseLayer> nextEltwiseLayer;
@ -1647,7 +1649,7 @@ struct Net::Impl
// the optimization #3. if there is concat layer that concatenates channels
// from the inputs together (i.e. axis == 1) then we make the inputs of
// the concat layer to write to the concatetion output buffer
// the concat layer to write to the concatenation output buffer
// (and so we eliminate the concatenation layer, because the channels
// are concatenated implicitly).
Ptr<ConcatLayer> concatLayer = ld.layerInstance.dynamicCast<ConcatLayer>();

@ -242,7 +242,7 @@ bool HalideScheduler::process(Ptr<BackendNode>& node)
std::map<std::string, Halide::Func> funcsMap; // Scheduled functions.
// For every function, from top to bottom, we try to find a scheduling node.
// Scheduling is successful (return true) if for the first function (top)
// node is respresented.
// node is represented.
CV_Assert(!node.empty());
std::vector<Halide::Func>& funcs = node.dynamicCast<HalideBackendNode>()->funcs;
for (int i = funcs.size() - 1; i >= 0; --i)

@ -84,6 +84,7 @@ void initializeLayerFactory()
CV_DNN_REGISTER_LAYER_CLASS(Reshape, ReshapeLayer);
CV_DNN_REGISTER_LAYER_CLASS(Flatten, FlattenLayer);
CV_DNN_REGISTER_LAYER_CLASS(ResizeNearestNeighbor, ResizeNearestNeighborLayer);
CV_DNN_REGISTER_LAYER_CLASS(CropAndResize, CropAndResizeLayer);
CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
CV_DNN_REGISTER_LAYER_CLASS(Deconvolution, DeconvolutionLayer);

@ -676,7 +676,7 @@ public:
int j0 = std::max(0, (-in_j + dilation_w-1)/dilation_w);
int j1 = std::min(kernel_w, (width - in_j + dilation_w-1)/dilation_w);
// here some non-continous sub-row of the row will not be
// here some non-continuous sub-row of the row will not be
// filled from the tensor; we need to make sure that the uncovered
// elements are explicitly set to 0's. the easiest way is to
// set all the elements to 0's before the loop.
@ -966,8 +966,7 @@ public:
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget) &&
OCL_PERFORMANCE_CHECK(ocl::Device::getDefault().isIntel()),
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
forward_ocl(inputs_arr, outputs_arr, internals_arr))
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);

@ -0,0 +1,108 @@
#include "../precomp.hpp"
#include "layers_common.hpp"
namespace cv { namespace dnn {
class CropAndResizeLayerImpl CV_FINAL : public CropAndResizeLayer
{
public:
CropAndResizeLayerImpl(const LayerParams& params)
{
CV_Assert(params.has("width"), params.has("height"));
outWidth = params.get<float>("width");
outHeight = params.get<float>("height");
}
bool getMemoryShapes(const std::vector<MatShape> &inputs,
const int requiredOutputs,
std::vector<MatShape> &outputs,
std::vector<MatShape> &internals) const CV_OVERRIDE
{
CV_Assert(inputs.size() == 2, inputs[0].size() == 4);
if (inputs[0][0] != 1)
CV_Error(Error::StsNotImplemented, "");
outputs.resize(1, MatShape(4));
outputs[0][0] = inputs[1][2]; // Number of bounding boxes.
outputs[0][1] = inputs[0][1]; // Number of channels.
outputs[0][2] = outHeight;
outputs[0][3] = outWidth;
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());
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
}
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals) CV_OVERRIDE
{
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
Mat& inp = *inputs[0];
Mat& out = outputs[0];
Mat boxes = inputs[1]->reshape(1, inputs[1]->total() / 7);
const int numChannels = inp.size[1];
const int inpHeight = inp.size[2];
const int inpWidth = inp.size[3];
const int inpSpatialSize = inpHeight * inpWidth;
const int outSpatialSize = outHeight * outWidth;
CV_Assert(inp.isContinuous(), out.isContinuous());
for (int b = 0; b < boxes.rows; ++b)
{
float* outDataBox = out.ptr<float>(b);
float left = boxes.at<float>(b, 3);
float top = boxes.at<float>(b, 4);
float right = boxes.at<float>(b, 5);
float bottom = boxes.at<float>(b, 6);
float boxWidth = right - left;
float boxHeight = bottom - top;
float heightScale = boxHeight * static_cast<float>(inpHeight - 1) / (outHeight - 1);
float widthScale = boxWidth * static_cast<float>(inpWidth - 1) / (outWidth - 1);
for (int y = 0; y < outHeight; ++y)
{
float input_y = top * (inpHeight - 1) + y * heightScale;
int y0 = static_cast<int>(input_y);
const float* inpData_row0 = (float*)inp.data + y0 * inpWidth;
const float* inpData_row1 = (y0 + 1 < inpHeight) ? (inpData_row0 + inpWidth) : inpData_row0;
for (int x = 0; x < outWidth; ++x)
{
float input_x = left * (inpWidth - 1) + x * widthScale;
int x0 = static_cast<int>(input_x);
int x1 = std::min(x0 + 1, inpWidth - 1);
float* outData = outDataBox + y * outWidth + x;
const float* inpData_row0_c = inpData_row0;
const float* inpData_row1_c = inpData_row1;
for (int c = 0; c < numChannels; ++c)
{
*outData = inpData_row0_c[x0] +
(input_y - y0) * (inpData_row1_c[x0] - inpData_row0_c[x0]) +
(input_x - x0) * (inpData_row0_c[x1] - inpData_row0_c[x0] +
(input_y - y0) * (inpData_row1_c[x1] - inpData_row0_c[x1] - inpData_row1_c[x0] + inpData_row0_c[x0]));
inpData_row0_c += inpSpatialSize;
inpData_row1_c += inpSpatialSize;
outData += outSpatialSize;
}
}
}
}
}
private:
int outWidth, outHeight;
};
Ptr<Layer> CropAndResizeLayer::create(const LayerParams& params)
{
return Ptr<CropAndResizeLayer>(new CropAndResizeLayerImpl(params));
}
} // namespace dnn
} // namespace cv

@ -110,7 +110,7 @@ public:
float _nmsThreshold;
int _topK;
// Whenever predicted bounding boxes are respresented in YXHW instead of XYWH layout.
// Whenever predicted bounding boxes are represented in YXHW instead of XYWH layout.
bool _locPredTransposed;
// It's true whenever predicted bounding boxes and proposals are normalized to [0, 1].
bool _bboxesNormalized;
@ -208,8 +208,9 @@ public:
CV_Assert(inputs[0][0] == inputs[1][0]);
int numPriors = inputs[2][2] / 4;
CV_Assert((numPriors * _numLocClasses * 4) == inputs[0][1]);
CV_Assert(int(numPriors * _numClasses) == inputs[1][1]);
CV_Assert((numPriors * _numLocClasses * 4) == total(inputs[0], 1));
CV_Assert(int(numPriors * _numClasses) == total(inputs[1], 1));
CV_Assert(inputs[2][1] == 1 + (int)(!_varianceEncodedInTarget));
// num() and channels() are 1.
// Since the number of bboxes to be kept is unknown before nms, we manually

@ -117,7 +117,7 @@ public:
{
return backendId == DNN_BACKEND_DEFAULT ||
backendId == DNN_BACKEND_HALIDE && haveHalide() ||
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine() && this->type != "Sigmoid";
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine();
}
virtual Ptr<BackendNode> tryAttach(const Ptr<BackendNode>& node) CV_OVERRIDE
@ -176,8 +176,7 @@ public:
{
CV_TRACE_FUNCTION();
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(this->preferableTarget) &&
OCL_PERFORMANCE_CHECK(ocl::Device::getDefault().isIntel()),
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(this->preferableTarget),
func.applyOCL(inputs_arr, outputs_arr, internals_arr))
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
@ -335,6 +334,7 @@ struct ReLUFunctor
lp.type = "ReLU";
std::shared_ptr<InferenceEngine::ReLULayer> ieLayer(new InferenceEngine::ReLULayer(lp));
ieLayer->negative_slope = slope;
ieLayer->params["negative_slope"] = format("%f", slope);
return ieLayer;
}
#endif // HAVE_INF_ENGINE
@ -432,6 +432,8 @@ struct ReLU6Functor
std::shared_ptr<InferenceEngine::ClampLayer> ieLayer(new InferenceEngine::ClampLayer(lp));
ieLayer->min_value = minValue;
ieLayer->max_value = maxValue;
ieLayer->params["min"] = format("%f", minValue);
ieLayer->params["max"] = format("%f", maxValue);
return ieLayer;
}
#endif // HAVE_INF_ENGINE
@ -557,8 +559,9 @@ struct SigmoidFunctor
#ifdef HAVE_INF_ENGINE
InferenceEngine::CNNLayerPtr initInfEngine(InferenceEngine::LayerParams& lp)
{
CV_Error(Error::StsNotImplemented, "Sigmoid");
return InferenceEngine::CNNLayerPtr();
lp.type = "Sigmoid";
std::shared_ptr<InferenceEngine::CNNLayer> ieLayer(new InferenceEngine::CNNLayer(lp));
return ieLayer;
}
#endif // HAVE_INF_ENGINE

@ -79,7 +79,7 @@ public:
else if (operation == "max")
op = MAX;
else
CV_Error(cv::Error::StsBadArg, "Unknown operaticon type \"" + operation + "\"");
CV_Error(cv::Error::StsBadArg, "Unknown operation type \"" + operation + "\"");
}
if (params.has("coeff"))

@ -73,7 +73,7 @@ public:
virtual bool tryFuse(Ptr<Layer>& top) CV_OVERRIDE
{
if (preferableTarget == DNN_TARGET_OPENCL && !fuse_batch_norm)
if (!fuse_batch_norm)
{
top->getScaleShift(scale, shift);
fuse_batch_norm = !scale.empty() || !shift.empty();
@ -252,8 +252,7 @@ public:
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget) &&
OCL_PERFORMANCE_CHECK(ocl::Device::getDefault().isIntel()),
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
forward_ocl(inputs_arr, outputs_arr, internals_arr))
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
@ -274,25 +273,53 @@ public:
for( i = 0; i < splitDim; i++ )
newRows *= inpBlob.size[i];
if (inpBlob.total() == newRows)
Mat inpMat = inpBlob.reshape(1, newRows);
Mat outMat = outBlob.reshape(1, newRows);
if ( inpBlob.total() == newRows )
{
// MVN is applied to single values at an every row.
outBlob.setTo(0);
if (shift.empty())
{
outBlob.setTo(0);
}
else
{
for ( i = 0; i < newRows; i++ )
{
outMat.row(i).setTo(((float*)shift.data)[i]);
}
}
return;
}
Mat inpMat = inpBlob.reshape(1, newRows);
Mat outMat = outBlob.reshape(1, newRows);
Scalar mean, dev;
for ( i = 0; i < newRows; i++)
{
Mat inpRow = inpMat.row(i);
Mat outRow = outMat.row(i);
float weight = 1.f;
float bias = 0.f;
if (fuse_batch_norm)
{
weight = i < scale.cols ? ((float*)scale.data)[i] : weight;
bias = i < shift.cols ? ((float*)shift.data)[i] : bias;
}
cv::meanStdDev(inpRow, mean, (normVariance) ? dev : noArray());
double alpha = (normVariance) ? 1/(eps + dev[0]) : 1;
inpRow.convertTo(outRow, outRow.type(), alpha, -mean[0] * alpha);
double normalizationScale = 1.0;
double normalizationShift = 0.0;
if (fuse_batch_norm)
{
normalizationScale = alpha * weight;
normalizationShift = -mean[0] * normalizationScale + bias;
}
else
{
normalizationScale = alpha;
normalizationShift = -mean[0] * alpha;
}
inpRow.convertTo(outRow, outRow.type(), normalizationScale, normalizationShift);
}
}
}

@ -191,8 +191,7 @@ public:
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget) &&
OCL_PERFORMANCE_CHECK(ocl::Device::getDefault().isIntel()),
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
forward_ocl(inputs_arr, outputs_arr, internals_arr))
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);

@ -271,7 +271,7 @@ public:
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_DEFAULT ||
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine() && !_explicitSizes;
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine();
}
bool getMemoryShapes(const std::vector<MatShape> &inputs,
@ -366,7 +366,7 @@ public:
kernel.set(13, (int)_imageWidth);
kernel.run(1, &nthreads, NULL, false);
// clip the prior's coordidate such that it is within [0, 1]
// clip the prior's coordinate such that it is within [0, 1]
if (_clip)
{
Mat mat = outputs[0].getMat(ACCESS_READ);
@ -442,7 +442,7 @@ public:
}
}
}
// clip the prior's coordidate such that it is within [0, 1]
// clip the prior's coordinate such that it is within [0, 1]
if (_clip)
{
int _outChannelSize = _layerHeight * _layerWidth * _numPriors * 4;
@ -484,18 +484,33 @@ public:
#ifdef HAVE_INF_ENGINE
InferenceEngine::LayerParams lp;
lp.name = name;
lp.type = "PriorBox";
lp.type = _explicitSizes ? "PriorBoxClustered" : "PriorBox";
lp.precision = InferenceEngine::Precision::FP32;
std::shared_ptr<InferenceEngine::CNNLayer> ieLayer(new InferenceEngine::CNNLayer(lp));
ieLayer->params["min_size"] = format("%f", _minSize);
ieLayer->params["max_size"] = _maxSize > 0 ? format("%f", _maxSize) : "";
if (!_aspectRatios.empty())
if (_explicitSizes)
{
CV_Assert(!_boxWidths.empty(), !_boxHeights.empty(),
_boxWidths.size() == _boxHeights.size());
ieLayer->params["width"] = format("%f", _boxWidths[0]);
ieLayer->params["height"] = format("%f", _boxHeights[0]);
for (int i = 1; i < _boxWidths.size(); ++i)
{
ieLayer->params["width"] += format(",%f", _boxWidths[i]);
ieLayer->params["height"] += format(",%f", _boxHeights[i]);
}
}
else
{
ieLayer->params["aspect_ratio"] = format("%f", _aspectRatios[0]);
for (int i = 1; i < _aspectRatios.size(); ++i)
ieLayer->params["aspect_ratio"] += format(",%f", _aspectRatios[i]);
ieLayer->params["min_size"] = format("%f", _minSize);
ieLayer->params["max_size"] = _maxSize > 0 ? format("%f", _maxSize) : "";
if (!_aspectRatios.empty())
{
ieLayer->params["aspect_ratio"] = format("%f", _aspectRatios[0]);
for (int i = 1; i < _aspectRatios.size(); ++i)
ieLayer->params["aspect_ratio"] += format(",%f", _aspectRatios[i]);
}
}
ieLayer->params["flip"] = "0"; // We already flipped aspect ratios.
@ -550,7 +565,7 @@ private:
std::vector<float> _variance;
std::vector<float> _offsetsX;
std::vector<float> _offsetsY;
// Precomputed final widhts and heights based on aspect ratios or explicit sizes.
// Precomputed final widths and heights based on aspect ratios or explicit sizes.
std::vector<float> _boxWidths;
std::vector<float> _boxHeights;

@ -95,11 +95,6 @@ public:
return false;
}
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_DEFAULT;
}
float logistic_activate(float x) { return 1.F / (1.F + exp(-x)); }
void softmax_activate(const float* input, const int n, const float temp, float* output)

@ -6,6 +6,7 @@
// Third party copyrights are property of their respective owners.
#include "../precomp.hpp"
#include "layers_common.hpp"
#include "../op_inf_engine.hpp"
#include <opencv2/imgproc.hpp>
namespace cv { namespace dnn {
@ -39,6 +40,12 @@ 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_DEFAULT ||
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine();
}
virtual void finalize(const std::vector<Mat*>& inputs, std::vector<Mat> &outputs) CV_OVERRIDE
{
if (!outWidth && !outHeight)
@ -75,6 +82,26 @@ public:
}
}
}
virtual Ptr<BackendNode> initInfEngine(const std::vector<Ptr<BackendWrapper> >&) CV_OVERRIDE
{
#ifdef HAVE_INF_ENGINE
InferenceEngine::LayerParams lp;
lp.name = name;
lp.type = "Resample";
lp.precision = InferenceEngine::Precision::FP32;
std::shared_ptr<InferenceEngine::CNNLayer> ieLayer(new InferenceEngine::CNNLayer(lp));
ieLayer->params["type"] = "caffe.ResampleParameter.NEAREST";
ieLayer->params["antialias"] = "0";
ieLayer->params["width"] = cv::format("%d", outWidth);
ieLayer->params["height"] = cv::format("%d", outHeight);
return Ptr<BackendNode>(new InfEngineBackendNode(ieLayer));
#endif // HAVE_INF_ENGINE
return Ptr<BackendNode>();
}
private:
int outWidth, outHeight, zoomFactor;
bool alignCorners;

@ -709,7 +709,7 @@ bool OCL4DNNConvSpatial<Dtype>::swizzleWeight(const UMat &weight,
return false;
}
} else {
// assumption: kernel dimesion is 2
// assumption: kernel dimension is 2
Mat weightMat = weight.getMat(ACCESS_READ);
Dtype* cpu_weight = (Dtype *)weightMat.ptr<float>();
Mat swizzledWeightMat;

@ -18,11 +18,6 @@ namespace cv { namespace dnn {
#ifdef HAVE_INF_ENGINE
static int infEngineVersion()
{
return std::atoi(InferenceEngine::GetInferenceEngineVersion()->buildNumber);
}
InfEngineBackendNode::InfEngineBackendNode(const InferenceEngine::CNNLayerPtr& _layer)
: BackendNode(DNN_BACKEND_INFERENCE_ENGINE), layer(_layer) {}
@ -59,27 +54,23 @@ infEngineWrappers(const std::vector<Ptr<BackendWrapper> >& ptrs)
return wrappers;
}
static InferenceEngine::Layout estimateLayout(const Mat& m)
{
if (m.dims == 4)
return InferenceEngine::Layout::NCHW;
else if (m.dims == 2)
return InferenceEngine::Layout::NC;
else
return InferenceEngine::Layout::ANY;
}
static InferenceEngine::DataPtr wrapToInfEngineDataNode(const Mat& m, const std::string& name = "")
{
std::vector<size_t> reversedShape(&m.size[0], &m.size[0] + m.dims);
std::reverse(reversedShape.begin(), reversedShape.end());
if (infEngineVersion() > 5855)
{
InferenceEngine::Layout l = InferenceEngine::Layout::ANY;
if (m.dims == 4)
l = InferenceEngine::Layout::NCHW;
else if (m.dims == 2)
l = InferenceEngine::Layout::NC;
return InferenceEngine::DataPtr(
new InferenceEngine::Data(name, reversedShape, InferenceEngine::Precision::FP32, l)
);
}
else
{
return InferenceEngine::DataPtr(
new InferenceEngine::Data(name, reversedShape, InferenceEngine::Precision::FP32)
);
}
return InferenceEngine::DataPtr(
new InferenceEngine::Data(name, reversedShape, InferenceEngine::Precision::FP32, estimateLayout(m))
);
}
InferenceEngine::TBlob<float>::Ptr wrapToInfEngineBlob(const Mat& m, const std::vector<size_t>& shape,
@ -108,7 +99,7 @@ InfEngineBackendWrapper::InfEngineBackendWrapper(int targetId, const cv::Mat& m)
: BackendWrapper(DNN_BACKEND_INFERENCE_ENGINE, targetId)
{
dataPtr = wrapToInfEngineDataNode(m);
blob = wrapToInfEngineBlob(m);
blob = wrapToInfEngineBlob(m, estimateLayout(m));
}
InfEngineBackendWrapper::~InfEngineBackendWrapper()
@ -252,7 +243,8 @@ InfEngineBackendNet::getLayerByName(const char *layerName, InferenceEngine::CNNL
void InfEngineBackendNet::setTargetDevice(InferenceEngine::TargetDevice device) noexcept
{
if (device != InferenceEngine::TargetDevice::eCPU &&
device != InferenceEngine::TargetDevice::eGPU)
device != InferenceEngine::TargetDevice::eGPU &&
device != InferenceEngine::TargetDevice::eMYRIAD)
CV_Error(Error::StsNotImplemented, "");
targetDevice = device;
}
@ -296,7 +288,7 @@ void InfEngineBackendNet::init(int targetId)
}
for (const InferenceEngine::DataPtr& out : l->outData)
{
// TODO: Replace to uniquness assertion.
// TODO: Replace to uniqueness assertion.
if (internalOutputs.find(out->name) == internalOutputs.end())
internalOutputs[out->name] = out;
}
@ -313,7 +305,7 @@ void InfEngineBackendNet::init(int targetId)
// Add all outputs.
for (const InferenceEngine::DataPtr& out : l->outData)
{
// TODO: Replace to uniquness assertion.
// TODO: Replace to uniqueness assertion.
if (unconnectedOuts.find(out->name) == unconnectedOuts.end())
unconnectedOuts[out->name] = out;
}
@ -352,6 +344,11 @@ void InfEngineBackendNet::init(int targetId)
case DNN_TARGET_CPU: setTargetDevice(InferenceEngine::TargetDevice::eCPU); break;
case DNN_TARGET_OPENCL_FP16: setPrecision(InferenceEngine::Precision::FP16); // Fallback to the next.
case DNN_TARGET_OPENCL: setTargetDevice(InferenceEngine::TargetDevice::eGPU); break;
case DNN_TARGET_MYRIAD:
{
setPrecision(InferenceEngine::Precision::FP16);
setTargetDevice(InferenceEngine::TargetDevice::eMYRIAD); break;
}
default:
CV_Error(Error::StsError, format("Unknown target identifier: %d", targetId));
}
@ -364,11 +361,21 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
{
CV_Assert(!isInitialized());
InferenceEngine::StatusCode status;
InferenceEngine::ResponseDesc resp;
static std::map<std::string, InferenceEngine::InferenceEnginePluginPtr> sharedPlugins;
std::string deviceName = InferenceEngine::getDeviceName(targetDevice);
auto pluginIt = sharedPlugins.find(deviceName);
if (pluginIt != sharedPlugins.end())
{
enginePtr = pluginIt->second;
}
else
{
enginePtr = InferenceEngine::PluginDispatcher({""}).getSuitablePlugin(targetDevice);
sharedPlugins[deviceName] = enginePtr;
}
plugin = InferenceEngine::InferencePlugin(enginePtr);
plugin = InferenceEngine::PluginDispatcher({""}).getSuitablePlugin(targetDevice);
if (infEngineVersion() > 5855 && targetDevice == InferenceEngine::TargetDevice::eCPU)
if (targetDevice == InferenceEngine::TargetDevice::eCPU)
{
#ifdef _WIN32
InferenceEngine::IExtensionPtr extension =
@ -377,18 +384,17 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
InferenceEngine::IExtensionPtr extension =
InferenceEngine::make_so_pointer<InferenceEngine::IExtension>("libcpu_extension.so");
#endif // _WIN32
status = plugin->AddExtension(extension, &resp);
if (status != InferenceEngine::StatusCode::OK)
CV_Error(Error::StsAssert, resp.msg);
plugin.AddExtension(extension);
}
status = plugin->LoadNetwork(net, &resp);
if (status != InferenceEngine::StatusCode::OK)
CV_Error(Error::StsAssert, resp.msg);
netExec = plugin.LoadNetwork(net, {});
infRequest = netExec.CreateInferRequest();
infRequest.SetInput(inpBlobs);
infRequest.SetOutput(outBlobs);
}
bool InfEngineBackendNet::isInitialized()
{
return (bool)plugin;
return (bool)enginePtr;
}
void InfEngineBackendNet::addBlobs(const std::vector<Ptr<BackendWrapper> >& ptrs)
@ -402,10 +408,7 @@ void InfEngineBackendNet::addBlobs(const std::vector<Ptr<BackendWrapper> >& ptrs
void InfEngineBackendNet::forward()
{
InferenceEngine::ResponseDesc resp;
InferenceEngine::StatusCode status = plugin->Infer(inpBlobs, outBlobs, &resp);
if (status != InferenceEngine::StatusCode::OK)
CV_Error(Error::StsAssert, resp.msg);
infRequest.Infer();
}
Mat infEngineBlobToMat(const InferenceEngine::Blob::Ptr& blob)

@ -89,7 +89,10 @@ private:
InferenceEngine::BlobMap allBlobs;
InferenceEngine::TargetDevice targetDevice;
InferenceEngine::Precision precision;
InferenceEngine::InferenceEnginePluginPtr plugin;
InferenceEngine::InferenceEnginePluginPtr enginePtr;
InferenceEngine::InferencePlugin plugin;
InferenceEngine::ExecutableNetwork netExec;
InferenceEngine::InferRequest infRequest;
void initPlugin(InferenceEngine::ICNNNetwork& net);
};

@ -89,7 +89,8 @@ __kernel void CALC_MEAN(__global const Dtype* src,
Dtype mean_val = mean[x];
vec_type src_vec = load(src, index);
vec_type dst_vec = native_powr(src_vec - (vec_type)mean_val, 2);
vec_type dst_vec = src_vec - (vec_type)mean_val;
dst_vec = dst_vec * dst_vec;
store(dst_vec, dst, index);
}
@ -197,10 +198,14 @@ __kernel void MEAN_FUSE(__global const T * A,
const T4 a2 = vload4(i, src0_read + 2 * A_col_size);
const T4 a3 = vload4(i, src0_read + 3 * A_col_size);
dot0 = native_powr(convert_float4(a0) - (Dtype4)sum.x, 2);
dot1 = native_powr(convert_float4(a1) - (Dtype4)sum.y, 2);
dot2 = native_powr(convert_float4(a2) - (Dtype4)sum.z, 2);
dot3 = native_powr(convert_float4(a3) - (Dtype4)sum.w, 2);
dot0 = convert_float4(a0) - (Dtype4)sum.x;
dot1 = convert_float4(a1) - (Dtype4)sum.y;
dot2 = convert_float4(a2) - (Dtype4)sum.z;
dot3 = convert_float4(a3) - (Dtype4)sum.w;
dot0 = dot0 * dot0;
dot1 = dot1 * dot1;
dot2 = dot2 * dot2;
dot3 = dot3 * dot3;
vstore4(dot0, i, dst0_read);
vstore4(dot1, i, dst0_read + A_col_size);

@ -86,7 +86,7 @@ message NodeDef {
// | ( ("gpu" | "cpu") ":" ([1-9][0-9]* | "*") )
//
// Valid values for this string include:
// * "@other/node" (colocate with "other/node")
// * "@other/node" (collocate with "other/node")
// * "/job:worker/replica:0/task:1/gpu:3" (full specification)
// * "/job:worker/gpu:3" (partial specification)
// * "" (no specification)

@ -5,6 +5,8 @@
// Copyright (C) 2018, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "../precomp.hpp"
#ifdef HAVE_PROTOBUF
#include "tf_graph_simplifier.hpp"

@ -644,8 +644,9 @@ void TFImporter::populateNet(Net dstNet)
CV_Assert(layer.input_size() == 3);
DictValue dilation = parseDims(getConstBlob(layer, value_id, 1));
CV_Assert(dilation.size() == 2 && dilation.get<int>(0) == dilation.get<int>(1));
layerParams.set("dilation", dilation.get<int>(0));
CV_Assert(dilation.size() == 2);
layerParams.set("dilation_h", dilation.get<int>(0));
layerParams.set("dilation_w", dilation.get<int>(1));
Mat paddings;
parseTensor<int>(getConstBlob(layer, value_id, 2), paddings);
@ -655,6 +656,10 @@ void TFImporter::populateNet(Net dstNet)
layerParams.set("pad_w", paddings.at<float>(2));
StrIntVector next_layers = getNextLayers(net, name, "Conv2D");
if (next_layers.empty())
{
next_layers = getNextLayers(net, name, "DepthwiseConv2dNative");
}
CV_Assert(next_layers.size() == 1);
layer = net.node(next_layers[0].second);
layers_to_ignore.insert(next_layers[0].first);
@ -1089,9 +1094,9 @@ void TFImporter::populateNet(Net dstNet)
CV_Assert(!begins.empty(), !sizes.empty(), begins.type() == CV_32SC1,
sizes.type() == CV_32SC1);
if (begins.total() == 4)
if (begins.total() == 4 && data_layouts[name] == DATA_LAYOUT_NHWC)
{
// Perhabs, we have an NHWC order. Swap it to NCHW.
// Swap NHWC parameters' order to NCHW.
std::swap(*begins.ptr<int32_t>(0, 2), *begins.ptr<int32_t>(0, 3));
std::swap(*begins.ptr<int32_t>(0, 1), *begins.ptr<int32_t>(0, 2));
std::swap(*sizes.ptr<int32_t>(0, 2), *sizes.ptr<int32_t>(0, 3));
@ -1171,6 +1176,9 @@ void TFImporter::populateNet(Net dstNet)
layers_to_ignore.insert(next_layers[0].first);
}
if (hasLayerAttr(layer, "axis"))
layerParams.set("axis", getLayerAttr(layer, "axis").i());
id = dstNet.addLayer(name, "Scale", layerParams);
}
layer_id[name] = id;
@ -1542,6 +1550,10 @@ void TFImporter::populateNet(Net dstNet)
layerParams.set("confidence_threshold", getLayerAttr(layer, "confidence_threshold").f());
if (hasLayerAttr(layer, "loc_pred_transposed"))
layerParams.set("loc_pred_transposed", getLayerAttr(layer, "loc_pred_transposed").b());
if (hasLayerAttr(layer, "clip"))
layerParams.set("clip", getLayerAttr(layer, "clip").b());
if (hasLayerAttr(layer, "variance_encoded_in_target"))
layerParams.set("variance_encoded_in_target", getLayerAttr(layer, "variance_encoded_in_target").b());
int id = dstNet.addLayer(name, "DetectionOutput", layerParams);
layer_id[name] = id;
@ -1558,6 +1570,26 @@ void TFImporter::populateNet(Net dstNet)
layer_id[name] = id;
connectToAllBlobs(layer_id, dstNet, parsePin(layer.input(0)), id, layer.input_size());
}
else if (type == "CropAndResize")
{
// op: "CropAndResize"
// input: "input"
// input: "boxes"
// input: "sizes"
CV_Assert(layer.input_size() == 3);
Mat cropSize = getTensorContent(getConstBlob(layer, value_id, 2));
CV_Assert(cropSize.type() == CV_32SC1, cropSize.total() == 2);
layerParams.set("height", cropSize.at<int>(0));
layerParams.set("width", cropSize.at<int>(1));
int id = dstNet.addLayer(name, "CropAndResize", layerParams);
layer_id[name] = id;
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
connect(layer_id, dstNet, parsePin(layer.input(1)), id, 1);
}
else if (type == "Mean")
{
Mat indices = getTensorContent(getConstBlob(layer, value_id, 1));

@ -311,11 +311,11 @@ struct TorchImporter
int numModules = curModule->modules.size();
readTorchObject(index);
if (tensors.count(index)) //tensor was readed
if (tensors.count(index)) //tensor was read
{
tensorParams.insert(std::make_pair(key, std::make_pair(index, tensors[index])));
}
else if (storages.count(index)) //storage was readed
else if (storages.count(index)) //storage was read
{
Mat &matStorage = storages[index];
Mat matCasted;
@ -399,7 +399,7 @@ struct TorchImporter
size_t requireElems = (size_t)offset + (size_t)steps[0] * (size_t)sizes[0];
size_t storageElems = storages[indexStorage].total();
if (requireElems > storageElems)
CV_Error(Error::StsBadSize, "Storage has insufficent number of elemements for requested Tensor");
CV_Error(Error::StsBadSize, "Storage has insufficient number of elements for requested Tensor");
//convert sizes
AutoBuffer<int, 4> isizes(ndims);

@ -49,7 +49,14 @@ public:
throw SkipTestException("OpenCL is not available/disabled in OpenCV");
}
}
if (target == DNN_TARGET_OPENCL_FP16)
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;
@ -80,10 +87,7 @@ public:
}
Mat out = net.forward(outputLayer).clone();
if (outputLayer == "detection_out")
normAssertDetections(outDefault, out, "First run", 0.2, l1, lInf);
else
normAssert(outDefault, out, "First run", l1, lInf);
check(outDefault, out, outputLayer, l1, lInf, "First run");
// Test 2: change input.
float* inpData = (float*)inp.data;
@ -97,18 +101,33 @@ public:
net.setInput(inp);
outDefault = netDefault.forward(outputLayer).clone();
out = net.forward(outputLayer).clone();
check(outDefault, out, outputLayer, l1, lInf, "Second run");
}
void check(Mat& ref, Mat& out, const std::string& outputLayer, double l1, double lInf, const char* msg)
{
if (outputLayer == "detection_out")
normAssertDetections(outDefault, out, "Second run", 0.2, l1, lInf);
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE)
{
// Inference Engine produces detections terminated by a row which starts from -1.
out = out.reshape(1, out.total() / 7);
int numDetections = 0;
while (numDetections < out.rows && out.at<float>(numDetections, 0) != -1)
{
numDetections += 1;
}
out = out.rowRange(0, numDetections);
}
normAssertDetections(ref, out, msg, 0.2, l1, lInf);
}
else
normAssert(outDefault, out, "Second run", l1, lInf);
normAssert(ref, out, msg, l1, lInf);
}
};
TEST_P(DNNTestNetwork, AlexNet)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
throw SkipTestException("");
processNet("dnn/bvlc_alexnet.caffemodel", "dnn/bvlc_alexnet.prototxt",
Size(227, 227), "prob",
target == DNN_TARGET_OPENCL ? "dnn/halide_scheduler_opencl_alexnet.yml" :
@ -158,8 +177,7 @@ TEST_P(DNNTestNetwork, ENet)
TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
@ -170,10 +188,11 @@ TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe)
inp, "detection_out", "", l1, lInf);
}
// TODO: update MobileNet model.
TEST_P(DNNTestNetwork, MobileNet_SSD_TensorFlow)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
backend == DNN_BACKEND_INFERENCE_ENGINE)
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
@ -185,31 +204,38 @@ TEST_P(DNNTestNetwork, MobileNet_SSD_TensorFlow)
TEST_P(DNNTestNetwork, SSD_VGG16)
{
if ((backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL_FP16) ||
(backend == DNN_BACKEND_HALIDE && target == DNN_TARGET_CPU) ||
(backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU))
if (backend == DNN_BACKEND_HALIDE && target == DNN_TARGET_CPU)
throw SkipTestException("");
double scoreThreshold = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.0252 : 0.0;
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f, Size(300, 300), Scalar(), false);
processNet("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel",
"dnn/ssd_vgg16.prototxt", Size(300, 300), "detection_out");
"dnn/ssd_vgg16.prototxt", inp, "detection_out", "", scoreThreshold);
}
TEST_P(DNNTestNetwork, OpenPose_pose_coco)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
processNet("dnn/openpose_pose_coco.caffemodel", "dnn/openpose_pose_coco.prototxt",
Size(368, 368));
}
TEST_P(DNNTestNetwork, OpenPose_pose_mpi)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi.prototxt",
Size(368, 368));
}
TEST_P(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
// The same .caffemodel but modified .prototxt
// See https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/src/openpose/pose/poseParameters.cpp
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi_faster_4_stages.prototxt",
@ -226,11 +252,13 @@ TEST_P(DNNTestNetwork, OpenFace)
TEST_P(DNNTestNetwork, opencv_face_detector)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
Size inpSize;
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
inpSize = Size(300, 300);
Mat img = imread(findDataFile("gpu/lbpcascade/er.png", false));
Mat inp = blobFromImage(img, 1.0, Size(), Scalar(104.0, 177.0, 123.0), false, false);
Mat inp = blobFromImage(img, 1.0, inpSize, Scalar(104.0, 177.0, 123.0), false, false);
processNet("dnn/opencv_face_detector.caffemodel", "dnn/opencv_face_detector.prototxt",
inp, "detection_out");
}
@ -238,12 +266,13 @@ TEST_P(DNNTestNetwork, opencv_face_detector)
TEST_P(DNNTestNetwork, Inception_v2_SSD_TensorFlow)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL) ||
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16))
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
float l1 = (backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL_FP16) ? 0.008 : 0.0;
float lInf = (backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL_FP16) ? 0.07 : 0.0;
float l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.008 : 0.0;
float lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.07 : 0.0;
processNet("dnn/ssd_inception_v2_coco_2017_11_17.pb", "dnn/ssd_inception_v2_coco_2017_11_17.pbtxt",
inp, "detection_out", "", l1, lInf);
}
@ -252,7 +281,8 @@ TEST_P(DNNTestNetwork, DenseNet_121)
{
if ((backend == DNN_BACKEND_HALIDE) ||
(backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL_FP16) ||
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16))
(backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL_FP16 ||
target == DNN_TARGET_MYRIAD)))
throw SkipTestException("");
processNet("dnn/DenseNet_121.caffemodel", "dnn/DenseNet_121.prototxt", Size(224, 224), "", "caffe");
}
@ -266,6 +296,7 @@ const tuple<DNNBackend, DNNTarget> testCases[] = {
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD),
#endif
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL_FP16)

@ -147,6 +147,28 @@ inline void normAssertDetections(cv::Mat ref, cv::Mat out, const char *comment =
testBoxes, comment, confThreshold, scores_diff, boxes_iou_diff);
}
inline bool checkMyriadTarget()
{
#ifndef HAVE_INF_ENGINE
return false;
#endif
cv::dnn::Net net;
cv::dnn::LayerParams lp;
net.addLayerToPrev("testLayer", "Identity", lp);
net.setPreferableBackend(cv::dnn::DNN_BACKEND_INFERENCE_ENGINE);
net.setPreferableTarget(cv::dnn::DNN_TARGET_MYRIAD);
net.setInput(cv::Mat::zeros(1, 1, CV_32FC1));
try
{
net.forward();
}
catch(...)
{
return false;
}
return true;
}
inline bool readFileInMemory(const std::string& filename, std::string& content)
{
std::ios::openmode mode = std::ios::in | std::ios::binary;

@ -71,13 +71,31 @@ static void testDarknetModel(const std::string& cfg, const std::string& weights,
const std::vector<int>& refClassIds,
const std::vector<float>& refConfidences,
const std::vector<Rect2d>& refBoxes,
int targetId, float confThreshold = 0.24)
int backendId, int targetId, float scoreDiff = 0.0,
float iouDiff = 0.0, float confThreshold = 0.24)
{
if (backendId == DNN_BACKEND_DEFAULT && targetId == DNN_TARGET_OPENCL)
{
#ifdef HAVE_OPENCL
if (!cv::ocl::useOpenCL())
#endif
{
throw SkipTestException("OpenCL is not available/disabled in OpenCV");
}
}
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD)
{
if (!checkMyriadTarget())
{
throw SkipTestException("Myriad is not available/disabled in OpenCV");
}
}
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<Mat> outs;
@ -108,42 +126,53 @@ static void testDarknetModel(const std::string& cfg, const std::string& weights,
}
}
normAssertDetections(refClassIds, refConfidences, refBoxes, classIds,
confidences, boxes, "", confThreshold, 8e-5, 3e-5);
confidences, boxes, "", confThreshold, scoreDiff, iouDiff);
}
typedef testing::TestWithParam<DNNTarget> Test_Darknet_nets;
typedef testing::TestWithParam<tuple<DNNBackend, DNNTarget> > Test_Darknet_nets;
TEST_P(Test_Darknet_nets, YoloVoc)
{
int targetId = GetParam();
int backendId = get<0>(GetParam());
int targetId = get<1>(GetParam());
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD)
throw SkipTestException("");
std::vector<cv::String> outNames(1, "detection_out");
std::vector<int> classIds(3);
std::vector<float> confidences(3);
std::vector<Rect2d> boxes(3);
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 bycicle
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) ? 7e-3 : 8e-5;
double iouDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 0.013 : 3e-5;
testDarknetModel("yolo-voc.cfg", "yolo-voc.weights", outNames,
classIds, confidences, boxes, targetId);
classIds, confidences, boxes, backendId, targetId, scoreDiff, iouDiff);
}
TEST_P(Test_Darknet_nets, TinyYoloVoc)
{
int targetId = GetParam();
int backendId = get<0>(GetParam());
int targetId = get<1>(GetParam());
std::vector<cv::String> outNames(1, "detection_out");
std::vector<int> classIds(2);
std::vector<float> confidences(2);
std::vector<Rect2d> 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;
testDarknetModel("tiny-yolo-voc.cfg", "tiny-yolo-voc.weights", outNames,
classIds, confidences, boxes, targetId);
classIds, confidences, boxes, backendId, targetId, scoreDiff, iouDiff);
}
TEST_P(Test_Darknet_nets, YOLOv3)
{
int targetId = GetParam();
int backendId = get<0>(GetParam());
int targetId = get<1>(GetParam());
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD)
throw SkipTestException("");
std::vector<cv::String> outNames(3);
outNames[0] = "yolo_82";
outNames[1] = "yolo_94";
@ -153,13 +182,27 @@ TEST_P(Test_Darknet_nets, YOLOv3)
std::vector<float> confidences(3);
std::vector<Rect2d> boxes(3);
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 bycicle
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;
testDarknetModel("yolov3.cfg", "yolov3.weights", outNames,
classIds, confidences, boxes, targetId);
classIds, confidences, boxes, backendId, targetId, scoreDiff, iouDiff);
}
INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_nets, availableDnnTargets());
const tuple<DNNBackend, DNNTarget> testCases[] = {
#ifdef HAVE_INF_ENGINE
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD),
#endif
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL_FP16)
};
INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_nets, testing::ValuesIn(testCases));
static void testDarknetLayer(const std::string& name, bool hasWeights = false)
{

@ -834,6 +834,84 @@ TEST(Test_DLDT, two_inputs)
normAssert(out, firstInp + secondInp);
}
class UnsupportedLayer : public Layer
{
public:
UnsupportedLayer(const LayerParams &params) {}
static Ptr<Layer> create(const LayerParams& params)
{
return Ptr<Layer>(new UnsupportedLayer(params));
}
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_DEFAULT;
}
virtual void forward(std::vector<cv::Mat*> &inputs, std::vector<cv::Mat> &outputs, std::vector<cv::Mat> &internals) CV_OVERRIDE {}
virtual void forward(cv::InputArrayOfArrays inputs, cv::OutputArrayOfArrays outputs, cv::OutputArrayOfArrays internals) CV_OVERRIDE {}
};
TEST(Test_DLDT, fused_output)
{
static const int kNumChannels = 3;
CV_DNN_REGISTER_LAYER_CLASS(Unsupported, UnsupportedLayer);
Net net;
{
LayerParams lp;
lp.set("kernel_size", 1);
lp.set("num_output", 3);
lp.set("bias_term", false);
lp.type = "Convolution";
lp.name = "testConv";
lp.blobs.push_back(Mat({kNumChannels, 1, 1, 1}, CV_32F, Scalar(1)));
net.addLayerToPrev(lp.name, lp.type, lp);
}
{
LayerParams lp;
lp.set("bias_term", false);
lp.type = "Scale";
lp.name = "testScale";
lp.blobs.push_back(Mat({kNumChannels}, CV_32F, Scalar(1)));
net.addLayerToPrev(lp.name, lp.type, lp);
}
{
LayerParams lp;
net.addLayerToPrev("unsupported_layer", "Unsupported", lp);
}
net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
net.setInput(Mat({1, 1, 1, 1}, CV_32FC1, Scalar(1)));
ASSERT_NO_THROW(net.forward());
LayerFactory::unregisterLayer("Unsupported");
}
TEST(Test_DLDT, multiple_networks)
{
Net nets[2];
for (int i = 0; i < 2; ++i)
{
nets[i].setInputsNames(std::vector<String>(1, format("input_%d", i)));
LayerParams lp;
lp.set("kernel_size", 1);
lp.set("num_output", 1);
lp.set("bias_term", false);
lp.type = "Convolution";
lp.name = format("testConv_%d", i);
lp.blobs.push_back(Mat({1, 1, 1, 1}, CV_32F, Scalar(1 + i)));
nets[i].addLayerToPrev(lp.name, lp.type, lp);
nets[i].setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
nets[i].setInput(Mat({1, 1, 1, 1}, CV_32FC1, Scalar(1)));
}
Mat out_1 = nets[0].forward();
Mat out_2 = nets[1].forward();
// After the second model is initialized we try to receive an output from the first network again.
out_1 = nets[0].forward();
normAssert(2 * out_1, out_2);
}
#endif // HAVE_INF_ENGINE
// Test a custom layer.

@ -49,11 +49,11 @@
#include "opencv2/dnn.hpp"
#include "test_common.hpp"
namespace opencv_test {
namespace opencv_test { namespace {
using namespace cv::dnn;
CV_ENUM(DNNBackend, DNN_BACKEND_DEFAULT, DNN_BACKEND_HALIDE, DNN_BACKEND_INFERENCE_ENGINE)
CV_ENUM(DNNTarget, DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16)
CV_ENUM(DNNTarget, DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16, DNN_TARGET_MYRIAD)
static testing::internal::ParamGenerator<DNNTarget> availableDnnTargets()
{
@ -69,6 +69,6 @@ static testing::internal::ParamGenerator<DNNTarget> availableDnnTargets()
return testing::ValuesIn(targets);
}
}
}}
#endif

@ -124,6 +124,7 @@ TEST_P(Test_TensorFlow_layers, conv)
runTensorFlowNet("atrous_conv2d_valid", targetId);
runTensorFlowNet("atrous_conv2d_same", targetId);
runTensorFlowNet("depthwise_conv2d", targetId);
runTensorFlowNet("keras_atrous_conv2d_same", targetId);
}
TEST_P(Test_TensorFlow_layers, padding)
@ -160,10 +161,12 @@ TEST_P(Test_TensorFlow_layers, batch_norm)
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);
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.
}
@ -267,6 +270,22 @@ TEST_P(Test_TensorFlow_nets, Inception_v2_SSD)
normAssertDetections(ref, out, "", 0.5);
}
TEST_P(Test_TensorFlow_nets, Inception_v2_Faster_RCNN)
{
std::string proto = findDataFile("dnn/faster_rcnn_inception_v2_coco_2018_01_28.pbtxt", false);
std::string model = findDataFile("dnn/faster_rcnn_inception_v2_coco_2018_01_28.pb", false);
Net net = readNetFromTensorflow(model, proto);
Mat img = imread(findDataFile("dnn/dog416.png", false));
Mat blob = blobFromImage(img, 1.0f / 127.5, Size(800, 600), Scalar(127.5, 127.5, 127.5), true, false);
net.setInput(blob);
Mat out = net.forward();
Mat ref = blobFromNPY(findDataFile("dnn/tensorflow/faster_rcnn_inception_v2_coco_2018_01_28.detection_out.npy"));
normAssertDetections(ref, out, "", 0.3);
}
TEST_P(Test_TensorFlow_nets, opencv_face_detector_uint8)
{
std::string proto = findDataFile("dnn/opencv_face_detector.pbtxt", false);

@ -250,7 +250,7 @@ TEST_P(Test_Torch_nets, ENet_accuracy)
Mat out = net.forward();
Mat ref = blobFromNPY(_tf("torch_enet_prob.npy", false));
// Due to numerical instability in Pooling-Unpooling layers (indexes jittering)
// thresholds for ENet must be changed. Accuracy of resuults was checked on
// thresholds for ENet must be changed. Accuracy of results was checked on
// Cityscapes dataset and difference in mIOU with Torch is 10E-4%
normAssert(ref, out, "", 0.00044, 0.44);

@ -7952,6 +7952,12 @@ public:
{
CV_INSTRUMENT_REGION()
if(_image.empty())
{
keypoints.clear();
return;
}
Mat mask = _mask.getMat(), grayImage;
UMat ugrayImage;
_InputArray gray = _image;

@ -522,6 +522,12 @@ public:
{
CV_INSTRUMENT_REGION()
if(_image.empty())
{
keypoints.clear();
return;
}
Mat mask = _mask.getMat(), grayImage;
UMat ugrayImage;
_InputArray gray = _image;

@ -80,6 +80,12 @@ public:
{
CV_INSTRUMENT_REGION()
if(_image.empty())
{
keypoints.clear();
return;
}
std::vector<Point2f> corners;
if (_image.isUMat())

@ -159,40 +159,7 @@ In OpenCV you only need applyColorMap to apply a colormap on a given image. The
code reads the path to an image from command line, applies a Jet colormap on it and shows the
result:
@code
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
// We need an input image. (can be grayscale or color)
if (argc < 2)
{
cerr << "We need an image to process here. Please run: colorMap [path_to_image]" << endl;
return -1;
}
Mat img_in = imread(argv[1]);
if(img_in.empty())
{
cerr << "Sample image (" << argv[1] << ") is empty. Please adjust your path, so it points to a valid input image!" << endl;
return -1;
}
// Holds the colormap version of the image:
Mat img_color;
// Apply the colormap:
applyColorMap(img_in, img_color, COLORMAP_JET);
// Show the result:
imshow("colorMap", img_color);
waitKey(0);
return 0;
}
@endcode
@include snippets/imgproc_applyColorMap.cpp
@see #ColormapTypes
@ -2007,58 +1974,7 @@ The function implements the probabilistic Hough transform algorithm for line det
in @cite Matas00
See the line detection example below:
@code
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src, dst, color_dst;
if( argc != 2 || !(src=imread(argv[1], 0)).data)
return -1;
Canny( src, dst, 50, 200, 3 );
cvtColor( dst, color_dst, COLOR_GRAY2BGR );
#if 0
vector<Vec2f> lines;
HoughLines( dst, lines, 1, CV_PI/180, 100 );
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0];
float theta = lines[i][1];
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
Point pt1(cvRound(x0 + 1000*(-b)),
cvRound(y0 + 1000*(a)));
Point pt2(cvRound(x0 - 1000*(-b)),
cvRound(y0 - 1000*(a)));
line( color_dst, pt1, pt2, Scalar(0,0,255), 3, 8 );
}
#else
vector<Vec4i> lines;
HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 );
for( size_t i = 0; i < lines.size(); i++ )
{
line( color_dst, Point(lines[i][0], lines[i][1]),
Point(lines[i][2], lines[i][3]), Scalar(0,0,255), 3, 8 );
}
#endif
namedWindow( "Source", 1 );
imshow( "Source", src );
namedWindow( "Detected Lines", 1 );
imshow( "Detected Lines", color_dst );
waitKey(0);
return 0;
}
@endcode
@include snippets/imgproc_HoughLinesP.cpp
This is a sample picture the function parameters have been tuned for:
![image](pics/building.jpg)
@ -2114,41 +2030,7 @@ An example using the Hough circle detector
The function finds circles in a grayscale image using a modification of the Hough transform.
Example: :
@code
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat img, gray;
if( argc != 2 || !(img=imread(argv[1], 1)).data)
return -1;
cvtColor(img, gray, COLOR_BGR2GRAY);
// smooth it, otherwise a lot of false circles may be detected
GaussianBlur( gray, gray, Size(9, 9), 2, 2 );
vector<Vec3f> circles;
HoughCircles(gray, circles, HOUGH_GRADIENT,
2, gray.rows/4, 200, 100 );
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the circle center
circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 );
// draw the circle outline
circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
namedWindow( "circles", 1 );
imshow( "circles", img );
waitKey(0);
return 0;
}
@endcode
@include snippets/imgproc_HoughLinesCircles.cpp
@note Usually the function detects the centers of circles well. However, it may fail to find correct
radii. You can assist to the function by specifying the radius range ( minRadius and maxRadius ) if
@ -3247,63 +3129,7 @@ An example for creating histograms of an image
The function cv::calcHist calculates the histogram of one or more arrays. The elements of a tuple used
to increment a histogram bin are taken from the corresponding input arrays at the same location. The
sample below shows how to compute a 2D Hue-Saturation histogram for a color image. :
@code
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
int main( int argc, char** argv )
{
Mat src, hsv;
if( argc != 2 || !(src=imread(argv[1], 1)).data )
return -1;
cvtColor(src, hsv, COLOR_BGR2HSV);
// Quantize the hue to 30 levels
// and the saturation to 32 levels
int hbins = 30, sbins = 32;
int histSize[] = {hbins, sbins};
// hue varies from 0 to 179, see cvtColor
float hranges[] = { 0, 180 };
// saturation varies from 0 (black-gray-white) to
// 255 (pure spectrum color)
float sranges[] = { 0, 256 };
const float* ranges[] = { hranges, sranges };
MatND hist;
// we compute the histogram from the 0-th and 1-st channels
int channels[] = {0, 1};
calcHist( &hsv, 1, channels, Mat(), // do not use mask
hist, 2, histSize, ranges,
true, // the histogram is uniform
false );
double maxVal=0;
minMaxLoc(hist, 0, &maxVal, 0, 0);
int scale = 10;
Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3);
for( int h = 0; h < hbins; h++ )
for( int s = 0; s < sbins; s++ )
{
float binVal = hist.at<float>(h, s);
int intensity = cvRound(binVal*255/maxVal);
rectangle( histImg, Point(h*scale, s*scale),
Point( (h+1)*scale - 1, (s+1)*scale - 1),
Scalar::all(intensity),
CV_FILLED );
}
namedWindow( "Source", 1 );
imshow( "Source", src );
namedWindow( "H-S Histogram", 1 );
imshow( "H-S Histogram", histImg );
waitKey();
}
@endcode
@include snippets/imgproc_calcHist.cpp
@param images Source arrays. They all should have the same depth, CV_8U, CV_16U or CV_32F , and the same
size. Each of them can have an arbitrary number of channels.
@ -4698,47 +4524,7 @@ An example using drawContours to clean up a background segmentation result
The function draws contour outlines in the image if \f$\texttt{thickness} \ge 0\f$ or fills the area
bounded by the contours if \f$\texttt{thickness}<0\f$ . The example below shows how to retrieve
connected components from the binary image and label them: :
@code
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
Mat src;
// the first command-line parameter must be a filename of the binary
// (black-n-white) image
if( argc != 2 || !(src=imread(argv[1], 0)).data)
return -1;
Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);
src = src > 1;
namedWindow( "Source", 1 );
imshow( "Source", src );
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( src, contours, hierarchy,
RETR_CCOMP, CHAIN_APPROX_SIMPLE );
// iterate through all the top-level contours,
// draw each connected component with its own random color
int idx = 0;
for( ; idx >= 0; idx = hierarchy[idx][0] )
{
Scalar color( rand()&255, rand()&255, rand()&255 );
drawContours( dst, contours, idx, color, FILLED, 8, hierarchy );
}
namedWindow( "Components", 1 );
imshow( "Components", dst );
waitKey(0);
}
@endcode
@include snippets/imgproc_drawContours.cpp
@param image Destination image.
@param contours All the input contours. Each contour is stored as a point vector.

@ -213,6 +213,91 @@ struct RGB2HSV_f
};
#if CV_SIMD128
inline void HSV2RGB_simd(v_float32x4& v_h, v_float32x4& v_s, v_float32x4& v_v, float hscale)
{
v_h = v_h * v_setall_f32(hscale);
v_float32x4 v_pre_sector = v_cvt_f32(v_trunc(v_h));
v_h = v_h - v_pre_sector;
v_float32x4 v_tab0 = v_v;
v_float32x4 v_one = v_setall_f32(1.0f);
v_float32x4 v_tab1 = v_v * (v_one - v_s);
v_float32x4 v_tab2 = v_v * (v_one - (v_s * v_h));
v_float32x4 v_tab3 = v_v * (v_one - (v_s * (v_one - v_h)));
v_float32x4 v_one_sixth = v_setall_f32(1.0f / 6.0f);
v_float32x4 v_sector = v_pre_sector * v_one_sixth;
v_sector = v_cvt_f32(v_trunc(v_sector));
v_float32x4 v_six = v_setall_f32(6.0f);
v_sector = v_pre_sector - (v_sector * v_six);
v_float32x4 v_two = v_setall_f32(2.0f);
v_h = v_tab1 & (v_sector < v_two);
v_h = v_h | (v_tab3 & (v_sector == v_two));
v_float32x4 v_three = v_setall_f32(3.0f);
v_h = v_h | (v_tab0 & (v_sector == v_three));
v_float32x4 v_four = v_setall_f32(4.0f);
v_h = v_h | (v_tab0 & (v_sector == v_four));
v_h = v_h | (v_tab2 & (v_sector > v_four));
v_s = v_tab3 & (v_sector < v_one);
v_s = v_s | (v_tab0 & (v_sector == v_one));
v_s = v_s | (v_tab0 & (v_sector == v_two));
v_s = v_s | (v_tab2 & (v_sector == v_three));
v_s = v_s | (v_tab1 & (v_sector > v_three));
v_v = v_tab0 & (v_sector < v_one);
v_v = v_v | (v_tab2 & (v_sector == v_one));
v_v = v_v | (v_tab1 & (v_sector == v_two));
v_v = v_v | (v_tab1 & (v_sector == v_three));
v_v = v_v | (v_tab3 & (v_sector == v_four));
v_v = v_v | (v_tab0 & (v_sector > v_four));
}
#endif
inline void HSV2RGB_native(const float* src, float* dst, const float hscale, const int bidx)
{
float h = src[0], s = src[1], v = src[2];
float b, g, r;
if( s == 0 )
b = g = r = v;
else
{
static const int sector_data[][3]=
{{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
float tab[4];
int sector;
h *= hscale;
if( h < 0 )
do h += 6; while( h < 0 );
else if( h >= 6 )
do h -= 6; while( h >= 6 );
sector = cvFloor(h);
h -= sector;
if( (unsigned)sector >= 6u )
{
sector = 0;
h = 0.f;
}
tab[0] = v;
tab[1] = v*(1.f - s);
tab[2] = v*(1.f - s*h);
tab[3] = v*(1.f - s*(1.f - h));
b = tab[sector_data[sector][0]];
g = tab[sector_data[sector][1]];
r = tab[sector_data[sector][2]];
}
dst[bidx] = b;
dst[1] = g;
dst[bidx^2] = r;
}
struct HSV2RGB_f
{
typedef float channel_type;
@ -224,152 +309,49 @@ struct HSV2RGB_f
#endif
}
#if CV_SIMD128
inline void process(v_float32x4& v_h, v_float32x4& v_s,
v_float32x4& v_v, v_float32x4& v_scale) const
{
v_h = v_h * v_scale;
v_float32x4 v_pre_sector = v_cvt_f32(v_trunc(v_h));
v_h = v_h - v_pre_sector;
v_float32x4 v_tab0 = v_v;
v_float32x4 v_one = v_setall_f32(1.0f);
v_float32x4 v_tab1 = v_v * (v_one - v_s);
v_float32x4 v_tab2 = v_v * (v_one - (v_s * v_h));
v_float32x4 v_tab3 = v_v * (v_one - (v_s * (v_one - v_h)));
v_float32x4 v_one_sixth = v_setall_f32(1.0f / 6.0f);
v_float32x4 v_sector = v_pre_sector * v_one_sixth;
v_sector = v_cvt_f32(v_trunc(v_sector));
v_float32x4 v_six = v_setall_f32(6.0f);
v_sector = v_pre_sector - (v_sector * v_six);
v_float32x4 v_two = v_setall_f32(2.0f);
v_h = v_tab1 & (v_sector < v_two);
v_h = v_h | (v_tab3 & (v_sector == v_two));
v_float32x4 v_three = v_setall_f32(3.0f);
v_h = v_h | (v_tab0 & (v_sector == v_three));
v_float32x4 v_four = v_setall_f32(4.0f);
v_h = v_h | (v_tab0 & (v_sector == v_four));
v_h = v_h | (v_tab2 & (v_sector > v_four));
v_s = v_tab3 & (v_sector < v_one);
v_s = v_s | (v_tab0 & (v_sector == v_one));
v_s = v_s | (v_tab0 & (v_sector == v_two));
v_s = v_s | (v_tab2 & (v_sector == v_three));
v_s = v_s | (v_tab1 & (v_sector > v_three));
v_v = v_tab0 & (v_sector < v_one);
v_v = v_v | (v_tab2 & (v_sector == v_one));
v_v = v_v | (v_tab1 & (v_sector == v_two));
v_v = v_v | (v_tab1 & (v_sector == v_three));
v_v = v_v | (v_tab3 & (v_sector == v_four));
v_v = v_v | (v_tab0 & (v_sector > v_four));
}
#endif
void operator()(const float* src, float* dst, int n) const
{
int i = 0, bidx = blueIdx, dcn = dstcn;
float alpha = ColorChannel<float>::max();
n *= 3;
#if CV_SIMD128
if (hasSIMD)
if (dcn == 3)
{
v_float32x4 v_scale = v_setall_f32(hscale);
if (dcn == 3)
#if CV_SIMD128
if (hasSIMD)
{
if (bidx)
{
for (; i <= n - 12; i += 12, dst += dcn * 4)
{
v_float32x4 v_h;
v_float32x4 v_s;
v_float32x4 v_v;
v_load_deinterleave(src + i, v_h, v_s, v_v);
process(v_h, v_s, v_v, v_scale);
v_store_interleave(dst, v_v, v_s, v_h);
}
} else {
for (; i <= n - 12; i += 12, dst += dcn * 4)
{
v_float32x4 v_h;
v_float32x4 v_s;
v_float32x4 v_v;
v_load_deinterleave(src + i, v_h, v_s, v_v);
process(v_h, v_s, v_v, v_scale);
v_store_interleave(dst, v_h, v_s, v_v);
}
}
} else { // dcn == 4
v_float32x4 v_a = v_setall_f32(alpha);
if (bidx)
for (; i <= n - 12; i += 12, dst += dcn * 4)
{
for (; i <= n - 12; i += 12, dst += dcn * 4)
{
v_float32x4 v_h;
v_float32x4 v_s;
v_float32x4 v_v;
v_load_deinterleave(src + i, v_h, v_s, v_v);
process(v_h, v_s, v_v, v_scale);
v_store_interleave(dst, v_v, v_s, v_h, v_a);
}
} else {
for (; i <= n - 12; i += 12, dst += dcn * 4)
{
v_float32x4 v_h;
v_float32x4 v_s;
v_float32x4 v_v;
v_load_deinterleave(src + i, v_h, v_s, v_v);
process(v_h, v_s, v_v, v_scale);
v_store_interleave(dst, v_h, v_s, v_v, v_a);
}
v_float32x4 v_src[3];
v_load_deinterleave(src + i, v_src[0], v_src[1], v_src[2]);
HSV2RGB_simd(v_src[0], v_src[1], v_src[2], hscale);
v_store_interleave(dst, v_src[bidx], v_src[1], v_src[bidx^2]);
}
}
}
#endif
for( ; i < n; i += 3, dst += dcn )
{
float h = src[i], s = src[i+1], v = src[i+2];
float b, g, r;
if( s == 0 )
b = g = r = v;
else
#endif
for( ; i < n; i += 3, dst += dcn )
{
static const int sector_data[][3]=
{{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
float tab[4];
int sector;
h *= hscale;
if( h < 0 )
do h += 6; while( h < 0 );
else if( h >= 6 )
do h -= 6; while( h >= 6 );
sector = cvFloor(h);
h -= sector;
if( (unsigned)sector >= 6u )
HSV2RGB_native(src + i, dst, hscale, bidx);
}
} else { // dcn == 4
float alpha = ColorChannel<float>::max();
#if CV_SIMD128
if (hasSIMD)
{
for (; i <= n - 12; i += 12, dst += dcn * 4)
{
sector = 0;
h = 0.f;
v_float32x4 v_src[3];
v_load_deinterleave(src + i, v_src[0], v_src[1], v_src[2]);
HSV2RGB_simd(v_src[0], v_src[1], v_src[2], hscale);
v_float32x4 v_a = v_setall_f32(alpha);
v_store_interleave(dst, v_src[bidx], v_src[1], v_src[bidx^2], v_a);
}
tab[0] = v;
tab[1] = v*(1.f - s);
tab[2] = v*(1.f - s*h);
tab[3] = v*(1.f - s*(1.f - h));
b = tab[sector_data[sector][0]];
g = tab[sector_data[sector][1]];
r = tab[sector_data[sector][2]];
}
dst[bidx] = b;
dst[1] = g;
dst[bidx^2] = r;
if( dcn == 4 )
#endif
for( ; i < n; i += 3, dst += dcn )
{
HSV2RGB_native(src + i, dst, hscale, bidx);
dst[3] = alpha;
}
}
}
@ -386,216 +368,111 @@ struct HSV2RGB_b
typedef uchar channel_type;
HSV2RGB_b(int _dstcn, int _blueIdx, int _hrange)
: dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange)
: dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.0f / _hrange)
{
#if CV_NEON
v_scale_inv = vdupq_n_f32(1.f/255.f);
v_scale = vdupq_n_f32(255.f);
v_alpha = vdup_n_u8(ColorChannel<uchar>::max());
#elif CV_SSE2
v_scale = _mm_set1_ps(255.0f);
v_alpha = _mm_set1_ps(ColorChannel<uchar>::max());
v_zero = _mm_setzero_si128();
haveSIMD = checkHardwareSupport(CV_CPU_SSE2);
#if CV_SIMD128
hasSIMD = hasSIMD128();
#endif
}
#if CV_SSE2
void process(__m128i v_r, __m128i v_g, __m128i v_b,
const __m128& v_coeffs_,
float * buf) const
{
__m128 v_r0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_r, v_zero));
__m128 v_g0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_g, v_zero));
__m128 v_b0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_b, v_zero));
__m128 v_r1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_r, v_zero));
__m128 v_g1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_g, v_zero));
__m128 v_b1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_b, v_zero));
__m128 v_coeffs = v_coeffs_;
v_r0 = _mm_mul_ps(v_r0, v_coeffs);
v_g1 = _mm_mul_ps(v_g1, v_coeffs);
v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49));
v_r1 = _mm_mul_ps(v_r1, v_coeffs);
v_b0 = _mm_mul_ps(v_b0, v_coeffs);
v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49));
v_g0 = _mm_mul_ps(v_g0, v_coeffs);
v_b1 = _mm_mul_ps(v_b1, v_coeffs);
_mm_store_ps(buf, v_r0);
_mm_store_ps(buf + 4, v_r1);
_mm_store_ps(buf + 8, v_g0);
_mm_store_ps(buf + 12, v_g1);
_mm_store_ps(buf + 16, v_b0);
_mm_store_ps(buf + 20, v_b1);
}
#endif
void operator()(const uchar* src, uchar* dst, int n) const
{
int i, j, dcn = dstcn;
int j = 0, dcn = dstcn;
uchar alpha = ColorChannel<uchar>::max();
float CV_DECL_ALIGNED(16) buf[3*BLOCK_SIZE];
#if CV_SSE2
__m128 v_coeffs = _mm_set_ps(1.f, 1.f/255.f, 1.f/255.f, 1.f);
#endif
for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
#if CV_SIMD128
if (hasSIMD)
{
int dn = std::min(n - i, (int)BLOCK_SIZE);
j = 0;
#if CV_NEON
for ( ; j <= (dn - 8) * 3; j += 24)
{
uint8x8x3_t v_src = vld3_u8(src + j);
uint16x8_t v_t0 = vmovl_u8(v_src.val[0]),
v_t1 = vmovl_u8(v_src.val[1]),
v_t2 = vmovl_u8(v_src.val[2]);
float32x4x3_t v_dst;
v_dst.val[0] = vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_t0)));
v_dst.val[1] = vmulq_f32(vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_t1))), v_scale_inv);
v_dst.val[2] = vmulq_f32(vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_t2))), v_scale_inv);
vst3q_f32(buf + j, v_dst);
v_dst.val[0] = vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_t0)));
v_dst.val[1] = vmulq_f32(vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_t1))), v_scale_inv);
v_dst.val[2] = vmulq_f32(vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_t2))), v_scale_inv);
vst3q_f32(buf + j + 12, v_dst);
}
#elif CV_SSE2
if (haveSIMD)
for (j = 0; j <= (n - 16) * 3; j += 48, dst += dcn * 16)
{
for ( ; j <= (dn - 8) * 3; j += 24)
v_uint8x16 h_b, s_b, v_b;
v_uint16x8 h_w[2], s_w[2], v_w[2];
v_uint32x4 h_u[4], s_u[4], v_u[4];
v_load_deinterleave(src + j, h_b, s_b, v_b);
v_expand(h_b, h_w[0], h_w[1]);
v_expand(s_b, s_w[0], s_w[1]);
v_expand(v_b, v_w[0], v_w[1]);
v_expand(h_w[0], h_u[0], h_u[1]);
v_expand(h_w[1], h_u[2], h_u[3]);
v_expand(s_w[0], s_u[0], s_u[1]);
v_expand(s_w[1], s_u[2], s_u[3]);
v_expand(v_w[0], v_u[0], v_u[1]);
v_expand(v_w[1], v_u[2], v_u[3]);
v_int32x4 b_i[4], g_i[4], r_i[4];
v_float32x4 v_coeff0 = v_setall_f32(1.0f / 255.0f);
v_float32x4 v_coeff1 = v_setall_f32(255.0f);
for( int k = 0; k < 4; k++ )
{
__m128i v_src0 = _mm_loadu_si128((__m128i const *)(src + j));
__m128i v_src1 = _mm_loadl_epi64((__m128i const *)(src + j + 16));
process(_mm_unpacklo_epi8(v_src0, v_zero),
_mm_unpackhi_epi8(v_src0, v_zero),
_mm_unpacklo_epi8(v_src1, v_zero),
v_coeffs,
buf + j);
v_float32x4 v_src[3];
v_src[0] = v_cvt_f32(v_reinterpret_as_s32(h_u[k]));
v_src[1] = v_cvt_f32(v_reinterpret_as_s32(s_u[k]));
v_src[2] = v_cvt_f32(v_reinterpret_as_s32(v_u[k]));
v_src[1] *= v_coeff0;
v_src[2] *= v_coeff0;
HSV2RGB_simd(v_src[0], v_src[1], v_src[2], hscale);
v_src[0] *= v_coeff1;
v_src[1] *= v_coeff1;
v_src[2] *= v_coeff1;
b_i[k] = v_trunc(v_src[0]);
g_i[k] = v_trunc(v_src[1]);
r_i[k] = v_trunc(v_src[2]);
}
}
#endif
for( ; j < dn*3; j += 3 )
{
buf[j] = src[j];
buf[j+1] = src[j+1]*(1.f/255.f);
buf[j+2] = src[j+2]*(1.f/255.f);
}
cvt(buf, buf, dn);
v_uint16x8 r_w[2], g_w[2], b_w[2];
v_uint8x16 r_b, g_b, b_b;
j = 0;
#if CV_NEON
for ( ; j <= (dn - 8) * 3; j += 24, dst += dcn * 8)
{
float32x4x3_t v_src0 = vld3q_f32(buf + j), v_src1 = vld3q_f32(buf + j + 12);
uint8x8_t v_dst0 = vqmovn_u16(vcombine_u16(vqmovn_u32(cv_vrndq_u32_f32(vmulq_f32(v_src0.val[0], v_scale))),
vqmovn_u32(cv_vrndq_u32_f32(vmulq_f32(v_src1.val[0], v_scale)))));
uint8x8_t v_dst1 = vqmovn_u16(vcombine_u16(vqmovn_u32(cv_vrndq_u32_f32(vmulq_f32(v_src0.val[1], v_scale))),
vqmovn_u32(cv_vrndq_u32_f32(vmulq_f32(v_src1.val[1], v_scale)))));
uint8x8_t v_dst2 = vqmovn_u16(vcombine_u16(vqmovn_u32(cv_vrndq_u32_f32(vmulq_f32(v_src0.val[2], v_scale))),
vqmovn_u32(cv_vrndq_u32_f32(vmulq_f32(v_src1.val[2], v_scale)))));
r_w[0] = v_pack_u(r_i[0], r_i[1]);
r_w[1] = v_pack_u(r_i[2], r_i[3]);
r_b = v_pack(r_w[0], r_w[1]);
g_w[0] = v_pack_u(g_i[0], g_i[1]);
g_w[1] = v_pack_u(g_i[2], g_i[3]);
g_b = v_pack(g_w[0], g_w[1]);
b_w[0] = v_pack_u(b_i[0], b_i[1]);
b_w[1] = v_pack_u(b_i[2], b_i[3]);
b_b = v_pack(b_w[0], b_w[1]);
if (dcn == 4)
if( dcn == 3 )
{
uint8x8x4_t v_dst;
v_dst.val[0] = v_dst0;
v_dst.val[1] = v_dst1;
v_dst.val[2] = v_dst2;
v_dst.val[3] = v_alpha;
vst4_u8(dst, v_dst);
if( blueIdx == 0 )
v_store_interleave(dst, b_b, g_b, r_b);
else
v_store_interleave(dst, r_b, g_b, b_b);
}
else
{
uint8x8x3_t v_dst;
v_dst.val[0] = v_dst0;
v_dst.val[1] = v_dst1;
v_dst.val[2] = v_dst2;
vst3_u8(dst, v_dst);
v_uint8x16 alpha_b = v_setall_u8(alpha);
if( blueIdx == 0 )
v_store_interleave(dst, b_b, g_b, r_b, alpha_b);
else
v_store_interleave(dst, r_b, g_b, b_b, alpha_b);
}
}
#elif CV_SSE2
if (dcn == 3 && haveSIMD)
{
for ( ; j <= (dn * 3 - 16); j += 16, dst += 16)
{
__m128 v_src0 = _mm_mul_ps(_mm_load_ps(buf + j), v_scale);
__m128 v_src1 = _mm_mul_ps(_mm_load_ps(buf + j + 4), v_scale);
__m128 v_src2 = _mm_mul_ps(_mm_load_ps(buf + j + 8), v_scale);
__m128 v_src3 = _mm_mul_ps(_mm_load_ps(buf + j + 12), v_scale);
__m128i v_dst0 = _mm_packs_epi32(_mm_cvtps_epi32(v_src0),
_mm_cvtps_epi32(v_src1));
__m128i v_dst1 = _mm_packs_epi32(_mm_cvtps_epi32(v_src2),
_mm_cvtps_epi32(v_src3));
_mm_storeu_si128((__m128i *)dst, _mm_packus_epi16(v_dst0, v_dst1));
}
int jr = j % 3;
if (jr)
dst -= jr, j -= jr;
}
else if (dcn == 4 && haveSIMD)
{
for ( ; j <= (dn * 3 - 12); j += 12, dst += 16)
{
__m128 v_buf0 = _mm_mul_ps(_mm_load_ps(buf + j), v_scale);
__m128 v_buf1 = _mm_mul_ps(_mm_load_ps(buf + j + 4), v_scale);
__m128 v_buf2 = _mm_mul_ps(_mm_load_ps(buf + j + 8), v_scale);
__m128 v_ba0 = _mm_unpackhi_ps(v_buf0, v_alpha);
__m128 v_ba1 = _mm_unpacklo_ps(v_buf2, v_alpha);
__m128i v_src0 = _mm_cvtps_epi32(_mm_shuffle_ps(v_buf0, v_ba0, 0x44));
__m128i v_src1 = _mm_shuffle_epi32(_mm_cvtps_epi32(_mm_shuffle_ps(v_ba0, v_buf1, 0x4e)), 0x78);
__m128i v_src2 = _mm_cvtps_epi32(_mm_shuffle_ps(v_buf1, v_ba1, 0x4e));
__m128i v_src3 = _mm_shuffle_epi32(_mm_cvtps_epi32(_mm_shuffle_ps(v_ba1, v_buf2, 0xee)), 0x78);
__m128i v_dst0 = _mm_packs_epi32(v_src0, v_src1);
__m128i v_dst1 = _mm_packs_epi32(v_src2, v_src3);
_mm_storeu_si128((__m128i *)dst, _mm_packus_epi16(v_dst0, v_dst1));
}
int jr = j % 3;
if (jr)
dst -= jr, j -= jr;
}
#endif
for( ; j < dn*3; j += 3, dst += dcn )
{
dst[0] = saturate_cast<uchar>(buf[j]*255.f);
dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
if( dcn == 4 )
dst[3] = alpha;
}
}
#endif
for( ; j < n * 3; j += 3, dst += dcn )
{
float buf[6];
buf[0] = src[j];
buf[1] = src[j+1] * (1.0f / 255.0f);
buf[2] = src[j+2] * (1.0f / 255.0f);
HSV2RGB_native(buf, buf + 3, hscale, blueIdx);
dst[0] = saturate_cast<uchar>(buf[3] * 255.0f);
dst[1] = saturate_cast<uchar>(buf[4] * 255.0f);
dst[2] = saturate_cast<uchar>(buf[5] * 255.0f);
if( dcn == 4 )
dst[3] = alpha;
}
}
int dstcn;
HSV2RGB_f cvt;
#if CV_NEON
float32x4_t v_scale, v_scale_inv;
uint8x8_t v_alpha;
#elif CV_SSE2
__m128 v_scale;
__m128 v_alpha;
__m128i v_zero;
bool haveSIMD;
int blueIdx;
float hscale;
#if CV_SIMD128
bool hasSIMD;
#endif
};

@ -821,6 +821,10 @@ static bool ipp_calchist(const Mat &image, Mat &hist, int histSize, const float*
return false;
#endif
// IPP_DISABLE_HISTOGRAM - https://github.com/opencv/opencv/issues/11544
if (uniform && (ranges[0][1] - ranges[0][0]) != histSize)
return false;
Mat ihist = hist;
if(accumulate)
ihist.create(1, &histSize, CV_32S);

@ -803,7 +803,7 @@ static bool ocl_HoughLines(InputArray _src, OutputArray _lines, double rho, doub
int total_points = counters.getMat(ACCESS_READ).at<int>(0, 0);
if (total_points <= 0)
{
_lines.assign(UMat(0,0,CV_32FC2));
_lines.release();
return true;
}
@ -831,7 +831,7 @@ static bool ocl_HoughLines(InputArray _src, OutputArray _lines, double rho, doub
if (total_lines > 0)
_lines.assign(lines.rowRange(Range(0, total_lines)));
else
_lines.assign(UMat(0,0,CV_32FC2));
_lines.release();
return true;
}
@ -857,7 +857,7 @@ static bool ocl_HoughLinesP(InputArray _src, OutputArray _lines, double rho, dou
int total_points = counters.getMat(ACCESS_READ).at<int>(0, 0);
if (total_points <= 0)
{
_lines.assign(UMat(0,0,CV_32SC4));
_lines.release();
return true;
}
@ -885,7 +885,7 @@ static bool ocl_HoughLinesP(InputArray _src, OutputArray _lines, double rho, dou
if (total_lines > 0)
_lines.assign(lines.rowRange(Range(0, total_lines)));
else
_lines.assign(UMat(0,0,CV_32SC4));
_lines.release();
return true;
}

@ -1918,5 +1918,35 @@ TEST(Imgproc_Hist_CalcBackProject, accuracy) { CV_CalcBackProjectTest test; test
TEST(Imgproc_Hist_CalcBackProjectPatch, accuracy) { CV_CalcBackProjectPatchTest test; test.safe_run(); }
TEST(Imgproc_Hist_BayesianProb, accuracy) { CV_BayesianProbTest test; test.safe_run(); }
TEST(Imgproc_Hist_Calc, calcHist_regression_11544)
{
cv::Mat1w m = cv::Mat1w::zeros(10, 10);
int n_images = 1;
int channels[] = { 0 };
cv::Mat mask;
cv::MatND hist1, hist2;
cv::MatND hist1_opt, hist2_opt;
int dims = 1;
int hist_size[] = { 1000 };
float range1[] = { 0, 900 };
float range2[] = { 0, 1000 };
const float* ranges1[] = { range1 };
const float* ranges2[] = { range2 };
setUseOptimized(false);
cv::calcHist(&m, n_images, channels, mask, hist1, dims, hist_size, ranges1);
cv::calcHist(&m, n_images, channels, mask, hist2, dims, hist_size, ranges2);
setUseOptimized(true);
cv::calcHist(&m, n_images, channels, mask, hist1_opt, dims, hist_size, ranges1);
cv::calcHist(&m, n_images, channels, mask, hist2_opt, dims, hist_size, ranges2);
for(int i = 0; i < 1000; i++)
{
EXPECT_EQ(hist1.at<float>(i, 0), hist1_opt.at<float>(i, 0)) << i;
EXPECT_EQ(hist2.at<float>(i, 0), hist2_opt.at<float>(i, 0)) << i;
}
}
}} // namespace
/* End Of File */

@ -10,6 +10,13 @@
#pragma warning(pop)
#endif
#define CV_PY_FN_WITH_KW_(fn, flags) (PyCFunction)(void*)(PyCFunctionWithKeywords)(fn), (flags) | METH_VARARGS | METH_KEYWORDS
#define CV_PY_FN_NOARGS_(fn, flags) (PyCFunction)(fn), (flags) | METH_NOARGS
#define CV_PY_FN_WITH_KW(fn) CV_PY_FN_WITH_KW_(fn, 0)
#define CV_PY_FN_NOARGS(fn) CV_PY_FN_NOARGS_(fn, 0)
#define MODULESTR "cv2"
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/ndarrayobject.h>
@ -474,8 +481,14 @@ typedef struct {
static bool PyObject_IsUMat(PyObject *o);
// UMatWrapper init - try to map arguments from python to UMat constructors
static int UMatWrapper_init(cv2_UMatWrapperObject *self, PyObject *args, PyObject *kwds)
static int UMatWrapper_init(PyObject* self_, PyObject *args, PyObject *kwds)
{
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
if (self == NULL)
{
PyErr_SetString(PyExc_TypeError, "Internal error");
return -1;
}
self->um = NULL;
{
// constructor ()
@ -548,8 +561,11 @@ static void UMatWrapper_dealloc(cv2_UMatWrapperObject* self)
// UMatWrapper.get() - returns numpy array by transferring UMat data to Mat and than wrapping it to numpy array
// (using numpy allocator - and so without unnecessary copy)
static PyObject * UMatWrapper_get(cv2_UMatWrapperObject* self)
static PyObject * UMatWrapper_get(PyObject* self_, PyObject * /*args*/)
{
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
if (self == NULL)
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
Mat m;
m.allocator = &g_numpyAllocator;
self->um->copyTo(m);
@ -558,8 +574,11 @@ static PyObject * UMatWrapper_get(cv2_UMatWrapperObject* self)
}
// UMatWrapper.handle() - returns the OpenCL handle of the UMat object
static PyObject * UMatWrapper_handle(cv2_UMatWrapperObject* self, PyObject *args, PyObject *kwds)
static PyObject * UMatWrapper_handle(PyObject* self_, PyObject *args, PyObject *kwds)
{
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
if (self == NULL)
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
const char *kwlist[] = {"accessFlags", NULL};
int accessFlags;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", (char**) kwlist, &accessFlags))
@ -568,51 +587,60 @@ static PyObject * UMatWrapper_handle(cv2_UMatWrapperObject* self, PyObject *args
}
// UMatWrapper.isContinuous() - returns true if the matrix data is continuous
static PyObject * UMatWrapper_isContinuous(cv2_UMatWrapperObject* self)
static PyObject * UMatWrapper_isContinuous(PyObject* self_, PyObject * /*args*/)
{
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
if (self == NULL)
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
return PyBool_FromLong(self->um->isContinuous());
}
// UMatWrapper.isContinuous() - returns true if the matrix is a submatrix of another matrix
static PyObject * UMatWrapper_isSubmatrix(cv2_UMatWrapperObject* self)
static PyObject * UMatWrapper_isSubmatrix(PyObject* self_, PyObject * /*args*/)
{
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
if (self == NULL)
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
return PyBool_FromLong(self->um->isSubmatrix());
}
// UMatWrapper.context() - returns the OpenCL context used by OpenCV UMat
static PyObject * UMatWrapper_context(cv2_UMatWrapperObject*)
static PyObject * UMatWrapper_context(PyObject* /*self_*/, PyObject * /*args*/)
{
return PyLong_FromVoidPtr(cv::ocl::Context::getDefault().ptr());
}
// UMatWrapper.context() - returns the OpenCL queue used by OpenCV UMat
static PyObject * UMatWrapper_queue(cv2_UMatWrapperObject*)
static PyObject * UMatWrapper_queue(PyObject* /*self_*/, PyObject * /*args*/)
{
return PyLong_FromVoidPtr(cv::ocl::Queue::getDefault().ptr());
}
static PyObject * UMatWrapper_offset_getter(cv2_UMatWrapperObject* self, void*)
static PyObject * UMatWrapper_offset_getter(PyObject* self_, void*)
{
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
if (self == NULL)
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
return PyLong_FromSsize_t(self->um->offset);
}
static PyMethodDef UMatWrapper_methods[] = {
{"get", (PyCFunction)UMatWrapper_get, METH_NOARGS,
{"get", CV_PY_FN_NOARGS(UMatWrapper_get),
"Returns numpy array"
},
{"handle", (PyCFunction)UMatWrapper_handle, METH_VARARGS | METH_KEYWORDS,
{"handle", CV_PY_FN_WITH_KW(UMatWrapper_handle),
"Returns UMat native handle"
},
{"isContinuous", (PyCFunction)UMatWrapper_isContinuous, METH_NOARGS,
{"isContinuous", CV_PY_FN_NOARGS(UMatWrapper_isContinuous),
"Returns true if the matrix data is continuous"
},
{"isSubmatrix", (PyCFunction)UMatWrapper_isSubmatrix, METH_NOARGS,
{"isSubmatrix", CV_PY_FN_NOARGS(UMatWrapper_isSubmatrix),
"Returns true if the matrix is a submatrix of another matrix"
},
{"context", (PyCFunction)UMatWrapper_context, METH_NOARGS | METH_STATIC,
{"context", CV_PY_FN_NOARGS_(UMatWrapper_context, METH_STATIC),
"Returns OpenCL context handle"
},
{"queue", (PyCFunction)UMatWrapper_queue, METH_NOARGS | METH_STATIC,
{"queue", CV_PY_FN_NOARGS_(UMatWrapper_queue, METH_STATIC),
"Returns OpenCL queue handle"
},
{NULL, NULL, 0, NULL} /* Sentinel */
@ -1778,15 +1806,15 @@ static int convert_to_char(PyObject *o, char *dst, const char *name = "no_name")
#include "pyopencv_generated_funcs.h"
static PyMethodDef special_methods[] = {
{"redirectError", (PyCFunction)pycvRedirectError, METH_VARARGS | METH_KEYWORDS, "redirectError(onError) -> None"},
{"redirectError", CV_PY_FN_WITH_KW(pycvRedirectError), "redirectError(onError) -> None"},
#ifdef HAVE_OPENCV_HIGHGUI
{"createTrackbar", pycvCreateTrackbar, METH_VARARGS, "createTrackbar(trackbarName, windowName, value, count, onChange) -> None"},
{"createButton", (PyCFunction)pycvCreateButton, METH_VARARGS | METH_KEYWORDS, "createButton(buttonName, onChange [, userData, buttonType, initialButtonState]) -> None"},
{"setMouseCallback", (PyCFunction)pycvSetMouseCallback, METH_VARARGS | METH_KEYWORDS, "setMouseCallback(windowName, onMouse [, param]) -> None"},
{"createTrackbar", (PyCFunction)pycvCreateTrackbar, METH_VARARGS, "createTrackbar(trackbarName, windowName, value, count, onChange) -> None"},
{"createButton", CV_PY_FN_WITH_KW(pycvCreateButton), "createButton(buttonName, onChange [, userData, buttonType, initialButtonState]) -> None"},
{"setMouseCallback", CV_PY_FN_WITH_KW(pycvSetMouseCallback), "setMouseCallback(windowName, onMouse [, param]) -> None"},
#endif
#ifdef HAVE_OPENCV_DNN
{"dnn_registerLayer", (PyCFunction)pyopencv_cv_dnn_registerLayer, METH_VARARGS | METH_KEYWORDS, "registerLayer(type, class) -> None"},
{"dnn_unregisterLayer", (PyCFunction)pyopencv_cv_dnn_unregisterLayer, METH_VARARGS | METH_KEYWORDS, "unregisterLayer(type) -> None"},
{"dnn_registerLayer", CV_PY_FN_WITH_KW(pyopencv_cv_dnn_registerLayer), "registerLayer(type, class) -> None"},
{"dnn_unregisterLayer", CV_PY_FN_WITH_KW(pyopencv_cv_dnn_unregisterLayer), "unregisterLayer(type) -> None"},
#endif
{NULL, NULL},
};

@ -599,13 +599,9 @@ class FuncInfo(object):
# Convert unicode chars to xml representation, but keep as string instead of bytes
full_docstring = full_docstring.encode('ascii', errors='xmlcharrefreplace').decode()
flags = ["METH_VARARGS", "METH_KEYWORDS"]
if self.isclassmethod:
flags.append("METH_CLASS")
return Template(' {"$py_funcname", (PyCFunction)$wrap_funcname, $flags, "$py_docstring"},\n'
return Template(' {"$py_funcname", CV_PY_FN_WITH_KW_($wrap_funcname, $flags), "$py_docstring"},\n'
).substitute(py_funcname = self.variants[0].wname, wrap_funcname=self.get_wrapper_name(),
flags = " | ".join(flags), py_docstring = full_docstring)
flags = 'METH_CLASS' if self.isclassmethod else '0', py_docstring = full_docstring)
def gen_code(self, codegen):
all_classes = codegen.classes

@ -23,7 +23,7 @@ class Bindings(NewOpenCVTests):
try:
cv.imshow("", None) # This causes an assert
self.assertEqual("Dead code", 0)
except cv.error as e:
except cv.error as _e:
pass
handler_called = [False]
@ -34,7 +34,7 @@ class Bindings(NewOpenCVTests):
try:
cv.imshow("", None) # This causes an assert
self.assertEqual("Dead code", 0)
except cv.error as e:
except cv.error as _e:
self.assertEqual(handler_called[0], True)
pass
@ -42,7 +42,7 @@ class Bindings(NewOpenCVTests):
try:
cv.imshow("", None) # This causes an assert
self.assertEqual("Dead code", 0)
except cv.error as e:
except cv.error as _e:
pass

@ -11539,12 +11539,15 @@ typename ParamNameGenFunc<ParamType>::Type *GetParamNameGen() {
return DefaultParamName;
}
} // namespace internal:: // fixes MacOS X issue with "friend class internal/*::anon*/::ParameterizedTestFactory;"
namespace { // wrap into anynomous namespace to avoid build warnings like GCC's -Wsubobject-linkage
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Stores a parameter value and later creates tests parameterized with that
// value.
template <class TestClass>
class ParameterizedTestFactory : public TestFactoryBase {
class ParameterizedTestFactory : public internal::TestFactoryBase {
public:
typedef typename TestClass::ParamType ParamType;
explicit ParameterizedTestFactory(ParamType parameter) :
@ -11559,6 +11562,8 @@ class ParameterizedTestFactory : public TestFactoryBase {
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
};
} // namespace
namespace internal {
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
@ -20405,6 +20410,12 @@ class GTEST_API_ AssertHelper {
} // namespace internal
#if GTEST_HAS_PARAM_TEST
namespace internal {
// Static value used for accessing test parameter during a test lifetime.
extern void* g_parameter_;
} // namespace internal
// The pure interface class that all value-parameterized tests inherit from.
// A value-parameterized class must inherit from both ::testing::Test and
// ::testing::WithParamInterface. In most cases that just means inheriting
@ -20451,29 +20462,28 @@ class WithParamInterface {
// like writing 'WithParamInterface<bool>::GetParam()' for a test that
// uses a fixture whose parameter type is int.
const ParamType& GetParam() const {
GTEST_CHECK_(parameter_ != NULL)
GTEST_CHECK_(GetParameterPtrRef_() != NULL)
<< "GetParam() can only be called inside a value-parameterized test "
<< "-- did you intend to write TEST_P instead of TEST_F?";
return *parameter_;
return *GetParameterPtrRef_();
}
private:
// Sets parameter value. The caller is responsible for making sure the value
// remains alive and unchanged throughout the current test.
static void SetParam(const ParamType* parameter) {
parameter_ = parameter;
GetParameterPtrRef_() = parameter;
}
// Static value used for accessing parameter during a test lifetime.
static const ParamType* parameter_;
static const ParamType*& GetParameterPtrRef_()
{
return (const ParamType*&)internal::g_parameter_;
}
// TestClass must be a subclass of WithParamInterface<T> and Test.
template <class TestClass> friend class internal::ParameterizedTestFactory;
template <class TestClass> friend class /*internal::*/ParameterizedTestFactory;
};
template <typename T>
const T* WithParamInterface<T>::parameter_ = NULL;
// Most value-parameterized classes can ignore the existence of
// WithParamInterface, and can just inherit from ::testing::TestWithParam.

@ -10441,5 +10441,7 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
#endif // GTEST_HAS_TYPED_TEST_P
void* g_parameter_ = NULL;
} // namespace internal
} // namespace testing

@ -20,6 +20,8 @@ set(videoio_hdrs
${CMAKE_CURRENT_LIST_DIR}/src/precomp.hpp
)
set(videoio_srcs
${CMAKE_CURRENT_LIST_DIR}/src/videoio_registry.cpp
${CMAKE_CURRENT_LIST_DIR}/src/videoio_c.cpp
${CMAKE_CURRENT_LIST_DIR}/src/cap.cpp
${CMAKE_CURRENT_LIST_DIR}/src/cap_images.cpp
${CMAKE_CURRENT_LIST_DIR}/src/cap_mjpeg_encoder.cpp
@ -165,6 +167,9 @@ if(HAVE_FFMPEG)
if(APPLE)
list(APPEND VIDEOIO_LIBRARIES "-framework VideoDecodeAcceleration" bz2)
endif()
if(HAVE_FFMPEG_WRAPPER)
add_definitions(-DHAVE_FFMPEG_WRAPPER=1)
endif()
endif(HAVE_FFMPEG)
if(HAVE_PVAPI)
@ -234,12 +239,6 @@ if(IOS)
list(APPEND VIDEOIO_LIBRARIES "-framework Accelerate" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreImage" "-framework CoreMedia" "-framework CoreVideo" "-framework QuartzCore" "-framework UIKit")
endif()
if(WIN32)
link_directories("${OpenCV_SOURCE_DIR}/3rdparty/lib") # for ffmpeg wrapper only
include_directories(AFTER SYSTEM "${OpenCV_SOURCE_DIR}/3rdparty/include") # for directshow in VS2005 and multi-monitor support on MinGW
include_directories(AFTER SYSTEM "${OpenCV_SOURCE_DIR}/3rdparty/include/ffmpeg_") # for tests
endif()
if(UNIX)
#these variables are set by CHECK_MODULE macro
foreach(P ${VIDEOIO_INCLUDE_DIRS})
@ -272,7 +271,7 @@ endif()
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated-declarations)
if(WIN32 AND HAVE_FFMPEG)
if(WIN32 AND HAVE_FFMPEG_WRAPPER)
#copy ffmpeg dll to the output folder
if(MSVC64 OR MINGW64)
set(FFMPEG_SUFFIX _64)

@ -40,40 +40,10 @@
//M*/
#include "precomp.hpp"
#include <iostream>
using namespace std;
#include "cap_intelperc.hpp"
#include "cap_librealsense.hpp"
#include "cap_dshow.hpp"
#ifdef HAVE_MFX
#include "cap_mfx_reader.hpp"
#include "cap_mfx_writer.hpp"
#endif
// All WinRT versions older than 8.0 should provide classes used for video support
#if defined(WINRT) && !defined(WINRT_8_0) && defined(__cplusplus_winrt)
# include "cap_winrt_capture.hpp"
# include "cap_winrt_bridge.hpp"
# define WINRT_VIDEO
#endif
#if defined _M_X64 && defined _MSC_VER && !defined CV_ICC
#pragma optimize("",off)
#pragma warning(disable: 4748)
#endif
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
#if defined(__GNUC__) && __GNUC__ >= 7
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
#include "videoio_registry.hpp"
using namespace cv;
namespace cv
{
namespace cv {
template<> void DefaultDeleter<CvCapture>::operator ()(CvCapture* obj) const
{ cvReleaseCapture(&obj); }
@ -81,536 +51,7 @@ template<> void DefaultDeleter<CvCapture>::operator ()(CvCapture* obj) const
template<> void DefaultDeleter<CvVideoWriter>::operator ()(CvVideoWriter* obj) const
{ cvReleaseVideoWriter(&obj); }
}
/************************* Reading AVIs & Camera data **************************/
static inline double icvGetCaptureProperty( const CvCapture* capture, int id )
{
return capture ? capture->getProperty(id) : 0;
}
CV_IMPL void cvReleaseCapture( CvCapture** pcapture )
{
if( pcapture && *pcapture )
{
delete *pcapture;
*pcapture = 0;
}
}
CV_IMPL IplImage* cvQueryFrame( CvCapture* capture )
{
if(!capture)
return 0;
if(!capture->grabFrame())
return 0;
return capture->retrieveFrame(0);
}
CV_IMPL int cvGrabFrame( CvCapture* capture )
{
return capture ? capture->grabFrame() : 0;
}
CV_IMPL IplImage* cvRetrieveFrame( CvCapture* capture, int idx )
{
return capture ? capture->retrieveFrame(idx) : 0;
}
CV_IMPL double cvGetCaptureProperty( CvCapture* capture, int id )
{
return icvGetCaptureProperty(capture, id);
}
CV_IMPL int cvSetCaptureProperty( CvCapture* capture, int id, double value )
{
return capture ? capture->setProperty(id, value) : 0;
}
CV_IMPL int cvGetCaptureDomain( CvCapture* capture)
{
return capture ? capture->getCaptureDomain() : 0;
}
static bool get_capture_debug_flag()
{
static bool initialized = false;
static bool flag = false;
if (!initialized)
{
#ifndef NO_GETENV
flag = getenv("OPENCV_VIDEOCAPTURE_DEBUG") ? true : false; // TODO Use getBoolParameter
#endif
initialized = true;
}
return flag;
}
#define TRY_OPEN(capture, backend_func) \
{ \
if (!capture) \
CV_TRY { \
if (get_capture_debug_flag()) fprintf(stderr, "VIDEOIO(%s): trying ...\n", #backend_func); \
capture = backend_func; \
if (get_capture_debug_flag()) fprintf(stderr, "VIDEOIO(%s): result=%p ...\n", #backend_func, capture); \
} CV_CATCH (cv::Exception, e) { \
fprintf(stderr, "VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what()); \
} CV_CATCH (std::exception, e) { \
fprintf(stderr, "VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what()); \
} CV_CATCH_ALL { \
fprintf(stderr, "VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func); \
} \
}
/**
* Camera dispatching method: index is the camera number.
* If given an index from 0 to 99, it tries to find the first
* API that can access a given camera index.
* Add multiples of 100 to select an API.
*/
CV_IMPL CvCapture * cvCreateCameraCapture (int index)
{
// interpret preferred interface (0 = autodetect)
int pref = (index / 100) * 100;
// remove pref from index
index -= pref;
// local variable to memorize the captured device
CvCapture *capture = 0;
switch (pref)
{
default:
// user specified an API we do not know
// bail out to let the user know that it is not available
if (pref) break;
case CAP_VFW: // or CAP_V4L or CAP_V4L2
#ifdef HAVE_VFW
TRY_OPEN(capture, cvCreateCameraCapture_VFW(index))
#endif
#if defined HAVE_LIBV4L || defined HAVE_CAMV4L || defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
TRY_OPEN(capture, cvCreateCameraCapture_V4L(index))
#endif
if (pref) break; // CAP_VFW or CAP_V4L or CAP_V4L2
case CAP_FIREWIRE:
#ifdef HAVE_DC1394_2
TRY_OPEN(capture, cvCreateCameraCapture_DC1394_2(index))
#endif
#ifdef HAVE_DC1394
TRY_OPEN(capture, cvCreateCameraCapture_DC1394(index))
#endif
#ifdef HAVE_CMU1394
TRY_OPEN(capture, cvCreateCameraCapture_CMU(index))
#endif
if (pref) break; // CAP_FIREWIRE
#ifdef HAVE_MIL
case CAP_MIL:
TRY_OPEN(capture, cvCreateCameraCapture_MIL(index))
if (pref) break;
#endif
#if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT)
case CAP_QT:
TRY_OPEN(capture, cvCreateCameraCapture_QT(index))
if (pref) break;
#endif
#ifdef HAVE_UNICAP
case CAP_UNICAP:
TRY_OPEN(capture, cvCreateCameraCapture_Unicap(index))
if (pref) break;
#endif
#ifdef HAVE_PVAPI
case CAP_PVAPI:
TRY_OPEN(capture, cvCreateCameraCapture_PvAPI(index))
if (pref) break;
#endif
#ifdef HAVE_OPENNI
case CAP_OPENNI:
TRY_OPEN(capture, cvCreateCameraCapture_OpenNI(index))
if (pref) break;
#endif
#ifdef HAVE_OPENNI2
case CAP_OPENNI2:
TRY_OPEN(capture, cvCreateCameraCapture_OpenNI2(index))
if (pref) break;
#endif
#ifdef HAVE_XIMEA
case CAP_XIAPI:
TRY_OPEN(capture, cvCreateCameraCapture_XIMEA(index))
if (pref) break;
#endif
#ifdef HAVE_AVFOUNDATION
case CAP_AVFOUNDATION:
TRY_OPEN(capture, cvCreateCameraCapture_AVFoundation(index))
if (pref) break;
#endif
#ifdef HAVE_GIGE_API
case CAP_GIGANETIX:
TRY_OPEN(capture, cvCreateCameraCapture_Giganetix(index))
if (pref) break; // CAP_GIGANETIX
#endif
#ifdef HAVE_ARAVIS_API
case CAP_ARAVIS:
TRY_OPEN(capture, cvCreateCameraCapture_Aravis(index))
if (pref) break;
#endif
}
return capture;
}
/**
* Videoreader dispatching method: it tries to find the first
* API that can access a given filename.
*/
CV_IMPL CvCapture * cvCreateFileCaptureWithPreference (const char * filename, int apiPreference)
{
CvCapture * result = 0;
switch(apiPreference) {
default:
// user specified an API we do not know
// bail out to let the user know that it is not available
if (apiPreference) break;
#if defined HAVE_LIBV4L || defined HAVE_CAMV4L || defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
case CAP_V4L:
TRY_OPEN(result, cvCreateCameraCapture_V4L(filename))
if (apiPreference) break;
#endif
#ifdef HAVE_VFW
case CAP_VFW:
TRY_OPEN(result, cvCreateFileCapture_VFW (filename))
if (apiPreference) break;
#endif
#if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT)
case CAP_QT:
TRY_OPEN(result, cvCreateFileCapture_QT (filename))
if (apiPreference) break;
#endif
#ifdef HAVE_AVFOUNDATION
case CAP_AVFOUNDATION:
TRY_OPEN(result, cvCreateFileCapture_AVFoundation (filename))
if (apiPreference) break;
#endif
#ifdef HAVE_OPENNI
case CAP_OPENNI:
TRY_OPEN(result, cvCreateFileCapture_OpenNI (filename))
if (apiPreference) break;
#endif
#ifdef HAVE_OPENNI2
case CAP_OPENNI2:
TRY_OPEN(result, cvCreateFileCapture_OpenNI2 (filename))
if (apiPreference) break;
#endif
#ifdef HAVE_XIMEA
case CAP_XIAPI:
TRY_OPEN(result, cvCreateCameraCapture_XIMEA(filename))
if (apiPreference) break;
#endif
case CAP_IMAGES:
TRY_OPEN(result, cvCreateFileCapture_Images (filename))
}
return result;
}
CV_IMPL CvCapture * cvCreateFileCapture (const char * filename)
{
return cvCreateFileCaptureWithPreference(filename, CAP_ANY);
}
/**
* Videowriter dispatching method: it tries to find the first
* API that can write a given stream.
*/
static CvVideoWriter* cvCreateVideoWriterWithPreference(const char* filename, int apiPreference, int fourcc,
double fps, CvSize frameSize, int is_color )
{
CV_UNUSED(frameSize);
CV_UNUSED(is_color);
CvVideoWriter *result = 0;
if(!fourcc || !fps)
TRY_OPEN(result, cvCreateVideoWriter_Images(filename))
CV_Assert(result || fps != 0);
switch(apiPreference)
{
default:
//exit if the specified API is unavaliable
if (apiPreference != CAP_ANY) break;
#ifdef HAVE_VFW
case CAP_VFW:
TRY_OPEN(result, cvCreateVideoWriter_VFW(filename, fourcc, fps, frameSize, is_color))
if (apiPreference != CAP_ANY) break;
#endif
#ifdef HAVE_AVFOUNDATION
case CAP_AVFOUNDATION:
TRY_OPEN(result, cvCreateVideoWriter_AVFoundation(filename, fourcc, fps, frameSize, is_color))
if (apiPreference != CAP_ANY) break;
#endif
#if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT)
case(CAP_QT):
TRY_OPEN(result, cvCreateVideoWriter_QT(filename, fourcc, fps, frameSize, is_color))
if (apiPreference != CAP_ANY) break;
#endif
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
TRY_OPEN(result, cvCreateVideoWriter_GStreamer (filename, fourcc, fps, frameSize, is_color))
if (apiPreference != CAP_ANY) break;
#endif
case CAP_IMAGES:
TRY_OPEN(result, cvCreateVideoWriter_Images(filename))
if (apiPreference != CAP_ANY) break;
}
return result;
}
CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc,
double fps, CvSize frameSize, int is_color )
{
return cvCreateVideoWriterWithPreference(filename, CAP_ANY, fourcc, fps, frameSize, is_color);
}
CV_IMPL int cvWriteFrame( CvVideoWriter* writer, const IplImage* image )
{
return writer ? writer->writeFrame(image) : 0;
}
CV_IMPL void cvReleaseVideoWriter( CvVideoWriter** pwriter )
{
if( pwriter && *pwriter )
{
delete *pwriter;
*pwriter = 0;
}
}
namespace cv
{
static Ptr<IVideoCapture> IVideoCapture_create(int index)
{
int domains[] =
{
#ifdef HAVE_GSTREAMER
CAP_GSTREAMER,
#endif
#ifdef HAVE_MSMF
CAP_MSMF,
#endif
#ifdef HAVE_DSHOW
CAP_DSHOW,
#endif
#ifdef HAVE_INTELPERC
CAP_INTELPERC,
#endif
#ifdef WINRT_VIDEO
CAP_WINRT,
#endif
#ifdef HAVE_GPHOTO2
CAP_GPHOTO2,
#endif
-1, -1
};
// interpret preferred interface (0 = autodetect)
int pref = (index / 100) * 100;
if (pref)
{
domains[0]=pref;
index %= 100;
domains[1]=-1;
}
// try every possibly installed camera API
for (int i = 0; domains[i] >= 0; i++)
{
#if defined(HAVE_GSTREAMER) || \
defined(HAVE_MSMF) || \
defined(HAVE_DSHOW) || \
defined(HAVE_INTELPERC) || \
defined(HAVE_LIBREALSENSE) || \
defined(WINRT_VIDEO) || \
defined(HAVE_GPHOTO2) || \
(0)
Ptr<IVideoCapture> capture;
switch (domains[i])
{
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
capture = createGStreamerCapture(index);
break;
#endif
#ifdef HAVE_MSMF
case CAP_MSMF:
capture = cvCreateCapture_MSMF(index);
break; // CAP_MSMF
#endif
#ifdef HAVE_DSHOW
case CAP_DSHOW:
capture = makePtr<VideoCapture_DShow>(index);
break; // CAP_DSHOW
#endif
#ifdef HAVE_INTELPERC
case CAP_INTELPERC:
capture = makePtr<VideoCapture_IntelPerC>();
break; // CAP_INTEL_PERC
#elif defined(HAVE_LIBREALSENSE)
case CAP_INTELPERC:
capture = makePtr<VideoCapture_LibRealsense>(index);
break;
#endif
#ifdef WINRT_VIDEO
case CAP_WINRT:
capture = Ptr<IVideoCapture>(new cv::VideoCapture_WinRT(index));
if (capture)
return capture;
break; // CAP_WINRT
#endif
#ifdef HAVE_GPHOTO2
case CAP_GPHOTO2:
capture = createGPhoto2Capture(index);
break;
#endif
}
if (capture && capture->isOpened())
return capture;
#endif
}
// failed open a camera
return Ptr<IVideoCapture>();
}
static Ptr<IVideoCapture> IVideoCapture_create(const String& filename, int apiPreference)
{
bool useAny = (apiPreference == CAP_ANY);
Ptr<IVideoCapture> capture;
#ifdef HAVE_FFMPEG
if (useAny || apiPreference == CAP_FFMPEG)
{
capture = cvCreateFileCapture_FFMPEG_proxy(filename);
if (capture && capture->isOpened())
return capture;
}
#endif
#ifdef HAVE_GSTREAMER
if (useAny || apiPreference == CAP_GSTREAMER)
{
capture = createGStreamerCapture(filename);
if (capture && capture->isOpened())
return capture;
}
#endif
#ifdef HAVE_XINE
if (useAny || apiPreference == CAP_XINE)
{
capture = createXINECapture(filename.c_str());
if (capture && capture->isOpened())
return capture;
}
#endif
#ifdef HAVE_MSMF
if (useAny || apiPreference == CAP_MSMF)
{
capture = cvCreateCapture_MSMF(filename);
if (capture && capture->isOpened())
return capture;
}
#endif
#ifdef HAVE_GPHOTO2
if (useAny || apiPreference == CAP_GPHOTO2)
{
capture = createGPhoto2Capture(filename);
if (capture && capture->isOpened())
return capture;
}
#endif
#ifdef HAVE_MFX
if (useAny || apiPreference == CAP_INTEL_MFX)
{
capture = makePtr<VideoCapture_IntelMFX>(filename);
if (capture && capture->isOpened())
return capture;
}
#endif
if (useAny || apiPreference == CAP_OPENCV_MJPEG)
{
capture = createMotionJpegCapture(filename);
if (capture && capture->isOpened())
return capture;
}
if (capture && !capture->isOpened())
capture.release();
return capture;
}
static Ptr<IVideoWriter> IVideoWriter_create(const String& filename, int apiPreference, int _fourcc, double fps, Size frameSize, bool isColor)
{
Ptr<IVideoWriter> iwriter;
#ifdef HAVE_FFMPEG
if (apiPreference == CAP_FFMPEG || apiPreference == CAP_ANY)
{
iwriter = cvCreateVideoWriter_FFMPEG_proxy(filename, _fourcc, fps, frameSize, isColor);
if (!iwriter.empty())
return iwriter;
}
#endif
#ifdef HAVE_MSMF
if (apiPreference == CAP_MSMF || apiPreference == CAP_ANY)
{
iwriter = cvCreateVideoWriter_MSMF(filename, _fourcc, fps, frameSize, isColor);
if (!iwriter.empty())
return iwriter;
}
#endif
#ifdef HAVE_MFX
if (apiPreference == CAP_INTEL_MFX || apiPreference == CAP_ANY)
{
iwriter = VideoWriter_IntelMFX::create(filename, _fourcc, fps, frameSize, isColor);
if (!iwriter.empty())
return iwriter;
}
#endif
if( (apiPreference == CAP_OPENCV_MJPEG || apiPreference == CAP_ANY)
&& _fourcc == CV_FOURCC('M', 'J', 'P', 'G') )
iwriter = createMotionJpegWriter(filename, fps, frameSize, isColor);
return iwriter;
}
VideoCapture::VideoCapture()
{}
@ -646,12 +87,30 @@ bool VideoCapture::open(const String& filename, int apiPreference)
CV_TRACE_FUNCTION();
if (isOpened()) release();
icap = IVideoCapture_create(filename, apiPreference);
if (!icap.empty())
return true;
cap.reset(cvCreateFileCaptureWithPreference(filename.c_str(), apiPreference));
return isOpened();
const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByFilename();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvCapture* capture = NULL;
VideoCapture_create(capture, icap, info.id, filename);
if (!icap.empty())
{
if (icap->isOpened())
return true;
icap.release();
}
if (capture)
{
cap.reset(capture);
// assume it is opened
return true;
}
}
}
return false;
}
bool VideoCapture::open(const String& filename)
@ -661,28 +120,56 @@ bool VideoCapture::open(const String& filename)
return open(filename, CAP_ANY);
}
bool VideoCapture::open(int index)
bool VideoCapture::open(int cameraNum, int apiPreference)
{
CV_TRACE_FUNCTION();
if (isOpened()) release();
icap = IVideoCapture_create(index);
if (!icap.empty())
return true;
cap.reset(cvCreateCameraCapture(index));
return isOpened();
const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByIndex();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvCapture* capture = NULL;
VideoCapture_create(capture, icap, info.id, cameraNum);
if (!icap.empty())
{
if (icap->isOpened())
return true;
icap.release();
}
if (capture)
{
cap.reset(capture);
// assume it is opened
return true;
}
}
}
return false;
}
bool VideoCapture::open(int cameraNum, int apiPreference)
bool VideoCapture::open(int index)
{
CV_TRACE_FUNCTION();
cameraNum = cameraNum + apiPreference;
return open(cameraNum);
// interpret preferred interface (0 = autodetect)
int backendID = (index / 100) * 100;
if (backendID)
{
index %= 100;
}
return open(index, backendID);
}
bool VideoCapture::isOpened() const
{
return (!cap.empty() || !icap.empty());
if (!icap.empty())
return icap->isOpened();
return !cap.empty(); // legacy interface doesn't support closed files
}
void VideoCapture::release()
@ -738,6 +225,7 @@ bool VideoCapture::read(OutputArray image)
VideoCapture& VideoCapture::operator >> (Mat& image)
{
#ifdef WINRT_VIDEO
// FIXIT grab/retrieve methods() should work too
if (grab())
{
if (retrieve(image))
@ -759,7 +247,6 @@ VideoCapture& VideoCapture::operator >> (Mat& image)
#else
read(image);
#endif
return *this;
}
@ -782,10 +269,14 @@ double VideoCapture::get(int propId) const
{
if (!icap.empty())
return icap->getProperty(propId);
return icvGetCaptureProperty(cap, propId);
return cap ? cap->getProperty(propId) : 0;
}
//=================================================================================================
VideoWriter::VideoWriter()
{}
@ -821,11 +312,30 @@ bool VideoWriter::open(const String& filename, int apiPreference, int _fourcc, d
CV_INSTRUMENT_REGION()
if (isOpened()) release();
iwriter = IVideoWriter_create(filename, apiPreference, _fourcc, fps, frameSize, isColor);
if (!iwriter.empty())
return true;
writer.reset(cvCreateVideoWriterWithPreference(filename.c_str(), apiPreference, _fourcc, fps, frameSize, isColor));
return isOpened();
const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_Writer();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvVideoWriter* writer_ = NULL;
VideoWriter_create(writer_, iwriter, info.id, filename, _fourcc, fps, frameSize, isColor);
if (!iwriter.empty())
{
if (iwriter->isOpened())
return true;
iwriter.release();
}
if (writer_)
{
// assume it is opened
writer.reset(writer_);
return true;
}
}
}
return false;
}
bool VideoWriter::isOpened() const
@ -869,9 +379,10 @@ VideoWriter& VideoWriter::operator << (const Mat& image)
return *this;
}
// FIXIT OpenCV 4.0: make inline
int VideoWriter::fourcc(char c1, char c2, char c3, char c4)
{
return (c1 & 255) + ((c2 & 255) << 8) + ((c3 & 255) << 16) + ((c4 & 255) << 24);
}
}
} // namespace

@ -41,13 +41,28 @@
#include "precomp.hpp"
#if defined(HAVE_FFMPEG)
#include <string>
#if defined HAVE_FFMPEG && !defined _WIN32
#if !defined(HAVE_FFMPEG_WRAPPER)
#include "cap_ffmpeg_impl.hpp"
#define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG
#define icvReleaseCapture_FFMPEG_p cvReleaseCapture_FFMPEG
#define icvGrabFrame_FFMPEG_p cvGrabFrame_FFMPEG
#define icvRetrieveFrame_FFMPEG_p cvRetrieveFrame_FFMPEG
#define icvSetCaptureProperty_FFMPEG_p cvSetCaptureProperty_FFMPEG
#define icvGetCaptureProperty_FFMPEG_p cvGetCaptureProperty_FFMPEG
#define icvCreateVideoWriter_FFMPEG_p cvCreateVideoWriter_FFMPEG
#define icvReleaseVideoWriter_FFMPEG_p cvReleaseVideoWriter_FFMPEG
#define icvWriteFrame_FFMPEG_p cvWriteFrame_FFMPEG
#else
#include "cap_ffmpeg_api.hpp"
#endif
namespace cv { namespace {
static CvCreateFileCapture_Plugin icvCreateFileCapture_FFMPEG_p = 0;
static CvReleaseCapture_Plugin icvReleaseCapture_FFMPEG_p = 0;
@ -99,7 +114,7 @@ private:
icvInitFFMPEG()
{
#if defined _WIN32
#if defined _WIN32
const wchar_t* module_name_ = L"opencv_ffmpeg"
CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION)
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
@ -161,7 +176,7 @@ private:
(CvReleaseVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseVideoWriter_FFMPEG");
icvWriteFrame_FFMPEG_p =
(CvWriteFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvWriteFrame_FFMPEG");
# endif // _WIN32
#if 0
if( icvCreateFileCapture_FFMPEG_p != 0 &&
icvReleaseCapture_FFMPEG_p != 0 &&
@ -181,21 +196,18 @@ private:
}
#endif
}
#elif defined HAVE_FFMPEG
icvCreateFileCapture_FFMPEG_p = (CvCreateFileCapture_Plugin)cvCreateFileCapture_FFMPEG;
icvReleaseCapture_FFMPEG_p = (CvReleaseCapture_Plugin)cvReleaseCapture_FFMPEG;
icvGrabFrame_FFMPEG_p = (CvGrabFrame_Plugin)cvGrabFrame_FFMPEG;
icvRetrieveFrame_FFMPEG_p = (CvRetrieveFrame_Plugin)cvRetrieveFrame_FFMPEG;
icvSetCaptureProperty_FFMPEG_p = (CvSetCaptureProperty_Plugin)cvSetCaptureProperty_FFMPEG;
icvGetCaptureProperty_FFMPEG_p = (CvGetCaptureProperty_Plugin)cvGetCaptureProperty_FFMPEG;
icvCreateVideoWriter_FFMPEG_p = (CvCreateVideoWriter_Plugin)cvCreateVideoWriter_FFMPEG;
icvReleaseVideoWriter_FFMPEG_p = (CvReleaseVideoWriter_Plugin)cvReleaseVideoWriter_FFMPEG;
icvWriteFrame_FFMPEG_p = (CvWriteFrame_Plugin)cvWriteFrame_FFMPEG;
#endif
}
};
}} // namespace
#endif // HAVE_FFMPEG_WRAPPER
namespace cv {
namespace {
class CvCapture_FFMPEG_proxy CV_FINAL : public cv::IVideoCapture
{
public:
@ -228,19 +240,20 @@ public:
}
virtual bool open( const cv::String& filename )
{
icvInitFFMPEG::Init();
close();
if( !icvCreateFileCapture_FFMPEG_p )
return false;
ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename.c_str() );
return ffmpegCapture != 0;
}
virtual void close()
{
if( ffmpegCapture && icvReleaseCapture_FFMPEG_p )
if (ffmpegCapture
#if defined(HAVE_FFMPEG_WRAPPER)
&& icvReleaseCapture_FFMPEG_p
#endif
)
icvReleaseCapture_FFMPEG_p( &ffmpegCapture );
assert( ffmpegCapture == 0 );
CV_Assert(ffmpegCapture == 0);
ffmpegCapture = 0;
}
@ -248,18 +261,26 @@ public:
virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_FFMPEG; }
protected:
void* ffmpegCapture;
CvCapture_FFMPEG* ffmpegCapture;
};
} // namespace
cv::Ptr<cv::IVideoCapture> cv::cvCreateFileCapture_FFMPEG_proxy(const cv::String& filename)
cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const cv::String& filename)
{
#if defined(HAVE_FFMPEG_WRAPPER)
icvInitFFMPEG::Init();
if (!icvCreateFileCapture_FFMPEG_p)
return cv::Ptr<cv::IVideoCapture>();
#endif
cv::Ptr<CvCapture_FFMPEG_proxy> capture = cv::makePtr<CvCapture_FFMPEG_proxy>(filename);
if (capture && capture->isOpened())
return capture;
return cv::Ptr<cv::IVideoCapture>();
}
namespace {
class CvVideoWriter_FFMPEG_proxy CV_FINAL :
public cv::IVideoWriter
{
@ -278,19 +299,20 @@ public:
}
virtual bool open( const cv::String& filename, int fourcc, double fps, cv::Size frameSize, bool isColor )
{
icvInitFFMPEG::Init();
close();
if( !icvCreateVideoWriter_FFMPEG_p )
return false;
ffmpegWriter = icvCreateVideoWriter_FFMPEG_p( filename.c_str(), fourcc, fps, frameSize.width, frameSize.height, isColor );
return ffmpegWriter != 0;
}
virtual void close()
{
if( ffmpegWriter && icvReleaseVideoWriter_FFMPEG_p )
if (ffmpegWriter
#if defined(HAVE_FFMPEG_WRAPPER)
&& icvReleaseVideoWriter_FFMPEG_p
#endif
)
icvReleaseVideoWriter_FFMPEG_p( &ffmpegWriter );
assert( ffmpegWriter == 0 );
CV_Assert(ffmpegWriter == 0);
ffmpegWriter = 0;
}
@ -299,15 +321,25 @@ public:
virtual bool isOpened() const CV_OVERRIDE { return ffmpegWriter != 0; }
protected:
void* ffmpegWriter;
CvVideoWriter_FFMPEG* ffmpegWriter;
};
} // namespace
cv::Ptr<cv::IVideoWriter> cv::cvCreateVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc,
double fps, cv::Size frameSize, int isColor)
cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc,
double fps, cv::Size frameSize, int isColor)
{
#if defined(HAVE_FFMPEG_WRAPPER)
icvInitFFMPEG::Init();
if (!icvCreateVideoWriter_FFMPEG_p)
return cv::Ptr<cv::IVideoWriter>();
#endif
cv::Ptr<CvVideoWriter_FFMPEG_proxy> writer = cv::makePtr<CvVideoWriter_FFMPEG_proxy>(filename, fourcc, fps, frameSize, isColor != 0);
if (writer && writer->isOpened())
return writer;
return cv::Ptr<cv::IVideoWriter>();
}
} // namespace
#endif // defined(HAVE_FFMPEG)

@ -28,6 +28,8 @@ enum
CV_FFMPEG_CAP_PROP_SAR_DEN=41
};
typedef struct CvCapture_FFMPEG CvCapture_FFMPEG;
typedef struct CvVideoWriter_FFMPEG CvVideoWriter_FFMPEG;
OPENCV_FFMPEG_API struct CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG(const char* filename);
OPENCV_FFMPEG_API struct CvCapture_FFMPEG_2* cvCreateFileCapture_FFMPEG_2(const char* filename);
@ -55,19 +57,19 @@ OPENCV_FFMPEG_API int cvWriteFrame_FFMPEG(struct CvVideoWriter_FFMPEG* writer, c
OPENCV_FFMPEG_API void cvReleaseVideoWriter_FFMPEG(struct CvVideoWriter_FFMPEG** writer);
typedef void* (*CvCreateFileCapture_Plugin)( const char* filename );
typedef void* (*CvCreateCameraCapture_Plugin)( int index );
typedef int (*CvGrabFrame_Plugin)( void* capture_handle );
typedef int (*CvRetrieveFrame_Plugin)( void* capture_handle, unsigned char** data, int* step,
typedef CvCapture_FFMPEG* (*CvCreateFileCapture_Plugin)( const char* filename );
typedef CvCapture_FFMPEG* (*CvCreateCameraCapture_Plugin)( int index );
typedef int (*CvGrabFrame_Plugin)( CvCapture_FFMPEG* capture_handle );
typedef int (*CvRetrieveFrame_Plugin)( CvCapture_FFMPEG* capture_handle, unsigned char** data, int* step,
int* width, int* height, int* cn );
typedef int (*CvSetCaptureProperty_Plugin)( void* capture_handle, int prop_id, double value );
typedef double (*CvGetCaptureProperty_Plugin)( void* capture_handle, int prop_id );
typedef void (*CvReleaseCapture_Plugin)( void** capture_handle );
typedef void* (*CvCreateVideoWriter_Plugin)( const char* filename, int fourcc,
typedef int (*CvSetCaptureProperty_Plugin)( CvCapture_FFMPEG* capture_handle, int prop_id, double value );
typedef double (*CvGetCaptureProperty_Plugin)( CvCapture_FFMPEG* capture_handle, int prop_id );
typedef void (*CvReleaseCapture_Plugin)( CvCapture_FFMPEG** capture_handle );
typedef CvVideoWriter_FFMPEG* (*CvCreateVideoWriter_Plugin)( const char* filename, int fourcc,
double fps, int width, int height, int iscolor );
typedef int (*CvWriteFrame_Plugin)( void* writer_handle, const unsigned char* data, int step,
typedef int (*CvWriteFrame_Plugin)( CvVideoWriter_FFMPEG* writer_handle, const unsigned char* data, int step,
int width, int height, int cn, int origin);
typedef void (*CvReleaseVideoWriter_Plugin)( void** writer );
typedef void (*CvReleaseVideoWriter_Plugin)( CvVideoWriter_FFMPEG** writer );
/*
* For CUDA encoder

@ -754,6 +754,17 @@ private:
AutoLock& operator = (const AutoLock&); // disabled
};
static void ffmpeg_log_callback(void *ptr, int level, const char *fmt, va_list vargs)
{
static bool skip_header = false;
static int prev_level = -1;
(void)ptr;
if (!skip_header || level != prev_level) printf("[OPENCV:FFMPEG:%02d] ", level);
vprintf(fmt, vargs);
size_t fmt_len = strlen(fmt);
skip_header = fmt_len > 0 && fmt[fmt_len - 1] != '\n';
prev_level = level;
}
class InternalFFMpegRegister
{
@ -773,7 +784,18 @@ public:
/* register a callback function for synchronization */
av_lockmgr_register(&LockCallBack);
av_log_set_level(AV_LOG_ERROR);
#ifndef NO_GETENV
char* debug_option = getenv("OPENCV_FFMPEG_DEBUG");
if (debug_option != NULL)
{
av_log_set_level(AV_LOG_VERBOSE);
av_log_set_callback(ffmpeg_log_callback);
}
else
#endif
{
av_log_set_level(AV_LOG_ERROR);
}
_initialized = true;
}
@ -1587,6 +1609,9 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(52, 42, 0)
st->avg_frame_rate = (AVRational){frame_rate, frame_rate_base};
#endif
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 20, 0)
st->time_base = c->time_base;
#endif
return st;
}

@ -1530,8 +1530,11 @@ void MotionJpegWriter::writeFrameData( const uchar* data, int step, int colorspa
}
Ptr<IVideoWriter> createMotionJpegWriter( const String& filename, double fps, Size frameSize, bool iscolor )
Ptr<IVideoWriter> createMotionJpegWriter(const String& filename, int fourcc, double fps, Size frameSize, bool iscolor)
{
if (fourcc != CV_FOURCC('M', 'J', 'P', 'G'))
return Ptr<IVideoWriter>();
Ptr<IVideoWriter> iwriter = makePtr<mjpeg::MotionJpegWriter>(filename, fps, frameSize, iscolor);
if( !iwriter->isOpened() )
iwriter.release();

File diff suppressed because it is too large Load Diff

@ -47,6 +47,9 @@
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
#include <opencv2/core/utils/configuration.private.hpp>
#include <opencv2/core/utils/logger.hpp>
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
@ -59,7 +62,7 @@
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <assert.h>
#include <assert.h> // FIXIT remove this
#if defined _WIN32 || defined WINCE
#if !defined _WIN32_WINNT
@ -178,7 +181,7 @@ namespace cv
};
Ptr<IVideoCapture> createMotionJpegCapture(const String& filename);
Ptr<IVideoWriter> createMotionJpegWriter( const String& filename, double fps, Size frameSize, bool iscolor );
Ptr<IVideoWriter> createMotionJpegWriter(const String& filename, int fourcc, double fps, Size frameSize, bool iscolor);
Ptr<IVideoCapture> createGPhoto2Capture(int index);
Ptr<IVideoCapture> createGPhoto2Capture(const String& deviceName);

@ -0,0 +1,152 @@
// 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.
#include "precomp.hpp"
#include "videoio_registry.hpp"
using namespace cv;
// Legacy C-like API
CV_IMPL CvCapture* cvCreateCameraCapture(int index)
{
// interpret preferred interface (0 = autodetect)
int apiPreference = (index / 100) * 100;
if (apiPreference)
{
index %= 100;
}
const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByIndex();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvCapture* capture = NULL;
Ptr<IVideoCapture> icap; // unused
VideoCapture_create(capture, icap, info.id, index);
if (capture)
{
return capture;
}
if (!icap.empty())
{
CV_LOG_WARNING(NULL, "cvCreateFileCaptureWithPreference: backend " << info.name << " doesn't support legacy API anymore.")
}
}
}
return NULL;
}
CV_IMPL CvCapture* cvCreateFileCaptureWithPreference(const char* filename, int apiPreference)
{
const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByFilename();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvCapture* capture = NULL;
Ptr<IVideoCapture> icap; // unused
VideoCapture_create(capture, icap, info.id, filename);
if (capture)
{
return capture;
}
if (!icap.empty())
{
CV_LOG_WARNING(NULL, "cvCreateFileCaptureWithPreference: backend " << info.name << " doesn't support legacy API anymore.")
}
}
}
return NULL;
}
CV_IMPL CvCapture* cvCreateFileCapture(const char * filename)
{
return cvCreateFileCaptureWithPreference(filename, CAP_ANY);
}
CV_IMPL CvVideoWriter* cvCreateVideoWriter(const char* filename, int fourcc,
double fps, CvSize frameSize, int is_color)
{
const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_Writer();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
{
CvVideoWriter* writer_ = NULL;
Ptr<IVideoWriter> iwriter; // unused
VideoWriter_create(writer_, iwriter, info.id, filename, fourcc, fps, frameSize, is_color != 0);
if (writer_)
{
return writer_;
}
if (!iwriter.empty())
{
CV_LOG_WARNING(NULL, "cvCreateVideoWriter: backend " << info.name << " doesn't support legacy API anymore.")
}
}
}
return NULL;
}
CV_IMPL int cvWriteFrame(CvVideoWriter* writer, const IplImage* image)
{
return writer ? writer->writeFrame(image) : 0;
}
CV_IMPL void cvReleaseVideoWriter(CvVideoWriter** pwriter)
{
if( pwriter && *pwriter )
{
delete *pwriter;
*pwriter = 0;
}
}
CV_IMPL void cvReleaseCapture(CvCapture** pcapture)
{
if (pcapture && *pcapture)
{
delete *pcapture;
*pcapture = 0;
}
}
CV_IMPL IplImage* cvQueryFrame(CvCapture* capture)
{
if (!capture)
return 0;
if (!capture->grabFrame())
return 0;
return capture->retrieveFrame(0);
}
CV_IMPL int cvGrabFrame(CvCapture* capture)
{
return capture ? capture->grabFrame() : 0;
}
CV_IMPL IplImage* cvRetrieveFrame(CvCapture* capture, int idx)
{
return capture ? capture->retrieveFrame(idx) : 0;
}
CV_IMPL double cvGetCaptureProperty(CvCapture* capture, int id)
{
return capture ? capture->getProperty(id) : 0;
}
CV_IMPL int cvSetCaptureProperty(CvCapture* capture, int id, double value)
{
return capture ? capture->setProperty(id, value) : 0;
}
CV_IMPL int cvGetCaptureDomain(CvCapture* capture)
{
return capture ? capture->getCaptureDomain() : 0;
}

@ -0,0 +1,644 @@
// 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.
#include "precomp.hpp"
#include "videoio_registry.hpp"
#include "cap_intelperc.hpp"
#include "cap_librealsense.hpp"
#include "cap_dshow.hpp"
#ifdef HAVE_MFX
#include "cap_mfx_reader.hpp"
#include "cap_mfx_writer.hpp"
#endif
// All WinRT versions older than 8.0 should provide classes used for video support
#if defined(WINRT) && !defined(WINRT_8_0) && defined(__cplusplus_winrt)
# include "cap_winrt_capture.hpp"
# include "cap_winrt_bridge.hpp"
# define WINRT_VIDEO
#endif
#if defined _M_X64 && defined _MSC_VER && !defined CV_ICC
#pragma optimize("",off)
#pragma warning(disable: 4748)
#endif
using namespace cv;
namespace cv
{
static bool param_VIDEOIO_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_DEBUG", false);
static bool param_VIDEOCAPTURE_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOCAPTURE_DEBUG", false);
static bool param_VIDEOWRITER_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOWRITER_DEBUG", false);
namespace {
#define DECLARE_BACKEND(cap, name, mode) { cap, (BackendMode)(mode), 1000, name }
/** Ordering guidelines:
- modern optimized, multi-platform libraries: ffmpeg, gstreamer, Media SDK
- platform specific universal SDK: WINRT, QTKIT/AVFOUNDATION, MSMF/VFW/DSHOW, V4L/V4L2
- RGB-D: OpenNI/OpenNI2, INTELPERC/REALSENSE
- special OpenCV (file-based): "images", "mjpeg"
- special camera SDKs, including stereo: other special SDKs: FIREWIRE/1394, XIMEA/ARAVIS/GIGANETIX/PVAPI(GigE), UNICAP
- other: XINE, gphoto2, etc
*/
static const struct VideoBackendInfo builtin_backends[] =
{
#ifdef HAVE_FFMPEG
DECLARE_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
#endif
#ifdef HAVE_GSTREAMER
DECLARE_BACKEND(CAP_GSTREAMER, "GSTREAMER", MODE_CAPTURE_ALL | MODE_WRITER),
#endif
#ifdef HAVE_MFX // Media SDK
DECLARE_BACKEND(CAP_INTEL_MFX, "INTEL_MFX", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
#endif
// Apple platform
#if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT)
DECLARE_BACKEND(CAP_QT, "QUICKTIME", MODE_CAPTURE_ALL | MODE_WRITER),
#endif
#ifdef HAVE_AVFOUNDATION
DECLARE_BACKEND(CAP_AVFOUNDATION, "AVFOUNDATION", MODE_CAPTURE_ALL | MODE_WRITER),
#endif
// Windows
#ifdef WINRT_VIDEO
DECLARE_BACKEND(CAP_WINRT, "WINRT", MODE_CAPTURE_BY_FILENAME),
#endif
#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_ALL),
#endif
// Linux, some Unix
#if defined HAVE_CAMV4L2
DECLARE_BACKEND(CAP_V4L2, "V4L2", MODE_CAPTURE_ALL),
#elif defined HAVE_LIBV4L || defined HAVE_CAMV4L
DECLARE_BACKEND(CAP_V4L, "V4L", MODE_CAPTURE_ALL),
#endif
// RGB-D universal
#ifdef HAVE_OPENNI
DECLARE_BACKEND(CAP_OPENNI, "OPENNI", MODE_CAPTURE_ALL),
#endif
#ifdef HAVE_OPENNI2
DECLARE_BACKEND(CAP_OPENNI2, "OPENNI2", MODE_CAPTURE_ALL),
#endif
#ifdef HAVE_INTELPERC
DECLARE_BACKEND(CAP_INTELPERC, "INTEL_PERC", MODE_CAPTURE_ALL),
#elif defined(HAVE_LIBREALSENSE)
DECLARE_BACKEND(CAP_INTELPERC, "INTEL_REALSENSE", MODE_CAPTURE_BY_INDEX),
#endif
// OpenCV file-based only
DECLARE_BACKEND(CAP_IMAGES, "CV_IMAGES", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
DECLARE_BACKEND(CAP_OPENCV_MJPEG, "CV_MJPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
// special interfaces / stereo cameras / other SDKs
#if defined(HAVE_DC1394_2) || defined(HAVE_DC1394) || defined(HAVE_CMU1394)
DECLARE_BACKEND(CAP_FIREWIRE, "FIREWIRE", MODE_CAPTURE_ALL),
#endif
// GigE
#ifdef HAVE_PVAPI
DECLARE_BACKEND(CAP_PVAPI, "PVAPI", MODE_CAPTURE_ALL),
#endif
#ifdef HAVE_XIMEA
DECLARE_BACKEND(CAP_XIAPI, "XIMEA", MODE_CAPTURE_ALL),
#endif
#ifdef HAVE_GIGE_API
DECLARE_BACKEND(CAP_GIGANETIX, "GIGANETIX", MODE_CAPTURE_ALL),
#endif
#ifdef HAVE_ARAVIS_API
DECLARE_BACKEND(CAP_ARAVIS, "ARAVIS", MODE_CAPTURE_ALL),
#endif
#ifdef HAVE_UNICAP
DECLARE_BACKEND(CAP_UNICAP, "UNICAP", MODE_CAPTURE_BY_FILENAME),
#endif
#ifdef HAVE_GPHOTO2
DECLARE_BACKEND(CAP_GPHOTO2, "GPHOTO2", MODE_CAPTURE_ALL),
#endif
#ifdef HAVE_XINE
DECLARE_BACKEND(CAP_XINE, "XINE", MODE_CAPTURE_BY_FILENAME),
#endif
// dropped backends: MIL, TYZX, Android
};
bool sortByPriority(const VideoBackendInfo &lhs, const VideoBackendInfo &rhs)
{
return lhs.priority > rhs.priority;
}
/** @brief Manages list of enabled backends
*/
class VideoBackendRegistry
{
protected:
std::vector<VideoBackendInfo> enabledBackends;
VideoBackendRegistry()
{
const int N = sizeof(builtin_backends)/sizeof(builtin_backends[0]);
enabledBackends.assign(builtin_backends, builtin_backends + N);
for (int i = 0; i < N; i++)
{
VideoBackendInfo& info = enabledBackends[i];
info.priority = 1000 - i * 10;
}
CV_LOG_DEBUG(NULL, "VIDEOIO: Builtin backends(" << N << "): " << dumpBackends());
if (readPrioritySettings())
{
CV_LOG_INFO(NULL, "VIDEOIO: Updated backends priorities: " << dumpBackends());
}
int enabled = 0;
for (int i = 0; i < N; i++)
{
VideoBackendInfo& info = enabledBackends[enabled];
if (enabled != i)
info = enabledBackends[i];
size_t param_priority = utils::getConfigurationParameterSizeT(cv::format("OPENCV_VIDEOIO_PRIORITY_%s", info.name).c_str(), (size_t)info.priority);
CV_Assert(param_priority == (size_t)(int)param_priority); // overflow check
if (param_priority > 0)
{
info.priority = (int)param_priority;
enabled++;
}
else
{
CV_LOG_INFO(NULL, "VIDEOIO: Disable backend: " << info.name);
}
}
enabledBackends.resize(enabled);
CV_LOG_DEBUG(NULL, "VIDEOIO: Available backends(" << enabled << "): " << dumpBackends());
std::sort(enabledBackends.begin(), enabledBackends.end(), sortByPriority);
CV_LOG_INFO(NULL, "VIDEOIO: Enabled backends(" << enabled << ", sorted by priority): " << dumpBackends());
}
static std::vector<std::string> tokenize_string(const std::string& input, char token)
{
std::vector<std::string> result;
std::string::size_type prev_pos = 0, pos = 0;
while((pos = input.find(token, pos)) != std::string::npos)
{
result.push_back(input.substr(prev_pos, pos-prev_pos));
prev_pos = ++pos;
}
result.push_back(input.substr(prev_pos));
return result;
}
bool readPrioritySettings()
{
bool hasChanges = false;
cv::String prioritized_backends = utils::getConfigurationParameterString("OPENCV_VIDEOIO_PRIORITY_LIST", NULL);
if (prioritized_backends.empty())
return hasChanges;
CV_LOG_INFO(NULL, "VIDEOIO: Configured priority list (OPENCV_VIDEOIO_PRIORITY_LIST): " << prioritized_backends);
const std::vector<std::string> names = tokenize_string(prioritized_backends, ',');
for (size_t i = 0; i < names.size(); i++)
{
const std::string& name = names[i];
bool found = false;
for (size_t k = 0; k < enabledBackends.size(); k++)
{
VideoBackendInfo& info = enabledBackends[k];
if (name == info.name)
{
info.priority = (int)(100000 + (names.size() - i) * 1000);
CV_LOG_DEBUG(NULL, "VIDEOIO: New backend priority: '" << name << "' => " << info.priority);
found = true;
hasChanges = true;
break;
}
}
if (!found)
{
CV_LOG_WARNING(NULL, "VIDEOIO: Can't prioritize unknown/unavailable backend: '" << name << "'");
}
}
return hasChanges;
}
public:
std::string dumpBackends() const
{
std::ostringstream os;
for (size_t i = 0; i < enabledBackends.size(); i++)
{
if (i > 0) os << "; ";
const VideoBackendInfo& info = enabledBackends[i];
os << info.name << '(' << info.priority << ')';
}
return os.str();
}
static VideoBackendRegistry& getInstance()
{
static VideoBackendRegistry g_instance;
return g_instance;
}
inline std::vector<VideoBackendInfo> getAvailableBackends_CaptureByIndex() const
{
std::vector<VideoBackendInfo> result;
for (size_t i = 0; i < enabledBackends.size(); i++)
{
const VideoBackendInfo& info = enabledBackends[i];
if (info.mode & MODE_CAPTURE_BY_INDEX)
result.push_back(info);
}
return result;
}
inline std::vector<VideoBackendInfo> getAvailableBackends_CaptureByFilename() const
{
std::vector<VideoBackendInfo> result;
for (size_t i = 0; i < enabledBackends.size(); i++)
{
const VideoBackendInfo& info = enabledBackends[i];
if (info.mode & MODE_CAPTURE_BY_FILENAME)
result.push_back(info);
}
return result;
}
inline std::vector<VideoBackendInfo> getAvailableBackends_Writer() const
{
std::vector<VideoBackendInfo> result;
for (size_t i = 0; i < enabledBackends.size(); i++)
{
const VideoBackendInfo& info = enabledBackends[i];
if (info.mode & MODE_WRITER)
result.push_back(info);
}
return result;
}
};
} // namespace
namespace videoio_registry {
std::vector<VideoBackendInfo> getAvailableBackends_CaptureByIndex()
{
const std::vector<VideoBackendInfo> result = VideoBackendRegistry::getInstance().getAvailableBackends_CaptureByIndex();
return result;
}
std::vector<VideoBackendInfo> getAvailableBackends_CaptureByFilename()
{
const std::vector<VideoBackendInfo> result = VideoBackendRegistry::getInstance().getAvailableBackends_CaptureByFilename();
return result;
}
std::vector<VideoBackendInfo> getAvailableBackends_Writer()
{
const std::vector<VideoBackendInfo> result = VideoBackendRegistry::getInstance().getAvailableBackends_Writer();
return result;
}
} // namespace registry
#define TRY_OPEN(backend_func) \
{ \
try { \
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
icap = backend_func; \
if (param_VIDEOIO_DEBUG ||param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p isOpened=%d ...\n", \
#backend_func, icap.empty() ? NULL : icap.get(), icap.empty() ? -1: icap->isOpened())); \
} catch(const cv::Exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
} catch (const std::exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
} catch(...) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
} \
break; \
}
#define TRY_OPEN_LEGACY(backend_func) \
{ \
try { \
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
capture = backend_func; \
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p ...\n", #backend_func, capture)); \
} catch(const cv::Exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
} catch (const std::exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
} catch(...) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
} \
break; \
}
void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, int index)
{
CV_UNUSED(capture); CV_UNUSED(icap);
switch (api)
{
default:
CV_LOG_WARNING(NULL, "VideoCapture(index=" << index << ") was built without support of requested backendID=" << (int)api);
break;
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
TRY_OPEN(createGStreamerCapture(index));
break;
#endif
#ifdef HAVE_MSMF
case CAP_MSMF:
TRY_OPEN(cvCreateCapture_MSMF(index));
break;
#endif
#ifdef HAVE_DSHOW
case CAP_DSHOW:
TRY_OPEN(makePtr<VideoCapture_DShow>(index));
break;
#endif
#ifdef HAVE_INTELPERC
case CAP_INTELPERC:
TRY_OPEN(makePtr<VideoCapture_IntelPerC>());
break;
#elif defined(HAVE_LIBREALSENSE)
case CAP_INTELPERC:
TRY_OPEN(makePtr<VideoCapture_LibRealsense>(index));
break;
#endif
#ifdef WINRT_VIDEO
case CAP_WINRT:
TRY_OPEN(makePtr<cv::VideoCapture_WinRT>(index));
break;
#endif
#ifdef HAVE_GPHOTO2
case CAP_GPHOTO2:
TRY_OPEN(createGPhoto2Capture(index));
break;
#endif
case CAP_VFW: // or CAP_V4L or CAP_V4L2
#ifdef HAVE_VFW
TRY_OPEN_LEGACY(cvCreateCameraCapture_VFW(index))
#endif
#if defined HAVE_LIBV4L || defined HAVE_CAMV4L || defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
TRY_OPEN_LEGACY(cvCreateCameraCapture_V4L(index))
#endif
break;
case CAP_FIREWIRE:
#ifdef HAVE_DC1394_2
TRY_OPEN_LEGACY(cvCreateCameraCapture_DC1394_2(index))
#endif
#ifdef HAVE_DC1394
TRY_OPEN_LEGACY(cvCreateCameraCapture_DC1394(index))
#endif
#ifdef HAVE_CMU1394
TRY_OPEN_LEGACY(cvCreateCameraCapture_CMU(index))
#endif
break; // CAP_FIREWIRE
#ifdef HAVE_MIL
case CAP_MIL:
TRY_OPEN_LEGACY(cvCreateCameraCapture_MIL(index))
break;
#endif
#if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT)
case CAP_QT:
TRY_OPEN_LEGACY(cvCreateCameraCapture_QT(index))
break;
#endif
#ifdef HAVE_UNICAP
case CAP_UNICAP:
TRY_OPEN_LEGACY(cvCreateCameraCapture_Unicap(index))
break;
#endif
#ifdef HAVE_PVAPI
case CAP_PVAPI:
TRY_OPEN_LEGACY(cvCreateCameraCapture_PvAPI(index))
break;
#endif
#ifdef HAVE_OPENNI
case CAP_OPENNI:
TRY_OPEN_LEGACY(cvCreateCameraCapture_OpenNI(index))
break;
#endif
#ifdef HAVE_OPENNI2
case CAP_OPENNI2:
TRY_OPEN_LEGACY(cvCreateCameraCapture_OpenNI2(index))
break;
#endif
#ifdef HAVE_XIMEA
case CAP_XIAPI:
TRY_OPEN_LEGACY(cvCreateCameraCapture_XIMEA(index))
break;
#endif
#ifdef HAVE_AVFOUNDATION
case CAP_AVFOUNDATION:
TRY_OPEN_LEGACY(cvCreateCameraCapture_AVFoundation(index))
break;
#endif
#ifdef HAVE_GIGE_API
case CAP_GIGANETIX:
TRY_OPEN_LEGACY(cvCreateCameraCapture_Giganetix(index))
break;
#endif
#ifdef HAVE_ARAVIS_API
case CAP_ARAVIS:
TRY_OPEN_LEGACY(cvCreateCameraCapture_Aravis(index))
break;
#endif
} // switch (api)
}
void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, const cv::String& filename)
{
switch (api)
{
default:
CV_LOG_WARNING(NULL, "VideoCapture(filename=" << filename << ") was built without support of requested backendID=" << (int)api);
break;
#if defined HAVE_LIBV4L || defined HAVE_CAMV4L || defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
case CAP_V4L:
TRY_OPEN_LEGACY(cvCreateCameraCapture_V4L(filename.c_str()))
break;
#endif
#ifdef HAVE_VFW
case CAP_VFW:
TRY_OPEN_LEGACY(cvCreateFileCapture_VFW(filename.c_str()))
break;
#endif
#if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT)
case CAP_QT:
TRY_OPEN_LEGACY(cvCreateFileCapture_QT(filename.c_str()))
break;
#endif
#ifdef HAVE_AVFOUNDATION
case CAP_AVFOUNDATION:
TRY_OPEN_LEGACY(cvCreateFileCapture_AVFoundation(filename.c_str()))
break;
#endif
#ifdef HAVE_OPENNI
case CAP_OPENNI:
TRY_OPEN_LEGACY(cvCreateFileCapture_OpenNI(filename.c_str()))
break;
#endif
#ifdef HAVE_OPENNI2
case CAP_OPENNI2:
TRY_OPEN_LEGACY(cvCreateFileCapture_OpenNI2(filename.c_str()))
break;
#endif
#ifdef HAVE_XIMEA
case CAP_XIAPI:
TRY_OPEN_LEGACY(cvCreateCameraCapture_XIMEA(filename.c_str()))
break;
#endif
case CAP_IMAGES:
TRY_OPEN_LEGACY(cvCreateFileCapture_Images(filename.c_str()))
break;
#ifdef HAVE_FFMPEG
case CAP_FFMPEG:
TRY_OPEN(cvCreateFileCapture_FFMPEG_proxy(filename))
break;
#endif
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
TRY_OPEN(createGStreamerCapture(filename))
break;
#endif
#ifdef HAVE_XINE
case CAP_XINE:
TRY_OPEN(createXINECapture(filename.c_str()))
break;
#endif
#ifdef HAVE_MSMF
case CAP_MSMF:
TRY_OPEN(cvCreateCapture_MSMF(filename))
break;
#endif
#ifdef HAVE_GPHOTO2
case CAP_GPHOTO2:
TRY_OPEN(createGPhoto2Capture(filename))
break;
#endif
#ifdef HAVE_MFX
case CAP_INTEL_MFX:
TRY_OPEN(makePtr<VideoCapture_IntelMFX>(filename))
break;
#endif
case CAP_OPENCV_MJPEG:
TRY_OPEN(createMotionJpegCapture(filename))
break;
} // switch
}
void VideoWriter_create(CvVideoWriter*& writer, Ptr<IVideoWriter>& iwriter, VideoCaptureAPIs api,
const String& filename, int fourcc, double fps, const Size& frameSize, bool isColor)
{
#define CREATE_WRITER(backend_func) \
{ \
try { \
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
iwriter = backend_func; \
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p isOpened=%d...\n", #backend_func, iwriter.empty() ? NULL : iwriter.get(), iwriter.empty() ? iwriter->isOpened() : -1)); \
} catch(const cv::Exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
} catch (const std::exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
} catch(...) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
} \
break; \
}
#define CREATE_WRITER_LEGACY(backend_func) \
{ \
try { \
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
writer = backend_func; \
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p...\n", #backend_func, writer)); \
} catch(const cv::Exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
} catch (const std::exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
} catch(...) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
} \
break; \
}
switch (api)
{
default:
CV_LOG_ERROR(NULL, "Unknown VideoWriter backend (check getBuildInformation()): " << (int)api);
break;
#ifdef HAVE_FFMPEG
case CAP_FFMPEG:
CREATE_WRITER(cvCreateVideoWriter_FFMPEG_proxy(filename, fourcc, fps, frameSize, isColor));
break;
#endif
#ifdef HAVE_MSMF
case CAP_MSMF:
CREATE_WRITER(cvCreateVideoWriter_MSMF(filename, fourcc, fps, frameSize, isColor));
break;
#endif
#ifdef HAVE_MFX
case CAP_INTEL_MFX:
CREATE_WRITER(VideoWriter_IntelMFX::create(filename, fourcc, fps, frameSize, isColor));
break;
#endif
#ifdef HAVE_VFW
case CAP_VFW:
CREATE_WRITER_LEGACY(cvCreateVideoWriter_VFW(filename.c_str(), fourcc, fps, frameSize, isColor))
break;
#endif
#ifdef HAVE_AVFOUNDATION
case CAP_AVFOUNDATION:
CREATE_WRITER_LEGACY(cvCreateVideoWriter_AVFoundation(filename.c_str(), fourcc, fps, frameSize, isColor))
break;
#endif
#if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT)
case(CAP_QT):
CREATE_WRITER_LEGACY(cvCreateVideoWriter_QT(filename.c_str(), fourcc, fps, frameSize, isColor))
break;
#endif
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
CREATE_WRITER_LEGACY(cvCreateVideoWriter_GStreamer (filename.c_str(), fourcc, fps, frameSize, isColor))
break;
#endif
case CAP_OPENCV_MJPEG:
CREATE_WRITER(createMotionJpegWriter(filename, fourcc, fps, frameSize, isColor));
break;
case CAP_IMAGES:
if(!fourcc || !fps)
{
CREATE_WRITER_LEGACY(cvCreateVideoWriter_Images(filename.c_str()));
}
break;
} // switch(api)
}
} // namespace

@ -0,0 +1,43 @@
// 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.
#ifndef __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
#define __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
namespace cv
{
/** Capabilities bitmask */
enum BackendMode {
MODE_CAPTURE_BY_INDEX = 1 << 0, //!< device index
MODE_CAPTURE_BY_FILENAME = 1 << 1, //!< filename or device path (v4l2)
MODE_WRITER = 1 << 4, //!< writer
MODE_CAPTURE_ALL = MODE_CAPTURE_BY_INDEX + MODE_CAPTURE_BY_FILENAME,
};
struct VideoBackendInfo {
VideoCaptureAPIs id;
BackendMode mode;
int priority; // 1000-<index*10> - default builtin priority
// 0 - disabled (OPENCV_VIDEOIO_PRIORITY_<name> = 0)
// >10000 - prioritized list (OPENCV_VIDEOIO_PRIORITY_LIST)
const char* name;
};
namespace videoio_registry {
std::vector<VideoBackendInfo> getAvailableBackends_CaptureByIndex();
std::vector<VideoBackendInfo> getAvailableBackends_CaptureByFilename();
std::vector<VideoBackendInfo> getAvailableBackends_Writer();
} // namespace
void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, int index);
void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, const cv::String& filename);
void VideoWriter_create(CvVideoWriter*& writer, Ptr<IVideoWriter>& iwriter, VideoCaptureAPIs api,
const String& filename, int fourcc, double fps, const Size& frameSize, bool isColor);
} // namespace
#endif // __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__

@ -228,7 +228,7 @@ public:
static std::string TmpDirectory;
CreateVideoWriterInvoker(std::vector<VideoWriter*>& _writers, std::vector<std::string>& _files) :
ParallelLoopBody(), writers(&_writers), files(&_files)
writers(_writers), files(_files)
{
}
@ -240,16 +240,16 @@ public:
stream << i << ".avi";
std::string fileName = tempfile(stream.str().c_str());
files->operator[](i) = fileName;
writers->operator[](i) = new VideoWriter(fileName, CAP_FFMPEG, VideoWriter::fourcc('X','V','I','D'), 25.0f, FrameSize);
files[i] = fileName;
writers[i] = new VideoWriter(fileName, CAP_FFMPEG, VideoWriter::fourcc('X','V','I','D'), 25.0f, FrameSize);
CV_Assert(writers->operator[](i)->isOpened());
CV_Assert(writers[i]->isOpened());
}
}
private:
std::vector<VideoWriter*>* writers;
std::vector<std::string>* files;
std::vector<VideoWriter*>& writers;
std::vector<std::string>& files;
};
std::string CreateVideoWriterInvoker::TmpDirectory;
@ -357,6 +357,8 @@ public:
for (unsigned int i = 0; i < frameCount && next; ++i)
{
SCOPED_TRACE(cv::format("frame=%d/%d", (int)i, (int)frameCount));
Mat actual;
(*capture) >> actual;

@ -19,7 +19,7 @@ if(NOT BUILD_SHARED_LIBS)
endif()
endforeach()
if(_conflicts)
message(STATUS "Disabling VIZ module due conflicts with VTK dependencies: ${_conflicts}")
message(STATUS "Disabling VIZ module due to conflicts with VTK dependencies: ${_conflicts}")
ocv_module_disable(viz)
endif()
endif()

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save