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

Compare commits

..

178 Commits

Author SHA1 Message Date
Alexander Alekhin 69357b1e88 release: OpenCV 4.5.2 2021-04-02 11:23:54 +00:00
Alexander Alekhin 9ef20ad20e Merge pull request #19833 from alalek:workaround_19678 2021-04-02 10:37:29 +00:00
Anastasia M 1263949e70 Merge pull request #18237 from LupusSanctus:am/pytorch_tf_det_tutorial
[GSoC] Added TF and PyTorch detection model conversion cases

* Added object detection convertion pipeline and tutorials

* Added tutorial corrections
2021-04-02 01:50:35 +00:00
Alexander Alekhin 12d80b9e64 Merge remote-tracking branch 'upstream/3.4' into merge-3.4 2021-04-01 21:48:52 +00:00
Anastasia M ad333e0d22 Merge pull request #17801 from LupusSanctus:am/pytorch_tf_segm
[GSoC] Added TF and PyTorch segmentation conversion cases

* WIP: Added conversion of segmentation models

* Added tutorial mds

* remove unused
2021-04-01 20:42:08 +00:00
Orest Chura 34a8a45a6a Merge pull request #19828 from OrestChura:oc/fix_garray_garray_input
[G-API] Fix bug of GArray<GArray> passing through a graph

* Add test to check GArray<GArray> passing through a graph (assertion failed)

* G-API: Flatten GArray<T> to std::vector<T> when capturing VCtr

- Also: Fix formatting in garray.hpp

* Refactored test, added valuable check

* Initialize size_t

Co-authored-by: Dmitry Matveev <dmitry.matveev@intel.com>
2021-04-01 20:39:31 +00:00
Alexander Alekhin 6a72bf5085 Merge pull request #19823 from alalek:issue_contrib_2895 2021-04-01 20:38:46 +00:00
Alexander Alekhin 1e51f87298 Merge pull request #19817 from alalek:cmake_fix_tracking_headers 2021-04-01 20:38:14 +00:00
Alexander Alekhin 8095f601d1 gapi(test): avoid compilation failure with GCC11 2021-04-01 20:23:29 +00:00
Alexander Alekhin 0ff57e3292 Merge pull request #19830 from alalek:issue_19368 2021-04-01 15:30:18 +00:00
Alexander Alekhin 5db484b6c2 Merge pull request #19831 from alalek:backport_19771 2021-04-01 14:05:09 +00:00
Alexander Alekhin b40d24ad75 Merge pull request #19829 from alalek:hotfix_19693 2021-04-01 14:04:36 +00:00
Alexander Alekhin 6865787a75 Merge pull request #19827 from alalek:build_videoio_macosx_override_3.4 2021-04-01 12:34:23 +00:00
Alexander Alekhin 7f664850f5 Merge pull request #19825 from alalek:cmake_fix_headers_order_python_3.4 2021-04-01 12:34:10 +00:00
Alexander Alekhin 2907fb88f5 Merge pull request #19822 from alalek:core_wui_backward_compatibility 2021-04-01 12:32:33 +00:00
Alexander Alekhin f839fa4070 Merge pull request #19820 from alalek:issue_19405 2021-04-01 12:32:09 +00:00
Kun Liang 32d51313d0 Merge pull request #19771 from lionkunonly:opencvjsNodeFix
* fix the perf tests of OpenCV.js so that it can run on Node.js successfully

* do not modify the CMakeLists.txt

Co-authored-by: lionkun <871518554@qq.com>
2021-04-01 12:29:48 +00:00
Alexander Alekhin 69341edfe6 Merge pull request #19816 from alalek:python_customize_namespaces 2021-04-01 12:27:04 +00:00
Alexander Alekhin 81f0b0e0dc cmake: fix tracking detail headers 2021-04-01 12:21:18 +00:00
Alexander Alekhin d7cb2ea210 videoio(dshow): add NULL ptr check 2021-04-01 11:28:41 +00:00
Alexander Alekhin 28f919d9d2 apps(model_diagnostics): fix invalid callback 2021-04-01 10:26:22 +00:00
Alexander Alekhin 4ae2c11520 videoio(build): eliminate inconsistent 'override' warnings 2021-04-01 09:56:21 +00:00
Alexander Alekhin 3e1673e8b2 Merge remote-tracking branch 'upstream/3.4' into merge-3.4 2021-04-01 09:54:57 +00:00
Alexander Alekhin 1b3e0b27af cmake: fix files order in Python bindings
- with changes backport from 4.x
2021-04-01 09:48:50 +00:00
Alexander Alekhin e4b0251e9d cuda: fix inplace condition in cv::cuda::flip 2021-04-01 02:26:59 +00:00
Alexander Alekhin b26f5b9468 core: backward compatibility for vx_store/vx_store_aligned calls 2021-04-01 02:17:47 +00:00
Alexander Alekhin 5340dc6686 Merge pull request #19819 from alalek:cmake_fix_headers_order 2021-04-01 01:34:21 +00:00
Alexander Alekhin 174753921d Merge pull request #19818 from alalek:workaround_python_build_failures 2021-04-01 01:12:07 +00:00
Alexander Alekhin aa32e3deb1 cmake: fix ADE dependency handling 2021-03-31 23:40:19 +00:00
Alexander Alekhin 2b86de217a cmake: fix order of headers
- cmake uses filesystem's order which may vary
- unpredictable headers order may cause build failures (primary bindings)
2021-03-31 23:16:46 +00:00
Alexander Alekhin 1615afd7f4 Merge pull request #19814 from alalek:pyopencv_to_safe 2021-03-31 22:58:18 +00:00
Alexander Alekhin 908957317f Merge pull request #19813 from alalek:issue_19506 2021-03-31 22:57:50 +00:00
Alexander Alekhin 6fa2bdd7f2 Merge pull request #19812 from alalek:workaround_19634 2021-03-31 22:57:15 +00:00
Alexander Alekhin f82303d614 Merge pull request #19811 from alalek:issue_19599 2021-03-31 22:56:48 +00:00
Alexander Alekhin 6773fa03e2 Merge pull request #19808 from alalek:3.4_python_fix_wrap_as 2021-03-31 22:56:14 +00:00
Alexander Alekhin 47fe017a6c build: workaround sporadic failures of python binding compilation 2021-03-31 22:44:27 +00:00
Alexander Alekhin 7baae20c20 Merge pull request #19815 from OrestChura:oc/fix_garray_garray_input 2021-03-31 22:33:14 +00:00
OrestChura 921c4551d9 Fix conversion of the kernel's input for GArray<GArray<U>> -> vector<vector<U>> 2021-03-31 23:37:44 +03:00
Alexander Alekhin c20a424e3a gapi(python): rename cv.gapi_wip_op / cv.gapi_wip_kernels 2021-03-31 20:34:04 +00:00
Alexander Alekhin 2e005f5dc2 python: allow to customize Python namespaces
- extra methods through PYOPENCV_EXTRA_METHODS_<NS_UPPER> macros
- extra constants through PYOPENCV_EXTRA_CONSTANTS_<NS_UPPER> macros
2021-03-31 20:33:38 +00:00
Alexander Alekhin 9f13fdb840 Merge pull request #19732 from aDanPin:danpin/gapi/stereo_operation_and_test
G-API Stereo operation and tests
2021-03-31 23:22:29 +03:00
aDanPin e6f52b0996 Adding stereo operation and tests 2021-03-31 20:09:10 +03:00
Alexander Alekhin d651ff8d6b python: exception-free pyopencv_to() wrapper 2021-03-31 14:18:32 +00:00
Alexander Alekhin e11408f6ad Merge pull request #18903 from mpashchenkov:mp/onnx-disable-output
G-API: ONNX. Disable unnecessary outputs
2021-03-31 16:46:22 +03:00
Alexander Alekhin 8069a6b4f8 core(IPP): disable some ippsMagnitude_32f calls 2021-03-31 13:38:57 +00:00
Alexander Alekhin b697b3162f videoio(mjpeg): disable parallel encoder 2021-03-31 12:35:12 +00:00
Alexander Alekhin 53a16b1186 Merge pull request #19809 from alalek:issue_19513 2021-03-31 10:50:20 +00:00
Alexander Alekhin a2a92999be core(arithm_op): workaround problem with scalars handling 2021-03-31 10:35:52 +00:00
Alexander Alekhin 40c0830b63 videoio(avfoundation): add getCaptureDomain() 2021-03-31 09:35:11 +00:00
eplankin 6f1eefec69 Merge pull request #19681 from eplankin:link_problem
* Workaround for IPP linking problem

* Apply -Bsymbolic to all cases when IPP is on

* Tried to hide symbols on MacOS

* Tried on --exclude-libs option

* Fixed macos and win warnings

* Fixed win build

* cmake(IPP): move --exclude-libs,libippcore.a to IPP CMake file

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-31 09:24:37 +00:00
Maxim Pashchenkov 61a4100d0c Added overload for cfgPostPros 2021-03-31 12:20:04 +03:00
Alexander Alekhin bb6e15f2c0 python: fix CV_WRAP_AS handling 2021-03-30 22:02:48 +00:00
Alexander Alekhin 0dcb99cf23 Merge pull request #19798 from LupusSanctus:am/reduce_sum_ch 2021-03-30 21:37:13 +00:00
Maxim Pashchenkov 69fc0acd1a Merge pull request #19752 from mpashchenkov:mp/onnx-int64-to-32
G-API: ONNX. Adding INT64-32 conversion for output.

* Added int64 to 32 conversion

* Added warning

* Added type checks for all toCV

* Added type checks for tests

* Small fixes

* Const for fixture in test

* std::tuple if retutn value for toCV

* Mistake

* Changed toCV for tests

* Added Assert

* Fix for comments

* One conversion for ONNX and IE

* Clean up

* One more fix

* Added copyFromONNX

* Removed warning

* Apply review comments
2021-03-30 21:08:43 +00:00
Anatoliy Talamanov 3f14cb073b Merge pull request #19804 from TolyaTalamanov:at/python-custom-op
[G-API] Introduce custom python operator API

* Introduce custom python operator API

* Add wip namespace
2021-03-30 20:59:02 +00:00
Anastasia Murzova cc6d48959e Added reduce sum by channel support 2021-03-30 23:01:22 +03:00
Alexander Alekhin 5ffe32439d Merge pull request #19806 from rgarnov:rg/fix_double_nv12_y_accessor_test_instantiation 2021-03-30 18:25:32 +00:00
Ruslan Garnov 76a9c0ccb0 Fixed Y accessor in BGR accessor test, added more instantiations 2021-03-30 19:51:48 +03:00
Vitaly Tuzov aab62aa6dd Merge pull request #18952 from terfendail:wui_doc
* Updated UI documentation to address WUI

* Added documentation for vx_ calls

* Removed vx_store operation overload

* Doxyfile updated to enable wide UI

* Enable doxygen documentation for vx_ WUI functions

* Wide intrinsics definition rework

* core: fix SIMD C++ emulator build (supports 128-bit only)
2021-03-30 16:18:03 +00:00
Alexander Alekhin c89084e6b7 Merge pull request #19223 from YashasSamaga:cuda4dnn-halfpix-linear-resize 2021-03-30 13:19:41 +00:00
Alexander Alekhin 64072e44cc Merge pull request #19351 from TolyaTalamanov:at/python-backend 2021-03-29 21:54:44 +00:00
Maxim Pashchenkov e7007668a6 Merge pull request #19792 from mpashchenkov:mp/ie-add-int32
G-API: IE. Adding support for INT32 type.

* Added support for int32

* Added sample for semantic-segmentation-adas-0001

* Alignment

* Alignment 2

* Rstrt build

* Removed test for sem seg
2021-03-29 20:59:55 +00:00
Alexander Alekhin 105b57c8d9 Merge pull request #19802 from rgarnov:rg/fix_accessor_tests_valgrind_warnings 2021-03-29 20:57:57 +00:00
Anatoliy Talamanov 79d4a38d87 Implement python backend 2021-03-29 22:51:24 +03:00
Anastasia M e08de1101d Merge pull request #19693 from LupusSanctus:onnx_diagnostic
ONNX diagnostic tool

* Final

* Add forgotten Normalize layer to the set of supported types

* ONNX diagnostic tool corrections

* Fixed CI test warnings

* Added code minor corrections

Co-authored-by: Sergey Slashchinin <sergei.slashchinin@xperience.ai>
2021-03-29 16:38:28 +00:00
Ruslan Garnov b5339cc01b Fixed valgrind warnings in accessors tests 2021-03-29 17:42:53 +03:00
Alexander Alekhin ac9f3a1242 Merge pull request #19793 from aarongreig:aaron/imgproc/relaxCornerEigenValTest 2021-03-29 13:41:44 +00:00
Aaron Greig 53652a6194 Relax accuracy requirement on OpenCL MinEigenVal corner kernel test.
The MinEigenVal path through the corner.cl kernel makes use of native_sqrt,
a math builtin function which has implementation defined accuracy.

Partially addresses issue #9821
2021-03-29 12:06:02 +01:00
lionkun 8d232a63ad fix the perf tests of OpenCV.js so that it can run on Node.js successfully 2021-03-27 21:52:44 +00:00
Alexander Alekhin 35eaacd1db Merge remote-tracking branch 'upstream/3.4' into merge-3.4 2021-03-27 15:35:16 +00:00
Alexander Alekhin bf03f5fa3a Merge pull request #19786 from alalek:build_opencv_winpack_dldt_2021.3.0 2021-03-26 22:38:52 +00:00
Alexander Alekhin 6e8022a3af Merge pull request #19773 from jondea:add-aarch64-specialised-v_expand-3.4 2021-03-26 16:54:51 +00:00
Alexander Alekhin d27eb79fa6 Merge pull request #19785 from alalek:dnn_ocl_fix_async_kernels 2021-03-26 12:27:58 +00:00
Anastasia M 3e48a91d97 Merge pull request #19546 from LupusSanctus:am/slice_steps
* Added Steps support in DNN Slice layer

* Added code corrections

* dnn(slice): fix OCL and OCL_FP16 processing
2021-03-26 11:04:57 +00:00
Orest Chura ad2f5ccc66 Merge pull request #19712 from OrestChura:oc/Kalm_ptest
[G-API]: Performance tests for KalmanFilter

* Kalman perf.tests and some tests refactoring

* Input generation moved to a separate function; Slowest case sneario testing added

* Generating refactored

* Generating refactoring

* Addressing comments
2021-03-26 09:41:54 +00:00
Alexander Alekhin 77bfd9434b Merge pull request #19782 from TolyaTalamanov:at/rmat-plaidml-backend 2021-03-26 09:36:38 +00:00
Alexander Alekhin 144443d011 build: winpack_dldt with dldt 2021.3.0 2021-03-26 08:58:00 +00:00
Anatoliy Talamanov 6ba99068c9 Support RMat for PlaidML backend 2021-03-26 09:00:18 +03:00
Alexander Alekhin 86d0a86141 dnn(ocl): fix gemm kernel scheduling 2021-03-26 00:35:00 +00:00
Alexander Alekhin b7f6584dab Merge pull request #19784 from alalek:gapi_win32_build_warning 2021-03-26 01:57:59 +03:00
Alexander Alekhin 3290a5f370 gapi(build): eliminate Win32 build warning 2021-03-25 22:15:06 +00:00
Mikhail Nikolskii bf9f67e93f Merge pull request #19783 from mikhail-nikolskiy:interop-perf
Performance optimization in DirectX and VAAPI interop

* optimization in OpenCL NV12<>BGR kernels

* reduce kernel work-size
2021-03-25 21:27:31 +00:00
Alexander Alekhin 26ea4760ad Merge pull request #19774 from aarongreig:aaron/dnn/oclTestAccuracyThresholds 2021-03-25 16:58:07 +00:00
Anatoliy Talamanov 0753408e10 Merge pull request #19318 from TolyaTalamanov:at/python-generic-infer
[G-API] Python ROI generic inference

* Python generic infer overloads

* Move wrappers to appropriate file
2021-03-25 16:55:29 +00:00
Aaron Greig f59917bea1 Introduce relaxed accuracy thresholds for CL target in some dnn tests.
Partially addresses #9821
2021-03-25 10:58:23 +00:00
Alexander Alekhin b62d015285 Merge remote-tracking branch 'upstream/3.4' into merge-3.4 2021-03-24 18:58:46 +00:00
Alexander Alekhin a394c8b10b Merge pull request #19770 from alalek:dnn_openvino_2021.3.0 2021-03-24 18:50:47 +00:00
Alexander Alekhin 24002a5dfe Merge pull request #19731 from rgarnov:rg/basic_frame_drop 2021-03-24 15:20:38 +00:00
Lukas-Alexander Weber 7c4b873ba3 Merge pull request #19762 from lukasalexanderweber:master
* Error Message for SURF if not implemented

In OpenCV 4.5.1 

import cv2 as cv
cv.xfeatures2d_SURF.create

will not create an AttributeError, even if the function is excluded (no nonfree option)

In Line 305 (now 306) however ´finder = FEATURES_FIND_CHOICES[args.features]()´ will raise an 

error: OpenCV(4.5.1) ..\opencv_contrib\modules\xfeatures2d\src\surf.cpp:1029: error: (-213:The function/feature is not implemented) This algorithm is patented and is excluded in this configuration; Set OPENCV_ENABLE_NONFREE CMake option and rebuild the library in function 'cv::xfeatures2d::SURF::create'

So we should check with cv.xfeatures2d_SURF.create() correctly if SURF is available
2021-03-24 15:02:20 +00:00
Alexander Alekhin e56e4876e7 dnn(test): update tests for OpenVINO 2021.3 2021-03-24 14:50:42 +00:00
Alexander Alekhin 7949983c41 Merge pull request #19325 from AsyaPronina:asyadev/extract_y
[G-API] Added Y, UV accessors for cv::MediaFrame
2021-03-24 16:37:05 +03:00
Alexander Alekhin 56bdd7db5c dnn: use OpenVINO 2021.3 defines
original commit: 6291503793
2021-03-24 10:26:24 +00:00
Alexander Alekhin 3df6bc58e9 Merge pull request #19765 from LupusSanctus:am/mobilenetv3 2021-03-24 09:43:27 +00:00
Anastasiya Pronina b0d66e06f4 Added Y, UV accessors to cv::MediaFrame 2021-03-24 12:34:44 +03:00
Anastasia Murzova e75f1b071b Added reshape corrections 2021-03-24 10:53:11 +03:00
Anastasia Murzova 7a2b3ed471 Corrected DNN elementwise multiplication 2021-03-24 10:53:11 +03:00
Anastasia M 551d4a8ec1 Merge pull request #19477 from LupusSanctus:am/eltwice_vec
* Aligned OpenCV DNN and TF sum op behaviour

Support Mat (shape: [1, m, k, n] ) + Vec (shape: [1, 1, 1, n]) operation
by vec to mat expansion

* Added code corrections: backend, minor refactoring
2021-03-23 22:16:09 +00:00
Jonathan Deakin 29a289dfa1 Add v_expand for AArch64, fuse vmovl+vget_high into vmovl_high 2021-03-23 15:06:41 +00:00
Alexander Alekhin a00d6b8377 Merge pull request #19763 from TolyaTalamanov:at/blockingdesc-order-fix 2021-03-23 13:39:58 +00:00
Alexander Alekhin ca8c3dd9b5 Merge remote-tracking branch 'upstream/3.4' into merge-3.4 2021-03-22 12:05:23 +00:00
Anatoliy Talamanov c434ca74a2 Blocking dims order fix 2021-03-22 13:57:57 +03:00
Alexander Alekhin bdd2b57e5d Merge pull request #19757 from alalek:js_setLogLevel 2021-03-21 17:37:05 +00:00
Alexander Alekhin a97f6f8058 js: support setLogLevel() / getLogLevel() calls 2021-03-20 18:14:10 +00:00
Liubov Batanina c0dd82fb53 Merge pull request #19632 from l-bat:lb/ie_arm_target
Added OpenVINO ARM target

* Added IE ARM target

* Added OpenVINO ARM target

* Delete ARM target

* Detect ARM platform

* Changed device name in ArmPlugin

* Change ARM detection
2021-03-20 11:20:02 +00:00
Alexander Alekhin 94f00cf096 Merge pull request #19747 from alalek:issue_19733 2021-03-19 12:53:32 +00:00
Alexander Alekhin 1211a8b9cd Merge pull request #19745 from alalek:issue_19729 2021-03-19 12:52:34 +00:00
Anatoliy Talamanov 50a264d832 Merge pull request #19310 from TolyaTalamanov:at/generic-infer-overloads
[G-API] Support generic infer overloads

* Overloads for generic infer

* Fix build

* Refactoring

* Fix docs

* Put extra stuff to detail namespace

* Add doc for usings

* Remove uneccessary template in Priv
2021-03-19 12:50:45 +00:00
Alexander Alekhin 3f52d0e46c Merge pull request #19738 from TolyaTalamanov:at/giebackend-blockingdesc-fix 2021-03-19 11:54:43 +00:00
Ruslan Garnov 716bdd5ee5 Implemented basic frame drop functionality 2021-03-19 14:26:14 +03:00
Anatoliy Talamanov bad08d26da Fix blocking desc usage 2021-03-19 12:47:17 +03:00
Alexander Alekhin a41394c885 core(parallel): fix plugins handling if no filesystem available 2021-03-18 23:05:12 +00:00
Alexander Alekhin f680505086 features2d(mser): chi_table.h notes 2021-03-18 21:30:12 +00:00
Alexander Alekhin ae60bbc7e4 Merge pull request #19741 from alalek:ml_logistic_regression_use_opencv_license_header 2021-03-18 20:47:44 +00:00
Anatoliy Talamanov dc31e20925 Merge pull request #19709 from TolyaTalamanov:at/async-inferlist-infer2
G-API: Implement async version for InferList & Infer2

* Implement async version for InferList & Infer2

* Fix warning

* Fix bug with roi ordering

* Post input meta instead of empty

* Fix comments to review
2021-03-18 23:33:19 +03:00
Alexander Alekhin 7664e6d090 ml: use OpenCV license header for logistic regression 2021-03-17 20:29:52 +00:00
Alexander Alekhin af63fffb63 Merge pull request #19739 from alalek:fix_valgrind_run 2021-03-17 13:59:52 +00:00
Alexander Alekhin 0a6adedaf1 valgrind: filter out hardware-accelerated videoio tests 2021-03-17 08:59:56 +00:00
Alexander Alekhin b19f860384 Merge remote-tracking branch 'upstream/3.4' into merge-3.4 2021-03-13 13:02:18 +00:00
Ziachnix 960f501cc1 Merge pull request #19284 from Ziachnix:feature/js-qr-code-detector
Add QRCodeDetector to JavaScript Build

* ADD: js support for qrCodeDetector

- cherry picked commit to solve rebase error

* CHG. Revert haarcascade path

* FIX: Tests without images

* ADD: decodeCurved

* js(docs): don't require OPENCV_TEST_DATA_PATH

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-13 12:52:44 +00:00
Alexander Alekhin 7a8e171691 Merge pull request #19720 from alalek:ocl_test_skip_spir_amd 2021-03-13 12:48:20 +00:00
Alexander Alekhin 7ca9740da5 Merge pull request #19718 from alalek:backport_19683 2021-03-13 12:46:24 +00:00
Alexander Alekhin 68fae94cbb Merge pull request #19717 from danbey:bad_value_param_should_be_passed_by_reference 2021-03-13 12:45:55 +00:00
Alexander Alekhin 6da5c7c1d0 Merge pull request #19716 from l-bat:lb/fix_resize 2021-03-13 12:45:07 +00:00
Alexander Alekhin 87e607a19b core(ocl): skip SPIR test on AMD devices if problem detected 2021-03-13 06:12:52 +00:00
Dale Phurrough cbe236652b noexcept def construct Mat, UMat, Mat_, MatSize, MatStep
original commit: 1b0f781b7c
2021-03-12 20:26:32 +00:00
Dan Ben Yosef d4d805cb3e Avoiding copy by passing param by reference
It is best to pass bad_value_ param by reference to avoid copy.
2021-03-12 14:17:11 -05:00
Liubov Batanina 8d29a902e4 Added ngraph::op::v6::MVN 2021-03-12 21:02:03 +03:00
Alexander Alekhin 4c1d5840bb Merge pull request #19707 from AsyaPronina:asyadev/upstream_fixes_from_release 2021-03-12 14:27:41 +00:00
Alexander Alekhin f136adcad5 Merge pull request #19715 from seiko2plus:issue_19698 2021-03-12 09:45:19 +00:00
Liubov Batanina 95ab9468c1 Added ngraph::op::v4::Interpolation 2021-03-12 12:00:59 +03:00
Sayed Adel f8181fbef8 core:ppc64 fix detecting CPU features when optimization is off 2021-03-12 02:02:31 +00:00
Alexander Alekhin c5c2b6f9bf Merge pull request #19683 from diablodale:add_defconstruct_noexcept_matumat 2021-03-11 22:02:06 +00:00
Xinguang Bian b995de4ff3 Merge pull request #19253 from mightbxg:bugfix_PnPRansac
* fix unexpected Exception in solvePnPRansac caused by input points

* calib3d: solvePnPRansac - keep minimal changes to handle DLT 6 points requirement

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-12 00:53:06 +03:00
Alexander Alekhin 825dadfbdd Merge pull request #19703 from danbey:setting_StereoSGBMParams_in_init_list 2021-03-11 21:33:19 +00:00
Anastasiya Pronina 0f4b27c300 Upstream fixes from release 2021-03-11 23:27:23 +03:00
Dan Ben Yosef 63048812c7 Init params (StereoSGBMParams) in StereoSGBMImpl constructor initialization list
To improve preformence it is better to init the params (StereoSGBMParams) in the
    initialization list.
2021-03-10 13:05:35 -05:00
Alexander Alekhin fbb38cc245 Merge pull request #19222 from YashasSamaga:cuda4dnn-fix-build-diagnostics 2021-03-10 17:40:36 +00:00
Orest Chura c1a57a10a4 Merge pull request #19542 from OrestChura:oc/BGSub_ptest
[G-API]: Performance tests for BackgroundSubtractor

* Perf.Tests for BackgroundSubtractor kernel

* Fix CI

* Addressing comments

* Addressing a comment

* Test cycle and validation changes

* Addressing  comment

* Added assert
2021-03-10 17:37:55 +00:00
Alexander Alekhin e4692ac079 Merge pull request #19613 from WeiChungChang:NMS_refine 2021-03-10 17:36:57 +00:00
Maxim Pashchenkov 12fa8d8444 Merge pull request #18240 from mpashchenkov:mp/ocv-gapi-input-cnn-reshape
[G-API]: Adding reshape for CNN input.

* Added CNN input IE reshape

* rbs

* Added unordered_set instead vector

* Alignment
2021-03-10 16:06:46 +00:00
Qoo 47337e2196 boost NMS performance 2021-03-10 15:59:26 +00:00
Alexey Smirnov ddd2447192 Merge pull request #19617 from smirnov-alexey:as/extend_kernel_package_api
G-API: Extend GKernelPackage and serialization API

* Extend GKernelPackage API

* Adding tests

* Extend serialization API

* Address review comments
2021-03-10 15:58:34 +00:00
Alexander Alekhin 1d6a1e5f9c Merge pull request #19692 from seiko2plus:issue_19647 2021-03-09 18:14:41 +00:00
Amir Tulegenov 04d907fb97 Merge pull request #19619 from amirtu:OCV-221_get_and_set_cameras_on_stitcher
* Get and set cameras for sticher.

* Code review fixes.

Co-authored-by: amir.tulegenov <amir.tulegenov@xperience.ai>
Co-authored-by: Alexander Smorkalov <alexander.smorkalov@xperience.ai>
2021-03-09 17:51:40 +00:00
Sayed Adel 84fcc4ab9b core:ppc64 fix the build with the newer versions of Eigen on IBM/Power
It also fixes the build when universal intrinsics is disabled
   via `-DDCV_ENABLE_INTRINSICS=OFF`.
2021-03-09 19:20:18 +02:00
Daniel Playfair Cal 65b51e1538 Merge pull request #19690 from hedgepigdaniel:fix/calibration_fisheye
* fix(samples/camera_calibration): set new camera matrix for fisheye

* fix(camera_calibration): ignore inapplicable flags for fisheye
2021-03-09 15:09:08 +00:00
Alexander Alekhin e2610df073 Merge pull request #19688 from alalek:videoio_docs_hwaccel 2021-03-09 15:06:43 +00:00
Alexander Alekhin 6c9be1bc1d Merge pull request #19675 from asmorkalov:as/pylint_warnings 2021-03-09 09:43:52 +00:00
Alexander Smorkalov 4c48f1eed2 Removed unused variables found by pylint. 2021-03-09 10:56:45 +03:00
Dan Ben-Yosef 31f66766b7 Merge pull request #19685 from danbey:setting_stereoBMImpl_in_init_list
Init params (StereoBMParams) in StereoBMImpl constructor initialization list

* Init StereoBMImpl in initialization list

To improve preformence it is better to init the params (StereoBMImpl) in the
initialization list.

* coding style

* drop useless copy/move ctor

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-07 20:06:08 +03:00
Alexander Alekhin 601690695e Merge pull request #19687 from alalek:videoio_docs_fixes_3.4 2021-03-07 16:23:24 +00:00
Alexander Alekhin 4287961aed videoio(doc): add 'videoio_hwaccel' group, fix typos 2021-03-07 04:47:22 +00:00
Alexander Alekhin 85009800b3 videoio(docs): fixes 2021-03-07 04:26:49 +00:00
Alexander Alekhin d643a90efa Merge remote-tracking branch 'upstream/3.4' into merge-3.4 2021-03-06 17:31:08 +00:00
Vitaly Tuzov 04a9ff88d8 Merge pull request #19622 from terfendail:ref_doc
* Updated cpp reference implementations for a few intrinsics to address wide universal intrinsics as well

* Updated cpp reference implementations for a few more universal intrinsics
2021-03-06 17:22:21 +00:00
Alexander Alekhin dc24663e8d Merge pull request #19641 from LupusSanctus:am/tf_reshape 2021-03-06 17:21:34 +00:00
Alexander Alekhin d2cc63e779 Merge pull request #19680 from alalek:cmake_update_python_linters 2021-03-06 17:20:02 +00:00
YashasSamaga d0fe6ad109 fix checkVersions() 2021-03-06 19:03:03 +05:30
Alexander Alekhin 358878caf7 Merge pull request #19671 from SamFC10:sam-darknet 2021-03-05 15:12:21 +00:00
cyy b450dd7a87 Merge pull request #19565 from cyyever:minor_fix
Local objects optimization in calibration init

* use emplace_back

* use {} initilization

* remove a tailing white space
2021-03-05 15:04:51 +00:00
Mradul Agrawal 640f188ca2 Merge pull request #19583 from theroyalpekka:patch-1
* Update polynom_solver.cpp

This pull request is in the response to Issue  #19526. I have fixed the problem with the cube root calculation of 2*R. The Issue was in the usage of pow function with negative values of R, but if it is calculated for only positive values of R then changing x0 according to the parity of R, the Issue is resolved. Kindly consider it, Thanks!

* add cv::cubeRoot(double)

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-05 13:55:52 +00:00
Alexander Alekhin a1e2c4f338 Merge pull request #19655 from raaldrid:EXR_rw_alpha_support_16115 2021-03-05 16:54:31 +03:00
Alexander Alekhin 625d4fc884 cmake: update Python linters handling
- exclude from getBuildInformation()
- fix pylint version
2021-03-05 12:54:51 +00:00
Alexander Alekhin f821530eb0 Merge pull request #19677 from APrigarina:detection_fix 2021-03-05 08:40:27 +00:00
Anastasia Murzova 7894cd3c73 Aligned TF Reshape layer behaviour 2021-03-05 01:01:37 +03:00
APrigarina 125cc79c17 fix false positive detection 2021-03-04 19:20:31 +03:00
Alexander Smorkalov 2e429268ff Merge pull request #19668 from asmorkalov:as/filesystem_py
* Add Python Bindings for getCacheDirectory function

