1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-25 13:23:02 +04:00

Compare commits

...

75 Commits

Author SHA1 Message Date
Alexander Alekhin 6d4f66472e OpenCV version++
3.4.0
2017-12-22 19:46:21 +00:00
Alexander Alekhin eba176c299 Merge pull request #10398 from alalek:ml_simplify_simulated_annealing 2017-12-22 22:43:59 +03:00
Alexander Alekhin 00e43a9022 ml(ANN_MLP): ensure that train() call is always successful 2017-12-22 18:50:04 +00:00
Alexander Alekhin 9148a37624 Merge pull request #10401 from terfendail:resize_linear_revert 2017-12-22 16:18:50 +00:00
Alexander Alekhin 019b7c5a66 Merge pull request #10402 from dkurt:dnn_tf_quantized 2017-12-22 15:58:56 +00:00
Alexander Alekhin 59e825ee02 Merge pull request #10385 from pengli:dnn 2017-12-22 15:48:40 +00:00
Dmitry Kurtaev bcc669f3f7 TensorFlow weights dequantization 2017-12-22 17:25:10 +03:00
Vitaly Tuzov e5313246a7 Reverted calls to linear resize back to generic version for floating point matrices 2017-12-22 17:10:03 +03:00
Alexander Alekhin 97af608030 Merge pull request #10397 from mshabunin:fix-incorrect-assert 2017-12-22 14:07:02 +00:00
Li Peng 181b448c4d add one more convolution kernel tuning candidate
Signed-off-by: Li Peng <peng.li@intel.com>
2017-12-22 21:37:00 +08:00
Alexander Alekhin 289a8da39e ml: simplify interfaces of SimulatedAnnealingSolver 2017-12-22 16:35:48 +03:00
Vadim Pisarevsky b85c77283b Merge pull request #10396 from berak:fix_superres_sample 2017-12-22 13:35:36 +00:00
Vadim Pisarevsky 0742e12f0b Merge pull request #10265 from dkurt:nms_for_region_layer 2017-12-22 13:29:37 +00:00
Vadim Pisarevsky 9b659736da Merge pull request #10394 from alalek:cmake_fix_pch_pic_pie 2017-12-22 13:26:32 +00:00
Vadim Pisarevsky 69a6765bf7 Merge pull request #10387 from terfendail:resize23_perftest 2017-12-22 13:26:05 +00:00
Vadim Pisarevsky 3f68d6d8a7 Merge pull request #10392 from terfendail:bitexact_fallback 2017-12-22 13:23:55 +00:00
Alexander Alekhin 83b8cd0152 Merge pull request #10375 from tomoaki0705:buildWarningMSVC 2017-12-22 13:17:12 +00:00
Alexander Alekhin 4e542a65a3 Merge pull request #10390 from alalek:ocl_option_buffer_rect 2017-12-22 12:52:56 +00:00
Maksim Shabunin aa46e31c6d Replaced incorrect CV_Assert calls with CV_Error 2017-12-22 15:20:13 +03:00
berak ddbd074678 samples: check for valid input in gpu/super_resolution.cpp 2017-12-22 12:34:25 +01:00
Vitaly Tuzov 5fdb42a7c9 Added fallback to generic linear resize in case bit-exact resize of provided matrix isn't supported 2017-12-22 14:29:50 +03:00
Alexander Alekhin 6c252d8cdc cmake: fix -fPIC/-fPIE handling in precompiled headers (PCH) 2017-12-22 13:57:06 +03:00
Vadim Pisarevsky 636b7ec0c4 Merge pull request #10386 from terfendail:resizeexact_c3 2017-12-22 10:54:49 +00:00
Alexander Alekhin 534645a12f ocl: workaround option to disable usage of buffer "Rect" operations 2017-12-22 13:05:03 +03:00
Alexander Alekhin 09c84a0164 Merge pull request #10389 from wxzs5:yangli 2017-12-22 10:04:05 +00:00
Vadim Pisarevsky 325cbd7c84 Merge pull request #10364 from dkurt:dnn_smooth_tf_data_layout 2017-12-22 09:56:45 +00:00
wxzs5 b19cd93738 Remove redundant return variable 2017-12-22 17:13:57 +08:00
Vitaly Tuzov 019162486c Disabled universal intrinsic based implementation for bit-exact resize of 3-channel images 2017-12-22 10:08:30 +03:00
Tomoaki Teshima fe7b3f1228 clean up the code
* disable the warning in CMake, not int the code using pragma
2017-12-22 08:42:21 +09:00
Alexander Alekhin 1bc1f3d311 Merge pull request #10374 from tomoaki0705:removeGstreamerTest 2017-12-21 19:02:13 +00:00
Vadim Pisarevsky a8a51db42b Merge pull request #10316 from terfendail:bitexact_c234 2017-12-21 18:56:54 +00:00
Vadim Pisarevsky 70d49446e9 Merge pull request #10369 from alalek:issue_10351 2017-12-21 18:48:38 +00:00
Alexander Alekhin a2620f72c7 Merge pull request #10370 from pengli:dnn 2017-12-21 15:36:23 +00:00
Tomoaki Teshima 50d44e06e3 avoid the test which is too strict
* confirmed test failure on Jetson TX1 and TX2
  * show the performance but not bit exact result
