mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Compare commits
100 Commits
4.5.2-openvino
...
3.4.14
| Author | SHA1 | Date | |
|---|---|---|---|
| d0e3e638c3 | |||
| 6a72bf5085 | |||
| 0ff57e3292 | |||
| 5db484b6c2 | |||
| 6865787a75 | |||
| 7f664850f5 | |||
| 2907fb88f5 | |||
| d7cb2ea210 | |||
| 4ae2c11520 | |||
| 1b3e0b27af | |||
| e4b0251e9d | |||
| b26f5b9468 | |||
| 5340dc6686 | |||
| 2b86de217a | |||
| 1615afd7f4 | |||
| 908957317f | |||
| 6fa2bdd7f2 | |||
| f82303d614 | |||
| 6773fa03e2 | |||
| d651ff8d6b | |||
| 8069a6b4f8 | |||
| b697b3162f | |||
| 53a16b1186 | |||
| a2a92999be | |||
| 40c0830b63 | |||
| 6f1eefec69 | |||
| bb6e15f2c0 | |||
| 0dcb99cf23 | |||
| cc6d48959e | |||
| aab62aa6dd | |||
| ac9f3a1242 | |||
| 53652a6194 | |||
| 8d232a63ad | |||
| bf03f5fa3a | |||
| 6e8022a3af | |||
| d27eb79fa6 | |||
| 3e48a91d97 | |||
| 144443d011 | |||
| 86d0a86141 | |||
| bf9f67e93f | |||
| 26ea4760ad | |||
| f59917bea1 | |||
| a394c8b10b | |||
| e56e4876e7 | |||
| 56bdd7db5c | |||
| 3df6bc58e9 | |||
| e75f1b071b | |||
| 7a2b3ed471 | |||
| 551d4a8ec1 | |||
| 29a289dfa1 | |||
| bdd2b57e5d | |||
| a97f6f8058 | |||
| c0dd82fb53 | |||
| 1211a8b9cd | |||
| f680505086 | |||
| ae60bbc7e4 | |||
| 7664e6d090 | |||
| 960f501cc1 | |||
| 7a8e171691 | |||
| 7ca9740da5 | |||
| 68fae94cbb | |||
| 6da5c7c1d0 | |||
| 87e607a19b | |||
| cbe236652b | |||
| d4d805cb3e | |||
| 8d29a902e4 | |||
| f136adcad5 | |||
| 95ab9468c1 | |||
| f8181fbef8 | |||
| b995de4ff3 | |||
| 825dadfbdd | |||
| 63048812c7 | |||
| e4692ac079 | |||
| 47337e2196 | |||
| 1d6a1e5f9c | |||
| 84fcc4ab9b | |||
| 65b51e1538 | |||
| 6c9be1bc1d | |||
| 4c48f1eed2 | |||
| 31f66766b7 | |||
| 601690695e | |||
| 85009800b3 | |||
| 04a9ff88d8 | |||
| dc24663e8d | |||
| d2cc63e779 | |||
| 358878caf7 | |||
| 640f188ca2 | |||
| a1e2c4f338 | |||
| 625d4fc884 | |||
| f821530eb0 | |||
| 7894cd3c73 | |||
| 125cc79c17 | |||
| 2a808aeec0 | |||
| 94533e12eb | |||
| a0008de281 | |||
| a42d4da003 | |||
| 0689c70dba | |||
| 75ad74c893 | |||
| cbfd38bd41 | |||
| cc22a73d0f |
Vendored
+5
-5
@@ -1,8 +1,8 @@
|
||||
# Binaries branch name: ffmpeg/3.4_20200907
|
||||
# Binaries were created for OpenCV: 03bee14372f5537daa56c62e771ec16181ca1f98
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "2a96257b743695a47f8012aab1ffb995a1dee8b4")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "5e68a3ff82f43ac6524e50e448a34c9c")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "205db629d893e7d4865fd1459807ff47")
|
||||
# Binaries branch name: ffmpeg/3.4_20210302
|
||||
# Binaries were created for OpenCV: 2ab1f3f166fccc3a01497209cc01c5cea44ff201
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "e99214251d9f3cde7c48abd46b2259bddc9885b6")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "fad5ada9be36120bba8966709e7953a8")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "650e2272728491923e566f784f79cfef")
|
||||
ocv_update(FFMPEG_FILE_HASH_CMAKE "3b90f67f4b429e77d3da36698cef700c")
|
||||
|
||||
function(download_win_ffmpeg script_var)
|
||||
|
||||
+6
-6
@@ -1000,6 +1000,12 @@ if(COMMAND ocv_pylint_finalize)
|
||||
ocv_pylint_add_directory_recurse(${CMAKE_CURRENT_LIST_DIR}/samples/python/tutorial_code)
|
||||
ocv_pylint_finalize()
|
||||
endif()
|
||||
if(TARGET check_pylint)
|
||||
message(STATUS "Registered 'check_pylint' target: using ${PYLINT_EXECUTABLE} (ver: ${PYLINT_VERSION}), checks: ${PYLINT_TOTAL_TARGETS}")
|
||||
endif()
|
||||
if(TARGET check_flake8)
|
||||
message(STATUS "Registered 'check_flake8' target: using ${FLAKE8_EXECUTABLE} (ver: ${FLAKE8_VERSION})")
|
||||
endif()
|
||||
|
||||
if(OPENCV_GENERATE_SETUPVARS)
|
||||
include(cmake/OpenCVGenSetupVars.cmake)
|
||||
@@ -1633,12 +1639,6 @@ endif()
|
||||
|
||||
status("")
|
||||
status(" Python (for build):" PYTHON_DEFAULT_AVAILABLE THEN "${PYTHON_DEFAULT_EXECUTABLE}" ELSE NO)
|
||||
if(PYLINT_FOUND AND PYLINT_EXECUTABLE)
|
||||
status(" Pylint:" PYLINT_FOUND THEN "${PYLINT_EXECUTABLE} (ver: ${PYLINT_VERSION}, checks: ${PYLINT_TOTAL_TARGETS})" ELSE NO)
|
||||
endif()
|
||||
if(FLAKE8_FOUND AND FLAKE8_EXECUTABLE)
|
||||
status(" Flake8:" FLAKE8_FOUND THEN "${FLAKE8_EXECUTABLE} (ver: ${FLAKE8_VERSION})" ELSE NO)
|
||||
endif()
|
||||
|
||||
# ========================== java ==========================
|
||||
if(BUILD_JAVA)
|
||||
|
||||
@@ -16,7 +16,7 @@ if(PYLINT_EXECUTABLE AND NOT DEFINED PYLINT_VERSION)
|
||||
execute_process(COMMAND ${PYLINT_EXECUTABLE} --version RESULT_VARIABLE _result OUTPUT_VARIABLE PYLINT_VERSION_RAW)
|
||||
if(NOT _result EQUAL 0)
|
||||
ocv_clear_vars(PYLINT_EXECUTABLE PYLINT_VERSION)
|
||||
elseif(PYLINT_VERSION_RAW MATCHES "pylint([^,]*) ([0-9\\.]+[0-9])")
|
||||
elseif(PYLINT_VERSION_RAW MATCHES "pylint([^,\n]*) ([0-9\\.]+[0-9])")
|
||||
set(PYLINT_VERSION "${CMAKE_MATCH_2}")
|
||||
else()
|
||||
set(PYLINT_VERSION "unknown")
|
||||
|
||||
@@ -141,9 +141,9 @@ endif()
|
||||
|
||||
if(INF_ENGINE_TARGET)
|
||||
if(NOT INF_ENGINE_RELEASE)
|
||||
message(WARNING "InferenceEngine version has not been set, 2021.2 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
|
||||
message(WARNING "InferenceEngine version has not been set, 2021.3 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
|
||||
endif()
|
||||
set(INF_ENGINE_RELEASE "2021020000" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2020.1.0.2 -> 2020010002)")
|
||||
set(INF_ENGINE_RELEASE "2021030000" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2020.1.0.2 -> 2020010002)")
|
||||
set_target_properties(${INF_ENGINE_TARGET} PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
|
||||
)
|
||||
|
||||
@@ -143,10 +143,25 @@ macro(ipp_detect_version)
|
||||
list(APPEND IPP_LIBRARIES ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX})
|
||||
else ()
|
||||
add_library(ipp${name} STATIC IMPORTED)
|
||||
set(_filename "${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}")
|
||||
set_target_properties(ipp${name} PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LIBRARIES ""
|
||||
IMPORTED_LOCATION ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
|
||||
IMPORTED_LOCATION ${IPP_LIBRARY_DIR}/${_filename}
|
||||
)
|
||||
if("${name}" STREQUAL "core") # https://github.com/opencv/opencv/pull/19681
|
||||
if(OPENCV_FORCE_IPP_EXCLUDE_LIBS OR OPENCV_FORCE_IPP_EXCLUDE_LIBS_CORE
|
||||
OR (UNIX AND NOT ANDROID AND NOT APPLE
|
||||
AND (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
)
|
||||
AND NOT OPENCV_SKIP_IPP_EXCLUDE_LIBS_CORE
|
||||
)
|
||||
if(CMAKE_VERSION VERSION_LESS "3.13.0")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--exclude-libs,${_filename} ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
else()
|
||||
target_link_options(ipp${name} INTERFACE "LINKER:--exclude-libs,${_filename}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
list(APPEND IPP_LIBRARIES ipp${name})
|
||||
if (NOT BUILD_SHARED_LIBS AND (HAVE_IPP_ICV OR ";${OPENCV_INSTALL_EXTERNAL_DEPENDENCIES};" MATCHES ";ipp;"))
|
||||
# CMake doesn't support "install(TARGETS ${IPP_PREFIX}${name} " command with imported targets
|
||||
|
||||
@@ -876,7 +876,9 @@ endmacro()
|
||||
macro(_ocv_create_module)
|
||||
|
||||
ocv_compiler_optimization_process_sources(OPENCV_MODULE_${the_module}_SOURCES OPENCV_MODULE_${the_module}_DEPS_EXT ${the_module})
|
||||
set(OPENCV_MODULE_${the_module}_HEADERS ${OPENCV_MODULE_${the_module}_HEADERS} CACHE INTERNAL "List of header files for ${the_module}")
|
||||
set(__module_headers ${OPENCV_MODULE_${the_module}_HEADERS})
|
||||
list(SORT __module_headers) # fix headers order, useful for bindings
|
||||
set(OPENCV_MODULE_${the_module}_HEADERS ${__module_headers} CACHE INTERNAL "List of header files for ${the_module}")
|
||||
set(OPENCV_MODULE_${the_module}_SOURCES ${OPENCV_MODULE_${the_module}_SOURCES} CACHE INTERNAL "List of source files for ${the_module}")
|
||||
|
||||
# The condition we ought to be testing here is whether ocv_add_precompiled_headers will
|
||||
|
||||
@@ -122,7 +122,6 @@ function(ocv_pylint_finalize)
|
||||
|
||||
list(LENGTH PYLINT_TARGET_ID __total)
|
||||
set(PYLINT_TOTAL_TARGETS "${__total}" CACHE INTERNAL "")
|
||||
message(STATUS "Pylint: registered ${__total} targets. Build 'check_pylint' target to run checks (\"cmake --build . --target check_pylint\" or \"make check_pylint\")")
|
||||
configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/pylint.cmake.in" "${CMAKE_BINARY_DIR}/pylint.cmake" @ONLY)
|
||||
|
||||
add_custom_target(check_pylint
|
||||
|
||||
@@ -249,6 +249,12 @@ PREDEFINED = __cplusplus=1 \
|
||||
CV_DEFAULT(x)=" = x" \
|
||||
CV_NEON=1 \
|
||||
CV_SSE2=1 \
|
||||
CV_SIMD128=1 \
|
||||
CV_SIMD256=1 \
|
||||
CV_SIMD512=1 \
|
||||
CV_SIMD128_64F=1 \
|
||||
CV_SIMD256_64F=1 \
|
||||
CV_SIMD512_64F=1 \
|
||||
CV__DEBUG_NS_BEGIN= \
|
||||
CV__DEBUG_NS_END= \
|
||||
CV_DEPRECATED_EXTERNAL= \
|
||||
|
||||
@@ -138,6 +138,7 @@ Building OpenCV.js from Source
|
||||
python ./platforms/js/build_js.py build_js --cmake_option="-DOPENCV_EXTRA_MODULES_PATH=opencv_contrib/modules"
|
||||
@endcode
|
||||
|
||||
|
||||
Running OpenCV.js Tests
|
||||
---------------------------------------
|
||||
|
||||
@@ -303,6 +304,12 @@ The example uses latest version of emscripten. If the build fails you should try
|
||||
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk:2.0.10 emcmake python3 ./platforms/js/build_js.py build_js
|
||||
@endcode
|
||||
|
||||
In Windows use the following PowerShell command:
|
||||
|
||||
@code{.bash}
|
||||
docker run --rm --workdir /src -v "$(get-location):/src" "emscripten/emsdk:2.0.10" emcmake python3 ./platforms/js/build_js.py build_js
|
||||
@endcode
|
||||
|
||||
### Building the documentation with Docker
|
||||
|
||||
To build the documentation `doxygen` needs to be installed. Create a file named `Dockerfile` with the following content:
|
||||
|
||||
@@ -59,7 +59,7 @@ extension, its first version. A direct limitation of this is that you cannot sav
|
||||
larger than 2 GB. Furthermore you can only create and expand a single video track inside the
|
||||
container. No audio or other track editing support here. Nevertheless, any video codec present on
|
||||
your system might work. If you encounter some of these limitations you will need to look into more
|
||||
specialized video writing libraries such as *FFMpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As
|
||||
specialized video writing libraries such as *FFmpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As
|
||||
an alternative, create the video track with OpenCV and expand it with sound tracks or convert it to
|
||||
other formats by using video manipulation programs such as *VirtualDub* or *AviSynth*.
|
||||
|
||||
|
||||
@@ -65,7 +65,8 @@ int solve_deg3(double a, double b, double c, double d,
|
||||
return 3;
|
||||
}
|
||||
else {
|
||||
x0 = pow(2 * R, 1 / 3.0) - b_a_3;
|
||||
double cube_root = cv::cubeRoot(2 * R);
|
||||
x0 = cube_root - b_a_3;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -82,8 +83,15 @@ int solve_deg3(double a, double b, double c, double d,
|
||||
}
|
||||
|
||||
// D > 0, only one real root
|
||||
double AD = pow(fabs(R) + sqrt(D), 1.0 / 3.0) * (R > 0 ? 1 : (R < 0 ? -1 : 0));
|
||||
double BD = (AD == 0) ? 0 : -Q / AD;
|
||||
double AD = 0.;
|
||||
double BD = 0.;
|
||||
double R_abs = fabs(R);
|
||||
if (R_abs > DBL_EPSILON)
|
||||
{
|
||||
AD = cv::cubeRoot(R_abs + sqrt(D));
|
||||
AD = (R >= 0) ? AD : -AD;
|
||||
BD = -Q / AD;
|
||||
}
|
||||
|
||||
// Calculate the only real root
|
||||
x0 = AD + BD - b_a_3;
|
||||
|
||||
@@ -311,18 +311,42 @@ bool solvePnPRansac(InputArray _opoints, InputArray _ipoints,
|
||||
|
||||
opoints_inliers.resize(npoints1);
|
||||
ipoints_inliers.resize(npoints1);
|
||||
result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix,
|
||||
distCoeffs, rvec, tvec, useExtrinsicGuess,
|
||||
(flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1;
|
||||
try
|
||||
{
|
||||
result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix,
|
||||
distCoeffs, rvec, tvec, useExtrinsicGuess,
|
||||
(flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1;
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
{
|
||||
if (flags == SOLVEPNP_ITERATIVE &&
|
||||
npoints1 == 5 &&
|
||||
e.what() &&
|
||||
std::string(e.what()).find("DLT algorithm needs at least 6 points") != std::string::npos
|
||||
)
|
||||
{
|
||||
CV_LOG_INFO(NULL, "solvePnPRansac(): solvePnP stage to compute the final pose using points "
|
||||
"in the consensus set raised DLT 6 points exception, use result from MSS (Minimal Sample Sets) stage instead.");
|
||||
rvec = _local_model.col(0); // output rotation vector
|
||||
tvec = _local_model.col(1); // output translation vector
|
||||
result = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// raise other exceptions
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if( result <= 0 )
|
||||
if (result <= 0)
|
||||
{
|
||||
_rvec.assign(_local_model.col(0)); // output rotation vector
|
||||
_tvec.assign(_local_model.col(1)); // output translation vector
|
||||
|
||||
if( _inliers.needed() )
|
||||
if (_inliers.needed())
|
||||
_inliers.release();
|
||||
|
||||
CV_LOG_DEBUG(NULL, "solvePnPRansac(): solvePnP stage to compute the final pose using points in the consensus set failed. Return false");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1148,13 +1148,15 @@ class StereoBMImpl CV_FINAL : public StereoBM
|
||||
{
|
||||
public:
|
||||
StereoBMImpl()
|
||||
: params()
|
||||
{
|
||||
params = StereoBMParams();
|
||||
// nothing
|
||||
}
|
||||
|
||||
StereoBMImpl( int _numDisparities, int _SADWindowSize )
|
||||
: params(_numDisparities, _SADWindowSize)
|
||||
{
|
||||
params = StereoBMParams(_numDisparities, _SADWindowSize);
|
||||
// nothing
|
||||
}
|
||||
|
||||
void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) CV_OVERRIDE
|
||||
|
||||
@@ -2186,19 +2186,21 @@ class StereoSGBMImpl CV_FINAL : public StereoSGBM
|
||||
{
|
||||
public:
|
||||
StereoSGBMImpl()
|
||||
: params()
|
||||
{
|
||||
params = StereoSGBMParams();
|
||||
// nothing
|
||||
}
|
||||
|
||||
StereoSGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize,
|
||||
int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap,
|
||||
int _uniquenessRatio, int _speckleWindowSize, int _speckleRange,
|
||||
int _mode )
|
||||
: params(_minDisparity, _numDisparities, _SADWindowSize,
|
||||
_P1, _P2, _disp12MaxDiff, _preFilterCap,
|
||||
_uniquenessRatio, _speckleWindowSize, _speckleRange,
|
||||
_mode)
|
||||
{
|
||||
params = StereoSGBMParams( _minDisparity, _numDisparities, _SADWindowSize,
|
||||
_P1, _P2, _disp12MaxDiff, _preFilterCap,
|
||||
_uniquenessRatio, _speckleWindowSize, _speckleRange,
|
||||
_mode );
|
||||
// nothing
|
||||
}
|
||||
|
||||
void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) CV_OVERRIDE
|
||||
|
||||
@@ -837,6 +837,43 @@ TEST(Calib3d_SolvePnPRansac, double_support)
|
||||
EXPECT_LE(cvtest::norm(t, Mat_<double>(tF), NORM_INF), 1e-3);
|
||||
}
|
||||
|
||||
TEST(Calib3d_SolvePnPRansac, bad_input_points_19253)
|
||||
{
|
||||
// with this specific data
|
||||
// when computing the final pose using points in the consensus set with SOLVEPNP_ITERATIVE and solvePnP()
|
||||
// an exception is thrown from solvePnP because there are 5 non-coplanar 3D points and the DLT algorithm needs at least 6 non-coplanar 3D points
|
||||
// with PR #19253 we choose to return true, with the pose estimated from the MSS stage instead of throwing the exception
|
||||
|
||||
float pts2d_[] = {
|
||||
-5.38358629e-01f, -5.09638414e-02f,
|
||||
-5.07192254e-01f, -2.20743284e-01f,
|
||||
-5.43107152e-01f, -4.90474701e-02f,
|
||||
-5.54325163e-01f, -1.86715424e-01f,
|
||||
-5.59334219e-01f, -4.01909500e-02f,
|
||||
-5.43504596e-01f, -4.61776406e-02f
|
||||
};
|
||||
Mat pts2d(6, 2, CV_32FC1, pts2d_);
|
||||
|
||||
float pts3d_[] = {
|
||||
-3.01153604e-02f, -1.55665115e-01f, 4.50000018e-01f,
|
||||
4.27827090e-01f, 4.28645730e-01f, 1.08600008e+00f,
|
||||
-3.14165242e-02f, -1.52656138e-01f, 4.50000018e-01f,
|
||||
-1.46217480e-01f, 5.57961613e-02f, 7.17000008e-01f,
|
||||
-4.89348806e-02f, -1.38795510e-01f, 4.47000027e-01f,
|
||||
-3.13065052e-02f, -1.52636901e-01f, 4.51000035e-01f
|
||||
};
|
||||
Mat pts3d(6, 3, CV_32FC1, pts3d_);
|
||||
|
||||
Mat camera_mat = Mat::eye(3, 3, CV_64FC1);
|
||||
Mat rvec, tvec;
|
||||
vector<int> inliers;
|
||||
|
||||
// solvePnPRansac will return true with 5 inliers, which means the result is from MSS stage.
|
||||
bool result = solvePnPRansac(pts3d, pts2d, camera_mat, noArray(), rvec, tvec, false, 100, 4.f / 460.f, 0.99, inliers);
|
||||
EXPECT_EQ(inliers.size(), size_t(5));
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
TEST(Calib3d_SolvePnP, input_type)
|
||||
{
|
||||
Matx33d intrinsics(5.4794130238156129e+002, 0., 2.9835545700043139e+002, 0.,
|
||||
|
||||
@@ -112,6 +112,10 @@ ocv_target_link_libraries(${the_module} PRIVATE
|
||||
"${OPENCV_HAL_LINKER_LIBS}"
|
||||
)
|
||||
|
||||
if(OPENCV_CORE_EXCLUDE_C_API)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "OPENCV_EXCLUDE_C_API=1")
|
||||
endif()
|
||||
|
||||
ocv_add_accuracy_tests()
|
||||
ocv_add_perf_tests()
|
||||
|
||||
|
||||
@@ -587,6 +587,21 @@ _AccTp normInf(const _Tp* a, const _Tp* b, int n)
|
||||
*/
|
||||
CV_EXPORTS_W float cubeRoot(float val);
|
||||
|
||||
/** @overload
|
||||
|
||||
cubeRoot with argument of `double` type calls `std::cbrt(double)` (C++11) or falls back on `pow()` for C++98 compilation mode.
|
||||
*/
|
||||
static inline
|
||||
double cubeRoot(double val)
|
||||
{
|
||||
#ifdef CV_CXX11
|
||||
return std::cbrt(val);
|
||||
#else
|
||||
double v = pow(abs(val), 1/3.); // pow doesn't support negative inputs with fractional exponents
|
||||
return val >= 0 ? v : -v;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @brief Calculates the angle of a 2D vector in degrees.
|
||||
|
||||
The function fastAtan2 calculates the full-range angle of an input 2D vector. The angle is measured
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <opencv2/core/async.hpp>
|
||||
#include <opencv2/core/detail/async_promise.hpp>
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -144,7 +145,26 @@ AsyncArray testAsyncException()
|
||||
return p.getArrayResult();
|
||||
}
|
||||
|
||||
//! @}
|
||||
}} // namespace
|
||||
//! @} // core_utils
|
||||
} // namespace cv::utils
|
||||
|
||||
//! @cond IGNORED
|
||||
|
||||
CV_WRAP static inline
|
||||
int setLogLevel(int level)
|
||||
{
|
||||
// NB: Binding generators doesn't work with enums properly yet, so we define separate overload here
|
||||
return cv::utils::logging::setLogLevel((cv::utils::logging::LogLevel)level);
|
||||
}
|
||||
|
||||
CV_WRAP static inline
|
||||
int getLogLevel()
|
||||
{
|
||||
return cv::utils::logging::getLogLevel();
|
||||
}
|
||||
|
||||
//! @endcond IGNORED
|
||||
|
||||
} // namespaces cv / utils
|
||||
|
||||
#endif // OPENCV_CORE_BINDINGS_UTILS_HPP
|
||||
|
||||
@@ -76,6 +76,9 @@
|
||||
#if defined __PPC64__ && defined __GNUC__ && defined _ARCH_PWR8 \
|
||||
&& !defined(OPENCV_SKIP_INCLUDE_ALTIVEC_H)
|
||||
#include <altivec.h>
|
||||
#undef vector
|
||||
#undef bool
|
||||
#undef pixel
|
||||
#endif
|
||||
|
||||
#if defined(CV_INLINE_ROUND_FLT)
|
||||
|
||||
@@ -104,7 +104,7 @@ template<typename _Tp> struct V_TypeTraits
|
||||
{
|
||||
};
|
||||
|
||||
#define CV_INTRIN_DEF_TYPE_TRAITS(type, int_type_, uint_type_, abs_type_, w_type_, q_type_, sum_type_, nlanes128_) \
|
||||
#define CV_INTRIN_DEF_TYPE_TRAITS(type, int_type_, uint_type_, abs_type_, w_type_, q_type_, sum_type_) \
|
||||
template<> struct V_TypeTraits<type> \
|
||||
{ \
|
||||
typedef type value_type; \
|
||||
@@ -114,7 +114,6 @@ template<typename _Tp> struct V_TypeTraits
|
||||
typedef w_type_ w_type; \
|
||||
typedef q_type_ q_type; \
|
||||
typedef sum_type_ sum_type; \
|
||||
enum { nlanes128 = nlanes128_ }; \
|
||||
\
|
||||
static inline int_type reinterpret_int(type x) \
|
||||
{ \
|
||||
@@ -131,7 +130,7 @@ template<typename _Tp> struct V_TypeTraits
|
||||
} \
|
||||
}
|
||||
|
||||
#define CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(type, int_type_, uint_type_, abs_type_, w_type_, sum_type_, nlanes128_) \
|
||||
#define CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(type, int_type_, uint_type_, abs_type_, w_type_, sum_type_) \
|
||||
template<> struct V_TypeTraits<type> \
|
||||
{ \
|
||||
typedef type value_type; \
|
||||
@@ -140,7 +139,6 @@ template<typename _Tp> struct V_TypeTraits
|
||||
typedef uint_type_ uint_type; \
|
||||
typedef w_type_ w_type; \
|
||||
typedef sum_type_ sum_type; \
|
||||
enum { nlanes128 = nlanes128_ }; \
|
||||
\
|
||||
static inline int_type reinterpret_int(type x) \
|
||||
{ \
|
||||
@@ -157,16 +155,16 @@ template<typename _Tp> struct V_TypeTraits
|
||||
} \
|
||||
}
|
||||
|
||||
CV_INTRIN_DEF_TYPE_TRAITS(uchar, schar, uchar, uchar, ushort, unsigned, unsigned, 16);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS(schar, schar, uchar, uchar, short, int, int, 16);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS(ushort, short, ushort, ushort, unsigned, uint64, unsigned, 8);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS(short, short, ushort, ushort, int, int64, int, 8);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(unsigned, int, unsigned, unsigned, uint64, unsigned, 4);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int, int, unsigned, unsigned, int64, int, 4);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(float, int, unsigned, float, double, float, 4);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(uint64, int64, uint64, uint64, void, uint64, 2);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int64, int64, uint64, uint64, void, int64, 2);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(double, int64, uint64, double, void, double, 2);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS(uchar, schar, uchar, uchar, ushort, unsigned, unsigned);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS(schar, schar, uchar, uchar, short, int, int);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS(ushort, short, ushort, ushort, unsigned, uint64, unsigned);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS(short, short, ushort, ushort, int, int64, int);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(unsigned, int, unsigned, unsigned, uint64, unsigned);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int, int, unsigned, unsigned, int64, int);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(float, int, unsigned, float, double, float);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(uint64, int64, uint64, uint64, void, uint64);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int64, int64, uint64, uint64, void, int64);
|
||||
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(double, int64, uint64, double, void, double);
|
||||
|
||||
#ifndef CV_DOXYGEN
|
||||
|
||||
@@ -310,54 +308,6 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
|
||||
inline vtyp vx_setall_##short_typ(typ v) { return prefix##_setall_##short_typ(v); } \
|
||||
inline vtyp vx_setzero_##short_typ() { return prefix##_setzero_##short_typ(); } \
|
||||
inline vtyp vx_##loadsfx(const typ* ptr) { return prefix##_##loadsfx(ptr); } \
|
||||
inline vtyp vx_##loadsfx##_aligned(const typ* ptr) { return prefix##_##loadsfx##_aligned(ptr); } \
|
||||
inline vtyp vx_##loadsfx##_low(const typ* ptr) { return prefix##_##loadsfx##_low(ptr); } \
|
||||
inline vtyp vx_##loadsfx##_halves(const typ* ptr0, const typ* ptr1) { return prefix##_##loadsfx##_halves(ptr0, ptr1); } \
|
||||
inline void vx_store(typ* ptr, const vtyp& v) { return v_store(ptr, v); } \
|
||||
inline void vx_store_aligned(typ* ptr, const vtyp& v) { return v_store_aligned(ptr, v); } \
|
||||
inline vtyp vx_lut(const typ* ptr, const int* idx) { return prefix##_lut(ptr, idx); } \
|
||||
inline vtyp vx_lut_pairs(const typ* ptr, const int* idx) { return prefix##_lut_pairs(ptr, idx); }
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_LUT_QUAD(typ, vtyp, prefix) \
|
||||
inline vtyp vx_lut_quads(const typ* ptr, const int* idx) { return prefix##_lut_quads(ptr, idx); }
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
|
||||
inline wtyp vx_load_expand(const typ* ptr) { return prefix##_load_expand(ptr); }
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND_Q(typ, qtyp, prefix) \
|
||||
inline qtyp vx_load_expand_q(const typ* ptr) { return prefix##_load_expand_q(ptr); }
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(typ, vtyp, short_typ, wtyp, qtyp, prefix, loadsfx) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(typ, vtyp, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND_Q(typ, qtyp, prefix)
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(uchar, v_uint8, u8, v_uint16, v_uint32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(schar, v_int8, s8, v_int16, v_int32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(ushort, v_uint16, u16, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(ushort, v_uint16, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(ushort, v_uint32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(short, v_int16, s16, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(short, v_int16, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(short, v_int32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(int, v_int32, s32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(int, v_int32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(int, v_int64, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(unsigned, v_uint32, u32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(unsigned, v_uint32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(unsigned, v_uint64, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(float, v_float32, f32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(float, v_float32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(int64, v_int64, s64, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(uint64, v_uint64, u64, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(float16_t, v_float32, prefix)
|
||||
|
||||
template<typename _Tp> struct V_RegTraits
|
||||
{
|
||||
};
|
||||
@@ -417,6 +367,7 @@ template<typename _Tp> struct V_RegTraits
|
||||
CV_DEF_REG_TRAITS(v512, v_int64x8, int64, s64, v_uint64x8, void, void, v_int64x8, void);
|
||||
CV_DEF_REG_TRAITS(v512, v_float64x8, double, f64, v_float64x8, void, void, v_int64x8, v_int32x16);
|
||||
#endif
|
||||
//! @endcond
|
||||
|
||||
#if CV_SIMD512 && (!defined(CV__SIMD_FORCE_WIDTH) || CV__SIMD_FORCE_WIDTH == 512)
|
||||
#define CV__SIMD_NAMESPACE simd512
|
||||
@@ -425,21 +376,33 @@ namespace CV__SIMD_NAMESPACE {
|
||||
#define CV_SIMD_64F CV_SIMD512_64F
|
||||
#define CV_SIMD_FP16 CV_SIMD512_FP16
|
||||
#define CV_SIMD_WIDTH 64
|
||||
//! @addtogroup core_hal_intrin
|
||||
//! @{
|
||||
//! @brief Maximum available vector register capacity 8-bit unsigned integer values
|
||||
typedef v_uint8x64 v_uint8;
|
||||
//! @brief Maximum available vector register capacity 8-bit signed integer values
|
||||
typedef v_int8x64 v_int8;
|
||||
//! @brief Maximum available vector register capacity 16-bit unsigned integer values
|
||||
typedef v_uint16x32 v_uint16;
|
||||
//! @brief Maximum available vector register capacity 16-bit signed integer values
|
||||
typedef v_int16x32 v_int16;
|
||||
//! @brief Maximum available vector register capacity 32-bit unsigned integer values
|
||||
typedef v_uint32x16 v_uint32;
|
||||
//! @brief Maximum available vector register capacity 32-bit signed integer values
|
||||
typedef v_int32x16 v_int32;
|
||||
//! @brief Maximum available vector register capacity 64-bit unsigned integer values
|
||||
typedef v_uint64x8 v_uint64;
|
||||
//! @brief Maximum available vector register capacity 64-bit signed integer values
|
||||
typedef v_int64x8 v_int64;
|
||||
//! @brief Maximum available vector register capacity 32-bit floating point values (single precision)
|
||||
typedef v_float32x16 v_float32;
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v512)
|
||||
#if CV_SIMD512_64F
|
||||
#if CV_SIMD512_64F
|
||||
//! @brief Maximum available vector register capacity 64-bit floating point values (double precision)
|
||||
typedef v_float64x8 v_float64;
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v512, load)
|
||||
#endif
|
||||
inline void vx_cleanup() { v512_cleanup(); }
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
#define VXPREFIX(func) v512##func
|
||||
} // namespace
|
||||
using namespace CV__SIMD_NAMESPACE;
|
||||
#elif CV_SIMD256 && (!defined(CV__SIMD_FORCE_WIDTH) || CV__SIMD_FORCE_WIDTH == 256)
|
||||
@@ -449,21 +412,33 @@ namespace CV__SIMD_NAMESPACE {
|
||||
#define CV_SIMD_64F CV_SIMD256_64F
|
||||
#define CV_SIMD_FP16 CV_SIMD256_FP16
|
||||
#define CV_SIMD_WIDTH 32
|
||||
//! @addtogroup core_hal_intrin
|
||||
//! @{
|
||||
//! @brief Maximum available vector register capacity 8-bit unsigned integer values
|
||||
typedef v_uint8x32 v_uint8;
|
||||
//! @brief Maximum available vector register capacity 8-bit signed integer values
|
||||
typedef v_int8x32 v_int8;
|
||||
//! @brief Maximum available vector register capacity 16-bit unsigned integer values
|
||||
typedef v_uint16x16 v_uint16;
|
||||
//! @brief Maximum available vector register capacity 16-bit signed integer values
|
||||
typedef v_int16x16 v_int16;
|
||||
//! @brief Maximum available vector register capacity 32-bit unsigned integer values
|
||||
typedef v_uint32x8 v_uint32;
|
||||
//! @brief Maximum available vector register capacity 32-bit signed integer values
|
||||
typedef v_int32x8 v_int32;
|
||||
//! @brief Maximum available vector register capacity 64-bit unsigned integer values
|
||||
typedef v_uint64x4 v_uint64;
|
||||
//! @brief Maximum available vector register capacity 64-bit signed integer values
|
||||
typedef v_int64x4 v_int64;
|
||||
//! @brief Maximum available vector register capacity 32-bit floating point values (single precision)
|
||||
typedef v_float32x8 v_float32;
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v256)
|
||||
#if CV_SIMD256_64F
|
||||
//! @brief Maximum available vector register capacity 64-bit floating point values (double precision)
|
||||
typedef v_float64x4 v_float64;
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v256, load)
|
||||
#endif
|
||||
inline void vx_cleanup() { v256_cleanup(); }
|
||||
//! @}
|
||||
|
||||
#define VXPREFIX(func) v256##func
|
||||
} // namespace
|
||||
using namespace CV__SIMD_NAMESPACE;
|
||||
#elif (CV_SIMD128 || CV_SIMD128_CPP) && (!defined(CV__SIMD_FORCE_WIDTH) || CV__SIMD_FORCE_WIDTH == 128)
|
||||
@@ -476,25 +451,228 @@ namespace CV__SIMD_NAMESPACE {
|
||||
#define CV_SIMD CV_SIMD128
|
||||
#define CV_SIMD_64F CV_SIMD128_64F
|
||||
#define CV_SIMD_WIDTH 16
|
||||
//! @addtogroup core_hal_intrin
|
||||
//! @{
|
||||
//! @brief Maximum available vector register capacity 8-bit unsigned integer values
|
||||
typedef v_uint8x16 v_uint8;
|
||||
//! @brief Maximum available vector register capacity 8-bit signed integer values
|
||||
typedef v_int8x16 v_int8;
|
||||
//! @brief Maximum available vector register capacity 16-bit unsigned integer values
|
||||
typedef v_uint16x8 v_uint16;
|
||||
//! @brief Maximum available vector register capacity 16-bit signed integer values
|
||||
typedef v_int16x8 v_int16;
|
||||
//! @brief Maximum available vector register capacity 32-bit unsigned integer values
|
||||
typedef v_uint32x4 v_uint32;
|
||||
//! @brief Maximum available vector register capacity 32-bit signed integer values
|
||||
typedef v_int32x4 v_int32;
|
||||
//! @brief Maximum available vector register capacity 64-bit unsigned integer values
|
||||
typedef v_uint64x2 v_uint64;
|
||||
//! @brief Maximum available vector register capacity 64-bit signed integer values
|
||||
typedef v_int64x2 v_int64;
|
||||
//! @brief Maximum available vector register capacity 32-bit floating point values (single precision)
|
||||
typedef v_float32x4 v_float32;
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v)
|
||||
#if CV_SIMD128_64F
|
||||
//! @brief Maximum available vector register capacity 64-bit floating point values (double precision)
|
||||
typedef v_float64x2 v_float64;
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v, load)
|
||||
#endif
|
||||
inline void vx_cleanup() { v_cleanup(); }
|
||||
//! @}
|
||||
|
||||
#define VXPREFIX(func) v##func
|
||||
} // namespace
|
||||
using namespace CV__SIMD_NAMESPACE;
|
||||
#endif
|
||||
|
||||
namespace CV__SIMD_NAMESPACE {
|
||||
//! @addtogroup core_hal_intrin
|
||||
//! @{
|
||||
//! @name Wide init with value
|
||||
//! @{
|
||||
//! @brief Create maximum available capacity vector with elements set to a specific value
|
||||
inline v_uint8 vx_setall_u8(uchar v) { return VXPREFIX(_setall_u8)(v); }
|
||||
inline v_int8 vx_setall_s8(schar v) { return VXPREFIX(_setall_s8)(v); }
|
||||
inline v_uint16 vx_setall_u16(ushort v) { return VXPREFIX(_setall_u16)(v); }
|
||||
inline v_int16 vx_setall_s16(short v) { return VXPREFIX(_setall_s16)(v); }
|
||||
inline v_int32 vx_setall_s32(int v) { return VXPREFIX(_setall_s32)(v); }
|
||||
inline v_uint32 vx_setall_u32(unsigned v) { return VXPREFIX(_setall_u32)(v); }
|
||||
inline v_float32 vx_setall_f32(float v) { return VXPREFIX(_setall_f32)(v); }
|
||||
inline v_int64 vx_setall_s64(int64 v) { return VXPREFIX(_setall_s64)(v); }
|
||||
inline v_uint64 vx_setall_u64(uint64 v) { return VXPREFIX(_setall_u64)(v); }
|
||||
#if CV_SIMD_64F
|
||||
inline v_float64 vx_setall_f64(double v) { return VXPREFIX(_setall_f64)(v); }
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
//! @name Wide init with zero
|
||||
//! @{
|
||||
//! @brief Create maximum available capacity vector with elements set to zero
|
||||
inline v_uint8 vx_setzero_u8() { return VXPREFIX(_setzero_u8)(); }
|
||||
inline v_int8 vx_setzero_s8() { return VXPREFIX(_setzero_s8)(); }
|
||||
inline v_uint16 vx_setzero_u16() { return VXPREFIX(_setzero_u16)(); }
|
||||
inline v_int16 vx_setzero_s16() { return VXPREFIX(_setzero_s16)(); }
|
||||
inline v_int32 vx_setzero_s32() { return VXPREFIX(_setzero_s32)(); }
|
||||
inline v_uint32 vx_setzero_u32() { return VXPREFIX(_setzero_u32)(); }
|
||||
inline v_float32 vx_setzero_f32() { return VXPREFIX(_setzero_f32)(); }
|
||||
inline v_int64 vx_setzero_s64() { return VXPREFIX(_setzero_s64)(); }
|
||||
inline v_uint64 vx_setzero_u64() { return VXPREFIX(_setzero_u64)(); }
|
||||
#if CV_SIMD_64F
|
||||
inline v_float64 vx_setzero_f64() { return VXPREFIX(_setzero_f64)(); }
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
//! @name Wide load from memory
|
||||
//! @{
|
||||
//! @brief Load maximum available capacity register contents from memory
|
||||
inline v_uint8 vx_load(const uchar * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
inline v_int8 vx_load(const schar * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
inline v_uint16 vx_load(const ushort * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
inline v_int16 vx_load(const short * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
inline v_int32 vx_load(const int * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
inline v_uint32 vx_load(const unsigned * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
inline v_float32 vx_load(const float * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
inline v_int64 vx_load(const int64 * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
inline v_uint64 vx_load(const uint64 * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
#if CV_SIMD_64F
|
||||
inline v_float64 vx_load(const double * ptr) { return VXPREFIX(_load)(ptr); }
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
//! @name Wide load from memory(aligned)
|
||||
//! @{
|
||||
//! @brief Load maximum available capacity register contents from memory(aligned)
|
||||
inline v_uint8 vx_load_aligned(const uchar * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
inline v_int8 vx_load_aligned(const schar * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
inline v_uint16 vx_load_aligned(const ushort * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
inline v_int16 vx_load_aligned(const short * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
inline v_int32 vx_load_aligned(const int * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
inline v_uint32 vx_load_aligned(const unsigned * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
inline v_float32 vx_load_aligned(const float * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
inline v_int64 vx_load_aligned(const int64 * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
inline v_uint64 vx_load_aligned(const uint64 * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
#if CV_SIMD_64F
|
||||
inline v_float64 vx_load_aligned(const double * ptr) { return VXPREFIX(_load_aligned)(ptr); }
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
//! @name Wide load lower half from memory
|
||||
//! @{
|
||||
//! @brief Load lower half of maximum available capacity register from memory
|
||||
inline v_uint8 vx_load_low(const uchar * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
inline v_int8 vx_load_low(const schar * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
inline v_uint16 vx_load_low(const ushort * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
inline v_int16 vx_load_low(const short * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
inline v_int32 vx_load_low(const int * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
inline v_uint32 vx_load_low(const unsigned * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
inline v_float32 vx_load_low(const float * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
inline v_int64 vx_load_low(const int64 * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
inline v_uint64 vx_load_low(const uint64 * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
#if CV_SIMD_64F
|
||||
inline v_float64 vx_load_low(const double * ptr) { return VXPREFIX(_load_low)(ptr); }
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
//! @name Wide load halfs from memory
|
||||
//! @{
|
||||
//! @brief Load maximum available capacity register contents from two memory blocks
|
||||
inline v_uint8 vx_load_halves(const uchar * ptr0, const uchar * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
inline v_int8 vx_load_halves(const schar * ptr0, const schar * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
inline v_uint16 vx_load_halves(const ushort * ptr0, const ushort * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
inline v_int16 vx_load_halves(const short * ptr0, const short * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
inline v_int32 vx_load_halves(const int * ptr0, const int * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
inline v_uint32 vx_load_halves(const unsigned * ptr0, const unsigned * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
inline v_float32 vx_load_halves(const float * ptr0, const float * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
inline v_int64 vx_load_halves(const int64 * ptr0, const int64 * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
inline v_uint64 vx_load_halves(const uint64 * ptr0, const uint64 * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
#if CV_SIMD_64F
|
||||
inline v_float64 vx_load_halves(const double * ptr0, const double * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
//! @name Wide LUT of elements
|
||||
//! @{
|
||||
//! @brief Load maximum available capacity register contents with array elements by provided indexes
|
||||
inline v_uint8 vx_lut(const uchar * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
inline v_int8 vx_lut(const schar * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
inline v_uint16 vx_lut(const ushort * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
inline v_int16 vx_lut(const short* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
inline v_int32 vx_lut(const int* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
inline v_uint32 vx_lut(const unsigned* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
inline v_float32 vx_lut(const float* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
inline v_int64 vx_lut(const int64 * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
inline v_uint64 vx_lut(const uint64 * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
#if CV_SIMD_64F
|
||||
inline v_float64 vx_lut(const double* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
//! @name Wide LUT of element pairs
|
||||
//! @{
|
||||
//! @brief Load maximum available capacity register contents with array element pairs by provided indexes
|
||||
inline v_uint8 vx_lut_pairs(const uchar * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
inline v_int8 vx_lut_pairs(const schar * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
inline v_uint16 vx_lut_pairs(const ushort * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
inline v_int16 vx_lut_pairs(const short* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
inline v_int32 vx_lut_pairs(const int* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
inline v_uint32 vx_lut_pairs(const unsigned* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
inline v_float32 vx_lut_pairs(const float* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
inline v_int64 vx_lut_pairs(const int64 * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
inline v_uint64 vx_lut_pairs(const uint64 * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
#if CV_SIMD_64F
|
||||
inline v_float64 vx_lut_pairs(const double* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
//! @name Wide LUT of element quads
|
||||
//! @{
|
||||
//! @brief Load maximum available capacity register contents with array element quads by provided indexes
|
||||
inline v_uint8 vx_lut_quads(const uchar* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
|
||||
inline v_int8 vx_lut_quads(const schar* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
|
||||
inline v_uint16 vx_lut_quads(const ushort* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
|
||||
inline v_int16 vx_lut_quads(const short* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
|
||||
inline v_int32 vx_lut_quads(const int* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
|
||||
inline v_uint32 vx_lut_quads(const unsigned* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
|
||||
inline v_float32 vx_lut_quads(const float* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
|
||||
//! @}
|
||||
|
||||
//! @name Wide load with double expansion
|
||||
//! @{
|
||||
//! @brief Load maximum available capacity register contents from memory with double expand
|
||||
inline v_uint16 vx_load_expand(const uchar * ptr) { return VXPREFIX(_load_expand)(ptr); }
|
||||
inline v_int16 vx_load_expand(const schar * ptr) { return VXPREFIX(_load_expand)(ptr); }
|
||||
inline v_uint32 vx_load_expand(const ushort * ptr) { return VXPREFIX(_load_expand)(ptr); }
|
||||
inline v_int32 vx_load_expand(const short* ptr) { return VXPREFIX(_load_expand)(ptr); }
|
||||
inline v_int64 vx_load_expand(const int* ptr) { return VXPREFIX(_load_expand)(ptr); }
|
||||
inline v_uint64 vx_load_expand(const unsigned* ptr) { return VXPREFIX(_load_expand)(ptr); }
|
||||
inline v_float32 vx_load_expand(const float16_t * ptr) { return VXPREFIX(_load_expand)(ptr); }
|
||||
//! @}
|
||||
|
||||
//! @name Wide load with quad expansion
|
||||
//! @{
|
||||
//! @brief Load maximum available capacity register contents from memory with quad expand
|
||||
inline v_uint32 vx_load_expand_q(const uchar * ptr) { return VXPREFIX(_load_expand_q)(ptr); }
|
||||
inline v_int32 vx_load_expand_q(const schar * ptr) { return VXPREFIX(_load_expand_q)(ptr); }
|
||||
//! @}
|
||||
|
||||
/** @brief SIMD processing state cleanup call */
|
||||
inline void vx_cleanup() { VXPREFIX(_cleanup)(); }
|
||||
|
||||
|
||||
//! @cond IGNORED
|
||||
|
||||
// backward compatibility
|
||||
template<typename _Tp, typename _Tvec> static inline
|
||||
void vx_store(_Tp* dst, const _Tvec& v) { return v_store(dst, v); }
|
||||
// backward compatibility
|
||||
template<typename _Tp, typename _Tvec> static inline
|
||||
void vx_store_aligned(_Tp* dst, const _Tvec& v) { return v_store_aligned(dst, v); }
|
||||
|
||||
//! @endcond
|
||||
|
||||
|
||||
//! @}
|
||||
#undef VXPREFIX
|
||||
} // namespace
|
||||
|
||||
//! @cond IGNORED
|
||||
#ifndef CV_SIMD_64F
|
||||
#define CV_SIMD_64F 0
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1539,6 +1539,26 @@ OPENCV_HAL_IMPL_NEON_SELECT(v_float32x4, f32, u32)
|
||||
OPENCV_HAL_IMPL_NEON_SELECT(v_float64x2, f64, u64)
|
||||
#endif
|
||||
|
||||
#if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_EXPAND(_Tpvec, _Tpwvec, _Tp, suffix) \
|
||||
inline void v_expand(const _Tpvec& a, _Tpwvec& b0, _Tpwvec& b1) \
|
||||
{ \
|
||||
b0.val = vmovl_##suffix(vget_low_##suffix(a.val)); \
|
||||
b1.val = vmovl_high_##suffix(a.val); \
|
||||
} \
|
||||
inline _Tpwvec v_expand_low(const _Tpvec& a) \
|
||||
{ \
|
||||
return _Tpwvec(vmovl_##suffix(vget_low_##suffix(a.val))); \
|
||||
} \
|
||||
inline _Tpwvec v_expand_high(const _Tpvec& a) \
|
||||
{ \
|
||||
return _Tpwvec(vmovl_high_##suffix(a.val)); \
|
||||
} \
|
||||
inline _Tpwvec v_load_expand(const _Tp* ptr) \
|
||||
{ \
|
||||
return _Tpwvec(vmovl_##suffix(vld1_##suffix(ptr))); \
|
||||
}
|
||||
#else
|
||||
#define OPENCV_HAL_IMPL_NEON_EXPAND(_Tpvec, _Tpwvec, _Tp, suffix) \
|
||||
inline void v_expand(const _Tpvec& a, _Tpwvec& b0, _Tpwvec& b1) \
|
||||
{ \
|
||||
@@ -1557,6 +1577,7 @@ inline _Tpwvec v_load_expand(const _Tp* ptr) \
|
||||
{ \
|
||||
return _Tpwvec(vmovl_##suffix(vld1_##suffix(ptr))); \
|
||||
}
|
||||
#endif
|
||||
|
||||
OPENCV_HAL_IMPL_NEON_EXPAND(v_uint8x16, v_uint16x8, uchar, u8)
|
||||
OPENCV_HAL_IMPL_NEON_EXPAND(v_int8x16, v_int16x8, schar, s8)
|
||||
|
||||
@@ -583,24 +583,24 @@ struct CV_EXPORTS UMatData
|
||||
|
||||
struct CV_EXPORTS MatSize
|
||||
{
|
||||
explicit MatSize(int* _p);
|
||||
int dims() const;
|
||||
explicit MatSize(int* _p) CV_NOEXCEPT;
|
||||
int dims() const CV_NOEXCEPT;
|
||||
Size operator()() const;
|
||||
const int& operator[](int i) const;
|
||||
int& operator[](int i);
|
||||
operator const int*() const; // TODO OpenCV 4.0: drop this
|
||||
bool operator == (const MatSize& sz) const;
|
||||
bool operator != (const MatSize& sz) const;
|
||||
operator const int*() const CV_NOEXCEPT; // TODO OpenCV 4.0: drop this
|
||||
bool operator == (const MatSize& sz) const CV_NOEXCEPT;
|
||||
bool operator != (const MatSize& sz) const CV_NOEXCEPT;
|
||||
|
||||
int* p;
|
||||
};
|
||||
|
||||
struct CV_EXPORTS MatStep
|
||||
{
|
||||
MatStep();
|
||||
explicit MatStep(size_t s);
|
||||
const size_t& operator[](int i) const;
|
||||
size_t& operator[](int i);
|
||||
MatStep() CV_NOEXCEPT;
|
||||
explicit MatStep(size_t s) CV_NOEXCEPT;
|
||||
const size_t& operator[](int i) const CV_NOEXCEPT;
|
||||
size_t& operator[](int i) CV_NOEXCEPT;
|
||||
operator size_t() const;
|
||||
MatStep& operator = (size_t s);
|
||||
|
||||
@@ -819,7 +819,7 @@ public:
|
||||
The constructed matrix can further be assigned to another matrix or matrix expression or can be
|
||||
allocated with Mat::create . In the former case, the old content is de-referenced.
|
||||
*/
|
||||
Mat();
|
||||
Mat() CV_NOEXCEPT;
|
||||
|
||||
/** @overload
|
||||
@param rows Number of rows in a 2D array.
|
||||
@@ -2220,7 +2220,7 @@ public:
|
||||
typedef MatConstIterator_<_Tp> const_iterator;
|
||||
|
||||
//! default constructor
|
||||
Mat_();
|
||||
Mat_() CV_NOEXCEPT;
|
||||
//! equivalent to Mat(_rows, _cols, DataType<_Tp>::type)
|
||||
Mat_(int _rows, int _cols);
|
||||
//! constructor that sets each matrix element to specified value
|
||||
@@ -2420,7 +2420,7 @@ class CV_EXPORTS UMat
|
||||
{
|
||||
public:
|
||||
//! default constructor
|
||||
UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT);
|
||||
UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT) CV_NOEXCEPT;
|
||||
//! constructs 2D matrix of the specified size and type
|
||||
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
|
||||
UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
|
||||
|
||||
@@ -1218,11 +1218,11 @@ Mat& Mat::operator = (Mat&& m)
|
||||
///////////////////////////// MatSize ////////////////////////////
|
||||
|
||||
inline
|
||||
MatSize::MatSize(int* _p)
|
||||
MatSize::MatSize(int* _p) CV_NOEXCEPT
|
||||
: p(_p) {}
|
||||
|
||||
inline
|
||||
int MatSize::dims() const
|
||||
int MatSize::dims() const CV_NOEXCEPT
|
||||
{
|
||||
return (p - 1)[0];
|
||||
}
|
||||
@@ -1255,13 +1255,13 @@ int& MatSize::operator[](int i)
|
||||
}
|
||||
|
||||
inline
|
||||
MatSize::operator const int*() const
|
||||
MatSize::operator const int*() const CV_NOEXCEPT
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
inline
|
||||
bool MatSize::operator != (const MatSize& sz) const
|
||||
bool MatSize::operator != (const MatSize& sz) const CV_NOEXCEPT
|
||||
{
|
||||
return !(*this == sz);
|
||||
}
|
||||
@@ -1271,25 +1271,25 @@ bool MatSize::operator != (const MatSize& sz) const
|
||||
///////////////////////////// MatStep ////////////////////////////
|
||||
|
||||
inline
|
||||
MatStep::MatStep()
|
||||
MatStep::MatStep() CV_NOEXCEPT
|
||||
{
|
||||
p = buf; p[0] = p[1] = 0;
|
||||
}
|
||||
|
||||
inline
|
||||
MatStep::MatStep(size_t s)
|
||||
MatStep::MatStep(size_t s) CV_NOEXCEPT
|
||||
{
|
||||
p = buf; p[0] = s; p[1] = 0;
|
||||
}
|
||||
|
||||
inline
|
||||
const size_t& MatStep::operator[](int i) const
|
||||
const size_t& MatStep::operator[](int i) const CV_NOEXCEPT
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
|
||||
inline
|
||||
size_t& MatStep::operator[](int i)
|
||||
size_t& MatStep::operator[](int i) CV_NOEXCEPT
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
@@ -1312,7 +1312,7 @@ inline MatStep& MatStep::operator = (size_t s)
|
||||
////////////////////////////// Mat_<_Tp> ////////////////////////////
|
||||
|
||||
template<typename _Tp> inline
|
||||
Mat_<_Tp>::Mat_()
|
||||
Mat_<_Tp>::Mat_() CV_NOEXCEPT
|
||||
: Mat()
|
||||
{
|
||||
flags = (flags & ~CV_MAT_TYPE_MASK) | traits::Type<_Tp>::value;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#define CV_VERSION_MAJOR 3
|
||||
#define CV_VERSION_MINOR 4
|
||||
#define CV_VERSION_REVISION 14
|
||||
#define CV_VERSION_STATUS "-pre"
|
||||
#define CV_VERSION_STATUS ""
|
||||
|
||||
#define CVAUX_STR_EXP(__A) #__A
|
||||
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
|
||||
|
||||
@@ -497,11 +497,13 @@ VSX_IMPL_CONV_EVEN_2_4(vec_uint4, vec_double2, vec_ctu, vec_ctuo)
|
||||
VSX_FINLINE(rt) fnm(const rg& a, int only_truncate) \
|
||||
{ \
|
||||
assert(only_truncate == 0); \
|
||||
CV_UNUSED(only_truncate); \
|
||||
CV_UNUSED(only_truncate); \
|
||||
return fn2(a); \
|
||||
}
|
||||
VSX_IMPL_CONV_2VARIANT(vec_int4, vec_float4, vec_cts, vec_cts)
|
||||
VSX_IMPL_CONV_2VARIANT(vec_uint4, vec_float4, vec_ctu, vec_ctu)
|
||||
VSX_IMPL_CONV_2VARIANT(vec_float4, vec_int4, vec_ctf, vec_ctf)
|
||||
VSX_IMPL_CONV_2VARIANT(vec_float4, vec_uint4, vec_ctf, vec_ctf)
|
||||
// define vec_cts for converting double precision to signed doubleword
|
||||
// which isn't compatible with xlc but its okay since Eigen only uses it for gcc
|
||||
VSX_IMPL_CONV_2VARIANT(vec_dword2, vec_double2, vec_cts, vec_ctsl)
|
||||
|
||||
+16
-27
@@ -57,24 +57,6 @@ namespace cv
|
||||
* logical operations *
|
||||
\****************************************************************************************/
|
||||
|
||||
void convertAndUnrollScalar( const Mat& sc, int buftype, uchar* scbuf, size_t blocksize )
|
||||
{
|
||||
int scn = (int)sc.total(), cn = CV_MAT_CN(buftype);
|
||||
size_t esz = CV_ELEM_SIZE(buftype);
|
||||
getConvertFunc(sc.depth(), buftype)(sc.ptr(), 1, 0, 1, scbuf, 1, Size(std::min(cn, scn), 1), 0);
|
||||
// unroll the scalar
|
||||
if( scn < cn )
|
||||
{
|
||||
CV_Assert( scn == 1 );
|
||||
size_t esz1 = CV_ELEM_SIZE1(buftype);
|
||||
for( size_t i = esz1; i < esz; i++ )
|
||||
scbuf[i] = scbuf[i - esz1];
|
||||
}
|
||||
for( size_t i = esz; i < blocksize*esz; i++ )
|
||||
scbuf[i] = scbuf[i - esz];
|
||||
}
|
||||
|
||||
|
||||
enum { OCL_OP_ADD=0, OCL_OP_SUB=1, OCL_OP_RSUB=2, OCL_OP_ABSDIFF=3, OCL_OP_MUL=4,
|
||||
OCL_OP_MUL_SCALE=5, OCL_OP_DIV_SCALE=6, OCL_OP_RECIP_SCALE=7, OCL_OP_ADDW=8,
|
||||
OCL_OP_AND=9, OCL_OP_OR=10, OCL_OP_XOR=11, OCL_OP_NOT=12, OCL_OP_MIN=13, OCL_OP_MAX=14,
|
||||
@@ -641,7 +623,8 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst,
|
||||
(kind1 == _InputArray::MATX && (sz1 == Size(1,4) || sz1 == Size(1,1))) ||
|
||||
(kind2 == _InputArray::MATX && (sz2 == Size(1,4) || sz2 == Size(1,1))) )
|
||||
{
|
||||
if( checkScalar(*psrc1, type2, kind1, kind2) )
|
||||
if ((type1 == CV_64F && (sz1.height == 1 || sz1.height == 4)) &&
|
||||
checkScalar(*psrc1, type2, kind1, kind2))
|
||||
{
|
||||
// src1 is a scalar; swap it with src2
|
||||
swap(psrc1, psrc2);
|
||||
@@ -1041,9 +1024,7 @@ static BinaryFuncC* getRecipTab()
|
||||
return recipTab;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cv::multiply(InputArray src1, InputArray src2,
|
||||
void multiply(InputArray src1, InputArray src2,
|
||||
OutputArray dst, double scale, int dtype)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
@@ -1052,7 +1033,7 @@ void cv::multiply(InputArray src1, InputArray src2,
|
||||
true, &scale, std::abs(scale - 1.0) < DBL_EPSILON ? OCL_OP_MUL : OCL_OP_MUL_SCALE);
|
||||
}
|
||||
|
||||
void cv::divide(InputArray src1, InputArray src2,
|
||||
void divide(InputArray src1, InputArray src2,
|
||||
OutputArray dst, double scale, int dtype)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
@@ -1060,7 +1041,7 @@ void cv::divide(InputArray src1, InputArray src2,
|
||||
arithm_op(src1, src2, dst, noArray(), dtype, getDivTab(), true, &scale, OCL_OP_DIV_SCALE);
|
||||
}
|
||||
|
||||
void cv::divide(double scale, InputArray src2,
|
||||
void divide(double scale, InputArray src2,
|
||||
OutputArray dst, int dtype)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
@@ -1068,13 +1049,17 @@ void cv::divide(double scale, InputArray src2,
|
||||
arithm_op(src2, src2, dst, noArray(), dtype, getRecipTab(), true, &scale, OCL_OP_RECIP_SCALE);
|
||||
}
|
||||
|
||||
UMat UMat::mul(InputArray m, double scale) const
|
||||
{
|
||||
UMat dst;
|
||||
multiply(*this, m, dst, scale);
|
||||
return dst;
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
* addWeighted *
|
||||
\****************************************************************************************/
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
static BinaryFuncC* getAddWeightedTab()
|
||||
{
|
||||
static BinaryFuncC addWeightedTab[] =
|
||||
@@ -1879,6 +1864,9 @@ void cv::inRange(InputArray _src, InputArray _lowerb,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
/****************************************************************************************\
|
||||
* Earlier API: cvAdd etc. *
|
||||
\****************************************************************************************/
|
||||
@@ -2141,4 +2129,5 @@ cvMaxS( const void* srcarr1, double value, void* dstarr )
|
||||
cv::max( src1, value, dst );
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
/* End of file. */
|
||||
|
||||
+45
-44
@@ -48,6 +48,8 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
#define CV_ORIGIN_TL 0
|
||||
#define CV_ORIGIN_BL 1
|
||||
|
||||
@@ -3223,51 +3225,50 @@ template<> void DefaultDeleter<CvMemStorage>::operator ()(CvMemStorage* obj) con
|
||||
template<> void DefaultDeleter<CvFileStorage>::operator ()(CvFileStorage* obj) const
|
||||
{ cvReleaseFileStorage(&obj); }
|
||||
|
||||
template <typename T> static inline
|
||||
void scalarToRawData_(const Scalar& s, T * const buf, const int cn, const int unroll_to)
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < cn; i++)
|
||||
buf[i] = saturate_cast<T>(s.val[i]);
|
||||
for(; i < unroll_to; i++)
|
||||
buf[i] = buf[i-cn];
|
||||
}
|
||||
|
||||
void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
const int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
CV_Assert(cn <= 4);
|
||||
switch(depth)
|
||||
{
|
||||
case CV_8U:
|
||||
scalarToRawData_<uchar>(s, (uchar*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_8S:
|
||||
scalarToRawData_<schar>(s, (schar*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_16U:
|
||||
scalarToRawData_<ushort>(s, (ushort*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_16S:
|
||||
scalarToRawData_<short>(s, (short*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_32S:
|
||||
scalarToRawData_<int>(s, (int*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_32F:
|
||||
scalarToRawData_<float>(s, (float*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_64F:
|
||||
scalarToRawData_<double>(s, (double*)_buf, cn, unroll_to);
|
||||
break;
|
||||
default:
|
||||
CV_Error(CV_StsUnsupportedFormat,"");
|
||||
}
|
||||
}
|
||||
|
||||
} // cv::
|
||||
|
||||
|
||||
/* universal functions */
|
||||
CV_IMPL void
|
||||
cvRelease( void** struct_ptr )
|
||||
{
|
||||
CvTypeInfo* info;
|
||||
|
||||
if( !struct_ptr )
|
||||
CV_Error( CV_StsNullPtr, "NULL double pointer" );
|
||||
|
||||
if( *struct_ptr )
|
||||
{
|
||||
info = cvTypeOf( *struct_ptr );
|
||||
if( !info )
|
||||
CV_Error( CV_StsError, "Unknown object type" );
|
||||
if( !info->release )
|
||||
CV_Error( CV_StsError, "release function pointer is NULL" );
|
||||
|
||||
info->release( struct_ptr );
|
||||
*struct_ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void* cvClone( const void* struct_ptr )
|
||||
{
|
||||
void* struct_copy = 0;
|
||||
CvTypeInfo* info;
|
||||
|
||||
if( !struct_ptr )
|
||||
CV_Error( CV_StsNullPtr, "NULL structure pointer" );
|
||||
|
||||
info = cvTypeOf( struct_ptr );
|
||||
if( !info )
|
||||
CV_Error( CV_StsError, "Unknown object type" );
|
||||
if( !info->clone )
|
||||
CV_Error( CV_StsError, "clone function pointer is NULL" );
|
||||
|
||||
struct_copy = info->clone( struct_ptr );
|
||||
return struct_copy;
|
||||
}
|
||||
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
/* End of file. */
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
CV_IMPL void
|
||||
cvSplit( const void* srcarr, void* dstarr0, void* dstarr1, void* dstarr2, void* dstarr3 )
|
||||
@@ -132,3 +133,5 @@ CV_IMPL void cvNormalize( const CvArr* srcarr, CvArr* dstarr,
|
||||
CV_Assert( dst.size() == src.size() && src.channels() == dst.channels() );
|
||||
cv::normalize( src, dst, a, b, norm_type, dst.type(), mask );
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "convert_scale.simd.hpp"
|
||||
#include "convert_scale.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
|
||||
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
@@ -117,143 +116,4 @@ void convertScaleAbs(InputArray _src, OutputArray _dst, double alpha, double bet
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_normalize( InputArray _src, InputOutputArray _dst, InputArray _mask, int dtype,
|
||||
double scale, double delta )
|
||||
{
|
||||
UMat src = _src.getUMat();
|
||||
|
||||
if( _mask.empty() )
|
||||
src.convertTo( _dst, dtype, scale, delta );
|
||||
else if (src.channels() <= 4)
|
||||
{
|
||||
const ocl::Device & dev = ocl::Device::getDefault();
|
||||
|
||||
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
|
||||
ddepth = CV_MAT_DEPTH(dtype), wdepth = std::max(CV_32F, std::max(sdepth, ddepth)),
|
||||
rowsPerWI = dev.isIntel() ? 4 : 1;
|
||||
|
||||
float fscale = static_cast<float>(scale), fdelta = static_cast<float>(delta);
|
||||
bool haveScale = std::fabs(scale - 1) > DBL_EPSILON,
|
||||
haveZeroScale = !(std::fabs(scale) > DBL_EPSILON),
|
||||
haveDelta = std::fabs(delta) > DBL_EPSILON,
|
||||
doubleSupport = dev.doubleFPConfig() > 0;
|
||||
|
||||
if (!haveScale && !haveDelta && stype == dtype)
|
||||
{
|
||||
_src.copyTo(_dst, _mask);
|
||||
return true;
|
||||
}
|
||||
if (haveZeroScale)
|
||||
{
|
||||
_dst.setTo(Scalar(delta), _mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((sdepth == CV_64F || ddepth == CV_64F) && !doubleSupport)
|
||||
return false;
|
||||
|
||||
char cvt[2][40];
|
||||
String opts = format("-D srcT=%s -D dstT=%s -D convertToWT=%s -D cn=%d -D rowsPerWI=%d"
|
||||
" -D convertToDT=%s -D workT=%s%s%s%s -D srcT1=%s -D dstT1=%s",
|
||||
ocl::typeToStr(stype), ocl::typeToStr(dtype),
|
||||
ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]), cn,
|
||||
rowsPerWI, ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]),
|
||||
ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : "",
|
||||
haveScale ? " -D HAVE_SCALE" : "",
|
||||
haveDelta ? " -D HAVE_DELTA" : "",
|
||||
ocl::typeToStr(sdepth), ocl::typeToStr(ddepth));
|
||||
|
||||
ocl::Kernel k("normalizek", ocl::core::normalize_oclsrc, opts);
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat mask = _mask.getUMat(), dst = _dst.getUMat();
|
||||
|
||||
ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
|
||||
maskarg = ocl::KernelArg::ReadOnlyNoSize(mask),
|
||||
dstarg = ocl::KernelArg::ReadWrite(dst);
|
||||
|
||||
if (haveScale)
|
||||
{
|
||||
if (haveDelta)
|
||||
k.args(srcarg, maskarg, dstarg, fscale, fdelta);
|
||||
else
|
||||
k.args(srcarg, maskarg, dstarg, fscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (haveDelta)
|
||||
k.args(srcarg, maskarg, dstarg, fdelta);
|
||||
else
|
||||
k.args(srcarg, maskarg, dstarg);
|
||||
}
|
||||
|
||||
size_t globalsize[2] = { (size_t)src.cols, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
UMat temp;
|
||||
src.convertTo( temp, dtype, scale, delta );
|
||||
temp.copyTo( _dst, _mask );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void normalize(InputArray _src, InputOutputArray _dst, double a, double b,
|
||||
int norm_type, int rtype, InputArray _mask)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
double scale = 1, shift = 0;
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type);
|
||||
|
||||
if( rtype < 0 )
|
||||
rtype = _dst.fixedType() ? _dst.depth() : depth;
|
||||
|
||||
if( norm_type == CV_MINMAX )
|
||||
{
|
||||
double smin = 0, smax = 0;
|
||||
double dmin = MIN( a, b ), dmax = MAX( a, b );
|
||||
minMaxIdx( _src, &smin, &smax, 0, 0, _mask );
|
||||
scale = (dmax - dmin)*(smax - smin > DBL_EPSILON ? 1./(smax - smin) : 0);
|
||||
if( rtype == CV_32F )
|
||||
{
|
||||
scale = (float)scale;
|
||||
shift = (float)dmin - (float)(smin*scale);
|
||||
}
|
||||
else
|
||||
shift = dmin - smin*scale;
|
||||
}
|
||||
else if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C )
|
||||
{
|
||||
scale = norm( _src, norm_type, _mask );
|
||||
scale = scale > DBL_EPSILON ? a/scale : 0.;
|
||||
shift = 0;
|
||||
}
|
||||
else
|
||||
CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" );
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat(),
|
||||
ocl_normalize(_src, _dst, _mask, rtype, scale, shift))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
if( _mask.empty() )
|
||||
src.convertTo( _dst, rtype, scale, shift );
|
||||
else
|
||||
{
|
||||
Mat temp;
|
||||
src.convertTo( temp, rtype, scale, shift );
|
||||
temp.copyTo( _dst, _mask );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
+73
-484
@@ -53,6 +53,75 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
template <typename T> static inline
|
||||
void scalarToRawData_(const Scalar& s, T * const buf, const int cn, const int unroll_to)
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < cn; i++)
|
||||
buf[i] = saturate_cast<T>(s.val[i]);
|
||||
for(; i < unroll_to; i++)
|
||||
buf[i] = buf[i-cn];
|
||||
}
|
||||
|
||||
void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
const int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
CV_Assert(cn <= 4);
|
||||
switch(depth)
|
||||
{
|
||||
case CV_8U:
|
||||
scalarToRawData_<uchar>(s, (uchar*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_8S:
|
||||
scalarToRawData_<schar>(s, (schar*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_16U:
|
||||
scalarToRawData_<ushort>(s, (ushort*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_16S:
|
||||
scalarToRawData_<short>(s, (short*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_32S:
|
||||
scalarToRawData_<int>(s, (int*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_32F:
|
||||
scalarToRawData_<float>(s, (float*)_buf, cn, unroll_to);
|
||||
break;
|
||||
case CV_64F:
|
||||
scalarToRawData_<double>(s, (double*)_buf, cn, unroll_to);
|
||||
break;
|
||||
#if CV_VERSION_MAJOR >= 4
|
||||
case CV_16F:
|
||||
scalarToRawData_<float16_t>(s, (float16_t*)_buf, cn, unroll_to);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
CV_Error(CV_StsUnsupportedFormat,"");
|
||||
}
|
||||
}
|
||||
|
||||
void convertAndUnrollScalar( const Mat& sc, int buftype, uchar* scbuf, size_t blocksize )
|
||||
{
|
||||
int scn = (int)sc.total(), cn = CV_MAT_CN(buftype);
|
||||
size_t esz = CV_ELEM_SIZE(buftype);
|
||||
BinaryFunc cvtFn = getConvertFunc(sc.depth(), buftype);
|
||||
CV_Assert(cvtFn);
|
||||
cvtFn(sc.ptr(), 1, 0, 1, scbuf, 1, Size(std::min(cn, scn), 1), 0);
|
||||
// unroll the scalar
|
||||
if( scn < cn )
|
||||
{
|
||||
CV_Assert( scn == 1 );
|
||||
size_t esz1 = CV_ELEM_SIZE1(buftype);
|
||||
for( size_t i = esz1; i < esz; i++ )
|
||||
scbuf[i] = scbuf[i - esz1];
|
||||
}
|
||||
for( size_t i = esz; i < blocksize*esz; i++ )
|
||||
scbuf[i] = scbuf[i - esz];
|
||||
}
|
||||
|
||||
|
||||
template<typename T> static void
|
||||
copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
|
||||
{
|
||||
@@ -594,490 +663,6 @@ Mat& Mat::setTo(InputArray _value, InputArray _mask)
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if CV_SIMD128
|
||||
template<typename V> CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
typedef typename V::lane_type T;
|
||||
int end = (int)(size.width*esz);
|
||||
int width = (end + 1)/2;
|
||||
int width_1 = width & -v_uint8x16::nlanes;
|
||||
int i, j;
|
||||
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(T)>(src, dst));
|
||||
#endif
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for( i = 0, j = end; i < width_1; i += v_uint8x16::nlanes, j -= v_uint8x16::nlanes )
|
||||
{
|
||||
V t0, t1;
|
||||
|
||||
t0 = v_load((T*)((uchar*)src + i));
|
||||
t1 = v_load((T*)((uchar*)src + j - v_uint8x16::nlanes));
|
||||
t0 = v_reverse(t0);
|
||||
t1 = v_reverse(t1);
|
||||
v_store((T*)(dst + j - v_uint8x16::nlanes), t0);
|
||||
v_store((T*)(dst + i), t1);
|
||||
}
|
||||
if (isAligned<sizeof(T)>(src, dst))
|
||||
{
|
||||
for ( ; i < width; i += sizeof(T), j -= sizeof(T) )
|
||||
{
|
||||
T t0, t1;
|
||||
|
||||
t0 = *((T*)((uchar*)src + i));
|
||||
t1 = *((T*)((uchar*)src + j - sizeof(T)));
|
||||
*((T*)(dst + j - sizeof(T))) = t0;
|
||||
*((T*)(dst + i)) = t1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ; i < width; i += sizeof(T), j -= sizeof(T) )
|
||||
{
|
||||
for (int k = 0; k < (int)sizeof(T); k++)
|
||||
{
|
||||
uchar t0, t1;
|
||||
|
||||
t0 = *((uchar*)src + i + k);
|
||||
t1 = *((uchar*)src + j + k - sizeof(T));
|
||||
*(dst + j + k - sizeof(T)) = t0;
|
||||
*(dst + i + k) = t1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T1, typename T2> CV_ALWAYS_INLINE void flipHoriz_double( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
int end = (int)(size.width*esz);
|
||||
int width = (end + 1)/2;
|
||||
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(T1)>(src, dst));
|
||||
CV_Assert(isAligned<sizeof(T2)>(src, dst));
|
||||
#endif
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for ( int i = 0, j = end; i < width; i += sizeof(T1) + sizeof(T2), j -= sizeof(T1) + sizeof(T2) )
|
||||
{
|
||||
T1 t0, t1;
|
||||
T2 t2, t3;
|
||||
|
||||
t0 = *((T1*)((uchar*)src + i));
|
||||
t2 = *((T2*)((uchar*)src + i + sizeof(T1)));
|
||||
t1 = *((T1*)((uchar*)src + j - sizeof(T1) - sizeof(T2)));
|
||||
t3 = *((T2*)((uchar*)src + j - sizeof(T2)));
|
||||
*((T1*)(dst + j - sizeof(T1) - sizeof(T2))) = t0;
|
||||
*((T2*)(dst + j - sizeof(T2))) = t2;
|
||||
*((T1*)(dst + i)) = t1;
|
||||
*((T2*)(dst + i + sizeof(T1))) = t3;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
#if CV_SIMD
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
size_t alignmentMark = ((size_t)src)|((size_t)dst)|sstep|dstep;
|
||||
#endif
|
||||
if (esz == 2 * v_uint8x16::nlanes)
|
||||
{
|
||||
int end = (int)(size.width*esz);
|
||||
int width = end/2;
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for( int i = 0, j = end - 2 * v_uint8x16::nlanes; i < width; i += 2 * v_uint8x16::nlanes, j -= 2 * v_uint8x16::nlanes )
|
||||
{
|
||||
#if CV_SIMD256
|
||||
v_uint8x32 t0, t1;
|
||||
|
||||
t0 = v256_load((uchar*)src + i);
|
||||
t1 = v256_load((uchar*)src + j);
|
||||
v_store(dst + j, t0);
|
||||
v_store(dst + i, t1);
|
||||
#else
|
||||
v_uint8x16 t0, t1, t2, t3;
|
||||
|
||||
t0 = v_load((uchar*)src + i);
|
||||
t1 = v_load((uchar*)src + i + v_uint8x16::nlanes);
|
||||
t2 = v_load((uchar*)src + j);
|
||||
t3 = v_load((uchar*)src + j + v_uint8x16::nlanes);
|
||||
v_store(dst + j, t0);
|
||||
v_store(dst + j + v_uint8x16::nlanes, t1);
|
||||
v_store(dst + i, t2);
|
||||
v_store(dst + i + v_uint8x16::nlanes, t3);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (esz == v_uint8x16::nlanes)
|
||||
{
|
||||
int end = (int)(size.width*esz);
|
||||
int width = end/2;
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for( int i = 0, j = end - v_uint8x16::nlanes; i < width; i += v_uint8x16::nlanes, j -= v_uint8x16::nlanes )
|
||||
{
|
||||
v_uint8x16 t0, t1;
|
||||
|
||||
t0 = v_load((uchar*)src + i);
|
||||
t1 = v_load((uchar*)src + j);
|
||||
v_store(dst + j, t0);
|
||||
v_store(dst + i, t1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (esz == 8
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(uint64)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
flipHoriz_single<v_uint64x2>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 4
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(unsigned)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
flipHoriz_single<v_uint32x4>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 2
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(ushort)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
flipHoriz_single<v_uint16x8>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 1)
|
||||
{
|
||||
flipHoriz_single<v_uint8x16>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 24
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(uint64_t)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int end = (int)(size.width*esz);
|
||||
int width = (end + 1)/2;
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for ( int i = 0, j = end; i < width; i += v_uint8x16::nlanes + sizeof(uint64_t), j -= v_uint8x16::nlanes + sizeof(uint64_t) )
|
||||
{
|
||||
v_uint8x16 t0, t1;
|
||||
uint64_t t2, t3;
|
||||
|
||||
t0 = v_load((uchar*)src + i);
|
||||
t2 = *((uint64_t*)((uchar*)src + i + v_uint8x16::nlanes));
|
||||
t1 = v_load((uchar*)src + j - v_uint8x16::nlanes - sizeof(uint64_t));
|
||||
t3 = *((uint64_t*)((uchar*)src + j - sizeof(uint64_t)));
|
||||
v_store(dst + j - v_uint8x16::nlanes - sizeof(uint64_t), t0);
|
||||
*((uint64_t*)(dst + j - sizeof(uint64_t))) = t2;
|
||||
v_store(dst + i, t1);
|
||||
*((uint64_t*)(dst + i + v_uint8x16::nlanes)) = t3;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !CV_STRONG_ALIGNMENT
|
||||
else if (esz == 12)
|
||||
{
|
||||
flipHoriz_double<uint64_t,uint>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 6)
|
||||
{
|
||||
flipHoriz_double<uint,ushort>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 3)
|
||||
{
|
||||
flipHoriz_double<ushort,uchar>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
#endif // CV_SIMD
|
||||
{
|
||||
int i, j, limit = (int)(((size.width + 1)/2)*esz);
|
||||
AutoBuffer<int> _tab(size.width*esz);
|
||||
int* tab = _tab.data();
|
||||
|
||||
for( i = 0; i < size.width; i++ )
|
||||
for( size_t k = 0; k < esz; k++ )
|
||||
tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for( i = 0; i < limit; i++ )
|
||||
{
|
||||
j = tab[i];
|
||||
uchar t0 = src[i], t1 = src[j];
|
||||
dst[i] = t1; dst[j] = t0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
const uchar* src1 = src0 + (size.height - 1)*sstep;
|
||||
uchar* dst1 = dst0 + (size.height - 1)*dstep;
|
||||
size.width *= (int)esz;
|
||||
|
||||
for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
|
||||
dst0 += dstep, dst1 -= dstep )
|
||||
{
|
||||
int i = 0;
|
||||
#if CV_SIMD
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
|
||||
#endif
|
||||
{
|
||||
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
|
||||
{
|
||||
v_int32 t0 = vx_load((int*)(src0 + i));
|
||||
v_int32 t1 = vx_load((int*)(src1 + i));
|
||||
vx_store((int*)(dst0 + i), t1);
|
||||
vx_store((int*)(dst1 + i), t0);
|
||||
}
|
||||
}
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
else
|
||||
{
|
||||
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
|
||||
{
|
||||
v_uint8 t0 = vx_load(src0 + i);
|
||||
v_uint8 t1 = vx_load(src1 + i);
|
||||
vx_store(dst0 + i, t1);
|
||||
vx_store(dst1 + i, t0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
|
||||
{
|
||||
for( ; i <= size.width - 16; i += 16 )
|
||||
{
|
||||
int t0 = ((int*)(src0 + i))[0];
|
||||
int t1 = ((int*)(src1 + i))[0];
|
||||
|
||||
((int*)(dst0 + i))[0] = t1;
|
||||
((int*)(dst1 + i))[0] = t0;
|
||||
|
||||
t0 = ((int*)(src0 + i))[1];
|
||||
t1 = ((int*)(src1 + i))[1];
|
||||
|
||||
((int*)(dst0 + i))[1] = t1;
|
||||
((int*)(dst1 + i))[1] = t0;
|
||||
|
||||
t0 = ((int*)(src0 + i))[2];
|
||||
t1 = ((int*)(src1 + i))[2];
|
||||
|
||||
((int*)(dst0 + i))[2] = t1;
|
||||
((int*)(dst1 + i))[2] = t0;
|
||||
|
||||
t0 = ((int*)(src0 + i))[3];
|
||||
t1 = ((int*)(src1 + i))[3];
|
||||
|
||||
((int*)(dst0 + i))[3] = t1;
|
||||
((int*)(dst1 + i))[3] = t0;
|
||||
}
|
||||
|
||||
for( ; i <= size.width - 4; i += 4 )
|
||||
{
|
||||
int t0 = ((int*)(src0 + i))[0];
|
||||
int t1 = ((int*)(src1 + i))[0];
|
||||
|
||||
((int*)(dst0 + i))[0] = t1;
|
||||
((int*)(dst1 + i))[0] = t0;
|
||||
}
|
||||
}
|
||||
|
||||
for( ; i < size.width; i++ )
|
||||
{
|
||||
uchar t0 = src0[i];
|
||||
uchar t1 = src1[i];
|
||||
|
||||
dst0[i] = t1;
|
||||
dst1[i] = t0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS };
|
||||
|
||||
static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
|
||||
{
|
||||
CV_Assert(flipCode >= -1 && flipCode <= 1);
|
||||
|
||||
const ocl::Device & dev = ocl::Device::getDefault();
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
|
||||
flipType, kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4);
|
||||
|
||||
bool doubleSupport = dev.doubleFPConfig() > 0;
|
||||
if (!doubleSupport && depth == CV_64F)
|
||||
kercn = cn;
|
||||
|
||||
if (cn > 4)
|
||||
return false;
|
||||
|
||||
const char * kernelName;
|
||||
if (flipCode == 0)
|
||||
kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
|
||||
else if (flipCode > 0)
|
||||
kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
|
||||
else
|
||||
kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
|
||||
|
||||
int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
|
||||
kercn = (cn!=3 || flipType == FLIP_ROWS) ? std::max(kercn, cn) : cn;
|
||||
|
||||
ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
|
||||
format( "-D T=%s -D T1=%s -D DEPTH=%d -D cn=%d -D PIX_PER_WI_Y=%d -D kercn=%d",
|
||||
kercn != cn ? ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)) : ocl::vecopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
|
||||
kercn != cn ? ocl::typeToStr(depth) : ocl::vecopTypeToStr(depth), depth, cn, pxPerWIy, kercn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
Size size = _src.size();
|
||||
_dst.create(size, type);
|
||||
UMat src = _src.getUMat(), dst = _dst.getUMat();
|
||||
|
||||
int cols = size.width * cn / kercn, rows = size.height;
|
||||
cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols;
|
||||
rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows;
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src),
|
||||
ocl::KernelArg::WriteOnly(dst, cn, kercn), rows, cols);
|
||||
|
||||
size_t maxWorkGroupSize = dev.maxWorkGroupSize();
|
||||
CV_Assert(maxWorkGroupSize % 4 == 0);
|
||||
|
||||
size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy },
|
||||
localsize[2] = { maxWorkGroupSize / 4, 4 };
|
||||
return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined HAVE_IPP
|
||||
static bool ipp_flip(Mat &src, Mat &dst, int flip_mode)
|
||||
{
|
||||
#ifdef HAVE_IPP_IW
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
// Details: https://github.com/opencv/opencv/issues/12943
|
||||
if (flip_mode <= 0 /* swap rows */
|
||||
&& cv::ipp::getIppTopFeatures() != ippCPUID_SSE42
|
||||
&& (int64_t)(src.total()) * src.elemSize() >= CV_BIG_INT(0x80000000)/*2Gb*/
|
||||
)
|
||||
return false;
|
||||
|
||||
IppiAxis ippMode;
|
||||
if(flip_mode < 0)
|
||||
ippMode = ippAxsBoth;
|
||||
else if(flip_mode == 0)
|
||||
ippMode = ippAxsHorizontal;
|
||||
else
|
||||
ippMode = ippAxsVertical;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiImage iwSrc = ippiGetImage(src);
|
||||
::ipp::IwiImage iwDst = ippiGetImage(dst);
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiMirror, iwSrc, iwDst, ippMode);
|
||||
}
|
||||
catch(const ::ipp::IwException &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(flip_mode);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void flip( InputArray _src, OutputArray _dst, int flip_mode )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert( _src.dims() <= 2 );
|
||||
Size size = _src.size();
|
||||
|
||||
if (flip_mode < 0)
|
||||
{
|
||||
if (size.width == 1)
|
||||
flip_mode = 0;
|
||||
if (size.height == 1)
|
||||
flip_mode = 1;
|
||||
}
|
||||
|
||||
if ((size.width == 1 && flip_mode > 0) ||
|
||||
(size.height == 1 && flip_mode == 0))
|
||||
{
|
||||
return _src.copyTo(_dst);
|
||||
}
|
||||
|
||||
CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
int type = src.type();
|
||||
_dst.create( size, type );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
CV_IPP_RUN_FAST(ipp_flip(src, dst, flip_mode));
|
||||
|
||||
size_t esz = CV_ELEM_SIZE(type);
|
||||
|
||||
if( flip_mode <= 0 )
|
||||
flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
|
||||
else
|
||||
flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
|
||||
|
||||
if( flip_mode < 0 )
|
||||
flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
|
||||
}
|
||||
|
||||
void rotate(InputArray _src, OutputArray _dst, int rotateMode)
|
||||
{
|
||||
CV_Assert(_src.dims() <= 2);
|
||||
|
||||
switch (rotateMode)
|
||||
{
|
||||
case ROTATE_90_CLOCKWISE:
|
||||
transpose(_src, _dst);
|
||||
flip(_dst, _dst, 1);
|
||||
break;
|
||||
case ROTATE_180:
|
||||
flip(_src, _dst, -1);
|
||||
break;
|
||||
case ROTATE_90_COUNTERCLOCKWISE:
|
||||
transpose(_src, _dst);
|
||||
flip(_dst, _dst, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined HAVE_OPENCL && !defined __APPLE__
|
||||
|
||||
@@ -1499,6 +1084,9 @@ void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
/* dst = src */
|
||||
CV_IMPL void
|
||||
cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
|
||||
@@ -1614,4 +1202,5 @@ cvRepeat( const CvArr* srcarr, CvArr* dstarr )
|
||||
cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst);
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
/* End of file. */
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
//M*/
|
||||
#include "precomp.hpp"
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
/* default alignment for dynamic data strucutures, resided in storages. */
|
||||
#define CV_STRUCT_ALIGN ((int)sizeof(double))
|
||||
|
||||
@@ -3585,4 +3587,5 @@ void seqInsertSlice( CvSeq* seq, int before_index, const CvArr* from_arr )
|
||||
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
/* End of file. */
|
||||
|
||||
@@ -901,7 +901,7 @@ bool ocl_convert_nv12_to_bgr(
|
||||
|
||||
k.args(clImageY, clImageUV, clBuffer, step, cols, rows);
|
||||
|
||||
size_t globalsize[] = { (size_t)cols, (size_t)rows };
|
||||
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
|
||||
return k.run(2, globalsize, 0, false);
|
||||
}
|
||||
|
||||
@@ -922,7 +922,7 @@ bool ocl_convert_bgr_to_nv12(
|
||||
|
||||
k.args(clBuffer, step, cols, rows, clImageY, clImageUV);
|
||||
|
||||
size_t globalsize[] = { (size_t)cols, (size_t)rows };
|
||||
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
|
||||
return k.run(2, globalsize, 0, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -4640,6 +4640,9 @@ int cv::getOptimalDFTSize( int size0 )
|
||||
return optimalDFTSizeTab[b];
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
CV_IMPL void
|
||||
cvDFT( const CvArr* srcarr, CvArr* dstarr, int flags, int nonzero_rows )
|
||||
{
|
||||
@@ -4695,4 +4698,5 @@ cvGetOptimalDFTSize( int size0 )
|
||||
return cv::getOptimalDFTSize(size0);
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
/* End of file. */
|
||||
|
||||
+15
-10
@@ -753,8 +753,6 @@ SVBkSb( int m, int n, const double* w, size_t wstep,
|
||||
(double*)alignPtr(buffer, sizeof(double)), DBL_EPSILON*2 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
* Determinant of the matrix *
|
||||
\****************************************************************************************/
|
||||
@@ -764,7 +762,7 @@ SVBkSb( int m, int n, const double* w, size_t wstep,
|
||||
m(0,1)*((double)m(1,0)*m(2,2) - (double)m(1,2)*m(2,0)) + \
|
||||
m(0,2)*((double)m(1,0)*m(2,1) - (double)m(1,1)*m(2,0)))
|
||||
|
||||
double cv::determinant( InputArray _mat )
|
||||
double determinant( InputArray _mat )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -842,7 +840,7 @@ double cv::determinant( InputArray _mat )
|
||||
#define Df( y, x ) ((float*)(dstdata + y*dststep))[x]
|
||||
#define Dd( y, x ) ((double*)(dstdata + y*dststep))[x]
|
||||
|
||||
double cv::invert( InputArray _src, OutputArray _dst, int method )
|
||||
double invert( InputArray _src, OutputArray _dst, int method )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -1069,13 +1067,19 @@ double cv::invert( InputArray _src, OutputArray _dst, int method )
|
||||
return result;
|
||||
}
|
||||
|
||||
UMat UMat::inv(int method) const
|
||||
{
|
||||
UMat m;
|
||||
invert(*this, m, method);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
* Solving a linear system *
|
||||
\****************************************************************************************/
|
||||
|
||||
bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int method )
|
||||
bool solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int method )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -1374,7 +1378,7 @@ bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int meth
|
||||
|
||||
/////////////////// finding eigenvalues and eigenvectors of a symmetric matrix ///////////////
|
||||
|
||||
bool cv::eigen( InputArray _src, OutputArray _evals, OutputArray _evects )
|
||||
bool eigen( InputArray _src, OutputArray _evals, OutputArray _evects )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -1396,7 +1400,7 @@ bool cv::eigen( InputArray _src, OutputArray _evals, OutputArray _evects )
|
||||
const bool evecNeeded = _evects.needed();
|
||||
const int esOptions = evecNeeded ? Eigen::ComputeEigenvectors : Eigen::EigenvaluesOnly;
|
||||
_evals.create(n, 1, type);
|
||||
cv::Mat evals = _evals.getMat();
|
||||
Mat evals = _evals.getMat();
|
||||
if ( type == CV_64F )
|
||||
{
|
||||
Eigen::MatrixXd src_eig, zeros_eig;
|
||||
@@ -1448,9 +1452,6 @@ bool cv::eigen( InputArray _src, OutputArray _evals, OutputArray _evects )
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
static void _SVDcompute( InputArray _aarr, OutputArray _w,
|
||||
OutputArray _u, OutputArray _vt, int flags )
|
||||
{
|
||||
@@ -1598,6 +1599,9 @@ void cv::SVBackSubst(InputArray w, InputArray u, InputArray vt, InputArray rhs,
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
CV_IMPL double
|
||||
cvDet( const CvArr* arr )
|
||||
{
|
||||
@@ -1789,3 +1793,4 @@ cvSVBkSb( const CvArr* warr, const CvArr* uarr,
|
||||
cv::SVD::backSubst(w, u, v, rhs, dst);
|
||||
CV_Assert( dst.data == dst0.data );
|
||||
}
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
|
||||
@@ -1637,6 +1637,9 @@ void patchNaNs( InputOutputArray _a, double _val )
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
CV_IMPL float cvCbrt(float value) { return cv::cubeRoot(value); }
|
||||
CV_IMPL float cvFastArctan(float y, float x) { return cv::fastAtan2(y, x); }
|
||||
|
||||
@@ -1720,6 +1723,7 @@ CV_IMPL int cvCheckArr( const CvArr* arr, int flags,
|
||||
return cv::checkRange(cv::cvarrToMat(arr), (flags & CV_CHECK_QUIET) != 0, 0, minVal, maxVal );
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
|
||||
/*
|
||||
Finds real roots of cubic, quadratic or linear equation.
|
||||
@@ -2015,6 +2019,8 @@ double cv::solvePoly( InputArray _coeffs0, OutputArray _roots0, int maxIters )
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
CV_IMPL int
|
||||
cvSolveCubic( const CvMat* coeffs, CvMat* roots )
|
||||
{
|
||||
@@ -2034,6 +2040,7 @@ void cvSolvePoly(const CvMat* a, CvMat *r, int maxiter, int)
|
||||
CV_Assert( _r.data == _r0.data ); // check that the array of roots was not reallocated
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
|
||||
|
||||
// Common constants for dispatched code
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
#include "mathfuncs_core.simd.hpp"
|
||||
#include "mathfuncs_core.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
|
||||
|
||||
|
||||
#define IPP_DISABLE_MAGNITUDE_32F 1 // accuracy: https://github.com/opencv/opencv/issues/19506
|
||||
|
||||
|
||||
namespace cv { namespace hal {
|
||||
|
||||
///////////////////////////////////// ATAN2 ////////////////////////////////////
|
||||
@@ -44,8 +48,25 @@ void magnitude32f(const float* x, const float* y, float* mag, int len)
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CALL_HAL(magnitude32f, cv_hal_magnitude32f, x, y, mag, len);
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
bool allowIPP = true;
|
||||
#ifdef IPP_DISABLE_MAGNITUDE_32F
|
||||
if (cv::ipp::getIppTopFeatures() & (
|
||||
#if IPP_VERSION_X100 >= 201700
|
||||
ippCPUID_AVX512F |
|
||||
#endif
|
||||
ippCPUID_AVX2)
|
||||
)
|
||||
{
|
||||
allowIPP = (len & 7) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// SSE42 performance issues
|
||||
CV_IPP_RUN(IPP_VERSION_X100 > 201800 || cv::ipp::getIppTopFeatures() != ippCPUID_SSE42, CV_INSTRUMENT_FUN_IPP(ippsMagnitude_32f, x, y, mag, len) >= 0);
|
||||
CV_IPP_RUN((IPP_VERSION_X100 > 201800 || cv::ipp::getIppTopFeatures() != ippCPUID_SSE42) && allowIPP,
|
||||
CV_INSTRUMENT_FUN_IPP(ippsMagnitude_32f, x, y, mag, len) >= 0);
|
||||
#endif
|
||||
|
||||
CV_CPU_DISPATCH(magnitude32f, (x, y, mag, len),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
|
||||
@@ -999,8 +999,79 @@ double Mat::dot(InputArray _mat) const
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_dot( InputArray _src1, InputArray _src2, double & res )
|
||||
{
|
||||
UMat src1 = _src1.getUMat().reshape(1), src2 = _src2.getUMat().reshape(1);
|
||||
|
||||
int type = src1.type(), depth = CV_MAT_DEPTH(type),
|
||||
kercn = ocl::predictOptimalVectorWidth(src1, src2);
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
if ( !doubleSupport && depth == CV_64F )
|
||||
return false;
|
||||
|
||||
int dbsize = ocl::Device::getDefault().maxComputeUnits();
|
||||
size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
|
||||
int ddepth = std::max(CV_32F, depth);
|
||||
|
||||
int wgs2_aligned = 1;
|
||||
while (wgs2_aligned < (int)wgs)
|
||||
wgs2_aligned <<= 1;
|
||||
wgs2_aligned >>= 1;
|
||||
|
||||
char cvt[40];
|
||||
ocl::Kernel k("reduce", ocl::core::reduce_oclsrc,
|
||||
format("-D srcT=%s -D srcT1=%s -D dstT=%s -D dstTK=%s -D ddepth=%d -D convertToDT=%s -D OP_DOT "
|
||||
"-D WGS=%d -D WGS2_ALIGNED=%d%s%s%s -D kercn=%d",
|
||||
ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), ocl::typeToStr(depth),
|
||||
ocl::typeToStr(ddepth), ocl::typeToStr(CV_MAKE_TYPE(ddepth, kercn)),
|
||||
ddepth, ocl::convertTypeStr(depth, ddepth, kercn, cvt),
|
||||
(int)wgs, wgs2_aligned, doubleSupport ? " -D DOUBLE_SUPPORT" : "",
|
||||
_src1.isContinuous() ? " -D HAVE_SRC_CONT" : "",
|
||||
_src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "", kercn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat db(1, dbsize, ddepth);
|
||||
|
||||
ocl::KernelArg src1arg = ocl::KernelArg::ReadOnlyNoSize(src1),
|
||||
src2arg = ocl::KernelArg::ReadOnlyNoSize(src2),
|
||||
dbarg = ocl::KernelArg::PtrWriteOnly(db);
|
||||
|
||||
k.args(src1arg, src1.cols, (int)src1.total(), dbsize, dbarg, src2arg);
|
||||
|
||||
size_t globalsize = dbsize * wgs;
|
||||
if (k.run(1, &globalsize, &wgs, false))
|
||||
{
|
||||
res = sum(db.getMat(ACCESS_READ))[0];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
double UMat::dot(InputArray m) const
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert(m.sameSize(*this) && m.type() == type());
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
double r = 0;
|
||||
CV_OCL_RUN_(dims <= 2, ocl_dot(*this, m, r), r)
|
||||
#endif
|
||||
|
||||
return getMat(ACCESS_READ).dot(m);
|
||||
}
|
||||
|
||||
} // namespace cv::
|
||||
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
/****************************************************************************************\
|
||||
* Earlier API *
|
||||
\****************************************************************************************/
|
||||
@@ -1225,4 +1296,6 @@ cvBackProjectPCA( const CvArr* proj_arr, const CvArr* avg_arr,
|
||||
CV_Assert(dst0.data == dst.data);
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
|
||||
/* End of file. */
|
||||
|
||||
@@ -204,7 +204,7 @@ MatAllocator* Mat::getStdAllocator()
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
bool MatSize::operator==(const MatSize& sz) const
|
||||
bool MatSize::operator==(const MatSize& sz) const CV_NOEXCEPT
|
||||
{
|
||||
int d = dims();
|
||||
int dsz = sz.dims();
|
||||
@@ -337,7 +337,7 @@ void finalizeHdr(Mat& m)
|
||||
|
||||
//======================================= Mat ======================================================
|
||||
|
||||
Mat::Mat()
|
||||
Mat::Mat() CV_NOEXCEPT
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "opencv2/core/mat.hpp"
|
||||
#include "opencv2/core/types_c.h"
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
// glue
|
||||
|
||||
CvMatND cvMatND(const cv::Mat& m)
|
||||
@@ -360,7 +361,6 @@ cvSort( const CvArr* _src, CvArr* _dst, CvArr* _idx, int flags )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL int
|
||||
cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels,
|
||||
CvTermCriteria termcrit, int attempts, CvRNG*,
|
||||
@@ -389,3 +389,5 @@ cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels,
|
||||
*_compactness = compactness;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
|
||||
@@ -226,6 +226,23 @@ void cv::setIdentity( InputOutputArray _m, const Scalar& s )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace cv {
|
||||
|
||||
UMat UMat::eye(int rows, int cols, int type)
|
||||
{
|
||||
return UMat::eye(Size(cols, rows), type);
|
||||
}
|
||||
|
||||
UMat UMat::eye(Size size, int type)
|
||||
{
|
||||
UMat m(size, type);
|
||||
setIdentity(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//////////////////////////////////////////// trace ///////////////////////////////////////////
|
||||
|
||||
cv::Scalar cv::trace( InputArray _m )
|
||||
@@ -260,285 +277,6 @@ cv::Scalar cv::trace( InputArray _m )
|
||||
return cv::sum(m.diag());
|
||||
}
|
||||
|
||||
////////////////////////////////////// transpose /////////////////////////////////////////
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
template<typename T> static void
|
||||
transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
|
||||
{
|
||||
int i=0, j, m = sz.width, n = sz.height;
|
||||
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for(; i <= m - 4; i += 4 )
|
||||
{
|
||||
T* d0 = (T*)(dst + dstep*i);
|
||||
T* d1 = (T*)(dst + dstep*(i+1));
|
||||
T* d2 = (T*)(dst + dstep*(i+2));
|
||||
T* d3 = (T*)(dst + dstep*(i+3));
|
||||
|
||||
for( j = 0; j <= n - 4; j += 4 )
|
||||
{
|
||||
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
|
||||
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
|
||||
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
|
||||
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
|
||||
|
||||
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
|
||||
d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1];
|
||||
d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2];
|
||||
d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3];
|
||||
}
|
||||
|
||||
for( ; j < n; j++ )
|
||||
{
|
||||
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
|
||||
d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; i < m; i++ )
|
||||
{
|
||||
T* d0 = (T*)(dst + dstep*i);
|
||||
j = 0;
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for(; j <= n - 4; j += 4 )
|
||||
{
|
||||
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
|
||||
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
|
||||
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
|
||||
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
|
||||
|
||||
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
|
||||
}
|
||||
#endif
|
||||
for( ; j < n; j++ )
|
||||
{
|
||||
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
|
||||
d0[j] = s0[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> static void
|
||||
transposeI_( uchar* data, size_t step, int n )
|
||||
{
|
||||
for( int i = 0; i < n; i++ )
|
||||
{
|
||||
T* row = (T*)(data + step*i);
|
||||
uchar* data1 = data + i*sizeof(T);
|
||||
for( int j = i+1; j < n; j++ )
|
||||
std::swap( row[j], *(T*)(data1 + step*j) );
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz );
|
||||
typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n );
|
||||
|
||||
#define DEF_TRANSPOSE_FUNC(suffix, type) \
|
||||
static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \
|
||||
{ transpose_<type>(src, sstep, dst, dstep, sz); } \
|
||||
\
|
||||
static void transposeI_##suffix( uchar* data, size_t step, int n ) \
|
||||
{ transposeI_<type>(data, step, n); }
|
||||
|
||||
DEF_TRANSPOSE_FUNC(8u, uchar)
|
||||
DEF_TRANSPOSE_FUNC(16u, ushort)
|
||||
DEF_TRANSPOSE_FUNC(8uC3, Vec3b)
|
||||
DEF_TRANSPOSE_FUNC(32s, int)
|
||||
DEF_TRANSPOSE_FUNC(16uC3, Vec3s)
|
||||
DEF_TRANSPOSE_FUNC(32sC2, Vec2i)
|
||||
DEF_TRANSPOSE_FUNC(32sC3, Vec3i)
|
||||
DEF_TRANSPOSE_FUNC(32sC4, Vec4i)
|
||||
DEF_TRANSPOSE_FUNC(32sC6, Vec6i)
|
||||
DEF_TRANSPOSE_FUNC(32sC8, Vec8i)
|
||||
|
||||
static TransposeFunc transposeTab[] =
|
||||
{
|
||||
0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0,
|
||||
transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4,
|
||||
0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8
|
||||
};
|
||||
|
||||
static TransposeInplaceFunc transposeInplaceTab[] =
|
||||
{
|
||||
0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0,
|
||||
transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4,
|
||||
0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_transpose( InputArray _src, OutputArray _dst )
|
||||
{
|
||||
const ocl::Device & dev = ocl::Device::getDefault();
|
||||
const int TILE_DIM = 32, BLOCK_ROWS = 8;
|
||||
int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
|
||||
rowsPerWI = dev.isIntel() ? 4 : 1;
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
_dst.create(src.cols, src.rows, type);
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
String kernelName("transpose");
|
||||
bool inplace = dst.u == src.u;
|
||||
|
||||
if (inplace)
|
||||
{
|
||||
CV_Assert(dst.cols == dst.rows);
|
||||
kernelName += "_inplace";
|
||||
}
|
||||
else
|
||||
{
|
||||
// check required local memory size
|
||||
size_t required_local_memory = (size_t) TILE_DIM*(TILE_DIM+1)*CV_ELEM_SIZE(type);
|
||||
if (required_local_memory > ocl::Device::getDefault().localMemSize())
|
||||
return false;
|
||||
}
|
||||
|
||||
ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc,
|
||||
format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d%s",
|
||||
ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth),
|
||||
cn, TILE_DIM, BLOCK_ROWS, rowsPerWI, inplace ? " -D INPLACE" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
if (inplace)
|
||||
k.args(ocl::KernelArg::ReadWriteNoSize(dst), dst.rows);
|
||||
else
|
||||
k.args(ocl::KernelArg::ReadOnly(src),
|
||||
ocl::KernelArg::WriteOnlyNoSize(dst));
|
||||
|
||||
size_t localsize[2] = { TILE_DIM, BLOCK_ROWS };
|
||||
size_t globalsize[2] = { (size_t)src.cols, inplace ? ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI : (divUp((size_t)src.rows, TILE_DIM) * BLOCK_ROWS) };
|
||||
|
||||
if (inplace && dev.isIntel())
|
||||
{
|
||||
localsize[0] = 16;
|
||||
localsize[1] = dev.maxWorkGroupSize() / localsize[0];
|
||||
}
|
||||
|
||||
return k.run(2, globalsize, localsize, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
static bool ipp_transpose( Mat &src, Mat &dst )
|
||||
{
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
int type = src.type();
|
||||
typedef IppStatus (CV_STDCALL * IppiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize);
|
||||
typedef IppStatus (CV_STDCALL * IppiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize);
|
||||
IppiTranspose ippiTranspose = 0;
|
||||
IppiTransposeI ippiTranspose_I = 0;
|
||||
|
||||
if (dst.data == src.data && dst.cols == dst.rows)
|
||||
{
|
||||
CV_SUPPRESS_DEPRECATED_START
|
||||
ippiTranspose_I =
|
||||
type == CV_8UC1 ? (IppiTransposeI)ippiTranspose_8u_C1IR :
|
||||
type == CV_8UC3 ? (IppiTransposeI)ippiTranspose_8u_C3IR :
|
||||
type == CV_8UC4 ? (IppiTransposeI)ippiTranspose_8u_C4IR :
|
||||
type == CV_16UC1 ? (IppiTransposeI)ippiTranspose_16u_C1IR :
|
||||
type == CV_16UC3 ? (IppiTransposeI)ippiTranspose_16u_C3IR :
|
||||
type == CV_16UC4 ? (IppiTransposeI)ippiTranspose_16u_C4IR :
|
||||
type == CV_16SC1 ? (IppiTransposeI)ippiTranspose_16s_C1IR :
|
||||
type == CV_16SC3 ? (IppiTransposeI)ippiTranspose_16s_C3IR :
|
||||
type == CV_16SC4 ? (IppiTransposeI)ippiTranspose_16s_C4IR :
|
||||
type == CV_32SC1 ? (IppiTransposeI)ippiTranspose_32s_C1IR :
|
||||
type == CV_32SC3 ? (IppiTransposeI)ippiTranspose_32s_C3IR :
|
||||
type == CV_32SC4 ? (IppiTransposeI)ippiTranspose_32s_C4IR :
|
||||
type == CV_32FC1 ? (IppiTransposeI)ippiTranspose_32f_C1IR :
|
||||
type == CV_32FC3 ? (IppiTransposeI)ippiTranspose_32f_C3IR :
|
||||
type == CV_32FC4 ? (IppiTransposeI)ippiTranspose_32f_C4IR : 0;
|
||||
CV_SUPPRESS_DEPRECATED_END
|
||||
}
|
||||
else
|
||||
{
|
||||
ippiTranspose =
|
||||
type == CV_8UC1 ? (IppiTranspose)ippiTranspose_8u_C1R :
|
||||
type == CV_8UC3 ? (IppiTranspose)ippiTranspose_8u_C3R :
|
||||
type == CV_8UC4 ? (IppiTranspose)ippiTranspose_8u_C4R :
|
||||
type == CV_16UC1 ? (IppiTranspose)ippiTranspose_16u_C1R :
|
||||
type == CV_16UC3 ? (IppiTranspose)ippiTranspose_16u_C3R :
|
||||
type == CV_16UC4 ? (IppiTranspose)ippiTranspose_16u_C4R :
|
||||
type == CV_16SC1 ? (IppiTranspose)ippiTranspose_16s_C1R :
|
||||
type == CV_16SC3 ? (IppiTranspose)ippiTranspose_16s_C3R :
|
||||
type == CV_16SC4 ? (IppiTranspose)ippiTranspose_16s_C4R :
|
||||
type == CV_32SC1 ? (IppiTranspose)ippiTranspose_32s_C1R :
|
||||
type == CV_32SC3 ? (IppiTranspose)ippiTranspose_32s_C3R :
|
||||
type == CV_32SC4 ? (IppiTranspose)ippiTranspose_32s_C4R :
|
||||
type == CV_32FC1 ? (IppiTranspose)ippiTranspose_32f_C1R :
|
||||
type == CV_32FC3 ? (IppiTranspose)ippiTranspose_32f_C3R :
|
||||
type == CV_32FC4 ? (IppiTranspose)ippiTranspose_32f_C4R : 0;
|
||||
}
|
||||
|
||||
IppiSize roiSize = { src.cols, src.rows };
|
||||
if (ippiTranspose != 0)
|
||||
{
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0)
|
||||
return true;
|
||||
}
|
||||
else if (ippiTranspose_I != 0)
|
||||
{
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose_I, dst.ptr(), (int)dst.step, roiSize) >= 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cv::transpose( InputArray _src, OutputArray _dst )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
int type = _src.type(), esz = CV_ELEM_SIZE(type);
|
||||
CV_Assert( _src.dims() <= 2 && esz <= 32 );
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat(),
|
||||
ocl_transpose(_src, _dst))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
if( src.empty() )
|
||||
{
|
||||
_dst.release();
|
||||
return;
|
||||
}
|
||||
|
||||
_dst.create(src.cols, src.rows, src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
// handle the case of single-column/single-row matrices, stored in STL vectors.
|
||||
if( src.rows != dst.cols || src.cols != dst.rows )
|
||||
{
|
||||
CV_Assert( src.size() == dst.size() && (src.cols == 1 || src.rows == 1) );
|
||||
src.copyTo(dst);
|
||||
return;
|
||||
}
|
||||
|
||||
CV_IPP_RUN_FAST(ipp_transpose(src, dst))
|
||||
|
||||
if( dst.data == src.data )
|
||||
{
|
||||
TransposeInplaceFunc func = transposeInplaceTab[esz];
|
||||
CV_Assert( func != 0 );
|
||||
CV_Assert( dst.cols == dst.rows );
|
||||
func( dst.ptr(), dst.step, dst.rows );
|
||||
}
|
||||
else
|
||||
{
|
||||
TransposeFunc func = transposeTab[esz];
|
||||
CV_Assert( func != 0 );
|
||||
func( src.ptr(), src.step, dst.ptr(), dst.step, src.size() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////// completeSymm /////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,770 @@
|
||||
// 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 "opencl_kernels_core.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
////////////////////////////////////// transpose /////////////////////////////////////////
|
||||
|
||||
template<typename T> static void
|
||||
transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
|
||||
{
|
||||
int i=0, j, m = sz.width, n = sz.height;
|
||||
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for(; i <= m - 4; i += 4 )
|
||||
{
|
||||
T* d0 = (T*)(dst + dstep*i);
|
||||
T* d1 = (T*)(dst + dstep*(i+1));
|
||||
T* d2 = (T*)(dst + dstep*(i+2));
|
||||
T* d3 = (T*)(dst + dstep*(i+3));
|
||||
|
||||
for( j = 0; j <= n - 4; j += 4 )
|
||||
{
|
||||
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
|
||||
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
|
||||
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
|
||||
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
|
||||
|
||||
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
|
||||
d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1];
|
||||
d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2];
|
||||
d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3];
|
||||
}
|
||||
|
||||
for( ; j < n; j++ )
|
||||
{
|
||||
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
|
||||
d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; i < m; i++ )
|
||||
{
|
||||
T* d0 = (T*)(dst + dstep*i);
|
||||
j = 0;
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for(; j <= n - 4; j += 4 )
|
||||
{
|
||||
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
|
||||
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
|
||||
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
|
||||
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
|
||||
|
||||
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
|
||||
}
|
||||
#endif
|
||||
for( ; j < n; j++ )
|
||||
{
|
||||
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
|
||||
d0[j] = s0[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> static void
|
||||
transposeI_( uchar* data, size_t step, int n )
|
||||
{
|
||||
for( int i = 0; i < n; i++ )
|
||||
{
|
||||
T* row = (T*)(data + step*i);
|
||||
uchar* data1 = data + i*sizeof(T);
|
||||
for( int j = i+1; j < n; j++ )
|
||||
std::swap( row[j], *(T*)(data1 + step*j) );
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz );
|
||||
typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n );
|
||||
|
||||
#define DEF_TRANSPOSE_FUNC(suffix, type) \
|
||||
static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \
|
||||
{ transpose_<type>(src, sstep, dst, dstep, sz); } \
|
||||
\
|
||||
static void transposeI_##suffix( uchar* data, size_t step, int n ) \
|
||||
{ transposeI_<type>(data, step, n); }
|
||||
|
||||
DEF_TRANSPOSE_FUNC(8u, uchar)
|
||||
DEF_TRANSPOSE_FUNC(16u, ushort)
|
||||
DEF_TRANSPOSE_FUNC(8uC3, Vec3b)
|
||||
DEF_TRANSPOSE_FUNC(32s, int)
|
||||
DEF_TRANSPOSE_FUNC(16uC3, Vec3s)
|
||||
DEF_TRANSPOSE_FUNC(32sC2, Vec2i)
|
||||
DEF_TRANSPOSE_FUNC(32sC3, Vec3i)
|
||||
DEF_TRANSPOSE_FUNC(32sC4, Vec4i)
|
||||
DEF_TRANSPOSE_FUNC(32sC6, Vec6i)
|
||||
DEF_TRANSPOSE_FUNC(32sC8, Vec8i)
|
||||
|
||||
static TransposeFunc transposeTab[] =
|
||||
{
|
||||
0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0,
|
||||
transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4,
|
||||
0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8
|
||||
};
|
||||
|
||||
static TransposeInplaceFunc transposeInplaceTab[] =
|
||||
{
|
||||
0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0,
|
||||
transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4,
|
||||
0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_transpose( InputArray _src, OutputArray _dst )
|
||||
{
|
||||
const ocl::Device & dev = ocl::Device::getDefault();
|
||||
const int TILE_DIM = 32, BLOCK_ROWS = 8;
|
||||
int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
|
||||
rowsPerWI = dev.isIntel() ? 4 : 1;
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
_dst.create(src.cols, src.rows, type);
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
String kernelName("transpose");
|
||||
bool inplace = dst.u == src.u;
|
||||
|
||||
if (inplace)
|
||||
{
|
||||
CV_Assert(dst.cols == dst.rows);
|
||||
kernelName += "_inplace";
|
||||
}
|
||||
else
|
||||
{
|
||||
// check required local memory size
|
||||
size_t required_local_memory = (size_t) TILE_DIM*(TILE_DIM+1)*CV_ELEM_SIZE(type);
|
||||
if (required_local_memory > ocl::Device::getDefault().localMemSize())
|
||||
return false;
|
||||
}
|
||||
|
||||
ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc,
|
||||
format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d%s",
|
||||
ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth),
|
||||
cn, TILE_DIM, BLOCK_ROWS, rowsPerWI, inplace ? " -D INPLACE" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
if (inplace)
|
||||
k.args(ocl::KernelArg::ReadWriteNoSize(dst), dst.rows);
|
||||
else
|
||||
k.args(ocl::KernelArg::ReadOnly(src),
|
||||
ocl::KernelArg::WriteOnlyNoSize(dst));
|
||||
|
||||
size_t localsize[2] = { TILE_DIM, BLOCK_ROWS };
|
||||
size_t globalsize[2] = { (size_t)src.cols, inplace ? ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI : (divUp((size_t)src.rows, TILE_DIM) * BLOCK_ROWS) };
|
||||
|
||||
if (inplace && dev.isIntel())
|
||||
{
|
||||
localsize[0] = 16;
|
||||
localsize[1] = dev.maxWorkGroupSize() / localsize[0];
|
||||
}
|
||||
|
||||
return k.run(2, globalsize, localsize, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
static bool ipp_transpose( Mat &src, Mat &dst )
|
||||
{
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
int type = src.type();
|
||||
typedef IppStatus (CV_STDCALL * IppiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize);
|
||||
typedef IppStatus (CV_STDCALL * IppiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize);
|
||||
IppiTranspose ippiTranspose = 0;
|
||||
IppiTransposeI ippiTranspose_I = 0;
|
||||
|
||||
if (dst.data == src.data && dst.cols == dst.rows)
|
||||
{
|
||||
CV_SUPPRESS_DEPRECATED_START
|
||||
ippiTranspose_I =
|
||||
type == CV_8UC1 ? (IppiTransposeI)ippiTranspose_8u_C1IR :
|
||||
type == CV_8UC3 ? (IppiTransposeI)ippiTranspose_8u_C3IR :
|
||||
type == CV_8UC4 ? (IppiTransposeI)ippiTranspose_8u_C4IR :
|
||||
type == CV_16UC1 ? (IppiTransposeI)ippiTranspose_16u_C1IR :
|
||||
type == CV_16UC3 ? (IppiTransposeI)ippiTranspose_16u_C3IR :
|
||||
type == CV_16UC4 ? (IppiTransposeI)ippiTranspose_16u_C4IR :
|
||||
type == CV_16SC1 ? (IppiTransposeI)ippiTranspose_16s_C1IR :
|
||||
type == CV_16SC3 ? (IppiTransposeI)ippiTranspose_16s_C3IR :
|
||||
type == CV_16SC4 ? (IppiTransposeI)ippiTranspose_16s_C4IR :
|
||||
type == CV_32SC1 ? (IppiTransposeI)ippiTranspose_32s_C1IR :
|
||||
type == CV_32SC3 ? (IppiTransposeI)ippiTranspose_32s_C3IR :
|
||||
type == CV_32SC4 ? (IppiTransposeI)ippiTranspose_32s_C4IR :
|
||||
type == CV_32FC1 ? (IppiTransposeI)ippiTranspose_32f_C1IR :
|
||||
type == CV_32FC3 ? (IppiTransposeI)ippiTranspose_32f_C3IR :
|
||||
type == CV_32FC4 ? (IppiTransposeI)ippiTranspose_32f_C4IR : 0;
|
||||
CV_SUPPRESS_DEPRECATED_END
|
||||
}
|
||||
else
|
||||
{
|
||||
ippiTranspose =
|
||||
type == CV_8UC1 ? (IppiTranspose)ippiTranspose_8u_C1R :
|
||||
type == CV_8UC3 ? (IppiTranspose)ippiTranspose_8u_C3R :
|
||||
type == CV_8UC4 ? (IppiTranspose)ippiTranspose_8u_C4R :
|
||||
type == CV_16UC1 ? (IppiTranspose)ippiTranspose_16u_C1R :
|
||||
type == CV_16UC3 ? (IppiTranspose)ippiTranspose_16u_C3R :
|
||||
type == CV_16UC4 ? (IppiTranspose)ippiTranspose_16u_C4R :
|
||||
type == CV_16SC1 ? (IppiTranspose)ippiTranspose_16s_C1R :
|
||||
type == CV_16SC3 ? (IppiTranspose)ippiTranspose_16s_C3R :
|
||||
type == CV_16SC4 ? (IppiTranspose)ippiTranspose_16s_C4R :
|
||||
type == CV_32SC1 ? (IppiTranspose)ippiTranspose_32s_C1R :
|
||||
type == CV_32SC3 ? (IppiTranspose)ippiTranspose_32s_C3R :
|
||||
type == CV_32SC4 ? (IppiTranspose)ippiTranspose_32s_C4R :
|
||||
type == CV_32FC1 ? (IppiTranspose)ippiTranspose_32f_C1R :
|
||||
type == CV_32FC3 ? (IppiTranspose)ippiTranspose_32f_C3R :
|
||||
type == CV_32FC4 ? (IppiTranspose)ippiTranspose_32f_C4R : 0;
|
||||
}
|
||||
|
||||
IppiSize roiSize = { src.cols, src.rows };
|
||||
if (ippiTranspose != 0)
|
||||
{
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0)
|
||||
return true;
|
||||
}
|
||||
else if (ippiTranspose_I != 0)
|
||||
{
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose_I, dst.ptr(), (int)dst.step, roiSize) >= 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void transpose( InputArray _src, OutputArray _dst )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
int type = _src.type(), esz = CV_ELEM_SIZE(type);
|
||||
CV_Assert( _src.dims() <= 2 && esz <= 32 );
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat(),
|
||||
ocl_transpose(_src, _dst))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
if( src.empty() )
|
||||
{
|
||||
_dst.release();
|
||||
return;
|
||||
}
|
||||
|
||||
_dst.create(src.cols, src.rows, src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
// handle the case of single-column/single-row matrices, stored in STL vectors.
|
||||
if( src.rows != dst.cols || src.cols != dst.rows )
|
||||
{
|
||||
CV_Assert( src.size() == dst.size() && (src.cols == 1 || src.rows == 1) );
|
||||
src.copyTo(dst);
|
||||
return;
|
||||
}
|
||||
|
||||
CV_IPP_RUN_FAST(ipp_transpose(src, dst))
|
||||
|
||||
if( dst.data == src.data )
|
||||
{
|
||||
TransposeInplaceFunc func = transposeInplaceTab[esz];
|
||||
CV_Assert( func != 0 );
|
||||
CV_Assert( dst.cols == dst.rows );
|
||||
func( dst.ptr(), dst.step, dst.rows );
|
||||
}
|
||||
else
|
||||
{
|
||||
TransposeFunc func = transposeTab[esz];
|
||||
CV_Assert( func != 0 );
|
||||
func( src.ptr(), src.step, dst.ptr(), dst.step, src.size() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if CV_SIMD128
|
||||
template<typename V> CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
typedef typename V::lane_type T;
|
||||
int end = (int)(size.width*esz);
|
||||
int width = (end + 1)/2;
|
||||
int width_1 = width & -v_uint8x16::nlanes;
|
||||
int i, j;
|
||||
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(T)>(src, dst));
|
||||
#endif
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for( i = 0, j = end; i < width_1; i += v_uint8x16::nlanes, j -= v_uint8x16::nlanes )
|
||||
{
|
||||
V t0, t1;
|
||||
|
||||
t0 = v_load((T*)((uchar*)src + i));
|
||||
t1 = v_load((T*)((uchar*)src + j - v_uint8x16::nlanes));
|
||||
t0 = v_reverse(t0);
|
||||
t1 = v_reverse(t1);
|
||||
v_store((T*)(dst + j - v_uint8x16::nlanes), t0);
|
||||
v_store((T*)(dst + i), t1);
|
||||
}
|
||||
if (isAligned<sizeof(T)>(src, dst))
|
||||
{
|
||||
for ( ; i < width; i += sizeof(T), j -= sizeof(T) )
|
||||
{
|
||||
T t0, t1;
|
||||
|
||||
t0 = *((T*)((uchar*)src + i));
|
||||
t1 = *((T*)((uchar*)src + j - sizeof(T)));
|
||||
*((T*)(dst + j - sizeof(T))) = t0;
|
||||
*((T*)(dst + i)) = t1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ; i < width; i += sizeof(T), j -= sizeof(T) )
|
||||
{
|
||||
for (int k = 0; k < (int)sizeof(T); k++)
|
||||
{
|
||||
uchar t0, t1;
|
||||
|
||||
t0 = *((uchar*)src + i + k);
|
||||
t1 = *((uchar*)src + j + k - sizeof(T));
|
||||
*(dst + j + k - sizeof(T)) = t0;
|
||||
*(dst + i + k) = t1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T1, typename T2> CV_ALWAYS_INLINE void flipHoriz_double( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
int end = (int)(size.width*esz);
|
||||
int width = (end + 1)/2;
|
||||
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(T1)>(src, dst));
|
||||
CV_Assert(isAligned<sizeof(T2)>(src, dst));
|
||||
#endif
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for ( int i = 0, j = end; i < width; i += sizeof(T1) + sizeof(T2), j -= sizeof(T1) + sizeof(T2) )
|
||||
{
|
||||
T1 t0, t1;
|
||||
T2 t2, t3;
|
||||
|
||||
t0 = *((T1*)((uchar*)src + i));
|
||||
t2 = *((T2*)((uchar*)src + i + sizeof(T1)));
|
||||
t1 = *((T1*)((uchar*)src + j - sizeof(T1) - sizeof(T2)));
|
||||
t3 = *((T2*)((uchar*)src + j - sizeof(T2)));
|
||||
*((T1*)(dst + j - sizeof(T1) - sizeof(T2))) = t0;
|
||||
*((T2*)(dst + j - sizeof(T2))) = t2;
|
||||
*((T1*)(dst + i)) = t1;
|
||||
*((T2*)(dst + i + sizeof(T1))) = t3;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
#if CV_SIMD
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
size_t alignmentMark = ((size_t)src)|((size_t)dst)|sstep|dstep;
|
||||
#endif
|
||||
if (esz == 2 * v_uint8x16::nlanes)
|
||||
{
|
||||
int end = (int)(size.width*esz);
|
||||
int width = end/2;
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for( int i = 0, j = end - 2 * v_uint8x16::nlanes; i < width; i += 2 * v_uint8x16::nlanes, j -= 2 * v_uint8x16::nlanes )
|
||||
{
|
||||
#if CV_SIMD256
|
||||
v_uint8x32 t0, t1;
|
||||
|
||||
t0 = v256_load((uchar*)src + i);
|
||||
t1 = v256_load((uchar*)src + j);
|
||||
v_store(dst + j, t0);
|
||||
v_store(dst + i, t1);
|
||||
#else
|
||||
v_uint8x16 t0, t1, t2, t3;
|
||||
|
||||
t0 = v_load((uchar*)src + i);
|
||||
t1 = v_load((uchar*)src + i + v_uint8x16::nlanes);
|
||||
t2 = v_load((uchar*)src + j);
|
||||
t3 = v_load((uchar*)src + j + v_uint8x16::nlanes);
|
||||
v_store(dst + j, t0);
|
||||
v_store(dst + j + v_uint8x16::nlanes, t1);
|
||||
v_store(dst + i, t2);
|
||||
v_store(dst + i + v_uint8x16::nlanes, t3);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (esz == v_uint8x16::nlanes)
|
||||
{
|
||||
int end = (int)(size.width*esz);
|
||||
int width = end/2;
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for( int i = 0, j = end - v_uint8x16::nlanes; i < width; i += v_uint8x16::nlanes, j -= v_uint8x16::nlanes )
|
||||
{
|
||||
v_uint8x16 t0, t1;
|
||||
|
||||
t0 = v_load((uchar*)src + i);
|
||||
t1 = v_load((uchar*)src + j);
|
||||
v_store(dst + j, t0);
|
||||
v_store(dst + i, t1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (esz == 8
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(uint64)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
flipHoriz_single<v_uint64x2>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 4
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(unsigned)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
flipHoriz_single<v_uint32x4>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 2
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(ushort)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
flipHoriz_single<v_uint16x8>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 1)
|
||||
{
|
||||
flipHoriz_single<v_uint8x16>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 24
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(uint64_t)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int end = (int)(size.width*esz);
|
||||
int width = (end + 1)/2;
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for ( int i = 0, j = end; i < width; i += v_uint8x16::nlanes + sizeof(uint64_t), j -= v_uint8x16::nlanes + sizeof(uint64_t) )
|
||||
{
|
||||
v_uint8x16 t0, t1;
|
||||
uint64_t t2, t3;
|
||||
|
||||
t0 = v_load((uchar*)src + i);
|
||||
t2 = *((uint64_t*)((uchar*)src + i + v_uint8x16::nlanes));
|
||||
t1 = v_load((uchar*)src + j - v_uint8x16::nlanes - sizeof(uint64_t));
|
||||
t3 = *((uint64_t*)((uchar*)src + j - sizeof(uint64_t)));
|
||||
v_store(dst + j - v_uint8x16::nlanes - sizeof(uint64_t), t0);
|
||||
*((uint64_t*)(dst + j - sizeof(uint64_t))) = t2;
|
||||
v_store(dst + i, t1);
|
||||
*((uint64_t*)(dst + i + v_uint8x16::nlanes)) = t3;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !CV_STRONG_ALIGNMENT
|
||||
else if (esz == 12)
|
||||
{
|
||||
flipHoriz_double<uint64_t,uint>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 6)
|
||||
{
|
||||
flipHoriz_double<uint,ushort>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 3)
|
||||
{
|
||||
flipHoriz_double<ushort,uchar>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
#endif // CV_SIMD
|
||||
{
|
||||
int i, j, limit = (int)(((size.width + 1)/2)*esz);
|
||||
AutoBuffer<int> _tab(size.width*esz);
|
||||
int* tab = _tab.data();
|
||||
|
||||
for( i = 0; i < size.width; i++ )
|
||||
for( size_t k = 0; k < esz; k++ )
|
||||
tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
for( i = 0; i < limit; i++ )
|
||||
{
|
||||
j = tab[i];
|
||||
uchar t0 = src[i], t1 = src[j];
|
||||
dst[i] = t1; dst[j] = t0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
const uchar* src1 = src0 + (size.height - 1)*sstep;
|
||||
uchar* dst1 = dst0 + (size.height - 1)*dstep;
|
||||
size.width *= (int)esz;
|
||||
|
||||
for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
|
||||
dst0 += dstep, dst1 -= dstep )
|
||||
{
|
||||
int i = 0;
|
||||
#if CV_SIMD
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
|
||||
#endif
|
||||
{
|
||||
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
|
||||
{
|
||||
v_int32 t0 = vx_load((int*)(src0 + i));
|
||||
v_int32 t1 = vx_load((int*)(src1 + i));
|
||||
v_store((int*)(dst0 + i), t1);
|
||||
v_store((int*)(dst1 + i), t0);
|
||||
}
|
||||
}
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
else
|
||||
{
|
||||
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
|
||||
{
|
||||
v_uint8 t0 = vx_load(src0 + i);
|
||||
v_uint8 t1 = vx_load(src1 + i);
|
||||
v_store(dst0 + i, t1);
|
||||
v_store(dst1 + i, t0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
|
||||
{
|
||||
for( ; i <= size.width - 16; i += 16 )
|
||||
{
|
||||
int t0 = ((int*)(src0 + i))[0];
|
||||
int t1 = ((int*)(src1 + i))[0];
|
||||
|
||||
((int*)(dst0 + i))[0] = t1;
|
||||
((int*)(dst1 + i))[0] = t0;
|
||||
|
||||
t0 = ((int*)(src0 + i))[1];
|
||||
t1 = ((int*)(src1 + i))[1];
|
||||
|
||||
((int*)(dst0 + i))[1] = t1;
|
||||
((int*)(dst1 + i))[1] = t0;
|
||||
|
||||
t0 = ((int*)(src0 + i))[2];
|
||||
t1 = ((int*)(src1 + i))[2];
|
||||
|
||||
((int*)(dst0 + i))[2] = t1;
|
||||
((int*)(dst1 + i))[2] = t0;
|
||||
|
||||
t0 = ((int*)(src0 + i))[3];
|
||||
t1 = ((int*)(src1 + i))[3];
|
||||
|
||||
((int*)(dst0 + i))[3] = t1;
|
||||
((int*)(dst1 + i))[3] = t0;
|
||||
}
|
||||
|
||||
for( ; i <= size.width - 4; i += 4 )
|
||||
{
|
||||
int t0 = ((int*)(src0 + i))[0];
|
||||
int t1 = ((int*)(src1 + i))[0];
|
||||
|
||||
((int*)(dst0 + i))[0] = t1;
|
||||
((int*)(dst1 + i))[0] = t0;
|
||||
}
|
||||
}
|
||||
|
||||
for( ; i < size.width; i++ )
|
||||
{
|
||||
uchar t0 = src0[i];
|
||||
uchar t1 = src1[i];
|
||||
|
||||
dst0[i] = t1;
|
||||
dst1[i] = t0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS };
|
||||
|
||||
static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
|
||||
{
|
||||
CV_Assert(flipCode >= -1 && flipCode <= 1);
|
||||
|
||||
const ocl::Device & dev = ocl::Device::getDefault();
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
|
||||
flipType, kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4);
|
||||
|
||||
bool doubleSupport = dev.doubleFPConfig() > 0;
|
||||
if (!doubleSupport && depth == CV_64F)
|
||||
kercn = cn;
|
||||
|
||||
if (cn > 4)
|
||||
return false;
|
||||
|
||||
const char * kernelName;
|
||||
if (flipCode == 0)
|
||||
kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
|
||||
else if (flipCode > 0)
|
||||
kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
|
||||
else
|
||||
kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
|
||||
|
||||
int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
|
||||
kercn = (cn!=3 || flipType == FLIP_ROWS) ? std::max(kercn, cn) : cn;
|
||||
|
||||
ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
|
||||
format( "-D T=%s -D T1=%s -D DEPTH=%d -D cn=%d -D PIX_PER_WI_Y=%d -D kercn=%d",
|
||||
kercn != cn ? ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)) : ocl::vecopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
|
||||
kercn != cn ? ocl::typeToStr(depth) : ocl::vecopTypeToStr(depth), depth, cn, pxPerWIy, kercn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
Size size = _src.size();
|
||||
_dst.create(size, type);
|
||||
UMat src = _src.getUMat(), dst = _dst.getUMat();
|
||||
|
||||
int cols = size.width * cn / kercn, rows = size.height;
|
||||
cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols;
|
||||
rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows;
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src),
|
||||
ocl::KernelArg::WriteOnly(dst, cn, kercn), rows, cols);
|
||||
|
||||
size_t maxWorkGroupSize = dev.maxWorkGroupSize();
|
||||
CV_Assert(maxWorkGroupSize % 4 == 0);
|
||||
|
||||
size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy },
|
||||
localsize[2] = { maxWorkGroupSize / 4, 4 };
|
||||
return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined HAVE_IPP
|
||||
static bool ipp_flip(Mat &src, Mat &dst, int flip_mode)
|
||||
{
|
||||
#ifdef HAVE_IPP_IW
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
// Details: https://github.com/opencv/opencv/issues/12943
|
||||
if (flip_mode <= 0 /* swap rows */
|
||||
&& cv::ipp::getIppTopFeatures() != ippCPUID_SSE42
|
||||
&& (int64_t)(src.total()) * src.elemSize() >= CV_BIG_INT(0x80000000)/*2Gb*/
|
||||
)
|
||||
return false;
|
||||
|
||||
IppiAxis ippMode;
|
||||
if(flip_mode < 0)
|
||||
ippMode = ippAxsBoth;
|
||||
else if(flip_mode == 0)
|
||||
ippMode = ippAxsHorizontal;
|
||||
else
|
||||
ippMode = ippAxsVertical;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiImage iwSrc = ippiGetImage(src);
|
||||
::ipp::IwiImage iwDst = ippiGetImage(dst);
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiMirror, iwSrc, iwDst, ippMode);
|
||||
}
|
||||
catch(const ::ipp::IwException &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(flip_mode);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void flip( InputArray _src, OutputArray _dst, int flip_mode )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert( _src.dims() <= 2 );
|
||||
Size size = _src.size();
|
||||
|
||||
if (flip_mode < 0)
|
||||
{
|
||||
if (size.width == 1)
|
||||
flip_mode = 0;
|
||||
if (size.height == 1)
|
||||
flip_mode = 1;
|
||||
}
|
||||
|
||||
if ((size.width == 1 && flip_mode > 0) ||
|
||||
(size.height == 1 && flip_mode == 0))
|
||||
{
|
||||
return _src.copyTo(_dst);
|
||||
}
|
||||
|
||||
CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
int type = src.type();
|
||||
_dst.create( size, type );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
CV_IPP_RUN_FAST(ipp_flip(src, dst, flip_mode));
|
||||
|
||||
size_t esz = CV_ELEM_SIZE(type);
|
||||
|
||||
if( flip_mode <= 0 )
|
||||
flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
|
||||
else
|
||||
flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
|
||||
|
||||
if( flip_mode < 0 )
|
||||
flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
|
||||
}
|
||||
|
||||
void rotate(InputArray _src, OutputArray _dst, int rotateMode)
|
||||
{
|
||||
CV_Assert(_src.dims() <= 2);
|
||||
|
||||
switch (rotateMode)
|
||||
{
|
||||
case ROTATE_90_CLOCKWISE:
|
||||
transpose(_src, _dst);
|
||||
flip(_dst, _dst, 1);
|
||||
break;
|
||||
case ROTATE_180:
|
||||
flip(_src, _dst, -1);
|
||||
break;
|
||||
case ROTATE_90_COUNTERCLOCKWISE:
|
||||
transpose(_src, _dst);
|
||||
flip(_dst, _dst, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -316,6 +316,7 @@ void _InputArray::getUMatVector(std::vector<UMat>& umv) const
|
||||
|
||||
cuda::GpuMat _InputArray::getGpuMat() const
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
int k = kind();
|
||||
|
||||
if (k == CUDA_GPU_MAT)
|
||||
@@ -339,14 +340,22 @@ cuda::GpuMat _InputArray::getGpuMat() const
|
||||
return cuda::GpuMat();
|
||||
|
||||
CV_Error(cv::Error::StsNotImplemented, "getGpuMat is available only for cuda::GpuMat and cuda::HostMem");
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
void _InputArray::getGpuMatVector(std::vector<cuda::GpuMat>& gpumv) const
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
int k = kind();
|
||||
if (k == STD_VECTOR_CUDA_GPU_MAT)
|
||||
{
|
||||
gpumv = *(std::vector<cuda::GpuMat>*)obj;
|
||||
}
|
||||
#else
|
||||
CV_UNUSED(gpumv);
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
ogl::Buffer _InputArray::getOGlBuffer() const
|
||||
{
|
||||
@@ -457,11 +466,15 @@ Size _InputArray::size(int i) const
|
||||
|
||||
if (k == STD_VECTOR_CUDA_GPU_MAT)
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
|
||||
if (i < 0)
|
||||
return vv.empty() ? Size() : Size((int)vv.size(), 1);
|
||||
CV_Assert(i < (int)vv.size());
|
||||
return vv[i].size();
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
|
||||
if( k == STD_VECTOR_UMAT )
|
||||
@@ -795,6 +808,7 @@ int _InputArray::type(int i) const
|
||||
|
||||
if (k == STD_VECTOR_CUDA_GPU_MAT)
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
|
||||
if (vv.empty())
|
||||
{
|
||||
@@ -803,6 +817,9 @@ int _InputArray::type(int i) const
|
||||
}
|
||||
CV_Assert(i < (int)vv.size());
|
||||
return vv[i >= 0 ? i : 0].type();
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
|
||||
if( k == OPENGL_BUFFER )
|
||||
@@ -1164,22 +1181,34 @@ void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, int
|
||||
{
|
||||
CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == _sz);
|
||||
CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
|
||||
#ifdef HAVE_CUDA
|
||||
((cuda::GpuMat*)obj)->create(_sz, mtype);
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
||||
{
|
||||
CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == _sz);
|
||||
CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
|
||||
#ifdef HAVE_OPENGL
|
||||
((ogl::Buffer*)obj)->create(_sz, mtype);
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "OpenGL support is not enabled in this OpenCV build (missing HAVE_OPENGL)");
|
||||
#endif
|
||||
}
|
||||
if( k == CUDA_HOST_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
||||
{
|
||||
CV_Assert(!fixedSize() || ((cuda::HostMem*)obj)->size() == _sz);
|
||||
CV_Assert(!fixedType() || ((cuda::HostMem*)obj)->type() == mtype);
|
||||
#ifdef HAVE_CUDA
|
||||
((cuda::HostMem*)obj)->create(_sz, mtype);
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
int sizes[] = {_sz.height, _sz.width};
|
||||
create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
|
||||
@@ -1206,22 +1235,34 @@ void _OutputArray::create(int _rows, int _cols, int mtype, int i, bool allowTran
|
||||
{
|
||||
CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == Size(_cols, _rows));
|
||||
CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
|
||||
#ifdef HAVE_CUDA
|
||||
((cuda::GpuMat*)obj)->create(_rows, _cols, mtype);
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
||||
{
|
||||
CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == Size(_cols, _rows));
|
||||
CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
|
||||
#ifdef HAVE_OPENGL
|
||||
((ogl::Buffer*)obj)->create(_rows, _cols, mtype);
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "OpenGL support is not enabled in this OpenCV build (missing HAVE_OPENGL)");
|
||||
#endif
|
||||
}
|
||||
if( k == CUDA_HOST_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
||||
{
|
||||
CV_Assert(!fixedSize() || ((cuda::HostMem*)obj)->size() == Size(_cols, _rows));
|
||||
CV_Assert(!fixedType() || ((cuda::HostMem*)obj)->type() == mtype);
|
||||
#ifdef HAVE_CUDA
|
||||
((cuda::HostMem*)obj)->create(_rows, _cols, mtype);
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
int sizes[] = {_rows, _cols};
|
||||
create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
|
||||
@@ -1644,20 +1685,32 @@ void _OutputArray::release() const
|
||||
|
||||
if( k == CUDA_GPU_MAT )
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
((cuda::GpuMat*)obj)->release();
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
|
||||
if( k == CUDA_HOST_MEM )
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
((cuda::HostMem*)obj)->release();
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
|
||||
if( k == OPENGL_BUFFER )
|
||||
{
|
||||
#ifdef HAVE_OPENGL
|
||||
((ogl::Buffer*)obj)->release();
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "OpenGL support is not enabled in this OpenCV build (missing HAVE_OPENGL)");
|
||||
#endif
|
||||
}
|
||||
|
||||
if( k == NONE )
|
||||
@@ -1688,8 +1741,12 @@ void _OutputArray::release() const
|
||||
}
|
||||
if (k == STD_VECTOR_CUDA_GPU_MAT)
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
((std::vector<cuda::GpuMat>*)obj)->clear();
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
|
||||
}
|
||||
@@ -1797,9 +1854,13 @@ void _OutputArray::setTo(const _InputArray& arr, const _InputArray & mask) const
|
||||
((UMat*)obj)->setTo(arr, mask);
|
||||
else if( k == CUDA_GPU_MAT )
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
Mat value = arr.getMat();
|
||||
CV_Assert( checkScalar(value, type(), arr.kind(), _InputArray::CUDA_GPU_MAT) );
|
||||
((cuda::GpuMat*)obj)->setTo(Scalar(Vec<double, 4>(value.ptr<double>())), mask);
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsNotImplemented, "");
|
||||
|
||||
+149
-25
@@ -205,13 +205,10 @@ int normL1_(const uchar* a, const uchar* b, int n)
|
||||
return d;
|
||||
}
|
||||
|
||||
}} //cv::hal
|
||||
} //cv::hal
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
template<typename T, typename ST> int
|
||||
normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn)
|
||||
{
|
||||
@@ -591,12 +588,10 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result)
|
||||
CV_UNUSED(src); CV_UNUSED(normType); CV_UNUSED(mask); CV_UNUSED(result);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
} // ipp_norm()
|
||||
#endif // HAVE_IPP
|
||||
|
||||
} // cv::
|
||||
|
||||
double cv::norm( InputArray _src, int normType, InputArray _mask )
|
||||
double norm( InputArray _src, int normType, InputArray _mask )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -769,9 +764,6 @@ double cv::norm( InputArray _src, int normType, InputArray _mask )
|
||||
//==================================================================================================
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cv {
|
||||
|
||||
static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask, double & result )
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
@@ -826,15 +818,10 @@ static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, InputArr
|
||||
result /= (s2 + DBL_EPSILON);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
} // ocl_norm()
|
||||
#endif // HAVE_OPENCL
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
namespace cv
|
||||
{
|
||||
static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArray _mask, double &result)
|
||||
{
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
@@ -1060,12 +1047,11 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra
|
||||
CV_UNUSED(_src1); CV_UNUSED(_src2); CV_UNUSED(normType); CV_UNUSED(_mask); CV_UNUSED(result);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // ipp_norm
|
||||
#endif // HAVE_IPP
|
||||
|
||||
|
||||
double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask )
|
||||
double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -1234,12 +1220,12 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m
|
||||
return result.d;
|
||||
}
|
||||
|
||||
cv::Hamming::ResultType cv::Hamming::operator()( const unsigned char* a, const unsigned char* b, int size ) const
|
||||
cv::Hamming::ResultType Hamming::operator()( const unsigned char* a, const unsigned char* b, int size ) const
|
||||
{
|
||||
return cv::hal::normHamming(a, b, size);
|
||||
}
|
||||
|
||||
double cv::PSNR(InputArray _src1, InputArray _src2)
|
||||
double PSNR(InputArray _src1, InputArray _src2)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -1249,3 +1235,141 @@ double cv::PSNR(InputArray _src1, InputArray _src2)
|
||||
double diff = std::sqrt(norm(_src1, _src2, NORM_L2SQR)/(_src1.total()*_src1.channels()));
|
||||
return 20*log10(255./(diff+DBL_EPSILON));
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
static bool ocl_normalize( InputArray _src, InputOutputArray _dst, InputArray _mask, int dtype,
|
||||
double scale, double delta )
|
||||
{
|
||||
UMat src = _src.getUMat();
|
||||
|
||||
if( _mask.empty() )
|
||||
src.convertTo( _dst, dtype, scale, delta );
|
||||
else if (src.channels() <= 4)
|
||||
{
|
||||
const ocl::Device & dev = ocl::Device::getDefault();
|
||||
|
||||
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
|
||||
ddepth = CV_MAT_DEPTH(dtype), wdepth = std::max(CV_32F, std::max(sdepth, ddepth)),
|
||||
rowsPerWI = dev.isIntel() ? 4 : 1;
|
||||
|
||||
float fscale = static_cast<float>(scale), fdelta = static_cast<float>(delta);
|
||||
bool haveScale = std::fabs(scale - 1) > DBL_EPSILON,
|
||||
haveZeroScale = !(std::fabs(scale) > DBL_EPSILON),
|
||||
haveDelta = std::fabs(delta) > DBL_EPSILON,
|
||||
doubleSupport = dev.doubleFPConfig() > 0;
|
||||
|
||||
if (!haveScale && !haveDelta && stype == dtype)
|
||||
{
|
||||
_src.copyTo(_dst, _mask);
|
||||
return true;
|
||||
}
|
||||
if (haveZeroScale)
|
||||
{
|
||||
_dst.setTo(Scalar(delta), _mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((sdepth == CV_64F || ddepth == CV_64F) && !doubleSupport)
|
||||
return false;
|
||||
|
||||
char cvt[2][40];
|
||||
String opts = format("-D srcT=%s -D dstT=%s -D convertToWT=%s -D cn=%d -D rowsPerWI=%d"
|
||||
" -D convertToDT=%s -D workT=%s%s%s%s -D srcT1=%s -D dstT1=%s",
|
||||
ocl::typeToStr(stype), ocl::typeToStr(dtype),
|
||||
ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]), cn,
|
||||
rowsPerWI, ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]),
|
||||
ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : "",
|
||||
haveScale ? " -D HAVE_SCALE" : "",
|
||||
haveDelta ? " -D HAVE_DELTA" : "",
|
||||
ocl::typeToStr(sdepth), ocl::typeToStr(ddepth));
|
||||
|
||||
ocl::Kernel k("normalizek", ocl::core::normalize_oclsrc, opts);
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat mask = _mask.getUMat(), dst = _dst.getUMat();
|
||||
|
||||
ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
|
||||
maskarg = ocl::KernelArg::ReadOnlyNoSize(mask),
|
||||
dstarg = ocl::KernelArg::ReadWrite(dst);
|
||||
|
||||
if (haveScale)
|
||||
{
|
||||
if (haveDelta)
|
||||
k.args(srcarg, maskarg, dstarg, fscale, fdelta);
|
||||
else
|
||||
k.args(srcarg, maskarg, dstarg, fscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (haveDelta)
|
||||
k.args(srcarg, maskarg, dstarg, fdelta);
|
||||
else
|
||||
k.args(srcarg, maskarg, dstarg);
|
||||
}
|
||||
|
||||
size_t globalsize[2] = { (size_t)src.cols, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
UMat temp;
|
||||
src.convertTo( temp, dtype, scale, delta );
|
||||
temp.copyTo( _dst, _mask );
|
||||
}
|
||||
|
||||
return true;
|
||||
} // ocl_normalize
|
||||
#endif // HAVE_OPENCL
|
||||
|
||||
void normalize(InputArray _src, InputOutputArray _dst, double a, double b,
|
||||
int norm_type, int rtype, InputArray _mask)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
double scale = 1, shift = 0;
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type);
|
||||
|
||||
if( rtype < 0 )
|
||||
rtype = _dst.fixedType() ? _dst.depth() : depth;
|
||||
|
||||
if( norm_type == CV_MINMAX )
|
||||
{
|
||||
double smin = 0, smax = 0;
|
||||
double dmin = MIN( a, b ), dmax = MAX( a, b );
|
||||
minMaxIdx( _src, &smin, &smax, 0, 0, _mask );
|
||||
scale = (dmax - dmin)*(smax - smin > DBL_EPSILON ? 1./(smax - smin) : 0);
|
||||
if( rtype == CV_32F )
|
||||
{
|
||||
scale = (float)scale;
|
||||
shift = (float)dmin - (float)(smin*scale);
|
||||
}
|
||||
else
|
||||
shift = dmin - smin*scale;
|
||||
}
|
||||
else if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C )
|
||||
{
|
||||
scale = norm( _src, norm_type, _mask );
|
||||
scale = scale > DBL_EPSILON ? a/scale : 0.;
|
||||
shift = 0;
|
||||
}
|
||||
else
|
||||
CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" );
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat(),
|
||||
ocl_normalize(_src, _dst, _mask, rtype, scale, shift))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
if( _mask.empty() )
|
||||
src.convertTo( _dst, rtype, scale, shift );
|
||||
else
|
||||
{
|
||||
Mat temp;
|
||||
src.convertTo( temp, rtype, scale, shift );
|
||||
temp.copyTo( _dst, _mask );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -91,63 +91,50 @@ void YUV2BGR_NV12_8u(
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
// each iteration computes 2*2=4 pixels
|
||||
int x2 = x*2;
|
||||
int y2 = y*2;
|
||||
|
||||
if (x + 1 < cols)
|
||||
{
|
||||
if (y + 1 < rows)
|
||||
{
|
||||
__global uchar* pDstRow1 = pBGR + mad24(y, bgrStep, mad24(x, NCHANNELS, 0));
|
||||
__global uchar* pDstRow2 = pDstRow1 + bgrStep;
|
||||
if (x2 + 1 < cols) {
|
||||
if (y2 + 1 < rows) {
|
||||
__global uchar *pDstRow1 = pBGR + mad24(y2, bgrStep, mad24(x2, NCHANNELS, 0));
|
||||
__global uchar *pDstRow2 = pDstRow1 + bgrStep;
|
||||
|
||||
float4 Y1 = read_imagef(imgY, (int2)(x+0, y+0));
|
||||
float4 Y2 = read_imagef(imgY, (int2)(x+1, y+0));
|
||||
float4 Y3 = read_imagef(imgY, (int2)(x+0, y+1));
|
||||
float4 Y4 = read_imagef(imgY, (int2)(x+1, y+1));
|
||||
float4 Y1 = read_imagef(imgY, (int2)(x2 + 0, y2 + 0));
|
||||
float4 Y2 = read_imagef(imgY, (int2)(x2 + 1, y2 + 0));
|
||||
float4 Y3 = read_imagef(imgY, (int2)(x2 + 0, y2 + 1));
|
||||
float4 Y4 = read_imagef(imgY, (int2)(x2 + 1, y2 + 1));
|
||||
float4 Y = (float4)(Y1.x, Y2.x, Y3.x, Y4.x);
|
||||
|
||||
float4 UV = read_imagef(imgUV, (int2)(x/2, y/2)) - d2;
|
||||
float4 UV = read_imagef(imgUV, (int2)(x, y)) - d2;
|
||||
|
||||
__constant float* coeffs = c_YUV2RGBCoeffs_420;
|
||||
__constant float *coeffs = c_YUV2RGBCoeffs_420;
|
||||
|
||||
Y1 = max(0.f, Y1 - d1) * coeffs[0];
|
||||
Y2 = max(0.f, Y2 - d1) * coeffs[0];
|
||||
Y3 = max(0.f, Y3 - d1) * coeffs[0];
|
||||
Y4 = max(0.f, Y4 - d1) * coeffs[0];
|
||||
Y = max(0.f, Y - d1) * coeffs[0];
|
||||
|
||||
float ruv = fma(coeffs[4], UV.y, 0.0f);
|
||||
float guv = fma(coeffs[3], UV.y, fma(coeffs[2], UV.x, 0.0f));
|
||||
float buv = fma(coeffs[1], UV.x, 0.0f);
|
||||
|
||||
float R1 = (Y1.x + ruv) * CV_8U_MAX;
|
||||
float G1 = (Y1.x + guv) * CV_8U_MAX;
|
||||
float B1 = (Y1.x + buv) * CV_8U_MAX;
|
||||
float4 R = (Y + ruv) * CV_8U_MAX;
|
||||
float4 G = (Y + guv) * CV_8U_MAX;
|
||||
float4 B = (Y + buv) * CV_8U_MAX;
|
||||
|
||||
float R2 = (Y2.x + ruv) * CV_8U_MAX;
|
||||
float G2 = (Y2.x + guv) * CV_8U_MAX;
|
||||
float B2 = (Y2.x + buv) * CV_8U_MAX;
|
||||
pDstRow1[0*NCHANNELS + 0] = convert_uchar_sat(B.x);
|
||||
pDstRow1[0*NCHANNELS + 1] = convert_uchar_sat(G.x);
|
||||
pDstRow1[0*NCHANNELS + 2] = convert_uchar_sat(R.x);
|
||||
|
||||
float R3 = (Y3.x + ruv) * CV_8U_MAX;
|
||||
float G3 = (Y3.x + guv) * CV_8U_MAX;
|
||||
float B3 = (Y3.x + buv) * CV_8U_MAX;
|
||||
pDstRow1[1*NCHANNELS + 0] = convert_uchar_sat(B.y);
|
||||
pDstRow1[1*NCHANNELS + 1] = convert_uchar_sat(G.y);
|
||||
pDstRow1[1*NCHANNELS + 2] = convert_uchar_sat(R.y);
|
||||
|
||||
float R4 = (Y4.x + ruv) * CV_8U_MAX;
|
||||
float G4 = (Y4.x + guv) * CV_8U_MAX;
|
||||
float B4 = (Y4.x + buv) * CV_8U_MAX;
|
||||
pDstRow2[0*NCHANNELS + 0] = convert_uchar_sat(B.z);
|
||||
pDstRow2[0*NCHANNELS + 1] = convert_uchar_sat(G.z);
|
||||
pDstRow2[0*NCHANNELS + 2] = convert_uchar_sat(R.z);
|
||||
|
||||
pDstRow1[0*NCHANNELS + 0] = convert_uchar_sat(B1);
|
||||
pDstRow1[0*NCHANNELS + 1] = convert_uchar_sat(G1);
|
||||
pDstRow1[0*NCHANNELS + 2] = convert_uchar_sat(R1);
|
||||
|
||||
pDstRow1[1*NCHANNELS + 0] = convert_uchar_sat(B2);
|
||||
pDstRow1[1*NCHANNELS + 1] = convert_uchar_sat(G2);
|
||||
pDstRow1[1*NCHANNELS + 2] = convert_uchar_sat(R2);
|
||||
|
||||
pDstRow2[0*NCHANNELS + 0] = convert_uchar_sat(B3);
|
||||
pDstRow2[0*NCHANNELS + 1] = convert_uchar_sat(G3);
|
||||
pDstRow2[0*NCHANNELS + 2] = convert_uchar_sat(R3);
|
||||
|
||||
pDstRow2[1*NCHANNELS + 0] = convert_uchar_sat(B4);
|
||||
pDstRow2[1*NCHANNELS + 1] = convert_uchar_sat(G4);
|
||||
pDstRow2[1*NCHANNELS + 2] = convert_uchar_sat(R4);
|
||||
pDstRow2[1*NCHANNELS + 0] = convert_uchar_sat(B.w);
|
||||
pDstRow2[1*NCHANNELS + 1] = convert_uchar_sat(G.w);
|
||||
pDstRow2[1*NCHANNELS + 2] = convert_uchar_sat(R.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,12 +159,15 @@ void BGR2YUV_NV12_8u(
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
// each iteration computes 2*2=4 pixels
|
||||
int x2 = x*2;
|
||||
int y2 = y*2;
|
||||
|
||||
if (x < cols)
|
||||
if (x2 + 1 < cols)
|
||||
{
|
||||
if (y < rows)
|
||||
if (y2 + 1 < rows)
|
||||
{
|
||||
__global const uchar* pSrcRow1 = pBGR + mad24(y, bgrStep, mad24(x, NCHANNELS, 0));
|
||||
__global const uchar* pSrcRow1 = pBGR + mad24(y2, bgrStep, mad24(x2, NCHANNELS, 0));
|
||||
__global const uchar* pSrcRow2 = pSrcRow1 + bgrStep;
|
||||
|
||||
float4 src_pix1 = convert_float4(vload4(0, pSrcRow1 + 0*NCHANNELS)) * CV_8U_SCALE;
|
||||
@@ -196,12 +186,12 @@ void BGR2YUV_NV12_8u(
|
||||
UV.x = fma(coeffs[3], src_pix1.z, fma(coeffs[4], src_pix1.y, fma(coeffs[5], src_pix1.x, d2)));
|
||||
UV.y = fma(coeffs[5], src_pix1.z, fma(coeffs[6], src_pix1.y, fma(coeffs[7], src_pix1.x, d2)));
|
||||
|
||||
write_imagef(imgY, (int2)(x+0, y+0), Y1);
|
||||
write_imagef(imgY, (int2)(x+1, y+0), Y2);
|
||||
write_imagef(imgY, (int2)(x+0, y+1), Y3);
|
||||
write_imagef(imgY, (int2)(x+1, y+1), Y4);
|
||||
write_imagef(imgY, (int2)(x2+0, y2+0), Y1);
|
||||
write_imagef(imgY, (int2)(x2+1, y2+0), Y2);
|
||||
write_imagef(imgY, (int2)(x2+0, y2+1), Y3);
|
||||
write_imagef(imgY, (int2)(x2+1, y2+1), Y4);
|
||||
|
||||
write_imagef(imgUV, (int2)((x/2), (y/2)), UV);
|
||||
write_imagef(imgUV, (int2)(x, y), UV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1378,48 +1378,6 @@ cvTypeOf( const void* struct_ptr )
|
||||
}
|
||||
|
||||
|
||||
/* universal functions */
|
||||
CV_IMPL void
|
||||
cvRelease( void** struct_ptr )
|
||||
{
|
||||
CvTypeInfo* info;
|
||||
|
||||
if( !struct_ptr )
|
||||
CV_Error( CV_StsNullPtr, "NULL double pointer" );
|
||||
|
||||
if( *struct_ptr )
|
||||
{
|
||||
info = cvTypeOf( *struct_ptr );
|
||||
if( !info )
|
||||
CV_Error( CV_StsError, "Unknown object type" );
|
||||
if( !info->release )
|
||||
CV_Error( CV_StsError, "release function pointer is NULL" );
|
||||
|
||||
info->release( struct_ptr );
|
||||
*struct_ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void* cvClone( const void* struct_ptr )
|
||||
{
|
||||
void* struct_copy = 0;
|
||||
CvTypeInfo* info;
|
||||
|
||||
if( !struct_ptr )
|
||||
CV_Error( CV_StsNullPtr, "NULL structure pointer" );
|
||||
|
||||
info = cvTypeOf( struct_ptr );
|
||||
if( !info )
|
||||
CV_Error( CV_StsError, "Unknown object type" );
|
||||
if( !info->clone )
|
||||
CV_Error( CV_StsError, "clone function pointer is NULL" );
|
||||
|
||||
struct_copy = info->clone( struct_ptr );
|
||||
return struct_copy;
|
||||
}
|
||||
|
||||
|
||||
/* reads matrix, image, sequence, graph etc. */
|
||||
CV_IMPL void*
|
||||
cvRead( CvFileStorage* fs, CvFileNode* node, CvAttrList* list )
|
||||
|
||||
@@ -867,6 +867,9 @@ void cv::randShuffle( InputOutputArray _dst, double iterFactor, RNG* _rng )
|
||||
func( dst, rng, iterFactor );
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
CV_IMPL void
|
||||
cvRandArr( CvRNG* _rng, CvArr* arr, int disttype, CvScalar param1, CvScalar param2 )
|
||||
{
|
||||
@@ -884,6 +887,9 @@ CV_IMPL void cvRandShuffle( CvArr* arr, CvRNG* _rng, double iter_factor )
|
||||
cv::randShuffle( dst, iter_factor, &rng );
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
|
||||
|
||||
// Mersenne Twister random number generator.
|
||||
// Inspired by http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#ifndef OPENCV_EXCLUDE_C_API
|
||||
|
||||
CV_IMPL CvScalar cvSum( const CvArr* srcarr )
|
||||
{
|
||||
cv::Scalar sum = cv::sum(cv::cvarrToMat(srcarr, false, true, 1));
|
||||
@@ -117,3 +119,5 @@ cvNorm( const void* imgA, const void* imgB, int normType, const void* maskarr )
|
||||
|
||||
return !maskarr ? cv::norm(a, b, normType) : cv::norm(a, b, normType, mask);
|
||||
}
|
||||
|
||||
#endif // OPENCV_EXCLUDE_C_API
|
||||
|
||||
@@ -128,11 +128,14 @@ void* allocSingletonNewBuffer(size_t size) { return malloc(size); }
|
||||
#endif
|
||||
|
||||
|
||||
#if CV_VSX && defined __linux__
|
||||
#if (defined __ppc64__ || defined __PPC64__) && defined __linux__
|
||||
# include "sys/auxv.h"
|
||||
# ifndef AT_HWCAP2
|
||||
# define AT_HWCAP2 26
|
||||
# endif
|
||||
# ifndef PPC_FEATURE2_ARCH_2_07
|
||||
# define PPC_FEATURE2_ARCH_2_07 0x80000000
|
||||
# endif
|
||||
# ifndef PPC_FEATURE2_ARCH_3_00
|
||||
# define PPC_FEATURE2_ARCH_3_00 0x00800000
|
||||
# endif
|
||||
@@ -587,14 +590,25 @@ struct HWFeatures
|
||||
#ifdef __mips_msa
|
||||
have[CV_CPU_MSA] = true;
|
||||
#endif
|
||||
// there's no need to check VSX availability in runtime since it's always available on ppc64le CPUs
|
||||
have[CV_CPU_VSX] = (CV_VSX);
|
||||
// TODO: Check VSX3 availability in runtime for other platforms
|
||||
#if CV_VSX && defined __linux__
|
||||
uint64 hwcap2 = getauxval(AT_HWCAP2);
|
||||
have[CV_CPU_VSX3] = (hwcap2 & PPC_FEATURE2_ARCH_3_00);
|
||||
|
||||
#if (defined __ppc64__ || defined __PPC64__) && defined __linux__
|
||||
unsigned int hwcap = getauxval(AT_HWCAP);
|
||||
if (hwcap & PPC_FEATURE_HAS_VSX) {
|
||||
hwcap = getauxval(AT_HWCAP2);
|
||||
if (hwcap & PPC_FEATURE2_ARCH_3_00) {
|
||||
have[CV_CPU_VSX] = have[CV_CPU_VSX3] = true;
|
||||
} else {
|
||||
have[CV_CPU_VSX] = (hwcap & PPC_FEATURE2_ARCH_2_07) != 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
have[CV_CPU_VSX3] = (CV_VSX3);
|
||||
// TODO: AIX, FreeBSD
|
||||
#if CV_VSX || defined _ARCH_PWR8 || defined __POWER9_VECTOR__
|
||||
have[CV_CPU_VSX] = true;
|
||||
#endif
|
||||
#if CV_VSX3 || defined __POWER9_VECTOR__
|
||||
have[CV_CPU_VSX3] = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool skip_baseline_check = false;
|
||||
@@ -1924,7 +1938,7 @@ class ParseError
|
||||
{
|
||||
std::string bad_value;
|
||||
public:
|
||||
ParseError(const std::string bad_value_) :bad_value(bad_value_) {}
|
||||
ParseError(const std::string &bad_value_) :bad_value(bad_value_) {}
|
||||
std::string toString(const std::string ¶m) const
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
@@ -230,7 +230,7 @@ UMatDataAutoLock::~UMatDataAutoLock()
|
||||
|
||||
//////////////////////////////// UMat ////////////////////////////////
|
||||
|
||||
UMat::UMat(UMatUsageFlags _usageFlags)
|
||||
UMat::UMat(UMatUsageFlags _usageFlags) CV_NOEXCEPT
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{}
|
||||
|
||||
@@ -1259,88 +1259,6 @@ UMat UMat::t() const
|
||||
return m;
|
||||
}
|
||||
|
||||
UMat UMat::inv(int method) const
|
||||
{
|
||||
UMat m;
|
||||
invert(*this, m, method);
|
||||
return m;
|
||||
}
|
||||
|
||||
UMat UMat::mul(InputArray m, double scale) const
|
||||
{
|
||||
UMat dst;
|
||||
multiply(*this, m, dst, scale);
|
||||
return dst;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_dot( InputArray _src1, InputArray _src2, double & res )
|
||||
{
|
||||
UMat src1 = _src1.getUMat().reshape(1), src2 = _src2.getUMat().reshape(1);
|
||||
|
||||
int type = src1.type(), depth = CV_MAT_DEPTH(type),
|
||||
kercn = ocl::predictOptimalVectorWidth(src1, src2);
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
if ( !doubleSupport && depth == CV_64F )
|
||||
return false;
|
||||
|
||||
int dbsize = ocl::Device::getDefault().maxComputeUnits();
|
||||
size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
|
||||
int ddepth = std::max(CV_32F, depth);
|
||||
|
||||
int wgs2_aligned = 1;
|
||||
while (wgs2_aligned < (int)wgs)
|
||||
wgs2_aligned <<= 1;
|
||||
wgs2_aligned >>= 1;
|
||||
|
||||
char cvt[40];
|
||||
ocl::Kernel k("reduce", ocl::core::reduce_oclsrc,
|
||||
format("-D srcT=%s -D srcT1=%s -D dstT=%s -D dstTK=%s -D ddepth=%d -D convertToDT=%s -D OP_DOT "
|
||||
"-D WGS=%d -D WGS2_ALIGNED=%d%s%s%s -D kercn=%d",
|
||||
ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), ocl::typeToStr(depth),
|
||||
ocl::typeToStr(ddepth), ocl::typeToStr(CV_MAKE_TYPE(ddepth, kercn)),
|
||||
ddepth, ocl::convertTypeStr(depth, ddepth, kercn, cvt),
|
||||
(int)wgs, wgs2_aligned, doubleSupport ? " -D DOUBLE_SUPPORT" : "",
|
||||
_src1.isContinuous() ? " -D HAVE_SRC_CONT" : "",
|
||||
_src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "", kercn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat db(1, dbsize, ddepth);
|
||||
|
||||
ocl::KernelArg src1arg = ocl::KernelArg::ReadOnlyNoSize(src1),
|
||||
src2arg = ocl::KernelArg::ReadOnlyNoSize(src2),
|
||||
dbarg = ocl::KernelArg::PtrWriteOnly(db);
|
||||
|
||||
k.args(src1arg, src1.cols, (int)src1.total(), dbsize, dbarg, src2arg);
|
||||
|
||||
size_t globalsize = dbsize * wgs;
|
||||
if (k.run(1, &globalsize, &wgs, false))
|
||||
{
|
||||
res = sum(db.getMat(ACCESS_READ))[0];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
double UMat::dot(InputArray m) const
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert(m.sameSize(*this) && m.type() == type());
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
double r = 0;
|
||||
CV_OCL_RUN_(dims <= 2, ocl_dot(*this, m, r), r)
|
||||
#endif
|
||||
|
||||
return getMat(ACCESS_READ).dot(m);
|
||||
}
|
||||
|
||||
UMat UMat::zeros(int rows, int cols, int type)
|
||||
{
|
||||
return UMat(rows, cols, type, Scalar::all(0));
|
||||
@@ -1371,18 +1289,6 @@ UMat UMat::ones(int ndims, const int* sz, int type)
|
||||
return UMat(ndims, sz, type, Scalar(1));
|
||||
}
|
||||
|
||||
UMat UMat::eye(int rows, int cols, int type)
|
||||
{
|
||||
return UMat::eye(Size(cols, rows), type);
|
||||
}
|
||||
|
||||
UMat UMat::eye(Size size, int type)
|
||||
{
|
||||
UMat m(size, type);
|
||||
setIdentity(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
|
||||
@@ -158,7 +158,7 @@ static bool ocl_convert_nv12_to_bgr(cl_mem clImageY, cl_mem clImageUV, cl_mem cl
|
||||
|
||||
k.args(clImageY, clImageUV, clBuffer, step, cols, rows);
|
||||
|
||||
size_t globalsize[] = { (size_t)cols, (size_t)rows };
|
||||
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
|
||||
return k.run(2, globalsize, 0, false);
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ static bool ocl_convert_bgr_to_nv12(cl_mem clBuffer, int step, int cols, int row
|
||||
|
||||
k.args(clBuffer, step, cols, rows, clImageY, clImageUV);
|
||||
|
||||
size_t globalsize[] = { (size_t)cols, (size_t)rows };
|
||||
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
|
||||
return k.run(2, globalsize, 0, false);
|
||||
}
|
||||
#endif // HAVE_VA_INTEL && HAVE_OPENCL
|
||||
|
||||
@@ -120,6 +120,11 @@ TEST(OpenCL, support_SPIR_programs)
|
||||
cv::ocl::ProgramSource src = cv::ocl::ProgramSource::fromSPIR(module_name, "simple_spir", (uchar*)&program_binary_code[0], program_binary_code.size(), "");
|
||||
cv::String errmsg;
|
||||
cv::ocl::Program program(src, "", errmsg);
|
||||
if (program.ptr() == NULL && device.isAMD())
|
||||
{
|
||||
// https://community.amd.com/t5/opencl/spir-support-in-new-drivers-lost/td-p/170165
|
||||
throw cvtest::SkipTestException("Bypass AMD OpenCL runtime bug: 'cl_khr_spir' extension is declared, but it doesn't really work");
|
||||
}
|
||||
ASSERT_TRUE(program.ptr() != NULL);
|
||||
k.create("test_kernel", program);
|
||||
}
|
||||
|
||||
@@ -2376,4 +2376,16 @@ TEST(Core_MinMaxIdx, rows_overflow)
|
||||
}
|
||||
|
||||
|
||||
TEST(Core_Magnitude, regression_19506)
|
||||
{
|
||||
for (int N = 1; N <= 64; ++N)
|
||||
{
|
||||
Mat a(1, N, CV_32FC1, Scalar::all(1e-20));
|
||||
Mat res;
|
||||
magnitude(a, a, res);
|
||||
EXPECT_LE(cvtest::norm(res, NORM_L1), 1e-15) << N;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -1466,7 +1466,7 @@ template<typename R> struct TheTest
|
||||
R r1 = vx_load_expand((const cv::float16_t*)data.a.d);
|
||||
R r2(r1);
|
||||
EXPECT_EQ(1.0f, r1.get0());
|
||||
vx_store(data_f32.a.d, r2);
|
||||
v_store(data_f32.a.d, r2);
|
||||
EXPECT_EQ(-2.0f, data_f32.a.d[R::nlanes - 1]);
|
||||
|
||||
out.a.clear();
|
||||
|
||||
@@ -1551,4 +1551,14 @@ TEST(Core_MatExpr, empty_check_15760)
|
||||
EXPECT_THROW(Mat c = Mat().cross(Mat()), cv::Exception);
|
||||
}
|
||||
|
||||
TEST(Core_Arithm, scalar_handling_19599) // https://github.com/opencv/opencv/issues/19599 (OpenCV 4.x+ only)
|
||||
{
|
||||
Mat a(1, 1, CV_32F, Scalar::all(1));
|
||||
Mat b(4, 1, CV_64F, Scalar::all(1)); // MatExpr may convert Scalar to Mat
|
||||
Mat c;
|
||||
EXPECT_NO_THROW(cv::multiply(a, b, c));
|
||||
EXPECT_EQ(1, c.cols);
|
||||
EXPECT_EQ(1, c.rows);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -163,7 +163,7 @@ void cv::cuda::flip(InputArray _src, OutputArray _dst, int flipCode, Stream& str
|
||||
|
||||
_dst.create(src.size(), src.type());
|
||||
GpuMat dst = getOutputMat(_dst, src.size(), src.type(), stream);
|
||||
bool isInplace = (src.data == dst.data) || (src.refcount == dst.refcount);
|
||||
bool isInplace = (src.data == dst.data);
|
||||
bool isSizeOdd = (src.cols & 1) == 1 || (src.rows & 1) == 1;
|
||||
if (isInplace && isSizeOdd)
|
||||
CV_Error(Error::BadROISize, "In-place version of flip only accepts even width/height");
|
||||
|
||||
@@ -364,6 +364,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
|
||||
* Inner vector has slice ranges for the first number of input dimensions.
|
||||
*/
|
||||
std::vector<std::vector<Range> > sliceRanges;
|
||||
std::vector<std::vector<int> > sliceSteps;
|
||||
int axis;
|
||||
int num_split;
|
||||
|
||||
|
||||
@@ -235,6 +235,23 @@ Range normalize_axis_range(const Range& r, int axisSize)
|
||||
return clamped;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool isAllOnes(const MatShape &inputShape, int startPos, int endPos)
|
||||
{
|
||||
CV_Assert(!inputShape.empty());
|
||||
|
||||
CV_CheckGE((int) inputShape.size(), startPos, "");
|
||||
CV_CheckGE(startPos, 0, "");
|
||||
CV_CheckLE(startPos, endPos, "");
|
||||
CV_CheckLE((size_t)endPos, inputShape.size(), "");
|
||||
|
||||
for (size_t i = startPos; i < endPos; i++)
|
||||
{
|
||||
if (inputShape[i] != 1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
CV__DNN_EXPERIMENTAL_NS_END
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ CV_EXPORTS_W void resetMyriadDevice();
|
||||
#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2 "Myriad2"
|
||||
/// Intel(R) Neural Compute Stick 2, NCS2 (USB 03e7:2485), MyriadX (https://software.intel.com/ru-ru/neural-compute-stick)
|
||||
#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X "MyriadX"
|
||||
#define CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE "ARM_COMPUTE"
|
||||
#define CV_DNN_INFERENCE_ENGINE_CPU_TYPE_X86 "X86"
|
||||
|
||||
|
||||
/** @brief Returns Inference Engine VPU type.
|
||||
@@ -57,6 +59,11 @@ CV_EXPORTS_W void resetMyriadDevice();
|
||||
*/
|
||||
CV_EXPORTS_W cv::String getInferenceEngineVPUType();
|
||||
|
||||
/** @brief Returns Inference Engine CPU type.
|
||||
*
|
||||
* Specify OpenVINO plugin: CPU or ARM.
|
||||
*/
|
||||
CV_EXPORTS_W cv::String getInferenceEngineCPUType();
|
||||
|
||||
CV__DNN_EXPERIMENTAL_NS_END
|
||||
}} // namespace
|
||||
|
||||
@@ -558,6 +558,29 @@ namespace cv {
|
||||
fused_layer_names.push_back(last_layer);
|
||||
}
|
||||
|
||||
void setSAM(int from)
|
||||
{
|
||||
cv::dnn::LayerParams eltwise_param;
|
||||
eltwise_param.name = "SAM-name";
|
||||
eltwise_param.type = "Eltwise";
|
||||
|
||||
eltwise_param.set<std::string>("operation", "prod");
|
||||
eltwise_param.set<std::string>("output_channels_mode", "same");
|
||||
|
||||
darknet::LayerParameter lp;
|
||||
std::string layer_name = cv::format("sam_%d", layer_id);
|
||||
lp.layer_name = layer_name;
|
||||
lp.layer_type = eltwise_param.type;
|
||||
lp.layerParams = eltwise_param;
|
||||
lp.bottom_indexes.push_back(last_layer);
|
||||
lp.bottom_indexes.push_back(fused_layer_names.at(from));
|
||||
last_layer = layer_name;
|
||||
net->layers.push_back(lp);
|
||||
|
||||
layer_id++;
|
||||
fused_layer_names.push_back(last_layer);
|
||||
}
|
||||
|
||||
void setUpsample(int scaleFactor)
|
||||
{
|
||||
cv::dnn::LayerParams param;
|
||||
@@ -837,6 +860,14 @@ namespace cv {
|
||||
from = from < 0 ? from + layers_counter : from;
|
||||
setParams.setScaleChannels(from);
|
||||
}
|
||||
else if (layer_type == "sam")
|
||||
{
|
||||
std::string bottom_layer = getParam<std::string>(layer_params, "from", "");
|
||||
CV_Assert(!bottom_layer.empty());
|
||||
int from = std::atoi(bottom_layer.c_str());
|
||||
from = from < 0 ? from + layers_counter : from;
|
||||
setParams.setSAM(from);
|
||||
}
|
||||
else if (layer_type == "upsample")
|
||||
{
|
||||
int scaleFactor = getParam<int>(layer_params, "stride", 1);
|
||||
|
||||
@@ -1286,17 +1286,19 @@ struct Net::Impl : public detail::NetImplBase
|
||||
CV_Assert(preferableBackend != DNN_BACKEND_HALIDE ||
|
||||
preferableTarget == DNN_TARGET_CPU ||
|
||||
preferableTarget == DNN_TARGET_OPENCL);
|
||||
#ifdef HAVE_INF_ENGINE
|
||||
if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 ||
|
||||
preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
{
|
||||
CV_Assert(
|
||||
preferableTarget == DNN_TARGET_CPU ||
|
||||
(preferableTarget == DNN_TARGET_CPU && (!isArmComputePlugin() || preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)) ||
|
||||
preferableTarget == DNN_TARGET_OPENCL ||
|
||||
preferableTarget == DNN_TARGET_OPENCL_FP16 ||
|
||||
preferableTarget == DNN_TARGET_MYRIAD ||
|
||||
preferableTarget == DNN_TARGET_FPGA
|
||||
);
|
||||
}
|
||||
#endif
|
||||
if (!netWasAllocated || this->blobsToKeep != blobsToKeep_)
|
||||
{
|
||||
if (preferableBackend == DNN_BACKEND_OPENCV && IS_DNN_OPENCL_TARGET(preferableTarget))
|
||||
@@ -1972,8 +1974,8 @@ struct Net::Impl : public detail::NetImplBase
|
||||
return;
|
||||
}
|
||||
|
||||
bool supportsCPUFallback = preferableTarget == DNN_TARGET_CPU ||
|
||||
BackendRegistry::checkIETarget(DNN_TARGET_CPU);
|
||||
bool supportsCPUFallback = !isArmComputePlugin() && (preferableTarget == DNN_TARGET_CPU ||
|
||||
BackendRegistry::checkIETarget(DNN_TARGET_CPU));
|
||||
|
||||
// Build Inference Engine networks from sets of layers that support this
|
||||
// backend. Split a whole model on several Inference Engine networks if
|
||||
|
||||
@@ -769,8 +769,14 @@ static InferenceEngine::Layout estimateLayout(const Mat& m)
|
||||
{
|
||||
if (m.dims == 4)
|
||||
return InferenceEngine::Layout::NCHW;
|
||||
else if (m.dims == 3)
|
||||
return InferenceEngine::Layout::CHW;
|
||||
else if (m.dims == 2)
|
||||
return InferenceEngine::Layout::NC;
|
||||
else if (m.dims == 1)
|
||||
return InferenceEngine::Layout::C;
|
||||
else if (m.dims == 5)
|
||||
return InferenceEngine::Layout::NCDHW;
|
||||
else
|
||||
return InferenceEngine::Layout::ANY;
|
||||
}
|
||||
|
||||
@@ -382,7 +382,11 @@ public:
|
||||
shape[1] = weights_.total();
|
||||
auto weight = std::make_shared<ngraph::op::Constant>(ngraph::element::f32, ngraph::Shape(shape), weights_.data);
|
||||
auto bias = std::make_shared<ngraph::op::Constant>(ngraph::element::f32, ngraph::Shape(shape), bias_.data);
|
||||
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2021_2)
|
||||
auto scale_node = std::make_shared<ngraph::op::v1::Multiply>(ieInpNode, weight, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
#else
|
||||
auto scale_node = std::make_shared<ngraph::op::v0::Multiply>(ieInpNode, weight, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
#endif
|
||||
auto scale_shift = std::make_shared<ngraph::op::v1::Add>(scale_node, bias, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
return Ptr<BackendNode>(new InfEngineNgraphNode(scale_shift));
|
||||
}
|
||||
|
||||
@@ -273,10 +273,13 @@ public:
|
||||
#ifdef HAVE_INF_ENGINE
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
{
|
||||
if (ksize == 1)
|
||||
bool isArmTarget = preferableTarget == DNN_TARGET_CPU && isArmComputePlugin();
|
||||
if (isArmTarget && blobs.empty())
|
||||
return false;
|
||||
if (ksize == 1)
|
||||
return isArmTarget;
|
||||
if (ksize == 3)
|
||||
return preferableTarget == DNN_TARGET_CPU;
|
||||
return preferableTarget != DNN_TARGET_MYRIAD && !isArmTarget;
|
||||
if ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || preferableTarget != DNN_TARGET_MYRIAD) && blobs.empty())
|
||||
return false;
|
||||
return (preferableTarget != DNN_TARGET_MYRIAD || dilation.width == dilation.height);
|
||||
@@ -578,7 +581,7 @@ public:
|
||||
CV_Assert_N(inputs.size() >= 1, nodes.size() >= 1);
|
||||
auto& ieInpNode = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
|
||||
std::vector<size_t> dims = ieInpNode->get_shape();
|
||||
CV_Assert(dims.size() == 4 || dims.size() == 5);
|
||||
CV_Check(dims.size(), dims.size() >= 3 && dims.size() <= 5, "");
|
||||
std::shared_ptr<ngraph::Node> ieWeights = nodes.size() > 1 ? nodes[1].dynamicCast<InfEngineNgraphNode>()->node : nullptr;
|
||||
if (nodes.size() > 1)
|
||||
CV_Assert(ieWeights); // dynamic_cast should not fail
|
||||
@@ -616,7 +619,7 @@ public:
|
||||
else
|
||||
{
|
||||
auto shape = std::make_shared<ngraph::op::Constant>(ngraph::element::i64,
|
||||
ngraph::Shape{kernel_shape.size()}, kernel_shape.data());
|
||||
ngraph::Shape{kernel_shape.size()}, std::vector<int64_t>(kernel_shape.begin(), kernel_shape.end()));
|
||||
ieWeights = std::make_shared<ngraph::op::v1::Reshape>(ieWeights, shape, true);
|
||||
}
|
||||
|
||||
@@ -651,7 +654,7 @@ public:
|
||||
if (nodes.size() == 3)
|
||||
{
|
||||
auto bias_shape = std::make_shared<ngraph::op::Constant>(ngraph::element::i64,
|
||||
ngraph::Shape{shape.size()}, shape.data());
|
||||
ngraph::Shape{shape.size()}, std::vector<int64_t>(shape.begin(), shape.end()));
|
||||
bias = std::make_shared<ngraph::op::v1::Reshape>(nodes[2].dynamicCast<InfEngineNgraphNode>()->node, bias_shape, true);
|
||||
}
|
||||
else
|
||||
@@ -1020,7 +1023,7 @@ public:
|
||||
v20*vw20 + v21*vw21 + v22*vw22 + vbias;
|
||||
if (relu)
|
||||
vout = v_select(vout > z, vout, vout*vrc);
|
||||
vx_store(outptr + out_j, vout);
|
||||
v_store(outptr + out_j, vout);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -133,6 +133,12 @@ public:
|
||||
|
||||
typedef std::map<int, std::vector<util::NormalizedBBox> > LabelBBox;
|
||||
|
||||
inline int getNumOfTargetClasses() {
|
||||
unsigned numBackground =
|
||||
(_backgroundLabelId >= 0 && _backgroundLabelId < _numClasses) ? 1 : 0;
|
||||
return (_numClasses - numBackground);
|
||||
}
|
||||
|
||||
bool getParameterDict(const LayerParams ¶ms,
|
||||
const std::string ¶meterName,
|
||||
DictValue& result)
|
||||
@@ -584,12 +590,13 @@ public:
|
||||
LabelBBox::const_iterator label_bboxes = decodeBBoxes.find(label);
|
||||
if (label_bboxes == decodeBBoxes.end())
|
||||
CV_Error_(cv::Error::StsError, ("Could not find location predictions for label %d", label));
|
||||
int limit = (getNumOfTargetClasses() == 1) ? _keepTopK : std::numeric_limits<int>::max();
|
||||
if (_bboxesNormalized)
|
||||
NMSFast_(label_bboxes->second, scores, _confidenceThreshold, _nmsThreshold, 1.0, _topK,
|
||||
indices[c], util::caffe_norm_box_overlap);
|
||||
indices[c], util::caffe_norm_box_overlap, limit);
|
||||
else
|
||||
NMSFast_(label_bboxes->second, scores, _confidenceThreshold, _nmsThreshold, 1.0, _topK,
|
||||
indices[c], util::caffe_box_overlap);
|
||||
indices[c], util::caffe_box_overlap, limit);
|
||||
numDetections += indices[c].size();
|
||||
}
|
||||
if (_keepTopK > -1 && numDetections > (size_t)_keepTopK)
|
||||
|
||||
@@ -1164,11 +1164,15 @@ struct PowerFunctor : public BaseFunctor
|
||||
ngraph::Shape{1}, &scale);
|
||||
auto shift_node = std::make_shared<ngraph::op::Constant>(ngraph::element::f32,
|
||||
ngraph::Shape{1}, &shift);
|
||||
auto power_node = std::make_shared<ngraph::op::Constant>(ngraph::element::f32,
|
||||
ngraph::Shape{1}, &power);
|
||||
|
||||
auto mul = std::make_shared<ngraph::op::v1::Multiply>(scale_node, node, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
auto scale_shift = std::make_shared<ngraph::op::v1::Add>(mul, shift_node, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
|
||||
if (power == 1)
|
||||
return scale_shift;
|
||||
|
||||
auto power_node = std::make_shared<ngraph::op::Constant>(ngraph::element::f32,
|
||||
ngraph::Shape{1}, &power);
|
||||
return std::make_shared<ngraph::op::v1::Power>(scale_shift, power_node, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
}
|
||||
#endif // HAVE_DNN_NGRAPH
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "../op_halide.hpp"
|
||||
#include "../op_inf_engine.hpp"
|
||||
#include "../ie_ngraph.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
#include "opencl_kernels_dnn.hpp"
|
||||
@@ -90,6 +91,7 @@ public:
|
||||
: outputChannels(0)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
hasVecInput = false;
|
||||
op = SUM;
|
||||
if (params.has("operation"))
|
||||
{
|
||||
@@ -149,6 +151,9 @@ public:
|
||||
|
||||
virtual bool supportBackend(int backendId) CV_OVERRIDE
|
||||
{
|
||||
if (hasVecInput && ELTWISE_CHANNNELS_SAME)
|
||||
return backendId == DNN_BACKEND_OPENCV;
|
||||
|
||||
return backendId == DNN_BACKEND_OPENCV ||
|
||||
backendId == DNN_BACKEND_HALIDE ||
|
||||
((((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (preferableTarget != DNN_TARGET_OPENCL || coeffs.empty()))
|
||||
@@ -197,9 +202,6 @@ public:
|
||||
{
|
||||
CV_Assert(0 && "Internal error");
|
||||
}
|
||||
|
||||
for (size_t j = 2; j < dims; j++)
|
||||
CV_Assert(inputs[0][j] == inputs[i][j]);
|
||||
}
|
||||
|
||||
channelsMode = variableChannels ? channelsModeInput : ELTWISE_CHANNNELS_SAME;
|
||||
@@ -207,9 +209,56 @@ public:
|
||||
|
||||
outputs.assign(1, inputs[0]);
|
||||
outputs[0][1] = numChannels;
|
||||
|
||||
if (dims > 2)
|
||||
{
|
||||
size_t vecIdx = 0;
|
||||
bool isVecFound = false;
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
bool allOnes = isAllOnes(inputs[i], 2, dims);
|
||||
if (!allOnes && !isVecFound)
|
||||
{
|
||||
vecIdx = i;
|
||||
isVecFound = true;
|
||||
}
|
||||
|
||||
if (!allOnes && i != vecIdx)
|
||||
{
|
||||
for (size_t j = 2; j < dims; j++)
|
||||
{
|
||||
CV_Assert(inputs[vecIdx][j] == inputs[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (channelsModeInput == ELTWISE_CHANNNELS_SAME && isVecFound)
|
||||
{
|
||||
for (size_t j = 2; j < dims; j++)
|
||||
{
|
||||
outputs[0][j] = inputs[vecIdx][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays) CV_OVERRIDE
|
||||
{
|
||||
std::vector<Mat> inputs;
|
||||
inputs_arr.getMatVector(inputs);
|
||||
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
MatShape inpShape = shape(inputs[i].size);
|
||||
if (isAllOnes(inpShape, 2, inputs[i].dims))
|
||||
{
|
||||
hasVecInput = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EltwiseInvoker : public ParallelLoopBody
|
||||
{
|
||||
@@ -502,6 +551,9 @@ public:
|
||||
if ((inputs_.depth() == CV_16S && op != SUM) || (channelsMode != ELTWISE_CHANNNELS_SAME))
|
||||
return false;
|
||||
|
||||
if (hasVecInput)
|
||||
return false; // TODO not implemented yet: https://github.com/opencv/opencv/pull/19477
|
||||
|
||||
inputs_.getUMatVector(inputs);
|
||||
outputs_.getUMatVector(outputs);
|
||||
|
||||
@@ -602,6 +654,47 @@ public:
|
||||
|
||||
CV_Assert(outputs.size() == 1);
|
||||
const int nstripes = getNumThreads();
|
||||
|
||||
if (channelsModeInput == ELTWISE_CHANNNELS_SAME && inputs[0].dims > 2)
|
||||
{
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
MatShape inpShape = shape(inputs[i].size);
|
||||
bool allOnes = isAllOnes(inpShape, 2, inputs[i].dims);
|
||||
|
||||
if (allOnes)
|
||||
{
|
||||
Mat tmpInput = inputs[i];
|
||||
MatShape outShape = shape(outputs[0].size);
|
||||
size_t xSize = outShape[2];
|
||||
for (size_t j = 3; j < outShape.size(); j++)
|
||||
xSize *= outShape[j];
|
||||
|
||||
int dimVec[3] = {outShape[0], outShape[1], (int) xSize};
|
||||
std::vector<int> matSizesVec(&dimVec[0], &dimVec[0] + 3);
|
||||
inputs[i] = Mat(matSizesVec, tmpInput.type());
|
||||
|
||||
std::vector<int> idx(outShape.size(), 0);
|
||||
std::vector<int> outIdx(inpShape.size(), 0);
|
||||
|
||||
for (size_t j = 0; j < outShape[0]; j++)
|
||||
{
|
||||
outIdx[0] = idx[0] = j;
|
||||
for(size_t k = 0; k < outShape[1]; k++)
|
||||
{
|
||||
outIdx[1] = idx[1] = k;
|
||||
for (size_t x = 0; x < xSize; x++)
|
||||
{
|
||||
outIdx[2] = x;
|
||||
inputs[i].at<float>(outIdx.data()) = tmpInput.at<float>(idx.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
inputs[i] = inputs[i].reshape(0, outShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EltwiseInvoker::run(*this,
|
||||
&inputs[0], (int)inputs.size(), outputs[0],
|
||||
nstripes);
|
||||
@@ -739,6 +832,9 @@ public:
|
||||
}
|
||||
|
||||
Ptr<ActivationLayer> activ;
|
||||
|
||||
private:
|
||||
bool hasVecInput;
|
||||
};
|
||||
|
||||
Ptr<EltwiseLayer> EltwiseLayer::create(const LayerParams& params)
|
||||
|
||||
@@ -394,7 +394,15 @@ public:
|
||||
const std::vector<Ptr<BackendNode> >& nodes) CV_OVERRIDE
|
||||
{
|
||||
auto& ieInpNode = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
|
||||
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2021_2)
|
||||
auto mvn = std::make_shared<ngraph::op::MVN>(ieInpNode, acrossChannels, normVariance, eps);
|
||||
#else
|
||||
int64_t start_axis = acrossChannels ? 1 : 2;
|
||||
std::vector<int64_t> axes_v(ieInpNode->get_shape().size() - start_axis);
|
||||
std::iota(axes_v.begin(), axes_v.end(), start_axis);
|
||||
auto axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{axes_v.size()}, axes_v.data());
|
||||
auto mvn = std::make_shared<ngraph::op::v6::MVN>(ieInpNode, axes, normVariance, eps, ngraph::op::MVNEpsMode::INSIDE_SQRT);
|
||||
#endif
|
||||
return Ptr<BackendNode>(new InfEngineNgraphNode(mvn));
|
||||
}
|
||||
#endif // HAVE_DNN_NGRAPH
|
||||
|
||||
@@ -324,8 +324,8 @@ public:
|
||||
if (!acrossSpatial) {
|
||||
axes_data.push_back(1);
|
||||
} else {
|
||||
axes_data.resize(ieInpNode->get_shape().size());
|
||||
std::iota(axes_data.begin(), axes_data.end(), 0);
|
||||
axes_data.resize(ieInpNode->get_shape().size() - 1);
|
||||
std::iota(axes_data.begin(), axes_data.end(), 1);
|
||||
}
|
||||
auto axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{axes_data.size()}, axes_data);
|
||||
auto norm = std::make_shared<ngraph::op::NormalizeL2>(ieInpNode, axes, epsilon, ngraph::op::EpsMode::ADD);
|
||||
@@ -334,19 +334,18 @@ public:
|
||||
std::vector<size_t> shape(ieInpNode->get_shape().size(), 1);
|
||||
shape[0] = blobs.empty() ? 1 : batch;
|
||||
shape[1] = numChannels;
|
||||
std::shared_ptr<ngraph::op::Constant> weight;
|
||||
if (blobs.empty())
|
||||
if (!blobs.empty())
|
||||
{
|
||||
std::vector<float> ones(numChannels, 1);
|
||||
weight = std::make_shared<ngraph::op::Constant>(ngraph::element::f32, ngraph::Shape(shape), ones.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
weight = std::make_shared<ngraph::op::Constant>(
|
||||
auto weight = std::make_shared<ngraph::op::Constant>(
|
||||
ngraph::element::f32, ngraph::Shape(shape), blobs[0].data);
|
||||
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2021_2)
|
||||
auto mul = std::make_shared<ngraph::op::v1::Multiply>(norm, weight, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
#else
|
||||
auto mul = std::make_shared<ngraph::op::v0::Multiply>(norm, weight, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
#endif
|
||||
return Ptr<BackendNode>(new InfEngineNgraphNode(mul));
|
||||
}
|
||||
auto mul = std::make_shared<ngraph::op::v0::Multiply>(norm, weight, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
return Ptr<BackendNode>(new InfEngineNgraphNode(mul));
|
||||
return Ptr<BackendNode>(new InfEngineNgraphNode(norm));
|
||||
}
|
||||
#endif // HAVE_DNN_NGRAPH
|
||||
|
||||
|
||||
@@ -97,9 +97,12 @@ public:
|
||||
{
|
||||
#ifdef HAVE_INF_ENGINE
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
return INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R1) &&
|
||||
(preferableTarget != DNN_TARGET_MYRIAD ||
|
||||
(dstRanges.size() == 4 && paddings[0].first == 0 && paddings[0].second == 0));
|
||||
{
|
||||
if (INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R1) && preferableTarget == DNN_TARGET_MYRIAD)
|
||||
return dstRanges.size() == 4 && paddings[0].first == 0 && paddings[0].second == 0;
|
||||
|
||||
return (dstRanges.size() <= 4 || !isArmComputePlugin());
|
||||
}
|
||||
#endif
|
||||
return backendId == DNN_BACKEND_OPENCV ||
|
||||
(backendId == DNN_BACKEND_HALIDE && haveHalide() && dstRanges.size() == 4);
|
||||
|
||||
@@ -105,6 +105,10 @@ public:
|
||||
|
||||
virtual bool supportBackend(int backendId) CV_OVERRIDE
|
||||
{
|
||||
#ifdef HAVE_INF_ENGINE
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && preferableTarget == DNN_TARGET_CPU)
|
||||
return _order.size() <= 4 || !isArmComputePlugin();
|
||||
#endif
|
||||
return backendId == DNN_BACKEND_OPENCV ||
|
||||
((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine());
|
||||
}
|
||||
|
||||
@@ -205,7 +205,9 @@ public:
|
||||
#endif
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
{
|
||||
return !computeMaxIdx && type != STOCHASTIC && kernel_size.size() > 1;
|
||||
#ifdef HAVE_DNN_NGRAPH
|
||||
return !computeMaxIdx && type != STOCHASTIC && kernel_size.size() > 1 && (kernel_size.size() != 3 || !isArmComputePlugin());
|
||||
#endif
|
||||
}
|
||||
else if (backendId == DNN_BACKEND_OPENCV)
|
||||
{
|
||||
|
||||
@@ -393,8 +393,10 @@ public:
|
||||
std::vector<int64_t> mask(anchors, 1);
|
||||
region = std::make_shared<ngraph::op::RegionYolo>(tr_input, coords, classes, anchors, useSoftmax, mask, 1, 3, anchors_vec);
|
||||
|
||||
auto tr_shape = tr_input->get_shape();
|
||||
auto shape_as_inp = std::make_shared<ngraph::op::Constant>(ngraph::element::i64,
|
||||
ngraph::Shape{tr_input->get_shape().size()}, tr_input->get_shape().data());
|
||||
ngraph::Shape{tr_shape.size()},
|
||||
std::vector<int64_t>(tr_shape.begin(), tr_shape.end()));
|
||||
|
||||
region = std::make_shared<ngraph::op::v1::Reshape>(region, shape_as_inp, true);
|
||||
new_axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{4}, std::vector<int64_t>{0, 2, 3, 1});
|
||||
@@ -540,7 +542,7 @@ public:
|
||||
result = std::make_shared<ngraph::op::Transpose>(result, tr_axes);
|
||||
if (b > 1)
|
||||
{
|
||||
std::vector<size_t> sizes = {(size_t)b, result->get_shape()[0] / b, result->get_shape()[1]};
|
||||
std::vector<int64_t> sizes{b, static_cast<int64_t>(result->get_shape()[0]) / b, static_cast<int64_t>(result->get_shape()[1])};
|
||||
auto shape_node = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{sizes.size()}, sizes.data());
|
||||
result = std::make_shared<ngraph::op::v1::Reshape>(result, shape_node, true);
|
||||
}
|
||||
|
||||
@@ -257,6 +257,7 @@ public:
|
||||
{
|
||||
auto& ieInpNode = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
|
||||
|
||||
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2021_2)
|
||||
ngraph::op::InterpolateAttrs attrs;
|
||||
attrs.pads_begin.push_back(0);
|
||||
attrs.pads_end.push_back(0);
|
||||
@@ -275,6 +276,37 @@ public:
|
||||
std::vector<int64_t> shape = {outHeight, outWidth};
|
||||
auto out_shape = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{2}, shape.data());
|
||||
auto interp = std::make_shared<ngraph::op::Interpolate>(ieInpNode, out_shape, attrs);
|
||||
#else
|
||||
ngraph::op::v4::Interpolate::InterpolateAttrs attrs;
|
||||
|
||||
if (interpolation == "nearest") {
|
||||
attrs.mode = ngraph::op::v4::Interpolate::InterpolateMode::nearest;
|
||||
attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::half_pixel;
|
||||
} else if (interpolation == "bilinear") {
|
||||
attrs.mode = ngraph::op::v4::Interpolate::InterpolateMode::linear_onnx;
|
||||
attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::asymmetric;
|
||||
} else {
|
||||
CV_Error(Error::StsNotImplemented, format("Unsupported interpolation: %s", interpolation.c_str()));
|
||||
}
|
||||
attrs.shape_calculation_mode = ngraph::op::v4::Interpolate::ShapeCalcMode::sizes;
|
||||
|
||||
if (alignCorners) {
|
||||
attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::align_corners;
|
||||
}
|
||||
|
||||
attrs.nearest_mode = ngraph::op::v4::Interpolate::NearestMode::round_prefer_floor;
|
||||
|
||||
std::vector<int64_t> shape = {outHeight, outWidth};
|
||||
auto out_shape = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{2}, shape.data());
|
||||
|
||||
auto& input_shape = ieInpNode->get_shape();
|
||||
CV_Assert_N(input_shape[2] != 0, input_shape[3] != 0);
|
||||
std::vector<float> scales = {static_cast<float>(outHeight) / input_shape[2], static_cast<float>(outWidth) / input_shape[3]};
|
||||
auto scales_shape = std::make_shared<ngraph::op::Constant>(ngraph::element::f32, ngraph::Shape{2}, scales.data());
|
||||
|
||||
auto axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{2}, std::vector<int64_t>{2, 3});
|
||||
auto interp = std::make_shared<ngraph::op::v4::Interpolate>(ieInpNode, out_shape, scales_shape, axes, attrs);
|
||||
#endif
|
||||
return Ptr<BackendNode>(new InfEngineNgraphNode(interp));
|
||||
}
|
||||
#endif // HAVE_DNN_NGRAPH
|
||||
|
||||
@@ -249,7 +249,11 @@ public:
|
||||
auto weight = blobs.empty() ? ieInpNode1 :
|
||||
std::make_shared<ngraph::op::Constant>(ngraph::element::f32, ngraph::Shape(shape), blobs[0].data);
|
||||
|
||||
node = std::make_shared<ngraph::op::v0::Multiply>(node, weight, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2021_2)
|
||||
node = std::make_shared<ngraph::op::v1::Multiply>(node, weight, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
#else
|
||||
node = std::make_shared<ngraph::op::v0::Multiply>(node, weight, ngraph::op::AutoBroadcastType::NUMPY);
|
||||
#endif
|
||||
}
|
||||
if (hasBias || !hasWeights)
|
||||
{
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
SliceLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
hasSteps = false;
|
||||
axis = params.get<int>("axis", 1);
|
||||
num_split = params.get<int>("num_split", 0);
|
||||
hasDynamicShapes = params.get<bool>("has_dynamic_shapes", false);
|
||||
@@ -112,6 +113,22 @@ public:
|
||||
sliceRanges[0][i].end = end; // We'll finalize a negative value later.
|
||||
}
|
||||
}
|
||||
|
||||
if (params.has("steps"))
|
||||
{
|
||||
const DictValue &steps = params.get("steps");
|
||||
sliceSteps.resize(1);
|
||||
sliceSteps[0].resize(steps.size());
|
||||
|
||||
for (int i = 0; i < steps.size(); ++i)
|
||||
{
|
||||
int step = steps.get<int>(i);
|
||||
CV_Assert(step >= 1);
|
||||
if (step > 1)
|
||||
hasSteps = true;
|
||||
sliceSteps[0][i] = step;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,11 +137,11 @@ public:
|
||||
#ifdef HAVE_DNN_IE_NN_BUILDER_2019
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
return INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R1) &&
|
||||
sliceRanges.size() == 1 && sliceRanges[0].size() == 4;
|
||||
sliceRanges.size() == 1 && sliceRanges[0].size() == 4 && !hasSteps;
|
||||
#endif
|
||||
#ifdef HAVE_DNN_NGRAPH
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
return sliceRanges.size() == 1;
|
||||
return sliceRanges.size() == 1 && !hasSteps;
|
||||
#endif
|
||||
return backendId == DNN_BACKEND_OPENCV;
|
||||
}
|
||||
@@ -147,6 +164,9 @@ public:
|
||||
{
|
||||
if (shapesInitialized || inpShape[j] > 0)
|
||||
outputs[i][j] = normalize_axis_range(sliceRanges[i][j], inpShape[j]).size();
|
||||
|
||||
if (!sliceSteps.empty() && (i < sliceSteps.size()) && (j < sliceSteps[i].size()) && (sliceSteps[i][j] > 1))
|
||||
outputs[i][j] = (outputs[i][j] + sliceSteps[i][j] - 1) / sliceSteps[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,6 +201,7 @@ public:
|
||||
const MatSize& inpShape = inputs[0].size;
|
||||
|
||||
finalSliceRanges = sliceRanges;
|
||||
|
||||
if (sliceRanges.empty())
|
||||
{
|
||||
// Divide input blob on equal parts by axis.
|
||||
@@ -213,6 +234,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (!sliceSteps.empty() && sliceSteps[0].size() != inputs[0].dims)
|
||||
sliceSteps[0].resize(inputs[0].dims, 1);
|
||||
|
||||
#if 0
|
||||
std::cout << "DEBUG: DNN/Slice: " << outputs.size() << " inpShape=" << inpShape << std::endl;
|
||||
for (int i = 0; i < outputs.size(); ++i)
|
||||
@@ -420,6 +444,9 @@ public:
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
if (hasSteps)
|
||||
return false; // TODO not implemented yet: https://github.com/opencv/opencv/pull/19546
|
||||
|
||||
std::vector<UMat> inputs;
|
||||
std::vector<UMat> outputs;
|
||||
|
||||
@@ -478,9 +505,24 @@ public:
|
||||
|
||||
const Mat& inpMat = inputs[0];
|
||||
CV_Assert(outputs.size() == finalSliceRanges.size());
|
||||
for (size_t i = 0; i < outputs.size(); i++)
|
||||
|
||||
if (!hasSteps)
|
||||
{
|
||||
inpMat(finalSliceRanges[i]).copyTo(outputs[i]);
|
||||
for (size_t i = 0; i < outputs.size(); i++)
|
||||
{
|
||||
inpMat(finalSliceRanges[i]).copyTo(outputs[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int dimsNum = inpMat.dims;
|
||||
|
||||
for (size_t i = 0; i < outputs.size(); i++)
|
||||
{
|
||||
std::vector<int> inpIdx(dimsNum, 0);
|
||||
std::vector<int> outIdx(dimsNum, 0);
|
||||
getSliceRecursive(inpMat, inpIdx, finalSliceRanges[i], sliceSteps[i], 0, dimsNum, outputs[i], outIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,11 +612,42 @@ public:
|
||||
}
|
||||
#endif // HAVE_DNN_NGRAPH
|
||||
|
||||
private:
|
||||
void getSliceRecursive(const Mat &inpMat, std::vector<int> &inpIdx,
|
||||
const std::vector<Range> &sliceRanges,
|
||||
const std::vector<int> &sliceSteps, int dim, int dimsNum,
|
||||
Mat &outputs, std::vector<int> &outIdx)
|
||||
{
|
||||
int begin = sliceRanges[dim].start;
|
||||
int end = sliceRanges[dim].end;
|
||||
int step = !sliceSteps.empty() ? sliceSteps[dim] : 1;
|
||||
|
||||
const bool is32F = inpMat.depth() == CV_32F;
|
||||
|
||||
// TODO optimization is required (for 2D tail case at least)
|
||||
for (int k = begin, j = 0; k < end; k += step, j++)
|
||||
{
|
||||
inpIdx[dim] = k;
|
||||
outIdx[dim] = j;
|
||||
|
||||
if (dim + 1 < dimsNum)
|
||||
getSliceRecursive(inpMat, inpIdx, sliceRanges, sliceSteps, dim + 1, dimsNum, outputs, outIdx);
|
||||
else
|
||||
{
|
||||
if (is32F)
|
||||
outputs.at<float>(outIdx.data()) = inpMat.at<float>(inpIdx.data());
|
||||
else
|
||||
outputs.at<short>(outIdx.data()) = inpMat.at<short>(inpIdx.data()); // 16F emulation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
// The actual non-negative values determined from @p sliceRanges depends on input size.
|
||||
std::vector<std::vector<Range> > finalSliceRanges;
|
||||
bool hasDynamicShapes;
|
||||
bool shapesInitialized;
|
||||
bool hasSteps;
|
||||
};
|
||||
|
||||
class CropLayerImpl CV_FINAL : public SliceLayerImpl
|
||||
|
||||
@@ -62,12 +62,15 @@ inline void GetMaxScoreIndex(const std::vector<float>& scores, const float thres
|
||||
// score_threshold: a threshold used to filter detection results.
|
||||
// nms_threshold: a threshold used in non maximum suppression.
|
||||
// top_k: if not > 0, keep at most top_k picked indices.
|
||||
// limit: early terminate once the # of picked indices has reached it.
|
||||
// indices: the kept indices of bboxes after nms.
|
||||
template <typename BoxType>
|
||||
inline void NMSFast_(const std::vector<BoxType>& bboxes,
|
||||
const std::vector<float>& scores, const float score_threshold,
|
||||
const float nms_threshold, const float eta, const int top_k,
|
||||
std::vector<int>& indices, float (*computeOverlap)(const BoxType&, const BoxType&))
|
||||
std::vector<int>& indices,
|
||||
float (*computeOverlap)(const BoxType&, const BoxType&),
|
||||
int limit = std::numeric_limits<int>::max())
|
||||
{
|
||||
CV_Assert(bboxes.size() == scores.size());
|
||||
|
||||
@@ -86,8 +89,12 @@ inline void NMSFast_(const std::vector<BoxType>& bboxes,
|
||||
float overlap = computeOverlap(bboxes[idx], bboxes[kept_idx]);
|
||||
keep = overlap <= adaptive_threshold;
|
||||
}
|
||||
if (keep)
|
||||
if (keep) {
|
||||
indices.push_back(idx);
|
||||
if (indices.size() >= limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (keep && eta < 1 && adaptive_threshold > 0.5) {
|
||||
adaptive_threshold *= eta;
|
||||
}
|
||||
|
||||
@@ -112,14 +112,14 @@ ocl::Image2D ocl4dnnGEMMCopyBufferToImage(UMat buffer, int offset,
|
||||
global_copy[0] = padded_width;
|
||||
global_copy[1] = padded_height;
|
||||
|
||||
oclk_gemm_copy
|
||||
bool res = oclk_gemm_copy
|
||||
.args(
|
||||
ocl::KernelArg::PtrReadOnly(buffer),
|
||||
image, offset,
|
||||
width, height,
|
||||
ld)
|
||||
.run(2, global_copy, NULL, false);
|
||||
oclk_gemm_copy.run(2, global_copy, NULL, false);
|
||||
CV_Assert(res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -641,20 +641,11 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
int axis = 0;
|
||||
std::vector<int> begin;
|
||||
std::vector<int> end;
|
||||
std::vector<int> steps;
|
||||
int inp_size = node_proto.input_size();
|
||||
|
||||
if (inp_size == 1)
|
||||
{
|
||||
if (layerParams.has("steps"))
|
||||
{
|
||||
DictValue steps = layerParams.get("steps");
|
||||
for (int i = 0; i < steps.size(); ++i)
|
||||
{
|
||||
if (steps.get<int>(i) != 1)
|
||||
CV_Error(Error::StsNotImplemented,
|
||||
"Slice layer only supports steps = 1");
|
||||
}
|
||||
}
|
||||
if (layerParams.has("axes")) {
|
||||
DictValue axes = layerParams.get("axes");
|
||||
for (int i = 1; i < axes.size(); ++i) {
|
||||
@@ -677,7 +668,7 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
int finish = ends.get<int>(i);
|
||||
end.push_back((finish < 0) ? --finish : finish); // numpy doesn't include last dim
|
||||
}
|
||||
} else {
|
||||
} else { // inp_size > 1
|
||||
CV_Assert(inp_size >= 3);
|
||||
for (int i = 1; i < inp_size; i++) {
|
||||
CV_Assert(constBlobs.find(node_proto.input(i)) != constBlobs.end());
|
||||
@@ -711,6 +702,12 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
if (inp_size == 5) {
|
||||
CV_Assert(constBlobs.find(node_proto.input(4)) != constBlobs.end());
|
||||
Mat step_blob = getBlob(node_proto, 4);
|
||||
const int* steps_ptr = step_blob.ptr<int>();
|
||||
|
||||
if (axis > 0)
|
||||
steps.resize(axis, 1);
|
||||
|
||||
std::copy(steps_ptr, steps_ptr + step_blob.total(), std::back_inserter(steps));
|
||||
|
||||
// Very strange application for Slice op with tensor reversing.
|
||||
// We just workaround it for 2d constants.
|
||||
@@ -728,13 +725,15 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
return;
|
||||
}
|
||||
}
|
||||
CV_CheckEQ(countNonZero(step_blob != 1), 0, "Slice layer only supports steps = 1");
|
||||
}
|
||||
}
|
||||
layerParams.set("begin", DictValue::arrayInt(&begin[0], begin.size()));
|
||||
layerParams.set("end", DictValue::arrayInt(&end[0], end.size()));
|
||||
layerParams.set("axis", axis);
|
||||
|
||||
if (!steps.empty())
|
||||
layerParams.set("steps", DictValue::arrayInt(&steps[0], steps.size()));
|
||||
|
||||
if (constBlobs.find(node_proto.input(0)) != constBlobs.end())
|
||||
{
|
||||
Mat inp = getBlob(node_proto, 0);
|
||||
|
||||
@@ -651,6 +651,22 @@ InferenceEngine::Core& getCore(const std::string& id)
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool detectArmPlugin_()
|
||||
{
|
||||
InferenceEngine::Core& ie = getCore("CPU");
|
||||
const std::vector<std::string> devices = ie.GetAvailableDevices();
|
||||
for (std::vector<std::string>::const_iterator i = devices.begin(); i != devices.end(); ++i)
|
||||
{
|
||||
if (i->find("CPU") != std::string::npos)
|
||||
{
|
||||
const std::string name = ie.GetMetric(*i, METRIC_KEY(FULL_DEVICE_NAME)).as<std::string>();
|
||||
CV_LOG_INFO(NULL, "CPU plugin: " << name);
|
||||
return name.find("arm_compute::NEON") != std::string::npos;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT)
|
||||
static bool detectMyriadX_()
|
||||
{
|
||||
@@ -1162,6 +1178,12 @@ bool isMyriadX()
|
||||
return myriadX;
|
||||
}
|
||||
|
||||
bool isArmComputePlugin()
|
||||
{
|
||||
static bool armPlugin = getInferenceEngineCPUType() == CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE;
|
||||
return armPlugin;
|
||||
}
|
||||
|
||||
static std::string getInferenceEngineVPUType_()
|
||||
{
|
||||
static std::string param_vpu_type = utils::getConfigurationParameterString("OPENCV_DNN_IE_VPU_TYPE", "");
|
||||
@@ -1199,6 +1221,14 @@ cv::String getInferenceEngineVPUType()
|
||||
return vpu_type;
|
||||
}
|
||||
|
||||
cv::String getInferenceEngineCPUType()
|
||||
{
|
||||
static cv::String cpu_type = detectArmPlugin_() ?
|
||||
CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE :
|
||||
CV_DNN_INFERENCE_ENGINE_CPU_TYPE_X86;
|
||||
return cpu_type;
|
||||
}
|
||||
|
||||
#else // HAVE_INF_ENGINE
|
||||
|
||||
cv::String getInferenceEngineBackendType()
|
||||
@@ -1214,6 +1244,11 @@ cv::String getInferenceEngineVPUType()
|
||||
{
|
||||
CV_Error(Error::StsNotImplemented, "This OpenCV build doesn't include InferenceEngine support");
|
||||
}
|
||||
|
||||
cv::String getInferenceEngineCPUType()
|
||||
{
|
||||
CV_Error(Error::StsNotImplemented, "This OpenCV build doesn't include InferenceEngine support");
|
||||
}
|
||||
#endif // HAVE_INF_ENGINE
|
||||
|
||||
|
||||
|
||||
@@ -29,10 +29,11 @@
|
||||
#define INF_ENGINE_RELEASE_2020_4 2020040000
|
||||
#define INF_ENGINE_RELEASE_2021_1 2021010000
|
||||
#define INF_ENGINE_RELEASE_2021_2 2021020000
|
||||
#define INF_ENGINE_RELEASE_2021_3 2021030000
|
||||
|
||||
#ifndef INF_ENGINE_RELEASE
|
||||
#warning("IE version have not been provided via command-line. Using 2021.2 by default")
|
||||
#define INF_ENGINE_RELEASE INF_ENGINE_RELEASE_2021_2
|
||||
#warning("IE version have not been provided via command-line. Using 2021.3 by default")
|
||||
#define INF_ENGINE_RELEASE INF_ENGINE_RELEASE_2021_3
|
||||
#endif
|
||||
|
||||
#define INF_ENGINE_VER_MAJOR_GT(ver) (((INF_ENGINE_RELEASE) / 10000) > ((ver) / 10000))
|
||||
@@ -254,6 +255,8 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
|
||||
|
||||
bool isMyriadX();
|
||||
|
||||
bool isArmComputePlugin();
|
||||
|
||||
CV__DNN_EXPERIMENTAL_NS_END
|
||||
|
||||
InferenceEngine::Core& getCore(const std::string& id);
|
||||
|
||||
@@ -12,6 +12,7 @@ Implementation of Tensorflow models parser
|
||||
#include "../precomp.hpp"
|
||||
|
||||
#include <opencv2/core/utils/logger.defines.hpp>
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
#undef CV_LOG_STRIP_LEVEL
|
||||
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
@@ -295,6 +296,22 @@ DataLayout getDataLayout(
|
||||
return it != data_layouts.end() ? it->second : DATA_LAYOUT_UNKNOWN;
|
||||
}
|
||||
|
||||
static
|
||||
bool hasAllOnes(const Mat &inputs, int startPos, int endPos)
|
||||
{
|
||||
CV_CheckLE(inputs.dims, 2, "");
|
||||
CV_CheckGE(startPos, 0, "");
|
||||
CV_CheckLE(startPos, endPos, "");
|
||||
CV_CheckLT((size_t)endPos, inputs.total(), "");
|
||||
|
||||
for (int i = startPos; i < endPos; i++)
|
||||
{
|
||||
if (inputs.at<int>(i) != 1 && inputs.at<int>(i) != -1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void setStrides(LayerParams &layerParams, const tensorflow::NodeDef &layer)
|
||||
{
|
||||
if (hasLayerAttr(layer, "strides"))
|
||||
@@ -490,6 +507,9 @@ protected:
|
||||
std::map<String, Mat> sharedWeights;
|
||||
|
||||
std::map<String, int> layer_id;
|
||||
|
||||
private:
|
||||
void addPermuteLayer(const int* order, const std::string& permName, Pin& inpId);
|
||||
};
|
||||
|
||||
TFImporter::TFImporter(Net& net, const char *model, const char *config)
|
||||
@@ -895,6 +915,17 @@ void TFImporter::populateNet()
|
||||
CV_LOG_DEBUG(NULL, "DNN/TF: ===================== Import completed =====================");
|
||||
}
|
||||
|
||||
void TFImporter::addPermuteLayer(const int* order, const std::string& permName, Pin& inpId)
|
||||
{
|
||||
LayerParams permLP;
|
||||
permLP.set("order", DictValue::arrayInt<const int*>(order, 4));
|
||||
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);
|
||||
}
|
||||
|
||||
void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
|
||||
{
|
||||
tensorflow::NodeDef layer = layer_;
|
||||
@@ -1276,37 +1307,49 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
|
||||
if (value_id.find(layer.input(1)) != value_id.end())
|
||||
{
|
||||
Mat newShape = getTensorContent(getConstBlob(layer, value_id, 1));
|
||||
if (newShape.total() == 4)
|
||||
int newShapeSize = newShape.total();
|
||||
bool hasSwap = false;
|
||||
if (newShapeSize == 4 && hasAllOnes(newShape, 0, 2))
|
||||
{
|
||||
// NHWC->NCHW
|
||||
std::swap(*newShape.ptr<int32_t>(0, 2), *newShape.ptr<int32_t>(0, 3));
|
||||
std::swap(*newShape.ptr<int32_t>(0, 1), *newShape.ptr<int32_t>(0, 2));
|
||||
hasSwap = true;
|
||||
}
|
||||
if (inpLayout == DATA_LAYOUT_NHWC)
|
||||
{
|
||||
if (newShape.total() != 4 || newShape.at<int>(1) == 1)
|
||||
if (newShapeSize >= 2 || newShape.at<int>(1) == 1)
|
||||
{
|
||||
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);
|
||||
inpLayout = DATA_LAYOUT_NCHW;
|
||||
addPermuteLayer(order, name + "/nhwc", inpId);
|
||||
if (newShapeSize < 4)
|
||||
{
|
||||
inpLayout = DATA_LAYOUT_NCHW;
|
||||
}
|
||||
else
|
||||
{
|
||||
inpLayout = DATA_LAYOUT_NHWC;
|
||||
}
|
||||
}
|
||||
}
|
||||
layerParams.set("dim", DictValue::arrayInt<int*>(newShape.ptr<int>(), newShape.total()));
|
||||
layerParams.set("dim", DictValue::arrayInt<int*>(newShape.ptr<int>(), newShapeSize));
|
||||
|
||||
int id = dstNet.addLayer(name, "Reshape", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
// one input only
|
||||
connect(layer_id, dstNet, inpId, id, 0);
|
||||
data_layouts[name] = newShape.total() == 2 ? DATA_LAYOUT_PLANAR : inpLayout;
|
||||
inpId = Pin(name);
|
||||
|
||||
if ((inpLayout == DATA_LAYOUT_NHWC || inpLayout == DATA_LAYOUT_UNKNOWN || inpLayout == DATA_LAYOUT_PLANAR) &&
|
||||
newShapeSize == 4 && !hasSwap)
|
||||
{
|
||||
int order[] = {0, 3, 1, 2}; // Transform back to OpenCV's NCHW.
|
||||
addPermuteLayer(order, name + "/nchw", inpId);
|
||||
inpLayout = DATA_LAYOUT_NCHW;
|
||||
}
|
||||
|
||||
data_layouts[name] = newShapeSize == 2 ? DATA_LAYOUT_PLANAR : inpLayout;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1783,6 +1826,7 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
|
||||
{
|
||||
// Check if all the inputs have the same shape.
|
||||
bool equalInpShapes = true;
|
||||
bool isShapeOnes = false;
|
||||
MatShape outShape0;
|
||||
for (int ii = 0; ii < num_inputs && !netInputShapes.empty(); ii++)
|
||||
{
|
||||
@@ -1803,12 +1847,14 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
|
||||
else if (outShape != outShape0)
|
||||
{
|
||||
equalInpShapes = false;
|
||||
isShapeOnes = isAllOnes(outShape, 2, outShape.size()) ||
|
||||
isAllOnes(outShape0, 2, outShape0.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int id;
|
||||
if (equalInpShapes || netInputShapes.empty())
|
||||
if (equalInpShapes || netInputShapes.empty() || (!equalInpShapes && isShapeOnes))
|
||||
{
|
||||
layerParams.set("operation", type == "RealDiv" ? "div" : "prod");
|
||||
id = dstNet.addLayer(name, "Eltwise", layerParams);
|
||||
@@ -2314,12 +2360,9 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
|
||||
// To keep correct order after squeeze dims we first need to change layout from NCHW to 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, Pin(name), permId, 0);
|
||||
Pin inpId = Pin(name);
|
||||
addPermuteLayer(order, permName, inpId);
|
||||
|
||||
LayerParams squeezeLp;
|
||||
std::string squeezeName = name + "/squeeze";
|
||||
@@ -2331,6 +2374,38 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
|
||||
connect(layer_id, dstNet, Pin(permName), squeezeId, 0);
|
||||
}
|
||||
}
|
||||
else if (axis == 1)
|
||||
{
|
||||
int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC.
|
||||
Pin inpId = parsePin(layer.input(0));
|
||||
addPermuteLayer(order, name + "/nhwc", inpId);
|
||||
|
||||
layerParams.set("pool", type == "Mean" ? "ave" : "sum");
|
||||
layerParams.set("kernel_h", 1);
|
||||
layerParams.set("global_pooling_w", true);
|
||||
int id = dstNet.addLayer(name, "Pooling", layerParams);
|
||||
layer_id[name] = id;
|
||||
connect(layer_id, dstNet, inpId, id, 0);
|
||||
|
||||
if (!keepDims)
|
||||
{
|
||||
LayerParams squeezeLp;
|
||||
std::string squeezeName = name + "/squeeze";
|
||||
CV_Assert(layer_id.find(squeezeName) == layer_id.end());
|
||||
int channel_id = 3; // TF NHWC layout
|
||||
squeezeLp.set("axis", channel_id - 1);
|
||||
squeezeLp.set("end_axis", channel_id);
|
||||
int squeezeId = dstNet.addLayer(squeezeName, "Flatten", squeezeLp);
|
||||
layer_id[squeezeName] = squeezeId;
|
||||
connect(layer_id, dstNet, Pin(name), squeezeId, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int order[] = {0, 3, 1, 2}; // From NHWC to OpenCV's NCHW.
|
||||
Pin inpId = parsePin(name);
|
||||
addPermuteLayer(order, name + "/nchw", inpId);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (indices.total() != 2 || indices.at<int>(0) != 1 || indices.at<int>(1) != 2)
|
||||
CV_Error(Error::StsNotImplemented, "Unsupported mode of reduce_mean or reduce_sum operation.");
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_2019R1_1 "dnn_skip_ie_2019r1_1"
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_2019R2 "dnn_skip_ie_2019r2"
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_2019R3 "dnn_skip_ie_2019r3"
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_CPU "dnn_skip_ie_cpu"
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_OPENCL "dnn_skip_ie_ocl"
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16 "dnn_skip_ie_ocl_fp16"
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2 "dnn_skip_ie_myriad2"
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X "dnn_skip_ie_myriadx"
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_MYRIAD CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2, CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X
|
||||
#define CV_TEST_TAG_DNN_SKIP_IE_ARM_CPU "dnn_skip_ie_arm_cpu"
|
||||
|
||||
|
||||
#ifdef HAVE_INF_ENGINE
|
||||
|
||||
@@ -385,13 +385,13 @@ void initDNNTests()
|
||||
#ifdef HAVE_DNN_IE_NN_BUILDER_2019
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER,
|
||||
#endif
|
||||
""
|
||||
CV_TEST_TAG_DNN_SKIP_IE_CPU
|
||||
);
|
||||
#endif
|
||||
registerGlobalSkipTag(
|
||||
// see validateVPUType(): CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2, CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X
|
||||
CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -694,6 +694,10 @@ TEST_P(Test_Darknet_layers, shortcut)
|
||||
|
||||
TEST_P(Test_Darknet_layers, upsample)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
testDarknetLayer("upsample");
|
||||
}
|
||||
|
||||
@@ -770,6 +774,11 @@ TEST_P(Test_Darknet_layers, relu)
|
||||
testDarknetLayer("relu");
|
||||
}
|
||||
|
||||
TEST_P(Test_Darknet_layers, sam)
|
||||
{
|
||||
testDarknetLayer("sam", true);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_layers, dnnBackendsAndTargets());
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -16,7 +16,7 @@ using namespace cv;
|
||||
using namespace cv::dnn;
|
||||
using namespace testing;
|
||||
|
||||
static void test(Mat& input, Net& net, Backend backendId, Target targetId, bool skipCheck = false, bool randInput = true)
|
||||
static void test(Mat& input, Net& net, Backend backendId, Target targetId, bool skipCheck = false, bool randInput = true, double l1 = 0.0, double lInf = 0.0)
|
||||
{
|
||||
DNNTestLayer::checkBackend(backendId, targetId);
|
||||
if (randInput)
|
||||
@@ -33,8 +33,12 @@ static void test(Mat& input, Net& net, Backend backendId, Target targetId, bool
|
||||
if (skipCheck)
|
||||
return;
|
||||
|
||||
double l1, lInf;
|
||||
DNNTestLayer::getDefaultThresholds(backendId, targetId, &l1, &lInf);
|
||||
double default_l1, default_lInf;
|
||||
DNNTestLayer::getDefaultThresholds(backendId, targetId, &default_l1, &default_lInf);
|
||||
if (l1 == 0.0)
|
||||
l1 = default_l1;
|
||||
if (lInf == 0.0)
|
||||
lInf = default_lInf;
|
||||
#if 0
|
||||
std::cout << "l1=" << l1 << " lInf=" << lInf << std::endl;
|
||||
std::cout << outputDefault.reshape(1, outputDefault.total()).t() << std::endl;
|
||||
@@ -43,11 +47,11 @@ static void test(Mat& input, Net& net, Backend backendId, Target targetId, bool
|
||||
normAssert(outputDefault, outputHalide, "", l1, lInf);
|
||||
}
|
||||
|
||||
static void test(LayerParams& params, Mat& input, Backend backendId, Target targetId, bool skipCheck = false)
|
||||
static void test(LayerParams& params, Mat& input, Backend backendId, Target targetId, bool skipCheck = false, double l1 = 0.0, double lInf = 0.0)
|
||||
{
|
||||
Net net;
|
||||
net.addLayerToPrev(params.name, params.type, params);
|
||||
test(input, net, backendId, targetId, skipCheck);
|
||||
test(input, net, backendId, targetId, skipCheck, true, l1, lInf);
|
||||
}
|
||||
|
||||
static inline testing::internal::ParamGenerator<tuple<Backend, Target> > dnnBackendsAndTargetsWithHalide()
|
||||
@@ -251,7 +255,17 @@ TEST_P(LRN, Accuracy)
|
||||
|
||||
int sz[] = {1, inChannels, inSize.height, inSize.width};
|
||||
Mat input(4, &sz[0], CV_32F);
|
||||
test(lp, input, backendId, targetId);
|
||||
|
||||
double l1 = 0.0, lInf = 0.0;
|
||||
// The OpenCL kernels use the native_ math functions which have
|
||||
// implementation defined accuracy, so we use relaxed thresholds. See
|
||||
// https://github.com/opencv/opencv/issues/9821 for more details.
|
||||
if (targetId == DNN_TARGET_OPENCL)
|
||||
{
|
||||
l1 = 0.01;
|
||||
lInf = 0.01;
|
||||
}
|
||||
test(lp, input, backendId, targetId, false, l1, lInf);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, LRN, Combine(
|
||||
|
||||
@@ -169,8 +169,17 @@ TEST_P(Test_Caffe_layers, Softmax)
|
||||
|
||||
TEST_P(Test_Caffe_layers, LRN)
|
||||
{
|
||||
testLayerUsingCaffeModels("layer_lrn_spatial");
|
||||
testLayerUsingCaffeModels("layer_lrn_channels");
|
||||
double l1 = 0.0, lInf = 0.0;
|
||||
// The OpenCL kernels use the native_ math functions which have
|
||||
// implementation defined accuracy, so we use relaxed thresholds. See
|
||||
// https://github.com/opencv/opencv/issues/9821 for more details.
|
||||
if (target == DNN_TARGET_OPENCL)
|
||||
{
|
||||
l1 = 0.01;
|
||||
lInf = 0.01;
|
||||
}
|
||||
testLayerUsingCaffeModels("layer_lrn_spatial", false, true, l1, lInf);
|
||||
testLayerUsingCaffeModels("layer_lrn_channels", false, true, l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Convolution)
|
||||
@@ -1553,6 +1562,11 @@ TEST_P(Test_Caffe_layers, Interp)
|
||||
TEST_P(Test_Caffe_layers, DISABLED_Interp) // requires patched protobuf (available in OpenCV source tree only)
|
||||
#endif
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
|
||||
|
||||
|
||||
@@ -144,6 +144,10 @@ TEST_P(Test_ONNX_layers, Convolution_variable_weight_bias)
|
||||
backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU &&
|
||||
getInferenceEngineCPUType() == CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_ARM_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
String basename = "conv_variable_wb";
|
||||
Net net = readNetFromONNX(_tf("models/" + basename + ".onnx"));
|
||||
ASSERT_FALSE(net.empty());
|
||||
@@ -402,11 +406,19 @@ TEST_P(Test_ONNX_layers, BatchNormalization3D)
|
||||
|
||||
TEST_P(Test_ONNX_layers, BatchNormalizationUnfused)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
testONNXModels("frozenBatchNorm2d");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, BatchNormalizationSubgraph)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
testONNXModels("batch_norm_subgraph");
|
||||
}
|
||||
|
||||
@@ -615,6 +627,26 @@ TEST_P(Test_ONNX_layers, Slice)
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, Slice_Steps_2DInput)
|
||||
{
|
||||
testONNXModels("slice_opset_11_steps_2d");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, Slice_Steps_3DInput)
|
||||
{
|
||||
testONNXModels("slice_opset_11_steps_3d");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, Slice_Steps_4DInput)
|
||||
{
|
||||
testONNXModels("slice_opset_11_steps_4d");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, Slice_Steps_5DInput)
|
||||
{
|
||||
testONNXModels("slice_opset_11_steps_5d");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, Softmax)
|
||||
{
|
||||
testONNXModels("softmax");
|
||||
@@ -717,6 +749,8 @@ TEST_P(Test_ONNX_layers, Conv1d_variable_weight_bias)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
{
|
||||
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
if (target == DNN_TARGET_CPU && getInferenceEngineCPUType() == CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_ARM_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
}
|
||||
String basename = "conv1d_variable_wb";
|
||||
Net net = readNetFromONNX(_tf("models/" + basename + ".onnx"));
|
||||
@@ -740,6 +774,13 @@ TEST_P(Test_ONNX_layers, Conv1d_variable_weight_bias)
|
||||
|
||||
TEST_P(Test_ONNX_layers, GatherMultiOutput)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
|
||||
#if defined(INF_ENGINE_RELEASE)
|
||||
if (target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE);
|
||||
@@ -836,6 +877,7 @@ TEST_P(Test_ONNX_layers, PoolConv1d)
|
||||
|
||||
TEST_P(Test_ONNX_layers, ConvResizePool1d)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
{
|
||||
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
@@ -843,7 +885,12 @@ TEST_P(Test_ONNX_layers, ConvResizePool1d)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
{
|
||||
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
#if INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
testONNXModels("conv_resize_pool_1d");
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,16 @@ TEST_P(Test_TensorFlow_layers, reduce_sum)
|
||||
runTensorFlowNet("sum_pool_by_axis");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, reduce_sum_channel)
|
||||
{
|
||||
runTensorFlowNet("reduce_sum_channel");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, reduce_sum_channel_keep_dims)
|
||||
{
|
||||
runTensorFlowNet("reduce_sum_channel", false, 0.0, 0.0, false, "_keep_dims");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, conv_single_conv)
|
||||
{
|
||||
runTensorFlowNet("single_conv");
|
||||
@@ -205,6 +215,17 @@ TEST_P(Test_TensorFlow_layers, eltwise)
|
||||
runTensorFlowNet("eltwise_sub");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, eltwise_add_vec)
|
||||
{
|
||||
runTensorFlowNet("eltwise_add_vec");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, eltwise_mul_vec)
|
||||
{
|
||||
runTensorFlowNet("eltwise_mul_vec");
|
||||
}
|
||||
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, channel_broadcast)
|
||||
{
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
@@ -219,6 +240,12 @@ TEST_P(Test_TensorFlow_layers, pad_and_concat)
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, concat_axis_1)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
runTensorFlowNet("concat_axis_1");
|
||||
}
|
||||
|
||||
@@ -279,6 +306,10 @@ TEST_P(Test_TensorFlow_layers, batch_norm_10)
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_11)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // nan
|
||||
#endif
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
runTensorFlowNet("mvn_batch_norm_1x1");
|
||||
@@ -457,6 +488,21 @@ TEST_P(Test_TensorFlow_layers, unfused_flatten)
|
||||
runTensorFlowNet("unfused_flatten_unknown_batch");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, reshape_layer)
|
||||
{
|
||||
runTensorFlowNet("reshape_layer");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, reshape_nchw)
|
||||
{
|
||||
runTensorFlowNet("reshape_nchw");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, reshape_conv)
|
||||
{
|
||||
runTensorFlowNet("reshape_conv");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, leaky_relu)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000)
|
||||
@@ -992,12 +1038,20 @@ TEST_P(Test_TensorFlow_layers, keras_mobilenet_head)
|
||||
// TF case: align_corners=False, half_pixel_centers=False
|
||||
TEST_P(Test_TensorFlow_layers, resize_bilinear)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
runTensorFlowNet("resize_bilinear");
|
||||
}
|
||||
|
||||
// TF case: align_corners=True, half_pixel_centers=False
|
||||
TEST_P(Test_TensorFlow_layers, resize_bilinear_align_corners)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
runTensorFlowNet("resize_bilinear",
|
||||
false, 0.0, 0.0, false, // default parameters
|
||||
"_align_corners");
|
||||
|
||||
@@ -218,9 +218,21 @@ TEST_P(Test_Torch_layers, net_conv_gemm_lrn)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
runTorchNet("net_conv_gemm_lrn", "", false, true, true,
|
||||
target == DNN_TARGET_OPENCL_FP16 ? 0.046 : 0.0,
|
||||
target == DNN_TARGET_OPENCL_FP16 ? 0.023 : 0.0);
|
||||
double l1 = 0.0, lInf = 0.0;
|
||||
if (target == DNN_TARGET_OPENCL_FP16)
|
||||
{
|
||||
l1 = 0.046;
|
||||
lInf = 0.023;
|
||||
}
|
||||
// The OpenCL kernels use the native_ math functions which have
|
||||
// implementation defined accuracy, so we use relaxed thresholds. See
|
||||
// https://github.com/opencv/opencv/issues/9821 for more details.
|
||||
else if (target == DNN_TARGET_OPENCL)
|
||||
{
|
||||
l1 = 0.02;
|
||||
lInf = 0.02;
|
||||
}
|
||||
runTorchNet("net_conv_gemm_lrn", "", false, true, true, l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Torch_layers, net_inception_block)
|
||||
@@ -242,6 +254,15 @@ TEST_P(Test_Torch_layers, net_padding)
|
||||
|
||||
TEST_P(Test_Torch_layers, net_non_spatial)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // crash
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 &&
|
||||
(target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
@@ -537,6 +558,11 @@ private:
|
||||
|
||||
TEST_P(Test_Torch_layers, upsampling_nearest)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // TODO
|
||||
#endif
|
||||
|
||||
// Test a custom layer.
|
||||
CV_DNN_REGISTER_LAYER_CLASS(SpatialUpSamplingNearest, SpatialUpSamplingNearestLayer);
|
||||
try
|
||||
|
||||
@@ -468,8 +468,7 @@ article](http://en.wikipedia.org/wiki/Maximally_stable_extremal_regions)).
|
||||
than union-find method; it actually get 1.5~2m/s on my centrino L7200 1.2GHz laptop.
|
||||
|
||||
- the color image algorithm is taken from: @cite forssen2007maximally ; it should be much slower
|
||||
than grey image method ( 3~4 times ); the chi_table.h file is taken directly from paper's source
|
||||
code which is distributed under GPL.
|
||||
than grey image method ( 3~4 times )
|
||||
|
||||
- (Python) A complete example showing the use of the %MSER detector can be found at samples/python/mser.py
|
||||
*/
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
* it actually get 1.5~2m/s on my centrino L7200 1.2GHz laptop.
|
||||
* 3. the color image algorithm is taken from: Maximally Stable Colour Regions for Recognition and Match;
|
||||
* it should be much slower than gray image method ( 3~4 times );
|
||||
* the chi_table.h file is taken directly from paper's source code which is distributed under GPL.
|
||||
* the chi_table.h file is taken directly from paper's source code which is distributed under permissive BSD-like license: http://users.isy.liu.se/cvl/perfo/software/chi_table.h
|
||||
* 4. though the name is *contours*, the result actually is a list of point set.
|
||||
*/
|
||||
|
||||
|
||||
@@ -84,12 +84,13 @@ ExrDecoder::ExrDecoder()
|
||||
{
|
||||
m_signature = "\x76\x2f\x31\x01";
|
||||
m_file = 0;
|
||||
m_red = m_green = m_blue = 0;
|
||||
m_red = m_green = m_blue = m_alpha = 0;
|
||||
m_type = ((Imf::PixelType)0);
|
||||
m_iscolor = false;
|
||||
m_bit_depth = 0;
|
||||
m_isfloat = false;
|
||||
m_ischroma = false;
|
||||
m_hasalpha = false;
|
||||
m_native_depth = false;
|
||||
|
||||
}
|
||||
@@ -113,7 +114,7 @@ void ExrDecoder::close()
|
||||
|
||||
int ExrDecoder::type() const
|
||||
{
|
||||
return CV_MAKETYPE((m_isfloat ? CV_32F : CV_32S), m_iscolor ? 3 : 1);
|
||||
return CV_MAKETYPE((m_isfloat ? CV_32F : CV_32S), ((m_iscolor && m_hasalpha) ? 4 : m_iscolor ? 3 : m_hasalpha ? 2 : 1));
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +142,11 @@ bool ExrDecoder::readHeader()
|
||||
m_red = channels.findChannel( "R" );
|
||||
m_green = channels.findChannel( "G" );
|
||||
m_blue = channels.findChannel( "B" );
|
||||
m_alpha = channels.findChannel( "A" );
|
||||
|
||||
if( m_alpha ) // alpha channel supported in RGB, Y, and YC scenarios
|
||||
m_hasalpha = true;
|
||||
|
||||
if( m_red || m_green || m_blue )
|
||||
{
|
||||
m_iscolor = true;
|
||||
@@ -178,7 +184,8 @@ bool ExrDecoder::readHeader()
|
||||
bool ExrDecoder::readData( Mat& img )
|
||||
{
|
||||
m_native_depth = CV_MAT_DEPTH(type()) == img.depth();
|
||||
bool color = img.channels() > 1;
|
||||
bool color = img.channels() > 2; // output mat has 3+ channels; Y or YA are the 1 and 2 channel scenario
|
||||
bool alphasupported = ( img.channels() % 2 == 0 ); // even number of channels indicates alpha
|
||||
int channels = 0;
|
||||
uchar* data = img.ptr();
|
||||
size_t step = img.step;
|
||||
@@ -187,18 +194,22 @@ bool ExrDecoder::readData( Mat& img )
|
||||
bool rgbtogray = ( !m_ischroma && m_iscolor && !color );
|
||||
bool result = true;
|
||||
FrameBuffer frame;
|
||||
int xsample[3] = {1, 1, 1};
|
||||
const int defaultchannels = 3;
|
||||
int xsample[defaultchannels] = {1, 1, 1};
|
||||
char *buffer;
|
||||
size_t xstep = 0;
|
||||
CV_Assert(m_type == FLOAT);
|
||||
const size_t floatsize = sizeof(float);
|
||||
size_t xstep = m_native_depth ? floatsize : 1; // 4 bytes if native depth (FLOAT), otherwise converting to 1 byte U8 depth
|
||||
size_t ystep = 0;
|
||||
|
||||
xstep = m_native_depth ? 4 : 1;
|
||||
const int channelstoread = ( (m_iscolor && alphasupported) ? 4 :
|
||||
( (m_iscolor && !m_ischroma) || color) ? 3 : alphasupported ? 2 : 1 ); // number of channels to read may exceed channels in output img
|
||||
size_t xStride = floatsize * channelstoread;
|
||||
|
||||
AutoBuffer<char> copy_buffer;
|
||||
|
||||
if( !justcopy )
|
||||
{
|
||||
copy_buffer.allocate(sizeof(float) * m_width * 3);
|
||||
copy_buffer.allocate(floatsize * m_width * defaultchannels);
|
||||
buffer = copy_buffer.data();
|
||||
ystep = 0;
|
||||
}
|
||||
@@ -215,49 +226,49 @@ bool ExrDecoder::readData( Mat& img )
|
||||
if( m_blue )
|
||||
{
|
||||
frame.insert( "BY", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
|
||||
12, ystep, m_blue->xSampling, m_blue->ySampling, 0.0 ));
|
||||
xsample[0] = m_blue->ySampling;
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep,
|
||||
xStride, ystep, m_blue->xSampling, m_blue->ySampling, 0.0 ));
|
||||
xsample[0] = m_blue->xSampling;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.insert( "BY", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
|
||||
12, ystep, 1, 1, 0.0 ));
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep,
|
||||
xStride, ystep, 1, 1, 0.0 ));
|
||||
}
|
||||
if( m_green )
|
||||
{
|
||||
frame.insert( "Y", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
|
||||
12, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
|
||||
xsample[1] = m_green->ySampling;
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep + floatsize,
|
||||
xStride, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
|
||||
xsample[1] = m_green->xSampling;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.insert( "Y", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
|
||||
12, ystep, 1, 1, 0.0 ));
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep + floatsize,
|
||||
xStride, ystep, 1, 1, 0.0 ));
|
||||
}
|
||||
if( m_red )
|
||||
{
|
||||
frame.insert( "RY", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
|
||||
12, ystep, m_red->xSampling, m_red->ySampling, 0.0 ));
|
||||
xsample[2] = m_red->ySampling;
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep + (floatsize * 2),
|
||||
xStride, ystep, m_red->xSampling, m_red->ySampling, 0.0 ));
|
||||
xsample[2] = m_red->xSampling;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.insert( "RY", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
|
||||
12, ystep, 1, 1, 0.0 ));
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep + (floatsize * 2),
|
||||
xStride, ystep, 1, 1, 0.0 ));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.insert( "Y", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 4 - m_datawindow.min.y * ystep,
|
||||
4, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
|
||||
xsample[0] = m_green->ySampling;
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep,
|
||||
xStride, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
|
||||
xsample[0] = m_green->xSampling;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -265,67 +276,85 @@ bool ExrDecoder::readData( Mat& img )
|
||||
if( m_blue )
|
||||
{
|
||||
frame.insert( "B", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
|
||||
12, ystep, m_blue->xSampling, m_blue->ySampling, 0.0 ));
|
||||
xsample[0] = m_blue->ySampling;
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep,
|
||||
xStride, ystep, m_blue->xSampling, m_blue->ySampling, 0.0 ));
|
||||
xsample[0] = m_blue->xSampling;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.insert( "B", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
|
||||
12, ystep, 1, 1, 0.0 ));
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep,
|
||||
xStride, ystep, 1, 1, 0.0 ));
|
||||
}
|
||||
if( m_green )
|
||||
{
|
||||
frame.insert( "G", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
|
||||
12, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
|
||||
xsample[1] = m_green->ySampling;
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep + floatsize,
|
||||
xStride, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
|
||||
xsample[1] = m_green->xSampling;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.insert( "G", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
|
||||
12, ystep, 1, 1, 0.0 ));
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep + floatsize,
|
||||
xStride, ystep, 1, 1, 0.0 ));
|
||||
}
|
||||
if( m_red )
|
||||
{
|
||||
frame.insert( "R", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
|
||||
12, ystep, m_red->xSampling, m_red->ySampling, 0.0 ));
|
||||
xsample[2] = m_red->ySampling;
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep + (floatsize * 2),
|
||||
xStride, ystep, m_red->xSampling, m_red->ySampling, 0.0 ));
|
||||
xsample[2] = m_red->xSampling;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.insert( "R", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
|
||||
12, ystep, 1, 1, 0.0 ));
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep + (floatsize * 2),
|
||||
xStride, ystep, 1, 1, 0.0 ));
|
||||
}
|
||||
}
|
||||
|
||||
if( justcopy && m_hasalpha && alphasupported )
|
||||
{ // alpha preserved only in justcopy scenario where alpha is desired (alphasupported)
|
||||
// and present in original file (m_hasalpha)
|
||||
CV_Assert(channelstoread == img.channels());
|
||||
int offset = (channelstoread - 1) * floatsize;
|
||||
frame.insert( "A", Slice( m_type,
|
||||
buffer - m_datawindow.min.x * xStride - m_datawindow.min.y * ystep + offset,
|
||||
xStride, ystep, m_alpha->xSampling, m_alpha->ySampling, 0.0 ));
|
||||
}
|
||||
|
||||
for (FrameBuffer::Iterator it = frame.begin(); it != frame.end(); it++) {
|
||||
channels++;
|
||||
}
|
||||
|
||||
CV_Assert(channels == channelstoread);
|
||||
|
||||
if( (channels != channelstoread) || (!justcopy && channels > defaultchannels) )
|
||||
{ // safety checking what ought to be true here
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_file->setFrameBuffer( frame );
|
||||
if( justcopy )
|
||||
{
|
||||
m_file->readPixels( m_datawindow.min.y, m_datawindow.max.y );
|
||||
|
||||
if( color )
|
||||
if( m_iscolor )
|
||||
{
|
||||
if( m_blue && (m_blue->xSampling != 1 || m_blue->ySampling != 1) )
|
||||
UpSample( data, 3, step / xstep, xsample[0], m_blue->ySampling );
|
||||
UpSample( data, channelstoread, step / xstep, m_blue->xSampling, m_blue->ySampling );
|
||||
if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
|
||||
UpSample( data + xstep, 3, step / xstep, xsample[1], m_green->ySampling );
|
||||
UpSample( data + xstep, channelstoread, step / xstep, m_green->xSampling, m_green->ySampling );
|
||||
if( m_red && (m_red->xSampling != 1 || m_red->ySampling != 1) )
|
||||
UpSample( data + 2 * xstep, 3, step / xstep, xsample[2], m_red->ySampling );
|
||||
UpSample( data + 2 * xstep, channelstoread, step / xstep, m_red->xSampling, m_red->ySampling );
|
||||
}
|
||||
else if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
|
||||
UpSample( data, 1, step / xstep, xsample[0], m_green->ySampling );
|
||||
UpSample( data, channelstoread, step / xstep, m_green->xSampling, m_green->ySampling );
|
||||
|
||||
if( chromatorgb )
|
||||
ChromaToBGR( (float *)data, m_height, step / xstep );
|
||||
ChromaToBGR( (float *)data, m_height, channelstoread, step / xstep );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -347,7 +376,7 @@ bool ExrDecoder::readData( Mat& img )
|
||||
else
|
||||
{
|
||||
if( chromatorgb )
|
||||
ChromaToBGR( (float *)buffer, 1, step );
|
||||
ChromaToBGR( (float *)buffer, 1, defaultchannels, step );
|
||||
|
||||
if( m_type == FLOAT )
|
||||
{
|
||||
@@ -372,11 +401,11 @@ bool ExrDecoder::readData( Mat& img )
|
||||
if( color )
|
||||
{
|
||||
if( m_blue && (m_blue->xSampling != 1 || m_blue->ySampling != 1) )
|
||||
UpSampleY( data, 3, step / xstep, m_blue->ySampling );
|
||||
UpSampleY( data, defaultchannels, step / xstep, m_blue->ySampling );
|
||||
if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
|
||||
UpSampleY( data + xstep, 3, step / xstep, m_green->ySampling );
|
||||
UpSampleY( data + xstep, defaultchannels, step / xstep, m_green->ySampling );
|
||||
if( m_red && (m_red->xSampling != 1 || m_red->ySampling != 1) )
|
||||
UpSampleY( data + 2 * xstep, 3, step / xstep, m_red->ySampling );
|
||||
UpSampleY( data + 2 * xstep, defaultchannels, step / xstep, m_red->ySampling );
|
||||
}
|
||||
else if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
|
||||
UpSampleY( data, 1, step / xstep, m_green->ySampling );
|
||||
@@ -457,7 +486,7 @@ void ExrDecoder::UpSampleY( uchar *data, int xstep, int ystep, int ysample )
|
||||
/**
|
||||
// algorithm from ImfRgbaYca.cpp
|
||||
*/
|
||||
void ExrDecoder::ChromaToBGR( float *data, int numlines, int step )
|
||||
void ExrDecoder::ChromaToBGR( float *data, int numlines, int xstep, int ystep )
|
||||
{
|
||||
for( int y = 0; y < numlines; y++ )
|
||||
{
|
||||
@@ -466,15 +495,15 @@ void ExrDecoder::ChromaToBGR( float *data, int numlines, int step )
|
||||
double b, Y, r;
|
||||
if( m_type == FLOAT )
|
||||
{
|
||||
b = data[y * step + x * 3];
|
||||
Y = data[y * step + x * 3 + 1];
|
||||
r = data[y * step + x * 3 + 2];
|
||||
b = data[y * ystep + x * xstep];
|
||||
Y = data[y * ystep + x * xstep + 1];
|
||||
r = data[y * ystep + x * xstep + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
b = ((unsigned *)data)[y * step + x * 3];
|
||||
Y = ((unsigned *)data)[y * step + x * 3 + 1];
|
||||
r = ((unsigned *)data)[y * step + x * 3 + 2];
|
||||
b = ((unsigned *)data)[y * ystep + x * xstep];
|
||||
Y = ((unsigned *)data)[y * ystep + x * xstep + 1];
|
||||
r = ((unsigned *)data)[y * ystep + x * xstep + 2];
|
||||
}
|
||||
r = (r + 1) * Y;
|
||||
b = (b + 1) * Y;
|
||||
@@ -482,18 +511,18 @@ void ExrDecoder::ChromaToBGR( float *data, int numlines, int step )
|
||||
|
||||
if( m_type == FLOAT )
|
||||
{
|
||||
data[y * step + x * 3] = (float)b;
|
||||
data[y * step + x * 3 + 1] = (float)Y;
|
||||
data[y * step + x * 3 + 2] = (float)r;
|
||||
data[y * ystep + x * xstep] = (float)b;
|
||||
data[y * ystep + x * xstep + 1] = (float)Y;
|
||||
data[y * ystep + x * xstep + 2] = (float)r;
|
||||
}
|
||||
else
|
||||
{
|
||||
int t = cvRound(b);
|
||||
((unsigned *)data)[y * step + x * 3 + 0] = (unsigned)MAX(t, 0);
|
||||
((unsigned *)data)[y * ystep + x * xstep + 0] = (unsigned)MAX(t, 0);
|
||||
t = cvRound(Y);
|
||||
((unsigned *)data)[y * step + x * 3 + 1] = (unsigned)MAX(t, 0);
|
||||
((unsigned *)data)[y * ystep + x * xstep + 1] = (unsigned)MAX(t, 0);
|
||||
t = cvRound(r);
|
||||
((unsigned *)data)[y * step + x * 3 + 2] = (unsigned)MAX(t, 0);
|
||||
((unsigned *)data)[y * ystep + x * xstep + 2] = (unsigned)MAX(t, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -571,7 +600,6 @@ bool ExrEncoder::write( const Mat& img, const std::vector<int>& params )
|
||||
int depth = img.depth();
|
||||
CV_Assert( depth == CV_32F );
|
||||
int channels = img.channels();
|
||||
CV_Assert( channels == 3 || channels == 1 );
|
||||
bool result = false;
|
||||
Header header( width, height );
|
||||
Imf::PixelType type = FLOAT;
|
||||
@@ -594,7 +622,7 @@ bool ExrEncoder::write( const Mat& img, const std::vector<int>& params )
|
||||
}
|
||||
}
|
||||
|
||||
if( channels == 3 )
|
||||
if( channels == 3 || channels == 4 )
|
||||
{
|
||||
header.channels().insert( "R", Channel( type ) );
|
||||
header.channels().insert( "G", Channel( type ) );
|
||||
@@ -607,6 +635,11 @@ bool ExrEncoder::write( const Mat& img, const std::vector<int>& params )
|
||||
//printf("gray\n");
|
||||
}
|
||||
|
||||
if( channels % 2 == 0 )
|
||||
{ // even number of channels indicates Alpha
|
||||
header.channels().insert( "A", Channel( type ) );
|
||||
}
|
||||
|
||||
OutputFile file( m_filename.c_str(), header );
|
||||
|
||||
FrameBuffer frame;
|
||||
@@ -629,14 +662,19 @@ bool ExrEncoder::write( const Mat& img, const std::vector<int>& params )
|
||||
size = 4;
|
||||
}
|
||||
|
||||
if( channels == 3 )
|
||||
if( channels == 3 || channels == 4 )
|
||||
{
|
||||
frame.insert( "B", Slice( type, buffer, size * 3, bufferstep ));
|
||||
frame.insert( "G", Slice( type, buffer + size, size * 3, bufferstep ));
|
||||
frame.insert( "R", Slice( type, buffer + size * 2, size * 3, bufferstep ));
|
||||
frame.insert( "B", Slice( type, buffer, size * channels, bufferstep ));
|
||||
frame.insert( "G", Slice( type, buffer + size, size * channels, bufferstep ));
|
||||
frame.insert( "R", Slice( type, buffer + size * 2, size * channels, bufferstep ));
|
||||
}
|
||||
else
|
||||
frame.insert( "Y", Slice( type, buffer, size, bufferstep ));
|
||||
frame.insert( "Y", Slice( type, buffer, size * channels, bufferstep ));
|
||||
|
||||
if( channels % 2 == 0 )
|
||||
{ // even channel count indicates Alpha channel
|
||||
frame.insert( "A", Slice( type, buffer + size * (channels - 1), size * channels, bufferstep ));
|
||||
}
|
||||
|
||||
file.setFrameBuffer( frame );
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ protected:
|
||||
void UpSample( uchar *data, int xstep, int ystep, int xsample, int ysample );
|
||||
void UpSampleX( float *data, int xstep, int xsample );
|
||||
void UpSampleY( uchar *data, int xstep, int ystep, int ysample );
|
||||
void ChromaToBGR( float *data, int numlines, int step );
|
||||
void ChromaToBGR( float *data, int numlines, int xstep, int ystep );
|
||||
void RGBToGray( float *in, float *out );
|
||||
|
||||
InputFile *m_file;
|
||||
@@ -91,11 +91,13 @@ protected:
|
||||
const Channel *m_red;
|
||||
const Channel *m_green;
|
||||
const Channel *m_blue;
|
||||
const Channel *m_alpha;
|
||||
Chromaticities m_chroma;
|
||||
int m_bit_depth;
|
||||
bool m_native_depth;
|
||||
bool m_iscolor;
|
||||
bool m_isfloat;
|
||||
bool m_hasalpha;
|
||||
|
||||
private:
|
||||
ExrDecoder(const ExrDecoder &); // copy disabled
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Imgcodecs_EXR, readWrite_32FC1)
|
||||
{
|
||||
{ // Y channels
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test32FC1.exr";
|
||||
const string filenameOutput = cv::tempfile(".exr");
|
||||
@@ -31,7 +31,7 @@ TEST(Imgcodecs_EXR, readWrite_32FC1)
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_EXR, readWrite_32FC3)
|
||||
{
|
||||
{ // RGB channels
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test32FC3.exr";
|
||||
const string filenameOutput = cv::tempfile(".exr");
|
||||
@@ -113,5 +113,159 @@ TEST(Imgcodecs_EXR, readWrite_32FC3_half)
|
||||
EXPECT_EQ(0, remove(filenameOutput.c_str()));
|
||||
}
|
||||
|
||||
// Note: YC to GRAYSCALE (IMREAD_GRAYSCALE | IMREAD_ANYDEPTH)
|
||||
// outputs a black image,
|
||||
// as does Y to RGB (IMREAD_COLOR | IMREAD_ANYDEPTH).
|
||||
// This behavoir predates adding EXR alpha support issue
|
||||
// 16115.
|
||||
|
||||
TEST(Imgcodecs_EXR, read_YA_ignore_alpha)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_YA.exr";
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_GRAYSCALE | IMREAD_ANYDEPTH);
|
||||
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_32FC1, img.type());
|
||||
|
||||
// Writing Y covered by test 32FC1
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_EXR, read_YA_unchanged)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_YA.exr";
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
|
||||
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_32FC2, img.type());
|
||||
|
||||
// Cannot test writing, 2 channel writing not suppported by loadsave
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_EXR, read_YC_changeDepth)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_YRYBY.exr";
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_8UC3, img.type());
|
||||
|
||||
// Cannot test writing, EXR encoder doesn't support 8U depth
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_EXR, readwrite_YCA_ignore_alpha)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_YRYBYA.exr";
|
||||
const string filenameOutput = cv::tempfile(".exr");
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_COLOR | IMREAD_ANYDEPTH);
|
||||
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_32FC3, img.type());
|
||||
|
||||
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
|
||||
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
|
||||
ASSERT_EQ(img2.type(), img.type());
|
||||
ASSERT_EQ(img2.size(), img.size());
|
||||
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
|
||||
EXPECT_EQ(0, remove(filenameOutput.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_EXR, read_YC_unchanged)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_YRYBY.exr";
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
|
||||
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_32FC3, img.type());
|
||||
|
||||
// Writing YC covered by test readwrite_YCA_ignore_alpha
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_EXR, readwrite_YCA_unchanged)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_YRYBYA.exr";
|
||||
const string filenameOutput = cv::tempfile(".exr");
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
|
||||
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_32FC4, img.type());
|
||||
|
||||
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
|
||||
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
|
||||
ASSERT_EQ(img2.type(), img.type());
|
||||
ASSERT_EQ(img2.size(), img.size());
|
||||
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
|
||||
EXPECT_EQ(0, remove(filenameOutput.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_EXR, readwrite_RGBA_togreyscale)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_GeneratedRGBA.exr";
|
||||
const string filenameOutput = cv::tempfile(".exr");
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_GRAYSCALE | IMREAD_ANYDEPTH);
|
||||
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_32FC1, img.type());
|
||||
|
||||
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
|
||||
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
|
||||
ASSERT_EQ(img2.type(), img.type());
|
||||
ASSERT_EQ(img2.size(), img.size());
|
||||
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
|
||||
EXPECT_EQ(0, remove(filenameOutput.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_EXR, read_RGBA_ignore_alpha)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_GeneratedRGBA.exr";
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_COLOR | IMREAD_ANYDEPTH);
|
||||
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_32FC3, img.type());
|
||||
|
||||
// Writing RGB covered by test 32FC3
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_EXR, read_RGBA_unchanged)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_GeneratedRGBA.exr";
|
||||
const string filenameOutput = cv::tempfile(".exr");
|
||||
|
||||
#ifndef GENERATE_DATA
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
|
||||
#else
|
||||
const Size sz(64, 32);
|
||||
Mat img(sz, CV_32FC4, Scalar(0.5, 0.1, 1, 1));
|
||||
img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0, 1));
|
||||
img(Rect(10, 20, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 1, 0, 0));
|
||||
ASSERT_TRUE(cv::imwrite(filenameInput, img));
|
||||
#endif
|
||||
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_32FC4, img.type());
|
||||
|
||||
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
|
||||
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
|
||||
ASSERT_EQ(img2.type(), img.type());
|
||||
ASSERT_EQ(img2.size(), img.size());
|
||||
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
|
||||
EXPECT_EQ(0, remove(filenameOutput.c_str()));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -234,7 +234,10 @@ OCL_TEST_P(CornerMinEigenVal, Mat)
|
||||
OCL_OFF(cv::cornerMinEigenVal(src_roi, dst_roi, blockSize, apertureSize, borderType));
|
||||
OCL_ON(cv::cornerMinEigenVal(usrc_roi, udst_roi, blockSize, apertureSize, borderType));
|
||||
|
||||
Near(1e-5, true);
|
||||
if (ocl::Device::getDefault().isIntel())
|
||||
Near(1e-5, true);
|
||||
else
|
||||
Near(0.1, true); // using native_* OpenCL functions may lose accuracy
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@ ocv_list_filterout(opencv_hdrs "modules/cuda.*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/cudev")
|
||||
ocv_list_filterout(opencv_hdrs "modules/core/.*/hal/")
|
||||
ocv_list_filterout(opencv_hdrs "modules/.*/detection_based_tracker.hpp") # Conditional compilation
|
||||
ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/utils/.*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/utils/*.private.*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/utils/instrumentation.hpp")
|
||||
ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/utils/trace*")
|
||||
|
||||
ocv_update_file("${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}")
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ type_dict = {
|
||||
'InputOutputArray': 'cv::Mat&',
|
||||
'InputArrayOfArrays': 'const std::vector<cv::Mat>&',
|
||||
'OutputArrayOfArrays': 'std::vector<cv::Mat>&',
|
||||
'string': 'std::string',
|
||||
'String': 'std::string',
|
||||
'const String&':'const std::string&'
|
||||
}
|
||||
@@ -462,8 +463,7 @@ class JSWrapperGenerator(object):
|
||||
ret_type = type_dict[ptr_type]
|
||||
for key in type_dict:
|
||||
if key in ret_type:
|
||||
ret_type = ret_type.replace(key, type_dict[key])
|
||||
|
||||
ret_type = re.sub('(^|[^\w])' + key + '($|[^\w])', type_dict[key], ret_type)
|
||||
arg_types = []
|
||||
unwrapped_arg_types = []
|
||||
for arg in variant.args:
|
||||
@@ -567,7 +567,7 @@ class JSWrapperGenerator(object):
|
||||
# consider the default parameter variants
|
||||
args_num = len(variant.args) - j
|
||||
if args_num in class_info.constructor_arg_num:
|
||||
# FIXME: workaournd for constructor overload with same args number
|
||||
# FIXME: workaround for constructor overload with same args number
|
||||
# e.g. DescriptorMatcher
|
||||
continue
|
||||
class_info.constructor_arg_num.add(args_num)
|
||||
@@ -627,7 +627,6 @@ class JSWrapperGenerator(object):
|
||||
ret_type = 'void' if variant.rettype.strip() == '' else variant.rettype
|
||||
|
||||
ret_type = ret_type.strip()
|
||||
|
||||
if ret_type.startswith('Ptr'): #smart pointer
|
||||
ptr_type = ret_type.replace('Ptr<', '').replace('>', '')
|
||||
if ptr_type in type_dict:
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
if (typeof window === 'undefined') {
|
||||
var cv = require("../opencv");
|
||||
if (cv instanceof Promise) {
|
||||
loadOpenCV();
|
||||
} else {
|
||||
cv.onRuntimeInitialized = perf;
|
||||
}
|
||||
}
|
||||
|
||||
let gCvSize;
|
||||
@@ -24,6 +29,10 @@ function getCvSize() {
|
||||
return gCvSize;
|
||||
}
|
||||
|
||||
async function loadOpenCV() {
|
||||
cv = await cv;
|
||||
}
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
exports.getCvSize = getCvSize;
|
||||
}
|
||||
@@ -1,3 +1,10 @@
|
||||
const isNodeJs = (typeof window) === 'undefined'? true : false;
|
||||
|
||||
if(isNodeJs) {
|
||||
var Base = require("./base");
|
||||
global.getCvSize = Base.getCvSize;
|
||||
}
|
||||
|
||||
var fillGradient = function(cv, img, delta=5) {
|
||||
let ch = img.channels();
|
||||
console.assert(!img.empty() && img.depth() == cv.CV_8U && ch <= 4);
|
||||
@@ -56,8 +63,8 @@ var smoothBorder = function(cv, img, color, delta=5) {
|
||||
|
||||
var cvtStr2cvSize = function(strSize) {
|
||||
let size;
|
||||
|
||||
let cvSize = getCvSize();
|
||||
|
||||
switch(strSize) {
|
||||
case "127,61": size = cvSize.szODD;break;
|
||||
case '320,240': size = cvSize.szQVGA;break;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user