* Added getCacheDirectory interop test with image codecs.

Co-authored-by: Sergey Slashchinin <sergei.slashchinin@xperience.ai>
2021-03-04 16:17:57 +00:00
Alexander Alekhin 2a808aeec0 Merge pull request #19674 from l-bat:lb/fix_ie_tests 2021-03-04 14:52:20 +00:00
Liubov Batanina 94533e12eb Determine layout 2021-03-04 13:05:01 +03:00
Alexander Alekhin a0008de281 Merge pull request #19607 from alalek:backport_19606 2021-03-03 21:10:57 +00:00
SamFC10 a42d4da003 Added Spatial Attention Module in Darknet Importer 2021-03-03 22:42:47 +05:30
Alexander Smorkalov e2ca50f1cb Merge pull request #19539 from asmorkalov:as/calib_fix_focal_length
* Added CALIB_FIX_FOCAL_LENGTH to fisheye calibration #13450

Sometimes you want to calibrate just the principal point of a camera, or just the distortion coefficients. In this case, you can pass the CALIB_FIX_FOCAL_LENGTH flag to keep Fx and Fy

* Added test for CALIB_FIX_FOCAL_LENGTH option in fisheye callinration.
2021-03-03 14:06:59 +00:00
Alexander Alekhin 0689c70dba Merge pull request #19665 from alalek:update_ffmpeg_3.4 2021-03-03 11:22:56 +00:00
Alexander Alekhin 75ad74c893 ffmpeg/3.4: update FFmpeg wrapper 2021.03
- FFmpeg 3.4.8
2021-03-02 23:59:38 +00:00
Alexander Alekhin cbfd38bd41 core: rework code locality
- to reduce binaries size of FFmpeg Windows wrapper
- MinGW linker doesn't support -ffunction-sections (used for FFmpeg Windows wrapper)
- move code to improve locality with its used dependencies
- move UMat::dot() to matmul.dispatch.cpp (Mat::dot() is already there)
- move UMat::inv() to lapack.cpp
- move UMat::mul() to arithm.cpp
- move UMat:eye() to matrix_operations.cpp (near setIdentity() implementation)
- move normalize(): convert_scale.cpp => norm.cpp
- move convertAndUnrollScalar(): arithm.cpp => copy.cpp
- move scalarToRawData(): array.cpp => copy.cpp
- move transpose(): matrix_operations.cpp => matrix_transform.cpp
- move flip(), rotate(): copy.cpp => matrix_transform.cpp (rotate90 uses flip and transpose)
- add 'OPENCV_CORE_EXCLUDE_C_API' CMake variable to exclude compilation of C-API functions from the core module
- matrix_wrap.cpp: add compile-time checks for CUDA/OpenGL calls
- the steps above allow to reduce FFmpeg wrapper size for ~1.5Mb (initial size of OpenCV part is about 3Mb)

