1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-22 03:43:03 +04:00

Compare commits

...

269 Commits

Author SHA1 Message Date
Alexander Alekhin 64e6cf9fe5 release: OpenCV 3.4.9 2019-12-19 18:16:47 +03:00
Sajarin ed788229ed Merge pull request #16165 from sajarindider:macOS_install
* doc: added macOS installation guide

* doc: added clarification and corrections

* docs: introduction entry, lowercase file names and ids
2019-12-19 18:15:59 +03:00
Alexander Alekhin 9564aa1fdb Merge pull request #16195 from alalek:tbb_version_2020 2019-12-19 10:55:31 +00:00
Alexander Alekhin 24b05cb308 Merge pull request #16196 from alalek:issue_13574 2019-12-19 10:35:54 +00:00
Alexander Alekhin dff8e29f98 Merge pull request #16139 from alalek:core_flip_avoid_unaligned 2019-12-19 10:29:07 +00:00
Alexander Alekhin 4733a19bab Merge pull request #16194 from alalek:fix_16192
* imgproc(test): resize(LANCZOS4) reproducer 16192

* imgproc: fix resize LANCZOS4 coefficients generation
2019-12-19 13:20:42 +03:00
jeffeDurand 5bf7345743 Merge pull request #16090 from jeffeDurand:cuda_mog2_issue_5296
* cuda_mog2_issue_5296
2019-12-19 13:02:48 +03:00
Alexander Alekhin 4342657762 Merge pull request #16034 from Quantizs:irLoadFromBuffer 2019-12-19 10:00:07 +00:00
Sebastien Wybo e801f0e954 Merge pull request #16011 from sebastien-wybo:fix_16007
* Fix #16007 - colinearity computed using all 3 coordinates

* calib3d(test): estimateAffine3D regression 16007
2019-12-19 12:59:18 +03:00
Alexander Alekhin 9cd1d087c3 android(camera2): apply .disconnectCamera() patch from issue 13574 2019-12-19 00:29:53 +00:00
Alexander Alekhin 8d22ac200f core: workaround flipHoriz() alignment issues 2019-12-19 00:05:23 +00:00
Alexander Alekhin 28a5f7d66b 3rdparty: TBB version 2019u8 => 2020.0 2019-12-18 23:14:38 +00:00
Alexander Alekhin a8345133ac Merge pull request #16191 from terfendail:lres2c_fix 2019-12-18 22:31:52 +00:00
Vitaly Tuzov f5a84f75c4 Fix for CV_8UC2 linear resize vectorization 2019-12-18 21:41:36 +00:00
antalzsiroscandid aa80f754f4 dnn: reading IR models from buffer 2019-12-18 15:31:08 +01:00
mcellis33 5d15c65e48 Merge pull request #16136 from mcellis33:mec-nan
* Handle det == 0 in findCircle3pts.

Issue 16051 shows a case where findCircle3pts returns NaN for the
center coordinates and radius due to dividing by a determinant of 0. In
this case, the points are colinear, so the longest distance between any
2 points is the diameter of the minimum enclosing circle.

* imgproc(test): update test checks for minEnclosingCircle()

* imgproc: fix handling of special cases in minEnclosingCircle()
2019-12-18 17:25:59 +03:00
Alexander Alekhin f8b16fa293 Merge pull request #16188 from saskatchewancatch:issue-13551 2019-12-18 10:30:35 +00:00
Rajkiran Natarajan af04b422c9 Change program type in hdr format files to modern value: RADIANCE so
modern readers that expect RADIANCE will read it
2019-12-17 20:17:32 -08:00
Alexander Alekhin c97ff6c0f9 Merge pull request #16104 from alalek:issue_16095 2019-12-17 19:02:15 +00:00
Tatsuro Shibamura 971ae00942 Merge pull request #16027 from shibayan:arm64-windows10
* Support ARM64 Windows 10 platform

* Fixed detection issue for ARM64 Windows 10

* Try enabling ARM NEON intrin

* build: disable NEON with MSVC compiler

* samples(directx): gdi32 dependency
2019-12-17 00:23:30 +03:00
Sajarin 21ee54c3d1 Merge pull request #16100 from sajarindider:brief
* (doc): added info about STAR

* (doc): fixed typos and sentence structure

* fixed trailing whitespaces
2019-12-15 12:42:19 +03:00
Alexander Alekhin 90a17cf964 Merge pull request #16159 from alalek:imgcodecs_bmp_ubsan_enum_handling 2019-12-15 09:28:08 +00:00
Alexander Alekhin 60ba6ef916 Merge pull request #16163 from alalek:fix_16122 2019-12-14 18:51:22 +00:00
Alexander Alekhin 424e1150ae cmake: fix OpenCV_ARCH 2019-12-14 15:02:43 +00:00
Alexander Alekhin d1c35e7b61 imgcodecs(bmp): make happy UBSAN with enum value range check 2019-12-13 18:51:46 +03:00
Xuanda Yang 3d60a9b96c Merge pull request #16156 from TH3CHARLie:3.4
* Eltwise::DIV support in Halide backend

* fix typo

* remove div from generated test suite to pass CI, switching to manual test...

* ensure divisor not near to zero

* use randu

* dnn(test): update test data for Eltwise.Accuracy/DIV layer test
2019-12-13 18:29:39 +03:00
Alexander Alekhin 60f81032bb Merge pull request #16157 from alalek:update_libwebp_1.0.3
* 3rdparty: update libwebp 1.0.2 => 1.0.3

https://github.com/webmproject/libwebp/releases/tag/v1.0.3

* 3rdparty(libwebp): re-apply patches
2019-12-13 17:54:42 +03:00
Alexander Alekhin a45928045a Merge pull request #16150 from alalek:cmake_avoid_deprecated_link_private
* cmake: avoid deprecated LINK_PRIVATE/LINK_PUBLIC

see CMP0023 (CMake 2.8.12+)

* cmake: fix 3rdparty list

- don't include OpenCV modules
2019-12-13 17:52:40 +03:00
Alexander Alekhin f62241b780 Merge pull request #16148 from alalek:doxygen_update_config 2019-12-13 14:51:37 +00:00
Alexander Alekhin 43302c79ca Merge pull request #16122 from alalek:cmake_update_cpu_compiler_detection 2019-12-13 14:51:19 +00:00
Alexander Alekhin 94f73ee680 Merge pull request #16153 from vsuyi:master 2019-12-13 13:43:58 +00:00
ysy ff4d3d27dd fix wrong method name 2019-12-13 19:54:53 +08:00
Alexander Alekhin 682653c6f8 doc: update doxygen configuration 2019-12-13 01:41:45 +00:00
RAJKIRAN NATARAJAN e6ce752da1 Merge pull request #15966 from saskatchewancatch:issue-15760
Add checks for empty operands in Matrix expressions that don't check properly

* Starting to add checks for empty operands in Matrix expressions that
don't check properly.

* Adding checks and delcarations for checker functions

* Fix signatures and add checks for each class of Matrix Expr operation

* Make it catch the right exception

* Don't expose helper functions to public API
2019-12-12 19:23:57 +03:00
Paul Murphy 1c4a64f0a1 Merge pull request #16138 from pmur:reg_16137
* imgproc: Prevent 1B overrun of 8C3 SIMD optimization

The fourth value read via v_load_q is essentially ignored,
but can cause trouble if it happens to cross page boundaries.

The final few iterations may attempt to read the most extreme
elements of S, which will read 1B beyond the array in most
aligment cases. Dynamically compute the stop. This could be
hoised from the loop, but will require a more extensive change.

Likewise, cleanup the iteration increment statements to make
it more obvious they do channel count (3) elements per pass.

This should resolve #16137

* imgproc(resize): extra check
2019-12-12 13:00:44 +03:00
Alexander Alekhin afa072578c Merge pull request #16120 from alalek:python3.8 2019-12-11 17:18:51 +00:00
Alexander Alekhin 5ee7abbe3c Merge pull request #16088 from alalek:dnn_eltwise_layer_different_src_channels
dnn(eltwise): fix handling of different number of channels

* dnn(test): reproducer for Eltwise layer issue from PR16063

* dnn(eltwise): rework support for inputs with different channels

* dnn(eltwise): get rid of finalize(), variableChannels

* dnn(eltwise): update input sorting by number of channels

- do not swap inputs if number of channels are same after truncation

* dnn(test): skip "shortcut" with batch size 2 on MYRIAD targets
2019-12-11 20:16:58 +03:00
Alexander Alekhin f2cce5fd8c Merge pull request #16125 from alalek:core_safe_xadd 2019-12-11 14:15:46 +00:00
Alexander Alekhin 7d61426279 Merge pull request #16124 from alalek:issue_13354 2019-12-11 14:15:23 +00:00
Alexander Alekhin 8b97c93f3d Merge pull request #16123 from alalek:opencv_include_port_file 2019-12-11 14:15:04 +00:00
Alexander Alekhin 2a11103a73 Merge pull request #16098 from alalek:dnn_clarify_error_getMemoryShapes 2019-12-11 14:02:15 +00:00
Alexander Alekhin 15612ebd39 python: enable Python 3.8 2019-12-11 16:52:38 +03:00
Alexander Alekhin d1bb2055da Merge pull request #16121 from shimat:fix_voronoi_typo 2019-12-11 12:30:47 +00:00
Alexander Alekhin 416848066c core: provide safe implementations of CV_XADD() only 2019-12-11 00:48:45 +00:00
Alexander Alekhin 76b5e19eb3 core: add "namespace cv" in CV_StaticAssert fallback implementation 2019-12-11 00:35:13 +00:00
Alexander Alekhin a675c4937a core: OPENCV_INCLUDE_PORT_FILE for custom platform configuration 2019-12-11 00:31:45 +00:00
Alexander Alekhin 6ea29a7696 cmake: prefer using CMAKE_SYSTEM_PROCESSOR / CMAKE_SIZEOF_VOID_P
Drop:
- discouraged CMAKE_CL_64
- MSVC64
- MINGW64
2019-12-11 00:21:10 +00:00
shimat b89581960c s/Voroni/Voronoi/g 2019-12-11 09:13:58 +09:00
Alexander Alekhin 4ec4ec844f python: fix issue with bindings loading on Python 3.8 2019-12-10 19:00:10 +00:00
Alexander Alekhin e47f3e5bcc Merge pull request #16109 from pixelb:gcc-9-pch 2019-12-10 16:29:07 +00:00
Alexander Alekhin 9a27901edc Merge pull request #16117 from mshabunin:fix-hist-args-34 2019-12-10 15:14:22 +00:00
Pádraig Brady 7b298b0995 Fix pch generation when linker flags used with GCC
-c is required to avoid linking (and the associated missing "main" message)
when linker flags like "-Wl,-z,relro" are passed to GCC
2019-12-10 14:55:56 +00:00
Maksim Shabunin 435c97c7a2 imgproc: add parameter checks in calcHist and calcBackProj 2019-12-10 16:10:19 +03:00
Alexander Alekhin 939099b9ce Merge pull request #16107 from dkurt:dnn_ie_ngraph_v1_conv 2019-12-10 12:10:50 +00:00
Alexander Alekhin 2a19db0f0a Merge pull request #16106 from dkurt:dnn_ie_ngraph_weights_fusion 2019-12-10 12:08:04 +00:00
Dmitry Kurtaev fe77223dee Modify nGraph's ConvolutionBackpropData and GroupConvolution 2019-12-10 14:14:00 +03:00
Alexander Alekhin 45f6931352 Merge pull request #16089 from dkurt:dnn_ie_fix_fpga 2019-12-09 19:26:00 +00:00
RAJKIRAN NATARAJAN b9435b9e38 Merge pull request #16094 from saskatchewancatch:issue-16053
* Add eps error checking for approxPolyDP to allow sensible values only
for epsilon value of Douglas-Peucker algorithm.

* Review changes for PR
2019-12-09 22:24:35 +03:00
Alexander Alekhin a2642d83d3 Merge pull request #16093 from alalek:core_itt_thread_name_16072 2019-12-09 18:29:53 +00:00
Alexander Alekhin a4cb914656 Merge pull request #16101 from dkurt:dnn_ie_ngraph_detection_output 2019-12-09 18:29:24 +00:00
Alexander Alekhin 2817cbe450 Merge pull request #16102 from asmorkalov:as/xperience_c 2019-12-09 18:28:29 +00:00
Dmitry Kurtaev c2ca3ee2fa Fix weights fusion for Convolution and Deconvolution layers in nGraph 2019-12-09 19:06:47 +03:00
Alexander Alekhin 13bc55a015 calib3d: clarify error messages in collectCalibrationData() 2019-12-09 18:36:13 +03:00
Alexander Smorkalov 766465ce94 Added Xperience.AI to copyright file. 2019-12-09 15:58:24 +03:00
Paul Murphy a011035ed6 Merge pull request #15257 from pmur:resize
* resize: HResizeLinear reduce duplicate work

There appears to be a 2x unroll of the HResizeLinear against k,
however the k value is only incremented by 1 during the unroll. This
results in k - 1 duplicate passes when k > 1.

Likewise, the final pass may not respect the work done by the vector
loop. Start it with the offset returned by the vector op if
implemented. Note, no vector ops are implemented today.

The performance is most noticable on a linear downscale. A set of
performance tests are added to characterize this.  The performance
improvement is 10-50% depending on the scaling.

* imgproc: vectorize HResizeLinear

Performance is mostly gated by the gather operations
for x inputs.

Likewise, provide a 2x unroll against k, this reduces the
number of alpha gathers by 1/2 for larger k.

While not a 4x improvement, it still performs substantially
better under P9 for a 1.4x improvement. P8 baseline is
1.05-1.10x due to reduced VSX instruction set.

For float types, this results in a more modest
1.2x improvement.

* Update U8 processing for non-bitexact linear resize

* core: hal: vsx: improve v_load_expand_q

With a little help, we can do this quickly without gprs on
all VSX enabled targets.

* resize: Fix cn == 3 step per feedback

Per feedback, ensure we don't overrun. This was caught via the
failure observed in Test_TensorFlow.inception_accuracy.
2019-12-09 14:54:06 +03:00
Alexander Alekhin 734de34b7a Merge pull request #16085 from alalek:imgproc_threshold_to_zero_ipp_bug
* imgproc(IPP): wrong result from threshold(THRESH_TOZERO)

* imgproc(IPP): disable IPP code to pass THRESH_TOZERO test
2019-12-09 14:51:02 +03:00
Dmitry Kurtaev 883c4c60c3 Remove Dummy layer 2019-12-09 12:49:47 +03:00
Alexander Alekhin b1b505f783 dnn: clarify error message from getMemoryShapes() 2019-12-08 22:17:24 +00:00
Alexander Alekhin 816f82682b core(trace/itt): avoid calling __itt_thread_set_name() by default
- don't override current application thread names
- set name for own threads only
2019-12-07 21:41:15 +00:00
Lubov Batanina 629d47fcd8 Merge pull request #15988 from l-bat:custom_layer
Test create custom layer in python

* check is contiguos

* Add custom layer test

* Fix test

* Remove assert

* Move assert to pyopencv dnn

* remove assert

* Add unregister

* Fix python2

* proto to bytearray

* Fix data type
2019-12-06 21:29:57 +03:00
Dmitry Kurtaev beb5b291b9 Fix HETERO:FPGA,CPU plugin for IE backend 2019-12-06 19:35:11 +03:00
Alexander Alekhin 51d54ad4f0 Merge pull request #16076 from l-bat:prior_ngraph 2019-12-06 14:08:21 +00:00
Alexander Alekhin fb5db23463 Merge pull request #16079 from alalek:imgproc_color_clarify_error_message 2019-12-06 12:33:07 +00:00
Alexander Alekhin 0a35b97e75 Merge pull request #16070 from dkurt:backport_15611 2019-12-06 12:32:22 +00:00
Alexander Alekhin eea517be92 Merge pull request #16071 from alalek:update_version_3.4.9-pre 2019-12-06 11:25:05 +00:00
Alexander Alekhin b369c456f2 imgproc(color): clarify error message 2019-12-06 13:25:51 +03:00
Liubov Batanina 660a709840 Support Swish and Mish activations 2019-12-06 11:27:59 +03:00
Liubov Batanina d99d18304a Slice v1 op 2019-12-06 09:56:21 +03:00
Alexander Alekhin 76a27e3399 pre: OpenCV 3.4.9 (version++) 2019-12-05 18:28:38 +00:00
Dmitry Kurtaev 134094a442 Backport fix for autodetection of input shapes 2019-12-05 19:25:51 +03:00
Alexander Alekhin c790779a37 Merge pull request #16024 from alalek:issue_15953 2019-12-05 14:23:48 +00:00
Alexander Alekhin 72f35e0626 Merge pull request #16052 from alalek:issue_16040
* calib3d: use normalized input in solvePnPGeneric()

* calib3d: java regression test for solvePnPGeneric

* calib3d: python regression test for solvePnPGeneric
2019-12-05 15:36:39 +03:00
Alexander Alekhin f21bde4d9f Merge pull request #16046 from alalek:issue_15990
* core: disable invalid constructors in C API by default

- C API objects will lose their default initializers through constructors

* samples: stop using of C API
2019-12-05 14:48:18 +03:00
Alexander Alekhin 986c5084a4 Merge pull request #16036 from dkurt:dnn_backport_15203 2019-12-05 09:56:00 +00:00
Alexander Alekhin 38180c2c97 Merge pull request #16014 from dkurt:dnn_ie_pooling_with_indices 2019-12-05 09:52:03 +00:00
Alexander Alekhin 95e36fd488 Merge pull request #16055 from alalek:issue_16041 2019-12-05 07:54:17 +00:00
Alexander Alekhin 36c9f7c3df Merge pull request #16061 from alalek:bindings_parser_support_simple_if 2019-12-04 19:13:22 +00:00
Dmitry Kurtaev d8e10f3a8d Enable MaxPooling with indices in Inference Engine 2019-12-04 19:14:55 +03:00
Alexander Alekhin 4dfa0a0383 bindings: basic support for #if preprocessor directives
- #if 0
- #ifdef __OPENCV_BUILD
2019-12-04 18:42:31 +03:00
Alexander Alekhin 818585fd12 core(tls): unblock TlsAbstraction destructor call
- required to unregister callbacks from system
2019-12-04 08:27:01 +00:00
Alexander Alekhin eb44e0a556 Merge pull request #16028 from catree:improve_calib3d_doc 2019-12-03 12:34:10 +00:00
Dmitry Kurtaev ca1ba7a53d Backport for dnn input shape estimation 2019-12-02 16:28:59 +03:00
Lubov Batanina 7523c777c5 Merge pull request #15537 from l-bat:ngraph
* Support nGraph

* Fix resize
2019-12-02 16:16:06 +03:00
catree 43d58aa760 Improve calib3d documentation:
- add reference to Rodrigues Jacobian
  - add references to SE(3) and Lie Groups topics
  - update some conventions and pinhole figure
2019-12-02 03:04:56 +01:00
Alexander Alekhin 20ac7f40f6 Merge pull request #16025 from dkurt:thebhatman/Mish_swish_3.4 2019-12-01 21:07:26 +00:00
thebhatman 8a18d132fc Port Swish and Mish layers 2019-12-01 11:55:39 +03:00
Alexander Alekhin 9a4404276a calib3d: revert stereoRectify() changes from PRs: 6836, 6972, 6955
(1/4) Revert "Correct image borders and principal point computation in cv::stereoRectify"

This reverts commit 93ff1fb2f2.

(2/4) Revert "fix calib3d changes in 6836 plus some others"

This reverts commit fa42a1cfc2.

(3/4) Revert "fix compiler warning"

This reverts commit b3d55489d3.

(4/4) Revert "add test for 6836"

This reverts commit d06b8c4ea9.
2019-11-30 23:37:49 +00:00
Alexander Alekhin f5b9705c70 Merge pull request #16006 from sajarindider:typo 2019-11-30 20:20:56 +00:00
sajarindider 101a147496 fixed Scheimpflug typo 2019-11-30 18:52:23 +00:00
Vadim Levin 8d74101f07 Merge pull request #15955 from VadimLevin:dev/vlevin/generator_tests
Tests for argument conversion of Python bindings generator

* Tests for parsing elemental types from Python bindings

  - Add positive and negative tests for int, float, double, size_t,
    const char*, bool.
  - Tests with wrong conversion behavior are skipped.

* Move implicit conversion of bool to integer/floating types to wrong
conversion behavior.
2019-11-29 16:24:13 +03:00
Alexander Alekhin 41af8aa046 Merge pull request #16017 from berak:fix_svm_train_auto 2019-11-29 11:38:22 +00:00
berak 0dfab6bbd0 ml: fix check in SVM::trainAuto 2019-11-28 20:33:58 +01:00
Alexander Alekhin 873250f5de Merge pull request #15998 from alalek:ts_count_skip_exception 2019-11-27 19:23:27 +00:00
Alexander Alekhin 6c37e10c83 Merge pull request #15994 from SSteve:affine_transform_docs 2019-11-27 19:23:09 +00:00
Alexander Alekhin 70146700aa Merge pull request #15839 from alalek:core_simd_v_setall_template 2019-11-27 19:19:35 +00:00
Alexander Alekhin 5af747c6fd Merge pull request #16001 from alalek:backport_15995 2019-11-26 18:35:28 +00:00
Alexander Alekhin 17dfae77af Merge pull request #15991 from collinbrake:feature_grammar_fixes_8 2019-11-26 15:48:22 +00:00
Brian Wignall af997529a1 Fix some typos 2019-11-26 18:41:19 +03:00
Alexander Alekhin 5639f5a296 ts: count skipped tests via SkipTestException
- apply tag 'skip_other'
2019-11-26 18:34:04 +03:00
Steve Nicholson 0c644d1ec8 Rename parameter R to H in AffineWarper member declarations 2019-11-25 16:31:03 -08:00
Alexander Alekhin a093a0e05c Merge pull request #15986 from dkurt:fix_15863 2019-11-25 20:04:47 +00:00
Alexander Alekhin cdc469786c Merge pull request #15978 from alalek:videoio_refactor_v4l 2019-11-25 20:04:25 +00:00
Maksim Shabunin 5ff1fababc Merge pull request #15959 from mshabunin:refactor-ml-tests
ml: refactored tests

* use parametrized tests where appropriate
* use stable theRNG in most tests
* use modern style with EXPECT_/ASSERT_ checks
2019-11-25 23:03:16 +03:00
Collin Brake 6276b86a78 grammar corrections 2019-11-25 13:49:09 -05:00
Dmitry Kurtaev 6e14cc2189 Resolve https://github.com/opencv/opencv/issues/15863 2019-11-24 21:59:25 +03:00
Alexander Alekhin 9e906d9e21 Merge pull request #15980 from SSteve:doxygen_links 2019-11-24 09:39:48 +00:00
Steve Nicholson dc4af58be0 Update links to Doxygen website 2019-11-23 22:23:17 -08:00
Alexander Alekhin 4a3ab8fbdb Merge pull request #15975 from SSteve:ios_install 2019-11-23 22:59:01 +00:00
Steve Nicholson b38547ee9a Update and add information to iOS build instructions. 2019-11-23 13:53:08 -08:00
Alexander Alekhin 501ff7f056 videoio(v4l2): use logging, update handling of EBUSY, device closing
- DEBUG logging compilation is enabled for all videoio backends
- eliminate output through perror(), stderr
2019-11-23 10:36:43 +00:00
Vadim Levin 373160ce00 Merge pull request #15973 from VadimLevin:dev/vlevin/video_capture_inf_loop
* Fix infinite loop when trying to change state of the busy camera

  - Add finite number of attempts in tryIoctl functions
    10 by default.

* Introduced new flag for ioctl call to handle EBUSY
2019-11-23 01:10:16 +03:00
Alexander Alekhin 50ac880335 Merge pull request #15971 from alalek:core_kmeans_handle_overflow 2019-11-22 21:36:02 +00:00
Natsu 54e6f5c237 Merge pull request #15970 from akemimadoka:master
* Fix android armv7 c++_static init crash

* core: move initialization of 'ios_base::Init' for Android
2019-11-22 18:42:25 +03:00
Alexander Alekhin 3266ac7667 core(kmeans): bailout if can't select cluster center 2019-11-22 14:40:02 +00:00
Alexander Alekhin ca28274895 Merge pull request #15968 from alalek:fix_msa_build 2019-11-21 17:36:10 +00:00
Alexander Alekhin ec55b6f6db core: fix MSA build 2019-11-21 18:59:41 +03:00
Alexander Alekhin 16ad53f354 Merge pull request #15962 from alalek:dnn_fix_ie_opencvlayer 2019-11-21 13:04:09 +00:00
Alexander Alekhin 86042af108 dnn: fix registration of custom OpenCVLayer
- do not require extensions library
2019-11-20 21:42:26 +00:00
Alexander Alekhin e459a5108c Merge pull request #15951 from alalek:python_reduce_code_size 2019-11-20 19:05:15 +00:00
Alexander Alekhin a2aa8db5a9 Merge pull request #15956 from lorenzolightsgdwarf:dnn_fix_tf_ssd 2019-11-20 15:43:32 +00:00
Everton Constantino 75315fb297 Merge pull request #15494 from everton1984:hal_vector_get_n
Improving VSX performance of integral function

* Adding support for vector get function on VSX datatypes so the
integral function gains a bit of performance.

* Removing get as a datatype member function and implementing a new HAL
instruction v_extract_n to get the n-th element of a vector register.

* Adding SSE/NEON/AVX intrinsics.

* Implement new HAL instruction v_broadcast_element on VSX/AVX/NEON/SSE.

* core(simd): add tests for v_extract_n/v_broadcast_element

- updated docs
- commented out code to repair compilation
- added WASM and MSA default implementations

* core(simd): fix compilation

- x86: avoid _mm256_extract_epi64/32/16/8 with MSVS 2015
- x86: _mm_extract_epi64 is 64-bit only

* cleanup
2019-11-20 13:41:07 +03:00
Lorenzo Lucignano c40fbad12e Samples DNN: tf_text_graph_sd.py loads box coder variance and box NMS params from config file 2019-11-20 10:45:57 +01:00
Alexander Alekhin 5d96f984b1 python: reduce code size of cv2.cpp 2019-11-19 22:43:28 +00:00
Alexander Alekhin 9d14c0b37a Merge pull request #15939 from alalek:ffmpeg_update_3.4 2019-11-19 18:45:39 +00:00
Alexander Alekhin 2f636b4456 Merge pull request #15918 from alalek:python_debug_parameter 2019-11-19 18:39:56 +00:00
Alexander Alekhin e07a488012 Merge pull request #15925 from alalek:core_test_simd_cpp_emulation
core(test): extending tests with SIMD C++ emulation code (intrin_cpp.hpp)

* core(test): test SIMD CPP emulation code (intrin_cpp.hpp)