2017-12-22 00:14:10 +09:00
Li Peng c5fc8e03ff cleanup unnecessary macros in convolution ocl kernel
Signed-off-by: Li Peng <peng.li@intel.com>
2017-12-21 20:32:36 +08:00
Li Peng 0aa5e43a14 refactor candidate generation of convolution auto-tuning
Signed-off-by: Li Peng <peng.li@intel.com>
2017-12-21 23:05:54 +08:00
Dmitry Kurtaev c67e75b68f Refactor NMS procedure at RegionLayer 2017-12-21 12:21:45 +03:00
Vadim Pisarevsky 047ad4ff71 Merge pull request #10366 from alalek:ocl_fix_cvtcolor_read 2017-12-21 08:33:59 +00:00
Vadim Pisarevsky ae8bb718cd Merge pull request #10340 from alalek:log_level_option 2017-12-21 08:33:18 +00:00
Alexander Alekhin 7bbe1a53cf imgcodecs(pxm): fix memcpy size 2017-12-21 01:10:24 +00:00
Vitaly Tuzov b6fe4cc807 Added performance tests for linear resize of 2 and 3-channel images 2017-12-20 18:11:21 +03:00
Vadim Pisarevsky eecb64a973 Merge pull request #10331 from arrybn:python_dnn_net 2017-12-20 14:30:27 +00:00
Vadim Pisarevsky e72a053cca Merge pull request #10354 from catree:add_python_sample_show_extrinsics 2017-12-20 14:23:01 +00:00
LaurentBerger e43997dbb5 Calcerror uses now weighted samples (#10346)
* Calcerror uses now sample weights

* catree comment in #10319
2017-12-20 17:24:46 +03:00
Alexander Alekhin 813ff37967 imgproc(ocl): fix RGB2RGBA kernel out of range access 2017-12-20 14:19:46 +00:00
Vadim Pisarevsky b8a24b36ce Merge pull request #10356 from dkurt:dnn_rfcn 2017-12-20 14:19:46 +00:00
Vadim Pisarevsky d2f13a8259 Merge pull request #10360 from sturkmen72:update_links 2017-12-20 14:19:17 +00:00
Vadim Pisarevsky 94d84c5fad Merge pull request #10358 from catree:add_tutorial_homography_panorama_stitching 2017-12-20 14:18:41 +00:00
Vitaly Tuzov 1eb2fa9efb Added universal intrinsics based implementations for CV_8UC2, CV_8UC3, CV_8UC4 bit-exact resizes. 2017-12-20 17:17:10 +03:00
Dmitry Kurtaev 7e48fa58eb Manage TensorFlow's NHWC data layout is smoother 2017-12-20 14:13:40 +03:00
catree 59ec224009 Update left_intrinsics.yml file with chessboard square_size=0.025 and with extrinsic parameters. Add camera_calibration_show_extrinsics.py, a Python sample that allows to display the extrinsics saved during the camera calibration process (cpp-example-calibration). 2017-12-20 12:06:08 +01:00
Dmitry Kurtaev 0ed2cbc931 R-FCN models support 2017-12-20 10:43:22 +03:00
Suleyman TURKMEN 1ff33e6e4d Update links 2017-12-20 02:55:29 +03:00
Alexander Alekhin b450811e4b core(logger): add log level configuration option 2017-12-19 22:57:07 +00:00
catree 87160cb297 Add Demo 5: Basic panorama stitching from a rotating camera in the homography tutorial. 2017-12-19 22:45:35 +01:00
Alexander Alekhin dcdd6af5a8 Merge pull request #10341 from pengli:dnn 2017-12-19 14:04:55 +00:00
Alexander Alekhin badc3bd312 Merge pull request #10348 from ElenaGvozdeva:Canny_HAL 2017-12-19 13:07:59 +00:00
Vadim Pisarevsky b1ed8bc0d1 Merge pull request #10347 from dkurt:dnn_remove_deprecated_importer 2017-12-19 11:03:06 +00:00
Li Peng 3b84acfc48 add ocl accuracy test for tf mobilenet ssd
Signed-off-by: Li Peng <peng.li@intel.com>
2017-12-19 18:38:55 +08:00
Li Peng 436d7e4eaf add depthwise convolution kernel
Signed-off-by: Li Peng <peng.li@intel.com>
2017-12-19 17:59:13 +08:00
Li Peng 910d7dab1f prior box layer ocl implementation
Signed-off-by: Li Peng <peng.li@intel.com>
2017-12-19 17:44:10 +08:00
elenagvo b0e9d76ced HAL for canny 2017-12-19 11:03:10 +03:00
Alexander Alekhin 05b259fe2e Merge pull request #10344 from tomoaki0705:fixBuildLibtiff 2017-12-18 17:00:45 +00:00
Dmitry Kurtaev 6aabd6cc7a Remove cv::dnn::Importer 2017-12-18 18:08:28 +03:00
Alexander Rybnikov 19c914db51 Changed wrapping mode for cv::dnn::Net::forward 2017-12-18 15:56:09 +03:00
Tomoaki Teshima c057d29192 fix compilation error on Visual Studio 2013 and earlier
- fix compilation error about "inline"
  - fix linker error about "_TIFF_snprintf_f"
2017-12-18 21:51:33 +09:00
Vadim Pisarevsky e29de5dd2b Merge pull request #10343 from tomoaki0705:suppressWarningEncoding 2017-12-18 10:53:24 +00:00
Suleyman TURKMEN 1654dfe3a9 Update samples (#10333)
* Update samples

* Update calib3d.hpp

* Update calib3d.hpp

* Update calib3d.hpp

* Update calib3d.hpp
2017-12-18 13:44:11 +03:00
Vadim Pisarevsky d3a124c820 Merge pull request #10339 from catree:add_doc_solvepnp_figure_desc 2017-12-18 09:13:06 +00:00
Vadim Pisarevsky 86cc4f3aa4 Merge pull request #10337 from dkurt:fix_pooling_layer 2017-12-18 09:11:54 +00:00
Alexander Alekhin 9de87d96cc Merge pull request #10338 from hrnr:fix-build 2017-12-18 06:52:08 +00:00
Tomoaki Teshima 65f502bc99 suppress warning on Visual Studio
* remove non ASCII character from the comment
2017-12-18 15:32:06 +09:00
catree fcb537bacd Add a figure and some formulas to illustrate the PnP pose estimation principle. 2017-12-17 21:38:22 +01:00
Jiri Horner 3dbf392d48 fix build with intrinsics enabled
* since #10231 opencv with instrumentation does not build
2017-12-17 20:23:15 +01:00
Dmitry Kurtaev 2b43d4f477 Fix default pooling layer type 2017-12-17 16:46:40 +03:00
111 changed files with 4111 additions and 1647 deletions
+21 -24
View File
@@ -35,31 +35,27 @@ if(NOT MSVC)
check_include_file(unistd.h HAVE_UNISTD_H)
endif()
if(MSVC)
set(INLINE_KEYWORD "inline")
else()
# Inspired from /usr/share/autoconf/autoconf/c.m4
foreach(inline_keyword "inline" "__inline__" "__inline")
if(NOT DEFINED C_INLINE)
set(CMAKE_REQUIRED_DEFINITIONS_SAVE ${CMAKE_REQUIRED_DEFINITIONS})
set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
"-Dinline=${inline_keyword}")
check_c_source_compiles("
typedef int foo_t;
static inline foo_t static_foo() {return 0;}
foo_t foo(){return 0;}
int main(int argc, char *argv[]) {return 0;}"
C_HAS_${inline_keyword})
set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS_SAVE})
if(C_HAS_${inline_keyword})
set(C_INLINE TRUE)
set(INLINE_KEYWORD "${inline_keyword}")
endif()
endif()
endforeach()
# Inspired from /usr/share/autoconf/autoconf/c.m4
foreach(inline_keyword "inline" "__inline__" "__inline")
if(NOT DEFINED C_INLINE)
set(INLINE_KEYWORD)
endif()
set(CMAKE_REQUIRED_DEFINITIONS_SAVE ${CMAKE_REQUIRED_DEFINITIONS})
set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
"-Dinline=${inline_keyword}")
check_c_source_compiles("
typedef int foo_t;
static inline foo_t static_foo() {return 0;}
foo_t foo(){return 0;}
int main(int argc, char *argv[]) {return 0;}"
C_HAS_${inline_keyword})
set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS_SAVE})
if(C_HAS_${inline_keyword})
set(C_INLINE TRUE)
set(INLINE_KEYWORD "${inline_keyword}")
endif()
endif()
endforeach()
if(NOT DEFINED C_INLINE)
set(INLINE_KEYWORD)
endif()
@@ -414,6 +410,7 @@ set(lib_srcs
tif_write.c
tif_zip.c
tif_stream.cxx
snprintf.c
t4.h
tif_dir.h
tif_fax3.h
+38
View File
@@ -0,0 +1,38 @@
/**
* Workaround for lack of snprintf(3) in Visual Studio. See
* http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010/8712996#8712996
* It's a trivial wrapper around the builtin _vsnprintf_s and
* _vscprintf functions.
*/
#ifdef _MSC_VER
#include <stdio.h>
#include <stdarg.h>
int _TIFF_vsnprintf_f(char* str, size_t size, const char* format, va_list ap)
{
int count = -1;
if (size != 0)
count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
int _TIFF_snprintf_f(char* str, size_t size, const char* format, ...)
{
int count;
va_list ap;
va_start(ap, format);
count = vsnprintf(str, size, format, ap);
va_end(ap);
return count;
}
#endif // _MSC_VER
+1 -1
View File
@@ -605,7 +605,7 @@ static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
}
// Implement a Lehmer random number generator with a multiplicative constant of
// 48271 and a modulo constant of 2^31 1.
// 48271 and a modulo constant of 2^31 - 1.
static uint32_t MyRand(uint32_t* const seed) {
*seed = (uint32_t)(((uint64_t)(*seed) * 48271u) % 2147483647u);
assert(*seed > 0);
+1 -3
View File
@@ -309,9 +309,6 @@ if(MSVC)
if(MSVC_VERSION EQUAL 1400)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4510 /wd4610 /wd4312 /wd4201 /wd4244 /wd4328 /wd4267)
endif()
if(MSVC_VERSION LESS 1900) # MSVS2015
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127) # warning C4127: conditional expression is constant
endif()
endif()
# allow extern "C" functions throw exceptions
@@ -323,6 +320,7 @@ if(MSVC)
endforeach()
if(NOT ENABLE_NOISY_WARNINGS)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127) # conditional expression is constant
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4251) # class 'std::XXX' needs to have dll-interface to be used by clients of YYY
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4324) # 'struct_name' : structure was padded due to __declspec(align())
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4275) # non dll-interface class 'std::exception' used as base for dll-interface class 'cv::Exception'
+18
View File
@@ -261,6 +261,24 @@ MACRO(ADD_PRECOMPILED_HEADER _targetName _input)
endif()
endif()
if(type STREQUAL "SHARED_LIBRARY" OR type STREQUAL "STATIC_LIBRARY")
get_target_property(__pic ${_targetName} POSITION_INDEPENDENT_CODE)
if(__pic AND CMAKE_CXX_COMPILE_OPTIONS_PIC
AND NOT OPENCV_SKIP_PCH_PIC_HANDLING
AND NOT OPENCV_SKIP_PCH_PIC_HANDLING_${_targetName}
)
list(APPEND _compile_FLAGS "${CMAKE_CXX_COMPILE_OPTIONS_PIC}")
endif()
elseif(type STREQUAL "EXECUTABLE")
get_target_property(__pie ${_targetName} POSITION_INDEPENDENT_CODE)
if(__pie AND CMAKE_CXX_COMPILE_OPTIONS_PIE
AND NOT OPENCV_SKIP_PCH_PIE_HANDLING
AND NOT OPENCV_SKIP_PCH_PIE_HANDLING_${_targetName}
)
list(APPEND _compile_FLAGS "${CMAKE_CXX_COMPILE_OPTIONS_PIE}")
endif()
endif()
get_target_property(DIRINC ${_targetName} INCLUDE_DIRECTORIES)
set_target_properties(${_targetName}_pch_dephelp PROPERTIES INCLUDE_DIRECTORIES "${DIRINC}")
@@ -41,7 +41,7 @@
<script src="utils.js" type="text/javascript"></script>
<script id="codeSnippet" type="text/code-snippet">
let src = cv.imread('canvasInput');
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8U);
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
let lines = new cv.Mat();
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
cv.Canny(src, src, 50, 200, 3);
@@ -41,7 +41,7 @@
<script src="utils.js" type="text/javascript"></script>
<script id="codeSnippet" type="text/code-snippet">
let src = cv.imread('canvasInput');
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8U);
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
let lines = new cv.Mat();
let color = new cv.Scalar(255, 0, 0);
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
@@ -70,7 +70,7 @@ for fname in glob.glob('left*.jpg'):
corners2 = cv.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
# Find the rotation and translation vectors.
ret,rvecs, tvecs, inliers = cv.solvePnP(objp, corners2, mtx, dist)
ret,rvecs, tvecs = cv.solvePnP(objp, corners2, mtx, dist)
# project 3D points to image plane
imgpts, jac = cv.projectPoints(axis, rvecs, tvecs, mtx, dist)
@@ -1,8 +1,10 @@
Basic concepts of the homography explained with code {#tutorial_homography}
=============================
====================================================
Introduction
----
@tableofcontents
Introduction {#tutorial_homography_Introduction}
============
This tutorial will demonstrate the basic concepts of the homography with some codes.
For detailed explanations about the theory, please refer to a computer vision course or a computer vision book, e.g.:
@@ -13,10 +15,10 @@ For detailed explanations about the theory, please refer to a computer vision co
The tutorial code can be found [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/features2D/Homography).
The images used in this tutorial can be found [here](https://github.com/opencv/opencv/tree/master/samples/data) (`left*.jpg`).
Basic theory
----
Basic theory {#tutorial_homography_Basic_theory}
------------
### What is the homography matrix?
### What is the homography matrix? {#tutorial_homography_What_is_the_homography_matrix}
Briefly, the planar homography relates the transformation between two planes (up to a scale factor):
@@ -61,7 +63,7 @@ The following examples show different kinds of transformation but all relate a t
![](images/homography_transformation_example3.jpg)
### How the homography transformation can be useful?
### How the homography transformation can be useful? {#tutorial_homography_How_the_homography_transformation_can_be_useful}
* Camera pose estimation from coplanar points for augmented reality with marker for instance (see the previous first example)
@@ -75,10 +77,10 @@ The following examples show different kinds of transformation but all relate a t
![](images/homography_panorama_stitching.jpg)
Demonstration codes
----
Demonstration codes {#tutorial_homography_Demonstration_codes}
-------------------
### Demo 1: Pose estimation from coplanar points
### Demo 1: Pose estimation from coplanar points {#tutorial_homography_Demo1}
\note Please note that the code to estimate the camera pose from the homography is an example and you should use instead @ref cv::solvePnP if you want to estimate the camera pose for a planar or an arbitrary object.
@@ -89,31 +91,31 @@ This can be tested easily using a chessboard object and `findChessboardCorners()
The first thing consists to detect the chessboard corners, the chessboard size (`patternSize`), here `9x6`, is required:
@snippet tutorial_homography_ex1_pose_from_homography.cpp find-chessboard-corners
@snippet pose_from_homography.cpp find-chessboard-corners
![](images/homography_pose_chessboard_corners.jpg)
The object points expressed in the object frame can be computed easily knowing the size of a chessboard square:
@snippet tutorial_homography_ex1_pose_from_homography.cpp compute-chessboard-object-points
@snippet pose_from_homography.cpp compute-chessboard-object-points
The coordinate `Z=0` must be removed for the homography estimation part:
@snippet tutorial_homography_ex1_pose_from_homography.cpp compute-object-points
@snippet pose_from_homography.cpp compute-object-points
The image points expressed in the normalized camera can be computed from the corner points and by applying a reverse perspective transformation using the camera intrinsics and the distortion coefficients:
@snippet tutorial_homography_ex1_pose_from_homography.cpp load-intrinsics
@snippet pose_from_homography.cpp load-intrinsics
@snippet tutorial_homography_ex1_pose_from_homography.cpp compute-image-points
@snippet pose_from_homography.cpp compute-image-points
The homography can then be estimated with:
@snippet tutorial_homography_ex1_pose_from_homography.cpp estimate-homography
@snippet pose_from_homography.cpp estimate-homography
A quick solution to retrieve the pose from the homography matrix is (see \ref pose_ar "5"):
@snippet tutorial_homography_ex1_pose_from_homography.cpp pose-from-homography
@snippet pose_from_homography.cpp pose-from-homography
\f[
\begin{align*}
@@ -151,11 +153,16 @@ A quick solution to retrieve the pose from the homography matrix is (see \ref po
This is a quick solution (see also \ref projective_transformations "2") as this does not ensure that the resulting rotation matrix will be orthogonal and the scale is estimated roughly by normalize the first column to 1.
A solution to have a proper rotation matrix (with the properties of a rotation matrix) consists to apply a polar decomposition
(see \ref polar_decomposition "6" or \ref polar_decomposition_svd "7" for some information):
@snippet pose_from_homography.cpp polar-decomposition-of-the-rotation-matrix
To check the result, the object frame projected into the image with the estimated camera pose is displayed:
![](images/homography_pose.jpg)
### Demo 2: Perspective correction
### Demo 2: Perspective correction {#tutorial_homography_Demo2}
In this example, a source image will be transformed into a desired perspective view by computing the homography that maps the source points into the desired points.
The following image shows the source image (left) and the chessboard view that we want to transform into the desired chessboard view (right).
@@ -164,15 +171,15 @@ The following image shows the source image (left) and the chessboard view that w
The first step consists to detect the chessboard corners in the source and desired images:
@snippet tutorial_homography_ex2_perspective_correction.cpp find-corners
@snippet perspective_correction.cpp find-corners
The homography is estimated easily with:
@snippet tutorial_homography_ex2_perspective_correction.cpp estimate-homography
@snippet perspective_correction.cpp estimate-homography
To warp the source chessboard view into the desired chessboard view, we use @ref cv::warpPerspective
@snippet tutorial_homography_ex2_perspective_correction.cpp warp-chessboard
@snippet perspective_correction.cpp warp-chessboard
The result image is:
@@ -180,13 +187,13 @@ The result image is:
To compute the coordinates of the source corners transformed by the homography:
@snippet tutorial_homography_ex2_perspective_correction.cpp compute-transformed-corners
@snippet perspective_correction.cpp compute-transformed-corners
To check the correctness of the calculation, the matching lines are displayed:
![](images/homography_perspective_correction_chessboard_matches.jpg)
### Demo 3: Homography from the camera displacement
### Demo 3: Homography from the camera displacement {#tutorial_homography_Demo3}
The homography relates the transformation between two planes and it is possible to retrieve the corresponding camera displacement that allows to go from the first to the second plane view (see @cite Malis for more information).
Before going into the details that allow to compute the homography from the camera displacement, some recalls about camera pose and homogeneous transformation.
@@ -295,13 +302,13 @@ To transform a 3D point expressed in the camera 1 frame to the camera 2 frame:
In this example, we will compute the camera displacement between two camera poses with respect to the chessboard object. The first step consists to compute the camera poses for the two images:
@snippet tutorial_homography_ex3_homography_from_camera_displacement.cpp compute-poses
@snippet homography_from_camera_displacement.cpp compute-poses
![](images/homography_camera_displacement_poses.jpg)
The camera displacement can be computed from the camera poses using the formulas above:
@snippet tutorial_homography_ex3_homography_from_camera_displacement.cpp compute-c2Mc1
@snippet homography_from_camera_displacement.cpp compute-c2Mc1
The homography related to a specific plane computed from the camera displacement is:
@@ -320,11 +327,11 @@ the translation vector between the two camera frames.
Here the normal vector `n` is the plane normal expressed in the camera frame 1 and can be computed as the cross product of 2 vectors (using 3 non collinear points that lie on the plane) or in our case directly with:
@snippet tutorial_homography_ex3_homography_from_camera_displacement.cpp compute-plane-normal-at-camera-pose-1
@snippet homography_from_camera_displacement.cpp compute-plane-normal-at-camera-pose-1
The distance `d` can be computed as the dot product between the plane normal and a point on the plane or by computing the [plane equation](http://mathworld.wolfram.com/Plane.html) and using the D coefficient:
@snippet tutorial_homography_ex3_homography_from_camera_displacement.cpp compute-plane-distance-to-the-camera-frame-1
@snippet homography_from_camera_displacement.cpp compute-plane-distance-to-the-camera-frame-1
The projective homography matrix \f$ \textbf{G} \f$ can be computed from the Euclidean homography \f$ \textbf{H} \f$ using the intrinsic matrix \f$ \textbf{K} \f$ (see @cite Malis), here assuming the same camera between the two plane views:
@@ -332,7 +339,7 @@ The projective homography matrix \f$ \textbf{G} \f$ can be computed from the Euc
\textbf{G} = \gamma \textbf{K} \textbf{H} \textbf{K}^{-1}
\f]
@snippet tutorial_homography_ex3_homography_from_camera_displacement.cpp compute-homography
@snippet homography_from_camera_displacement.cpp compute-homography
In our case, the Z-axis of the chessboard goes inside the object whereas in the homography figure it goes outside. This is just a matter of sign:
@@ -340,7 +347,7 @@ In our case, the Z-axis of the chessboard goes inside the object whereas in the
^{2}\textrm{H}_{1} = \hspace{0.2em} ^{2}\textrm{R}_{1} + \hspace{0.1em} \frac{^{2}\textrm{t}_{1} \cdot n^T}{d}
\f]
@snippet tutorial_homography_ex3_homography_from_camera_displacement.cpp compute-homography-from-camera-displacement
@snippet homography_from_camera_displacement.cpp compute-homography-from-camera-displacement
We will now compare the projective homography computed from the camera displacement with the one estimated with @ref cv::findHomography
@@ -363,16 +370,16 @@ The homography matrices are similar. If we compare the image 1 warped using both
Visually, it is hard to distinguish a difference between the result image from the homography computed from the camera displacement and the one estimated with @ref cv::findHomography function.
### Demo 4: Decompose the homography matrix
### Demo 4: Decompose the homography matrix {#tutorial_homography_Demo4}
OpenCV 3 contains the function @ref cv::decomposeHomographyMat which allows to decompose the homography matrix to a set of rotations, translations and plane normals.
First we will decompose the homography matrix computed from the camera displacement:
@snippet tutorial_homography_ex4_decompose_homography.cpp compute-homography-from-camera-displacement
@snippet decompose_homography.cpp compute-homography-from-camera-displacement
The results of @ref cv::decomposeHomographyMat are:
@snippet tutorial_homography_ex4_decompose_homography.cpp decompose-homography-from-camera-displacement
@snippet decompose_homography.cpp decompose-homography-from-camera-displacement
```
Solution 0:
@@ -457,11 +464,66 @@ plane normal at camera 1 pose: [0.1973513139420654, -0.6283451996579068, 0.75248
Again, there is also a solution that matches with the computed camera displacement.
Additional references
----
### Demo 5: Basic panorama stitching from a rotating camera {#tutorial_homography_Demo5}
\note This example is made to illustrate the concept of image stitching based on a pure rotational motion of the camera and should not be used to stitch panorama images.
The [stitching module](@ref stitching) provides a complete pipeline to stitch images.
The homography transformation applies only for planar structure. But in the case of a rotating camera (pure rotation around the camera axis of projection, no translation), an arbitrary world can be considered
([see previously](@ref tutorial_homography_What_is_the_homography_matrix)).
The homography can then be computed using the rotation transformation and the camera intrinsic parameters as (see for instance \ref homography_course "8"):
\f[
s
\begin{bmatrix}
x^{'} \\
y^{'} \\
1
\end{bmatrix} =
\bf{K} \hspace{0.1em} \bf{R} \hspace{0.1em} \bf{K}^{-1}
\begin{bmatrix}
x \\
y \\
1
\end{bmatrix}
\f]
To illustrate, we used Blender, a free and open-source 3D computer graphics software, to generate two camera views with only a rotation transformation between each other.
More information about how to retrieve the camera intrinsic parameters and the `3x4` extrinsic matrix with respect to the world can be found in \ref answer_blender "9" (an additional transformation
is needed to get the transformation between the camera and the object frames) with Blender.
The figure below shows the two generated views of the Suzanne model, with only a rotation transformation:
![](images/homography_stitch_compare.jpg)
With the known associated camera poses and the intrinsic parameters, the relative rotation between the two views can be computed:
@snippet panorama_stitching_rotating_camera.cpp extract-rotation
@snippet panorama_stitching_rotating_camera.cpp compute-rotation-displacement
Here, the second image will be stitched with respect to the first image. The homography can be calculated using the formula above:
@snippet panorama_stitching_rotating_camera.cpp compute-homography
The stitching is made simply with:
@snippet panorama_stitching_rotating_camera.cpp stitch
The resulting image is:
![](images/homography_stitch_Suzanne.jpg)
Additional references {#tutorial_homography_Additional_references}
---------------------
* \anchor lecture_16 1. [Lecture 16: Planar Homographies](http://www.cse.psu.edu/~rtc12/CSE486/lecture16.pdf), Robert Collins
* \anchor projective_transformations 2. [2D projective transformations (homographies)](https://ags.cs.uni-kl.de/fileadmin/inf_ags/3dcv-ws11-12/3DCV_WS11-12_lec04.pdf), Christiano Gava, Gabriele Bleser
* \anchor szeliski 3. [Computer Vision: Algorithms and Applications](http://szeliski.org/Book/drafts/SzeliskiBook_20100903_draft.pdf), Richard Szeliski
* \anchor answer_dsp 4. [Step by Step Camera Pose Estimation for Visual Tracking and Planar Markers](https://dsp.stackexchange.com/a/2737)
* \anchor pose_ar 5. [Pose from homography estimation](https://team.inria.fr/lagadic/camera_localization/tutorial-pose-dlt-planar-opencv.html)
* \anchor polar_decomposition 6. [Polar Decomposition (in Continuum Mechanics)](http://www.continuummechanics.org/polardecomposition.html)
* \anchor polar_decomposition_svd 7. [A Personal Interview with the Singular Value Decomposition](https://web.stanford.edu/~gavish/documents/SVD_ans_you.pdf), Matan Gavish
* \anchor homography_course 8. [Homography](http://people.scs.carleton.ca/~c_shu/Courses/comp4900d/notes/homography.pdf), Dr. Gerhard Roth
* \anchor answer_blender 9. [3x4 camera matrix from blender camera](https://blender.stackexchange.com/a/38210)
Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

@@ -92,10 +92,10 @@ Source Code
-----------
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/tree/master/samples/cpp/tutorial_code/ml/introduction_to_pca/introduction_to_pca.cpp).
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ml/introduction_to_pca/introduction_to_pca.cpp).
@include cpp/tutorial_code/ml/introduction_to_pca/introduction_to_pca.cpp
@note Another example using PCA for dimensionality reduction while maintaining an amount of variance can be found at [opencv_source_code/samples/cpp/pca.cpp](https://github.com/opencv/tree/master/samples/cpp/pca.cpp)
@note Another example using PCA for dimensionality reduction while maintaining an amount of variance can be found at [opencv_source_code/samples/cpp/pca.cpp](https://github.com/opencv/opencv/tree/master/samples/cpp/pca.cpp)
Explanation
-----------
@@ -87,7 +87,7 @@ Source Code
-----------
You may also find the source code in `samples/cpp/tutorial_code/ml/non_linear_svms` folder of the OpenCV source library or
[download it from here](https://github.com/opencv/tree/master/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp).
[download it from here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp).
@note The following code has been implemented with OpenCV 3.0 classes and functions. An equivalent version of the code
using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/2.4/doc/tutorials/ml/non_linear_svms/non_linear_svms.html#nonlinearsvms)
+1 -1
View File
@@ -78,5 +78,5 @@ there are two flags that should be used to set/get property of the needed genera
flag value is assumed by default if neither of the two possible values of the property is set.
For more information please refer to the example of usage
[intelperc_capture.cpp](https://github.com/opencv/tree/master/samples/cpp/intelperc_capture.cpp)
[intelperc_capture.cpp](https://github.com/opencv/opencv/tree/master/samples/cpp/intelperc_capture.cpp)
in opencv/samples/cpp folder.
+1 -1
View File
@@ -134,5 +134,5 @@ property. The following properties of cameras available through OpenNI interface
- CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_REGISTRATION
For more information please refer to the example of usage
[openni_capture.cpp](https://github.com/opencv/tree/master/samples/cpp/openni_capture.cpp) in
[openni_capture.cpp](https://github.com/opencv/opencv/tree/master/samples/cpp/openni_capture.cpp) in
opencv/samples/cpp folder.
+109 -7
View File
@@ -306,6 +306,12 @@ optimization procedures like calibrateCamera, stereoCalibrate, or solvePnP .
*/
CV_EXPORTS_W void Rodrigues( InputArray src, OutputArray dst, OutputArray jacobian = noArray() );
/** @example pose_from_homography.cpp
An example program about pose estimation from coplanar points
Check @ref tutorial_homography "the corresponding tutorial" for more details
*/
/** @brief Finds a perspective transformation between two planes.
@param srcPoints Coordinates of the points in the original plane, a matrix of the type CV_32FC2
@@ -364,12 +370,6 @@ cannot be estimated, an empty one will be returned.
@sa
getAffineTransform, estimateAffine2D, estimateAffinePartial2D, getPerspectiveTransform, warpPerspective,
perspectiveTransform
@note
- A example on calculating a homography for image matching can be found at
opencv_source_code/samples/cpp/video_homography.cpp
*/
CV_EXPORTS_W Mat findHomography( InputArray srcPoints, InputArray dstPoints,
int method = 0, double ransacReprojThreshold = 3,
@@ -525,6 +525,12 @@ CV_EXPORTS_W void projectPoints( InputArray objectPoints,
OutputArray jacobian = noArray(),
double aspectRatio = 0 );
/** @example homography_from_camera_displacement.cpp
An example program about homography from the camera displacement
Check @ref tutorial_homography "the corresponding tutorial" for more details
*/
/** @brief Finds an object pose from 3D-2D point correspondences.
@param objectPoints Array of object points in the object coordinate space, Nx3 1-channel or
@@ -567,7 +573,97 @@ focal length.
function requires exactly four object and image points.
The function estimates the object pose given a set of object points, their corresponding image
projections, as well as the camera matrix and the distortion coefficients.
projections, as well as the camera matrix and the distortion coefficients, see the figure below
(more precisely, the X-axis of the camera frame is pointing to the right, the Y-axis downward
and the Z-axis forward).
![](pnp.jpg)
Points expressed in the world frame \f$ \bf{X}_w \f$ are projected into the image plane \f$ \left[ u, v \right] \f$
using the perspective projection model \f$ \Pi \f$ and the camera intrinsic parameters matrix \f$ \bf{A} \f$:
\f[
\begin{align*}
\begin{bmatrix}
u \\
v \\
1
\end{bmatrix} &=
\bf{A} \hspace{0.1em} \Pi \hspace{0.2em} ^{c}\bf{M}_w
\begin{bmatrix}
X_{w} \\
Y_{w} \\
Z_{w} \\
1
\end{bmatrix} \\
\begin{bmatrix}
u \\
v \\
1
\end{bmatrix} &=
\begin{bmatrix}
f_x & 0 & c_x \\
0 & f_y & c_y \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0
\end{bmatrix}
\begin{bmatrix}
r_{11} & r_{12} & r_{13} & t_x \\
r_{21} & r_{22} & r_{23} & t_y \\
r_{31} & r_{32} & r_{33} & t_z \\
0 & 0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
X_{w} \\
Y_{w} \\
Z_{w} \\
1
\end{bmatrix}
\end{align*}
\f]
The estimated pose is thus the rotation (`rvec`) and the translation (`tvec`) vectors that allow to transform
a 3D point expressed in the world frame into the camera frame:
\f[
\begin{align*}
\begin{bmatrix}
X_c \\
Y_c \\
Z_c \\
1
\end{bmatrix} &=
\hspace{0.2em} ^{c}\bf{M}_w
\begin{bmatrix}
X_{w} \\
Y_{w} \\
Z_{w} \\
1
\end{bmatrix} \\
\begin{bmatrix}
X_c \\
Y_c \\
Z_c \\
1
\end{bmatrix} &=
\begin{bmatrix}
r_{11} & r_{12} & r_{13} & t_x \\
r_{21} & r_{22} & r_{23} & t_y \\
r_{31} & r_{32} & r_{33} & t_z \\
0 & 0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
X_{w} \\
Y_{w} \\
Z_{w} \\
1
\end{bmatrix}
\end{align*}
\f]
@note
- An example of how to use solvePnP for planar augmented reality can be found at
@@ -1789,6 +1885,12 @@ CV_EXPORTS_W cv::Mat estimateAffinePartial2D(InputArray from, InputArray to, Out
size_t maxIters = 2000, double confidence = 0.99,
size_t refineIters = 10);
/** @example decompose_homography.cpp
An example program with homography decomposition.
Check @ref tutorial_homography "the corresponding tutorial" for more details.
*/
/** @brief Decompose a homography matrix to rotation(s), translation(s) and plane normal(s).
@param H The input homography matrix between two images.
@@ -0,0 +1,22 @@
// 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_LOGGER_DEFINES_HPP
#define OPENCV_LOGGER_DEFINES_HPP
//! @addtogroup core_logging
//! @{
// Supported logging levels and their semantic
#define CV_LOG_LEVEL_SILENT 0 //!< for using in setLogLevel() call
#define CV_LOG_LEVEL_FATAL 1 //!< Fatal (critical) error (unrecoverable internal error)
#define CV_LOG_LEVEL_ERROR 2 //!< Error message
#define CV_LOG_LEVEL_WARN 3 //!< Warning message
#define CV_LOG_LEVEL_INFO 4 //!< Info message
#define CV_LOG_LEVEL_DEBUG 5 //!< Debug message. Disabled in the "Release" build.
#define CV_LOG_LEVEL_VERBOSE 6 //!< Verbose (trace) messages. Requires verbosity level. Disabled in the "Release" build.
//! @}
#endif // OPENCV_LOGGER_DEFINES_HPP
@@ -2,14 +2,14 @@
// 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_LOGGING_HPP
#define OPENCV_LOGGING_HPP
#ifndef OPENCV_LOGGER_HPP
#define OPENCV_LOGGER_HPP
#include <iostream>
#include <sstream>
#include <limits.h> // INT_MAX
// TODO This file contains just interface part with implementation stubs.
#include "logger.defines.hpp"
//! @addtogroup core_logging
// This section describes OpenCV logging utilities.
@@ -20,15 +20,6 @@ namespace cv {
namespace utils {
namespace logging {
// Supported logging levels and their semantic
#define CV_LOG_LEVEL_SILENT 0 //!< for using in setLogVevel() call
#define CV_LOG_LEVEL_FATAL 1 //!< Fatal (critical) error (unrecoverable internal error)
#define CV_LOG_LEVEL_ERROR 2 //!< Error message
#define CV_LOG_LEVEL_WARN 3 //!< Warning message
#define CV_LOG_LEVEL_INFO 4 //!< Info message
#define CV_LOG_LEVEL_DEBUG 5 //!< Debug message. Disabled in the "Release" build.
#define CV_LOG_LEVEL_VERBOSE 6 //!< Verbose (trace) messages. Requires verbosity level. Disabled in the "Release" build.
//! Supported logging levels and their semantic
enum LogLevel {
LOG_LEVEL_SILENT = 0, //!< for using in setLogVevel() call
@@ -43,6 +34,17 @@ enum LogLevel {
#endif
};
/** Set global logging level
@return previous logging level
*/
CV_EXPORTS LogLevel setLogLevel(LogLevel logLevel);
/** Get global logging level */
CV_EXPORTS LogLevel getLogLevel();
namespace internal {
/** Write log message */
CV_EXPORTS void writeLogMessage(LogLevel logLevel, const char* message);
} // namespace
/**
* \def CV_LOG_STRIP_LEVEL
@@ -58,23 +60,23 @@ enum LogLevel {
#endif
#define CV_LOG_FATAL(tag, ...) for(;;) { std::stringstream ss; ss << "[FATAL:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cerr << ss.str() << std::flush; break; }
#define CV_LOG_ERROR(tag, ...) for(;;) { std::stringstream ss; ss << "[ERROR:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cerr << ss.str() << std::flush; break; }
#define CV_LOG_WARNING(tag, ...) for(;;) { std::stringstream ss; ss << "[ WARN:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cout << ss.str() << std::flush; break; }
#define CV_LOG_FATAL(tag, ...) for(;;) { if (cv::utils::logging::getLogLevel() < cv::utils::logging::LOG_LEVEL_FATAL) break; std::stringstream ss; ss << __VA_ARGS__; cv::utils::logging::internal::writeLogMessage(cv::utils::logging::LOG_LEVEL_FATAL, ss.str().c_str()); break; }
#define CV_LOG_ERROR(tag, ...) for(;;) { if (cv::utils::logging::getLogLevel() < cv::utils::logging::LOG_LEVEL_ERROR) break; std::stringstream ss; ss << __VA_ARGS__; cv::utils::logging::internal::writeLogMessage(cv::utils::logging::LOG_LEVEL_ERROR, ss.str().c_str()); break; }
#define CV_LOG_WARNING(tag, ...) for(;;) { if (cv::utils::logging::getLogLevel() < cv::utils::logging::LOG_LEVEL_WARNING) break; std::stringstream ss; ss << __VA_ARGS__; cv::utils::logging::internal::writeLogMessage(cv::utils::logging::LOG_LEVEL_WARNING, ss.str().c_str()); break; }
#if CV_LOG_STRIP_LEVEL <= CV_LOG_LEVEL_INFO
#define CV_LOG_INFO(tag, ...)
#else
#define CV_LOG_INFO(tag, ...) for(;;) { std::stringstream ss; ss << "[ INFO:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cout << ss.str(); break; }
#define CV_LOG_INFO(tag, ...) for(;;) { if (cv::utils::logging::getLogLevel() < cv::utils::logging::LOG_LEVEL_INFO) break; std::stringstream ss; ss << __VA_ARGS__; cv::utils::logging::internal::writeLogMessage(cv::utils::logging::LOG_LEVEL_INFO, ss.str().c_str()); break; }
#endif
#if CV_LOG_STRIP_LEVEL <= CV_LOG_LEVEL_DEBUG
#define CV_LOG_DEBUG(tag, ...)
#else
#define CV_LOG_DEBUG(tag, ...) for(;;) { std::stringstream ss; ss << "[DEBUG:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cout << ss.str(); break; }
#define CV_LOG_DEBUG(tag, ...) for(;;) { if (cv::utils::logging::getLogLevel() < cv::utils::logging::LOG_LEVEL_DEBUG) break; std::stringstream ss; ss << __VA_ARGS__; cv::utils::logging::internal::writeLogMessage(cv::utils::logging::LOG_LEVEL_DEBUG, ss.str().c_str()); break; }
#endif
#if CV_LOG_STRIP_LEVEL <= CV_LOG_LEVEL_VERBOSE
#define CV_LOG_VERBOSE(tag, v, ...)
#else
#define CV_LOG_VERBOSE(tag, v, ...) for(;;) { std::stringstream ss; ss << "[VERB" << v << ":" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cout << ss.str(); break; }
#define CV_LOG_VERBOSE(tag, v, ...) for(;;) { if (cv::utils::logging::getLogLevel() < cv::utils::logging::LOG_LEVEL_VERBOSE) break; std::stringstream ss; ss << "[VERB" << v << ":" << cv::utils::getThreadID() << "] " << __VA_ARGS__; cv::utils::logging::internal::writeLogMessage(cv::utils::logging::LOG_LEVEL_VERBOSE, ss.str().c_str()); break; }
#endif
@@ -82,4 +84,4 @@ enum LogLevel {
//! @}
#endif // OPENCV_LOGGING_HPP
#endif // OPENCV_LOGGER_HPP
@@ -53,7 +53,7 @@
#define CV_VERSION_MAJOR 3
#define CV_VERSION_MINOR 4
#define CV_VERSION_REVISION 0
#define CV_VERSION_STATUS "-rc"
#define CV_VERSION_STATUS ""
#define CVAUX_STR_EXP(__A) #__A
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
+85
View File
@@ -0,0 +1,85 @@
// 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 <opencv2/core/utils/configuration.private.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <sstream>
#include <iostream>
#include <fstream>
namespace cv {
namespace utils {
namespace logging {
static LogLevel parseLogLevelConfiguration()
{
static cv::String param_log_level = utils::getConfigurationParameterString("OPENCV_LOG_LEVEL", "INFO");
if (param_log_level == "DISABLED" || param_log_level == "disabled" ||
param_log_level == "0" || param_log_level == "OFF" || param_log_level == "off")
return LOG_LEVEL_SILENT;
if (param_log_level == "FATAL" || param_log_level == "fatal")
return LOG_LEVEL_FATAL;
if (param_log_level == "ERROR" || param_log_level == "error")
return LOG_LEVEL_ERROR;
if (param_log_level == "WARNING" || param_log_level == "warning" ||
param_log_level == "WARNINGS" || param_log_level == "warnings" ||
param_log_level == "WARN" || param_log_level == "warn")
return LOG_LEVEL_WARNING;
if (param_log_level == "INFO" || param_log_level == "info")
return LOG_LEVEL_INFO;
if (param_log_level == "DEBUG" || param_log_level == "debug")
return LOG_LEVEL_DEBUG;
if (param_log_level == "VERBOSE" || param_log_level == "verbose")
return LOG_LEVEL_VERBOSE;
std::cerr << "ERROR: Unexpected logging level value: " << param_log_level << std::endl;
return LOG_LEVEL_INFO;
}
static LogLevel& getLogLevelVariable()
{
static LogLevel g_logLevel = parseLogLevelConfiguration();
return g_logLevel;
}
LogLevel setLogLevel(LogLevel logLevel)
{
LogLevel old = getLogLevelVariable();
getLogLevelVariable() = logLevel;
return old;
}
LogLevel getLogLevel()
{
return getLogLevelVariable();
}
namespace internal {
void writeLogMessage(LogLevel logLevel, const char* message)
{
const int threadID = cv::utils::getThreadID();
std::ostream* out = (logLevel <= LOG_LEVEL_WARNING) ? &std::cerr : &std::cout;
std::stringstream ss;
switch (logLevel)
{
case LOG_LEVEL_FATAL: ss << "[FATAL:" << threadID << "] " << message << std::endl; break;
case LOG_LEVEL_ERROR: ss << "[ERROR:" << threadID << "] " << message << std::endl; break;
case LOG_LEVEL_WARNING: ss << "[ WARN:" << threadID << "] " << message << std::endl; break;
case LOG_LEVEL_INFO: ss << "[ INFO:" << threadID << "] " << message << std::endl; break;
case LOG_LEVEL_DEBUG: ss << "[DEBUG:" << threadID << "] " << message << std::endl; break;
case LOG_LEVEL_VERBOSE: ss << message << std::endl; break;
default:
return;
}
(*out) << ss.str();
if (logLevel <= LOG_LEVEL_WARNING)
(*out) << std::flush;
}
} // namespace
}}} // namespace
+16 -14
View File
@@ -151,6 +151,8 @@ struct DummyImpl
#define CV_OCL_DBG_CHECK_(expr, check_result) expr; (void)check_result
#define CV_OCL_DBG_CHECK(expr) do { cl_int __cl_result = (expr); CV_OCL_CHECK_RESULT(__cl_result, #expr); } while (0)
static const bool CV_OPENCL_DISABLE_BUFFER_RECT_OPERATIONS = false;
#else // HAVE_OPENCL
#ifndef _DEBUG
@@ -225,6 +227,15 @@ static const bool CV_OPENCL_CACHE_CLEANUP = utils::getConfigurationParameterBool
static const bool CV_OPENCL_VALIDATE_BINARY_PROGRAMS_VALUE = utils::getConfigurationParameterBool("OPENCV_OPENCL_VALIDATE_BINARY_PROGRAMS", false);
#endif
// Option to disable calls clEnqueueReadBufferRect / clEnqueueWriteBufferRect / clEnqueueCopyBufferRect
static const bool CV_OPENCL_DISABLE_BUFFER_RECT_OPERATIONS = utils::getConfigurationParameterBool("OPENCV_OPENCL_DISABLE_BUFFER_RECT_OPERATIONS",
#ifdef __APPLE__
true
#else
false
#endif
);
#endif // HAVE_OPENCL
struct UMat2D
@@ -3660,9 +3671,9 @@ struct Program::Impl
CV_Assert(src_);
CV_Assert(src_->kind_ == ProgramSource::Impl::PROGRAM_SOURCE_CODE);
CV_Assert(handle == NULL);
CV_INSTRUMENT_REGION_OPENCL_COMPILE(cv::format("Build OpenCL program: %s/%s %" PRIx64 " options: %s",
CV_INSTRUMENT_REGION_OPENCL_COMPILE(cv::format("Build OpenCL program: %s/%s %s options: %s",
sourceModule_.c_str(), sourceName_.c_str(),
src.hash(), buildflags.c_str()).c_str());
src_->sourceHash_.c_str(), buildflags.c_str()).c_str());
CV_LOG_VERBOSE(NULL, 0, "Compile... " << sourceModule_.c_str() << "/" << sourceName_.c_str());
@@ -5206,8 +5217,7 @@ public:
CV_OCL_CHECK(clEnqueueReadBuffer(q, (cl_mem)u->handle, CL_TRUE,
srcrawofs, total, alignedPtr.getAlignedPtr(), 0, 0, 0));
}
#ifdef __APPLE__
else
else if (CV_OPENCL_DISABLE_BUFFER_RECT_OPERATIONS)
{
const size_t padding = CV_OPENCL_DATA_PTR_ALIGNMENT;
size_t new_srcrawofs = srcrawofs & ~(padding-1);
@@ -5224,7 +5234,6 @@ public:
for( size_t i = 0; i < new_sz[1]; i++ )
memcpy( (uchar*)dstptr + i*new_dststep[0], ptr + i*new_srcstep[0] + membuf_ofs, new_sz[0]);
}
#else
else
{
AlignedDataPtr2D<false, true> alignedPtr((uchar*)dstptr, new_sz[1], new_sz[0], new_dststep[0], CV_OPENCL_DATA_PTR_ALIGNMENT);
@@ -5236,7 +5245,6 @@ public:
new_dststep[0], 0,
ptr, 0, 0, 0));
}
#endif
}
}
@@ -5343,8 +5351,7 @@ public:
CV_OCL_CHECK(clEnqueueWriteBuffer(q, (cl_mem)u->handle, CL_TRUE,
dstrawofs, total, alignedPtr.getAlignedPtr(), 0, 0, 0));
}
#ifdef __APPLE__
else
else if (CV_OPENCL_DISABLE_BUFFER_RECT_OPERATIONS)
{
const size_t padding = CV_OPENCL_DATA_PTR_ALIGNMENT;
size_t new_dstrawofs = dstrawofs & ~(padding-1);
@@ -5366,7 +5373,6 @@ public:
CV_OCL_CHECK(clEnqueueWriteBuffer(q, (cl_mem)u->handle, CL_TRUE,
new_dstrawofs, total, ptr, 0, 0, 0));
}
#else
else
{
AlignedDataPtr2D<true, false> alignedPtr((uchar*)srcptr, new_sz[1], new_sz[0], new_srcstep[0], CV_OPENCL_DATA_PTR_ALIGNMENT);
@@ -5378,7 +5384,6 @@ public:
new_srcstep[0], 0,
ptr, 0, 0, 0));
}
#endif
}
u->markHostCopyObsolete(true);
#ifdef HAVE_OPENCL_SVM
@@ -5520,8 +5525,7 @@ public:
CV_OCL_CHECK(retval = clEnqueueCopyBuffer(q, (cl_mem)src->handle, (cl_mem)dst->handle,
srcrawofs, dstrawofs, total, 0, 0, 0));
}
#ifdef __APPLE__
else
else if (CV_OPENCL_DISABLE_BUFFER_RECT_OPERATIONS)
{
const size_t padding = CV_OPENCL_DATA_PTR_ALIGNMENT;
size_t new_srcrawofs = srcrawofs & ~(padding-1);
@@ -5554,7 +5558,6 @@ public:
CV_OCL_CHECK(clEnqueueWriteBuffer(q, (cl_mem)dst->handle, CL_TRUE,
new_dstrawofs, dst_total, dstptr, 0, 0, 0));
}
#else
else
{
CV_OCL_CHECK(retval = clEnqueueCopyBufferRect(q, (cl_mem)src->handle, (cl_mem)dst->handle,
@@ -5563,7 +5566,6 @@ public:
new_dststep[0], 0,
0, 0, 0));
}
#endif
}
if (retval == CL_SUCCESS)
{
+1 -1
View File
@@ -44,7 +44,7 @@
#define _ncvtest_hpp_
#if defined _MSC_VER
# pragma warning( disable : 4201 4408 4127 4100)
# pragma warning( disable : 4201 4408 4100)
#endif
#include <string>
-12
View File
@@ -97,15 +97,3 @@ if(BUILD_PERF_TESTS)
endif()
endif()
endif()
# ----------------------------------------------------------------------------
# Torch7 importer of blobs and models, produced by Torch.nn module
# ----------------------------------------------------------------------------
OCV_OPTION(${the_module}_BUILD_TORCH_IMPORTER "Build Torch model importer" ON)
if(${the_module}_BUILD_TORCH_IMPORTER)
message(STATUS "Torch importer has been enabled. To run the tests you have to install Torch "
"('th' executable should be available) "
"and generate testdata using opencv_extra/testdata/dnn/generate_torch_models.py script.")
add_definitions(-DENABLE_TORCH_IMPORTER=1)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4702 /wd4127 /wd4267) #supress warnings in original torch files
endif()
@@ -58,7 +58,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
You can use both API, but factory API is less convinient for native C++ programming and basically designed for use inside importers (see @ref readNetFromCaffe(), @ref readNetFromTorch(), @ref readNetFromTensorflow()).
Bult-in layers partially reproduce functionality of corresponding Caffe and Torch7 layers.
In partuclar, the following layers and Caffe @ref Importer were tested to reproduce <a href="http://caffe.berkeleyvision.org/tutorial/layers.html">Caffe</a> functionality:
In partuclar, 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
@@ -242,6 +242,8 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
// ROIPooling parameters.
Size pooledSize;
float spatialScale;
// PSROIPooling parameters.
int psRoiOutChannels;
static Ptr<PoolingLayer> create(const LayerParams& params);
};
+20 -60
View File
@@ -423,17 +423,8 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* @param outputBlobs contains all output blobs for each layer specified in @p outBlobNames.
* @param outBlobNames names for layers which outputs are needed to get
*/
void forward(std::vector<std::vector<Mat> >& outputBlobs,
const std::vector<String>& outBlobNames);
//TODO:
/** @brief Optimized forward.
* @warning Not implemented yet.
* @details Makes forward only those layers which weren't changed after previous forward().
*/
void forwardOpt(LayerId toLayer);
/** @overload */
void forwardOpt(const std::vector<LayerId> &toLayers);
CV_WRAP_AS(forwardAndRetrieve) void forward(CV_OUT std::vector<std::vector<Mat> >& outputBlobs,
const std::vector<String>& outBlobNames);
/**
* @brief Compile Halide layers.
@@ -609,38 +600,18 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
Ptr<Impl> impl;
};
/**
* @deprecated Deprecated as external interface. Will be for internal needs only.
* @brief Small interface class for loading trained serialized models of different dnn-frameworks. */
class CV_EXPORTS_W Importer : public Algorithm
{
public:
/** @brief Adds loaded layers into the @p net and sets connections between them. */
CV_DEPRECATED CV_WRAP virtual void populateNet(Net net) = 0;
virtual ~Importer();
};
/** @brief Reads a network model stored in <a href="https://pjreddie.com/darknet/">Darknet</a> model files.
* @param cfgFile path to the .cfg file with text description of the network architecture.
* @param darknetModel path to the .weights file with learned network.
* @returns Network object that ready to do forward, throw an exception in failure cases.
* @details This is shortcut consisting from DarknetImporter and Net::populateNet calls.
* @returns Net object.
*/
CV_EXPORTS_W Net readNetFromDarknet(const String &cfgFile, const String &darknetModel = String());
/**
* @deprecated Use @ref readNetFromCaffe instead.
* @brief Creates the importer of <a href="http://caffe.berkeleyvision.org">Caffe</a> framework network.
* @param prototxt path to the .prototxt file with text description of the network architecture.
* @param caffeModel path to the .caffemodel file with learned network.
* @returns Pointer to the created importer, NULL in failure cases.
*/
CV_DEPRECATED CV_EXPORTS_W Ptr<Importer> createCaffeImporter(const String &prototxt, const String &caffeModel = String());
/** @brief Reads a network model stored in Caffe model files.
* @details This is shortcut consisting from createCaffeImporter and Net::populateNet calls.
/** @brief Reads a network model stored in <a href="http://caffe.berkeleyvision.org">Caffe</a> framework's format.
* @param prototxt path to the .prototxt file with text description of the network architecture.
* @param caffeModel path to the .caffemodel file with learned network.
* @returns Net object.
*/
CV_EXPORTS_W Net readNetFromCaffe(const String &prototxt, const String &caffeModel = String());
@@ -651,16 +622,21 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* @param lenProto length of bufferProto
* @param bufferModel buffer containing the content of the .caffemodel file
* @param lenModel length of bufferModel
* @returns Net object.
*/
CV_EXPORTS Net readNetFromCaffe(const char *bufferProto, size_t lenProto,
const char *bufferModel = NULL, size_t lenModel = 0);
/** @brief Reads a network model stored in Tensorflow model file.
* @details This is shortcut consisting from createTensorflowImporter and Net::populateNet calls.
/** @brief Reads a network model stored in <a href="https://www.tensorflow.org/">TensorFlow</a> framework's format.
* @param model path to the .pb file with binary protobuf description of the network architecture
* @param config path to the .pbtxt file that contains text graph definition in protobuf format.
* Resulting Net object is built by text graph using weights from a binary one that
* let us make it more flexible.
* @returns Net object.
*/
CV_EXPORTS_W Net readNetFromTensorflow(const String &model, const String &config = String());
/** @brief Reads a network model stored in Tensorflow model in memory.
/** @brief Reads a network model stored in <a href="https://www.tensorflow.org/">TensorFlow</a> framework's format.
* @details This is an overloaded member function, provided for convenience.
* It differs from the above function only in what argument(s) it accepts.
* @param bufferModel buffer containing the content of the pb file
@@ -671,27 +647,11 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
CV_EXPORTS Net readNetFromTensorflow(const char *bufferModel, size_t lenModel,
const char *bufferConfig = NULL, size_t lenConfig = 0);
/** @brief Reads a network model stored in Torch model file.
* @details This is shortcut consisting from createTorchImporter and Net::populateNet calls.
*/
CV_EXPORTS_W Net readNetFromTorch(const String &model, bool isBinary = true);
/**
* @deprecated Use @ref readNetFromTensorflow instead.
* @brief Creates the importer of <a href="http://www.tensorflow.org">TensorFlow</a> framework network.
* @param model path to the .pb file with binary protobuf description of the network architecture.
* @returns Pointer to the created importer, NULL in failure cases.
*/
CV_DEPRECATED CV_EXPORTS_W Ptr<Importer> createTensorflowImporter(const String &model);
/**
* @deprecated Use @ref readNetFromTorch instead.
* @brief Creates the importer of <a href="http://torch.ch">Torch7</a> framework network.
* @param filename path to the file, dumped from Torch by using torch.save() function.
* @brief Reads a network model stored in <a href="http://torch.ch">Torch7</a> framework's format.
* @param model path to the file, dumped from Torch by using torch.save() function.
* @param isBinary specifies whether the network was serialized in ascii mode or binary.
* @returns Pointer to the created importer, NULL in failure cases.
*
* @warning Torch7 importer is experimental now, you need explicitly set CMake `opencv_dnn_BUILD_TORCH_IMPORTER` flag to compile its.
* @returns Net object.
*
* @note Ascii mode of Torch serializer is more preferable, because binary mode extensively use `long` type of C language,
* which has various bit-length on different systems.
@@ -712,10 +672,10 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
*
* Also some equivalents of these classes from cunn, cudnn, and fbcunn may be successfully imported.
*/
CV_DEPRECATED CV_EXPORTS_W Ptr<Importer> createTorchImporter(const String &filename, bool isBinary = true);
CV_EXPORTS_W Net readNetFromTorch(const String &model, bool isBinary = true);
/** @brief Loads blob which was serialized as torch.Tensor object of Torch7 framework.
* @warning This function has the same limitations as createTorchImporter().
* @warning This function has the same limitations as readNetFromTorch().
*/
CV_EXPORTS_W Mat readTorchBlob(const String &filename, bool isBinary = true);
/** @brief Creates 4-dimensional blob from image. Optionally resizes and crops @p image from center,
File diff suppressed because it is too large Load Diff
+343 -49
View File
@@ -80,6 +80,7 @@ class NonMaximumSuppressionParameter;
class NormalizeBBoxParameter;
class NormalizedBBox;
class PReLUParameter;
class PSROIPoolingParameter;
class ParamSpec;
class ParameterParameter;
class PermuteParameter;
@@ -1781,6 +1782,13 @@ class DetectionOutputParameter : public ::google::protobuf::Message /* @@protoc_
float confidence_threshold() const;
void set_confidence_threshold(float value);
// optional bool normalized_bbox = 10 [default = true];
bool has_normalized_bbox() const;
void clear_normalized_bbox();
static const int kNormalizedBboxFieldNumber = 10;
bool normalized_bbox() const;
void set_normalized_bbox(bool value);
// @@protoc_insertion_point(class_scope:opencv_caffe.DetectionOutputParameter)
private:
inline void set_has_num_classes();
@@ -1801,6 +1809,8 @@ class DetectionOutputParameter : public ::google::protobuf::Message /* @@protoc_
inline void clear_has_keep_top_k();
inline void set_has_confidence_threshold();
inline void clear_has_confidence_threshold();
inline void set_has_normalized_bbox();
inline void clear_has_normalized_bbox();
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
::google::protobuf::internal::HasBits<1> _has_bits_;
@@ -1812,8 +1822,9 @@ class DetectionOutputParameter : public ::google::protobuf::Message /* @@protoc_
bool variance_encoded_in_target_;
float confidence_threshold_;
::google::protobuf::int32 keep_top_k_;
bool share_location_;
int code_type_;
bool share_location_;
bool normalized_bbox_;
friend void protobuf_InitDefaults_opencv_2dcaffe_2eproto_impl();
friend void protobuf_AddDesc_opencv_2dcaffe_2eproto_impl();
friend void protobuf_AssignDesc_opencv_2dcaffe_2eproto();
@@ -4148,6 +4159,15 @@ class LayerParameter : public ::google::protobuf::Message /* @@protoc_insertion_
::opencv_caffe::ProposalParameter* release_proposal_param();
void set_allocated_proposal_param(::opencv_caffe::ProposalParameter* proposal_param);
// optional .opencv_caffe.PSROIPoolingParameter psroi_pooling_param = 10001;
bool has_psroi_pooling_param() const;
void clear_psroi_pooling_param();
static const int kPsroiPoolingParamFieldNumber = 10001;
const ::opencv_caffe::PSROIPoolingParameter& psroi_pooling_param() const;
::opencv_caffe::PSROIPoolingParameter* mutable_psroi_pooling_param();
::opencv_caffe::PSROIPoolingParameter* release_psroi_pooling_param();
void set_allocated_psroi_pooling_param(::opencv_caffe::PSROIPoolingParameter* psroi_pooling_param);
// optional .opencv_caffe.PythonParameter python_param = 130;
bool has_python_param() const;
void clear_python_param();
@@ -4367,6 +4387,8 @@ class LayerParameter : public ::google::protobuf::Message /* @@protoc_insertion_
inline void clear_has_prior_box_param();
inline void set_has_proposal_param();
inline void clear_has_proposal_param();
inline void set_has_psroi_pooling_param();
inline void clear_has_psroi_pooling_param();
inline void set_has_python_param();
inline void clear_has_python_param();
inline void set_has_recurrent_param();
@@ -4399,7 +4421,8 @@ class LayerParameter : public ::google::protobuf::Message /* @@protoc_insertion_
inline void clear_has_window_data_param();
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
::google::protobuf::internal::HasBits<2> _has_bits_;
::google::protobuf::internal::HasBits<3> _has_bits_;
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::std::string> bottom_;
::google::protobuf::RepeatedPtrField< ::std::string> top_;
::google::protobuf::RepeatedField< float > loss_weight_;
@@ -4448,6 +4471,7 @@ class LayerParameter : public ::google::protobuf::Message /* @@protoc_insertion_
::opencv_caffe::PReLUParameter* prelu_param_;
::opencv_caffe::PriorBoxParameter* prior_box_param_;
::opencv_caffe::ProposalParameter* proposal_param_;
::opencv_caffe::PSROIPoolingParameter* psroi_pooling_param_;
::opencv_caffe::PythonParameter* python_param_;
::opencv_caffe::RecurrentParameter* recurrent_param_;
::opencv_caffe::ReductionParameter* reduction_param_;
@@ -4464,7 +4488,6 @@ class LayerParameter : public ::google::protobuf::Message /* @@protoc_insertion_
::opencv_caffe::TileParameter* tile_param_;
::opencv_caffe::WindowDataParameter* window_data_param_;
int phase_;
mutable int _cached_size_;
friend void protobuf_InitDefaults_opencv_2dcaffe_2eproto_impl();
friend void protobuf_AddDesc_opencv_2dcaffe_2eproto_impl();
friend void protobuf_AssignDesc_opencv_2dcaffe_2eproto();
@@ -13111,6 +13134,127 @@ class ProposalParameter : public ::google::protobuf::Message /* @@protoc_inserti
};
extern ::google::protobuf::internal::ExplicitlyConstructed<ProposalParameter> ProposalParameter_default_instance_;
// -------------------------------------------------------------------
class PSROIPoolingParameter : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:opencv_caffe.PSROIPoolingParameter) */ {
public:
PSROIPoolingParameter();
virtual ~PSROIPoolingParameter();
PSROIPoolingParameter(const PSROIPoolingParameter& from);
inline PSROIPoolingParameter& operator=(const PSROIPoolingParameter& from) {
CopyFrom(from);
return *this;
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _internal_metadata_.mutable_unknown_fields();
}
static const ::google::protobuf::Descriptor* descriptor();
static const PSROIPoolingParameter& default_instance();
static const PSROIPoolingParameter* internal_default_instance();
void Swap(PSROIPoolingParameter* other);
// implements Message ----------------------------------------------
inline PSROIPoolingParameter* New() const { return New(NULL); }
PSROIPoolingParameter* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const PSROIPoolingParameter& from);
void MergeFrom(const PSROIPoolingParameter& from);
void Clear();
bool IsInitialized() const;
size_t ByteSizeLong() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
return InternalSerializeWithCachedSizesToArray(false, output);
}
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
void InternalSwap(PSROIPoolingParameter* other);
void UnsafeMergeFrom(const PSROIPoolingParameter& from);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
}
inline void* MaybeArenaPtr() const {
return _internal_metadata_.raw_arena_ptr();
}
public:
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// required float spatial_scale = 1;
bool has_spatial_scale() const;
void clear_spatial_scale();
static const int kSpatialScaleFieldNumber = 1;
float spatial_scale() const;
void set_spatial_scale(float value);
// required int32 output_dim = 2;
bool has_output_dim() const;
void clear_output_dim();
static const int kOutputDimFieldNumber = 2;
::google::protobuf::int32 output_dim() const;
void set_output_dim(::google::protobuf::int32 value);
// required int32 group_size = 3;
bool has_group_size() const;
void clear_group_size();
static const int kGroupSizeFieldNumber = 3;
::google::protobuf::int32 group_size() const;
void set_group_size(::google::protobuf::int32 value);
// @@protoc_insertion_point(class_scope:opencv_caffe.PSROIPoolingParameter)
private:
inline void set_has_spatial_scale();
inline void clear_has_spatial_scale();
inline void set_has_output_dim();
inline void clear_has_output_dim();
inline void set_has_group_size();
inline void clear_has_group_size();
// helper for ByteSizeLong()
size_t RequiredFieldsByteSizeFallback() const;
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
::google::protobuf::internal::HasBits<1> _has_bits_;
mutable int _cached_size_;
float spatial_scale_;
::google::protobuf::int32 output_dim_;
::google::protobuf::int32 group_size_;
friend void protobuf_InitDefaults_opencv_2dcaffe_2eproto_impl();
friend void protobuf_AddDesc_opencv_2dcaffe_2eproto_impl();
friend void protobuf_AssignDesc_opencv_2dcaffe_2eproto();
friend void protobuf_ShutdownFile_opencv_2dcaffe_2eproto();
void InitAsDefaultInstance();
};
extern ::google::protobuf::internal::ExplicitlyConstructed<PSROIPoolingParameter> PSROIPoolingParameter_default_instance_;
// ===================================================================
@@ -14411,6 +14555,30 @@ inline void DetectionOutputParameter::set_confidence_threshold(float value) {
// @@protoc_insertion_point(field_set:opencv_caffe.DetectionOutputParameter.confidence_threshold)
}
// optional bool normalized_bbox = 10 [default = true];
inline bool DetectionOutputParameter::has_normalized_bbox() const {
return (_has_bits_[0] & 0x00000200u) != 0;
}
inline void DetectionOutputParameter::set_has_normalized_bbox() {
_has_bits_[0] |= 0x00000200u;
}
inline void DetectionOutputParameter::clear_has_normalized_bbox() {
_has_bits_[0] &= ~0x00000200u;
}
inline void DetectionOutputParameter::clear_normalized_bbox() {
normalized_bbox_ = true;
clear_has_normalized_bbox();
}
inline bool DetectionOutputParameter::normalized_bbox() const {
// @@protoc_insertion_point(field_get:opencv_caffe.DetectionOutputParameter.normalized_bbox)
return normalized_bbox_;
}
inline void DetectionOutputParameter::set_normalized_bbox(bool value) {
set_has_normalized_bbox();
normalized_bbox_ = value;
// @@protoc_insertion_point(field_set:opencv_caffe.DetectionOutputParameter.normalized_bbox)
}
inline const DetectionOutputParameter* DetectionOutputParameter::internal_default_instance() {
return &DetectionOutputParameter_default_instance_.get();
}
@@ -19163,16 +19331,61 @@ inline void LayerParameter::set_allocated_proposal_param(::opencv_caffe::Proposa
// @@protoc_insertion_point(field_set_allocated:opencv_caffe.LayerParameter.proposal_param)
}
// optional .opencv_caffe.PythonParameter python_param = 130;
inline bool LayerParameter::has_python_param() const {
// optional .opencv_caffe.PSROIPoolingParameter psroi_pooling_param = 10001;
inline bool LayerParameter::has_psroi_pooling_param() const {
return (_has_bits_[1] & 0x00020000u) != 0;
}
inline void LayerParameter::set_has_python_param() {
inline void LayerParameter::set_has_psroi_pooling_param() {
_has_bits_[1] |= 0x00020000u;
}
inline void LayerParameter::clear_has_python_param() {
inline void LayerParameter::clear_has_psroi_pooling_param() {
_has_bits_[1] &= ~0x00020000u;
}
inline void LayerParameter::clear_psroi_pooling_param() {
if (psroi_pooling_param_ != NULL) psroi_pooling_param_->::opencv_caffe::PSROIPoolingParameter::Clear();
clear_has_psroi_pooling_param();
}
inline const ::opencv_caffe::PSROIPoolingParameter& LayerParameter::psroi_pooling_param() const {
// @@protoc_insertion_point(field_get:opencv_caffe.LayerParameter.psroi_pooling_param)
return psroi_pooling_param_ != NULL ? *psroi_pooling_param_
: *::opencv_caffe::PSROIPoolingParameter::internal_default_instance();
}
inline ::opencv_caffe::PSROIPoolingParameter* LayerParameter::mutable_psroi_pooling_param() {
set_has_psroi_pooling_param();
if (psroi_pooling_param_ == NULL) {
psroi_pooling_param_ = new ::opencv_caffe::PSROIPoolingParameter;
}
// @@protoc_insertion_point(field_mutable:opencv_caffe.LayerParameter.psroi_pooling_param)
return psroi_pooling_param_;
}
inline ::opencv_caffe::PSROIPoolingParameter* LayerParameter::release_psroi_pooling_param() {
// @@protoc_insertion_point(field_release:opencv_caffe.LayerParameter.psroi_pooling_param)
clear_has_psroi_pooling_param();
::opencv_caffe::PSROIPoolingParameter* temp = psroi_pooling_param_;
psroi_pooling_param_ = NULL;
return temp;
}
inline void LayerParameter::set_allocated_psroi_pooling_param(::opencv_caffe::PSROIPoolingParameter* psroi_pooling_param) {
delete psroi_pooling_param_;
psroi_pooling_param_ = psroi_pooling_param;
if (psroi_pooling_param) {
set_has_psroi_pooling_param();
} else {
clear_has_psroi_pooling_param();
}
// @@protoc_insertion_point(field_set_allocated:opencv_caffe.LayerParameter.psroi_pooling_param)
}
// optional .opencv_caffe.PythonParameter python_param = 130;
inline bool LayerParameter::has_python_param() const {
return (_has_bits_[1] & 0x00040000u) != 0;
}
inline void LayerParameter::set_has_python_param() {
_has_bits_[1] |= 0x00040000u;
}
inline void LayerParameter::clear_has_python_param() {
_has_bits_[1] &= ~0x00040000u;
}
inline void LayerParameter::clear_python_param() {
if (python_param_ != NULL) python_param_->::opencv_caffe::PythonParameter::Clear();
clear_has_python_param();
@@ -19210,13 +19423,13 @@ inline void LayerParameter::set_allocated_python_param(::opencv_caffe::PythonPar
// optional .opencv_caffe.RecurrentParameter recurrent_param = 146;
inline bool LayerParameter::has_recurrent_param() const {
return (_has_bits_[1] & 0x00040000u) != 0;
return (_has_bits_[1] & 0x00080000u) != 0;
}
inline void LayerParameter::set_has_recurrent_param() {
_has_bits_[1] |= 0x00040000u;
_has_bits_[1] |= 0x00080000u;
}
inline void LayerParameter::clear_has_recurrent_param() {
_has_bits_[1] &= ~0x00040000u;
_has_bits_[1] &= ~0x00080000u;
}
inline void LayerParameter::clear_recurrent_param() {
if (recurrent_param_ != NULL) recurrent_param_->::opencv_caffe::RecurrentParameter::Clear();
@@ -19255,13 +19468,13 @@ inline void LayerParameter::set_allocated_recurrent_param(::opencv_caffe::Recurr
// optional .opencv_caffe.ReductionParameter reduction_param = 136;
inline bool LayerParameter::has_reduction_param() const {
return (_has_bits_[1] & 0x00080000u) != 0;
return (_has_bits_[1] & 0x00100000u) != 0;
}
inline void LayerParameter::set_has_reduction_param() {
_has_bits_[1] |= 0x00080000u;
_has_bits_[1] |= 0x00100000u;
}
inline void LayerParameter::clear_has_reduction_param() {
_has_bits_[1] &= ~0x00080000u;
_has_bits_[1] &= ~0x00100000u;
}
inline void LayerParameter::clear_reduction_param() {
if (reduction_param_ != NULL) reduction_param_->::opencv_caffe::ReductionParameter::Clear();
@@ -19300,13 +19513,13 @@ inline void LayerParameter::set_allocated_reduction_param(::opencv_caffe::Reduct
// optional .opencv_caffe.ReLUParameter relu_param = 123;
inline bool LayerParameter::has_relu_param() const {
return (_has_bits_[1] & 0x00100000u) != 0;
return (_has_bits_[1] & 0x00200000u) != 0;
}
inline void LayerParameter::set_has_relu_param() {
_has_bits_[1] |= 0x00100000u;
_has_bits_[1] |= 0x00200000u;
}
inline void LayerParameter::clear_has_relu_param() {
_has_bits_[1] &= ~0x00100000u;
_has_bits_[1] &= ~0x00200000u;
}
inline void LayerParameter::clear_relu_param() {
if (relu_param_ != NULL) relu_param_->::opencv_caffe::ReLUParameter::Clear();
@@ -19345,13 +19558,13 @@ inline void LayerParameter::set_allocated_relu_param(::opencv_caffe::ReLUParamet
// optional .opencv_caffe.ReshapeParameter reshape_param = 133;
inline bool LayerParameter::has_reshape_param() const {
return (_has_bits_[1] & 0x00200000u) != 0;
return (_has_bits_[1] & 0x00400000u) != 0;
}
inline void LayerParameter::set_has_reshape_param() {
_has_bits_[1] |= 0x00200000u;
_has_bits_[1] |= 0x00400000u;
}
inline void LayerParameter::clear_has_reshape_param() {
_has_bits_[1] &= ~0x00200000u;
_has_bits_[1] &= ~0x00400000u;
}
inline void LayerParameter::clear_reshape_param() {
if (reshape_param_ != NULL) reshape_param_->::opencv_caffe::ReshapeParameter::Clear();
@@ -19390,13 +19603,13 @@ inline void LayerParameter::set_allocated_reshape_param(::opencv_caffe::ReshapeP
// optional .opencv_caffe.ROIPoolingParameter roi_pooling_param = 8266711;
inline bool LayerParameter::has_roi_pooling_param() const {
return (_has_bits_[1] & 0x00400000u) != 0;
return (_has_bits_[1] & 0x00800000u) != 0;
}
inline void LayerParameter::set_has_roi_pooling_param() {
_has_bits_[1] |= 0x00400000u;
_has_bits_[1] |= 0x00800000u;
}
inline void LayerParameter::clear_has_roi_pooling_param() {
_has_bits_[1] &= ~0x00400000u;
_has_bits_[1] &= ~0x00800000u;
}
inline void LayerParameter::clear_roi_pooling_param() {
if (roi_pooling_param_ != NULL) roi_pooling_param_->::opencv_caffe::ROIPoolingParameter::Clear();
@@ -19435,13 +19648,13 @@ inline void LayerParameter::set_allocated_roi_pooling_param(::opencv_caffe::ROIP
// optional .opencv_caffe.ScaleParameter scale_param = 142;
inline bool LayerParameter::has_scale_param() const {
return (_has_bits_[1] & 0x00800000u) != 0;
return (_has_bits_[1] & 0x01000000u) != 0;
}
inline void LayerParameter::set_has_scale_param() {
_has_bits_[1] |= 0x00800000u;
_has_bits_[1] |= 0x01000000u;
}
inline void LayerParameter::clear_has_scale_param() {
_has_bits_[1] &= ~0x00800000u;
_has_bits_[1] &= ~0x01000000u;
}
inline void LayerParameter::clear_scale_param() {
if (scale_param_ != NULL) scale_param_->::opencv_caffe::ScaleParameter::Clear();
@@ -19480,13 +19693,13 @@ inline void LayerParameter::set_allocated_scale_param(::opencv_caffe::ScaleParam
// optional .opencv_caffe.SigmoidParameter sigmoid_param = 124;
inline bool LayerParameter::has_sigmoid_param() const {
return (_has_bits_[1] & 0x01000000u) != 0;
return (_has_bits_[1] & 0x02000000u) != 0;
}
inline void LayerParameter::set_has_sigmoid_param() {
_has_bits_[1] |= 0x01000000u;
_has_bits_[1] |= 0x02000000u;
}
inline void LayerParameter::clear_has_sigmoid_param() {
_has_bits_[1] &= ~0x01000000u;
_has_bits_[1] &= ~0x02000000u;
}
inline void LayerParameter::clear_sigmoid_param() {
if (sigmoid_param_ != NULL) sigmoid_param_->::opencv_caffe::SigmoidParameter::Clear();
@@ -19525,13 +19738,13 @@ inline void LayerParameter::set_allocated_sigmoid_param(::opencv_caffe::SigmoidP
// optional .opencv_caffe.SoftmaxParameter softmax_param = 125;
inline bool LayerParameter::has_softmax_param() const {
return (_has_bits_[1] & 0x02000000u) != 0;
return (_has_bits_[1] & 0x04000000u) != 0;
}
inline void LayerParameter::set_has_softmax_param() {
_has_bits_[1] |= 0x02000000u;
_has_bits_[1] |= 0x04000000u;
}
inline void LayerParameter::clear_has_softmax_param() {
_has_bits_[1] &= ~0x02000000u;
_has_bits_[1] &= ~0x04000000u;
}
inline void LayerParameter::clear_softmax_param() {
if (softmax_param_ != NULL) softmax_param_->::opencv_caffe::SoftmaxParameter::Clear();
@@ -19570,13 +19783,13 @@ inline void LayerParameter::set_allocated_softmax_param(::opencv_caffe::SoftmaxP
// optional .opencv_caffe.SPPParameter spp_param = 132;
inline bool LayerParameter::has_spp_param() const {
return (_has_bits_[1] & 0x04000000u) != 0;
return (_has_bits_[1] & 0x08000000u) != 0;
}
inline void LayerParameter::set_has_spp_param() {
_has_bits_[1] |= 0x04000000u;
_has_bits_[1] |= 0x08000000u;
}
inline void LayerParameter::clear_has_spp_param() {
_has_bits_[1] &= ~0x04000000u;
_has_bits_[1] &= ~0x08000000u;
}
inline void LayerParameter::clear_spp_param() {
if (spp_param_ != NULL) spp_param_->::opencv_caffe::SPPParameter::Clear();
@@ -19615,13 +19828,13 @@ inline void LayerParameter::set_allocated_spp_param(::opencv_caffe::SPPParameter
// optional .opencv_caffe.SliceParameter slice_param = 126;
inline bool LayerParameter::has_slice_param() const {
return (_has_bits_[1] & 0x08000000u) != 0;
return (_has_bits_[1] & 0x10000000u) != 0;
}
inline void LayerParameter::set_has_slice_param() {
_has_bits_[1] |= 0x08000000u;
_has_bits_[1] |= 0x10000000u;
}
inline void LayerParameter::clear_has_slice_param() {
_has_bits_[1] &= ~0x08000000u;
_has_bits_[1] &= ~0x10000000u;
}
inline void LayerParameter::clear_slice_param() {
if (slice_param_ != NULL) slice_param_->::opencv_caffe::SliceParameter::Clear();
@@ -19660,13 +19873,13 @@ inline void LayerParameter::set_allocated_slice_param(::opencv_caffe::SliceParam
// optional .opencv_caffe.TanHParameter tanh_param = 127;
inline bool LayerParameter::has_tanh_param() const {
return (_has_bits_[1] & 0x10000000u) != 0;
return (_has_bits_[1] & 0x20000000u) != 0;
}
inline void LayerParameter::set_has_tanh_param() {
_has_bits_[1] |= 0x10000000u;
_has_bits_[1] |= 0x20000000u;
}
inline void LayerParameter::clear_has_tanh_param() {
_has_bits_[1] &= ~0x10000000u;
_has_bits_[1] &= ~0x20000000u;
}
inline void LayerParameter::clear_tanh_param() {
if (tanh_param_ != NULL) tanh_param_->::opencv_caffe::TanHParameter::Clear();
@@ -19705,13 +19918,13 @@ inline void LayerParameter::set_allocated_tanh_param(::opencv_caffe::TanHParamet
// optional .opencv_caffe.ThresholdParameter threshold_param = 128;
inline bool LayerParameter::has_threshold_param() const {
return (_has_bits_[1] & 0x20000000u) != 0;
return (_has_bits_[1] & 0x40000000u) != 0;
}
inline void LayerParameter::set_has_threshold_param() {
_has_bits_[1] |= 0x20000000u;
_has_bits_[1] |= 0x40000000u;
}
inline void LayerParameter::clear_has_threshold_param() {
_has_bits_[1] &= ~0x20000000u;
_has_bits_[1] &= ~0x40000000u;
}
inline void LayerParameter::clear_threshold_param() {
if (threshold_param_ != NULL) threshold_param_->::opencv_caffe::ThresholdParameter::Clear();
@@ -19750,13 +19963,13 @@ inline void LayerParameter::set_allocated_threshold_param(::opencv_caffe::Thresh
// optional .opencv_caffe.TileParameter tile_param = 138;
inline bool LayerParameter::has_tile_param() const {
return (_has_bits_[1] & 0x40000000u) != 0;
return (_has_bits_[1] & 0x80000000u) != 0;
}
inline void LayerParameter::set_has_tile_param() {
_has_bits_[1] |= 0x40000000u;
_has_bits_[1] |= 0x80000000u;
}
inline void LayerParameter::clear_has_tile_param() {
_has_bits_[1] &= ~0x40000000u;
_has_bits_[1] &= ~0x80000000u;
}
inline void LayerParameter::clear_tile_param() {
if (tile_param_ != NULL) tile_param_->::opencv_caffe::TileParameter::Clear();
@@ -19795,13 +20008,13 @@ inline void LayerParameter::set_allocated_tile_param(::opencv_caffe::TileParamet
// optional .opencv_caffe.WindowDataParameter window_data_param = 129;
inline bool LayerParameter::has_window_data_param() const {
return (_has_bits_[1] & 0x80000000u) != 0;
return (_has_bits_[2] & 0x00000001u) != 0;
}
inline void LayerParameter::set_has_window_data_param() {
_has_bits_[1] |= 0x80000000u;
_has_bits_[2] |= 0x00000001u;
}
inline void LayerParameter::clear_has_window_data_param() {
_has_bits_[1] &= ~0x80000000u;
_has_bits_[2] &= ~0x00000001u;
}
inline void LayerParameter::clear_window_data_param() {
if (window_data_param_ != NULL) window_data_param_->::opencv_caffe::WindowDataParameter::Clear();
@@ -29392,6 +29605,85 @@ inline void ProposalParameter::set_nms_thresh(float value) {
inline const ProposalParameter* ProposalParameter::internal_default_instance() {
return &ProposalParameter_default_instance_.get();
}
// -------------------------------------------------------------------
// PSROIPoolingParameter
// required float spatial_scale = 1;
inline bool PSROIPoolingParameter::has_spatial_scale() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
inline void PSROIPoolingParameter::set_has_spatial_scale() {
_has_bits_[0] |= 0x00000001u;
}
inline void PSROIPoolingParameter::clear_has_spatial_scale() {
_has_bits_[0] &= ~0x00000001u;
}
inline void PSROIPoolingParameter::clear_spatial_scale() {
spatial_scale_ = 0;
clear_has_spatial_scale();
}
inline float PSROIPoolingParameter::spatial_scale() const {
// @@protoc_insertion_point(field_get:opencv_caffe.PSROIPoolingParameter.spatial_scale)
return spatial_scale_;
}
inline void PSROIPoolingParameter::set_spatial_scale(float value) {
set_has_spatial_scale();
spatial_scale_ = value;
// @@protoc_insertion_point(field_set:opencv_caffe.PSROIPoolingParameter.spatial_scale)
}
// required int32 output_dim = 2;
inline bool PSROIPoolingParameter::has_output_dim() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
inline void PSROIPoolingParameter::set_has_output_dim() {
_has_bits_[0] |= 0x00000002u;
}
inline void PSROIPoolingParameter::clear_has_output_dim() {
_has_bits_[0] &= ~0x00000002u;
}
inline void PSROIPoolingParameter::clear_output_dim() {
output_dim_ = 0;
clear_has_output_dim();
}
inline ::google::protobuf::int32 PSROIPoolingParameter::output_dim() const {
// @@protoc_insertion_point(field_get:opencv_caffe.PSROIPoolingParameter.output_dim)
return output_dim_;
}
inline void PSROIPoolingParameter::set_output_dim(::google::protobuf::int32 value) {
set_has_output_dim();
output_dim_ = value;
// @@protoc_insertion_point(field_set:opencv_caffe.PSROIPoolingParameter.output_dim)
}
// required int32 group_size = 3;
inline bool PSROIPoolingParameter::has_group_size() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
inline void PSROIPoolingParameter::set_has_group_size() {
_has_bits_[0] |= 0x00000004u;
}
inline void PSROIPoolingParameter::clear_has_group_size() {
_has_bits_[0] &= ~0x00000004u;
}
inline void PSROIPoolingParameter::clear_group_size() {
group_size_ = 0;
clear_has_group_size();
}
inline ::google::protobuf::int32 PSROIPoolingParameter::group_size() const {
// @@protoc_insertion_point(field_get:opencv_caffe.PSROIPoolingParameter.group_size)
return group_size_;
}
inline void PSROIPoolingParameter::set_group_size(::google::protobuf::int32 value) {
set_has_group_size();
group_size_ = value;
// @@protoc_insertion_point(field_set:opencv_caffe.PSROIPoolingParameter.group_size)
}
inline const PSROIPoolingParameter* PSROIPoolingParameter::internal_default_instance() {
return &PSROIPoolingParameter_default_instance_.get();
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
@@ -29531,6 +29823,8 @@ inline const ProposalParameter* ProposalParameter::internal_default_instance() {
// -------------------------------------------------------------------
// -------------------------------------------------------------------
// @@protoc_insertion_point(namespace_scope)
+16 -8
View File
@@ -68,14 +68,6 @@ static caffe::Net<float>* initNet(std::string proto, std::string weights)
return net;
}
PERF_TEST(GoogLeNet_caffe, CaffePerfTest)
{
caffe::Net<float>* net = initNet("dnn/bvlc_googlenet.prototxt",
"dnn/bvlc_googlenet.caffemodel");
TEST_CYCLE() net->Forward();
SANITY_CHECK_NOTHING();
}
PERF_TEST(AlexNet_caffe, CaffePerfTest)
{
caffe::Net<float>* net = initNet("dnn/bvlc_alexnet.prototxt",
@@ -84,6 +76,14 @@ PERF_TEST(AlexNet_caffe, CaffePerfTest)
SANITY_CHECK_NOTHING();
}
PERF_TEST(GoogLeNet_caffe, CaffePerfTest)
{
caffe::Net<float>* net = initNet("dnn/bvlc_googlenet.prototxt",
"dnn/bvlc_googlenet.caffemodel");
TEST_CYCLE() net->Forward();
SANITY_CHECK_NOTHING();
}
PERF_TEST(ResNet50_caffe, CaffePerfTest)
{
caffe::Net<float>* net = initNet("dnn/ResNet-50-deploy.prototxt",
@@ -100,6 +100,14 @@ PERF_TEST(SqueezeNet_v1_1_caffe, CaffePerfTest)
SANITY_CHECK_NOTHING();
}
PERF_TEST(MobileNet_SSD, CaffePerfTest)
{
caffe::Net<float>* net = initNet("dnn/MobileNetSSD_deploy.prototxt",
"dnn/MobileNetSSD_deploy.caffemodel");
TEST_CYCLE() net->Forward();
SANITY_CHECK_NOTHING();
}
} // namespace cvtest
#endif // HAVE_CAFFE
+19 -1
View File
@@ -70,7 +70,7 @@ public:
}
else if (framework == "tensorflow")
{
net = cv::dnn::readNetFromTensorflow(weights);
net = cv::dnn::readNetFromTensorflow(weights, proto);
}
else
CV_Error(Error::StsNotImplemented, "Unknown framework " + framework);
@@ -148,6 +148,24 @@ PERF_TEST_P_(DNNTestNetwork, SSD)
Mat(cv::Size(300, 300), CV_32FC3), "detection_out", "caffe");
}
PERF_TEST_P_(DNNTestNetwork, OpenFace)
{
processNet("dnn/openface_nn4.small2.v1.t7", "", "",
Mat(cv::Size(96, 96), CV_32FC3), "", "torch");
}
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_Caffe)
{
processNet("dnn/MobileNetSSD_deploy.caffemodel", "dnn/MobileNetSSD_deploy.prototxt", "",
Mat(cv::Size(300, 300), CV_32FC3), "detection_out", "caffe");
}
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_TensorFlow)
{
processNet("dnn/ssd_mobilenet_v1_coco.pb", "ssd_mobilenet_v1_coco.pbtxt", "",
Mat(cv::Size(300, 300), CV_32FC3), "", "tensorflow");
}
INSTANTIATE_TEST_CASE_P(/*nothing*/, DNNTestNetwork,
testing::Combine(
::testing::Values(TEST_DNN_BACKEND),
+1 -12
View File
@@ -75,7 +75,7 @@ static cv::String toString(const T &v)
return ss.str();
}
class CaffeImporter : public Importer
class CaffeImporter
{
caffe::NetParameter net;
caffe::NetParameter netBinary;
@@ -390,21 +390,10 @@ public:
dstNet.connect(addedBlobs[idx].layerId, addedBlobs[idx].outNum, layerId, inNum);
}
~CaffeImporter()
{
}
};
}
Ptr<Importer> createCaffeImporter(const String &prototxt, const String &caffeModel)
{
return Ptr<Importer>(new CaffeImporter(prototxt.c_str(), caffeModel.c_str()));
}
Net readNetFromCaffe(const String &prototxt, const String &caffeModel /*= String()*/)
{
CaffeImporter caffeImporter(prototxt.c_str(), caffeModel.c_str());
+10
View File
@@ -179,6 +179,8 @@ message DetectionOutputParameter {
// Only consider detections whose confidences are larger than a threshold.
// If not provided, consider all boxes.
optional float confidence_threshold = 9;
// If prior boxes are normalized to [0, 1] or not.
optional bool normalized_bbox = 10 [default = true];
}
message Datum {
@@ -548,6 +550,7 @@ message LayerParameter {
optional PReLUParameter prelu_param = 131;
optional PriorBoxParameter prior_box_param = 150;
optional ProposalParameter proposal_param = 201;
optional PSROIPoolingParameter psroi_pooling_param = 10001; // https://github.com/daijifeng001/caffe-rfcn
optional PythonParameter python_param = 130;
optional RecurrentParameter recurrent_param = 146;
optional ReductionParameter reduction_param = 136;
@@ -1633,3 +1636,10 @@ message ProposalParameter {
optional uint32 post_nms_topn = 7 [default = 300];
optional float nms_thresh = 8 [default = 0.7];
}
// origin: https://github.com/daijifeng001/caffe-rfcn
message PSROIPoolingParameter {
required float spatial_scale = 1;
required int32 output_dim = 2; // output channel number
required int32 group_size = 3; // equal to pooled_size
}
+1 -7
View File
@@ -58,7 +58,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
namespace
{
class DarknetImporter : public Importer
class DarknetImporter
{
darknet::NetParameter net;
@@ -173,12 +173,6 @@ public:
dstNet.connect(addedBlobs[idx].layerId, addedBlobs[idx].outNum, layerId, inNum);
}
~DarknetImporter()
{
}
};
}
+1 -1
View File
@@ -482,7 +482,7 @@ namespace cv {
}
else if (layer_type == "region")
{
float thresh = 0.001; // in the original Darknet is equal to the detection threshold set by the user
float thresh = getParam<float>(layer_params, "thresh", 0.001);
int coords = getParam<int>(layer_params, "coords", 4);
int classes = getParam<int>(layer_params, "classes", -1);
int num_of_anchors = getParam<int>(layer_params, "num", -1);
-2
View File
@@ -2294,8 +2294,6 @@ int64 Net::getPerfProfile(std::vector<double>& timings)
//////////////////////////////////////////////////////////////////////////
Importer::~Importer() {}
Layer::Layer() { preferableTarget = DNN_TARGET_CPU; }
Layer::Layer(const LayerParams &params)
+1
View File
@@ -89,6 +89,7 @@ void initializeLayerFactory()
CV_DNN_REGISTER_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
CV_DNN_REGISTER_LAYER_CLASS(Pooling, PoolingLayer);
CV_DNN_REGISTER_LAYER_CLASS(ROIPooling, PoolingLayer);
CV_DNN_REGISTER_LAYER_CLASS(PSROIPooling, PoolingLayer);
CV_DNN_REGISTER_LAYER_CLASS(LRN, LRNLayer);
CV_DNN_REGISTER_LAYER_CLASS(InnerProduct, InnerProductLayer);
CV_DNN_REGISTER_LAYER_CLASS(Softmax, SoftmaxLayer);
+83 -22
View File
@@ -57,9 +57,9 @@ namespace cv
{
namespace dnn
{
static inline int scaleAndRoundRoi(float f, float scale)
static inline int roundRoiSize(float v)
{
return (int)(f * scale + (f >= 0.f ? 0.5f : -0.5f));
return (int)(v + (v >= 0.f ? 0.5f : -0.5f));
}
class PoolingLayerImpl : public PoolingLayer
@@ -67,13 +67,14 @@ class PoolingLayerImpl : public PoolingLayer
public:
PoolingLayerImpl(const LayerParams& params)
{
type = MAX;
computeMaxIdx = true;
globalPooling = false;
stride = Size(1, 1);
if (params.has("pool"))
if (params.has("pool") || params.has("kernel_size") ||
params.has("kernel_w") || params.has("kernel_h"))
{
String pool = params.get<String>("pool").toLowerCase();
String pool = params.get<String>("pool", "max").toLowerCase();
if (pool == "max")
type = MAX;
else if (pool == "ave")
@@ -85,15 +86,24 @@ public:
getPoolingKernelParams(params, kernel.height, kernel.width, globalPooling,
pad.height, pad.width, stride.height, stride.width, padMode);
}
else if (params.has("pooled_w") || params.has("pooled_h") || params.has("spatial_scale"))
else if (params.has("pooled_w") || params.has("pooled_h"))
{
type = ROI;
computeMaxIdx = false;
pooledSize.width = params.get<uint32_t>("pooled_w", 1);
pooledSize.height = params.get<uint32_t>("pooled_h", 1);
}
else if (params.has("output_dim") && params.has("group_size"))
{
type = PSROI;
pooledSize.width = params.get<int>("group_size");
pooledSize.height = pooledSize.width;
psRoiOutChannels = params.get<int>("output_dim");
}
else
CV_Error(Error::StsBadArg, "Cannot determine pooling type");
setParamsFrom(params);
ceilMode = params.get<bool>("ceil_mode", true);
pooledSize.width = params.get<uint32_t>("pooled_w", 1);
pooledSize.height = params.get<uint32_t>("pooled_h", 1);
spatialScale = params.get<float>("spatial_scale", 1);
}
@@ -192,7 +202,7 @@ public:
CV_Assert(inputs.size() == 1, outputs.size() == 1);
avePooling(*inputs[0], outputs[0]);
break;
case ROI:
case ROI: case PSROI:
CV_Assert(inputs.size() == 2, outputs.size() == 1);
roiPooling(*inputs[0], *inputs[1], outputs[0]);
break;
@@ -231,11 +241,11 @@ public:
Size stride, Size pad, int poolingType, float spatialScale,
bool computeMaxIdx, int nstripes)
{
CV_Assert(src.isContinuous() && dst.isContinuous() &&
src.type() == CV_32F && src.type() == dst.type() &&
src.dims == 4 && dst.dims == 4 &&
(poolingType == ROI && dst.size[0] == rois.size[0] ||
src.size[0] == dst.size[0]) && src.size[1] == dst.size[1] &&
CV_Assert(src.isContinuous(), dst.isContinuous(),
src.type() == CV_32F, src.type() == dst.type(),
src.dims == 4, dst.dims == 4,
((poolingType == ROI || poolingType == PSROI) && dst.size[0] ==rois.size[0] || src.size[0] == dst.size[0]),
poolingType == PSROI || src.size[1] == dst.size[1],
(mask.empty() || (mask.type() == src.type() && mask.size == dst.size)));
PoolingInvoker p;
@@ -294,12 +304,12 @@ public:
int n = (int)(ofs / channels);
int ystart, yend;
const float *srcData;
const float *srcData = 0;
if (poolingType == ROI)
{
const float *roisData = rois->ptr<float>(n);
int ystartROI = scaleAndRoundRoi(roisData[2], spatialScale);
int yendROI = scaleAndRoundRoi(roisData[4], spatialScale);
int ystartROI = roundRoiSize(roisData[2] * spatialScale);
int yendROI = roundRoiSize(roisData[4] * spatialScale);
int roiHeight = std::max(yendROI - ystartROI + 1, 1);
float roiRatio = (float)roiHeight / height;
@@ -309,6 +319,17 @@ public:
CV_Assert(roisData[0] < src->size[0]);
srcData = src->ptr<float>(roisData[0], c);
}
else if (poolingType == PSROI)
{
const float *roisData = rois->ptr<float>(n);
float ystartROI = roundRoiSize(roisData[2]) * spatialScale;
float yendROI = roundRoiSize(roisData[4] + 1) * spatialScale;
float roiHeight = std::max(yendROI - ystartROI, 0.1f);
float roiRatio = roiHeight / height;
ystart = (int)std::floor(ystartROI + y0 * roiRatio);
yend = (int)std::ceil(ystartROI + (y0 + 1) * roiRatio);
}
else
{
ystart = y0 * stride_h - pad_h;
@@ -527,11 +548,11 @@ public:
}
}
}
else // ROI
else if (poolingType == ROI)
{
const float *roisData = rois->ptr<float>(n);
int xstartROI = scaleAndRoundRoi(roisData[1], spatialScale);
int xendROI = scaleAndRoundRoi(roisData[3], spatialScale);
int xstartROI = roundRoiSize(roisData[1] * spatialScale);
int xendROI = roundRoiSize(roisData[3] * spatialScale);
int roiWidth = std::max(xendROI - xstartROI + 1, 1);
float roiRatio = (float)roiWidth / width;
for( ; x0 < x1; x0++ )
@@ -558,6 +579,38 @@ public:
dstData[x0] = max_val;
}
}
else // PSROI
{
const float *roisData = rois->ptr<float>(n);
CV_Assert(roisData[0] < src->size[0]);
float xstartROI = roundRoiSize(roisData[1]) * spatialScale;
float xendROI = roundRoiSize(roisData[3] + 1) * spatialScale;
float roiWidth = std::max(xendROI - xstartROI, 0.1f);
float roiRatio = roiWidth / width;
for( ; x0 < x1; x0++ )
{
int xstart = (int)std::floor(xstartROI + x0 * roiRatio);
int xend = (int)std::ceil(xstartROI + (x0 + 1) * roiRatio);
xstart = max(xstart, 0);
xend = min(xend, inp_width);
if (xstart >= xend || ystart >= yend)
{
dstData[x0] = 0;
continue;
}
srcData = src->ptr<float>(roisData[0], (c * height + y0) * width + x0);
float sum_val = 0.f;
for (int y = ystart; y < yend; ++y)
for (int x = xstart; x < xend; ++x)
{
const int index = y * inp_width + x;
float val = srcData[index];
sum_val += val;
}
dstData[x0] = sum_val / ((yend - ystart) * (xend - xstart));
}
}
}
}
};
@@ -716,7 +769,7 @@ public:
out.height = 1;
out.width = 1;
}
else if (type == ROI)
else if (type == ROI || type == PSROI)
{
out.height = pooledSize.height;
out.width = pooledSize.width;
@@ -751,6 +804,13 @@ public:
CV_Assert(inputs.size() == 2);
dims[0] = inputs[1][0]; // Number of proposals;
}
else if (type == PSROI)
{
CV_Assert(inputs.size() == 2);
CV_Assert(psRoiOutChannels * pooledSize.width * pooledSize.height == inputs[0][1]);
dims[0] = inputs[1][0]; // Number of proposals;
dims[1] = psRoiOutChannels;
}
outputs.assign(type == MAX ? 2 : 1, shape(dims));
return false;
}
@@ -781,7 +841,8 @@ private:
MAX,
AVE,
STOCHASTIC,
ROI
ROI, // RoI pooling, https://arxiv.org/pdf/1504.08083.pdf
PSROI // Position-sensitive RoI pooling, https://arxiv.org/pdf/1605.06409.pdf
};
};
+106
View File
@@ -45,6 +45,7 @@
#include <float.h>
#include <algorithm>
#include <cmath>
#include "opencl_kernels_dnn.hpp"
namespace cv
{
@@ -270,11 +271,108 @@ public:
return false;
}
#ifdef HAVE_OPENCL
bool forward_ocl(InputArrayOfArrays inps, OutputArrayOfArrays outs, OutputArrayOfArrays internals)
{
std::vector<UMat> inputs;
std::vector<UMat> outputs;
inps.getUMatVector(inputs);
outs.getUMatVector(outputs);
int _layerWidth = inputs[0].size[3];
int _layerHeight = inputs[0].size[2];
int _imageWidth = inputs[1].size[3];
int _imageHeight = inputs[1].size[2];
float stepX, stepY;
if (_stepX == 0 || _stepY == 0)
{
stepX = static_cast<float>(_imageWidth) / _layerWidth;
stepY = static_cast<float>(_imageHeight) / _layerHeight;
} else {
stepX = _stepX;
stepY = _stepY;
}
if (umat_offsetsX.empty())
{
Mat offsetsX(1, _offsetsX.size(), CV_32FC1, &_offsetsX[0]);
Mat offsetsY(1, _offsetsX.size(), CV_32FC1, &_offsetsY[0]);
Mat aspectRatios(1, _aspectRatios.size(), CV_32FC1, &_aspectRatios[0]);
Mat variance(1, _variance.size(), CV_32FC1, &_variance[0]);
offsetsX.copyTo(umat_offsetsX);
offsetsY.copyTo(umat_offsetsY);
aspectRatios.copyTo(umat_aspectRatios);
variance.copyTo(umat_variance);
int real_numPriors = _numPriors / pow(2, _offsetsX.size() - 1);
umat_scales = UMat(1, &real_numPriors, CV_32F, 1.0f);
}
size_t nthreads = _layerHeight * _layerWidth;
ocl::Kernel kernel("prior_box", ocl::dnn::prior_box_oclsrc);
kernel.set(0, (int)nthreads);
kernel.set(1, (float)stepX);
kernel.set(2, (float)stepY);
kernel.set(3, (float)_minSize);
kernel.set(4, (float)_maxSize);
kernel.set(5, ocl::KernelArg::PtrReadOnly(umat_offsetsX));
kernel.set(6, ocl::KernelArg::PtrReadOnly(umat_offsetsY));
kernel.set(7, (int)_offsetsX.size());
kernel.set(8, ocl::KernelArg::PtrReadOnly(umat_aspectRatios));
kernel.set(9, (int)_aspectRatios.size());
kernel.set(10, ocl::KernelArg::PtrReadOnly(umat_scales));
kernel.set(11, ocl::KernelArg::PtrWriteOnly(outputs[0]));
kernel.set(12, (int)_layerHeight);
kernel.set(13, (int)_layerWidth);
kernel.set(14, (int)_imageHeight);
kernel.set(15, (int)_imageWidth);
kernel.run(1, &nthreads, NULL, false);
// clip the prior's coordidate such that it is within [0, 1]
if (_clip)
{
Mat mat = outputs[0].getMat(ACCESS_READ);
int aspect_count = (_maxSize > 0) ? 1 : 0;
int offset = nthreads * 4 * _offsetsX.size() * (1 + aspect_count + _aspectRatios.size());
float* outputPtr = mat.ptr<float>() + offset;
int _outChannelSize = _layerHeight * _layerWidth * _numPriors * 4;
for (size_t d = 0; d < _outChannelSize; ++d)
{
outputPtr[d] = std::min<float>(std::max<float>(outputPtr[d], 0.), 1.);
}
}
// set the variance.
{
ocl::Kernel kernel("set_variance", ocl::dnn::prior_box_oclsrc);
int offset = total(shape(outputs[0]), 2);
size_t nthreads = _layerHeight * _layerWidth * _numPriors;
kernel.set(0, (int)nthreads);
kernel.set(1, (int)offset);
kernel.set(2, (int)_variance.size());
kernel.set(3, ocl::KernelArg::PtrReadOnly(umat_variance));
kernel.set(4, ocl::KernelArg::PtrWriteOnly(outputs[0]));
if (!kernel.run(1, &nthreads, NULL, false))
return false;
}
return true;
}
#endif
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr)
{
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
CV_OCL_RUN((preferableTarget == DNN_TARGET_OPENCL) &&
OCL_PERFORMANCE_CHECK(ocl::Device::getDefault().isIntel()),
forward_ocl(inputs_arr, outputs_arr, internals_arr))
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
}
@@ -441,6 +539,14 @@ private:
std::vector<float> _offsetsX;
std::vector<float> _offsetsY;
#ifdef HAVE_OPENCL
UMat umat_offsetsX;
UMat umat_offsetsY;
UMat umat_aspectRatios;
UMat umat_scales;
UMat umat_variance;
#endif
bool _flip;
bool _clip;
bool _explicitSizes;
+30 -111
View File
@@ -43,7 +43,7 @@
#include "../precomp.hpp"
#include <opencv2/dnn/shape_utils.hpp>
#include <opencv2/dnn/all_layers.hpp>
#include <iostream>
#include "nms.inl.hpp"
#include "opencl_kernels_dnn.hpp"
namespace cv
@@ -173,8 +173,7 @@ public:
if (nmsThreshold > 0) {
Mat mat = outBlob.getMat(ACCESS_WRITE);
float *dstData = mat.ptr<float>();
do_nms_sort(dstData, rows*cols*anchors, nmsThreshold);
//do_nms(dstData, rows*cols*anchors, nmsThreshold);
do_nms_sort(dstData, rows*cols*anchors, thresh, nmsThreshold);
}
}
@@ -263,128 +262,48 @@ public:
}
if (nmsThreshold > 0) {
do_nms_sort(dstData, rows*cols*anchors, nmsThreshold);
//do_nms(dstData, rows*cols*anchors, nmsThreshold);
do_nms_sort(dstData, rows*cols*anchors, thresh, nmsThreshold);
}
}
}
struct box {
float x, y, w, h;
float *probs;
};
float overlap(float x1, float w1, float x2, float w2)
static inline float rectOverlap(const Rect2f& a, const Rect2f& b)
{
float l1 = x1 - w1 / 2;
float l2 = x2 - w2 / 2;
float left = l1 > l2 ? l1 : l2;
float r1 = x1 + w1 / 2;
float r2 = x2 + w2 / 2;
float right = r1 < r2 ? r1 : r2;
return right - left;
return 1.0f - jaccardDistance(a, b);
}
float box_intersection(box a, box b)
void do_nms_sort(float *detections, int total, float score_thresh, float nms_thresh)
{
float w = overlap(a.x, a.w, b.x, b.w);
float h = overlap(a.y, a.h, b.y, b.h);
if (w < 0 || h < 0) return 0;
float area = w*h;
return area;
}
std::vector<Rect2f> boxes(total);
std::vector<float> scores(total);
float box_union(box a, box b)
{
float i = box_intersection(a, b);
float u = a.w*a.h + b.w*b.h - i;
return u;
}
float box_iou(box a, box b)
{
return box_intersection(a, b) / box_union(a, b);
}
struct sortable_bbox {
int index;
float *probs;
};
struct nms_comparator {
int k;
nms_comparator(int _k) : k(_k) {}
bool operator ()(sortable_bbox v1, sortable_bbox v2) {
return v2.probs[k] < v1.probs[k];
}
};
void do_nms_sort(float *detections, int total, float nms_thresh)
{
std::vector<box> boxes(total);
for (int i = 0; i < total; ++i) {
box &b = boxes[i];
for (int i = 0; i < total; ++i)
{
Rect2f &b = boxes[i];
int box_index = i * (classes + coords + 1);
b.x = detections[box_index + 0];
b.y = detections[box_index + 1];
b.w = detections[box_index + 2];
b.h = detections[box_index + 3];
int class_index = i * (classes + 5) + 5;
b.probs = (detections + class_index);
b.width = detections[box_index + 2];
b.height = detections[box_index + 3];
b.x = detections[box_index + 0] - b.width / 2;
b.y = detections[box_index + 1] - b.height / 2;
}
std::vector<sortable_bbox> s(total);
for (int i = 0; i < total; ++i) {
s[i].index = i;
int class_index = i * (classes + 5) + 5;
s[i].probs = (detections + class_index);
}
for (int k = 0; k < classes; ++k) {
std::stable_sort(s.begin(), s.end(), nms_comparator(k));
for (int i = 0; i < total; ++i) {
if (boxes[s[i].index].probs[k] == 0) continue;
box a = boxes[s[i].index];
for (int j = i + 1; j < total; ++j) {
box b = boxes[s[j].index];
if (box_iou(a, b) > nms_thresh) {
boxes[s[j].index].probs[k] = 0;
}
}
std::vector<int> indices;
for (int k = 0; k < classes; ++k)
{
for (int i = 0; i < total; ++i)
{
int box_index = i * (classes + coords + 1);
int class_index = box_index + 5;
scores[i] = detections[class_index + k];
detections[class_index + k] = 0;
}
}
}
void do_nms(float *detections, int total, float nms_thresh)
{
std::vector<box> boxes(total);
for (int i = 0; i < total; ++i) {
box &b = boxes[i];
int box_index = i * (classes + coords + 1);
b.x = detections[box_index + 0];
b.y = detections[box_index + 1];
b.w = detections[box_index + 2];
b.h = detections[box_index + 3];
int class_index = i * (classes + 5) + 5;
b.probs = (detections + class_index);
}
for (int i = 0; i < total; ++i) {
bool any = false;
for (int k = 0; k < classes; ++k) any = any || (boxes[i].probs[k] > 0);
if (!any) {
continue;
}
for (int j = i + 1; j < total; ++j) {
if (box_iou(boxes[i], boxes[j]) > nms_thresh) {
for (int k = 0; k < classes; ++k) {
if (boxes[i].probs[k] < boxes[j].probs[k]) boxes[i].probs[k] = 0;
else boxes[j].probs[k] = 0;
}
}
NMSFast_(boxes, scores, score_thresh, nms_thresh, 1, 0, indices, rectOverlap);
for (int i = 0, n = indices.size(); i < n; ++i)
{
int box_index = indices[i] * (classes + coords + 1);
int class_index = box_index + 5;
detections[class_index + k] = scores[indices[i]];
}
}
}
@@ -215,6 +215,9 @@ class OCL4DNNConvSpatial
bool createGEMMLikeConvKernel(int32_t blockWidth,
int32_t blockHeight,
int32_t blockDepth);
bool createDWConvKernel(int32_t blockWidth,
int32_t blockHeight,
int32_t blockDepth);
void CreateSubBuffer(const UMat& buffer, UMat& sub_buffer,
int32_t offset, int32_t size, bool write_only);
bool convolve(const UMat &bottom, UMat &top,
@@ -255,6 +258,12 @@ class OCL4DNNConvSpatial
int lx, int ly, int lz,
bool swizzle, bool nullLocal);
void generateTunerItems(std::vector< cv::Ptr<tunerParam> > &tunerItems);
void generate_dwconv_tuneritems(std::vector< cv::Ptr<tunerParam> > &tunerItems,
int blockM, int blockK, int blockN);
void generate_gemmlike_tuneritems(std::vector< cv::Ptr<tunerParam> > &tunerItems,
int blockM, int blockK, int blockN);
void generate_idlf_tuneritems(std::vector< cv::Ptr<tunerParam> > &tunerItems,
int blockM, int blockK, int simd_size);
void setFusionDefine(ocl4dnnFusedActiv_t fused_activ, bool fused_eltwise);
void setFusionArg(ocl4dnnFusedActiv_t fused_activ, bool fused_eltwise, ocl::Kernel &kernel, cl_uint &argIdx);
@@ -282,6 +291,8 @@ class OCL4DNNConvSpatial
int32_t M_;
bool tuned_;
bool dwconv_;
std::string key_, key_sanitized_;
std::string short_key_;
std::string kernel_name_;
@@ -103,6 +103,7 @@ OCL4DNNConvSpatial<Dtype>::OCL4DNNConvSpatial(OCL4DNNConvConfig config)
top_dim_ = num_output_ * output_w_ * output_h_;
cache_path_ = utils::getConfigurationParameterString("OPENCV_OCL4DNN_CONFIG_PATH", "");
dwconv_ = (num_output_ == channels_ && channels_ == group_);
use_cache_path_ = false;
if (!cache_path_.empty())
@@ -203,7 +204,8 @@ void OCL4DNNConvSpatial<Dtype>::collectCommonInformation()
typedef enum {
KERNEL_TYPE_INTEL_IDLF = 2,
KERNEL_TYPE_BASIC = 4,
KERNEL_TYPE_GEMM_LIKE = 5
KERNEL_TYPE_GEMM_LIKE = 5,
KERNEL_TYPE_DWCONV = 6
} ocl4dnnConvSpatialKernelType_t;
template<typename Dtype>
@@ -255,11 +257,7 @@ void OCL4DNNConvSpatial<Dtype>::setupKernelDetails(int32_t kernelType,
addDef("INPUT_DEPTH", channels_ / group_);
addDef("TOTAL_INPUT_DEPTH_SIZE", channels_);
addDef("TOTAL_OUTPUT_DEPTH", num_output_);
addDef("INPUT_START_X", 0);
addDef("INPUT_START_Y", 0);
addDef("INPUT_START_Z", 0);
addDef("NUM_FILTERS", M_);
addDef("OUT_BUFF_OFFSET", 0);
addDef("TILE_X", tile_x);
addDef("TILE_Y", tile_y);
addDef("TILE_Y_STRIDE", tile_y_stride);
@@ -313,6 +311,7 @@ void OCL4DNNConvSpatial<Dtype>::setupKernelDetails(int32_t kernelType,
if (clOptionSupport("-cl-no-subgroup-ifp"))
options_ << " -cl-no-subgroup-ifp ";
addDef("KERNEL_GEMM_LIKE");
addDef("INPUT_DEPTH", channels_);
addDef("WIDTH1", M_);
addDef("OUT_PADDING_LEFT", 0);
@@ -329,6 +328,28 @@ void OCL4DNNConvSpatial<Dtype>::setupKernelDetails(int32_t kernelType,
setFusionDefine(fused_activ_, fused_eltwise_);
src_ = ocl::dnn::conv_layer_spatial_oclsrc;
}
else if (kernelType == KERNEL_TYPE_DWCONV)
{
kernelUKey = generateSpecificKey(KERNEL_TYPE_DWCONV, blockM, blockK, blockN);
kernel_name_ = "DWCONV_";
kernel_name_ += kernelUKey.c_str();
options_ << " -cl-fast-relaxed-math ";
if (clOptionSupport("-cl-no-subgroup-ifp"))
options_ << " -cl-no-subgroup-ifp ";
addDef("KERNEL_DWCONV");
addDef("KERNEL_SIZE", kernel_w_ * kernel_h_);
addDef("KERNEL_W", kernel_w_);
addDef("KERNEL_H", kernel_h_);
addDef("APPLY_BIAS", bias_term_);
addDef("OUTPUT_Z", num_output_ * num_);
addDef("CHANNELS", num_output_);
setFusionDefine(fused_activ_, fused_eltwise_);
options_ << " -D DWCONV=" << kernel_name_;
src_ = cv::ocl::dnn::conv_layer_spatial_oclsrc;
}
}
template<typename Dtype>
@@ -906,6 +927,33 @@ bool OCL4DNNConvSpatial<float>::convolve(const UMat &bottom, UMat &top,
return false;
}
}
} else if (config->kernelType == KERNEL_TYPE_DWCONV) {
ocl::Kernel kernel(config->kernelName.c_str(), program);
if (kernel.empty())
return false;
cl_uint argIdx = 0;
setFusionArg(fused_activ_, fused_eltwise_, kernel, argIdx);
kernel.set(argIdx++, ocl::KernelArg::PtrReadOnly(bottom));
kernel.set(argIdx++, ocl::KernelArg::PtrReadOnly(weight));
if (bias_term_)
kernel.set(argIdx++, ocl::KernelArg::PtrReadOnly(bias));
kernel.set(argIdx++, ocl::KernelArg::PtrWriteOnly(top));
kernel.set(argIdx++, (uint16_t)width_);
kernel.set(argIdx++, (uint16_t)height_);
kernel.set(argIdx++, (uint16_t)output_w_);
kernel.set(argIdx++, (uint16_t)output_h_);
size_t global_size[3];
global_size[0] = output_w_;
global_size[1] = output_h_;
global_size[2] = num_output_ * num_;
if (!kernel.run(3, global_size, NULL, false))
{
std::cout << "DWCONV kernel run failed." << std::endl;
return false;
}
} else {
for (int32_t n = 0; n < numImages; ++n) {
for (int32_t g = 0; g < group_; ++g) {
@@ -1222,6 +1270,39 @@ bool OCL4DNNConvSpatial<float>::createIDLFKernel(int32_t blockWidth,
return false;
}
template<>
bool OCL4DNNConvSpatial<float>::createDWConvKernel(int32_t blockWidth,
int32_t blockHeight,
int32_t blockDepth)
{
if (!dwconv_)
return false;
int workItemOutput[3] = { 1, 1, 1 };
size_t local_size[3] = { 1, 1, 1 };
size_t global_size[3];
global_size[0] = divUp(output_w_, workItemOutput[0]);
global_size[1] = divUp(output_h_, workItemOutput[1]);
global_size[2] = divUp(M_ * num_, workItemOutput[2]);
kernelType_ = KERNEL_TYPE_DWCONV;
blockM_ = blockWidth;
blockK_ = blockHeight;
blockN_ = blockDepth;
setupKernel();
ocl::Program program = compileKernel();
if (program.ptr())
{
kernelQueue.push_back(makePtr<kernelConfig>(kernel_name_, &global_size[0], &local_size[0],
&workItemOutput[0], false, KERNEL_TYPE_DWCONV));
return true;
}
else
return false;
}
template<>
bool OCL4DNNConvSpatial<float>::createConvolutionKernel(int32_t kernelType,
int32_t blockWidth,
@@ -1238,72 +1319,136 @@ bool OCL4DNNConvSpatial<float>::createConvolutionKernel(int32_t kernelType,
return createBasicKernel(blockWidth, blockHeight, blockDepth);
else if (kernelType == KERNEL_TYPE_GEMM_LIKE)
return createGEMMLikeConvKernel(blockWidth, blockHeight, blockDepth);
else if (kernelType == KERNEL_TYPE_DWCONV)
return createDWConvKernel(blockWidth, blockHeight, blockDepth);
else
CV_Assert(0 && "Internal error");
return false;
}
template<>
void OCL4DNNConvSpatial<float>::generate_gemmlike_tuneritems(std::vector< cv::Ptr<tunerParam> > &tunerItems,
int blockM, int blockK, int blockN)
{
if (group_ != 1 || ((M_ % 8 != 0) || (M_ % 32 == 24)))
return;
if (blockM != 1 && blockM != 2)
return;
if (blockN != 32)
return;
if (blockK != 8 && blockK != 16)
return;
if (blockK == 16)
{
if ((blockM == 1 && (kernel_w_ > 4)) || M_ % 32 != 0)
return;
if ((blockM == 2) || M_ % 32 != 0)
return;
}
tunerItems.push_back(makePtr<tunerParam>(KERNEL_TYPE_GEMM_LIKE, blockM, blockK, blockN));
}
template<>
void OCL4DNNConvSpatial<float>::generate_idlf_tuneritems(std::vector< cv::Ptr<tunerParam> > &tunerItems,
int blockM, int blockK, int simd_size)
{
int max_compute_units = ocl::Device::getDefault().maxComputeUnits();
if (simd_size != 8 && simd_size != 16)
return;
if (simd_size == 8 && !((group_ == 1 || M_ % 8 == 0)))
return;
if (simd_size == 16 && !(group_ == 1 || M_ % 16 == 0))
return;
int width_max, height_max, block_size_max;
width_max = 14;
height_max = 14;
block_size_max = 32;
if (blockM > width_max)
return;
if (blockK > height_max)
return;
if (blockM > output_w_)
return;
if (blockK > output_h_)
return;
// Only when the work items count is less than the device
// max work items or the M_ is less than 16, we will tune
// for simd 8.
if (simd_size == 8 && M_ >= 16 &&
((num_ * M_ * output_w_ * output_h_ / static_cast<float>(blockM * blockK)) >=
max_compute_units * 7 * 16))
return;
int actual_tile_x = kernel_w_ * dilation_w_ + (blockM - 1) * stride_w_ ;
int tile_x = alignSize(actual_tile_x, 4);
int tile_y = kernel_h_ * dilation_h_ + (blockK - 1) * stride_h_;
if (tile_x > (4 * simd_size))
return;
if ((blockM * blockK + divUp(tile_x * tile_y, simd_size)) > block_size_max)
return;
int tile_y_stride = (4 * simd_size) / tile_x;
int invec_size = divUp(tile_y, tile_y_stride);
if (invec_size > 4)
return;
tunerItems.push_back(makePtr<tunerParam>(KERNEL_TYPE_INTEL_IDLF, blockM, blockK, simd_size));
}
template<>
void OCL4DNNConvSpatial<float>::generate_dwconv_tuneritems(std::vector< cv::Ptr<tunerParam> > &tunerItems,
int blockM, int blockK, int blockN)
{
if (!dwconv_)
return;
tunerItems.push_back(makePtr<tunerParam>(KERNEL_TYPE_DWCONV, blockM, blockK, blockN));
}
template<>
void OCL4DNNConvSpatial<float>::generateTunerItems(std::vector< cv::Ptr<tunerParam> > &tunerItems)
{
if (ocl::Device::getDefault().intelSubgroupsSupport()) {
/* IDLF kernels are using Intel specific extension which make
them intel only. */
// Generates static key_
int max_compute_units = ocl::Device::getDefault().maxComputeUnits();
int kernelCnt = 0;
if (group_ == 1 && ((M_ % 8 == 0) && (M_ % 32 != 24))) {
tunerItems.push_back(makePtr<tunerParam>(KERNEL_TYPE_GEMM_LIKE, 1, 8, 32));
tunerItems.push_back(makePtr<tunerParam>(KERNEL_TYPE_GEMM_LIKE, 2, 8, 32));
if (ocl::Device::getDefault().intelSubgroupsSupport())
{
// depthwise kernel
generate_dwconv_tuneritems(tunerItems, 1, 1, 1);
if (tunerItems.size() > 0 && group_ > 8)
return;
if (kernel_w_ < 4 && M_ % 32 == 0)
tunerItems.push_back(makePtr<tunerParam>(KERNEL_TYPE_GEMM_LIKE, 1, 16, 32));
}
// gemm like kernel
generate_gemmlike_tuneritems(tunerItems, 1, 8, 32);
generate_gemmlike_tuneritems(tunerItems, 2, 8, 32);
generate_gemmlike_tuneritems(tunerItems, 1, 16, 32);
generate_gemmlike_tuneritems(tunerItems, 2, 16, 32);
for (int simd_size = 8; simd_size <= 16; simd_size += 8) {
if (simd_size == 8 && !((group_ == 1 || M_ % 8 == 0)))
continue;
if (simd_size == 16 && !(group_ == 1 || M_ % 16 == 0))
continue;
const int width_max = 14, height_max = 8, block_size_max = 32;
for (uint32_t width = width_max; width > 0; width--) {
int candidate = 0;
if (width > output_w_)
continue;
for (uint32_t height = height_max; height > 0; height--) {
if (width * height > block_size_max || height > output_h_)
continue;
// Only when the work items count is less than the device
// max work items or the M_ is less than 16, we will tune
// for simd 8.
if (simd_size == 8 &&
M_ >= 16 &&
((num_ * M_ * output_w_ * output_h_ / static_cast<float>(width * height)) >=
max_compute_units * 7 * 16))
continue;
int actual_tile_x = kernel_w_ * dilation_w_ + (width - 1) * stride_w_;
int tile_x = alignSize(actual_tile_x, 4);
int tile_y = kernel_h_ * dilation_h_ + (height - 1) * stride_h_;
if (tile_x > (4 * simd_size))
continue;
// If actual_tile_x is multiple of 4, we may waste some IO bandwidth.
// This could reduce 75% tuning candidates. It has slightly performance
// impact for the final tuning result, less than 2% for most cases.
if (actual_tile_x % 4 != 0)
continue;
if ((width * height + divUp(tile_x * tile_y, simd_size)) > block_size_max)
continue;
int tile_y_stride = (4 * simd_size) / tile_x;
if (divUp(tile_y, tile_y_stride) < 4) {
tunerItems.push_back(makePtr<tunerParam>(KERNEL_TYPE_INTEL_IDLF, width, height, simd_size));
candidate++;
}
if (candidate >= 4 && height == 2)
// idlf kernel
for (int simd_size = 8; simd_size <= 16; simd_size += 8)
{
int width_max, height_max;
width_max = 14;
height_max = 14;
for (uint32_t width = width_max; width > 0; width--)
{
for (uint32_t height = height_max; height > 0; height--)
{
generate_idlf_tuneritems(tunerItems, width, height, simd_size);
if (tunerItems.size() >= 8 && height == 2)
break;
}
kernelCnt += candidate;
if (kernelCnt >= 12 && width == 2)
if (tunerItems.size() >= 12 && width == 2)
break;
}
}
+296 -19
View File
@@ -189,10 +189,8 @@ __kernel void ConvolveBasic(
// NDRange: (output_width+pad)/ OUT_BLOCK_WIDTH, (output_height+pad)/OUT_BLOCK_HEIGHT, NUM_FILTERS/OUT_BLOCK_DEPTH
// NOTE: for beignet this reqd_work_group_size does not guarantee that SIMD16 mode will be used, the compiler could choose to use two SIMD8 threads, and if that happens the code will break.
#ifndef __BEIGNET__
__attribute__((reqd_work_group_size(1, 1, SIMD_SIZE)))
__attribute__((intel_reqd_sub_group_size(SIMD_SIZE)))
#endif
__kernel void
convolve_simd(
ELTWISE_DATA_ARG
@@ -232,12 +230,12 @@ convolve_simd(
int curr_local_y = ( lid / ( TILE_X / 4 ) );
int curr_local_x = ( lid % ( TILE_X / 4 ) ) * 4;
int curr_y = or * STRIDE_Y + INPUT_START_Y + curr_local_y;
int curr_x = oc * STRIDE_X + INPUT_START_X + curr_local_x;
int curr_y = or * STRIDE_Y + curr_local_y;
int curr_x = oc * STRIDE_X + curr_local_x;
#if INPUT_PAD_W != 0 || INPUT_PAD_H != 0
int saved_y = curr_y;
#endif
in_addr = input_batch_offset + INPUT_START_Z * input_height * input_width
in_addr = input_batch_offset
+ (curr_y - INPUT_PAD_H) * input_width // y tile offset
+ curr_x - INPUT_PAD_W; // x tile offset
union {
@@ -363,7 +361,7 @@ convolve_simd(
fm = fm % ALIGNED_NUM_FILTERS;
if ((ALIGNED_NUM_FILTERS == NUM_FILTERS || fm < NUM_FILTERS)) {
unsigned int out_addr = OUT_BUFF_OFFSET + ( num_in_batch * TOTAL_OUTPUT_DEPTH + fm ) * output_width * output_height;
unsigned int out_addr = ( num_in_batch * TOTAL_OUTPUT_DEPTH + fm ) * output_width * output_height;
out_addr += or * output_width + oc;
// we need this address calculation for biases because we support views and batching
#if APPLY_BIAS
@@ -383,10 +381,9 @@ convolve_simd(
}
}
#else // KERNEL_GEMM_LIKE
#elif defined KERNEL_GEMM_LIKE
#if APPLY_BIAS
// Dtype bias[4];
#define SUBGROUP_GET_BIAS(k, i) intel_sub_group_shuffle(bias[k], i)
#else
#define SUBGROUP_GET_BIAS(k, i) ((Dtype)0)
@@ -448,9 +445,7 @@ typedef struct float0 { float s0; } float0; //never used but makes compiler happ
#define TILE_K KERNEL_WIDTH
#define TILE_N 32
#ifndef __BEIGNET__
__attribute__((intel_reqd_sub_group_size(8)))
#endif
__kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
{
const int group_x = get_group_id(0);
@@ -610,6 +605,11 @@ __kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
Dtype4 *bias_vec;
bias_vec = (Dtype4*)bias;
*bias_vec = as_Dtype4(SUB_GROUP_BLOCK_READ4((__global INT_TYPE *)biases_base + group_x * TILE_N));
if (group_x > 0xFFFFFFFEul) {
dst[0] = bias[0] + bias[1] + bias[2] + bias[3];
}
#else
const Dtype bias[4] = {0, 0, 0, 0};
#endif
if (global_y * TILE_M < output_width * output_height )
{
@@ -770,6 +770,11 @@ __kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
Dtype4 *bias_vec;
bias_vec = (Dtype4*)bias;
*bias_vec = as_Dtype4(SUB_GROUP_BLOCK_READ4((__global INT_TYPE *)biases_base + group_x * TILE_N));
if (group_x > 0xFFFFFFFEul) {
dst[0] = bias[0] + bias[1] + bias[2] + bias[3];
}
#else
const Dtype bias[4] = {0, 0, 0, 0};
#endif
if (global_y * TILE_M < output_width * output_height )
@@ -815,9 +820,7 @@ __kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
#define TILE_K KERNEL_WIDTH
#define TILE_N 32
#ifndef __BEIGNET__
__attribute__((intel_reqd_sub_group_size(8)))
#endif
__kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
{
const int group_x = get_group_id(0);
@@ -1014,6 +1017,11 @@ __kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
Dtype4 *bias_vec;
bias_vec = (Dtype4*)bias;
*bias_vec = as_Dtype4(SUB_GROUP_BLOCK_READ4((__global INT_TYPE *)biases_base + group_x * TILE_N));
if (group_x > 0xFFFFFFFEul) {
dst[0] = bias[0] + bias[1] + bias[2] + bias[3];
}
#else
const Dtype bias[4] = {0, 0, 0, 0};
#endif
if( global_y * TILE_M < output_width * output_height )
@@ -1223,6 +1231,11 @@ __kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
Dtype4 *bias_vec;
bias_vec = (Dtype4*)bias;
*bias_vec = as_Dtype4(SUB_GROUP_BLOCK_READ4((__global INT_TYPE *)biases_base + group_x * TILE_N));
if (group_x > 0xFFFFFFFEul) {
dst[0] = bias[0] + bias[1] + bias[2] + bias[3];
}
#else
const Dtype bias[4] = {0, 0, 0, 0};
#endif
if( global_y * TILE_M < output_width * output_height )
{
@@ -1336,9 +1349,7 @@ __kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
#define TILE_K KERNEL_WIDTH
#define TILE_N 32
#ifndef __BEIGNET__
__attribute__((intel_reqd_sub_group_size(16)))
#endif
__kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
{
const int group_x = get_group_id(0);
@@ -1398,18 +1409,14 @@ __kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
// Inner loop loads and FMADs one row (KERNEL_WIDTH) of each input patch
// and KERNEL_WIDTH/2 rows of interleaved filter.
int patch_depth = 0;
#ifndef __BEIGNET__
__attribute__((opencl_unroll_hint(1)))
#endif
do
{
int patch_row = 0;
#if INPUT_PAD_H != 0 || INPUT_PAD_W != 0 || DILATION_X != 1 || DILATION_Y != 1
curr_y = saved_y;
#endif
#ifndef __BEIGNET__
__attribute__((opencl_unroll_hint(1)))
#endif
do
{
// Load atile and btile.
@@ -1497,8 +1504,278 @@ __kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
Dtype2 *bias_vec;
bias_vec = (Dtype2*)bias;
*bias_vec = as_Dtype2(SUB_GROUP_BLOCK_READ2((__global INT_TYPE *)biases_base + group_x * TILE_N));
if (group_x > 0xFFFFFFFEul) {
dst[0] = bias[0] + bias[1];
}
#else
const Dtype bias[2] = {0, 0};
#endif
INTERLEAVED_SIMD16_OUTPUT(dst, out_offset, 0);
}
#endif
#endif // KERNEL_BASIC/IDLF/GEMM_LIKE
#ifdef GEMM_LIKE_CONV_32_2_SIMD16
//////////////////////////////////////////////////////////////////////////////
// Conv_Interleaved_32_2_SIMD16
//
// Convolution: each workitem computes 1 patch x 32 filters worth of output
// data.
#define TILE_M 2
#define TILE_K KERNEL_WIDTH
#define TILE_N 32
__attribute__((intel_reqd_sub_group_size(16)))
__kernel void Conv_Interleaved(GEMM_LIKE_KERNEL_ARGS)
{
const int group_x = get_group_id(0);
const int group_y = get_group_id(1);
const int global_x = get_global_id(0);
const int global_y = get_global_id(1);
const int global_z = get_global_id(2);
int interleaved_y;
int kernel_y;
int kernel_idx;
#define DOT_PRODUCT_16( _result, _rowA, colB ) \
{ \
_result.s0 = mad( _rowA, sub_group_broadcast( colB, 0 ), _result.s0 ); \
_result.s1 = mad( _rowA, sub_group_broadcast( colB, 1 ), _result.s1 ); \
_result.s2 = mad( _rowA, sub_group_broadcast( colB, 2 ), _result.s2 ); \
_result.s3 = mad( _rowA, sub_group_broadcast( colB, 3 ), _result.s3 ); \
_result.s4 = mad( _rowA, sub_group_broadcast( colB, 4 ), _result.s4 ); \
_result.s5 = mad( _rowA, sub_group_broadcast( colB, 5 ), _result.s5 ); \
_result.s6 = mad( _rowA, sub_group_broadcast( colB, 6 ), _result.s6 ); \
_result.s7 = mad( _rowA, sub_group_broadcast( colB, 7 ), _result.s7 ); \
_result.s8 = mad( _rowA, sub_group_broadcast( colB, 8 ), _result.s8 ); \
_result.s9 = mad( _rowA, sub_group_broadcast( colB, 9 ), _result.s9 ); \
_result.sa = mad( _rowA, sub_group_broadcast( colB, 10 ), _result.sa ); \
_result.sb = mad( _rowA, sub_group_broadcast( colB, 11 ), _result.sb ); \
_result.sc = mad( _rowA, sub_group_broadcast( colB, 12 ), _result.sc ); \
_result.sd = mad( _rowA, sub_group_broadcast( colB, 13 ), _result.sd ); \
_result.se = mad( _rowA, sub_group_broadcast( colB, 14 ), _result.se ); \
_result.sf = mad( _rowA, sub_group_broadcast( colB, 15 ), _result.sf ); \
}
typedef CAT( Dtype, KERNEL_WIDTH ) Dtype_t;
// True for all threads if filter_width is multiple of TILE_N
// else, true for all but right-most column of threads.
{
// Result ctile (*dst) is M rows x N columns
// LWG size is 1x8. Thus each thread calculates 8*M rows x N cols of ctile.
Dtype16 blockC00 = 0.f;
Dtype16 blockC10 = 0.f;
Dtype16 blockC01 = 0.f;
Dtype16 blockC11 = 0.f;
// Src0 (patch input) is directly used as atile.
// Each work item points to the start of a different patch.
// atile is M rows x K columns.
int curr_x0 = ( ( global_y * TILE_M + 0 ) % output_width ) * STRIDE_X;
int curr_x1 = ( ( global_y * TILE_M + 1 ) % output_width ) * STRIDE_X;
int curr_y0 = ( ( global_y * TILE_M + 0 ) / output_width ) * STRIDE_Y;
int curr_y1 = ( ( global_y * TILE_M + 1 ) / output_width ) * STRIDE_Y;
#if INPUT_PAD_H != 0 || INPUT_PAD_W != 0 || DILATION_X != 1 || DILATION_Y != 1
int saved_y0 = curr_y0;
int saved_y1 = curr_y1;
#endif
const __global Dtype *src0_read0 = src0
+ aligned_input_size * global_z // batch offset
+ (curr_y0 - INPUT_PAD_H) * ROW_PITCH // y offset
+ curr_x0 - INPUT_PAD_W; // x offset
const __global Dtype *src0_read1 = src0
+ aligned_input_size * global_z // batch offset
+ (curr_y1 - INPUT_PAD_H) * ROW_PITCH // y offset
+ curr_x1 - INPUT_PAD_W; // x offset
// Src1 (filter) is directly used as btile.
// It starts at the top of src1 and walks down.
// btile is K rows x N columns.
const __global Dtype *src1_read = src1 + ( global_x * TILE_N * 2);
// Walk DOWN src0 (patch 0, 1, 2, ...) and DOWN src1.
// Inner loop loads and FMADs one row (KERNEL_WIDTH) of each input patch
// and KERNEL_WIDTH/2 rows of interleaved filter.
int patch_depth = 0;
do
{
int patch_row = 0;
do
{
// Load atile and btile.
// Kernel data is partially interleaved. Every 2 rows are interleaved at Dtype8 granularity.
// The exception is that if KERNEL_WIDTH is odd the last row is not interleaved. The non
// interleaved row is padded with zero to ensure same size as interleaved rows. This
// interleaving is done to ensure 0% GDR bank conflicts. For example, this is how the
// kernel data would be arranged before/after interleaving for KERNEL_WIDTH=3.
// (0, 0) (8, 0) (16, 0) (24, 0) ... (0, 0) (0, 1) (8, 0) (0, 1) (16, 0) (0, 1) (24, 0) ..
// (0, 1) (8, 1) (16, 1) (24, 1) ... => (0, 2) (8, 2) (16, 2) (24, 2) ...
// (0, 2) (8, 2) (16, 2) (24, 2) ... ...
// ...
const bool kernel_width_is_odd = KERNEL_WIDTH % 2 == 1;
#if INPUT_PAD_H == 0 && INPUT_PAD_W == 0 && DILATION_X == 1 && DILATION_Y == 1
Dtype_t blockA00 = ( (const __global Dtype_t*)src0_read0 )[ 0 ]; src0_read0 += ROW_PITCH;
Dtype_t blockA01 = ( (const __global Dtype_t*)src0_read1 )[ 0 ]; src0_read1 += ROW_PITCH;
Dtype* pblockA00 = (Dtype*)(&blockA00);
Dtype* pblockA01 = (Dtype*)(&blockA01);
#else
Dtype_t blockA00;
Dtype* pblockA00 = (Dtype*)(&blockA00);
int pos = 0;
LOOP(KERNEL_WIDTH, pos,
{
if (curr_y0 >= INPUT_PAD_H && curr_y0 < input_height + INPUT_PAD_H && curr_x0 + pos * DILATION_X >= INPUT_PAD_W && curr_x0 + pos * DILATION_X < input_width + INPUT_PAD_W)
pblockA00[pos] = src0_read0[pos * DILATION_X];
else
pblockA00[pos] = 0;
})
curr_y0 += DILATION_Y;
Dtype_t blockA01;
Dtype* pblockA01 = (Dtype*)(&blockA01);
pos = 0;
LOOP(KERNEL_WIDTH, pos,
{
if (curr_y1 >= INPUT_PAD_H && curr_y1 < input_height + INPUT_PAD_H && curr_x1 + pos * DILATION_X >= INPUT_PAD_W && curr_x1 + pos * DILATION_X < input_width + INPUT_PAD_W)
pblockA01[pos] = src0_read1[pos * DILATION_X];
else
pblockA01[pos] = 0;
})
curr_y1 += DILATION_Y;
src0_read0 += (ROW_PITCH * DILATION_Y);
src0_read1 += (ROW_PITCH * DILATION_Y);
#endif
Dtype blockB00[KERNEL_WIDTH*2];
Dtype4* p4BlockB00 = (Dtype4*)blockB00;
Dtype2* p2BlockB00 = (Dtype2*)blockB00;
Dtype* pBlockB00 = (Dtype* )blockB00;
interleaved_y = 0;
LOOP(KERNEL_WIDTH_DIV2, interleaved_y,
{
p4BlockB00[interleaved_y] = as_Dtype4( SUB_GROUP_BLOCK_READ4( (const __global INT_TYPE*)src1_read ) );
src1_read += WIDTH1 * 2;
} )
if ( kernel_width_is_odd )
{
p2BlockB00[KERNEL_WIDTH - 1] = as_Dtype2( SUB_GROUP_BLOCK_READ2( (const __global INT_TYPE*)src1_read ) );
src1_read += WIDTH1 * 2;
}
// Perform MADs
kernel_idx = 0;
interleaved_y = 0;
LOOP(KERNEL_WIDTH_DIV2, interleaved_y,
{
kernel_y = interleaved_y * 2;
DOT_PRODUCT_16( blockC00, pblockA00[kernel_y ], pBlockB00[kernel_idx] );
DOT_PRODUCT_16( blockC01, pblockA01[kernel_y ], pBlockB00[kernel_idx] ); kernel_idx++;
DOT_PRODUCT_16( blockC00, pblockA00[kernel_y + 1], pBlockB00[kernel_idx] );
DOT_PRODUCT_16( blockC01, pblockA01[kernel_y + 1], pBlockB00[kernel_idx] ); kernel_idx++;
DOT_PRODUCT_16( blockC10, pblockA00[kernel_y ], pBlockB00[kernel_idx] );
DOT_PRODUCT_16( blockC11, pblockA01[kernel_y ], pBlockB00[kernel_idx] ); kernel_idx++;
DOT_PRODUCT_16( blockC10, pblockA00[kernel_y + 1], pBlockB00[kernel_idx] );
DOT_PRODUCT_16( blockC11, pblockA01[kernel_y + 1], pBlockB00[kernel_idx] ); kernel_idx++;
} )
if ( kernel_width_is_odd )
{
kernel_y = interleaved_y * 2;
DOT_PRODUCT_16( blockC00, pblockA00[kernel_y], pBlockB00[kernel_idx] );
DOT_PRODUCT_16( blockC01, pblockA01[kernel_y], pBlockB00[kernel_idx] ); kernel_idx++;
DOT_PRODUCT_16( blockC10, pblockA00[kernel_y], pBlockB00[kernel_idx] );
DOT_PRODUCT_16( blockC11, pblockA01[kernel_y], pBlockB00[kernel_idx] ); kernel_idx++;
}
}
//while( ++patch_row < 1 ); //debug
while( ++patch_row < KERNEL_HEIGHT );
#if INPUT_PAD_W != 0 || INPUT_PAD_H != 0 || DILATION_X != 1 || DILATION_Y != 1
curr_y0 = saved_y0;
curr_y1 = saved_y1;
#endif
src0_read0 += slice_pitch - ( KERNEL_HEIGHT * ROW_PITCH * DILATION_Y); // reset to start of next slice of patch
src0_read1 += slice_pitch - ( KERNEL_HEIGHT * ROW_PITCH * DILATION_Y);
}
//while ( ++patch_depth < 1 ); //debug
while ( ++patch_depth < INPUT_DEPTH );
// Dst resembles a cube of width x height x (output channel * batches). Each tile writes:
// (SIMD * TILE_M) x 1 x TILE_N. Partial writes most likely generated if padding used.
int out0_offset = global_z * out_pitch_z // batch offset
+ ( group_x * TILE_N ) * out_pitch_y // channel offset
+ ( ( global_y * TILE_M + 0 ) / output_width + OUT_PADDING_HEIGHT ) * OUT_PITCH_X // y offset
+ ( ( global_y * TILE_M + 0 ) % output_width ) + OUT_PADDING_LEFT; // x offset
int out1_offset = global_z * out_pitch_z // batch offset
+ ( group_x * TILE_N ) * out_pitch_y // channel offset
+ ( ( global_y * TILE_M + 1 ) / output_width + OUT_PADDING_HEIGHT ) * OUT_PITCH_X // y offset
+ ( ( global_y * TILE_M + 1 ) % output_width ) + OUT_PADDING_LEFT; // x offset
#if APPLY_BIAS
Dtype bias[2];
Dtype2 *bias_vec;
bias_vec = (Dtype2*)bias;
*bias_vec = as_Dtype2(SUB_GROUP_BLOCK_READ2((__global INT_TYPE *)biases_base + group_x * TILE_N));
if (group_x > 0xFFFFFFFEul) {
dst[0] = bias[0] + bias[1];
}
#else
const Dtype bias[2] = {0, 0};
#endif
INTERLEAVED_SIMD16_OUTPUT(dst, out0_offset, 0);
INTERLEAVED_SIMD16_OUTPUT(dst, out1_offset, 1);
}
}
#endif
#elif defined KERNEL_DWCONV
__kernel void DWCONV(
ELTWISE_DATA_ARG
NEGATIVE_SLOPE_ARG
__global Dtype* image_data,
__global Dtype* kernel_data,
BIAS_KERNEL_ARG
__global Dtype* convolved_image,
const ushort input_width,
const ushort input_height,
const ushort output_width,
const ushort output_height) {
const int outputX = get_global_id(0);
const int outputY = get_global_id(1);
const int outputZ = get_global_id(2);
if(outputX < output_width && outputY < output_height)
{
Dtype sum = 0.;
const int org_y = outputY * STRIDE_Y - INPUT_PAD_H;
const int org_x = outputX * STRIDE_X - INPUT_PAD_W;
const int currentKernelOffset = KERNEL_SIZE*(outputZ%CHANNELS);
const int biasIndex=outputZ%CHANNELS;
const int local_image_offset = org_y*input_width + org_x;
const int imageSize = input_width*input_height;
__global Dtype* image_dataPtrFloat = (image_data + (imageSize*outputZ + local_image_offset));
__global Dtype* kernel_dataPtrFloat = (kernel_data + (currentKernelOffset));
for(int y = 0; y < KERNEL_H; y++)
{
for(int x = 0; x < KERNEL_W; x++)
{
if(!(org_y + y * DILATION_Y >= 0 && org_y + y * DILATION_Y < input_height && org_x + x * DILATION_X >= 0 && org_x + x * DILATION_X < input_width))
{
continue;
}
sum += image_dataPtrFloat[x * DILATION_X] * kernel_dataPtrFloat[x];
}
image_dataPtrFloat += input_width * DILATION_Y;
kernel_dataPtrFloat += KERNEL_W;
}
#if APPLY_BIAS
int offset = outputZ*output_height*output_width + outputY*output_width + outputX;
ACTIVATION_FUNCTION(convolved_image, offset, sum + biases_base[biasIndex], biasIndex);
#else
int offset = outputZ*output_height*output_width + outputY*output_width + outputX;
ACTIVATION_FUNCTION(convolved_image, offset, sum, biasIndex);
#endif
}
}
#endif // KERNEL_BASIC/IDLF/GEMM_LIKE/DWCONV
+148
View File
@@ -0,0 +1,148 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (c) 2016-2017 Fabian David Tschopp, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#define Dtype float
#define Dtype4 float4
__kernel void prior_box(const int nthreads,
const Dtype stepX,
const Dtype stepY,
const Dtype _minSize,
const Dtype _maxSize,
__global const Dtype* _offsetsX,
__global const Dtype* _offsetsY,
const int offsetsX_size,
__global const Dtype* _aspectRatios,
const int aspectRatios_size,
__global const Dtype* scales,
__global Dtype* dst,
const int _layerHeight,
const int _layerWidth,
const int imgHeight,
const int imgWidth)
{
for (int index = get_global_id(0); index < nthreads; index += get_global_size(0))
{
int w = index % _layerWidth;
int h = index / _layerWidth;
__global Dtype* outputPtr;
int aspect_count = (_maxSize > 0) ? 1 : 0;
outputPtr = dst + index * 4 * offsetsX_size * (1 + aspect_count + aspectRatios_size);
Dtype _boxWidth, _boxHeight;
Dtype4 vec;
_boxWidth = _boxHeight = _minSize * scales[0];
for (int i = 0; i < offsetsX_size; ++i)
{
float center_x = (w + _offsetsX[i]) * stepX;
float center_y = (h + _offsetsY[i]) * stepY;
vec.x = (center_x - _boxWidth * 0.5f) / imgWidth; // xmin
vec.y = (center_y - _boxHeight * 0.5f) / imgHeight; // ymin
vec.z = (center_x + _boxWidth * 0.5f) / imgWidth; // xmax
vec.w = (center_y + _boxHeight * 0.5f) / imgHeight; // ymax
vstore4(vec, 0, outputPtr);
outputPtr += 4;
}
if (_maxSize > 0)
{
_boxWidth = _boxHeight = native_sqrt(_minSize * _maxSize) * scales[1];
for (int i = 0; i < offsetsX_size; ++i)
{
float center_x = (w + _offsetsX[i]) * stepX;
float center_y = (h + _offsetsY[i]) * stepY;
vec.x = (center_x - _boxWidth * 0.5f) / imgWidth; // xmin
vec.y = (center_y - _boxHeight * 0.5f) / imgHeight; // ymin
vec.z = (center_x + _boxWidth * 0.5f) / imgWidth; // xmax
vec.w = (center_y + _boxHeight * 0.5f) / imgHeight; // ymax
vstore4(vec, 0, outputPtr);
outputPtr += 4;
}
}
for (int r = 0; r < aspectRatios_size; ++r)
{
float ar = native_sqrt(_aspectRatios[r]);
float scale = scales[(_maxSize > 0 ? 2 : 1) + r];
_boxWidth = _minSize * ar * scale;
_boxHeight = _minSize / ar * scale;
for (int i = 0; i < offsetsX_size; ++i)
{
float center_x = (w + _offsetsX[i]) * stepX;
float center_y = (h + _offsetsY[i]) * stepY;
vec.x = (center_x - _boxWidth * 0.5f) / imgWidth; // xmin
vec.y = (center_y - _boxHeight * 0.5f) / imgHeight; // ymin
vec.z = (center_x + _boxWidth * 0.5f) / imgWidth; // xmax
vec.w = (center_y + _boxHeight * 0.5f) / imgHeight; // ymax
vstore4(vec, 0, outputPtr);
outputPtr += 4;
}
}
}
}
__kernel void set_variance(const int nthreads,
const int offset,
const int variance_size,
__global const Dtype* variance,
__global Dtype* dst)
{
for (int index = get_global_id(0); index < nthreads; index += get_global_size(0))
{
Dtype4 var_vec;
if (variance_size == 1)
var_vec = (Dtype4)(variance[0]);
else
var_vec = vload4(0, variance);
vstore4(var_vec, 0, dst + offset + index * 4);
}
}
+190 -27
View File
@@ -42,6 +42,14 @@ namespace
static int toNCHW[] = {0, 2, 3, 1};
// This values are used to indicate layer output's data layout where it's possible.
enum DataLayout
{
DATA_LAYOUT_NHWC,
DATA_LAYOUT_NCHW,
DATA_LAYOUT_UNKNOWN
};
typedef std::vector<std::pair<String, int> > StrIntVector;
struct Pin
@@ -138,6 +146,11 @@ static Mat getTensorContent(const tensorflow::TensorProto &tensor)
convertFp16(halfsSigned, floats);
return floats;
}
case tensorflow::DT_QUINT8:
{
CV_Assert(!content.empty());
return Mat(1, content.size(), CV_8UC1, (void*)content.c_str()).clone();
}
default:
CV_Error(Error::StsError, "Tensor's data type is not supported");
break;
@@ -446,14 +459,13 @@ void ExcludeLayer(tensorflow::GraphDef& net, const int layer_index, const int in
net.mutable_node()->DeleteSubrange(layer_index, 1);
}
class TFImporter : public Importer {
class TFImporter {
public:
TFImporter(const char *model, const char *config = NULL);
TFImporter(const char *dataModel, size_t lenModel,
const char *dataConfig = NULL, size_t lenConfig = 0);
void populateNet(Net dstNet);
~TFImporter() {}
private:
void kernelFromTensor(const tensorflow::TensorProto &tensor, Mat &dstBlob);
@@ -589,7 +601,7 @@ const tensorflow::TensorProto& TFImporter::getConstBlob(const tensorflow::NodeDe
}
}
static void addConstNodes(const tensorflow::GraphDef& net, std::map<String, int>& const_layers,
static void addConstNodes(tensorflow::GraphDef& net, std::map<String, int>& const_layers,
std::set<String>& layers_to_ignore)
{
for (int li = 0; li < net.node_size(); li++)
@@ -598,7 +610,52 @@ static void addConstNodes(const tensorflow::GraphDef& net, std::map<String, int>
String name = layer.name();
String type = layer.op();
if (type != "Const")
if (type == "Dequantize")
{
// Example of Dequantize node:
// name: "conv2d_1/bias"
// op: "Dequantize"
// input: "conv2d_1/bias_quantized_const" (tensor of dtype DT_QUINT8)
// input: "conv2d_1/bias_quantized_min"
// input: "conv2d_1/bias_quantized_max"
// attr { key: "T" value { type: DT_QUINT8 } } (quantized type)
// attr { key: "mode" value { s: "MIN_FIRST" } } (quantization technique)
CV_Assert(layer.input_size() == 3);
for (int i = 0; i < 3; ++i)
CV_Assert(const_layers.find(layer.input(i)) != const_layers.end());
CV_Assert(hasLayerAttr(layer, "mode") &&
getLayerAttr(layer, "mode").s() == "MIN_FIRST");
int tensorId = const_layers[layer.input(0)];
int minId = const_layers[layer.input(1)];
int maxId = const_layers[layer.input(2)];
tensorflow::TensorProto* tensor = net.mutable_node(tensorId)
->mutable_attr()->at("value")
.mutable_tensor();
CV_Assert(tensor->dtype() == tensorflow::DT_QUINT8);
Mat qMin = getTensorContent(net.node(minId).attr().at("value").tensor());
Mat qMax = getTensorContent(net.node(maxId).attr().at("value").tensor());
CV_Assert(qMin.total() == 1, qMin.type() == CV_32FC1,
qMax.total() == 1, qMax.type() == CV_32FC1);
Mat content = getTensorContent(*tensor);
float minVal = qMin.at<float>(0);
float rangeScale = (qMax.at<float>(0) - minVal) / 255;
CV_Assert(rangeScale >= 0);
content.convertTo(content, CV_32FC1, rangeScale,
rangeScale * cvRound(minVal / rangeScale));
tensor->set_dtype(tensorflow::DT_FLOAT);
tensor->set_tensor_content(content.data, content.total() * content.elemSize1());
ExcludeLayer(net, li, 0, false);
layers_to_ignore.insert(name);
continue;
}
else if (type != "Const")
continue; // only Const parameters are supported
if (layer.attr().find("value") != layer.attr().end())
@@ -609,6 +666,31 @@ static void addConstNodes(const tensorflow::GraphDef& net, std::map<String, int>
}
}
// If all inputs of specific layer have the same data layout we can say that
// this layer's output has this data layout too. Returns DATA_LAYOUT_UNKNOWN otherwise.
static int predictOutputDataLayout(const tensorflow::NodeDef& layer, const std::map<String, int>& data_layouts)
{
int layout = DATA_LAYOUT_UNKNOWN;
std::map<String, int>::const_iterator it;
for (int i = 0, n = layer.input_size(); i < n; ++i)
{
it = data_layouts.find(layer.input(i));
if (it != data_layouts.end())
{
if (it->second == DATA_LAYOUT_UNKNOWN)
return DATA_LAYOUT_UNKNOWN;
else if (it->second != layout)
{
if (layout == DATA_LAYOUT_UNKNOWN)
layout = it->second;
else
return DATA_LAYOUT_UNKNOWN;
}
}
}
return layout;
}
void TFImporter::populateNet(Net dstNet)
{
RemoveIdentityOps(netBin);
@@ -620,6 +702,8 @@ void TFImporter::populateNet(Net dstNet)
int layersSize = net.node_size();
std::map<String, int> data_layouts;
// find all Const layers for params
std::map<String, int> value_id;
addConstNodes(netBin, value_id, layers_to_ignore);
@@ -637,6 +721,8 @@ void TFImporter::populateNet(Net dstNet)
if(layers_to_ignore.find(name) != layers_to_ignore.end())
continue;
data_layouts[name] = predictOutputDataLayout(layer, data_layouts);
if (type == "Conv2D" || type == "SpaceToBatchND" || type == "DepthwiseConv2dNative")
{
// The first node of dilated convolution subgraph.
@@ -732,6 +818,19 @@ void TFImporter::populateNet(Net dstNet)
// one input only
connect(layer_id, dstNet, parsePin(input), id, 0);
if (hasLayerAttr(layer, "data_format"))
{
std::string format = getLayerAttr(layer, "data_format").s();
if (format == "NHWC")
data_layouts[name] = DATA_LAYOUT_NHWC;
else if (format == "NCHW")
data_layouts[name] = DATA_LAYOUT_NCHW;
else
CV_Error(Error::StsParseError, "Unknown data_format value: " + format);
}
else
data_layouts[name] = DATA_LAYOUT_NHWC;
}
else if (type == "BiasAdd" || type == "Add")
{
@@ -807,22 +906,55 @@ void TFImporter::populateNet(Net dstNet)
// one input only
int input_blob_index = kernel_blob_index == 0 ? 1 : 0;
connect(layer_id, dstNet, parsePin(layer.input(input_blob_index)), id, 0);
data_layouts[name] = DATA_LAYOUT_UNKNOWN;
}
else if (type == "Reshape")
{
layerParams.set("dim", parseDims(getConstBlob(layer, value_id, 1)));
Pin inpId = parsePin(layer.input(0));
DictValue newShape = parseDims(getConstBlob(layer, value_id, 1));
if (newShape.size() != 4 && data_layouts[layer.input(0)] == DATA_LAYOUT_NHWC)
{
LayerParams permLP;
int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC.
permLP.set("order", DictValue::arrayInt<int*>(order, 4));
std::string permName = name + "/nchw";
CV_Assert(layer_id.find(permName) == layer_id.end());
int permId = dstNet.addLayer(permName, "Permute", permLP);
layer_id[permName] = permId;
connect(layer_id, dstNet, inpId, permId, 0);
inpId = Pin(permName);
}
layerParams.set("dim", newShape);
int id = dstNet.addLayer(name, "Reshape", layerParams);
layer_id[name] = id;
// one input only
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
connect(layer_id, dstNet, inpId, id, 0);
data_layouts[name] = DATA_LAYOUT_UNKNOWN;
}
else if (type == "Flatten")
{
Pin inpId = parsePin(layer.input(0));
if (data_layouts[layer.input(0)] == DATA_LAYOUT_NHWC)
{
LayerParams permLP;
int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC.
permLP.set("order", DictValue::arrayInt<int*>(order, 4));
std::string permName = name + "/nchw";
CV_Assert(layer_id.find(permName) == layer_id.end());
int permId = dstNet.addLayer(permName, "Permute", permLP);
layer_id[permName] = permId;
connect(layer_id, dstNet, inpId, permId, 0);
inpId = Pin(permName);
}
int id = dstNet.addLayer(name, "Flatten", layerParams);
layer_id[name] = id;
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
connect(layer_id, dstNet, inpId, id, 0);
data_layouts[name] = DATA_LAYOUT_UNKNOWN;
}
else if (type == "Transpose")
{
@@ -831,16 +963,57 @@ void TFImporter::populateNet(Net dstNet)
int* permData = (int*)perm.data;
if (perm.total() == 4)
{
for (int i = 0; i < 4; ++i)
permData[i] = toNCHW[permData[i]];
// Only NHWC <-> NCHW permutations are allowed. OpenCV is always
// keep NCHW layout this way.
if (data_layouts[layer.input(0)] == DATA_LAYOUT_NHWC)
{
if (permData[0] == 0 && permData[1] == 3 && permData[2] == 1 && permData[3] == 2)
{
// in TensorFlow: NHWC->NCHW
// in OpenCV: NCHW->NCHW
data_layouts[name] = DATA_LAYOUT_NCHW;
}
else if (permData[0] == 0 && permData[1] == 1 && permData[2] == 2 && permData[3] == 3)
{
// in TensorFlow: NHWC->NHWC
// in OpenCV: NCHW->NCHW
data_layouts[name] = DATA_LAYOUT_NHWC;
}
else
CV_Error(Error::StsParseError, "Only NHWC <-> NCHW permutations are allowed.");
}
else if (data_layouts[layer.input(0)] == DATA_LAYOUT_NCHW)
{
if (permData[0] == 0 && permData[1] == 2 && permData[2] == 3 && permData[3] == 1)
{
// in TensorFlow: NCHW->NHWC
// in OpenCV: NCHW->NCHW
data_layouts[name] = DATA_LAYOUT_NHWC;
}
else if (permData[0] == 0 && permData[1] == 1 && permData[2] == 2 && permData[3] == 3)
{
// in TensorFlow: NCHW->NCHW
// in OpenCV: NCHW->NCHW
data_layouts[name] = DATA_LAYOUT_NCHW;
}
else
CV_Error(Error::StsParseError, "Only NHWC <-> NCHW permutations are allowed.");
}
int id = dstNet.addLayer(name, "Identity", layerParams);
layer_id[name] = id;
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
}
layerParams.set("order", DictValue::arrayInt<int*>(permData, perm.total()));
else
{
layerParams.set("order", DictValue::arrayInt<int*>(permData, perm.total()));
int id = dstNet.addLayer(name, "Permute", layerParams);
layer_id[name] = id;
int id = dstNet.addLayer(name, "Permute", layerParams);
layer_id[name] = id;
// one input only
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
// one input only
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
data_layouts[name] = DATA_LAYOUT_UNKNOWN;
}
}
else if (type == "Const")
{
@@ -1208,6 +1381,7 @@ void TFImporter::populateNet(Net dstNet)
// one input only
connect(layer_id, dstNet, parsePin(layer.input(1)), id, 0);
data_layouts[name] = DATA_LAYOUT_UNKNOWN;
}
else if (type == "ResizeNearestNeighbor")
{
@@ -1259,6 +1433,7 @@ void TFImporter::populateNet(Net dstNet)
layer_id[name] = id;
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
connect(layer_id, dstNet, parsePin(layer.input(1)), id, 1);
data_layouts[name] = DATA_LAYOUT_UNKNOWN;
}
else if (type == "DetectionOutput")
{
@@ -1289,6 +1464,7 @@ void TFImporter::populateNet(Net dstNet)
layer_id[name] = id;
for (int i = 0; i < 3; ++i)
connect(layer_id, dstNet, parsePin(layer.input(i)), id, i);
data_layouts[name] = DATA_LAYOUT_UNKNOWN;
}
else if (type == "Abs" || type == "Tanh" || type == "Sigmoid" ||
type == "Relu" || type == "Elu" || type == "Softmax" ||
@@ -1315,19 +1491,6 @@ void TFImporter::populateNet(Net dstNet)
} // namespace
Ptr<Importer> createTensorflowImporter(const String &model)
{
return Ptr<Importer>(new TFImporter(model.c_str()));
}
#else //HAVE_PROTOBUF
Ptr<Importer> createTensorflowImporter(const String&)
{
CV_Error(cv::Error::StsNotImplemented, "libprotobuf required to import data from TensorFlow models");
return Ptr<Importer>();
}
#endif //HAVE_PROTOBUF
Net readNetFromTensorflow(const String &model, const String &config)
-2
View File
@@ -1,5 +1,4 @@
#include "../precomp.hpp"
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
#include "THGeneral.h"
#include "THDiskFile.h"
#include "THFilePrivate.h"
@@ -517,4 +516,3 @@ THFile *THDiskFile_new(const std::string &name, const char *mode, int isQuiet)
}
}
#endif
-2
View File
@@ -1,5 +1,4 @@
#include "../precomp.hpp"
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
#include "THFile.h"
#include "THFilePrivate.h"
@@ -119,4 +118,3 @@ IMPLEMENT_THFILE_SCALAR(Float, float)
IMPLEMENT_THFILE_SCALAR(Double, double)
} // namespace
#endif
-2
View File
@@ -2,7 +2,6 @@
#define TH_FILE_INC
//#include "THStorage.h"
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
#include "opencv2/core/hal/interface.h"
#include "THGeneral.h"
@@ -51,5 +50,4 @@ TH_API long THFile_position(THFile *self);
TH_API void THFile_close(THFile *self);
TH_API void THFile_free(THFile *self);
} // namespace
#endif //defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
#endif //TH_FILE_INC
-3
View File
@@ -1,5 +1,4 @@
#include "../precomp.hpp"
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
#if defined(TH_DISABLE_HEAP_TRACKING)
#elif (defined(__unix) || defined(_WIN32))
@@ -9,5 +8,3 @@
#endif
#include "THGeneral.h"
#endif
+5 -36
View File
@@ -47,15 +47,12 @@
#include <iostream>
#include <fstream>
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
#include "THDiskFile.h"
#endif
namespace cv {
namespace dnn {
CV__DNN_EXPERIMENTAL_NS_BEGIN
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
using namespace TH;
//#ifdef NDEBUG
@@ -95,7 +92,7 @@ static inline bool endsWith(const String &str, const char *substr)
return str.rfind(substr) == str.length() - strlen(substr);
}
struct TorchImporter : public ::cv::dnn::Importer
struct TorchImporter
{
typedef std::map<String, std::pair<int, Mat> > TensorsMap;
Net net;
@@ -1191,19 +1188,13 @@ struct TorchImporter : public ::cv::dnn::Importer
}
};
Ptr<Importer> createTorchImporter(const String &filename, bool isBinary)
{
return Ptr<Importer>(new TorchImporter(filename, isBinary));
}
Mat readTorchBlob(const String &filename, bool isBinary)
{
Ptr<TorchImporter> importer(new TorchImporter(filename, isBinary));
importer->readObject();
CV_Assert(importer->tensors.size() == 1);
TorchImporter importer(filename, isBinary);
importer.readObject();
CV_Assert(importer.tensors.size() == 1);
return importer->tensors.begin()->second;
return importer.tensors.begin()->second;
}
Net readNetFromTorch(const String &model, bool isBinary)
@@ -1216,27 +1207,5 @@ Net readNetFromTorch(const String &model, bool isBinary)
return net;
}
#else
Ptr<Importer> createTorchImporter(const String&, bool)
{
CV_Error(Error::StsNotImplemented, "Torch importer is disabled in current build");
return Ptr<Importer>();
}
Mat readTorchBlob(const String&, bool)
{
CV_Error(Error::StsNotImplemented, "Torch importer is disabled in current build");
return Mat();
}
Net readNetFromTorch(const String &model, bool isBinary)
{
CV_Error(Error::StsNotImplemented, "Torch importer is disabled in current build");
return Net();
}
#endif //defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
CV__DNN_EXPERIMENTAL_NS_END
}} // namespace
+46
View File
@@ -11,6 +11,8 @@ Test for Tensorflow models loading
#include "test_precomp.hpp"
#include "npy_blob.hpp"
#include <opencv2/core/ocl.hpp>
#include <opencv2/ts/ocl_test.hpp>
namespace cvtest
{
@@ -157,6 +159,8 @@ TEST(Test_TensorFlow, deconvolution)
TEST(Test_TensorFlow, matmul)
{
runTensorFlowNet("matmul");
runTensorFlowNet("nhwc_reshape_matmul");
runTensorFlowNet("nhwc_transpose_reshape_matmul");
}
TEST(Test_TensorFlow, defun)
@@ -186,6 +190,11 @@ TEST(Test_TensorFlow, fp16)
runTensorFlowNet("fp16_padding_same", false, l1, lInf);
}
TEST(Test_TensorFlow, quantized)
{
runTensorFlowNet("uint8_single_conv");
}
TEST(Test_TensorFlow, MobileNet_SSD)
{
std::string netPath = findDataFile("dnn/ssd_mobilenet_v1_coco.pb", false);
@@ -219,6 +228,43 @@ TEST(Test_TensorFlow, MobileNet_SSD)
normAssert(target[2].reshape(1, 1), output[2].reshape(1, 1), "", 4e-5, 1e-2);
}
OCL_TEST(Test_TensorFlow, MobileNet_SSD)
{
std::string netPath = findDataFile("dnn/ssd_mobilenet_v1_coco.pb", false);
std::string netConfig = findDataFile("dnn/ssd_mobilenet_v1_coco.pbtxt", false);
std::string imgPath = findDataFile("dnn/street.png", false);
Mat inp;
resize(imread(imgPath), inp, Size(300, 300));
inp = blobFromImage(inp, 1.0f / 127.5, Size(), Scalar(127.5, 127.5, 127.5), true);
std::vector<String> outNames(3);
outNames[0] = "concat";
outNames[1] = "concat_1";
outNames[2] = "detection_out";
std::vector<Mat> target(outNames.size());
for (int i = 0; i < outNames.size(); ++i)
{
std::string path = findDataFile("dnn/tensorflow/ssd_mobilenet_v1_coco." + outNames[i] + ".npy", false);
target[i] = blobFromNPY(path);
}
Net net = readNetFromTensorflow(netPath, netConfig);
net.setPreferableBackend(DNN_BACKEND_DEFAULT);
net.setPreferableTarget(DNN_TARGET_OPENCL);
net.setInput(inp);
std::vector<Mat> output;
net.forward(output, outNames);
normAssert(target[0].reshape(1, 1), output[0].reshape(1, 1));
normAssert(target[1].reshape(1, 1), output[1].reshape(1, 1), "", 1e-5, 2e-4);
normAssert(target[2].reshape(1, 1), output[2].reshape(1, 1), "", 4e-5, 1e-2);
}
TEST(Test_TensorFlow, lstm)
{
runTensorFlowNet("lstm", true);
+2 -7
View File
@@ -39,8 +39,6 @@
//
//M*/
#ifdef ENABLE_TORCH_IMPORTER
#include "test_precomp.hpp"
#include "npy_blob.hpp"
#include <opencv2/dnn/shape_utils.hpp>
@@ -316,9 +314,8 @@ OCL_TEST(Torch_Importer, ENet_accuracy)
Net net;
{
const string model = findDataFile("dnn/Enet-model-best.net", false);
Ptr<Importer> importer = createTorchImporter(model, true);
ASSERT_TRUE(importer != NULL);
importer->populateNet(net);
net = readNetFromTorch(model, true);
ASSERT_TRUE(!net.empty());
}
net.setPreferableBackend(DNN_BACKEND_DEFAULT);
@@ -421,5 +418,3 @@ OCL_TEST(Torch_Importer, FastNeuralStyle_accuracy)
}
}
#endif
-4
View File
@@ -45,10 +45,6 @@ The references are:
#include "precomp.hpp"
#include "agast_score.hpp"
#ifdef _MSC_VER
#pragma warning( disable : 4127 )
#endif
namespace cv
{
-4
View File
@@ -44,10 +44,6 @@ The references are:
#include "agast_score.hpp"
#ifdef _MSC_VER
#pragma warning( disable : 4127 )
#endif
namespace cv
{
-3
View File
@@ -48,9 +48,6 @@ The references are:
#include "opencv2/core/hal/intrin.hpp"
#include "opencv2/core/openvx/ovx_defs.hpp"
#if defined _MSC_VER
# pragma warning( disable : 4127)
#endif
namespace cv
{
-7
View File
@@ -78,18 +78,11 @@ extern "C" {
namespace cv
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4324) //structure was padded due to __declspec(align())
#endif
struct JpegErrorMgr
{
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
struct JpegSource
{
+1 -1
View File
@@ -333,7 +333,7 @@ bool PxMDecoder::readData( Mat& img )
}
}
else
memcpy( data, src, CV_ELEM_SIZE1(m_type)*m_width);
memcpy(data, src, img.elemSize1()*m_width);
}
else
{
+20
View File
@@ -12,7 +12,12 @@ typedef TestBaseWithParam<MatInfo_Size_Size_t> MatInfo_Size_Size;
PERF_TEST_P(MatInfo_Size_Size, resizeUpLinear,
testing::Values(
MatInfo_Size_Size_t(CV_8UC1, szVGA, szqHD),
MatInfo_Size_Size_t(CV_8UC2, szVGA, szqHD),
MatInfo_Size_Size_t(CV_8UC3, szVGA, szqHD),
MatInfo_Size_Size_t(CV_8UC4, szVGA, szqHD),
MatInfo_Size_Size_t(CV_8UC1, szVGA, sz720p),
MatInfo_Size_Size_t(CV_8UC2, szVGA, sz720p),
MatInfo_Size_Size_t(CV_8UC3, szVGA, sz720p),
MatInfo_Size_Size_t(CV_8UC4, szVGA, sz720p)
)
)
@@ -37,9 +42,24 @@ PERF_TEST_P(MatInfo_Size_Size, resizeUpLinear,
PERF_TEST_P(MatInfo_Size_Size, resizeDownLinear,
testing::Values(
MatInfo_Size_Size_t(CV_8UC1, szVGA, szQVGA),
MatInfo_Size_Size_t(CV_8UC2, szVGA, szQVGA),
MatInfo_Size_Size_t(CV_8UC3, szVGA, szQVGA),
MatInfo_Size_Size_t(CV_8UC4, szVGA, szQVGA),
MatInfo_Size_Size_t(CV_8UC1, szqHD, szVGA),
MatInfo_Size_Size_t(CV_8UC2, szqHD, szVGA),
MatInfo_Size_Size_t(CV_8UC3, szqHD, szVGA),
MatInfo_Size_Size_t(CV_8UC4, szqHD, szVGA),
MatInfo_Size_Size_t(CV_8UC1, sz720p, Size(120 * sz720p.width / sz720p.height, 120)),//face detection min_face_size = 20%
MatInfo_Size_Size_t(CV_8UC2, sz720p, Size(120 * sz720p.width / sz720p.height, 120)),//face detection min_face_size = 20%
MatInfo_Size_Size_t(CV_8UC3, sz720p, Size(120 * sz720p.width / sz720p.height, 120)),//face detection min_face_size = 20%
MatInfo_Size_Size_t(CV_8UC4, sz720p, Size(120 * sz720p.width / sz720p.height, 120)),//face detection min_face_size = 20%
MatInfo_Size_Size_t(CV_8UC1, sz720p, szVGA),
MatInfo_Size_Size_t(CV_8UC2, sz720p, szVGA),
MatInfo_Size_Size_t(CV_8UC3, sz720p, szVGA),
MatInfo_Size_Size_t(CV_8UC4, sz720p, szVGA),
MatInfo_Size_Size_t(CV_8UC1, sz720p, szQVGA),
MatInfo_Size_Size_t(CV_8UC2, sz720p, szQVGA),
MatInfo_Size_Size_t(CV_8UC3, sz720p, szQVGA),
MatInfo_Size_Size_t(CV_8UC4, sz720p, szQVGA)
)
)
+5 -5
View File
@@ -47,10 +47,6 @@
#include "opencv2/core/openvx/ovx_defs.hpp"
#ifdef _MSC_VER
#pragma warning( disable: 4127 ) // conditional expression is constant
#endif
#if CV_SIMD128
#define CV_MALLOC_SIMD128 16
#endif
@@ -956,7 +952,11 @@ void Canny( InputArray _src, OutputArray _dst,
CV_OCL_RUN(_dst.isUMat() && (_src.channels() == 1 || _src.channels() == 3),
ocl_Canny<false>(_src, UMat(), UMat(), _dst, (float)low_thresh, (float)high_thresh, aperture_size, L2gradient, _src.channels(), size))
Mat src = _src.getMat(), dst = _dst.getMat();
Mat src0 = _src.getMat(), dst = _dst.getMat();
Mat src(src0.size(), src0.type(), src0.data, src0.step);
CALL_HAL(canny, cv_hal_canny, src.data, src.step, dst.data, dst.step, src.cols, src.rows, src.channels(),
low_thresh, high_thresh, aperture_size, L2gradient);
CV_OVX_RUN(
false && /* disabling due to accuracy issues */
+16
View File
@@ -756,6 +756,22 @@ inline int hal_ni_pyrdown(const uchar* src_data, size_t src_step, int src_width,
#define cv_hal_pyrdown hal_ni_pyrdown
//! @endcond
/**
@brief Canny edge detector
@param src_data,src_step Source image
@param dst_data,dst_step Destination image
@param width,height Source image dimensions
@param cn Number of channels
@param lowThreshold, highThreshold Thresholds value
@param ksize Kernel size for Sobel operator.
@param L2gradient Flag, indicating use L2 or L1 norma.
*/
inline int hal_ni_canny(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int cn, double lowThreshold, double highThreshold, int ksize, bool L2gradient) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
//! @cond IGNORED
#define cv_hal_canny hal_ni_canny
//! @endcond
//! @}
#if defined __GNUC__
+4
View File
@@ -877,7 +877,11 @@ __kernel void RGB(__global const uchar* srcptr, int src_step, int src_offset,
{
__global const DATA_TYPE * src = (__global const DATA_TYPE *)(srcptr + src_index);
__global DATA_TYPE * dst = (__global DATA_TYPE *)(dstptr + dst_index);
#if scn == 3
DATA_TYPE_3 src_pix = vload3(0, src);
#else
DATA_TYPE_4 src_pix = vload4(0, src);
#endif
#ifdef REVERSE
dst[0] = src_pix.z;
+124 -16
View File
@@ -356,7 +356,7 @@ void hlineResizeCn<uint8_t, ufixedpoint16, 2, true, 1>(uint8_t* src, int, int *o
}
for (; i < dst_max - 7 && ofst[i + 7] + 15 <= ofst[dst_width - 1]; i += 8, m += 16, dst += 8)
{
v_uint32x4 v_src01 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + ofst[i])), v_reinterpret_as_u32(v_load_expand(src + ofst[i + 1])));
v_uint32x4 v_src01 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + ofst[i ])), v_reinterpret_as_u32(v_load_expand(src + ofst[i + 1])));
v_uint32x4 v_src23 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + ofst[i + 2])), v_reinterpret_as_u32(v_load_expand(src + ofst[i + 3])));
v_uint32x4 v_src45 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + ofst[i + 4])), v_reinterpret_as_u32(v_load_expand(src + ofst[i + 5])));
v_uint32x4 v_src67 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + ofst[i + 6])), v_reinterpret_as_u32(v_load_expand(src + ofst[i + 7])));
@@ -390,18 +390,123 @@ void hlineResizeCn<uint8_t, ufixedpoint16, 2, true, 1>(uint8_t* src, int, int *o
*(dst++) = src_0;
}
}
template <>
void hlineResizeCn<uint8_t, ufixedpoint16, 2, true, 2>(uint8_t* src, int, int *ofst, ufixedpoint16* m, ufixedpoint16* dst, int dst_min, int dst_max, int dst_width)
{
int i = 0;
ufixedpoint16 srccn[8] = { src[0], src[1], src[0], src[1], src[0], src[1], src[0], src[1] };
v_uint16x8 v_srccn = v_load((uint16_t*)srccn);
for (; i < dst_min - 3; i += 4, m += 8, dst += 8) // Points that fall left from src image so became equal to leftmost src point
{
v_store((uint16_t*)dst, v_srccn);
}
for (; i < dst_min; i++, m += 2)
{
*(dst++) = srccn[0];
*(dst++) = srccn[1];
}
for (; i < dst_max - 3 && ofst[i + 3] + 7 <= ofst[dst_width - 1]; i += 4, m += 8, dst += 8)
{
v_uint32x4 v_src0 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + 2 * ofst[i ])), v_reinterpret_as_u32(v_load_expand(src + 2 * ofst[i + 1])));
v_uint32x4 v_src1 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + 2 * ofst[i + 2])), v_reinterpret_as_u32(v_load_expand(src + 2 * ofst[i + 3])));
v_uint32x4 v_zip0, v_zip1;
v_zip(v_src0, v_src1, v_zip0, v_zip1);
v_zip(v_zip0, v_zip1, v_src0, v_src1);
v_int16x8 v_src0123, v_src4567;
v_zip(v_reinterpret_as_s16(v_src0), v_reinterpret_as_s16(v_src1), v_src0123, v_src4567);
v_uint32x4 v_mul = v_load((uint32_t*)m);//AaBbCcDd
v_zip(v_mul, v_mul, v_zip0, v_zip1);//AaAaBbBb CcCcDdDd
v_uint32x4 v_res0 = v_reinterpret_as_u32(v_dotprod(v_src0123, v_reinterpret_as_s16(v_zip0)));
v_uint32x4 v_res1 = v_reinterpret_as_u32(v_dotprod(v_src4567, v_reinterpret_as_s16(v_zip1)));
v_store((uint16_t*)dst, v_pack(v_res0, v_res1));//AB1AB2CD1CD2
}
for (; i < dst_max; i += 1, m += 2)
{
uint8_t* px = src + 2 * ofst[i];
*(dst++) = m[0] * px[0] + m[1] * px[2];
*(dst++) = m[0] * px[1] + m[1] * px[3];
}
srccn[0] = (src + 2 * ofst[dst_width - 1])[0]; srccn[1] = (src + 2 * ofst[dst_width - 1])[1]; srccn[2] = (src + 2 * ofst[dst_width - 1])[0]; srccn[3] = (src + 2 * ofst[dst_width - 1])[1];
srccn[4] = (src + 2 * ofst[dst_width - 1])[0]; srccn[5] = (src + 2 * ofst[dst_width - 1])[1]; srccn[6] = (src + 2 * ofst[dst_width - 1])[0]; srccn[7] = (src + 2 * ofst[dst_width - 1])[1];
v_srccn = v_load((uint16_t*)srccn);
for (; i < dst_width - 3; i += 4, dst += 8) // Points that fall left from src image so became equal to leftmost src point
{
v_store((uint16_t*)dst, v_srccn);
}
for (; i < dst_width; i++)
{
*(dst++) = srccn[0];
*(dst++) = srccn[1];
}
}
template <>
void hlineResizeCn<uint8_t, ufixedpoint16, 2, true, 4>(uint8_t* src, int, int *ofst, ufixedpoint16* m, ufixedpoint16* dst, int dst_min, int dst_max, int dst_width)
{
int i = 0;
ufixedpoint16 srccn[8] = { src[0], src[1], src[2], src[3], src[0], src[1], src[2], src[3] };
v_uint16x8 v_srccn = v_load((uint16_t*)srccn);
for (; i < dst_min - 1; i += 2, m += 4, dst += 8) // Points that fall left from src image so became equal to leftmost src point
{
v_store((uint16_t*)dst, v_srccn);
}
if (i < dst_min) // Points that fall left from src image so became equal to leftmost src point
{
*(dst++) = srccn[0];
*(dst++) = srccn[1];
*(dst++) = srccn[2];
*(dst++) = srccn[3];
i++; m += 2;
}
for (; i < dst_max - 1 && ofst[i + 1] + 3 <= ofst[dst_width - 1]; i += 2, m += 4, dst += 8)
{
v_int16x8 v_src01 = v_reinterpret_as_s16(v_load_expand(src + 4 * ofst[i ]));
v_int16x8 v_src23 = v_reinterpret_as_s16(v_load_expand(src + 4 * ofst[i + 1]));
v_int16x8 v_tmp0, v_tmp1;
v_recombine(v_src01, v_src23, v_tmp0, v_tmp1);
v_zip(v_tmp0, v_tmp1, v_src01, v_src23);
v_int16x8 v_mul01 = v_reinterpret_as_s16(v_setall_u32(((uint32_t*)m)[0]));//AaAaAaAa
v_int16x8 v_mul23 = v_reinterpret_as_s16(v_setall_u32(((uint32_t*)m)[1]));//BbBbBbBb
v_uint32x4 v_res0 = v_reinterpret_as_u32(v_dotprod(v_src01, v_mul01));
v_uint32x4 v_res1 = v_reinterpret_as_u32(v_dotprod(v_src23, v_mul23));
v_store((uint16_t*)dst, v_pack(v_res0, v_res1));//AB1AB2CD1CD2
}
for (; i < dst_max; i += 1, m += 2)
{
uint8_t* px = src + 4 * ofst[i];
*(dst++) = m[0] * px[0] + m[1] * px[4];
*(dst++) = m[0] * px[1] + m[1] * px[5];
*(dst++) = m[0] * px[2] + m[1] * px[6];
*(dst++) = m[0] * px[3] + m[1] * px[7];
}
srccn[0] = (src + 4 * ofst[dst_width - 1])[0]; srccn[1] = (src + 4 * ofst[dst_width - 1])[1]; srccn[2] = (src + 4 * ofst[dst_width - 1])[2]; srccn[3] = (src + 4 * ofst[dst_width - 1])[3];
srccn[4] = (src + 4 * ofst[dst_width - 1])[0]; srccn[5] = (src + 4 * ofst[dst_width - 1])[1]; srccn[6] = (src + 4 * ofst[dst_width - 1])[2]; srccn[7] = (src + 4 * ofst[dst_width - 1])[3];
v_srccn = v_load((uint16_t*)srccn);
for (; i < dst_width - 1; i += 2, dst += 8) // Points that fall right from src image so became equal to rightmost src point
{
v_store((uint16_t*)dst, v_srccn);
}
if (i < dst_width)
{
*(dst++) = srccn[0];
*(dst++) = srccn[1];
*(dst++) = srccn[2];
*(dst++) = srccn[3];
}
}
template <>
void hlineResizeCn<uint16_t, ufixedpoint32, 2, true, 1>(uint16_t* src, int, int *ofst, ufixedpoint32* m, ufixedpoint32* dst, int dst_min, int dst_max, int dst_width)
{
typedef v_uint32x4 v_fixedtype;
typedef uint32_t lanetype;
int i = 0;
ufixedpoint32 src_0(src[0]);
v_fixedtype v_src_0 = v_setall_u32(*((lanetype*)&src_0));
v_uint32x4 v_src_0 = v_setall_u32(*((uint32_t*)&src_0));
for (; i < dst_min - 3; i += 4, m += 8, dst += 4) // Points that fall left from src image so became equal to leftmost src point
{
v_store((lanetype*)dst, v_src_0);
v_store((uint32_t*)dst, v_src_0);
}
for (; i < dst_min; i++, m += 2)
{
@@ -409,17 +514,17 @@ void hlineResizeCn<uint16_t, ufixedpoint32, 2, true, 1>(uint16_t* src, int, int
}
for (; i < dst_max - 3 && ofst[i + 3] + 8 <= ofst[dst_width - 1]; i += 4, m += 8, dst += 4)
{
v_fixedtype v_src0 = v_combine_low(v_load_expand(src + ofst[i]), v_load_expand(src + ofst[i + 1]));
v_fixedtype v_mul0 = v_load((lanetype*)m);
v_fixedtype v_src1 = v_combine_low(v_load_expand(src + ofst[i + 2]), v_load_expand(src + ofst[i + 3]));
v_fixedtype v_mul1 = v_load((lanetype*)m + 4);
v_fixedtype v_res0 = v_src0 * v_mul0;//a1a2b1b2
v_fixedtype v_res1 = v_src1 * v_mul1;//c1c2d1d2
v_fixedtype v_tmp0, v_tmp1;
v_uint32x4 v_src0 = v_combine_low(v_load_expand(src + ofst[i]), v_load_expand(src + ofst[i + 1]));
v_uint32x4 v_mul0 = v_load((uint32_t*)m);
v_uint32x4 v_src1 = v_combine_low(v_load_expand(src + ofst[i + 2]), v_load_expand(src + ofst[i + 3]));
v_uint32x4 v_mul1 = v_load((uint32_t*)m + 4);
v_uint32x4 v_res0 = v_src0 * v_mul0;//a1a2b1b2
v_uint32x4 v_res1 = v_src1 * v_mul1;//c1c2d1d2
v_uint32x4 v_tmp0, v_tmp1;
v_recombine(v_res0, v_res1, v_tmp0, v_tmp1);//a1a2c1c2 b1b2d1d2
v_zip(v_tmp0, v_tmp1, v_res0, v_res1);//a1b1a2b2 c1d1c2d2
v_recombine(v_res0, v_res1, v_tmp0, v_tmp1);//a1b1c1d1 a2b2c2d2
v_store((lanetype*)dst, v_tmp0 + v_tmp1);//abcd
v_store((uint32_t*)dst, v_tmp0 + v_tmp1);//abcd
}
for (; i < dst_max; i += 1, m += 2)
{
@@ -427,10 +532,10 @@ void hlineResizeCn<uint16_t, ufixedpoint32, 2, true, 1>(uint16_t* src, int, int
*(dst++) = m[0] * px[0] + m[1] * px[1];
}
src_0 = (src + ofst[dst_width - 1])[0];
v_src_0 = v_setall_u32(*((lanetype*)&src_0));
v_src_0 = v_setall_u32(*((uint32_t*)&src_0));
for (; i < dst_width - 3; i += 4, dst += 4)
{
v_store((lanetype*)dst, v_src_0);
v_store((uint32_t*)dst, v_src_0);
}
for (; i < dst_width; i++)
{
@@ -3714,7 +3819,7 @@ void resize(int src_type,
{
// in case of inv_scale_x && inv_scale_y is equal to 0.5
// INTER_AREA (fast) is equal to bit exact INTER_LINEAR
if (is_area_fast && iscale_x == 2 && iscale_y == 2)
if (is_area_fast && iscale_x == 2 && iscale_y == 2 && cn != 2)//Area resize implementation for 2-channel images isn't bit-exact
interpolation = INTER_AREA;
else
{
@@ -3950,6 +4055,9 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
inv_scale_y = (double)dsize.height/ssize.height;
}
if (interpolation == INTER_LINEAR_EXACT && (_src.depth() == CV_32F || _src.depth() == CV_64F))
interpolation = INTER_LINEAR; // If depth isn't supported fallback to generic resize
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat() && _src.cols() > 10 && _src.rows() > 10,
ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation))
+52 -11
View File
@@ -26,18 +26,59 @@ TEST(Resize_Bitexact, Linear8U)
{
static const int64_t fixedOne = (1L << fixedShiftU8);
int types[] = { CV_8UC1, CV_8UC4 };
// NOTICE: 2x downscaling ommitted since it use different rounding
// 1/2 1 1 1/2 1/2 1/2 1/4 1/4 1/256 1/256 1/3 1/2 1/3 1/3 1/2 1/3 1/7 1/7
Size dstsizes[] = {Size(512, 768), Size(1024, 384), Size(512, 384), Size(256, 192), Size(4, 3), Size(342, 384), Size(342, 256), Size(512, 256), Size(146, 110),
// 10/11 10/11 10/12 10/12 251/256 2 2 3 3 7 7
Size(931, 698), Size(853, 640), Size(1004, 753), Size(2048,1536), Size(3072,2304), Size(7168,5376) };
struct testmode
{
int type;
Size sz;
} modes[] = {
{ CV_8UC1, Size( 512, 768) }, // 1/2 1
{ CV_8UC3, Size( 512, 768) },
{ CV_8UC1, Size(1024, 384) }, // 1 1/2
{ CV_8UC4, Size(1024, 384) },
{ CV_8UC1, Size( 512, 384) }, // 1/2 1/2
{ CV_8UC2, Size( 512, 384) },
{ CV_8UC3, Size( 512, 384) },
{ CV_8UC4, Size( 512, 384) },
{ CV_8UC1, Size( 256, 192) }, // 1/4 1/4
{ CV_8UC2, Size( 256, 192) },
{ CV_8UC3, Size( 256, 192) },
{ CV_8UC4, Size( 256, 192) },
{ CV_8UC1, Size( 4, 3) }, // 1/256 1/256
{ CV_8UC2, Size( 4, 3) },
{ CV_8UC3, Size( 4, 3) },
{ CV_8UC4, Size( 4, 3) },
{ CV_8UC1, Size( 342, 384) }, // 1/3 1/2
{ CV_8UC1, Size( 342, 256) }, // 1/3 1/3
{ CV_8UC1, Size( 342, 256) },
{ CV_8UC1, Size( 342, 256) },
{ CV_8UC1, Size( 342, 256) },
{ CV_8UC1, Size( 512, 256) }, // 1/2 1/3
{ CV_8UC1, Size( 146, 110) }, // 1/7 1/7
{ CV_8UC3, Size( 146, 110) },
{ CV_8UC4, Size( 146, 110) },
{ CV_8UC1, Size( 931, 698) }, // 10/11 10/11
{ CV_8UC2, Size( 931, 698) },
{ CV_8UC3, Size( 931, 698) },
{ CV_8UC4, Size( 931, 698) },
{ CV_8UC1, Size( 853, 640) }, // 10/12 10/12
{ CV_8UC3, Size( 853, 640) },
{ CV_8UC4, Size( 853, 640) },
{ CV_8UC1, Size(1004, 753) }, // 251/256 251/256
{ CV_8UC2, Size(1004, 753) },
{ CV_8UC3, Size(1004, 753) },
{ CV_8UC4, Size(1004, 753) },
{ CV_8UC1, Size(2048,1536) }, // 2 2
{ CV_8UC2, Size(2048,1536) },
{ CV_8UC4, Size(2048,1536) },
{ CV_8UC1, Size(3072,2304) }, // 3 3
{ CV_8UC3, Size(3072,2304) },
{ CV_8UC1, Size(7168,5376) } // 7 7
};
for (int dsizeind = 0, _dsizecnt = sizeof(dstsizes) / sizeof(dstsizes[0]); dsizeind < _dsizecnt; ++dsizeind)
for (int typeind = 0, _typecnt = sizeof(types) / sizeof(types[0]); typeind < _typecnt; ++typeind)
for (int modeind = 0, _modecnt = sizeof(modes) / sizeof(modes[0]); modeind < _modecnt; ++modeind)
{
int type = types[typeind], depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
int dcols = dstsizes[dsizeind].width, drows = dstsizes[dsizeind].height;
int type = modes[modeind].type, depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
int dcols = modes[modeind].sz.width, drows = modes[modeind].sz.height;
int cols = 1024, rows = 768;
double inv_scale_x = (double)dcols / cols;
@@ -111,7 +152,7 @@ TEST(Resize_Bitexact, Linear8U)
cv::resize(src, dst, Size(dcols, drows), 0, 0, cv::INTER_LINEAR_EXACT);
EXPECT_GE(0, cvtest::norm(refdst, dst, cv::NORM_L1))
<< "Resize from " << cols << "x" << rows << " to " << dcols << "x" << drows << " failed with max diff " << cvtest::norm(refdst, dst, cv::NORM_INF);
<< "Resize " << cn << "-chan mat from " << cols << "x" << rows << " to " << dcols << "x" << drows << " failed with max diff " << cvtest::norm(refdst, dst, cv::NORM_INF);
}
}
+26 -52
View File
@@ -1912,75 +1912,49 @@ public:
* Simulated annealing solver *
\****************************************************************************************/
/** @brief The class defines interface for system state used in simulated annealing optimization algorithm.
#ifdef CV_DOXYGEN
/** @brief This class declares example interface for system state used in simulated annealing optimization algorithm.
@cite Kirkpatrick83 for details
@note This class is not defined in C++ code and can't be use directly - you need your own implementation with the same methods.
*/
class CV_EXPORTS SimulatedAnnealingSolverSystem
struct SimulatedAnnealingSolverSystem
{
protected:
inline SimulatedAnnealingSolverSystem() {}
public:
virtual ~SimulatedAnnealingSolverSystem() {}
/** Give energy value for a state of system.*/
virtual double energy() const = 0;
double energy() const;
/** Function which change the state of system (random pertubation).*/
virtual void changeState() = 0;
void changeState();
/** Function to reverse to the previous state. Can be called once only after changeState(). */
virtual void reverseState() = 0;
void reverseState();
};
#endif // CV_DOXYGEN
/** @brief The class implements simulated annealing for optimization.
*
@cite Kirkpatrick83 for details
@param solverSystem optimization system (see SimulatedAnnealingSolverSystem)
@param initialTemperature initial temperature
@param finalTemperature final temperature
@param coolingRatio temperature step multiplies
@param iterationsPerStep number of iterations per temperature changing step
@param lastTemperature optional output for last used temperature
@param rngEnergy specify custom random numbers generator (cv::theRNG() by default)
*/
class CV_EXPORTS SimulatedAnnealingSolver : public Algorithm
{
public:
SimulatedAnnealingSolver(const Ptr<SimulatedAnnealingSolverSystem>& system);
inline ~SimulatedAnnealingSolver() { release(); }
/** Simulated annealing procedure. */
int run();
/** Set/initialize RNG (energy).
@param rng new RNG
*/
void setEnergyRNG(const RNG& rng);
/** Set initial temperature of simulated annealing procedure.
@param x new initial temperature. x\>0
*/
void setInitialTemperature(double x);
/** Set final temperature of simulated annealing procedure.
@param x new final temperature value. 0\<x\<initial temperature
*/
void setFinalTemperature(double x);
/** Get final temperature of simulated annealing procedure. */
double getFinalTemperature();
/** Set setCoolingRatio of simulated annealing procedure : T(t) = coolingRatio * T(t-1).
@param x new cooling ratio value. 0\<x\<1
*/
void setCoolingRatio(double x);
/** Set number iteration per temperature step.
@param ite number of iteration per temperature step ite \> 0
*/
void setIterPerStep(int ite);
void release();
SimulatedAnnealingSolver(const SimulatedAnnealingSolver&);
SimulatedAnnealingSolver& operator=(const SimulatedAnnealingSolver&);
struct Impl; friend struct Impl;
protected:
Impl* impl;
};
template<class SimulatedAnnealingSolverSystem>
int simulatedAnnealingSolver(SimulatedAnnealingSolverSystem& solverSystem,
double initialTemperature, double finalTemperature, double coolingRatio,
size_t iterationsPerStep,
CV_OUT double* lastTemperature = NULL,
cv::RNG& rngEnergy = cv::theRNG()
);
//! @} ml
}
}
#include <opencv2/ml/ml.inl.hpp>
#endif // __cplusplus
#endif // OPENCV_ML_HPP
+60
View File
@@ -0,0 +1,60 @@
// 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_ML_INL_HPP
#define OPENCV_ML_INL_HPP
namespace cv { namespace ml {
// declared in ml.hpp
template<class SimulatedAnnealingSolverSystem>
int simulatedAnnealingSolver(SimulatedAnnealingSolverSystem& solverSystem,
double initialTemperature, double finalTemperature, double coolingRatio,
size_t iterationsPerStep,
CV_OUT double* lastTemperature,
cv::RNG& rngEnergy
)
{
CV_Assert(finalTemperature > 0);
CV_Assert(initialTemperature > finalTemperature);
CV_Assert(iterationsPerStep > 0);
CV_Assert(coolingRatio < 1.0f);
double Ti = initialTemperature;
double previousEnergy = solverSystem.energy();
int exchange = 0;
while (Ti > finalTemperature)
{
for (size_t i = 0; i < iterationsPerStep; i++)
{
solverSystem.changeState();
double newEnergy = solverSystem.energy();
if (newEnergy < previousEnergy)
{
previousEnergy = newEnergy;
exchange++;
}
else
{
double r = rngEnergy.uniform(0.0, 1.0);
if (r < std::exp(-(newEnergy - previousEnergy) / Ti))
{
previousEnergy = newEnergy;
exchange++;
}
else
{
solverSystem.reverseState();
}
}
}
Ti *= coolingRatio;
}
if (lastTemperature)
*lastTemperature = Ti;
return exchange;
}
}} //namespace
#endif // OPENCV_ML_INL_HPP
+5 -156
View File
@@ -42,41 +42,6 @@
namespace cv { namespace ml {
struct SimulatedAnnealingSolver::Impl
{
int refcount;
const Ptr<SimulatedAnnealingSolverSystem> systemPtr;
SimulatedAnnealingSolverSystem& system;
RNG rEnergy;
double coolingRatio;
double initialT;
double finalT;
int iterPerStep;
Impl(const Ptr<SimulatedAnnealingSolverSystem>& s) :
refcount(1),
systemPtr(s),
system(*(s.get())),
rEnergy(12345)
{
CV_Assert(!systemPtr.empty());
initialT = 2;
finalT = 0.1;
coolingRatio = 0.95;
iterPerStep = 100;
}
inline double energy() { return system.energy(); }
inline void changeState() { system.changeState(); }
inline void reverseState() { system.reverseState(); }
void addref() { CV_XADD(&refcount, 1); }
void release() { if (CV_XADD(&refcount, -1) == 1) delete this; }
protected:
virtual ~Impl() { CV_Assert(refcount==0); }
};
struct AnnParams
{
AnnParams()
@@ -115,103 +80,7 @@ inline T inBounds(T val, T min_val, T max_val)
return std::min(std::max(val, min_val), max_val);
}
SimulatedAnnealingSolver::SimulatedAnnealingSolver(const Ptr<SimulatedAnnealingSolverSystem>& system)
{
impl = new Impl(system);
}
SimulatedAnnealingSolver::SimulatedAnnealingSolver(const SimulatedAnnealingSolver& b)
{
if (b.impl) b.impl->addref();
release();
impl = b.impl;
}
void SimulatedAnnealingSolver::release()
{
if (impl) { impl->release(); impl = NULL; }
}
void SimulatedAnnealingSolver::setIterPerStep(int ite)
{
CV_Assert(impl);
CV_Assert(ite>0);
impl->iterPerStep = ite;
}
int SimulatedAnnealingSolver::run()
{
CV_Assert(impl);
CV_Assert(impl->initialT>impl->finalT);
double Ti = impl->initialT;
double previousEnergy = impl->energy();
int exchange = 0;
while (Ti > impl->finalT)
{
for (int i = 0; i < impl->iterPerStep; i++)
{
impl->changeState();
double newEnergy = impl->energy();
if (newEnergy < previousEnergy)
{
previousEnergy = newEnergy;
//??? exchange++;
}
else
{
double r = impl->rEnergy.uniform(0.0, 1.0);
if (r < std::exp(-(newEnergy - previousEnergy) / Ti))
{
previousEnergy = newEnergy;
exchange++;
}
else
{
impl->reverseState();
}
}
}
Ti *= impl->coolingRatio;
}
impl->finalT = Ti;
return exchange;
}
void SimulatedAnnealingSolver::setEnergyRNG(const RNG& rng)
{
CV_Assert(impl);
impl->rEnergy = rng;
}
void SimulatedAnnealingSolver::setInitialTemperature(double x)
{
CV_Assert(impl);
CV_Assert(x>0);
impl->initialT = x;
}
void SimulatedAnnealingSolver::setFinalTemperature(double x)
{
CV_Assert(impl);
CV_Assert(x>0);
impl->finalT = x;
}
double SimulatedAnnealingSolver::getFinalTemperature()
{
CV_Assert(impl);
return impl->finalT;
}
void SimulatedAnnealingSolver::setCoolingRatio(double x)
{
CV_Assert(impl);
CV_Assert(x>0 && x<1);
impl->coolingRatio = x;
}
class SimulatedAnnealingANN_MLP : public SimulatedAnnealingSolverSystem
class SimulatedAnnealingANN_MLP
{
protected:
ml::ANN_MLP& nn;
@@ -228,7 +97,7 @@ public:
initVarMap();
}
~SimulatedAnnealingANN_MLP() {}
protected:
void changeState()
{
index = rIndex.uniform(0, nbVariables);
@@ -405,21 +274,6 @@ public:
param2 = 0.1;
params.bpMomentScale = std::min(param2, 1.);
}
/* else if (method == ANN_MLP::ANNEAL)
{
if (param1 <= 0)
param1 = 10;
if (param2 <= 0 || param2>param1)
param2 = 0.1;
if (param3 <= 0 || param3 >=1)
param3 = 0.95;
if (param4 <= 0)
param4 = 10;
params.initialT = param1;
params.finalT = param2;
params.coolingRatio = param3;
params.itePerStep = param4;
}*/
}
int getTrainMethod() const
@@ -1090,16 +944,11 @@ public:
}
int train_anneal(const Ptr<TrainData>& trainData)
{
SimulatedAnnealingSolver t(Ptr<SimulatedAnnealingANN_MLP>(new SimulatedAnnealingANN_MLP(*this, trainData)));
t.setEnergyRNG(params.rEnergy);
t.setFinalTemperature(params.finalT);
t.setInitialTemperature(params.initialT);
t.setCoolingRatio(params.coolingRatio);
t.setIterPerStep(params.itePerStep);
SimulatedAnnealingANN_MLP s(*this, trainData);
trained = true; // Enable call to CalcError
int iter = t.run();
int iter = simulatedAnnealingSolver(s, params.initialT, params.finalT, params.coolingRatio, params.itePerStep, NULL, params.rEnergy);
trained =false;
return iter;
return iter + 1; // ensure that 'train()' call is always successful
}
int train_backprop( const Mat& inputs, const Mat& outputs, const Mat& _sw, TermCriteria termCrit )
+13 -5
View File
@@ -94,26 +94,29 @@ public:
int idxErr = range.start;
CV_TRACE_FUNCTION_SKIP_NESTED();
Mat samples = data->getSamples();
Mat weights=testerr? data->getTestSampleWeights() : data->getTrainSampleWeights();
int layout = data->getLayout();
Mat sidx = testerr ? data->getTestSampleIdx() : data->getTrainSampleIdx();
const int* sidx_ptr = sidx.ptr<int>();
bool isclassifier = s.isClassifier();
Mat responses = data->getResponses();
int responses_type = responses.type();
double err = 0;
const float* sw = weights.empty() ? 0 : weights.ptr<float>();
for (int i = range.start; i < range.end; i++)
{
int si = sidx_ptr ? sidx_ptr[i] : i;
double sweight = sw ? static_cast<double>(sw[i]) : 1.;
Mat sample = layout == ROW_SAMPLE ? samples.row(si) : samples.col(si);
float val = s.predict(sample);
float val0 = (responses_type == CV_32S) ? (float)responses.at<int>(si) : responses.at<float>(si);
if (isclassifier)
err += fabs(val - val0) > FLT_EPSILON;
err += sweight * fabs(val - val0) > FLT_EPSILON;
else
err += (val - val0)*(val - val0);
err += sweight * (val - val0)*(val - val0);
if (!resp.empty())
resp.at<float>(i) = val;
}
@@ -133,12 +136,17 @@ float StatModel::calcError(const Ptr<TrainData>& data, bool testerr, OutputArray
CV_TRACE_FUNCTION_SKIP_NESTED();
Mat samples = data->getSamples();
Mat sidx = testerr ? data->getTestSampleIdx() : data->getTrainSampleIdx();
Mat weights = testerr ? data->getTestSampleWeights() : data->getTrainSampleWeights();
int n = (int)sidx.total();
bool isclassifier = isClassifier();
Mat responses = data->getResponses();
if (n == 0)
{
n = data->getNSamples();
weights = data->getTrainSampleWeights();
testerr =false;
}
if (n == 0)
return -FLT_MAX;
@@ -155,11 +163,11 @@ float StatModel::calcError(const Ptr<TrainData>& data, bool testerr, OutputArray
for (size_t i = 0; i < errStrip.size(); i++)
err += errStrip[i];
float weightSum= weights.empty() ? n: static_cast<float>(sum(weights)(0));
if (_resp.needed())
resp.copyTo(_resp);
return (float)(err / n * (isclassifier ? 100 : 1));
return (float)(err/ weightSum * (isclassifier ? 100 : 1));
}
/* Calculates upper triangular matrix S, where A is a symmetrical matrix A=S'*S */
+2 -2
View File
@@ -233,7 +233,7 @@ void Decolor::weak_order(Mat img, vector <double> &alf)
if((h + w) > 800)
{
sizefactor = (double)800/(h+w);
resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)), 0, 0, INTER_LINEAR_EXACT);
resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)));
}
Mat curIm = Mat(img.size(),CV_32FC1);
@@ -309,7 +309,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad,
if((h + w) > 800)
{
sizefactor = (double)800/(h+w);
resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)), 0, 0, INTER_LINEAR_EXACT);
resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)));
}
h = img.size().height;
-1
View File
@@ -34,7 +34,6 @@
#endif
#ifdef _MSC_VER
#pragma warning( disable: 4127 ) // conditional expression is constant
#pragma warning( disable: 4503 ) // decorated name length exceeded, name was truncated
#endif
-9
View File
@@ -7976,20 +7976,11 @@ GTEST_API_ std::string AppendUserMessage(
// std::runtime_error inherits from std::exception, many testing
// frameworks know how to extract and print the message inside it.
#ifdef _MSC_VER
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4275) // Temporarily disables warning 4275.
#endif // _MSC_VER
class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
public:
explicit GoogleTestFailureException(const TestPartResult& failure);
};
#ifdef _MSC_VER
# pragma warning(pop) // Restores the warning state.
#endif // _MSC_VER
#endif // GTEST_HAS_EXCEPTIONS
// A helper class for creating scoped traces in user programs.
+1 -1
View File
@@ -98,7 +98,7 @@ OCL_PERF_TEST_P(MOG2_GetBackgroundImage, Mog2, Combine(Values("gpu/video/768x576
}
mog2->getBackgroundImage(u_background);
}
SANITY_CHECK(u_background);
SANITY_CHECK_NOTHING();
}
}}// namespace cvtest::ocl
+3 -3
View File
@@ -767,7 +767,7 @@ private:
{
if (!gaussianBlurOcl(frames_[i], smoothSize/2, blurredFrame[i]))
return false;
resize(blurredFrame[i], pyrLevel[i], Size(width, height), INTER_LINEAR_EXACT);
resize(blurredFrame[i], pyrLevel[i], Size(width, height), INTER_LINEAR);
if (!polynomialExpansionOcl(pyrLevel[i], R[i]))
return false;
}
@@ -1153,7 +1153,7 @@ void FarnebackOpticalFlowImpl::calc(InputArray _prev0, InputArray _next0,
}
else
{
resize( prevFlow, flow, Size(width, height), 0, 0, INTER_LINEAR);
resize( prevFlow, flow, Size(width, height), 0, 0, INTER_LINEAR );
flow *= 1./pyrScale_;
}
@@ -1162,7 +1162,7 @@ void FarnebackOpticalFlowImpl::calc(InputArray _prev0, InputArray _next0,
{
img[i]->convertTo(fimg, CV_32F);
GaussianBlur(fimg, fimg, Size(smooth_sz, smooth_sz), sigma, sigma);
resize( fimg, I, Size(width, height), INTER_LINEAR);
resize( fimg, I, Size(width, height), INTER_LINEAR );
FarnebackPolyExp( I, R[i], polyN_, polySigma_ );
}
+2 -2
View File
@@ -51,7 +51,7 @@
#define CALC_FFMPEG_VERSION(a,b,c) ( a<<16 | b<<8 | c )
#if defined _MSC_VER && _MSC_VER >= 1200
#pragma warning( disable: 4244 4510 4512 4610 )
#pragma warning( disable: 4244 4510 4610 )
#endif
#ifdef __GNUC__
@@ -83,7 +83,7 @@ extern "C" {
#endif
#if defined _MSC_VER && _MSC_VER >= 1200
#pragma warning( default: 4244 4510 4512 4610 )
#pragma warning( default: 4244 4510 4610 )
#endif
#ifdef NDEBUG
-9
View File
@@ -2084,11 +2084,6 @@ public:
// succeed but return a nullptr pointer. By default, the list does not allow nullptr
// pointers.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127) // constant expression
#endif
template <class T, bool NULLABLE = FALSE>
class ComPtrList : public List<T*>
{
@@ -2179,10 +2174,6 @@ protected:
}
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
/* Be sure to declare webcam device capability in manifest
For better media capture support, add the following snippet with correct module name to the project manifest
(videoio needs DLL activation class factoryentry points):
+1 -3
View File
@@ -8,8 +8,6 @@
#include <opencv2/objdetect.hpp>
#include <stdio.h>
#include <string>
#include <vector>
using namespace std;
using namespace cv;
@@ -84,7 +82,7 @@ int main(int , char** )
do
{
VideoStream >> ReferenceFrame;
cvtColor(ReferenceFrame, GrayFrame, COLOR_RGB2GRAY);
cvtColor(ReferenceFrame, GrayFrame, COLOR_BGR2GRAY);
Detector.process(GrayFrame);
Detector.getObjects(Faces);
+9 -16
View File
@@ -2,7 +2,7 @@
using namespace cv;
class TravelSalesman : public ml::SimulatedAnnealingSolverSystem
class TravelSalesman
{
private :
const std::vector<Point>& posCity;
@@ -17,11 +17,11 @@ public:
rng = theRNG();
}
/** Give energy value for a state of system.*/
/*virtual*/ double energy() const;
double energy() const;
/** Function which change the state of system (random pertubation).*/
/*virtual*/ void changeState();
void changeState();
/** Function to reverse to the previous state.*/
/*virtual*/ void reverseState();
void reverseState();
};
@@ -81,31 +81,24 @@ int main(void)
posCity[i].y = static_cast<int>(radius*sin(theta)) + center.y;
next[i]=(i+1)%nbCity;
}
Ptr<TravelSalesman> ts_system(new TravelSalesman(posCity, next));
ml::SimulatedAnnealingSolver ts(ts_system);
TravelSalesman ts_system(posCity, next);
ts.setIterPerStep(10000*nbCity);
ts.setCoolingRatio(0.99);
ts.setInitialTemperature(100);
ts.setFinalTemperature(100*0.97);
DrawTravelMap(img,posCity,next);
imshow("Map",img);
waitKey(10);
double currentTemperature = 100.0;
for (int i = 0, zeroChanges = 0; zeroChanges < 10; i++)
{
int changesApplied = ts.run();
img = Mat::zeros(img.size(),CV_8UC3);
int changesApplied = ml::simulatedAnnealingSolver(ts_system, currentTemperature, currentTemperature*0.97, 0.99, 10000*nbCity, &currentTemperature, rng);
img.setTo(Scalar::all(0));
DrawTravelMap(img, posCity, next);
imshow("Map", img);
int k = waitKey(10);
double ti=ts.getFinalTemperature();
std::cout << "i=" << i << " changesApplied=" << changesApplied << " temp=" << ti << " result=" << ts_system->energy() << std::endl;
std::cout << "i=" << i << " changesApplied=" << changesApplied << " temp=" << currentTemperature << " result=" << ts_system.energy() << std::endl;
if (k == 27 || k == 'q' || k == 'Q')
return 0;
if (changesApplied == 0)
zeroChanges++;
ts.setInitialTemperature(ti);
ts.setFinalTemperature(ti*0.97);
}
std::cout << "Done" << std::endl;
waitKey(0);
@@ -15,7 +15,7 @@ using namespace std;
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
Mat src, dst;
@@ -23,12 +23,14 @@ int main( int, char** argv )
const char* equalized_window = "Equalized Image";
/// Load image
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if( src.empty() )
{ cout<<"Usage: ./EqualizeHist_Demo <path_to_image>"<<endl;
return -1;
}
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
/// Convert to grayscale
cvtColor( src, src, COLOR_BGR2GRAY );
@@ -5,10 +5,11 @@
*/
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
/// Global variables
Mat src, erosion_dst, dilation_dst;
@@ -27,13 +28,17 @@ void Dilation( int, void* );
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
/// Load an image
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/chicky_512.png | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if( src.empty() )
{ return -1; }
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
/// Create windows
namedWindow( "Erosion Demo", WINDOW_AUTOSIZE );
@@ -7,6 +7,7 @@
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
@@ -32,15 +33,14 @@ void Morphology_Operations( int, void* );
int main( int argc, char** argv )
{
//![load]
String imageName("../data/baboon.jpg"); // by default
if (argc > 1)
CommandLineParser parser( argc, argv, "{@input | ../data/baboon.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if (src.empty())
{
imageName = argv[1];
std::cout << "Could not open or find the image!\n" << std::endl;
std::cout << "Usage: " << argv[0] << " <Input image>" << std::endl;
return -1;
}
src = imread(imageName, IMREAD_COLOR); // Load an image
if( src.empty() )
{ return -1; }
//![load]
//![window]
@@ -11,16 +11,15 @@ void show_wait_destroy(const char* winname, cv::Mat img);
using namespace std;
using namespace cv;
int main(int, char** argv)
int main(int argc, char** argv)
{
//! [load_image]
// Load the image
Mat src = imread(argv[1]);
// Check if image is loaded fine
if(src.empty()){
printf(" Error opening image\n");
printf(" Program Arguments: [image_path]\n");
CommandLineParser parser(argc, argv, "{@input | ../data/notes.png | input image}");
Mat src = imread(parser.get<String>("@input"), IMREAD_COLOR);
if (src.empty())
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
@@ -5,8 +5,8 @@
*/
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
@@ -56,13 +56,18 @@ static void CannyThreshold(int, void*)
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
//![load]
src = imread( argv[1], IMREAD_COLOR ); // Load an image
CommandLineParser parser( argc, argv, "{@input | ../data/fruits.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR ); // Load an image
if( src.empty() )
{ return -1; }
{
std::cout << "Could not open or find the image!\n" << std::endl;
std::cout << "Usage: " << argv[0] << " <Input image>" << std::endl;
return -1;
}
//![load]
//![create_mat]
@@ -20,7 +20,7 @@ const char* warp_rotate_window = "Warp + Rotate";
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
Point2f srcTri[3];
Point2f dstTri[3];
@@ -30,7 +30,14 @@ int main( int, char** argv )
Mat src, warp_dst, warp_rotate_dst;
/// Load the image
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
/// Set the dst image the same type and size as src
warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
@@ -12,7 +12,7 @@ using namespace std;
int main(int argc, char** argv)
{
//![load]
const char* filename = argc >=2 ? argv[1] : "../../../data/smarties.png";
const char* filename = argc >=2 ? argv[1] : "../data/smarties.png";
// Loads an image
Mat src = imread( filename, IMREAD_COLOR );
@@ -16,7 +16,7 @@ int main(int argc, char** argv)
Mat dst, cdst, cdstP;
//![load]
const char* default_file = "../../../data/sudoku.png";
const char* default_file = "../data/sudoku.png";
const char* filename = argc >=2 ? argv[1] : default_file;
// Loads an image
@@ -23,11 +23,18 @@ void thresh_callback(int, void* );
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
//![setup]
/// Load source image
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/stuff.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
/// Convert image to gray and blur it
cvtColor( src, src_gray, COLOR_BGR2GRAY );
@@ -84,8 +91,8 @@ void thresh_callback(int, void* )
//![allthework]
for( size_t i = 0; i < contours.size(); i++ )
{
approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
boundRect[i] = boundingRect( Mat(contours_poly[i]) );
approxPolyDP( contours[i], contours_poly[i], 3, true );
boundRect[i] = boundingRect( contours_poly[i] );
minEnclosingCircle( contours_poly[i], center[i], radius[i] );
}
//![allthework]
@@ -23,10 +23,17 @@ void thresh_callback(int, void* );
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/stuff.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
/// Convert image to gray and blur it
cvtColor( src, src_gray, COLOR_BGR2GRAY );
@@ -63,9 +70,9 @@ void thresh_callback(int, void* )
vector<RotatedRect> minEllipse( contours.size() );
for( size_t i = 0; i < contours.size(); i++ )
{ minRect[i] = minAreaRect( Mat(contours[i]) );
{ minRect[i] = minAreaRect( contours[i] );
if( contours[i].size() > 5 )
{ minEllipse[i] = fitEllipse( Mat(contours[i]) ); }
{ minEllipse[i] = fitEllipse( contours[i] ); }
}
/// Draw contours + rotated rects + ellipses
@@ -23,10 +23,17 @@ void thresh_callback(int, void* );
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/stuff.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
/// Convert image to gray and blur it
cvtColor( src, src_gray, COLOR_BGR2GRAY );
@@ -62,7 +69,7 @@ void thresh_callback(int, void* )
/// Find the convex hull object for each contour
vector<vector<Point> >hull( contours.size() );
for( size_t i = 0; i < contours.size(); i++ )
{ convexHull( Mat(contours[i]), hull[i], false ); }
{ convexHull( contours[i], hull[i], false ); }
/// Draw contours + hull results
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
@@ -23,10 +23,18 @@ void thresh_callback(int, void* );
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/stuff.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "usage: " << argv[0] << " <Input image>" << endl;
exit(0);
}
/// Convert image to gray and blur it
cvtColor( src, src_gray, COLOR_BGR2GRAY );
@@ -51,12 +59,11 @@ void thresh_callback(int, void* )
{
Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using canny
Canny( src_gray, canny_output, thresh, thresh*2, 3 );
/// Find contours
findContours( canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE );
/// Get the moments
vector<Moments> mu(contours.size() );
@@ -73,7 +80,7 @@ void thresh_callback(int, void* )
for( size_t i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, (int)i, color, 2, 8, hierarchy, 0, Point() );
drawContours( drawing, contours, (int)i, color, 2, LINE_8 );
circle( drawing, mc[i], 4, color, -1, 8, 0 );
}
@@ -87,7 +94,7 @@ void thresh_callback(int, void* )
{
printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", (int)i, mu[i].m00, contourArea(contours[i]), arcLength( contours[i], true ) );
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, (int)i, color, 2, 8, hierarchy, 0, Point() );
drawContours( drawing, contours, (int)i, color, 2, LINE_8 );
circle( drawing, mc[i], 4, color, -1, 8, 0 );
}
}
@@ -35,10 +35,9 @@ int main( void )
{ line( src, vert[j], vert[(j+1)%6], Scalar( 255 ), 3, 8 ); }
/// Get the contours
vector<vector<Point> > contours; vector<Vec4i> hierarchy;
Mat src_copy = src.clone();
vector<vector<Point> > contours;
findContours( src_copy, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
findContours( src, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);
/// Calculate the distances to the contour
Mat raw_dist( src.size(), CV_32FC1 );
@@ -67,11 +66,8 @@ int main( void )
}
}
/// Create Window and show your results
const char* source_window = "Source";
namedWindow( source_window, WINDOW_AUTOSIZE );
imshow( source_window, src );
namedWindow( "Distance", WINDOW_AUTOSIZE );
/// Show your results
imshow( "Source", src );
imshow( "Distance", drawing );
waitKey(0);
@@ -4,7 +4,6 @@
* @author OpenCV team
*/
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
@@ -36,10 +35,17 @@ void myHarris_function( int, void* );
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/stuff.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if ( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
cvtColor( src, src_gray, COLOR_BGR2GRAY );
/// Set some parameters
@@ -4,7 +4,6 @@
* @author OpenCV team
*/
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
@@ -26,10 +25,17 @@ void cornerHarris_demo( int, void* );
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/building.jpg | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if ( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
cvtColor( src, src_gray, COLOR_BGR2GRAY );
/// Create a window and a trackbar
@@ -4,7 +4,6 @@
* @author OpenCV team
*/
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
@@ -27,10 +26,17 @@ void goodFeaturesToTrack_Demo( int, void* );
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/pic3.png | input image}" );
src = imread(parser.get<String>( "@input" ), IMREAD_COLOR);
if ( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
cvtColor( src, src_gray, COLOR_BGR2GRAY );
/// Create Window
@@ -27,10 +27,17 @@ void goodFeaturesToTrack_Demo( int, void* );
/**
* @function main
*/
int main( int, char** argv )
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], IMREAD_COLOR );
CommandLineParser parser( argc, argv, "{@input | ../data/pic3.png | input image}" );
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
if( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
cvtColor( src, src_gray, COLOR_BGR2GRAY );
/// Create Window
@@ -1,7 +1,6 @@
#include <opencv2/features2d.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
using namespace std;
@@ -10,13 +9,17 @@ using namespace cv;
const float inlier_threshold = 2.5f; // Distance threshold to identify inliers
const float nn_match_ratio = 0.8f; // Nearest neighbor matching ratio
int main(void)
int main(int argc, char* argv[])
{
Mat img1 = imread("../data/graf1.png", IMREAD_GRAYSCALE);
Mat img2 = imread("../data/graf3.png", IMREAD_GRAYSCALE);
CommandLineParser parser(argc, argv,
"{@img1 | ../data/graf1.png | input image 1}"
"{@img2 | ../data/graf3.png | input image 2}"
"{@homography | ../data/H1to3p.xml | homography matrix}");
Mat img1 = imread(parser.get<String>("@img1"), IMREAD_GRAYSCALE);
Mat img2 = imread(parser.get<String>("@img2"), IMREAD_GRAYSCALE);
Mat homography;
FileStorage fs("../data/H1to3p.xml", FileStorage::READ);
FileStorage fs(parser.get<String>("@homography"), FileStorage::READ);
fs.getFirstTopLevelNode() >> homography;
vector<KeyPoint> kpts1, kpts2;
@@ -153,16 +153,13 @@ void decomposeHomography(const string &img1Path, const string &img2Path, const S
//! [decompose-homography-estimated-by-findHomography]
}
const char* about = "Code for homography tutorial.\n"
"Example 4: decompose the homography matrix.\n";
const char* params
= "{ h help | false | print usage }"
"{ image1 | | path to the source chessboard image (left02.jpg) }"
"{ image2 | | path to the desired chessboard image (left01.jpg) }"
"{ intrinsics | | path to camera intrinsics (left_intrinsics.yml) }"
"{ width w | 9 | chessboard width }"
"{ height h | 6 | chessboard height }"
= "{ help h | | print usage }"
"{ image1 | ../data/left02.jpg | path to the source chessboard image }"
"{ image2 | ../data/left01.jpg | path to the desired chessboard image }"
"{ intrinsics | ../data/left_intrinsics.yml | path to camera intrinsics }"
"{ width bw | 9 | chessboard width }"
"{ height bh | 6 | chessboard height }"
"{ square_size | 0.025 | chessboard square size }";
}
@@ -170,19 +167,20 @@ int main(int argc, char *argv[])
{
CommandLineParser parser(argc, argv, params);
if (parser.get<bool>("help"))
if ( parser.has("help") )
{
cout << about << endl;
parser.about( "Code for homography tutorial.\n"
"Example 4: decompose the homography matrix.\n" );
parser.printMessage();
return 0;
}
Size patternSize(parser.get<int>("width"), parser.get<int>("height"));
float squareSize = (float) parser.get<double>("square_size");
decomposeHomography(parser.get<string>("image1"),
parser.get<string>("image2"),
decomposeHomography(parser.get<String>("image1"),
parser.get<String>("image2"),
patternSize, squareSize,
parser.get<string>("intrinsics"));
parser.get<String>("intrinsics"));
return 0;
}
@@ -168,16 +168,13 @@ void homographyFromCameraDisplacement(const string &img1Path, const string &img2
waitKey();
}
const char* about = "Code for homography tutorial.\n"
"Example 3: homography from the camera displacement.\n";
const char* params
= "{ h help | false | print usage }"
"{ image1 | | path to the source chessboard image (left02.jpg) }"
"{ image2 | | path to the desired chessboard image (left01.jpg) }"
"{ intrinsics | | path to camera intrinsics (left_intrinsics.yml) }"
"{ width w | 9 | chessboard width }"
"{ height h | 6 | chessboard height }"
= "{ help h | | print usage }"
"{ image1 | ../data/left02.jpg | path to the source chessboard image }"
"{ image2 | ../data/left01.jpg | path to the desired chessboard image }"
"{ intrinsics | ../data/left_intrinsics.yml | path to camera intrinsics }"
"{ width bw | 9 | chessboard width }"
"{ height bh | 6 | chessboard height }"
"{ square_size | 0.025 | chessboard square size }";
}
@@ -185,19 +182,20 @@ int main(int argc, char *argv[])
{
CommandLineParser parser(argc, argv, params);
if (parser.get<bool>("help"))
if (parser.has("help"))
{
cout << about << endl;
parser.about("Code for homography tutorial.\n"
"Example 3: homography from the camera displacement.\n");
parser.printMessage();
return 0;
}
Size patternSize(parser.get<int>("width"), parser.get<int>("height"));
float squareSize = (float) parser.get<double>("square_size");
homographyFromCameraDisplacement(parser.get<string>("image1"),
parser.get<string>("image2"),
homographyFromCameraDisplacement(parser.get<String>("image1"),
parser.get<String>("image2"),
patternSize, squareSize,
parser.get<string>("intrinsics"));
parser.get<String>("intrinsics"));
return 0;
}
@@ -1,23 +0,0 @@
%YAML:1.0
---
image_width: 640
image_height: 480
board_width: 9
board_height: 6
square_size: 1.
aspectRatio: 1.
flags: 2
camera_matrix: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 5.3591575307485539e+02, 0., 3.4228314953752817e+02, 0.,
5.3591575307485539e+02, 2.3557082321320789e+02, 0., 0., 1. ]
distortion_coefficients: !!opencv-matrix
rows: 5
cols: 1
dt: d
data: [ -2.6637290673868386e-01, -3.8586722644459073e-02,
1.7831841406179300e-03, -2.8122035403651473e-04,
2.3838760574917545e-01 ]
avg_reprojection_error: 3.9259109564815858e-01
@@ -0,0 +1,88 @@
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
namespace
{
void basicPanoramaStitching(const string &img1Path, const string &img2Path)
{
Mat img1 = imread(img1Path);
Mat img2 = imread(img2Path);
//! [camera-pose-from-Blender-at-location-1]
Mat c1Mo = (Mat_<double>(4,4) << 0.9659258723258972, 0.2588190734386444, 0.0, 1.5529145002365112,
0.08852133899927139, -0.3303661346435547, -0.9396926164627075, -0.10281121730804443,
-0.24321036040782928, 0.9076734185218811, -0.342020183801651, 6.130080699920654,
0, 0, 0, 1);
//! [camera-pose-from-Blender-at-location-1]
//! [camera-pose-from-Blender-at-location-2]
Mat c2Mo = (Mat_<double>(4,4) << 0.9659258723258972, -0.2588190734386444, 0.0, -1.5529145002365112,
-0.08852133899927139, -0.3303661346435547, -0.9396926164627075, -0.10281121730804443,
0.24321036040782928, 0.9076734185218811, -0.342020183801651, 6.130080699920654,
0, 0, 0, 1);
//! [camera-pose-from-Blender-at-location-2]
//! [camera-intrinsics-from-Blender]
Mat cameraMatrix = (Mat_<double>(3,3) << 700.0, 0.0, 320.0,
0.0, 700.0, 240.0,
0, 0, 1);
//! [camera-intrinsics-from-Blender]
//! [extract-rotation]
Mat R1 = c1Mo(Range(0,3), Range(0,3));
Mat R2 = c2Mo(Range(0,3), Range(0,3));
//! [extract-rotation]
//! [compute-rotation-displacement]
//c1Mo * oMc2
Mat R_2to1 = R1*R2.t();
//! [compute-rotation-displacement]
//! [compute-homography]
Mat H = cameraMatrix * R_2to1 * cameraMatrix.inv();
H /= H.at<double>(2,2);
cout << "H:\n" << H << endl;
//! [compute-homography]
//! [stitch]
Mat img_stitch;
warpPerspective(img2, img_stitch, H, Size(img2.cols*2, img2.rows));
Mat half = img_stitch(Rect(0, 0, img1.cols, img1.rows));
img1.copyTo(half);
//! [stitch]
Mat img_compare;
Mat img_space = Mat::zeros(Size(50, img1.rows), CV_8UC3);
hconcat(img1, img_space, img_compare);
hconcat(img_compare, img2, img_compare);
imshow("Compare images", img_compare);
imshow("Panorama stitching", img_stitch);
waitKey();
}
const char* params
= "{ help h | | print usage }"
"{ image1 | ../data/Blender_Suzanne1.jpg | path to the first Blender image }"
"{ image2 | ../data/Blender_Suzanne2.jpg | path to the second Blender image }";
}
int main(int argc, char *argv[])
{
CommandLineParser parser(argc, argv, params);
if (parser.has("help"))
{
parser.about( "Code for homography tutorial.\n"
"Example 5: basic panorama stitching from a rotating camera.\n" );
parser.printMessage();
return 0;
}
basicPanoramaStitching(parser.get<String>("image1"), parser.get<String>("image2"));
return 0;
}
@@ -92,15 +92,12 @@ void perspectiveCorrection(const string &img1Path, const string &img2Path, const
//! [compute-transformed-corners]
}
const char* about = "Code for homography tutorial.\n"
"Example 2: perspective correction.\n";
const char* params
= "{ h help | false | print usage }"
"{ image1 | | path to the source chessboard image (left02.jpg) }"
"{ image2 | | path to the desired chessboard image (left01.jpg) }"
"{ width w | 9 | chessboard width }"
"{ height h | 6 | chessboard height }";
= "{ help h | | print usage }"
"{ image1 | ../data/left02.jpg | path to the source chessboard image }"
"{ image2 | ../data/left01.jpg | path to the desired chessboard image }"
"{ width bw | 9 | chessboard width }"
"{ height bh | 6 | chessboard height }";
}
int main(int argc, char *argv[])
@@ -108,16 +105,17 @@ int main(int argc, char *argv[])
cv::RNG rng( 0xFFFFFFFF );
CommandLineParser parser(argc, argv, params);
if (parser.get<bool>("help"))
if (parser.has("help"))
{
cout << about << endl;
parser.about("Code for homography tutorial.\n"
"Example 2: perspective correction.\n");
parser.printMessage();
return 0;
}
Size patternSize(parser.get<int>("width"), parser.get<int>("height"));
perspectiveCorrection(parser.get<string>("image1"),
parser.get<string>("image2"),
perspectiveCorrection(parser.get<String>("image1"),
parser.get<String>("image2"),
patternSize, rng);
return 0;
@@ -107,6 +107,14 @@ void poseEstimationFromCoplanarPoints(const string &imgPath, const string &intri
}
//! [pose-from-homography]
//! [polar-decomposition-of-the-rotation-matrix]
cout << "R (before polar decomposition):\n" << R << "\ndet(R): " << determinant(R) << endl;
Mat W, U, Vt;
SVDecomp(R, W, U, Vt);
R = U*Vt;
cout << "R (after polar decomposition):\n" << R << "\ndet(R): " << determinant(R) << endl;
//! [polar-decomposition-of-the-rotation-matrix]
//! [display-pose]
Mat rvec;
Rodrigues(R, rvec);
@@ -116,15 +124,12 @@ void poseEstimationFromCoplanarPoints(const string &imgPath, const string &intri
//! [display-pose]
}
const char* about = "Code for homography tutorial.\n"
"Example 1: pose from homography with coplanar points.\n";
const char* params
= "{ h help | false | print usage }"
"{ image | | path to a chessboard image (left04.jpg) }"
"{ intrinsics | | path to camera intrinsics (left_intrinsics.yml) }"
"{ width w | 9 | chessboard width }"
"{ height h | 6 | chessboard height }"
= "{ help h | | print usage }"
"{ image | ../data/left04.jpg | path to a chessboard image }"
"{ intrinsics | ../data/left_intrinsics.yml | path to camera intrinsics }"
"{ width bw | 9 | chessboard width }"
"{ height bh | 6 | chessboard height }"
"{ square_size | 0.025 | chessboard square size }";
}
@@ -132,17 +137,18 @@ int main(int argc, char *argv[])
{
CommandLineParser parser(argc, argv, params);
if (parser.get<bool>("help"))
if (parser.has("help"))
{
cout << about << endl;
parser.about("Code for homography tutorial.\n"
"Example 1: pose from homography with coplanar points.\n");
parser.printMessage();
return 0;
}
Size patternSize(parser.get<int>("width"), parser.get<int>("height"));
float squareSize = (float) parser.get<double>("square_size");
poseEstimationFromCoplanarPoints(parser.get<string>("image"),
parser.get<string>("intrinsics"),
poseEstimationFromCoplanarPoints(parser.get<String>("image"),
parser.get<String>("intrinsics"),
patternSize, squareSize);
return 0;
@@ -4,8 +4,10 @@
* @author OpenCV team
*/
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
@@ -30,16 +32,16 @@ void drawAxis(Mat& img, Point p, Point q, Scalar colour, const float scale = 0.2
// Here we lengthen the arrow by a factor of scale
q.x = (int) (p.x - scale * hypotenuse * cos(angle));
q.y = (int) (p.y - scale * hypotenuse * sin(angle));
line(img, p, q, colour, 1, CV_AA);
line(img, p, q, colour, 1, LINE_AA);
// create the arrow hooks
p.x = (int) (q.x + 9 * cos(angle + CV_PI / 4));
p.y = (int) (q.y + 9 * sin(angle + CV_PI / 4));
line(img, p, q, colour, 1, CV_AA);
line(img, p, q, colour, 1, LINE_AA);
p.x = (int) (q.x + 9 * cos(angle - CV_PI / 4));
p.y = (int) (q.y + 9 * sin(angle - CV_PI / 4));
line(img, p, q, colour, 1, CV_AA);
line(img, p, q, colour, 1, LINE_AA);
//! [visualization1]
}
@@ -59,7 +61,7 @@ double getOrientation(const vector<Point> &pts, Mat &img)
}
//Perform PCA analysis
PCA pca_analysis(data_pts, Mat(), CV_PCA_DATA_AS_ROW);
PCA pca_analysis(data_pts, Mat(), PCA::DATA_AS_ROW);
//Store the center of the object
Point cntr = Point(static_cast<int>(pca_analysis.mean.at<double>(0, 0)),
@@ -98,15 +100,14 @@ int main(int argc, char** argv)
{
//! [pre-process]
// Load image
String imageName("../data/pca_test1.jpg"); // by default
if (argc > 1)
{
imageName = argv[1];
}
Mat src = imread( imageName );
CommandLineParser parser(argc, argv, "{@input | ../data/pca_test1.jpg | input image}");
parser.about( "This program demonstrates how to use OpenCV PCA to extract the orienation of an object.\n" );
parser.printMessage();
Mat src = imread(parser.get<String>("@input"));
// Check if image is loaded successfully
if(!src.data || src.empty())
if(src.empty())
{
cout << "Problem loading image!!!" << endl;
return EXIT_FAILURE;
@@ -120,14 +121,13 @@ int main(int argc, char** argv)
// Convert image to binary
Mat bw;
threshold(gray, bw, 50, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
threshold(gray, bw, 50, 255, THRESH_BINARY | THRESH_OTSU);
//! [pre-process]
//! [contours]
// Find all the contours in the thresholded image
vector<Vec4i> hierarchy;
vector<vector<Point> > contours;
findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
findContours(bw, contours, RETR_LIST, CHAIN_APPROX_NONE);
for (size_t i = 0; i < contours.size(); ++i)
{
@@ -137,7 +137,7 @@ int main(int argc, char** argv)
if (area < 1e2 || 1e5 < area) continue;
// Draw each contour only for visualisation purposes
drawContours(src, contours, static_cast<int>(i), Scalar(0, 0, 255), 2, 8, hierarchy, 0);
drawContours(src, contours, static_cast<int>(i), Scalar(0, 0, 255), 2, LINE_8);
// Find the orientation of each shape
getOrientation(contours[i], src);
}
@@ -1,9 +1,7 @@
#include "opencv2/objdetect.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
@@ -26,12 +24,12 @@ int main( int argc, const char** argv )
"{face_cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|}"
"{eyes_cascade|../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|}");
cout << "\nThis program demonstrates using the cv::CascadeClassifier class to detect objects (Face + eyes) in a video stream.\n"
"You can use Haar or LBP features.\n\n";
parser.about( "\nThis program demonstrates using the cv::CascadeClassifier class to detect objects (Face + eyes) in a video stream.\n"
"You can use Haar or LBP features.\n\n" );
parser.printMessage();
face_cascade_name = parser.get<string>("face_cascade");
eyes_cascade_name = parser.get<string>("eyes_cascade");
face_cascade_name = parser.get<String>("face_cascade");
eyes_cascade_name = parser.get<String>("eyes_cascade");
VideoCapture capture;
Mat frame;
@@ -54,8 +52,7 @@ int main( int argc, const char** argv )
//-- 3. Apply the classifier to the frame
detectAndDisplay( frame );
char c = (char)waitKey(10);
if( c == 27 ) { break; } // escape
if( waitKey(10) == 27 ) { break; } // escape
}
return 0;
}
@@ -70,7 +67,7 @@ void detectAndDisplay( Mat frame )
equalizeHist( frame_gray, frame_gray );
//-- Detect faces
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CASCADE_SCALE_IMAGE, Size(30, 30) );
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CASCADE_SCALE_IMAGE, Size(60, 60) );
for ( size_t i = 0; i < faces.size(); i++ )
{

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