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

Compare commits

...

107 Commits

Author SHA1 Message Date
Alexander Alekhin 6bdb9ca725 OpenCV release (3.4.8)
OpenCV 3.4.8
2019-10-09 14:42:29 +03:00
Maksim Shabunin 1ca74c3c03 Merge pull request #15544 from mshabunin:disable_posix_memalign
* Disable posix_memalign by default

* core: fix memalign parameter handling
2019-10-09 14:06:12 +03:00
Alexander Smorkalov c3a588037a Merge pull request #15666 from seanm:Wnewline 2019-10-09 11:04:44 +00:00
Marcin Tolysz 3fd36c1be1 Merge pull request #15658 from tolysz:patch-1
* Cuda + OpenGL on ARM

There might be multiple ways of getting OpenCV compile on Tegra (NVIDIA Jetson) platform, but mainly they modify CUDA(8,9,10...) source code, this one fixes it for all installations. 
( https://devtalk.nvidia.com/default/topic/1007290/jetson-tx2/building-opencv-with-opengl-support-/post/5141945/#5141945 et al.).
This way is exactly the same as the one proposed but the code change happens in OpenCV.

* Updated,
The link provided mentions: cuda8 + 9, I have cuda 10 + 10.1 (and can confirm it is still defined this way).
NVIDIA is probably using some other "secret" backend with Jetson.
2019-10-09 11:38:10 +03:00
Sean McBride 24effe8cd6 Fixed clang -Wnewline-eof warning by adding newline to end of file 2019-10-09 10:12:09 +03:00
Alexander Alekhin 2ff1fb60ad Merge pull request #15661 from alalek:fix_android_build_avx2 2019-10-08 23:36:26 +00:00
Alexander Alekhin 374d952e09 Merge pull request #15664 from alalek:build_eliminate_cuda_warnings 2019-10-08 15:27:54 +00:00
Alexander Alekhin 6efdfee3f0 build: eliminate CUDA warnings 2019-10-08 15:30:02 +03:00
Alexander Alekhin 42ac089e12 build: update AVX2 check
- _mm256_bslli_epi128() works in GCC 4.9.3+ only
- Android NDK r10 doesn't support this instruction
2019-10-08 13:12:02 +03:00
Alexander Alekhin 4748aca61f Merge pull request #15642 from alalek:issue_15597 2019-10-08 00:33:20 +03:00
Sayed Adel f2fe6f40c2 Merge pull request #15510 from seiko2plus:issue15506
* core: rework and optimize SIMD implementation of dotProd

  - add new universal intrinsics v_dotprod[int32], v_dotprod_expand[u&int8, u&int16, int32], v_cvt_f64(int64)
  - add a boolean param for all v_dotprod&_expand intrinsics that change the behavior of addition order between
    pairs in some platforms in order to reach the maximum optimization when the sum among all lanes is what only matters
  - fix clang build on ppc64le
  - support wide universal intrinsics for dotProd_32s
  - remove raw SIMD and activate universal intrinsics for dotProd_8
  - implement SIMD optimization for dotProd_s16&u16
  - extend performance test data types of dotprod
  - fix GCC VSX workaround of vec_mule and vec_mulo (in little-endian it must be swapped)
  - optimize v_mul_expand(int32) on VSX

* core: remove boolean param from v_dotprod&_expand and implement v_dotprod_fast&v_dotprod_expand_fast

  this changes made depend on "terfendail" review
2019-10-07 22:01:35 +03:00
Alexander Alekhin 7837ae0e19 Merge pull request #15654 from sturkmen72:patch-3 2019-10-07 16:15:04 +00:00
Alexander Alekhin a007220c52 imgproc: update histogram test 2019-10-07 15:06:43 +03:00
Alexander Alekhin ebb77bb311 Merge pull request #15653 from tolysz:patch-1 2019-10-07 12:04:13 +00:00
Marcin Tolysz 53400d86e2 Fix compiler warnings for latest cuda npp which defines this itself as:
```
#define NPP_VER_MAJOR 10
#define NPP_VER_MINOR 2
#define NPP_VER_PATCH 0
#define NPP_VER_BUILD 243

#define NPP_VERSION (NPP_VER_MAJOR * 1000 +     \
                     NPP_VER_MINOR *  100 +     \
                     NPP_VER_PATCH)
2019-10-07 11:45:26 +01:00
Suleyman TURKMEN c0489963bb Update copy.cpp 2019-10-07 11:59:52 +03:00
Alexander Alekhin 98fc098216 Merge pull request #15646 from alalek:fix_avx512_detection 2019-10-05 15:30:09 +00:00
Alexander Alekhin 953c60829e Merge pull request #15644 from wise86-android:upgradePySetup 2019-10-05 15:29:13 +00:00
Alexander Alekhin 6d811f9879 Merge pull request #15641 from alalek:dnn_pytest_update_3.4 2019-10-05 15:28:52 +00:00
Alexander Alekhin 22d0c57a1c Merge pull request #15602 from alalek:core_softfloat_ubsan_shift 2019-10-05 15:27:35 +00:00
Wise86 b1485d0337 upgrade the file to use the correct package name and include py3/gtk3 support 2019-10-05 14:53:09 +02:00
Alexander Alekhin bdc097495a fix avx512 detection
- renamed Cascade Lake AVX512_CEL => AVX512_CLX (align with Intel SDE tool)
- fixed CLX instruction sets (no IFMA/VBMI)
- added flag to bypass CPU baseline check: OPENCV_SKIP_CPU_BASELINE_CHECK
2019-10-05 11:03:57 +00:00
Alexander Alekhin feff8bf972 Merge pull request #15626 from alalek:dnn_openvino_2019r3 2019-10-04 19:45:37 +00:00
Alexander Alekhin f301f17b61 imgproc: accurate histogram value thresholding 2019-10-04 19:56:25 +03:00
Alexander Alekhin c13a5ce229 Merge pull request #15622 from dkurt:enet_ie_cpu 2019-10-04 16:31:05 +00:00
Alexander Alekhin ab5252c18e dnn(pytest): backport changes from master, update test setUp() 2019-10-04 18:43:35 +03:00
Dmitry Kurtaev e35fd463e7 Enable ENet with Inference Engine backend on CPU 2019-10-04 18:10:11 +03:00
Alexander Alekhin fd11e3a81d dnn: update IE tests 2019-10-04 17:49:10 +03:00
Alexander Alekhin 22d86116ee Merge pull request #15634 from alalek:issue_15083_4903 2019-10-04 11:54:54 +00:00
Alexander Alekhin deea46000e Merge pull request #15637 from APrigarina:3.4_version2
QR-Code detection: accuracy improvement (fixed)
2019-10-04 14:09:35 +03:00
APrigarina c99db2b9db bug fix 2019-10-04 13:02:54 +03:00
Alexander Alekhin c69245da1f imgproc: fix fitLine() implementation
- update optimal solutions on each iteration
2019-10-03 21:23:52 +00:00
Alexander Alekhin 2b66495a9d dnn: use OpenVINO 2019R3 defines 2019-10-02 18:47:01 +03:00
Alexander Alekhin a105f56957 Merge pull request #15621 from alalek:cmake_ipp_licenses 2019-10-02 14:30:17 +00:00
Alexander Alekhin 23bd1866ca Merge pull request #15620 from alalek:issue_14727 2019-10-02 14:29:56 +00:00
Alexander Alekhin 59c182ed2b Merge pull request #15467 from elmsfu:dshow/add_save_graph_file 2019-10-02 14:27:56 +00:00
Alexander Alekhin c06115cb3f Merge pull request #15619 from alalek:dnn_eltwise_sum_ie_ocl 2019-10-01 18:02:45 +00:00
Elms 8b483a91bc dshow: Add ability to save direct show graph 2019-10-01 09:46:07 -07:00
Alexander Alekhin 8814645c8d dnn(test): skip IE/OCL test for "sum" 2019-10-01 18:29:47 +03:00
Alexander Alekhin c92f3072b4 cmake: add check for IPP IW license files 2019-10-01 18:24:03 +03:00
Alexander Alekhin ffea927ac2 Merge pull request #15618 from alalek:dnn_test_async_timeout 2019-10-01 14:48:47 +00:00
Alexander Alekhin 77346d7286 core: workaround transform() inplace calls 2019-10-01 16:52:14 +03:00
Alexander Alekhin 440a937d24 dnn: increase async test timeout 2019-10-01 13:31:57 +03:00
Alexander Alekhin ba0b3983c6 Merge pull request #15609 from sturkmen72:update_loadsave_cpp 2019-09-30 18:37:21 +00:00
Sebastián Gurin a3144cbadc Merge pull request #15480 from cancerberoSgx:estimateAffine2D
js - cv.estimateAffine2D, cv.warpPolar
2019-09-30 21:35:26 +03:00
ann 5c9a624a85 Merge pull request #15356 from APrigarina:3.4_version2
QR-Code detection: accuracy improvement

* first commit

* resize improvement

* resize improvement

* dummy commit

* warnings fix

* warnings fix

* warnings fix

* test added

* resize fix

* resize fix

* tests changed

* tests changed
2019-09-30 21:33:58 +03:00
Suleyman TURKMEN d88d1c9935 Update loadsave.cpp 2019-09-28 23:24:17 +03:00
Alexander Alekhin ed9bca969c core: fix UBSAN in softfloat 2019-09-27 16:29:50 +03:00
Alexander Alekhin aa61e79615 Merge pull request #15600 from alalek:imgproc_pyramid_fix_indexing 2019-09-27 10:21:52 +00:00
Brandon 25dee8383c Merge pull request #15595 from frastlin:rodrigues
* Added Rodrigues to the JS embindgen.py and a unittest in test_calib3d.js on 3.4 base
2019-09-27 13:06:07 +03:00
Alexander Alekhin f81e401cd0 imgproc: fix indexing issue in pyramids
UBSAN violation expression: 'tab = tabR - x;'
2019-09-26 18:09:47 +03:00
Alexander Alekhin 7ce9428e96 Merge pull request #15580 from smbz:dnn-lstm-reverse 2019-09-25 15:54:06 +00:00
Alexander Alekhin 677b94c92e Merge pull request #15579 from alalek:ocl_use_host_mem_ptr_flag 2019-09-25 15:12:59 +00:00
Andrew Ryrie b88435fdc2 dnn: Allow LSTM layer to operate in reverse direction
This is useful for bidirectional LSTMs.
2019-09-25 14:12:43 +01:00
Alexander Alekhin 790927bb55 Merge pull request #15582 from terfendail:pyrdown_oob 2019-09-25 12:37:31 +00:00
Lubov Batanina e923712d81 Merge pull request #15572 from l-bat:deconv3d
Fix computation of internal shapes in Deconvolution layer

* Fix computation of internal shapes

* Refactoring
2019-09-25 15:35:04 +03:00
Alexander Alekhin eacadf0e73 core(ocl): add flag OPENCV_OPENCL_ENABLE_MEM_USE_HOST_PTR
to control CL_MEM_USE_HOST_PTR usage
2019-09-25 15:12:36 +03:00
Alexander Alekhin e3daf489c8 Merge pull request #15581 from takacsd:3.4 2019-09-25 10:45:49 +00:00
Vitaly Tuzov 1c17b3281a Fixed OOB reading in pyrDown 2019-09-25 13:24:17 +03:00
Alexander Alekhin d2cacac07a Merge pull request #15573 from alalek:build_cxx11_warnings 2019-09-24 22:08:55 +00:00
takacsd e0be771b64 Add option to disable features in iOS build. 2019-09-24 17:42:35 +02:00
Wenzhao Xiang c2096771cb Merge pull request #15371 from Wenzhao-Xiang:gsoc_2019
[GSoC 2019] Improve the performance of JavaScript version of OpenCV (OpenCV.js)

* [GSoC 2019]

Improve the performance of JavaScript version of OpenCV (OpenCV.js):
1. Create the base of OpenCV.js performance test:
     This perf test is based on benchmark.js(https://benchmarkjs.com). And first add `cvtColor`, `Resize`, `Threshold` into it.
2. Optimize the OpenCV.js performance by WASM threads:
     This optimization is based on Web Worker API and SharedArrayBuffer, so it can be only used in browser.
3. Optimize the OpenCV.js performance by WASM SIMD:
     Add WASM SIMD backend for OpenCV Universal Intrinsics. It's experimental as WASM SIMD is still in development.

* [GSoC2019] 

1. use short license header
2. fix documentation node issue
3. remove the unused `hasSIMD128()` api

* [GSoC2019]

1. fix emscripten define
2. use fallback function for f16

* [GSoC2019]

Fix rebase issue
2019-09-24 16:30:42 +03:00
Alexander Alekhin 3cf9185159 Merge pull request #15538 from terfendail:wui_checkany 2019-09-23 15:52:24 +00:00
Maksim Shabunin c8abf2ad14 backport: fixed warnings produced by clang-9.0.0
ea3dc78986
https://github.com/opencv/opencv_contrib/commit/83fc27cb99db4435d07974090fbdc77d831931cd
2019-09-23 18:36:18 +03:00
Alexander Alekhin c4d2e3c0b3 Merge pull request #15566 from alalek:issue_15558 2019-09-23 09:22:06 +00:00
Alexander Alekhin b40fd6de32 Merge pull request #15565 from alalek:issue_15561 2019-09-23 09:21:49 +00:00
Alexander Alekhin 3516d0835e Merge pull request #15564 from alalek:issue_15560 2019-09-23 09:21:27 +00:00
Alexander Alekhin fcc69d5a60 core(test): fix check conditions 2019-09-22 11:28:41 +00:00
Alexander Alekhin fef7fc343e ml: add checks of empty train data 2019-09-22 11:12:19 +00:00
Alexander Alekhin ad2854c8b3 imgcodecs: add check image.empty() in imwrite()/imencode() 2019-09-22 10:45:00 +00:00
Alexander Alekhin eabbe38001 Merge pull request #15554 from alalek:pr15422_patch_files
* 3rdparty: libpng v1.6.37 MSA patch (pr15422)

original files: https://github.com/glennrp/libpng/tree/v1.6.37/mips

* 3rdparty: libwebp MSA asm patch (pr15422)
2019-09-21 00:07:24 +03:00
mipsopen-fwu b1ea91d8bd Merge pull request #15422 from mipsopen-fwu:msa-dev
* Added MSA implementations for mips platforms. Intrinsics for MSA and build scripts for MIPS platforms are added.

Signed-off-by: Fei Wu <fwu@wavecomp.com>

* Removed some unused code in mips.toolchain.cmake.

Signed-off-by: Fei Wu <fwu@wavecomp.com>

* Added comments for mips toolchain configuration and disabled compiling warnings for libpng.

Signed-off-by: Fei Wu <fwu@wavecomp.com>

* Fixed the build error of unsupported opcode 'pause' when mips isa_rev is less than 2.

Signed-off-by: Fei Wu <fwu@wavecomp.com>

* 1. Removed FP16 related item in MSA option defines in OpenCVCompilerOptimizations.cmake.
2. Use CV_CPU_COMPILE_MSA instead of __mips_msa for MSA feature check in cv_cpu_dispatch.h.
3. Removed hasSIMD128() in intrin_msa.hpp.
4. Define CPU_MSA as 150.
Signed-off-by: Fei Wu <fwu@wavecomp.com>

* 1. Removed unnecessary CV_SIMD128_64F guarding in intrin_msa.hpp.
2. Removed unnecessary CV_MSA related code block in dotProd_8u().

Signed-off-by: Fei Wu <fwu@wavecomp.com>

* 1. Defined CPU_MSA_FLAGS_ON as "-mmsa".
2. Removed CV_SIMD128_64F guardings in intrin_msa.hpp.

Signed-off-by: Fei Wu <fwu@wavecomp.com>

* Removed unused msa_mlal_u16() and msa_mlal_s16 from msa_macros.h.

Signed-off-by: Fei Wu <fwu@wavecomp.com>
2019-09-20 19:52:48 +03:00
Vitaly Tuzov 66842f5a18 Extended v_check_any/v_check_all universal intrinsics to support 64-bit integer 2019-09-19 18:31:31 +03:00
Alexander Alekhin 33e9fe9312 Merge pull request #15540 from alalek:issue_15278_2 2019-09-18 20:12:36 +00:00
Alexander Alekhin 65c209fad3 Merge pull request #15519 from mshabunin:fix-custom-install 2019-09-18 15:31:25 +00:00
dab0bby a9163a53d3 Merge pull request #15477 from dab0bby:remove-old-build-java-option
* remove old BUILD_opencv_java option

* replace old build_java option with new BUILD_JAVA option
2019-09-18 18:30:01 +03:00
Alexander Alekhin c657c6cbac cmake: use 'long long' for atomic check 2019-09-18 15:18:09 +00:00
Alexander Alekhin 8167d47efc Merge pull request #15516 from dkurt:dnn_detection_model_fix_3.4 2019-09-18 11:22:27 +00:00
Alexander Alekhin 1ecea1f4a6 Merge pull request #15529 from collinbrake:feature_grammar_fixes 2019-09-18 11:19:59 +00:00
Alexander Alekhin 46fd112f9b Merge pull request #15399 from terfendail:perf_stereobm 2019-09-17 14:26:43 +00:00
collin bcf7d3160c Grammer fixes on python image display tutorial 2019-09-16 17:57:22 -04:00
Daniel Kapusi d2872afce0 Merge pull request #15341 from DiebBlue:is5769
* issue 5769 fixed: cv::stereoRectify fails if given inliers mask of type vector<uchar>

* issue5769 fix using reshape and add regression test

* regression test with outlier detection, testing vector and mat data

* Size comparision of wrong vector within CV_Assert in regression test corrected

* cleanup test code
2019-09-17 00:04:05 +03:00
Alexander Alekhin 70c88a2087 Merge pull request #15517 from mshabunin:fix-osx-avfoundation-auth 2019-09-16 15:28:34 +00:00
Alexander Alekhin 7770ba1f10 Merge pull request #15491 from terfendail:undistort_fix 2019-09-16 15:24:29 +00:00
Vitaly Tuzov 7b3a752012 Fixed universal intrinsic undistort() implementation 2019-09-16 17:16:38 +03:00
Maksim Shabunin 5a75808516 Windows: partially restore install config generation 2019-09-16 12:11:48 +03:00
Alexander Alekhin 03c4c67dad Merge pull request #15518 from mshabunin:fix-osx-qt 2019-09-13 17:06:00 +00:00
Alexander Alekhin f5f9187720 Merge pull request #15476 from cancerberoSgx:js-docker 2019-09-13 17:04:52 +00:00
Alexander Alekhin 89b82e796e Merge pull request #15449 from mshabunin:cmake-download-params 2019-09-13 17:03:28 +00:00
Alexander Alekhin 48fa39f675 Merge pull request #15487 from dkurt:fix_ie_2019r1 2019-09-13 16:57:34 +00:00
Alexander Alekhin 69c19dc3d3 Merge pull request #15511 from pmur:vmuleo-fix-gcc7 2019-09-13 16:48:18 +00:00
Maksim Shabunin 5c0502b470 Fixed OSX build with Qt 2019-09-13 15:23:59 +03:00
Maksim Shabunin f10fce9ab4 AVFoundation: backported runtime authorization check from master 2019-09-13 13:20:29 +03:00
Maksim Shabunin aaad238c6e AVFoundation: fix authorization request not being shown 2019-09-13 13:11:35 +03:00
Dmitry Kurtaev 741aee6901 Fix dnn object detection sample 2019-09-13 11:50:50 +03:00
Dmitry Kurtaev 0428f60d66 Fix OpenVINO 2019R1 compilation 2019-09-13 09:22:34 +03:00
Paul E. Murphy b465c82696 core: workaround old gcc vec_mul{e,o} (Issue #15506)
ISA 2.07 (aka POWER8) effectively extended the expanding multiply
operation to word types. The altivec intrinsics prior to gcc 8 did
not get the update.

Workaround this deficiency similar to other fixes.

This was exposed by commit 33fb253a66
which leverages the int -> dword expanding multiply.

This fixes Issue #15506
2019-09-12 09:54:02 -05:00
Alexander Alekhin 8609198b05 Merge pull request #15466 from alalek:ffmpeg_update_3.4 2019-09-10 09:57:38 +00:00
Vitaly Tuzov bf8b5ffeb1 Added performance test for StereoBM algorithm 2019-09-09 16:37:06 +03:00
Sebastián Gurín a17231a6b4 js docker build docs emcc latest warning 2019-09-06 15:18:34 -03:00
Alexander Alekhin b3a0507546 Merge pull request #15475 from alalek:build_eliminate_warning_array_bounds 2019-09-06 15:57:52 +00:00
Alexander Alekhin f139a0bda8 Merge pull request #15461 from alalek:imgproc_connectedcomponents_allocation 2019-09-06 15:32:04 +00:00
Alexander Alekhin bdf23ce855 ts: eliminate -Warray-bounds warning 2019-09-06 18:06:02 +03:00
Alexander Alekhin 6a49887695 ffmpeg/3.4: update FFmpeg wrapper 2019-09-05 21:36:06 +00:00
Alexander Alekhin e7b6753a10 imgproc: avoid manual memory allocation in connectedcomponents.cpp 2019-09-05 16:20:08 +03:00
Maksim Shabunin 9d4f01626c cmake: add directory creation to download helper scripts 2019-09-04 17:09:13 +03:00
Maksim Shabunin d974d4c6ce cmake: download tries, customizable download parameters 2019-09-04 17:09:13 +03:00
132 changed files with 13356 additions and 764 deletions
+5 -5
View File
@@ -1,8 +1,8 @@
# Binaries branch name: ffmpeg/3.4_20190612
# Binaries were created for OpenCV: 1c661e754812d3423e8c15ccb9cdab57fc122c44
ocv_update(FFMPEG_BINARIES_COMMIT "d284fd09e76966e95f08e1ac3a1a28b227447501")
ocv_update(FFMPEG_FILE_HASH_BIN32 "a7032bf6cc1cb010dc055f352277792c")
ocv_update(FFMPEG_FILE_HASH_BIN64 "40d1a38b83a0413a3fcf9df1044fff2a")
# Binaries branch name: ffmpeg/3.4_20190905
# Binaries were created for OpenCV: fafada28ebc0f2e5423a7d8ece425574ef01ff60
ocv_update(FFMPEG_BINARIES_COMMIT "bf1730f4c4ba1996bed1fe268b52e4e942151cd6")
ocv_update(FFMPEG_FILE_HASH_BIN32 "6899624f88cb4cbb1604edc5e12b18ab")
ocv_update(FFMPEG_FILE_HASH_BIN64 "4729c052cb0c53ab56e9a0eed91559df")
ocv_update(FFMPEG_FILE_HASH_CMAKE "3b90f67f4b429e77d3da36698cef700c")
function(download_win_ffmpeg script_var)
+9
View File
@@ -46,6 +46,15 @@ if(";${CPU_BASELINE_FINAL};" MATCHES "SSE2"
add_definitions(-DPNG_INTEL_SSE)
endif()
# set definitions and sources for MIPS
if(";${CPU_BASELINE_FINAL};" MATCHES "MSA")
list(APPEND lib_srcs mips/mips_init.c mips/filter_msa_intrinsics.c)
add_definitions(-DPNG_MIPS_MSA_OPT=2)
ocv_warnings_disable(CMAKE_C_FLAGS -Wshadow)
else()
add_definitions(-DPNG_MIPS_MSA_OPT=0)
endif()
if(PPC64LE OR PPC64)
# VSX3 features are backwards compatible
if(";${CPU_BASELINE_FINAL};" MATCHES "VSX.*"
+808
View File
@@ -0,0 +1,808 @@
/* filter_msa_intrinsics.c - MSA optimised filter functions
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2016 Glenn Randers-Pehrson
* Written by Mandar Sahastrabuddhe, August 2016.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include <stdio.h>
#include <stdint.h>
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
/* This code requires -mfpu=msa on the command line: */
#if PNG_MIPS_MSA_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
#include <msa.h>
/* libpng row pointers are not necessarily aligned to any particular boundary,
* however this code will only work with appropriate alignment. mips/mips_init.c
* checks for this (and will not compile unless it is done). This code uses
* variants of png_aligncast to avoid compiler warnings.
*/
#define png_ptr(type,pointer) png_aligncast(type *,pointer)
#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
/* The following relies on a variable 'temp_pointer' being declared with type
* 'type'. This is written this way just to hide the GCC strict aliasing
* warning; note that the code is safe because there never is an alias between
* the input and output pointers.
*/
#define png_ldr(type,pointer)\
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
#if PNG_MIPS_MSA_OPT > 0
#ifdef CLANG_BUILD
#define MSA_SRLI_B(a, b) __msa_srli_b((v16i8) a, b)
#define LW(psrc) \
( { \
uint8_t *psrc_lw_m = (uint8_t *) (psrc); \
uint32_t val_m; \
\
asm volatile ( \
"lw %[val_m], %[psrc_lw_m] \n\t" \
\
: [val_m] "=r" (val_m) \
: [psrc_lw_m] "m" (*psrc_lw_m) \
); \
\
val_m; \
} )
#define SH(val, pdst) \
{ \
uint8_t *pdst_sh_m = (uint8_t *) (pdst); \
uint16_t val_m = (val); \
\
asm volatile ( \
"sh %[val_m], %[pdst_sh_m] \n\t" \
\
: [pdst_sh_m] "=m" (*pdst_sh_m) \
: [val_m] "r" (val_m) \
); \
}
#define SW(val, pdst) \
{ \
uint8_t *pdst_sw_m = (uint8_t *) (pdst); \
uint32_t val_m = (val); \
\
asm volatile ( \
"sw %[val_m], %[pdst_sw_m] \n\t" \
\
: [pdst_sw_m] "=m" (*pdst_sw_m) \
: [val_m] "r" (val_m) \
); \
}
#if (__mips == 64)
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
uint64_t val_m = (val); \
\
asm volatile ( \
"sd %[val_m], %[pdst_sd_m] \n\t" \
\
: [pdst_sd_m] "=m" (*pdst_sd_m) \
: [val_m] "r" (val_m) \
); \
}
#else
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
uint32_t val0_m, val1_m; \
\
val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF); \
val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF); \
\
SW(val0_m, pdst_sd_m); \
SW(val1_m, pdst_sd_m + 4); \
}
#endif
#else
#define MSA_SRLI_B(a, b) (a >> b)
#if (__mips_isa_rev >= 6)
#define LW(psrc) \
( { \
uint8_t *psrc_lw_m = (uint8_t *) (psrc); \
uint32_t val_m; \
\
asm volatile ( \
"lw %[val_m], %[psrc_lw_m] \n\t" \
\
: [val_m] "=r" (val_m) \
: [psrc_lw_m] "m" (*psrc_lw_m) \
); \
\
val_m; \
} )
#define SH(val, pdst) \
{ \
uint8_t *pdst_sh_m = (uint8_t *) (pdst); \
uint16_t val_m = (val); \
\
asm volatile ( \
"sh %[val_m], %[pdst_sh_m] \n\t" \
\
: [pdst_sh_m] "=m" (*pdst_sh_m) \
: [val_m] "r" (val_m) \
); \
}
#define SW(val, pdst) \
{ \
uint8_t *pdst_sw_m = (uint8_t *) (pdst); \
uint32_t val_m = (val); \
\
asm volatile ( \
"sw %[val_m], %[pdst_sw_m] \n\t" \
\
: [pdst_sw_m] "=m" (*pdst_sw_m) \
: [val_m] "r" (val_m) \
); \
}
#if (__mips == 64)
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
uint64_t val_m = (val); \
\
asm volatile ( \
"sd %[val_m], %[pdst_sd_m] \n\t" \
\
: [pdst_sd_m] "=m" (*pdst_sd_m) \
: [val_m] "r" (val_m) \
); \
}
#else
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
uint32_t val0_m, val1_m; \
\
val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF); \
val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF); \
\
SW(val0_m, pdst_sd_m); \
SW(val1_m, pdst_sd_m + 4); \
}
#endif
#else // !(__mips_isa_rev >= 6)
#define LW(psrc) \
( { \
uint8_t *psrc_lw_m = (uint8_t *) (psrc); \
uint32_t val_m; \
\
asm volatile ( \
"ulw %[val_m], %[psrc_lw_m] \n\t" \
\
: [val_m] "=r" (val_m) \
: [psrc_lw_m] "m" (*psrc_lw_m) \
); \
\
val_m; \
} )
#define SH(val, pdst) \
{ \
uint8_t *pdst_sh_m = (uint8_t *) (pdst); \
uint16_t val_m = (val); \
\
asm volatile ( \
"ush %[val_m], %[pdst_sh_m] \n\t" \
\
: [pdst_sh_m] "=m" (*pdst_sh_m) \
: [val_m] "r" (val_m) \
); \
}
#define SW(val, pdst) \
{ \
uint8_t *pdst_sw_m = (uint8_t *) (pdst); \
uint32_t val_m = (val); \
\
asm volatile ( \
"usw %[val_m], %[pdst_sw_m] \n\t" \
\
: [pdst_sw_m] "=m" (*pdst_sw_m) \
: [val_m] "r" (val_m) \
); \
}
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
uint32_t val0_m, val1_m; \
\
val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF); \
val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF); \
\
SW(val0_m, pdst_sd_m); \
SW(val1_m, pdst_sd_m + 4); \
}
#define SW_ZERO(pdst) \
{ \
uint8_t *pdst_m = (uint8_t *) (pdst); \
\
asm volatile ( \
"usw $0, %[pdst_m] \n\t" \
\
: [pdst_m] "=m" (*pdst_m) \
: \
); \
}
#endif // (__mips_isa_rev >= 6)
#endif
#define LD_B(RTYPE, psrc) *((RTYPE *) (psrc))
#define LD_UB(...) LD_B(v16u8, __VA_ARGS__)
#define LD_B2(RTYPE, psrc, stride, out0, out1) \
{ \
out0 = LD_B(RTYPE, (psrc)); \
out1 = LD_B(RTYPE, (psrc) + stride); \
}
#define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__)
#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) \
{ \
LD_B2(RTYPE, (psrc), stride, out0, out1); \
LD_B2(RTYPE, (psrc) + 2 * stride , stride, out2, out3); \
}
#define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__)
#define ST_B(RTYPE, in, pdst) *((RTYPE *) (pdst)) = (in)
#define ST_UB(...) ST_B(v16u8, __VA_ARGS__)
#define ST_B2(RTYPE, in0, in1, pdst, stride) \
{ \
ST_B(RTYPE, in0, (pdst)); \
ST_B(RTYPE, in1, (pdst) + stride); \
}
#define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__)
#define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride) \
{ \
ST_B2(RTYPE, in0, in1, (pdst), stride); \
ST_B2(RTYPE, in2, in3, (pdst) + 2 * stride, stride); \
}
#define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__)
#define ADD2(in0, in1, in2, in3, out0, out1) \
{ \
out0 = in0 + in1; \
out1 = in2 + in3; \
}
#define ADD3(in0, in1, in2, in3, in4, in5, \
out0, out1, out2) \
{ \
ADD2(in0, in1, in2, in3, out0, out1); \
out2 = in4 + in5; \
}
#define ADD4(in0, in1, in2, in3, in4, in5, in6, in7, \
out0, out1, out2, out3) \
{ \
ADD2(in0, in1, in2, in3, out0, out1); \
ADD2(in4, in5, in6, in7, out2, out3); \
}
#define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1) \
{ \
out0 = (RTYPE) __msa_ilvr_b((v16i8) in0, (v16i8) in1); \
out1 = (RTYPE) __msa_ilvr_b((v16i8) in2, (v16i8) in3); \
}
#define ILVR_B2_SH(...) ILVR_B2(v8i16, __VA_ARGS__)
#define HSUB_UB2(RTYPE, in0, in1, out0, out1) \
{ \
out0 = (RTYPE) __msa_hsub_u_h((v16u8) in0, (v16u8) in0); \
out1 = (RTYPE) __msa_hsub_u_h((v16u8) in1, (v16u8) in1); \
}
#define HSUB_UB2_SH(...) HSUB_UB2(v8i16, __VA_ARGS__)
#define SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val) \
{ \
v16i8 zero_m = { 0 }; \
out0 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in0, slide_val); \
out1 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in1, slide_val); \
}
#define SLDI_B2_0_UB(...) SLDI_B2_0(v16u8, __VA_ARGS__)
#define SLDI_B3_0(RTYPE, in0, in1, in2, out0, out1, out2, slide_val) \
{ \
v16i8 zero_m = { 0 }; \
SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val); \
out2 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in2, slide_val); \
}
#define SLDI_B3_0_UB(...) SLDI_B3_0(v16u8, __VA_ARGS__)
#define ILVEV_W2(RTYPE, in0, in1, in2, in3, out0, out1) \
{ \
out0 = (RTYPE) __msa_ilvev_w((v4i32) in1, (v4i32) in0); \
out1 = (RTYPE) __msa_ilvev_w((v4i32) in3, (v4i32) in2); \
}
#define ILVEV_W2_UB(...) ILVEV_W2(v16u8, __VA_ARGS__)
#define ADD_ABS_H3(RTYPE, in0, in1, in2, out0, out1, out2) \
{ \
RTYPE zero = {0}; \
\
out0 = __msa_add_a_h((v8i16) zero, in0); \
out1 = __msa_add_a_h((v8i16) zero, in1); \
out2 = __msa_add_a_h((v8i16) zero, in2); \
}
#define ADD_ABS_H3_SH(...) ADD_ABS_H3(v8i16, __VA_ARGS__)
#define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) \
{ \
out0 = (RTYPE) __msa_vshf_b((v16i8) mask0, (v16i8) in1, (v16i8) in0); \
out1 = (RTYPE) __msa_vshf_b((v16i8) mask1, (v16i8) in3, (v16i8) in2); \
}
#define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__)
#define CMP_AND_SELECT(inp0, inp1, inp2, inp3, inp4, inp5, out0) \
{ \
v8i16 _sel_h0, _sel_h1; \
v16u8 _sel_b0, _sel_b1; \
_sel_h0 = (v8i16) __msa_clt_u_h((v8u16) inp1, (v8u16) inp0); \
_sel_b0 = (v16u8) __msa_pckev_b((v16i8) _sel_h0, (v16i8) _sel_h0); \
inp0 = (v8i16) __msa_bmnz_v((v16u8) inp0, (v16u8) inp1, (v16u8) _sel_h0); \
inp4 = (v16u8) __msa_bmnz_v(inp3, inp4, _sel_b0); \
_sel_h1 = (v8i16) __msa_clt_u_h((v8u16) inp2, (v8u16) inp0); \
_sel_b1 = (v16u8) __msa_pckev_b((v16i8) _sel_h1, (v16i8) _sel_h1); \
inp4 = (v16u8) __msa_bmnz_v(inp4, inp5, _sel_b1); \
out0 += inp4; \
}
void png_read_filter_row_up_msa(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t i, cnt, cnt16, cnt32;
size_t istop = row_info->rowbytes;
png_bytep rp = row;
png_const_bytep pp = prev_row;
v16u8 src0, src1, src2, src3, src4, src5, src6, src7;
for (i = 0; i < (istop >> 6); i++)
{
LD_UB4(rp, 16, src0, src1, src2, src3);
LD_UB4(pp, 16, src4, src5, src6, src7);
pp += 64;
ADD4(src0, src4, src1, src5, src2, src6, src3, src7,
src0, src1, src2, src3);
ST_UB4(src0, src1, src2, src3, rp, 16);
rp += 64;
}
if (istop & 0x3F)
{
cnt32 = istop & 0x20;
cnt16 = istop & 0x10;
cnt = istop & 0xF;
if(cnt32)
{
if (cnt16 && cnt)
{
LD_UB4(rp, 16, src0, src1, src2, src3);
LD_UB4(pp, 16, src4, src5, src6, src7);
ADD4(src0, src4, src1, src5, src2, src6, src3, src7,
src0, src1, src2, src3);
ST_UB4(src0, src1, src2, src3, rp, 16);
rp += 64;
}
else if (cnt16 || cnt)
{
LD_UB2(rp, 16, src0, src1);
LD_UB2(pp, 16, src4, src5);
pp += 32;
src2 = LD_UB(rp + 32);
src6 = LD_UB(pp);
ADD3(src0, src4, src1, src5, src2, src6, src0, src1, src2);
ST_UB2(src0, src1, rp, 16);
rp += 32;
ST_UB(src2, rp);
rp += 16;
}
else
{
LD_UB2(rp, 16, src0, src1);
LD_UB2(pp, 16, src4, src5);
ADD2(src0, src4, src1, src5, src0, src1);
ST_UB2(src0, src1, rp, 16);
rp += 32;
}
}
else if (cnt16 && cnt)
{
LD_UB2(rp, 16, src0, src1);
LD_UB2(pp, 16, src4, src5);
ADD2(src0, src4, src1, src5, src0, src1);
ST_UB2(src0, src1, rp, 16);
rp += 32;
}
else if (cnt16 || cnt)
{
src0 = LD_UB(rp);
src4 = LD_UB(pp);
pp += 16;
src0 += src4;
ST_UB(src0, rp);
rp += 16;
}
}
}
void png_read_filter_row_sub4_msa(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t count;
size_t istop = row_info->rowbytes;
png_bytep src = row;
png_bytep nxt = row + 4;
int32_t inp0;
v16u8 src0, src1, src2, src3, src4;
v16u8 dst0, dst1;
v16u8 zero = { 0 };
istop -= 4;
inp0 = LW(src);
src += 4;
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
for (count = 0; count < istop; count += 16)
{
src1 = LD_UB(src);
src += 16;
src2 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 4);
src3 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 8);
src4 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 12);
src1 += src0;
src2 += src1;
src3 += src2;
src4 += src3;
src0 = src4;
ILVEV_W2_UB(src1, src2, src3, src4, dst0, dst1);
dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0);
ST_UB(dst0, nxt);
nxt += 16;
}
}
void png_read_filter_row_sub3_msa(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t count;
size_t istop = row_info->rowbytes;
png_bytep src = row;
png_bytep nxt = row + 3;
int64_t out0;
int32_t inp0, out1;
v16u8 src0, src1, src2, src3, src4, dst0, dst1;
v16u8 zero = { 0 };
v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 };
istop -= 3;
inp0 = LW(src);
src += 3;
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
for (count = 0; count < istop; count += 12)
{
src1 = LD_UB(src);
src += 12;
src2 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 3);
src3 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 6);
src4 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 9);
src1 += src0;
src2 += src1;
src3 += src2;
src4 += src3;
src0 = src4;
VSHF_B2_UB(src1, src2, src3, src4, mask0, mask0, dst0, dst1);
dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0);
out0 = __msa_copy_s_d((v2i64) dst0, 0);
out1 = __msa_copy_s_w((v4i32) dst0, 2);
SD(out0, nxt);
nxt += 8;
SW(out1, nxt);
nxt += 4;
}
}
void png_read_filter_row_avg4_msa(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t i;
png_bytep src = row;
png_bytep nxt = row;
png_const_bytep pp = prev_row;
size_t istop = row_info->rowbytes - 4;
int32_t inp0, inp1, out0;
v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1;
v16u8 zero = { 0 };
inp0 = LW(pp);
pp += 4;
inp1 = LW(src);
src += 4;
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
src0 = (v16u8) MSA_SRLI_B(src0, 1);
src1 += src0;
out0 = __msa_copy_s_w((v4i32) src1, 0);
SW(out0, nxt);
nxt += 4;
for (i = 0; i < istop; i += 16)
{
src2 = LD_UB(pp);
pp += 16;
src6 = LD_UB(src);
src += 16;
SLDI_B2_0_UB(src2, src6, src3, src7, 4);
SLDI_B2_0_UB(src2, src6, src4, src8, 8);
SLDI_B2_0_UB(src2, src6, src5, src9, 12);
src2 = __msa_ave_u_b(src2, src1);
src6 += src2;
src3 = __msa_ave_u_b(src3, src6);
src7 += src3;
src4 = __msa_ave_u_b(src4, src7);
src8 += src4;
src5 = __msa_ave_u_b(src5, src8);
src9 += src5;
src1 = src9;
ILVEV_W2_UB(src6, src7, src8, src9, dst0, dst1);
dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0);
ST_UB(dst0, nxt);
nxt += 16;
}
}
void png_read_filter_row_avg3_msa(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t i;
png_bytep src = row;
png_bytep nxt = row;
png_const_bytep pp = prev_row;
size_t istop = row_info->rowbytes - 3;
int64_t out0;
int32_t inp0, inp1, out1;
int16_t out2;
v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1;
v16u8 zero = { 0 };
v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 };
inp0 = LW(pp);
pp += 3;
inp1 = LW(src);
src += 3;
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
src0 = (v16u8) MSA_SRLI_B(src0, 1);
src1 += src0;
out2 = __msa_copy_s_h((v8i16) src1, 0);
SH(out2, nxt);
nxt += 2;
nxt[0] = src1[2];
nxt++;
for (i = 0; i < istop; i += 12)
{
src2 = LD_UB(pp);
pp += 12;
src6 = LD_UB(src);
src += 12;
SLDI_B2_0_UB(src2, src6, src3, src7, 3);
SLDI_B2_0_UB(src2, src6, src4, src8, 6);
SLDI_B2_0_UB(src2, src6, src5, src9, 9);
src2 = __msa_ave_u_b(src2, src1);
src6 += src2;
src3 = __msa_ave_u_b(src3, src6);
src7 += src3;
src4 = __msa_ave_u_b(src4, src7);
src8 += src4;
src5 = __msa_ave_u_b(src5, src8);
src9 += src5;
src1 = src9;
VSHF_B2_UB(src6, src7, src8, src9, mask0, mask0, dst0, dst1);
dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0);
out0 = __msa_copy_s_d((v2i64) dst0, 0);
out1 = __msa_copy_s_w((v4i32) dst0, 2);
SD(out0, nxt);
nxt += 8;
SW(out1, nxt);
nxt += 4;
}
}
void png_read_filter_row_paeth4_msa(png_row_infop row_info,
png_bytep row,
png_const_bytep prev_row)
{
int32_t count, rp_end;
png_bytep nxt;
png_const_bytep prev_nxt;
int32_t inp0, inp1, res0;
v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9;
v16u8 src10, src11, src12, src13, dst0, dst1;
v8i16 vec0, vec1, vec2;
v16u8 zero = { 0 };
nxt = row;
prev_nxt = prev_row;
inp0 = LW(nxt);
inp1 = LW(prev_nxt);
prev_nxt += 4;
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
src1 += src0;
res0 = __msa_copy_s_w((v4i32) src1, 0);
SW(res0, nxt);
nxt += 4;
/* Remainder */
rp_end = row_info->rowbytes - 4;
for (count = 0; count < rp_end; count += 16)
{
src2 = LD_UB(prev_nxt);
prev_nxt += 16;
src6 = LD_UB(prev_row);
prev_row += 16;
src10 = LD_UB(nxt);
SLDI_B3_0_UB(src2, src6, src10, src3, src7, src11, 4);
SLDI_B3_0_UB(src2, src6, src10, src4, src8, src12, 8);
SLDI_B3_0_UB(src2, src6, src10, src5, src9, src13, 12);
ILVR_B2_SH(src2, src6, src1, src6, vec0, vec1);
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
vec2 = vec0 + vec1;
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
CMP_AND_SELECT(vec0, vec1, vec2, src1, src2, src6, src10);
ILVR_B2_SH(src3, src7, src10, src7, vec0, vec1);
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
vec2 = vec0 + vec1;
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
CMP_AND_SELECT(vec0, vec1, vec2, src10, src3, src7, src11);
ILVR_B2_SH(src4, src8, src11, src8, vec0, vec1);
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
vec2 = vec0 + vec1;
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
CMP_AND_SELECT(vec0, vec1, vec2, src11, src4, src8, src12);
ILVR_B2_SH(src5, src9, src12, src9, vec0, vec1);
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
vec2 = vec0 + vec1;
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
CMP_AND_SELECT(vec0, vec1, vec2, src12, src5, src9, src13);
src1 = src13;
ILVEV_W2_UB(src10, src11, src12, src1, dst0, dst1);
dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0);
ST_UB(dst0, nxt);
nxt += 16;
}
}
void png_read_filter_row_paeth3_msa(png_row_infop row_info,
png_bytep row,
png_const_bytep prev_row)
{
int32_t count, rp_end;
png_bytep nxt;
png_const_bytep prev_nxt;
int64_t out0;
int32_t inp0, inp1, out1;
int16_t out2;
v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1;
v16u8 src10, src11, src12, src13;
v8i16 vec0, vec1, vec2;
v16u8 zero = { 0 };
v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 };
nxt = row;
prev_nxt = prev_row;
inp0 = LW(nxt);
inp1 = LW(prev_nxt);
prev_nxt += 3;
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
src1 += src0;
out2 = __msa_copy_s_h((v8i16) src1, 0);
SH(out2, nxt);
nxt += 2;
nxt[0] = src1[2];
nxt++;
/* Remainder */
rp_end = row_info->rowbytes - 3;
for (count = 0; count < rp_end; count += 12)
{
src2 = LD_UB(prev_nxt);
prev_nxt += 12;
src6 = LD_UB(prev_row);
prev_row += 12;
src10 = LD_UB(nxt);
SLDI_B3_0_UB(src2, src6, src10, src3, src7, src11, 3);
SLDI_B3_0_UB(src2, src6, src10, src4, src8, src12, 6);
SLDI_B3_0_UB(src2, src6, src10, src5, src9, src13, 9);
ILVR_B2_SH(src2, src6, src1, src6, vec0, vec1);
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
vec2 = vec0 + vec1;
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
CMP_AND_SELECT(vec0, vec1, vec2, src1, src2, src6, src10);
ILVR_B2_SH(src3, src7, src10, src7, vec0, vec1);
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
vec2 = vec0 + vec1;
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
CMP_AND_SELECT(vec0, vec1, vec2, src10, src3, src7, src11);
ILVR_B2_SH(src4, src8, src11, src8, vec0, vec1);
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
vec2 = vec0 + vec1;
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
CMP_AND_SELECT(vec0, vec1, vec2, src11, src4, src8, src12);
ILVR_B2_SH(src5, src9, src12, src9, vec0, vec1);
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
vec2 = vec0 + vec1;
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
CMP_AND_SELECT(vec0, vec1, vec2, src12, src5, src9, src13);
src1 = src13;
VSHF_B2_UB(src10, src11, src12, src13, mask0, mask0, dst0, dst1);
dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0);
out0 = __msa_copy_s_d((v2i64) dst0, 0);
out1 = __msa_copy_s_w((v4i32) dst0, 2);
SD(out0, nxt);
nxt += 8;
SW(out1, nxt);
nxt += 4;
}
}
#endif /* PNG_MIPS_MSA_OPT > 0 */
#endif /* PNG_MIPS_MSA_IMPLEMENTATION == 1 (intrinsics) */
#endif /* READ */
+127
View File
@@ -0,0 +1,127 @@
/* mips_init.c - MSA optimised filter functions
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2016 Glenn Randers-Pehrson
* Written by Mandar Sahastrabuddhe, 2016.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
* called.
*/
#define _POSIX_SOURCE 1
#include <stdio.h>
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
#if PNG_MIPS_MSA_OPT > 0
#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED /* Do run-time checks */
/* WARNING: it is strongly recommended that you do not build libpng with
* run-time checks for CPU features if at all possible. In the case of the MIPS
* MSA instructions there is no processor-specific way of detecting the
* presence of the required support, therefore run-time detection is extremely
* OS specific.
*
* You may set the macro PNG_MIPS_MSA_FILE to the file name of file containing
* a fragment of C source code which defines the png_have_msa function. There
* are a number of implementations in contrib/mips-msa, but the only one that
* has partial support is contrib/mips-msa/linux.c - a generic Linux
* implementation which reads /proc/cpufino.
*/
#ifndef PNG_MIPS_MSA_FILE
# ifdef __linux__
# define PNG_MIPS_MSA_FILE "contrib/mips-msa/linux.c"
# endif
#endif
#ifdef PNG_MIPS_MSA_FILE
#include <signal.h> /* for sig_atomic_t */
static int png_have_msa(png_structp png_ptr);
#include PNG_MIPS_MSA_FILE
#else /* PNG_MIPS_MSA_FILE */
# error "PNG_MIPS_MSA_FILE undefined: no support for run-time MIPS MSA checks"
#endif /* PNG_MIPS_MSA_FILE */
#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
#endif
void
png_init_filter_functions_msa(png_structp pp, unsigned int bpp)
{
/* The switch statement is compiled in for MIPS_MSA_API, the call to
* png_have_msa is compiled in for MIPS_MSA_CHECK. If both are defined
* the check is only performed if the API has not set the MSA option on
* or off explicitly. In this case the check controls what happens.
*/
#ifdef PNG_MIPS_MSA_API_SUPPORTED
switch ((pp->options >> PNG_MIPS_MSA) & 3)
{
case PNG_OPTION_UNSET:
/* Allow the run-time check to execute if it has been enabled -
* thus both API and CHECK can be turned on. If it isn't supported
* this case will fall through to the 'default' below, which just
* returns.
*/
#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED
{
static volatile sig_atomic_t no_msa = -1; /* not checked */
if (no_msa < 0)
no_msa = !png_have_msa(pp);
if (no_msa)
return;
}
#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */
break;
default: /* OFF or INVALID */
return;
case PNG_OPTION_ON:
/* Option turned on */
break;
}
/* IMPORTANT: any new external functions used here must be declared using
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
* 'prefix' option to configure works:
*
* ./configure --with-libpng-prefix=foobar_
*
* Verify you have got this right by running the above command, doing a build
* and examining pngprefix.h; it must contain a #define for every external
* function you add. (Notice that this happens automatically for the
* initialization function.)
*/
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_msa;
if (bpp == 3)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_msa;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_msa;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_msa;
}
else if (bpp == 4)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_msa;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_msa;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_msa;
}
#else
(void)pp;
(void)bpp;
#endif /* PNG_MIPS_MSA_API_SUPPORTED */
}
#endif /* PNG_MIPS_MSA_OPT > 0 */
#endif /* READ */
+53
View File
@@ -0,0 +1,53 @@
diff --git a/3rdparty/libpng/mips/mips_init.c b/3rdparty/libpng/mips/mips_init.c
index 8dd283deef..6a061cccfa 100644
--- a/3rdparty/libpng/mips/mips_init.c
+++ b/3rdparty/libpng/mips/mips_init.c
@@ -73,7 +73,6 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp)
* this case will fall through to the 'default' below, which just
* returns.
*/
-#endif /* PNG_MIPS_MSA_API_SUPPORTED */
#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED
{
static volatile sig_atomic_t no_msa = -1; /* not checked */
@@ -84,12 +83,9 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp)
if (no_msa)
return;
}
-#ifdef PNG_MIPS_MSA_API_SUPPORTED
- break;
-#endif
#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */
+ break;
-#ifdef PNG_MIPS_MSA_API_SUPPORTED
default: /* OFF or INVALID */
return;
@@ -97,8 +93,6 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp)
/* Option turned on */
break;
}
-#endif
-
/* IMPORTANT: any new external functions used here must be declared using
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
* 'prefix' option to configure works:
@@ -118,13 +112,16 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp)
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_msa;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_msa;
}
-
else if (bpp == 4)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_msa;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_msa;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_msa;
}
+#else
+ (void)pp;
+ (void)bpp;
+#endif /* PNG_MIPS_MSA_API_SUPPORTED */
}
#endif /* PNG_MIPS_MSA_OPT > 0 */
#endif /* READ */
+22
View File
@@ -0,0 +1,22 @@
diff --git a/3rdparty/libwebp/src/dsp/msa_macro.h b/3rdparty/libwebp/src/dsp/msa_macro.h
index de026a1d9e..a16c0bb300 100644
--- a/3rdparty/libwebp/src/dsp/msa_macro.h
+++ b/3rdparty/libwebp/src/dsp/msa_macro.h
@@ -73,7 +73,7 @@
static inline TYPE FUNC_NAME(const void* const psrc) { \
const uint8_t* const psrc_m = (const uint8_t*)psrc; \
TYPE val_m; \
- asm volatile ( \
+ __asm__ volatile ( \
"" #INSTR " %[val_m], %[psrc_m] \n\t" \
: [val_m] "=r" (val_m) \
: [psrc_m] "m" (*psrc_m)); \
@@ -86,7 +86,7 @@
static inline void FUNC_NAME(TYPE val, void* const pdst) { \
uint8_t* const pdst_m = (uint8_t*)pdst; \
TYPE val_m = val; \
- asm volatile ( \
+ __asm__ volatile ( \
" " #INSTR " %[val_m], %[pdst_m] \n\t" \
: [pdst_m] "=m" (*pdst_m) \
: [val_m] "r" (val_m)); \
+2 -2
View File
@@ -73,7 +73,7 @@
static inline TYPE FUNC_NAME(const void* const psrc) { \
const uint8_t* const psrc_m = (const uint8_t*)psrc; \
TYPE val_m; \
asm volatile ( \
__asm__ volatile ( \
"" #INSTR " %[val_m], %[psrc_m] \n\t" \
: [val_m] "=r" (val_m) \
: [psrc_m] "m" (*psrc_m)); \
@@ -86,7 +86,7 @@
static inline void FUNC_NAME(TYPE val, void* const pdst) { \
uint8_t* const pdst_m = (uint8_t*)pdst; \
TYPE val_m = val; \
asm volatile ( \
__asm__ volatile ( \
" " #INSTR " %[val_m], %[pdst_m] \n\t" \
: [pdst_m] "=m" (*pdst_m) \
: [val_m] "r" (val_m)); \
+11 -5
View File
@@ -487,6 +487,7 @@ OCV_OPTION(CV_DISABLE_OPTIMIZATION "Disable explicit optimized code (dispatch
OCV_OPTION(CV_TRACE "Enable OpenCV code trace" ON)
OCV_OPTION(OPENCV_GENERATE_SETUPVARS "Generate setup_vars* scripts" ON IF (NOT ANDROID AND NOT APPLE_FRAMEWORK) )
OCV_OPTION(ENABLE_CONFIG_VERIFICATION "Fail build if actual configuration doesn't match requested (WITH_XXX != HAVE_XXX)" OFF)
OCV_OPTION(OPENCV_ENABLE_MEMALIGN "Enable posix_memalign or memalign usage" ON)
OCV_OPTION(ENABLE_PYLINT "Add target with Pylint checks" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )
OCV_OPTION(ENABLE_FLAKE8 "Add target with Python flake8 checker" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )
@@ -635,10 +636,15 @@ if(UNIX)
set(HAVE_PTHREAD 1)
endif()
CHECK_SYMBOL_EXISTS(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN)
CHECK_INCLUDE_FILE(malloc.h HAVE_MALLOC_H)
if(HAVE_MALLOC_H)
CHECK_SYMBOL_EXISTS(memalign malloc.h HAVE_MEMALIGN)
if(OPENCV_ENABLE_MEMALIGN)
CHECK_SYMBOL_EXISTS(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN)
CHECK_INCLUDE_FILE(malloc.h HAVE_MALLOC_H)
if(HAVE_MALLOC_H)
CHECK_SYMBOL_EXISTS(memalign malloc.h HAVE_MEMALIGN)
endif()
# TODO:
# - _aligned_malloc() on Win32
# - std::aligned_alloc() C++17 / C11
endif()
endif()
@@ -1571,7 +1577,7 @@ if(FLAKE8_FOUND AND FLAKE8_EXECUTABLE)
endif()
# ========================== java ==========================
if(BUILD_JAVA OR BUILD_opencv_java)
if(BUILD_JAVA)
status("")
status(" Java:" BUILD_FAT_JAVA_LIB THEN "export all functions" ELSE "")
status(" ant:" ANT_EXECUTABLE THEN "${ANT_EXECUTABLE} (ver ${ANT_VERSION})" ELSE NO)
+17 -9
View File
@@ -5,13 +5,15 @@
# AVX / AVX2 / AVX_512F
# FMA3
#
# AVX512 details: https://en.wikipedia.org/wiki/AVX-512#CPUs_with_AVX-512
#
# CPU features groups:
# AVX512_COMMON (Common instructions AVX-512F/CD for all CPUs that support AVX-512)
# AVX512_KNL (Knights Landing with AVX-512F/CD/ER/PF)
# AVX512_KNM (Knights Mill with AVX-512F/CD/ER/PF/4FMAPS/4VNNIW/VPOPCNTDQ)
# AVX512_SKX (Skylake-X with AVX-512F/CD/BW/DQ/VL)
# AVX512_CNL (Cannon Lake with AVX-512F/CD/BW/DQ/VL/IFMA/VBMI)
# AVX512_CEL (Cascade Lake with AVX-512F/CD/BW/DQ/VL/IFMA/VBMI/VNNI)
# AVX512_CLX (Cascade Lake with AVX-512F/CD/BW/DQ/VL/VNNI)
# AVX512_ICL (Ice Lake with AVX-512F/CD/BW/DQ/VL/IFMA/VBMI/VNNI/VBMI2/BITALG/VPOPCNTDQ/VPCLMULQDQ*/GFNI*/VAES*)
# ppc64le arch:
@@ -43,8 +45,9 @@
# CPU_{opt}_ENABLED_DEFAULT=ON/OFF - has compiler support without additional flag (CPU_BASELINE_DETECT=ON only)
set(CPU_ALL_OPTIMIZATIONS "SSE;SSE2;SSE3;SSSE3;SSE4_1;SSE4_2;POPCNT;AVX;FP16;AVX2;FMA3;AVX_512F")
list(APPEND CPU_ALL_OPTIMIZATIONS "AVX512_COMMON;AVX512_KNL;AVX512_KNM;AVX512_SKX;AVX512_CNL;AVX512_CEL;AVX512_ICL")
list(APPEND CPU_ALL_OPTIMIZATIONS "AVX512_COMMON;AVX512_KNL;AVX512_KNM;AVX512_SKX;AVX512_CNL;AVX512_CLX;AVX512_ICL")
list(APPEND CPU_ALL_OPTIMIZATIONS NEON VFPV3 FP16)
list(APPEND CPU_ALL_OPTIMIZATIONS MSA)
list(APPEND CPU_ALL_OPTIMIZATIONS VSX VSX3)
list(REMOVE_DUPLICATES CPU_ALL_OPTIMIZATIONS)
@@ -162,15 +165,15 @@ elseif(" ${CMAKE_CXX_FLAGS} " MATCHES " -march=native | -xHost | /QxHost ")
endif()
if(X86 OR X86_64)
ocv_update(CPU_KNOWN_OPTIMIZATIONS "SSE;SSE2;SSE3;SSSE3;SSE4_1;POPCNT;SSE4_2;FP16;FMA3;AVX;AVX2;AVX_512F;AVX512_COMMON;AVX512_KNL;AVX512_KNM;AVX512_SKX;AVX512_CNL;AVX512_CEL;AVX512_ICL")
ocv_update(CPU_KNOWN_OPTIMIZATIONS "SSE;SSE2;SSE3;SSSE3;SSE4_1;POPCNT;SSE4_2;FP16;FMA3;AVX;AVX2;AVX_512F;AVX512_COMMON;AVX512_KNL;AVX512_KNM;AVX512_SKX;AVX512_CNL;AVX512_CLX;AVX512_ICL")
ocv_update(CPU_AVX512_COMMON_GROUP "AVX_512F;AVX_512CD")
ocv_update(CPU_AVX512_KNL_GROUP "AVX512_COMMON;AVX512_KNL_EXTRA")
ocv_update(CPU_AVX512_KNM_GROUP "AVX512_KNL;AVX512_KNM_EXTRA;AVX_512VPOPCNTDQ")
ocv_update(CPU_AVX512_SKX_GROUP "AVX512_COMMON;AVX_512VL;AVX_512BW;AVX_512DQ")
ocv_update(CPU_AVX512_CNL_GROUP "AVX512_SKX;AVX_512IFMA;AVX_512VBMI")
ocv_update(CPU_AVX512_CEL_GROUP "AVX512_CNL;AVX_512VNNI")
ocv_update(CPU_AVX512_ICL_GROUP "AVX512_CEL;AVX_512VBMI2;AVX_512BITALG;AVX_512VPOPCNTDQ") # ? VPCLMULQDQ, GFNI, VAES
ocv_update(CPU_AVX512_CLX_GROUP "AVX512_SKX;AVX_512VNNI")
ocv_update(CPU_AVX512_ICL_GROUP "AVX512_SKX;AVX_512IFMA;AVX_512VBMI;AVX_512VNNI;AVX_512VBMI2;AVX_512BITALG;AVX_512VPOPCNTDQ") # ? VPCLMULQDQ, GFNI, VAES
ocv_update(CPU_SSE_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_sse.cpp")
ocv_update(CPU_SSE2_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_sse2.cpp")
@@ -188,12 +191,12 @@ if(X86 OR X86_64)
ocv_update(CPU_AVX512_KNM_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_avx512knm.cpp")
ocv_update(CPU_AVX512_SKX_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_avx512skx.cpp")
ocv_update(CPU_AVX512_CNL_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_avx512cnl.cpp")
ocv_update(CPU_AVX512_CEL_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_avx512cel.cpp")
ocv_update(CPU_AVX512_CLX_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_avx512clx.cpp")
ocv_update(CPU_AVX512_ICL_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_avx512icl.cpp")
if(NOT OPENCV_CPU_OPT_IMPLIES_IGNORE)
ocv_update(CPU_AVX512_ICL_IMPLIES "AVX512_CEL")
ocv_update(CPU_AVX512_CEL_IMPLIES "AVX512_CNL")
ocv_update(CPU_AVX512_ICL_IMPLIES "AVX512_SKX")
ocv_update(CPU_AVX512_CLX_IMPLIES "AVX512_SKX")
ocv_update(CPU_AVX512_CNL_IMPLIES "AVX512_SKX")
ocv_update(CPU_AVX512_SKX_IMPLIES "AVX512_COMMON")
ocv_update(CPU_AVX512_KNM_IMPLIES "AVX512_KNL")
@@ -250,7 +253,7 @@ if(X86 OR X86_64)
ocv_intel_compiler_optimization_option(AVX512_KNM "-xKNM" "/Qx:KNM")
ocv_intel_compiler_optimization_option(AVX512_SKX "-xSKYLAKE-AVX512" "/Qx:SKYLAKE-AVX512")
ocv_intel_compiler_optimization_option(AVX512_CNL "-xCANNONLAKE" "/Qx:CANNONLAKE")
ocv_intel_compiler_optimization_option(AVX512_CEL "-xCASCADELAKE" "/Qx:CASCADELAKE")
ocv_intel_compiler_optimization_option(AVX512_CLX "-xCASCADELAKE" "/Qx:CASCADELAKE")
ocv_intel_compiler_optimization_option(AVX512_ICL "-xICELAKE-CLIENT" "/Qx:ICELAKE-CLIENT")
elseif(CV_GCC OR CV_CLANG)
ocv_update(CPU_AVX2_FLAGS_ON "-mavx2")
@@ -339,6 +342,11 @@ elseif(ARM OR AARCH64)
ocv_update(CPU_FP16_IMPLIES "NEON")
set(CPU_BASELINE "NEON;FP16" CACHE STRING "${HELP_CPU_BASELINE}")
endif()
elseif(MIPS)
ocv_update(CPU_MSA_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_msa.cpp")
ocv_update(CPU_KNOWN_OPTIMIZATIONS "MSA")
ocv_update(CPU_MSA_FLAGS_ON "-mmsa")
set(CPU_BASELINE "MSA" CACHE STRING "${HELP_CPU_BASELINE}")
elseif(PPC64LE)
ocv_update(CPU_KNOWN_OPTIMIZATIONS "VSX;VSX3")
ocv_update(CPU_VSX_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_vsx.cpp")
+2
View File
@@ -100,6 +100,8 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
set(PPC64LE 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64")
set(PPC64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(mips.*|MIPS.*)")
set(MIPS 1)
endif()
# Workaround for 32-bit operating systems on x86_64/aarch64 processor
+2 -2
View File
@@ -87,9 +87,9 @@ endif()
if(INF_ENGINE_TARGET)
if(NOT INF_ENGINE_RELEASE)
message(WARNING "InferenceEngine version have not been set, 2019R2 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
message(WARNING "InferenceEngine version have not been set, 2019R3 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
endif()
set(INF_ENGINE_RELEASE "2019020000" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2018R2.0.2 -> 2018020002)")
set(INF_ENGINE_RELEASE "2019030000" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2018R2.0.2 -> 2018020002)")
set_target_properties(${INF_ENGINE_TARGET} PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
)
+16 -7
View File
@@ -22,6 +22,9 @@ set(OPENCV_DOWNLOAD_PATH "${OpenCV_SOURCE_DIR}/.cache" CACHE PATH "${HELP_OPENCV
set(OPENCV_DOWNLOAD_LOG "${OpenCV_BINARY_DIR}/CMakeDownloadLog.txt")
set(OPENCV_DOWNLOAD_WITH_CURL "${OpenCV_BINARY_DIR}/download_with_curl.sh")
set(OPENCV_DOWNLOAD_WITH_WGET "${OpenCV_BINARY_DIR}/download_with_wget.sh")
set(OPENCV_DOWNLOAD_TRIES_LIST 1 CACHE STRING "List of download tries") # a list
set(OPENCV_DOWNLOAD_PARAMS INACTIVITY_TIMEOUT 60 TIMEOUT 600 CACHE STRING "Download parameters to be passed to file(DOWNLAOD ...)")
mark_as_advanced(OPENCV_DOWNLOAD_TRIES_LIST OPENCV_DOWNLOAD_PARAMS)
# Init download cache directory and log file and helper scripts
if(NOT EXISTS "${OPENCV_DOWNLOAD_PATH}")
@@ -154,11 +157,17 @@ function(ocv_download)
# Download
if(NOT EXISTS "${CACHE_CANDIDATE}")
ocv_download_log("#cmake_download \"${CACHE_CANDIDATE}\" \"${DL_URL}\"")
file(DOWNLOAD "${DL_URL}" "${CACHE_CANDIDATE}"
INACTIVITY_TIMEOUT 60
TIMEOUT 600
STATUS status
LOG __log)
foreach(try ${OPENCV_DOWNLOAD_TRIES_LIST})
ocv_download_log("#try ${try}")
file(DOWNLOAD "${DL_URL}" "${CACHE_CANDIDATE}"
STATUS status
LOG __log
${OPENCV_DOWNLOAD_PARAMS})
if(status EQUAL 0)
break()
endif()
message(STATUS "Try ${try} failed")
endforeach()
if(NOT OPENCV_SKIP_FILE_DOWNLOAD_DUMP) # workaround problem with old CMake versions: "Invalid escape sequence"
string(LENGTH "${__log}" __log_length)
if(__log_length LESS 65536)
@@ -195,8 +204,8 @@ For details please refer to the download log file:
${OPENCV_DOWNLOAD_LOG}
")
# write helper scripts for failed downloads
file(APPEND "${OPENCV_DOWNLOAD_WITH_CURL}" "curl --output \"${CACHE_CANDIDATE}\" \"${DL_URL}\"\n")
file(APPEND "${OPENCV_DOWNLOAD_WITH_WGET}" "wget -O \"${CACHE_CANDIDATE}\" \"${DL_URL}\"\n")
file(APPEND "${OPENCV_DOWNLOAD_WITH_CURL}" "curl --create-dirs --output \"${CACHE_CANDIDATE}\" \"${DL_URL}\"\n")
file(APPEND "${OPENCV_DOWNLOAD_WITH_WGET}" "mkdir -p $(dirname ${CACHE_CANDIDATE}) && wget -O \"${CACHE_CANDIDATE}\" \"${DL_URL}\"\n")
return()
endif()
+23 -14
View File
@@ -29,6 +29,16 @@ macro(ippiw_debugmsg MESSAGE)
message(STATUS "${MESSAGE}")
endif()
endmacro()
macro(ippiw_done)
foreach(__file ${IPP_IW_LICENSE_FILES})
if(EXISTS "${__file}")
ocv_install_3rdparty_licenses(ippiw "${__file}")
endif()
endforeach()
return()
endmacro()
file(TO_CMAKE_PATH "${IPPROOT}" IPPROOT)
# This function detects Intel IPP Integration Wrappers version by analyzing .h file
@@ -81,7 +91,7 @@ macro(ippiw_setup PATH BUILD)
if(EXISTS "${FILE}")
set(HAVE_IPP_IW_LL 1)
endif()
return()
ippiw_done()
else()
ippiw_debugmsg("sources\tno")
endif()
@@ -120,7 +130,7 @@ macro(ippiw_setup PATH BUILD)
if(EXISTS "${FILE}")
set(HAVE_IPP_IW_LL 1)
endif()
return()
ippiw_done()
else()
ippiw_debugmsg("binaries\tno")
endif()
@@ -147,14 +157,12 @@ if(BUILD_IPP_IW)
ippiw_setup("${OpenCV_SOURCE_DIR}/3rdparty/ippiw" 1)
set(IPPIW_ROOT "${IPPROOT}/../iw")
ocv_install_3rdparty_licenses(ippiw
"${IPPIW_ROOT}/../support.txt"
"${IPPIW_ROOT}/../third-party-programs.txt")
if(WIN32)
ocv_install_3rdparty_licenses(ippiw "${IPPIW_ROOT}/../EULA.rtf")
else()
ocv_install_3rdparty_licenses(ippiw "${IPPIW_ROOT}/../EULA.txt")
endif()
set(IPP_IW_LICENSE_FILES ${IPP_IW_LICENSE_FILES_EXTRA}
"${IPPIW_ROOT}/../support.txt"
"${IPPIW_ROOT}/../third-party-programs.txt"
"${IPPIW_ROOT}/../EULA.rtf"
"${IPPIW_ROOT}/../EULA.txt"
)
# Package sources
get_filename_component(__PATH "${IPPROOT}/../iw/" ABSOLUTE)
@@ -167,10 +175,11 @@ if(BUILD_IPP_IW)
include("${OpenCV_SOURCE_DIR}/3rdparty/ippicv/ippicv.cmake")
download_ippicv(TEMP_ROOT)
set(IPPIW_ROOT "${TEMP_ROOT}/iw/")
ocv_install_3rdparty_licenses(ippiw
"${IPPIW_ROOT}/../EULA.txt"
"${IPPIW_ROOT}/../support.txt"
"${IPPIW_ROOT}/../third-party-programs.txt")
set(IPP_IW_LICENSE_FILES ${IPP_IW_LICENSE_FILES_EXTRA}
"${IPPIW_ROOT}/../EULA.txt"
"${IPPIW_ROOT}/../support.txt"
"${IPPIW_ROOT}/../third-party-programs.txt"
)
ippiw_setup("${IPPIW_ROOT}" 1)
endif()
+4 -2
View File
@@ -122,8 +122,10 @@ endif()
# Part 3/3: ${BIN_DIR}/win-install/OpenCVConfig.cmake -> For use within binary installers/packages
# --------------------------------------------------------------------------------------------
if(WIN32)
if(CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
ocv_gen_config("${CMAKE_BINARY_DIR}/win-install" "${OPENCV_LIB_INSTALL_PATH}" "OpenCVConfig.root-WIN32.cmake.in")
if(CMAKE_HOST_SYSTEM_NAME MATCHES Windows AND NOT OPENCV_SKIP_CMAKE_ROOT_CONFIG)
ocv_gen_config("${CMAKE_BINARY_DIR}/win-install"
"${OPENCV_INSTALL_BINARIES_PREFIX}${OPENCV_INSTALL_BINARIES_SUFFIX}"
"OpenCVConfig.root-WIN32.cmake.in")
else()
ocv_gen_config("${CMAKE_BINARY_DIR}/win-install" "" "")
endif()
+8 -8
View File
@@ -23,15 +23,15 @@ if(ANDROID)
elseif(WIN32 AND CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
if(DEFINED OpenCV_RUNTIME AND DEFINED OpenCV_ARCH)
set(_prefix "${OpenCV_ARCH}/${OpenCV_RUNTIME}/")
ocv_update(OPENCV_INSTALL_BINARIES_PREFIX "${OpenCV_ARCH}/${OpenCV_RUNTIME}/")
else()
message(STATUS "Can't detect runtime and/or arch")
set(_prefix "")
ocv_update(OPENCV_INSTALL_BINARIES_PREFIX "")
endif()
if(OpenCV_STATIC)
set(_suffix "staticlib")
ocv_update(OPENCV_INSTALL_BINARIES_SUFFIX "staticlib")
else()
set(_suffix "lib")
ocv_update(OPENCV_INSTALL_BINARIES_SUFFIX "lib")
endif()
if(INSTALL_CREATE_DISTRIB)
set(_jni_suffix "/${OpenCV_ARCH}")
@@ -39,12 +39,12 @@ elseif(WIN32 AND CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
set(_jni_suffix "")
endif()
ocv_update(OPENCV_BIN_INSTALL_PATH "${_prefix}bin")
ocv_update(OPENCV_BIN_INSTALL_PATH "${OPENCV_INSTALL_BINARIES_PREFIX}bin")
ocv_update(OPENCV_TEST_INSTALL_PATH "${OPENCV_BIN_INSTALL_PATH}")
ocv_update(OPENCV_SAMPLES_BIN_INSTALL_PATH "${_prefix}samples")
ocv_update(OPENCV_LIB_INSTALL_PATH "${_prefix}${_suffix}")
ocv_update(OPENCV_SAMPLES_BIN_INSTALL_PATH "${OPENCV_INSTALL_BINARIES_PREFIX}samples")
ocv_update(OPENCV_LIB_INSTALL_PATH "${OPENCV_INSTALL_BINARIES_PREFIX}${OPENCV_INSTALL_BINARIES_SUFFIX}")
ocv_update(OPENCV_LIB_ARCHIVE_INSTALL_PATH "${OPENCV_LIB_INSTALL_PATH}")
ocv_update(OPENCV_3P_LIB_INSTALL_PATH "${_prefix}staticlib")
ocv_update(OPENCV_3P_LIB_INSTALL_PATH "${OPENCV_INSTALL_BINARIES_PREFIX}staticlib")
ocv_update(OPENCV_CONFIG_INSTALL_PATH ".")
ocv_update(OPENCV_INCLUDE_INSTALL_PATH "include")
ocv_update(OPENCV_OTHER_INSTALL_PATH "etc")
+1 -1
View File
@@ -2,7 +2,7 @@
static int test()
{
std::atomic<int> x;
std::atomic<long long> x;
return x;
}
+1
View File
@@ -6,5 +6,6 @@ void test()
{
int data[8] = {0,0,0,0, 0,0,0,0};
__m256i a = _mm256_loadu_si256((const __m256i *)data);
__m256i b = _mm256_bslli_epi128(a, 1); // available in GCC 4.9.3+
}
int main() { return 0; }
@@ -3,9 +3,9 @@
void test()
{
__m512i a, b, c;
a = _mm512_dpwssd_epi32(a, b, c);
a = _mm512_dpwssd_epi32(a, b, c); // VNNI
}
#else
#error "AVX512-CEL is not supported"
#error "AVX512-CLX is not supported"
#endif
int main() { return 0; }
int main() { return 0; }
+4 -3
View File
@@ -3,9 +3,10 @@
void test()
{
__m512i a, b, c;
a = _mm512_popcnt_epi8(a);
a = _mm512_shrdv_epi64(a, b, c);
a = _mm512_popcnt_epi64(a);
a = _mm512_popcnt_epi8(a); // BITALG
a = _mm512_shrdv_epi64(a, b, c); // VBMI2
a = _mm512_popcnt_epi64(a); // VPOPCNTDQ
a = _mm512_dpwssd_epi32(a, b, c); // VNNI
}
#else
#error "AVX512-ICL is not supported"
+23
View File
@@ -0,0 +1,23 @@
#include <stdio.h>
#if defined(__mips_msa)
# include <msa.h>
# define CV_MSA 1
#endif
#if defined CV_MSA
int test()
{
const float src[] = { 0.0f, 0.0f, 0.0f, 0.0f };
v4f32 val = (v4f32)__msa_ld_w((const float*)(src), 0);
return __msa_copy_s_w(__builtin_msa_ftint_s_w (val), 0);
}
#else
#error "MSA is not supported"
#endif
int main()
{
printf("%d\n", test());
return 0;
}
@@ -107,6 +107,90 @@ Building OpenCV.js from Source
@note
It requires `node` installed in your development environment.
-# [optional] To build `opencv.js` with threads optimization, append `--threads` option.
For example:
@code{.bash}
python ./platforms/js/build_js.py build_js --build_wasm --threads
@endcode
The default threads number is the logic core number of your device. You can use `cv.parallel_pthreads_set_threads_num(number)` to set threads number by yourself and use `cv.parallel_pthreads_get_threads_num()` to get the current threads number.
@note
You should build wasm version of `opencv.js` if you want to enable this optimization. And the threads optimization only works in browser, not in node.js. You need to enable the `WebAssembly threads support` feature first with your browser. For example, if you use Chrome, please enable this flag in chrome://flags.
-# [optional] To build `opencv.js` with wasm simd optimization, append `--simd` option.
For example:
@code{.bash}
python ./platforms/js/build_js.py build_js --build_wasm --simd
@endcode
The simd optimization is experimental as wasm simd is still in development.
@note
Now only emscripten LLVM upstream backend supports wasm simd, refering to https://emscripten.org/docs/porting/simd.html. So you need to setup upstream backend environment with the following command first:
@code{.bash}
./emsdk update
./emsdk install latest-upstream
./emsdk activate latest-upstream
source ./emsdk_env.sh
@endcode
@note
You should build wasm version of `opencv.js` if you want to enable this optimization. For browser, you need to enable the `WebAssembly SIMD support` feature first. For example, if you use Chrome, please enable this flag in chrome://flags. For Node.js, you need to run script with flag `--experimental-wasm-simd`.
@note
The simd version of `opencv.js` built by latest LLVM upstream may not work with the stable browser or old version of Node.js. Please use the latest version of unstable browser or Node.js to get new features, like `Chrome Dev`.
-# [optional] To build wasm intrinsics tests, append `--build_wasm_intrin_test` option.
For example:
@code{.bash}
python ./platforms/js/build_js.py build_js --build_wasm --simd --build_wasm_intrin_test
@endcode
For wasm intrinsics tests, you can use the following function to test all the cases:
@code{.js}
cv.test_hal_intrin_all()
@endcode
And the failed cases will be logged in the JavaScript debug console.
If you only want to test single data type of wasm intrinsics, you can use the following functions:
@code{.js}
cv.test_hal_intrin_uint8()
cv.test_hal_intrin_int8()
cv.test_hal_intrin_uint16()
cv.test_hal_intrin_int16()
cv.test_hal_intrin_uint32()
cv.test_hal_intrin_int32()
cv.test_hal_intrin_uint64()
cv.test_hal_intrin_int64()
cv.test_hal_intrin_float32()
cv.test_hal_intrin_float64()
@endcode
-# [optional] To build performance tests, append `--build_perf` option.
For example:
@code{.bash}
python ./platforms/js/build_js.py build_js --build_perf
@endcode
To run performance tests, launch a local web server in \<build_dir\>/bin folder. For example, node http-server which serves on `localhost:8080`.
There are some kernels now in the performance test like `cvtColor`, `resize` and `threshold`. For example, if you want to test `threshold`, please navigate the web browser to `http://localhost:8080/perf/perf_imgproc/perf_threshold.html`. You need to input the test parameter like `(1920x1080, CV_8UC1, THRESH_BINARY)`, and then click the `Run` button to run the case. And if you don't input the parameter, it will run all the cases of this kernel.
You can also run tests using Node.js.
For example, run `threshold` with parameter `(1920x1080, CV_8UC1, THRESH_BINARY)`:
@code{.sh}
cd bin/perf
npm install
node perf_threshold.js --test_param_filter="(1920x1080, CV_8UC1, THRESH_BINARY)"
@endcode
Building OpenCV.js with Docker
---------------------------------------
@@ -117,14 +201,41 @@ So, make sure [docker](https://www.docker.com/) is installed in your system and
@code{.bash}
git clone https://github.com/opencv/opencv.git
cd opencv
docker run --rm --workdir /code -v "$PWD":/code "trzeci/emscripten:latest" python ./platforms/js/build_js.py build_js
docker run --rm --workdir /code -v "$PWD":/code "trzeci/emscripten:latest" python ./platforms/js/build_js.py build
@endcode
In Windows use the following PowerShell command:
@code{.bash}
docker run --rm --workdir /code -v "$(get-location):/code" "trzeci/emscripten:latest" python ./platforms/js/build_js.py build_js
docker run --rm --workdir /code -v "$(get-location):/code" "trzeci/emscripten:latest" python ./platforms/js/build_js.py build
@endcode
@note
The example uses latest version of [trzeci/emscripten](https://hub.docker.com/r/trzeci/emscripten) docker container. At this time, the latest version works fine and is `trzeci/emscripten:sdk-tag-1.38.32-64bit`
@warning
The example uses latest version of emscripten. If the build fails you should try a version that is known to work fine which is `1.38.32` using the following command:
@code{.bash}
docker run --rm --workdir /code -v "$PWD":/code "trzeci/emscripten:sdk-tag-1.38.32-64bit" python ./platforms/js/build_js.py build
@endcode
### Building the documentation with Docker
To build the documentation `doxygen` needs to be installed. Create a file named `Dockerfile` with the following content:
```
FROM trzeci/emscripten:sdk-tag-1.38.32-64bit
RUN apt-get update -y
RUN apt-get install -y doxygen
```
Then we build the docker image and name it `opencv-js-doc` with the following command (that needs to be run only once):
@code{.bash}
docker build . -t opencv-js-doc
@endcode
Now run the build command again, this time using the new image and passing `--build_doc`:
@code{.bash}
docker run --rm --workdir /code -v "$PWD":/code "opencv-js-doc" python ./platforms/js/build_js.py build --build_doc
@endcode
@@ -4,7 +4,7 @@ Getting Started with Images {#tutorial_py_image_display}
Goals
-----
- Here, you will learn how to read an image, how to display it and how to save it back
- Here, you will learn how to read an image, how to display it, and how to save it back
- You will learn these functions : **cv.imread()**, **cv.imshow()** , **cv.imwrite()**
- Optionally, you will learn how to display images with Matplotlib
@@ -30,7 +30,7 @@ See the code below:
import numpy as np
import cv2 as cv
# Load an color image in grayscale
# Load a color image in grayscale
img = cv.imread('messi5.jpg',0)
@endcode
@@ -43,7 +43,7 @@ Even if the image path is wrong, it won't throw any error, but `print img` will
Use the function **cv.imshow()** to display an image in a window. The window automatically fits to
the image size.
First argument is a window name which is a string. second argument is our image. You can create as
First argument is a window name which is a string. Second argument is our image. You can create as
many windows as you wish, but with different window names.
@code{.py}
cv.imshow('image',img)
@@ -66,11 +66,11 @@ MUST use it to actually display the image.
specific window, use the function **cv.destroyWindow()** where you pass the exact window name as
the argument.
@note There is a special case where you can already create a window and load image to it later. In
that case, you can specify whether window is resizable or not. It is done with the function
**cv.namedWindow()**. By default, the flag is cv.WINDOW_AUTOSIZE. But if you specify flag to be
cv.WINDOW_NORMAL, you can resize window. It will be helpful when image is too large in dimension
and adding track bar to windows.
@note There is a special case where you can create an empty window and load an image to it later. In
that case, you can specify whether the window is resizable or not. It is done with the function
**cv.namedWindow()**. By default, the flag is cv.WINDOW_AUTOSIZE. But if you specify the flag to be
cv.WINDOW_NORMAL, you can resize window. It will be helpful when an image is too large in dimension
and when adding track bars to windows.
See the code below:
@code{.py}
@@ -91,8 +91,8 @@ This will save the image in PNG format in the working directory.
### Sum it up
Below program loads an image in grayscale, displays it, save the image if you press 's' and exit, or
simply exit without saving if you press ESC key.
Below program loads an image in grayscale, displays it, saves the image if you press 's' and exit, or
simply exits without saving if you press ESC key.
@code{.py}
import numpy as np
import cv2 as cv
@@ -117,7 +117,7 @@ Using Matplotlib
Matplotlib is a plotting library for Python which gives you wide variety of plotting methods. You
will see them in coming articles. Here, you will learn how to display image with Matplotlib. You can
zoom images, save it etc using Matplotlib.
zoom images, save them, etc, using Matplotlib.
@code{.py}
import numpy as np
import cv2 as cv
@@ -5,7 +5,7 @@ Goals
-----
In this tutorial We will learn to setup OpenCV-Python in Ubuntu System.
Below steps are tested for Ubuntu 16.04 (64-bit) and Ubuntu 14.04 (32-bit).
Below steps are tested for Ubuntu 16.04 and 18.04 (both 64-bit).
OpenCV-Python can be installed in Ubuntu in two ways:
- Install from pre-built binaries available in Ubuntu repositories
@@ -62,18 +62,36 @@ We need **CMake** to configure the installation, **GCC** for compilation, **Pyth
```
sudo apt-get install cmake
sudo apt-get install python-dev python-numpy
sudo apt-get install gcc g++
```
to support python2:
Next we need **GTK** support for GUI features, Camera support (libv4l), Media Support
```
sudo apt-get install python-dev python-numpy
```
to support python3:
```
sudo apt-get install python3-dev python3-numpy
```
Next we need **GTK** support for GUI features, Camera support (v4l), Media Support
(ffmpeg, gstreamer) etc.
```
sudo apt-get install gtk2-devel
sudo apt-get install libv4l-devel
sudo apt-get install ffmpeg-devel
sudo apt-get install gstreamer-plugins-base-devel
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev
```
to support gtk2:
```
sudo apt-get install libgtk2.0-dev
```
to support gtk3:
```
sudo apt-get install libgtk-3-dev
```
### Optional Dependencies
@@ -87,14 +105,15 @@ But it may be a little old.
If you want to get latest libraries, you can install development files for system libraries of these formats.
```
sudo apt-get install libpng-devel
sudo apt-get install libjpeg-turbo-devel
sudo apt-get install jasper-devel
sudo apt-get install openexr-devel
sudo apt-get install libtiff-devel
sudo apt-get install libwebp-devel
sudo apt-get install libpng-dev
sudo apt-get install libjpeg-dev
sudo apt-get install libopenexr-dev
sudo apt-get install libtiff-dev
sudo apt-get install libwebp-dev
```
@note If you are using Ubuntu 16.04 you can also install ```libjasper-dev``` to add a system level support for the JPEG2000 format.
### Downloading OpenCV
To download the latest source from OpenCV's [GitHub Repository](https://github.com/opencv/opencv).
@@ -213,7 +213,7 @@ Supported platform: Drive PX 2
-DBUILD_JASPER=OFF \
-DBUILD_ZLIB=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_opencv_java=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_python2=ON \
-DBUILD_opencv_python3=OFF \
-DENABLE_NEON=ON \
@@ -263,7 +263,7 @@ Configuration is slightly different for the Jetson TK1 and the Jetson TX1 system
-DBUILD_JASPER=OFF \
-DBUILD_ZLIB=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_opencv_java=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_python2=ON \
-DBUILD_opencv_python3=OFF \
-DENABLE_NEON=ON \
@@ -300,7 +300,7 @@ __Note:__ This uses CUDA 6.5, not 8.0.
-DBUILD_JASPER=OFF \
-DBUILD_ZLIB=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_opencv_java=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_python2=ON \
-DBUILD_opencv_python3=OFF \
-DENABLE_PRECOMPILED_HEADERS=OFF \
@@ -345,7 +345,7 @@ The configuration options given to `cmake` below are targeted towards the functi
-DBUILD_JASPER=OFF \
-DBUILD_ZLIB=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_opencv_java=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_python2=ON \
-DBUILD_opencv_python3=OFF \
-DWITH_OPENCL=OFF \
@@ -476,7 +476,7 @@ For DRIVE PX 2:
-DBUILD_JASPER=OFF \
-DBUILD_ZLIB=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_opencv_java=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_nonfree=OFF \
-DBUILD_opencv_python=ON \
-DENABLE_NEON=ON \
@@ -513,7 +513,7 @@ For Jetson TK1:
-DBUILD_JASPER=OFF \
-DBUILD_ZLIB=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_opencv_java=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_nonfree=OFF \
-DBUILD_opencv_python=ON \
-DENABLE_NEON=ON \
@@ -548,7 +548,7 @@ For Jetson TX1:
-DBUILD_JASPER=OFF \
-DBUILD_ZLIB=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_opencv_java=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_nonfree=OFF \
-DBUILD_opencv_python=ON \
-DENABLE_PRECOMPILED_HEADERS=OFF \
@@ -585,7 +585,7 @@ For both 14.04 LTS and 16.04 LTS:
-DBUILD_JASPER=OFF \
-DBUILD_ZLIB=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_opencv_java=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_nonfree=OFF \
-DBUILD_opencv_python=ON \
-DWITH_OPENCL=OFF \
@@ -626,7 +626,7 @@ The following is a table of all the parameters passed to CMake in the recommende
|BUILD_TBB|OFF|As above, for `tbb`| |
|BUILD_TIFF|OFF|As above, for `libtiff`| |
|BUILD_ZLIB|OFF|As above, for `zlib`| |
|BUILD_opencv_java|OFF|Controls the building of the Java bindings for OpenCV|Building the Java bindings requires OpenCV libraries be built for static linking only|
|BUILD_JAVA|OFF|Controls the building of the Java bindings for OpenCV|Building the Java bindings requires OpenCV libraries be built for static linking only|
|BUILD_opencv_nonfree|OFF|Controls the building of non-free (non-open-source) elements|Used only for building 2.4.X|
|BUILD_opencv_python|ON|Controls the building of the Python 2 bindings in OpenCV 2.4.X|Used only for building 2.4.X|
|BUILD_opencv_python2|ON|Controls the building of the Python 2 bindings in OpenCV 3.1.0|Not used in 2.4.X|
+32 -8
View File
@@ -41,20 +41,18 @@ namespace opencv_test
using namespace perf;
using namespace testing;
static void MakeArtificialExample(RNG rng, Mat& dst_left_view, Mat& dst_view);
static void MakeArtificialExample(Mat& dst_left_view, Mat& dst_view);
CV_ENUM(SGBMModes, StereoSGBM::MODE_SGBM, StereoSGBM::MODE_SGBM_3WAY, StereoSGBM::MODE_HH4);
typedef tuple<Size, int, SGBMModes> SGBMParams;
typedef TestBaseWithParam<SGBMParams> TestStereoCorresp;
typedef TestBaseWithParam<SGBMParams> TestStereoCorrespSGBM;
#ifndef _DEBUG
PERF_TEST_P( TestStereoCorresp, SGBM, Combine(Values(Size(1280,720),Size(640,480)), Values(256,128), SGBMModes::all()) )
PERF_TEST_P( TestStereoCorrespSGBM, SGBM, Combine(Values(Size(1280,720),Size(640,480)), Values(256,128), SGBMModes::all()) )
#else
PERF_TEST_P( TestStereoCorresp, DISABLED_TooLongInDebug_SGBM, Combine(Values(Size(1280,720),Size(640,480)), Values(256,128), SGBMModes::all()) )
PERF_TEST_P( TestStereoCorrespSGBM, DISABLED_TooLongInDebug_SGBM, Combine(Values(Size(1280,720),Size(640,480)), Values(256,128), SGBMModes::all()) )
#endif
{
RNG rng(0);
SGBMParams params = GetParam();
Size sz = get<0>(params);
@@ -65,7 +63,7 @@ PERF_TEST_P( TestStereoCorresp, DISABLED_TooLongInDebug_SGBM, Combine(Values(Siz
Mat src_right(sz, CV_8UC3);
Mat dst(sz, CV_16S);
MakeArtificialExample(rng,src_left,src_right);
MakeArtificialExample(src_left,src_right);
int wsize = 3;
int P1 = 8*src_left.channels()*wsize*wsize;
@@ -78,8 +76,34 @@ PERF_TEST_P( TestStereoCorresp, DISABLED_TooLongInDebug_SGBM, Combine(Values(Siz
SANITY_CHECK(dst, .01, ERROR_RELATIVE);
}
void MakeArtificialExample(RNG rng, Mat& dst_left_view, Mat& dst_right_view)
typedef tuple<Size, int> BMParams;
typedef TestBaseWithParam<BMParams> TestStereoCorrespBM;
PERF_TEST_P(TestStereoCorrespBM, BM, Combine(Values(Size(1280, 720), Size(640, 480)), Values(256, 128)))
{
BMParams params = GetParam();
Size sz = get<0>(params);
int num_disparities = get<1>(params);
Mat src_left(sz, CV_8UC1);
Mat src_right(sz, CV_8UC1);
Mat dst(sz, CV_16S);
MakeArtificialExample(src_left, src_right);
int wsize = 21;
TEST_CYCLE()
{
Ptr<StereoBM> bm = StereoBM::create(num_disparities, wsize);
bm->compute(src_left, src_right, dst);
}
SANITY_CHECK(dst, .01, ERROR_RELATIVE);
}
void MakeArtificialExample(Mat& dst_left_view, Mat& dst_right_view)
{
RNG rng(0);
int w = dst_left_view.cols;
int h = dst_left_view.rows;
+2 -1
View File
@@ -571,7 +571,8 @@ int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2,
if (!_mask.empty())
{
Mat mask = _mask.getMat();
CV_Assert(mask.size() == mask1.size());
CV_Assert(npoints == mask.checkVector(1));
mask = mask.reshape(1, npoints);
bitwise_and(mask, mask1, mask1);
bitwise_and(mask, mask2, mask2);
bitwise_and(mask, mask3, mask3);
@@ -2439,4 +2439,102 @@ TEST(Calib3d_Triangulate, accuracy)
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
TEST(CV_RecoverPoseTest, regression_15341)
{
// initialize test data
const int invalid_point_count = 2;
const float _points1_[] = {
1537.7f, 166.8f,
1599.1f, 179.6f,
1288.0f, 207.5f,
1507.1f, 193.2f,
1742.7f, 210.0f,
1041.6f, 271.7f,
1591.8f, 247.2f,
1524.0f, 261.3f,
1330.3f, 285.0f,
1403.1f, 284.0f,
1506.6f, 342.9f,
1502.8f, 347.3f,
1344.9f, 364.9f,
0.0f, 0.0f // last point is initial invalid
};
const float _points2_[] = {
1533.4f, 532.9f,
1596.6f, 552.4f,
1277.0f, 556.4f,
1502.1f, 557.6f,
1744.4f, 601.3f,
1023.0f, 612.6f,
1589.2f, 621.6f,
1519.4f, 629.0f,
1320.3f, 637.3f,
1395.2f, 642.2f,
1501.5f, 710.3f,
1497.6f, 714.2f,
1335.1f, 719.61f,
1000.0f, 1000.0f // last point is initial invalid
};
vector<Point2f> _points1; Mat(14, 1, CV_32FC2, (void*)_points1_).copyTo(_points1);
vector<Point2f> _points2; Mat(14, 1, CV_32FC2, (void*)_points2_).copyTo(_points2);
const int point_count = (int) _points1.size();
CV_Assert(point_count == (int) _points2.size());
// camera matrix with both focal lengths = 1, and principal point = (0, 0)
const Mat cameraMatrix = Mat::eye(3, 3, CV_64F);
int Inliers = 0;
const int ntests = 3;
for (int testcase = 1; testcase <= ntests; ++testcase)
{
if (testcase == 1) // testcase with vector input data
{
// init temporary test data
vector<unsigned char> mask(point_count);
vector<Point2f> points1(_points1);
vector<Point2f> points2(_points2);
// Estimation of fundamental matrix using the RANSAC algorithm
Mat E, R, t;
E = findEssentialMat(points1, points2, cameraMatrix, RANSAC, 0.999, 1.0, mask);
EXPECT_EQ(0, (int)mask[13]) << "Detecting outliers in function findEssentialMat failed, testcase " << testcase;
points2[12] = Point2f(0.0f, 0.0f); // provoke another outlier detection for recover Pose
Inliers = recoverPose(E, points1, points2, cameraMatrix, R, t, mask);
EXPECT_EQ(0, (int)mask[12]) << "Detecting outliers in function failed, testcase " << testcase;
}
else // testcase with mat input data
{
Mat points1(_points1, true);
Mat points2(_points2, true);
Mat mask;
if (testcase == 2)
{
// init temporary testdata
mask = Mat::zeros(point_count, 1, CV_8UC1);
}
else // testcase == 3 - with transposed mask
{
mask = Mat::zeros(1, point_count, CV_8UC1);
}
// Estimation of fundamental matrix using the RANSAC algorithm
Mat E, R, t;
E = findEssentialMat(points1, points2, cameraMatrix, RANSAC, 0.999, 1.0, mask);
EXPECT_EQ(0, (int)mask.at<unsigned char>(13)) << "Detecting outliers in function findEssentialMat failed, testcase " << testcase;
points2.at<Point2f>(12) = Point2f(0.0f, 0.0f); // provoke an outlier detection
Inliers = recoverPose(E, points1, points2, cameraMatrix, R, t, mask);
EXPECT_EQ(0, (int)mask.at<unsigned char>(12)) << "Detecting outliers in function failed, testcase " << testcase;
}
EXPECT_EQ(Inliers, point_count - invalid_point_count) <<
"Number of inliers differs from expected number of inliers, testcase " << testcase;
}
}
}} // namespace
+38
View File
@@ -1114,6 +1114,44 @@ TEST(Calib3d_UndistortPoints, outputShape)
}
}
TEST(Imgproc_undistort, regression_15286)
{
double kmat_data[9] = { 3217, 0, 1592, 0, 3217, 1201, 0, 0, 1 };
Mat kmat(3, 3, CV_64F, kmat_data);
double dist_coeff_data[5] = { 0.04, -0.4, -0.01, 0.04, 0.7 };
Mat dist_coeffs(5, 1, CV_64F, dist_coeff_data);
Mat img = Mat::zeros(512, 512, CV_8UC1);
img.at<uchar>(128, 128) = 255;
img.at<uchar>(128, 384) = 255;
img.at<uchar>(384, 384) = 255;
img.at<uchar>(384, 128) = 255;
Mat ref = Mat::zeros(512, 512, CV_8UC1);
ref.at<uchar>(Point(24, 98)) = 78;
ref.at<uchar>(Point(24, 99)) = 114;
ref.at<uchar>(Point(25, 98)) = 36;
ref.at<uchar>(Point(25, 99)) = 60;
ref.at<uchar>(Point(27, 361)) = 6;
ref.at<uchar>(Point(28, 361)) = 188;
ref.at<uchar>(Point(28, 362)) = 49;
ref.at<uchar>(Point(29, 361)) = 44;
ref.at<uchar>(Point(29, 362)) = 16;
ref.at<uchar>(Point(317, 366)) = 134;
ref.at<uchar>(Point(317, 367)) = 78;
ref.at<uchar>(Point(318, 366)) = 40;
ref.at<uchar>(Point(318, 367)) = 29;
ref.at<uchar>(Point(310, 104)) = 106;
ref.at<uchar>(Point(310, 105)) = 30;
ref.at<uchar>(Point(311, 104)) = 112;
ref.at<uchar>(Point(311, 105)) = 38;
Mat img_undist;
undistort(img, img_undist, kmat, dist_coeffs);
ASSERT_EQ(0.0, cvtest::norm(img_undist, ref, cv::NORM_INF));
}
TEST(Calib3d_initUndistortRectifyMap, regression_14467)
{
Size size_w_h(512 + 3, 512);
+1 -1
View File
@@ -6,7 +6,7 @@ ocv_add_dispatched_file(arithm SSE2 SSE4_1 AVX2 VSX3)
ocv_add_dispatched_file(convert SSE2 AVX2 VSX3)
ocv_add_dispatched_file(convert_scale SSE2 AVX2)
ocv_add_dispatched_file(count_non_zero SSE2 AVX2)
ocv_add_dispatched_file(matmul SSE2 AVX2)
ocv_add_dispatched_file(matmul SSE2 SSE4_1 AVX2 AVX512_SKX)
ocv_add_dispatched_file(mean SSE2 AVX2)
ocv_add_dispatched_file(merge SSE2 AVX2)
ocv_add_dispatched_file(split SSE2 AVX2)
@@ -113,12 +113,18 @@
# define CV_AVX_512IFMA 1
# define CV_AVX_512VBMI 1
#endif
#ifdef CV_CPU_COMPILE_AVX512_CEL
# define CV_AVX512_CEL 1
#ifdef CV_CPU_COMPILE_AVX512_CLX
# define CV_AVX512_CLX 1
# define CV_AVX_512VNNI 1
#endif
#ifdef CV_CPU_COMPILE_AVX512_ICL
# define CV_AVX512_ICL 1
# undef CV_AVX_512IFMA
# define CV_AVX_512IFMA 1
# undef CV_AVX_512VBMI
# define CV_AVX_512VBMI 1
# undef CV_AVX_512VNNI
# define CV_AVX_512VNNI 1
# define CV_AVX_512VBMI2 1
# define CV_AVX_512BITALG 1
# define CV_AVX_512VPOPCNTDQ 1
@@ -152,6 +158,16 @@
# define CV_VSX3 1
#endif
#ifdef CV_CPU_COMPILE_MSA
# include "hal/msa_macros.h"
# define CV_MSA 1
#endif
#ifdef __EMSCRIPTEN__
# define CV_WASM_SIMD 1
# include <wasm_simd128.h>
#endif
#endif // CV_ENABLE_INTRINSICS && !CV_DISABLE_OPTIMIZATION && !__CUDACC__
#if defined CV_CPU_COMPILE_AVX && !defined CV_CPU_BASELINE_COMPILE_AVX
@@ -301,8 +317,8 @@ struct VZeroUpperGuard {
#ifndef CV_AVX512_CNL
# define CV_AVX512_CNL 0
#endif
#ifndef CV_AVX512_CEL
# define CV_AVX512_CEL 0
#ifndef CV_AVX512_CLX
# define CV_AVX512_CLX 0
#endif
#ifndef CV_AVX512_ICL
# define CV_AVX512_ICL 0
@@ -319,3 +335,11 @@ struct VZeroUpperGuard {
#ifndef CV_VSX3
# define CV_VSX3 0
#endif
#ifndef CV_MSA
# define CV_MSA 0
#endif
#ifndef CV_WASM_SIMD
# define CV_WASM_SIMD 0
#endif
@@ -357,26 +357,26 @@
#endif
#define __CV_CPU_DISPATCH_CHAIN_AVX512_CNL(fn, args, mode, ...) CV_CPU_CALL_AVX512_CNL(fn, args); __CV_EXPAND(__CV_CPU_DISPATCH_CHAIN_ ## mode(fn, args, __VA_ARGS__))
#if !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_COMPILE_AVX512_CEL
# define CV_TRY_AVX512_CEL 1
# define CV_CPU_FORCE_AVX512_CEL 1
# define CV_CPU_HAS_SUPPORT_AVX512_CEL 1
# define CV_CPU_CALL_AVX512_CEL(fn, args) return (cpu_baseline::fn args)
# define CV_CPU_CALL_AVX512_CEL_(fn, args) return (opt_AVX512_CEL::fn args)
#elif !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_DISPATCH_COMPILE_AVX512_CEL
# define CV_TRY_AVX512_CEL 1
# define CV_CPU_FORCE_AVX512_CEL 0
# define CV_CPU_HAS_SUPPORT_AVX512_CEL (cv::checkHardwareSupport(CV_CPU_AVX512_CEL))
# define CV_CPU_CALL_AVX512_CEL(fn, args) if (CV_CPU_HAS_SUPPORT_AVX512_CEL) return (opt_AVX512_CEL::fn args)
# define CV_CPU_CALL_AVX512_CEL_(fn, args) if (CV_CPU_HAS_SUPPORT_AVX512_CEL) return (opt_AVX512_CEL::fn args)
#if !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_COMPILE_AVX512_CLX
# define CV_TRY_AVX512_CLX 1
# define CV_CPU_FORCE_AVX512_CLX 1
# define CV_CPU_HAS_SUPPORT_AVX512_CLX 1
# define CV_CPU_CALL_AVX512_CLX(fn, args) return (cpu_baseline::fn args)
# define CV_CPU_CALL_AVX512_CLX_(fn, args) return (opt_AVX512_CLX::fn args)
#elif !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_DISPATCH_COMPILE_AVX512_CLX
# define CV_TRY_AVX512_CLX 1
# define CV_CPU_FORCE_AVX512_CLX 0
# define CV_CPU_HAS_SUPPORT_AVX512_CLX (cv::checkHardwareSupport(CV_CPU_AVX512_CLX))
# define CV_CPU_CALL_AVX512_CLX(fn, args) if (CV_CPU_HAS_SUPPORT_AVX512_CLX) return (opt_AVX512_CLX::fn args)
# define CV_CPU_CALL_AVX512_CLX_(fn, args) if (CV_CPU_HAS_SUPPORT_AVX512_CLX) return (opt_AVX512_CLX::fn args)
#else
# define CV_TRY_AVX512_CEL 0
# define CV_CPU_FORCE_AVX512_CEL 0
# define CV_CPU_HAS_SUPPORT_AVX512_CEL 0
# define CV_CPU_CALL_AVX512_CEL(fn, args)
# define CV_CPU_CALL_AVX512_CEL_(fn, args)
# define CV_TRY_AVX512_CLX 0
# define CV_CPU_FORCE_AVX512_CLX 0
# define CV_CPU_HAS_SUPPORT_AVX512_CLX 0
# define CV_CPU_CALL_AVX512_CLX(fn, args)
# define CV_CPU_CALL_AVX512_CLX_(fn, args)
#endif
#define __CV_CPU_DISPATCH_CHAIN_AVX512_CEL(fn, args, mode, ...) CV_CPU_CALL_AVX512_CEL(fn, args); __CV_EXPAND(__CV_CPU_DISPATCH_CHAIN_ ## mode(fn, args, __VA_ARGS__))
#define __CV_CPU_DISPATCH_CHAIN_AVX512_CLX(fn, args, mode, ...) CV_CPU_CALL_AVX512_CLX(fn, args); __CV_EXPAND(__CV_CPU_DISPATCH_CHAIN_ ## mode(fn, args, __VA_ARGS__))
#if !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_COMPILE_AVX512_ICL
# define CV_TRY_AVX512_ICL 1
@@ -420,6 +420,27 @@
#endif
#define __CV_CPU_DISPATCH_CHAIN_NEON(fn, args, mode, ...) CV_CPU_CALL_NEON(fn, args); __CV_EXPAND(__CV_CPU_DISPATCH_CHAIN_ ## mode(fn, args, __VA_ARGS__))
#if !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_COMPILE_MSA
# define CV_TRY_MSA 1
# define CV_CPU_FORCE_MSA 1
# define CV_CPU_HAS_SUPPORT_MSA 1
# define CV_CPU_CALL_MSA(fn, args) return (cpu_baseline::fn args)
# define CV_CPU_CALL_MSA_(fn, args) return (opt_MSA::fn args)
#elif !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_DISPATCH_COMPILE_MSA
# define CV_TRY_MSA 1
# define CV_CPU_FORCE_MSA 0
# define CV_CPU_HAS_SUPPORT_MSA (cv::checkHardwareSupport(CV_CPU_MSA))
# define CV_CPU_CALL_MSA(fn, args) if (CV_CPU_HAS_SUPPORT_MSA) return (opt_MSA::fn args)
# define CV_CPU_CALL_MSA_(fn, args) if (CV_CPU_HAS_SUPPORT_MSA) return (opt_MSA::fn args)
#else
# define CV_TRY_MSA 0
# define CV_CPU_FORCE_MSA 0
# define CV_CPU_HAS_SUPPORT_MSA 0
# define CV_CPU_CALL_MSA(fn, args)
# define CV_CPU_CALL_MSA_(fn, args)
#endif
#define __CV_CPU_DISPATCH_CHAIN_MSA(fn, args, mode, ...) CV_CPU_CALL_MSA(fn, args); __CV_EXPAND(__CV_CPU_DISPATCH_CHAIN_ ## mode(fn, args, __VA_ARGS__))
#if !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_COMPILE_VSX
# define CV_TRY_VSX 1
# define CV_CPU_FORCE_VSX 1
+13 -2
View File
@@ -258,6 +258,8 @@ namespace cv { namespace debug_build_guard { } using namespace debug_build_guard
#define CV_CPU_NEON 100
#define CV_CPU_MSA 150
#define CV_CPU_VSX 200
#define CV_CPU_VSX3 201
@@ -267,7 +269,7 @@ namespace cv { namespace debug_build_guard { } using namespace debug_build_guard
#define CV_CPU_AVX512_KNL 258
#define CV_CPU_AVX512_KNM 259
#define CV_CPU_AVX512_CNL 260
#define CV_CPU_AVX512_CEL 261
#define CV_CPU_AVX512_CLX 261
#define CV_CPU_AVX512_ICL 262
// when adding to this list remember to update the following enum
@@ -308,6 +310,8 @@ enum CpuFeatures {
CPU_NEON = 100,
CPU_MSA = 150,
CPU_VSX = 200,
CPU_VSX3 = 201,
@@ -316,7 +320,7 @@ enum CpuFeatures {
CPU_AVX512_KNL = 258, //!< Knights Landing with AVX-512F/CD/ER/PF
CPU_AVX512_KNM = 259, //!< Knights Mill with AVX-512F/CD/ER/PF/4FMAPS/4VNNIW/VPOPCNTDQ
CPU_AVX512_CNL = 260, //!< Cannon Lake with AVX-512F/CD/BW/DQ/VL/IFMA/VBMI
CPU_AVX512_CEL = 261, //!< Cascade Lake with AVX-512F/CD/BW/DQ/VL/IFMA/VBMI/VNNI
CPU_AVX512_CLX = 261, //!< Cascade Lake with AVX-512F/CD/BW/DQ/VL/VNNI
CPU_AVX512_ICL = 262, //!< Ice Lake with AVX-512F/CD/BW/DQ/VL/IFMA/VBMI/VNNI/VBMI2/BITALG/VPOPCNTDQ
CPU_MAX_FEATURE = 512 // see CV_HARDWARE_MAX_FEATURE
@@ -584,6 +588,13 @@ Cv64suf;
# endif
#endif
#ifdef CV_CXX_MOVE_SEMANTICS
#define CV_CXX_MOVE(x) std::move(x)
#else
#define CV_CXX_MOVE(x) (x)
#endif
/****************************************************************************************\
* C++11 std::array *
\****************************************************************************************/
@@ -165,9 +165,10 @@ using namespace CV_CPU_OPTIMIZATION_HAL_NAMESPACE;
# undef CV_NEON
# undef CV_VSX
# undef CV_FP16
# undef CV_MSA
#endif
#if CV_SSE2 || CV_NEON || CV_VSX
#if CV_SSE2 || CV_NEON || CV_VSX || CV_MSA || CV_WASM_SIMD
#define CV__SIMD_FORWARD 128
#include "opencv2/core/hal/intrin_forward.hpp"
#endif
@@ -185,6 +186,13 @@ using namespace CV_CPU_OPTIMIZATION_HAL_NAMESPACE;
#include "opencv2/core/hal/intrin_vsx.hpp"
#elif CV_MSA
#include "opencv2/core/hal/intrin_msa.hpp"
#elif CV_WASM_SIMD
#include "opencv2/core/hal/intrin_wasm.hpp"
#else
#define CV_SIMD128_CPP 1
@@ -1241,6 +1241,11 @@ inline int v_signmask(const v_int32x8& a)
inline int v_signmask(const v_uint32x8& a)
{ return v_signmask(v_reinterpret_as_f32(a)); }
inline int v_signmask(const v_int64x4& a)
{ return v_signmask(v_reinterpret_as_f64(a)); }
inline int v_signmask(const v_uint64x4& a)
{ return v_signmask(v_reinterpret_as_f64(a)); }
inline int v_scan_forward(const v_int8x32& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))); }
inline int v_scan_forward(const v_uint8x32& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))); }
inline int v_scan_forward(const v_int16x16& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))) / 2; }
@@ -1253,40 +1258,23 @@ inline int v_scan_forward(const v_uint64x4& a) { return trailingZeros32(v_signma
inline int v_scan_forward(const v_float64x4& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))) / 8; }
/** Checks **/
#define OPENCV_HAL_IMPL_AVX_CHECK(_Tpvec, and_op, allmask) \
inline bool v_check_all(const _Tpvec& a) \
{ \
int mask = v_signmask(v_reinterpret_as_s8(a)); \
return and_op(mask, allmask) == allmask; \
} \
inline bool v_check_any(const _Tpvec& a) \
{ \
int mask = v_signmask(v_reinterpret_as_s8(a)); \
return and_op(mask, allmask) != 0; \
}
OPENCV_HAL_IMPL_AVX_CHECK(v_uint8x32, OPENCV_HAL_1ST, -1)
OPENCV_HAL_IMPL_AVX_CHECK(v_int8x32, OPENCV_HAL_1ST, -1)
OPENCV_HAL_IMPL_AVX_CHECK(v_uint16x16, OPENCV_HAL_AND, (int)0xaaaaaaaa)
OPENCV_HAL_IMPL_AVX_CHECK(v_int16x16, OPENCV_HAL_AND, (int)0xaaaaaaaa)
OPENCV_HAL_IMPL_AVX_CHECK(v_uint32x8, OPENCV_HAL_AND, (int)0x88888888)
OPENCV_HAL_IMPL_AVX_CHECK(v_int32x8, OPENCV_HAL_AND, (int)0x88888888)
#define OPENCV_HAL_IMPL_AVX_CHECK_FLT(_Tpvec, allmask) \
inline bool v_check_all(const _Tpvec& a) \
{ \
int mask = v_signmask(a); \
return mask == allmask; \
} \
inline bool v_check_any(const _Tpvec& a) \
{ \
int mask = v_signmask(a); \
return mask != 0; \
}
OPENCV_HAL_IMPL_AVX_CHECK_FLT(v_float32x8, 255)
OPENCV_HAL_IMPL_AVX_CHECK_FLT(v_float64x4, 15)
#define OPENCV_HAL_IMPL_AVX_CHECK(_Tpvec, allmask) \
inline bool v_check_all(const _Tpvec& a) { return v_signmask(a) == allmask; } \
inline bool v_check_any(const _Tpvec& a) { return v_signmask(a) != 0; }
OPENCV_HAL_IMPL_AVX_CHECK(v_uint8x32, -1)
OPENCV_HAL_IMPL_AVX_CHECK(v_int8x32, -1)
OPENCV_HAL_IMPL_AVX_CHECK(v_uint32x8, 255)
OPENCV_HAL_IMPL_AVX_CHECK(v_int32x8, 255)
OPENCV_HAL_IMPL_AVX_CHECK(v_uint64x4, 15)
OPENCV_HAL_IMPL_AVX_CHECK(v_int64x4, 15)
OPENCV_HAL_IMPL_AVX_CHECK(v_float32x8, 255)
OPENCV_HAL_IMPL_AVX_CHECK(v_float64x4, 15)
#define OPENCV_HAL_IMPL_AVX_CHECK_SHORT(_Tpvec) \
inline bool v_check_all(const _Tpvec& a) { return (v_signmask(v_reinterpret_as_s8(a)) & 0xaaaaaaaa) == 0xaaaaaaaa; } \
inline bool v_check_any(const _Tpvec& a) { return (v_signmask(v_reinterpret_as_s8(a)) & 0xaaaaaaaa) != 0; }
OPENCV_HAL_IMPL_AVX_CHECK_SHORT(v_uint16x16)
OPENCV_HAL_IMPL_AVX_CHECK_SHORT(v_int16x16)
////////// Other math /////////
@@ -1443,6 +1431,28 @@ inline v_float64x4 v_cvt_f64(const v_float32x8& a)
inline v_float64x4 v_cvt_f64_high(const v_float32x8& a)
{ return v_float64x4(_mm256_cvtps_pd(_v256_extract_high(a.val))); }
// from (Mysticial and wim) https://stackoverflow.com/q/41144668
inline v_float64x4 v_cvt_f64(const v_int64x4& v)
{
// constants encoded as floating-point
__m256i magic_i_lo = _mm256_set1_epi64x(0x4330000000000000); // 2^52
__m256i magic_i_hi32 = _mm256_set1_epi64x(0x4530000080000000); // 2^84 + 2^63
__m256i magic_i_all = _mm256_set1_epi64x(0x4530000080100000); // 2^84 + 2^63 + 2^52
__m256d magic_d_all = _mm256_castsi256_pd(magic_i_all);
// Blend the 32 lowest significant bits of v with magic_int_lo
__m256i v_lo = _mm256_blend_epi32(magic_i_lo, v.val, 0x55);
// Extract the 32 most significant bits of v
__m256i v_hi = _mm256_srli_epi64(v.val, 32);
// Flip the msb of v_hi and blend with 0x45300000
v_hi = _mm256_xor_si256(v_hi, magic_i_hi32);
// Compute in double precision
__m256d v_hi_dbl = _mm256_sub_pd(_mm256_castsi256_pd(v_hi), magic_d_all);
// (v_hi - magic_d_all) + v_lo Do not assume associativity of floating point addition
__m256d result = _mm256_add_pd(v_hi_dbl, _mm256_castsi256_pd(v_lo));
return v_float64x4(result);
}
////////////// Lookup table access ////////////////////
inline v_int8x32 v256_lut(const schar* tab, const int* idx)
@@ -1650,12 +1660,165 @@ inline v_float32x8 v_pack_triplets(const v_float32x8& vec)
////////// Matrix operations /////////
//////// Dot Product ////////
// 16 >> 32
inline v_int32x8 v_dotprod(const v_int16x16& a, const v_int16x16& b)
{ return v_int32x8(_mm256_madd_epi16(a.val, b.val)); }
inline v_int32x8 v_dotprod(const v_int16x16& a, const v_int16x16& b, const v_int32x8& c)
{ return v_dotprod(a, b) + c; }
// 32 >> 64
inline v_int64x4 v_dotprod(const v_int32x8& a, const v_int32x8& b)
{
__m256i even = _mm256_mul_epi32(a.val, b.val);
__m256i odd = _mm256_mul_epi32(_mm256_srli_epi64(a.val, 32), _mm256_srli_epi64(b.val, 32));
return v_int64x4(_mm256_add_epi64(even, odd));
}
inline v_int64x4 v_dotprod(const v_int32x8& a, const v_int32x8& b, const v_int64x4& c)
{ return v_dotprod(a, b) + c; }
// 8 >> 32
inline v_uint32x8 v_dotprod_expand(const v_uint8x32& a, const v_uint8x32& b)
{
__m256i even_m = _mm256_set1_epi32(0xFF00FF00);
__m256i even_a = _mm256_blendv_epi8(a.val, _mm256_setzero_si256(), even_m);
__m256i odd_a = _mm256_srli_epi16(a.val, 8);
__m256i even_b = _mm256_blendv_epi8(b.val, _mm256_setzero_si256(), even_m);
__m256i odd_b = _mm256_srli_epi16(b.val, 8);
__m256i prod0 = _mm256_madd_epi16(even_a, even_b);
__m256i prod1 = _mm256_madd_epi16(odd_a, odd_b);
return v_uint32x8(_mm256_add_epi32(prod0, prod1));
}
inline v_uint32x8 v_dotprod_expand(const v_uint8x32& a, const v_uint8x32& b, const v_uint32x8& c)
{ return v_dotprod_expand(a, b) + c; }
inline v_int32x8 v_dotprod_expand(const v_int8x32& a, const v_int8x32& b)
{
__m256i even_a = _mm256_srai_epi16(_mm256_bslli_epi128(a.val, 1), 8);
__m256i odd_a = _mm256_srai_epi16(a.val, 8);
__m256i even_b = _mm256_srai_epi16(_mm256_bslli_epi128(b.val, 1), 8);
__m256i odd_b = _mm256_srai_epi16(b.val, 8);
__m256i prod0 = _mm256_madd_epi16(even_a, even_b);
__m256i prod1 = _mm256_madd_epi16(odd_a, odd_b);
return v_int32x8(_mm256_add_epi32(prod0, prod1));
}
inline v_int32x8 v_dotprod_expand(const v_int8x32& a, const v_int8x32& b, const v_int32x8& c)
{ return v_dotprod_expand(a, b) + c; }
// 16 >> 64
inline v_uint64x4 v_dotprod_expand(const v_uint16x16& a, const v_uint16x16& b)
{
__m256i mullo = _mm256_mullo_epi16(a.val, b.val);
__m256i mulhi = _mm256_mulhi_epu16(a.val, b.val);
__m256i mul0 = _mm256_unpacklo_epi16(mullo, mulhi);
__m256i mul1 = _mm256_unpackhi_epi16(mullo, mulhi);
__m256i p02 = _mm256_blend_epi32(mul0, _mm256_setzero_si256(), 0xAA);
__m256i p13 = _mm256_srli_epi64(mul0, 32);
__m256i p46 = _mm256_blend_epi32(mul1, _mm256_setzero_si256(), 0xAA);
__m256i p57 = _mm256_srli_epi64(mul1, 32);
__m256i p15_ = _mm256_add_epi64(p02, p13);
__m256i p9d_ = _mm256_add_epi64(p46, p57);
return v_uint64x4(_mm256_add_epi64(
_mm256_unpacklo_epi64(p15_, p9d_),
_mm256_unpackhi_epi64(p15_, p9d_)
));
}
inline v_uint64x4 v_dotprod_expand(const v_uint16x16& a, const v_uint16x16& b, const v_uint64x4& c)
{ return v_dotprod_expand(a, b) + c; }
inline v_int64x4 v_dotprod_expand(const v_int16x16& a, const v_int16x16& b)
{
__m256i prod = _mm256_madd_epi16(a.val, b.val);
__m256i sign = _mm256_srai_epi32(prod, 31);
__m256i lo = _mm256_unpacklo_epi32(prod, sign);
__m256i hi = _mm256_unpackhi_epi32(prod, sign);
return v_int64x4(_mm256_add_epi64(
_mm256_unpacklo_epi64(lo, hi),
_mm256_unpackhi_epi64(lo, hi)
));
}
inline v_int64x4 v_dotprod_expand(const v_int16x16& a, const v_int16x16& b, const v_int64x4& c)
{ return v_dotprod_expand(a, b) + c; }
// 32 >> 64f
inline v_float64x4 v_dotprod_expand(const v_int32x8& a, const v_int32x8& b)
{ return v_cvt_f64(v_dotprod(a, b)); }
inline v_float64x4 v_dotprod_expand(const v_int32x8& a, const v_int32x8& b, const v_float64x4& c)
{ return v_dotprod_expand(a, b) + c; }
//////// Fast Dot Product ////////
// 16 >> 32
inline v_int32x8 v_dotprod_fast(const v_int16x16& a, const v_int16x16& b)
{ return v_dotprod(a, b); }
inline v_int32x8 v_dotprod_fast(const v_int16x16& a, const v_int16x16& b, const v_int32x8& c)
{ return v_dotprod(a, b, c); }
// 32 >> 64
inline v_int64x4 v_dotprod_fast(const v_int32x8& a, const v_int32x8& b)
{ return v_dotprod(a, b); }
inline v_int64x4 v_dotprod_fast(const v_int32x8& a, const v_int32x8& b, const v_int64x4& c)
{ return v_dotprod(a, b, c); }
// 8 >> 32
inline v_uint32x8 v_dotprod_expand_fast(const v_uint8x32& a, const v_uint8x32& b)
{ return v_dotprod_expand(a, b); }
inline v_uint32x8 v_dotprod_expand_fast(const v_uint8x32& a, const v_uint8x32& b, const v_uint32x8& c)
{ return v_dotprod_expand(a, b, c); }
inline v_int32x8 v_dotprod_expand_fast(const v_int8x32& a, const v_int8x32& b)
{ return v_dotprod_expand(a, b); }
inline v_int32x8 v_dotprod_expand_fast(const v_int8x32& a, const v_int8x32& b, const v_int32x8& c)
{ return v_dotprod_expand(a, b, c); }
// 16 >> 64
inline v_uint64x4 v_dotprod_expand_fast(const v_uint16x16& a, const v_uint16x16& b)
{
__m256i mullo = _mm256_mullo_epi16(a.val, b.val);
__m256i mulhi = _mm256_mulhi_epu16(a.val, b.val);
__m256i mul0 = _mm256_unpacklo_epi16(mullo, mulhi);
__m256i mul1 = _mm256_unpackhi_epi16(mullo, mulhi);
__m256i p02 = _mm256_blend_epi32(mul0, _mm256_setzero_si256(), 0xAA);
__m256i p13 = _mm256_srli_epi64(mul0, 32);
__m256i p46 = _mm256_blend_epi32(mul1, _mm256_setzero_si256(), 0xAA);
__m256i p57 = _mm256_srli_epi64(mul1, 32);
__m256i p15_ = _mm256_add_epi64(p02, p13);
__m256i p9d_ = _mm256_add_epi64(p46, p57);
return v_uint64x4(_mm256_add_epi64(p15_, p9d_));
}
inline v_uint64x4 v_dotprod_expand_fast(const v_uint16x16& a, const v_uint16x16& b, const v_uint64x4& c)
{ return v_dotprod_expand_fast(a, b) + c; }
inline v_int64x4 v_dotprod_expand_fast(const v_int16x16& a, const v_int16x16& b)
{
__m256i prod = _mm256_madd_epi16(a.val, b.val);
__m256i sign = _mm256_srai_epi32(prod, 31);
__m256i lo = _mm256_unpacklo_epi32(prod, sign);
__m256i hi = _mm256_unpackhi_epi32(prod, sign);
return v_int64x4(_mm256_add_epi64(lo, hi));
}
inline v_int64x4 v_dotprod_expand_fast(const v_int16x16& a, const v_int16x16& b, const v_int64x4& c)
{ return v_dotprod_expand_fast(a, b) + c; }
// 32 >> 64f
inline v_float64x4 v_dotprod_expand_fast(const v_int32x8& a, const v_int32x8& b)
{ return v_dotprod_expand(a, b); }
inline v_float64x4 v_dotprod_expand_fast(const v_int32x8& a, const v_int32x8& b, const v_float64x4& c)
{ return v_dotprod_expand(a, b, c); }
#define OPENCV_HAL_AVX_SPLAT2_PS(a, im) \
v_float32x8(_mm256_permute_ps(a.val, _MM_SHUFFLE(im, im, im, im)))
@@ -1473,6 +1473,32 @@ inline v_float64x8 v_cvt_f64(const v_float32x16& a)
inline v_float64x8 v_cvt_f64_high(const v_float32x16& a)
{ return v_float64x8(_mm512_cvtps_pd(_v512_extract_high(a.val))); }
// from (Mysticial and wim) https://stackoverflow.com/q/41144668
inline v_float64x8 v_cvt_f64(const v_int64x8& v)
{
#if CV_AVX_512DQ
return v_float64x8(_mm512_cvtepi64_pd(v.val));
#else
// constants encoded as floating-point
__m512i magic_i_lo = _mm512_set1_epi64x(0x4330000000000000); // 2^52
__m512i magic_i_hi32 = _mm512_set1_epi64x(0x4530000080000000); // 2^84 + 2^63
__m512i magic_i_all = _mm512_set1_epi64x(0x4530000080100000); // 2^84 + 2^63 + 2^52
__m512d magic_d_all = _mm512_castsi512_pd(magic_i_all);
// Blend the 32 lowest significant bits of v with magic_int_lo
__m512i v_lo = _mm512_blend_epi32(magic_i_lo, v.val, 0x55);
// Extract the 32 most significant bits of v
__m512i v_hi = _mm512_srli_epi64(v.val, 32);
// Flip the msb of v_hi and blend with 0x45300000
v_hi = _mm512_xor_si512(v_hi, magic_i_hi32);
// Compute in double precision
__m512d v_hi_dbl = _mm512_sub_pd(_mm512_castsi512_pd(v_hi), magic_d_all);
// (v_hi - magic_d_all) + v_lo Do not assume associativity of floating point addition
__m512d result = _mm512_add_pd(v_hi_dbl, _mm512_castsi512_pd(v_lo));
return v_float64x8(result);
#endif
}
////////////// Lookup table access ////////////////////
inline v_int8x64 v512_lut(const schar* tab, const int* idx)
@@ -1672,12 +1698,152 @@ inline v_float32x16 v_pack_triplets(const v_float32x16& vec)
////////// Matrix operations /////////
//////// Dot Product ////////
// 16 >> 32
inline v_int32x16 v_dotprod(const v_int16x32& a, const v_int16x32& b)
{ return v_int32x16(_mm512_madd_epi16(a.val, b.val)); }
inline v_int32x16 v_dotprod(const v_int16x32& a, const v_int16x32& b, const v_int32x16& c)
{ return v_dotprod(a, b) + c; }
// 32 >> 64
inline v_int64x8 v_dotprod(const v_int32x16& a, const v_int32x16& b)
{
__m512i even = _mm512_mul_epi32(a.val, b.val);
__m512i odd = _mm512_mul_epi32(_mm512_srli_epi64(a.val, 32), _mm512_srli_epi64(b.val, 32));
return v_int64x8(_mm512_add_epi64(even, odd));
}
inline v_int64x8 v_dotprod(const v_int32x16& a, const v_int32x16& b, const v_int64x8& c)
{ return v_dotprod(a, b) + c; }
// 8 >> 32
inline v_uint32x16 v_dotprod_expand(const v_uint8x64& a, const v_uint8x64& b)
{
__m512i even_a = _mm512_mask_blend_epi8(0xAAAAAAAAAAAAAAAA, a.val, _mm512_setzero_si512());
__m512i odd_a = _mm512_srli_epi16(a.val, 8);
__m512i even_b = _mm512_mask_blend_epi8(0xAAAAAAAAAAAAAAAA, b.val, _mm512_setzero_si512());
__m512i odd_b = _mm512_srli_epi16(b.val, 8);
__m512i prod0 = _mm512_madd_epi16(even_a, even_b);
__m512i prod1 = _mm512_madd_epi16(odd_a, odd_b);
return v_uint32x16(_mm512_add_epi32(prod0, prod1));
}
inline v_uint32x16 v_dotprod_expand(const v_uint8x64& a, const v_uint8x64& b, const v_uint32x16& c)
{ return v_dotprod_expand(a, b) + c; }
inline v_int32x16 v_dotprod_expand(const v_int8x64& a, const v_int8x64& b)
{
__m512i even_a = _mm512_srai_epi16(_mm512_bslli_epi128(a.val, 1), 8);
__m512i odd_a = _mm512_srai_epi16(a.val, 8);
__m512i even_b = _mm512_srai_epi16(_mm512_bslli_epi128(b.val, 1), 8);
__m512i odd_b = _mm512_srai_epi16(b.val, 8);
__m512i prod0 = _mm512_madd_epi16(even_a, even_b);
__m512i prod1 = _mm512_madd_epi16(odd_a, odd_b);
return v_int32x16(_mm512_add_epi32(prod0, prod1));
}
inline v_int32x16 v_dotprod_expand(const v_int8x64& a, const v_int8x64& b, const v_int32x16& c)
{ return v_dotprod_expand(a, b) + c; }
// 16 >> 64
inline v_uint64x8 v_dotprod_expand(const v_uint16x32& a, const v_uint16x32& b)
{
__m512i mullo = _mm512_mullo_epi16(a.val, b.val);
__m512i mulhi = _mm512_mulhi_epu16(a.val, b.val);
__m512i mul0 = _mm512_unpacklo_epi16(mullo, mulhi);
__m512i mul1 = _mm512_unpackhi_epi16(mullo, mulhi);
__m512i p02 = _mm512_mask_blend_epi32(0xAAAA, mul0, _mm512_setzero_si512());
__m512i p13 = _mm512_srli_epi64(mul0, 32);
__m512i p46 = _mm512_mask_blend_epi32(0xAAAA, mul1, _mm512_setzero_si512());
__m512i p57 = _mm512_srli_epi64(mul1, 32);
__m512i p15_ = _mm512_add_epi64(p02, p13);
__m512i p9d_ = _mm512_add_epi64(p46, p57);
return v_uint64x8(_mm512_add_epi64(
_mm512_unpacklo_epi64(p15_, p9d_),
_mm512_unpackhi_epi64(p15_, p9d_)
));
}
inline v_uint64x8 v_dotprod_expand(const v_uint16x32& a, const v_uint16x32& b, const v_uint64x8& c)
{ return v_dotprod_expand(a, b) + c; }
inline v_int64x8 v_dotprod_expand(const v_int16x32& a, const v_int16x32& b)
{
__m512i prod = _mm512_madd_epi16(a.val, b.val);
__m512i even = _mm512_srai_epi64(_mm512_bslli_epi128(prod, 4), 32);
__m512i odd = _mm512_srai_epi64(prod, 32);
return v_int64x8(_mm512_add_epi64(even, odd));
}
inline v_int64x8 v_dotprod_expand(const v_int16x32& a, const v_int16x32& b, const v_int64x8& c)
{ return v_dotprod_expand(a, b) + c; }
// 32 >> 64f
inline v_float64x8 v_dotprod_expand(const v_int32x16& a, const v_int32x16& b)
{ return v_cvt_f64(v_dotprod(a, b)); }
inline v_float64x8 v_dotprod_expand(const v_int32x16& a, const v_int32x16& b, const v_float64x8& c)
{ return v_dotprod_expand(a, b) + c; }
//////// Fast Dot Product ////////
// 16 >> 32
inline v_int32x16 v_dotprod_fast(const v_int16x32& a, const v_int16x32& b)
{ return v_dotprod(a, b); }
inline v_int32x16 v_dotprod_fast(const v_int16x32& a, const v_int16x32& b, const v_int32x16& c)
{ return v_dotprod(a, b, c); }
// 32 >> 64
inline v_int64x8 v_dotprod_fast(const v_int32x16& a, const v_int32x16& b)
{ return v_dotprod(a, b); }
inline v_int64x8 v_dotprod_fast(const v_int32x16& a, const v_int32x16& b, const v_int64x8& c)
{ return v_dotprod(a, b, c); }
// 8 >> 32
inline v_uint32x16 v_dotprod_expand_fast(const v_uint8x64& a, const v_uint8x64& b)
{ return v_dotprod_expand(a, b); }
inline v_uint32x16 v_dotprod_expand_fast(const v_uint8x64& a, const v_uint8x64& b, const v_uint32x16& c)
{ return v_dotprod_expand(a, b, c); }
inline v_int32x16 v_dotprod_expand_fast(const v_int8x64& a, const v_int8x64& b)
{ return v_dotprod_expand(a, b); }
inline v_int32x16 v_dotprod_expand_fast(const v_int8x64& a, const v_int8x64& b, const v_int32x16& c)
{ return v_dotprod_expand(a, b, c); }
// 16 >> 64
inline v_uint64x8 v_dotprod_expand_fast(const v_uint16x32& a, const v_uint16x32& b)
{
__m512i mullo = _mm512_mullo_epi16(a.val, b.val);
__m512i mulhi = _mm512_mulhi_epu16(a.val, b.val);
__m512i mul0 = _mm512_unpacklo_epi16(mullo, mulhi);
__m512i mul1 = _mm512_unpackhi_epi16(mullo, mulhi);
__m512i p02 = _mm512_mask_blend_epi32(0xAAAA, mul0, _mm512_setzero_si512());
__m512i p13 = _mm512_srli_epi64(mul0, 32);
__m512i p46 = _mm512_mask_blend_epi32(0xAAAA, mul1, _mm512_setzero_si512());
__m512i p57 = _mm512_srli_epi64(mul1, 32);
__m512i p15_ = _mm512_add_epi64(p02, p13);
__m512i p9d_ = _mm512_add_epi64(p46, p57);
return v_uint64x8(_mm512_add_epi64(p15_, p9d_));
}
inline v_uint64x8 v_dotprod_expand_fast(const v_uint16x32& a, const v_uint16x32& b, const v_uint64x8& c)
{ return v_dotprod_expand_fast(a, b) + c; }
inline v_int64x8 v_dotprod_expand_fast(const v_int16x32& a, const v_int16x32& b)
{ return v_dotprod_expand(a, b); }
inline v_int64x8 v_dotprod_expand_fast(const v_int16x32& a, const v_int16x32& b, const v_int64x8& c)
{ return v_dotprod_expand(a, b, c); }
// 32 >> 64f
inline v_float64x8 v_dotprod_expand_fast(const v_int32x16& a, const v_int32x16& b)
{ return v_dotprod_expand(a, b); }
inline v_float64x8 v_dotprod_expand_fast(const v_int32x16& a, const v_int32x16& b, const v_float64x8& c)
{ return v_dotprod_expand(a, b) + c; }
#define OPENCV_HAL_AVX512_SPLAT2_PS(a, im) \
v_float32x16(_mm512_permute_ps(a.val, _MM_SHUFFLE(im, im, im, im)))
@@ -171,7 +171,8 @@ Different type conversions and casts:
### Matrix operations
In these operations vectors represent matrix rows/columns: @ref v_dotprod, @ref v_matmul, @ref v_transpose4x4
In these operations vectors represent matrix rows/columns: @ref v_dotprod, @ref v_dotprod_fast,
@ref v_dotprod_expand, @ref v_dotprod_expand_fast, @ref v_matmul, @ref v_transpose4x4
### Usability
@@ -195,7 +196,10 @@ Regular integers:
|mul_expand | x | x | x | x | x | |
|compare | x | x | x | x | x | x |
|shift | | | x | x | x | x |
|dotprod | | | | x | | |
|dotprod | | | | x | | x |
|dotprod_fast | | | | x | | x |
|dotprod_expand | x | x | x | x | | x |
|dotprod_expand_fast| x | x | x | x | | x |
|logical | x | x | x | x | x | x |
|min, max | x | x | x | x | x | x |
|absdiff | x | x | x | x | x | x |
@@ -222,6 +226,7 @@ Big integers:
|logical | x | x |
|extract | x | x |
|rotate (lanes) | x | x |
|cvt_flt64 | | x |
Floating point:
@@ -853,17 +858,18 @@ inline v_reg<_Tp, n> v_muladd(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
/** @brief Dot product of elements
Multiply values in two registers and sum adjacent result pairs.
Scheme:
@code
{A1 A2 ...} // 16-bit
x {B1 B2 ...} // 16-bit
-------------
{A1B1+A2B2 ...} // 32-bit
@endcode
Implemented only for 16-bit signed source type (v_int16x8).
*/
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_dotprod(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
v_dotprod(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
typedef typename V_TypeTraits<_Tp>::w_type w_type;
v_reg<w_type, n/2> c;
@@ -881,12 +887,11 @@ Scheme:
x {B1 B2 ...} // 16-bit
-------------
{A1B1+A2B2+C1 ...} // 32-bit
@endcode
Implemented only for 16-bit signed source type (v_int16x8).
*/
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_dotprod(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, const v_reg<typename V_TypeTraits<_Tp>::w_type, n / 2>& c)
v_dotprod(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<typename V_TypeTraits<_Tp>::w_type, n / 2>& c)
{
typedef typename V_TypeTraits<_Tp>::w_type w_type;
v_reg<w_type, n/2> s;
@@ -895,6 +900,95 @@ template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::w_type, n
return s;
}
/** @brief Fast Dot product of elements
Same as cv::v_dotprod, but it may perform unorder sum between result pairs in some platforms,
this intrinsic can be used if the sum among all lanes is only matters
and also it should be yielding better performance on the affected platforms.
*/
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_dotprod_fast(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{ return v_dotprod(a, b); }
/** @brief Fast Dot product of elements
Same as cv::v_dotprod_fast, but add a third element to the sum of adjacent pairs.
*/
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_dotprod_fast(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<typename V_TypeTraits<_Tp>::w_type, n / 2>& c)
{ return v_dotprod(a, b, c); }
/** @brief Dot product of elements and expand
Multiply values in two registers and expand the sum of adjacent result pairs.
Scheme:
@code
{A1 A2 A3 A4 ...} // 8-bit
x {B1 B2 B3 B4 ...} // 8-bit
-------------
{A1B1+A2B2+A3B3+A4B4 ...} // 32-bit
@endcode
*/
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::q_type, n/4>
v_dotprod_expand(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
typedef typename V_TypeTraits<_Tp>::q_type q_type;
v_reg<q_type, n/4> s;
for( int i = 0; i < (n/4); i++ )
s.s[i] = (q_type)a.s[i*4 ]*b.s[i*4 ] + (q_type)a.s[i*4 + 1]*b.s[i*4 + 1] +
(q_type)a.s[i*4 + 2]*b.s[i*4 + 2] + (q_type)a.s[i*4 + 3]*b.s[i*4 + 3];
return s;
}
/** @brief Dot product of elements
Same as cv::v_dotprod_expand, but add a third element to the sum of adjacent pairs.
Scheme:
@code
{A1 A2 A3 A4 ...} // 8-bit
x {B1 B2 B3 B4 ...} // 8-bit
-------------
{A1B1+A2B2+A3B3+A4B4+C1 ...} // 32-bit
@endcode
*/
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::q_type, n/4>
v_dotprod_expand(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<typename V_TypeTraits<_Tp>::q_type, n / 4>& c)
{
typedef typename V_TypeTraits<_Tp>::q_type q_type;
v_reg<q_type, n/4> s;
for( int i = 0; i < (n/4); i++ )
s.s[i] = (q_type)a.s[i*4 ]*b.s[i*4 ] + (q_type)a.s[i*4 + 1]*b.s[i*4 + 1] +
(q_type)a.s[i*4 + 2]*b.s[i*4 + 2] + (q_type)a.s[i*4 + 3]*b.s[i*4 + 3] + c.s[i];
return s;
}
/** @brief Fast Dot product of elements and expand
Multiply values in two registers and expand the sum of adjacent result pairs.
Same as cv::v_dotprod_expand, but it may perform unorder sum between result pairs in some platforms,
this intrinsic can be used if the sum among all lanes is only matters
and also it should be yielding better performance on the affected platforms.
*/
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::q_type, n/4>
v_dotprod_expand_fast(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{ return v_dotprod_expand(a, b); }
/** @brief Fast Dot product of elements
Same as cv::v_dotprod_expand_fast, but add a third element to the sum of adjacent pairs.
*/
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::q_type, n/4>
v_dotprod_expand_fast(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<typename V_TypeTraits<_Tp>::q_type, n / 4>& c)
{ return v_dotprod_expand(a, b, c); }
/** @brief Multiply and expand
Multiply values two registers and store results in two registers with wider pack type.
@@ -1080,7 +1174,7 @@ Example:
v_int32x4 r; // set to {-1, -1, 1, 1}
int mask = v_signmask(r); // mask = 3 <== 00000000 00000000 00000000 00000011
@endcode
For all types except 64-bit. */
*/
template<typename _Tp, int n> inline int v_signmask(const v_reg<_Tp, n>& a)
{
int mask = 0;
@@ -1109,7 +1203,7 @@ template <typename _Tp, int n> inline int v_scan_forward(const v_reg<_Tp, n>& a)
/** @brief Check if all packed values are less than zero
Unsigned values will be casted to signed: `uchar 254 => char -2`.
For all types except 64-bit. */
*/
template<typename _Tp, int n> inline bool v_check_all(const v_reg<_Tp, n>& a)
{
for( int i = 0; i < n; i++ )
@@ -1121,7 +1215,7 @@ template<typename _Tp, int n> inline bool v_check_all(const v_reg<_Tp, n>& a)
/** @brief Check if any of packed values is less than zero
Unsigned values will be casted to signed: `uchar 254 => char -2`.
For all types except 64-bit. */
*/
template<typename _Tp, int n> inline bool v_check_any(const v_reg<_Tp, n>& a)
{
for( int i = 0; i < n; i++ )
@@ -1810,6 +1904,17 @@ template<int n> inline v_reg<double, n> v_cvt_f64(const v_reg<float, n*2>& a)
return c;
}
/** @brief Convert to double
Supported input type is cv::v_int64x2. */
template<int n> inline v_reg<double, n> v_cvt_f64(const v_reg<int64, n>& a)
{
v_reg<double, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (double)a.s[i];
return c;
}
template<typename _Tp> inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_lut(const _Tp* tab, const int* idx)
{
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
@@ -160,6 +160,16 @@ void v_mul_expand(const __CV_V_UINT32&, const __CV_V_UINT32&, __CV_V_UINT64&, __
void v_mul_expand(const __CV_V_INT32&, const __CV_V_INT32&, __CV_V_INT64&, __CV_V_INT64&);
#endif
// Conversions
__CV_V_FLOAT32 v_cvt_f32(const __CV_V_INT32& a);
__CV_V_FLOAT32 v_cvt_f32(const __CV_V_FLOAT64& a);
__CV_V_FLOAT32 v_cvt_f32(const __CV_V_FLOAT64& a, const __CV_V_FLOAT64& b);
__CV_V_FLOAT64 v_cvt_f64(const __CV_V_INT32& a);
__CV_V_FLOAT64 v_cvt_f64_high(const __CV_V_INT32& a);
__CV_V_FLOAT64 v_cvt_f64(const __CV_V_FLOAT32& a);
__CV_V_FLOAT64 v_cvt_f64_high(const __CV_V_FLOAT32& a);
__CV_V_FLOAT64 v_cvt_f64(const __CV_V_INT64& a);
/** Cleanup **/
#undef CV__SIMD_FORWARD
#undef __CV_VX
File diff suppressed because it is too large Load Diff
@@ -62,23 +62,63 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
#define CV_SIMD128_64F 0
#endif
// TODO
#define CV_NEON_DOT 0
//////////// Utils ////////////
#if CV_SIMD128_64F
#define OPENCV_HAL_IMPL_NEON_UNZIP(_Tpv, _Tpvx2, suffix) \
inline void _v128_unzip(const _Tpv& a, const _Tpv& b, _Tpv& c, _Tpv& d) \
{ c = vuzp1q_##suffix(a, b); d = vuzp2q_##suffix(a, b); }
#define OPENCV_HAL_IMPL_NEON_UNZIP_L(_Tpv, _Tpvx2, suffix) \
inline void _v128_unzip(const _Tpv&a, const _Tpv&b, _Tpv& c, _Tpv& d) \
{ c = vuzp1_##suffix(a, b); d = vuzp2_##suffix(a, b); }
#else
#define OPENCV_HAL_IMPL_NEON_UNZIP(_Tpv, _Tpvx2, suffix) \
inline void _v128_unzip(const _Tpv& a, const _Tpv& b, _Tpv& c, _Tpv& d) \
{ _Tpvx2 ab = vuzpq_##suffix(a, b); c = ab.val[0]; d = ab.val[1]; }
#define OPENCV_HAL_IMPL_NEON_UNZIP_L(_Tpv, _Tpvx2, suffix) \
inline void _v128_unzip(const _Tpv& a, const _Tpv& b, _Tpv& c, _Tpv& d) \
{ _Tpvx2 ab = vuzp_##suffix(a, b); c = ab.val[0]; d = ab.val[1]; }
#endif
#if CV_SIMD128_64F
#define OPENCV_HAL_IMPL_NEON_REINTERPRET(_Tpv, suffix) \
template <typename T> static inline \
_Tpv vreinterpretq_##suffix##_f64(T a) { return (_Tpv) a; } \
template <typename T> static inline \
float64x2_t vreinterpretq_f64_##suffix(T a) { return (float64x2_t) a; }
OPENCV_HAL_IMPL_NEON_REINTERPRET(uint8x16_t, u8)
OPENCV_HAL_IMPL_NEON_REINTERPRET(int8x16_t, s8)
OPENCV_HAL_IMPL_NEON_REINTERPRET(uint16x8_t, u16)
OPENCV_HAL_IMPL_NEON_REINTERPRET(int16x8_t, s16)
OPENCV_HAL_IMPL_NEON_REINTERPRET(uint32x4_t, u32)
OPENCV_HAL_IMPL_NEON_REINTERPRET(int32x4_t, s32)
OPENCV_HAL_IMPL_NEON_REINTERPRET(uint64x2_t, u64)
OPENCV_HAL_IMPL_NEON_REINTERPRET(int64x2_t, s64)
OPENCV_HAL_IMPL_NEON_REINTERPRET(float32x4_t, f32)
template <typename T> static inline \
_Tpv vreinterpretq_##suffix##_f64(T a) { return (_Tpv) a; } \
template <typename T> static inline \
float64x2_t vreinterpretq_f64_##suffix(T a) { return (float64x2_t) a; }
#else
#define OPENCV_HAL_IMPL_NEON_REINTERPRET(_Tpv, suffix)
#endif
#define OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX(_Tpv, _Tpvl, suffix) \
OPENCV_HAL_IMPL_NEON_UNZIP(_Tpv##_t, _Tpv##x2_t, suffix) \
OPENCV_HAL_IMPL_NEON_UNZIP_L(_Tpvl##_t, _Tpvl##x2_t, suffix) \
OPENCV_HAL_IMPL_NEON_REINTERPRET(_Tpv##_t, suffix)
#define OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX_I64(_Tpv, _Tpvl, suffix) \
OPENCV_HAL_IMPL_NEON_REINTERPRET(_Tpv##_t, suffix)
#define OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX_F64(_Tpv, _Tpvl, suffix) \
OPENCV_HAL_IMPL_NEON_UNZIP(_Tpv##_t, _Tpv##x2_t, suffix)
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX(uint8x16, uint8x8, u8)
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX(int8x16, int8x8, s8)
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX(uint16x8, uint16x4, u16)
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX(int16x8, int16x4, s16)
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX(uint32x4, uint32x2, u32)
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX(int32x4, int32x2, s32)
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX(float32x4, float32x2, f32)
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX_I64(uint64x2, uint64x1, u64)
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX_I64(int64x2, int64x1, s64)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_NEON_UTILS_SUFFIX_F64(float64x2, float64x1,f64)
#endif
//////////// Types ////////////
struct v_uint8x16
{
typedef uchar lane_type;
@@ -528,20 +568,272 @@ inline v_uint16x8 v_mul_hi(const v_uint16x8& a, const v_uint16x8& b)
));
}
//////// Dot Product ////////
// 16 >> 32
inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b)
{
int32x4_t c = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val));
int32x4_t d = vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val));
int32x4x2_t cd = vuzpq_s32(c, d);
return v_int32x4(vaddq_s32(cd.val[0], cd.val[1]));
int16x8_t uzp1, uzp2;
_v128_unzip(a.val, b.val, uzp1, uzp2);
int16x4_t a0 = vget_low_s16(uzp1);
int16x4_t b0 = vget_high_s16(uzp1);
int16x4_t a1 = vget_low_s16(uzp2);
int16x4_t b1 = vget_high_s16(uzp2);
int32x4_t p = vmull_s16(a0, b0);
return v_int32x4(vmlal_s16(p, a1, b1));
}
inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c)
{
v_int32x4 s = v_dotprod(a, b);
return v_int32x4(vaddq_s32(s.val , c.val));
int16x8_t uzp1, uzp2;
_v128_unzip(a.val, b.val, uzp1, uzp2);
int16x4_t a0 = vget_low_s16(uzp1);
int16x4_t b0 = vget_high_s16(uzp1);
int16x4_t a1 = vget_low_s16(uzp2);
int16x4_t b1 = vget_high_s16(uzp2);
int32x4_t p = vmlal_s16(c.val, a0, b0);
return v_int32x4(vmlal_s16(p, a1, b1));
}
// 32 >> 64
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b)
{
int32x4_t uzp1, uzp2;
_v128_unzip(a.val, b.val, uzp1, uzp2);
int32x2_t a0 = vget_low_s32(uzp1);
int32x2_t b0 = vget_high_s32(uzp1);
int32x2_t a1 = vget_low_s32(uzp2);
int32x2_t b1 = vget_high_s32(uzp2);
int64x2_t p = vmull_s32(a0, b0);
return v_int64x2(vmlal_s32(p, a1, b1));
}
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
{
int32x4_t uzp1, uzp2;
_v128_unzip(a.val, b.val, uzp1, uzp2);
int32x2_t a0 = vget_low_s32(uzp1);
int32x2_t b0 = vget_high_s32(uzp1);
int32x2_t a1 = vget_low_s32(uzp2);
int32x2_t b1 = vget_high_s32(uzp2);
int64x2_t p = vmlal_s32(c.val, a0, b0);
return v_int64x2(vmlal_s32(p, a1, b1));
}
// 8 >> 32
inline v_uint32x4 v_dotprod_expand(const v_uint8x16& a, const v_uint8x16& b)
{
#if CV_NEON_DOT
return v_uint32x4(vdotq_u32(vdupq_n_u32(0), a.val, b.val));
#else
const uint8x16_t zero = vreinterpretq_u8_u32(vdupq_n_u32(0));
const uint8x16_t mask = vreinterpretq_u8_u32(vdupq_n_u32(0x00FF00FF));
const uint16x8_t zero32 = vreinterpretq_u16_u32(vdupq_n_u32(0));
const uint16x8_t mask32 = vreinterpretq_u16_u32(vdupq_n_u32(0x0000FFFF));
uint16x8_t even = vmulq_u16(vreinterpretq_u16_u8(vbslq_u8(mask, a.val, zero)),
vreinterpretq_u16_u8(vbslq_u8(mask, b.val, zero)));
uint16x8_t odd = vmulq_u16(vshrq_n_u16(vreinterpretq_u16_u8(a.val), 8),
vshrq_n_u16(vreinterpretq_u16_u8(b.val), 8));
uint32x4_t s0 = vaddq_u32(vreinterpretq_u32_u16(vbslq_u16(mask32, even, zero32)),
vreinterpretq_u32_u16(vbslq_u16(mask32, odd, zero32)));
uint32x4_t s1 = vaddq_u32(vshrq_n_u32(vreinterpretq_u32_u16(even), 16),
vshrq_n_u32(vreinterpretq_u32_u16(odd), 16));
return v_uint32x4(vaddq_u32(s0, s1));
#endif
}
inline v_uint32x4 v_dotprod_expand(const v_uint8x16& a, const v_uint8x16& b,
const v_uint32x4& c)
{
#if CV_NEON_DOT
return v_uint32x4(vdotq_u32(c.val, a.val, b.val));
#else
return v_dotprod_expand(a, b) + c;
#endif
}
inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b)
{
#if CV_NEON_DOT
return v_int32x4(vdotq_s32(vdupq_n_s32(0), a.val, b.val));
#else
int16x8_t p0 = vmull_s8(vget_low_s8(a.val), vget_low_s8(b.val));
int16x8_t p1 = vmull_s8(vget_high_s8(a.val), vget_high_s8(b.val));
int16x8_t uzp1, uzp2;
_v128_unzip(p0, p1, uzp1, uzp2);
int16x8_t sum = vaddq_s16(uzp1, uzp2);
int16x4_t uzpl1, uzpl2;
_v128_unzip(vget_low_s16(sum), vget_high_s16(sum), uzpl1, uzpl2);
return v_int32x4(vaddl_s16(uzpl1, uzpl2));
#endif
}
inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b,
const v_int32x4& c)
{
#if CV_NEON_DOT
return v_int32x4(vdotq_s32(c.val, a.val, b.val));
#else
return v_dotprod_expand(a, b) + c;
#endif
}
// 16 >> 64
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b)
{
const uint16x8_t zero = vreinterpretq_u16_u32(vdupq_n_u32(0));
const uint16x8_t mask = vreinterpretq_u16_u32(vdupq_n_u32(0x0000FFFF));
uint32x4_t even = vmulq_u32(vreinterpretq_u32_u16(vbslq_u16(mask, a.val, zero)),
vreinterpretq_u32_u16(vbslq_u16(mask, b.val, zero)));
uint32x4_t odd = vmulq_u32(vshrq_n_u32(vreinterpretq_u32_u16(a.val), 16),
vshrq_n_u32(vreinterpretq_u32_u16(b.val), 16));
uint32x4_t uzp1, uzp2;
_v128_unzip(even, odd, uzp1, uzp2);
uint64x2_t s0 = vaddl_u32(vget_low_u32(uzp1), vget_high_u32(uzp1));
uint64x2_t s1 = vaddl_u32(vget_low_u32(uzp2), vget_high_u32(uzp2));
return v_uint64x2(vaddq_u64(s0, s1));
}
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c)
{ return v_dotprod_expand(a, b) + c; }
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b)
{
int32x4_t p0 = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val));
int32x4_t p1 = vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val));
int32x4_t uzp1, uzp2;
_v128_unzip(p0, p1, uzp1, uzp2);
int32x4_t sum = vaddq_s32(uzp1, uzp2);
int32x2_t uzpl1, uzpl2;
_v128_unzip(vget_low_s32(sum), vget_high_s32(sum), uzpl1, uzpl2);
return v_int64x2(vaddl_s32(uzpl1, uzpl2));
}
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b,
const v_int64x2& c)
{ return v_dotprod_expand(a, b) + c; }
// 32 >> 64f
#if CV_SIMD128_64F
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b)
{ return v_cvt_f64(v_dotprod(a, b)); }
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b,
const v_float64x2& c)
{ return v_dotprod_expand(a, b) + c; }
#endif
//////// Fast Dot Product ////////
// 16 >> 32
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b)
{
int16x4_t a0 = vget_low_s16(a.val);
int16x4_t a1 = vget_high_s16(a.val);
int16x4_t b0 = vget_low_s16(b.val);
int16x4_t b1 = vget_high_s16(b.val);
int32x4_t p = vmull_s16(a0, b0);
return v_int32x4(vmlal_s16(p, a1, b1));
}
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c)
{
int16x4_t a0 = vget_low_s16(a.val);
int16x4_t a1 = vget_high_s16(a.val);
int16x4_t b0 = vget_low_s16(b.val);
int16x4_t b1 = vget_high_s16(b.val);
int32x4_t p = vmlal_s16(c.val, a0, b0);
return v_int32x4(vmlal_s16(p, a1, b1));
}
// 32 >> 64
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b)
{
int32x2_t a0 = vget_low_s32(a.val);
int32x2_t a1 = vget_high_s32(a.val);
int32x2_t b0 = vget_low_s32(b.val);
int32x2_t b1 = vget_high_s32(b.val);
int64x2_t p = vmull_s32(a0, b0);
return v_int64x2(vmlal_s32(p, a1, b1));
}
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
{
int32x2_t a0 = vget_low_s32(a.val);
int32x2_t a1 = vget_high_s32(a.val);
int32x2_t b0 = vget_low_s32(b.val);
int32x2_t b1 = vget_high_s32(b.val);
int64x2_t p = vmlal_s32(c.val, a0, b0);
return v_int64x2(vmlal_s32(p, a1, b1));
}
// 8 >> 32
inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b)
{
#if CV_NEON_DOT
return v_uint32x4(vdotq_u32(vdupq_n_u32(0), a.val, b.val));
#else
uint16x8_t p0 = vmull_u8(vget_low_u8(a.val), vget_low_u8(b.val));
uint16x8_t p1 = vmull_u8(vget_high_u8(a.val), vget_high_u8(b.val));
uint32x4_t s0 = vaddl_u16(vget_low_u16(p0), vget_low_u16(p1));
uint32x4_t s1 = vaddl_u16(vget_high_u16(p0), vget_high_u16(p1));
return v_uint32x4(vaddq_u32(s0, s1));
#endif
}
inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b, const v_uint32x4& c)
{
#if CV_NEON_DOT
return v_uint32x4(vdotq_u32(c.val, a.val, b.val));
#else
return v_dotprod_expand_fast(a, b) + c;
#endif
}
inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b)
{
#if CV_NEON_DOT
return v_int32x4(vdotq_s32(vdupq_n_s32(0), a.val, b.val));
#else
int16x8_t prod = vmull_s8(vget_low_s8(a.val), vget_low_s8(b.val));
prod = vmlal_s8(prod, vget_high_s8(a.val), vget_high_s8(b.val));
return v_int32x4(vaddl_s16(vget_low_s16(prod), vget_high_s16(prod)));
#endif
}
inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b, const v_int32x4& c)
{
#if CV_NEON_DOT
return v_int32x4(vdotq_s32(c.val, a.val, b.val));
#else
return v_dotprod_expand_fast(a, b) + c;
#endif
}
// 16 >> 64
inline v_uint64x2 v_dotprod_expand_fast(const v_uint16x8& a, const v_uint16x8& b)
{
uint32x4_t p0 = vmull_u16(vget_low_u16(a.val), vget_low_u16(b.val));
uint32x4_t p1 = vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val));
uint64x2_t s0 = vaddl_u32(vget_low_u32(p0), vget_high_u32(p0));
uint64x2_t s1 = vaddl_u32(vget_low_u32(p1), vget_high_u32(p1));
return v_uint64x2(vaddq_u64(s0, s1));
}
inline v_uint64x2 v_dotprod_expand_fast(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c)
{ return v_dotprod_expand_fast(a, b) + c; }
inline v_int64x2 v_dotprod_expand_fast(const v_int16x8& a, const v_int16x8& b)
{
int32x4_t prod = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val));
prod = vmlal_s16(prod, vget_high_s16(a.val), vget_high_s16(b.val));
return v_int64x2(vaddl_s32(vget_low_s32(prod), vget_high_s32(prod)));
}
inline v_int64x2 v_dotprod_expand_fast(const v_int16x8& a, const v_int16x8& b, const v_int64x2& c)
{ return v_dotprod_expand_fast(a, b) + c; }
// 32 >> 64f
#if CV_SIMD128_64F
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b)
{ return v_cvt_f64(v_dotprod_fast(a, b)); }
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b, const v_float64x2& c)
{ return v_dotprod_expand_fast(a, b) + c; }
#endif
#define OPENCV_HAL_IMPL_NEON_LOGIC_OP(_Tpvec, suffix) \
OPENCV_HAL_IMPL_NEON_BIN_OP(&, _Tpvec, vandq_##suffix) \
OPENCV_HAL_IMPL_NEON_BIN_OP(|, _Tpvec, vorrq_##suffix) \
@@ -1139,9 +1431,17 @@ inline bool v_check_any(const v_##_Tpvec& a) \
OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint8x16, u8, 7)
OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint16x8, u16, 15)
OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint32x4, u32, 31)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint64x2, u64, 63)
#endif
inline bool v_check_all(const v_uint64x2& a)
{
uint64x2_t v0 = vshrq_n_u64(a.val, 63);
return (vgetq_lane_u64(v0, 0) & vgetq_lane_u64(v0, 1)) == 1;
}
inline bool v_check_any(const v_uint64x2& a)
{
uint64x2_t v0 = vshrq_n_u64(a.val, 63);
return (vgetq_lane_u64(v0, 0) | vgetq_lane_u64(v0, 1)) != 0;
}
inline bool v_check_all(const v_int8x16& a)
{ return v_check_all(v_reinterpret_as_u8(a)); }
@@ -1161,13 +1461,13 @@ inline bool v_check_any(const v_int32x4& a)
inline bool v_check_any(const v_float32x4& a)
{ return v_check_any(v_reinterpret_as_u32(a)); }
#if CV_SIMD128_64F
inline bool v_check_all(const v_int64x2& a)
{ return v_check_all(v_reinterpret_as_u64(a)); }
inline bool v_check_all(const v_float64x2& a)
{ return v_check_all(v_reinterpret_as_u64(a)); }
inline bool v_check_any(const v_int64x2& a)
{ return v_check_any(v_reinterpret_as_u64(a)); }
#if CV_SIMD128_64F
inline bool v_check_all(const v_float64x2& a)
{ return v_check_all(v_reinterpret_as_u64(a)); }
inline bool v_check_any(const v_float64x2& a)
{ return v_check_any(v_reinterpret_as_u64(a)); }
#endif
@@ -1585,6 +1885,10 @@ inline v_float64x2 v_cvt_f64_high(const v_float32x4& a)
{
return v_float64x2(vcvt_f64_f32(vget_high_f32(a.val)));
}
inline v_float64x2 v_cvt_f64(const v_int64x2& a)
{ return v_float64x2(vcvtq_f64_s64(a.val)); }
#endif
////////////// Lookup table access ////////////////////
@@ -225,9 +225,13 @@ struct v_uint64x2
}
uint64 get0() const
{
#if !defined(__x86_64__) && !defined(_M_X64)
int a = _mm_cvtsi128_si32(val);
int b = _mm_cvtsi128_si32(_mm_srli_epi64(val, 32));
return (unsigned)a | ((uint64)(unsigned)b << 32);
#else
return (uint64)_mm_cvtsi128_si64(val);
#endif
}
__m128i val;
@@ -247,9 +251,13 @@ struct v_int64x2
}
int64 get0() const
{
#if !defined(__x86_64__) && !defined(_M_X64)
int a = _mm_cvtsi128_si32(val);
int b = _mm_cvtsi128_si32(_mm_srli_epi64(val, 32));
return (int64)((unsigned)a | ((uint64)(unsigned)b << 32));
#else
return _mm_cvtsi128_si64(val);
#endif
}
__m128i val;
@@ -791,15 +799,195 @@ inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b,
inline v_int16x8 v_mul_hi(const v_int16x8& a, const v_int16x8& b) { return v_int16x8(_mm_mulhi_epi16(a.val, b.val)); }
inline v_uint16x8 v_mul_hi(const v_uint16x8& a, const v_uint16x8& b) { return v_uint16x8(_mm_mulhi_epu16(a.val, b.val)); }
inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b)
{
return v_int32x4(_mm_madd_epi16(a.val, b.val));
}
//////// Dot Product ////////
// 16 >> 32
inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b)
{ return v_int32x4(_mm_madd_epi16(a.val, b.val)); }
inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c)
{ return v_dotprod(a, b) + c; }
// 32 >> 64
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b)
{
return v_int32x4(_mm_add_epi32(_mm_madd_epi16(a.val, b.val), c.val));
#if CV_SSE4_1
__m128i even = _mm_mul_epi32(a.val, b.val);
__m128i odd = _mm_mul_epi32(_mm_srli_epi64(a.val, 32), _mm_srli_epi64(b.val, 32));
return v_int64x2(_mm_add_epi64(even, odd));
#else
__m128i even_u = _mm_mul_epu32(a.val, b.val);
__m128i odd_u = _mm_mul_epu32(_mm_srli_epi64(a.val, 32), _mm_srli_epi64(b.val, 32));
// convert unsigned to signed high multiplication (from: Agner Fog(veclib) and H S Warren: Hacker's delight, 2003, p. 132)
__m128i a_sign = _mm_srai_epi32(a.val, 31);
__m128i b_sign = _mm_srai_epi32(b.val, 31);
// |x * sign of x
__m128i axb = _mm_and_si128(a.val, b_sign);
__m128i bxa = _mm_and_si128(b.val, a_sign);
// sum of sign corrections
__m128i ssum = _mm_add_epi32(bxa, axb);
__m128i even_ssum = _mm_slli_epi64(ssum, 32);
__m128i odd_ssum = _mm_and_si128(ssum, _mm_set_epi32(-1, 0, -1, 0));
// convert to signed and prod
return v_int64x2(_mm_add_epi64(_mm_sub_epi64(even_u, even_ssum), _mm_sub_epi64(odd_u, odd_ssum)));
#endif
}
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
{ return v_dotprod(a, b) + c; }
// 8 >> 32
inline v_uint32x4 v_dotprod_expand(const v_uint8x16& a, const v_uint8x16& b)
{
__m128i a0 = _mm_srli_epi16(_mm_slli_si128(a.val, 1), 8); // even
__m128i a1 = _mm_srli_epi16(a.val, 8); // odd
__m128i b0 = _mm_srli_epi16(_mm_slli_si128(b.val, 1), 8);
__m128i b1 = _mm_srli_epi16(b.val, 8);
__m128i p0 = _mm_madd_epi16(a0, b0);
__m128i p1 = _mm_madd_epi16(a1, b1);
return v_uint32x4(_mm_add_epi32(p0, p1));
}
inline v_uint32x4 v_dotprod_expand(const v_uint8x16& a, const v_uint8x16& b, const v_uint32x4& c)
{ return v_dotprod_expand(a, b) + c; }
inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b)
{
__m128i a0 = _mm_srai_epi16(_mm_slli_si128(a.val, 1), 8); // even
__m128i a1 = _mm_srai_epi16(a.val, 8); // odd
__m128i b0 = _mm_srai_epi16(_mm_slli_si128(b.val, 1), 8);
__m128i b1 = _mm_srai_epi16(b.val, 8);
__m128i p0 = _mm_madd_epi16(a0, b0);
__m128i p1 = _mm_madd_epi16(a1, b1);
return v_int32x4(_mm_add_epi32(p0, p1));
}
inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b, const v_int32x4& c)
{ return v_dotprod_expand(a, b) + c; }
// 16 >> 64
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b)
{
v_uint32x4 c, d;
v_mul_expand(a, b, c, d);
v_uint64x2 c0, c1, d0, d1;
v_expand(c, c0, c1);
v_expand(d, d0, d1);
c0 += c1; d0 += d1;
return v_uint64x2(_mm_add_epi64(
_mm_unpacklo_epi64(c0.val, d0.val),
_mm_unpackhi_epi64(c0.val, d0.val)
));
}
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c)
{ return v_dotprod_expand(a, b) + c; }
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b)
{
v_int32x4 prod = v_dotprod(a, b);
v_int64x2 c, d;
v_expand(prod, c, d);
return v_int64x2(_mm_add_epi64(
_mm_unpacklo_epi64(c.val, d.val),
_mm_unpackhi_epi64(c.val, d.val)
));
}
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b, const v_int64x2& c)
{ return v_dotprod_expand(a, b) + c; }
// 32 >> 64f
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b)
{
#if CV_SSE4_1
return v_cvt_f64(v_dotprod(a, b));
#else
v_float64x2 c = v_cvt_f64(a) * v_cvt_f64(b);
v_float64x2 d = v_cvt_f64_high(a) * v_cvt_f64_high(b);
return v_float64x2(_mm_add_pd(
_mm_unpacklo_pd(c.val, d.val),
_mm_unpackhi_pd(c.val, d.val)
));
#endif
}
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b, const v_float64x2& c)
{ return v_dotprod_expand(a, b) + c; }
//////// Fast Dot Product ////////
// 16 >> 32
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b)
{ return v_dotprod(a, b); }
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c)
{ return v_dotprod(a, b) + c; }
// 32 >> 64
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b)
{ return v_dotprod(a, b); }
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
{ return v_dotprod_fast(a, b) + c; }
// 8 >> 32
inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b)
{
__m128i a0 = v_expand_low(a).val;
__m128i a1 = v_expand_high(a).val;
__m128i b0 = v_expand_low(b).val;
__m128i b1 = v_expand_high(b).val;
__m128i p0 = _mm_madd_epi16(a0, b0);
__m128i p1 = _mm_madd_epi16(a1, b1);
return v_uint32x4(_mm_add_epi32(p0, p1));
}
inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b, const v_uint32x4& c)
{ return v_dotprod_expand_fast(a, b) + c; }
inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b)
{
#if CV_SSE4_1
__m128i a0 = _mm_cvtepi8_epi16(a.val);
__m128i a1 = v_expand_high(a).val;
__m128i b0 = _mm_cvtepi8_epi16(b.val);
__m128i b1 = v_expand_high(b).val;
__m128i p0 = _mm_madd_epi16(a0, b0);
__m128i p1 = _mm_madd_epi16(a1, b1);
return v_int32x4(_mm_add_epi32(p0, p1));
#else
return v_dotprod_expand(a, b);
#endif
}
inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b, const v_int32x4& c)
{ return v_dotprod_expand_fast(a, b) + c; }
// 16 >> 64
inline v_uint64x2 v_dotprod_expand_fast(const v_uint16x8& a, const v_uint16x8& b)
{
v_uint32x4 c, d;
v_mul_expand(a, b, c, d);
v_uint64x2 c0, c1, d0, d1;
v_expand(c, c0, c1);
v_expand(d, d0, d1);
c0 += c1; d0 += d1;
return c0 + d0;
}
inline v_uint64x2 v_dotprod_expand_fast(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c)
{ return v_dotprod_expand_fast(a, b) + c; }
inline v_int64x2 v_dotprod_expand_fast(const v_int16x8& a, const v_int16x8& b)
{
v_int32x4 prod = v_dotprod(a, b);
v_int64x2 c, d;
v_expand(prod, c, d);
return c + d;
}
inline v_int64x2 v_dotprod_expand_fast(const v_int16x8& a, const v_int16x8& b, const v_int64x2& c)
{ return v_dotprod_expand_fast(a, b) + c; }
// 32 >> 64f
v_float64x2 v_fma(const v_float64x2& a, const v_float64x2& b, const v_float64x2& c);
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b)
{ return v_fma(v_cvt_f64(a), v_cvt_f64(b), v_cvt_f64_high(a) * v_cvt_f64_high(b)); }
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b, const v_float64x2& c)
{ return v_fma(v_cvt_f64(a), v_cvt_f64(b), v_fma(v_cvt_f64_high(a), v_cvt_f64_high(b), c)); }
#define OPENCV_HAL_IMPL_SSE_LOGIC_OP(_Tpvec, suffix, not_const) \
OPENCV_HAL_IMPL_SSE_BIN_OP(&, _Tpvec, _mm_and_##suffix) \
@@ -1591,31 +1779,25 @@ inline v_uint32x4 v_popcount(const v_int32x4& a)
inline v_uint64x2 v_popcount(const v_int64x2& a)
{ return v_popcount(v_reinterpret_as_u64(a)); }
#define OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(_Tpvec, suffix, pack_op, and_op, signmask, allmask) \
inline int v_signmask(const _Tpvec& a) \
{ \
return and_op(_mm_movemask_##suffix(pack_op(a.val)), signmask); \
} \
inline bool v_check_all(const _Tpvec& a) \
{ return and_op(_mm_movemask_##suffix(a.val), allmask) == allmask; } \
inline bool v_check_any(const _Tpvec& a) \
{ return and_op(_mm_movemask_##suffix(a.val), allmask) != 0; }
#define OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(_Tpvec, suffix, cast_op, allmask) \
inline int v_signmask(const _Tpvec& a) { return _mm_movemask_##suffix(cast_op(a.val)); } \
inline bool v_check_all(const _Tpvec& a) { return _mm_movemask_##suffix(cast_op(a.val)) == allmask; } \
inline bool v_check_any(const _Tpvec& a) { return _mm_movemask_##suffix(cast_op(a.val)) != 0; }
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_uint8x16, epi8, OPENCV_HAL_NOP, 65535)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_int8x16, epi8, OPENCV_HAL_NOP, 65535)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_uint32x4, ps, _mm_castsi128_ps, 15)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_int32x4, ps, _mm_castsi128_ps, 15)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_uint64x2, pd, _mm_castsi128_pd, 3)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_int64x2, pd, _mm_castsi128_pd, 3)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_float32x4, ps, OPENCV_HAL_NOP, 15)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_float64x2, pd, OPENCV_HAL_NOP, 3)
#define OPENCV_HAL_PACKS(a) _mm_packs_epi16(a, a)
inline __m128i v_packq_epi32(__m128i a)
{
__m128i b = _mm_packs_epi32(a, a);
return _mm_packs_epi16(b, b);
}
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_uint8x16, epi8, OPENCV_HAL_NOP, OPENCV_HAL_1ST, 65535, 65535)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_int8x16, epi8, OPENCV_HAL_NOP, OPENCV_HAL_1ST, 65535, 65535)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_uint16x8, epi8, OPENCV_HAL_PACKS, OPENCV_HAL_AND, 255, (int)0xaaaa)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_int16x8, epi8, OPENCV_HAL_PACKS, OPENCV_HAL_AND, 255, (int)0xaaaa)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_uint32x4, epi8, v_packq_epi32, OPENCV_HAL_AND, 15, (int)0x8888)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_int32x4, epi8, v_packq_epi32, OPENCV_HAL_AND, 15, (int)0x8888)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_float32x4, ps, OPENCV_HAL_NOP, OPENCV_HAL_1ST, 15, 15)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_float64x2, pd, OPENCV_HAL_NOP, OPENCV_HAL_1ST, 3, 3)
#define OPENCV_HAL_IMPL_SSE_CHECK_SIGNS_SHORT(_Tpvec) \
inline int v_signmask(const _Tpvec& a) { return _mm_movemask_epi8(_mm_packs_epi16(a.val, a.val)) & 255; } \
inline bool v_check_all(const _Tpvec& a) { return (_mm_movemask_epi8(a.val) & 0xaaaa) == 0xaaaa; } \
inline bool v_check_any(const _Tpvec& a) { return (_mm_movemask_epi8(a.val) & 0xaaaa) != 0; }
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS_SHORT(v_uint16x8)
OPENCV_HAL_IMPL_SSE_CHECK_SIGNS_SHORT(v_int16x8)
inline int v_scan_forward(const v_int8x16& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))); }
inline int v_scan_forward(const v_uint8x16& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))); }
@@ -2745,6 +2927,32 @@ inline v_float64x2 v_cvt_f64_high(const v_float32x4& a)
return v_float64x2(_mm_cvtps_pd(_mm_movehl_ps(a.val, a.val)));
}
// from (Mysticial and wim) https://stackoverflow.com/q/41144668
inline v_float64x2 v_cvt_f64(const v_int64x2& v)
{
// constants encoded as floating-point
__m128i magic_i_hi32 = _mm_set1_epi64x(0x4530000080000000); // 2^84 + 2^63
__m128i magic_i_all = _mm_set1_epi64x(0x4530000080100000); // 2^84 + 2^63 + 2^52
__m128d magic_d_all = _mm_castsi128_pd(magic_i_all);
// Blend the 32 lowest significant bits of v with magic_int_lo
#if CV_SSE4_1
__m128i magic_i_lo = _mm_set1_epi64x(0x4330000000000000); // 2^52
__m128i v_lo = _mm_blend_epi16(v.val, magic_i_lo, 0xcc);
#else
__m128i magic_i_lo = _mm_set1_epi32(0x43300000); // 2^52
__m128i v_lo = _mm_unpacklo_epi32(_mm_shuffle_epi32(v.val, _MM_SHUFFLE(0, 0, 2, 0)), magic_i_lo);
#endif
// Extract the 32 most significant bits of v
__m128i v_hi = _mm_srli_epi64(v.val, 32);
// Flip the msb of v_hi and blend with 0x45300000
v_hi = _mm_xor_si128(v_hi, magic_i_hi32);
// Compute in double precision
__m128d v_hi_dbl = _mm_sub_pd(_mm_castsi128_pd(v_hi), magic_d_all);
// (v_hi - magic_d_all) + v_lo Do not assume associativity of floating point addition
__m128d result = _mm_add_pd(v_hi_dbl, _mm_castsi128_pd(v_lo));
return v_float64x2(result);
}
////////////// Lookup table access ////////////////////
inline v_int8x16 v_lut(const schar* tab, const int* idx)
@@ -499,12 +499,6 @@ inline void v_mul_expand(const Tvec& a, const Tvec& b, Twvec& c, Twvec& d)
v_zip(p0, p1, c, d);
}
inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b, v_uint64x2& c, v_uint64x2& d)
{
c.val = vec_mul(vec_unpackhu(a.val), vec_unpackhu(b.val));
d.val = vec_mul(vec_unpacklu(a.val), vec_unpacklu(b.val));
}
inline v_int16x8 v_mul_hi(const v_int16x8& a, const v_int16x8& b)
{
vec_int4 p0 = vec_mule(a.val, b.val);
@@ -899,6 +893,8 @@ inline bool v_check_all(const v_uint16x8& a)
{ return v_check_all(v_reinterpret_as_s16(a)); }
inline bool v_check_all(const v_uint32x4& a)
{ return v_check_all(v_reinterpret_as_s32(a)); }
inline bool v_check_all(const v_uint64x2& a)
{ return v_check_all(v_reinterpret_as_s64(a)); }
inline bool v_check_all(const v_float32x4& a)
{ return v_check_all(v_reinterpret_as_s32(a)); }
inline bool v_check_all(const v_float64x2& a)
@@ -913,6 +909,8 @@ inline bool v_check_any(const v_uint16x8& a)
{ return v_check_any(v_reinterpret_as_s16(a)); }
inline bool v_check_any(const v_uint32x4& a)
{ return v_check_any(v_reinterpret_as_s32(a)); }
inline bool v_check_any(const v_uint64x2& a)
{ return v_check_any(v_reinterpret_as_s64(a)); }
inline bool v_check_any(const v_float32x4& a)
{ return v_check_any(v_reinterpret_as_s32(a)); }
inline bool v_check_any(const v_float64x2& a)
@@ -1039,14 +1037,8 @@ inline v_float64x2 v_cvt_f64(const v_float32x4& a)
inline v_float64x2 v_cvt_f64_high(const v_float32x4& a)
{ return v_float64x2(vec_cvfo(vec_mergel(a.val, a.val))); }
// The altivec intrinsic is missing for this 2.06 insn
inline v_float64x2 v_cvt_f64(const v_int64x2& a)
{
vec_double2 out;
__asm__ ("xvcvsxddp %x0,%x1" : "=wa"(out) : "wa"(a.val));
return v_float64x2(out);
}
{ return v_float64x2(vec_ctd(a.val)); }
////////////// Lookup table access ////////////////////
@@ -1318,12 +1310,134 @@ inline void v_cleanup() {}
////////// Matrix operations /////////
//////// Dot Product ////////
// 16 >> 32
inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b)
{ return v_int32x4(vec_msum(a.val, b.val, vec_int4_z)); }
inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c)
{ return v_int32x4(vec_msum(a.val, b.val, c.val)); }
// 32 >> 64
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b)
{
vec_dword2 even = vec_mule(a.val, b.val);
vec_dword2 odd = vec_mulo(a.val, b.val);
return v_int64x2(vec_add(even, odd));
}
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
{ return v_dotprod(a, b) + c; }
// 8 >> 32
inline v_uint32x4 v_dotprod_expand(const v_uint8x16& a, const v_uint8x16& b, const v_uint32x4& c)
{ return v_uint32x4(vec_msum(a.val, b.val, c.val)); }
inline v_uint32x4 v_dotprod_expand(const v_uint8x16& a, const v_uint8x16& b)
{ return v_uint32x4(vec_msum(a.val, b.val, vec_uint4_z)); }
inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b)
{
const vec_ushort8 eight = vec_ushort8_sp(8);
vec_short8 a0 = vec_sra((vec_short8)vec_sld(a.val, a.val, 1), eight); // even
vec_short8 a1 = vec_sra((vec_short8)a.val, eight); // odd
vec_short8 b0 = vec_sra((vec_short8)vec_sld(b.val, b.val, 1), eight);
vec_short8 b1 = vec_sra((vec_short8)b.val, eight);
return v_int32x4(vec_msum(a0, b0, vec_msum(a1, b1, vec_int4_z)));
}
inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b, const v_int32x4& c)
{
const vec_ushort8 eight = vec_ushort8_sp(8);
vec_short8 a0 = vec_sra((vec_short8)vec_sld(a.val, a.val, 1), eight); // even
vec_short8 a1 = vec_sra((vec_short8)a.val, eight); // odd
vec_short8 b0 = vec_sra((vec_short8)vec_sld(b.val, b.val, 1), eight);
vec_short8 b1 = vec_sra((vec_short8)b.val, eight);
return v_int32x4(vec_msum(a0, b0, vec_msum(a1, b1, c.val)));
}
// 16 >> 64
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b)
{
const vec_uint4 zero = vec_uint4_z;
vec_uint4 even = vec_mule(a.val, b.val);
vec_uint4 odd = vec_mulo(a.val, b.val);
vec_udword2 e0 = (vec_udword2)vec_mergee(even, zero);
vec_udword2 e1 = (vec_udword2)vec_mergeo(even, zero);
vec_udword2 o0 = (vec_udword2)vec_mergee(odd, zero);
vec_udword2 o1 = (vec_udword2)vec_mergeo(odd, zero);
vec_udword2 s0 = vec_add(e0, o0);
vec_udword2 s1 = vec_add(e1, o1);
return v_uint64x2(vec_add(s0, s1));
}
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c)
{ return v_dotprod_expand(a, b) + c; }
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b)
{
v_int32x4 prod = v_dotprod(a, b);
v_int64x2 c, d;
v_expand(prod, c, d);
return v_int64x2(vec_add(vec_mergeh(c.val, d.val), vec_mergel(c.val, d.val)));
}
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b, const v_int64x2& c)
{ return v_dotprod_expand(a, b) + c; }
// 32 >> 64f
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b)
{ return v_cvt_f64(v_dotprod(a, b)); }
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b, const v_float64x2& c)
{ return v_dotprod_expand(a, b) + c; }
//////// Fast Dot Product ////////
// 16 >> 32
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b)
{ return v_dotprod(a, b); }
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c)
{ return v_int32x4(vec_msum(a.val, b.val, vec_int4_z)) + c; }
// 32 >> 64
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b)
{ return v_dotprod(a, b); }
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
{ return v_dotprod(a, b, c); }
// 8 >> 32
inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b)
{ return v_dotprod_expand(a, b); }
inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b, const v_uint32x4& c)
{ return v_uint32x4(vec_msum(a.val, b.val, vec_uint4_z)) + c; }
inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b)
{
vec_short8 a0 = vec_unpackh(a.val);
vec_short8 a1 = vec_unpackl(a.val);
vec_short8 b0 = vec_unpackh(b.val);
vec_short8 b1 = vec_unpackl(b.val);
return v_int32x4(vec_msum(a0, b0, vec_msum(a1, b1, vec_int4_z)));
}
inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b, const v_int32x4& c)
{ return v_dotprod_expand_fast(a, b) + c; }
// 16 >> 64
inline v_uint64x2 v_dotprod_expand_fast(const v_uint16x8& a, const v_uint16x8& b)
{ return v_dotprod_expand(a, b); }
inline v_uint64x2 v_dotprod_expand_fast(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c)
{ return v_dotprod_expand(a, b, c); }
inline v_int64x2 v_dotprod_expand_fast(const v_int16x8& a, const v_int16x8& b)
{
v_int32x4 prod = v_dotprod(a, b);
v_int64x2 c, d;
v_expand(prod, c, d);
return c + d;
}
inline v_int64x2 v_dotprod_expand_fast(const v_int16x8& a, const v_int16x8& b, const v_int64x2& c)
{ return v_dotprod_expand_fast(a, b) + c; }
// 32 >> 64f
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b)
{ return v_dotprod_expand(a, b); }
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b, const v_float64x2& c)
{ return v_dotprod_expand(a, b, c); }
inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0,
const v_float32x4& m1, const v_float32x4& m2,
const v_float32x4& m3)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -72,7 +72,9 @@
# include "opencv2/core/cuda_stream_accessor.hpp"
# include "opencv2/core/cuda/common.hpp"
# ifndef NPP_VERSION
# define NPP_VERSION (NPP_VERSION_MAJOR * 1000 + NPP_VERSION_MINOR * 100 + NPP_VERSION_BUILD)
# endif
# define CUDART_MINIMUM_REQUIRED_VERSION 6050
@@ -8,7 +8,7 @@
#define CV_VERSION_MAJOR 3
#define CV_VERSION_MINOR 4
#define CV_VERSION_REVISION 8
#define CV_VERSION_STATUS "-pre"
#define CV_VERSION_STATUS ""
#define CVAUX_STR_EXP(__A) #__A
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
@@ -124,6 +124,33 @@ VSX_FINLINE(rt) fnm(const rg& a, const rg& b) \
#define VSX_IMPL_2VRG(rt, rg, opc, fnm) VSX_IMPL_2VRG_F(rt, rg, #opc" %0,%1,%2", fnm)
#if __GNUG__ < 8
// Support for int4 -> dword2 expanding multiply was added in GCC 8.
#ifdef vec_mule
#undef vec_mule
#endif
#ifdef vec_mulo
#undef vec_mulo
#endif
VSX_REDIRECT_2RG(vec_ushort8, vec_uchar16, vec_mule, __builtin_vec_mule)
VSX_REDIRECT_2RG(vec_short8, vec_char16, vec_mule, __builtin_vec_mule)
VSX_REDIRECT_2RG(vec_int4, vec_short8, vec_mule, __builtin_vec_mule)
VSX_REDIRECT_2RG(vec_uint4, vec_ushort8, vec_mule, __builtin_vec_mule)
VSX_REDIRECT_2RG(vec_ushort8, vec_uchar16, vec_mulo, __builtin_vec_mulo)
VSX_REDIRECT_2RG(vec_short8, vec_char16, vec_mulo, __builtin_vec_mulo)
VSX_REDIRECT_2RG(vec_int4, vec_short8, vec_mulo, __builtin_vec_mulo)
VSX_REDIRECT_2RG(vec_uint4, vec_ushort8, vec_mulo, __builtin_vec_mulo)
// dword2 support arrived in ISA 2.07 and GCC 8+
VSX_IMPL_2VRG(vec_dword2, vec_int4, vmulosw, vec_mule)
VSX_IMPL_2VRG(vec_udword2, vec_uint4, vmulouw, vec_mule)
VSX_IMPL_2VRG(vec_dword2, vec_int4, vmulesw, vec_mulo)
VSX_IMPL_2VRG(vec_udword2, vec_uint4, vmuleuw, vec_mulo)
#endif
#if __GNUG__ < 7
// up to GCC 6 vec_mul only supports precisions and llong
# ifdef vec_mul
+1 -1
View File
@@ -9,7 +9,7 @@ typedef TestBaseWithParam<MatType_Length_t> MatType_Length;
PERF_TEST_P( MatType_Length, dot,
testing::Combine(
testing::Values( CV_8UC1, CV_32SC1, CV_32FC1 ),
testing::Values( CV_8UC1, CV_8SC1, CV_16SC1, CV_16UC1, CV_32SC1, CV_32FC1 ),
testing::Values( 32, 64, 128, 256, 512, 1024 )
))
{
+56 -15
View File
@@ -46,6 +46,7 @@
#undef CV_LOG_STRIP_LEVEL
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/core/utils/configuration.private.hpp>
#define CV__ALLOCATOR_STATS_LOG(...) CV_LOG_VERBOSE(NULL, 0, "alloc.cpp: " << __VA_ARGS__)
#include "opencv2/core/utils/allocator_stats.impl.hpp"
@@ -81,6 +82,38 @@ cv::utils::AllocatorStatisticsInterface& getAllocatorStatistics()
return allocator_stats;
}
#if defined HAVE_POSIX_MEMALIGN || defined HAVE_MEMALIGN
static bool readMemoryAlignmentParameter()
{
bool value = true;
#if defined(__GLIBC__) && defined(__linux__) \
&& !defined(CV_STATIC_ANALYSIS) \
&& !defined(OPENCV_ENABLE_MEMORY_SANITIZER) \
&& !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) /* oss-fuzz */ \
&& !defined(_WIN32) /* MinGW? */
{
// https://github.com/opencv/opencv/issues/15526
value = false;
}
#endif
value = cv::utils::getConfigurationParameterBool("OPENCV_ENABLE_MEMALIGN", value); // should not call fastMalloc() internally
// TODO add checks for valgrind, ASAN if value == false
return value;
}
static inline
bool isAlignedAllocationEnabled()
{
static bool initialized = false;
static bool useMemalign = true;
if (!initialized)
{
initialized = true; // trick to avoid stuck in acquire (works only if allocations are scope based)
useMemalign = readMemoryAlignmentParameter();
}
return useMemalign;
}
#endif
#ifdef OPENCV_ALLOC_ENABLE_STATISTICS
static inline
void* fastMalloc_(size_t size)
@@ -89,25 +122,30 @@ void* fastMalloc(size_t size)
#endif
{
#ifdef HAVE_POSIX_MEMALIGN
void* ptr = NULL;
if(posix_memalign(&ptr, CV_MALLOC_ALIGN, size))
ptr = NULL;
if(!ptr)
return OutOfMemoryError(size);
return ptr;
if (isAlignedAllocationEnabled())
{
void* ptr = NULL;
if(posix_memalign(&ptr, CV_MALLOC_ALIGN, size))
ptr = NULL;
if(!ptr)
return OutOfMemoryError(size);
return ptr;
}
#elif defined HAVE_MEMALIGN
void* ptr = memalign(CV_MALLOC_ALIGN, size);
if(!ptr)
return OutOfMemoryError(size);
return ptr;
#else
if (isAlignedAllocationEnabled())
{
void* ptr = memalign(CV_MALLOC_ALIGN, size);
if(!ptr)
return OutOfMemoryError(size);
return ptr;
}
#endif
uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN);
if(!udata)
return OutOfMemoryError(size);
uchar** adata = alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN);
adata[-1] = udata;
return adata;
#endif
}
#ifdef OPENCV_ALLOC_ENABLE_STATISTICS
@@ -118,8 +156,12 @@ void fastFree(void* ptr)
#endif
{
#if defined HAVE_POSIX_MEMALIGN || defined HAVE_MEMALIGN
free(ptr);
#else
if (isAlignedAllocationEnabled())
{
free(ptr);
return;
}
#endif
if(ptr)
{
uchar* udata = ((uchar**)ptr)[-1];
@@ -127,7 +169,6 @@ void fastFree(void* ptr)
((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*)+CV_MALLOC_ALIGN));
free(udata);
}
#endif
}
#ifdef OPENCV_ALLOC_ENABLE_STATISTICS
+2 -2
View File
@@ -409,13 +409,13 @@ static void bin_loop(const T1* src1, size_t step1, const T1* src2, size_t step2,
int x = 0;
#if CV_SIMD
#if !CV_NEON
#if !CV_NEON && !CV_MSA
if (is_aligned(src1, src2, dst))
{
for (; x <= width - wide_step_l; x += wide_step_l)
{
ldr::la(src1 + x, src2 + x, dst + x);
#if !CV_NEON && CV_SIMD_WIDTH == 16
#if CV_SIMD_WIDTH == 16
ldr::la(src1 + x + wide_step, src2 + x + wide_step, dst + x + wide_step);
#endif
}
-26
View File
@@ -782,36 +782,10 @@ void flip( InputArray _src, OutputArray _dst, int flip_mode )
flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
}
#ifdef HAVE_OPENCL
static bool ocl_rotate(InputArray _src, OutputArray _dst, int rotateMode)
{
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;
}
return true;
}
#endif
void rotate(InputArray _src, OutputArray _dst, int rotateMode)
{
CV_Assert(_src.dims() <= 2);
CV_OCL_RUN(_dst.isUMat(), ocl_rotate(_src, _dst, rotateMode))
switch (rotateMode)
{
case ROTATE_90_CLOCKWISE:
+5 -5
View File
@@ -31,6 +31,11 @@ using namespace cv;
namespace {
static const float atan2_p1 = 0.9997878412794807f*(float)(180/CV_PI);
static const float atan2_p3 = -0.3258083974640975f*(float)(180/CV_PI);
static const float atan2_p5 = 0.1555786518463281f*(float)(180/CV_PI);
static const float atan2_p7 = -0.04432655554792128f*(float)(180/CV_PI);
#ifdef __EMSCRIPTEN__
static inline float atan_f32(float y, float x)
{
@@ -42,11 +47,6 @@ static inline float atan_f32(float y, float x)
return a; // range [0; 360)
}
#else
static const float atan2_p1 = 0.9997878412794807f*(float)(180/CV_PI);
static const float atan2_p3 = -0.3258083974640975f*(float)(180/CV_PI);
static const float atan2_p5 = 0.1555786518463281f*(float)(180/CV_PI);
static const float atan2_p7 = -0.04432655554792128f*(float)(180/CV_PI);
static inline float atan_f32(float y, float x)
{
float ax = std::abs(x), ay = std::abs(y);
+6
View File
@@ -442,6 +442,12 @@ void transform(InputArray _src, OutputArray _dst, InputArray _mtx)
_dst.create( src.size(), CV_MAKETYPE(depth, dcn) );
Mat dst = _dst.getMat();
if (src.data == dst.data) // inplace case
{
CV_Assert(scn == dcn);
src = src.clone(); // TODO Add performance warning
}
int mtype = depth == CV_32S || depth == CV_64F ? CV_64F : CV_32F;
AutoBuffer<double> _mbuf;
double* mbuf;
+92 -129
View File
@@ -2320,26 +2320,22 @@ double dotProd_8u(const uchar* src1, const uchar* src2, int len)
while (i < len0)
{
blockSize = std::min(len0 - i, blockSize0);
v_int32 v_sum = vx_setzero_s32();
v_uint32 v_sum = vx_setzero_u32();
const int cWidth = v_uint16::nlanes;
int j = 0;
for (; j <= blockSize - cWidth * 2; j += cWidth * 2)
{
v_uint16 v_src10, v_src20, v_src11, v_src21;
v_expand(vx_load(src1 + j), v_src10, v_src11);
v_expand(vx_load(src2 + j), v_src20, v_src21);
v_sum += v_dotprod(v_reinterpret_as_s16(v_src10), v_reinterpret_as_s16(v_src20));
v_sum += v_dotprod(v_reinterpret_as_s16(v_src11), v_reinterpret_as_s16(v_src21));
v_uint8 v_src1 = vx_load(src1 + j);
v_uint8 v_src2 = vx_load(src2 + j);
v_sum = v_dotprod_expand_fast(v_src1, v_src2, v_sum);
}
for (; j <= blockSize - cWidth; j += cWidth)
{
v_int16 v_src10 = v_reinterpret_as_s16(vx_load_expand(src1 + j));
v_int16 v_src20 = v_reinterpret_as_s16(vx_load_expand(src2 + j));
v_sum += v_dotprod(v_src10, v_src20);
v_sum += v_reinterpret_as_u32(v_dotprod_fast(v_src10, v_src20));
}
r += (double)v_reduce_sum(v_sum);
@@ -2348,48 +2344,6 @@ double dotProd_8u(const uchar* src1, const uchar* src2, int len)
i += blockSize;
}
vx_cleanup();
#elif CV_NEON
if( cv::checkHardwareSupport(CV_CPU_NEON) )
{
int len0 = len & -8, blockSize0 = (1 << 15), blockSize;
uint32x4_t v_zero = vdupq_n_u32(0u);
CV_DECL_ALIGNED(16) uint buf[4];
while( i < len0 )
{
blockSize = std::min(len0 - i, blockSize0);
uint32x4_t v_sum = v_zero;
int j = 0;
for( ; j <= blockSize - 16; j += 16 )
{
uint8x16_t v_src1 = vld1q_u8(src1 + j), v_src2 = vld1q_u8(src2 + j);
uint16x8_t v_src10 = vmovl_u8(vget_low_u8(v_src1)), v_src20 = vmovl_u8(vget_low_u8(v_src2));
v_sum = vmlal_u16(v_sum, vget_low_u16(v_src10), vget_low_u16(v_src20));
v_sum = vmlal_u16(v_sum, vget_high_u16(v_src10), vget_high_u16(v_src20));
v_src10 = vmovl_u8(vget_high_u8(v_src1));
v_src20 = vmovl_u8(vget_high_u8(v_src2));
v_sum = vmlal_u16(v_sum, vget_low_u16(v_src10), vget_low_u16(v_src20));
v_sum = vmlal_u16(v_sum, vget_high_u16(v_src10), vget_high_u16(v_src20));
}
for( ; j <= blockSize - 8; j += 8 )
{
uint16x8_t v_src1 = vmovl_u8(vld1_u8(src1 + j)), v_src2 = vmovl_u8(vld1_u8(src2 + j));
v_sum = vmlal_u16(v_sum, vget_low_u16(v_src1), vget_low_u16(v_src2));
v_sum = vmlal_u16(v_sum, vget_high_u16(v_src1), vget_high_u16(v_src2));
}
vst1q_u32(buf, v_sum);
r += buf[0] + buf[1] + buf[2] + buf[3];
src1 += blockSize;
src2 += blockSize;
i += blockSize;
}
}
#endif
return r + dotProd_(src1, src2, len - i);
}
@@ -2412,20 +2366,16 @@ double dotProd_8s(const schar* src1, const schar* src2, int len)
int j = 0;
for (; j <= blockSize - cWidth * 2; j += cWidth * 2)
{
v_int16 v_src10, v_src20, v_src11, v_src21;
v_expand(vx_load(src1 + j), v_src10, v_src11);
v_expand(vx_load(src2 + j), v_src20, v_src21);
v_sum += v_dotprod(v_src10, v_src20);
v_sum += v_dotprod(v_src11, v_src21);
v_int8 v_src1 = vx_load(src1 + j);
v_int8 v_src2 = vx_load(src2 + j);
v_sum = v_dotprod_expand_fast(v_src1, v_src2, v_sum);
}
for (; j <= blockSize - cWidth; j += cWidth)
{
v_int16 v_src10 = vx_load_expand(src1 + j);
v_int16 v_src20 = vx_load_expand(src2 + j);
v_sum += v_dotprod(v_src10, v_src20);
v_int16 v_src1 = vx_load_expand(src1 + j);
v_int16 v_src2 = vx_load_expand(src2 + j);
v_sum = v_dotprod_fast(v_src1, v_src2, v_sum);
}
r += (double)v_reduce_sum(v_sum);
@@ -2434,48 +2384,6 @@ double dotProd_8s(const schar* src1, const schar* src2, int len)
i += blockSize;
}
vx_cleanup();
#elif CV_NEON
if( cv::checkHardwareSupport(CV_CPU_NEON) )
{
int len0 = len & -8, blockSize0 = (1 << 14), blockSize;
int32x4_t v_zero = vdupq_n_s32(0);
CV_DECL_ALIGNED(16) int buf[4];
while( i < len0 )
{
blockSize = std::min(len0 - i, blockSize0);
int32x4_t v_sum = v_zero;
int j = 0;
for( ; j <= blockSize - 16; j += 16 )
{
int8x16_t v_src1 = vld1q_s8(src1 + j), v_src2 = vld1q_s8(src2 + j);
int16x8_t v_src10 = vmovl_s8(vget_low_s8(v_src1)), v_src20 = vmovl_s8(vget_low_s8(v_src2));
v_sum = vmlal_s16(v_sum, vget_low_s16(v_src10), vget_low_s16(v_src20));
v_sum = vmlal_s16(v_sum, vget_high_s16(v_src10), vget_high_s16(v_src20));
v_src10 = vmovl_s8(vget_high_s8(v_src1));
v_src20 = vmovl_s8(vget_high_s8(v_src2));
v_sum = vmlal_s16(v_sum, vget_low_s16(v_src10), vget_low_s16(v_src20));
v_sum = vmlal_s16(v_sum, vget_high_s16(v_src10), vget_high_s16(v_src20));
}
for( ; j <= blockSize - 8; j += 8 )
{
int16x8_t v_src1 = vmovl_s8(vld1_s8(src1 + j)), v_src2 = vmovl_s8(vld1_s8(src2 + j));
v_sum = vmlal_s16(v_sum, vget_low_s16(v_src1), vget_low_s16(v_src2));
v_sum = vmlal_s16(v_sum, vget_high_s16(v_src1), vget_high_s16(v_src2));
}
vst1q_s32(buf, v_sum);
r += buf[0] + buf[1] + buf[2] + buf[3];
src1 += blockSize;
src2 += blockSize;
i += blockSize;
}
}
#endif
return r + dotProd_(src1, src2, len - i);
@@ -2483,42 +2391,97 @@ double dotProd_8s(const schar* src1, const schar* src2, int len)
double dotProd_16u(const ushort* src1, const ushort* src2, int len)
{
return dotProd_(src1, src2, len);
double r = 0.0;
int i = 0;
#if CV_SIMD
int len0 = len & -v_uint16::nlanes, blockSize0 = (1 << 24), blockSize;
while (i < len0)
{
blockSize = std::min(len0 - i, blockSize0);
v_uint64 v_sum = vx_setzero_u64();
const int cWidth = v_uint16::nlanes;
int j = 0;
for (; j <= blockSize - cWidth; j += cWidth)
{
v_uint16 v_src1 = vx_load(src1 + j);
v_uint16 v_src2 = vx_load(src2 + j);
v_sum = v_dotprod_expand_fast(v_src1, v_src2, v_sum);
}
r += (double)v_reduce_sum(v_sum);
src1 += blockSize;
src2 += blockSize;
i += blockSize;
}
vx_cleanup();
#endif
return r + dotProd_(src1, src2, len - i);
}
double dotProd_16s(const short* src1, const short* src2, int len)
{
return dotProd_(src1, src2, len);
double r = 0.0;
int i = 0;
#if CV_SIMD
int len0 = len & -v_int16::nlanes, blockSize0 = (1 << 24), blockSize;
while (i < len0)
{
blockSize = std::min(len0 - i, blockSize0);
v_int64 v_sum = vx_setzero_s64();
const int cWidth = v_int16::nlanes;
int j = 0;
for (; j <= blockSize - cWidth; j += cWidth)
{
v_int16 v_src1 = vx_load(src1 + j);
v_int16 v_src2 = vx_load(src2 + j);
v_sum = v_dotprod_expand_fast(v_src1, v_src2, v_sum);
}
r += (double)v_reduce_sum(v_sum);
src1 += blockSize;
src2 += blockSize;
i += blockSize;
}
vx_cleanup();
#endif
return r + dotProd_(src1, src2, len - i);
}
double dotProd_32s(const int* src1, const int* src2, int len)
{
#if CV_SIMD128_64F
double r = 0.0;
#if CV_SIMD_64F
double r = .0;
int i = 0;
int lenAligned = len & -v_int32x4::nlanes;
v_float64x2 a(0.0, 0.0);
v_float64x2 b(0.0, 0.0);
for( i = 0; i < lenAligned; i += v_int32x4::nlanes )
{
v_int32x4 s1 = v_load(src1);
v_int32x4 s2 = v_load(src2);
#if CV_VSX
// Do 32x32->64 multiplies, convert/round to double, accumulate
// Potentially less precise than FMA, but 1.5x faster than fma below.
a += v_cvt_f64(v_int64(vec_mule(s1.val, s2.val)));
b += v_cvt_f64(v_int64(vec_mulo(s1.val, s2.val)));
#else
a = v_fma(v_cvt_f64(s1), v_cvt_f64(s2), a);
b = v_fma(v_cvt_f64_high(s1), v_cvt_f64_high(s2), b);
const int step = v_int32::nlanes;
v_float64 v_sum0 = vx_setzero_f64();
#if CV_SIMD_WIDTH == 16
const int wstep = step * 2;
v_float64 v_sum1 = vx_setzero_f64();
for (; i < len - wstep; i += wstep, src1 += wstep, src2 += wstep)
{
v_int32 v_src10 = vx_load(src1);
v_int32 v_src20 = vx_load(src2);
v_int32 v_src11 = vx_load(src1 + step);
v_int32 v_src21 = vx_load(src2 + step);
v_sum0 = v_dotprod_expand_fast(v_src10, v_src20, v_sum0);
v_sum1 = v_dotprod_expand_fast(v_src11, v_src21, v_sum1);
}
v_sum0 += v_sum1;
#endif
src1 += v_int32x4::nlanes;
src2 += v_int32x4::nlanes;
}
a += b;
r = v_reduce_sum(a);
for (; i < len - step; i += step, src1 += step, src2 += step)
{
v_int32 v_src1 = vx_load(src1);
v_int32 v_src2 = vx_load(src2);
v_sum0 = v_dotprod_expand_fast(v_src1, v_src2, v_sum0);
}
r = v_reduce_sum(v_sum0);
vx_cleanup();
return r + dotProd_(src1, src2, len - i);
#else
return dotProd_(src1, src2, len);
+14 -3
View File
@@ -267,6 +267,9 @@ static const String getBuildExtraOptions()
return param_buildExtraOptions;
}
static const bool CV_OPENCL_ENABLE_MEM_USE_HOST_PTR = utils::getConfigurationParameterBool("OPENCV_OPENCL_ENABLE_MEM_USE_HOST_PTR", true);
static const size_t CV_OPENCL_ALIGNMENT_MEM_USE_HOST_PTR = utils::getConfigurationParameterSizeT("OPENCV_OPENCL_ALIGNMENT_MEM_USE_HOST_PTR", 4);
#endif // HAVE_OPENCL
struct UMat2D
@@ -4675,6 +4678,9 @@ public:
bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const CV_OVERRIDE
{
#ifndef HAVE_OPENCL
return false;
#else
if(!u)
return false;
@@ -4749,8 +4755,12 @@ public:
#endif
{
tempUMatFlags = UMatData::TEMP_UMAT;
if (u->origdata == cv::alignPtr(u->origdata, 4) // There are OpenCL runtime issues for less aligned data
&& !(u->originalUMatData && u->originalUMatData->handle) // Avoid sharing of host memory between OpenCL buffers
if (CV_OPENCL_ENABLE_MEM_USE_HOST_PTR
// There are OpenCL runtime issues for less aligned data
&& (CV_OPENCL_ALIGNMENT_MEM_USE_HOST_PTR != 0
&& u->origdata == cv::alignPtr(u->origdata, (int)CV_OPENCL_ALIGNMENT_MEM_USE_HOST_PTR))
// Avoid sharing of host memory between OpenCL buffers
&& !(u->originalUMatData && u->originalUMatData->handle)
)
{
handle = clCreateBuffer(ctx_handle, CL_MEM_USE_HOST_PTR|createFlags,
@@ -4780,6 +4790,7 @@ public:
u->markHostCopyObsolete(true);
opencl_allocator_stats.onAllocate(u->size);
return true;
#endif // HAVE_OPENCL
}
/*void sync(UMatData* u) const
@@ -4908,7 +4919,7 @@ public:
(CL_MAP_READ | CL_MAP_WRITE),
0, u->size, 0, 0, 0, &retval);
CV_OCL_CHECK_RESULT(retval, cv::format("clEnqueueMapBuffer(handle=%p, sz=%lld) => %p", (void*)u->handle, (long long int)u->size, data).c_str());
CV_Assert(u->origdata == data);
CV_Assert(u->origdata == data && "Details: https://github.com/opencv/opencv/issues/6293");
if (u->originalUMatData)
{
CV_Assert(u->originalUMatData->data == data);
+7
View File
@@ -45,6 +45,13 @@
#ifdef HAVE_OPENGL
# include "gl_core_3_1.hpp"
# ifdef HAVE_CUDA
# if (defined(__arm__) || defined(__aarch64__)) \
&& !defined(OPENCV_SKIP_CUDA_OPENGL_ARM_WORKAROUND)
# include <GL/gl.h>
# ifndef GL_VERSION
# define GL_VERSION 0x1F02
# endif
# endif
# include <cuda_gl_interop.h>
# endif
#else // HAVE_OPENGL
+2 -2
View File
@@ -54,7 +54,7 @@
#endif
#if defined __linux__ || defined __APPLE__ || defined __GLIBC__ \
|| defined __HAIKU__
|| defined __HAIKU__ || defined __EMSCRIPTEN__
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
@@ -793,7 +793,7 @@ int cv::getNumberOfCPUs(void)
#elif defined __ANDROID__
static int ncpus = getNumberOfCPUsImpl();
return ncpus;
#elif defined __linux__ || defined __GLIBC__ || defined __HAIKU__
#elif defined __linux__ || defined __GLIBC__ || defined __HAIKU__ || defined __EMSCRIPTEN__
return (int)sysconf( _SC_NPROCESSORS_ONLN );
#elif defined __APPLE__
int numCPU=0;
+2
View File
@@ -59,6 +59,8 @@ DECLARE_CV_PAUSE
# define CV_PAUSE(v) do { for (int __delay = (v); __delay > 0; --__delay) { asm volatile("yield" ::: "memory"); } } while (0)
# elif defined __GNUC__ && defined __arm__
# define CV_PAUSE(v) do { for (int __delay = (v); __delay > 0; --__delay) { asm volatile("" ::: "memory"); } } while (0)
# elif defined __GNUC__ && defined __mips__ && __mips_isa_rev >= 2
# define CV_PAUSE(v) do { for (int __delay = (v); __delay > 0; --__delay) { asm volatile("pause" ::: "memory"); } } while (0)
# elif defined __GNUC__ && defined __PPC64__
# define CV_PAUSE(v) do { for (int __delay = (v); __delay > 0; --__delay) { asm volatile("or 27,27,27" ::: "memory"); } } while (0)
# else
+9 -5
View File
@@ -2065,13 +2065,17 @@ static int_fast64_t f64_to_i64(float64_t a, uint_fast8_t roundingMode, bool exac
if (exp) sig |= UINT64_C(0x0010000000000000);
shiftDist = 0x433 - exp;
if (shiftDist <= 0) {
uint_fast64_t z = sig << -shiftDist;
if ((shiftDist < -11) || (z & UINT64_C(0x8000000000000000)))
bool isValid = shiftDist >= -11;
if (isValid)
{
raiseFlags(flag_invalid);
return sign ? i64_fromNegOverflow : i64_fromPosOverflow;
uint_fast64_t z = sig << -shiftDist;
if (0 == (z & UINT64_C(0x8000000000000000)))
{
return sign ? -(int_fast64_t)z : (int_fast64_t)z;
}
}
return sign ? -(int_fast64_t)z : (int_fast64_t)z;
raiseFlags(flag_invalid);
return sign ? i64_fromNegOverflow : i64_fromPosOverflow;
}
else {
if (shiftDist < 64)
+24 -8
View File
@@ -368,11 +368,14 @@ struct HWFeatures
g_hwFeatureNames[CPU_VSX] = "VSX";
g_hwFeatureNames[CPU_VSX3] = "VSX3";
g_hwFeatureNames[CPU_MSA] = "CPU_MSA";
g_hwFeatureNames[CPU_AVX512_COMMON] = "AVX512-COMMON";
g_hwFeatureNames[CPU_AVX512_SKX] = "AVX512-SKX";
g_hwFeatureNames[CPU_AVX512_KNL] = "AVX512-KNL";
g_hwFeatureNames[CPU_AVX512_KNM] = "AVX512-KNM";
g_hwFeatureNames[CPU_AVX512_CNL] = "AVX512-CNL";
g_hwFeatureNames[CPU_AVX512_CEL] = "AVX512-CEL";
g_hwFeatureNames[CPU_AVX512_CLX] = "AVX512-CLX";
g_hwFeatureNames[CPU_AVX512_ICL] = "AVX512-ICL";
}
@@ -483,9 +486,11 @@ struct HWFeatures
have[CV_CPU_AVX_5124VNNIW] && have[CV_CPU_AVX_512VPOPCNTDQ];
have[CV_CPU_AVX512_SKX] = have[CV_CPU_AVX_512BW] && have[CV_CPU_AVX_512DQ] && have[CV_CPU_AVX_512VL];
have[CV_CPU_AVX512_CNL] = have[CV_CPU_AVX512_SKX] && have[CV_CPU_AVX_512IFMA] && have[CV_CPU_AVX_512VBMI];
have[CV_CPU_AVX512_CEL] = have[CV_CPU_AVX512_CNL] && have[CV_CPU_AVX_512VNNI];
have[CV_CPU_AVX512_ICL] = have[CV_CPU_AVX512_CEL] && have[CV_CPU_AVX_512VBMI2] &&
have[CV_CPU_AVX_512BITALG] && have[CV_CPU_AVX_512VPOPCNTDQ];
have[CV_CPU_AVX512_CLX] = have[CV_CPU_AVX512_SKX] && have[CV_CPU_AVX_512VNNI];
have[CV_CPU_AVX512_ICL] = have[CV_CPU_AVX512_SKX] &&
have[CV_CPU_AVX_512IFMA] && have[CV_CPU_AVX_512VBMI] &&
have[CV_CPU_AVX_512VNNI] &&
have[CV_CPU_AVX_512VBMI2] && have[CV_CPU_AVX_512BITALG] && have[CV_CPU_AVX_512VPOPCNTDQ];
}
else
{
@@ -493,7 +498,7 @@ struct HWFeatures
have[CV_CPU_AVX512_KNM] = false;
have[CV_CPU_AVX512_SKX] = false;
have[CV_CPU_AVX512_CNL] = false;
have[CV_CPU_AVX512_CEL] = false;
have[CV_CPU_AVX512_CLX] = false;
have[CV_CPU_AVX512_ICL] = false;
}
}
@@ -557,6 +562,9 @@ struct HWFeatures
#if defined _ARM_ && (defined(_WIN32_WCE) && _WIN32_WCE >= 0x800)
have[CV_CPU_NEON] = true;
#endif
#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
@@ -567,8 +575,16 @@ struct HWFeatures
have[CV_CPU_VSX3] = (CV_VSX3);
#endif
bool skip_baseline_check = false;
#ifndef NO_GETENV
if (getenv("OPENCV_SKIP_CPU_BASELINE_CHECK"))
{
skip_baseline_check = true;
}
#endif
int baseline_features[] = { CV_CPU_BASELINE_FEATURES };
if (!checkFeatures(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0])))
if (!checkFeatures(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0]))
&& !skip_baseline_check)
{
fprintf(stderr, "\n"
"******************************************************************\n"
@@ -595,12 +611,12 @@ struct HWFeatures
{
if (have[feature])
{
if (dump) fprintf(stderr, "%s - OK\n", getHWFeatureNameSafe(feature));
if (dump) fprintf(stderr, " ID=%3d (%s) - OK\n", feature, getHWFeatureNameSafe(feature));
}
else
{
result = false;
if (dump) fprintf(stderr, "%s - NOT AVAILABLE\n", getHWFeatureNameSafe(feature));
if (dump) fprintf(stderr, " ID=%3d (%s) - NOT AVAILABLE\n", feature, getHWFeatureNameSafe(feature));
}
}
}
+120 -5
View File
@@ -603,12 +603,14 @@ template<typename R> struct TheTest
return *this;
}
TheTest & test_dot_prod()
TheTest & test_dotprod()
{
typedef typename V_RegTraits<R>::w_reg Rx2;
typedef typename Rx2::lane_type w_type;
Data<R> dataA, dataB(2);
Data<R> dataA, dataB;
dataA += std::numeric_limits<LaneType>::max() - R::nlanes;
dataB += std::numeric_limits<LaneType>::min() + R::nlanes;
R a = dataA, b = dataB;
Data<Rx2> dataC;
@@ -621,12 +623,95 @@ template<typename R> struct TheTest
resE = v_dotprod(a, b, c);
const int n = R::nlanes / 2;
w_type sumAB = 0, sumABC = 0, tmp_sum;
for (int i = 0; i < n; ++i)
{
SCOPED_TRACE(cv::format("i=%d", i));
EXPECT_EQ(dataA[i*2] * dataB[i*2] + dataA[i*2 + 1] * dataB[i*2 + 1], resD[i]);
EXPECT_EQ(dataA[i*2] * dataB[i*2] + dataA[i*2 + 1] * dataB[i*2 + 1] + dataC[i], resE[i]);
tmp_sum = (w_type)dataA[i*2] * (w_type)dataB[i*2] +
(w_type)dataA[i*2 + 1] * (w_type)dataB[i*2 + 1];
sumAB += tmp_sum;
EXPECT_EQ(tmp_sum, resD[i]);
tmp_sum = tmp_sum + dataC[i];
sumABC += tmp_sum;
EXPECT_EQ(tmp_sum, resE[i]);
}
w_type resF = v_reduce_sum(v_dotprod_fast(a, b)),
resG = v_reduce_sum(v_dotprod_fast(a, b, c));
EXPECT_EQ(sumAB, resF);
EXPECT_EQ(sumABC, resG);
return *this;
}
TheTest & test_dotprod_expand()
{
typedef typename V_RegTraits<R>::q_reg Rx4;
typedef typename Rx4::lane_type l4_type;
Data<R> dataA, dataB;
dataA += std::numeric_limits<LaneType>::max() - R::nlanes;
dataB += std::numeric_limits<LaneType>::min() + R::nlanes;
R a = dataA, b = dataB;
Data<Rx4> dataC;
Rx4 c = dataC;
Data<Rx4> resD = v_dotprod_expand(a, b),
resE = v_dotprod_expand(a, b, c);
l4_type sumAB = 0, sumABC = 0, tmp_sum;
for (int i = 0; i < Rx4::nlanes; ++i)
{
SCOPED_TRACE(cv::format("i=%d", i));
tmp_sum = (l4_type)dataA[i*4] * (l4_type)dataB[i*4] +
(l4_type)dataA[i*4 + 1] * (l4_type)dataB[i*4 + 1] +
(l4_type)dataA[i*4 + 2] * (l4_type)dataB[i*4 + 2] +
(l4_type)dataA[i*4 + 3] * (l4_type)dataB[i*4 + 3];
sumAB += tmp_sum;
EXPECT_EQ(tmp_sum, resD[i]);
tmp_sum = tmp_sum + dataC[i];
sumABC += tmp_sum;
EXPECT_EQ(tmp_sum, resE[i]);
}
l4_type resF = v_reduce_sum(v_dotprod_expand_fast(a, b)),
resG = v_reduce_sum(v_dotprod_expand_fast(a, b, c));
EXPECT_EQ(sumAB, resF);
EXPECT_EQ(sumABC, resG);
return *this;
}
TheTest & test_dotprod_expand_f64()
{
#if CV_SIMD_64F
Data<R> dataA, dataB;
dataA += std::numeric_limits<LaneType>::max() - R::nlanes;
dataB += std::numeric_limits<LaneType>::min();
R a = dataA, b = dataB;
Data<v_float64> dataC;
v_float64 c = dataC;
Data<v_float64> resA = v_dotprod_expand(a, a),
resB = v_dotprod_expand(b, b),
resC = v_dotprod_expand(a, b, c);
const int n = R::nlanes / 2;
for (int i = 0; i < n; ++i)
{
SCOPED_TRACE(cv::format("i=%d", i));
EXPECT_EQ((double)dataA[i*2] * (double)dataA[i*2] +
(double)dataA[i*2 + 1] * (double)dataA[i*2 + 1], resA[i]);
EXPECT_EQ((double)dataB[i*2] * (double)dataB[i*2] +
(double)dataB[i*2 + 1] * (double)dataB[i*2 + 1], resB[i]);
EXPECT_EQ((double)dataA[i*2] * (double)dataB[i*2] +
(double)dataA[i*2 + 1] * (double)dataB[i*2 + 1] + dataC[i], resC[i]);
}
#endif
return *this;
}
@@ -1165,6 +1250,29 @@ template<typename R> struct TheTest
return *this;
}
TheTest & test_cvt64_double()
{
#if CV_SIMD_64F
Data<R> dataA(std::numeric_limits<LaneType>::max()),
dataB(std::numeric_limits<LaneType>::min());
dataB += R::nlanes;
R a = dataA, b = dataB;
v_float64 c = v_cvt_f64(a), d = v_cvt_f64(b);
Data<v_float64> resC = c;
Data<v_float64> resD = d;
for (int i = 0; i < R::nlanes; ++i)
{
SCOPED_TRACE(cv::format("i=%d", i));
EXPECT_EQ((double)dataA[i], resC[i]);
EXPECT_EQ((double)dataB[i], resD[i]);
}
#endif
return *this;
}
TheTest & test_matmul()
{
Data<R> dataV, dataA, dataB, dataC, dataD;
@@ -1341,6 +1449,7 @@ void test_hal_intrin_uint8()
.test_mul_expand()
.test_cmp()
.test_logic()
.test_dotprod_expand()
.test_min_max()
.test_absdiff()
.test_reduce_sad()
@@ -1378,6 +1487,7 @@ void test_hal_intrin_int8()
.test_mul_expand()
.test_cmp()
.test_logic()
.test_dotprod_expand()
.test_min_max()
.test_absdiff()
.test_absdiffs()
@@ -1408,6 +1518,7 @@ void test_hal_intrin_uint16()
.test_cmp()
.test_shift<1>()
.test_shift<8>()
.test_dotprod_expand()
.test_logic()
.test_min_max()
.test_absdiff()
@@ -1437,7 +1548,8 @@ void test_hal_intrin_int16()
.test_cmp()
.test_shift<1>()
.test_shift<8>()
.test_dot_prod()
.test_dotprod()
.test_dotprod_expand()
.test_logic()
.test_min_max()
.test_absdiff()
@@ -1497,6 +1609,8 @@ void test_hal_intrin_int32()
.test_cmp()
.test_popcount()
.test_shift<1>().test_shift<8>()
.test_dotprod()
.test_dotprod_expand_f64()
.test_logic()
.test_min_max()
.test_absdiff()
@@ -1538,6 +1652,7 @@ void test_hal_intrin_int64()
.test_logic()
.test_extract<0>().test_extract<1>()
.test_rotate<0>().test_rotate<1>()
.test_cvt64_double()
;
}
+12 -12
View File
@@ -795,10 +795,10 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo
EXPECT_EQ(_em_in.depth(), _em_out.depth());
EXPECT_TRUE(_em_in.empty());
EXPECT_EQ(_2d_in.rows , _2d_out.rows);
EXPECT_EQ(_2d_in.cols , _2d_out.cols);
EXPECT_EQ(_2d_in.dims , _2d_out.dims);
EXPECT_EQ(_2d_in.depth(), _2d_out.depth());
ASSERT_EQ(_2d_in.rows , _2d_out.rows);
ASSERT_EQ(_2d_in.cols , _2d_out.cols);
ASSERT_EQ(_2d_in.dims , _2d_out.dims);
ASSERT_EQ(_2d_in.depth(), _2d_out.depth());
errors = 0;
for(int i = 0; i < _2d_out.rows; ++i)
@@ -819,16 +819,16 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo
}
}
EXPECT_EQ(_nd_in.rows , _nd_out.rows);
EXPECT_EQ(_nd_in.cols , _nd_out.cols);
EXPECT_EQ(_nd_in.dims , _nd_out.dims);
EXPECT_EQ(_nd_in.depth(), _nd_out.depth());
ASSERT_EQ(_nd_in.rows , _nd_out.rows);
ASSERT_EQ(_nd_in.cols , _nd_out.cols);
ASSERT_EQ(_nd_in.dims , _nd_out.dims);
ASSERT_EQ(_nd_in.depth(), _nd_out.depth());
EXPECT_EQ(0, cv::norm(_nd_in, _nd_out, NORM_INF));
EXPECT_EQ(_rd_in.rows , _rd_out.rows);
EXPECT_EQ(_rd_in.cols , _rd_out.cols);
EXPECT_EQ(_rd_in.dims , _rd_out.dims);
EXPECT_EQ(_rd_in.depth(), _rd_out.depth());
ASSERT_EQ(_rd_in.rows , _rd_out.rows);
ASSERT_EQ(_rd_in.cols , _rd_out.cols);
ASSERT_EQ(_rd_in.dims , _rd_out.dims);
ASSERT_EQ(_rd_in.depth(), _rd_out.depth());
EXPECT_EQ(0, cv::norm(_rd_in, _rd_out, NORM_INF));
}
}
@@ -955,7 +955,7 @@ NCVStatus NCVBroxOpticalFlow(const NCVBroxOpticalFlowDescriptor desc,
//compute derivatives
dim3 dBlocks(iDivUp(kLevelWidth, 32), iDivUp(kLevelHeight, 6));
dim3 dThreads(32, 6);
//dim3 dThreads(32, 6);
const int kPitchTex = kLevelStride * sizeof(float);
@@ -1121,7 +1121,7 @@ NCVStatus NCVBroxOpticalFlow(const NCVBroxOpticalFlowDescriptor desc,
Ncv32u ns = alignUp(nw, kStrideAlignmentFloat);
dim3 p_blocks(iDivUp(nw, 32), iDivUp(nh, 8));
dim3 p_threads(32, 8);
//dim3 p_threads(32, 8);
NcvSize32u inner_srcSize (kLevelWidth, kLevelHeight);
NcvSize32u dstSize (nw, nh);
+29 -17
View File
@@ -21,15 +21,11 @@ def box2str(box):
width, height = box[2] - left, box[3] - top
return '[%f x %f from (%f, %f)]' % (width, height, left, top)
def normAssertDetections(test, ref, out, confThreshold=0.0, scores_diff=1e-5, boxes_iou_diff=1e-4):
ref = np.array(ref, np.float32)
refClassIds, testClassIds = ref[:, 1], out[:, 1]
refScores, testScores = ref[:, 2], out[:, 2]
refBoxes, testBoxes = ref[:, 3:], out[:, 3:]
def normAssertDetections(test, refClassIds, refScores, refBoxes, testClassIds, testScores, testBoxes,
confThreshold=0.0, scores_diff=1e-5, boxes_iou_diff=1e-4):
matchedRefBoxes = [False] * len(refBoxes)
errMsg = ''
for i in range(len(refBoxes)):
for i in range(len(testBoxes)):
testScore = testScores[i]
if testScore < confThreshold:
continue
@@ -66,12 +62,21 @@ def printParams(backend, target):
}
print('%s/%s' % (backendNames[backend], targetNames[target]))
testdata_required = bool(os.environ.get('OPENCV_DNN_TEST_REQUIRE_TESTDATA', False))
g_dnnBackendsAndTargets = None
class dnn_test(NewOpenCVTests):
def setUp(self):
super(dnn_test, self).setUp()
global g_dnnBackendsAndTargets
if g_dnnBackendsAndTargets is None:
g_dnnBackendsAndTargets = self.initBackendsAndTargets()
self.dnnBackendsAndTargets = g_dnnBackendsAndTargets
def initBackendsAndTargets(self):
self.dnnBackendsAndTargets = [
[cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_CPU],
]
@@ -89,15 +94,18 @@ class dnn_test(NewOpenCVTests):
self.dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_OPENCL])
if self.checkIETarget(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_OPENCL_FP16):
self.dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_OPENCL_FP16])
return self.dnnBackendsAndTargets
def find_dnn_file(self, filename, required=True):
if not required:
required = testdata_required
return self.find_file(filename, [os.environ.get('OPENCV_DNN_TEST_DATA_PATH', os.getcwd()),
os.environ['OPENCV_TEST_DATA_PATH']],
required=required)
def checkIETarget(self, backend, target):
proto = self.find_dnn_file('dnn/layers/layer_convolution.prototxt', required=True)
model = self.find_dnn_file('dnn/layers/layer_convolution.caffemodel', required=True)
proto = self.find_dnn_file('dnn/layers/layer_convolution.prototxt')
model = self.find_dnn_file('dnn/layers/layer_convolution.caffemodel')
net = cv.dnn.readNet(proto, model)
net.setPreferableBackend(backend)
net.setPreferableTarget(target)
@@ -137,9 +145,8 @@ class dnn_test(NewOpenCVTests):
def test_face_detection(self):
testdata_required = bool(os.environ.get('OPENCV_DNN_TEST_REQUIRE_TESTDATA', False))
proto = self.find_dnn_file('dnn/opencv_face_detector.prototxt', required=testdata_required)
model = self.find_dnn_file('dnn/opencv_face_detector.caffemodel', required=testdata_required)
proto = self.find_dnn_file('dnn/opencv_face_detector.prototxt')
model = self.find_dnn_file('dnn/opencv_face_detector.caffemodel', required=False)
if proto is None or model is None:
raise unittest.SkipTest("Missing DNN test files (dnn/opencv_face_detector.{prototxt/caffemodel}). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
@@ -166,13 +173,18 @@ class dnn_test(NewOpenCVTests):
scoresDiff = 4e-3 if target in [cv.dnn.DNN_TARGET_OPENCL_FP16, cv.dnn.DNN_TARGET_MYRIAD] else 1e-5
iouDiff = 2e-2 if target in [cv.dnn.DNN_TARGET_OPENCL_FP16, cv.dnn.DNN_TARGET_MYRIAD] else 1e-4
normAssertDetections(self, ref, out, 0.5, scoresDiff, iouDiff)
ref = np.array(ref, np.float32)
refClassIds, testClassIds = ref[:, 1], out[:, 1]
refScores, testScores = ref[:, 2], out[:, 2]
refBoxes, testBoxes = ref[:, 3:], out[:, 3:]
normAssertDetections(self, refClassIds, refScores, refBoxes, testClassIds,
testScores, testBoxes, 0.5, scoresDiff, iouDiff)
def test_async(self):
timeout = 500*10**6 # in nanoseconds (500ms)
testdata_required = bool(os.environ.get('OPENCV_DNN_TEST_REQUIRE_TESTDATA', False))
proto = self.find_dnn_file('dnn/layers/layer_convolution.prototxt', required=testdata_required)
model = self.find_dnn_file('dnn/layers/layer_convolution.caffemodel', required=testdata_required)
timeout = 10*1000*10**6 # in nanoseconds (10 sec)
proto = self.find_dnn_file('dnn/layers/layer_convolution.prototxt')
model = self.find_dnn_file('dnn/layers/layer_convolution.caffemodel')
if proto is None or model is None:
raise unittest.SkipTest("Missing DNN test files (dnn/layers/layer_convolution.{prototxt/caffemodel}). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
+8 -1
View File
@@ -1556,7 +1556,8 @@ struct Net::Impl
Ptr<Layer> layer = ld.layerInstance;
if (!fused && !layer->supportBackend(preferableBackend))
{
bool customizable = ld.id != 0 && ld.outputBlobs.size() == 1;
bool customizable = ld.id != 0 && ld.outputBlobs.size() == 1 &&
INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R2);
// TODO: there is a bug in Myriad plugin with custom layers shape infer.
if (preferableTarget == DNN_TARGET_MYRIAD)
{
@@ -2451,6 +2452,12 @@ struct Net::Impl
int requiredOutputs = layers[id].requiredOutputs.size();
inOutShapes[id].supportInPlace =
layers[id].getLayerInstance()->getMemoryShapes(is, requiredOutputs, os, ints);
for (int i = 0; i < ints.size(); i++)
CV_Assert(total(ints[i]) > 0);
for (int i = 0; i < os.size(); i++)
CV_Assert(total(os[i]) > 0);
}
void getLayersShapes(const ShapesVec& netInputShapes,
+14 -7
View File
@@ -240,10 +240,14 @@ public:
MatShape computeColRowShape(const MatShape &inpShape, const MatShape &outShape) const CV_OVERRIDE
{
Size out(outShape[3], outShape[2]);
int dims = inpShape.size();
int inpD = dims == 5 ? inpShape[2] : 1;
int inpH = inpShape[dims - 2];
int inpW = inpShape.back();
int inpGroupCn = blobs[0].size[1];
int ksize = inpGroupCn * kernel.height * kernel.width;
return shape(out.area(), ksize);
int ksize = inpGroupCn * std::accumulate(kernel_size.begin(), kernel_size.end(),
1, std::multiplies<size_t>());
return shape(inpD * inpH * inpW, ksize);
}
virtual bool supportBackend(int backendId) CV_OVERRIDE
@@ -1228,14 +1232,17 @@ public:
MatShape computeColRowShape(const MatShape &inpShape, const MatShape &outShape) const CV_OVERRIDE
{
int dims = inpShape.size();
int inpCn = inpShape[1];
int inpH = inpShape[2];
int inpW = inpShape[3];
int inpD = dims == 5 ? inpShape[2] : 1;
int inpH = inpShape[dims - 2];
int inpW = inpShape.back();
int outCn = outShape[1];
int ngroups = inpCn / blobs[0].size[0];
int outGroupCn = outCn / ngroups;
int ksize = outGroupCn * kernel.height * kernel.width;
return shape(ksize, inpH * inpW);
int ksize = outGroupCn * std::accumulate(kernel_size.begin(), kernel_size.end(),
1, std::multiplies<size_t>());
return shape(ksize, inpD * inpH * inpW);
}
virtual bool supportBackend(int backendId) CV_OVERRIDE
+2
View File
@@ -162,6 +162,8 @@ public:
{
if (backendId == DNN_BACKEND_INFERENCE_ENGINE)
{
if (computeMaxIdx)
return false;
#ifdef HAVE_INF_ENGINE
if (kernel_size.size() == 3)
return preferableTarget == DNN_TARGET_CPU;
+14 -1
View File
@@ -92,6 +92,7 @@ class LSTMLayerImpl CV_FINAL : public LSTMLayer
bool produceCellOutput;
float forgetBias, cellClip;
bool useCellClip, usePeephole;
bool reverse; // If true, go in negative direction along the time axis
public:
@@ -133,6 +134,7 @@ public:
cellClip = params.get<float>("cell_clip", 0.0f);
useCellClip = params.get<bool>("use_cell_clip", false);
usePeephole = params.get<bool>("use_peephole", false);
reverse = params.get<bool>("reverse", false);
allocated = false;
outTailShape.clear();
@@ -288,7 +290,18 @@ public:
Mat hOutTs = output[0].reshape(1, numSamplesTotal);
Mat cOutTs = produceCellOutput ? output[1].reshape(1, numSamplesTotal) : Mat();
for (int ts = 0; ts < numTimeStamps; ts++)
int tsStart, tsEnd, tsInc;
if (reverse) {
tsStart = numTimeStamps - 1;
tsEnd = -1;
tsInc = -1;
}
else {
tsStart = 0;
tsEnd = numTimeStamps;
tsInc = 1;
}
for (int ts = tsStart; ts != tsEnd; ts += tsInc)
{
Range curRowRange(ts*numSamples, (ts + 1)*numSamples);
Mat xCurr = xTs.rowRange(curRowRange);
+2 -1
View File
@@ -581,7 +581,6 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::CNNNetwork& net)
try
{
AutoLock lock(getInitializationMutex());
InferenceEngine::Core& ie = getCore();
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
auto& sharedPlugins = getSharedPlugins();
auto pluginIt = sharedPlugins.find(device_name);
@@ -590,6 +589,8 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::CNNNetwork& net)
enginePtr = pluginIt->second;
}
else
#else
InferenceEngine::Core& ie = getCore();
#endif
{
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
+3 -2
View File
@@ -22,10 +22,11 @@
#define INF_ENGINE_RELEASE_2018R5 2018050000
#define INF_ENGINE_RELEASE_2019R1 2019010000
#define INF_ENGINE_RELEASE_2019R2 2019020000
#define INF_ENGINE_RELEASE_2019R3 2019030000
#ifndef INF_ENGINE_RELEASE
#warning("IE version have not been provided via command-line. Using 2019R2 by default")
#define INF_ENGINE_RELEASE INF_ENGINE_RELEASE_2019R2
#warning("IE version have not been provided via command-line. Using 2019R3 by default")
#define INF_ENGINE_RELEASE INF_ENGINE_RELEASE_2019R3
#endif
#define INF_ENGINE_VER_MAJOR_GT(ver) (((INF_ENGINE_RELEASE) / 10000) > ((ver) / 10000))
+1
View File
@@ -19,6 +19,7 @@
#define CV_TEST_TAG_DNN_SKIP_IE_2019R1 "dnn_skip_ie_2019r1"
#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_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"
+2
View File
@@ -315,6 +315,8 @@ void initDNNTests()
# endif
#elif INF_ENGINE_VER_MAJOR_EQ(2019020000)
CV_TEST_TAG_DNN_SKIP_IE_2019R2,
#elif INF_ENGINE_VER_MAJOR_EQ(2019030000)
CV_TEST_TAG_DNN_SKIP_IE_2019R3,
#endif
CV_TEST_TAG_DNN_SKIP_IE
);
+3 -1
View File
@@ -329,11 +329,13 @@ TEST_P(Test_Darknet_nets, TinyYoloVoc)
}
#ifdef HAVE_INF_ENGINE
static const std::chrono::milliseconds async_timeout(500);
static const std::chrono::milliseconds async_timeout(10000);
typedef testing::TestWithParam<tuple<std::string, Target> > Test_Darknet_nets_async;
TEST_P(Test_Darknet_nets_async, Accuracy)
{
if (INF_ENGINE_VER_MAJOR_LT(2019020000))
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE);
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
std::string prefix = get<0>(GetParam());
+8 -2
View File
@@ -554,9 +554,9 @@ TEST_P(ReLU, Accuracy)
Backend backendId = get<0>(get<1>(GetParam()));
Target targetId = get<1>(get<1>(GetParam()));
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019020000)
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019020000)
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD && negativeSlope < 0)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R2);
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_2019R3, CV_TEST_TAG_DNN_SKIP_IE_2019R2, CV_TEST_TAG_DNN_SKIP_IE);
#endif
LayerParams lp;
@@ -758,6 +758,12 @@ TEST_P(Eltwise, Accuracy)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R1, CV_TEST_TAG_DNN_SKIP_IE_2019R1_1);
#endif
#if defined(INF_ENGINE_RELEASE)
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_OPENCL &&
op == "sum" && numConv == 1 && !weighted)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE);
#endif
Net net;
std::vector<int> convLayerIds(numConv);
+49
View File
@@ -461,6 +461,55 @@ TEST(Layer_RNN_Test_Accuracy_with_, CaffeRecurrent)
normAssert(h_ref, output[0]);
}
TEST(Layer_LSTM_Test_Accuracy_, Reverse)
{
// This handcrafted setup calculates (approximately) the prefix sum of the
// input, assuming the inputs are suitably small.
cv::Mat input(2, 1, CV_32FC1);
input.at<float>(0, 0) = 1e-5f;
input.at<float>(1, 0) = 2e-5f;
cv::Mat Wx(4, 1, CV_32FC1);
Wx.at<float>(0, 0) = 0.f; // Input gate
Wx.at<float>(1, 0) = 0.f; // Forget gate
Wx.at<float>(2, 0) = 0.f; // Output gate
Wx.at<float>(3, 0) = 1.f; // Update signal
cv::Mat Wh(4, 1, CV_32FC1);
Wh.at<float>(0, 0) = 0.f; // Input gate
Wh.at<float>(1, 0) = 0.f; // Forget gate
Wh.at<float>(2, 0) = 0.f; // Output gate
Wh.at<float>(3, 0) = 0.f; // Update signal
cv::Mat bias(4, 1, CV_32FC1);
bias.at<float>(0, 0) = 1e10f; // Input gate - always allows input to c
bias.at<float>(1, 0) = 1e10f; // Forget gate - never forget anything on c
bias.at<float>(2, 0) = 1e10f; // Output gate - always output everything
bias.at<float>(3, 0) = 0.f; // Update signal
LayerParams lp;
lp.set("reverse", true);
lp.set("use_timestamp_dim", true);
lp.blobs.clear();
lp.blobs.push_back(Wh);
lp.blobs.push_back(Wx);
lp.blobs.push_back(bias);
cv::Ptr<cv::dnn::LSTMLayer> layer = LSTMLayer::create(lp);
std::vector<cv::Mat> outputs;
std::vector<cv::Mat> inputs;
inputs.push_back(input);
runLayer(layer, inputs, outputs);
ASSERT_EQ(1, outputs.size());
cv::Mat out = outputs[0];
ASSERT_EQ(3, out.dims);
ASSERT_EQ(shape(2, 1, 1), shape(out));
float* data = reinterpret_cast<float*>(out.data);
EXPECT_NEAR(std::tanh(1e-5f) + std::tanh(2e-5f), data[0], 1e-10);
EXPECT_NEAR(std::tanh(2e-5f), data[1], 1e-10);
}
class Layer_RNN_Test : public ::testing::Test
{
+1 -1
View File
@@ -361,7 +361,7 @@ TEST(Net, forwardAndRetrieve)
}
#ifdef HAVE_INF_ENGINE
static const std::chrono::milliseconds async_timeout(500);
static const std::chrono::milliseconds async_timeout(10000);
// This test runs network in synchronous mode for different inputs and then
// runs the same model asynchronously for the same inputs.
+13 -4
View File
@@ -86,8 +86,8 @@ TEST_P(Test_ONNX_layers, InstanceNorm)
TEST_P(Test_ONNX_layers, MaxPooling)
{
testONNXModels("maxpooling");
testONNXModels("two_maxpooling");
testONNXModels("maxpooling", npy, 0, 0, false, false);
testONNXModels("two_maxpooling", npy, 0, 0, false, false);
}
TEST_P(Test_ONNX_layers, Convolution)
@@ -212,7 +212,7 @@ TEST_P(Test_ONNX_layers, MaxPooling3D)
#endif
if (target != DNN_TARGET_CPU)
throw SkipTestException("Only CPU is supported");
testONNXModels("max_pool3d");
testONNXModels("max_pool3d", npy, 0, 0, false, false);
}
TEST_P(Test_ONNX_layers, AvePooling3D)
@@ -422,13 +422,22 @@ TEST_P(Test_ONNX_nets, Googlenet)
TEST_P(Test_ONNX_nets, CaffeNet)
{
applyTestTag(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB);
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
&& getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_2019R3);
#endif
testONNXModels("caffenet", pb);
}
TEST_P(Test_ONNX_nets, RCNN_ILSVRC13)
{
applyTestTag(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB);
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
&& getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_2019R3);
#endif
// Reference output values are in range [-4.992, -1.161]
testONNXModels("rcnn_ilsvrc13", pb, 0.0045);
}
+7 -4
View File
@@ -146,13 +146,13 @@ TEST_P(Test_TensorFlow_layers, padding)
runTensorFlowNet("padding_valid");
runTensorFlowNet("spatial_padding");
runTensorFlowNet("mirror_pad");
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019020000)
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019020000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE)
{
if (target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2019R2);
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2019R3, CV_TEST_TAG_DNN_SKIP_IE_2019R2);
if (target == DNN_TARGET_OPENCL_FP16)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_2019R2);
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_2019R3, CV_TEST_TAG_DNN_SKIP_IE_2019R2);
}
#endif
runTensorFlowNet("keras_pad_concat");
@@ -481,8 +481,11 @@ TEST_P(Test_TensorFlow_nets, Faster_RCNN)
"faster_rcnn_resnet50_coco_2018_01_28"};
checkBackend();
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
#ifdef INF_ENGINE_RELEASE
if (backend == DNN_BACKEND_INFERENCE_ENGINE &&
(INF_ENGINE_VER_MAJOR_LT(2019020000) || target != DNN_TARGET_CPU))
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE);
#endif
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
+9 -3
View File
@@ -337,9 +337,15 @@ TEST_P(Test_Torch_nets, ENet_accuracy)
{
applyTestTag(target == DNN_TARGET_CPU ? "" : CV_TEST_TAG_MEMORY_512MB);
checkBackend();
if (backend == DNN_BACKEND_INFERENCE_ENGINE ||
(backend == DNN_BACKEND_OPENCV && 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);
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
throw SkipTestException("");
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
{
if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16);
if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL);
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
throw SkipTestException("");
}
Net net;
{
+6 -5
View File
@@ -85,12 +85,12 @@ CV_IMPL void cvSetWindowProperty(const char* name, int prop_id, double prop_valu
break;
case cv::WND_PROP_TOPMOST:
#if defined(HAVE_WIN32UI)
#if defined (HAVE_QT)
// nothing
#elif defined(HAVE_WIN32UI)
cvSetPropTopmost_W32(name, (prop_value != 0 ? true : false));
#elif defined(HAVE_COCOA)
cvSetPropTopmost_COCOA(name, (prop_value != 0 ? true : false));
#else
CV_LOG_WARNING(NULL, "Property WND_PROP_TOPMOST is not supported on current GUI backend");
#endif
break;
@@ -175,12 +175,13 @@ CV_IMPL double cvGetWindowProperty(const char* name, int prop_id)
break;
case cv::WND_PROP_TOPMOST:
#if defined(HAVE_WIN32UI)
#if defined (HAVE_QT)
return -1;
#elif defined(HAVE_WIN32UI)
return cvGetPropTopmost_W32(name);
#elif defined(HAVE_COCOA)
return cvGetPropTopmost_COCOA(name);
#else
CV_LOG_WARNING(NULL, "Property WND_PROP_TOPMOST is not supported on current GUI backend");
return -1;
#endif
break;
+2
View File
@@ -824,6 +824,7 @@ bool TiffEncoder::writeLibTiff( const std::vector<Mat>& img_vec, const std::vect
for (size_t page = 0; page < img_vec.size(); page++)
{
const Mat& img = img_vec[page];
CV_Assert(!img.empty());
int channels = img.channels();
int width = img.cols, height = img.rows;
int type = img.type();
@@ -883,6 +884,7 @@ bool TiffEncoder::writeLibTiff( const std::vector<Mat>& img_vec, const std::vect
const int bitsPerByte = 8;
size_t fileStep = (width * channels * bitsPerChannel) / bitsPerByte;
CV_Assert(fileStep > 0);
int rowsPerStrip = (int)((1 << 13) / fileStep);
readParam(params, TIFFTAG_ROWSPERSTRIP, rowsPerStrip);
+15 -10
View File
@@ -40,7 +40,7 @@
//M*/
//
// Loading and saving IPL images.
// Loading and saving images.
//
#include "precomp.hpp"
@@ -391,7 +391,6 @@ static void ApplyExifOrientation(const Mat& buf, Mat& img)
* LOAD_MAT=2
* }
* @param[in] mat Reference to C++ Mat object (If LOAD_MAT)
* @param[in] scale_denom Scale value
*
*/
static void*
@@ -463,11 +462,11 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 )
int type = decoder->type();
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
{
if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
if( (flags & IMREAD_ANYDEPTH) == 0 )
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
if( (flags & IMREAD_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
@@ -583,11 +582,11 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)
int type = decoder->type();
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
{
if ((flags & CV_LOAD_IMAGE_ANYDEPTH) == 0)
if ((flags & IMREAD_ANYDEPTH) == 0)
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if ((flags & CV_LOAD_IMAGE_COLOR) != 0 ||
((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
@@ -689,6 +688,8 @@ static bool imwrite_( const String& filename, const std::vector<Mat>& img_vec,
for (size_t page = 0; page < img_vec.size(); page++)
{
Mat image = img_vec[page];
CV_Assert(!image.empty());
CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 );
Mat temp;
@@ -735,6 +736,9 @@ bool imwrite( const String& filename, InputArray _img,
const std::vector<int>& params )
{
CV_TRACE_FUNCTION();
CV_Assert(!_img.empty());
std::vector<Mat> img_vec;
if (_img.isMatVector() || _img.isUMatVector())
_img.getMatVector(img_vec);
@@ -814,11 +818,11 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 )
int type = decoder->type();
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
{
if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
if( (flags & IMREAD_ANYDEPTH) == 0 )
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
if( (flags & IMREAD_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
@@ -919,6 +923,7 @@ bool imencode( const String& ext, InputArray _image,
CV_TRACE_FUNCTION();
Mat image = _image.getMat();
CV_Assert(!image.empty());
int channels = image.channels();
CV_Assert( channels == 1 || channels == 3 || channels == 4 );
@@ -807,7 +807,7 @@ public class ImgprocTest extends OpenCVTestCase {
points.put(0, 0, 0, 0, 2, 3, 3, 4, 5, 8);
Mat linePoints = new Mat(4, 1, CvType.CV_32FC1);
linePoints.put(0, 0, 0.53196341, 0.84676737, 2.496531, 3.7467217);
linePoints.put(0, 0, 0.53198653, 0.84675282, 2.5, 3.75);
Imgproc.fitLine(points, dst, Imgproc.CV_DIST_L12, 0, 0.01, 0.01);
+8 -11
View File
@@ -2543,10 +2543,10 @@ namespace cv{
//Array used to store info and labeled pixel by each thread.
//Different threads affect different memory location of chunksSizeAndLabels
const int chunksSizeAndLabelsSize = h + 1;
int *chunksSizeAndLabels = (int *)cv::fastMalloc(chunksSizeAndLabelsSize * sizeof(int));
cv::AutoBuffer<int, 0> chunksSizeAndLabels(chunksSizeAndLabelsSize);
//Tree of labels
LabelT *P = (LabelT *)cv::fastMalloc(Plength * sizeof(LabelT));
cv::AutoBuffer<LabelT, 0> P(Plength);
//First label is for background
P[0] = 0;
@@ -2555,30 +2555,27 @@ namespace cv{
//First scan, each thread works with chunk of img.rows/nThreads rows
//e.g. 300 rows, 4 threads -> each chunks is composed of 75 rows
cv::parallel_for_(range, FirstScan(img, imgLabels, P, chunksSizeAndLabels), nParallelStripes);
cv::parallel_for_(range, FirstScan(img, imgLabels, P.data(), chunksSizeAndLabels.data()), nParallelStripes);
//merge labels of different chunks
mergeLabels(img, imgLabels, P, chunksSizeAndLabels);
mergeLabels(img, imgLabels, P.data(), chunksSizeAndLabels.data());
LabelT nLabels = 1;
for (int i = 0; i < h; i = chunksSizeAndLabels[i]){
CV_Assert(i + 1 < chunksSizeAndLabelsSize);
flattenL(P, LabelT((i + 1) / 2) * LabelT((w + 1) / 2) + 1, chunksSizeAndLabels[i + 1], nLabels);
flattenL(P.data(), LabelT((i + 1) / 2) * LabelT((w + 1) / 2) + 1, chunksSizeAndLabels[i + 1], nLabels);
}
//Array for statistics data
StatsOp *sopArray = new StatsOp[h];
cv::AutoBuffer<StatsOp, 0> sopArray(h);
sop.init(nLabels);
//Second scan
cv::parallel_for_(range, SecondScan(img, imgLabels, P, sop, sopArray, nLabels), nParallelStripes);
cv::parallel_for_(range, SecondScan(img, imgLabels, P.data(), sop, sopArray.data(), nLabels), nParallelStripes);
StatsOp::mergeStats(imgLabels, sopArray, sop, nLabels);
StatsOp::mergeStats(imgLabels, sopArray.data(), sop, nLabels);
sop.finish();
delete[] sopArray;
cv::fastFree(chunksSizeAndLabels);
cv::fastFree(P);
return nLabels;
}
};//End struct LabelingGranaParallel
+120 -36
View File
@@ -50,6 +50,8 @@ namespace cv
////////////////// Helper functions //////////////////////
#define CV_CLAMP_INT(v, vmin, vmax) (v < vmin ? vmin : (vmax < v ? vmax : v))
static const size_t OUT_OF_RANGE = (size_t)1 << (sizeof(size_t)*8 - 2);
static void
@@ -71,15 +73,18 @@ calcHistLookupTables_8u( const Mat& hist, const SparseMat& shist,
int sz = !issparse ? hist.size[i] : shist.size(i);
size_t step = !issparse ? hist.step[i] : 1;
double v_lo = ranges[i][0];
double v_hi = ranges[i][1];
for( j = low; j < high; j++ )
{
int idx = cvFloor(j*a + b);
size_t written_idx;
if( (unsigned)idx < (unsigned)sz )
size_t written_idx = OUT_OF_RANGE;
if (j >= v_lo && j < v_hi)
{
idx = CV_CLAMP_INT(idx, 0, sz - 1);
written_idx = idx*step;
else
written_idx = OUT_OF_RANGE;
}
tab[i*(high - low) + j - low] = written_idx;
}
}
@@ -197,6 +202,10 @@ static void histPrepareImages( const Mat* images, int nimages, const int* channe
double t = histSize[i]/(high - low);
uniranges[i*2] = t;
uniranges[i*2+1] = -t*low;
#if 0 // This should be true by math, but it is not accurate numerically
CV_Assert(cvFloor(low * uniranges[i*2] + uniranges[i*2+1]) == 0);
CV_Assert((high * uniranges[i*2] + uniranges[i*2+1]) < histSize[i]);
#endif
}
}
else
@@ -243,22 +252,33 @@ calcHist_( std::vector<uchar*>& _ptrs, const std::vector<int>& _deltas,
int sz = size[0], d0 = deltas[0], step0 = deltas[1];
const T* p0 = (const T*)ptrs[0];
double v0_lo = _ranges[0][0];
double v0_hi = _ranges[0][1];
for( ; imsize.height--; p0 += step0, mask += mstep )
{
if( !mask )
for( x = 0; x < imsize.width; x++, p0 += d0 )
{
int idx = cvFloor(*p0*a + b);
if( (unsigned)idx < (unsigned)sz )
((int*)H)[idx]++;
double v0 = (double)*p0;
int idx = cvFloor(v0*a + b);
if (v0 < v0_lo || v0 >= v0_hi)
continue;
idx = CV_CLAMP_INT(idx, 0, sz - 1);
CV_DbgAssert((unsigned)idx < (unsigned)sz);
((int*)H)[idx]++;
}
else
for( x = 0; x < imsize.width; x++, p0 += d0 )
if( mask[x] )
{
int idx = cvFloor(*p0*a + b);
if( (unsigned)idx < (unsigned)sz )
((int*)H)[idx]++;
double v0 = (double)*p0;
int idx = cvFloor(v0*a + b);
if (v0 < v0_lo || v0 >= v0_hi)
continue;
idx = CV_CLAMP_INT(idx, 0, sz - 1);
CV_DbgAssert((unsigned)idx < (unsigned)sz);
((int*)H)[idx]++;
}
}
return;
@@ -273,24 +293,45 @@ calcHist_( std::vector<uchar*>& _ptrs, const std::vector<int>& _deltas,
const T* p0 = (const T*)ptrs[0];
const T* p1 = (const T*)ptrs[1];
double v0_lo = _ranges[0][0];
double v0_hi = _ranges[0][1];
double v1_lo = _ranges[1][0];
double v1_hi = _ranges[1][1];
for( ; imsize.height--; p0 += step0, p1 += step1, mask += mstep )
{
if( !mask )
for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1 )
{
int idx0 = cvFloor(*p0*a0 + b0);
int idx1 = cvFloor(*p1*a1 + b1);
if( (unsigned)idx0 < (unsigned)sz0 && (unsigned)idx1 < (unsigned)sz1 )
((int*)(H + hstep0*idx0))[idx1]++;
double v0 = (double)*p0;
double v1 = (double)*p1;
int idx0 = cvFloor(v0*a0 + b0);
int idx1 = cvFloor(v1*a1 + b1);
if (v0 < v0_lo || v0 >= v0_hi)
continue;
if (v1 < v1_lo || v1 >= v1_hi)
continue;
idx0 = CV_CLAMP_INT(idx0, 0, sz0 - 1);
idx1 = CV_CLAMP_INT(idx1, 0, sz1 - 1);
CV_DbgAssert((unsigned)idx0 < (unsigned)sz0 && (unsigned)idx1 < (unsigned)sz1);
((int*)(H + hstep0*idx0))[idx1]++;
}
else
for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1 )
if( mask[x] )
{
int idx0 = cvFloor(*p0*a0 + b0);
int idx1 = cvFloor(*p1*a1 + b1);
if( (unsigned)idx0 < (unsigned)sz0 && (unsigned)idx1 < (unsigned)sz1 )
((int*)(H + hstep0*idx0))[idx1]++;
double v0 = (double)*p0;
double v1 = (double)*p1;
int idx0 = cvFloor(v0*a0 + b0);
int idx1 = cvFloor(v1*a1 + b1);
if (v0 < v0_lo || v0 >= v0_hi)
continue;
if (v1 < v1_lo || v1 >= v1_hi)
continue;
idx0 = CV_CLAMP_INT(idx0, 0, sz0 - 1);
idx1 = CV_CLAMP_INT(idx1, 0, sz1 - 1);
CV_DbgAssert((unsigned)idx0 < (unsigned)sz0 && (unsigned)idx1 < (unsigned)sz1);
((int*)(H + hstep0*idx0))[idx1]++;
}
}
return;
@@ -309,30 +350,63 @@ calcHist_( std::vector<uchar*>& _ptrs, const std::vector<int>& _deltas,
const T* p1 = (const T*)ptrs[1];
const T* p2 = (const T*)ptrs[2];
double v0_lo = _ranges[0][0];
double v0_hi = _ranges[0][1];
double v1_lo = _ranges[1][0];
double v1_hi = _ranges[1][1];
double v2_lo = _ranges[2][0];
double v2_hi = _ranges[2][1];
for( ; imsize.height--; p0 += step0, p1 += step1, p2 += step2, mask += mstep )
{
if( !mask )
for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1, p2 += d2 )
{
int idx0 = cvFloor(*p0*a0 + b0);
int idx1 = cvFloor(*p1*a1 + b1);
int idx2 = cvFloor(*p2*a2 + b2);
if( (unsigned)idx0 < (unsigned)sz0 &&
double v0 = (double)*p0;
double v1 = (double)*p1;
double v2 = (double)*p2;
int idx0 = cvFloor(v0*a0 + b0);
int idx1 = cvFloor(v1*a1 + b1);
int idx2 = cvFloor(v2*a2 + b2);
if (v0 < v0_lo || v0 >= v0_hi)
continue;
if (v1 < v1_lo || v1 >= v1_hi)
continue;
if (v2 < v2_lo || v2 >= v2_hi)
continue;
idx0 = CV_CLAMP_INT(idx0, 0, sz0 - 1);
idx1 = CV_CLAMP_INT(idx1, 0, sz1 - 1);
idx2 = CV_CLAMP_INT(idx2, 0, sz2 - 1);
CV_DbgAssert(
(unsigned)idx0 < (unsigned)sz0 &&
(unsigned)idx1 < (unsigned)sz1 &&
(unsigned)idx2 < (unsigned)sz2 )
((int*)(H + hstep0*idx0 + hstep1*idx1))[idx2]++;
(unsigned)idx2 < (unsigned)sz2);
((int*)(H + hstep0*idx0 + hstep1*idx1))[idx2]++;
}
else
for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1, p2 += d2 )
if( mask[x] )
{
int idx0 = cvFloor(*p0*a0 + b0);
int idx1 = cvFloor(*p1*a1 + b1);
int idx2 = cvFloor(*p2*a2 + b2);
if( (unsigned)idx0 < (unsigned)sz0 &&
(unsigned)idx1 < (unsigned)sz1 &&
(unsigned)idx2 < (unsigned)sz2 )
((int*)(H + hstep0*idx0 + hstep1*idx1))[idx2]++;
double v0 = (double)*p0;
double v1 = (double)*p1;
double v2 = (double)*p2;
int idx0 = cvFloor(v0*a0 + b0);
int idx1 = cvFloor(v1*a1 + b1);
int idx2 = cvFloor(v2*a2 + b2);
if (v0 < v0_lo || v0 >= v0_hi)
continue;
if (v1 < v1_lo || v1 >= v1_hi)
continue;
if (v2 < v2_lo || v2 >= v2_hi)
continue;
idx0 = CV_CLAMP_INT(idx0, 0, sz0 - 1);
idx1 = CV_CLAMP_INT(idx1, 0, sz1 - 1);
idx2 = CV_CLAMP_INT(idx2, 0, sz2 - 1);
CV_DbgAssert(
(unsigned)idx0 < (unsigned)sz0 &&
(unsigned)idx1 < (unsigned)sz1 &&
(unsigned)idx2 < (unsigned)sz2);
((int*)(H + hstep0*idx0 + hstep1*idx1))[idx2]++;
}
}
}
@@ -346,9 +420,14 @@ calcHist_( std::vector<uchar*>& _ptrs, const std::vector<int>& _deltas,
uchar* Hptr = H;
for( i = 0; i < dims; i++ )
{
int idx = cvFloor(*ptrs[i]*uniranges[i*2] + uniranges[i*2+1]);
if( (unsigned)idx >= (unsigned)size[i] )
double v_lo = _ranges[i][0];
double v_hi = _ranges[i][1];
double v = *ptrs[i];
if (v < v_lo || v >= v_hi)
break;
int idx = cvFloor(v*uniranges[i*2] + uniranges[i*2+1]);
idx = CV_CLAMP_INT(idx, 0, size[i] - 1);
CV_DbgAssert((unsigned)idx < (unsigned)size[i]);
ptrs[i] += deltas[i*2];
Hptr += idx*hstep[i];
}
@@ -367,9 +446,14 @@ calcHist_( std::vector<uchar*>& _ptrs, const std::vector<int>& _deltas,
if( mask[x] )
for( ; i < dims; i++ )
{
int idx = cvFloor(*ptrs[i]*uniranges[i*2] + uniranges[i*2+1]);
if( (unsigned)idx >= (unsigned)size[i] )
double v_lo = _ranges[i][0];
double v_hi = _ranges[i][1];
double v = *ptrs[i];
if (v < v_lo || v >= v_hi)
break;
int idx = cvFloor(v*uniranges[i*2] + uniranges[i*2+1]);
idx = CV_CLAMP_INT(idx, 0, size[i] - 1);
CV_DbgAssert((unsigned)idx < (unsigned)size[i]);
ptrs[i] += deltas[i*2];
Hptr += idx*hstep[i];
}
+15 -4
View File
@@ -408,8 +408,14 @@ static void fitLine2D( const Point2f * points, int count, int dist,
}
/* calculate distances */
err = calcDist2D( points, count, _line, r );
if( err < EPS )
break;
if (err < min_err)
{
min_err = err;
memcpy(line, _line, 4 * sizeof(line[0]));
if (err < EPS)
break;
}
/* calculate weights */
if( calc_weights )
@@ -550,8 +556,13 @@ static void fitLine3D( Point3f * points, int count, int dist,
}
/* calculate distances */
err = calcDist3D( points, count, _line, r );
//if( err < FLT_EPSILON*count )
// break;
if (err < min_err)
{
min_err = err;
memcpy(line, _line, 6 * sizeof(line[0]));
if (err < EPS)
break;
}
/* calculate weights */
if( calc_weights )
+62 -60
View File
@@ -87,13 +87,13 @@ template<typename T1, typename T2> int PyrUpVecV(T1**, T2**, int) { return 0; }
template<> int PyrDownVecH<uchar, int, 1>(const uchar* src, int* row, int width)
{
int x = 0;
const uchar *src0 = src, *src2 = src + 2, *src4 = src + 3;
const uchar *src01 = src, *src23 = src + 2, *src4 = src + 3;
v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_reinterpret_as_s16(vx_load_expand(src0)), v_1_4) +
v_dotprod(v_reinterpret_as_s16(vx_load_expand(src2)), v_6_4) +
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src01 += v_int16::nlanes, src23 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_reinterpret_as_s16(vx_load_expand(src01)), v_1_4) +
v_dotprod(v_reinterpret_as_s16(vx_load_expand(src23)), v_6_4) +
(v_reinterpret_as_s32(vx_load_expand(src4)) >> 16));
vx_cleanup();
@@ -102,13 +102,13 @@ template<> int PyrDownVecH<uchar, int, 1>(const uchar* src, int* row, int width)
template<> int PyrDownVecH<uchar, int, 2>(const uchar* src, int* row, int width)
{
int x = 0;
const uchar *src0 = src, *src2 = src + 4, *src4 = src + 6;
const uchar *src01 = src, *src23 = src + 4, *src4 = src + 6;
v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(vx_load_expand(src0))), v_1_4) +
v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(vx_load_expand(src2))), v_6_4) +
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src01 += v_int16::nlanes, src23 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(vx_load_expand(src01))), v_1_4) +
v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(vx_load_expand(src23))), v_6_4) +
(v_reinterpret_as_s32(v_interleave_pairs(vx_load_expand(src4))) >> 16));
vx_cleanup();
@@ -150,13 +150,13 @@ template<> int PyrDownVecH<uchar, int, 3>(const uchar* src, int* row, int width)
template<> int PyrDownVecH<uchar, int, 4>(const uchar* src, int* row, int width)
{
int x = 0;
const uchar *src0 = src, *src2 = src + 8, *src4 = src + 12;
const uchar *src01 = src, *src23 = src + 8, *src4 = src + 12;
v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_interleave_quads(v_reinterpret_as_s16(vx_load_expand(src0))), v_1_4) +
v_dotprod(v_interleave_quads(v_reinterpret_as_s16(vx_load_expand(src2))), v_6_4) +
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src01 += v_int16::nlanes, src23 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_interleave_quads(v_reinterpret_as_s16(vx_load_expand(src01))), v_1_4) +
v_dotprod(v_interleave_quads(v_reinterpret_as_s16(vx_load_expand(src23))), v_6_4) +
(v_reinterpret_as_s32(v_interleave_quads(vx_load_expand(src4))) >> 16));
vx_cleanup();
@@ -166,13 +166,13 @@ template<> int PyrDownVecH<uchar, int, 4>(const uchar* src, int* row, int width)
template<> int PyrDownVecH<short, int, 1>(const short* src, int* row, int width)
{
int x = 0;
const short *src0 = src, *src2 = src + 2, *src4 = src + 3;
const short *src01 = src, *src23 = src + 2, *src4 = src + 3;
v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(vx_load(src0), v_1_4) +
v_dotprod(vx_load(src2), v_6_4) +
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src01 += v_int16::nlanes, src23 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(vx_load(src01), v_1_4) +
v_dotprod(vx_load(src23), v_6_4) +
(v_reinterpret_as_s32(vx_load(src4)) >> 16));
vx_cleanup();
@@ -181,13 +181,13 @@ template<> int PyrDownVecH<short, int, 1>(const short* src, int* row, int width)
template<> int PyrDownVecH<short, int, 2>(const short* src, int* row, int width)
{
int x = 0;
const short *src0 = src, *src2 = src + 4, *src4 = src + 6;
const short *src01 = src, *src23 = src + 4, *src4 = src + 6;
v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_interleave_pairs(vx_load(src0)), v_1_4) +
v_dotprod(v_interleave_pairs(vx_load(src2)), v_6_4) +
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src01 += v_int16::nlanes, src23 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_interleave_pairs(vx_load(src01)), v_1_4) +
v_dotprod(v_interleave_pairs(vx_load(src23)), v_6_4) +
(v_reinterpret_as_s32(v_interleave_pairs(vx_load(src4))) >> 16));
vx_cleanup();
@@ -247,15 +247,15 @@ template<> int PyrDownVecH<short, int, 4>(const short* src, int* row, int width)
template<> int PyrDownVecH<ushort, int, 1>(const ushort* src, int* row, int width)
{
int x = 0;
const ushort *src0 = src, *src2 = src + 2, *src4 = src + 3;
const ushort *src01 = src, *src23 = src + 2, *src4 = src + 3;
v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
v_uint16 v_half = vx_setall_u16(0x8000);
v_int32 v_half15 = vx_setall_s32(0x00078000);
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_reinterpret_as_s16(v_sub_wrap(vx_load(src0), v_half)), v_1_4) +
v_dotprod(v_reinterpret_as_s16(v_sub_wrap(vx_load(src2), v_half)), v_6_4) +
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src01 += v_int16::nlanes, src23 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_reinterpret_as_s16(v_sub_wrap(vx_load(src01), v_half)), v_1_4) +
v_dotprod(v_reinterpret_as_s16(v_sub_wrap(vx_load(src23), v_half)), v_6_4) +
v_reinterpret_as_s32(v_reinterpret_as_u32(vx_load(src4)) >> 16) + v_half15);
vx_cleanup();
@@ -264,15 +264,15 @@ template<> int PyrDownVecH<ushort, int, 1>(const ushort* src, int* row, int widt
template<> int PyrDownVecH<ushort, int, 2>(const ushort* src, int* row, int width)
{
int x = 0;
const ushort *src0 = src, *src2 = src + 4, *src4 = src + 6;
const ushort *src01 = src, *src23 = src + 4, *src4 = src + 6;
v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
v_uint16 v_half = vx_setall_u16(0x8000);
v_int32 v_half15 = vx_setall_s32(0x00078000);
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(v_sub_wrap(vx_load(src0), v_half))), v_1_4) +
v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(v_sub_wrap(vx_load(src2), v_half))), v_6_4) +
for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src01 += v_int16::nlanes, src23 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
v_store(row, v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(v_sub_wrap(vx_load(src01), v_half))), v_1_4) +
v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(v_sub_wrap(vx_load(src23), v_half))), v_6_4) +
v_reinterpret_as_s32(v_reinterpret_as_u32(v_interleave_pairs(vx_load(src4))) >> 16) + v_half15);
vx_cleanup();
@@ -344,15 +344,15 @@ template<> int PyrDownVecH<ushort, int, 4>(const ushort* src, int* row, int widt
template<> int PyrDownVecH<float, float, 1>(const float* src, float* row, int width)
{
int x = 0;
const float *src0 = src, *src2 = src + 2, *src4 = src + 4;
const float *src01 = src, *src23 = src + 2, *src4 = src + 3;
v_float32 _4 = vx_setall_f32(4.f), _6 = vx_setall_f32(6.f);
for (; x <= width - v_float32::nlanes; x += v_float32::nlanes, src0 += 2*v_float32::nlanes, src2 += 2*v_float32::nlanes, src4 += 2*v_float32::nlanes, row+=v_float32::nlanes)
for (; x <= width - v_float32::nlanes; x += v_float32::nlanes, src01 += 2*v_float32::nlanes, src23 += 2*v_float32::nlanes, src4 += 2*v_float32::nlanes, row+=v_float32::nlanes)
{
v_float32 r0, r1, r2, r3, r4, rtmp;
v_load_deinterleave(src0, r0, r1);
v_load_deinterleave(src2, r2, r3);
v_load_deinterleave(src4, r4, rtmp);
v_load_deinterleave(src01, r0, r1);
v_load_deinterleave(src23, r2, r3);
v_load_deinterleave(src4, rtmp, r4);
v_store(row, v_muladd(r2, _6, v_muladd(r1 + r3, _4, r0 + r4)));
}
vx_cleanup();
@@ -362,14 +362,14 @@ template<> int PyrDownVecH<float, float, 1>(const float* src, float* row, int wi
template<> int PyrDownVecH<float, float, 2>(const float* src, float* row, int width)
{
int x = 0;
const float *src0 = src, *src2 = src + 4, *src4 = src + 6;
const float *src01 = src, *src23 = src + 4, *src4 = src + 6;
v_float32 _4 = vx_setall_f32(4.f), _6 = vx_setall_f32(6.f);
for (; x <= width - 2*v_float32::nlanes; x += 2*v_float32::nlanes, src0 += 4*v_float32::nlanes, src2 += 4*v_float32::nlanes, src4 += 4*v_float32::nlanes, row += 2*v_float32::nlanes)
for (; x <= width - 2*v_float32::nlanes; x += 2*v_float32::nlanes, src01 += 4*v_float32::nlanes, src23 += 4*v_float32::nlanes, src4 += 4*v_float32::nlanes, row += 2*v_float32::nlanes)
{
v_float32 r0a, r0b, r1a, r1b, r2a, r2b, r3a, r3b, r4a, r4b, rtmpa, rtmpb;
v_load_deinterleave(src0, r0a, r0b, r1a, r1b);
v_load_deinterleave(src2, r2a, r2b, r3a, r3b);
v_load_deinterleave(src01, r0a, r0b, r1a, r1b);
v_load_deinterleave(src23, r2a, r2b, r3a, r3b);
v_load_deinterleave(src4, rtmpa, rtmpb, r4a, r4b);
v_store_interleave(row, v_muladd(r2a, _6, v_muladd(r1a + r3a, _4, r0a + r4a)), v_muladd(r2b, _6, v_muladd(r1b + r3b, _4, r0b + r4b)));
}
@@ -430,15 +430,15 @@ template<> int PyrDownVecH<float, float, 4>(const float* src, float* row, int wi
template<> int PyrDownVecH<double, double, 1>(const double* src, double* row, int width)
{
int x = 0;
const double *src0 = src, *src2 = src + 2, *src4 = src + 4;
const double *src01 = src, *src23 = src + 2, *src4 = src + 3;
v_float64 _4 = vx_setall_f64(4.f), _6 = vx_setall_f64(6.f);
for (; x <= width - v_float64::nlanes; x += v_float64::nlanes, src0 += 2*v_float64::nlanes, src2 += 2*v_float64::nlanes, src4 += 2*v_float64::nlanes, row += v_float64::nlanes)
for (; x <= width - v_float64::nlanes; x += v_float64::nlanes, src01 += 2*v_float64::nlanes, src23 += 2*v_float64::nlanes, src4 += 2*v_float64::nlanes, row += v_float64::nlanes)
{
v_float64 r0, r1, r2, r3, r4, rtmp;
v_load_deinterleave(src0, r0, r1);
v_load_deinterleave(src2, r2, r3);
v_load_deinterleave(src4, r4, rtmp);
v_load_deinterleave(src01, r0, r1);
v_load_deinterleave(src23, r2, r3);
v_load_deinterleave(src4, rtmp, r4);
v_store(row, v_muladd(r2, _6, v_muladd(r1 + r3, _4, r0 + r4)));
}
vx_cleanup();
@@ -741,13 +741,13 @@ pyrDown_( const Mat& _src, Mat& _dst, int borderType )
CV_Assert( ssize.width > 0 && ssize.height > 0 &&
std::abs(dsize.width*2 - ssize.width) <= 2 &&
std::abs(dsize.height*2 - ssize.height) <= 2 );
int k, x, sy0 = -PD_SZ/2, sy = sy0, width0 = std::min((ssize.width-PD_SZ/2-1)/2 + 1, dsize.width);
int sy0 = -PD_SZ/2, sy = sy0, width0 = std::min((ssize.width-PD_SZ/2-1)/2 + 1, dsize.width);
for( x = 0; x <= PD_SZ+1; x++ )
for (int x = 0; x <= PD_SZ+1; x++)
{
int sx0 = borderInterpolate(x - PD_SZ/2, ssize.width, borderType)*cn;
int sx1 = borderInterpolate(x + width0*2 - PD_SZ/2, ssize.width, borderType)*cn;
for( k = 0; k < cn; k++ )
for (int k = 0; k < cn; k++)
{
tabL[x*cn + k] = sx0 + k;
tabR[x*cn + k] = sx1 + k;
@@ -758,10 +758,10 @@ pyrDown_( const Mat& _src, Mat& _dst, int borderType )
dsize.width *= cn;
width0 *= cn;
for( x = 0; x < dsize.width; x++ )
for (int x = 0; x < dsize.width; x++)
tabM[x] = (x/cn)*2*cn + x % cn;
for( int y = 0; y < dsize.height; y++ )
for (int y = 0; y < dsize.height; y++)
{
T* dst = _dst.ptr<T>(y);
WT *row0, *row1, *row2, *row3, *row4;
@@ -772,15 +772,13 @@ pyrDown_( const Mat& _src, Mat& _dst, int borderType )
WT* row = buf + ((sy - sy0) % PD_SZ)*bufstep;
int _sy = borderInterpolate(sy, ssize.height, borderType);
const T* src = _src.ptr<T>(_sy);
int limit = cn;
const int* tab = tabL;
for( x = 0;;)
{
for( ; x < limit; x++ )
do {
int x = 0;
for( ; x < cn; x++ )
{
row[x] = src[tab[x+cn*2]]*6 + (src[tab[x+cn]] + src[tab[x+cn*3]])*4 +
src[tab[x]] + src[tab[x+cn*4]];
row[x] = src[tabL[x+cn*2]]*6 + (src[tabL[x+cn]] + src[tabL[x+cn*3]])*4 +
src[tabL[x]] + src[tabL[x+cn*4]];
}
if( x == dsize.width )
@@ -840,18 +838,22 @@ pyrDown_( const Mat& _src, Mat& _dst, int borderType )
}
}
limit = dsize.width;
tab = tabR - x;
}
// tabR
for (int x_ = 0; x < dsize.width; x++, x_++)
{
row[x] = src[tabR[x_+cn*2]]*6 + (src[tabR[x_+cn]] + src[tabR[x_+cn*3]])*4 +
src[tabR[x_]] + src[tabR[x_+cn*4]];
}
} while (0);
}
// do vertical convolution and decimation and write the result to the destination image
for( k = 0; k < PD_SZ; k++ )
for (int k = 0; k < PD_SZ; k++)
rows[k] = buf + ((y*2 - PD_SZ/2 + k - sy0) % PD_SZ)*bufstep;
row0 = rows[0]; row1 = rows[1]; row2 = rows[2]; row3 = rows[3]; row4 = rows[4];
x = PyrDownVecV<WT, T>(rows, dst, dsize.width);
for( ; x < dsize.width; x++ )
int x = PyrDownVecV<WT, T>(rows, dst, dsize.width);
for (; x < dsize.width; x++ )
dst[x] = castOp(row2[x]*6 + (row1[x] + row3[x])*4 + row0[x] + row4[x]);
}
}
+13 -8
View File
@@ -153,19 +153,24 @@ public:
m_2 = vx_setall_f64(k5);
m_0 /= v_muladd(v_muladd(v_muladd(m_3, r2_0, m_2), r2_0, vx_setall_f64(k4)), r2_0, v_one);
m_1 /= v_muladd(v_muladd(v_muladd(m_3, r2_1, m_2), r2_1, vx_setall_f64(k4)), r2_1, v_one);
m_3 = vx_setall_f64(2.0);
xd_0 = v_muladd(m_3, xd_0, r2_0);
yd_0 = v_muladd(m_3, yd_0, r2_0);
xd_1 = v_muladd(m_3, xd_1, r2_1);
yd_1 = v_muladd(m_3, yd_1, r2_1);
m_2 = x_0 * y_0 * m_3;
m_3 = x_1 * y_1 * m_3;
x_0 *= m_0; y_0 *= m_0; x_1 *= m_1; y_1 *= m_1;
m_0 = vx_setall_f64(p1);
m_1 = vx_setall_f64(p2);
m_2 = vx_setall_f64(2.0);
xd_0 = v_muladd(v_muladd(m_2, xd_0, r2_0), m_1, x_0);
yd_0 = v_muladd(v_muladd(m_2, yd_0, r2_0), m_0, y_0);
xd_1 = v_muladd(v_muladd(m_2, xd_1, r2_1), m_1, x_1);
yd_1 = v_muladd(v_muladd(m_2, yd_1, r2_1), m_0, y_1);
xd_0 = v_muladd(xd_0, m_1, x_0);
yd_0 = v_muladd(yd_0, m_0, y_0);
xd_1 = v_muladd(xd_1, m_1, x_1);
yd_1 = v_muladd(yd_1, m_0, y_1);
m_0 *= m_2; m_1 *= m_2;
m_2 = x_0 * y_0;
m_3 = x_1 * y_1;
xd_0 = v_muladd(m_0, m_2, xd_0);
yd_0 = v_muladd(m_1, m_2, yd_0);
xd_1 = v_muladd(m_0, m_3, xd_1);
+35
View File
@@ -1609,6 +1609,8 @@ int CV_FitLineTest::validate_test_results( int test_case_idx )
int k, max_k = 0;
double vec_diff = 0, t;
//std::cout << dims << " " << Mat(1, dims*2, CV_32FC1, line.data()) << " " << Mat(1, dims, CV_32FC1, line0.data()) << std::endl;
for( k = 0; k < dims*2; k++ )
{
if( cvIsNaN(line[k]) || cvIsInf(line[k]) )
@@ -2038,5 +2040,38 @@ INSTANTIATE_TEST_CASE_P(Imgproc, ConvexityDefects_regression_5908,
testing::Values(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
));
TEST(Imgproc_FitLine, regression_15083)
{
int points2i_[] = {
432, 654,
370, 656,
390, 656,
410, 656,
348, 658
};
Mat points(5, 1, CV_32SC2, points2i_);
Vec4f lineParam;
fitLine(points, lineParam, DIST_L1, 0, 0.01, 0.01);
EXPECT_GE(fabs(lineParam[0]), fabs(lineParam[1]) * 4) << lineParam;
}
TEST(Imgproc_FitLine, regression_4903)
{
float points2f_[] = {
1224.0, 576.0,
1234.0, 683.0,
1215.0, 471.0,
1184.0, 137.0,
1079.0, 377.0,
1239.0, 788.0,
};
Mat points(6, 1, CV_32FC2, points2f_);
Vec4f lineParam;
fitLine(points, lineParam, DIST_WELSCH, 0, 0.01, 0.01);
EXPECT_GE(fabs(lineParam[1]), fabs(lineParam[0]) * 4) << lineParam;
}
}} // namespace
/* End of file. */
+11 -2
View File
@@ -1307,9 +1307,18 @@ cvTsCalcHist( const vector<Mat>& images, CvHistogram* hist, Mat mask, const vect
for( k = 0; k < cdims; k++ )
{
double v = val[k], lo = hist->thresh[k][0], hi = hist->thresh[k][1];
idx[k] = cvFloor((v - lo)*dims[k]/(hi - lo));
if( idx[k] < 0 || idx[k] >= dims[k] )
if (v < lo || v >= hi)
break;
double idx_ = (v - lo)*dims[k]/(hi - lo);
idx[k] = cvFloor(idx_);
if (idx[k] < 0)
{
idx[k] = 0;
}
if (idx[k] >= dims[k])
{
idx[k] = dims[k] - 1;
}
}
}
else
+35 -2
View File
@@ -82,11 +82,21 @@ add_definitions("-std=c++11")
link_libraries(${OPENCV_MODULE_${the_module}_DEPS})
ocv_add_executable(${the_module} ${bindings_cpp})
OCV_OPTION(BUILD_WASM_INTRIN_TESTS "Build WASM intrin tests" OFF )
if(BUILD_WASM_INTRIN_TESTS)
add_definitions(-DTEST_WASM_INTRIN)
ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../ts/include")
ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../imgcodecs/include")
ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../videoio/include")
ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../highgui/include")
ocv_add_executable(${the_module} ${bindings_cpp} "${CMAKE_CURRENT_SOURCE_DIR}/../ts/src/ts_gtest.cpp")
else()
ocv_add_executable(${the_module} ${bindings_cpp})
endif()
set_target_properties(${the_module} PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes")
set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} --memory-init-file 0 -s TOTAL_MEMORY=134217728 -s ALLOW_MEMORY_GROWTH=1")
set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} --memory-init-file 0 -s TOTAL_MEMORY=128MB -s WASM_MEM_MAX=1GB -s ALLOW_MEMORY_GROWTH=1")
set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s MODULARIZE=1 -s SINGLE_FILE=1")
set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s EXPORT_NAME=\"'cv'\" -s DEMANGLE_SUPPORT=1")
set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s FORCE_FILESYSTEM=1 --use-preload-plugins --bind --post-js ${JS_HELPER} -Wno-missing-prototypes")
@@ -142,3 +152,26 @@ list(APPEND opencv_test_js_file_deps "${test_data_path}" "${opencv_test_js_bin_d
add_custom_target(${PROJECT_NAME}_test ALL
DEPENDS ${OCV_JS_PATH} ${opencv_test_js_file_deps})
# perf
set(opencv_perf_js_bin_dir "${EXECUTABLE_OUTPUT_PATH}/perf")
set(perf_dir ${CMAKE_CURRENT_SOURCE_DIR}/perf)
set(opencv_perf_js_file_deps "")
# make sure the build directory exists
file(MAKE_DIRECTORY "${opencv_perf_js_bin_dir}")
# gather and copy specific files for js perf
file(GLOB_RECURSE perf_files RELATIVE "${perf_dir}" "${perf_dir}/*")
foreach(f ${perf_files})
add_custom_command(OUTPUT "${opencv_perf_js_bin_dir}/${f}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${perf_dir}/${f}" "${opencv_perf_js_bin_dir}/${f}"
DEPENDS "${perf_dir}/${f}"
COMMENT "Copying ${f}"
)
list(APPEND opencv_perf_js_file_deps "${perf_dir}/${f}" "${opencv_perf_js_bin_dir}/${f}")
endforeach()
add_custom_target(${PROJECT_NAME}_perf ALL
DEPENDS ${OCV_JS_PATH} ${opencv_perf_js_file_deps})
+35
View File
@@ -0,0 +1,35 @@
# OpenCV.js Performance Test
## Node.js Version
### Prerequisites
1. node.js, npm: Make sure you have installed these beforehand with the system package manager.
2. Benchmark.js: Make sure you have installed Benchmark.js by npm before use. Please run `npm install` in the directory `<build_dir>/bin/perf`.
### How to Use
For example, if you want to test the performance of cvtColor, please run `perf_cvtcolor.js` by node in terminal:
```sh
node perf_cvtcolor.js
```
All tests of cvtColor will be run by above command.
If you just want to run one specific case, please use `--test_param_filter="()"` flag, like:
```sh
node perf_cvtcolor.js --test_param_filter="(1920x1080, COLOR_BGR2GRAY)"
```
## Browser Version
### How to Use
To run performance tests, please launch a local web server in <build_dir>/bin folder. For example, node http-server which serves on localhost:8080.
Navigate the web browser to the kernel page you want to test, like http://localhost:8080/perf/imgproc/cvtcolor.html.
You can input the paramater, and then click the `Run` button to run the specific case, or it will run all the cases.
+18
View File
@@ -0,0 +1,18 @@
if (typeof window === 'undefined') {
var cv = require("../opencv");
}
const cvSize = {
szODD: new cv.Size(127, 61),
szQVGA: new cv.Size(320, 240),
szVGA: new cv.Size(640, 480),
szqHD: new cv.Size(960, 540),
sz720p: new cv.Size(1280, 720),
sz1080p: new cv.Size(1920, 1080),
sz130x60: new cv.Size(130, 60),
sz213x120: new cv.Size(120 * 1280 / 720, 120),
}
if (typeof window === 'undefined') {
exports.cvSize = cvSize;
}
+19
View File
@@ -0,0 +1,19 @@
{
"name": "opencv_js_perf",
"description": "Perfermance tests for opencv js bindings",
"version": "1.0.0",
"dependencies" : {
"benchmark" : "latest"
},
"repository": {
"type": "git",
"url": "https://github.com/opencv/opencv.git"
},
"keywords": [],
"author": "",
"license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/opencv/opencv/issues"
},
"homepage": "https://github.com/opencv/opencv"
}
+59
View File
@@ -0,0 +1,59 @@
var fillGradient = function(cv, img, delta=5) {
let ch = img.channels();
console.assert(!img.empty() && img.depth() == cv.CV_8U && ch <= 4);
let n = 255 / delta;
for(let r = 0; r < img.rows; ++r) {
let kR = r % (2*n);
let valR = (kR<=n) ? delta*kR : delta*(2*n-kR);
for(let c = 0; c < img.cols; ++c) {
let kC = c % (2*n);
let valC = (kC<=n) ? delta*kC : delta*(2*n-kC);
let vals = [valR, valC, 200*r/img.rows, 255];
let p = img.ptr(r, c);
for(let i = 0; i < ch; ++i) p[i] = vals[i];
}
}
}
var cvtStr2cvSize = function(strSize) {
let size;
switch(strSize) {
case "127,61": size = cvSize.szODD;break;
case '320,240': size = cvSize.szQVGA;break;
case '640,480': size = cvSize.szVGA;break;
case '960,540': size = cvSize.szqHD;break;
case '1280,720': size = cvSize.sz720p;break;
case '1920,1080': size = cvSize.sz1080p;break;
case "130,60": size = cvSize.sz130x60;break;
case '213,120': size = cvSize.sz213x120;break;
default: console.error("unsupported size for this case");
}
return size;
}
var combine = function() {
let result = [[]];
for (let i = 0; i < arguments.length; ++i) {
result = permute(result, arguments[i]);
}
return result;
}
function permute (source, target) {
let result = [];
for (let i = 0; i < source.length; ++i) {
for (let j = 0; j < target.length; ++j) {
let tmp = source[i].slice();
tmp.push(target[j]);
result.push(tmp);
}
}
return result;
}
if (typeof window === 'undefined') {
exports.fillGradient = fillGradient;
exports.cvtStr2cvSize = cvtStr2cvSize;
exports.combine = combine;
}
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OpenCV.js Performance Test</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
body {
font-size: 13px;
}
.top-margin {
margin-top:10px;
}
h1, h4 {
margin: 24px 0 0;
}
h1 {
font-size: 2.0em;
}
h4 {
font-size: 1.2em;
}
pre {
font-family: 'Consolas', 'Monaco', monospace, serif;
font-size: 12px;
tab-size: 2;
}
input[type=checkbox] {
vertical-align: middle;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="row">
<div class="col-12">
<h1>OpenCV.js Performance Test</h1>
<div>
<h4>Modules</h4>
<h7>Image Processing</h7>
</div>
<div>
<h4>Kernels</h4>
<h7>CvtColor</h7>
</div>
<div>
<h4>Parameters Filter</h4>
<input type="text" id="params" min="1" size="40" placeholder="default: run all the case"/> for example: (640x480,COLOR_RGBA2GRAY)
</div>
<div class='row labels-wrapper' id='labelitem'></div>
<div class="row top-margin">
</div>
<div>
<button type="button" id="runButton" class="btn btn-primary disabled" disabled="disabled">Loading</button>
(It will take several minutes)</div>
<div class="row top-margin">
</div>
<div>
<pre id="log"></pre>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.4/benchmark.js"></script>
<script src="../../opencv.js" type="text/javascript"></script>
<script src="../base.js"></script>
<script src="../perf_helpfunc.js"></script>
<script src="./perf_cvtcolor.js"></script>
</body>
</html>
@@ -0,0 +1,572 @@
const isNodeJs = (typeof window) === 'undefined'? true : false;
if (isNodeJs) {
var Benchmark = require('benchmark');
var cv = require('../../opencv');
var HelpFunc = require('../perf_helpfunc');
var Base = require('../base');
} else {
var paramsElement = document.getElementById('params');
var runButton = document.getElementById('runButton');
var logElement = document.getElementById('log');
}
cv.onRuntimeInitialized = () => {
console.log('opencv.js loaded');
if (isNodeJs) {
global.cv = cv;
global.combine = HelpFunc.combine;
global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize;
global.cvSize = Base.cvSize;
} else {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
let totalCaseNum, currentCaseId;
//extra color conversions supported implicitly
{
cv.CX_BGRA2HLS = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2HLS,
cv.CX_BGRA2HLS_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2HLS_FULL,
cv.CX_BGRA2HSV = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2HSV,
cv.CX_BGRA2HSV_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2HSV_FULL,
cv.CX_BGRA2Lab = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2Lab,
cv.CX_BGRA2Luv = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2Luv,
cv.CX_BGRA2XYZ = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2XYZ,
cv.CX_BGRA2YCrCb = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2YCrCb,
cv.CX_BGRA2YUV = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2YUV,
cv.CX_HLS2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_HLS2BGR,
cv.CX_HLS2BGRA_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_HLS2BGR_FULL,
cv.CX_HLS2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_HLS2RGB,
cv.CX_HLS2RGBA_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_HLS2RGB_FULL,
cv.CX_HSV2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_HSV2BGR,
cv.CX_HSV2BGRA_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_HSV2BGR_FULL,
cv.CX_HSV2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_HSV2RGB,
cv.CX_HSV2RGBA_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_HSV2RGB_FULL,
cv.CX_Lab2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Lab2BGR,
cv.CX_Lab2LBGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Lab2LBGR,
cv.CX_Lab2LRGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Lab2LRGB,
cv.CX_Lab2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Lab2RGB,
cv.CX_LBGRA2Lab = cv.COLOR_COLORCVT_MAX + cv.COLOR_LBGR2Lab,
cv.CX_LBGRA2Luv = cv.COLOR_COLORCVT_MAX + cv.COLOR_LBGR2Luv,
cv.CX_LRGBA2Lab = cv.COLOR_COLORCVT_MAX + cv.COLOR_LRGB2Lab,
cv.CX_LRGBA2Luv = cv.COLOR_COLORCVT_MAX + cv.COLOR_LRGB2Luv,
cv.CX_Luv2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Luv2BGR,
cv.CX_Luv2LBGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Luv2LBGR,
cv.CX_Luv2LRGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Luv2LRGB,
cv.CX_Luv2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Luv2RGB,
cv.CX_RGBA2HLS = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2HLS,
cv.CX_RGBA2HLS_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2HLS_FULL,
cv.CX_RGBA2HSV = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2HSV,
cv.CX_RGBA2HSV_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2HSV_FULL,
cv.CX_RGBA2Lab = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2Lab,
cv.CX_RGBA2Luv = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2Luv,
cv.CX_RGBA2XYZ = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2XYZ,
cv.CX_RGBA2YCrCb = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2YCrCb,
cv.CX_RGBA2YUV = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2YUV,
cv.CX_XYZ2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_XYZ2BGR,
cv.CX_XYZ2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_XYZ2RGB,
cv.CX_YCrCb2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_YCrCb2BGR,
cv.CX_YCrCb2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_YCrCb2RGB,
cv.CX_YUV2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_YUV2BGR,
cv.CX_YUV2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_YUV2RGB
};
const CvtMode = [
"COLOR_BGR2BGR555", "COLOR_BGR2BGR565", "COLOR_BGR2BGRA", "COLOR_BGR2GRAY",
"COLOR_BGR2HLS", "COLOR_BGR2HLS_FULL", "COLOR_BGR2HSV", "COLOR_BGR2HSV_FULL",
"COLOR_BGR2Lab", "COLOR_BGR2Luv", "COLOR_BGR2RGB", "COLOR_BGR2RGBA", "COLOR_BGR2XYZ",
"COLOR_BGR2YCrCb", "COLOR_BGR2YUV", "COLOR_BGR5552BGR", "COLOR_BGR5552BGRA",
"COLOR_BGR5552GRAY", "COLOR_BGR5552RGB", "COLOR_BGR5552RGBA", "COLOR_BGR5652BGR",
"COLOR_BGR5652BGRA", "COLOR_BGR5652GRAY", "COLOR_BGR5652RGB", "COLOR_BGR5652RGBA",
"COLOR_BGRA2BGR", "COLOR_BGRA2BGR555", "COLOR_BGRA2BGR565", "COLOR_BGRA2GRAY", "COLOR_BGRA2RGBA",
"CX_BGRA2HLS", "CX_BGRA2HLS_FULL", "CX_BGRA2HSV", "CX_BGRA2HSV_FULL",
"CX_BGRA2Lab", "CX_BGRA2Luv", "CX_BGRA2XYZ",
"CX_BGRA2YCrCb", "CX_BGRA2YUV",
"COLOR_GRAY2BGR", "COLOR_GRAY2BGR555", "COLOR_GRAY2BGR565", "COLOR_GRAY2BGRA",
"COLOR_HLS2BGR", "COLOR_HLS2BGR_FULL", "COLOR_HLS2RGB", "COLOR_HLS2RGB_FULL",
"CX_HLS2BGRA", "CX_HLS2BGRA_FULL", "CX_HLS2RGBA", "CX_HLS2RGBA_FULL",
"COLOR_HSV2BGR", "COLOR_HSV2BGR_FULL", "COLOR_HSV2RGB", "COLOR_HSV2RGB_FULL",
"CX_HSV2BGRA", "CX_HSV2BGRA_FULL", "CX_HSV2RGBA", "CX_HSV2RGBA_FULL",
"COLOR_Lab2BGR", "COLOR_Lab2LBGR", "COLOR_Lab2LRGB", "COLOR_Lab2RGB",
"CX_Lab2BGRA", "CX_Lab2LBGRA", "CX_Lab2LRGBA", "CX_Lab2RGBA",
"COLOR_LBGR2Lab", "COLOR_LBGR2Luv", "COLOR_LRGB2Lab", "COLOR_LRGB2Luv",
"CX_LBGRA2Lab", "CX_LBGRA2Luv", "CX_LRGBA2Lab", "CX_LRGBA2Luv",
"COLOR_Luv2BGR", "COLOR_Luv2LBGR", "COLOR_Luv2LRGB", "COLOR_Luv2RGB",
"CX_Luv2BGRA", "CX_Luv2LBGRA", "CX_Luv2LRGBA", "CX_Luv2RGBA",
"COLOR_RGB2BGR555", "COLOR_RGB2BGR565", "COLOR_RGB2GRAY",
"COLOR_RGB2HLS", "COLOR_RGB2HLS_FULL", "COLOR_RGB2HSV", "COLOR_RGB2HSV_FULL",
"COLOR_RGB2Lab", "COLOR_RGB2Luv", "COLOR_RGB2XYZ", "COLOR_RGB2YCrCb", "COLOR_RGB2YUV",
"COLOR_RGBA2BGR", "COLOR_RGBA2BGR555", "COLOR_RGBA2BGR565", "COLOR_RGBA2GRAY",
"CX_RGBA2HLS", "CX_RGBA2HLS_FULL", "CX_RGBA2HSV", "CX_RGBA2HSV_FULL",
"CX_RGBA2Lab", "CX_RGBA2Luv", "CX_RGBA2XYZ",
"CX_RGBA2YCrCb", "CX_RGBA2YUV",
"COLOR_XYZ2BGR", "COLOR_XYZ2RGB", "CX_XYZ2BGRA", "CX_XYZ2RGBA",
"COLOR_YCrCb2BGR", "COLOR_YCrCb2RGB", "CX_YCrCb2BGRA", "CX_YCrCb2RGBA",
"COLOR_YUV2BGR", "COLOR_YUV2RGB", "CX_YUV2BGRA", "CX_YUV2RGBA"
];
const CvtModeSize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p];
const combiCvtMode = combine(CvtModeSize, CvtMode);
// didn't support 16u and 32f perf tests according to
// https://github.com/opencv/opencv/commit/4e679e1cc5b075ec006b29a58b4fe117523fba1d
const CvtMode16U = [
"COLOR_BGR2BGRA", "COLOR_BGR2GRAY",
"COLOR_BGR2RGB", "COLOR_BGR2RGBA", "COLOR_BGR2XYZ",
"COLOR_BGR2YCrCb", "COLOR_BGR2YUV",
"COLOR_BGRA2BGR", "COLOR_BGRA2GRAY", "COLOR_BGRA2RGBA",
"CX_BGRA2XYZ",
"CX_BGRA2YCrCb", "CX_BGRA2YUV",
"COLOR_GRAY2BGR", "COLOR_GRAY2BGRA",
"COLOR_RGB2GRAY",
"COLOR_RGB2XYZ", "COLOR_RGB2YCrCb", "COLOR_RGB2YUV",
"COLOR_RGBA2BGR", "COLOR_RGBA2GRAY",
"CX_RGBA2XYZ",
"CX_RGBA2YCrCb", "CX_RGBA2YUV",
"COLOR_XYZ2BGR", "COLOR_XYZ2RGB", "CX_XYZ2BGRA", "CX_XYZ2RGBA",
"COLOR_YCrCb2BGR", "COLOR_YCrCb2RGB", "CX_YCrCb2BGRA", "CX_YCrCb2RGBA",
"COLOR_YUV2BGR", "COLOR_YUV2RGB", "CX_YUV2BGRA", "CX_YUV2RGBA"
];
const CvtMode16USize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p];
const combiCvtMode16U = combine(CvtMode16USize, CvtMode16U);
const CvtMode32F = [
"COLOR_BGR2BGRA", "COLOR_BGR2GRAY",
"COLOR_BGR2HLS", "COLOR_BGR2HLS_FULL", "COLOR_BGR2HSV", "COLOR_BGR2HSV_FULL",
"COLOR_BGR2Lab", "COLOR_BGR2Luv", "COLOR_BGR2RGB", "COLOR_BGR2RGBA", "COLOR_BGR2XYZ",
"COLOR_BGR2YCrCb", "COLOR_BGR2YUV",
"COLOR_BGRA2BGR", "COLOR_BGRA2GRAY", "COLOR_BGRA2RGBA",
"CX_BGRA2HLS", "CX_BGRA2HLS_FULL", "CX_BGRA2HSV", "CX_BGRA2HSV_FULL",
"CX_BGRA2Lab", "CX_BGRA2Luv", "CX_BGRA2XYZ",
"CX_BGRA2YCrCb", "CX_BGRA2YUV",
"COLOR_GRAY2BGR", "COLOR_GRAY2BGRA",
"COLOR_HLS2BGR", "COLOR_HLS2BGR_FULL", "COLOR_HLS2RGB", "COLOR_HLS2RGB_FULL",
"CX_HLS2BGRA", "CX_HLS2BGRA_FULL", "CX_HLS2RGBA", "CX_HLS2RGBA_FULL",
"COLOR_HSV2BGR", "COLOR_HSV2BGR_FULL", "COLOR_HSV2RGB", "COLOR_HSV2RGB_FULL",
"CX_HSV2BGRA", "CX_HSV2BGRA_FULL", "CX_HSV2RGBA", "CX_HSV2RGBA_FULL",
"COLOR_Lab2BGR", "COLOR_Lab2LBGR", "COLOR_Lab2LRGB", "COLOR_Lab2RGB",
"CX_Lab2BGRA", "CX_Lab2LBGRA", "CX_Lab2LRGBA", "CX_Lab2RGBA",
"COLOR_LBGR2Lab", "COLOR_LBGR2Luv", "COLOR_LRGB2Lab", "COLOR_LRGB2Luv",
"CX_LBGRA2Lab", "CX_LBGRA2Luv", "CX_LRGBA2Lab", "CX_LRGBA2Luv",
"COLOR_Luv2BGR", "COLOR_Luv2LBGR", "COLOR_Luv2LRGB", "COLOR_Luv2RGB",
"CX_Luv2BGRA", "CX_Luv2LBGRA", "CX_Luv2LRGBA", "CX_Luv2RGBA",
"COLOR_RGB2GRAY",
"COLOR_RGB2HLS", "COLOR_RGB2HLS_FULL", "COLOR_RGB2HSV", "COLOR_RGB2HSV_FULL",
"COLOR_RGB2Lab", "COLOR_RGB2Luv", "COLOR_RGB2XYZ", "COLOR_RGB2YCrCb", "COLOR_RGB2YUV",
"COLOR_RGBA2BGR", "COLOR_RGBA2GRAY",
"CX_RGBA2HLS", "CX_RGBA2HLS_FULL", "CX_RGBA2HSV", "CX_RGBA2HSV_FULL",
"CX_RGBA2Lab", "CX_RGBA2Luv", "CX_RGBA2XYZ",
"CX_RGBA2YCrCb", "CX_RGBA2YUV",
"COLOR_XYZ2BGR", "COLOR_XYZ2RGB", "CX_XYZ2BGRA", "CX_XYZ2RGBA",
"COLOR_YCrCb2BGR", "COLOR_YCrCb2RGB", "CX_YCrCb2BGRA", "CX_YCrCb2RGBA",
"COLOR_YUV2BGR", "COLOR_YUV2RGB", "CX_YUV2BGRA", "CX_YUV2RGBA"
];
const CvtMode32FSize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p];
const combiCvtMode32F = combine(CvtMode32FSize, CvtMode32F);
const CvtModeBayer = [
"COLOR_BayerBG2BGR", "COLOR_BayerBG2BGRA", "COLOR_BayerBG2BGR_VNG", "COLOR_BayerBG2GRAY",
"COLOR_BayerGB2BGR", "COLOR_BayerGB2BGRA", "COLOR_BayerGB2BGR_VNG", "COLOR_BayerGB2GRAY",
"COLOR_BayerGR2BGR", "COLOR_BayerGR2BGRA", "COLOR_BayerGR2BGR_VNG", "COLOR_BayerGR2GRAY",
"COLOR_BayerRG2BGR", "COLOR_BayerRG2BGRA", "COLOR_BayerRG2BGR_VNG", "COLOR_BayerRG2GRAY"
];
const CvtModeBayerSize = [cvSize.szODD, cvSize.szVGA];
const combiCvtModeBayer = combine(CvtModeBayerSize, CvtModeBayer);
const CvtMode2 = [
"COLOR_YUV2BGR_NV12", "COLOR_YUV2BGRA_NV12", "COLOR_YUV2RGB_NV12", "COLOR_YUV2RGBA_NV12", "COLOR_YUV2BGR_NV21", "COLOR_YUV2BGRA_NV21", "COLOR_YUV2RGB_NV21", "COLOR_YUV2RGBA_NV21",
"COLOR_YUV2BGR_YV12", "COLOR_YUV2BGRA_YV12", "COLOR_YUV2RGB_YV12", "COLOR_YUV2RGBA_YV12", "COLOR_YUV2BGR_IYUV", "COLOR_YUV2BGRA_IYUV", "COLOR_YUV2RGB_IYUV", "COLOR_YUV2RGBA_IYUV",
"COLOR_YUV2GRAY_420", "COLOR_YUV2RGB_UYVY", "COLOR_YUV2BGR_UYVY", "COLOR_YUV2RGBA_UYVY", "COLOR_YUV2BGRA_UYVY", "COLOR_YUV2RGB_YUY2", "COLOR_YUV2BGR_YUY2", "COLOR_YUV2RGB_YVYU",
"COLOR_YUV2BGR_YVYU", "COLOR_YUV2RGBA_YUY2", "COLOR_YUV2BGRA_YUY2", "COLOR_YUV2RGBA_YVYU", "COLOR_YUV2BGRA_YVYU"
];
const CvtMode2Size = [cvSize.szVGA, cvSize.sz1080p, cvSize.sz130x60];
const combiCvtMode2 = combine(CvtMode2Size, CvtMode2);
const CvtMode3 = [
"COLOR_RGB2YUV_IYUV", "COLOR_BGR2YUV_IYUV", "COLOR_RGBA2YUV_IYUV", "COLOR_BGRA2YUV_IYUV",
"COLOR_RGB2YUV_YV12", "COLOR_BGR2YUV_YV12", "COLOR_RGBA2YUV_YV12", "COLOR_BGRA2YUV_YV12"
];
const CvtMode3Size = [cvSize.szVGA, cvSize.sz720p, cvSize.sz1080p, cvSize.sz130x60];
const combiCvtMode3 = combine(CvtMode3Size, CvtMode3);
const EdgeAwareBayerMode = [
"COLOR_BayerBG2BGR_EA", "COLOR_BayerGB2BGR_EA", "COLOR_BayerRG2BGR_EA", "COLOR_BayerGR2BGR_EA"
];
const EdgeAwareBayerModeSize = [cvSize.szVGA, cvSize.sz720p, cvSize.sz1080p, cvSize.sz130x60];
const combiEdgeAwareBayer = combine(EdgeAwareBayerModeSize, EdgeAwareBayerMode);
// This function returns an array. The 1st element is the channel number of
// source mat and 2nd element is the channel number of destination mat.
function getConversionInfo(cvtMode) {
switch(cvtMode) {
case "COLOR_BayerBG2GRAY": case "COLOR_BayerGB2GRAY":
case "COLOR_BayerGR2GRAY": case "COLOR_BayerRG2GRAY":
case "COLOR_YUV2GRAY_420":
return [1, 1];
case "COLOR_GRAY2BGR555": case "COLOR_GRAY2BGR565":
return [1, 2];
case "COLOR_BayerBG2BGR": case "COLOR_BayerBG2BGR_VNG":
case "COLOR_BayerGB2BGR": case "COLOR_BayerGB2BGR_VNG":
case "COLOR_BayerGR2BGR": case "COLOR_BayerGR2BGR_VNG":
case "COLOR_BayerRG2BGR": case "COLOR_BayerRG2BGR_VNG":
case "COLOR_GRAY2BGR":
case "COLOR_YUV2BGR_NV12": case "COLOR_YUV2RGB_NV12":
case "COLOR_YUV2BGR_NV21": case "COLOR_YUV2RGB_NV21":
case "COLOR_YUV2BGR_YV12": case "COLOR_YUV2RGB_YV12":
case "COLOR_YUV2BGR_IYUV": case "COLOR_YUV2RGB_IYUV":
return [1, 3];
case "COLOR_GRAY2BGRA":
case "COLOR_YUV2BGRA_NV12": case "COLOR_YUV2RGBA_NV12":
case "COLOR_YUV2BGRA_NV21": case "COLOR_YUV2RGBA_NV21":
case "COLOR_YUV2BGRA_YV12": case "COLOR_YUV2RGBA_YV12":
case "COLOR_YUV2BGRA_IYUV": case "COLOR_YUV2RGBA_IYUV":
case "COLOR_BayerBG2BGRA": case "COLOR_BayerGB2BGRA":
case "COLOR_BayerGR2BGRA": case "COLOR_BayerRG2BGRA":
return [1, 4];
case "COLOR_BGR5552GRAY": case "COLOR_BGR5652GRAY":
return [2, 1];
case "COLOR_BGR5552BGR": case "COLOR_BGR5552RGB":
case "COLOR_BGR5652BGR": case "COLOR_BGR5652RGB":
case "COLOR_YUV2RGB_UYVY": case "COLOR_YUV2BGR_UYVY":
case "COLOR_YUV2RGB_YUY2": case "COLOR_YUV2BGR_YUY2":
case "COLOR_YUV2RGB_YVYU": case "COLOR_YUV2BGR_YVYU":
return [2, 3];
case "COLOR_BGR5552BGRA": case "COLOR_BGR5552RGBA":
case "COLOR_BGR5652BGRA": case "COLOR_BGR5652RGBA":
case "COLOR_YUV2RGBA_UYVY": case "COLOR_YUV2BGRA_UYVY":
case "COLOR_YUV2RGBA_YUY2": case "COLOR_YUV2BGRA_YUY2":
case "COLOR_YUV2RGBA_YVYU": case "COLOR_YUV2BGRA_YVYU":
return [2, 4];
case "COLOR_BGR2GRAY": case "COLOR_RGB2GRAY":
case "COLOR_RGB2YUV_IYUV": case "COLOR_RGB2YUV_YV12":
case "COLOR_BGR2YUV_IYUV": case "COLOR_BGR2YUV_YV12":
return [3, 1];
case "COLOR_BGR2BGR555": case "COLOR_BGR2BGR565":
case "COLOR_RGB2BGR555": case "COLOR_RGB2BGR565":
return [3, 2];
case "COLOR_BGR2HLS": case "COLOR_BGR2HLS_FULL":
case "COLOR_BGR2HSV": case "COLOR_BGR2HSV_FULL":
case "COLOR_BGR2Lab": case "COLOR_BGR2Luv":
case "COLOR_BGR2RGB": case "COLOR_BGR2XYZ":
case "COLOR_BGR2YCrCb": case "COLOR_BGR2YUV":
case "COLOR_HLS2BGR": case "COLOR_HLS2BGR_FULL":
case "COLOR_HLS2RGB": case "COLOR_HLS2RGB_FULL":
case "COLOR_HSV2BGR": case "COLOR_HSV2BGR_FULL":
case "COLOR_HSV2RGB": case "COLOR_HSV2RGB_FULL":
case "COLOR_Lab2BGR": case "COLOR_Lab2LBGR":
case "COLOR_Lab2LRGB": case "COLOR_Lab2RGB":
case "COLOR_LBGR2Lab": case "COLOR_LBGR2Luv":
case "COLOR_LRGB2Lab": case "COLOR_LRGB2Luv":
case "COLOR_Luv2BGR": case "COLOR_Luv2LBGR":
case "COLOR_Luv2LRGB": case "COLOR_Luv2RGB":
case "COLOR_RGB2HLS": case "COLOR_RGB2HLS_FULL":
case "COLOR_RGB2HSV": case "COLOR_RGB2HSV_FULL":
case "COLOR_RGB2Lab": case "COLOR_RGB2Luv":
case "COLOR_RGB2XYZ": case "COLOR_RGB2YCrCb":
case "COLOR_RGB2YUV": case "COLOR_XYZ2BGR":
case "COLOR_XYZ2RGB": case "COLOR_YCrCb2BGR":
case "COLOR_YCrCb2RGB": case "COLOR_YUV2BGR":
case "COLOR_YUV2RGB":
return [3, 3];
case "COLOR_BGR2BGRA": case "COLOR_BGR2RGBA":
case "CX_HLS2BGRA": case "CX_HLS2BGRA_FULL":
case "CX_HLS2RGBA": case "CX_HLS2RGBA_FULL":
case "CX_HSV2BGRA": case "CX_HSV2BGRA_FULL":
case "CX_HSV2RGBA": case "CX_HSV2RGBA_FULL":
case "CX_Lab2BGRA": case "CX_Lab2LBGRA":
case "CX_Lab2LRGBA": case "CX_Lab2RGBA":
case "CX_Luv2BGRA": case "CX_Luv2LBGRA":
case "CX_Luv2LRGBA": case "CX_Luv2RGBA":
case "CX_XYZ2BGRA": case "CX_XYZ2RGBA":
case "CX_YCrCb2BGRA": case "CX_YCrCb2RGBA":
case "CX_YUV2BGRA": case "CX_YUV2RGBA":
return [3, 4];
case "COLOR_BGRA2GRAY": case "COLOR_RGBA2GRAY":
case "COLOR_RGBA2YUV_IYUV": case "COLOR_RGBA2YUV_YV12":
case "COLOR_BGRA2YUV_IYUV": case "COLOR_BGRA2YUV_YV12":
return [4, 1];
case "COLOR_BGRA2BGR555": case "COLOR_BGRA2BGR565":
case "COLOR_RGBA2BGR555": case "COLOR_RGBA2BGR565":
return [4, 2];
case "COLOR_BGRA2BGR": case "CX_BGRA2HLS":
case "CX_BGRA2HLS_FULL": case "CX_BGRA2HSV":
case "CX_BGRA2HSV_FULL": case "CX_BGRA2Lab":
case "CX_BGRA2Luv": case "CX_BGRA2XYZ":
case "CX_BGRA2YCrCb": case "CX_BGRA2YUV":
case "CX_LBGRA2Lab": case "CX_LBGRA2Luv":
case "CX_LRGBA2Lab": case "CX_LRGBA2Luv":
case "COLOR_RGBA2BGR": case "CX_RGBA2HLS":
case "CX_RGBA2HLS_FULL": case "CX_RGBA2HSV":
case "CX_RGBA2HSV_FULL": case "CX_RGBA2Lab":
case "CX_RGBA2Luv": case "CX_RGBA2XYZ":
case "CX_RGBA2YCrCb": case "CX_RGBA2YUV":
return [4, 3];
case "COLOR_BGRA2RGBA":
return [4, 4];
default:
console.error("Unknown conversion type");
break;
};
return [0, 0];
}
function getMatType(chPair) {
let dataType = "8U"; // now just support "8U" data type, we can set it as a param to extend the data type later.
let mat1Type, mat2Type;
if (chPair[0] === 0) {
mat1Type = `CV_${dataType}C`;
} else {
mat1Type = `CV_${dataType}C${chPair[0].toString()}`;
}
if (chPair[1] === 0) {
mat2Type = `CV_${dataType}C`;
} else {
mat2Type = `CV_${dataType}C${chPair[1].toString()}`;
}
return [mat1Type, mat2Type];
}
function addCvtColorCase(suite) {
suite.add('cvtColor', function() {
cv.cvtColor(mat1, mat2, mode, 0);
}, {
'setup': function() {
let size = this.params.size;
let matType = this.params.matType;
let mode = cv[this.params.mode]%cv.COLOR_COLORCVT_MAX;
let mat1 = new cv.Mat(size[1], size[0], cv[matType[0]]);
let mat2 = new cv.Mat(size[1], size[0], cv[matType[1]]);
},
'teardown': function() {
mat1.delete();
mat2.delete();
}
});
}
function addCvtModeCase(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function addCvtModeBayerCase(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function addCvtMode2Case(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height+size.height/2];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function addCvtMode3Case(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height+size.height/2];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function addEdgeAwareBayerModeCase(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function decodeParams2Case(suite, params) {
let sizeStr = (params.match(/[0-9]+/g) || []).slice(0, 2).toString();
let mode = (params.match(/CX\_[A-z]+2[A-z]+/) || params.match(/COLOR\_[A-z]+2[A-z]+/) || []).toString();
let size = cvtStr2cvSize(sizeStr);
// check if the params match and add case
for (let i = 0; i < combinations.length; ++i) {
let combination = combinations[i];
for (let j = 0; j < combination.length; ++j) {
if (size === combination[j][0] && mode === combination[j][1]) {
cvtFunc[i](suite, [combination[j]]);
}
}
}
}
function log(message) {
console.log(message);
if (!isNodeJs) {
logElement.innerHTML += `\n${'\t' + message}`;
}
}
function setBenchmarkSuite(suite) {
suite
// add listeners
.on('cycle', function(event) {
++currentCaseId;
let params = event.target.params;
let mode = params.mode;
let size = params.size;
log(`=== ${event.target.name} ${currentCaseId} ===`);
log(`params: (${parseInt(size[0])}x${parseInt(size[1])}, ${mode})`);
log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms');
log('mean time:' +String(event.target.stats.mean*1000)+' ms');
log('stddev time:' +String(event.target.stats.deviation*1000)+' ms');
log(String(event.target));
})
.on('error', function(event) { log(`test case ${event.target.name} failed`); })
.on('complete', function(event) {
log(`\n ###################################`)
log(`Finished testing ${event.currentTarget.length} cases \n`);
if (!isNodeJs) {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
});
}
function genBenchmarkCase(paramsContent) {
let suite = new Benchmark.Suite;
totalCaseNum = 0;
currentCaseId = 0;
if (/\([0-9]+x[0-9]+,[\ ]*\w+\)/g.test(paramsContent.toString())) {
let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+\)/g)[0];
decodeParams2Case(suite, params);
} else {
log("no filter or getting invalid params, run all the cases");
addCvtModeCase(suite, combiCvtMode);
addCvtModeBayerCase(suite, combiCvtModeBayer);
addCvtMode2Case(suite, combiCvtMode2);
addCvtMode3Case(suite, combiCvtMode3);
}
setBenchmarkSuite(suite);
log(`Running ${totalCaseNum} tests from CvtColor`);
suite.run({ 'async': true }); // run the benchmark
}
// init
let cvtFunc = [addCvtModeCase, addCvtModeBayerCase, addCvtMode2Case, addCvtMode3Case];//, addEdgeAwareBayerModeCase];
let combinations = [combiCvtMode, combiCvtModeBayer, combiCvtMode2, combiCvtMode3];//, combiEdgeAwareBayer];
// set test filter params
if (isNodeJs) {
const args = process.argv.slice(2);
let paramsContent = '';
if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+\)/g.test(args.toString())) {
paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+\)/g)[0];
}
genBenchmarkCase(paramsContent);
} else {
runButton.onclick = function() {
let paramsContent = paramsElement.value;
genBenchmarkCase(paramsContent);
if (totalCaseNum !== 0) {
runButton.setAttribute("disabled", "disabled");
runButton.setAttribute('class', 'btn btn-primary disabled');
runButton.innerHTML = "Running";
}
}
}
};
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OpenCV.js Performance Test</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
body {
font-size: 13px;
}
.top-margin {
margin-top:10px;
}
h1, h4 {
margin: 24px 0 0;
}
h1 {
font-size: 2.0em;
}
h4 {
font-size: 1.2em;
}
pre {
font-family: 'Consolas', 'Monaco', monospace, serif;
font-size: 12px;
tab-size: 2;
}
input[type=checkbox] {
vertical-align: middle;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="row">
<div class="col-12">
<h1>OpenCV.js Performance Test</h1>
<div>
<h4>Modules</h4>
<h7>Image Processing</h7>
</div>
<div>
<h4>Kernels</h4>
<h7>Resize</h7>
</div>
<div>
<h4>Parameters Filter</h4>
<input type="text" id="params" min="1" size="40" placeholder="default: run all the case"/> for example: (CV_8UC1,640x480,960x540)
</div>
<div class='row labels-wrapper' id='labelitem'></div>
<div class="row top-margin">
</div>
<div>
<button type="button" id="runButton" class="btn btn-primary disabled" disabled="disabled">Loading</button>
(It will take several minutes)</div>
<div class="row top-margin">
</div>
<div>
<pre id="log"></pre>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.4/benchmark.js"></script>
<script src="../../opencv.js" type="text/javascript"></script>
<script src="../base.js"></script>
<script src="../perf_helpfunc.js"></script>
<script src="./perf_resize.js"></script>
</body>
</html>
+262
View File
@@ -0,0 +1,262 @@
const isNodeJs = (typeof window) === 'undefined'? true : false;
if (isNodeJs) {
var Benchmark = require('benchmark');
var cv = require('../../opencv');
var HelpFunc = require('../perf_helpfunc');
var Base = require('../base');
} else {
var paramsElement = document.getElementById('params');
var runButton = document.getElementById('runButton');
var logElement = document.getElementById('log');
}
cv.onRuntimeInitialized = () => {
console.log('opencv.js loaded');
if (isNodeJs) {
global.cv = cv;
global.combine = HelpFunc.combine;
global.fillGradient = HelpFunc.fillGradient;
global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize;
global.cvSize = Base.cvSize;
} else {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
let totalCaseNum, currentCaseId;
const matTypesUpLinear = ['CV_8UC1', 'CV_8UC2', 'CV_8UC3', 'CV_8UC4'];
const size1UpLinear = [cvSize.szVGA];
const size2UpLinear = [cvSize.szqHD, cvSize.sz720p];
const combiUpLinear = combine(matTypesUpLinear, size1UpLinear, size2UpLinear);
const combiDownLinear = [
['CV_8UC1', cvSize.szVGA, cvSize.szQVGA],
['CV_8UC2', cvSize.szVGA, cvSize.szQVGA],
['CV_8UC3', cvSize.szVGA, cvSize.szQVGA],
['CV_8UC4', cvSize.szVGA, cvSize.szQVGA],
['CV_8UC1', cvSize.szqHD, cvSize.szVGA],
['CV_8UC2', cvSize.szqHD, cvSize.szVGA],
['CV_8UC3', cvSize.szqHD, cvSize.szVGA],
['CV_8UC4', cvSize.szqHD, cvSize.szVGA],
['CV_8UC1', cvSize.sz720p, cvSize.sz213x120],// face detection min_face_size = 20%
['CV_8UC2', cvSize.sz720p, cvSize.sz213x120],// face detection min_face_size = 20%
['CV_8UC3', cvSize.sz720p, cvSize.sz213x120],// face detection min_face_size = 20%
['CV_8UC4', cvSize.sz720p, cvSize.sz213x120],// face detection min_face_size = 20%
['CV_8UC1', cvSize.sz720p, cvSize.szVGA],
['CV_8UC2', cvSize.sz720p, cvSize.szVGA],
['CV_8UC3', cvSize.sz720p, cvSize.szVGA],
['CV_8UC4', cvSize.sz720p, cvSize.szVGA],
['CV_8UC1', cvSize.sz720p, cvSize.szQVGA],
['CV_8UC2', cvSize.sz720p, cvSize.szQVGA],
['CV_8UC3', cvSize.sz720p, cvSize.szQVGA],
['CV_8UC4', cvSize.sz720p, cvSize.szQVGA]
];
const matTypesAreaFast = ['CV_8UC1', 'CV_8UC3', 'CV_8UC4', 'CV_16UC1', 'CV_16UC3', 'CV_16UC4'];
const sizesAreaFast = [cvSize.szVGA, cvSize.szqHD, cvSize.sz720p, cvSize.sz1080p];
const scalesAreaFast = [2];
const combiAreaFast = combine(matTypesAreaFast, sizesAreaFast, scalesAreaFast);
function addResizeUpLinearCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matType = combination[i][0];
let from = combination[i][1];
let to = combination[i][2];
suite.add('resize', function() {
cv.resize(src, dst, to, 0, 0, cv.INTER_LINEAR_EXACT);
}, {
'setup': function() {
let from = this.params.from;
let to = this.params.to;
let matType = cv[this.params.matType];
let src = new cv.Mat(from, matType);
let dst = new cv.Mat(to, matType);
fillGradient(cv, src);
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
from: from,
to: to,
matType: matType
};
}
}
function addResizeDownLinearCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matType = combination[i][0];
let from = combination[i][1];
let to = combination[i][2];
suite.add('resize', function() {
cv.resize(src, dst, to, 0, 0, cv.INTER_LINEAR_EXACT);
}, {
'setup': function() {
let from = this.params.from;
let to = this.params.to;
let matType = cv[this.params.matType];
let src = new cv.Mat(from, matType);
let dst = new cv.Mat(to, matType);
fillGradient(cv, src);
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
from: from,
to: to,
matType: matType
};
}
}
function addResizeAreaFastCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matType = combination[i][0];
let from = combination[i][1];
let scale = combination[i][2];
from.width = (Math.floor(from.width/scale))*scale;
from.height = (Math.floor(from.height/scale))*scale;
let to = {
width: from.width/scale,
height: from.height/scale}; // for params print
suite.add('resize', function() {
cv.resize(src, dst, dst.size(), 0, 0, cv.INTER_AREA);
}, {
'setup': function() {
let from = this.params.from;
let scale = this.params.scale;
let matType = cv[this.params.matType];
let src = new cv.Mat(from, matType);
let dst = new cv.Mat(from.height/scale, from.width/scale, matType);
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
from: from,
scale: scale,
matType: matType
};
}
}
function decodeParams2Case(suite, params) {
let sizeString = (params.match(/[0-9]+x[0-9]+/g) || []).slice(0, 2).toString();
let sizes = (sizeString.match(/[0-9]+/g) || []);
let size1Str = sizes.slice(0, 2).toString();
let size2Str = sizes.slice(2, 5).toString();
let matType = (params.match(/CV\_[0-9]+[A-z][A-z][0-9]/) || []).toString();
let size1 = cvtStr2cvSize(size1Str);
let size2 = cvtStr2cvSize(size2Str);
// check if the params match and add case
for (let i = 0; i < combinations.length; ++i) {
let combination = combinations[i];
for (let j = 0; j < combination.length; ++j) {
if (matType === combination[j][0] && size1 === combination[j][1] && size2 === combination[j][2]) {
resizeFunc[i](suite, [combination[j]]);
}
}
}
}
function log(message) {
console.log(message);
if (!isNodeJs) {
logElement.innerHTML += `\n${'\t'.repeat(1) + message}`;
}
}
function setBenchmarkSuite(suite) {
suite
// add listeners
.on('cycle', function(event) {
++currentCaseId;
let params = event.target.params;
let matType = params.matType;
let size1 = params.from;
let size2 = params.to;
log(`=== ${event.target.name} ${currentCaseId} ===`);
log(`params: (${matType},${parseInt(size1.width)}x${parseInt(size1.height)},`+
`${parseInt(size2.width)}x${parseInt(size2.height)})`);
log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms');
log('mean time:' +String(event.target.stats.mean*1000)+' ms');
log('stddev time:' +String(event.target.stats.deviation*1000)+' ms');
log(String(event.target));
})
.on('error', function(event) { log(`test case ${event.target.name} failed`); })
.on('complete', function(event) {
log(`\n ###################################`)
log(`Finished testing ${event.currentTarget.length} cases \n`);
if (!isNodeJs) {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
});
}
function genBenchmarkCase(paramsContent) {
let suite = new Benchmark.Suite;
totalCaseNum = 0;
currentCaseId = 0;
if (/\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g.test(paramsContent.toString())) {
let params = paramsContent.toString().match(/\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g)[0];
decodeParams2Case(suite, params);
} else {
log("no filter or getting invalid params, run all the cases");
addResizeUpLinearCase(suite, combiUpLinear);
addResizeDownLinearCase(suite, combiDownLinear);
}
setBenchmarkSuite(suite);
log(`Running ${totalCaseNum} tests from Resize`);
suite.run({ 'async': true }); // run the benchmark
}
// init
let resizeFunc = [addResizeUpLinearCase, addResizeDownLinearCase];//, addResizeAreaFastCase];
let combinations = [combiUpLinear, combiDownLinear];//, combiAreaFast];
// set test filter params
if (isNodeJs) {
const args = process.argv.slice(2);
let paramsContent = '';
if (/--test_param_filter=\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g.test(args.toString())) {
paramsContent = args.toString().match(/\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g)[0];
}
genBenchmarkCase(paramsContent);
} else {
runButton.onclick = function() {
let paramsContent = paramsElement.value;
genBenchmarkCase(paramsContent);
if (totalCaseNum !== 0) {
runButton.setAttribute("disabled", "disabled");
runButton.setAttribute('class', 'btn btn-primary disabled');
runButton.innerHTML = "Running";
}
}
}
};
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OpenCV.js Performance Test</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
body {
font-size: 13px;
}
.top-margin {
margin-top:10px;
}
h1, h4 {
margin: 24px 0 0;
}
h1 {
font-size: 2.0em;
}
h4 {
font-size: 1.2em;
}
pre {
font-family: 'Consolas', 'Monaco', monospace, serif;
font-size: 12px;
tab-size: 2;
}
input[type=checkbox] {
vertical-align: middle;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="row">
<div class="col-12">
<h1>OpenCV.js Performance Test</h1>
<div>
<h4>Modules</h4>
<h7>Image Processing</h7>
</div>
<div>
<h4>Kernels</h4>
<h7>Threshold</h7>
</div>
<div>
<h4>Parameters Filter</h4>
<input type="text" id="params" min="1" size="40" placeholder="default: run all the case"/> for example: (1920x1080, CV_8UC1, THRESH_BINARY)
</div>
<div class='row labels-wrapper' id='labelitem'></div>
<div class="row top-margin">
</div>
<div>
<button type="button" id="runButton" class="btn btn-primary disabled" disabled="disabled">Loading</button>
(It will take several minutes)</div>
<div class="row top-margin">
</div>
<div>
<pre id="log"></pre>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.4/benchmark.js"></script>
<script src="../../opencv.js" type="text/javascript"></script>
<script src="../base.js"></script>
<script src="../perf_helpfunc.js"></script>
<script src="./perf_threshold.js"></script>
</body>
</html>
@@ -0,0 +1,217 @@
const isNodeJs = (typeof window) === 'undefined'? true : false;
if (isNodeJs) {
var Benchmark = require('benchmark');
var cv = require('../../opencv');
var HelpFunc = require('../perf_helpfunc');
var Base = require('../base');
} else {
var paramsElement = document.getElementById('params');
var runButton = document.getElementById('runButton');
var logElement = document.getElementById('log');
}
cv.onRuntimeInitialized = () => {
console.log('opencv.js loaded');
if (isNodeJs) {
global.cv = cv;
global.combine = HelpFunc.combine;
global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize;
global.cvSize = Base.cvSize;
} else {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
let totalCaseNum, currentCaseId;
const typicalMatSizes = [cvSize.szVGA, cvSize.sz720p, cvSize.sz1080p, cvSize.szODD];
const matTypes = ['CV_8UC1', 'CV_16SC1', 'CV_32FC1', 'CV_64FC1'];
const threshTypes = ['THRESH_BINARY', 'THRESH_BINARY_INV', 'THRESH_TRUNC', 'THRESH_TOZERO', 'THRESH_TOZERO_INV'];
const combiSizeMatTypeThreshType = combine(typicalMatSizes, matTypes, threshTypes);
const combiSizeOnly = combine(typicalMatSizes, ['CV_8UC1'], ['THRESH_BINARY|THRESH_OTSU']);
function addSizeMatTypeThreshTypeCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matSize = combination[i][0];
let matType = combination[i][1];
let threshType = combination[i][2];
suite.add('threshold', function() {
cv.threshold(src, dst, threshold, thresholdMax, threshType);
}, {
'setup': function() {
let matSize = this.params.matSize;
let matType = cv[this.params.matType];
let threshType = cv[this.params.threshType];
let threshold = 127.0;
let thresholdMax = 210.0;
let src = new cv.Mat(matSize, matType);
let dst = new cv.Mat(matSize, matType);
let srcView = src.data;
srcView[0] = 0;
srcView[1] = 100;
srcView[2] = 200;
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
matSize: matSize,
matType: matType,
threshType: threshType
};
}
}
function addSizeOnlyCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matSize = combination[i][0];
suite.add('threshold', function() {
cv.threshold(src, dst, threshold, thresholdMax, cv.THRESH_BINARY|cv.THRESH_OTSU);
}, {
'setup': function() {
let matSize = this.params.matSize;
let threshold = 127.0;
let thresholdMax = 210.0;
let src = new cv.Mat(matSize, cv.CV_8UC1);
let dst = new cv.Mat(matSize, cv.CV_8UC1);
let srcView = src.data;
srcView[0] = 0;
srcView[1] = 100;
srcView[2] = 200;
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
matSize: matSize,
matType: 'CV_8UC1',
threshType: 'THRESH_BINARY|THRESH_OTSU'
};
}
}
function decodeParams2Case(suite, params, isSizeOnly) {
let sizeString = params.match(/[0-9]+x[0-9]+/g).toString();
let sizes = sizeString.match(/[0-9]+/g);
let size1Str = sizes.slice(0, 2).toString();
let matSize = cvtStr2cvSize(size1Str);
let matType, threshType;
if (isSizeOnly) {
matType = 'CV_8UC1';
threshType = 'THRESH_BINARY|THRESH_OTSU';
} else {
matType = (params.match(/CV\_[0-9]+[A-z][A-z][0-9]/) || []).toString();
threshType = (params.match(/THRESH\_[A-z]+\_?[A-z]*/) || []).toString();
}
// check if the params match and add case
for (let i = 0; i < combinations.length; ++i) {
let combination = combinations[i];
for (let j = 0; j < combination.length; ++j) {
if (matSize === combination[j][0] && matType === combination[j][1] && threshType === combination[j][2]) {
thresholdFunc[i](suite, [combination[j]]);
}
}
}
}
function log(message) {
console.log(message);1
if (!isNodeJs) {
logElement.innerHTML += `\n${'\t'.repeat(1) + message}`;
}
}
function setBenchmarkSuite(suite) {
suite
// add listeners
.on('cycle', function(event) {
++currentCaseId;
let params = event.target.params;
let matSize = params.matSize;
let matType = params.matType;
let threshType = params.threshType;
log(`=== ${event.target.name} ${currentCaseId} ===`);
log(`params: (${parseInt(matSize.width)}x${parseInt(matSize.height)},`+
`${matType},${threshType})`);
log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms');
log('mean time:' +String(event.target.stats.mean*1000)+' ms');
log('stddev time:' +String(event.target.stats.deviation*1000)+' ms');
log(String(event.target));
})
.on('error', function(event) { log(`test case ${event.target.name} failed`); })
.on('complete', function(event) {
log(`\n ###################################`)
log(`Finished testing ${event.currentTarget.length} cases \n`);
if (!isNodeJs) {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
});
}
function genBenchmarkCase(paramsContent) {
let suite = new Benchmark.Suite;
totalCaseNum = 0;
currentCaseId = 0;
if (/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g.test(paramsContent.toString())) {
let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g)[0];
let isSizeOnly = 0;
decodeParams2Case(suite, params, isSizeOnly);
} else if (/[\ ]*[0-9]+x[0-9]+[\ ]*/g.test(paramsContent.toString())) {
let params = paramsContent.toString().match(/[\ ]*[0-9]+x[0-9]+[\ ]*/g)[0];
let isSizeOnly = 1;
decodeParams2Case(suite, params, isSizeOnly);
}
else {
log("no filter or getting invalid params, run all the cases");
addSizeMatTypeThreshTypeCase(suite, combiSizeMatTypeThreshType);
addSizeOnlyCase(suite, combiSizeOnly);
}
setBenchmarkSuite(suite);
log(`Running ${totalCaseNum} tests from Threshold`);
suite.run({ 'async': true }); // run the benchmark
}
// init
let thresholdFunc = [addSizeMatTypeThreshTypeCase, addSizeOnlyCase];
let combinations = [combiSizeMatTypeThreshType, combiSizeOnly];
// set test filter params
if (isNodeJs) {
const args = process.argv.slice(2);
let paramsContent = '';
if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g.test(args.toString())) {
paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g)[0];
} else if (/--test_param_filter=[\ ]*[0-9]+x[0-9]+[\ ]*/g.test(args.toString())) {
paramsContent = args.toString().match(/[\ ]*[0-9]+x[0-9]+[\ ]*/g)[0];
}
genBenchmarkCase(paramsContent);
} else {
runButton.onclick = function() {
let paramsContent = paramsElement.value;
genBenchmarkCase(paramsContent);
if (totalCaseNum !== 0) {
runButton.setAttribute("disabled", "disabled");
runButton.setAttribute('class', 'btn btn-primary disabled');
runButton.innerHTML = "Running";
}
}
}
};

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