* core(simd): eliminate build warnings from intrin_cpp.hpp
2019-11-19 21:08:45 +03:00
Alexander Alekhin 77bf5593e5 Merge pull request #15946 from alalek:fix_js_test_features2d 2019-11-19 14:25:28 +00:00
Alexander Alekhin 26513285dd Merge pull request #15945 from alalek:dnn_ie_extension_handling 2019-11-19 14:25:12 +00:00
Alexander Alekhin de64db3064 Merge pull request #15919 from alalek:python_fix_arginfo 2019-11-19 13:24:58 +00:00
Alexander Alekhin ec8db970f9 js(test): update features2d test 2019-11-19 07:40:12 +00:00
Alexander Alekhin 09d54c9f52 dnn: update InferenceEngine extension handling 2019-11-19 06:55:14 +00:00
Alexander Alekhin d00eb451bf ffmpeg/3.4: update FFmpeg wrapper 2019-11-18 19:13:45 +00:00
Alexander Alekhin 3f431a16a3 videoio: fix ffmpeg wrapper build 2019-11-18 18:56:57 +00:00
Alexander Alekhin 593e240d7c Merge pull request #15938 from alalek:backport_15290 2019-11-18 18:26:00 +00:00
Alexander Alekhin fb9d59ab15 Merge pull request #15937 from clunietp:3.4-fix-13577 2019-11-18 18:23:48 +00:00
cudawarped aff8c9bd28 videoio: retrieve encoded frames through FFmpeg backend
- backport 15290
- add extra test case
2019-11-18 19:23:19 +03:00
clunietp 2185bce4b7 Fix 13577 2019-11-18 07:41:34 -05:00
Alexander Alekhin f4d55d512f imgproc: fix bit-exact GaussianBlur() / sepFilter2D() (#15855)
* imgproc: fix bit-exact GaussianBlur() / sepFilter2D()

- avoid kernels with bad approximation
- GaussiabBlur - apply error-diffusion approximation for kernel (8-bit fraction)

* java(test): update features2d ref data

* test: update test_facedetect
2019-11-18 01:39:27 +03:00
Sebastián Gurin 955b20230c Merge pull request #15503 from cancerberoSgx:js-test-puppeteer
Js test puppeteer

* run_puppeteer.js / tests

* js run test section

* rollback html

* whitespace

* js: update OpenCV.js tests infrastructure

* js: exclude puppeteer from default 'npm install'

* js: update notes

* js: more fixes in run_puppeteer

* fix build folder
2019-11-17 00:29:38 +03:00
Alexander Alekhin 686ea5c1a6 Merge pull request #15917 from ChipKerchner:demosaicingToHal2 2019-11-16 19:45:37 +00:00
Alexander Alekhin 7ec91aefc1 python: force using of ArgInfo 2019-11-15 19:16:22 +03:00
Alexander Alekhin 973b367da6 python: emit bindings conversion failures on OPENCV_PYTHON_DEBUG=1 2019-11-15 18:55:24 +03:00
ChipKerchner 1d33335e33 Convert demosiacing with variable number of gradients to HAL - 5.5x faster 2019-11-15 07:42:03 -06:00
Alexander Alekhin 1f57eb93fd Merge pull request #15911 from l-bat:fix_reducel2 2019-11-15 11:04:05 +00:00
Alexander Alekhin 6773b938b3 Merge pull request #15896 from alalek:build_gcc_9 2019-11-14 14:22:02 +00:00
Liubov Batanina ac4fd4f4ae Fix ReduceL2 2019-11-14 15:30:53 +03:00
Alexander Alekhin 94f1c3d152 Merge pull request #15905 from alalek:issue_15904 2019-11-14 10:33:29 +00:00
Alexander Alekhin ad8d7e84b9 Merge pull request #15900 from komakai:fix-osx-build 2019-11-13 17:02:08 +00:00
Sebastián Gurin b48959fa57 Merge pull request #15425 from cancerberoSgx:nodejs
JS - adds a tutorial about running opencv.js in Node.js
2019-11-13 18:14:53 +03:00
Giles Payne 3cdbcc1645 Fix MacOS build 2019-11-13 21:10:08 +09:00
Alexander Alekhin 763b80d5fa imgproc(IPP): disable ippiDistanceTransform_3x3_8u32f_C1R 2019-11-13 14:14:19 +03:00
Alexander Alekhin d0c767428b Merge pull request #15891 from alalek:issue_15886 2019-11-12 22:57:15 +00:00
Alexander Alekhin a67248f386 Merge pull request #15883 from cbachhuber:refactor-opencl-information 2019-11-12 22:56:51 +00:00
Christoph Bachhuber c638f085aa Refactor for clarity and avoiding code duplication
Implement GArik's comments

Remove unnecessary c_str()

Fix brace position
2019-11-12 19:22:42 +01:00
Alexander Alekhin 7ecdcf6ca6 build: GCC9 compilation 2019-11-12 18:49:34 +03:00
Alexander Alekhin af92a517a7 cmake: set _WIN32_WINNT for Windows 7 API 2019-11-11 20:19:40 +00:00
Alexander Alekhin ba58bba4e8 Merge pull request #15875 from gyadam:fix-windows-install-doc 2019-11-10 09:35:59 +00:00
Alexander Alekhin e0b5637474 Merge pull request #15877 from mshabunin:fix-gst-relative-34 2019-11-10 09:25:29 +00:00
Alexander Alekhin d32d31577c Merge pull request #15835 from alalek:cmake_cpu_optimizations_fix_15802 2019-11-10 09:22:45 +00:00
Alexander Alekhin e9dcecf9b4 Merge pull request #15826 from alalek:cmake_fix_itt_define_condition 2019-11-10 09:22:22 +00:00
Maksim Shabunin fccf284088 Fixed relative paths handling in cap_gstreamer: 2019-11-09 11:34:30 +00:00
Lubov Batanina cfc781949d Merge pull request #15811 from l-bat:eltwise_div
Supported ONNX Squeeze, ReduceL2 and Eltwise::DIV

* Support eltwise div

* Fix test

* OpenCL support added

* refactoring

* fix code style

* Only squeeze with axes supported
2019-11-09 14:11:09 +03:00
Adam Gyarmati 3755099bd4 Fix Windows installation script error
Fix an error during Windows installation caused by trying to create the already existing Build directory. Also excluding intermediate steps for Install directory creation.
2019-11-08 19:05:46 -08:00
Alexander Alekhin af23375352 Merge pull request #15861 from dkurt:dnn_fix_get_input_layers 2019-11-08 22:01:07 +00:00
Alexander Alekhin 6053996253 Merge pull request #15319 from cancerberoSgx:fs 2019-11-08 13:20:09 +00:00
Sebastián Gurín dd9262c318 expose FS 2019-11-08 15:13:25 +03:00
collinbrake 35cebbd167 Merge pull request #15832 from collinbrake:feature_grammar_fixes_4
* Grammar fixes for python core operations docs

* fixed whitespace error

* reverted changes
2019-11-08 12:27:37 +03:00
Alexander Alekhin d66aa2e0ff Merge pull request #15848 from alalek:backport_test_15842 2019-11-07 16:48:41 +00:00
Dimitri Gerin 7c4158d8c2 Fix dnn::getLayerInputs 2019-11-07 08:13:33 +03:00
Alexander Alekhin c546a27de7 Merge pull request #15854 from czgdp1807:rem-typo 2019-11-06 13:47:37 +00:00
Alexander Smorkalov 377fcc062d Merge pull request #15159 from SSE4:fix_find_openexr 2019-11-06 13:37:37 +00:00
czgdp1807 07ef08e966 removed typo 2019-11-06 17:15:31 +05:30
SSE4 2e20f06f8e - fix FindOpenEXR to respect OPENEXR_ROOT
Signed-off-by: SSE4 <tomskside@gmail.com>
2019-11-06 17:26:52 +07:00
Alexander Alekhin 54d9597522 Merge pull request #15814 from i-murzov:3.4-ocl-cleanup 2019-11-06 09:54:29 +00:00
Alexander Alekhin f3e788b8ab Merge pull request #15813 from i-murzov:3.4-ocl-empty-platform 2019-11-06 08:12:40 +00:00
Igor Murzov cdbfdcc363 Fix OpenCL device detection when some OpenCL platform has no devices
It's not an error if some OpenCL platform has no devices. This makes
OpenCL device detection work correctly in the following scenario:

$ OPENCV_OPENCL_DEVICE=:GPU: ./opencv_test_dnn

OpenCV version: 4.1.2-dev
OpenCV VCS version: 4.1.2-80-g467748ee98-dirty
Build type: Debug
Compiler: /usr/bin/g++  (ver 7.4.0)
Parallel framework: pthreads
CPU features: SSE SSE2 SSE3 *SSE4.1 *SSE4.2 *FP16 *AVX *AVX2 *AVX512-SKX?
Intel(R) IPP version: ippIP AVX2 (l9) 2019.0.0 Gold (-) Jul 24 2018
OpenCL Platforms:
    AMD Accelerated Parallel Processing
    Portable Computing Language
        CPU: pthread-AMD Ryzen 7 2700X Eight-Core Processor (OpenCL 1.2 pocl HSTR: pthread-x86_64-pc-linux-gnu-znver1)
    NVIDIA CUDA
        dGPU: GeForce GTX 1080 (OpenCL 1.2 CUDA)
Current OpenCL device:
    Type = dGPU
    Name = GeForce GTX 1080
    Version = OpenCL 1.2 CUDA
    Driver version = 430.26
2019-11-05 20:02:39 +03:00
Chip Kerchner 2112aa31e6 Merge pull request #15828 from ChipKerchner:momentsToHal
* Convert moments in tile algorithms to HAL (1.3x faster for VSX).

* Adding NEON code back in for non 64-bit platforms.

* Remove floats from post processing.
2019-11-05 18:52:35 +03:00
TH3CHARLie 2c2716de0f core(test): add test for YAML parse multiple documents
- added removal of temporary file
2019-11-05 18:39:07 +03:00
Igor Murzov 6d5b900324 Simplify OpenCL info dumping code:
* Reduce code nesting
* Drop redundant .c_str() calls
2019-11-05 14:49:49 +03:00
Oleg Alexandrov 53139e6ebe Merge pull request #15838 from oleg-alexandrov:patch-2
Correct stereoRectify documentation
2019-11-03 16:37:25 +03:00
Alexander Alekhin a893969ec9 core(simd): v_setall template 2019-11-03 12:49:25 +00:00
Alexander Alekhin d5bbb16066 Merge pull request #15834 from berak:python_fix_type_error 2019-11-02 18:50:46 +00:00
Alexander Alekhin 21c38bbdaf cmake(cpu optmizations): fix cleanup of OPENCV_DEPENDANT_TARGETS_* vars 2019-11-02 10:34:54 +00:00
berak b7c8e9e874 python: fix type error msg 2019-11-02 08:17:07 +01:00
Gael Colas e65b51ca3c Merge pull request #15821 from ColasGael:colasg-viz-color
Fix wrong definition of viz::Color::navy()
2019-11-01 22:37:34 +03:00
Oleg Alexandrov d56535afce Merge pull request #15820 from oleg-alexandrov:patch-1
Clarify stereoRectify() doc

The function stereoRectify() takes as input a coordinate transform between two cameras. It is ambiguous how it goes. I clarified that it goes from the second camera to the first.
2019-11-01 22:34:11 +03:00
yuriyluxriot 4e156a162f Merge pull request #15812 from yuriyluxriot:fls_replaces_tls
* Use FlsAlloc/FlsFree/FlsGetValue/FlsSetValue instead of TlsAlloc/TlsFree/TlsGetValue/TlsSetValue to implment TLS value cleanup when thread has been terminated on Windows Vista and above

* Fix 32-bit build

* Fixed calling convention of cleanup callback

* WINAPI changed to NTAPI

* Use proper guard macro
2019-11-01 22:33:12 +03:00
Chip Kerchner ed7e4273cd Merge pull request #15555 from ChipKerchner:flipVectorize
* Vectorize flipHoriz and flipVert functions.

* Change v_load_mirror_1 to use vec_revb for VSX

* Only use vec_revb in ISA3.0

* Removing vec_revb code since some of the older compilers don't fully support it.

* Use new v_reverse intrinsic and cleanup code.

* Ensure there are no alignment issues with copies
2019-11-01 22:30:48 +03:00
Alexander Alekhin 657c17bb8c cmake: fix ITT define condition 2019-11-01 15:07:49 +03:00
Alexander Alekhin cec7cc037b Merge pull request #15819 from alalek:ts_unblock_reporting_of_disabled_tests 2019-10-31 20:39:41 +00:00
Alexander Alekhin 5c12bafe80 Merge pull request #15805 from i-murzov:3.4 2019-10-31 20:39:16 +00:00
Ciprian Alexandru Pitis d2e02779c4 Merge pull request #15799 from Cpitis:feature/parallelization
Parallelize pyrDown & calcSharrDeriv

* ::pyrDown has been parallelized

* CalcSharrDeriv parallelized

* Fixed whitespace

* Set granularity based on amount of threads enabled

* Granularity changed to cv::getNumThreads, now each thread should receive 1/n sized stripes

* imgproc: move PyrDownInvoker<CastOp>::operator() implementation

* imgproc(pyramid): remove syloopboundary()

* video: SharrDerivInvoker replace 'Mat*' => 'Mat&' fields
2019-10-31 23:38:49 +03:00
CJ Smith c2f2ea6b85 Merge pull request #15789 from CJSmith-0141:15779-scale-bug-in-stereo-match-sample
* Changes disparity image to float representation

Signed-off-by: Connor James Smith <cjs.connor.smith@gmail.com>

* samples: update disparity multiplier handling in stereo_match.cpp
2019-10-31 22:29:04 +03:00
Oleg Alexandrov af433d0352 Merge pull request #15780 from oleg-alexandrov:master
* Doc bugfix

The documentation page StereoBinaryBM and StereoBinarySGBM says that it returns a disparity that is scaled multiplied by 16. This scaling must be undone before calling reprojectImageTo3D, otherwise the results are wrong. The function reprojectImageTo3D() could do this scaling internally, maybe, but at least the documentation must explain that this has to be done.

* calib3d: update reprojectImageTo3D documentation

* calib3d: add StereoBM/StereoSGBM into notes list
2019-10-31 22:28:01 +03:00
Alexander Alekhin ee044771a7 Merge pull request #15478 from terfendail:wintr_stereosgbm 2019-10-31 19:24:06 +00:00
Dizhenin Vlad edc5518f68 Merge pull request #15608 from SimpleVlad:3.4
* Add flags for build js

* Add poi.json

* Rebase whitelist into JSON file

* Rework generator of white_list

* Fix small typos

* Transfer opencv_js.josn in opencv_js.config.py

* Edit OPENCV_JS_WHITELIST

* Write comment

* Add description

* Fix typos in desc

* flag's append deleeted

* Fix whitespace

* variable deleted

* fix comment on lines 229 and 235
2019-10-31 22:09:33 +03:00
Alexander Alekhin 79f792ad05 ts: do not block reporting of launched "DISABLED_" tests
If tests are run through GTest option `--gtest_also_run_disabled_tests`
2019-10-31 15:13:50 +03:00
Igor Murzov a9d23a6479 Fix wording in some tutorials 2019-10-30 13:27:17 +03:00
Alexander Alekhin bad4e5c3eb Merge pull request #15692 from alalek:core_tls_handle_thread_termination 2019-10-29 20:40:35 +00:00
Alexander Alekhin e86c888a92 Merge pull request #15791 from alalek:android_camera2_issue_14915 2019-10-29 19:10:00 +00:00
Chip Kerchner a71ff50130 Merge pull request #15623 from ChipKerchner:optimizeHOGpipeline
* Use circular lut hustory buffer in computeGradient of HOG

* Initialize prefetch data outside main loop.  Avoid code duplication.
2019-10-29 13:42:20 +03:00
Alexander Alekhin 80c4cedd25 android: use .getRowStride() in JavaCamera2View 2019-10-28 18:45:56 +00:00
Alexander Alekhin 732657cc46 Merge pull request #15793 from Cherubin7th:3.4 2019-10-27 22:45:19 +00:00
André Lippok 86a8ff6129 Fixed typo in assertion 2019-10-27 17:43:31 +01:00
Alexander Alekhin d8ab83600b Merge pull request #15761 from alalek:core_trace_itt_parameter 2019-10-26 21:39:08 +00:00
Alexander Alekhin 6ec5ae0215 core(trace): add ITT control parameter
- OPENCV_TRACE_ITT_ENABLE
2019-10-26 15:03:51 +00:00
Alexander Alekhin 7cf1054d36 Merge pull request #15764 from ChipKerchner:demosaicingToHal 2019-10-25 13:49:46 +00:00
Vitaly Tuzov 42b1d04999 StereoSGBM algorithm updated to use wide universal intrinsics 2019-10-25 16:34:16 +03:00
Alexander Alekhin eabe679f78 Merge pull request #15770 from terfendail:stereobm_fix 2019-10-24 17:58:22 +00:00
Vitaly Tuzov 1ce5a724c7 Fixed StereoBM uniqueness check 2019-10-24 17:54:49 +03:00
Alexander Alekhin d65fead337 Merge pull request #15752 from dkurt:fix_15750 2019-10-24 07:06:32 +00:00
Alexander Alekhin 17e2bf5717 core(tls): implement releasing of TLS on thread termination
- move TLS & instrumentation code out of core/utility.hpp
- (*) TLSData lost .gather() method (to dispose thread data on thread termination)
- use TLSDataAccumulator for reliable collecting of thread data
- prefer using of .detachData() + .cleanupDetachedData() instead of .gather() method

(*) API is broken: replace TLSData => TLSDataAccumulator if gather required
(objects disposal on threads termination is not available in accumulator mode)
2019-10-24 06:36:18 +00:00
Alexander Alekhin 5e8d8df847 Merge pull request #15754 from float13:patch-1 2019-10-23 17:02:22 +00:00
ChipKerchner c46f119e0e Convert demosaic functions to HAL 2019-10-23 10:47:07 -05:00
float13 1accf3b3f4 Tutorial - Make required input args positional.
I think it would help to change all 3 of the the input file arguments to be "positional" for consistency with the other tutorials. This also simplifies the command line input to run this tutorial by reducing typing, and helpfully prints the "usage" info if any of the 3 required inputs are missing.

I'm new to OpenCV and working through the tutorials. I kept getting runtime errors with this one until I realized that the arguments weren't positional, and I was missing the "--input1", "--input2, "--input3" flags preceding the filenames. All of the previous tutorials had required filenames as positional arguments and didn't require this.

The original code would require each input to be specified like this:
./compareHist_Demo --input1 filename1 --input2 filename2 --input3 filename3 

But with this change, the above command is simplified to:
./compareHist_Demo  filename1 filename2 filename3

This avoids a confusing runtime error to make things simpler for newcomers like me :)
2019-10-23 13:07:52 +03:00
Chip Kerchner 5a6a49405d Merge pull request #15738 from ChipKerchner:bugInt64x2Comparison
Fixing bug with comparison of v_int64x2 or v_uint64x2

* Casting v_uint64x2 to v_float64x2 and comparing does NOT work in all cases.  Rewrite using epi64 instructions - faster too.

* Fix bad merge.

* Fix equal comparsion for non-SSE4.1. Add test cases for v_int64x2 comparisons.

* Try to fix merge conflict.

* Only test v_int64x2 comparisons if CV_SIMD_64F

* Fix compiler warning.
2019-10-22 16:37:20 +03:00
Alexander Alekhin 1864b64f64 Merge pull request #15739 from dkurt:darknet_shortcut_asymm 2019-10-22 12:52:13 +00:00
Alexander Alekhin 4bd2ad30c4 Merge pull request #15756 from dankamongmen:dankamongmen/stitching_surf_default 2019-10-22 12:51:30 +00:00
nick black 6e9eca29e2 stitching_detailed: use correct match_conf default
The usage function states that the default for match_conf is
0.65 if the default SURF feature finder is used, and 0.3 for
orbs. Indeed, if --feature orbs is used, match_conf is set
to 0.3f. This is a NOP, because the real default is also set
to 0.3f. Change it to 0.65f when SURF is in play.
2019-10-22 08:03:46 -04:00
Dmitry Kurtaev dfe0368835 Fix custom IE layers in case of no MKLDNN plugin 2019-10-21 19:09:44 +03:00
Alexander Alekhin a8d14e88fe Merge pull request #15743 from collinbrake:feature_grammar_fixes_2 2019-10-20 13:08:28 +00:00
Alexander Alekhin 6576e8b927 Merge pull request #14518 from SSteve:intersectConvexConvex-example 2019-10-20 13:06:27 +00:00
Steve Nicholson acb3b3bd4d Add documentation and example program for intersectConvexConvex 2019-10-19 22:08:07 -07:00
Dmitry Kurtaev af61a15839 Fix Darknet eltwise 2019-10-19 12:54:15 +03:00
collin 3ada597449 grammar corrections for python gui docs 2019-10-18 17:42:56 -04:00
Alexander Alekhin 938d8dce06 Merge pull request #15685 from pmur:cnz64f-simd 2019-10-18 20:19:40 +00:00
Alexander Alekhin 6e85e852d4 Merge pull request #15740 from xerus:fix_typo 2019-10-18 18:41:35 +00:00
Alexander Alekhin 70a5553499 Merge pull request #15741 from mipsopen-fwu:issue_15730 2019-10-18 18:40:25 +00:00
Fei Wu 90af2835a2 Fix issue 15730. 2019-10-19 00:36:18 +08:00
Pavel Grunt 83e2e124a3 OpenCVFindMKL: Fix a typo 2019-10-18 18:33:06 +02:00
Dmitry Kurtaev adbd613660 Enable Eltwise layer with different numbers of inputs channels 2019-10-18 18:51:52 +03:00
Alexander Alekhin 849d8d31fe Merge pull request #15737 from alalek:issue_15705 2019-10-18 14:52:26 +00:00
Alexander Alekhin 24ebca5c59 core(simd): v_reverse() for MSA backend 2019-10-18 16:43:03 +03:00
Alexander Alekhin ead7d6d80f Merge pull request #15716 from alalek:javadoc_fix 2019-10-17 22:35:14 +00:00
Alexander Alekhin 34df28db2b Merge pull request #15180 from terfendail:wintr_stereobm 2019-10-17 20:18:30 +00:00
Alexander Alekhin a2b3cd9a2c Merge pull request #15709 from alalek:js_simd_reverse 2019-10-17 13:14:50 +00:00
Alexander Alekhin d31da08d43 Merge pull request #15708 from alalek:js_simd_support_1.38.48 2019-10-17 13:14:34 +00:00
Alexander Alekhin 17e9fde75a Merge pull request #15718 from alalek:pylint_warnings 2019-10-17 10:46:03 +00:00
Alexander Smorkalov 692e1eccb6 Merge pull request #15720 from alalek:cmake_fix_uwp 2019-10-17 10:35:27 +00:00
Alexander Smorkalov 009f5f74ef Merge pull request #15722 from jasjuang:3.4 2019-10-17 10:19:47 +00:00
jasjuang 4c7db02925 document CC_STAT_MAX in ConnectedComponentsTypes 2019-10-16 17:22:25 -07:00
Alexander Alekhin c4e2e17b0c cmake: fix UWP scripts path 2019-10-16 21:42:31 +00:00
Alexander Alekhin 9255df44d0 Merge pull request #15715 from adamrankin:patch-1 2019-10-16 18:52:10 +00:00
Alexander Alekhin 0e40c8a031 fix pylint warnings
pylint 1.8.3
2019-10-16 18:49:33 +03:00
Alexander Alekhin 86e7d82418 javadoc: fix generation with OpenJDK 11 2019-10-16 18:14:07 +03:00
Adam Rankin 3b070517ad COMP: Enabling build with recent VTK version
VTK_MAJOR_VERSION not found unless header is included
2019-10-16 10:04:41 -04:00
Alexander Alekhin ad5d14ec0e Merge pull request #15701 from alalek:issue_15691 2019-10-16 11:13:07 +00:00
Alexander Alekhin bce653117f Merge pull request #15700 from alalek:issue_12943 2019-10-16 11:12:49 +00:00
Alexander Alekhin ad172726c0 js(simd): v_reverse implementation 2019-10-15 18:46:08 +03:00
Alexander Alekhin b1a8de0901 js(simd): support Emscripten 1.38.48-upstream 2019-10-15 15:39:22 +03:00
Alexander Alekhin 823884b064 core(alloc): force initialization of memalign flag
- before main() launch
2019-10-15 13:07:11 +03:00
Alexander Alekhin 6a7d1c15d3 core(ipp): skip huge input in flip()
- IPP/SSE4.2 works well
2019-10-14 18:26:19 +03:00
Alexander Smorkalov d154fa4b4c Merge pull request #15688 from JamesNewton:3.4 2019-10-12 18:05:55 +00:00
JamesNewton 47fc889df0 Update js_image_arithmetics.markdown 2019-10-11 10:07:22 -07:00
Chip Kerchner 027769bf5d Merge pull request #15662 from ChipKerchner:addVReverseIntrinsic
* New v_reverse HAL intrinsic for reversing the ordering of a vector

* Fix conflict.

* Try to resolve conflict again.

* Try one more time.

* Add _MM_SHUFFLE. Remove non-vectorize code in SSE2. Fix copy and paste issue with NEON.

* Change v_uint16x8 SSE2 version to use shuffles
2019-10-11 18:34:17 +03:00
Everton Constantino 9ca9249992 Merge pull request #15527 from everton1984:faster_acc
* Adding support for vectorized masking for uchar/ushort.

* Fixing bug where mask was zeroing the dst. Improved the way to calculate
the mask and tweaked for further performance improvements.

* Fixing mask comparison test.

* Restricting to one channel.