backport is done to improve merge experience (less conflicts)
backport of commit: 65eb946756
2021-03-02 23:24:28 +00:00
Rachel A cc22a73d0f EXR alpha support for 4 channel reading and writing. Issue https://github.com/opencv/opencv/issues/16115. 2021-03-02 11:49:56 -08:00
Dale Phurrough 1b0f781b7c noexcept def construct Mat, UMat, Mat_, MatSize, MatStep 2021-03-01 22:42:13 +01:00
YashasSamaga 8c74d7e4fa add half pixel centers and align corners param 2020-12-27 15:05:39 +05:30
237 changed files with 10198 additions and 1971 deletions
+6 -6
View File
@@ -999,6 +999,12 @@ if(COMMAND ocv_pylint_finalize)
ocv_pylint_add_directory_recurse(${CMAKE_CURRENT_LIST_DIR}/samples/python/tutorial_code)
ocv_pylint_finalize()
endif()
if(TARGET check_pylint)
message(STATUS "Registered 'check_pylint' target: using ${PYLINT_EXECUTABLE} (ver: ${PYLINT_VERSION}), checks: ${PYLINT_TOTAL_TARGETS}")
endif()
if(TARGET check_flake8)
message(STATUS "Registered 'check_flake8' target: using ${FLAKE8_EXECUTABLE} (ver: ${FLAKE8_VERSION})")
endif()
if(OPENCV_GENERATE_SETUPVARS)
include(cmake/OpenCVGenSetupVars.cmake)
@@ -1628,12 +1634,6 @@ endif()
status("")
status(" Python (for build):" PYTHON_DEFAULT_AVAILABLE THEN "${PYTHON_DEFAULT_EXECUTABLE}" ELSE NO)
if(PYLINT_FOUND AND PYLINT_EXECUTABLE)
status(" Pylint:" PYLINT_FOUND THEN "${PYLINT_EXECUTABLE} (ver: ${PYLINT_VERSION}, checks: ${PYLINT_TOTAL_TARGETS})" ELSE NO)
endif()
if(FLAKE8_FOUND AND FLAKE8_EXECUTABLE)
status(" Flake8:" FLAKE8_FOUND THEN "${FLAKE8_EXECUTABLE} (ver: ${FLAKE8_VERSION})" ELSE NO)
endif()
# ========================== java ==========================
if(BUILD_JAVA)
+1
View File
@@ -59,3 +59,4 @@ ocv_add_app(annotation)
ocv_add_app(visualisation)
ocv_add_app(interactive-calibration)
ocv_add_app(version)
ocv_add_app(model-diagnostics)
+3
View File
@@ -0,0 +1,3 @@
ocv_add_application(opencv_model_diagnostics
MODULES opencv_core opencv_dnn
SRCS model_diagnostics.cpp)
@@ -0,0 +1,65 @@
/*************************************************
USAGE:
./model_diagnostics -m <onnx file location>
**************************************************/
#include <opencv2/dnn.hpp>
#include <opencv2/core/utils/filesystem.hpp>
#include <iostream>
using namespace cv;
using namespace dnn;
static
int diagnosticsErrorCallback(int /*status*/, const char* /*func_name*/,
const char* /*err_msg*/, const char* /*file_name*/,
int /*line*/, void* /*userdata*/)
{
fflush(stdout);
fflush(stderr);
return 0;
}
static std::string checkFileExists(const std::string& fileName)
{
if (fileName.empty() || utils::fs::exists(fileName))
return fileName;
CV_Error(Error::StsObjectNotFound, "File " + fileName + " was not found! "
"Please, specify a full path to the file.");
}
std::string diagnosticKeys =
"{ model m | | Path to the model .onnx file. }"
"{ config c | | Path to the model configuration file. }"
"{ framework f | | [Optional] Name of the model framework. }";
int main( int argc, const char** argv )
{
CommandLineParser argParser(argc, argv, diagnosticKeys);
argParser.about("Use this tool to run the diagnostics of provided ONNX model"
"to obtain the information about its support (supported layers).");
if (argc == 1)
{
argParser.printMessage();
return 0;
}
std::string model = checkFileExists(argParser.get<std::string>("model"));
std::string config = checkFileExists(argParser.get<std::string>("config"));
std::string frameworkId = argParser.get<std::string>("framework");
CV_Assert(!model.empty());
enableModelDiagnostics(true);
redirectError(diagnosticsErrorCallback, NULL);
Net ocvNet = readNet(model, config, frameworkId);
return 0;
}
+1 -1
View File
@@ -16,7 +16,7 @@ if(PYLINT_EXECUTABLE AND NOT DEFINED PYLINT_VERSION)
execute_process(COMMAND ${PYLINT_EXECUTABLE} --version RESULT_VARIABLE _result OUTPUT_VARIABLE PYLINT_VERSION_RAW)
if(NOT _result EQUAL 0)
ocv_clear_vars(PYLINT_EXECUTABLE PYLINT_VERSION)
elseif(PYLINT_VERSION_RAW MATCHES "pylint([^,]*) ([0-9\\.]+[0-9])")
elseif(PYLINT_VERSION_RAW MATCHES "pylint([^,\n]*) ([0-9\\.]+[0-9])")
set(PYLINT_VERSION "${CMAKE_MATCH_2}")
else()
set(PYLINT_VERSION "unknown")
+16 -1
View File
@@ -143,10 +143,25 @@ macro(ipp_detect_version)
list(APPEND IPP_LIBRARIES ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX})
else ()
add_library(ipp${name} STATIC IMPORTED)
set(_filename "${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}")
set_target_properties(ipp${name} PROPERTIES
IMPORTED_LINK_INTERFACE_LIBRARIES ""
IMPORTED_LOCATION ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
IMPORTED_LOCATION ${IPP_LIBRARY_DIR}/${_filename}
)
if("${name}" STREQUAL "core") # https://github.com/opencv/opencv/pull/19681
if(OPENCV_FORCE_IPP_EXCLUDE_LIBS OR OPENCV_FORCE_IPP_EXCLUDE_LIBS_CORE
OR (UNIX AND NOT ANDROID AND NOT APPLE
AND (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
)
AND NOT OPENCV_SKIP_IPP_EXCLUDE_LIBS_CORE
)
if(CMAKE_VERSION VERSION_LESS "3.13.0")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--exclude-libs,${_filename} ${CMAKE_SHARED_LINKER_FLAGS}")
else()
target_link_options(ipp${name} INTERFACE "LINKER:--exclude-libs,${_filename}")
endif()
endif()
endif()
list(APPEND IPP_LIBRARIES ipp${name})
if (NOT BUILD_SHARED_LIBS AND (HAVE_IPP_ICV OR ";${OPENCV_INSTALL_EXTERNAL_DEPENDENCIES};" MATCHES ";ipp;"))
# CMake doesn't support "install(TARGETS ${IPP_PREFIX}${name} " command with imported targets
+3 -1
View File
@@ -879,7 +879,9 @@ endmacro()
macro(_ocv_create_module)
ocv_compiler_optimization_process_sources(OPENCV_MODULE_${the_module}_SOURCES OPENCV_MODULE_${the_module}_DEPS_EXT ${the_module})
set(OPENCV_MODULE_${the_module}_HEADERS ${OPENCV_MODULE_${the_module}_HEADERS} CACHE INTERNAL "List of header files for ${the_module}")
set(__module_headers ${OPENCV_MODULE_${the_module}_HEADERS})
list(SORT __module_headers) # fix headers order, useful for bindings
set(OPENCV_MODULE_${the_module}_HEADERS ${__module_headers} CACHE INTERNAL "List of header files for ${the_module}")
set(OPENCV_MODULE_${the_module}_SOURCES ${OPENCV_MODULE_${the_module}_SOURCES} CACHE INTERNAL "List of source files for ${the_module}")
# The condition we ought to be testing here is whether ocv_add_precompiled_headers will
-1
View File
@@ -122,7 +122,6 @@ function(ocv_pylint_finalize)
list(LENGTH PYLINT_TARGET_ID __total)
set(PYLINT_TOTAL_TARGETS "${__total}" CACHE INTERNAL "")
message(STATUS "Pylint: registered ${__total} targets. Build 'check_pylint' target to run checks (\"cmake --build . --target check_pylint\" or \"make check_pylint\")")
configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/pylint.cmake.in" "${CMAKE_BINARY_DIR}/pylint.cmake" @ONLY)
add_custom_target(check_pylint
+6
View File
@@ -255,6 +255,12 @@ PREDEFINED = __cplusplus=1 \
CV_DEFAULT(x)=" = x" \
CV_NEON=1 \
CV_SSE2=1 \
CV_SIMD128=1 \
CV_SIMD256=1 \
CV_SIMD512=1 \
CV_SIMD128_64F=1 \
CV_SIMD256_64F=1 \
CV_SIMD512_64F=1 \
CV__DEBUG_NS_BEGIN= \
CV__DEBUG_NS_END= \
CV_DEPRECATED_EXTERNAL= \
@@ -145,6 +145,7 @@ Building OpenCV.js from Source
python ./platforms/js/build_js.py build_js --cmake_option="-DOPENCV_EXTRA_MODULES_PATH=opencv_contrib/modules"
@endcode
Running OpenCV.js Tests
---------------------------------------
@@ -310,6 +311,12 @@ The example uses latest version of emscripten. If the build fails you should try
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk:2.0.10 emcmake python3 ./platforms/js/build_js.py build_js
@endcode
In Windows use the following PowerShell command:
@code{.bash}
docker run --rm --workdir /src -v "$(get-location):/src" "emscripten/emsdk:2.0.10" emcmake python3 ./platforms/js/build_js.py build_js
@endcode
### Building the documentation with Docker
To build the documentation `doxygen` needs to be installed. Create a file named `Dockerfile` with the following content:
+1 -1
View File
@@ -66,7 +66,7 @@ extension, its first version. A direct limitation of this is that you cannot sav
larger than 2 GB. Furthermore you can only create and expand a single video track inside the
container. No audio or other track editing support here. Nevertheless, any video codec present on
your system might work. If you encounter some of these limitations you will need to look into more
specialized video writing libraries such as *FFMpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As
specialized video writing libraries such as *FFmpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As
an alternative, create the video track with OpenCV and expand it with sound tracks or convert it to
other formats by using video manipulation programs such as *VirtualDub* or *AviSynth*.
Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

@@ -0,0 +1,140 @@
# Conversion of TensorFlow Detection Models and Launch with OpenCV Python {#tf_det_tutorial_dnn_conversion}
| | |
| -: | :- |
| Original author | Anastasia Murzova |
| Compatibility | OpenCV >= 4.5 |
## Goals
In this tutorial you will learn how to:
* obtain frozen graphs of TensorFlow (TF) detection models
* run converted TensorFlow model with OpenCV Python API
We will explore the above-listed points by the example of SSD MobileNetV1.
## Introduction
Let's briefly view the key concepts involved in the pipeline of TensorFlow models transition with OpenCV API. The initial step in the conversion of TensorFlow models into cv.dnn.Net
is obtaining the frozen TF model graph. A frozen graph defines the combination of the model graph structure with kept values of the required variables, for example, weights. The frozen graph is saved in [protobuf](https://en.wikipedia.org/wiki/Protocol_Buffers) (```.pb```) files.
There are special functions for reading ``.pb`` graphs in OpenCV: cv.dnn.readNetFromTensorflow and cv.dnn.readNet.
## Requirements
To be able to experiment with the below code you will need to install a set of libraries. We will use a virtual environment with python3.7+ for this:
```console
virtualenv -p /usr/bin/python3.7 <env_dir_path>
source <env_dir_path>/bin/activate
```
For OpenCV-Python building from source, follow the corresponding instructions from the @ref tutorial_py_table_of_contents_setup.
Before you start the installation of the libraries, you can customize the [requirements.txt](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/requirements.txt), excluding or including (for example, ``opencv-python``) some dependencies.
The below line initiates requirements installation into the previously activated virtual environment:
```console
pip install -r requirements.txt
```
## Practice
In this part we are going to cover the following points:
1. create a TF classification model conversion pipeline and provide the inference
2. provide the inference, process prediction results
### Model Preparation
The code in this subchapter is located in the ``samples/dnn/dnn_model_runner`` module and can be executed with the below line:
```console
python -m dnn_model_runner.dnn_conversion.tf.detection.py_to_py_ssd_mobilenet
```
The following code contains the steps of the TF SSD MobileNetV1 model retrieval:
```python
tf_model_name = 'ssd_mobilenet_v1_coco_2017_11_17'
graph_extraction_dir = "./"
frozen_graph_path = extract_tf_frozen_graph(tf_model_name, graph_extraction_dir)
print("Frozen graph path for {}: {}".format(tf_model_name, frozen_graph_path))
```
In ``extract_tf_frozen_graph`` function we extract the provided in model archive ``frozen_inference_graph.pb`` for its further processing:
```python
# define model archive name
tf_model_tar = model_name + '.tar.gz'
# define link to retrieve model archive
model_link = DETECTION_MODELS_URL + tf_model_tar
tf_frozen_graph_name = 'frozen_inference_graph'
try:
urllib.request.urlretrieve(model_link, tf_model_tar)
except Exception:
print("TF {} was not retrieved: {}".format(model_name, model_link))
return
print("TF {} was retrieved.".format(model_name))
tf_model_tar = tarfile.open(tf_model_tar)
frozen_graph_path = ""
for model_tar_elem in tf_model_tar.getmembers():
if tf_frozen_graph_name in os.path.basename(model_tar_elem.name):
tf_model_tar.extract(model_tar_elem, extracted_model_path)
frozen_graph_path = os.path.join(extracted_model_path, model_tar_elem.name)
break
tf_model_tar.close()
```
After the successful execution of the above code we will get the following output:
```console
TF ssd_mobilenet_v1_coco_2017_11_17 was retrieved.
Frozen graph path for ssd_mobilenet_v1_coco_2017_11_17: ./ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb
```
To provide model inference we will use the below [double-decker bus photo](https://www.pexels.com/photo/bus-and-car-on-one-way-street-3626589/) (under [Pexels](https://www.pexels.com/license/) license):
![Double-decker bus](images/pexels_double_decker_bus.jpg)
To initiate the test process we need to provide an appropriate model configuration. We will use [``ssd_mobilenet_v1_coco.config``](https://github.com/tensorflow/models/blob/master/research/object_detection/samples/configs/ssd_mobilenet_v1_coco.config) from [TensorFlow Object Detection API](https://github.com/tensorflow/models/tree/master/research/object_detection#tensorflow-object-detection-api).
TensorFlow Object Detection API framework contains helpful mechanisms for object detection model manipulations.
We will use this configuration to provide a text graph representation. To generate ``.pbtxt`` we will use the corresponding [``samples/dnn/tf_text_graph_ssd.py``](https://github.com/opencv/opencv/blob/master/samples/dnn/tf_text_graph_ssd.py) script:
```console
python tf_text_graph_ssd.py --input ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb --config ssd_mobilenet_v1_coco_2017_11_17/ssd_mobilenet_v1_coco.config --output ssd_mobilenet_v1_coco_2017_11_17.pbtxt
```
After successful execution ``ssd_mobilenet_v1_coco_2017_11_17.pbtxt`` will be created.
Before we run ``object_detection.py``, let's have a look at the default values for the SSD MobileNetV1 test process configuration. They are located in [``models.yml``](https://github.com/opencv/opencv/blob/master/samples/dnn/models.yml):
```yml
ssd_tf:
model: "ssd_mobilenet_v1_coco_2017_11_17.pb"
config: "ssd_mobilenet_v1_coco_2017_11_17.pbtxt"
mean: [0, 0, 0]
scale: 1.0
width: 300
height: 300
rgb: true
classes: "object_detection_classes_coco.txt"
sample: "object_detection"
```
To fetch these values we need to provide frozen graph ``ssd_mobilenet_v1_coco_2017_11_17.pb`` model and text graph ``ssd_mobilenet_v1_coco_2017_11_17.pbtxt``:
```console
python object_detection.py ssd_tf --input ../data/pexels_double_decker_bus.jpg
```
This line is equivalent to:
```console
python object_detection.py --model ssd_mobilenet_v1_coco_2017_11_17.pb --config ssd_mobilenet_v1_coco_2017_11_17.pbtxt --input ../data/pexels_double_decker_bus.jpg --width 300 --height 300 --classes ../data/dnn/object_detection_classes_coco.txt
```
The result is:
![OpenCV SSD bus result](images/opencv_bus_res.jpg)
There are several helpful parameters, which can be also customized for result corrections: threshold (``--thr``) and non-maximum suppression (``--nms``) values.
@@ -0,0 +1,332 @@
# Conversion of PyTorch Segmentation Models and Launch with OpenCV {#pytorch_segm_tutorial_dnn_conversion}
## Goals
In this tutorial you will learn how to:
* convert PyTorch segmentation models
* run converted PyTorch model with OpenCV
* obtain an evaluation of the PyTorch and OpenCV DNN models
We will explore the above-listed points by the example of the FCN ResNet-50 architecture.
## Introduction
The key points involved in the transition pipeline of the [PyTorch classification](https://link_to_cls_tutorial) and segmentation models with OpenCV API are equal. The first step is model transferring into [ONNX](https://onnx.ai/about.html) format with PyTorch [``torch.onnx.export``](https://pytorch.org/docs/stable/onnx.html#torch.onnx.export) built-in function.
Further the obtained ``.onnx`` model is passed into cv.dnn.readNetFromONNX, which returns cv.dnn.Net object ready for DNN manipulations.
## Practice
In this part we are going to cover the following points:
1. create a segmentation model conversion pipeline and provide the inference
2. evaluate and test segmentation models
If you'd like merely to run evaluation or test model pipelines, the "Model Conversion Pipeline" part can be skipped.
### Model Conversion Pipeline
The code in this subchapter is located in the ``dnn_model_runner`` module and can be executed with the line:
``
python -m dnn_model_runner.dnn_conversion.pytorch.segmentation.py_to_py_fcnresnet50
``
The following code contains the description of the below-listed steps:
1. instantiate PyTorch model
2. convert PyTorch model into ``.onnx``
3. read the transferred network with OpenCV API
4. prepare input data
5. provide inference
6. get colored masks from predictions
7. visualize results
```python
# initialize PyTorch FCN ResNet-50 model
original_model = models.segmentation.fcn_resnet50(pretrained=True)
# get the path to the converted into ONNX PyTorch model
full_model_path = get_pytorch_onnx_model(original_model)
# read converted .onnx model with OpenCV API
opencv_net = cv2.dnn.readNetFromONNX(full_model_path)
print("OpenCV model was successfully read. Layer IDs: \n", opencv_net.getLayerNames())
# get preprocessed image
img, input_img = get_processed_imgs("test_data/sem_segm/2007_000033.jpg")
# obtain OpenCV DNN predictions
opencv_prediction = get_opencv_dnn_prediction(opencv_net, input_img)
# obtain original PyTorch ResNet50 predictions
pytorch_prediction = get_pytorch_dnn_prediction(original_model, input_img)
pascal_voc_classes, pascal_voc_colors = read_colors_info("test_data/sem_segm/pascal-classes.txt")
# obtain colored segmentation masks
opencv_colored_mask = get_colored_mask(img.shape, opencv_prediction, pascal_voc_colors)
pytorch_colored_mask = get_colored_mask(img.shape, pytorch_prediction, pascal_voc_colors)
# obtain palette of PASCAL VOC colors
color_legend = get_legend(pascal_voc_classes, pascal_voc_colors)
cv2.imshow('PyTorch Colored Mask', pytorch_colored_mask)
cv2.imshow('OpenCV DNN Colored Mask', opencv_colored_mask)
cv2.imshow('Color Legend', color_legend)
cv2.waitKey(0)
```
To provide the model inference we will use the below picture from the [PASCAL VOC](http://host.robots.ox.ac.uk/pascal/VOC/) validation dataset:
![PASCAL VOC img](images/2007_000033.jpg)
The target segmented result is:
![PASCAL VOC ground truth](images/2007_000033.png)
For the PASCAL VOC colors decoding and its mapping with the predicted masks, we also need ``pascal-classes.txt`` file, which contains the full list of the PASCAL VOC classes and corresponding colors.
Let's go deeper into each code step by the example of pretrained PyTorch FCN ResNet-50:
* instantiate PyTorch FCN ResNet-50 model:
```python
# initialize PyTorch FCN ResNet-50 model
original_model = models.segmentation.fcn_resnet50(pretrained=True)
```
* convert PyTorch model into ONNX format:
```python
# define the directory for further converted model save
onnx_model_path = "models"
# define the name of further converted model
onnx_model_name = "fcnresnet50.onnx"
# create directory for further converted model
os.makedirs(onnx_model_path, exist_ok=True)
# get full path to the converted model
full_model_path = os.path.join(onnx_model_path, onnx_model_name)
# generate model input to build the graph
generated_input = Variable(
torch.randn(1, 3, 500, 500)
)
# model export into ONNX format
torch.onnx.export(
original_model,
generated_input,
full_model_path,
verbose=True,
input_names=["input"],
output_names=["output"],
opset_version=11
)
```
The code from this step does not differ from the classification conversion case. Thus, after the successful execution of the above code, we will get ``models/fcnresnet50.onnx``.
* read the transferred network with cv.dnn.readNetFromONNX passing the obtained in the previous step ONNX model into it:
```python
# read converted .onnx model with OpenCV API
opencv_net = cv2.dnn.readNetFromONNX(full_model_path)
```
* prepare input data:
```python
# read the image
input_img = cv2.imread(img_path, cv2.IMREAD_COLOR)
input_img = input_img.astype(np.float32)
# target image sizes
img_height = input_img.shape[0]
img_width = input_img.shape[1]
# define preprocess parameters
mean = np.array([0.485, 0.456, 0.406]) * 255.0
scale = 1 / 255.0
std = [0.229, 0.224, 0.225]
# prepare input blob to fit the model input:
# 1. subtract mean
# 2. scale to set pixel values from 0 to 1
input_blob = cv2.dnn.blobFromImage(
image=input_img,
scalefactor=scale,
size=(img_width, img_height), # img target size
mean=mean,
swapRB=True, # BGR -> RGB
crop=False # center crop
)
# 3. divide by std
input_blob[0] /= np.asarray(std, dtype=np.float32).reshape(3, 1, 1)
```
In this step we read the image and prepare model input with cv2.dnn.blobFromImage function, which returns 4-dimensional blob.
It should be noted that firstly in ``cv2.dnn.blobFromImage`` mean value is subtracted and only then pixel values are scaled. Thus, ``mean`` is multiplied by ``255.0`` to reproduce the original image preprocessing order:
```python
img /= 255.0
img -= [0.485, 0.456, 0.406]
img /= [0.229, 0.224, 0.225]
```
* OpenCV ``cv.dnn_Net`` inference:
```python
# set OpenCV DNN input
opencv_net.setInput(preproc_img)
# OpenCV DNN inference
out = opencv_net.forward()
print("OpenCV DNN segmentation prediction: \n")
print("* shape: ", out.shape)
# get IDs of predicted classes
out_predictions = np.argmax(out[0], axis=0)
```
After the above code execution we will get the following output:
```
OpenCV DNN segmentation prediction:
* shape: (1, 21, 500, 500)
```
Each prediction channel out of 21, where 21 represents the number of PASCAL VOC classes, contains probabilities, which indicate how likely the pixel corresponds to the PASCAL VOC class.
* PyTorch FCN ResNet-50 model inference:
```python
original_net.eval()
preproc_img = torch.FloatTensor(preproc_img)
with torch.no_grad():
# obtaining unnormalized probabilities for each class
out = original_net(preproc_img)['out']
print("\nPyTorch segmentation model prediction: \n")
print("* shape: ", out.shape)
# get IDs of predicted classes
out_predictions = out[0].argmax(dim=0)
```
After the above code launching we will get the following output:
```
PyTorch segmentation model prediction:
* shape: torch.Size([1, 21, 366, 500])
```
PyTorch prediction also contains probabilities corresponding to each class prediction.
* get colored masks from predictions:
```python
# convert mask values into PASCAL VOC colors
processed_mask = np.stack([colors[color_id] for color_id in segm_mask.flatten()])
# reshape mask into 3-channel image
processed_mask = processed_mask.reshape(mask_height, mask_width, 3)
processed_mask = cv2.resize(processed_mask, (img_width, img_height), interpolation=cv2.INTER_NEAREST).astype(
np.uint8)
# convert colored mask from BGR to RGB for compatibility with PASCAL VOC colors
processed_mask = cv2.cvtColor(processed_mask, cv2.COLOR_BGR2RGB)
```
In this step we map the probabilities from segmentation masks with appropriate colors of the predicted classes. Let's have a look at the results:
![OpenCV Colored Mask](images/legend_opencv_color_mask.png)
For the extended evaluation of the models, we can use ``py_to_py_segm`` script of the ``dnn_model_runner`` module. This module part will be described in the next subchapter.
### Evaluation of the Models
The proposed in ``dnn/samples`` ``dnn_model_runner`` module allows to run the full evaluation pipeline on the PASCAL VOC dataset and test execution for the following PyTorch segmentation models:
* FCN ResNet-50
* FCN ResNet-101
This list can be also extended with further appropriate evaluation pipeline configuration.
#### Evaluation Mode
The below line represents running of the module in the evaluation mode:
```
python -m dnn_model_runner.dnn_conversion.pytorch.segmentation.py_to_py_segm --model_name <pytorch_segm_model_name>
```
Chosen from the list segmentation model will be read into OpenCV ``cv.dnn_Net`` object. Evaluation results of PyTorch and OpenCV models (pixel accuracy, mean IoU, inference time) will be written into the log file. Inference time values will be also depicted in a chart to generalize the obtained model information.
Necessary evaluation configurations are defined in the [``test_config.py``](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py):
```python
@dataclass
class TestSegmConfig:
frame_size: int = 500
img_root_dir: str = "./VOC2012"
img_dir: str = os.path.join(img_root_dir, "JPEGImages/")
img_segm_gt_dir: str = os.path.join(img_root_dir, "SegmentationClass/")
# reduced val: https://github.com/shelhamer/fcn.berkeleyvision.org/blob/master/data/pascal/seg11valid.txt
segm_val_file: str = os.path.join(img_root_dir, "ImageSets/Segmentation/seg11valid.txt")
colour_file_cls: str = os.path.join(img_root_dir, "ImageSets/Segmentation/pascal-classes.txt")
```
These values can be modified in accordance with chosen model pipeline.
To initiate the evaluation of the PyTorch FCN ResNet-50, run the following line:
```
python -m dnn_model_runner.dnn_conversion.pytorch.segmentation.py_to_py_segm --model_name fcnresnet50
```
#### Test Mode
The below line represents running of the module in the test mode, which provides the steps for the model inference:
```
python -m dnn_model_runner.dnn_conversion.pytorch.segmentation.py_to_py_segm --model_name <pytorch_segm_model_name> --test True --default_img_preprocess <True/False> --evaluate False
```
Here ``default_img_preprocess`` key defines whether you'd like to parametrize the model test process with some particular values or use the default values, for example, ``scale``, ``mean`` or ``std``.
Test configuration is represented in [``test_config.py``](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py) ``TestSegmModuleConfig`` class:
```python
@dataclass
class TestSegmModuleConfig:
segm_test_data_dir: str = "test_data/sem_segm"
test_module_name: str = "segmentation"
test_module_path: str = "segmentation.py"
input_img: str = os.path.join(segm_test_data_dir, "2007_000033.jpg")
model: str = ""
frame_height: str = str(TestSegmConfig.frame_size)
frame_width: str = str(TestSegmConfig.frame_size)
scale: float = 1.0
mean: List[float] = field(default_factory=lambda: [0.0, 0.0, 0.0])
std: List[float] = field(default_factory=list)
crop: bool = False
rgb: bool = True
classes: str = os.path.join(segm_test_data_dir, "pascal-classes.txt")
```
The default image preprocessing options are defined in ``default_preprocess_config.py``:
```python
pytorch_segm_input_blob = {
"mean": ["123.675", "116.28", "103.53"],
"scale": str(1 / 255.0),
"std": ["0.229", "0.224", "0.225"],
"crop": "False",
"rgb": "True"
}
```
The basis of the model testing is represented in ``samples/dnn/segmentation.py``. ``segmentation.py`` can be executed autonomously with provided converted model in ``--input`` and populated parameters for ``cv2.dnn.blobFromImage``.
To reproduce from scratch the described in "Model Conversion Pipeline" OpenCV steps with ``dnn_model_runner`` execute the below line:
```
python -m dnn_model_runner.dnn_conversion.pytorch.segmentation.py_to_py_segm --model_name fcnresnet50 --test True --default_img_preprocess True --evaluate False
```
@@ -0,0 +1,406 @@
# Conversion of TensorFlow Segmentation Models and Launch with OpenCV {#tf_segm_tutorial_dnn_conversion}
## Goals
In this tutorial you will learn how to:
* convert TensorFlow (TF) segmentation models
* run converted TensorFlow model with OpenCV
* obtain an evaluation of the TensorFlow and OpenCV DNN models
We will explore the above-listed points by the example of the DeepLab architecture.
## Introduction
The key concepts involved in the transition pipeline of the [TensorFlow classification](https://link_to_cls_tutorial) and segmentation models with OpenCV API are almost equal excepting the phase of graph optimization. The initial step in conversion of TensorFlow models into cv.dnn.Net
is obtaining the frozen TF model graph. Frozen graph defines the combination of the model graph structure with kept values of the required variables, for example, weights. Usually the frozen graph is saved in [protobuf](https://en.wikipedia.org/wiki/Protocol_Buffers) (```.pb```) files.
To read the generated segmentation model ``.pb`` file with cv.dnn.readNetFromTensorflow, it is needed to modify the graph with TF [graph transform tool](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/graph_transforms).
## Practice
In this part we are going to cover the following points:
1. create a TF classification model conversion pipeline and provide the inference
2. evaluate and test TF classification models
If you'd like merely to run evaluation or test model pipelines, the "Model Conversion Pipeline" tutorial part can be skipped.
### Model Conversion Pipeline
The code in this subchapter is located in the ``dnn_model_runner`` module and can be executed with the line:
```
python -m dnn_model_runner.dnn_conversion.tf.segmentation.py_to_py_deeplab
```
TensorFlow segmentation models can be found in [TensorFlow Research Models](https://github.com/tensorflow/models/tree/master/research/#tensorflow-research-models) section, which contains the implementations of models on the basis of published research papers.
We will retrieve the archive with the pre-trained TF DeepLabV3 from the below link:
```
http://download.tensorflow.org/models/deeplabv3_mnv2_pascal_trainval_2018_01_29.tar.gz
```
The full frozen graph obtaining pipeline is described in ``deeplab_retrievement.py``:
```python
def get_deeplab_frozen_graph():
# define model path to download
models_url = 'http://download.tensorflow.org/models/'
mobilenetv2_voctrainval = 'deeplabv3_mnv2_pascal_trainval_2018_01_29.tar.gz'
# construct model link to download
model_link = models_url + mobilenetv2_voctrainval
try:
urllib.request.urlretrieve(model_link, mobilenetv2_voctrainval)
except Exception:
print("TF DeepLabV3 was not retrieved: {}".format(model_link))
return
tf_model_tar = tarfile.open(mobilenetv2_voctrainval)
# iterate the obtained model archive
for model_tar_elem in tf_model_tar.getmembers():
# check whether the model archive contains frozen graph
if TF_FROZEN_GRAPH_NAME in os.path.basename(model_tar_elem.name):
# extract frozen graph
tf_model_tar.extract(model_tar_elem, FROZEN_GRAPH_PATH)
tf_model_tar.close()
```
After running this script:
```
python -m dnn_model_runner.dnn_conversion.tf.segmentation.deeplab_retrievement
```
we will get ``frozen_inference_graph.pb`` in ``deeplab/deeplabv3_mnv2_pascal_trainval``.
Before going to the network loading with OpenCV it is needed to optimize the extracted ``frozen_inference_graph.pb``.
To optimize the graph we use TF ``TransformGraph`` with default parameters:
```python
DEFAULT_OPT_GRAPH_NAME = "optimized_frozen_inference_graph.pb"
DEFAULT_INPUTS = "sub_7"
DEFAULT_OUTPUTS = "ResizeBilinear_3"
DEFAULT_TRANSFORMS = "remove_nodes(op=Identity)" \
" merge_duplicate_nodes" \
" strip_unused_nodes" \
" fold_constants(ignore_errors=true)" \
" fold_batch_norms" \
" fold_old_batch_norms"
def optimize_tf_graph(
in_graph,
out_graph=DEFAULT_OPT_GRAPH_NAME,
inputs=DEFAULT_INPUTS,
outputs=DEFAULT_OUTPUTS,
transforms=DEFAULT_TRANSFORMS,
is_manual=True,
was_optimized=True
):
# ...
tf_opt_graph = TransformGraph(
tf_graph,
inputs,
outputs,
transforms
)
```
To run graph optimization process, execute the line:
```
python -m dnn_model_runner.dnn_conversion.tf.segmentation.tf_graph_optimizer --in_graph deeplab/deeplabv3_mnv2_pascal_trainval/frozen_inference_graph.pb
```
As a result ``deeplab/deeplabv3_mnv2_pascal_trainval`` directory will contain ``optimized_frozen_inference_graph.pb``.
After we have obtained the model graphs, let's examine the below-listed steps:
1. read TF ``frozen_inference_graph.pb`` graph
2. read optimized TF frozen graph with OpenCV API
3. prepare input data
4. provide inference
5. get colored masks from predictions
6. visualize results
```python
# get TF model graph from the obtained frozen graph
deeplab_graph = read_deeplab_frozen_graph(deeplab_frozen_graph_path)
# read DeepLab frozen graph with OpenCV API
opencv_net = cv2.dnn.readNetFromTensorflow(opt_deeplab_frozen_graph_path)
print("OpenCV model was successfully read. Model layers: \n", opencv_net.getLayerNames())
# get processed image
original_img_shape, tf_input_blob, opencv_input_img = get_processed_imgs("test_data/sem_segm/2007_000033.jpg")
# obtain OpenCV DNN predictions
opencv_prediction = get_opencv_dnn_prediction(opencv_net, opencv_input_img)
# obtain TF model predictions
tf_prediction = get_tf_dnn_prediction(deeplab_graph, tf_input_blob)
# get PASCAL VOC classes and colors
pascal_voc_classes, pascal_voc_colors = read_colors_info("test_data/sem_segm/pascal-classes.txt")
# obtain colored segmentation masks
opencv_colored_mask = get_colored_mask(original_img_shape, opencv_prediction, pascal_voc_colors)
tf_colored_mask = get_tf_colored_mask(original_img_shape, tf_prediction, pascal_voc_colors)
# obtain palette of PASCAL VOC colors
color_legend = get_legend(pascal_voc_classes, pascal_voc_colors)
cv2.imshow('TensorFlow Colored Mask', tf_colored_mask)
cv2.imshow('OpenCV DNN Colored Mask', opencv_colored_mask)
cv2.imshow('Color Legend', color_legend)
```
To provide the model inference we will use the below picture from the [PASCAL VOC](http://host.robots.ox.ac.uk/pascal/VOC/) validation dataset:
![PASCAL VOC img](images/2007_000033.jpg)
The target segmented result is:
![PASCAL VOC ground truth](images/2007_000033.png)
For the PASCAL VOC colors decoding and its mapping with the predicted masks, we also need ``pascal-classes.txt`` file, which contains the full list of the PASCAL VOC classes and corresponding colors.
Let's go deeper into each step by the example of pretrained TF DeepLabV3 MobileNetV2:
* read TF ``frozen_inference_graph.pb`` graph :
```python
# init deeplab model graph
model_graph = tf.Graph()
# obtain
with tf.io.gfile.GFile(frozen_graph_path, 'rb') as graph_file:
tf_model_graph = GraphDef()
tf_model_graph.ParseFromString(graph_file.read())
with model_graph.as_default():
tf.import_graph_def(tf_model_graph, name='')
```
* read optimized TF frozen graph with OpenCV API:
```python
# read DeepLab frozen graph with OpenCV API
opencv_net = cv2.dnn.readNetFromTensorflow(opt_deeplab_frozen_graph_path)
```
* prepare input data with cv2.dnn.blobFromImage function:
```python
# read the image
input_img = cv2.imread(img_path, cv2.IMREAD_COLOR)
input_img = input_img.astype(np.float32)
# preprocess image for TF model input
tf_preproc_img = cv2.resize(input_img, (513, 513))
tf_preproc_img = cv2.cvtColor(tf_preproc_img, cv2.COLOR_BGR2RGB)
# define preprocess parameters for OpenCV DNN
mean = np.array([1.0, 1.0, 1.0]) * 127.5
scale = 1 / 127.5
# prepare input blob to fit the model input:
# 1. subtract mean
# 2. scale to set pixel values from 0 to 1
input_blob = cv2.dnn.blobFromImage(
image=input_img,
scalefactor=scale,
size=(513, 513), # img target size
mean=mean,
swapRB=True, # BGR -> RGB
crop=False # center crop
)
```
Please, pay attention at the preprocessing order in the ``cv2.dnn.blobFromImage`` function. Firstly, the mean value is subtracted and only then pixel values are multiplied by the defined scale.
Therefore, to reproduce TF image preprocessing pipeline, we multiply ``mean`` by ``127.5``.
Another important point is image preprocessing for TF DeepLab. To pass the image into TF model we need only to construct an appropriate shape, the rest image preprocessing is described in [feature_extractor.py](https://github.com/tensorflow/models/blob/master/research/deeplab/core/feature_extractor.py) and will be invoked automatically.
* provide OpenCV ``cv.dnn_Net`` inference:
```python
# set OpenCV DNN input
opencv_net.setInput(preproc_img)
# OpenCV DNN inference
out = opencv_net.forward()
print("OpenCV DNN segmentation prediction: \n")
print("* shape: ", out.shape)
# get IDs of predicted classes
out_predictions = np.argmax(out[0], axis=0)
```
After the above code execution we will get the following output:
```
OpenCV DNN segmentation prediction:
* shape: (1, 21, 513, 513)
```
Each prediction channel out of 21, where 21 represents the number of PASCAL VOC classes, contains probabilities, which indicate how likely the pixel corresponds to the PASCAL VOC class.
* provide TF model inference:
```python
preproc_img = np.expand_dims(preproc_img, 0)
# init TF session
tf_session = Session(graph=model_graph)
input_tensor_name = "ImageTensor:0",
output_tensor_name = "SemanticPredictions:0"
# run inference
out = tf_session.run(
output_tensor_name,
feed_dict={input_tensor_name: [preproc_img]}
)
print("TF segmentation model prediction: \n")
print("* shape: ", out.shape)
```
TF inference results are the following:
```
TF segmentation model prediction:
* shape: (1, 513, 513)
```
TensorFlow prediction contains the indexes of corresponding PASCAL VOC classes.
* transform OpenCV prediction into colored mask:
```python
mask_height = segm_mask.shape[0]
mask_width = segm_mask.shape[1]
img_height = original_img_shape[0]
img_width = original_img_shape[1]
# convert mask values into PASCAL VOC colors
processed_mask = np.stack([colors[color_id] for color_id in segm_mask.flatten()])
# reshape mask into 3-channel image
processed_mask = processed_mask.reshape(mask_height, mask_width, 3)
processed_mask = cv2.resize(processed_mask, (img_width, img_height), interpolation=cv2.INTER_NEAREST).astype(
np.uint8)
# convert colored mask from BGR to RGB
processed_mask = cv2.cvtColor(processed_mask, cv2.COLOR_BGR2RGB)
```
In this step we map the probabilities from segmentation masks with appropriate colors of the predicted classes. Let's have a look at the results:
![Color Legend](images/colors_legend.png)
![OpenCV Colored Mask](images/deeplab_opencv_colored_mask.png)
* transform TF prediction into colored mask:
```python
colors = np.array(colors)
processed_mask = colors[segm_mask[0]]
img_height = original_img_shape[0]
img_width = original_img_shape[1]
processed_mask = cv2.resize(processed_mask, (img_width, img_height), interpolation=cv2.INTER_NEAREST).astype(
np.uint8)
# convert colored mask from BGR to RGB for compatibility with PASCAL VOC colors
processed_mask = cv2.cvtColor(processed_mask, cv2.COLOR_BGR2RGB)
```
The result is:
![TF Colored Mask](images/deeplab_tf_colored_mask.png)
As a result, we get two equal segmentation masks.
### Evaluation of the Models
The proposed in ``dnn/samples`` ``dnn_model_runner`` module allows to run the full evaluation pipeline on the PASCAL VOC dataset and test execution for the DeepLab MobileNet model.
#### Evaluation Mode
To below line represents running of the module in the evaluation mode:
```
python -m dnn_model_runner.dnn_conversion.tf.segmentation.py_to_py_segm
```
The model will be read into OpenCV ``cv.dnn_Net`` object. Evaluation results of TF and OpenCV models (pixel accuracy, mean IoU, inference time) will be written into the log file. Inference time values will be also depicted in a chart to generalize the obtained model information.
Necessary evaluation configurations are defined in the [``test_config.py``](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py):
```python
@dataclass
class TestSegmConfig:
frame_size: int = 500
img_root_dir: str = "./VOC2012"
img_dir: str = os.path.join(img_root_dir, "JPEGImages/")
img_segm_gt_dir: str = os.path.join(img_root_dir, "SegmentationClass/")
# reduced val: https://github.com/shelhamer/fcn.berkeleyvision.org/blob/master/data/pascal/seg11valid.txt
segm_val_file: str = os.path.join(img_root_dir, "ImageSets/Segmentation/seg11valid.txt")
colour_file_cls: str = os.path.join(img_root_dir, "ImageSets/Segmentation/pascal-classes.txt")
```
These values can be modified in accordance with chosen model pipeline.
#### Test Mode
The below line represents running of the module in the test mode, which provides the steps for the model inference:
```
python -m dnn_model_runner.dnn_conversion.tf.segmentation.py_to_py_segm --test True --default_img_preprocess <True/False> --evaluate False
```
Here ``default_img_preprocess`` key defines whether you'd like to parametrize the model test process with some particular values or use the default values, for example, ``scale``, ``mean`` or ``std``.
Test configuration is represented in [``test_config.py``](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py) ``TestSegmModuleConfig`` class:
```python
@dataclass
class TestSegmModuleConfig:
segm_test_data_dir: str = "test_data/sem_segm"
test_module_name: str = "segmentation"
test_module_path: str = "segmentation.py"
input_img: str = os.path.join(segm_test_data_dir, "2007_000033.jpg")
model: str = ""
frame_height: str = str(TestSegmConfig.frame_size)
frame_width: str = str(TestSegmConfig.frame_size)
scale: float = 1.0
mean: List[float] = field(default_factory=lambda: [0.0, 0.0, 0.0])
std: List[float] = field(default_factory=list)
crop: bool = False
rgb: bool = True
classes: str = os.path.join(segm_test_data_dir, "pascal-classes.txt")
```
The default image preprocessing options are defined in ``default_preprocess_config.py``:
```python
tf_segm_input_blob = {
"scale": str(1 / 127.5),
"mean": ["127.5", "127.5", "127.5"],
"std": [],
"crop": "False",
"rgb": "True"
}
```
The basis of the model testing is represented in ``samples/dnn/segmentation.py``. ``segmentation.py`` can be executed autonomously with provided converted model in ``--input`` and populated parameters for ``cv2.dnn.blobFromImage``.
To reproduce from scratch the described in "Model Conversion Pipeline" OpenCV steps with ``dnn_model_runner`` execute the below line:
```
python -m dnn_model_runner.dnn_conversion.tf.segmentation.py_to_py_segm --test True --default_img_preprocess True --evaluate False
```
@@ -15,7 +15,10 @@ Deep Neural Networks (dnn module) {#tutorial_table_of_content_dnn}
In this section you will find the guides, which describe how to run classification, segmentation and detection PyTorch DNN models with OpenCV.
- @subpage pytorch_cls_tutorial_dnn_conversion
- @subpage pytorch_cls_c_tutorial_dnn_conversion
- @subpage pytorch_segm_tutorial_dnn_conversion
#### TensorFlow models with OpenCV
In this section you will find the guides, which describe how to run classification, segmentation and detection TensorFlow DNN models with OpenCV.
- @subpage tf_cls_tutorial_dnn_conversion
- @subpage tf_det_tutorial_dnn_conversion
- @subpage tf_segm_tutorial_dnn_conversion
+4 -1
View File
@@ -3773,7 +3773,8 @@ namespace fisheye
CALIB_FIX_K4 = 1 << 7,
CALIB_FIX_INTRINSIC = 1 << 8,
CALIB_FIX_PRINCIPAL_POINT = 1 << 9,
CALIB_ZERO_DISPARITY = 1 << 10
CALIB_ZERO_DISPARITY = 1 << 10,
CALIB_FIX_FOCAL_LENGTH = 1 << 11
};
/** @brief Projects points using fisheye model
@@ -3927,6 +3928,8 @@ namespace fisheye
are set to zeros and stay zero.
- @ref fisheye::CALIB_FIX_PRINCIPAL_POINT The principal point is not changed during the global
optimization. It stays at the center or at a different location specified when @ref fisheye::CALIB_USE_INTRINSIC_GUESS is set too.
- @ref fisheye::CALIB_FIX_FOCAL_LENGTH The focal length is not changed during the global
optimization. It is the \f$max(width,height)/\pi\f$ or the provided \f$f_x\f$, \f$f_y\f$ when @ref fisheye::CALIB_USE_INTRINSIC_GUESS is set too.
@param criteria Termination criteria for the iterative optimization algorithm.
*/
CV_EXPORTS_W double calibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, const Size& image_size,
+1 -1
View File
@@ -1842,7 +1842,7 @@ void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags)
if (boardIdx != parentIdx && (boardIdx < 0 || contour_child_counter[boardIdx] < contour_child_counter[parentIdx]))
boardIdx = parentIdx;
contour_quads.push_back(QuadCountour(pt, parentIdx));
contour_quads.emplace_back(pt, parentIdx);
}
size_t total = contour_quads.size();
+1 -1
View File
@@ -78,7 +78,7 @@ static void icvGetQuadrangleHypotheses(const std::vector<std::vector< cv::Point
continue;
}
quads.push_back(std::pair<float, int>(box_size, class_id));
quads.emplace_back(box_size, class_id);
}
}
+31 -32
View File
@@ -384,15 +384,15 @@ void CirclesGridClusterFinder::rectifyPatternPoints(const std::vector<cv::Point2
{
//indices of corner points in pattern
std::vector<Point> trueIndices;
trueIndices.push_back(Point(0, 0));
trueIndices.push_back(Point(patternSize.width - 1, 0));
trueIndices.emplace_back(0, 0);
trueIndices.emplace_back(patternSize.width - 1, 0);
if(isAsymmetricGrid)
{
trueIndices.push_back(Point(patternSize.width - 1, 1));
trueIndices.push_back(Point(patternSize.width - 1, patternSize.height - 2));
trueIndices.emplace_back(patternSize.width - 1, 1);
trueIndices.emplace_back(patternSize.width - 1, patternSize.height - 2);
}
trueIndices.push_back(Point(patternSize.width - 1, patternSize.height - 1));
trueIndices.push_back(Point(0, patternSize.height - 1));
trueIndices.emplace_back(patternSize.width - 1, patternSize.height - 1);
trueIndices.emplace_back(0, patternSize.height - 1);
std::vector<Point2f> idealPoints;
for(size_t idx=0; idx<trueIndices.size(); idx++)
@@ -401,11 +401,11 @@ void CirclesGridClusterFinder::rectifyPatternPoints(const std::vector<cv::Point2
int j = trueIndices[idx].x;
if(isAsymmetricGrid)
{
idealPoints.push_back(Point2f((2*j + i % 2)*squareSize, i*squareSize));
idealPoints.emplace_back((2*j + i % 2)*squareSize, i*squareSize);
}
else
{
idealPoints.push_back(Point2f(j*squareSize, i*squareSize));
idealPoints.emplace_back(j*squareSize, i*squareSize);
}
}
@@ -477,7 +477,7 @@ void Graph::addVertex(size_t id)
{
CV_Assert( !doesVertexExist( id ) );
vertices.insert(std::pair<size_t, Vertex> (id, Vertex()));
vertices.emplace(id, Vertex());
}
void Graph::addEdge(size_t id1, size_t id2)
@@ -887,10 +887,9 @@ Mat CirclesGridFinder::rectifyGrid(Size detectedGridSize, const std::vector<Poin
convertPointsFromHomogeneous(dstKeypointsMat, dstKeypoints);
warpedKeypoints.clear();
for (size_t i = 0; i < dstKeypoints.size(); i++)
for (auto &pt:dstKeypoints)
{
Point2f pt = dstKeypoints[i];
warpedKeypoints.push_back(pt);
warpedKeypoints.emplace_back(std::move(pt));
}
return H;
@@ -1526,35 +1525,35 @@ void CirclesGridFinder::getCornerSegments(const std::vector<std::vector<size_t>
//all 8 segments with one end in a corner
std::vector<Segment> corner;
corner.push_back(Segment(keypoints[points[1][0]], keypoints[points[0][0]]));
corner.push_back(Segment(keypoints[points[0][0]], keypoints[points[0][1]]));
corner.emplace_back(keypoints[points[1][0]], keypoints[points[0][0]]);
corner.emplace_back(keypoints[points[0][0]], keypoints[points[0][1]]);
segments.push_back(corner);
cornerIndices.push_back(Point(0, 0));
firstSteps.push_back(Point(1, 0));
secondSteps.push_back(Point(0, 1));
cornerIndices.emplace_back(0, 0);
firstSteps.emplace_back(1, 0);
secondSteps.emplace_back(0, 1);
corner.clear();
corner.push_back(Segment(keypoints[points[0][w - 2]], keypoints[points[0][w - 1]]));
corner.push_back(Segment(keypoints[points[0][w - 1]], keypoints[points[1][w - 1]]));
corner.emplace_back(keypoints[points[0][w - 2]], keypoints[points[0][w - 1]]);
corner.emplace_back(keypoints[points[0][w - 1]], keypoints[points[1][w - 1]]);
segments.push_back(corner);
cornerIndices.push_back(Point(w - 1, 0));
firstSteps.push_back(Point(0, 1));
secondSteps.push_back(Point(-1, 0));
cornerIndices.emplace_back(w - 1, 0);
firstSteps.emplace_back(0, 1);
secondSteps.emplace_back(-1, 0);
corner.clear();
corner.push_back(Segment(keypoints[points[h - 2][w - 1]], keypoints[points[h - 1][w - 1]]));
corner.push_back(Segment(keypoints[points[h - 1][w - 1]], keypoints[points[h - 1][w - 2]]));
corner.emplace_back(keypoints[points[h - 2][w - 1]], keypoints[points[h - 1][w - 1]]);
corner.emplace_back(keypoints[points[h - 1][w - 1]], keypoints[points[h - 1][w - 2]]);
segments.push_back(corner);
cornerIndices.push_back(Point(w - 1, h - 1));
firstSteps.push_back(Point(-1, 0));
secondSteps.push_back(Point(0, -1));
cornerIndices.emplace_back(w - 1, h - 1);
firstSteps.emplace_back(-1, 0);
secondSteps.emplace_back(0, -1);
corner.clear();
corner.push_back(Segment(keypoints[points[h - 1][1]], keypoints[points[h - 1][0]]));
corner.push_back(Segment(keypoints[points[h - 1][0]], keypoints[points[h - 2][0]]));
cornerIndices.push_back(Point(0, h - 1));
firstSteps.push_back(Point(0, -1));
secondSteps.push_back(Point(1, 0));
corner.emplace_back(keypoints[points[h - 1][1]], keypoints[points[h - 1][0]]);
corner.emplace_back(keypoints[points[h - 1][0]], keypoints[points[h - 2][0]]);
cornerIndices.emplace_back(0, h - 1);
firstSteps.emplace_back(0, -1);
secondSteps.emplace_back(1, 0);
segments.push_back(corner);
corner.clear();
+2 -2
View File
@@ -754,8 +754,8 @@ double cv::fisheye::calibrate(InputArrayOfArrays objectPoints, InputArrayOfArray
IntrinsicParams currentParam;
IntrinsicParams errors;
finalParam.isEstimate[0] = 1;
finalParam.isEstimate[1] = 1;
finalParam.isEstimate[0] = flags & CALIB_FIX_FOCAL_LENGTH ? 0 : 1;
finalParam.isEstimate[1] = flags & CALIB_FIX_FOCAL_LENGTH ? 0 : 1;
finalParam.isEstimate[2] = flags & CALIB_FIX_PRINCIPAL_POINT ? 0 : 1;
finalParam.isEstimate[3] = flags & CALIB_FIX_PRINCIPAL_POINT ? 0 : 1;
finalParam.isEstimate[4] = flags & CALIB_FIX_SKEW ? 0 : 1;
+11 -3
View File
@@ -65,7 +65,8 @@ int solve_deg3(double a, double b, double c, double d,
return 3;
}
else {
x0 = pow(2 * R, 1 / 3.0) - b_a_3;
double cube_root = cv::cubeRoot(2 * R);
x0 = cube_root - b_a_3;
return 1;
}
}
@@ -82,8 +83,15 @@ int solve_deg3(double a, double b, double c, double d,
}
// D > 0, only one real root
double AD = pow(fabs(R) + sqrt(D), 1.0 / 3.0) * (R > 0 ? 1 : (R < 0 ? -1 : 0));
double BD = (AD == 0) ? 0 : -Q / AD;
double AD = 0.;
double BD = 0.;
double R_abs = fabs(R);
if (R_abs > DBL_EPSILON)
{
AD = cv::cubeRoot(R_abs + sqrt(D));
AD = (R >= 0) ? AD : -AD;
BD = -Q / AD;
}
// Calculate the only real root
x0 = AD + BD - b_a_3;
+29 -5
View File
@@ -334,18 +334,42 @@ bool solvePnPRansac(InputArray _opoints, InputArray _ipoints,
opoints_inliers.resize(npoints1);
ipoints_inliers.resize(npoints1);
result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix,
distCoeffs, rvec, tvec, useExtrinsicGuess,
(flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1;
try
{
result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix,
distCoeffs, rvec, tvec, useExtrinsicGuess,
(flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1;
}
catch (const cv::Exception& e)
{
if (flags == SOLVEPNP_ITERATIVE &&
npoints1 == 5 &&
e.what() &&
std::string(e.what()).find("DLT algorithm needs at least 6 points") != std::string::npos
)
{
CV_LOG_INFO(NULL, "solvePnPRansac(): solvePnP stage to compute the final pose using points "
"in the consensus set raised DLT 6 points exception, use result from MSS (Minimal Sample Sets) stage instead.");
rvec = _local_model.col(0); // output rotation vector
tvec = _local_model.col(1); // output translation vector
result = 1;
}
else
{
// raise other exceptions
throw;
}
}
if( result <= 0 )
if (result <= 0)
{
_rvec.assign(_local_model.col(0)); // output rotation vector
_tvec.assign(_local_model.col(1)); // output translation vector
if( _inliers.needed() )
if (_inliers.needed())
_inliers.release();
CV_LOG_DEBUG(NULL, "solvePnPRansac(): solvePnP stage to compute the final pose using points in the consensus set failed. Return false");
return false;
}
else
+4 -2
View File
@@ -1148,13 +1148,15 @@ class StereoBMImpl CV_FINAL : public StereoBM
{
public:
StereoBMImpl()
: params()
{
params = StereoBMParams();
// nothing
}
StereoBMImpl( int _numDisparities, int _SADWindowSize )
: params(_numDisparities, _SADWindowSize)
{
params = StereoBMParams(_numDisparities, _SADWindowSize);
// nothing
}
void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) CV_OVERRIDE
+7 -5
View File
@@ -2186,19 +2186,21 @@ class StereoSGBMImpl CV_FINAL : public StereoSGBM
{
public:
StereoSGBMImpl()
: params()
{
params = StereoSGBMParams();
// nothing
}
StereoSGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize,
int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap,
int _uniquenessRatio, int _speckleWindowSize, int _speckleRange,
int _mode )
: params(_minDisparity, _numDisparities, _SADWindowSize,
_P1, _P2, _disp12MaxDiff, _preFilterCap,
_uniquenessRatio, _speckleWindowSize, _speckleRange,
_mode)
{
params = StereoSGBMParams( _minDisparity, _numDisparities, _SADWindowSize,
_P1, _P2, _disp12MaxDiff, _preFilterCap,
_uniquenessRatio, _speckleWindowSize, _speckleRange,
_mode );
// nothing
}
void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) CV_OVERRIDE
+53 -5
View File
@@ -345,7 +345,7 @@ TEST_F(fisheyeTest, Calibration)
std::vector<std::vector<cv::Point2d> > imagePoints(n_images);
std::vector<std::vector<cv::Point3d> > objectPoints(n_images);
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
const std::string folder = combine(datasets_repository_path, "calib-3_stereo_from_JY");
cv::FileStorage fs_left(combine(folder, "left.xml"), cv::FileStorage::READ);
CV_Assert(fs_left.isOpened());
for(int i = 0; i < n_images; ++i)
@@ -373,6 +373,53 @@ TEST_F(fisheyeTest, Calibration)
EXPECT_MAT_NEAR(theD, this->D, 1e-10);
}
TEST_F(fisheyeTest, CalibrationWithFixedFocalLength)
{
const int n_images = 34;
std::vector<std::vector<cv::Point2d> > imagePoints(n_images);
std::vector<std::vector<cv::Point3d> > objectPoints(n_images);
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
cv::FileStorage fs_left(combine(folder, "left.xml"), cv::FileStorage::READ);
CV_Assert(fs_left.isOpened());
for(int i = 0; i < n_images; ++i)
fs_left[cv::format("image_%d", i )] >> imagePoints[i];
fs_left.release();
cv::FileStorage fs_object(combine(folder, "object.xml"), cv::FileStorage::READ);
CV_Assert(fs_object.isOpened());
for(int i = 0; i < n_images; ++i)
fs_object[cv::format("image_%d", i )] >> objectPoints[i];
fs_object.release();
int flag = 0;
flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
flag |= cv::fisheye::CALIB_CHECK_COND;
flag |= cv::fisheye::CALIB_FIX_SKEW;
flag |= cv::fisheye::CALIB_FIX_FOCAL_LENGTH;
flag |= cv::fisheye::CALIB_USE_INTRINSIC_GUESS;
cv::Matx33d theK = this->K;
const cv::Matx33d newK(
558.478088, 0.000000, 620.458461,
0.000000, 560.506767, 381.939362,
0.000000, 0.000000, 1.000000);
cv::Vec4d theD;
const cv::Vec4d newD(-0.001461, -0.003298, 0.006057, -0.003742);
cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, theK, theD,
cv::noArray(), cv::noArray(), flag, cv::TermCriteria(3, 20, 1e-6));
// ensure that CALIB_FIX_FOCAL_LENGTH works and focal lenght has not changed
EXPECT_EQ(theK(0,0), K(0,0));
EXPECT_EQ(theK(1,1), K(1,1));
EXPECT_MAT_NEAR(theK, newK, 1e-6);
EXPECT_MAT_NEAR(theD, newD, 1e-6);
}
TEST_F(fisheyeTest, Homography)
{
const int n_images = 1;
@@ -380,7 +427,7 @@ TEST_F(fisheyeTest, Homography)
std::vector<std::vector<cv::Point2d> > imagePoints(n_images);
std::vector<std::vector<cv::Point3d> > objectPoints(n_images);
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
const std::string folder = combine(datasets_repository_path, "calib-3_stereo_from_JY");
cv::FileStorage fs_left(combine(folder, "left.xml"), cv::FileStorage::READ);
CV_Assert(fs_left.isOpened());
for(int i = 0; i < n_images; ++i)
@@ -498,7 +545,7 @@ TEST_F(fisheyeTest, stereoRectify)
"For the purpose of continuity the following should be true: cv::CALIB_ZERO_DISPARITY == cv::fisheye::CALIB_ZERO_DISPARITY"
);
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
const std::string folder = combine(datasets_repository_path, "calib-3_stereo_from_JY");
cv::Size calibration_size = this->imageSize, requested_size = calibration_size;
cv::Matx33d K1 = this->K, K2 = K1;
@@ -599,7 +646,7 @@ TEST_F(fisheyeTest, stereoCalibrate)
{
const int n_images = 34;
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
const std::string folder = combine(datasets_repository_path, "calib-3_stereo_from_JY");
std::vector<std::vector<cv::Point2d> > leftPoints(n_images);
std::vector<std::vector<cv::Point2d> > rightPoints(n_images);
@@ -666,7 +713,7 @@ TEST_F(fisheyeTest, stereoCalibrateFixIntrinsic)
{
const int n_images = 34;
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
const std::string folder = combine(datasets_repository_path, "calib-3_stereo_from_JY");
std::vector<std::vector<cv::Point2d> > leftPoints(n_images);
std::vector<std::vector<cv::Point2d> > rightPoints(n_images);
@@ -822,6 +869,7 @@ const cv::Matx33d fisheyeTest::K(558.478087865323, 0, 620.45851536
const cv::Vec4d fisheyeTest::D(-0.0014613319981768, -0.00329861110580401, 0.00605760088590183, -0.00374209380722371);
const cv::Matx33d fisheyeTest::R ( 9.9756700084424932e-01, 6.9698277640183867e-02, 1.4929569991321144e-03,
-6.9711825162322980e-02, 9.9748249845531767e-01, 1.2997180766418455e-02,
-5.8331736398316541e-04,-1.3069635393884985e-02, 9.9991441852366736e-01);
@@ -837,6 +837,43 @@ TEST(Calib3d_SolvePnPRansac, double_support)
EXPECT_LE(cvtest::norm(t, Mat_<double>(tF), NORM_INF), 1e-3);
}
TEST(Calib3d_SolvePnPRansac, bad_input_points_19253)
{
// with this specific data
// when computing the final pose using points in the consensus set with SOLVEPNP_ITERATIVE and solvePnP()
// an exception is thrown from solvePnP because there are 5 non-coplanar 3D points and the DLT algorithm needs at least 6 non-coplanar 3D points
// with PR #19253 we choose to return true, with the pose estimated from the MSS stage instead of throwing the exception
float pts2d_[] = {
-5.38358629e-01f, -5.09638414e-02f,
-5.07192254e-01f, -2.20743284e-01f,
-5.43107152e-01f, -4.90474701e-02f,
-5.54325163e-01f, -1.86715424e-01f,
-5.59334219e-01f, -4.01909500e-02f,
-5.43504596e-01f, -4.61776406e-02f
};
Mat pts2d(6, 2, CV_32FC1, pts2d_);
float pts3d_[] = {
-3.01153604e-02f, -1.55665115e-01f, 4.50000018e-01f,
4.27827090e-01f, 4.28645730e-01f, 1.08600008e+00f,
-3.14165242e-02f, -1.52656138e-01f, 4.50000018e-01f,
-1.46217480e-01f, 5.57961613e-02f, 7.17000008e-01f,
-4.89348806e-02f, -1.38795510e-01f, 4.47000027e-01f,
-3.13065052e-02f, -1.52636901e-01f, 4.51000035e-01f
};
Mat pts3d(6, 3, CV_32FC1, pts3d_);
Mat camera_mat = Mat::eye(3, 3, CV_64FC1);
Mat rvec, tvec;
vector<int> inliers;
// solvePnPRansac will return true with 5 inliers, which means the result is from MSS stage.
bool result = solvePnPRansac(pts3d, pts2d, camera_mat, noArray(), rvec, tvec, false, 100, 4.f / 460.f, 0.99, inliers);
EXPECT_EQ(inliers.size(), size_t(5));
EXPECT_TRUE(result);
}
TEST(Calib3d_SolvePnP, input_type)
{
Matx33d intrinsics(5.4794130238156129e+002, 0., 2.9835545700043139e+002, 0.,
+5 -1
View File
@@ -18,8 +18,12 @@ ocv_add_dispatched_file_force_all(test_intrin256 TEST AVX2 AVX512_SKX)
ocv_add_dispatched_file_force_all(test_intrin512 TEST AVX512_SKX)
set(PARALLEL_ENABLE_PLUGINS_DEFAULT ON)
if(EMSCRIPTEN OR IOS OR WINRT)
set(PARALLEL_ENABLE_PLUGINS_DEFAULT OFF)
endif()
# parallel backends configuration
set(PARALLEL_ENABLE_PLUGINS "ON" CACHE BOOL "Allow building parallel plugin support")
set(PARALLEL_ENABLE_PLUGINS "${PARALLEL_ENABLE_PLUGINS_DEFAULT}" CACHE BOOL "Allow building parallel plugin support")
# TODO building plugins with OpenCV is not supported yet
#set(PARALLEL_PLUGIN_LIST "" CACHE STRING "List of parallel backends to be compiled as plugins (tbb, openmp or special value 'all')")
#string(REPLACE "," ";" PARALLEL_PLUGIN_LIST "${PARALLEL_PLUGIN_LIST}") # support comma-separated list (,) too
@@ -538,6 +538,16 @@ _AccTp normInf(const _Tp* a, const _Tp* b, int n)
*/
CV_EXPORTS_W float cubeRoot(float val);
/** @overload
cubeRoot with argument of `double` type calls `std::cbrt(double)`
*/
static inline
double cubeRoot(double val)
{
return std::cbrt(val);
}
/** @brief Calculates the angle of a 2D vector in degrees.
The function fastAtan2 calculates the full-range angle of an input 2D vector. The angle is measured
@@ -7,6 +7,7 @@
#include <opencv2/core/async.hpp>
#include <opencv2/core/detail/async_promise.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <stdexcept>
@@ -144,7 +145,30 @@ AsyncArray testAsyncException()
return p.getArrayResult();
}
//! @}
}} // namespace
namespace fs {
CV_EXPORTS_W cv::String getCacheDirectoryForDownloads();
} // namespace fs
//! @} // core_utils
} // namespace cv::utils
//! @cond IGNORED
CV_WRAP static inline
int setLogLevel(int level)
{
// NB: Binding generators doesn't work with enums properly yet, so we define separate overload here
return cv::utils::logging::setLogLevel((cv::utils::logging::LogLevel)level);
}
CV_WRAP static inline
int getLogLevel()
{
return cv::utils::logging::getLogLevel();
}
//! @endcond IGNORED
} // namespaces cv / utils
#endif // OPENCV_CORE_BINDINGS_UTILS_HPP
@@ -76,6 +76,9 @@
#if defined __PPC64__ && defined __GNUC__ && defined _ARCH_PWR8 \
&& !defined(OPENCV_SKIP_INCLUDE_ALTIVEC_H)
#include <altivec.h>
#undef vector
#undef bool
#undef pixel
#endif
#if defined(CV_INLINE_ROUND_FLT)
+251 -73
View File
@@ -104,7 +104,7 @@ template<typename _Tp> struct V_TypeTraits
{
};
#define CV_INTRIN_DEF_TYPE_TRAITS(type, int_type_, uint_type_, abs_type_, w_type_, q_type_, sum_type_, nlanes128_) \
#define CV_INTRIN_DEF_TYPE_TRAITS(type, int_type_, uint_type_, abs_type_, w_type_, q_type_, sum_type_) \
template<> struct V_TypeTraits<type> \
{ \
typedef type value_type; \
@@ -114,7 +114,6 @@ template<typename _Tp> struct V_TypeTraits
typedef w_type_ w_type; \
typedef q_type_ q_type; \
typedef sum_type_ sum_type; \
enum { nlanes128 = nlanes128_ }; \
\
static inline int_type reinterpret_int(type x) \
{ \
@@ -131,7 +130,7 @@ template<typename _Tp> struct V_TypeTraits
} \
}
#define CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(type, int_type_, uint_type_, abs_type_, w_type_, sum_type_, nlanes128_) \
#define CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(type, int_type_, uint_type_, abs_type_, w_type_, sum_type_) \
template<> struct V_TypeTraits<type> \
{ \
typedef type value_type; \
@@ -140,7 +139,6 @@ template<typename _Tp> struct V_TypeTraits
typedef uint_type_ uint_type; \
typedef w_type_ w_type; \
typedef sum_type_ sum_type; \
enum { nlanes128 = nlanes128_ }; \
\
static inline int_type reinterpret_int(type x) \
{ \
@@ -157,16 +155,16 @@ template<typename _Tp> struct V_TypeTraits
} \
}
CV_INTRIN_DEF_TYPE_TRAITS(uchar, schar, uchar, uchar, ushort, unsigned, unsigned, 16);
CV_INTRIN_DEF_TYPE_TRAITS(schar, schar, uchar, uchar, short, int, int, 16);
CV_INTRIN_DEF_TYPE_TRAITS(ushort, short, ushort, ushort, unsigned, uint64, unsigned, 8);
CV_INTRIN_DEF_TYPE_TRAITS(short, short, ushort, ushort, int, int64, int, 8);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(unsigned, int, unsigned, unsigned, uint64, unsigned, 4);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int, int, unsigned, unsigned, int64, int, 4);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(float, int, unsigned, float, double, float, 4);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(uint64, int64, uint64, uint64, void, uint64, 2);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int64, int64, uint64, uint64, void, int64, 2);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(double, int64, uint64, double, void, double, 2);
CV_INTRIN_DEF_TYPE_TRAITS(uchar, schar, uchar, uchar, ushort, unsigned, unsigned);
CV_INTRIN_DEF_TYPE_TRAITS(schar, schar, uchar, uchar, short, int, int);
CV_INTRIN_DEF_TYPE_TRAITS(ushort, short, ushort, ushort, unsigned, uint64, unsigned);
CV_INTRIN_DEF_TYPE_TRAITS(short, short, ushort, ushort, int, int64, int);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(unsigned, int, unsigned, unsigned, uint64, unsigned);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int, int, unsigned, unsigned, int64, int);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(float, int, unsigned, float, double, float);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(uint64, int64, uint64, uint64, void, uint64);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int64, int64, uint64, uint64, void, int64);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(double, int64, uint64, double, void, double);
#ifndef CV_DOXYGEN
@@ -314,54 +312,6 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
//==================================================================================================
#define CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
inline vtyp vx_setall_##short_typ(typ v) { return prefix##_setall_##short_typ(v); } \
inline vtyp vx_setzero_##short_typ() { return prefix##_setzero_##short_typ(); } \
inline vtyp vx_##loadsfx(const typ* ptr) { return prefix##_##loadsfx(ptr); } \
inline vtyp vx_##loadsfx##_aligned(const typ* ptr) { return prefix##_##loadsfx##_aligned(ptr); } \
inline vtyp vx_##loadsfx##_low(const typ* ptr) { return prefix##_##loadsfx##_low(ptr); } \
inline vtyp vx_##loadsfx##_halves(const typ* ptr0, const typ* ptr1) { return prefix##_##loadsfx##_halves(ptr0, ptr1); } \
inline void vx_store(typ* ptr, const vtyp& v) { return v_store(ptr, v); } \
inline void vx_store_aligned(typ* ptr, const vtyp& v) { return v_store_aligned(ptr, v); } \
inline vtyp vx_lut(const typ* ptr, const int* idx) { return prefix##_lut(ptr, idx); } \
inline vtyp vx_lut_pairs(const typ* ptr, const int* idx) { return prefix##_lut_pairs(ptr, idx); }
#define CV_INTRIN_DEFINE_WIDE_LUT_QUAD(typ, vtyp, prefix) \
inline vtyp vx_lut_quads(const typ* ptr, const int* idx) { return prefix##_lut_quads(ptr, idx); }
#define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
inline wtyp vx_load_expand(const typ* ptr) { return prefix##_load_expand(ptr); }
#define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND_Q(typ, qtyp, prefix) \
inline qtyp vx_load_expand_q(const typ* ptr) { return prefix##_load_expand_q(ptr); }
#define CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(typ, vtyp, short_typ, wtyp, qtyp, prefix, loadsfx) \
CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(typ, vtyp, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND_Q(typ, qtyp, prefix)
#define CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(uchar, v_uint8, u8, v_uint16, v_uint32, prefix, load) \
CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(schar, v_int8, s8, v_int16, v_int32, prefix, load) \
CV_INTRIN_DEFINE_WIDE_INTRIN(ushort, v_uint16, u16, prefix, load) \
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(ushort, v_uint16, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(ushort, v_uint32, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(short, v_int16, s16, prefix, load) \
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(short, v_int16, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(short, v_int32, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(int, v_int32, s32, prefix, load) \
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(int, v_int32, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(int, v_int64, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(unsigned, v_uint32, u32, prefix, load) \
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(unsigned, v_uint32, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(unsigned, v_uint64, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(float, v_float32, f32, prefix, load) \
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(float, v_float32, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(int64, v_int64, s64, prefix, load) \
CV_INTRIN_DEFINE_WIDE_INTRIN(uint64, v_uint64, u64, prefix, load) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(float16_t, v_float32, prefix)
template<typename _Tp> struct V_RegTraits
{
};
@@ -421,6 +371,7 @@ template<typename _Tp> struct V_RegTraits
CV_DEF_REG_TRAITS(v512, v_int64x8, int64, s64, v_uint64x8, void, void, v_int64x8, void);
CV_DEF_REG_TRAITS(v512, v_float64x8, double, f64, v_float64x8, void, void, v_int64x8, v_int32x16);
#endif
//! @endcond
#if CV_SIMD512 && (!defined(CV__SIMD_FORCE_WIDTH) || CV__SIMD_FORCE_WIDTH == 512)
#define CV__SIMD_NAMESPACE simd512
@@ -429,21 +380,33 @@ namespace CV__SIMD_NAMESPACE {
#define CV_SIMD_64F CV_SIMD512_64F
#define CV_SIMD_FP16 CV_SIMD512_FP16
#define CV_SIMD_WIDTH 64
//! @addtogroup core_hal_intrin
//! @{
//! @brief Maximum available vector register capacity 8-bit unsigned integer values
typedef v_uint8x64 v_uint8;
//! @brief Maximum available vector register capacity 8-bit signed integer values
typedef v_int8x64 v_int8;
//! @brief Maximum available vector register capacity 16-bit unsigned integer values
typedef v_uint16x32 v_uint16;
//! @brief Maximum available vector register capacity 16-bit signed integer values
typedef v_int16x32 v_int16;
//! @brief Maximum available vector register capacity 32-bit unsigned integer values
typedef v_uint32x16 v_uint32;
//! @brief Maximum available vector register capacity 32-bit signed integer values
typedef v_int32x16 v_int32;
//! @brief Maximum available vector register capacity 64-bit unsigned integer values
typedef v_uint64x8 v_uint64;
//! @brief Maximum available vector register capacity 64-bit signed integer values
typedef v_int64x8 v_int64;
//! @brief Maximum available vector register capacity 32-bit floating point values (single precision)
typedef v_float32x16 v_float32;
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v512)
#if CV_SIMD512_64F
#if CV_SIMD512_64F
//! @brief Maximum available vector register capacity 64-bit floating point values (double precision)
typedef v_float64x8 v_float64;
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v512, load)
#endif
inline void vx_cleanup() { v512_cleanup(); }
#endif
//! @}
#define VXPREFIX(func) v512##func
} // namespace
using namespace CV__SIMD_NAMESPACE;
#elif CV_SIMD256 && (!defined(CV__SIMD_FORCE_WIDTH) || CV__SIMD_FORCE_WIDTH == 256)
@@ -453,21 +416,33 @@ namespace CV__SIMD_NAMESPACE {
#define CV_SIMD_64F CV_SIMD256_64F
#define CV_SIMD_FP16 CV_SIMD256_FP16
#define CV_SIMD_WIDTH 32
//! @addtogroup core_hal_intrin
//! @{
//! @brief Maximum available vector register capacity 8-bit unsigned integer values
typedef v_uint8x32 v_uint8;
//! @brief Maximum available vector register capacity 8-bit signed integer values
typedef v_int8x32 v_int8;
//! @brief Maximum available vector register capacity 16-bit unsigned integer values
typedef v_uint16x16 v_uint16;
//! @brief Maximum available vector register capacity 16-bit signed integer values
typedef v_int16x16 v_int16;
//! @brief Maximum available vector register capacity 32-bit unsigned integer values
typedef v_uint32x8 v_uint32;
//! @brief Maximum available vector register capacity 32-bit signed integer values
typedef v_int32x8 v_int32;
//! @brief Maximum available vector register capacity 64-bit unsigned integer values
typedef v_uint64x4 v_uint64;
//! @brief Maximum available vector register capacity 64-bit signed integer values
typedef v_int64x4 v_int64;
//! @brief Maximum available vector register capacity 32-bit floating point values (single precision)
typedef v_float32x8 v_float32;
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v256)
#if CV_SIMD256_64F
//! @brief Maximum available vector register capacity 64-bit floating point values (double precision)
typedef v_float64x4 v_float64;
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v256, load)
#endif
inline void vx_cleanup() { v256_cleanup(); }
//! @}
#define VXPREFIX(func) v256##func
} // namespace
using namespace CV__SIMD_NAMESPACE;
#elif (CV_SIMD128 || CV_SIMD128_CPP) && (!defined(CV__SIMD_FORCE_WIDTH) || CV__SIMD_FORCE_WIDTH == 128)
@@ -480,25 +455,228 @@ namespace CV__SIMD_NAMESPACE {
#define CV_SIMD CV_SIMD128
#define CV_SIMD_64F CV_SIMD128_64F
#define CV_SIMD_WIDTH 16
//! @addtogroup core_hal_intrin
//! @{
//! @brief Maximum available vector register capacity 8-bit unsigned integer values
typedef v_uint8x16 v_uint8;
//! @brief Maximum available vector register capacity 8-bit signed integer values
typedef v_int8x16 v_int8;
//! @brief Maximum available vector register capacity 16-bit unsigned integer values
typedef v_uint16x8 v_uint16;
//! @brief Maximum available vector register capacity 16-bit signed integer values
typedef v_int16x8 v_int16;
//! @brief Maximum available vector register capacity 32-bit unsigned integer values
typedef v_uint32x4 v_uint32;
//! @brief Maximum available vector register capacity 32-bit signed integer values
typedef v_int32x4 v_int32;
//! @brief Maximum available vector register capacity 64-bit unsigned integer values
typedef v_uint64x2 v_uint64;
//! @brief Maximum available vector register capacity 64-bit signed integer values
typedef v_int64x2 v_int64;
//! @brief Maximum available vector register capacity 32-bit floating point values (single precision)
typedef v_float32x4 v_float32;
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v)
#if CV_SIMD128_64F
//! @brief Maximum available vector register capacity 64-bit floating point values (double precision)
typedef v_float64x2 v_float64;
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v, load)
#endif
inline void vx_cleanup() { v_cleanup(); }
//! @}
#define VXPREFIX(func) v##func
} // namespace
using namespace CV__SIMD_NAMESPACE;
#endif
namespace CV__SIMD_NAMESPACE {
//! @addtogroup core_hal_intrin
//! @{
//! @name Wide init with value
//! @{
//! @brief Create maximum available capacity vector with elements set to a specific value
inline v_uint8 vx_setall_u8(uchar v) { return VXPREFIX(_setall_u8)(v); }
inline v_int8 vx_setall_s8(schar v) { return VXPREFIX(_setall_s8)(v); }
inline v_uint16 vx_setall_u16(ushort v) { return VXPREFIX(_setall_u16)(v); }
inline v_int16 vx_setall_s16(short v) { return VXPREFIX(_setall_s16)(v); }
inline v_int32 vx_setall_s32(int v) { return VXPREFIX(_setall_s32)(v); }
inline v_uint32 vx_setall_u32(unsigned v) { return VXPREFIX(_setall_u32)(v); }
inline v_float32 vx_setall_f32(float v) { return VXPREFIX(_setall_f32)(v); }
inline v_int64 vx_setall_s64(int64 v) { return VXPREFIX(_setall_s64)(v); }
inline v_uint64 vx_setall_u64(uint64 v) { return VXPREFIX(_setall_u64)(v); }
#if CV_SIMD_64F
inline v_float64 vx_setall_f64(double v) { return VXPREFIX(_setall_f64)(v); }
#endif
//! @}
//! @name Wide init with zero
//! @{
//! @brief Create maximum available capacity vector with elements set to zero
inline v_uint8 vx_setzero_u8() { return VXPREFIX(_setzero_u8)(); }
inline v_int8 vx_setzero_s8() { return VXPREFIX(_setzero_s8)(); }
inline v_uint16 vx_setzero_u16() { return VXPREFIX(_setzero_u16)(); }
inline v_int16 vx_setzero_s16() { return VXPREFIX(_setzero_s16)(); }
inline v_int32 vx_setzero_s32() { return VXPREFIX(_setzero_s32)(); }
inline v_uint32 vx_setzero_u32() { return VXPREFIX(_setzero_u32)(); }
inline v_float32 vx_setzero_f32() { return VXPREFIX(_setzero_f32)(); }
inline v_int64 vx_setzero_s64() { return VXPREFIX(_setzero_s64)(); }
inline v_uint64 vx_setzero_u64() { return VXPREFIX(_setzero_u64)(); }
#if CV_SIMD_64F
inline v_float64 vx_setzero_f64() { return VXPREFIX(_setzero_f64)(); }
#endif
//! @}
//! @name Wide load from memory
//! @{
//! @brief Load maximum available capacity register contents from memory
inline v_uint8 vx_load(const uchar * ptr) { return VXPREFIX(_load)(ptr); }
inline v_int8 vx_load(const schar * ptr) { return VXPREFIX(_load)(ptr); }
inline v_uint16 vx_load(const ushort * ptr) { return VXPREFIX(_load)(ptr); }
inline v_int16 vx_load(const short * ptr) { return VXPREFIX(_load)(ptr); }
inline v_int32 vx_load(const int * ptr) { return VXPREFIX(_load)(ptr); }
inline v_uint32 vx_load(const unsigned * ptr) { return VXPREFIX(_load)(ptr); }
inline v_float32 vx_load(const float * ptr) { return VXPREFIX(_load)(ptr); }
inline v_int64 vx_load(const int64 * ptr) { return VXPREFIX(_load)(ptr); }
inline v_uint64 vx_load(const uint64 * ptr) { return VXPREFIX(_load)(ptr); }
#if CV_SIMD_64F
inline v_float64 vx_load(const double * ptr) { return VXPREFIX(_load)(ptr); }
#endif
//! @}
//! @name Wide load from memory(aligned)
//! @{
//! @brief Load maximum available capacity register contents from memory(aligned)
inline v_uint8 vx_load_aligned(const uchar * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_int8 vx_load_aligned(const schar * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_uint16 vx_load_aligned(const ushort * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_int16 vx_load_aligned(const short * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_int32 vx_load_aligned(const int * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_uint32 vx_load_aligned(const unsigned * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_float32 vx_load_aligned(const float * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_int64 vx_load_aligned(const int64 * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_uint64 vx_load_aligned(const uint64 * ptr) { return VXPREFIX(_load_aligned)(ptr); }
#if CV_SIMD_64F
inline v_float64 vx_load_aligned(const double * ptr) { return VXPREFIX(_load_aligned)(ptr); }
#endif
//! @}
//! @name Wide load lower half from memory
//! @{
//! @brief Load lower half of maximum available capacity register from memory
inline v_uint8 vx_load_low(const uchar * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_int8 vx_load_low(const schar * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_uint16 vx_load_low(const ushort * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_int16 vx_load_low(const short * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_int32 vx_load_low(const int * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_uint32 vx_load_low(const unsigned * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_float32 vx_load_low(const float * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_int64 vx_load_low(const int64 * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_uint64 vx_load_low(const uint64 * ptr) { return VXPREFIX(_load_low)(ptr); }
#if CV_SIMD_64F
inline v_float64 vx_load_low(const double * ptr) { return VXPREFIX(_load_low)(ptr); }
#endif
//! @}
//! @name Wide load halfs from memory
//! @{
//! @brief Load maximum available capacity register contents from two memory blocks
inline v_uint8 vx_load_halves(const uchar * ptr0, const uchar * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_int8 vx_load_halves(const schar * ptr0, const schar * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_uint16 vx_load_halves(const ushort * ptr0, const ushort * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_int16 vx_load_halves(const short * ptr0, const short * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_int32 vx_load_halves(const int * ptr0, const int * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_uint32 vx_load_halves(const unsigned * ptr0, const unsigned * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_float32 vx_load_halves(const float * ptr0, const float * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_int64 vx_load_halves(const int64 * ptr0, const int64 * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_uint64 vx_load_halves(const uint64 * ptr0, const uint64 * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
#if CV_SIMD_64F
inline v_float64 vx_load_halves(const double * ptr0, const double * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
#endif
//! @}
//! @name Wide LUT of elements
//! @{
//! @brief Load maximum available capacity register contents with array elements by provided indexes
inline v_uint8 vx_lut(const uchar * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_int8 vx_lut(const schar * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_uint16 vx_lut(const ushort * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_int16 vx_lut(const short* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_int32 vx_lut(const int* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_uint32 vx_lut(const unsigned* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_float32 vx_lut(const float* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_int64 vx_lut(const int64 * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_uint64 vx_lut(const uint64 * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
#if CV_SIMD_64F
inline v_float64 vx_lut(const double* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
#endif
//! @}
//! @name Wide LUT of element pairs
//! @{
//! @brief Load maximum available capacity register contents with array element pairs by provided indexes
inline v_uint8 vx_lut_pairs(const uchar * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_int8 vx_lut_pairs(const schar * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_uint16 vx_lut_pairs(const ushort * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_int16 vx_lut_pairs(const short* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_int32 vx_lut_pairs(const int* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_uint32 vx_lut_pairs(const unsigned* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_float32 vx_lut_pairs(const float* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_int64 vx_lut_pairs(const int64 * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_uint64 vx_lut_pairs(const uint64 * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
#if CV_SIMD_64F
inline v_float64 vx_lut_pairs(const double* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
#endif
//! @}
//! @name Wide LUT of element quads
//! @{
//! @brief Load maximum available capacity register contents with array element quads by provided indexes
inline v_uint8 vx_lut_quads(const uchar* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_int8 vx_lut_quads(const schar* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_uint16 vx_lut_quads(const ushort* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_int16 vx_lut_quads(const short* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_int32 vx_lut_quads(const int* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_uint32 vx_lut_quads(const unsigned* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_float32 vx_lut_quads(const float* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
//! @}
//! @name Wide load with double expansion
//! @{
//! @brief Load maximum available capacity register contents from memory with double expand
inline v_uint16 vx_load_expand(const uchar * ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_int16 vx_load_expand(const schar * ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_uint32 vx_load_expand(const ushort * ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_int32 vx_load_expand(const short* ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_int64 vx_load_expand(const int* ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_uint64 vx_load_expand(const unsigned* ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_float32 vx_load_expand(const float16_t * ptr) { return VXPREFIX(_load_expand)(ptr); }
//! @}
//! @name Wide load with quad expansion
//! @{
//! @brief Load maximum available capacity register contents from memory with quad expand
inline v_uint32 vx_load_expand_q(const uchar * ptr) { return VXPREFIX(_load_expand_q)(ptr); }
inline v_int32 vx_load_expand_q(const schar * ptr) { return VXPREFIX(_load_expand_q)(ptr); }
//! @}
/** @brief SIMD processing state cleanup call */
inline void vx_cleanup() { VXPREFIX(_cleanup)(); }
//! @cond IGNORED
// backward compatibility
template<typename _Tp, typename _Tvec> static inline
void vx_store(_Tp* dst, const _Tvec& v) { return v_store(dst, v); }
// backward compatibility
template<typename _Tp, typename _Tvec> static inline
void vx_store_aligned(_Tp* dst, const _Tvec& v) { return v_store_aligned(dst, v); }
//! @endcond
//! @}
#undef VXPREFIX
} // namespace
//! @cond IGNORED
#ifndef CV_SIMD_64F
#define CV_SIMD_64F 0
#endif
File diff suppressed because it is too large Load Diff
@@ -1539,6 +1539,26 @@ OPENCV_HAL_IMPL_NEON_SELECT(v_float32x4, f32, u32)
OPENCV_HAL_IMPL_NEON_SELECT(v_float64x2, f64, u64)
#endif
#if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_EXPAND(_Tpvec, _Tpwvec, _Tp, suffix) \
inline void v_expand(const _Tpvec& a, _Tpwvec& b0, _Tpwvec& b1) \
{ \
b0.val = vmovl_##suffix(vget_low_##suffix(a.val)); \
b1.val = vmovl_high_##suffix(a.val); \
} \
inline _Tpwvec v_expand_low(const _Tpvec& a) \
{ \
return _Tpwvec(vmovl_##suffix(vget_low_##suffix(a.val))); \
} \
inline _Tpwvec v_expand_high(const _Tpvec& a) \
{ \
return _Tpwvec(vmovl_high_##suffix(a.val)); \
} \
inline _Tpwvec v_load_expand(const _Tp* ptr) \
{ \
return _Tpwvec(vmovl_##suffix(vld1_##suffix(ptr))); \
}
#else
#define OPENCV_HAL_IMPL_NEON_EXPAND(_Tpvec, _Tpwvec, _Tp, suffix) \
inline void v_expand(const _Tpvec& a, _Tpwvec& b0, _Tpwvec& b1) \
{ \
@@ -1557,6 +1577,7 @@ inline _Tpwvec v_load_expand(const _Tp* ptr) \
{ \
return _Tpwvec(vmovl_##suffix(vld1_##suffix(ptr))); \
}
#endif
OPENCV_HAL_IMPL_NEON_EXPAND(v_uint8x16, v_uint16x8, uchar, u8)
OPENCV_HAL_IMPL_NEON_EXPAND(v_int8x16, v_int16x8, schar, s8)
+12 -12
View File
@@ -576,24 +576,24 @@ CV_ENUM_FLAGS(UMatData::MemoryFlag)
struct CV_EXPORTS MatSize
{
explicit MatSize(int* _p);
int dims() const;
explicit MatSize(int* _p) CV_NOEXCEPT;
int dims() const CV_NOEXCEPT;
Size operator()() const;
const int& operator[](int i) const;
int& operator[](int i);
operator const int*() const; // TODO OpenCV 4.0: drop this
bool operator == (const MatSize& sz) const;
bool operator != (const MatSize& sz) const;
operator const int*() const CV_NOEXCEPT; // TODO OpenCV 4.0: drop this
bool operator == (const MatSize& sz) const CV_NOEXCEPT;
bool operator != (const MatSize& sz) const CV_NOEXCEPT;
int* p;
};
struct CV_EXPORTS MatStep
{
MatStep();
explicit MatStep(size_t s);
const size_t& operator[](int i) const;
size_t& operator[](int i);
MatStep() CV_NOEXCEPT;
explicit MatStep(size_t s) CV_NOEXCEPT;
const size_t& operator[](int i) const CV_NOEXCEPT;
size_t& operator[](int i) CV_NOEXCEPT;
operator size_t() const;
MatStep& operator = (size_t s);
@@ -807,7 +807,7 @@ public:
The constructed matrix can further be assigned to another matrix or matrix expression or can be
allocated with Mat::create . In the former case, the old content is de-referenced.
*/
Mat();
Mat() CV_NOEXCEPT;
/** @overload
@param rows Number of rows in a 2D array.
@@ -2193,7 +2193,7 @@ public:
typedef MatConstIterator_<_Tp> const_iterator;
//! default constructor
Mat_();
Mat_() CV_NOEXCEPT;
//! equivalent to Mat(_rows, _cols, DataType<_Tp>::type)
Mat_(int _rows, int _cols);
//! constructor that sets each matrix element to specified value
@@ -2385,7 +2385,7 @@ class CV_EXPORTS UMat
{
public:
//! default constructor
UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT);
UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT) CV_NOEXCEPT;
//! constructs 2D matrix of the specified size and type
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
@@ -1116,11 +1116,11 @@ void Mat::push_back(const std::vector<_Tp>& v)
///////////////////////////// MatSize ////////////////////////////
inline
MatSize::MatSize(int* _p)
MatSize::MatSize(int* _p) CV_NOEXCEPT
: p(_p) {}
inline
int MatSize::dims() const
int MatSize::dims() const CV_NOEXCEPT
{
return (p - 1)[0];
}
@@ -1153,13 +1153,13 @@ int& MatSize::operator[](int i)
}
inline
MatSize::operator const int*() const
MatSize::operator const int*() const CV_NOEXCEPT
{
return p;
}
inline
bool MatSize::operator != (const MatSize& sz) const
bool MatSize::operator != (const MatSize& sz) const CV_NOEXCEPT
{
return !(*this == sz);
}
@@ -1169,25 +1169,25 @@ bool MatSize::operator != (const MatSize& sz) const
///////////////////////////// MatStep ////////////////////////////
inline
MatStep::MatStep()
MatStep::MatStep() CV_NOEXCEPT
{
p = buf; p[0] = p[1] = 0;
}
inline
MatStep::MatStep(size_t s)
MatStep::MatStep(size_t s) CV_NOEXCEPT
{
p = buf; p[0] = s; p[1] = 0;
}
inline
const size_t& MatStep::operator[](int i) const
const size_t& MatStep::operator[](int i) const CV_NOEXCEPT
{
return p[i];
}
inline
size_t& MatStep::operator[](int i)
size_t& MatStep::operator[](int i) CV_NOEXCEPT
{
return p[i];
}
@@ -1210,7 +1210,7 @@ inline MatStep& MatStep::operator = (size_t s)
////////////////////////////// Mat_<_Tp> ////////////////////////////
template<typename _Tp> inline
Mat_<_Tp>::Mat_()
Mat_<_Tp>::Mat_() CV_NOEXCEPT
: Mat()
{
flags = (flags & ~CV_MAT_TYPE_MASK) + traits::Type<_Tp>::value;
@@ -8,7 +8,7 @@
#define CV_VERSION_MAJOR 4
#define CV_VERSION_MINOR 5
#define CV_VERSION_REVISION 2
#define CV_VERSION_STATUS "-openvino"
#define CV_VERSION_STATUS ""
#define CVAUX_STR_EXP(__A) #__A
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
@@ -497,11 +497,13 @@ VSX_IMPL_CONV_EVEN_2_4(vec_uint4, vec_double2, vec_ctu, vec_ctuo)
VSX_FINLINE(rt) fnm(const rg& a, int only_truncate) \
{ \
assert(only_truncate == 0); \
CV_UNUSED(only_truncate); \
CV_UNUSED(only_truncate); \
return fn2(a); \
}
VSX_IMPL_CONV_2VARIANT(vec_int4, vec_float4, vec_cts, vec_cts)
VSX_IMPL_CONV_2VARIANT(vec_uint4, vec_float4, vec_ctu, vec_ctu)
VSX_IMPL_CONV_2VARIANT(vec_float4, vec_int4, vec_ctf, vec_ctf)
VSX_IMPL_CONV_2VARIANT(vec_float4, vec_uint4, vec_ctf, vec_ctf)
// define vec_cts for converting double precision to signed doubleword
// which isn't compatible with xlc but its okay since Eigen only uses it for gcc
VSX_IMPL_CONV_2VARIANT(vec_dword2, vec_double2, vec_cts, vec_ctsl)
+2 -1
View File
@@ -627,7 +627,8 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst,
(kind1 == _InputArray::MATX && (sz1 == Size(1,4) || sz1 == Size(1,1))) ||
(kind2 == _InputArray::MATX && (sz2 == Size(1,4) || sz2 == Size(1,1))) )
{
if( checkScalar(*psrc1, type2, kind1, kind2) )
if ((type1 == CV_64F && (sz1.height == 1 || sz1.height == 4)) &&
checkScalar(*psrc1, type2, kind1, kind2))
{
// src1 is a scalar; swap it with src2
swap(psrc1, psrc2);
+13
View File
@@ -5,6 +5,8 @@
#include "precomp.hpp"
#include "opencv2/core/bindings_utils.hpp"
#include <sstream>
#include <opencv2/core/utils/filesystem.hpp>
#include <opencv2/core/utils/filesystem.private.hpp>
namespace cv { namespace utils {
@@ -208,4 +210,15 @@ CV_EXPORTS_W String dumpInputOutputArrayOfArrays(InputOutputArrayOfArrays argume
return ss.str();
}
namespace fs {
cv::String getCacheDirectoryForDownloads()
{
#if OPENCV_HAVE_FILESYSTEM_SUPPORT
return cv::utils::fs::getCacheDirectory("downloads", "OPENCV_DOWNLOADS_CACHE_DIR");
#else
CV_Error(Error::StsNotImplemented, "File system support is disabled in this OpenCV build!");
#endif
}
} // namespace fs
}} // namespace
+2 -2
View File
@@ -1050,7 +1050,7 @@ bool ocl_convert_nv12_to_bgr(
k.args(clImageY, clImageUV, clBuffer, step, cols, rows);
size_t globalsize[] = { (size_t)cols, (size_t)rows };
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
return k.run(2, globalsize, 0, false);
}
@@ -1071,7 +1071,7 @@ bool ocl_convert_bgr_to_nv12(
k.args(clBuffer, step, cols, rows, clImageY, clImageUV);
size_t globalsize[] = { (size_t)cols, (size_t)rows };
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
return k.run(2, globalsize, 0, false);
}
+22 -1
View File
@@ -7,6 +7,10 @@
#include "mathfuncs_core.simd.hpp"
#include "mathfuncs_core.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
#define IPP_DISABLE_MAGNITUDE_32F 1 // accuracy: https://github.com/opencv/opencv/issues/19506
namespace cv { namespace hal {
///////////////////////////////////// ATAN2 ////////////////////////////////////
@@ -44,8 +48,25 @@ void magnitude32f(const float* x, const float* y, float* mag, int len)
CV_INSTRUMENT_REGION();
CALL_HAL(magnitude32f, cv_hal_magnitude32f, x, y, mag, len);
#ifdef HAVE_IPP
bool allowIPP = true;
#ifdef IPP_DISABLE_MAGNITUDE_32F
if (cv::ipp::getIppTopFeatures() & (
#if IPP_VERSION_X100 >= 201700
ippCPUID_AVX512F |
#endif
ippCPUID_AVX2)
)
{
allowIPP = (len & 7) == 0;
}
#endif
// SSE42 performance issues
CV_IPP_RUN(IPP_VERSION_X100 > 201800 || cv::ipp::getIppTopFeatures() != ippCPUID_SSE42, CV_INSTRUMENT_FUN_IPP(ippsMagnitude_32f, x, y, mag, len) >= 0);
CV_IPP_RUN((IPP_VERSION_X100 > 201800 || cv::ipp::getIppTopFeatures() != ippCPUID_SSE42) && allowIPP,
CV_INSTRUMENT_FUN_IPP(ippsMagnitude_32f, x, y, mag, len) >= 0);
#endif
CV_CPU_DISPATCH(magnitude32f, (x, y, mag, len),
CV_CPU_DISPATCH_MODES_ALL);
+2 -2
View File
@@ -204,7 +204,7 @@ MatAllocator* Mat::getStdAllocator()
//==================================================================================================
bool MatSize::operator==(const MatSize& sz) const
bool MatSize::operator==(const MatSize& sz) const CV_NOEXCEPT
{
int d = dims();
int dsz = sz.dims();
@@ -337,7 +337,7 @@ void finalizeHdr(Mat& m)
//======================================= Mat ======================================================
Mat::Mat()
Mat::Mat() CV_NOEXCEPT
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
datalimit(0), allocator(0), u(0), size(&rows), step(0)
{}
+4 -4
View File
@@ -536,8 +536,8 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size,
{
v_int32 t0 = vx_load((int*)(src0 + i));
v_int32 t1 = vx_load((int*)(src1 + i));
vx_store((int*)(dst0 + i), t1);
vx_store((int*)(dst1 + i), t0);
v_store((int*)(dst0 + i), t1);
v_store((int*)(dst1 + i), t0);
}
}
#if CV_STRONG_ALIGNMENT
@@ -547,8 +547,8 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size,
{
v_uint8 t0 = vx_load(src0 + i);
v_uint8 t1 = vx_load(src1 + i);
vx_store(dst0 + i, t1);
vx_store(dst1 + i, t0);
v_store(dst0 + i, t1);
v_store(dst1 + i, t0);
}
}
#endif
+41 -51
View File
@@ -91,63 +91,50 @@ void YUV2BGR_NV12_8u(
{
int x = get_global_id(0);
int y = get_global_id(1);
// each iteration computes 2*2=4 pixels
int x2 = x*2;
int y2 = y*2;
if (x + 1 < cols)
{
if (y + 1 < rows)
{
__global uchar* pDstRow1 = pBGR + mad24(y, bgrStep, mad24(x, NCHANNELS, 0));
__global uchar* pDstRow2 = pDstRow1 + bgrStep;
if (x2 + 1 < cols) {
if (y2 + 1 < rows) {
__global uchar *pDstRow1 = pBGR + mad24(y2, bgrStep, mad24(x2, NCHANNELS, 0));
__global uchar *pDstRow2 = pDstRow1 + bgrStep;
float4 Y1 = read_imagef(imgY, (int2)(x+0, y+0));
float4 Y2 = read_imagef(imgY, (int2)(x+1, y+0));
float4 Y3 = read_imagef(imgY, (int2)(x+0, y+1));
float4 Y4 = read_imagef(imgY, (int2)(x+1, y+1));
float4 Y1 = read_imagef(imgY, (int2)(x2 + 0, y2 + 0));
float4 Y2 = read_imagef(imgY, (int2)(x2 + 1, y2 + 0));
float4 Y3 = read_imagef(imgY, (int2)(x2 + 0, y2 + 1));
float4 Y4 = read_imagef(imgY, (int2)(x2 + 1, y2 + 1));
float4 Y = (float4)(Y1.x, Y2.x, Y3.x, Y4.x);
float4 UV = read_imagef(imgUV, (int2)(x/2, y/2)) - d2;
float4 UV = read_imagef(imgUV, (int2)(x, y)) - d2;
__constant float* coeffs = c_YUV2RGBCoeffs_420;
__constant float *coeffs = c_YUV2RGBCoeffs_420;
Y1 = max(0.f, Y1 - d1) * coeffs[0];
Y2 = max(0.f, Y2 - d1) * coeffs[0];
Y3 = max(0.f, Y3 - d1) * coeffs[0];
Y4 = max(0.f, Y4 - d1) * coeffs[0];
Y = max(0.f, Y - d1) * coeffs[0];
float ruv = fma(coeffs[4], UV.y, 0.0f);
float guv = fma(coeffs[3], UV.y, fma(coeffs[2], UV.x, 0.0f));
float buv = fma(coeffs[1], UV.x, 0.0f);
float R1 = (Y1.x + ruv) * CV_8U_MAX;
float G1 = (Y1.x + guv) * CV_8U_MAX;
float B1 = (Y1.x + buv) * CV_8U_MAX;
float4 R = (Y + ruv) * CV_8U_MAX;
float4 G = (Y + guv) * CV_8U_MAX;
float4 B = (Y + buv) * CV_8U_MAX;
float R2 = (Y2.x + ruv) * CV_8U_MAX;
float G2 = (Y2.x + guv) * CV_8U_MAX;
float B2 = (Y2.x + buv) * CV_8U_MAX;
pDstRow1[0*NCHANNELS + 0] = convert_uchar_sat(B.x);
pDstRow1[0*NCHANNELS + 1] = convert_uchar_sat(G.x);
pDstRow1[0*NCHANNELS + 2] = convert_uchar_sat(R.x);
float R3 = (Y3.x + ruv) * CV_8U_MAX;
float G3 = (Y3.x + guv) * CV_8U_MAX;
float B3 = (Y3.x + buv) * CV_8U_MAX;
pDstRow1[1*NCHANNELS + 0] = convert_uchar_sat(B.y);
pDstRow1[1*NCHANNELS + 1] = convert_uchar_sat(G.y);
pDstRow1[1*NCHANNELS + 2] = convert_uchar_sat(R.y);
float R4 = (Y4.x + ruv) * CV_8U_MAX;
float G4 = (Y4.x + guv) * CV_8U_MAX;
float B4 = (Y4.x + buv) * CV_8U_MAX;
pDstRow2[0*NCHANNELS + 0] = convert_uchar_sat(B.z);
pDstRow2[0*NCHANNELS + 1] = convert_uchar_sat(G.z);
pDstRow2[0*NCHANNELS + 2] = convert_uchar_sat(R.z);
pDstRow1[0*NCHANNELS + 0] = convert_uchar_sat(B1);
pDstRow1[0*NCHANNELS + 1] = convert_uchar_sat(G1);
pDstRow1[0*NCHANNELS + 2] = convert_uchar_sat(R1);
pDstRow1[1*NCHANNELS + 0] = convert_uchar_sat(B2);
pDstRow1[1*NCHANNELS + 1] = convert_uchar_sat(G2);
pDstRow1[1*NCHANNELS + 2] = convert_uchar_sat(R2);
pDstRow2[0*NCHANNELS + 0] = convert_uchar_sat(B3);
pDstRow2[0*NCHANNELS + 1] = convert_uchar_sat(G3);
pDstRow2[0*NCHANNELS + 2] = convert_uchar_sat(R3);
pDstRow2[1*NCHANNELS + 0] = convert_uchar_sat(B4);
pDstRow2[1*NCHANNELS + 1] = convert_uchar_sat(G4);
pDstRow2[1*NCHANNELS + 2] = convert_uchar_sat(R4);
pDstRow2[1*NCHANNELS + 0] = convert_uchar_sat(B.w);
pDstRow2[1*NCHANNELS + 1] = convert_uchar_sat(G.w);
pDstRow2[1*NCHANNELS + 2] = convert_uchar_sat(R.w);
}
}
}
@@ -172,12 +159,15 @@ void BGR2YUV_NV12_8u(
{
int x = get_global_id(0);
int y = get_global_id(1);
// each iteration computes 2*2=4 pixels
int x2 = x*2;
int y2 = y*2;
if (x < cols)
if (x2 + 1 < cols)
{
if (y < rows)
if (y2 + 1 < rows)
{
__global const uchar* pSrcRow1 = pBGR + mad24(y, bgrStep, mad24(x, NCHANNELS, 0));
__global const uchar* pSrcRow1 = pBGR + mad24(y2, bgrStep, mad24(x2, NCHANNELS, 0));
__global const uchar* pSrcRow2 = pSrcRow1 + bgrStep;
float4 src_pix1 = convert_float4(vload4(0, pSrcRow1 + 0*NCHANNELS)) * CV_8U_SCALE;
@@ -196,12 +186,12 @@ void BGR2YUV_NV12_8u(
UV.x = fma(coeffs[3], src_pix1.z, fma(coeffs[4], src_pix1.y, fma(coeffs[5], src_pix1.x, d2)));
UV.y = fma(coeffs[5], src_pix1.z, fma(coeffs[6], src_pix1.y, fma(coeffs[7], src_pix1.x, d2)));
write_imagef(imgY, (int2)(x+0, y+0), Y1);
write_imagef(imgY, (int2)(x+1, y+0), Y2);
write_imagef(imgY, (int2)(x+0, y+1), Y3);
write_imagef(imgY, (int2)(x+1, y+1), Y4);
write_imagef(imgY, (int2)(x2+0, y2+0), Y1);
write_imagef(imgY, (int2)(x2+1, y2+0), Y2);
write_imagef(imgY, (int2)(x2+0, y2+1), Y3);
write_imagef(imgY, (int2)(x2+1, y2+1), Y4);
write_imagef(imgUV, (int2)((x/2), (y/2)), UV);
write_imagef(imgUV, (int2)(x, y), UV);
}
}
}
+5 -1
View File
@@ -63,7 +63,11 @@ std::shared_ptr<ParallelForAPI> createParallelForAPI()
try
{
CV_LOG_DEBUG(NULL, "core(parallel): trying backend: " << info.name << " (priority=" << info.priority << ")");
CV_Assert(info.backendFactory);
if (!info.backendFactory)
{
CV_LOG_DEBUG(NULL, "core(parallel): factory is not available (plugins require filesystem support): " << info.name);
continue;
}
std::shared_ptr<ParallelForAPI> backend = info.backendFactory->create();
if (!backend)
{
@@ -6,17 +6,23 @@
// Not a standalone header, part of parallel.cpp
//
#include "opencv2/core/utils/filesystem.private.hpp" // OPENCV_HAVE_FILESYSTEM_SUPPORT
namespace cv { namespace parallel {
#if OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(PARALLEL_ENABLE_PLUGINS)
#define DECLARE_DYNAMIC_BACKEND(name) \
ParallelBackendInfo { \
1000, name, createPluginParallelBackendFactory(name) \
}
},
#else
#define DECLARE_DYNAMIC_BACKEND(name) /* nothing */
#endif
#define DECLARE_STATIC_BACKEND(name, createBackendAPI) \
ParallelBackendInfo { \
1000, name, std::make_shared<cv::parallel::StaticBackendFactory>([=] () -> std::shared_ptr<cv::parallel::ParallelForAPI> { return createBackendAPI(); }) \
}
},
static
std::vector<ParallelBackendInfo>& getBuiltinParallelBackendsInfo()
@@ -24,14 +30,14 @@ std::vector<ParallelBackendInfo>& getBuiltinParallelBackendsInfo()
static std::vector<ParallelBackendInfo> g_backends
{
#ifdef HAVE_TBB
DECLARE_STATIC_BACKEND("TBB", createParallelBackendTBB),
DECLARE_STATIC_BACKEND("TBB", createParallelBackendTBB)
#elif defined(PARALLEL_ENABLE_PLUGINS)
DECLARE_DYNAMIC_BACKEND("ONETBB"), // dedicated oneTBB plugin (interface >= 12000, binary incompatibe with TBB 2017-2020)
DECLARE_DYNAMIC_BACKEND("TBB"), // generic TBB plugins
DECLARE_DYNAMIC_BACKEND("ONETBB") // dedicated oneTBB plugin (interface >= 12000, binary incompatibe with TBB 2017-2020)
DECLARE_DYNAMIC_BACKEND("TBB") // generic TBB plugins
#endif
#ifdef HAVE_OPENMP
DECLARE_STATIC_BACKEND("OPENMP", createParallelBackendOpenMP),
DECLARE_STATIC_BACKEND("OPENMP", createParallelBackendOpenMP)
#elif defined(PARALLEL_ENABLE_PLUGINS)
DECLARE_DYNAMIC_BACKEND("OPENMP") // TODO Intel OpenMP?
#endif
+24 -11
View File
@@ -128,11 +128,14 @@ void* allocSingletonNewBuffer(size_t size) { return malloc(size); }
#endif
#if CV_VSX && defined __linux__
#if (defined __ppc64__ || defined __PPC64__) && defined __linux__
# include "sys/auxv.h"
# ifndef AT_HWCAP2
# define AT_HWCAP2 26
# endif
# ifndef PPC_FEATURE2_ARCH_2_07
# define PPC_FEATURE2_ARCH_2_07 0x80000000
# endif
# ifndef PPC_FEATURE2_ARCH_3_00
# define PPC_FEATURE2_ARCH_3_00 0x00800000
# endif
@@ -345,7 +348,6 @@ struct HWFeatures
HWFeatures(bool run_initialize = false)
{
memset( have, 0, sizeof(have[0]) * MAX_FEATURE );
if (run_initialize)
initialize();
}
@@ -589,14 +591,25 @@ struct HWFeatures
#ifdef __mips_msa
have[CV_CPU_MSA] = true;
#endif
// there's no need to check VSX availability in runtime since it's always available on ppc64le CPUs
have[CV_CPU_VSX] = (CV_VSX);
// TODO: Check VSX3 availability in runtime for other platforms
#if CV_VSX && defined __linux__
uint64 hwcap2 = getauxval(AT_HWCAP2);
have[CV_CPU_VSX3] = (hwcap2 & PPC_FEATURE2_ARCH_3_00);
#if (defined __ppc64__ || defined __PPC64__) && defined __linux__
unsigned int hwcap = getauxval(AT_HWCAP);
if (hwcap & PPC_FEATURE_HAS_VSX) {
hwcap = getauxval(AT_HWCAP2);
if (hwcap & PPC_FEATURE2_ARCH_3_00) {
have[CV_CPU_VSX] = have[CV_CPU_VSX3] = true;
} else {
have[CV_CPU_VSX] = (hwcap & PPC_FEATURE2_ARCH_2_07) != 0;
}
}
#else
have[CV_CPU_VSX3] = (CV_VSX3);
// TODO: AIX, FreeBSD
#if CV_VSX || defined _ARCH_PWR8 || defined __POWER9_VECTOR__
have[CV_CPU_VSX] = true;
#endif
#if CV_VSX3 || defined __POWER9_VECTOR__
have[CV_CPU_VSX3] = true;
#endif
#endif
#if defined __riscv && defined __riscv_vector
@@ -730,7 +743,7 @@ struct HWFeatures
}
}
bool have[MAX_FEATURE+1];
bool have[MAX_FEATURE+1]{};
};
static HWFeatures featuresEnabled(true), featuresDisabled = HWFeatures(false);
@@ -1862,7 +1875,7 @@ class ParseError
{
std::string bad_value;
public:
ParseError(const std::string bad_value_) :bad_value(bad_value_) {}
ParseError(const std::string &bad_value_) :bad_value(bad_value_) {}
std::string toString(const std::string &param) const
{
std::ostringstream out;
+1 -1
View File
@@ -230,7 +230,7 @@ UMatDataAutoLock::~UMatDataAutoLock()
//////////////////////////////// UMat ////////////////////////////////
UMat::UMat(UMatUsageFlags _usageFlags)
UMat::UMat(UMatUsageFlags _usageFlags) CV_NOEXCEPT
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
{}
+2 -2
View File
@@ -189,7 +189,7 @@ static bool ocl_convert_nv12_to_bgr(cl_mem clImageY, cl_mem clImageUV, cl_mem cl
k.args(clImageY, clImageUV, clBuffer, step, cols, rows);
size_t globalsize[] = { (size_t)cols, (size_t)rows };
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
return k.run(2, globalsize, 0, false);
}
@@ -202,7 +202,7 @@ static bool ocl_convert_bgr_to_nv12(cl_mem clBuffer, int step, int cols, int row
k.args(clBuffer, step, cols, rows, clImageY, clImageUV);
size_t globalsize[] = { (size_t)cols, (size_t)rows };
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
return k.run(2, globalsize, 0, false);
}
#endif // HAVE_VA_INTEL
+5
View File
@@ -120,6 +120,11 @@ TEST(OpenCL, support_SPIR_programs)
cv::ocl::ProgramSource src = cv::ocl::ProgramSource::fromSPIR(module_name, "simple_spir", (uchar*)&program_binary_code[0], program_binary_code.size(), "");
cv::String errmsg;
cv::ocl::Program program(src, "", errmsg);
if (program.ptr() == NULL && device.isAMD())
{
// https://community.amd.com/t5/opencl/spir-support-in-new-drivers-lost/td-p/170165
throw cvtest::SkipTestException("Bypass AMD OpenCL runtime bug: 'cl_khr_spir' extension is declared, but it doesn't really work");
}
ASSERT_TRUE(program.ptr() != NULL);
k.create("test_kernel", program);
}
+12
View File
@@ -2456,4 +2456,16 @@ TEST(Core_MinMaxIdx, rows_overflow)
}
TEST(Core_Magnitude, regression_19506)
{
for (int N = 1; N <= 64; ++N)
{
Mat a(1, N, CV_32FC1, Scalar::all(1e-20));
Mat res;
magnitude(a, a, res);
EXPECT_LE(cvtest::norm(res, NORM_L1), 1e-15) << N;
}
}
}} // namespace
+1 -1
View File
@@ -1466,7 +1466,7 @@ template<typename R> struct TheTest
R r1 = vx_load_expand((const cv::float16_t*)data.a.d);
R r2(r1);
EXPECT_EQ(1.0f, r1.get0());
vx_store(data_f32.a.d, r2);
v_store(data_f32.a.d, r2);
EXPECT_EQ(-2.0f, data_f32.a.d[R::nlanes - 1]);
out.a.clear();
+10
View File
@@ -1551,4 +1551,14 @@ TEST(Core_MatExpr, empty_check_15760)
EXPECT_THROW(Mat c = Mat().cross(Mat()), cv::Exception);
}
TEST(Core_Arithm, scalar_handling_19599) // https://github.com/opencv/opencv/issues/19599 (OpenCV 4.x+ only)
{
Mat a(1, 1, CV_32F, Scalar::all(1));
Mat b(4, 1, CV_64F, Scalar::all(1)); // MatExpr may convert Scalar to Mat
Mat c;
EXPECT_NO_THROW(cv::multiply(a, b, c));
EXPECT_EQ(1, c.cols);
EXPECT_EQ(1, c.rows);
}
}} // namespace
@@ -364,6 +364,7 @@ CV__DNN_INLINE_NS_BEGIN
* Inner vector has slice ranges for the first number of input dimensions.
*/
std::vector<std::vector<Range> > sliceRanges;
std::vector<std::vector<int> > sliceSteps;
int axis;
int num_split;
+12
View File
@@ -100,6 +100,18 @@ CV__DNN_INLINE_NS_BEGIN
CV_EXPORTS std::vector< std::pair<Backend, Target> > getAvailableBackends();
CV_EXPORTS_W std::vector<Target> getAvailableTargets(dnn::Backend be);
/**
* @brief Enables detailed logging of the DNN model loading with CV DNN API.
* @param[in] isDiagnosticsMode Indicates whether diagnostic mode should be set.
*
* Diagnostic mode provides detailed logging of the model loading stage to explore
* potential problems (ex.: not implemented layer type).
*
* @note In diagnostic mode series of assertions will be skipped, it can lead to the
* expected application crash.
*/
CV_EXPORTS void enableModelDiagnostics(bool isDiagnosticsMode);
/** @brief This class provides all data needed to initialize layer.
*
* It includes dictionary with scalar params (which can be read by using Dict interface),
@@ -0,0 +1,23 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_DNN_LAYER_REG_HPP
#define OPENCV_DNN_LAYER_REG_HPP
#include <opencv2/dnn.hpp>
namespace cv {
namespace dnn {
CV__DNN_INLINE_NS_BEGIN
//! @addtogroup dnn
//! @{
//! Register layer types of DNN model.
typedef std::map<std::string, std::vector<LayerFactory::Constructor> > LayerFactory_Impl;
LayerFactory_Impl& getLayerFactoryImpl();
//! @}
CV__DNN_INLINE_NS_END
}
}
#endif
@@ -235,6 +235,24 @@ Range normalize_axis_range(const Range& r, int axisSize)
return clamped;
}
static inline
bool isAllOnes(const MatShape &inputShape, int startPos, int endPos)
{
CV_Assert(!inputShape.empty());
CV_CheckGE((int) inputShape.size(), startPos, "");
CV_CheckGE(startPos, 0, "");
CV_CheckLE(startPos, endPos, "");
CV_CheckLE((size_t)endPos, inputShape.size(), "");
for (size_t i = startPos; i < endPos; i++)
{
if (inputShape[i] != 1)
return false;
}
return true;
}
CV__DNN_INLINE_NS_END
}
}
@@ -49,6 +49,8 @@ CV_EXPORTS_W void resetMyriadDevice();
#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2 "Myriad2"
/// Intel(R) Neural Compute Stick 2, NCS2 (USB 03e7:2485), MyriadX (https://software.intel.com/ru-ru/neural-compute-stick)
#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X "MyriadX"
#define CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE "ARM_COMPUTE"
#define CV_DNN_INFERENCE_ENGINE_CPU_TYPE_X86 "X86"
/** @brief Returns Inference Engine VPU type.
@@ -57,6 +59,11 @@ CV_EXPORTS_W void resetMyriadDevice();
*/
CV_EXPORTS_W cv::String getInferenceEngineVPUType();
/** @brief Returns Inference Engine CPU type.
*
* Specify OpenVINO plugin: CPU or ARM.
*/
CV_EXPORTS_W cv::String getInferenceEngineCPUType();
/** @brief Release a HDDL plugin.
*/
+4
View File
@@ -108,6 +108,10 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { namespace de
template <class T> __device__ T clamp(T value, T lower, T upper) { return min(max(value, lower), upper); }
template <class T> __device__ long lround(T value);
template <> inline __device__ long lround(double value) { return ::lround(value); }
template <> inline __device__ long lround(float value) { return lroundf(value); }
template <class T> __device__ T round(T value);
template <> inline __device__ double round(double value) { return ::round(value); }
template <> inline __device__ float round(float value) { return roundf(value); }
+37 -30
View File
@@ -26,7 +26,8 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
template <class T, std::size_t CHANNELS_PER_ITER>
__global__ void resize_nn(
Span<T> output, size_type out_height, size_type out_width,
View<T> input, size_type in_height, size_type in_width)
View<T> input, size_type in_height, size_type in_width,
float o2i_fy, float o2i_fx, bool round, bool half_pixel_centers)
{
auto in_image_size = in_height * in_width;
auto out_image_size = out_height * out_width;
@@ -60,12 +61,16 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
const index_type y = (iter % out_image_size) / out_width;
const index_type x = iter % out_width;
/* o2i = output to input */
auto o2i_fy = static_cast<float>(in_height) / out_height;
auto o2i_fx = static_cast<float>(in_width) / out_width;
auto in_yf = half_pixel_centers ? (y + 0.5f) * o2i_fy : y * o2i_fy;
auto in_xf = half_pixel_centers ? (x + 0.5f) * o2i_fx : x * o2i_fx;
auto in_y = static_cast<index_type>(y * o2i_fy);
auto in_x = static_cast<index_type>(x * o2i_fx);
using device::lround;
index_type in_y = round ? lround(in_yf) : static_cast<index_type>(in_yf);
index_type in_x = round ? lround(in_xf) : static_cast<index_type>(in_xf);
using device::min;
in_y = min(in_y, in_height - 1);
in_x = min(in_x, in_width - 1);
index_type in_idx = c_start * in_image_size + in_y * in_width + in_x;
index_type out_idx = c_start * out_image_size + y * out_width + x;
@@ -83,7 +88,7 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
__global__ void resize_bilinear(
Span<T> output, size_type out_height, size_type out_width,
View<T> input, size_type in_height, size_type in_width,
float o2i_fy, float o2i_fx)
float o2i_fy, float o2i_fx, bool half_pixel_centers)
{
auto in_image_size = in_height * in_width;
auto out_image_size = out_height * out_width;
@@ -119,8 +124,9 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
const index_type y = (iter % out_image_size) / out_width;
const index_type x = iter % out_width;
auto in_x = x * o2i_fx;
auto in_y = y * o2i_fy;
using device::max;
auto in_x = half_pixel_centers ? max<float>((x + 0.5f) * o2i_fx - 0.5f, 0.0f) : x * o2i_fx;
auto in_y = half_pixel_centers ? max<float>((y + 0.5f) * o2i_fy - 0.5f, 0.0f) : y * o2i_fy;
auto in_x0 = static_cast<index_type>(in_x);
auto in_y0 = static_cast<index_type>(in_y);
@@ -157,15 +163,16 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
template <class T, std::size_t CHANNELS_PER_ITER> static
void launch_multichannel_resize_nn(const Stream& stream,
Span<T> output, size_type out_height, size_type out_width,
View<T> input, size_type in_height, size_type in_width)
View<T> input, size_type in_height, size_type in_width,
float scale_y, float scale_x, bool round, bool half_pixel_centers)
{
auto kernel = raw::resize_nn<T, CHANNELS_PER_ITER>;
auto policy = make_policy(kernel, output.size() / CHANNELS_PER_ITER, 0, stream);
launch_kernel(kernel, policy, output, out_height, out_width, input, in_height, in_width);
launch_kernel(kernel, policy, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, round, half_pixel_centers);
}
template <class T>
void resize_nn(const Stream& stream, TensorSpan<T> output, TensorView<T> input) {
void resize_nn(const Stream& stream, TensorSpan<T> output, TensorView<T> input, float scale_y, float scale_x, bool round, bool half_pixel_centers) {
auto out_height = output.get_axis_size(-2);
auto out_width = output.get_axis_size(-1);
@@ -176,38 +183,38 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
auto num_iters = num_effective_channels * out_height * out_width;
if (num_effective_channels % 32 == 0 && num_iters > 655360) {
launch_multichannel_resize_nn<T, 32>(stream, output, out_height, out_width, input, in_height, in_width);
launch_multichannel_resize_nn<T, 32>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, round, half_pixel_centers);
} else if (num_effective_channels % 16 == 0 && num_iters > 327680) {
launch_multichannel_resize_nn<T, 16>(stream, output, out_height, out_width, input, in_height, in_width);
launch_multichannel_resize_nn<T, 16>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, round, half_pixel_centers);
} else if (num_effective_channels % 8 == 0 && num_iters > 163840) {
launch_multichannel_resize_nn<T, 8>(stream, output, out_height, out_width, input, in_height, in_width);
launch_multichannel_resize_nn<T, 8>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, round, half_pixel_centers);
} else if (num_effective_channels % 4 == 0 && num_iters > 81920) {
launch_multichannel_resize_nn<T, 4>(stream, output, out_height, out_width, input, in_height, in_width);
launch_multichannel_resize_nn<T, 4>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, round, half_pixel_centers);
} else if (num_effective_channels % 2 == 0) {
launch_multichannel_resize_nn<T, 2>(stream, output, out_height, out_width, input, in_height, in_width);
launch_multichannel_resize_nn<T, 2>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, round, half_pixel_centers);
} else {
launch_multichannel_resize_nn<T, 1>(stream, output, out_height, out_width, input, in_height, in_width);
launch_multichannel_resize_nn<T, 1>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, round, half_pixel_centers);
}
}
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
template void resize_nn<__half>(const Stream&, TensorSpan<__half>, TensorView<__half>);
template void resize_nn<__half>(const Stream&, TensorSpan<__half>, TensorView<__half>, float, float, bool, bool);
#endif
template void resize_nn<float>(const Stream&, TensorSpan<float>, TensorView<float>);
template void resize_nn<float>(const Stream&, TensorSpan<float>, TensorView<float>, float, float, bool,bool);
template <class T, std::size_t CHANNELS_PER_ITER> static
void launch_multichannel_resize_bilinear(const Stream& stream,
Span<T> output, size_type out_height, size_type out_width,
View<T> input, size_type in_height, size_type in_width,
float scale_y, float scale_x)
float scale_y, float scale_x, bool half_pixel_centers)
{
auto kernel = raw::resize_bilinear<T, CHANNELS_PER_ITER>;
auto policy = make_policy(kernel, output.size() / CHANNELS_PER_ITER, 0, stream);
launch_kernel(kernel, policy, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x);
launch_kernel(kernel, policy, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, half_pixel_centers);
}
template <class T>
void resize_bilinear(const Stream& stream, TensorSpan<T> output, TensorView<T> input, float scale_y, float scale_x) {
void resize_bilinear(const Stream& stream, TensorSpan<T> output, TensorView<T> input, float scale_y, float scale_x, bool half_pixel_centers) {
auto out_height = output.get_axis_size(-2);
auto out_width = output.get_axis_size(-1);
@@ -218,21 +225,21 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
auto num_iters = num_effective_channels * out_height * out_width;
if (num_effective_channels % 16 == 0 && num_iters > 163840) {
launch_multichannel_resize_bilinear<T, 16>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x);
launch_multichannel_resize_bilinear<T, 16>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, half_pixel_centers);
} else if (num_effective_channels % 8 == 0 && num_iters > 81920) {
launch_multichannel_resize_bilinear<T, 8>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x);
launch_multichannel_resize_bilinear<T, 8>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, half_pixel_centers);
} else if (num_effective_channels % 4 == 0 && num_iters > 40960) {
launch_multichannel_resize_bilinear<T, 4>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x);
launch_multichannel_resize_bilinear<T, 4>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, half_pixel_centers);
} else if (num_effective_channels % 2 == 0) {
launch_multichannel_resize_bilinear<T, 2>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x);
launch_multichannel_resize_bilinear<T, 2>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, half_pixel_centers);
} else {
launch_multichannel_resize_bilinear<T, 1>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x);
launch_multichannel_resize_bilinear<T, 1>(stream, output, out_height, out_width, input, in_height, in_width, scale_y, scale_x, half_pixel_centers);
}
}
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
template void resize_bilinear<__half>(const Stream&, TensorSpan<__half>, TensorView<__half>, float, float);
template void resize_bilinear<__half>(const Stream&, TensorSpan<__half>, TensorView<__half>, float, float, bool);
#endif
template void resize_bilinear<float>(const Stream&, TensorSpan<float>, TensorView<float>, float, float);
template void resize_bilinear<float>(const Stream&, TensorSpan<float>, TensorView<float>, float, float, bool);
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
+10 -26
View File
@@ -17,28 +17,18 @@ namespace cv { namespace dnn { namespace cuda4dnn {
void checkVersions()
{
int cudart_version = 0;
CUDA4DNN_CHECK_CUDA(cudaRuntimeGetVersion(&cudart_version));
if (cudart_version != CUDART_VERSION)
// https://docs.nvidia.com/deeplearning/cudnn/developer-guide/index.html#programming-model
// cuDNN API Compatibility
// Beginning in cuDNN 7, the binary compatibility of a patch and minor releases is maintained as follows:
// Any patch release x.y.z is forward or backward-compatible with applications built against another cuDNN patch release x.y.w (meaning, of the same major and minor version number, but having w!=z).
// cuDNN minor releases beginning with cuDNN 7 are binary backward-compatible with applications built against the same or earlier patch release (meaning, an application built against cuDNN 7.x is binary compatible with cuDNN library 7.y, where y>=x).
// Applications compiled with a cuDNN version 7.y are not guaranteed to work with 7.x release when y > x.
auto cudnn_bversion = cudnnGetVersion();
auto cudnn_major_bversion = cudnn_bversion / 1000, cudnn_minor_bversion = cudnn_bversion % 1000 / 100;
if (cudnn_major_bversion != CUDNN_MAJOR || cudnn_minor_bversion < CUDNN_MINOR)
{
std::ostringstream oss;
oss << "CUDART reports version " << cudart_version << " which does not match with the version " << CUDART_VERSION << " with which OpenCV was built";
CV_LOG_WARNING(NULL, oss.str().c_str());
}
auto cudnn_version = cudnnGetVersion();
if (cudnn_version != CUDNN_VERSION)
{
std::ostringstream oss;
oss << "cuDNN reports version " << cudnn_version << " which does not match with the version " << CUDNN_VERSION << " with which OpenCV was built";
CV_LOG_WARNING(NULL, oss.str().c_str());
}
auto cudnn_cudart_version = cudnnGetCudartVersion();
if (cudart_version != cudnn_cudart_version)
{
std::ostringstream oss;
oss << "CUDART version " << cudnn_cudart_version << " reported by cuDNN " << cudnn_version << " does not match with the version reported by CUDART " << cudart_version;
oss << "cuDNN reports version " << cudnn_major_bversion << "." << cudnn_minor_bversion << " which is not compatible with the version " << CUDNN_MAJOR << "." << CUDNN_MINOR << " with which OpenCV was built";
CV_LOG_WARNING(NULL, oss.str().c_str());
}
}
@@ -57,9 +47,6 @@ namespace cv { namespace dnn { namespace cuda4dnn {
bool isDeviceCompatible()
{
if (getDeviceCount() <= 0)
return false;
int device_id = getDevice();
if (device_id < 0)
return false;
@@ -80,9 +67,6 @@ namespace cv { namespace dnn { namespace cuda4dnn {
bool doesDeviceSupportFP16()
{
if (getDeviceCount() <= 0)
return false;
int device_id = getDevice();
if (device_id < 0)
return false;
+2 -2
View File
@@ -11,10 +11,10 @@
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
template <class T>
void resize_nn(const csl::Stream& stream, csl::TensorSpan<T> output, csl::TensorView<T> input);
void resize_nn(const csl::Stream& stream, csl::TensorSpan<T> output, csl::TensorView<T> input, float scale_y, float scale_x, bool round, bool half_pixel_centers);
template <class T>
void resize_bilinear(const csl::Stream& stream, csl::TensorSpan<T> output, csl::TensorView<T> input, float scale_y, float scale_x);
void resize_bilinear(const csl::Stream& stream, csl::TensorSpan<T> output, csl::TensorView<T> input, float scale_y, float scale_x, bool half_pixel_centers);
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
+25 -5
View File
@@ -20,14 +20,23 @@ namespace cv { namespace dnn { namespace cuda4dnn {
BILINEAR
};
struct ResizeConfiguration {
InterpolationType type;
bool align_corners;
bool half_pixel_centers;
};
template <class T>
class ResizeOp final : public CUDABackendNode {
public:
using wrapper_type = GetCUDABackendWrapperType<T>;
ResizeOp(csl::Stream stream_, InterpolationType type_, float scaleHeight_, float scaleWidth_)
: stream(std::move(stream_)), type{ type_ }, scaleHeight{ scaleHeight_ }, scaleWidth{ scaleWidth_ }
ResizeOp(csl::Stream stream_, const ResizeConfiguration& config)
: stream(std::move(stream_))
{
type = config.type;
align_corners = config.align_corners;
half_pixel_centers = config.half_pixel_centers;
}
void forward(
@@ -44,16 +53,27 @@ namespace cv { namespace dnn { namespace cuda4dnn {
auto output_wrapper = outputs[0].dynamicCast<wrapper_type>();
auto output = output_wrapper->getSpan();
const auto compute_scale = [this](std::size_t input_size, std::size_t output_size) {
return (align_corners && output_size > 1) ?
static_cast<float>(input_size - 1) / (output_size - 1) :
static_cast<float>(input_size) / output_size;
};
auto out_height = output.get_axis_size(-2), out_width = output.get_axis_size(-1);
auto in_height = input.get_axis_size(-2), in_width = input.get_axis_size(-1);
float scale_height = compute_scale(in_height, out_height),
scale_width = compute_scale(in_width, out_width);
if (type == InterpolationType::NEAREST_NEIGHBOUR)
kernels::resize_nn<T>(stream, output, input);
kernels::resize_nn<T>(stream, output, input, scale_height, scale_width, align_corners, half_pixel_centers);
else if (type == InterpolationType::BILINEAR)
kernels::resize_bilinear<T>(stream, output, input, scaleHeight, scaleWidth);
kernels::resize_bilinear<T>(stream, output, input, scale_height, scale_width, half_pixel_centers);
}
private:
csl::Stream stream;
InterpolationType type;
float scaleHeight, scaleWidth; /* for bilinear interpolation */
bool align_corners, half_pixel_centers;
};
}}} /* namespace cv::dnn::cuda4dnn */
+31
View File
@@ -558,6 +558,29 @@ namespace cv {
fused_layer_names.push_back(last_layer);
}
void setSAM(int from)
{
cv::dnn::LayerParams eltwise_param;
eltwise_param.name = "SAM-name";
eltwise_param.type = "Eltwise";
eltwise_param.set<std::string>("operation", "prod");
eltwise_param.set<std::string>("output_channels_mode", "same");
darknet::LayerParameter lp;
std::string layer_name = cv::format("sam_%d", layer_id);
lp.layer_name = layer_name;
lp.layer_type = eltwise_param.type;
lp.layerParams = eltwise_param;
lp.bottom_indexes.push_back(last_layer);
lp.bottom_indexes.push_back(fused_layer_names.at(from));
last_layer = layer_name;
net->layers.push_back(lp);
layer_id++;
fused_layer_names.push_back(last_layer);
}
void setUpsample(int scaleFactor)
{
cv::dnn::LayerParams param;
@@ -837,6 +860,14 @@ namespace cv {
from = from < 0 ? from + layers_counter : from;
setParams.setScaleChannels(from);
}
else if (layer_type == "sam")
{
std::string bottom_layer = getParam<std::string>(layer_params, "from", "");
CV_Assert(!bottom_layer.empty());
int from = std::atoi(bottom_layer.c_str());
from = from < 0 ? from + layers_counter : from;
setParams.setSAM(from);
}
else if (layer_type == "upsample")
{
int scaleFactor = getParam<int>(layer_params, "stride", 1);
+23 -11
View File
@@ -63,6 +63,7 @@
#include <memory>
#include <opencv2/dnn/shape_utils.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/dnn/layer_reg.private.hpp>
#include <opencv2/core/utils/configuration.private.hpp>
#include <opencv2/core/utils/logger.hpp>
@@ -93,6 +94,13 @@ static bool DNN_CHECK_NAN_INF = utils::getConfigurationParameterBool("OPENCV_DNN
static bool DNN_CHECK_NAN_INF_DUMP = utils::getConfigurationParameterBool("OPENCV_DNN_CHECK_NAN_INF_DUMP", false);
static bool DNN_CHECK_NAN_INF_RAISE_ERROR = utils::getConfigurationParameterBool("OPENCV_DNN_CHECK_NAN_INF_RAISE_ERROR", false);
bool DNN_DIAGNOSTICS_RUN = false;
void enableModelDiagnostics(bool isDiagnosticsMode)
{
DNN_DIAGNOSTICS_RUN = isDiagnosticsMode;
}
using std::vector;
using std::map;
using std::make_pair;
@@ -239,11 +247,10 @@ private:
#endif
#ifdef HAVE_CUDA
if (haveCUDA() && cuda4dnn::isDeviceCompatible())
if (haveCUDA())
{
backends.push_back(std::make_pair(DNN_BACKEND_CUDA, DNN_TARGET_CUDA));
if (cuda4dnn::doesDeviceSupportFP16())
backends.push_back(std::make_pair(DNN_BACKEND_CUDA, DNN_TARGET_CUDA_FP16));
backends.push_back(std::make_pair(DNN_BACKEND_CUDA, DNN_TARGET_CUDA_FP16));
}
#endif
}
@@ -1383,11 +1390,12 @@ struct Net::Impl : public detail::NetImplBase
CV_Assert(preferableBackend != DNN_BACKEND_HALIDE ||
preferableTarget == DNN_TARGET_CPU ||
preferableTarget == DNN_TARGET_OPENCL);
#ifdef HAVE_INF_ENGINE
if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 ||
preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
CV_Assert(
preferableTarget == DNN_TARGET_CPU ||
(preferableTarget == DNN_TARGET_CPU && (!isArmComputePlugin() || preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)) ||
preferableTarget == DNN_TARGET_OPENCL ||
preferableTarget == DNN_TARGET_OPENCL_FP16 ||
preferableTarget == DNN_TARGET_MYRIAD ||
@@ -1395,6 +1403,7 @@ struct Net::Impl : public detail::NetImplBase
preferableTarget == DNN_TARGET_FPGA
);
}
#endif
CV_Assert(preferableBackend != DNN_BACKEND_VKCOM ||
preferableTarget == DNN_TARGET_VULKAN);
CV_Assert(preferableBackend != DNN_BACKEND_CUDA ||
@@ -2099,8 +2108,8 @@ struct Net::Impl : public detail::NetImplBase
return;
}
bool supportsCPUFallback = preferableTarget == DNN_TARGET_CPU ||
BackendRegistry::checkIETarget(DNN_TARGET_CPU);
bool supportsCPUFallback = !isArmComputePlugin() && (preferableTarget == DNN_TARGET_CPU ||
BackendRegistry::checkIETarget(DNN_TARGET_CPU));
// Build Inference Engine networks from sets of layers that support this
// backend. Split a whole model on several Inference Engine networks if
@@ -2363,6 +2372,9 @@ struct Net::Impl : public detail::NetImplBase
CV_Assert(preferableBackend == DNN_BACKEND_CUDA);
#ifdef HAVE_CUDA
if (!cudaInfo) /* we need to check only once */
cuda4dnn::checkVersions();
if (cuda4dnn::getDeviceCount() <= 0)
CV_Error(Error::StsError, "No CUDA capable device found.");
@@ -2373,7 +2385,10 @@ struct Net::Impl : public detail::NetImplBase
CV_Error(Error::GpuNotSupported, "OpenCV was not built to work with the selected device. Please check CUDA_ARCH_PTX or CUDA_ARCH_BIN in your build configuration.");
if (preferableTarget == DNN_TARGET_CUDA_FP16 && !cuda4dnn::doesDeviceSupportFP16())
CV_Error(Error::StsError, "The selected CUDA device does not support FP16 operations.");
{
CV_LOG_WARNING(NULL, "The selected CUDA device does not support FP16 target; switching to FP32 target.");
preferableTarget = DNN_TARGET_CUDA;
}
if (!cudaInfo)
{
@@ -2384,7 +2399,6 @@ struct Net::Impl : public detail::NetImplBase
auto d2h_stream = cuda4dnn::csl::Stream(true); // stream for background D2H data transfers
cudaInfo = std::unique_ptr<CudaInfo_t>(new CudaInfo_t(std::move(context), std::move(d2h_stream)));
cuda4dnn::checkVersions();
}
cudaInfo->workspace = cuda4dnn::csl::Workspace(); // release workspace memory if any
@@ -5304,15 +5318,13 @@ static Mutex& getLayerFactoryMutex()
return *instance;
}
typedef std::map<String, std::vector<LayerFactory::Constructor> > LayerFactory_Impl;
static LayerFactory_Impl& getLayerFactoryImpl_()
{
static LayerFactory_Impl impl;
return impl;
}
static LayerFactory_Impl& getLayerFactoryImpl()
LayerFactory_Impl& getLayerFactoryImpl()
{
static LayerFactory_Impl* volatile instance = NULL;
if (instance == NULL)
+9 -6
View File
@@ -324,10 +324,13 @@ public:
#ifdef HAVE_INF_ENGINE
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
if (ksize == 1)
bool isArmTarget = preferableTarget == DNN_TARGET_CPU && isArmComputePlugin();
if (isArmTarget && blobs.empty())
return false;
if (ksize == 1)
return isArmTarget;
if (ksize == 3)
return preferableTarget == DNN_TARGET_CPU;
return preferableTarget != DNN_TARGET_MYRIAD && !isArmTarget;
bool isMyriad = preferableTarget == DNN_TARGET_MYRIAD || preferableTarget == DNN_TARGET_HDDL;
if ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || !isMyriad) && blobs.empty())
return false;
@@ -805,7 +808,7 @@ public:
CV_Assert_N(inputs.size() >= 1, nodes.size() >= 1);
auto& ieInpNode = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
std::vector<size_t> dims = ieInpNode->get_shape();
CV_Assert(dims.size() == 4 || dims.size() == 5);
CV_Check(dims.size(), dims.size() >= 3 && dims.size() <= 5, "");
std::shared_ptr<ngraph::Node> ieWeights = nodes.size() > 1 ? nodes[1].dynamicCast<InfEngineNgraphNode>()->node : nullptr;
if (nodes.size() > 1)
CV_Assert(ieWeights); // dynamic_cast should not fail
@@ -843,7 +846,7 @@ public:
else
{
auto shape = std::make_shared<ngraph::op::Constant>(ngraph::element::i64,
ngraph::Shape{kernel_shape.size()}, kernel_shape.data());
ngraph::Shape{kernel_shape.size()}, std::vector<int64_t>(kernel_shape.begin(), kernel_shape.end()));
ieWeights = std::make_shared<ngraph::op::v1::Reshape>(ieWeights, shape, true);
}
@@ -878,7 +881,7 @@ public:
if (nodes.size() == 3)
{
auto bias_shape = std::make_shared<ngraph::op::Constant>(ngraph::element::i64,
ngraph::Shape{shape.size()}, shape.data());
ngraph::Shape{shape.size()}, std::vector<int64_t>(shape.begin(), shape.end()));
bias = std::make_shared<ngraph::op::v1::Reshape>(nodes[2].dynamicCast<InfEngineNgraphNode>()->node, bias_shape, true);
}
else
@@ -1247,7 +1250,7 @@ public:
v20*vw20 + v21*vw21 + v22*vw22 + vbias;
if (relu)
vout = v_select(vout > z, vout, vout*vrc);
vx_store(outptr + out_j, vout);
v_store(outptr + out_j, vout);
}
}
#endif
@@ -138,6 +138,12 @@ public:
typedef std::map<int, std::vector<util::NormalizedBBox> > LabelBBox;
inline int getNumOfTargetClasses() {
unsigned numBackground =
(_backgroundLabelId >= 0 && _backgroundLabelId < _numClasses) ? 1 : 0;
return (_numClasses - numBackground);
}
bool getParameterDict(const LayerParams &params,
const std::string &parameterName,
DictValue& result)
@@ -590,12 +596,13 @@ public:
LabelBBox::const_iterator label_bboxes = decodeBBoxes.find(label);
if (label_bboxes == decodeBBoxes.end())
CV_Error_(cv::Error::StsError, ("Could not find location predictions for label %d", label));
int limit = (getNumOfTargetClasses() == 1) ? _keepTopK : std::numeric_limits<int>::max();
if (_bboxesNormalized)
NMSFast_(label_bboxes->second, scores, _confidenceThreshold, _nmsThreshold, 1.0, _topK,
indices[c], util::caffe_norm_box_overlap);
indices[c], util::caffe_norm_box_overlap, limit);
else
NMSFast_(label_bboxes->second, scores, _confidenceThreshold, _nmsThreshold, 1.0, _topK,
indices[c], util::caffe_box_overlap);
indices[c], util::caffe_box_overlap, limit);
numDetections += indices[c].size();
}
if (_keepTopK > -1 && numDetections > (size_t)_keepTopK)
@@ -1354,11 +1354,15 @@ struct PowerFunctor : public BaseFunctor
ngraph::Shape{1}, &scale);
auto shift_node = std::make_shared<ngraph::op::Constant>(ngraph::element::f32,
ngraph::Shape{1}, &shift);
auto power_node = std::make_shared<ngraph::op::Constant>(ngraph::element::f32,
ngraph::Shape{1}, &power);
auto mul = std::make_shared<ngraph::op::v1::Multiply>(scale_node, node, ngraph::op::AutoBroadcastType::NUMPY);
auto scale_shift = std::make_shared<ngraph::op::v1::Add>(mul, shift_node, ngraph::op::AutoBroadcastType::NUMPY);
if (power == 1)
return scale_shift;
auto power_node = std::make_shared<ngraph::op::Constant>(ngraph::element::f32,
ngraph::Shape{1}, &power);
return std::make_shared<ngraph::op::v1::Power>(scale_shift, power_node, ngraph::op::AutoBroadcastType::NUMPY);
}
#endif // HAVE_DNN_NGRAPH
+99 -3
View File
@@ -46,6 +46,7 @@
#include "../op_halide.hpp"
#include "../op_inf_engine.hpp"
#include "../ie_ngraph.hpp"
#include <opencv2/dnn/shape_utils.hpp>
#ifdef HAVE_OPENCL
#include "opencl_kernels_dnn.hpp"
@@ -97,6 +98,7 @@ public:
: outputChannels(0)
{
setParamsFrom(params);
hasVecInput = false;
op = SUM;
if (params.has("operation"))
{
@@ -156,6 +158,9 @@ public:
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
if (hasVecInput && ELTWISE_CHANNNELS_SAME)
return backendId == DNN_BACKEND_OPENCV;
if (backendId == DNN_BACKEND_CUDA)
{
if(channelsModeInput == ELTWISE_CHANNNELS_INPUT_0 || channelsModeInput == ELTWISE_CHANNNELS_INPUT_0_TRUNCATE)
@@ -211,9 +216,6 @@ public:
{
CV_Assert(0 && "Internal error");
}
for (size_t j = 2; j < dims; j++)
CV_Assert(inputs[0][j] == inputs[i][j]);
}
channelsMode = variableChannels ? channelsModeInput : ELTWISE_CHANNNELS_SAME;
@@ -221,9 +223,56 @@ public:
outputs.assign(1, inputs[0]);
outputs[0][1] = numChannels;
if (dims > 2)
{
size_t vecIdx = 0;
bool isVecFound = false;
for (size_t i = 0; i < inputs.size(); i++)
{
bool allOnes = isAllOnes(inputs[i], 2, dims);
if (!allOnes && !isVecFound)
{
vecIdx = i;
isVecFound = true;
}
if (!allOnes && i != vecIdx)
{
for (size_t j = 2; j < dims; j++)
{
CV_Assert(inputs[vecIdx][j] == inputs[i][j]);
}
}
}
if (channelsModeInput == ELTWISE_CHANNNELS_SAME && isVecFound)
{
for (size_t j = 2; j < dims; j++)
{
outputs[0][j] = inputs[vecIdx][j];
}
}
}
return false;
}
void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays) CV_OVERRIDE
{
std::vector<Mat> inputs;
inputs_arr.getMatVector(inputs);
for (size_t i = 0; i < inputs.size(); i++)
{
MatShape inpShape = shape(inputs[i].size);
if (isAllOnes(inpShape, 2, inputs[i].dims))
{
hasVecInput = true;
return;
}
}
}
class EltwiseInvoker : public ParallelLoopBody
{
@@ -516,6 +565,9 @@ public:
if ((inputs_.depth() == CV_16S && op != SUM) || (channelsMode != ELTWISE_CHANNNELS_SAME))
return false;
if (hasVecInput)
return false; // TODO not implemented yet: https://github.com/opencv/opencv/pull/19477
inputs_.getUMatVector(inputs);
outputs_.getUMatVector(outputs);
@@ -616,6 +668,47 @@ public:
CV_Assert(outputs.size() == 1);
const int nstripes = getNumThreads();
if (channelsModeInput == ELTWISE_CHANNNELS_SAME && inputs[0].dims > 2)
{
for (size_t i = 0; i < inputs.size(); i++)
{
MatShape inpShape = shape(inputs[i].size);
bool allOnes = isAllOnes(inpShape, 2, inputs[i].dims);
if (allOnes)
{
Mat tmpInput = inputs[i];
MatShape outShape = shape(outputs[0].size);
size_t xSize = outShape[2];
for (size_t j = 3; j < outShape.size(); j++)
xSize *= outShape[j];
int dimVec[3] = {outShape[0], outShape[1], (int) xSize};
std::vector<int> matSizesVec(&dimVec[0], &dimVec[0] + 3);
inputs[i] = Mat(matSizesVec, tmpInput.type());
std::vector<int> idx(outShape.size(), 0);
std::vector<int> outIdx(inpShape.size(), 0);
for (size_t j = 0; j < outShape[0]; j++)
{
outIdx[0] = idx[0] = j;
for(size_t k = 0; k < outShape[1]; k++)
{
outIdx[1] = idx[1] = k;
for (size_t x = 0; x < xSize; x++)
{
outIdx[2] = x;
inputs[i].at<float>(outIdx.data()) = tmpInput.at<float>(idx.data());
}
}
}
inputs[i] = inputs[i].reshape(0, outShape);
}
}
}
EltwiseInvoker::run(*this,
&inputs[0], (int)inputs.size(), outputs[0],
nstripes);
@@ -795,6 +888,9 @@ public:
}
Ptr<ActivationLayer> activ;
private:
bool hasVecInput;
};
Ptr<EltwiseLayer> EltwiseLayer::create(const LayerParams& params)
@@ -334,8 +334,8 @@ public:
if (!acrossSpatial) {
axes_data.push_back(1);
} else {
axes_data.resize(ieInpNode->get_shape().size());
std::iota(axes_data.begin(), axes_data.end(), 0);
axes_data.resize(ieInpNode->get_shape().size() - 1);
std::iota(axes_data.begin(), axes_data.end(), 1);
}
auto axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{axes_data.size()}, axes_data);
auto norm = std::make_shared<ngraph::op::NormalizeL2>(ieInpNode, axes, epsilon, ngraph::op::EpsMode::ADD);
@@ -344,23 +344,18 @@ public:
std::vector<size_t> shape(ieInpNode->get_shape().size(), 1);
shape[0] = blobs.empty() ? 1 : batch;
shape[1] = numChannels;
std::shared_ptr<ngraph::op::Constant> weight;
if (blobs.empty())
if (!blobs.empty())
{
std::vector<float> ones(numChannels, 1);
weight = std::make_shared<ngraph::op::Constant>(ngraph::element::f32, ngraph::Shape(shape), ones.data());
}
else
{
weight = std::make_shared<ngraph::op::Constant>(
auto weight = std::make_shared<ngraph::op::Constant>(
ngraph::element::f32, ngraph::Shape(shape), blobs[0].data);
}
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2021_2)
auto mul = std::make_shared<ngraph::op::v1::Multiply>(norm, weight, ngraph::op::AutoBroadcastType::NUMPY);
auto mul = std::make_shared<ngraph::op::v1::Multiply>(norm, weight, ngraph::op::AutoBroadcastType::NUMPY);
#else
auto mul = std::make_shared<ngraph::op::v0::Multiply>(norm, weight, ngraph::op::AutoBroadcastType::NUMPY);
auto mul = std::make_shared<ngraph::op::v0::Multiply>(norm, weight, ngraph::op::AutoBroadcastType::NUMPY);
#endif
return Ptr<BackendNode>(new InfEngineNgraphNode(mul));
return Ptr<BackendNode>(new InfEngineNgraphNode(mul));
}
return Ptr<BackendNode>(new InfEngineNgraphNode(norm));
}
#endif // HAVE_DNN_NGRAPH
+4 -3
View File
@@ -105,9 +105,10 @@ public:
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
bool isMyriad = preferableTarget == DNN_TARGET_MYRIAD || preferableTarget == DNN_TARGET_HDDL;
return INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R1) &&
(!isMyriad ||
(dstRanges.size() == 4 && paddings[0].first == 0 && paddings[0].second == 0));
if (INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R1) && isMyriad)
return dstRanges.size() == 4 && paddings[0].first == 0 && paddings[0].second == 0;
return (dstRanges.size() <= 4 || !isArmComputePlugin());
}
#endif
return backendId == DNN_BACKEND_OPENCV ||
+4
View File
@@ -113,6 +113,10 @@ public:
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
#ifdef HAVE_INF_ENGINE
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && preferableTarget == DNN_TARGET_CPU)
return _order.size() <= 4 || !isArmComputePlugin();
#endif
return backendId == DNN_BACKEND_OPENCV ||
backendId == DNN_BACKEND_CUDA ||
((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine()) ||
+3 -1
View File
@@ -220,7 +220,9 @@ public:
#endif
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
return !computeMaxIdx && type != STOCHASTIC && kernel_size.size() > 1;
#ifdef HAVE_DNN_NGRAPH
return !computeMaxIdx && type != STOCHASTIC && kernel_size.size() > 1 && (kernel_size.size() != 3 || !isArmComputePlugin());
#endif
}
else if (backendId == DNN_BACKEND_OPENCV)
{
+4 -2
View File
@@ -460,8 +460,10 @@ public:
std::vector<int64_t> mask(anchors, 1);
region = std::make_shared<ngraph::op::RegionYolo>(tr_input, coords, classes, anchors, useSoftmax, mask, 1, 3, anchors_vec);
auto tr_shape = tr_input->get_shape();
auto shape_as_inp = std::make_shared<ngraph::op::Constant>(ngraph::element::i64,
ngraph::Shape{tr_input->get_shape().size()}, tr_input->get_shape().data());
ngraph::Shape{tr_shape.size()},
std::vector<int64_t>(tr_shape.begin(), tr_shape.end()));
region = std::make_shared<ngraph::op::v1::Reshape>(region, shape_as_inp, true);
new_axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{4}, std::vector<int64_t>{0, 2, 3, 1});
@@ -607,7 +609,7 @@ public:
result = std::make_shared<ngraph::op::Transpose>(result, tr_axes);
if (b > 1)
{
std::vector<size_t> sizes = {(size_t)b, result->get_shape()[0] / b, result->get_shape()[1]};
std::vector<int64_t> sizes{b, static_cast<int64_t>(result->get_shape()[0]) / b, static_cast<int64_t>(result->get_shape()[1])};
auto shape_node = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{sizes.size()}, sizes.data());
result = std::make_shared<ngraph::op::v1::Reshape>(result, shape_node, true);
}
+19 -6
View File
@@ -72,7 +72,7 @@ public:
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
if (backendId == DNN_BACKEND_CUDA)
return interpolation == "nearest" || interpolation == "bilinear";
return interpolation == "nearest" || interpolation == "bilinear" || interpolation == "opencv_linear";
#ifdef HAVE_INF_ENGINE
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
@@ -331,15 +331,28 @@ public:
{
auto context = reinterpret_cast<csl::CSLContext*>(context_);
cuda4dnn::InterpolationType itype;
cuda4dnn::ResizeConfiguration config;
if (interpolation == "nearest")
itype = InterpolationType::NEAREST_NEIGHBOUR;
{
config.type = InterpolationType::NEAREST_NEIGHBOUR;
config.align_corners = alignCorners;
config.half_pixel_centers = halfPixelCenters;
}
else if (interpolation == "bilinear")
itype = InterpolationType::BILINEAR;
{
config.type = InterpolationType::BILINEAR;
config.align_corners = alignCorners;
config.half_pixel_centers = halfPixelCenters;
}
else if (interpolation == "opencv_linear")
{
config.type = InterpolationType::BILINEAR;
config.align_corners = false;
config.half_pixel_centers = true;
}
else
CV_Error(Error::StsNotImplemented, "Requested interpolation mode is not available in resize layer.");
return make_cuda_node<cuda4dnn::ResizeOp>(preferableTarget, std::move(context->stream), itype, scaleHeight, scaleWidth);
return make_cuda_node<cuda4dnn::ResizeOp>(preferableTarget, std::move(context->stream), config);
}
#endif
+83 -7
View File
@@ -70,6 +70,7 @@ public:
SliceLayerImpl(const LayerParams& params)
{
setParamsFrom(params);
hasSteps = false;
axis = params.get<int>("axis", 1);
num_split = params.get<int>("num_split", 0);
hasDynamicShapes = params.get<bool>("has_dynamic_shapes", false);
@@ -79,7 +80,7 @@ public:
CV_Assert(!params.has("begin") && !params.has("size") && !params.has("end"));
const DictValue &indicesValue = params.get("slice_point");
sliceRanges.resize(indicesValue.size() + 1,
std::vector<Range>(axis + 1, Range::all()));
std::vector<Range>(std::max(axis,0) + 1, Range::all()));
int prevSlice = 0;
for (int i = 0; i < indicesValue.size(); ++i)
{
@@ -118,6 +119,22 @@ public:
sliceRanges[0][i].end = end; // We'll finalize a negative value later.
}
}
if (params.has("steps"))
{
const DictValue &steps = params.get("steps");
sliceSteps.resize(1);
sliceSteps[0].resize(steps.size());
for (int i = 0; i < steps.size(); ++i)
{
int step = steps.get<int>(i);
CV_Assert(step >= 1);
if (step > 1)
hasSteps = true;
sliceSteps[0][i] = step;
}
}
}
}
@@ -126,14 +143,17 @@ public:
#ifdef HAVE_DNN_IE_NN_BUILDER_2019
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
return INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R1) &&
sliceRanges.size() == 1 && sliceRanges[0].size() == 4;
sliceRanges.size() == 1 && sliceRanges[0].size() == 4 && !hasSteps;
#endif
#ifdef HAVE_DNN_NGRAPH
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
return sliceRanges.size() == 1;
return sliceRanges.size() == 1 && !hasSteps;
#endif
return backendId == DNN_BACKEND_OPENCV ||
backendId == DNN_BACKEND_CUDA;
#ifdef HAVE_CUDA
if (backendId == DNN_BACKEND_CUDA)
return !hasSteps;
#endif
return backendId == DNN_BACKEND_OPENCV;
}
bool getMemoryShapes(const std::vector<MatShape> &inputs,
@@ -154,6 +174,9 @@ public:
{
if (shapesInitialized || inpShape[j] > 0)
outputs[i][j] = normalize_axis_range(sliceRanges[i][j], inpShape[j]).size();
if (!sliceSteps.empty() && (i < sliceSteps.size()) && (j < sliceSteps[i].size()) && (sliceSteps[i][j] > 1))
outputs[i][j] = (outputs[i][j] + sliceSteps[i][j] - 1) / sliceSteps[i][j];
}
}
}
@@ -188,6 +211,7 @@ public:
const MatSize& inpShape = inputs[0].size;
finalSliceRanges = sliceRanges;
if (sliceRanges.empty())
{
// Divide input blob on equal parts by axis.
@@ -220,6 +244,9 @@ public:
}
}
if (!sliceSteps.empty() && sliceSteps[0].size() != inputs[0].dims)
sliceSteps[0].resize(inputs[0].dims, 1);
#if 0
std::cout << "DEBUG: DNN/Slice: " << outputs.size() << " inpShape=" << inpShape << std::endl;
for (int i = 0; i < outputs.size(); ++i)
@@ -427,6 +454,9 @@ public:
{
CV_TRACE_FUNCTION();
if (hasSteps)
return false; // TODO not implemented yet: https://github.com/opencv/opencv/pull/19546
std::vector<UMat> inputs;
std::vector<UMat> outputs;
@@ -485,9 +515,24 @@ public:
const Mat& inpMat = inputs[0];
CV_Assert(outputs.size() == finalSliceRanges.size());
for (size_t i = 0; i < outputs.size(); i++)
if (!hasSteps)
{
inpMat(finalSliceRanges[i]).copyTo(outputs[i]);
for (size_t i = 0; i < outputs.size(); i++)
{
inpMat(finalSliceRanges[i]).copyTo(outputs[i]);
}
}
else
{
int dimsNum = inpMat.dims;
for (size_t i = 0; i < outputs.size(); i++)
{
std::vector<int> inpIdx(dimsNum, 0);
std::vector<int> outIdx(dimsNum, 0);
getSliceRecursive(inpMat, inpIdx, finalSliceRanges[i], sliceSteps[i], 0, dimsNum, outputs[i], outIdx);
}
}
}
@@ -603,11 +648,42 @@ public:
#endif
private:
void getSliceRecursive(const Mat &inpMat, std::vector<int> &inpIdx,
const std::vector<Range> &sliceRanges,
const std::vector<int> &sliceSteps, int dim, int dimsNum,
Mat &outputs, std::vector<int> &outIdx)
{
int begin = sliceRanges[dim].start;
int end = sliceRanges[dim].end;
int step = !sliceSteps.empty() ? sliceSteps[dim] : 1;
const bool is32F = inpMat.depth() == CV_32F;
// TODO optimization is required (for 2D tail case at least)
for (int k = begin, j = 0; k < end; k += step, j++)
{
inpIdx[dim] = k;
outIdx[dim] = j;
if (dim + 1 < dimsNum)
getSliceRecursive(inpMat, inpIdx, sliceRanges, sliceSteps, dim + 1, dimsNum, outputs, outIdx);
else
{
if (is32F)
outputs.at<float>(outIdx.data()) = inpMat.at<float>(inpIdx.data());
else
outputs.at<short>(outIdx.data()) = inpMat.at<short>(inpIdx.data()); // 16F emulation
}
}
}
protected:
// The actual non-negative values determined from @p sliceRanges depends on input size.
std::vector<std::vector<Range> > finalSliceRanges;
bool hasDynamicShapes;
bool shapesInitialized;
bool hasSteps;
};
class CropLayerImpl CV_FINAL : public SliceLayerImpl
+9 -2
View File
@@ -62,12 +62,15 @@ inline void GetMaxScoreIndex(const std::vector<float>& scores, const float thres
// score_threshold: a threshold used to filter detection results.
// nms_threshold: a threshold used in non maximum suppression.
// top_k: if not > 0, keep at most top_k picked indices.
// limit: early terminate once the # of picked indices has reached it.
// indices: the kept indices of bboxes after nms.
template <typename BoxType>
inline void NMSFast_(const std::vector<BoxType>& bboxes,
const std::vector<float>& scores, const float score_threshold,
const float nms_threshold, const float eta, const int top_k,
std::vector<int>& indices, float (*computeOverlap)(const BoxType&, const BoxType&))
std::vector<int>& indices,
float (*computeOverlap)(const BoxType&, const BoxType&),
int limit = std::numeric_limits<int>::max())
{
CV_Assert(bboxes.size() == scores.size());
@@ -86,8 +89,12 @@ inline void NMSFast_(const std::vector<BoxType>& bboxes,
float overlap = computeOverlap(bboxes[idx], bboxes[kept_idx]);
keep = overlap <= adaptive_threshold;
}
if (keep)
if (keep) {
indices.push_back(idx);
if (indices.size() >= limit) {
break;
}
}
if (keep && eta < 1 && adaptive_threshold > 0.5) {
adaptive_threshold *= eta;
}
@@ -112,14 +112,14 @@ ocl::Image2D ocl4dnnGEMMCopyBufferToImage(UMat buffer, int offset,
global_copy[0] = padded_width;
global_copy[1] = padded_height;
oclk_gemm_copy
bool res = oclk_gemm_copy
.args(
ocl::KernelArg::PtrReadOnly(buffer),
image, offset,
width, height,
ld)
.run(2, global_copy, NULL, false);
oclk_gemm_copy.run(2, global_copy, NULL, false);
CV_Assert(res);
}
}
+14 -2
View File
@@ -10,11 +10,14 @@
#include "../graph_simplifier.hpp"
#include "onnx_graph_simplifier.hpp"
#include <opencv2/core/utils/logger.hpp>
#include <queue>
namespace cv { namespace dnn {
CV__DNN_INLINE_NS_BEGIN
extern bool DNN_DIAGNOSTICS_RUN;
// This wrapper can behave differently for fake input nodes and real graph nodes.
class ONNXNodeWrapper : public ImportNodeWrapper
{
@@ -639,8 +642,17 @@ Mat getMatFromTensor(opencv_onnx::TensorProto& tensor_proto)
}
}
else
CV_Error(Error::StsUnsupportedFormat, "Unsupported data type: " +
opencv_onnx::TensorProto_DataType_Name(datatype));
{
std::string errorMsg = "Unsupported data type: " +
opencv_onnx::TensorProto_DataType_Name(datatype);
if (!DNN_DIAGNOSTICS_RUN)
{
CV_Error(Error::StsUnsupportedFormat, errorMsg);
}
CV_LOG_ERROR(NULL, errorMsg);
return blob;
}
if (tensor_proto.dims_size() == 0)
blob.dims = 1; // To force 1-dimensional cv::Mat for scalars.
return blob;
+322 -130
View File
@@ -8,6 +8,8 @@
#include "../precomp.hpp"
#include <opencv2/dnn/shape_utils.hpp>
#include <opencv2/dnn/layer_reg.private.hpp>
#include <opencv2/core/utils/logger.defines.hpp>
#undef CV_LOG_STRIP_LEVEL
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
@@ -37,6 +39,7 @@ namespace cv {
namespace dnn {
CV__DNN_INLINE_NS_BEGIN
extern bool DNN_DIAGNOSTICS_RUN;
class ONNXImporter
{
@@ -58,11 +61,12 @@ class ONNXImporter
void addConstant(const std::string& name, const Mat& blob);
void addLayer(LayerParams& layerParams,
const opencv_onnx::NodeProto& node_proto);
static const std::set<String>& getSupportedTypes();
public:
ONNXImporter(Net& net, const char *onnxFile)
: dstNet(net)
: dstNet(net), utilNet()
{
hasDynamicShapes = false;
CV_Assert(onnxFile);
@@ -83,7 +87,7 @@ public:
}
ONNXImporter(Net& net, const char* buffer, size_t sizeBuffer)
: dstNet(net)
: dstNet(net), utilNet()
{
hasDynamicShapes = false;
CV_LOG_DEBUG(NULL, "DNN/ONNX: processing in-memory ONNX model (" << sizeBuffer << " bytes)");
@@ -110,6 +114,7 @@ public:
protected:
Net& dstNet;
Net utilNet;
opencv_onnx::GraphProto graph_proto;
std::string framework_name;
@@ -182,6 +187,10 @@ std::map<std::string, Mat> ONNXImporter::getGraphTensors(
tensor_proto = graph_proto.initializer(i);
Mat mat = getMatFromTensor(tensor_proto);
releaseONNXTensor(tensor_proto);
if (DNN_DIAGNOSTICS_RUN && mat.empty())
continue;
layers_weights.insert(std::make_pair(tensor_proto.name(), mat));
}
return layers_weights;
@@ -201,118 +210,132 @@ LayerParams ONNXImporter::getLayerParams(const opencv_onnx::NodeProto& node_prot
opencv_onnx::AttributeProto attribute_proto = node_proto.attribute(i);
std::string attribute_name = attribute_proto.name();
if(attribute_name == "kernel_shape")
try
{
CV_Assert(attribute_proto.ints_size() == 1 || attribute_proto.ints_size() == 2 || attribute_proto.ints_size() == 3);
lp.set("kernel_size", parse(attribute_proto.ints()));
}
else if(attribute_name == "strides")
{
CV_Assert(attribute_proto.ints_size() == 1 || attribute_proto.ints_size() == 2 || attribute_proto.ints_size() == 3);
lp.set("stride", parse(attribute_proto.ints()));
}
else if(attribute_name == "pads")
{
if (node_proto.op_type() == "Pad")
if(attribute_name == "kernel_shape")
{
// Padding layer.
// Paddings are in order begin0, begin1, .. beginN, end0, end1, ..., endN.
// We need to shuffle it to begin0, end0, begin1, end1, ...
CV_Assert(attribute_proto.ints_size() % 2 == 0);
const int dims = attribute_proto.ints_size() / 2;
std::vector<int32_t> paddings;
paddings.reserve(attribute_proto.ints_size());
for (int i = 0; i < dims; ++i)
CV_Assert(attribute_proto.ints_size() == 1 || attribute_proto.ints_size() == 2 || attribute_proto.ints_size() == 3);
lp.set("kernel_size", parse(attribute_proto.ints()));
}
else if(attribute_name == "strides")
{
CV_Assert(attribute_proto.ints_size() == 1 || attribute_proto.ints_size() == 2 || attribute_proto.ints_size() == 3);
lp.set("stride", parse(attribute_proto.ints()));
}
else if(attribute_name == "pads")
{
if (node_proto.op_type() == "Pad")
{
paddings.push_back(attribute_proto.ints(i));
paddings.push_back(attribute_proto.ints(dims + i));
// Padding layer.
// Paddings are in order begin0, begin1, .. beginN, end0, end1, ..., endN.
// We need to shuffle it to begin0, end0, begin1, end1, ...
CV_Assert(attribute_proto.ints_size() % 2 == 0);
const int dims = attribute_proto.ints_size() / 2;
std::vector<int32_t> paddings;
paddings.reserve(attribute_proto.ints_size());
for (int i = 0; i < dims; ++i)
{
paddings.push_back(attribute_proto.ints(i));
paddings.push_back(attribute_proto.ints(dims + i));
}
lp.set("paddings", DictValue::arrayInt(&paddings[0], paddings.size()));
}
lp.set("paddings", DictValue::arrayInt(&paddings[0], paddings.size()));
else
{
// Convolution or pooling.
CV_Assert(attribute_proto.ints_size() == 2 || attribute_proto.ints_size() == 4 || attribute_proto.ints_size() == 6);
lp.set("pad", parse(attribute_proto.ints()));
}
}
else if(attribute_name == "auto_pad")
{
if (attribute_proto.s() == "SAME_UPPER" || attribute_proto.s() == "SAME_LOWER") {
lp.set("pad_mode", "SAME");
}
else if (attribute_proto.s() == "VALID") {
lp.set("pad_mode", "VALID");
}
}
else if(attribute_name == "dilations")
{
CV_Assert(attribute_proto.ints_size() == 1 || attribute_proto.ints_size() == 2 || attribute_proto.ints_size() == 3);
lp.set("dilation", parse(attribute_proto.ints()));
}
else if (attribute_proto.has_i())
{
::google::protobuf::int64 src = attribute_proto.i();
if (src < std::numeric_limits<int32_t>::min() || src > std::numeric_limits<int32_t>::max())
CV_Error(Error::StsOutOfRange, "Input is out of OpenCV 32S range");
else
lp.set(attribute_name, saturate_cast<int32_t>(src));
}
else if (attribute_proto.has_f())
{
lp.set(attribute_name, attribute_proto.f());
}
else if (attribute_proto.has_s())
{
lp.set(attribute_name, attribute_proto.s());
}
else if (attribute_proto.floats_size() > 0)
{
lp.set(attribute_name, DictValue::arrayReal(
attribute_proto.floats().data(), attribute_proto.floats_size()));
}
else if (attribute_proto.ints_size() > 0)
{
lp.set(attribute_name, parse(attribute_proto.ints()));
}
else if (attribute_proto.has_t())
{
opencv_onnx::TensorProto tensor = attribute_proto.t();
Mat blob = getMatFromTensor(tensor);
lp.blobs.push_back(blob);
}
else if (attribute_proto.has_g())
{
CV_Error(Error::StsNotImplemented, cv::format("DNN/ONNX/Attribute[%s]: 'Graph' is not supported", attribute_name.c_str()));
}
else if (attribute_proto.graphs_size() > 0)
{
CV_Error(Error::StsNotImplemented,
cv::format("DNN/ONNX/Attribute[%s]: 'Graphs' (%d) in attributes is not supported",
attribute_name.c_str(), attribute_proto.graphs_size())
);
}
else if (attribute_proto.strings_size() > 0)
{
std::string msg = cv::format("DNN/ONNX/Attribute[%s]: 'Strings' (%d) are not supported",
attribute_name.c_str(), attribute_proto.strings_size());
CV_LOG_ERROR(NULL, msg);
for (int i = 0; i < attribute_proto.strings_size(); i++)
{
CV_LOG_ERROR(NULL, " Attribute[" << attribute_name << "].string(" << i << ") = '" << attribute_proto.strings(i) << "'");
}
CV_Error(Error::StsNotImplemented, msg);
}
else if (attribute_proto.tensors_size() > 0)
{
CV_Error(Error::StsNotImplemented,
cv::format("DNN/ONNX/Attribute[%s]: 'Tensors' (%d) in attributes are not supported",
attribute_name.c_str(), attribute_proto.tensors_size())
);
}
else
{
// Convolution or pooling.
CV_Assert(attribute_proto.ints_size() == 2 || attribute_proto.ints_size() == 4 || attribute_proto.ints_size() == 6);
lp.set("pad", parse(attribute_proto.ints()));
CV_Error(Error::StsNotImplemented, cv::format("DNN/ONNX/Attribute[%s]: unsupported attribute format", attribute_name.c_str()));
}
}
else if(attribute_name == "auto_pad")
catch (const cv::Exception& e)
{
if (attribute_proto.s() == "SAME_UPPER" || attribute_proto.s() == "SAME_LOWER") {
lp.set("pad_mode", "SAME");
}
else if (attribute_proto.s() == "VALID") {
lp.set("pad_mode", "VALID");
}
}
else if(attribute_name == "dilations")
{
CV_Assert(attribute_proto.ints_size() == 1 || attribute_proto.ints_size() == 2 || attribute_proto.ints_size() == 3);
lp.set("dilation", parse(attribute_proto.ints()));
}
else if (attribute_proto.has_i())
{
::google::protobuf::int64 src = attribute_proto.i();
if (src < std::numeric_limits<int32_t>::min() || src > std::numeric_limits<int32_t>::max())
CV_Error(Error::StsOutOfRange, "Input is out of OpenCV 32S range");
else
lp.set(attribute_name, saturate_cast<int32_t>(src));
}
else if (attribute_proto.has_f())
{
lp.set(attribute_name, attribute_proto.f());
}
else if (attribute_proto.has_s())
{
lp.set(attribute_name, attribute_proto.s());
}
else if (attribute_proto.floats_size() > 0)
{
lp.set(attribute_name, DictValue::arrayReal(
attribute_proto.floats().data(), attribute_proto.floats_size()));
}
else if (attribute_proto.ints_size() > 0)
{
lp.set(attribute_name, parse(attribute_proto.ints()));
}
else if (attribute_proto.has_t())
{
opencv_onnx::TensorProto tensor = attribute_proto.t();
Mat blob = getMatFromTensor(tensor);
lp.blobs.push_back(blob);
}
else if (attribute_proto.has_g())
{
CV_Error(Error::StsNotImplemented, cv::format("DNN/ONNX/Attribute[%s]: 'Graph' is not supported", attribute_name.c_str()));
}
else if (attribute_proto.graphs_size() > 0)
{
CV_Error(Error::StsNotImplemented,
cv::format("DNN/ONNX/Attribute[%s]: 'Graphs' (%d) in attributes is not supported",
attribute_name.c_str(), attribute_proto.graphs_size())
);
}
else if (attribute_proto.strings_size() > 0)
{
std::string msg = cv::format("DNN/ONNX/Attribute[%s]: 'Strings' (%d) are not supported",
attribute_name.c_str(), attribute_proto.strings_size());
CV_LOG_ERROR(NULL, msg);
for (int i = 0; i < attribute_proto.strings_size(); i++)
CV_UNUSED(e);
if (DNN_DIAGNOSTICS_RUN)
{
CV_LOG_ERROR(NULL, " Attribute[" << attribute_name << "].string(" << i << ") = '" << attribute_proto.strings(i) << "'");
CV_LOG_ERROR(NULL, "DNN/ONNX: Potential problem with processing attributes for node " << node_proto.name() << " Attribute " << attribute_name.c_str()
);
continue;
}
CV_Error(Error::StsNotImplemented, msg);
}
else if (attribute_proto.tensors_size() > 0)
{
CV_Error(Error::StsNotImplemented,
cv::format("DNN/ONNX/Attribute[%s]: 'Tensors' (%d) in attributes are not supported",
attribute_name.c_str(), attribute_proto.tensors_size())
);
}
else
{
CV_Error(Error::StsNotImplemented, cv::format("DNN/ONNX/Attribute[%s]: unsupported attribute format", attribute_name.c_str()));
throw;
}
}
return lp;
@@ -338,7 +361,11 @@ Mat ONNXImporter::getBlob(const std::string& input_name)
void ONNXImporter::addLayer(LayerParams& layerParams,
const opencv_onnx::NodeProto& node_proto)
{
int id = dstNet.addLayer(layerParams.name, layerParams.type, layerParams);
int id;
if (DNN_DIAGNOSTICS_RUN)
id = utilNet.addLayer(layerParams.name, layerParams.type, layerParams);
else
id = dstNet.addLayer(layerParams.name, layerParams.type, layerParams);
for (int i = 0; i < node_proto.output_size(); ++i)
{
layer_id.insert(std::make_pair(node_proto.output(i), LayerInfo(id, i)));
@@ -351,7 +378,10 @@ void ONNXImporter::addLayer(LayerParams& layerParams,
const std::string& input_name = node_proto.input(j);
IterLayerId_t layerId = layer_id.find(input_name);
if (layerId != layer_id.end()) {
dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, inpNum);
if (DNN_DIAGNOSTICS_RUN)
utilNet.connect(layerId->second.layerId, layerId->second.outputId, id, inpNum);
else
dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, inpNum);
++inpNum;
// Collect input shapes.
IterShape_t shapeIt = outShapes.find(input_name);
@@ -360,7 +390,11 @@ void ONNXImporter::addLayer(LayerParams& layerParams,
}
}
// Compute shape of output blob for this layer.
Ptr<Layer> layer = dstNet.getLayer(id); // FIXIT: avoid instantiation of layers during the import stage
Ptr<Layer> layer;
if (DNN_DIAGNOSTICS_RUN)
layer = utilNet.getLayer(id);
else
layer = dstNet.getLayer(id); // FIXIT: avoid instantiation of layers during the import stage
layer->getMemoryShapes(layerInpShapes, 0, layerOutShapes, layerInternalShapes);
for (int i = 0; i < node_proto.output_size() && i < (int)layerOutShapes.size(); ++i)
{
@@ -437,8 +471,37 @@ void ONNXImporter::populateNet()
layer_id.insert(std::make_pair(name, LayerInfo(0, netInputs.size() - 1)));
}
}
utilNet.setInputsNames(netInputs);
dstNet.setInputsNames(netInputs);
if (DNN_DIAGNOSTICS_RUN) {
auto &supportedTypes = getSupportedTypes();
for (int li = 0; li < layersSize; li++) {
const opencv_onnx::NodeProto &node_proto = graph_proto.node(li);
std::string name = node_proto.output(0);
std::string layer_type = node_proto.op_type();
auto registered = supportedTypes.find(layer_type);
if (registered == supportedTypes.end()) {
CV_LOG_ERROR(NULL, "DNN/ONNX: NOTE: Potential problem with creating node " << name<< " with type " << layer_type << ".\n Type "
<< layer_type << " IS NOT SUPPORTED!\n"
);
}
}
auto oldConstBlobs = constBlobs;
auto oldOutShapes = outShapes;
auto oldLayerId = layer_id;
CV_LOG_INFO(NULL, "DNN/ONNX: start diagnostic run!");
for (int li = 0; li < layersSize; li++) {
const opencv_onnx::NodeProto &node_proto = graph_proto.node(li);
handleNode(node_proto);
}
CV_LOG_INFO(NULL, "DNN/ONNX: diagnostic run completed!");
constBlobs = oldConstBlobs;
outShapes = oldOutShapes;
layer_id = oldLayerId;
enableModelDiagnostics(false);
}
for(int li = 0; li < layersSize; li++)
{
const opencv_onnx::NodeProto& node_proto = graph_proto.node(li);
@@ -448,6 +511,80 @@ void ONNXImporter::populateNet()
CV_LOG_DEBUG(NULL, "DNN/ONNX: import completed!");
}
const std::set<String>& ONNXImporter::getSupportedTypes()
{
static const std::set<String> layerTypes = {
"MaxPool",
"AveragePool",
"GlobalAveragePool",
"GlobalMaxPool",
"ReduceMean",
"ReduceSum",
"ReduceMax",
"Slice",
"Split",
"Add",
"Sum",
"Sub",
"Pow",
"Max",
"Neg",
"Constant",
"LSTM",
"ImageScaler",
"Clip",
"LeakyRelu",
"Relu",
"Elu",
"Tanh",
"PRelu",
"LRN",
"InstanceNormalization",
"BatchNormalization",
"Gemm",
"MatMul",
"Mul",
"Div",
"Conv",
"ConvTranspose",
"Transpose",
"Squeeze",
"Flatten",
"Unsqueeze",
"Expand",
"Reshape",
"Pad",
"Shape",
"Cast",
"ConstantOfShape",
"ConstantFill",
"Gather",
"Concat",
"Resize",
"Upsample",
"SoftMax",
"Softmax",
"LogSoftmax",
"DetectionOutput",
"Interp",
"CropAndResize",
"ROIPooling",
"PSROIPooling",
"ChannelsPReLU",
"Sigmoid",
"Swish",
"Mish",
"AbsVal",
"BNLL",
"MaxUnpool",
"Dropout",
"Identity",
"Crop",
"Normalize"
};
return layerTypes;
}
void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
{
opencv_onnx::NodeProto node_proto = node_proto_; // TODO FIXIT
@@ -458,11 +595,11 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
CV_LOG_DEBUG(NULL, "DNN/ONNX: processing node with " << node_proto.input_size() << " inputs and " << node_proto.output_size() << " outputs: "
<< cv::format("[%s]:(%s)", layer_type.c_str(), name.c_str())
);
LayerParams layerParams;
try
{
// FIXIT not all cases can be repacked into "LayerParams". Importer should handle such cases directly for each "layer_type"
LayerParams layerParams = getLayerParams(node_proto);
layerParams = getLayerParams(node_proto);
layerParams.name = name;
layerParams.type = layer_type;
@@ -641,20 +778,11 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
int axis = 0;
std::vector<int> begin;
std::vector<int> end;
std::vector<int> steps;
int inp_size = node_proto.input_size();
if (inp_size == 1)
{
if (layerParams.has("steps"))
{
DictValue steps = layerParams.get("steps");
for (int i = 0; i < steps.size(); ++i)
{
if (steps.get<int>(i) != 1)
CV_Error(Error::StsNotImplemented,
"Slice layer only supports steps = 1");
}
}
if (layerParams.has("axes")) {
DictValue axes = layerParams.get("axes");
for (int i = 1; i < axes.size(); ++i) {
@@ -677,7 +805,7 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
int finish = ends.get<int>(i);
end.push_back((finish < 0) ? --finish : finish); // numpy doesn't include last dim
}
} else {
} else { // inp_size > 1
CV_Assert(inp_size >= 3);
for (int i = 1; i < inp_size; i++) {
CV_Assert(constBlobs.find(node_proto.input(i)) != constBlobs.end());
@@ -711,6 +839,12 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
if (inp_size == 5) {
CV_Assert(constBlobs.find(node_proto.input(4)) != constBlobs.end());
Mat step_blob = getBlob(node_proto, 4);
const int* steps_ptr = step_blob.ptr<int>();
if (axis > 0)
steps.resize(axis, 1);
std::copy(steps_ptr, steps_ptr + step_blob.total(), std::back_inserter(steps));
// Very strange application for Slice op with tensor reversing.
// We just workaround it for 2d constants.
@@ -728,13 +862,15 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
return;
}
}
CV_CheckEQ(countNonZero(step_blob != 1), 0, "Slice layer only supports steps = 1");
}
}
layerParams.set("begin", DictValue::arrayInt(&begin[0], begin.size()));
layerParams.set("end", DictValue::arrayInt(&end[0], end.size()));
layerParams.set("axis", axis);
if (!steps.empty())
layerParams.set("steps", DictValue::arrayInt(&steps[0], steps.size()));
if (constBlobs.find(node_proto.input(0)) != constBlobs.end())
{
Mat inp = getBlob(node_proto, 0);
@@ -799,7 +935,11 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
constParams.name = layerParams.name + "/const";
constParams.type = "Const";
constParams.blobs.push_back((isSub ? -1 : 1) * blob);
int id = dstNet.addLayer(constParams.name, constParams.type, constParams);
int id;
if (DNN_DIAGNOSTICS_RUN)
id = utilNet.addLayer(constParams.name, constParams.type, constParams);
else
id = dstNet.addLayer(constParams.name, constParams.type, constParams);
layer_id.insert(std::make_pair(constParams.name, LayerInfo(id, 0)));
outShapes[constParams.name] = shape(blob);
@@ -844,12 +984,19 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
powerParams.type = "Power";
powerParams.set("scale", -1);
int id;
//Create Power layer
int id = dstNet.addLayer(powerParams.name, powerParams.type, powerParams);
if (DNN_DIAGNOSTICS_RUN)
id = utilNet.addLayer(powerParams.name, powerParams.type, powerParams);
else
id = dstNet.addLayer(powerParams.name, powerParams.type, powerParams);
//Connect to input
IterLayerId_t layerId = layer_id.find(node_proto.input(1));
CV_Assert(layerId != layer_id.end());
dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0);
if (DNN_DIAGNOSTICS_RUN)
utilNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0);
else
dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0);
//Add shape
layer_id.insert(std::make_pair(powerParams.name, LayerInfo(id, 0)));
outShapes[powerParams.name] = outShapes[node_proto.input(1)];
@@ -1036,11 +1183,18 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
layerParams.erase("epsilon");
//Create MVN layer
int id = dstNet.addLayer(mvnParams.name, mvnParams.type, mvnParams);
int id;
if (DNN_DIAGNOSTICS_RUN)
id = utilNet.addLayer(mvnParams.name, mvnParams.type, mvnParams);
else
id = dstNet.addLayer(mvnParams.name, mvnParams.type, mvnParams);
//Connect to input
IterLayerId_t layerId = layer_id.find(node_proto.input(0));
CV_Assert(layerId != layer_id.end());
dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0);
if (DNN_DIAGNOSTICS_RUN)
utilNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0);
else
dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0);
//Add shape
layer_id.insert(std::make_pair(mvnParams.name, LayerInfo(id, 0)));
outShapes[mvnParams.name] = outShapes[node_proto.input(0)];
@@ -1233,12 +1387,19 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
powerParams.type = "Power";
powerParams.set("power", -1);
int id;
//Create Power layer
int id = dstNet.addLayer(powerParams.name, powerParams.type, powerParams);
if (DNN_DIAGNOSTICS_RUN)
id = utilNet.addLayer(powerParams.name, powerParams.type, powerParams);
else
id = dstNet.addLayer(powerParams.name, powerParams.type, powerParams);
//Connect to input
IterLayerId_t layerId = layer_id.find(node_proto.input(1));
CV_Assert(layerId != layer_id.end());
dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0);
if (DNN_DIAGNOSTICS_RUN)
utilNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0);
else
dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0);
//Add shape
layer_id.insert(std::make_pair(powerParams.name, LayerInfo(id, 0)));
outShapes[powerParams.name] = outShapes[node_proto.input(1)];
@@ -1923,9 +2084,31 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
}
catch (const cv::Exception& e)
{
CV_LOG_ERROR(NULL, "DNN/ONNX: ERROR during processing node with " << node_proto.input_size() << " inputs and " << node_proto.output_size() << " outputs: "
<< cv::format("[%s]:(%s)", layer_type.c_str(), name.c_str())
);
if (DNN_DIAGNOSTICS_RUN)
{
CV_LOG_ERROR(NULL, "DNN/ONNX: Potential problem during processing node with " << node_proto.input_size() << " inputs and " << node_proto.output_size() << " outputs: "
<< cv::format("[%s]:(%s)", layer_type.c_str(), name.c_str()) << "\n" << e.msg
);
auto registeredLayers = getLayerFactoryImpl();
if (registeredLayers.find(layerParams.type) != registeredLayers.end())
{
try
{
Ptr<Layer> layer = LayerFactory::createLayerInstance(layerParams.type, layerParams);
}
catch (const std::exception& e)
{
CV_LOG_ERROR(NULL, "DNN/ONNX: Layer of type " << layerParams.type << "(" << layer_type << ") cannot be created with parameters " << layerParams << ". Error: " << e.what()
);
}
}
}
else
{
CV_LOG_ERROR(NULL, "DNN/ONNX: ERROR during processing node with " << node_proto.input_size() << " inputs and " << node_proto.output_size() << " outputs: "
<< cv::format("[%s]:(%s)", layer_type.c_str(), name.c_str())
);
}
for (int i = 0; i < node_proto.input_size(); i++)
{
CV_LOG_INFO(NULL, " Input[" << i << "] = '" << node_proto.input(i) << "'");
@@ -1934,7 +2117,16 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
{
CV_LOG_INFO(NULL, " Output[" << i << "] = '" << node_proto.output(i) << "'");
}
CV_Error(Error::StsError, cv::format("Node [%s]:(%s) parse error: %s", layer_type.c_str(), name.c_str(), e.what()));
if (DNN_DIAGNOSTICS_RUN)
{
for (int i = 0; i < node_proto.output_size(); ++i)
{
layer_id.insert(std::make_pair(node_proto.output(i), LayerInfo(0, i)));
outShapes[node_proto.output(i)] = outShapes[node_proto.input(0)];
}
}
else
CV_Error(Error::StsError, cv::format("Node [%s]:(%s) parse error: %s", layer_type.c_str(), name.c_str(), e.what()));
}
}
+35
View File
@@ -655,6 +655,22 @@ InferenceEngine::Core& getCore(const std::string& id)
}
#endif
static bool detectArmPlugin_()
{
InferenceEngine::Core& ie = getCore("CPU");
const std::vector<std::string> devices = ie.GetAvailableDevices();
for (std::vector<std::string>::const_iterator i = devices.begin(); i != devices.end(); ++i)
{
if (i->find("CPU") != std::string::npos)
{
const std::string name = ie.GetMetric(*i, METRIC_KEY(FULL_DEVICE_NAME)).as<std::string>();
CV_LOG_INFO(NULL, "CPU plugin: " << name);
return name.find("arm_compute::NEON") != std::string::npos;
}
}
return false;
}
#if !defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT)
static bool detectMyriadX_(std::string device)
{
@@ -1185,6 +1201,12 @@ bool isMyriadX()
return myriadX;
}
bool isArmComputePlugin()
{
static bool armPlugin = getInferenceEngineCPUType() == CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE;
return armPlugin;
}
static std::string getInferenceEngineVPUType_()
{
static std::string param_vpu_type = utils::getConfigurationParameterString("OPENCV_DNN_IE_VPU_TYPE", "");
@@ -1223,6 +1245,14 @@ cv::String getInferenceEngineVPUType()
return vpu_type;
}
cv::String getInferenceEngineCPUType()
{
static cv::String cpu_type = detectArmPlugin_() ?
CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE :
CV_DNN_INFERENCE_ENGINE_CPU_TYPE_X86;
return cpu_type;
}
#else // HAVE_INF_ENGINE
cv::String getInferenceEngineBackendType()
@@ -1238,6 +1268,11 @@ cv::String getInferenceEngineVPUType()
{
CV_Error(Error::StsNotImplemented, "This OpenCV build doesn't include InferenceEngine support");
}
cv::String getInferenceEngineCPUType()
{
CV_Error(Error::StsNotImplemented, "This OpenCV build doesn't include InferenceEngine support");
}
#endif // HAVE_INF_ENGINE
+3
View File
@@ -256,8 +256,11 @@ CV__DNN_INLINE_NS_BEGIN
bool isMyriadX();
bool isArmComputePlugin();
CV__DNN_INLINE_NS_END
InferenceEngine::Core& getCore(const std::string& id);
template<typename T = size_t>
+95 -20
View File
@@ -12,6 +12,7 @@ Implementation of Tensorflow models parser
#include "../precomp.hpp"
#include <opencv2/core/utils/logger.defines.hpp>
#include <opencv2/dnn/shape_utils.hpp>
#undef CV_LOG_STRIP_LEVEL
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
#include <opencv2/core/utils/logger.hpp>
@@ -295,6 +296,22 @@ DataLayout getDataLayout(
return it != data_layouts.end() ? it->second : DATA_LAYOUT_UNKNOWN;
}
static
bool hasAllOnes(const Mat &inputs, int startPos, int endPos)
{
CV_CheckLE(inputs.dims, 2, "");
CV_CheckGE(startPos, 0, "");
CV_CheckLE(startPos, endPos, "");
CV_CheckLT((size_t)endPos, inputs.total(), "");
for (int i = startPos; i < endPos; i++)
{
if (inputs.at<int>(i) != 1 && inputs.at<int>(i) != -1)
return false;
}
return true;
}
void setStrides(LayerParams &layerParams, const tensorflow::NodeDef &layer)
{
if (hasLayerAttr(layer, "strides"))
@@ -490,6 +507,9 @@ protected:
std::map<String, Mat> sharedWeights;
std::map<String, int> layer_id;
private:
void addPermuteLayer(const int* order, const std::string& permName, Pin& inpId);
};
TFImporter::TFImporter(Net& net, const char *model, const char *config)
@@ -895,6 +915,17 @@ void TFImporter::populateNet()
CV_LOG_DEBUG(NULL, "DNN/TF: ===================== Import completed =====================");
}
void TFImporter::addPermuteLayer(const int* order, const std::string& permName, Pin& inpId)
{
LayerParams permLP;
permLP.set("order", DictValue::arrayInt<const int*>(order, 4));
CV_Assert(layer_id.find(permName) == layer_id.end());
int permId = dstNet.addLayer(permName, "Permute", permLP);
layer_id[permName] = permId;
connect(layer_id, dstNet, inpId, permId, 0);
inpId = Pin(permName);
}
void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
{
tensorflow::NodeDef layer = layer_;
@@ -1276,37 +1307,49 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
if (value_id.find(layer.input(1)) != value_id.end())
{
Mat newShape = getTensorContent(getConstBlob(layer, value_id, 1));
if (newShape.total() == 4)
int newShapeSize = newShape.total();
bool hasSwap = false;
if (newShapeSize == 4 && hasAllOnes(newShape, 0, 2))
{
// NHWC->NCHW
std::swap(*newShape.ptr<int32_t>(0, 2), *newShape.ptr<int32_t>(0, 3));
std::swap(*newShape.ptr<int32_t>(0, 1), *newShape.ptr<int32_t>(0, 2));
hasSwap = true;
}
if (inpLayout == DATA_LAYOUT_NHWC)
{
if (newShape.total() != 4 || newShape.at<int>(1) == 1)
if (newShapeSize >= 2 || newShape.at<int>(1) == 1)
{
LayerParams permLP;
int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC.
permLP.set("order", DictValue::arrayInt<int*>(order, 4));
std::string permName = name + "/nchw";
CV_Assert(layer_id.find(permName) == layer_id.end());
int permId = dstNet.addLayer(permName, "Permute", permLP);
layer_id[permName] = permId;
connect(layer_id, dstNet, inpId, permId, 0);
inpId = Pin(permName);
inpLayout = DATA_LAYOUT_NCHW;
addPermuteLayer(order, name + "/nhwc", inpId);
if (newShapeSize < 4)
{
inpLayout = DATA_LAYOUT_NCHW;
}
else
{
inpLayout = DATA_LAYOUT_NHWC;
}
}
}
layerParams.set("dim", DictValue::arrayInt<int*>(newShape.ptr<int>(), newShape.total()));
layerParams.set("dim", DictValue::arrayInt<int*>(newShape.ptr<int>(), newShapeSize));
int id = dstNet.addLayer(name, "Reshape", layerParams);
layer_id[name] = id;
// one input only
connect(layer_id, dstNet, inpId, id, 0);
data_layouts[name] = newShape.total() == 2 ? DATA_LAYOUT_PLANAR : inpLayout;
inpId = Pin(name);
if ((inpLayout == DATA_LAYOUT_NHWC || inpLayout == DATA_LAYOUT_UNKNOWN || inpLayout == DATA_LAYOUT_PLANAR) &&
newShapeSize == 4 && !hasSwap)
{
int order[] = {0, 3, 1, 2}; // Transform back to OpenCV's NCHW.
addPermuteLayer(order, name + "/nchw", inpId);
inpLayout = DATA_LAYOUT_NCHW;
}
data_layouts[name] = newShapeSize == 2 ? DATA_LAYOUT_PLANAR : inpLayout;
}
else
{
@@ -1783,6 +1826,7 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
{
// Check if all the inputs have the same shape.
bool equalInpShapes = true;
bool isShapeOnes = false;
MatShape outShape0;
for (int ii = 0; ii < num_inputs && !netInputShapes.empty(); ii++)
{
@@ -1803,12 +1847,14 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
else if (outShape != outShape0)
{
equalInpShapes = false;
isShapeOnes = isAllOnes(outShape, 2, outShape.size()) ||
isAllOnes(outShape0, 2, outShape0.size());
break;
}
}
int id;
if (equalInpShapes || netInputShapes.empty())
if (equalInpShapes || netInputShapes.empty() || (!equalInpShapes && isShapeOnes))
{
layerParams.set("operation", type == "RealDiv" ? "div" : "prod");
id = dstNet.addLayer(name, "Eltwise", layerParams);
@@ -2314,12 +2360,9 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
// To keep correct order after squeeze dims we first need to change layout from NCHW to NHWC
LayerParams permLP;
int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC.
permLP.set("order", DictValue::arrayInt<int*>(order, 4));
std::string permName = name + "/nchw";
CV_Assert(layer_id.find(permName) == layer_id.end());
int permId = dstNet.addLayer(permName, "Permute", permLP);
layer_id[permName] = permId;
connect(layer_id, dstNet, Pin(name), permId, 0);
Pin inpId = Pin(name);
addPermuteLayer(order, permName, inpId);
LayerParams squeezeLp;
std::string squeezeName = name + "/squeeze";
@@ -2331,6 +2374,38 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer_)
connect(layer_id, dstNet, Pin(permName), squeezeId, 0);
}
}
else if (axis == 1)
{
int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC.
Pin inpId = parsePin(layer.input(0));
addPermuteLayer(order, name + "/nhwc", inpId);
layerParams.set("pool", type == "Mean" ? "ave" : "sum");
layerParams.set("kernel_h", 1);
layerParams.set("global_pooling_w", true);
int id = dstNet.addLayer(name, "Pooling", layerParams);
layer_id[name] = id;
connect(layer_id, dstNet, inpId, id, 0);
if (!keepDims)
{
LayerParams squeezeLp;
std::string squeezeName = name + "/squeeze";
CV_Assert(layer_id.find(squeezeName) == layer_id.end());
int channel_id = 3; // TF NHWC layout
squeezeLp.set("axis", channel_id - 1);
squeezeLp.set("end_axis", channel_id);
int squeezeId = dstNet.addLayer(squeezeName, "Flatten", squeezeLp);
layer_id[squeezeName] = squeezeId;
connect(layer_id, dstNet, Pin(name), squeezeId, 0);
}
else
{
int order[] = {0, 3, 1, 2}; // From NHWC to OpenCV's NCHW.
Pin inpId = parsePin(name);
addPermuteLayer(order, name + "/nchw", inpId);
}
}
} else {
if (indices.total() != 2 || indices.at<int>(0) != 1 || indices.at<int>(1) != 2)
CV_Error(Error::StsNotImplemented, "Unsupported mode of reduce_mean or reduce_sum operation.");
+2
View File
@@ -30,11 +30,13 @@
#define CV_TEST_TAG_DNN_SKIP_IE_2019R1_1 "dnn_skip_ie_2019r1_1"
#define CV_TEST_TAG_DNN_SKIP_IE_2019R2 "dnn_skip_ie_2019r2"
#define CV_TEST_TAG_DNN_SKIP_IE_2019R3 "dnn_skip_ie_2019r3"
#define CV_TEST_TAG_DNN_SKIP_IE_CPU "dnn_skip_ie_cpu"
#define CV_TEST_TAG_DNN_SKIP_IE_OPENCL "dnn_skip_ie_ocl"
#define CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16 "dnn_skip_ie_ocl_fp16"
#define CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2 "dnn_skip_ie_myriad2"
#define CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X "dnn_skip_ie_myriadx"
#define CV_TEST_TAG_DNN_SKIP_IE_MYRIAD CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2, CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X
#define CV_TEST_TAG_DNN_SKIP_IE_ARM_CPU "dnn_skip_ie_arm_cpu"
#define CV_TEST_TAG_DNN_SKIP_VULKAN "dnn_skip_vulkan"
+2 -2
View File
@@ -453,13 +453,13 @@ void initDNNTests()
#ifdef HAVE_DNN_IE_NN_BUILDER_2019
CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER,
#endif
""
CV_TEST_TAG_DNN_SKIP_IE_CPU
);
#endif
registerGlobalSkipTag(
// see validateVPUType(): CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2, CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X
CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16
);
#endif
#ifdef HAVE_VULKAN
registerGlobalSkipTag(
CV_TEST_TAG_DNN_SKIP_VULKAN
@@ -727,6 +727,10 @@ TEST_P(Test_Darknet_layers, shortcut)
TEST_P(Test_Darknet_layers, upsample)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
testDarknetLayer("upsample");
}
@@ -803,6 +807,11 @@ TEST_P(Test_Darknet_layers, relu)
testDarknetLayer("relu");
}
TEST_P(Test_Darknet_layers, sam)
{
testDarknetLayer("sam", true);
}
INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_layers, dnnBackendsAndTargets());
}} // namespace
+11 -1
View File
@@ -258,7 +258,17 @@ TEST_P(LRN, Accuracy)
int sz[] = {1, inChannels, inSize.height, inSize.width};
Mat input(4, &sz[0], CV_32F);
test(lp, input, backendId, targetId);
double l1 = 0.0, lInf = 0.0;
// The OpenCL kernels use the native_ math functions which have
// implementation defined accuracy, so we use relaxed thresholds. See
// https://github.com/opencv/opencv/issues/9821 for more details.
if (targetId == DNN_TARGET_OPENCL)
{
l1 = 0.01;
lInf = 0.01;
}
test(lp, input, backendId, targetId, false, l1, lInf);
}
INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, LRN, Combine(
+16 -2
View File
@@ -169,8 +169,17 @@ TEST_P(Test_Caffe_layers, Softmax)
TEST_P(Test_Caffe_layers, LRN)
{
testLayerUsingCaffeModels("layer_lrn_spatial");
testLayerUsingCaffeModels("layer_lrn_channels");
double l1 = 0.0, lInf = 0.0;
// The OpenCL kernels use the native_ math functions which have
// implementation defined accuracy, so we use relaxed thresholds. See
// https://github.com/opencv/opencv/issues/9821 for more details.
if (target == DNN_TARGET_OPENCL)
{
l1 = 0.01;
lInf = 0.01;
}
testLayerUsingCaffeModels("layer_lrn_spatial", false, true, l1, lInf);
testLayerUsingCaffeModels("layer_lrn_channels", false, true, l1, lInf);
}
TEST_P(Test_Caffe_layers, Convolution)
@@ -1583,6 +1592,11 @@ TEST_P(Test_Caffe_layers, Interp)
TEST_P(Test_Caffe_layers, DISABLED_Interp) // requires patched protobuf (available in OpenCV source tree only)
#endif
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
+47
View File
@@ -156,6 +156,10 @@ TEST_P(Test_ONNX_layers, Convolution_variable_weight_bias)
if (backend == DNN_BACKEND_VKCOM)
applyTestTag(CV_TEST_TAG_DNN_SKIP_VULKAN); // not supported
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU &&
getInferenceEngineCPUType() == CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_ARM_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
String basename = "conv_variable_wb";
Net net = readNetFromONNX(_tf("models/" + basename + ".onnx"));
ASSERT_FALSE(net.empty());
@@ -436,11 +440,19 @@ TEST_P(Test_ONNX_layers, BatchNormalization3D)
TEST_P(Test_ONNX_layers, BatchNormalizationUnfused)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
testONNXModels("frozenBatchNorm2d");
}
TEST_P(Test_ONNX_layers, BatchNormalizationSubgraph)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
testONNXModels("batch_norm_subgraph");
}
@@ -652,6 +664,26 @@ TEST_P(Test_ONNX_layers, Slice)
#endif
}
TEST_P(Test_ONNX_layers, Slice_Steps_2DInput)
{
testONNXModels("slice_opset_11_steps_2d");
}
TEST_P(Test_ONNX_layers, Slice_Steps_3DInput)
{
testONNXModels("slice_opset_11_steps_3d");
}
TEST_P(Test_ONNX_layers, Slice_Steps_4DInput)
{
testONNXModels("slice_opset_11_steps_4d");
}
TEST_P(Test_ONNX_layers, Slice_Steps_5DInput)
{
testONNXModels("slice_opset_11_steps_5d");
}
TEST_P(Test_ONNX_layers, Softmax)
{
testONNXModels("softmax");
@@ -766,6 +798,8 @@ TEST_P(Test_ONNX_layers, Conv1d_variable_weight_bias)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
if (target == DNN_TARGET_CPU && getInferenceEngineCPUType() == CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_ARM_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
}
String basename = "conv1d_variable_wb";
Net net = readNetFromONNX(_tf("models/" + basename + ".onnx"));
@@ -789,6 +823,13 @@ TEST_P(Test_ONNX_layers, Conv1d_variable_weight_bias)
TEST_P(Test_ONNX_layers, GatherMultiOutput)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
#if defined(INF_ENGINE_RELEASE)
if (target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE);
@@ -885,6 +926,7 @@ TEST_P(Test_ONNX_layers, PoolConv1d)
TEST_P(Test_ONNX_layers, ConvResizePool1d)
{
#if defined(INF_ENGINE_RELEASE)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
@@ -892,7 +934,12 @@ TEST_P(Test_ONNX_layers, ConvResizePool1d)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
#if INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
}
#endif
testONNXModels("conv_resize_pool_1d");
}
+54
View File
@@ -135,6 +135,16 @@ TEST_P(Test_TensorFlow_layers, reduce_sum)
runTensorFlowNet("sum_pool_by_axis");
}
TEST_P(Test_TensorFlow_layers, reduce_sum_channel)
{
runTensorFlowNet("reduce_sum_channel");
}
TEST_P(Test_TensorFlow_layers, reduce_sum_channel_keep_dims)
{
runTensorFlowNet("reduce_sum_channel", false, 0.0, 0.0, false, "_keep_dims");
}
TEST_P(Test_TensorFlow_layers, conv_single_conv)
{
runTensorFlowNet("single_conv");
@@ -205,6 +215,17 @@ TEST_P(Test_TensorFlow_layers, eltwise)
runTensorFlowNet("eltwise_sub");
}
TEST_P(Test_TensorFlow_layers, eltwise_add_vec)
{
runTensorFlowNet("eltwise_add_vec");
}
TEST_P(Test_TensorFlow_layers, eltwise_mul_vec)
{
runTensorFlowNet("eltwise_mul_vec");
}
TEST_P(Test_TensorFlow_layers, channel_broadcast)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
@@ -219,6 +240,12 @@ TEST_P(Test_TensorFlow_layers, pad_and_concat)
TEST_P(Test_TensorFlow_layers, concat_axis_1)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
runTensorFlowNet("concat_axis_1");
}
@@ -279,6 +306,10 @@ TEST_P(Test_TensorFlow_layers, batch_norm_10)
}
TEST_P(Test_TensorFlow_layers, batch_norm_11)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_CPU, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // nan
#endif
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
runTensorFlowNet("mvn_batch_norm_1x1");
@@ -478,6 +509,21 @@ TEST_P(Test_TensorFlow_layers, unfused_flatten)
runTensorFlowNet("unfused_flatten_unknown_batch");
}
TEST_P(Test_TensorFlow_layers, reshape_layer)
{
runTensorFlowNet("reshape_layer");
}
TEST_P(Test_TensorFlow_layers, reshape_nchw)
{
runTensorFlowNet("reshape_nchw");
}
TEST_P(Test_TensorFlow_layers, reshape_conv)
{
runTensorFlowNet("reshape_conv");
}
TEST_P(Test_TensorFlow_layers, leaky_relu)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000)
@@ -1073,12 +1119,20 @@ TEST_P(Test_TensorFlow_layers, keras_mobilenet_head)
// TF case: align_corners=False, half_pixel_centers=False
TEST_P(Test_TensorFlow_layers, resize_bilinear)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
runTensorFlowNet("resize_bilinear");
}
// TF case: align_corners=True, half_pixel_centers=False
TEST_P(Test_TensorFlow_layers, resize_bilinear_align_corners)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
runTensorFlowNet("resize_bilinear",
false, 0.0, 0.0, false, // default parameters
"_align_corners");
+22
View File
@@ -258,6 +258,14 @@ TEST_P(Test_Torch_layers, net_conv_gemm_lrn)
l1 = 0.0042;
lInf = 0.021;
}
// The OpenCL kernels use the native_ math functions which have
// implementation defined accuracy, so we use relaxed thresholds. See
// https://github.com/opencv/opencv/issues/9821 for more details.
else if (target == DNN_TARGET_OPENCL)
{
l1 = 0.02;
lInf = 0.02;
}
runTorchNet("net_conv_gemm_lrn", "", false, true, true, l1, lInf);
}
@@ -282,6 +290,15 @@ TEST_P(Test_Torch_layers, net_padding)
TEST_P(Test_Torch_layers, net_non_spatial)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // crash
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
#endif
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 &&
(target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
@@ -592,6 +609,11 @@ private:
TEST_P(Test_Torch_layers, upsampling_nearest)
{
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // TODO
#endif
// Test a custom layer.
CV_DNN_REGISTER_LAYER_CLASS(SpatialUpSamplingNearest, SpatialUpSamplingNearestLayer);
try
@@ -481,8 +481,7 @@ article](http://en.wikipedia.org/wiki/Maximally_stable_extremal_regions)).
than union-find method; it actually get 1.5~2m/s on my centrino L7200 1.2GHz laptop.
- the color image algorithm is taken from: @cite forssen2007maximally ; it should be much slower
than grey image method ( 3~4 times ); the chi_table.h file is taken directly from paper's source
code which is distributed under GPL.
than grey image method ( 3~4 times )
- (Python) A complete example showing the use of the %MSER detector can be found at samples/python/mser.py
*/
+1 -1
View File
@@ -35,7 +35,7 @@
* it actually get 1.5~2m/s on my centrino L7200 1.2GHz laptop.
* 3. the color image algorithm is taken from: Maximally Stable Colour Regions for Recognition and Match;
* it should be much slower than gray image method ( 3~4 times );
* the chi_table.h file is taken directly from paper's source code which is distributed under GPL.
* the chi_table.h file is taken directly from paper's source code which is distributed under permissive BSD-like license: http://users.isy.liu.se/cvl/perfo/software/chi_table.h
* 4. though the name is *contours*, the result actually is a list of point set.
*/
+5 -1
View File
@@ -23,7 +23,7 @@ ocv_add_module(gapi
REQUIRED
opencv_imgproc
OPTIONAL
opencv_video
opencv_video opencv_calib3d
WRAP
python
)
@@ -53,6 +53,7 @@ file(GLOB gapi_ext_hdrs
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/streaming/*.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/plaidml/*.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/util/*.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/python/*.hpp"
)
set(gapi_srcs
@@ -76,6 +77,7 @@ set(gapi_srcs
src/api/kernels_video.cpp
src/api/kernels_nnparsers.cpp
src/api/kernels_streaming.cpp
src/api/kernels_stereo.cpp
src/api/render.cpp
src/api/render_ocv.cpp
src/api/ginfer.cpp
@@ -111,6 +113,7 @@ set(gapi_srcs
src/backends/cpu/gcpubackend.cpp
src/backends/cpu/gcpukernel.cpp
src/backends/cpu/gcpuimgproc.cpp
src/backends/cpu/gcpustereo.cpp
src/backends/cpu/gcpuvideo.cpp
src/backends/cpu/gcpucore.cpp
src/backends/cpu/gnnparsers.cpp
@@ -158,6 +161,7 @@ set(gapi_srcs
# Python bridge
src/backends/ie/bindings_ie.cpp
src/backends/python/gpythonbackend.cpp
)
ocv_add_dispatched_file(backends/fluid/gfluidimgproc_func SSE4_1 AVX2)
+17 -3
View File
@@ -20,12 +20,26 @@ endif()
set(ADE_root "${ade_src_dir}/${ade_subdir}/sources/ade")
file(GLOB_RECURSE ADE_sources "${ADE_root}/source/*.cpp")
file(GLOB_RECURSE ADE_include "${ADE_root}/include/ade/*.hpp")
add_library(ade STATIC ${ADE_include} ${ADE_sources})
add_library(ade STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL}
${ADE_include}
${ADE_sources}
)
target_include_directories(ade PUBLIC $<BUILD_INTERFACE:${ADE_root}/include>)
set_target_properties(ade PROPERTIES POSITION_INDEPENDENT_CODE True)
set_target_properties(ade PROPERTIES
POSITION_INDEPENDENT_CODE True
OUTPUT_NAME ade
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
COMPILE_PDB_NAME ade
COMPILE_PDB_NAME_DEBUG "ade${OPENCV_DEBUG_POSTFIX}"
ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH}
)
if(ENABLE_SOLUTION_FOLDERS)
set_target_properties(ade PROPERTIES FOLDER "3rdparty")
endif()
if(NOT BUILD_SHARED_LIBS)
ocv_install_target(ade EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)
ocv_install_target(ade EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev OPTIONAL)
endif()
ocv_install_3rdparty_licenses(ade "${ade_src_dir}/${ade_subdir}/LICENSE")
+2 -2
View File
@@ -645,7 +645,7 @@ Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref
@param ddepth optional depth of the output matrix.
@sa sub, addWeighted
*/
GAPI_EXPORTS GMat addC(const GMat& src1, const GScalar& c, int ddepth = -1);
GAPI_EXPORTS_W GMat addC(const GMat& src1, const GScalar& c, int ddepth = -1);
//! @overload
GAPI_EXPORTS GMat addC(const GScalar& c, const GMat& src1, int ddepth = -1);
@@ -1945,7 +1945,7 @@ Gets dimensions from rectangle.
@param r Input rectangle.
@return Size (rectangle dimensions).
*/
GAPI_EXPORTS GOpaque<Size> size(const GOpaque<Rect>& r);
GAPI_EXPORTS_W GOpaque<Size> size(const GOpaque<Rect>& r);
/** @brief Gets dimensions from MediaFrame.
@@ -190,6 +190,11 @@ template<> struct get_in<cv::GArray<cv::GScalar> >: public get_in<cv::GArray<cv:
{
};
// FIXME(dm): GArray<vector<U>>/GArray<GArray<U>> conversion should be done more gracefully in the system
template<typename U> struct get_in<cv::GArray<cv::GArray<U>> >: public get_in<cv::GArray<std::vector<U>> >
{
};
//FIXME(dm): GOpaque<Mat>/GOpaque<GMat> conversion should be done more gracefully in the system
template<> struct get_in<cv::GOpaque<cv::GMat> >: public get_in<cv::GOpaque<cv::Mat> >
{
@@ -0,0 +1,48 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2021 Intel Corporation
#ifndef OPENCV_GAPI_CPU_STEREO_API_HPP
#define OPENCV_GAPI_CPU_STEREO_API_HPP
#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
namespace cv {
namespace gapi {
namespace calib3d {
namespace cpu {
GAPI_EXPORTS GKernelPackage kernels();
/** @brief Structure for the Stereo operation initialization parameters.*/
struct GAPI_EXPORTS StereoInitParam {
StereoInitParam(int nD, int bS, double bL, double f):
numDisparities(nD), blockSize(bS), baseline(bL), focus(f) {}
StereoInitParam() = default;
int numDisparities = 0;
int blockSize = 21;
double baseline = 70.;
double focus = 1000.;
};
} // namespace cpu
} // namespace calib3d
} // namespace gapi
namespace detail {
template<> struct CompileArgTag<cv::gapi::calib3d::cpu::StereoInitParam> {
static const char* tag() {
return "org.opencv.stereoInit";
}
};
} // namespace detail
} // namespace cv
#endif // OPENCV_GAPI_CPU_STEREO_API_HPP

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