* Adding support for 3 channels, switch old approach to start using HAL's
v_select.
2019-10-11 18:32:59 +03:00
Paul E. Murphy ec91a3d59d core: vectorize countNonZero64f
Improves performance a bit. 2.2x on P9 and 2 - 3x on coffee lake
x86-64.
2019-10-11 09:02:46 -05:00
Alexander Alekhin dd4f591d54 Merge tag '3.4.8' 2019-10-09 18:33:35 +03:00
Vitaly Tuzov 0a1b957331 StereoBM algorithm updated to use wide universal intrinsics 2019-09-25 14:37:12 +03:00
389 changed files with 15882 additions and 7716 deletions
+1
View File
@@ -22,3 +22,4 @@ bin/
*.log
*.tlog
build
node_modules
+5 -5
View File
@@ -1,8 +1,8 @@
# Binaries branch name: ffmpeg/3.4_20190905
# Binaries were created for OpenCV: fafada28ebc0f2e5423a7d8ece425574ef01ff60
ocv_update(FFMPEG_BINARIES_COMMIT "bf1730f4c4ba1996bed1fe268b52e4e942151cd6")
ocv_update(FFMPEG_FILE_HASH_BIN32 "6899624f88cb4cbb1604edc5e12b18ab")
ocv_update(FFMPEG_FILE_HASH_BIN64 "4729c052cb0c53ab56e9a0eed91559df")
# Binaries branch name: ffmpeg/3.4_20191118
# Binaries were created for OpenCV: 3f431a16a38be35e52b4887a3591d23030d34fc5
ocv_update(FFMPEG_BINARIES_COMMIT "548e3c997a80d65f710b9048f1d33371e3a203ac")
ocv_update(FFMPEG_FILE_HASH_BIN32 "168635a192fc2d2ae7d7d40150f0b349")
ocv_update(FFMPEG_FILE_HASH_BIN64 "cbc25f8f2954475b127c7558558c18e6")
ocv_update(FFMPEG_FILE_HASH_CMAKE "3b90f67f4b429e77d3da36698cef700c")
function(download_win_ffmpeg script_var)
+11 -6
View File
@@ -61,12 +61,17 @@ static const uint16_t kAcTable[128] = {
void VP8ParseQuant(VP8Decoder* const dec) {
VP8BitReader* const br = &dec->br_;
const int base_q0 = VP8GetValue(br, 7);
const int dqy1_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dqy2_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dqy2_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dquv_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dquv_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int base_q0 = VP8GetValue(br, 7, "global-header");
const int dqy1_dc = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 4, "global-header") : 0;
const int dqy2_dc = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 4, "global-header") : 0;
const int dqy2_ac = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 4, "global-header") : 0;
const int dquv_dc = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 4, "global-header") : 0;
const int dquv_ac = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 4, "global-header") : 0;
const VP8SegmentHeader* const hdr = &dec->segment_hdr_;
int i;
+31 -26
View File
@@ -296,20 +296,21 @@ static void ParseIntraMode(VP8BitReader* const br,
// to decode more than 1 keyframe.
if (dec->segment_hdr_.update_map_) {
// Hardcoded tree parsing
block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0])
? VP8GetBit(br, dec->proba_.segments_[1])
: 2 + VP8GetBit(br, dec->proba_.segments_[2]);
block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0], "segments")
? VP8GetBit(br, dec->proba_.segments_[1], "segments")
: VP8GetBit(br, dec->proba_.segments_[2], "segments") + 2;
} else {
block->segment_ = 0; // default for intra
}
if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_);
if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_, "skip");
block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first
block->is_i4x4_ = !VP8GetBit(br, 145, "block-size");
if (!block->is_i4x4_) {
// Hardcoded 16x16 intra-mode decision tree.
const int ymode =
VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED)
: (VP8GetBit(br, 163) ? V_PRED : DC_PRED);
VP8GetBit(br, 156, "pred-modes") ?
(VP8GetBit(br, 128, "pred-modes") ? TM_PRED : H_PRED) :
(VP8GetBit(br, 163, "pred-modes") ? V_PRED : DC_PRED);
block->imodes_[0] = ymode;
memset(top, ymode, 4 * sizeof(*top));
memset(left, ymode, 4 * sizeof(*left));
@@ -323,22 +324,25 @@ static void ParseIntraMode(VP8BitReader* const br,
const uint8_t* const prob = kBModesProba[top[x]][ymode];
#if (USE_GENERIC_TREE == 1)
// Generic tree-parsing
int i = kYModesIntra4[VP8GetBit(br, prob[0])];
int i = kYModesIntra4[VP8GetBit(br, prob[0], "pred-modes")];
while (i > 0) {
i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i], "pred-modes")];
}
ymode = -i;
#else
// Hardcoded tree parsing
ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED :
!VP8GetBit(br, prob[1]) ? B_TM_PRED :
!VP8GetBit(br, prob[2]) ? B_VE_PRED :
!VP8GetBit(br, prob[3]) ?
(!VP8GetBit(br, prob[4]) ? B_HE_PRED :
(!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) :
(!VP8GetBit(br, prob[6]) ? B_LD_PRED :
(!VP8GetBit(br, prob[7]) ? B_VL_PRED :
(!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED)));
ymode = !VP8GetBit(br, prob[0], "pred-modes") ? B_DC_PRED :
!VP8GetBit(br, prob[1], "pred-modes") ? B_TM_PRED :
!VP8GetBit(br, prob[2], "pred-modes") ? B_VE_PRED :
!VP8GetBit(br, prob[3], "pred-modes") ?
(!VP8GetBit(br, prob[4], "pred-modes") ? B_HE_PRED :
(!VP8GetBit(br, prob[5], "pred-modes") ? B_RD_PRED
: B_VR_PRED)) :
(!VP8GetBit(br, prob[6], "pred-modes") ? B_LD_PRED :
(!VP8GetBit(br, prob[7], "pred-modes") ? B_VL_PRED :
(!VP8GetBit(br, prob[8], "pred-modes") ? B_HD_PRED
: B_HU_PRED))
);
#endif // USE_GENERIC_TREE
top[x] = ymode;
}
@@ -348,9 +352,9 @@ static void ParseIntraMode(VP8BitReader* const br,
}
}
// Hardcoded UVMode decision tree
block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
: !VP8GetBit(br, 114) ? V_PRED
: VP8GetBit(br, 183) ? TM_PRED : H_PRED;
block->uvmode_ = !VP8GetBit(br, 142, "pred-modes-uv") ? DC_PRED
: !VP8GetBit(br, 114, "pred-modes-uv") ? V_PRED
: VP8GetBit(br, 183, "pred-modes-uv") ? TM_PRED : H_PRED;
}
int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) {
@@ -514,8 +518,10 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
for (b = 0; b < NUM_BANDS; ++b) {
for (c = 0; c < NUM_CTX; ++c) {
for (p = 0; p < NUM_PROBAS; ++p) {
const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ?
VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p];
const int v =
VP8GetBit(br, CoeffsUpdateProba[t][b][c][p], "global-header") ?
VP8GetValue(br, 8, "global-header") :
CoeffsProba0[t][b][c][p];
proba->bands_[t][b].probas_[c][p] = v;
}
}
@@ -524,9 +530,8 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]];
}
}
dec->use_skip_proba_ = VP8Get(br);
dec->use_skip_proba_ = VP8Get(br, "global-header");
if (dec->use_skip_proba_) {
dec->skip_p_ = VP8GetValue(br, 8);
dec->skip_p_ = VP8GetValue(br, 8, "global-header");
}
}
+42 -39
View File
@@ -161,23 +161,26 @@ static int ParseSegmentHeader(VP8BitReader* br,
VP8SegmentHeader* hdr, VP8Proba* proba) {
assert(br != NULL);
assert(hdr != NULL);
hdr->use_segment_ = VP8Get(br);
hdr->use_segment_ = VP8Get(br, "global-header");
if (hdr->use_segment_) {
hdr->update_map_ = VP8Get(br);
if (VP8Get(br)) { // update data
hdr->update_map_ = VP8Get(br, "global-header");
if (VP8Get(br, "global-header")) { // update data
int s;
hdr->absolute_delta_ = VP8Get(br);
hdr->absolute_delta_ = VP8Get(br, "global-header");
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;
hdr->quantizer_[s] = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 7, "global-header") : 0;
}
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0;
hdr->filter_strength_[s] = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 6, "global-header") : 0;
}
}
if (hdr->update_map_) {
int s;
for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u;
proba->segments_[s] = VP8Get(br, "global-header") ?
VP8GetValue(br, 8, "global-header") : 255u;
}
}
} else {
@@ -205,7 +208,7 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
size_t last_part;
size_t p;
dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2)) - 1;
dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2, "global-header")) - 1;
last_part = dec->num_parts_minus_one_;
if (size < 3 * last_part) {
// we can't even read the sizes with sz[]! That's a failure.
@@ -229,21 +232,21 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
// Paragraph 9.4
static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) {
VP8FilterHeader* const hdr = &dec->filter_hdr_;
hdr->simple_ = VP8Get(br);
hdr->level_ = VP8GetValue(br, 6);
hdr->sharpness_ = VP8GetValue(br, 3);
hdr->use_lf_delta_ = VP8Get(br);
hdr->simple_ = VP8Get(br, "global-header");
hdr->level_ = VP8GetValue(br, 6, "global-header");
hdr->sharpness_ = VP8GetValue(br, 3, "global-header");
hdr->use_lf_delta_ = VP8Get(br, "global-header");
if (hdr->use_lf_delta_) {
if (VP8Get(br)) { // update lf-delta?
if (VP8Get(br, "global-header")) { // update lf-delta?
int i;
for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {
if (VP8Get(br)) {
hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6);
if (VP8Get(br, "global-header")) {
hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header");
}
}
for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
if (VP8Get(br)) {
hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6);
if (VP8Get(br, "global-header")) {
hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header");
}
}
}
@@ -352,8 +355,8 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
buf_size -= frm_hdr->partition_length_;
if (frm_hdr->key_frame_) {
pic_hdr->colorspace_ = VP8Get(br);
pic_hdr->clamp_type_ = VP8Get(br);
pic_hdr->colorspace_ = VP8Get(br, "global-header");
pic_hdr->clamp_type_ = VP8Get(br, "global-header");
}
if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
@@ -378,7 +381,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
"Not a key frame.");
}
VP8Get(br); // ignore the value of update_proba_
VP8Get(br, "global-header"); // ignore the value of update_proba_
VP8ParseProba(br, dec);
@@ -403,28 +406,28 @@ static const uint8_t kZigzag[16] = {
// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2
static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
int v;
if (!VP8GetBit(br, p[3])) {
if (!VP8GetBit(br, p[4])) {
if (!VP8GetBit(br, p[3], "coeffs")) {
if (!VP8GetBit(br, p[4], "coeffs")) {
v = 2;
} else {
v = 3 + VP8GetBit(br, p[5]);
v = 3 + VP8GetBit(br, p[5], "coeffs");
}
} else {
if (!VP8GetBit(br, p[6])) {
if (!VP8GetBit(br, p[7])) {
v = 5 + VP8GetBit(br, 159);
if (!VP8GetBit(br, p[6], "coeffs")) {
if (!VP8GetBit(br, p[7], "coeffs")) {
v = 5 + VP8GetBit(br, 159, "coeffs");
} else {
v = 7 + 2 * VP8GetBit(br, 165);
v += VP8GetBit(br, 145);
v = 7 + 2 * VP8GetBit(br, 165, "coeffs");
v += VP8GetBit(br, 145, "coeffs");
}
} else {
const uint8_t* tab;
const int bit1 = VP8GetBit(br, p[8]);
const int bit0 = VP8GetBit(br, p[9 + bit1]);
const int bit1 = VP8GetBit(br, p[8], "coeffs");
const int bit0 = VP8GetBit(br, p[9 + bit1], "coeffs");
const int cat = 2 * bit1 + bit0;
v = 0;
for (tab = kCat3456[cat]; *tab; ++tab) {
v += v + VP8GetBit(br, *tab);
v += v + VP8GetBit(br, *tab, "coeffs");
}
v += 3 + (8 << cat);
}
@@ -438,24 +441,24 @@ static int GetCoeffsFast(VP8BitReader* const br,
int ctx, const quant_t dq, int n, int16_t* out) {
const uint8_t* p = prob[n]->probas_[ctx];
for (; n < 16; ++n) {
if (!VP8GetBit(br, p[0])) {
if (!VP8GetBit(br, p[0], "coeffs")) {
return n; // previous coeff was last non-zero coeff
}
while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs
while (!VP8GetBit(br, p[1], "coeffs")) { // sequence of zero coeffs
p = prob[++n]->probas_[0];
if (n == 16) return 16;
}
{ // non zero coeff
const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];
int v;
if (!VP8GetBit(br, p[2])) {
if (!VP8GetBit(br, p[2], "coeffs")) {
v = 1;
p = p_ctx[1];
} else {
v = GetLargeValue(br, p);
p = p_ctx[2];
}
out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0];
}
}
return 16;
@@ -468,24 +471,24 @@ static int GetCoeffsAlt(VP8BitReader* const br,
int ctx, const quant_t dq, int n, int16_t* out) {
const uint8_t* p = prob[n]->probas_[ctx];
for (; n < 16; ++n) {
if (!VP8GetBitAlt(br, p[0])) {
if (!VP8GetBitAlt(br, p[0], "coeffs")) {
return n; // previous coeff was last non-zero coeff
}
while (!VP8GetBitAlt(br, p[1])) { // sequence of zero coeffs
while (!VP8GetBitAlt(br, p[1], "coeffs")) { // sequence of zero coeffs
p = prob[++n]->probas_[0];
if (n == 16) return 16;
}
{ // non zero coeff
const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];
int v;
if (!VP8GetBitAlt(br, p[2])) {
if (!VP8GetBitAlt(br, p[2], "coeffs")) {
v = 1;
p = p_ctx[1];
} else {
v = GetLargeValue(br, p);
p = p_ctx[2];
}
out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0];
}
}
return 16;
+1 -1
View File
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 0
#define DEC_REV_VERSION 2
#define DEC_REV_VERSION 3
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
+61 -64
View File
@@ -362,12 +362,8 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
// When reading htrees, some might be unused, as the format allows it.
// We will still read them but put them in this htree_group_bogus.
HTreeGroup htree_group_bogus;
HuffmanCode* huffman_tables = NULL;
HuffmanCode* huffman_tables_bogus = NULL;
HuffmanCode* next = NULL;
HuffmanCode* huffman_table = NULL;
int num_htree_groups = 1;
int num_htree_groups_max = 1;
int max_alphabet_size = 0;
@@ -418,12 +414,6 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
if (*mapped_group == -1) *mapped_group = num_htree_groups++;
huffman_image[i] = *mapped_group;
}
huffman_tables_bogus = (HuffmanCode*)WebPSafeMalloc(
table_size, sizeof(*huffman_tables_bogus));
if (huffman_tables_bogus == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error;
}
} else {
num_htree_groups = num_htree_groups_max;
}
@@ -453,63 +443,71 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
goto Error;
}
next = huffman_tables;
huffman_table = huffman_tables;
for (i = 0; i < num_htree_groups_max; ++i) {
// If the index "i" is unused in the Huffman image, read the coefficients
// but store them to a bogus htree_group.
const int is_bogus = (mapping != NULL && mapping[i] == -1);
HTreeGroup* const htree_group =
is_bogus ? &htree_group_bogus :
&htree_groups[(mapping == NULL) ? i : mapping[i]];
HuffmanCode** const htrees = htree_group->htrees;
HuffmanCode* huffman_tables_i = is_bogus ? huffman_tables_bogus : next;
int size;
int total_size = 0;
int is_trivial_literal = 1;
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
htrees[j] = huffman_tables_i;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += 1 << color_cache_bits;
}
size =
ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables_i);
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
is_trivial_literal = (huffman_tables_i->bits == 0);
}
total_size += huffman_tables_i->bits;
huffman_tables_i += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
for (k = 1; k < alphabet_size; ++k) {
if (code_lengths[k] > local_max_bits) {
local_max_bits = code_lengths[k];
}
// If the index "i" is unused in the Huffman image, just make sure the
// coefficients are valid but do not store them.
if (mapping != NULL && mapping[i] == -1) {
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
if (j == 0 && color_cache_bits > 0) {
alphabet_size += (1 << color_cache_bits);
}
// Passing in NULL so that nothing gets filled.
if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) {
goto Error;
}
max_bits += local_max_bits;
}
}
if (!is_bogus) next = huffman_tables_i;
htree_group->is_trivial_literal = is_trivial_literal;
htree_group->is_trivial_code = 0;
if (is_trivial_literal) {
const int red = htrees[RED][0].value;
const int blue = htrees[BLUE][0].value;
const int alpha = htrees[ALPHA][0].value;
htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
htree_group->is_trivial_code = 1;
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
} else {
HTreeGroup* const htree_group =
&htree_groups[(mapping == NULL) ? i : mapping[i]];
HuffmanCode** const htrees = htree_group->htrees;
int size;
int total_size = 0;
int is_trivial_literal = 1;
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
htrees[j] = huffman_table;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += (1 << color_cache_bits);
}
size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table);
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
is_trivial_literal = (huffman_table->bits == 0);
}
total_size += huffman_table->bits;
huffman_table += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
for (k = 1; k < alphabet_size; ++k) {
if (code_lengths[k] > local_max_bits) {
local_max_bits = code_lengths[k];
}
}
max_bits += local_max_bits;
}
}
htree_group->is_trivial_literal = is_trivial_literal;
htree_group->is_trivial_code = 0;
if (is_trivial_literal) {
const int red = htrees[RED][0].value;
const int blue = htrees[BLUE][0].value;
const int alpha = htrees[ALPHA][0].value;
htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
htree_group->is_trivial_code = 1;
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
}
}
htree_group->use_packed_table =
!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
}
htree_group->use_packed_table =
!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
}
ok = 1;
@@ -521,7 +519,6 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
Error:
WebPSafeFree(code_lengths);
WebPSafeFree(huffman_tables_bogus);
WebPSafeFree(mapping);
if (!ok) {
WebPSafeFree(huffman_image);
+1 -1
View File
@@ -25,7 +25,7 @@
#define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 0
#define DMUX_REV_VERSION 2
#define DMUX_REV_VERSION 3
typedef struct {
size_t start_; // start location of the data
+2 -2
View File
@@ -214,7 +214,7 @@ static void ApplyAlphaMultiply_SSE2(uint8_t* rgba, int alpha_first,
// Alpha detection
static int HasAlpha8b_SSE2(const uint8_t* src, int length) {
const __m128i all_0xff = _mm_set1_epi8(0xff);
const __m128i all_0xff = _mm_set1_epi8((char)0xff);
int i = 0;
for (; i + 16 <= length; i += 16) {
const __m128i v = _mm_loadu_si128((const __m128i*)(src + i));
@@ -228,7 +228,7 @@ static int HasAlpha8b_SSE2(const uint8_t* src, int length) {
static int HasAlpha32b_SSE2(const uint8_t* src, int length) {
const __m128i alpha_mask = _mm_set1_epi32(0xff);
const __m128i all_0xff = _mm_set1_epi8(0xff);
const __m128i all_0xff = _mm_set1_epi8((char)0xff);
int i = 0;
// We don't know if we can access the last 3 bytes after the last alpha
// value 'src[4 * length - 4]' (because we don't know if alpha is the first
+2 -2
View File
@@ -173,8 +173,8 @@ static int AndroidCPUInfo(CPUFeature feature) {
const AndroidCpuFamily cpu_family = android_getCpuFamily();
const uint64_t cpu_features = android_getCpuFeatures();
if (feature == kNEON) {
return (cpu_family == ANDROID_CPU_FAMILY_ARM &&
0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON));
return cpu_family == ANDROID_CPU_FAMILY_ARM &&
(cpu_features & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
}
return 0;
}
+7 -7
View File
@@ -326,7 +326,7 @@ static WEBP_INLINE void Update2Pixels_SSE2(__m128i* const pi, __m128i* const qi,
const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7);
const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7);
const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi);
const __m128i sign_bit = _mm_set1_epi8(0x80);
const __m128i sign_bit = _mm_set1_epi8((char)0x80);
*pi = _mm_adds_epi8(*pi, delta);
*qi = _mm_subs_epi8(*qi, delta);
FLIP_SIGN_BIT2(*pi, *qi);
@@ -338,9 +338,9 @@ static WEBP_INLINE void NeedsFilter_SSE2(const __m128i* const p1,
const __m128i* const q0,
const __m128i* const q1,
int thresh, __m128i* const mask) {
const __m128i m_thresh = _mm_set1_epi8(thresh);
const __m128i m_thresh = _mm_set1_epi8((char)thresh);
const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
const __m128i kFE = _mm_set1_epi8(0xFE);
const __m128i kFE = _mm_set1_epi8((char)0xFE);
const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero
const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2
@@ -360,7 +360,7 @@ static WEBP_INLINE void DoFilter2_SSE2(__m128i* const p1, __m128i* const p0,
__m128i* const q0, __m128i* const q1,
int thresh) {
__m128i a, mask;
const __m128i sign_bit = _mm_set1_epi8(0x80);
const __m128i sign_bit = _mm_set1_epi8((char)0x80);
// convert p1/q1 to int8_t (for GetBaseDelta_SSE2)
const __m128i p1s = _mm_xor_si128(*p1, sign_bit);
const __m128i q1s = _mm_xor_si128(*q1, sign_bit);
@@ -380,7 +380,7 @@ static WEBP_INLINE void DoFilter4_SSE2(__m128i* const p1, __m128i* const p0,
const __m128i* const mask,
int hev_thresh) {
const __m128i zero = _mm_setzero_si128();
const __m128i sign_bit = _mm_set1_epi8(0x80);
const __m128i sign_bit = _mm_set1_epi8((char)0x80);
const __m128i k64 = _mm_set1_epi8(64);
const __m128i k3 = _mm_set1_epi8(3);
const __m128i k4 = _mm_set1_epi8(4);
@@ -427,7 +427,7 @@ static WEBP_INLINE void DoFilter6_SSE2(__m128i* const p2, __m128i* const p1,
const __m128i* const mask,
int hev_thresh) {
const __m128i zero = _mm_setzero_si128();
const __m128i sign_bit = _mm_set1_epi8(0x80);
const __m128i sign_bit = _mm_set1_epi8((char)0x80);
__m128i a, not_hev;
// compute hev mask
@@ -941,7 +941,7 @@ static void VR4_SSE2(uint8_t* dst) { // Vertical-Right
const __m128i ABCD0 = _mm_srli_si128(XABCD, 1);
const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0);
const __m128i _XABCD = _mm_slli_si128(XABCD, 1);
const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0);
const __m128i IXABCD = _mm_insert_epi16(_XABCD, (short)(I | (X << 8)), 0);
const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0);
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
+1 -1
View File
@@ -777,7 +777,7 @@ static WEBP_INLINE void VR4_SSE2(uint8_t* dst,
const __m128i ABCD0 = _mm_srli_si128(XABCD, 1);
const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0);
const __m128i _XABCD = _mm_slli_si128(XABCD, 1);
const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0);
const __m128i IXABCD = _mm_insert_epi16(_XABCD, (short)(I | (X << 8)), 0);
const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0);
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
+6 -6
View File
@@ -33,9 +33,9 @@ static WEBP_INLINE void PredictLine_C(const uint8_t* src, const uint8_t* pred,
uint8_t* dst, int length, int inverse) {
int i;
if (inverse) {
for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i];
for (i = 0; i < length; ++i) dst[i] = (uint8_t)(src[i] + pred[i]);
} else {
for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i];
for (i = 0; i < length; ++i) dst[i] = (uint8_t)(src[i] - pred[i]);
}
}
@@ -155,7 +155,7 @@ static WEBP_INLINE void DoGradientFilter_C(const uint8_t* in,
const int pred = GradientPredictor_C(preds[w - 1],
preds[w - stride],
preds[w - stride - 1]);
out[w] = in[w] + (inverse ? pred : -pred);
out[w] = (uint8_t)(in[w] + (inverse ? pred : -pred));
}
++row;
preds += stride;
@@ -194,7 +194,7 @@ static void HorizontalUnfilter_C(const uint8_t* prev, const uint8_t* in,
uint8_t pred = (prev == NULL) ? 0 : prev[0];
int i;
for (i = 0; i < width; ++i) {
out[i] = pred + in[i];
out[i] = (uint8_t)(pred + in[i]);
pred = out[i];
}
}
@@ -206,7 +206,7 @@ static void VerticalUnfilter_C(const uint8_t* prev, const uint8_t* in,
HorizontalUnfilter_C(NULL, in, out, width);
} else {
int i;
for (i = 0; i < width; ++i) out[i] = prev[i] + in[i];
for (i = 0; i < width; ++i) out[i] = (uint8_t)(prev[i] + in[i]);
}
}
#endif // !WEBP_NEON_OMIT_C_CODE
@@ -220,7 +220,7 @@ static void GradientUnfilter_C(const uint8_t* prev, const uint8_t* in,
int i;
for (i = 0; i < width; ++i) {
top = prev[i]; // need to read this first, in case prev==out
left = in[i] + GradientPredictor_C(left, top, top_left);
left = (uint8_t)(in[i] + GradientPredictor_C(left, top, top_left));
top_left = top;
out[i] = left;
}
+9 -7
View File
@@ -163,7 +163,8 @@ static void GradientPredictDirect_SSE2(const uint8_t* const row,
_mm_storel_epi64((__m128i*)(out + i), H);
}
for (; i < length; ++i) {
out[i] = row[i] - GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]);
const int delta = GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]);
out[i] = (uint8_t)(row[i] - delta);
}
}
@@ -188,7 +189,7 @@ static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* in,
// Filter line-by-line.
while (row < last_row) {
out[0] = in[0] - in[-stride];
out[0] = (uint8_t)(in[0] - in[-stride]);
GradientPredictDirect_SSE2(in + 1, in + 1 - stride, out + 1, width - 1);
++row;
in += stride;
@@ -223,7 +224,7 @@ static void HorizontalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
uint8_t* out, int width) {
int i;
__m128i last;
out[0] = in[0] + (prev == NULL ? 0 : prev[0]);
out[0] = (uint8_t)(in[0] + (prev == NULL ? 0 : prev[0]));
if (width <= 1) return;
last = _mm_set_epi32(0, 0, 0, out[0]);
for (i = 1; i + 8 <= width; i += 8) {
@@ -238,7 +239,7 @@ static void HorizontalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
_mm_storel_epi64((__m128i*)(out + i), A7);
last = _mm_srli_epi64(A7, 56);
}
for (; i < width; ++i) out[i] = in[i] + out[i - 1];
for (; i < width; ++i) out[i] = (uint8_t)(in[i] + out[i - 1]);
}
static void VerticalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
@@ -259,7 +260,7 @@ static void VerticalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
_mm_storeu_si128((__m128i*)&out[i + 0], C0);
_mm_storeu_si128((__m128i*)&out[i + 16], C1);
}
for (; i < width; ++i) out[i] = in[i] + prev[i];
for (; i < width; ++i) out[i] = (uint8_t)(in[i] + prev[i]);
}
}
@@ -296,7 +297,8 @@ static void GradientPredictInverse_SSE2(const uint8_t* const in,
_mm_storel_epi64((__m128i*)&row[i], out);
}
for (; i < length; ++i) {
row[i] = in[i] + GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]);
const int delta = GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]);
row[i] = (uint8_t)(in[i] + delta);
}
}
}
@@ -306,7 +308,7 @@ static void GradientUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
if (prev == NULL) {
HorizontalUnfilter_SSE2(NULL, in, out, width);
} else {
out[0] = in[0] + prev[0]; // predict from above
out[0] = (uint8_t)(in[0] + prev[0]); // predict from above
GradientPredictInverse_SSE2(in + 1, prev + 1, out + 1, width - 1);
}
}
+2 -2
View File
@@ -270,14 +270,14 @@ void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
int i;
for (i = 0; i < num_pixels; ++i) {
const uint32_t argb = src[i];
const uint32_t green = argb >> 8;
const int8_t green = (int8_t)(argb >> 8);
const uint32_t red = argb >> 16;
int new_red = red & 0xff;
int new_blue = argb & 0xff;
new_red += ColorTransformDelta(m->green_to_red_, green);
new_red &= 0xff;
new_blue += ColorTransformDelta(m->green_to_blue_, green);
new_blue += ColorTransformDelta(m->red_to_blue_, new_red);
new_blue += ColorTransformDelta(m->red_to_blue_, (int8_t)new_red);
new_blue &= 0xff;
dst[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
}
+13 -8
View File
@@ -515,13 +515,17 @@ static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, int8_t color) {
return ((int)color_pred * color) >> 5;
}
static WEBP_INLINE int8_t U32ToS8(uint32_t v) {
return (int8_t)(v & 0xff);
}
void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
int num_pixels) {
int i;
for (i = 0; i < num_pixels; ++i) {
const uint32_t argb = data[i];
const uint32_t green = argb >> 8;
const uint32_t red = argb >> 16;
const int8_t green = U32ToS8(argb >> 8);
const int8_t red = U32ToS8(argb >> 16);
int new_red = red & 0xff;
int new_blue = argb & 0xff;
new_red -= ColorTransformDelta(m->green_to_red_, green);
@@ -535,7 +539,7 @@ void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
uint32_t argb) {
const uint32_t green = argb >> 8;
const int8_t green = U32ToS8(argb >> 8);
int new_red = argb >> 16;
new_red -= ColorTransformDelta(green_to_red, green);
return (new_red & 0xff);
@@ -544,9 +548,9 @@ static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
uint8_t red_to_blue,
uint32_t argb) {
const uint32_t green = argb >> 8;
const uint32_t red = argb >> 16;
uint8_t new_blue = argb;
const int8_t green = U32ToS8(argb >> 8);
const int8_t red = U32ToS8(argb >> 16);
uint8_t new_blue = argb & 0xff;
new_blue -= ColorTransformDelta(green_to_blue, green);
new_blue -= ColorTransformDelta(red_to_blue, red);
return (new_blue & 0xff);
@@ -558,7 +562,7 @@ void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride,
while (tile_height-- > 0) {
int x;
for (x = 0; x < tile_width; ++x) {
++histo[TransformColorRed(green_to_red, argb[x])];
++histo[TransformColorRed((uint8_t)green_to_red, argb[x])];
}
argb += stride;
}
@@ -571,7 +575,8 @@ void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride,
while (tile_height-- > 0) {
int x;
for (x = 0; x < tile_width; ++x) {
++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[x])];
++histo[TransformColorBlue((uint8_t)green_to_blue, (uint8_t)red_to_blue,
argb[x])];
}
argb += stride;
}
+2 -2
View File
@@ -363,7 +363,7 @@ static void BundleColorMap_SSE2(const uint8_t* const row, int width, int xbits,
assert(xbits <= 3);
switch (xbits) {
case 0: {
const __m128i ff = _mm_set1_epi16(0xff00);
const __m128i ff = _mm_set1_epi16((short)0xff00);
const __m128i zero = _mm_setzero_si128();
// Store 0xff000000 | (row[x] << 8).
for (x = 0; x + 16 <= width; x += 16, dst += 16) {
@@ -382,7 +382,7 @@ static void BundleColorMap_SSE2(const uint8_t* const row, int width, int xbits,
break;
}
case 1: {
const __m128i ff = _mm_set1_epi16(0xff00);
const __m128i ff = _mm_set1_epi16((short)0xff00);
const __m128i mul = _mm_set1_epi16(0x110);
for (x = 0; x + 16 <= width; x += 16, dst += 8) {
// 0a0b | (where a/b are 4 bits).
+3 -3
View File
@@ -51,9 +51,9 @@ static void CollectColorBlueTransforms_SSE41(const uint32_t* argb, int stride,
int histo[]) {
const __m128i mults_r = _mm_set1_epi16(CST_5b(red_to_blue));
const __m128i mults_g = _mm_set1_epi16(CST_5b(green_to_blue));
const __m128i mask_g = _mm_set1_epi16(0xff00); // green mask
const __m128i mask_gb = _mm_set1_epi32(0xffff); // green/blue mask
const __m128i mask_b = _mm_set1_epi16(0x00ff); // blue mask
const __m128i mask_g = _mm_set1_epi16((short)0xff00); // green mask
const __m128i mask_gb = _mm_set1_epi32(0xffff); // green/blue mask
const __m128i mask_b = _mm_set1_epi16(0x00ff); // blue mask
const __m128i shuffler_lo = _mm_setr_epi8(-1, 2, -1, 6, -1, 10, -1, 14, -1,
-1, -1, -1, -1, -1, -1, -1);
const __m128i shuffler_hi = _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1,
+15
View File
@@ -10,6 +10,8 @@
#ifndef WEBP_DSP_QUANT_H_
#define WEBP_DSP_QUANT_H_
#include <string.h>
#include "src/dsp/dsp.h"
#include "src/webp/types.h"
@@ -67,4 +69,17 @@ static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
#endif // defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) &&
// !defined(WEBP_HAVE_NEON_RTCD)
static WEBP_INLINE int IsFlatSource16(const uint8_t* src) {
const uint32_t v = src[0] * 0x01010101u;
int i;
for (i = 0; i < 16; ++i) {
if (memcmp(src + 0, &v, 4) || memcmp(src + 4, &v, 4) ||
memcmp(src + 8, &v, 4) || memcmp(src + 12, &v, 4)) {
return 0;
}
src += BPS;
}
return 1;
}
#endif // WEBP_DSP_QUANT_H_
+6 -10
View File
@@ -109,8 +109,7 @@ void WebPRescalerExportRowExpand_C(WebPRescaler* const wrk) {
for (x_out = 0; x_out < x_out_max; ++x_out) {
const uint32_t J = frow[x_out];
const int v = (int)MULT_FIX(J, wrk->fy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
}
} else {
const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
@@ -120,8 +119,7 @@ void WebPRescalerExportRowExpand_C(WebPRescaler* const wrk) {
+ (uint64_t)B * irow[x_out];
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
const int v = (int)MULT_FIX(J, wrk->fy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
}
}
}
@@ -138,17 +136,15 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
assert(!wrk->y_expand);
if (yscale) {
for (x_out = 0; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(frow[x_out], yscale);
const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
irow[x_out] = frac; // new fractional start
}
} else {
for (x_out = 0; x_out < x_out_max; ++x_out) {
const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
irow[x_out] = 0;
}
}
+6 -10
View File
@@ -107,10 +107,9 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
);
}
for (i = 0; i < (x_out_max & 0x3); ++i) {
const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale);
const int v = (int)MULT_FIX_FLOOR(*irow - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(*frow++, yscale);
const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale);
*dst++ = (v > 255) ? 255u : (uint8_t)v;
*irow++ = frac; // new fractional start
}
} else {
@@ -157,8 +156,7 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
}
for (i = 0; i < (x_out_max & 0x3); ++i) {
const int v = (int)MULT_FIX_FLOOR(*irow, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
*dst++ = (v > 255) ? 255u : (uint8_t)v;
*irow++ = 0;
}
}
@@ -219,8 +217,7 @@ static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
for (i = 0; i < (x_out_max & 0x3); ++i) {
const uint32_t J = *frow++;
const int v = (int)MULT_FIX(J, wrk->fy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
*dst++ = (v > 255) ? 255u : (uint8_t)v;
}
} else {
const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
@@ -291,8 +288,7 @@ static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
+ (uint64_t)B * *irow++;
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
const int v = (int)MULT_FIX(J, wrk->fy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
*dst++ = (v > 255) ? 255u : (uint8_t)v;
}
}
}
+6 -10
View File
@@ -166,8 +166,7 @@ static WEBP_INLINE void ExportRowExpand_0(const uint32_t* frow, uint8_t* dst,
for (x_out = 0; x_out < length; ++x_out) {
const uint32_t J = frow[x_out];
const int v = (int)MULT_FIX(J, wrk->fy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
}
}
}
@@ -241,8 +240,7 @@ static WEBP_INLINE void ExportRowExpand_1(const uint32_t* frow, uint32_t* irow,
+ (uint64_t)B * irow[x_out];
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
const int v = (int)MULT_FIX(J, wrk->fy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
}
}
}
@@ -342,10 +340,9 @@ static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
length -= 4;
}
for (x_out = 0; x_out < length; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(frow[x_out], yscale);
const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
irow[x_out] = frac;
}
}
@@ -406,8 +403,7 @@ static WEBP_INLINE void ExportRowShrink_1(uint32_t* irow, uint8_t* dst,
}
for (x_out = 0; x_out < length; ++x_out) {
const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
irow[x_out] = 0;
}
}
+14 -18
View File
@@ -81,14 +81,13 @@ static void RescalerExportRowExpand_NEON(WebPRescaler* const wrk) {
const uint32x4_t B1 = MULT_FIX(A1, fy_scale_half);
const uint16x4_t C0 = vmovn_u32(B0);
const uint16x4_t C1 = vmovn_u32(B1);
const uint8x8_t D = vmovn_u16(vcombine_u16(C0, C1));
const uint8x8_t D = vqmovn_u16(vcombine_u16(C0, C1));
vst1_u8(dst + x_out, D);
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t J = frow[x_out];
const int v = (int)MULT_FIX_C(J, fy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
}
} else {
const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
@@ -102,7 +101,7 @@ static void RescalerExportRowExpand_NEON(WebPRescaler* const wrk) {
const uint32x4_t D1 = MULT_FIX(C1, fy_scale_half);
const uint16x4_t E0 = vmovn_u32(D0);
const uint16x4_t E1 = vmovn_u32(D1);
const uint8x8_t F = vmovn_u16(vcombine_u16(E0, E1));
const uint8x8_t F = vqmovn_u16(vcombine_u16(E0, E1));
vst1_u8(dst + x_out, F);
}
for (; x_out < x_out_max; ++x_out) {
@@ -110,8 +109,7 @@ static void RescalerExportRowExpand_NEON(WebPRescaler* const wrk) {
+ (uint64_t)B * irow[x_out];
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
const int v = (int)MULT_FIX_C(J, fy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
}
}
}
@@ -135,23 +133,22 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
for (x_out = 0; x_out < max_span; x_out += 8) {
LOAD_32x8(frow + x_out, in0, in1);
LOAD_32x8(irow + x_out, in2, in3);
const uint32x4_t A0 = MULT_FIX(in0, yscale_half);
const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
const uint32x4_t A0 = MULT_FIX_FLOOR(in0, yscale_half);
const uint32x4_t A1 = MULT_FIX_FLOOR(in1, yscale_half);
const uint32x4_t B0 = vqsubq_u32(in2, A0);
const uint32x4_t B1 = vqsubq_u32(in3, A1);
const uint32x4_t C0 = MULT_FIX_FLOOR(B0, fxy_scale_half);
const uint32x4_t C1 = MULT_FIX_FLOOR(B1, fxy_scale_half);
const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half);
const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half);
const uint16x4_t D0 = vmovn_u32(C0);
const uint16x4_t D1 = vmovn_u32(C1);
const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
const uint8x8_t E = vqmovn_u16(vcombine_u16(D0, D1));
vst1_u8(dst + x_out, E);
STORE_32x8(A0, A1, irow + x_out);
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
const int v = (int)MULT_FIX_FLOOR_C(irow[x_out] - frac, fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
const uint32_t frac = (uint32_t)MULT_FIX_FLOOR_C(frow[x_out], yscale);
const int v = (int)MULT_FIX_C(irow[x_out] - frac, fxy_scale);
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
irow[x_out] = frac; // new fractional start
}
} else {
@@ -161,14 +158,13 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
const uint32x4_t A1 = MULT_FIX(in1, fxy_scale_half);
const uint16x4_t B0 = vmovn_u32(A0);
const uint16x4_t B1 = vmovn_u32(A1);
const uint8x8_t C = vmovn_u16(vcombine_u16(B0, B1));
const uint8x8_t C = vqmovn_u16(vcombine_u16(B0, B1));
vst1_u8(dst + x_out, C);
STORE_32x8(zero, zero, irow + x_out);
}
for (; x_out < x_out_max; ++x_out) {
const int v = (int)MULT_FIX_C(irow[x_out], fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
irow[x_out] = 0;
}
}
+11 -49
View File
@@ -225,35 +225,6 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0,
_mm_storel_epi64((__m128i*)dst, G);
}
static WEBP_INLINE void ProcessRow_Floor_SSE2(const __m128i* const A0,
const __m128i* const A1,
const __m128i* const A2,
const __m128i* const A3,
const __m128i* const mult,
uint8_t* const dst) {
const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
const __m128i B0 = _mm_mul_epu32(*A0, *mult);
const __m128i B1 = _mm_mul_epu32(*A1, *mult);
const __m128i B2 = _mm_mul_epu32(*A2, *mult);
const __m128i B3 = _mm_mul_epu32(*A3, *mult);
const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX);
const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
#if (WEBP_RESCALER_RFIX < 32)
const __m128i D2 =
_mm_and_si128(_mm_slli_epi64(B2, 32 - WEBP_RESCALER_RFIX), mask);
const __m128i D3 =
_mm_and_si128(_mm_slli_epi64(B3, 32 - WEBP_RESCALER_RFIX), mask);
#else
const __m128i D2 = _mm_and_si128(B2, mask);
const __m128i D3 = _mm_and_si128(B3, mask);
#endif
const __m128i E0 = _mm_or_si128(D0, D2);
const __m128i E1 = _mm_or_si128(D1, D3);
const __m128i F = _mm_packs_epi32(E0, E1);
const __m128i G = _mm_packus_epi16(F, F);
_mm_storel_epi64((__m128i*)dst, G);
}
static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
int x_out;
uint8_t* const dst = wrk->dst;
@@ -274,8 +245,7 @@ static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
for (; x_out < x_out_max; ++x_out) {
const uint32_t J = frow[x_out];
const int v = (int)MULT_FIX(J, wrk->fy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
}
} else {
const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
@@ -308,8 +278,7 @@ static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
+ (uint64_t)B * irow[x_out];
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
const int v = (int)MULT_FIX(J, wrk->fy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
}
}
}
@@ -328,20 +297,15 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
const int scale_xy = wrk->fxy_scale;
const __m128i mult_xy = _mm_set_epi32(0, scale_xy, 0, scale_xy);
const __m128i mult_y = _mm_set_epi32(0, yscale, 0, yscale);
const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
__m128i A0, A1, A2, A3, B0, B1, B2, B3;
LoadDispatchAndMult_SSE2(irow + x_out, NULL, &A0, &A1, &A2, &A3);
LoadDispatchAndMult_SSE2(frow + x_out, &mult_y, &B0, &B1, &B2, &B3);
{
const __m128i C0 = _mm_add_epi64(B0, rounder);
const __m128i C1 = _mm_add_epi64(B1, rounder);
const __m128i C2 = _mm_add_epi64(B2, rounder);
const __m128i C3 = _mm_add_epi64(B3, rounder);
const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); // = frac
const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX);
const __m128i D2 = _mm_srli_epi64(C2, WEBP_RESCALER_RFIX);
const __m128i D3 = _mm_srli_epi64(C3, WEBP_RESCALER_RFIX);
const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX); // = frac
const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
const __m128i D2 = _mm_srli_epi64(B2, WEBP_RESCALER_RFIX);
const __m128i D3 = _mm_srli_epi64(B3, WEBP_RESCALER_RFIX);
const __m128i E0 = _mm_sub_epi64(A0, D0); // irow[x] - frac
const __m128i E1 = _mm_sub_epi64(A1, D1);
const __m128i E2 = _mm_sub_epi64(A2, D2);
@@ -352,14 +316,13 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
const __m128i G1 = _mm_or_si128(D1, F3);
_mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
_mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
ProcessRow_Floor_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
}
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
const uint32_t frac = (int)MULT_FIX_FLOOR(frow[x_out], yscale);
const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
irow[x_out] = frac; // new fractional start
}
} else {
@@ -375,8 +338,7 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
}
for (; x_out < x_out_max; ++x_out) {
const int v = (int)MULT_FIX(irow[x_out], scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
irow[x_out] = 0;
}
}
+6 -5
View File
@@ -191,13 +191,14 @@ void VP8LHashChainClear(VP8LHashChain* const p) {
// -----------------------------------------------------------------------------
#define HASH_MULTIPLIER_HI (0xc6a4a793ULL)
#define HASH_MULTIPLIER_LO (0x5bd1e996ULL)
static const uint32_t kHashMultiplierHi = 0xc6a4a793u;
static const uint32_t kHashMultiplierLo = 0x5bd1e996u;
static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) {
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
uint32_t GetPixPairHash64(const uint32_t* const argb) {
uint32_t key;
key = (argb[1] * HASH_MULTIPLIER_HI) & 0xffffffffu;
key += (argb[0] * HASH_MULTIPLIER_LO) & 0xffffffffu;
key = argb[1] * kHashMultiplierHi;
key += argb[0] * kHashMultiplierLo;
key = key >> (32 - HASH_BITS);
return key;
}
+2 -3
View File
@@ -929,9 +929,8 @@ static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
}
mappings = (int*) WebPSafeMalloc(*num_used, sizeof(*mappings));
if (mappings == NULL || !HistoQueueInit(&histo_queue, kHistoQueueSize)) {
goto End;
}
if (mappings == NULL) return 0;
if (!HistoQueueInit(&histo_queue, kHistoQueueSize)) goto End;
// Fill the initial mapping.
for (j = 0, iter = 0; iter < image_histo->size; ++iter) {
if (histograms[iter] == NULL) continue;
+7 -7
View File
@@ -202,7 +202,7 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict,
}
if ((value >> 24) == 0 || (value >> 24) == 0xff) {
// Preserve transparency of fully transparent or fully opaque pixels.
a = NearLosslessDiff(value >> 24, predict >> 24);
a = NearLosslessDiff((value >> 24) & 0xff, (predict >> 24) & 0xff);
} else {
a = NearLosslessComponent(value >> 24, predict >> 24, 0xff, quantization);
}
@@ -215,12 +215,12 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict,
// The amount by which green has been adjusted during quantization. It is
// subtracted from red and blue for compensation, to avoid accumulating two
// quantization errors in them.
green_diff = NearLosslessDiff(new_green, value >> 8);
green_diff = NearLosslessDiff(new_green, (value >> 8) & 0xff);
}
r = NearLosslessComponent(NearLosslessDiff(value >> 16, green_diff),
r = NearLosslessComponent(NearLosslessDiff((value >> 16) & 0xff, green_diff),
(predict >> 16) & 0xff, 0xff - new_green,
quantization);
b = NearLosslessComponent(NearLosslessDiff(value, green_diff),
b = NearLosslessComponent(NearLosslessDiff(value & 0xff, green_diff),
predict & 0xff, 0xff - new_green, quantization);
return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
@@ -587,7 +587,7 @@ static void GetBestGreenToRed(
}
}
}
best_tx->green_to_red_ = green_to_red_best;
best_tx->green_to_red_ = (green_to_red_best & 0xff);
}
static float GetPredictionCostCrossColorBlue(
@@ -666,8 +666,8 @@ static void GetBestGreenRedToBlue(
break; // out of iter-loop.
}
}
best_tx->green_to_blue_ = green_to_blue_best;
best_tx->red_to_blue_ = red_to_blue_best;
best_tx->green_to_blue_ = green_to_blue_best & 0xff;
best_tx->red_to_blue_ = red_to_blue_best & 0xff;
}
#undef kGreenRedToBlueMaxIters
#undef kGreenRedToBlueNumAxis
+20 -6
View File
@@ -33,7 +33,7 @@
// number of non-zero coeffs below which we consider the block very flat
// (and apply a penalty to complex predictions)
#define FLATNESS_LIMIT_I16 10 // I16 mode
#define FLATNESS_LIMIT_I16 0 // I16 mode (special case)
#define FLATNESS_LIMIT_I4 3 // I4 mode
#define FLATNESS_LIMIT_UV 2 // UV mode
#define FLATNESS_PENALTY 140 // roughly ~1bit per block
@@ -988,6 +988,7 @@ static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
VP8ModeScore* rd_cur = &rd_tmp;
VP8ModeScore* rd_best = rd;
int mode;
int is_flat = IsFlatSource16(it->yuv_in_ + Y_OFF_ENC);
rd->mode_i16 = -1;
for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
@@ -1003,10 +1004,14 @@ static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) : 0;
rd_cur->H = VP8FixedCostsI16[mode];
rd_cur->R = VP8GetCostLuma16(it, rd_cur);
if (mode > 0 &&
IsFlat(rd_cur->y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16)) {
// penalty to avoid flat area to be mispredicted by complex mode
rd_cur->R += FLATNESS_PENALTY * kNumBlocks;
if (is_flat) {
// refine the first impression (which was in pixel space)
is_flat = IsFlat(rd_cur->y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16);
if (is_flat) {
// Block is very flat. We put emphasis on the distortion being very low!
rd_cur->D *= 2;
rd_cur->SD *= 2;
}
}
// Since we always examine Intra16 first, we can overwrite *rd directly.
@@ -1087,7 +1092,8 @@ static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
: 0;
rd_tmp.H = mode_costs[mode];
// Add flatness penalty
// Add flatness penalty, to avoid flat area to be mispredicted
// by a complex mode.
if (mode > 0 && IsFlat(tmp_levels, kNumBlocks, FLATNESS_LIMIT_I4)) {
rd_tmp.R = FLATNESS_PENALTY * kNumBlocks;
} else {
@@ -1242,11 +1248,19 @@ static void RefineUsingDistortion(VP8EncIterator* const it,
if (mode > 0 && VP8FixedCostsI16[mode] > bit_limit) {
continue;
}
if (score < best_score) {
best_mode = mode;
best_score = score;
}
}
if (it->x_ == 0 || it->y_ == 0) {
// avoid starting a checkerboard resonance from the border. See bug #432.
if (IsFlatSource16(src)) {
best_mode = (it->x_ == 0) ? 0 : 2;
try_both_modes = 0; // stick to i16
}
}
VP8SetIntra16Mode(it, best_mode);
// we'll reconstruct later, if i16 mode actually gets selected
}
+1 -1
View File
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 1
#define ENC_MIN_VERSION 0
#define ENC_REV_VERSION 2
#define ENC_REV_VERSION 3
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
+1 -1
View File
@@ -29,7 +29,7 @@ extern "C" {
#define MUX_MAJ_VERSION 1
#define MUX_MIN_VERSION 0
#define MUX_REV_VERSION 2
#define MUX_REV_VERSION 3
// Chunk object.
typedef struct WebPChunk WebPChunk;
+8 -3
View File
@@ -104,7 +104,8 @@ void VP8LoadNewBytes(VP8BitReader* const br) {
}
// Read a bit with proba 'prob'. Speed-critical function!
static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
static WEBP_INLINE int VP8GetBit(VP8BitReader* const br,
int prob, const char label[]) {
// Don't move this declaration! It makes a big speed difference to store
// 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't
// alter br->range_ value.
@@ -129,13 +130,14 @@ static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
br->bits_ -= shift;
}
br->range_ = range - 1;
BT_TRACK(br);
return bit;
}
}
// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here)
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
int VP8GetSigned(VP8BitReader* const br, int v) {
int VP8GetSigned(VP8BitReader* const br, int v, const char label[]) {
if (br->bits_ < 0) {
VP8LoadNewBytes(br);
}
@@ -148,11 +150,13 @@ int VP8GetSigned(VP8BitReader* const br, int v) {
br->range_ += mask;
br->range_ |= 1;
br->value_ -= (bit_t)((split + 1) & mask) << pos;
BT_TRACK(br);
return (v ^ mask) - mask;
}
}
static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br,
int prob, const char label[]) {
// Don't move this declaration! It makes a big speed difference to store
// 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't
// alter br->range_ value.
@@ -179,6 +183,7 @@ static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
br->bits_ -= shift;
}
br->range_ = range;
BT_TRACK(br);
return bit;
}
}
+81 -5
View File
@@ -102,17 +102,18 @@ void VP8LoadFinalBytes(VP8BitReader* const br) {
//------------------------------------------------------------------------------
// Higher-level calls
uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
uint32_t VP8GetValue(VP8BitReader* const br, int bits, const char label[]) {
uint32_t v = 0;
while (bits-- > 0) {
v |= VP8GetBit(br, 0x80) << bits;
v |= VP8GetBit(br, 0x80, label) << bits;
}
return v;
}
int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
const int value = VP8GetValue(br, bits);
return VP8Get(br) ? -value : value;
int32_t VP8GetSignedValue(VP8BitReader* const br, int bits,
const char label[]) {
const int value = VP8GetValue(br, bits, label);
return VP8Get(br, label) ? -value : value;
}
//------------------------------------------------------------------------------
@@ -220,3 +221,78 @@ uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
}
//------------------------------------------------------------------------------
// Bit-tracing tool
#if (BITTRACE > 0)
#include <stdlib.h> // for atexit()
#include <stdio.h>
#include <string.h>
#define MAX_NUM_LABELS 32
static struct {
const char* label;
int size;
int count;
} kLabels[MAX_NUM_LABELS];
static int last_label = 0;
static int last_pos = 0;
static const uint8_t* buf_start = NULL;
static int init_done = 0;
static void PrintBitTraces(void) {
int i;
int scale = 1;
int total = 0;
const char* units = "bits";
#if (BITTRACE == 2)
scale = 8;
units = "bytes";
#endif
for (i = 0; i < last_label; ++i) total += kLabels[i].size;
if (total < 1) total = 1; // avoid rounding errors
printf("=== Bit traces ===\n");
for (i = 0; i < last_label; ++i) {
const int skip = 16 - (int)strlen(kLabels[i].label);
const int value = (kLabels[i].size + scale - 1) / scale;
assert(skip > 0);
printf("%s \%*s: %6d %s \t[%5.2f%%] [count: %7d]\n",
kLabels[i].label, skip, "", value, units,
100.f * kLabels[i].size / total,
kLabels[i].count);
}
total = (total + scale - 1) / scale;
printf("Total: %d %s\n", total, units);
}
void BitTrace(const struct VP8BitReader* const br, const char label[]) {
int i, pos;
if (!init_done) {
memset(kLabels, 0, sizeof(kLabels));
atexit(PrintBitTraces);
buf_start = br->buf_;
init_done = 1;
}
pos = (int)(br->buf_ - buf_start) * 8 - br->bits_;
// if there's a too large jump, we've changed partition -> reset counter
if (abs(pos - last_pos) > 32) {
buf_start = br->buf_;
pos = 0;
last_pos = 0;
}
if (br->range_ >= 0x7f) pos += kVP8Log2Range[br->range_ - 0x7f];
for (i = 0; i < last_label; ++i) {
if (!strcmp(label, kLabels[i].label)) break;
}
if (i == MAX_NUM_LABELS) abort(); // overflow!
kLabels[i].label = label;
kLabels[i].size += pos - last_pos;
kLabels[i].count += 1;
if (i == last_label) ++last_label;
last_pos = pos;
}
#endif // BITTRACE > 0
//------------------------------------------------------------------------------
+26 -7
View File
@@ -21,6 +21,27 @@
#endif
#include "src/webp/types.h"
// Warning! This macro triggers quite some MACRO wizardry around func signature!
#if !defined(BITTRACE)
#define BITTRACE 0 // 0 = off, 1 = print bits, 2 = print bytes
#endif
#if (BITTRACE > 0)
struct VP8BitReader;
extern void BitTrace(const struct VP8BitReader* const br, const char label[]);
#define BT_TRACK(br) BitTrace(br, label)
#define VP8Get(BR, L) VP8GetValue(BR, 1, L)
#else
#define BT_TRACK(br)
// We'll REMOVE the 'const char label[]' from all signatures and calls (!!):
#define VP8GetValue(BR, N, L) VP8GetValue(BR, N)
#define VP8Get(BR, L) VP8GetValue(BR, 1, L)
#define VP8GetSignedValue(BR, N, L) VP8GetSignedValue(BR, N)
#define VP8GetBit(BR, P, L) VP8GetBit(BR, P)
#define VP8GetBitAlt(BR, P, L) VP8GetBitAlt(BR, P)
#define VP8GetSigned(BR, V, L) VP8GetSigned(BR, V)
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -92,17 +113,15 @@ void VP8BitReaderSetBuffer(VP8BitReader* const br,
void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset);
// return the next value made of 'num_bits' bits
uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) {
return VP8GetValue(br, 1);
}
uint32_t VP8GetValue(VP8BitReader* const br, int num_bits, const char label[]);
// return the next value with sign-extension.
int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits,
const char label[]);
// bit_reader_inl.h will implement the following methods:
// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob)
// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v)
// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob, ...)
// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v, ...)
// and should be included by the .c files that actually need them.
// This is to avoid recompiling the whole library whenever this file is touched,
// and also allowing platform-specific ad-hoc hacks.
+1 -1
View File
@@ -70,7 +70,7 @@ static void Flush(VP8BitWriter* const bw) {
const int value = (bits & 0x100) ? 0x00 : 0xff;
for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value;
}
bw->buf_[pos++] = bits;
bw->buf_[pos++] = bits & 0xff;
bw->pos_ = pos;
} else {
bw->run_++; // delay writing of bytes 0xff, pending eventual carry.
+5 -3
View File
@@ -17,6 +17,7 @@
#include <assert.h>
#include "src/dsp/dsp.h"
#include "src/webp/types.h"
#ifdef __cplusplus
@@ -30,10 +31,11 @@ typedef struct {
int hash_bits_;
} VP8LColorCache;
static const uint64_t kHashMul = 0x1e35a7bdull;
static const uint32_t kHashMul = 0x1e35a7bdu;
static WEBP_INLINE int VP8LHashPix(uint32_t argb, int shift) {
return (int)(((argb * kHashMul) & 0xffffffffu) >> shift);
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
int VP8LHashPix(uint32_t argb, int shift) {
return (int)((argb * kHashMul) >> shift);
}
static WEBP_INLINE uint32_t VP8LColorCacheLookup(
+19 -7
View File
@@ -91,7 +91,8 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
assert(code_lengths_size != 0);
assert(code_lengths != NULL);
assert(root_table != NULL);
assert((root_table != NULL && sorted != NULL) ||
(root_table == NULL && sorted == NULL));
assert(root_bits > 0);
// Build histogram of code lengths.
@@ -120,16 +121,22 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
for (symbol = 0; symbol < code_lengths_size; ++symbol) {
const int symbol_code_length = code_lengths[symbol];
if (code_lengths[symbol] > 0) {
sorted[offset[symbol_code_length]++] = symbol;
if (sorted != NULL) {
sorted[offset[symbol_code_length]++] = symbol;
} else {
offset[symbol_code_length]++;
}
}
}
// Special case code with only one value.
if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) {
HuffmanCode code;
code.bits = 0;
code.value = (uint16_t)sorted[0];
ReplicateValue(table, 1, total_size, code);
if (sorted != NULL) {
HuffmanCode code;
code.bits = 0;
code.value = (uint16_t)sorted[0];
ReplicateValue(table, 1, total_size, code);
}
return total_size;
}
@@ -151,6 +158,7 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
if (num_open < 0) {
return 0;
}
if (root_table == NULL) continue;
for (; count[len] > 0; --count[len]) {
HuffmanCode code;
code.bits = (uint8_t)len;
@@ -169,6 +177,7 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
if (num_open < 0) {
return 0;
}
if (root_table == NULL) continue;
for (; count[len] > 0; --count[len]) {
HuffmanCode code;
if ((key & mask) != low) {
@@ -206,7 +215,10 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
const int code_lengths[], int code_lengths_size) {
int total_size;
assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
if (root_table == NULL) {
total_size = BuildHuffmanTable(NULL, root_bits,
code_lengths, code_lengths_size, NULL);
} else if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
// use local stack-allocated array.
uint16_t sorted[SORTED_SIZE_CUTOFF];
total_size = BuildHuffmanTable(root_table, root_bits,
+2
View File
@@ -78,6 +78,8 @@ void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups);
// the huffman table.
// Returns built table size or 0 in case of error (invalid tree or
// memory error).
// If root_table is NULL, it returns 0 if a lookup cannot be built, something
// > 0 otherwise (but not the table size).
int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
const int code_lengths[], int code_lengths_size);
+4 -4
View File
@@ -84,14 +84,14 @@ int WebPRescalerGetScaledDimensions(int src_width, int src_height,
int height = *scaled_height;
// if width is unspecified, scale original proportionally to height ratio.
if (width == 0) {
if (width == 0 && src_height > 0) {
width =
(int)(((uint64_t)src_width * height + src_height / 2) / src_height);
(int)(((uint64_t)src_width * height + src_height - 1) / src_height);
}
// if height is unspecified, scale original proportionally to width ratio.
if (height == 0) {
if (height == 0 && src_width > 0) {
height =
(int)(((uint64_t)src_height * width + src_width / 2) / src_width);
(int)(((uint64_t)src_height * width + src_width - 1) / src_width);
}
// Check if the overall dimensions still make sense.
if (width <= 0 || height <= 0) {
+11 -1
View File
@@ -217,8 +217,12 @@ static THREADFN ThreadLoop(void* ptr) {
done = 1;
}
// signal to the main thread that we're done (for Sync())
pthread_cond_signal(&impl->condition_);
// Note the associated mutex does not need to be held when signaling the
// condition. Unlocking the mutex first may improve performance in some
// implementations, avoiding the case where the waiting thread can't
// reacquire the mutex when woken.
pthread_mutex_unlock(&impl->mutex_);
pthread_cond_signal(&impl->condition_);
}
return THREAD_RETURN(NULL); // Thread is finished
}
@@ -240,7 +244,13 @@ static void ChangeState(WebPWorker* const worker, WebPWorkerStatus new_status) {
// assign new status and release the working thread if needed
if (new_status != OK) {
worker->status_ = new_status;
// Note the associated mutex does not need to be held when signaling the
// condition. Unlocking the mutex first may improve performance in some
// implementations, avoiding the case where the waiting thread can't
// reacquire the mutex when woken.
pthread_mutex_unlock(&impl->mutex_);
pthread_cond_signal(&impl->condition_);
return;
}
}
pthread_mutex_unlock(&impl->mutex_);
+3 -3
View File
@@ -92,14 +92,14 @@ static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) {
// Store 16, 24 or 32 bits in little-endian order.
static WEBP_INLINE void PutLE16(uint8_t* const data, int val) {
assert(val < (1 << 16));
data[0] = (val >> 0);
data[1] = (val >> 8);
data[0] = (val >> 0) & 0xff;
data[1] = (val >> 8) & 0xff;
}
static WEBP_INLINE void PutLE24(uint8_t* const data, int val) {
assert(val < (1 << 24));
PutLE16(data, val & 0xffff);
data[2] = (val >> 16);
data[2] = (val >> 16) & 0xff;
}
static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
+4
View File
@@ -62,6 +62,10 @@ WEBP_EXTERN size_t WebPEncodeBGRA(const uint8_t* bgra,
// These functions are the equivalent of the above, but compressing in a
// lossless manner. Files are usually larger than lossy format, but will
// not suffer any compression loss.
// Note these functions, like the lossy versions, use the library's default
// settings. For lossless this means 'exact' is disabled. RGB values in
// transparent areas will be modified to improve compression. To avoid this,
// use WebPEncode() and set WebPConfig::exact to 1.
WEBP_EXTERN size_t WebPEncodeLosslessRGB(const uint8_t* rgb,
int width, int height, int stride,
uint8_t** output);
+1 -1
View File
@@ -45,7 +45,7 @@
// GCC and Visual Studio SSE2 compiler flags
#if defined __SSE2__ || (_MSC_VER >= 1300 && !_M_CEE_PURE)
#if defined __SSE2__ || (defined(_M_X64) || _M_IX86_FP == 2)
#define IMF_HAVE_SSE2 1
#endif
+1 -1
View File
@@ -5,7 +5,7 @@ target_include_directories(openvx_hal PUBLIC
${CMAKE_SOURCE_DIR}/modules/core/include
${CMAKE_SOURCE_DIR}/modules/imgproc/include
${OPENVX_INCLUDE_DIR})
target_link_libraries(openvx_hal LINK_PUBLIC ${OPENVX_LIBRARIES})
target_link_libraries(openvx_hal PUBLIC ${OPENVX_LIBRARIES})
set_target_properties(openvx_hal PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH})
if(NOT BUILD_SHARED_LIBS)
ocv_install_target(openvx_hal EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)
+1
View File
@@ -22,6 +22,7 @@ else()
-Wenum-compare-switch
-Wsuggest-override -Winconsistent-missing-override
-Wimplicit-fallthrough
-Warray-bounds # GCC 9+
)
endif()
if(CV_ICC)
+6 -3
View File
@@ -5,10 +5,11 @@ if (WIN32 AND NOT ARM)
message(FATAL_ERROR "BUILD_TBB option supports Windows on ARM only!\nUse regular official TBB build instead of the BUILD_TBB option!")
endif()
ocv_update(OPENCV_TBB_RELEASE "2019_U8")
ocv_update(OPENCV_TBB_RELEASE_MD5 "7c371d0f62726154d2c568a85697a0ad")
ocv_update(OPENCV_TBB_RELEASE "v2020.0")
ocv_update(OPENCV_TBB_RELEASE_MD5 "5858dd01ec007c139d5d178b21e06dae")
ocv_update(OPENCV_TBB_FILENAME "${OPENCV_TBB_RELEASE}.tar.gz")
ocv_update(OPENCV_TBB_SUBDIR "tbb-${OPENCV_TBB_RELEASE}")
string(REGEX REPLACE "^v" "" OPENCV_TBB_RELEASE_ "${OPENCV_TBB_RELEASE}")
ocv_update(OPENCV_TBB_SUBDIR "tbb-${OPENCV_TBB_RELEASE_}")
set(tbb_src_dir "${OpenCV_BINARY_DIR}/3rdparty/tbb")
ocv_download(FILENAME ${OPENCV_TBB_FILENAME}
@@ -34,10 +35,12 @@ ocv_include_directories("${tbb_src_dir}/include"
file(GLOB lib_srcs "${tbb_src_dir}/src/tbb/*.cpp")
file(GLOB lib_hdrs "${tbb_src_dir}/src/tbb/*.h")
list(APPEND lib_srcs "${tbb_src_dir}/src/rml/client/rml_tbb.cpp")
ocv_list_filterout(lib_srcs "${tbb_src_dir}/src/tbb/tbbbind.cpp") # hwloc.h requirement
if (WIN32)
add_definitions(/D__TBB_DYNAMIC_LOAD_ENABLED=0
/D__TBB_BUILD=1
/DTBB_SUPPRESS_DEPRECATED_MESSAGES=1
/DTBB_NO_LEGACY=1
/D_UNICODE
/DUNICODE
+30 -2
View File
@@ -276,6 +276,9 @@ OCV_OPTION(WITH_HALIDE "Include Halide support" OFF
OCV_OPTION(WITH_INF_ENGINE "Include Intel Inference Engine support" OFF
VISIBLE_IF TRUE
VERIFY INF_ENGINE_TARGET)
OCV_OPTION(WITH_NGRAPH "Include nGraph support" WITH_INF_ENGINE
VISIBLE_IF TRUE
VERIFY TARGET ngraph::ngraph)
OCV_OPTION(WITH_JASPER "Include JPEG2K support" ON
VISIBLE_IF NOT IOS
VERIFY HAVE_JASPER)
@@ -1489,12 +1492,37 @@ if(WITH_INF_ENGINE OR INF_ENGINE_TARGET)
)
get_target_property(_inc ${ie_target} INTERFACE_INCLUDE_DIRECTORIES)
status(" Inference Engine:" "${__msg}")
status(" libs:" "${_lib}")
status(" includes:" "${_inc}")
status(" * libs:" "${_lib}")
status(" * includes:" "${_inc}")
else()
status(" Inference Engine:" "NO")
endif()
endif()
if(WITH_NGRAPH OR HAVE_NGRAPH)
if(HAVE_NGRAPH)
set(__target ngraph::ngraph)
set(__msg "YES (${ngraph_VERSION})")
get_target_property(_lib ${__target} IMPORTED_LOCATION)
get_target_property(_lib_imp_rel ${__target} IMPORTED_IMPLIB_RELEASE)
get_target_property(_lib_imp_dbg ${__target} IMPORTED_IMPLIB_DEBUG)
get_target_property(_lib_rel ${__target} IMPORTED_LOCATION_RELEASE)
get_target_property(_lib_dbg ${__target} IMPORTED_LOCATION_DEBUG)
ocv_build_features_string(_lib
IF _lib THEN "${_lib}"
IF _lib_imp_rel AND _lib_imp_dbg THEN "${_lib_imp_rel} / ${_lib_imp_dbg}"
IF _lib_rel AND _lib_dbg THEN "${_lib_rel} / ${_lib_dbg}"
IF _lib_rel THEN "${_lib_rel}"
IF _lib_dbg THEN "${_lib_dbg}"
ELSE "unknown"
)
get_target_property(_inc ${__target} INTERFACE_INCLUDE_DIRECTORIES)
status(" nGraph:" "${__msg}")
status(" * libs:" "${_lib}")
status(" * includes:" "${_inc}")
else()
status(" nGraph:" "NO")
endif()
endif()
if(WITH_EIGEN OR HAVE_EIGEN)
status(" Eigen:" HAVE_EIGEN THEN "YES (ver ${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION})" ELSE NO)
+1
View File
@@ -13,6 +13,7 @@ Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved.
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved.
Copyright (C) 2015-2016, Itseez Inc., all rights reserved.
Copyright (C) 2019, Xperience AI, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
+6 -3
View File
@@ -288,7 +288,7 @@ if(X86 OR X86_64)
ocv_update(CPU_AVX2_FLAGS_ON "/arch:AVX2")
ocv_update(CPU_AVX_FLAGS_ON "/arch:AVX")
ocv_update(CPU_FP16_FLAGS_ON "/arch:AVX")
if(NOT MSVC64)
if(NOT X86_64)
# 64-bit MSVC compiler uses SSE/SSE2 by default
ocv_update(CPU_SSE_FLAGS_ON "/arch:SSE")
ocv_update(CPU_SSE_SUPPORTED ON)
@@ -346,7 +346,7 @@ elseif(MIPS)
ocv_update(CPU_MSA_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_msa.cpp")
ocv_update(CPU_KNOWN_OPTIMIZATIONS "MSA")
ocv_update(CPU_MSA_FLAGS_ON "-mmsa")
set(CPU_BASELINE "MSA" CACHE STRING "${HELP_CPU_BASELINE}")
set(CPU_BASELINE "DETECT" CACHE STRING "${HELP_CPU_BASELINE}")
elseif(PPC64LE)
ocv_update(CPU_KNOWN_OPTIMIZATIONS "VSX;VSX3")
ocv_update(CPU_VSX_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_vsx.cpp")
@@ -714,7 +714,10 @@ macro(ocv_compiler_optimization_process_sources SOURCES_VAR_NAME LIBS_VAR_NAME T
foreach(OPT ${CPU_DISPATCH_FINAL})
if(__result_${OPT})
#message("${OPT}: ${__result_${OPT}}")
if(CMAKE_GENERATOR MATCHES "^Visual")
if(CMAKE_GENERATOR MATCHES "^Visual"
OR OPENCV_CMAKE_CPU_OPTIMIZATIONS_FORCE_TARGETS
)
# MSVS generator is not able to properly order compilation flags:
# extra flags are added before common flags, so switching between optimizations doesn't work correctly
# Also CMAKE_CXX_FLAGS doesn't work (it is directory-based, so add_subdirectory is required)
add_library(${TARGET_BASE_NAME}_${OPT} OBJECT ${__result_${OPT}})
+13
View File
@@ -383,6 +383,19 @@ if(MSVC)
add_definitions(-D_VARIADIC_MAX=10)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
get_directory_property(__DIRECTORY_COMPILE_DEFINITIONS COMPILE_DEFINITIONS)
if((NOT " ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} ${OPENCV_EXTRA_CXX_FLAGS} ${OPENCV_EXTRA_FLAGS_RELEASE} ${__DIRECTORY_COMPILE_DEFINITIONS}" MATCHES "_WIN32_WINNT"
AND NOT OPENCV_CMAKE_SKIP_MACRO_WIN32_WINNT)
OR OPENCV_CMAKE_FORCE_MACRO_WIN32_WINNT
)
# https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt
# Target Windows 7 API
set(OPENCV_CMAKE_MACRO_WIN32_WINNT "0x0601" CACHE STRING "Value of _WIN32_WINNT macro")
add_definitions(-D_WIN32_WINNT=${OPENCV_CMAKE_MACRO_WIN32_WINNT})
endif()
endif()
# Enable compiler options for OpenCV modules/apps/samples only (ignore 3rdparty)
macro(ocv_add_modules_compiler_options)
if(MSVC AND NOT OPENCV_SKIP_MSVC_W4_OPTION)
+1 -1
View File
@@ -12,7 +12,7 @@ endif()
if(((NOT CMAKE_VERSION VERSION_LESS "3.9.0") # requires https://gitlab.kitware.com/cmake/cmake/merge_requests/663
OR OPENCV_CUDA_FORCE_EXTERNAL_CMAKE_MODULE)
AND NOT OPENCV_CUDA_FORCE_BUILTIN_CMAKE_MODULE)
ocv_update(CUDA_LINK_LIBRARIES_KEYWORD "LINK_PRIVATE")
ocv_update(CUDA_LINK_LIBRARIES_KEYWORD "PRIVATE")
find_host_package(CUDA "${MIN_VER_CUDA}" QUIET)
else()
# Use OpenCV's patched "FindCUDA" module
+48 -33
View File
@@ -3,15 +3,14 @@
# - CV_CLANG - Clang-compatible compiler (CMAKE_CXX_COMPILER_ID MATCHES "Clang" - Clang or AppleClang, see CMP0025)
# - CV_ICC - Intel compiler
# - MSVC - Microsoft Visual Compiler (CMake variable)
# - MSVC64 - additional flag, 64-bit
# - MINGW / CYGWIN / CMAKE_COMPILER_IS_MINGW / CMAKE_COMPILER_IS_CYGWIN (CMake original variables)
# - MINGW64 - 64-bit
#
# CPU Platforms:
# - X86 / X86_64
# - ARM - ARM CPU, not defined for AArch64
# - AARCH64 - ARMv8+ (64-bit)
# - PPC64 / PPC64LE - PowerPC
# - MIPS
#
# OS:
# - WIN32 - Windows | MINGW
@@ -21,9 +20,8 @@
# - APPLE - MacOSX | iOS
# ----------------------------------------------------------------------------
if(CMAKE_CL_64)
set(MSVC64 1)
endif()
ocv_declare_removed_variables(MINGW64 MSVC64)
# do not use (CMake variables): CMAKE_CL_64
if(NOT DEFINED CV_GCC AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(CV_GCC 1)
@@ -51,7 +49,7 @@ variable_watch(CMAKE_COMPILER_IS_CLANGCC access_CMAKE_COMPILER_IS_CLANGCXX)
# Detect Intel ICC compiler
# ----------------------------------------------------------------------------
if(UNIX)
if (__ICL)
if(__ICL)
set(CV_ICC __ICL)
elseif(__ICC)
set(CV_ICC __ICC)
@@ -70,53 +68,65 @@ if(MSVC AND CMAKE_C_COMPILER MATCHES "icc|icl")
set(CV_ICC __INTEL_COMPILER_FOR_WINDOWS)
endif()
if(NOT DEFINED CMAKE_CXX_COMPILER_VERSION)
message(WARNING "Compiler version is not available: CMAKE_CXX_COMPILER_VERSION is not set")
if(NOT DEFINED CMAKE_CXX_COMPILER_VERSION
AND NOT OPENCV_SUPPRESS_MESSAGE_MISSING_COMPILER_VERSION)
message(WARNING "OpenCV: Compiler version is not available: CMAKE_CXX_COMPILER_VERSION is not set")
endif()
if(WIN32 AND CV_GCC)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpmachine
OUTPUT_VARIABLE OPENCV_GCC_TARGET_MACHINE
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(OPENCV_GCC_TARGET_MACHINE MATCHES "amd64|x86_64|AMD64")
set(MINGW64 1)
endif()
if((NOT DEFINED CMAKE_SYSTEM_PROCESSOR OR CMAKE_SYSTEM_PROCESSOR STREQUAL "")
AND NOT OPENCV_SUPPRESS_MESSAGE_MISSING_CMAKE_SYSTEM_PROCESSOR)
message(WARNING "OpenCV: CMAKE_SYSTEM_PROCESSOR is not defined. Perhaps CMake toolchain is broken")
endif()
if(NOT DEFINED CMAKE_SIZEOF_VOID_P
AND NOT OPENCV_SUPPRESS_MESSAGE_MISSING_CMAKE_SIZEOF_VOID_P)
message(WARNING "OpenCV: CMAKE_SIZEOF_VOID_P is not defined. Perhaps CMake toolchain is broken")
endif()
message(STATUS "Detected processor: ${CMAKE_SYSTEM_PROCESSOR}")
if(MSVC64 OR MINGW64)
set(X86_64 1)
elseif(MINGW OR (MSVC AND NOT CMAKE_CROSSCOMPILING))
set(X86 1)
if(OPENCV_SKIP_SYSTEM_PROCESSOR_DETECTION)
# custom setup: required variables are passed through cache / CMake's command-line
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
set(X86_64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|AMD64.*")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*")
set(X86 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*|arm64.*|ARM64.*)")
set(AARCH64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)")
set(ARM 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)")
set(AARCH64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
set(PPC64LE 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64")
set(PPC64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(mips.*|MIPS.*)")
set(MIPS 1)
else()
if(NOT OPENCV_SUPPRESS_MESSAGE_UNRECOGNIZED_SYSTEM_PROCESSOR)
message(WARNING "OpenCV: unrecognized target processor configuration")
endif()
endif()
# Workaround for 32-bit operating systems on x86_64/aarch64 processor
if(CMAKE_SIZEOF_VOID_P EQUAL 4 AND NOT FORCE_X86_64)
# Workaround for 32-bit operating systems on x86_64
if(CMAKE_SIZEOF_VOID_P EQUAL 4 AND X86_64
AND NOT FORCE_X86_64 # deprecated (2019-12)
AND NOT OPENCV_FORCE_X86_64
)
message(STATUS "sizeof(void) = 4 on 64 bit processor. Assume 32-bit compilation mode")
if (X86_64)
if(X86_64)
unset(X86_64)
set(X86 1)
endif()
if (AARCH64)
endif()
# Workaround for 32-bit operating systems on aarch64 processor
if(CMAKE_SIZEOF_VOID_P EQUAL 4 AND AARCH64
AND NOT OPENCV_FORCE_AARCH64
)
message(STATUS "sizeof(void) = 4 on 64 bit processor. Assume 32-bit compilation mode")
if(AARCH64)
unset(AARCH64)
set(ARM 1)
endif()
endif()
# Similar code exists in OpenCVConfig.cmake
if(NOT DEFINED OpenCV_STATIC)
# look for global setting
@@ -130,14 +140,19 @@ endif()
if(DEFINED OpenCV_ARCH AND DEFINED OpenCV_RUNTIME)
# custom overridden values
elseif(MSVC)
if(CMAKE_CL_64)
set(OpenCV_ARCH x64)
elseif((CMAKE_GENERATOR MATCHES "ARM") OR ("${arch_hint}" STREQUAL "ARM") OR (CMAKE_VS_EFFECTIVE_PLATFORMS MATCHES "ARM|arm"))
# see Modules/CmakeGenericSystem.cmake
set(OpenCV_ARCH ARM)
# see Modules/CMakeGenericSystem.cmake
if("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
set(OpenCV_ARCH "x64")
elseif("${CMAKE_GENERATOR_PLATFORM}" MATCHES "ARM64")
set(OpenCV_ARCH "ARM64")
elseif("${CMAKE_GENERATOR}" MATCHES "ARM")
set(OpenCV_ARCH "ARM")
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set(OpenCV_ARCH "x64")
else()
set(OpenCV_ARCH x86)
endif()
if(MSVC_VERSION EQUAL 1400)
set(OpenCV_RUNTIME vc8)
elseif(MSVC_VERSION EQUAL 1500)
@@ -160,7 +175,7 @@ elseif(MSVC)
elseif(MINGW)
set(OpenCV_RUNTIME mingw)
if(MINGW64)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
set(OpenCV_ARCH x64)
else()
set(OpenCV_ARCH x86)
+28 -2
View File
@@ -35,6 +35,15 @@ function(add_custom_ie_build _inc _lib _lib_rel _lib_dbg _msg)
IMPORTED_IMPLIB_DEBUG "${_lib_dbg}"
INTERFACE_INCLUDE_DIRECTORIES "${_inc}"
)
find_library(ie_builder_custom_lib "inference_engine_nn_builder" PATHS "${INF_ENGINE_LIB_DIRS}" NO_DEFAULT_PATH)
if(EXISTS "${ie_builder_custom_lib}")
add_library(inference_engine_nn_builder UNKNOWN IMPORTED)
set_target_properties(inference_engine_nn_builder PROPERTIES
IMPORTED_LOCATION "${ie_builder_custom_lib}"
)
endif()
if(NOT INF_ENGINE_RELEASE VERSION_GREATER "2018050000")
find_library(INF_ENGINE_OMP_LIBRARY iomp5 PATHS "${INF_ENGINE_OMP_DIR}" NO_DEFAULT_PATH)
if(NOT INF_ENGINE_OMP_LIBRARY)
@@ -44,7 +53,12 @@ function(add_custom_ie_build _inc _lib _lib_rel _lib_dbg _msg)
endif()
endif()
set(INF_ENGINE_VERSION "Unknown" CACHE STRING "")
set(INF_ENGINE_TARGET inference_engine PARENT_SCOPE)
set(INF_ENGINE_TARGET inference_engine)
if(TARGET inference_engine_nn_builder)
list(APPEND INF_ENGINE_TARGET inference_engine_nn_builder)
set(_msg "${_msg}, with IE NN Builder API")
endif()
set(INF_ENGINE_TARGET "${INF_ENGINE_TARGET}" PARENT_SCOPE)
message(STATUS "Detected InferenceEngine: ${_msg}")
endfunction()
@@ -54,7 +68,7 @@ find_package(InferenceEngine QUIET)
if(InferenceEngine_FOUND)
set(INF_ENGINE_TARGET ${InferenceEngine_LIBRARIES})
set(INF_ENGINE_VERSION "${InferenceEngine_VERSION}" CACHE STRING "")
message(STATUS "Detected InferenceEngine: cmake package")
message(STATUS "Detected InferenceEngine: cmake package (${InferenceEngine_VERSION})")
endif()
if(NOT INF_ENGINE_TARGET AND INF_ENGINE_LIB_DIRS AND INF_ENGINE_INCLUDE_DIRS)
@@ -94,3 +108,15 @@ if(INF_ENGINE_TARGET)
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
)
endif()
if(WITH_NGRAPH)
find_package(ngraph QUIET)
if(ngraph_FOUND)
ocv_assert(TARGET ngraph::ngraph)
if(INF_ENGINE_RELEASE VERSION_LESS "2019039999")
message(WARNING "nGraph is not tested with current InferenceEngine version: INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}")
endif()
message(STATUS "Detected ngraph: cmake package (${ngraph_VERSION})")
set(HAVE_NGRAPH ON)
endif()
endif()
+2 -5
View File
@@ -40,11 +40,8 @@ if (X86 AND UNIX AND NOT APPLE AND NOT ANDROID AND BUILD_SHARED_LIBS)
endif()
set(IPP_X64 0)
if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8)
set(IPP_X64 1)
endif()
if(CMAKE_CL_64)
set(IPP_X64 1)
if(X86_64)
set(IPP_X64 1)
endif()
# This function detects Intel IPP version by analyzing .h file
+1 -1
View File
@@ -289,7 +289,7 @@ if(WIN32)
if(HAVE_VFW)
list(APPEND VIDEOIO_LIBRARIES vfw32)
endif()
if(MINGW64)
if(MINGW AND CMAKE_SIZEOF_VOID_P EQUAL 8)
list(APPEND VIDEOIO_LIBRARIES avifil32 avicap32 winmm msvfw32)
list(REMOVE_ITEM VIDEOIO_LIBRARIES vfw32)
elseif(MINGW)
+1 -1
View File
@@ -133,7 +133,7 @@ message(STATUS "Found MKL ${MKL_VERSION_STR} at: ${MKL_ROOT_DIR}")
set(HAVE_MKL ON)
set(MKL_ROOT_DIR "${MKL_ROOT_DIR}" CACHE PATH "Path to MKL directory")
set(MKL_INCLUDE_DIRS "${MKL_INCLUDE_DIRS}" CACHE PATH "Path to MKL include directory")
set(MKL_LIBRARIES "${MKL_LIBRARIES}" CACHE STRING "MKL libarries")
set(MKL_LIBRARIES "${MKL_LIBRARIES}" CACHE STRING "MKL libraries")
if(UNIX AND NOT MKL_LIBRARIES_DONT_HACK)
#it's ugly but helps to avoid cyclic lib problem
set(MKL_LIBRARIES ${MKL_LIBRARIES} ${MKL_LIBRARIES} ${MKL_LIBRARIES} "-lpthread" "-lm" "-ldl")
+75 -41
View File
@@ -15,60 +15,94 @@ file(TO_CMAKE_PATH "$ENV{ProgramFiles}" ProgramFiles_ENV_PATH)
if(WIN32)
SET(OPENEXR_ROOT "C:/Deploy" CACHE STRING "Path to the OpenEXR \"Deploy\" folder")
if(CMAKE_CL_64)
if(X86_64)
SET(OPENEXR_LIBSEARCH_SUFFIXES x64/Release x64 x64/Debug)
elseif(MSVC)
SET(OPENEXR_LIBSEARCH_SUFFIXES Win32/Release Win32 Win32/Debug)
endif()
else()
set(OPENEXR_ROOT "")
endif()
SET(LIBRARY_PATHS
/usr/lib
/usr/local/lib
/sw/lib
/opt/local/lib
"${ProgramFiles_ENV_PATH}/OpenEXR/lib/static"
"${OPENEXR_ROOT}/lib")
SET(SEARCH_PATHS
"${OPENEXR_ROOT}"
/usr
/usr/local
/sw
/opt
"${ProgramFiles_ENV_PATH}/OpenEXR")
FIND_PATH(OPENEXR_INCLUDE_PATH ImfRgbaFile.h
PATH_SUFFIXES OpenEXR
PATHS
/usr/include
/usr/local/include
/sw/include
/opt/local/include
"${ProgramFiles_ENV_PATH}/OpenEXR/include"
"${OPENEXR_ROOT}/include")
MACRO(FIND_OPENEXR_LIBRARY LIBRARY_NAME LIBRARY_SUFFIX)
string(TOUPPER "${LIBRARY_NAME}" LIBRARY_NAME_UPPER)
FIND_LIBRARY(OPENEXR_${LIBRARY_NAME_UPPER}_LIBRARY
NAMES ${LIBRARY_NAME}${LIBRARY_SUFFIX}
PATH_SUFFIXES ${OPENEXR_LIBSEARCH_SUFFIXES}
NO_DEFAULT_PATH
PATHS "${SEARCH_PATH}/lib" "${SEARCH_PATH}/lib/static")
ENDMACRO()
FIND_LIBRARY(OPENEXR_HALF_LIBRARY
NAMES Half
PATH_SUFFIXES ${OPENEXR_LIBSEARCH_SUFFIXES}
PATHS ${LIBRARY_PATHS})
FOREACH(SEARCH_PATH ${SEARCH_PATHS})
FIND_PATH(OPENEXR_INCLUDE_PATH ImfRgbaFile.h
PATH_SUFFIXES OpenEXR
NO_DEFAULT_PATH
PATHS
"${SEARCH_PATH}/include")
FIND_LIBRARY(OPENEXR_IEX_LIBRARY
NAMES Iex
PATH_SUFFIXES ${OPENEXR_LIBSEARCH_SUFFIXES}
PATHS ${LIBRARY_PATHS})
IF (OPENEXR_INCLUDE_PATH)
SET(OPENEXR_VERSION_FILE "${OPENEXR_INCLUDE_PATH}/OpenEXRConfig.h")
IF (EXISTS ${OPENEXR_VERSION_FILE})
FILE (STRINGS ${OPENEXR_VERSION_FILE} contents REGEX "#define OPENEXR_VERSION_MAJOR ")
IF (${contents} MATCHES "#define OPENEXR_VERSION_MAJOR ([0-9]+)")
SET(OPENEXR_VERSION_MAJOR "${CMAKE_MATCH_1}")
ENDIF ()
FILE (STRINGS ${OPENEXR_VERSION_FILE} contents REGEX "#define OPENEXR_VERSION_MINOR ")
IF (${contents} MATCHES "#define OPENEXR_VERSION_MINOR ([0-9]+)")
SET(OPENEXR_VERSION_MINOR "${CMAKE_MATCH_1}")
ENDIF ()
ENDIF ()
ENDIF ()
FIND_LIBRARY(OPENEXR_IMATH_LIBRARY
NAMES Imath
PATH_SUFFIXES ${OPENEXR_LIBSEARCH_SUFFIXES}
PATHS ${LIBRARY_PATHS})
IF (OPENEXR_VERSION_MAJOR AND OPENEXR_VERSION_MINOR)
set(OPENEXR_VERSION "${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}")
ENDIF ()
FIND_LIBRARY(OPENEXR_ILMIMF_LIBRARY
NAMES IlmImf
PATH_SUFFIXES ${OPENEXR_LIBSEARCH_SUFFIXES}
PATHS ${LIBRARY_PATHS})
SET(LIBRARY_SUFFIXES
"-${OPENEXR_VERSION}"
"-${OPENEXR_VERSION}_s"
"-${OPENEXR_VERSION}_d"
"-${OPEXEXR_VERSION}_s_d"
""
"_s"
"_d"
"_s_d")
FIND_LIBRARY(OPENEXR_ILMTHREAD_LIBRARY
NAMES IlmThread
PATH_SUFFIXES ${OPENEXR_LIBSEARCH_SUFFIXES}
PATHS ${LIBRARY_PATHS})
FOREACH(LIBRARY_SUFFIX ${LIBRARY_SUFFIXES})
FIND_OPENEXR_LIBRARY("Half" ${LIBRARY_SUFFIX})
FIND_OPENEXR_LIBRARY("Iex" ${LIBRARY_SUFFIX})
FIND_OPENEXR_LIBRARY("Imath" ${LIBRARY_SUFFIX})
FIND_OPENEXR_LIBRARY("IlmImf" ${LIBRARY_SUFFIX})
FIND_OPENEXR_LIBRARY("IlmThread" ${LIBRARY_SUFFIX})
IF (OPENEXR_INCLUDE_PATH AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY)
SET(OPENEXR_FOUND TRUE)
BREAK()
ENDIF()
UNSET(OPENEXR_IMATH_LIBRARY)
UNSET(OPENEXR_ILMIMF_LIBRARY)
UNSET(OPENEXR_IEX_LIBRARY)
UNSET(OPENEXR_ILMTHREAD_LIBRARY)
UNSET(OPENEXR_HALF_LIBRARY)
ENDFOREACH()
IF (OPENEXR_INCLUDE_PATH AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY)
SET(OPENEXR_FOUND TRUE)
IF (OPENEXR_FOUND)
BREAK()
ENDIF()
UNSET(OPENEXR_INCLUDE_PATH)
UNSET(OPENEXR_VERSION_FILE)
UNSET(OPENEXR_VERSION_MAJOR)
UNSET(OPENEXR_VERSION_MINOR)
UNSET(OPENEXR_VERSION)
ENDFOREACH()
IF (OPENEXR_FOUND)
SET(OPENEXR_INCLUDE_PATHS ${OPENEXR_INCLUDE_PATH} CACHE PATH "The include paths needed to use OpenEXR")
SET(OPENEXR_LIBRARIES ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_ILMIMF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} CACHE STRING "The libraries needed to use OpenEXR" FORCE)
ENDIF ()
+2 -2
View File
@@ -18,7 +18,7 @@ if(NOT "${OPENNI_PRIME_SENSOR_MODULE_BIN_DIR}" STREQUAL "${OPENNI_PRIME_SENSOR_M
endif()
if(WIN32)
if(NOT (MSVC64 OR MINGW64))
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
find_file(OPENNI_INCLUDES "XnCppWrapper.h" PATHS "$ENV{OPEN_NI_INSTALL_PATH}Include" DOC "OpenNI c++ interface header")
find_library(OPENNI_LIBRARY "OpenNI" PATHS $ENV{OPEN_NI_LIB} DOC "OpenNI library")
else()
@@ -34,7 +34,7 @@ if(OPENNI_LIBRARY AND OPENNI_INCLUDES)
set(HAVE_OPENNI TRUE)
# the check: are PrimeSensor Modules for OpenNI installed
if(WIN32)
if(NOT (MSVC64 OR MINGW64))
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
find_file(OPENNI_PRIME_SENSOR_MODULE "XnCore.dll" PATHS "$ENV{OPEN_NI_INSTALL_PATH}../PrimeSense/Sensor/Bin" "$ENV{OPEN_NI_INSTALL_PATH}../PrimeSense/SensorKinect/Bin" DOC "Core library of PrimeSensor Modules for OpenNI")
else()
find_file(OPENNI_PRIME_SENSOR_MODULE "XnCore64.dll" PATHS "$ENV{OPEN_NI_INSTALL_PATH64}../PrimeSense/Sensor/Bin64" "$ENV{OPEN_NI_INSTALL_PATH64}../PrimeSense/SensorKinect/Bin64" DOC "Core library of PrimeSensor Modules for OpenNI")
+1 -1
View File
@@ -13,7 +13,7 @@ if(NOT "${OPENNI2_INCLUDE_DIR}" STREQUAL "${OPENNI2_INCLUDE_DIR_INTERNAL}")
endif()
if(WIN32)
if(NOT (MSVC64 OR MINGW64))
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
find_file(OPENNI2_INCLUDES "OpenNI.h" PATHS $ENV{OPENNI2_INCLUDE} "$ENV{OPEN_NI_INSTALL_PATH}Include" DOC "OpenNI2 c++ interface header")
find_library(OPENNI2_LIBRARY "OpenNI2" PATHS $ENV{OPENNI2_LIB} DOC "OpenNI2 library")
else()
+11 -8
View File
@@ -63,7 +63,6 @@ foreach(mod ${OPENCV_MODULES_BUILD} ${OPENCV_MODULES_DISABLED_USER} ${OPENCV_MOD
unset(OPENCV_MODULE_${mod}_PRIVATE_OPT_DEPS CACHE)
unset(OPENCV_MODULE_${mod}_LINK_DEPS CACHE)
unset(OPENCV_MODULE_${mod}_WRAPPERS CACHE)
unset(OPENCV_DEPENDANT_TARGETS_${mod} CACHE)
endforeach()
# clean modules info which needs to be recalculated
@@ -935,11 +934,15 @@ macro(_ocv_create_module)
set_source_files_properties(${OPENCV_MODULE_${the_module}_HEADERS} ${OPENCV_MODULE_${the_module}_SOURCES} ${${the_module}_pch}
PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Module")
ocv_target_link_libraries(${the_module} LINK_PUBLIC ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK})
ocv_target_link_libraries(${the_module} LINK_PUBLIC ${OPENCV_MODULE_${the_module}_DEPS_EXT})
ocv_target_link_libraries(${the_module} LINK_PRIVATE ${OPENCV_LINKER_LIBS} ${OPENCV_HAL_LINKER_LIBS} ${IPP_LIBS} ${ARGN})
ocv_target_link_libraries(${the_module} PUBLIC ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK}
INTERFACE ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK}
)
ocv_target_link_libraries(${the_module} PUBLIC ${OPENCV_MODULE_${the_module}_DEPS_EXT}
INTERFACE ${OPENCV_MODULE_${the_module}_DEPS_EXT}
)
ocv_target_link_libraries(${the_module} PRIVATE ${OPENCV_LINKER_LIBS} ${OPENCV_HAL_LINKER_LIBS} ${IPP_LIBS} ${ARGN})
if (HAVE_CUDA)
ocv_target_link_libraries(${the_module} LINK_PRIVATE ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
ocv_target_link_libraries(${the_module} PRIVATE ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
endif()
if(OPENCV_MODULE_${the_module}_COMPILE_DEFINITIONS)
@@ -1146,7 +1149,7 @@ function(ocv_add_perf_tests)
source_group("Src" FILES "${${the_target}_pch}")
ocv_add_executable(${the_target} ${OPENCV_PERF_${the_module}_SOURCES} ${${the_target}_pch})
ocv_target_include_modules(${the_target} ${perf_deps})
ocv_target_link_libraries(${the_target} LINK_PRIVATE ${perf_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS} ${OPENCV_PERF_${the_module}_DEPS})
ocv_target_link_libraries(${the_target} PRIVATE ${perf_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS} ${OPENCV_PERF_${the_module}_DEPS})
add_dependencies(opencv_perf_tests ${the_target})
set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};PerfTest")
@@ -1227,7 +1230,7 @@ function(ocv_add_accuracy_tests)
if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/test")
ocv_target_include_directories(${the_target} "${CMAKE_CURRENT_BINARY_DIR}/test")
endif()
ocv_target_link_libraries(${the_target} LINK_PRIVATE ${test_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS} ${OPENCV_TEST_${the_module}_DEPS})
ocv_target_link_libraries(${the_target} PRIVATE ${test_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS} ${OPENCV_TEST_${the_module}_DEPS})
add_dependencies(opencv_tests ${the_target})
set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};AccuracyTest")
@@ -1288,7 +1291,7 @@ function(ocv_add_samples)
ocv_add_executable(${the_target} "${source}")
ocv_target_include_modules(${the_target} ${samples_deps})
ocv_target_link_libraries(${the_target} LINK_PRIVATE ${samples_deps})
ocv_target_link_libraries(${the_target} PRIVATE ${samples_deps})
set_target_properties(${the_target} PROPERTIES
PROJECT_LABEL "(sample) ${name}"
+2 -2
View File
@@ -125,11 +125,11 @@ MACRO(_PCH_GET_COMPILE_COMMAND out_command _input _output)
STRING(REGEX REPLACE "^ +" "" pchsupport_compiler_cxx_arg1 ${CMAKE_CXX_COMPILER_ARG1})
SET(${out_command}
${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} -x c++-header -o ${_output} ${_input}
${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} -x c++-header -o ${_output} -c ${_input}
)
ELSE(CMAKE_CXX_COMPILER_ARG1)
SET(${out_command}
${CMAKE_CXX_COMPILER} ${_compile_FLAGS} -x c++-header -o ${_output} ${_input}
${CMAKE_CXX_COMPILER} ${_compile_FLAGS} -x c++-header -o ${_output} -c ${_input}
)
ENDIF(CMAKE_CXX_COMPILER_ARG1)
ELSE()
+46 -3
View File
@@ -100,6 +100,30 @@ macro(ocv_update VAR)
endif()
endmacro()
function(_ocv_access_removed_variable VAR ACCESS)
if(ACCESS STREQUAL "MODIFIED_ACCESS")
set(OPENCV_SUPPRESS_MESSAGE_REMOVED_VARIABLE_${VAR} 1 PARENT_SCOPE)
return()
endif()
if(ACCESS MATCHES "UNKNOWN_.*"
AND NOT OPENCV_SUPPRESS_MESSAGE_REMOVED_VARIABLE
AND NOT OPENCV_SUPPRESS_MESSAGE_REMOVED_VARIABLE_${VAR}
)
message(WARNING "OpenCV: Variable has been removed from CMake scripts: ${VAR}")
set(OPENCV_SUPPRESS_MESSAGE_REMOVED_VARIABLE_${VAR} 1 PARENT_SCOPE) # suppress similar messages
endif()
endfunction()
macro(ocv_declare_removed_variable VAR)
if(NOT DEFINED ${VAR}) # don't hit external variables
variable_watch(${VAR} _ocv_access_removed_variable)
endif()
endmacro()
macro(ocv_declare_removed_variables)
foreach(_var ${ARGN})
ocv_declare_removed_variable(${_var})
endforeach()
endmacro()
# Search packages for the host system instead of packages for the target system
# in case of cross compilation these macros should be defined by the toolchain file
if(NOT COMMAND find_host_package)
@@ -288,9 +312,22 @@ function(ocv_append_target_property target prop)
endif()
endfunction()
if(DEFINED OPENCV_DEPENDANT_TARGETS_LIST)
foreach(v ${OPENCV_DEPENDANT_TARGETS_LIST})
unset(${v} CACHE)
endforeach()
unset(OPENCV_DEPENDANT_TARGETS_LIST CACHE)
endif()
function(ocv_append_dependant_targets target)
#ocv_debug_message("ocv_append_dependant_targets(${target} ${ARGN})")
_ocv_fix_target(target)
list(FIND OPENCV_DEPENDANT_TARGETS_LIST "OPENCV_DEPENDANT_TARGETS_${target}" __id)
if(__id EQUAL -1)
list(APPEND OPENCV_DEPENDANT_TARGETS_LIST "OPENCV_DEPENDANT_TARGETS_${target}")
list(SORT OPENCV_DEPENDANT_TARGETS_LIST)
set(OPENCV_DEPENDANT_TARGETS_LIST "${OPENCV_DEPENDANT_TARGETS_LIST}" CACHE INTERNAL "")
endif()
set(OPENCV_DEPENDANT_TARGETS_${target} "${OPENCV_DEPENDANT_TARGETS_${target}};${ARGN}" CACHE INTERNAL "" FORCE)
endfunction()
@@ -364,6 +401,7 @@ macro(ocv_clear_vars)
endmacro()
set(OCV_COMPILER_FAIL_REGEX
"argument '.*' is not valid" # GCC 9+
"command line option .* is valid for .* but not for C\\+\\+" # GNU
"command line option .* is valid for .* but not for C" # GNU
"unrecognized .*option" # GNU
@@ -1402,12 +1440,14 @@ endmacro()
function(ocv_target_link_libraries target)
set(LINK_DEPS ${ARGN})
_ocv_fix_target(target)
set(LINK_MODE "LINK_PRIVATE")
set(LINK_MODE "PRIVATE")
set(LINK_PENDING "")
foreach(dep ${LINK_DEPS})
if(" ${dep}" STREQUAL " ${target}")
# prevent "link to itself" warning (world problem)
elseif(" ${dep}" STREQUAL " LINK_PRIVATE" OR " ${dep}" STREQUAL "LINK_PUBLIC")
elseif(" ${dep}" STREQUAL " LINK_PRIVATE" OR " ${dep}" STREQUAL " LINK_PUBLIC" # deprecated
OR " ${dep}" STREQUAL " PRIVATE" OR " ${dep}" STREQUAL " PUBLIC" OR " ${dep}" STREQUAL " INTERFACE"
)
if(NOT LINK_PENDING STREQUAL "")
__ocv_push_target_link_libraries(${LINK_MODE} ${LINK_PENDING})
set(LINK_PENDING "")
@@ -1546,7 +1586,10 @@ macro(ocv_get_all_libs _modules _extra _3rdparty)
endif()
if (TARGET ${dep})
get_target_property(_type ${dep} TYPE)
if(_type STREQUAL "STATIC_LIBRARY" AND BUILD_SHARED_LIBS OR _type STREQUAL "INTERFACE_LIBRARY")
if((_type STREQUAL "STATIC_LIBRARY" AND BUILD_SHARED_LIBS)
OR _type STREQUAL "INTERFACE_LIBRARY"
OR DEFINED OPENCV_MODULE_${dep}_LOCATION # OpenCV modules
)
# nothing
else()
get_target_property(_output ${dep} IMPORTED_LOCATION)
+1 -1
View File
@@ -194,7 +194,7 @@ macro(add_android_project target path)
add_library(${JNI_LIB_NAME} SHARED ${android_proj_jni_files})
ocv_target_include_modules_recurse(${JNI_LIB_NAME} ${android_proj_NATIVE_DEPS})
ocv_target_include_directories(${JNI_LIB_NAME} "${path}/jni")
ocv_target_link_libraries(${JNI_LIB_NAME} LINK_PRIVATE ${OPENCV_LINKER_LIBS} ${android_proj_NATIVE_DEPS})
ocv_target_link_libraries(${JNI_LIB_NAME} PRIVATE ${OPENCV_LINKER_LIBS} ${android_proj_NATIVE_DEPS})
set_target_properties(${JNI_LIB_NAME} PROPERTIES
OUTPUT_NAME "${JNI_LIB_NAME}"
+5 -1
View File
@@ -1,6 +1,6 @@
#include <stdio.h>
#if defined _WIN32 && defined(_M_ARM)
#if defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64))
# include <Intrin.h>
# include <arm_neon.h>
# define CV_NEON 1
@@ -9,6 +9,10 @@
# define CV_NEON 1
#endif
// MSVC 2019 bug. Details: https://github.com/opencv/opencv/pull/16027
void test_aliased_type(const uint8x16_t& a) { }
void test_aliased_type(const int8x16_t& a) { }
#if defined CV_NEON
int test()
{
+1 -1
View File
@@ -1,4 +1,4 @@
include("${CMAKE_CURRENT_LIST_DIR}/OpenCV_WinRT.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/OpenCV-WinRT.cmake")
# Adding additional using directory for WindowsPhone 8.0 to get Windows.winmd properly
if(WINRT_8_0)
+1 -1
View File
@@ -1 +1 @@
include("${CMAKE_CURRENT_LIST_DIR}/OpenCV_WinRT.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/OpenCV-WinRT.cmake")
@@ -84,17 +84,31 @@ endfunction()
get_filename_component(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
if((NOT DEFINED CMAKE_SYSTEM_PROCESSOR OR CMAKE_SYSTEM_PROCESSOR STREQUAL "")
AND NOT OPENCV_SUPPRESS_MESSAGE_MISSING_CMAKE_SYSTEM_PROCESSOR)
message(WARNING "OpenCV: CMAKE_SYSTEM_PROCESSOR is not defined. Perhaps CMake toolchain is broken")
endif()
if(NOT DEFINED CMAKE_SIZEOF_VOID_P
AND NOT OPENCV_SUPPRESS_MESSAGE_MISSING_CMAKE_SIZEOF_VOID_P)
message(WARNING "OpenCV: CMAKE_SIZEOF_VOID_P is not defined. Perhaps CMake toolchain is broken")
endif()
if(DEFINED OpenCV_ARCH AND DEFINED OpenCV_RUNTIME)
# custom overridden values
elseif(MSVC)
if(CMAKE_CL_64)
set(OpenCV_ARCH x64)
elseif((CMAKE_GENERATOR MATCHES "ARM") OR ("${arch_hint}" STREQUAL "ARM") OR (CMAKE_VS_EFFECTIVE_PLATFORMS MATCHES "ARM|arm"))
# see Modules/CmakeGenericSystem.cmake
set(OpenCV_ARCH ARM)
# see Modules/CMakeGenericSystem.cmake
if("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
set(OpenCV_ARCH "x64")
elseif("${CMAKE_GENERATOR_PLATFORM}" MATCHES "ARM64")
set(OpenCV_ARCH "ARM64")
elseif("${CMAKE_GENERATOR}" MATCHES "ARM")
set(OpenCV_ARCH "ARM")
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set(OpenCV_ARCH "x64")
else()
set(OpenCV_ARCH x86)
endif()
if(MSVC_VERSION EQUAL 1400)
set(OpenCV_RUNTIME vc8)
elseif(MSVC_VERSION EQUAL 1500)
@@ -127,11 +141,7 @@ elseif(MSVC)
elseif(MINGW)
set(OpenCV_RUNTIME mingw)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpmachine
OUTPUT_VARIABLE OPENCV_GCC_TARGET_MACHINE
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(OPENCV_GCC_TARGET_MACHINE MATCHES "amd64|x86_64|AMD64")
set(MINGW64 1)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
set(OpenCV_ARCH x64)
else()
set(OpenCV_ARCH x86)
+2
View File
@@ -22,6 +22,8 @@
<skip_headers>
opencv2/core/hal/intrin*
opencv2/core/hal/*macros.*
opencv2/core/hal/*.impl.*
opencv2/core/cuda*
opencv2/core/opencl*
opencv2/core/private*
+20 -2
View File
@@ -157,9 +157,27 @@ if(DOXYGEN_FOUND)
list(APPEND CMAKE_DOXYGEN_HTML_FILES "${CMAKE_CURRENT_SOURCE_DIR}/tutorial-utils.js")
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_HTML_FILES "${CMAKE_DOXYGEN_HTML_FILES}")
set(OPENCV_DOCS_DOT_PATH "" CACHE PATH "Doxygen/DOT_PATH value")
set(CMAKECONFIG_DOT_PATH "${OPENCV_DOCS_DOT_PATH}")
set(OPENCV_DOCS_HAVE_DOT "NO" CACHE BOOL "Doxygen: build extra diagrams")
set(CMAKECONFIG_HAVE_DOT "${OPENCV_DOCS_HAVE_DOT}")
# 'png' is good enough for compatibility (but requires +50% storage space)
set(OPENCV_DOCS_DOT_IMAGE_FORMAT "svg" CACHE STRING "Doxygen/DOT_IMAGE_FORMAT value")
set(CMAKECONFIG_DOT_IMAGE_FORMAT "${OPENCV_DOCS_DOT_IMAGE_FORMAT}")
# Doxygen 1.8.16 fix: https://github.com/doxygen/doxygen/pull/6870
# NO is needed here: https://github.com/opencv/opencv/pull/16039
set(OPENCV_DOCS_INTERACTIVE_SVG "NO" CACHE BOOL "Doxygen/INTERACTIVE_SVG value")
set(CMAKECONFIG_INTERACTIVE_SVG "${OPENCV_DOCS_INTERACTIVE_SVG}")
set(OPENCV_DOCS_DOXYFILE_IN "Doxyfile.in" CACHE PATH "Doxygen configuration template file (Doxyfile.in)")
set(OPENCV_DOCS_DOXYGEN_LAYOUT "DoxygenLayout.xml" CACHE PATH "Doxygen layout file (.xml)")
# writing file
configure_file(DoxygenLayout.xml DoxygenLayout.xml @ONLY)
configure_file(Doxyfile.in ${doxyfile} @ONLY)
configure_file("${OPENCV_DOCS_DOXYGEN_LAYOUT}" DoxygenLayout.xml @ONLY)
configure_file("${OPENCV_DOCS_DOXYFILE_IN}" ${doxyfile} @ONLY)
configure_file(root.markdown.in ${rootfile} @ONLY)
# js tutorial assets
+4 -4
View File
@@ -264,7 +264,7 @@ EXTERNAL_PAGES = YES
CLASS_DIAGRAMS = YES
DIA_PATH =
HIDE_UNDOC_RELATIONS = NO
HAVE_DOT = NO
HAVE_DOT = @CMAKECONFIG_HAVE_DOT@
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
@@ -281,9 +281,9 @@ CALL_GRAPH = YES
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = svg
INTERACTIVE_SVG = YES
DOT_PATH =
DOT_IMAGE_FORMAT = @CMAKECONFIG_DOT_IMAGE_FORMAT@
INTERACTIVE_SVG = @CMAKECONFIG_INTERACTIVE_SVG@
DOT_PATH = @CMAKECONFIG_DOT_PATH@
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
@@ -27,7 +27,7 @@ src1.delete(); src2.delete(); dst.delete(); mask.delete();
Image Subtraction
--------------
You can subtract two images by OpenCV function, cv.subtract(). res = img1 - img2. Both images should be of same depth and type.
You can subtract two images by OpenCV function, cv.subtract(). res = img1 - img2. Both images should be of same depth and type. Note that when used with RGBA images, the alpha channel is also subtracted.
For example, consider below sample:
@code{.js}
@@ -59,4 +59,4 @@ Try it
<iframe src="../../js_image_arithmetics_bitwise.html" width="100%"
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
\endhtmlonly
\endhtmlonly
@@ -36,7 +36,7 @@ let x = document.getElementById('myRange');
@endcode
As a trackbar, the range element need a trackbar name, the default value, minimum value, maximum value,
step and the callback function which is executed everytime trackbar value changes. The callback function
step and the callback function which is executed every time trackbar value changes. The callback function
always has a default argument, which is the trackbar position. Additionally, a text element to display the
trackbar value is fine. In our case, we can create the trackbar as below:
@code{.html}
@@ -0,0 +1,345 @@
Using OpenCV.js In Node.js {#tutorial_js_nodejs}
==========================
Goals
-----
In this tutorial, you will learn:
- Use OpenCV.js in a [Node.js](https://nodejs.org) application.
- Load images with [jimp](https://www.npmjs.com/package/jimp) in order to use them with OpenCV.js.
- Using [jsdom](https://www.npmjs.com/package/canvas) and [node-canvas](https://www.npmjs.com/package/canvas) to support `cv.imread()`, `cv.imshow()`
- The basics of [emscripten](https://emscripten.org/) APIs, like [Module](https://emscripten.org/docs/api_reference/module.html) and [File System](https://emscripten.org/docs/api_reference/Filesystem-API.html) on which OpenCV.js is based.
- Learn Node.js basics. Although this tutorial assumes the user knows JavaScript, experience with Node.js is not required.
@note Besides giving instructions to run OpenCV.js in Node.js, another objective of this tutorial is to introduce users to the basics of [emscripten](https://emscripten.org/) APIs, like [Module](https://emscripten.org/docs/api_reference/module.html) and [File System](https://emscripten.org/docs/api_reference/Filesystem-API.html) and also Node.js.
Minimal example
-----
Create a file `example1.js` with the following content:
@code{.js}
// Define a global variable 'Module' with a method 'onRuntimeInitialized':
Module = {
onRuntimeInitialized() {
// this is our application:
console.log(cv.getBuildInformation())
}
}
// Load 'opencv.js' assigning the value to the global variable 'cv'
cv = require('./opencv.js')
@endcode
### Execute it ###
- Save the file as `example1.js`.
- Make sure the file `opencv.js` is in the same folder.
- Make sure [Node.js](https://nodejs.org) is installed on your system.
The following command should print OpenCV build information:
@code{.bash}
node example1.js
@endcode
### What just happened? ###
* **In the first statement**:, by defining a global variable named 'Module', emscripten will call `Module.onRuntimeInitialized()` when the library is ready to use. Our program is in that method and uses the global variable `cv` just like in the browser.
* The statement **"cv = require('./opencv.js')"** requires the file `opencv.js` and assign the return value to the global variable `cv`.
`require()` which is a Node.js API, is used to load modules and files.
In this case we load the file `opencv.js` form the current folder, and, as said previously emscripten will call `Module.onRuntimeInitialized()` when its ready.
* See [emscripten Module API](https://emscripten.org/docs/api_reference/module.html) for more details.
Working with images
-----
OpenCV.js doesn't support image formats so we can't load png or jpeg images directly. In the browser it uses the HTML DOM (like HTMLCanvasElement and HTMLImageElement to decode and decode images). In node.js we will need to use a library for this.
In this example we use [jimp](https://www.npmjs.com/package/jimp), which supports common image formats and is pretty easy to use.
### Example setup ###
Execute the following commands to create a new node.js package and install [jimp](https://www.npmjs.com/package/jimp) dependency:
@code{.bash}
mkdir project1
cd project1
npm init -y
npm install jimp
@endcode
### The example ###
@code{.js}
const Jimp = require('jimp');
async function onRuntimeInitialized(){
// load local image file with jimp. It supports jpg, png, bmp, tiff and gif:
var jimpSrc = await Jimp.read('./lena.jpg');
// `jimpImage.bitmap` property has the decoded ImageData that we can use to create a cv:Mat
var src = cv.matFromImageData(jimpSrc.bitmap);
// following lines is copy&paste of opencv.js dilate tutorial:
let dst = new cv.Mat();
let M = cv.Mat.ones(5, 5, cv.CV_8U);
let anchor = new cv.Point(-1, -1);
cv.dilate(src, dst, M, anchor, 1, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
// Now that we are finish, we want to write `dst` to file `output.png`. For this we create a `Jimp`
// image which accepts the image data as a [`Buffer`](https://nodejs.org/docs/latest-v10.x/api/buffer.html).
// `write('output.png')` will write it to disk and Jimp infers the output format from given file name:
new Jimp({
width: dst.cols,
height: dst.rows,
data: Buffer.from(dst.data)
})
.write('output.png');
src.delete();
dst.delete();
}
// Finally, load the open.js as before. The function `onRuntimeInitialized` contains our program.
Module = {
onRuntimeInitialized
};
cv = require('./opencv.js');
@endcode
### Execute it ###
- Save the file as `exampleNodeJimp.js`.
- Make sure a sample image `lena.jpg` exists in the current directory.
The following command should generate the file `output.png`:
@code{.bash}
node exampleNodeJimp.js
@endcode
Emulating HTML DOM and canvas
-----
As you might already seen, the rest of the examples use functions like `cv.imread()`, `cv.imshow()` to read and write images. Unfortunately as mentioned they won't work on Node.js since there is no HTML DOM.
In this section, you will learn how to use [jsdom](https://www.npmjs.com/package/canvas) and [node-canvas](https://www.npmjs.com/package/canvas) to emulate the HTML DOM on Node.js so those functions work.
### Example setup ###
As before, we create a Node.js project and install the dependencies we need:
@code{.bash}
mkdir project2
cd project2
npm init -y
npm install canvas jsdom
@endcode
### The example ###
@code{.js}
const { Canvas, createCanvas, Image, ImageData, loadImage } = require('canvas');
const { JSDOM } = require('jsdom');
const { writeFileSync } = require('fs');
// This is our program. This time we use JavaScript async / await and promises to handle asynchronicity.
(async () => {
// before loading opencv.js we emulate a minimal HTML DOM. See the function declaration below.
installDOM();
await loadOpenCV();
// using node-canvas, we an image file to an object compatible with HTML DOM Image and therefore with cv.imread()
const image = await loadImage('./lena.jpg');
const src = cv.imread(image);
const dst = new cv.Mat();
const M = cv.Mat.ones(5, 5, cv.CV_8U);
const anchor = new cv.Point(-1, -1);
cv.dilate(src, dst, M, anchor, 1, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
// we create an object compatible HTMLCanvasElement
const canvas = createCanvas(300, 300);
cv.imshow(canvas, dst);
writeFileSync('output.jpg', canvas.toBuffer('image/jpeg'));
src.delete();
dst.delete();
})();
// Load opencv.js just like before but using Promise instead of callbacks:
function loadOpenCV() {
return new Promise(resolve => {
global.Module = {
onRuntimeInitialized: resolve
};
global.cv = require('./opencv.js');
});
}
// Using jsdom and node-canvas we define some global variables to emulate HTML DOM.
// Although a complete emulation can be archived, here we only define those globals used
// by cv.imread() and cv.imshow().
function installDOM() {
const dom = new JSDOM();
global.document = dom.window.document;
// The rest enables DOM image and canvas and is provided by node-canvas
global.Image = Image;
global.HTMLCanvasElement = Canvas;
global.ImageData = ImageData;
global.HTMLImageElement = Image;
}
@endcode
### Execute it ###
- Save the file as `exampleNodeCanvas.js`.
- Make sure a sample image `lena.jpg` exists in the current directory.
The following command should generate the file `output.jpg`:
@code{.bash}
node exampleNodeCanvas.js
@endcode
Dealing with files
-----
In this tutorial you will learn how to configure emscripten so it uses the local filesystem for file operations instead of using memory. Also it tries to describe how [files are supported by emscripten applications](https://emscripten.org/docs/api_reference/Filesystem-API.html)
Accessing the emscripten filesystem is often needed in OpenCV applications for example to load machine learning models such as the ones used in @ref tutorial_dnn_googlenet and @ref tutorial_dnn_javascript.
### Example setup ###
Before the example, is worth consider first how files are handled in emscripten applications such as OpenCV.js. Remember that OpenCV library is written in C++ and the file opencv.js is just that C++ code being translated to JavaScript or WebAssembly by emscripten C++ compiler.
These C++ sources use standard APIs to access the filesystem and the implementation often ends up in system calls that read a file in the hard drive. Since JavaScript applications in the browser don't have access to the local filesystem, [emscripten emulates a standard filesystem](https://emscripten.org/docs/api_reference/Filesystem-API.html) so compiled C++ code works out of the box.
In the browser, this filesystem is emulated in memory while in Node.js there's also the possibility of using the local filesystem directly. This is often preferable since there's no need of copy file's content in memory. This section is explains how to do do just that, this is, configuring emscripten so files are accessed directly from our local filesystem and relative paths match files relative to the current local directory as expected.
### The example ###
The following is an adaptation of @ref tutorial_js_face_detection.
@code{.js}
const { Canvas, createCanvas, Image, ImageData, loadImage } = require('canvas');
const { JSDOM } = require('jsdom');
const { writeFileSync, readFileSync } = require('fs');
(async () => {
await loadOpenCV();
const image = await loadImage('lena.jpg');
const src = cv.imread(image);
let gray = new cv.Mat();
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
let faces = new cv.RectVector();
let eyes = new cv.RectVector();
let faceCascade = new cv.CascadeClassifier();
let eyeCascade = new cv.CascadeClassifier();
// Load pre-trained classifier files. Notice how we reference local files using relative paths just
// like we normally would do
faceCascade.load('./haarcascade_frontalface_default.xml');
eyeCascade.load('./haarcascade_eye.xml');
let mSize = new cv.Size(0, 0);
faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0, mSize, mSize);
for (let i = 0; i < faces.size(); ++i) {
let roiGray = gray.roi(faces.get(i));
let roiSrc = src.roi(faces.get(i));
let point1 = new cv.Point(faces.get(i).x, faces.get(i).y);
let point2 = new cv.Point(faces.get(i).x + faces.get(i).width, faces.get(i).y + faces.get(i).height);
cv.rectangle(src, point1, point2, [255, 0, 0, 255]);
eyeCascade.detectMultiScale(roiGray, eyes);
for (let j = 0; j < eyes.size(); ++j) {
let point1 = new cv.Point(eyes.get(j).x, eyes.get(j).y);
let point2 = new cv.Point(eyes.get(j).x + eyes.get(j).width, eyes.get(j).y + eyes.get(j).height);
cv.rectangle(roiSrc, point1, point2, [0, 0, 255, 255]);
}
roiGray.delete();
roiSrc.delete();
}
const canvas = createCanvas(image.width, image.height);
cv.imshow(canvas, src);
writeFileSync('output3.jpg', canvas.toBuffer('image/jpeg'));
src.delete(); gray.delete(); faceCascade.delete(); eyeCascade.delete(); faces.delete(); eyes.delete()
})();
/**
* Loads opencv.js.
*
* Installs HTML Canvas emulation to support `cv.imread()` and `cv.imshow`
*
* Mounts given local folder `localRootDir` in emscripten filesystem folder `rootDir`. By default it will mount the local current directory in emscripten `/work` directory. This means that `/work/foo.txt` will be resolved to the local file `./foo.txt`
* @param {string} rootDir The directory in emscripten filesystem in which the local filesystem will be mount.
* @param {string} localRootDir The local directory to mount in emscripten filesystem.
* @returns {Promise} resolved when the library is ready to use.
*/
function loadOpenCV(rootDir = '/work', localRootDir = process.cwd()) {
if(global.Module && global.Module.onRuntimeInitialized && global.cv && global.cv.imread) {
return Promise.resolve()
}
return new Promise(resolve => {
installDOM()
global.Module = {
onRuntimeInitialized() {
// We change emscripten current work directory to 'rootDir' so relative paths are resolved
// relative to the current local folder, as expected
cv.FS.chdir(rootDir)
resolve()
},
preRun() {
// preRun() is another callback like onRuntimeInitialized() but is called just before the
// library code runs. Here we mount a local folder in emscripten filesystem and we want to
// do this before the library is executed so the filesystem is accessible from the start
const FS = global.Module.FS
// create rootDir if it doesn't exists
if(!FS.analyzePath(rootDir).exists) {
FS.mkdir(rootDir);
}
// create localRootFolder if it doesn't exists
if(!existsSync(localRootDir)) {
mkdirSync(localRootDir, { recursive: true});
}
// FS.mount() is similar to Linux/POSIX mount operation. It basically mounts an external
// filesystem with given format, in given current filesystem directory.
FS.mount(FS.filesystems.NODEFS, { root: localRootDir}, rootDir);
}
};
global.cv = require('./opencv.js')
});
}
function installDOM(){
const dom = new JSDOM();
global.document = dom.window.document;
global.Image = Image;
global.HTMLCanvasElement = Canvas;
global.ImageData = ImageData;
global.HTMLImageElement = Image;
}
@endcode
### Execute it ###
- Save the file as `exampleNodeCanvasData.js`.
- Make sure the files `aarcascade_frontalface_default.xml` and `haarcascade_eye.xml` are present in project's directory. They can be obtained from [OpenCV sources](https://github.com/opencv/opencv/tree/master/data/haarcascades).
- Make sure a sample image file `lena.jpg` exists in project's directory. It should display people's faces for this example to make sense. The following image is known to work:
![image](lena.jpg)
The following command should generate the file `output3.jpg`:
@code{.bash}
node exampleNodeCanvasData.js
@endcode
@@ -91,21 +91,60 @@ Building OpenCV.js from Source
python ./platforms/js/build_js.py build_js --build_test
@endcode
To run tests, launch a local web server in \<build_dir\>/bin folder. For example, node http-server which serves on `localhost:8080`.
Running OpenCV.js Tests
---------------------------------------
Navigate the web browser to `http://localhost:8080/tests.html`, which runs the unit tests automatically.
Remember to launch the build command passing `--build_test` as mentioned previously. This will generate test source code ready to run together with `opencv.js` file in `build_js/bin`
You can also run tests using Node.js.
### Manually in your browser
For example:
@code{.sh}
cd bin
npm install
node tests.js
@endcode
To run tests, launch a local web server in `\<build_dir\>/bin` folder. For example, node http-server which serves on `localhost:8080`.
Navigate the web browser to `http://localhost:8080/tests.html`, which runs the unit tests automatically. Command example:
@code{.sh}
npx http-server build_js/bin
firefox http://localhost:8080/tests.html
@endcode
@note
This snippet and the following require [Node.js](https://nodejs.org) to be installed.
### Headless with Puppeteer
Alternatively tests can run with [GoogleChrome/puppeteer](https://github.com/GoogleChrome/puppeteer#readme) which is a version of Google Chrome that runs in the terminal (useful for Continuos integration like travis CI, etc)
@code{.sh}
cd build_js/bin
npm install
npm install --no-save puppeteer # automatically downloads Chromium package
node run_puppeteer.js
@endcode
@note
Checkout `node run_puppeteer --help` for more options to debug and reporting.
@note
The command `npm install` only needs to be executed once, since installs the tools dependencies; after that they are ready to use.
@note
Use `PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 npm install --no-save puppeteer` to skip automatic downloading of Chromium.
You may specify own Chromium/Chrome binary through `PUPPETEER_EXECUTABLE_PATH=$(which google-chrome)` environment variable.
**BEWARE**: Puppeteer is only guaranteed to work with the bundled Chromium, use at your own risk.
### Using Node.js.
For example:
@code{.sh}
cd build_js/bin
npm install
node tests.js
@endcode
@note If all tests are failed, then consider using Node.js from 8.x version (`lts/carbon` from `nvm`).
@note
It requires `node` installed in your development environment.
-# [optional] To build `opencv.js` with threads optimization, append `--threads` option.
@@ -12,3 +12,7 @@ Introduction to OpenCV.js {#tutorial_js_table_of_contents_setup}
- @subpage tutorial_js_setup
Build OpenCV.js from source
- @subpage tutorial_js_nodejs
Using OpenCV.js In Node.js
+29
View File
@@ -102,6 +102,14 @@
publisher = {Elsevier},
url = {https://www.cs.bgu.ac.il/~icbv161/wiki.files/Readings/1981-Ballard-Generalizing_the_Hough_Transform_to_Detect_Arbitrary_Shapes.pdf}
}
@techreport{blanco2010tutorial,
title = {A tutorial on SE(3) transformation parameterizations and on-manifold optimization},
author = {Blanco, Jose-Luis},
institution = {University of Malaga},
number = {012010},
year = {2010},
url = {http://ingmec.ual.es/~jlblanco/papers/jlblanco2010geometry3D_techrep.pdf}
}
@article{Borgefors86,
author = {Borgefors, Gunilla},
title = {Distance transformations in digital images},
@@ -277,6 +285,12 @@
year = {2013},
url = {http://ethaneade.com/optimization.pdf}
}
@misc{Eade17,
author = {Eade, Ethan},
title = {Lie Groups for 2D and 3D Transformation},
year = {2017},
url = {http://www.ethaneade.com/lie.pdf}
}
@inproceedings{EM11,
author = {Gastal, Eduardo SL and Oliveira, Manuel M},
title = {Domain transform for edge-aware image and video processing},
@@ -397,6 +411,14 @@
year = {1999},
url = {https://pdfs.semanticscholar.org/090d/25f94cb021bdd3400a2f547f989a6a5e07ec.pdf}
}
@article{Gallego2014ACF,
title = {A Compact Formula for the Derivative of a 3-D Rotation in Exponential Coordinates},
author = {Guillermo Gallego and Anthony J. Yezzi},
journal = {Journal of Mathematical Imaging and Vision},
year = {2014},
volume = {51},
pages = {378-384}
}
@article{taubin1991,
abstract = {The author addresses the problem of parametric representation and estimation of complex planar curves in 2-D surfaces in 3-D, and nonplanar space curves in 3-D. Curves and surfaces can be defined either parametrically or implicitly, with the latter representation used here. A planar curve is the set of zeros of a smooth function of two variables <e1>x</e1>-<e1>y</e1>, a surface is the set of zeros of a smooth function of three variables <e1>x</e1>-<e1>y</e1>-<e1>z</e1>, and a space curve is the intersection of two surfaces, which are the set of zeros of two linearly independent smooth functions of three variables <e1>x</e1>-<e1>y</e1>-<e1>z</e1> For example, the surface of a complex object in 3-D can be represented as a subset of a single implicit surface, with similar results for planar and space curves. It is shown how this unified representation can be used for object recognition, object position estimation, and segmentation of objects into meaningful subobjects, that is, the detection of `interest regions' that are more complex than high curvature regions and, hence, more useful as features for object recognition},
author = {Taubin, Gabriel},
@@ -915,6 +937,13 @@
journal = {Retrieved on August},
volume = {6}
}
@article{Sol2018AML,
title = {A micro Lie theory for state estimation in robotics},
author = {Joan Sol{\`a} and J{\'e}r{\'e}mie Deray and Dinesh Atchuthan},
journal = {ArXiv},
year = {2018},
volume={abs/1812.01537}
}
@misc{SteweniusCFS,
author = {Stewenius, Henrik},
title = {Calibrated Fivepoint solver},
@@ -8,13 +8,13 @@ Learn to:
- Access pixel values and modify them
- Access image properties
- Setting Region of Interest (ROI)
- Splitting and Merging images
- Set a Region of Interest (ROI)
- Split and merge images
Almost all the operations in this section is mainly related to Numpy rather than OpenCV. A good
Almost all the operations in this section are mainly related to Numpy rather than OpenCV. A good
knowledge of Numpy is required to write better optimized code with OpenCV.
*( Examples will be shown in Python terminal since most of them are just single line codes )*
*( Examples will be shown in a Python terminal, since most of them are just single lines of code )*
Accessing and Modifying pixel values
------------------------------------
@@ -45,15 +45,15 @@ You can modify the pixel values the same way.
[255 255 255]
@endcode
**warning**
**Warning**
Numpy is a optimized library for fast array calculations. So simply accessing each and every pixel
values and modifying it will be very slow and it is discouraged.
Numpy is an optimized library for fast array calculations. So simply accessing each and every pixel
value and modifying it will be very slow and it is discouraged.
@note The above method is normally used for selecting a region of an array, say the first 5 rows
and last 3 columns. For individual pixel access, the Numpy array methods, array.item() and
array.itemset() are considered better, however they always return a scalar. If you want to access
all B,G,R values, you need to call array.item() separately for all.
array.itemset() are considered better. They always return a scalar, however, so if you want to access
all the B,G,R values, you will need to call array.item() separately for each value.
Better pixel accessing and editing method :
@code{.py}
@@ -70,11 +70,10 @@ Better pixel accessing and editing method :
Accessing Image Properties
--------------------------
Image properties include number of rows, columns and channels, type of image data, number of pixels
etc.
Image properties include number of rows, columns, and channels; type of image data; number of pixels; etc.
The shape of an image is accessed by img.shape. It returns a tuple of number of rows, columns, and channels
(if image is color):
The shape of an image is accessed by img.shape. It returns a tuple of the number of rows, columns, and channels
(if the image is color):
@code{.py}
>>> print( img.shape )
(342, 548, 3)
@@ -95,13 +94,13 @@ uint8
@endcode
@note img.dtype is very important while debugging because a large number of errors in OpenCV-Python
code is caused by invalid datatype.
code are caused by invalid datatype.
Image ROI
---------
Sometimes, you will have to play with certain region of images. For eye detection in images, first
face detection is done all over the image. When a face is obtained, we select the face region alone
Sometimes, you will have to play with certain regions of images. For eye detection in images, first
face detection is done over the entire image. When a face is obtained, we select the face region alone
and search for eyes inside it instead of searching the whole image. It improves accuracy (because eyes
are always on faces :D ) and performance (because we search in a small area).
@@ -118,9 +117,9 @@ Check the results below:
Splitting and Merging Image Channels
------------------------------------
Sometimes you will need to work separately on B,G,R channels of image. In this case, you need
to split the BGR images to single channels. In other cases, you may need to join these individual
channels to a BGR image. You can do it simply by:
Sometimes you will need to work separately on the B,G,R channels of an image. In this case, you need
to split the BGR image into single channels. In other cases, you may need to join these individual
channels to create a BGR image. You can do this simply by:
@code{.py}
>>> b,g,r = cv.split(img)
>>> img = cv.merge((b,g,r))
@@ -129,7 +128,7 @@ Or
@code
>>> b = img[:,:,0]
@endcode
Suppose you want to set all the red pixels to zero, you do not need to split the channels first.
Suppose you want to set all the red pixels to zero - you do not need to split the channels first.
Numpy indexing is faster:
@code{.py}
>>> img[:,:,2] = 0
@@ -137,13 +136,13 @@ Numpy indexing is faster:
**Warning**
cv.split() is a costly operation (in terms of time). So do it only if you need it. Otherwise go
cv.split() is a costly operation (in terms of time). So use it only if necessary. Otherwise go
for Numpy indexing.
Making Borders for Images (Padding)
-----------------------------------
If you want to create a border around the image, something like a photo frame, you can use
If you want to create a border around an image, something like a photo frame, you can use
**cv.copyMakeBorder()**. But it has more applications for convolution operation, zero
padding etc. This function takes following arguments:
@@ -4,21 +4,20 @@ Arithmetic Operations on Images {#tutorial_py_image_arithmetics}
Goal
----
- Learn several arithmetic operations on images like addition, subtraction, bitwise operations
etc.
- You will learn these functions : **cv.add()**, **cv.addWeighted()** etc.
- Learn several arithmetic operations on images, like addition, subtraction, bitwise operations, and etc.
- Learn these functions: **cv.add()**, **cv.addWeighted()**, etc.
Image Addition
--------------
You can add two images by OpenCV function, cv.add() or simply by numpy operation,
res = img1 + img2. Both images should be of same depth and type, or second image can just be a
You can add two images with the OpenCV function, cv.add(), or simply by the numpy operation
res = img1 + img2. Both images should be of same depth and type, or the second image can just be a
scalar value.
@note There is a difference between OpenCV addition and Numpy addition. OpenCV addition is a
saturated operation while Numpy addition is a modulo operation.
For example, consider below sample:
For example, consider the below sample:
@code{.py}
>>> x = np.uint8([250])
>>> y = np.uint8([10])
@@ -29,13 +28,12 @@ For example, consider below sample:
>>> print( x+y ) # 250+10 = 260 % 256 = 4
[4]
@endcode
It will be more visible when you add two images. OpenCV function will provide a better result. So
always better stick to OpenCV functions.
This will be more visible when you add two images. Stick with OpenCV functions, because they will provide a better result.
Image Blending
--------------
This is also image addition, but different weights are given to images so that it gives a feeling of
This is also image addition, but different weights are given to images in order to give a feeling of
blending or transparency. Images are added as per the equation below:
\f[g(x) = (1 - \alpha)f_{0}(x) + \alpha f_{1}(x)\f]
@@ -43,8 +41,8 @@ blending or transparency. Images are added as per the equation below:
By varying \f$\alpha\f$ from \f$0 \rightarrow 1\f$, you can perform a cool transition between one image to
another.
Here I took two images to blend them together. First image is given a weight of 0.7 and second image
is given 0.3. cv.addWeighted() applies following equation on the image.
Here I took two images to blend together. The first image is given a weight of 0.7 and the second image
is given 0.3. cv.addWeighted() applies the following equation to the image:
\f[dst = \alpha \cdot img1 + \beta \cdot img2 + \gamma\f]
@@ -66,14 +64,14 @@ Check the result below:
Bitwise Operations
------------------
This includes bitwise AND, OR, NOT and XOR operations. They will be highly useful while extracting
This includes the bitwise AND, OR, NOT, and XOR operations. They will be highly useful while extracting
any part of the image (as we will see in coming chapters), defining and working with non-rectangular
ROI etc. Below we will see an example on how to change a particular region of an image.
ROI's, and etc. Below we will see an example of how to change a particular region of an image.
I want to put OpenCV logo above an image. If I add two images, it will change color. If I blend it,
I get an transparent effect. But I want it to be opaque. If it was a rectangular region, I could use
ROI as we did in last chapter. But OpenCV logo is a not a rectangular shape. So you can do it with
bitwise operations as below:
I want to put the OpenCV logo above an image. If I add two images, it will change the color. If I blend them,
I get a transparent effect. But I want it to be opaque. If it was a rectangular region, I could use
ROI as we did in the last chapter. But the OpenCV logo is a not a rectangular shape. So you can do it with
bitwise operations as shown below:
@code{.py}
# Load two images
img1 = cv.imread('messi5.jpg')
@@ -81,7 +79,7 @@ img2 = cv.imread('opencv-logo-white.png')
# I want to put logo on top-left corner, So I create a ROI
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols ]
roi = img1[0:rows, 0:cols]
# Now create a mask of logo and create its inverse mask also
img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
@@ -4,28 +4,27 @@ Performance Measurement and Improvement Techniques {#tutorial_py_optimization}
Goal
----
In image processing, since you are dealing with large number of operations per second, it is
mandatory that your code is not only providing the correct solution, but also in the fastest manner.
So in this chapter, you will learn
In image processing, since you are dealing with a large number of operations per second, it is mandatory that your code is not only providing the correct solution, but that it is also providing it in the fastest manner.
So in this chapter, you will learn:
- To measure the performance of your code.
- Some tips to improve the performance of your code.
- You will see these functions : **cv.getTickCount**, **cv.getTickFrequency** etc.
- You will see these functions: **cv.getTickCount**, **cv.getTickFrequency**, etc.
Apart from OpenCV, Python also provides a module **time** which is helpful in measuring the time of
execution. Another module **profile** helps to get detailed report on the code, like how much time
each function in the code took, how many times the function was called etc. But, if you are using
execution. Another module **profile** helps to get a detailed report on the code, like how much time
each function in the code took, how many times the function was called, etc. But, if you are using
IPython, all these features are integrated in an user-friendly manner. We will see some important
ones, and for more details, check links in **Additional Resources** section.
ones, and for more details, check links in the **Additional Resources** section.
Measuring Performance with OpenCV
---------------------------------
**cv.getTickCount** function returns the number of clock-cycles after a reference event (like the
moment machine was switched ON) to the moment this function is called. So if you call it before and
after the function execution, you get number of clock-cycles used to execute a function.
The **cv.getTickCount** function returns the number of clock-cycles after a reference event (like the
moment the machine was switched ON) to the moment this function is called. So if you call it before and
after the function execution, you get the number of clock-cycles used to execute a function.
**cv.getTickFrequency** function returns the frequency of clock-cycles, or the number of
The **cv.getTickFrequency** function returns the frequency of clock-cycles, or the number of
clock-cycles per second. So to find the time of execution in seconds, you can do following:
@code{.py}
e1 = cv.getTickCount()
@@ -33,8 +32,8 @@ e1 = cv.getTickCount()
e2 = cv.getTickCount()
time = (e2 - e1)/ cv.getTickFrequency()
@endcode
We will demonstrate with following example. Following example apply median filtering with a kernel
of odd size ranging from 5 to 49. (Don't worry about what will the result look like, that is not our
We will demonstrate with following example. The following example applies median filtering with kernels
of odd sizes ranging from 5 to 49. (Don't worry about what the result will look like - that is not our
goal):
@code{.py}
img1 = cv.imread('messi5.jpg')
@@ -48,16 +47,16 @@ print( t )
# Result I got is 0.521107655 seconds
@endcode
@note You can do the same with time module. Instead of cv.getTickCount, use time.time() function.
Then take the difference of two times.
@note You can do the same thing with the time module. Instead of cv.getTickCount, use the time.time() function.
Then take the difference of the two times.
Default Optimization in OpenCV
------------------------------
Many of the OpenCV functions are optimized using SSE2, AVX etc. It contains unoptimized code also.
Many of the OpenCV functions are optimized using SSE2, AVX, etc. It contains the unoptimized code also.
So if our system support these features, we should exploit them (almost all modern day processors
support them). It is enabled by default while compiling. So OpenCV runs the optimized code if it is
enabled, else it runs the unoptimized code. You can use **cv.useOptimized()** to check if it is
enabled, otherwise it runs the unoptimized code. You can use **cv.useOptimized()** to check if it is
enabled/disabled and **cv.setUseOptimized()** to enable/disable it. Let's see a simple example.
@code{.py}
# check if optimization is enabled
@@ -76,8 +75,8 @@ Out[8]: False
In [9]: %timeit res = cv.medianBlur(img,49)
10 loops, best of 3: 64.1 ms per loop
@endcode
See, optimized median filtering is \~2x faster than unoptimized version. If you check its source,
you can see median filtering is SIMD optimized. So you can use this to enable optimization at the
As you can see, optimized median filtering is \~2x faster than the unoptimized version. If you check its source,
you can see that median filtering is SIMD optimized. So you can use this to enable optimization at the
top of your code (remember it is enabled by default).
Measuring Performance in IPython
@@ -85,10 +84,10 @@ Measuring Performance in IPython
Sometimes you may need to compare the performance of two similar operations. IPython gives you a
magic command %timeit to perform this. It runs the code several times to get more accurate results.
Once again, they are suitable to measure single line codes.
Once again, it is suitable to measuring single lines of code.
For example, do you know which of the following addition operation is better, x = 5; y = x\*\*2,
x = 5; y = x\*x, x = np.uint8([5]); y = x\*x or y = np.square(x) ? We will find it with %timeit in
For example, do you know which of the following addition operations is better, x = 5; y = x\*\*2,
x = 5; y = x\*x, x = np.uint8([5]); y = x\*x, or y = np.square(x)? We will find out with %timeit in the
IPython shell.
@code{.py}
In [10]: x = 5
@@ -108,15 +107,15 @@ In [19]: %timeit y=np.square(z)
1000000 loops, best of 3: 1.16 us per loop
@endcode
You can see that, x = 5 ; y = x\*x is fastest and it is around 20x faster compared to Numpy. If you
consider the array creation also, it may reach upto 100x faster. Cool, right? *(Numpy devs are
consider the array creation also, it may reach up to 100x faster. Cool, right? *(Numpy devs are
working on this issue)*
@note Python scalar operations are faster than Numpy scalar operations. So for operations including
one or two elements, Python scalar is better than Numpy arrays. Numpy takes advantage when size of
array is a little bit bigger.
one or two elements, Python scalar is better than Numpy arrays. Numpy has the advantage when the size of
the array is a little bit bigger.
We will try one more example. This time, we will compare the performance of **cv.countNonZero()**
and **np.count_nonzero()** for same image.
and **np.count_nonzero()** for the same image.
@code{.py}
In [35]: %timeit z = cv.countNonZero(img)
@@ -125,7 +124,7 @@ In [35]: %timeit z = cv.countNonZero(img)
In [36]: %timeit z = np.count_nonzero(img)
1000 loops, best of 3: 370 us per loop
@endcode
See, OpenCV function is nearly 25x faster than Numpy function.
See, the OpenCV function is nearly 25x faster than the Numpy function.
@note Normally, OpenCV functions are faster than Numpy functions. So for same operation, OpenCV
functions are preferred. But, there can be exceptions, especially when Numpy works with views
@@ -134,8 +133,8 @@ instead of copies.
More IPython magic commands
---------------------------
There are several other magic commands to measure the performance, profiling, line profiling, memory
measurement etc. They all are well documented. So only links to those docs are provided here.
There are several other magic commands to measure performance, profiling, line profiling, memory
measurement, and etc. They all are well documented. So only links to those docs are provided here.
Interested readers are recommended to try them out.
Performance Optimization Techniques
@@ -143,19 +142,18 @@ Performance Optimization Techniques
There are several techniques and coding methods to exploit maximum performance of Python and Numpy.
Only relevant ones are noted here and links are given to important sources. The main thing to be
noted here is that, first try to implement the algorithm in a simple manner. Once it is working,
profile it, find the bottlenecks and optimize them.
noted here is, first try to implement the algorithm in a simple manner. Once it is working,
profile it, find the bottlenecks, and optimize them.
-# Avoid using loops in Python as far as possible, especially double/triple loops etc. They are
-# Avoid using loops in Python as much as possible, especially double/triple loops etc. They are
inherently slow.
2. Vectorize the algorithm/code to the maximum possible extent because Numpy and OpenCV are
2. Vectorize the algorithm/code to the maximum extent possible, because Numpy and OpenCV are
optimized for vector operations.
3. Exploit the cache coherence.
4. Never make copies of array unless it is needed. Try to use views instead. Array copying is a
4. Never make copies of an array unless it is necessary. Try to use views instead. Array copying is a
costly operation.
Even after doing all these operations, if your code is still slow, or use of large loops are
inevitable, use additional libraries like Cython to make it faster.
If your code is still slow after doing all of these operations, or if the use of large loops is inevitable, use additional libraries like Cython to make it faster.
Additional Resources
--------------------
@@ -43,11 +43,19 @@ points than for SURF points.
In short, BRIEF is a faster method feature descriptor calculation and matching. It also provides
high recognition rate unless there is large in-plane rotation.
STAR(CenSurE) in OpenCV
------
STAR is a feature detector derived from CenSurE.
Unlike CenSurE however, which uses polygons like squares, hexagons and octagons to approach a circle,
Star emulates a circle with 2 overlapping squares: 1 upright and 1 45-degree rotated. These polygons are bi-level.
They can be seen as polygons with thick borders. The borders and the enclosed area have weights of opposing signs.
This has better computational characteristics than other scale-space detectors and it is capable of real-time implementation.
In contrast to SIFT and SURF, which find extrema at sub-sampled pixels that compromises accuracy at larger scales,
CenSurE creates a feature vector using full spatial resolution at all scales in the pyramid.
BRIEF in OpenCV
---------------
Below code shows the computation of BRIEF descriptors with the help of CenSurE detector. (CenSurE
detector is called STAR detector in OpenCV)
Below code shows the computation of BRIEF descriptors with the help of CenSurE detector.
note, that you need [opencv contrib](https://github.com/opencv/opencv_contrib)) to use this.
@code{.py}
@@ -4,21 +4,21 @@ Gui Features in OpenCV {#tutorial_py_table_of_contents_gui}
- @subpage tutorial_py_image_display
Learn to load an
image, display it and save it back
image, display it, and save it back
- @subpage tutorial_py_video_display
Learn to play videos,
capture videos from Camera and write it as a video
capture videos from a camera, and write videos
- @subpage tutorial_py_drawing_functions
Learn to draw lines,
rectangles, ellipses, circles etc with OpenCV
rectangles, ellipses, circles, etc with OpenCV
- @subpage tutorial_py_mouse_handling
Draw stuffs with your
Draw stuff with your
mouse
- @subpage tutorial_py_trackbar
@@ -14,9 +14,9 @@ Here we will create a simple application which shows the color you specify. You
shows the color and three trackbars to specify each of B,G,R colors. You slide the trackbar and
correspondingly window color changes. By default, initial color will be set to Black.
For cv.getTrackbarPos() function, first argument is the trackbar name, second one is the window
For cv.createTrackbar() function, first argument is the trackbar name, second one is the window
name to which it is attached, third argument is the default value, fourth one is the maximum value
and fifth one is the callback function which is executed everytime trackbar value changes. The
and fifth one is the callback function which is executed every time trackbar value changes. The
callback function always has a default argument which is the trackbar position. In our case,
function does nothing, so we simply pass.
@@ -4,19 +4,19 @@ Getting Started with Videos {#tutorial_py_video_display}
Goal
----
- Learn to read video, display video and save video.
- Learn to capture from Camera and display it.
- Learn to read video, display video, and save video.
- Learn to capture video from a camera and display it.
- You will learn these functions : **cv.VideoCapture()**, **cv.VideoWriter()**
Capture Video from Camera
-------------------------
Often, we have to capture live stream with camera. OpenCV provides a very simple interface to this.
Let's capture a video from the camera (I am using the in-built webcam of my laptop), convert it into
Often, we have to capture live stream with a camera. OpenCV provides a very simple interface to do this.
Let's capture a video from the camera (I am using the built-in webcam on my laptop), convert it into
grayscale video and display it. Just a simple task to get started.
To capture a video, you need to create a **VideoCapture** object. Its argument can be either the
device index or the name of a video file. Device index is just the number to specify which camera.
device index or the name of a video file. A device index is just the number to specify which camera.
Normally one camera will be connected (as in my case). So I simply pass 0 (or -1). You can select
the second camera by passing 1 and so on. After that, you can capture frame-by-frame. But at the
end, don't forget to release the capture.
@@ -46,16 +46,16 @@ while True:
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()@endcode
`cap.read()` returns a bool (`True`/`False`). If frame is read correctly, it will be `True`. So you can
check end of the video by checking this return value.
`cap.read()` returns a bool (`True`/`False`). If the frame is read correctly, it will be `True`. So you can
check for the end of the video by checking this returned value.
Sometimes, cap may not have initialized the capture. In that case, this code shows error. You can
Sometimes, cap may not have initialized the capture. In that case, this code shows an error. You can
check whether it is initialized or not by the method **cap.isOpened()**. If it is `True`, OK.
Otherwise open it using **cap.open()**.
You can also access some of the features of this video using **cap.get(propId)** method where propId
is a number from 0 to 18. Each number denotes a property of the video (if it is applicable to that
video) and full details can be seen here: cv::VideoCapture::get().
video). Full details can be seen here: cv::VideoCapture::get().
Some of these values can be modified using **cap.set(propId, value)**. Value is the new value you
want.
@@ -63,13 +63,13 @@ For example, I can check the frame width and height by `cap.get(cv.CAP_PROP_FRAM
640x480 by default. But I want to modify it to 320x240. Just use `ret = cap.set(cv.CAP_PROP_FRAME_WIDTH,320)` and
`ret = cap.set(cv.CAP_PROP_FRAME_HEIGHT,240)`.
@note If you are getting error, make sure camera is working fine using any other camera application
@note If you are getting an error, make sure your camera is working fine using any other camera application
(like Cheese in Linux).
Playing Video from file
-----------------------
It is same as capturing from Camera, just change camera index with video file name. Also while
Playing video from file is the same as capturing it from camera, just change the camera index to a video file name. Also while
displaying the frame, use appropriate time for `cv.waitKey()`. If it is too less, video will be very
fast and if it is too high, video will be slow (Well, that is how you can display videos in slow
motion). 25 milliseconds will be OK in normal cases.
@@ -96,23 +96,23 @@ cap.release()
cv.destroyAllWindows()
@endcode
@note Make sure proper versions of ffmpeg or gstreamer is installed. Sometimes, it is a headache to
work with Video Capture mostly due to wrong installation of ffmpeg/gstreamer.
@note Make sure a proper version of ffmpeg or gstreamer is installed. Sometimes it is a headache to
work with video capture, mostly due to wrong installation of ffmpeg/gstreamer.
Saving a Video
--------------
So we capture a video, process it frame-by-frame and we want to save that video. For images, it is
very simple, just use `cv.imwrite()`. Here a little more work is required.
So we capture a video and process it frame-by-frame, and we want to save that video. For images, it is
very simple: just use `cv.imwrite()`. Here, a little more work is required.
This time we create a **VideoWriter** object. We should specify the output file name (eg:
output.avi). Then we should specify the **FourCC** code (details in next paragraph). Then number of
frames per second (fps) and frame size should be passed. And last one is **isColor** flag. If it is
`True`, encoder expect color frame, otherwise it works with grayscale frame.
frames per second (fps) and frame size should be passed. And the last one is the **isColor** flag. If it is
`True`, the encoder expect color frame, otherwise it works with grayscale frame.
[FourCC](http://en.wikipedia.org/wiki/FourCC) is a 4-byte code used to specify the video codec. The
list of available codes can be found in [fourcc.org](http://www.fourcc.org/codecs.php). It is
platform dependent. Following codecs works fine for me.
platform dependent. The following codecs work fine for me.
- In Fedora: DIVX, XVID, MJPG, X264, WMV1, WMV2. (XVID is more preferable. MJPG results in high
size video. X264 gives very small size video)
@@ -122,7 +122,7 @@ platform dependent. Following codecs works fine for me.
FourCC code is passed as `cv.VideoWriter_fourcc('M','J','P','G')` or
`cv.VideoWriter_fourcc(*'MJPG')` for MJPG.
Below code capture from a Camera, flip every frame in vertical direction and saves it.
The below code captures from a camera, flips every frame in the vertical direction, and saves the video.
@code{.py}
import numpy as np
import cv2 as cv
@@ -5,44 +5,44 @@ Goal
----
- In this tutorial, you will learn how to convert images from one color-space to another, like
BGR \f$\leftrightarrow\f$ Gray, BGR \f$\leftrightarrow\f$ HSV etc.
- In addition to that, we will create an application which extracts a colored object in a video
- You will learn following functions : **cv.cvtColor()**, **cv.inRange()** etc.
BGR \f$\leftrightarrow\f$ Gray, BGR \f$\leftrightarrow\f$ HSV, etc.
- In addition to that, we will create an application to extract a colored object in a video
- You will learn the following functions: **cv.cvtColor()**, **cv.inRange()**, etc.
Changing Color-space
--------------------
There are more than 150 color-space conversion methods available in OpenCV. But we will look into
only two which are most widely used ones, BGR \f$\leftrightarrow\f$ Gray and BGR \f$\leftrightarrow\f$ HSV.
only two, which are most widely used ones: BGR \f$\leftrightarrow\f$ Gray and BGR \f$\leftrightarrow\f$ HSV.
For color conversion, we use the function cv.cvtColor(input_image, flag) where flag determines the
type of conversion.
For BGR \f$\rightarrow\f$ Gray conversion we use the flags cv.COLOR_BGR2GRAY. Similarly for BGR
For BGR \f$\rightarrow\f$ Gray conversion, we use the flag cv.COLOR_BGR2GRAY. Similarly for BGR
\f$\rightarrow\f$ HSV, we use the flag cv.COLOR_BGR2HSV. To get other flags, just run following
commands in your Python terminal :
commands in your Python terminal:
@code{.py}
>>> import cv2 as cv
>>> flags = [i for i in dir(cv) if i.startswith('COLOR_')]
>>> print( flags )
@endcode
@note For HSV, Hue range is [0,179], Saturation range is [0,255] and Value range is [0,255].
@note For HSV, hue range is [0,179], saturation range is [0,255], and value range is [0,255].
Different software use different scales. So if you are comparing OpenCV values with them, you need
to normalize these ranges.
Object Tracking
---------------
Now we know how to convert BGR image to HSV, we can use this to extract a colored object. In HSV, it
is more easier to represent a color than in BGR color-space. In our application, we will try to extract
Now that we know how to convert a BGR image to HSV, we can use this to extract a colored object. In HSV, it
is easier to represent a color than in BGR color-space. In our application, we will try to extract
a blue colored object. So here is the method:
- Take each frame of the video
- Convert from BGR to HSV color-space
- We threshold the HSV image for a range of blue color
- Now extract the blue object alone, we can do whatever on that image we want.
- Now extract the blue object alone, we can do whatever we want on that image.
Below is the code which are commented in detail :
Below is the code which is commented in detail:
@code{.py}
import cv2 as cv
import numpy as np
@@ -80,18 +80,18 @@ Below image shows tracking of the blue object:
![image](images/frame.jpg)
@note There are some noises in the image. We will see how to remove them in later chapters.
@note There is some noise in the image. We will see how to remove it in later chapters.
@note This is the simplest method in object tracking. Once you learn functions of contours, you can
do plenty of things like find centroid of this object and use it to track the object, draw diagrams
just by moving your hand in front of camera and many other funny stuffs.
do plenty of things like find the centroid of an object and use it to track the object, draw diagrams
just by moving your hand in front of a camera, and other fun stuff.
How to find HSV values to track?
--------------------------------
This is a common question found in [stackoverflow.com](http://www.stackoverflow.com). It is very simple and
you can use the same function, cv.cvtColor(). Instead of passing an image, you just pass the BGR
values you want. For example, to find the HSV value of Green, try following commands in Python
values you want. For example, to find the HSV value of Green, try the following commands in a Python
terminal:
@code{.py}
>>> green = np.uint8([[[0,255,0 ]]])
@@ -99,7 +99,7 @@ terminal:
>>> print( hsv_green )
[[[ 60 255 255]]]
@endcode
Now you take [H-10, 100,100] and [H+10, 255, 255] as lower bound and upper bound respectively. Apart
Now you take [H-10, 100,100] and [H+10, 255, 255] as the lower bound and upper bound respectively. Apart
from this method, you can use any image editing tools like GIMP or any online converters to find
these values, but don't forget to adjust the HSV ranges.
@@ -109,5 +109,5 @@ Additional Resources
Exercises
---------
-# Try to find a way to extract more than one colored objects, for eg, extract red, blue, green
objects simultaneously.
-# Try to find a way to extract more than one colored object, for example, extract red, blue, and green
objects simultaneously.
@@ -5,24 +5,24 @@ Goals
-----
Learn to:
- Blur the images with various low pass filters
- Blur images with various low pass filters
- Apply custom-made filters to images (2D convolution)
2D Convolution ( Image Filtering )
----------------------------------
As in one-dimensional signals, images also can be filtered with various low-pass filters(LPF),
high-pass filters(HPF) etc. LPF helps in removing noises, blurring the images etc. HPF filters helps
in finding edges in the images.
As in one-dimensional signals, images also can be filtered with various low-pass filters (LPF),
high-pass filters (HPF), etc. LPF helps in removing noise, blurring images, etc. HPF filters help
in finding edges in images.
OpenCV provides a function **cv.filter2D()** to convolve a kernel with an image. As an example, we
will try an averaging filter on an image. A 5x5 averaging filter kernel will look like below:
will try an averaging filter on an image. A 5x5 averaging filter kernel will look like the below:
\f[K = \frac{1}{25} \begin{bmatrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \end{bmatrix}\f]
Operation is like this: keep this kernel above a pixel, add all the 25 pixels below this kernel,
take its average and replace the central pixel with the new average value. It continues this
operation for all the pixels in the image. Try this code and check the result:
The operation works like this: keep this kernel above a pixel, add all the 25 pixels below this kernel,
take the average, and replace the central pixel with the new average value. This operation is continued
for all the pixels in the image. Try this code and check the result:
@code{.py}
import numpy as np
import cv2 as cv
@@ -47,20 +47,20 @@ Image Blurring (Image Smoothing)
--------------------------------
Image blurring is achieved by convolving the image with a low-pass filter kernel. It is useful for
removing noises. It actually removes high frequency content (eg: noise, edges) from the image. So
edges are blurred a little bit in this operation. (Well, there are blurring techniques which doesn't
blur the edges too). OpenCV provides mainly four types of blurring techniques.
removing noise. It actually removes high frequency content (eg: noise, edges) from the image. So
edges are blurred a little bit in this operation (there are also blurring techniques which don't
blur the edges). OpenCV provides four main types of blurring techniques.
### 1. Averaging
This is done by convolving image with a normalized box filter. It simply takes the average of all
the pixels under kernel area and replace the central element. This is done by the function
This is done by convolving an image with a normalized box filter. It simply takes the average of all
the pixels under the kernel area and replaces the central element. This is done by the function
**cv.blur()** or **cv.boxFilter()**. Check the docs for more details about the kernel. We should
specify the width and height of kernel. A 3x3 normalized box filter would look like below:
specify the width and height of the kernel. A 3x3 normalized box filter would look like the below:
\f[K = \frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}\f]
@note If you don't want to use normalized box filter, use **cv.boxFilter()**. Pass an argument
@note If you don't want to use a normalized box filter, use **cv.boxFilter()**. Pass an argument
normalize=False to the function.
Check a sample demo below with a kernel of 5x5 size:
@@ -85,12 +85,12 @@ Result:
### 2. Gaussian Blurring
In this, instead of box filter, gaussian kernel is used. It is done with the function,
**cv.GaussianBlur()**. We should specify the width and height of kernel which should be positive
and odd. We also should specify the standard deviation in X and Y direction, sigmaX and sigmaY
respectively. If only sigmaX is specified, sigmaY is taken as same as sigmaX. If both are given as
zeros, they are calculated from kernel size. Gaussian blurring is highly effective in removing
gaussian noise from the image.
In this method, instead of a box filter, a Gaussian kernel is used. It is done with the function,
**cv.GaussianBlur()**. We should specify the width and height of the kernel which should be positive
and odd. We also should specify the standard deviation in the X and Y directions, sigmaX and sigmaY
respectively. If only sigmaX is specified, sigmaY is taken as the same as sigmaX. If both are given as
zeros, they are calculated from the kernel size. Gaussian blurring is highly effective in removing
Gaussian noise from an image.
If you want, you can create a Gaussian kernel with the function, **cv.getGaussianKernel()**.
@@ -104,14 +104,14 @@ Result:
### 3. Median Blurring
Here, the function **cv.medianBlur()** takes median of all the pixels under kernel area and central
Here, the function **cv.medianBlur()** takes the median of all the pixels under the kernel area and the central
element is replaced with this median value. This is highly effective against salt-and-pepper noise
in the images. Interesting thing is that, in the above filters, central element is a newly
in an image. Interestingly, in the above filters, the central element is a newly
calculated value which may be a pixel value in the image or a new value. But in median blurring,
central element is always replaced by some pixel value in the image. It reduces the noise
the central element is always replaced by some pixel value in the image. It reduces the noise
effectively. Its kernel size should be a positive odd integer.
In this demo, I added a 50% noise to our original image and applied median blur. Check the result:
In this demo, I added a 50% noise to our original image and applied median blurring. Check the result:
@code{.py}
median = cv.medianBlur(img,5)
@endcode
@@ -122,19 +122,19 @@ Result:
### 4. Bilateral Filtering
**cv.bilateralFilter()** is highly effective in noise removal while keeping edges sharp. But the
operation is slower compared to other filters. We already saw that gaussian filter takes the a
neighbourhood around the pixel and find its gaussian weighted average. This gaussian filter is a
operation is slower compared to other filters. We already saw that a Gaussian filter takes the
neighbourhood around the pixel and finds its Gaussian weighted average. This Gaussian filter is a
function of space alone, that is, nearby pixels are considered while filtering. It doesn't consider
whether pixels have almost same intensity. It doesn't consider whether pixel is an edge pixel or
whether pixels have almost the same intensity. It doesn't consider whether a pixel is an edge pixel or
not. So it blurs the edges also, which we don't want to do.
Bilateral filter also takes a gaussian filter in space, but one more gaussian filter which is a
function of pixel difference. Gaussian function of space make sure only nearby pixels are considered
for blurring while gaussian function of intensity difference make sure only those pixels with
similar intensity to central pixel is considered for blurring. So it preserves the edges since
Bilateral filtering also takes a Gaussian filter in space, but one more Gaussian filter which is a
function of pixel difference. The Gaussian function of space makes sure that only nearby pixels are considered
for blurring, while the Gaussian function of intensity difference makes sure that only those pixels with
similar intensities to the central pixel are considered for blurring. So it preserves the edges since
pixels at edges will have large intensity variation.
Below samples shows use bilateral filter (For details on arguments, visit docs).
The below sample shows use of a bilateral filter (For details on arguments, visit docs).
@code{.py}
blur = cv.bilateralFilter(img,9,75,75)
@endcode
@@ -142,7 +142,7 @@ Result:
![image](images/bilateral.jpg)
See, the texture on the surface is gone, but edges are still preserved.
See, the texture on the surface is gone, but the edges are still preserved.
Additional Resources
--------------------
@@ -4,7 +4,7 @@ Geometric Transformations of Images {#tutorial_py_geometric_transformations}
Goals
-----
- Learn to apply different geometric transformation to images like translation, rotation, affine
- Learn to apply different geometric transformations to images, like translation, rotation, affine
transformation etc.
- You will see these functions: **cv.getPerspectiveTransform**
@@ -12,7 +12,7 @@ Transformations
---------------
OpenCV provides two transformation functions, **cv.warpAffine** and **cv.warpPerspective**, with
which you can have all kinds of transformations. **cv.warpAffine** takes a 2x3 transformation
which you can perform all kinds of transformations. **cv.warpAffine** takes a 2x3 transformation
matrix while **cv.warpPerspective** takes a 3x3 transformation matrix as input.
### Scaling
@@ -21,8 +21,8 @@ Scaling is just resizing of the image. OpenCV comes with a function **cv.resize(
purpose. The size of the image can be specified manually, or you can specify the scaling factor.
Different interpolation methods are used. Preferable interpolation methods are **cv.INTER_AREA**
for shrinking and **cv.INTER_CUBIC** (slow) & **cv.INTER_LINEAR** for zooming. By default,
interpolation method used is **cv.INTER_LINEAR** for all resizing purposes. You can resize an
input image either of following methods:
the interpolation method **cv.INTER_LINEAR** is used for all resizing purposes. You can resize an
input image with either of following methods:
@code{.py}
import numpy as np
import cv2 as cv
@@ -38,13 +38,13 @@ res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)
@endcode
### Translation
Translation is the shifting of object's location. If you know the shift in (x,y) direction, let it
Translation is the shifting of an object's location. If you know the shift in the (x,y) direction and let it
be \f$(t_x,t_y)\f$, you can create the transformation matrix \f$\textbf{M}\f$ as follows:
\f[M = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \end{bmatrix}\f]
You can take make it into a Numpy array of type np.float32 and pass it into **cv.warpAffine()**
function. See below example for a shift of (100,50):
You can take make it into a Numpy array of type np.float32 and pass it into the **cv.warpAffine()**
function. See the below example for a shift of (100,50):
@code{.py}
import numpy as np
import cv2 as cv
@@ -61,7 +61,7 @@ cv.destroyAllWindows()
@endcode
**warning**
Third argument of the **cv.warpAffine()** function is the size of the output image, which should
The third argument of the **cv.warpAffine()** function is the size of the output image, which should
be in the form of **(width, height)**. Remember width = number of columns, and height = number of
rows.
@@ -76,7 +76,7 @@ Rotation of an image for an angle \f$\theta\f$ is achieved by the transformation
\f[M = \begin{bmatrix} cos\theta & -sin\theta \\ sin\theta & cos\theta \end{bmatrix}\f]
But OpenCV provides scaled rotation with adjustable center of rotation so that you can rotate at any
location you prefer. Modified transformation matrix is given by
location you prefer. The modified transformation matrix is given by
\f[\begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot center.x - \beta \cdot center.y \\ - \beta & \alpha & \beta \cdot center.x + (1- \alpha ) \cdot center.y \end{bmatrix}\f]
@@ -84,7 +84,7 @@ where:
\f[\begin{array}{l} \alpha = scale \cdot \cos \theta , \\ \beta = scale \cdot \sin \theta \end{array}\f]
To find this transformation matrix, OpenCV provides a function, **cv.getRotationMatrix2D**. Check
To find this transformation matrix, OpenCV provides a function, **cv.getRotationMatrix2D**. Check out the
below example which rotates the image by 90 degree with respect to center without any scaling.
@code{.py}
img = cv.imread('messi5.jpg',0)
@@ -101,11 +101,11 @@ See the result:
### Affine Transformation
In affine transformation, all parallel lines in the original image will still be parallel in the
output image. To find the transformation matrix, we need three points from input image and their
corresponding locations in output image. Then **cv.getAffineTransform** will create a 2x3 matrix
output image. To find the transformation matrix, we need three points from the input image and their
corresponding locations in the output image. Then **cv.getAffineTransform** will create a 2x3 matrix
which is to be passed to **cv.warpAffine**.
Check below example, and also look at the points I selected (which are marked in Green color):
Check the below example, and also look at the points I selected (which are marked in green color):
@code{.py}
img = cv.imread('drawing.png')
rows,cols,ch = img.shape
@@ -130,7 +130,7 @@ See the result:
For perspective transformation, you need a 3x3 transformation matrix. Straight lines will remain
straight even after the transformation. To find this transformation matrix, you need 4 points on the
input image and corresponding points on the output image. Among these 4 points, 3 of them should not
be collinear. Then transformation matrix can be found by the function
be collinear. Then the transformation matrix can be found by the function
**cv.getPerspectiveTransform**. Then apply **cv.warpPerspective** with this 3x3 transformation
matrix.
@@ -4,13 +4,13 @@ Image Thresholding {#tutorial_py_thresholding}
Goal
----
- In this tutorial, you will learn Simple thresholding, Adaptive thresholding and Otsu's thresholding.
- In this tutorial, you will learn simple thresholding, adaptive thresholding and Otsu's thresholding.
- You will learn the functions **cv.threshold** and **cv.adaptiveThreshold**.
Simple Thresholding
-------------------
Here, the matter is straight forward. For every pixel, the same threshold value is applied.
Here, the matter is straight-forward. For every pixel, the same threshold value is applied.
If the pixel value is smaller than the threshold, it is set to 0, otherwise it is set to a maximum value.
The function **cv.threshold** is used to apply the thresholding.
The first argument is the source image, which **should be a grayscale image**.
@@ -65,11 +65,11 @@ Adaptive Thresholding
In the previous section, we used one global value as a threshold.
But this might not be good in all cases, e.g. if an image has different lighting conditions in different areas.
In that case, adaptive thresholding thresholding can help.
In that case, adaptive thresholding can help.
Here, the algorithm determines the threshold for a pixel based on a small region around it.
So we get different thresholds for different regions of the same image which gives better results for images with varying illumination.
Additionally to the parameters described above, the method cv.adaptiveThreshold three input parameters:
In addition to the parameters described above, the method cv.adaptiveThreshold takes three input parameters:
The **adaptiveMethod** decides how the threshold value is calculated:
- cv.ADAPTIVE_THRESH_MEAN_C: The threshold value is the mean of the neighbourhood area minus the constant **C**.
@@ -168,8 +168,8 @@ Result:
### How does Otsu's Binarization work?
This section demonstrates a Python implementation of Otsu's binarization to show how it works
actually. If you are not interested, you can skip this.
This section demonstrates a Python implementation of Otsu's binarization to show how it actually
works. If you are not interested, you can skip this.
Since we are working with bimodal images, Otsu's algorithm tries to find a threshold value (t) which
minimizes the **weighted within-class variance** given by the relation:
@@ -54,7 +54,7 @@ print( accuracy )
@endcode
So our basic OCR app is ready. This particular example gave me an accuracy of 91%. One option
improve accuracy is to add more data for training, especially the wrong ones. So instead of finding
this training data everytime I start application, I better save it, so that next time, I directly
this training data every time I start application, I better save it, so that next time, I directly
read this data from a file and start classification. You can do it with the help of some Numpy
functions like np.savetxt, np.savez, np.load etc. Please check their docs for more details.
@code{.py}
@@ -150,7 +150,7 @@ We observe that @ref cv::Mat::zeros returns a Matlab-style zero initializer base
Notice the following (**C++ code only**):
- To access each pixel in the images we are using this syntax: *image.at\<Vec3b\>(y,x)[c]*
where *y* is the row, *x* is the column and *c* is R, G or B (0, 1 or 2).
where *y* is the row, *x* is the column and *c* is B, G or R (0, 1 or 2).
- Since the operation \f$\alpha \cdot p(i,j) + \beta\f$ can give values out of range or not
integers (if \f$\alpha\f$ is float), we use cv::saturate_cast to make sure the
values are valid.
@@ -220,12 +220,12 @@ gamma correction.
### Brightness and contrast adjustments
Increasing (/ decreasing) the \f$\beta\f$ value will add (/ subtract) a constant value to every pixel. Pixel values outside of the [0 ; 255]
range will be saturated (i.e. a pixel value higher (/ lesser) than 255 (/ 0) will be clamp to 255 (/ 0)).
range will be saturated (i.e. a pixel value higher (/ lesser) than 255 (/ 0) will be clamped to 255 (/ 0)).
![In light gray, histogram of the original image, in dark gray when brightness = 80 in Gimp](images/Basic_Linear_Transform_Tutorial_hist_beta.png)
The histogram represents for each color level the number of pixels with that color level. A dark image will have many pixels with
low color value and thus the histogram will present a peak in his left part. When adding a constant bias, the histogram is shifted to the
low color value and thus the histogram will present a peak in its left part. When adding a constant bias, the histogram is shifted to the
right as we have added a constant bias to all the pixels.
The \f$\alpha\f$ parameter will modify how the levels spread. If \f$ \alpha < 1 \f$, the color levels will be compressed and the result
@@ -10,7 +10,7 @@ Goal
We'll seek answers for the following questions:
- How to go through each and every pixel of an image?
- How is OpenCV matrix values stored?
- How are OpenCV matrix values stored?
- How to measure the performance of our algorithm?
- What are lookup tables and why use them?
@@ -45,13 +45,13 @@ operation. In case of the *uchar* system this is 256 to be exact.
Therefore, for larger images it would be wise to calculate all possible values beforehand and during
the assignment just make the assignment, by using a lookup table. Lookup tables are simple arrays
(having one or more dimensions) that for a given input value variation holds the final output value.
Its strength lies that we do not need to make the calculation, we just need to read the result.
Its strength is that we do not need to make the calculation, we just need to read the result.
Our test case program (and the sample presented here) will do the following: read in a console line
argument image (that may be either color or gray scale - console line argument too) and apply the
reduction with the given console line argument integer value. In OpenCV, at the moment there are
Our test case program (and the code sample below) will do the following: read in an image passed
as a command line argument (it may be either color or grayscale) and apply the reduction
with the given command line argument integer value. In OpenCV, at the moment there are
three major ways of going through an image pixel by pixel. To make things a little more interesting
will make the scanning for each image using all of these methods, and print out how long it took.
we'll make the scanning of the image using each of these methods, and print out how long it took.
You can download the full source code [here
](https://github.com/opencv/opencv/tree/3.4/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp) or look it up in
@@ -59,7 +59,7 @@ the samples directory of OpenCV at the cpp tutorial code for the core section. I
@code{.bash}
how_to_scan_images imageName.jpg intValueToReduce [G]
@endcode
The final argument is optional. If given the image will be loaded in gray scale format, otherwise
The final argument is optional. If given the image will be loaded in grayscale format, otherwise
the BGR color space is used. The first thing is to calculate the lookup table.
@snippet how_to_scan_images.cpp dividewith
@@ -71,8 +71,8 @@ No OpenCV specific stuff here.
Another issue is how do we measure time? Well OpenCV offers two simple functions to achieve this
cv::getTickCount() and cv::getTickFrequency() . The first returns the number of ticks of
your systems CPU from a certain event (like since you booted your system). The second returns how
many times your CPU emits a tick during a second. So to measure in seconds the number of time
elapsed between two operations is easy as:
many times your CPU emits a tick during a second. So, measuring amount of time elapsed between
two operations is as easy as:
@code{.cpp}
double t = (double)getTickCount();
// do something ...
@@ -85,8 +85,8 @@ How is the image matrix stored in memory?
-----------------------------------------
As you could already read in my @ref tutorial_mat_the_basic_image_container tutorial the size of the matrix
depends on the color system used. More accurately, it depends from the number of channels used. In
case of a gray scale image we have something like:
depends on the color system used. More accurately, it depends on the number of channels used. In
case of a grayscale image we have something like:
![](tutorial_how_matrix_stored_1.png)
@@ -117,12 +117,12 @@ three channels so we need to pass through three times more items in each row.
There's another way of this. The *data* data member of a *Mat* object returns the pointer to the
first row, first column. If this pointer is null you have no valid input in that object. Checking
this is the simplest method to check if your image loading was a success. In case the storage is
continuous we can use this to go through the whole data pointer. In case of a gray scale image this
continuous we can use this to go through the whole data pointer. In case of a grayscale image this
would look like:
@code{.cpp}
uchar* p = I.data;
for( unsigned int i =0; i < ncol*nrows; ++i)
for( unsigned int i = 0; i < ncol*nrows; ++i)
*p++ = table[*p];
@endcode
You would get the same result. However, this code is a lot harder to read later on. It gets even
@@ -135,7 +135,7 @@ The iterator (safe) method
In case of the efficient way making sure that you pass through the right amount of *uchar* fields
and to skip the gaps that may occur between the rows was your responsibility. The iterator method is
considered a safer way as it takes over these tasks from the user. All you need to do is ask the
considered a safer way as it takes over these tasks from the user. All you need to do is to ask the
begin and the end of the image matrix and then just increase the begin iterator until you reach the
end. To acquire the value *pointed* by the iterator use the \* operator (add it before it).
@@ -152,17 +152,17 @@ On-the-fly address calculation with reference returning
The final method isn't recommended for scanning. It was made to acquire or modify somehow random
elements in the image. Its basic usage is to specify the row and column number of the item you want
to access. During our earlier scanning methods you could already observe that is important through
to access. During our earlier scanning methods you could already notice that it is important through
what type we are looking at the image. It's no different here as you need to manually specify what
type to use at the automatic lookup. You can observe this in case of the gray scale images for the
type to use at the automatic lookup. You can observe this in case of the grayscale images for the
following source code (the usage of the + cv::Mat::at() function):
@snippet how_to_scan_images.cpp scan-random
The functions takes your input type and coordinates and calculates on the fly the address of the
The function takes your input type and coordinates and calculates the address of the
queried item. Then returns a reference to that. This may be a constant when you *get* the value and
non-constant when you *set* the value. As a safety step in **debug mode only**\* there is performed
a check that your input coordinates are valid and does exist. If this isn't the case you'll get a
non-constant when you *set* the value. As a safety step in **debug mode only**\* there is a check
performed that your input coordinates are valid and do exist. If this isn't the case you'll get a
nice output message of this on the standard error output stream. Compared to the efficient way in
release mode the only difference in using this is that for every element of the image you'll get a
new row pointer for what we use the C operator[] to acquire the column element.
@@ -173,7 +173,7 @@ OpenCV has a cv::Mat_ data type. It's the same as Mat with the extra need that a
you need to specify the data type through what to look at the data matrix, however in return you can
use the operator() for fast access of items. To make things even better this is easily convertible
from and to the usual cv::Mat data type. A sample usage of this you can see in case of the
color images of the upper function. Nevertheless, it's important to note that the same operation
color images of the function above. Nevertheless, it's important to note that the same operation
(with the same runtime speed) could have been done with the cv::Mat::at function. It's just a less
to write for the lazy programmer trick.
@@ -195,7 +195,7 @@ Finally call the function (I is our input image and J the output one):
Performance Difference
----------------------
For the best result compile the program and run it on your own speed. To make the differences more
For the best result compile the program and run it yourself. To make the differences more
clear, I've used a quite large (2560 X 1600) image. The performance presented here are for
color images. For a more accurate value I've averaged the value I got from the call of the function
for hundred times.
@@ -4,7 +4,7 @@ Mask operations on matrices {#tutorial_mat_mask_operations}
@prev_tutorial{tutorial_how_to_scan_images}
@next_tutorial{tutorial_mat_operations}
Mask operations on matrices are quite simple. The idea is that we recalculate each pixels value in
Mask operations on matrices are quite simple. The idea is that we recalculate each pixel's value in
an image according to a mask matrix (also known as kernel). This mask holds values that will adjust
how much influence neighboring pixels (and the current pixel) have on the new pixel value. From a
mathematical point of view we make a weighted average, with our specified values.
@@ -12,7 +12,7 @@ mathematical point of view we make a weighted average, with our specified values
Our test case
-------------
Let us consider the issue of an image contrast enhancement method. Basically we want to apply for
Let's consider the issue of an image contrast enhancement method. Basically we want to apply for
every pixel of the image the following formula:
\f[I(i,j) = 5*I(i,j) - [ I(i-1,j) + I(i+1,j) + I(i,j-1) + I(i,j+1)]\f]\f[\iff I(i,j)*M, \text{where }
@@ -144,7 +144,7 @@ Then we apply the sum and put the new value in the Result matrix.
The filter2D function
---------------------
Applying such filters are so common in image processing that in OpenCV there exist a function that
Applying such filters are so common in image processing that in OpenCV there is a function that
will take care of applying the mask (also called a kernel in some places). For this you first need
to define an object that holds the mask:
@@ -61,7 +61,7 @@ The last thing we want to do is further decrease the speed of your program by ma
copies of potentially *large* images.
To tackle this issue OpenCV uses a reference counting system. The idea is that each *Mat* object has
its own header, however the matrix may be shared between two instance of them by having their matrix
its own header, however a matrix may be shared between two *Mat* objects by having their matrix
pointers point to the same address. Moreover, the copy operators **will only copy the headers** and
the pointer to the large matrix, not the data itself.
@@ -74,32 +74,32 @@ Mat B(A); // Use the copy constructor
C = A; // Assignment operator
@endcode
All the above objects, in the end, point to the same single data matrix. Their headers are
different, however, and making a modification using any of them will affect all the other ones as
well. In practice the different objects just provide different access method to the same underlying
data. Nevertheless, their header parts are different. The real interesting part is that you can
create headers which refer to only a subsection of the full data. For example, to create a region of
interest (*ROI*) in an image you just create a new header with the new boundaries:
All the above objects, in the end, point to the same single data matrix and making a modification
using any of them will affect all the other ones as well. In practice the different objects just
provide different access methods to the same underlying data. Nevertheless, their header parts are
different. The real interesting part is that you can create headers which refer to only a subsection
of the full data. For example, to create a region of interest (*ROI*) in an image you just create
a new header with the new boundaries:
@code{.cpp}
Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries
@endcode
Now you may ask if the matrix itself may belong to multiple *Mat* objects who takes responsibility
Now you may ask -- if the matrix itself may belong to multiple *Mat* objects who takes responsibility
for cleaning it up when it's no longer needed. The short answer is: the last object that used it.
This is handled by using a reference counting mechanism. Whenever somebody copies a header of a
*Mat* object, a counter is increased for the matrix. Whenever a header is cleaned this counter is
decreased. When the counter reaches zero the matrix too is freed. Sometimes you will want to copy
the matrix itself too, so OpenCV provides the @ref cv::Mat::clone() and @ref cv::Mat::copyTo() functions.
*Mat* object, a counter is increased for the matrix. Whenever a header is cleaned, this counter
is decreased. When the counter reaches zero the matrix is freed. Sometimes you will want to copy
the matrix itself too, so OpenCV provides @ref cv::Mat::clone() and @ref cv::Mat::copyTo() functions.
@code{.cpp}
Mat F = A.clone();
Mat G;
A.copyTo(G);
@endcode
Now modifying *F* or *G* will not affect the matrix pointed by the *Mat* header. What you need to
Now modifying *F* or *G* will not affect the matrix pointed by the *A*'s header. What you need to
remember from all this is that:
- Output image allocation for OpenCV functions is automatic (unless specified otherwise).
- You do not need to think about memory management with OpenCVs C++ interface.
- You do not need to think about memory management with OpenCV's C++ interface.
- The assignment operator and the copy constructor only copies the header.
- The underlying matrix of an image may be copied using the @ref cv::Mat::clone() and @ref cv::Mat::copyTo()
functions.
@@ -109,7 +109,7 @@ Storing methods
This is about how you store the pixel values. You can select the color space and the data type used.
The color space refers to how we combine color components in order to code a given color. The
simplest one is the gray scale where the colors at our disposal are black and white. The combination
simplest one is the grayscale where the colors at our disposal are black and white. The combination
of these allows us to create many shades of gray.
For *colorful* ways we have a lot more methods to choose from. Each of them breaks it down to three
@@ -121,15 +121,15 @@ added.
There are, however, many other color systems each with their own advantages:
- RGB is the most common as our eyes use something similar, however keep in mind that OpenCV standard display
system composes colors using the BGR color space (a switch of the red and blue channel).
system composes colors using the BGR color space (red and blue channels are swapped places).
- The HSV and HLS decompose colors into their hue, saturation and value/luminance components,
which is a more natural way for us to describe colors. You might, for example, dismiss the last
component, making your algorithm less sensible to the light conditions of the input image.
- YCrCb is used by the popular JPEG image format.
- CIE L\*a\*b\* is a perceptually uniform color space, which comes handy if you need to measure
- CIE L\*a\*b\* is a perceptually uniform color space, which comes in handy if you need to measure
the *distance* of a given color to another color.
Each of the building components has their own valid domains. This leads to the data type used. How
Each of the building components has its own valid domains. This leads to the data type used. How
we store a component defines the control we have over its domain. The smallest data type possible is
*char*, which means one byte or 8 bits. This may be unsigned (so can store values from 0 to 255) or
signed (values from -127 to +127). Although in case of three components this already gives 16
@@ -165,8 +165,8 @@ object in multiple ways:
CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
@endcode
For instance, *CV_8UC3* means we use unsigned char types that are 8 bit long and each pixel has
three of these to form the three channels. This are predefined for up to four channel numbers. The
@ref cv::Scalar is four element short vector. Specify this and you can initialize all matrix
three of these to form the three channels. There are types predefined for up to four channels. The
@ref cv::Scalar is four element short vector. Specify it and you can initialize all matrix
points with a custom value. If you need more you can create the type with the upper macro, setting
the channel number in parenthesis as you can see below.
@@ -210,7 +210,7 @@ object in multiple ways:
@note
You can fill out a matrix with random values using the @ref cv::randu() function. You need to
give the lower and upper value for the random values:
give a lower and upper limit for the random values:
@snippet mat_the_basic_image_container.cpp random
@@ -12,7 +12,7 @@ Tutorial was written for the following versions of corresponding software:
- Download and install Android Studio from https://developer.android.com/studio.
- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases and unpack it (for example, `opencv-3.4.8-android-sdk.zip`).
- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases and unpack it (for example, `opencv-3.4.9-android-sdk.zip`).
- Download MobileNet object detection model from https://github.com/chuanqi305/MobileNet-SSD. We need a configuration file `MobileNetSSD_deploy.prototxt` and weights `MobileNetSSD_deploy.caffemodel`.
@@ -210,12 +210,12 @@ Explanation
@code{.cpp}
image2 = image - Scalar::all(i)
@endcode
So, **image2** is the substraction of **image** and **Scalar::all(i)**. In fact, what happens
here is that every pixel of **image2** will be the result of substracting every pixel of
So, **image2** is the subtraction of **image** and **Scalar::all(i)**. In fact, what happens
here is that every pixel of **image2** will be the result of subtracting every pixel of
**image** minus the value of **i** (remember that for each pixel we are considering three values
such as R, G and B, so each of them will be affected)
Also remember that the substraction operation *always* performs internally a **saturate**
Also remember that the subtraction operation *always* performs internally a **saturate**
operation, which means that the result obtained will always be inside the allowed range (no
negative and between 0 and 255 for our example).
@@ -4,7 +4,7 @@ Cross referencing OpenCV from other Doxygen projects {#tutorial_cross_referencin
Cross referencing OpenCV
------------------------
[Doxygen](https://www.stack.nl/~dimitri/doxygen/) is a tool to generate
[Doxygen](http://www.doxygen.nl) is a tool to generate
documentations like the OpenCV documentation you are reading right now.
It is used by a variety of software projects and if you happen to use it
to generate your own documentation, and you are using OpenCV inside your
@@ -36,14 +36,14 @@ Open your Doxyfile using your favorite text editor and search for the key
`TAGFILES`. Change it as follows:
@code
TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.8
TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.9
@endcode
If you had other definitions already, you can append the line using a `\`:
@code
TAGFILES = ./docs/doxygen-tags/libstdc++.tag=https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen \
./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.8
./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.9
@endcode
Doxygen can now use the information from the tag file to link to the OpenCV
@@ -57,5 +57,5 @@ contain a `your_project.tag` file in its root directory.
References
----------
- [Doxygen: Linking to external documentation](https://www.stack.nl/~dimitri/doxygen/manual/external.html)
- [Doxygen: Linking to external documentation](http://www.doxygen.nl/manual/external.html)
- [opencv.tag](opencv.tag)
@@ -684,12 +684,12 @@ References {#tutorial_documentation_refs}
- [Command reference] - supported commands and their parameters
<!-- invisible references list -->
[Doxygen]: http://www.stack.nl/~dimitri/doxygen/index.html)
[Doxygen download]: http://www.stack.nl/~dimitri/doxygen/download.html
[Doxygen installation]: http://www.stack.nl/~dimitri/doxygen/manual/install.html
[Documenting basics]: http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html
[Markdown support]: http://www.stack.nl/~dimitri/doxygen/manual/markdown.html
[Formulas support]: http://www.stack.nl/~dimitri/doxygen/manual/formulas.html
[Doxygen]: http://www.doxygen.nl
[Doxygen download]: http://doxygen.nl/download.html
[Doxygen installation]: http://doxygen.nl/manual/install.html
[Documenting basics]: http://www.doxygen.nl/manual/docblocks.html
[Markdown support]: http://www.doxygen.nl/manual/markdown.html
[Formulas support]: http://www.doxygen.nl/manual/formulas.html
[Supported formula commands]: http://docs.mathjax.org/en/latest/tex.html#supported-latex-commands
[Command reference]: http://www.stack.nl/~dimitri/doxygen/manual/commands.html
[Command reference]: http://www.doxygen.nl/manual/commands.html
[Google Scholar]: http://scholar.google.ru/
@@ -9,7 +9,7 @@ Required Packages
### Getting the Cutting-edge OpenCV from Git Repository
Launch GIT client and clone OpenCV repository from [here](http://github.com/opencv/opencv)
Launch Git client and clone OpenCV repository from [GitHub](http://github.com/opencv/opencv).
In MacOS it can be done using the following command in Terminal:
@@ -18,24 +18,48 @@ cd ~/<my_working _directory>
git clone https://github.com/opencv/opencv.git
@endcode
If you want to install OpenCVs extra modules, clone the opencv_contrib repository as well:
@code{.bash}
cd ~/<my_working _directory>
git clone https://github.com/opencv/opencv_contrib.git
@endcode
Building OpenCV from Source, using CMake and Command Line
---------------------------------------------------------
-# Make symbolic link for Xcode to let OpenCV build scripts find the compiler, header files etc.
1. Make sure the xcode command line tools are installed:
@code{.bash}
cd /
sudo ln -s /Applications/Xcode.app/Contents/Developer Developer
xcode-select --install
@endcode
-# Build OpenCV framework:
2. Build OpenCV framework:
@code{.bash}
cd ~/<my_working_directory>
python opencv/platforms/ios/build_framework.py ios
@endcode
If everything's fine, a few minutes later you will get
\~/\<my_working_directory\>/ios/opencv2.framework. You can add this framework to your Xcode
projects.
3. To install OpenCVs extra modules, append `--contrib opencv_contrib` to the python command above. **Note:** the extra modules are not included in the iOS Pack download at [OpenCV Releases](https://opencv.org/releases/). If you want to use the extra modules (e.g. aruco), you must build OpenCV yourself and include this option:
@code{.bash}
cd ~/<my_working_directory>
python opencv/platforms/ios/build_framework.py ios --contrib opencv_contrib
@endcode
4. To exclude a specific module, append `--without <module_name>`. For example, to exclude the "optflow" module from opencv_contrib:
@code{.bash}
cd ~/<my_working_directory>
python opencv/platforms/ios/build_framework.py ios --contrib opencv_contrib --without optflow
@endcode
5. The build process can take a significant amount of time. Currently (OpenCV 3.4 and 4.1), five separate architectures are built: armv7, armv7s, and arm64 for iOS plus i386 and x86_64 for the iPhone simulator. If you want to specify the architectures to include in the framework, use the `--iphoneos_archs` and/or `--iphonesimulator_archs` options. For example, to only build arm64 for iOS and x86_64 for the simulator:
@code{.bash}
cd ~/<my_working_directory>
python opencv/platforms/ios/build_framework.py ios --contrib opencv_contrib --iphoneos_archs arm64 --iphonesimulator_archs x86_64
@endcode
If everythings fine, the build process will create
`~/<my_working_directory>/ios/opencv2.framework`. You can add this framework to your Xcode projects.
Further Reading
---------------
@@ -0,0 +1,116 @@
Installation in MacOS {#tutorial_macos_install}
=====================
The following steps have been tested for MacOSX (Mavericks) but should work with other versions as well.
Required Packages
-----------------
- CMake 3.9 or higher
- Git
- Python 2.7 or later and Numpy 1.5 or later
This tutorial will assume you have [Python](https://docs.python.org/3/using/mac.html),
[Numpy](https://docs.scipy.org/doc/numpy-1.10.1/user/install.html) and
[Git](https://www.atlassian.com/git/tutorials/install-git) installed on your machine.
@note
OSX comes with Python 2.7 by default, you will need to install Python 3.8 if you want to use it specifically.
@note
If you XCode and XCode Command Line-Tools installed, you already have git installed on your machine.
Installing CMake
----------------
-# Find the version for your system and download CMake from their release's [page](https://cmake.org/download/)
-# Install the dmg package and launch it from Applications. That will give you the UI app of CMake
-# From the CMake app window, choose menu Tools --> Install For Command Line Use.
-# Install folder will be /usr/bin/ by default, submit it by choosing Install command line links.
-# Test that it works by running
@code{.bash}
cmake --version
@endcode
Getting OpenCV Source Code
--------------------------
You can use the latest stable OpenCV version or you can grab the latest snapshot from our
[Git repository](https://github.com/opencv/opencv.git).
### Getting the Latest Stable OpenCV Version
- Go to our [downloads page](http://opencv.org/releases.html).
- Download the source archive and unpack it.
### Getting the Cutting-edge OpenCV from the Git Repository
Launch Git client and clone [OpenCV repository](http://github.com/opencv/opencv).
If you need modules from [OpenCV contrib repository](http://github.com/opencv/opencv_contrib) then clone it as well.
For example
@code{.bash}
cd ~/<my_working_directory>
git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git
@endcode
Building OpenCV from Source Using CMake
---------------------------------------
-# Create a temporary directory, which we denote as `<cmake_build_dir>`, where you want to put
the generated Makefiles, project files as well the object files and output binaries and enter
there.
For example
@code{.bash}
mkdir build_opencv
cd build_opencv
@endcode
@note It is good practice to keep clean your source code directories. Create build directory outside of source tree.
-# Configuring. Run `cmake [<some optional parameters>] <path to the OpenCV source directory>`
For example
@code{.bash}
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=ON ../opencv
@endcode
or cmake-gui
- set full path to OpenCV source code, e.g. `/home/user/opencv`
- set full path to `<cmake_build_dir>`, e.g. `/home/user/build_opencv`
- set optional parameters
- run: "Configure"
- run: "Generate"
-# Description of some parameters
- build type: `CMAKE_BUILD_TYPE=Release` (or `Debug`)
- to build with modules from opencv_contrib set `OPENCV_EXTRA_MODULES_PATH` to `<path to
opencv_contrib>/modules`
- set `BUILD_DOCS=ON` for building documents (doxygen is required)
- set `BUILD_EXAMPLES=ON` to build all examples
-# [optional] Building python. Set the following python parameters:
- `PYTHON3_EXECUTABLE = <path to python>`
- `PYTHON3_INCLUDE_DIR = /usr/include/python<version>`
- `PYTHON3_NUMPY_INCLUDE_DIRS =
/usr/lib/python<version>/dist-packages/numpy/core/include/`
@note
To specify Python2 versions, you can replace `PYTHON3_` with `PYTHON2_` in the above parameters.
-# Build. From build directory execute *make*, it is recommended to do this in several threads
For example
@code{.bash}
make -j7 # runs 7 jobs in parallel
@endcode
-# To use OpenCV in your CMake-based projects through `find_package(OpenCV)` specify `OpenCV_DIR=<path_to_build_or_install_directory>` variable.
@note
You can also use a package manager like [Homebrew](https://brew.sh/)
or [pip](https://pip.pypa.io/en/stable/) to install releases of OpenCV only (Not the cutting edge).
@@ -110,11 +110,19 @@ Additionally you can find very basic sample source code to introduce you to the
Modify Android camera preview with OpenCL
- @subpage tutorial_macos_install
_Compatibility:_ \> OpenCV 3.4.x
_Author:_ [\@sajarindider](https://github.com/sajarindider)
We will learn how to setup OpenCV in MacOS.
- @subpage tutorial_ios_install
_Compatibility:_ \> OpenCV 2.4.2
_Author:_ Artem Myagkov, Eduard Feicho
_Author:_ Artem Myagkov, Eduard Feicho, Steve Nicholson
We will learn how to setup OpenCV for using it in iOS!
@@ -48,10 +48,8 @@ CMAKE_CONFIG_GENERATOR="Visual Studio 14 2015 Win64"
if [ ! -d "$myRepo/opencv" ]; then
echo "cloning opencv"
git clone https://github.com/opencv/opencv.git
mkdir Build
mkdir Build/opencv
mkdir Install
mkdir Install/opencv
mkdir -p Build/opencv
mkdir -p Install/opencv
else
cd opencv
git pull --rebase
@@ -60,8 +58,7 @@ fi
if [ ! -d "$myRepo/opencv_contrib" ]; then
echo "cloning opencv_contrib"
git clone https://github.com/opencv/opencv_contrib.git
mkdir Build
mkdir Build/opencv_contrib
mkdir -p Build/opencv_contrib
else
cd opencv_contrib
git pull --rebase
@@ -154,7 +151,7 @@ of them, you need to download and install them on your system.
image file format.
- The OpenNI Framework contains a set of open source APIs that provide support for natural interaction with devices via methods such as voice command recognition, hand gestures, and body
motion tracking. Prebuilt binaries can be found [here](http://structure.io/openni). The source code of [OpenNI](https://github.com/OpenNI/OpenNI) and [OpenNI2](https://github.com/OpenNI/OpenNI2) are also available on Github.
- [Doxygen](http://www.stack.nl/~dimitri/doxygen/) is a documentation generator and is the tool that will actually create the
- [Doxygen](http://www.doxygen.nl) is a documentation generator and is the tool that will actually create the
*OpenCV documentation*.
Now we will describe the steps to follow for a full build (using all the above frameworks, tools and
Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 26 KiB

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