mirror of
https://github.com/opencv/opencv.git
synced 2026-07-24 12:53:04 +04:00
Compare commits
462 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0dc474160 | |||
| adf89bbb33 | |||
| 583bd1a6e2 | |||
| 53eda42da7 | |||
| c26c4a61c6 | |||
| 65fcf22670 | |||
| d0572538ff | |||
| 3577265508 | |||
| 1a24e316d5 | |||
| 9da9e8244b | |||
| 8d51ef0f35 | |||
| 9cfae823a7 | |||
| d6151eae23 | |||
| 4a0a3281c6 | |||
| 1230075011 | |||
| 7459954377 | |||
| cf38098ba8 | |||
| 8ca394efaf | |||
| f9c7931800 | |||
| 24547f40ff | |||
| 72debee125 | |||
| 08c270f65a | |||
| e585453c2e | |||
| 86f4524010 | |||
| 6d098cc230 | |||
| 434c96e625 | |||
| d6e9616256 | |||
| e9187ae38c | |||
| 978dc76653 | |||
| b409fd32ac | |||
| a2ad997e97 | |||
| e9428726ca | |||
| 400906b433 | |||
| 50d7c61c01 | |||
| d9bf522b27 | |||
| 93dc0679ec | |||
| 1ddc51cfd1 | |||
| 50bf0e10f5 | |||
| d1ccb7e47f | |||
| 7e845a3b87 | |||
| ea1c970190 | |||
| 3d207ccf11 | |||
| aaf7f5ae02 | |||
| 50e8ad285b | |||
| bb5462e327 | |||
| df2e7fa6eb | |||
| 11f36bdf9a | |||
| bc0d4585b3 | |||
| 70917f291c | |||
| 9f6f0c7424 | |||
| 4722a8df3c | |||
| 7be8a71c60 | |||
| ce859edba8 | |||
| 90820cd044 | |||
| c929f1b62f | |||
| ff88132620 | |||
| 89f8d4ae12 | |||
| 3f4ffe7844 | |||
| ed567a2dd1 | |||
| 22a00036e2 | |||
| 2aac0a5a26 | |||
| 07ad6a437e | |||
| d9a444ca1a | |||
| 766f58ed7e | |||
| 1099b4c881 | |||
| 7c0f49fc36 | |||
| 761e796201 | |||
| 8d0fbc6a1e | |||
| affcea8822 | |||
| 53f0be00a9 | |||
| 602caa9cd6 | |||
| f35ec8c955 | |||
| 1316491e50 | |||
| 2cc4309bf8 | |||
| 612d43f284 | |||
| 56824d1769 | |||
| 2238ac7d59 | |||
| 2b5b192cd7 | |||
| 64e1d23cba | |||
| 40d2904f3d | |||
| 9712cc479b | |||
| 0ef1fb0b67 | |||
| 2b67bc448d | |||
| a3f81b79ed | |||
| 8d0dae4cec | |||
| dda96264df | |||
| 4af8e5c5c4 | |||
| eff5605be5 | |||
| 2b53ab23c0 | |||
| 2010de9104 | |||
| 280a99b3b6 | |||
| 646025589b | |||
| 4502003e61 | |||
| 07abb6240e | |||
| dea0815199 | |||
| e4ed2d2e42 | |||
| c8228e5789 | |||
| 667e5e4f89 | |||
| ada703a73a | |||
| 9e1e960116 | |||
| 82ae9ef541 | |||
| 1b07274e34 | |||
| 15ac54d5d6 | |||
| 1cdd8510fd | |||
| 039f3d01a0 | |||
| f63feea05e | |||
| fbac38d98b | |||
| ca2ab3387f | |||
| 64ded50bbf | |||
| d44ac61033 | |||
| 18ada77d8a | |||
| 6d0f1275c2 | |||
| a848eccfc6 | |||
| 2402fa4824 | |||
| 2bf4135afc | |||
| c677f132cd | |||
| ec4015d73c | |||
| 8c42dbf71c | |||
| 4ca679180d | |||
| 64da959619 | |||
| 88123e2512 | |||
| 87e98e8788 | |||
| 767857c516 | |||
| 2b60166e5c | |||
| 2e41db39f5 | |||
| a55fa8389e | |||
| d23142027f | |||
| 438fe3f9db | |||
| 5cc154147f | |||
| 9cd5a0a1e6 | |||
| 2958142e31 | |||
| 27c15bed60 | |||
| 2985739b8c | |||
| 2465d93330 | |||
| 556d211136 | |||
| 0ee2a58cdc | |||
| 7daf84fb44 | |||
| 9aff01c9a9 | |||
| a2b84e9897 | |||
| 66f3c2673c | |||
| 554d08c3a1 | |||
| 3a595ea5c4 | |||
| 03c9648f2e | |||
| e3a55af336 | |||
| be4a432bea | |||
| 0d32a24cba | |||
| e36948cfbc | |||
| 9aa647068b | |||
| 092030c1ca | |||
| 0bd261ded4 | |||
| 7ed557497d | |||
| d793ec2ffe | |||
| 271f7df343 | |||
| 08d44f588f | |||
| 84b4a5a495 | |||
| b2e20a82ba | |||
| 1b3a06a02a | |||
| 91a5e75151 | |||
| 4754b0e253 | |||
| 84b517f5a0 | |||
| 8ac88cf069 | |||
| 13a995cc1d | |||
| a93fb52632 | |||
| 4d927e73f1 | |||
| 38228709c8 | |||
| 38788a3161 | |||
| 46b6973c05 | |||
| af2b7708a8 | |||
| a233982931 | |||
| ed1439fbc6 | |||
| b379b67a32 | |||
| f3945fbddb | |||
| 8b44ee2ce1 | |||
| 7b582b71ba | |||
| 4e8c507276 | |||
| 9390c56831 | |||
| abebbf04b1 | |||
| 5e434073d4 | |||
| 3e4a566e46 | |||
| 6f5cf8c15f | |||
| b687bc807a | |||
| 5440fd6cb4 | |||
| b060151625 | |||
| be38d4ea93 | |||
| 56f21c4fd5 | |||
| 386df457a9 | |||
| e4abf6e723 | |||
| 1339ebaa84 | |||
| c9b90884da | |||
| 9b2b2c88df | |||
| e5bdab0355 | |||
| 4d46958c82 | |||
| 9dd8e4df7f | |||
| d98e07c3d3 | |||
| 78bc11465b | |||
| 8e8e4bbabc | |||
| 90671233c6 | |||
| 12bae51384 | |||
| 7b848e215f | |||
| 21872e2fb0 | |||
| 2a218b96c4 | |||
| e76cda6923 | |||
| 9d16612a9b | |||
| 63c865ace6 | |||
| 0a62de0d4f | |||
| 593996216f | |||
| 4eae23a2cc | |||
| f3699b5ac8 | |||
| 9ce0e51305 | |||
| 4c79318694 | |||
| f7ac724c5d | |||
| ee9fe1239a | |||
| b6b5c27cec | |||
| 632e07b749 | |||
| 48cd2d190f | |||
| 685797f403 | |||
| ef6f421f89 | |||
| e0ffd3e8a5 | |||
| 0d16b5fc38 | |||
| ac8a27cba9 | |||
| e5f2a8ebf2 | |||
| 54733eba6f | |||
| 93353aea70 | |||
| e16cb8b4a2 | |||
| 5bf3c1df24 | |||
| 419918076e | |||
| fb768c420d | |||
| eb067fee55 | |||
| 6390b50d6e | |||
| 5d8134ed32 | |||
| 852904e1a4 | |||
| a120adde63 | |||
| a80af177b6 | |||
| 8db7d435b9 | |||
| 901e0ddfe4 | |||
| ecb30409f6 | |||
| 44c2c77548 | |||
| 5be5efdacf | |||
| 057c3da82a | |||
| 8fa429caef | |||
| 87f526d82f | |||
| 1ae2320e09 | |||
| 54693cf7b1 | |||
| a082375d57 | |||
| 9c7adb7248 | |||
| ccebbbc0ac | |||
| ebb6915e58 | |||
| 5cc27fd3b5 | |||
| a332509e02 | |||
| 375fe81311 | |||
| d354ad1c34 | |||
| 119d8b3aca | |||
| cd9edba26f | |||
| 8f1c502d2b | |||
| 92312fbc0c | |||
| 2efcaa9e8e | |||
| aa53541235 | |||
| b863c25d21 | |||
| f77c3574af | |||
| f5105bac65 | |||
| 5a86592e93 | |||
| 2c83cfc14c | |||
| 863546e125 | |||
| 9198e30688 | |||
| 1890157faa | |||
| 0898f372b1 | |||
| b9e5256cf9 | |||
| 6b6d89b911 | |||
| d3e0193c8a | |||
| 31881209d6 | |||
| 5c7e893393 | |||
| 3c814ebf87 | |||
| 5cf1dca36e | |||
| 12338c1dc4 | |||
| 5b23752205 | |||
| 4e53f301d8 | |||
| 2b7803dbac | |||
| 446a278f3d | |||
| 0047d3f81a | |||
| 4e1f17d65b | |||
| f9b1dbe2ac | |||
| a251474144 | |||
| 8d88bb06b2 | |||
| 9f2ff3ed22 | |||
| 45cbf70265 | |||
| 59e16b88ae | |||
| 33f219dfe6 | |||
| 44db2eea70 | |||
| 12ab54648c | |||
| 19926e2979 | |||
| 1620a1e014 | |||
| 888546b6f5 | |||
| 3215db26aa | |||
| 76aff84788 | |||
| fc28ba3156 | |||
| effce0573b | |||
| e8db363431 | |||
| 9603b6877d | |||
| d5ecb5ff5a | |||
| dae73938e8 | |||
| 619b6dfae3 | |||
| 8f9c36b730 | |||
| 3eeec4faae | |||
| 972a4b95b6 | |||
| ffee1a4126 | |||
| 96e23c2ff6 | |||
| 08356007c9 | |||
| 5064b6f747 | |||
| 57d3002ee1 | |||
| a00a0dbfcd | |||
| b41d2c5c14 | |||
| 1da48beeec | |||
| b57ff73086 | |||
| 67978b5746 | |||
| 062f305d1a | |||
| 1f70d4e2a5 | |||
| aa5bc20c83 | |||
| 09af10f635 | |||
| 4d7953aa56 | |||
| 46e1560678 | |||
| 4d0148b417 | |||
| 1605d1d24d | |||
| 5190043e56 | |||
| f66a2ffa1e | |||
| d1e76a34a0 | |||
| 5b3d5f9f3c | |||
| 415a42f327 | |||
| 09f6e55338 | |||
| a351e05a17 | |||
| d37bcbdc92 | |||
| 437af37b13 | |||
| c62367612d | |||
| a92cba8484 | |||
| 5f7d922b10 | |||
| dc29632d4e | |||
| f4a7754cc0 | |||
| 6811d3d80b | |||
| 245f6273bd | |||
| 870c8d3c4e | |||
| d573472a86 | |||
| 441b6dbda0 | |||
| a7e6a1059c | |||
| 85719a0a5d | |||
| b5b52afd35 | |||
| dc35633aa4 | |||
| 9e3ba487fa | |||
| aee8425b68 | |||
| 94229bb262 | |||
| 1f6444fbea | |||
| 439ef6447d | |||
| 9cab808c5d | |||
| d41fcf7345 | |||
| ac51ba38f9 | |||
| ef85b24a78 | |||
| d88730685e | |||
| 16661847a7 | |||
| 7f782a1a24 | |||
| 9188ce68aa | |||
| 2b79a6ff8f | |||
| 70b0274c8e | |||
| 83ce1de8e7 | |||
| b1d484f827 | |||
| 123519165d | |||
| 30ff9c6775 | |||
| 906f5f7e96 | |||
| 9238316cf1 | |||
| 5e89b9a455 | |||
| e3a4ff33d2 | |||
| 5d9ea394ba | |||
| abb5c9fd92 | |||
| 266835cd2e | |||
| 92af03579c | |||
| 2e20f2b89f | |||
| e67593673f | |||
| d1b533d399 | |||
| 2647902fee | |||
| 574320ec3f | |||
| 3f2377017c | |||
| 2b5bb02817 | |||
| 302d14adef | |||
| b796ededae | |||
| f811ba8777 | |||
| eb7b45d26b | |||
| 17b2d92a3d | |||
| 22f0bcaf8f | |||
| e61277002c | |||
| ca5258f140 | |||
| 8f4473b3e3 | |||
| 51e8af9e5f | |||
| 82818e7324 | |||
| 6ae8103022 | |||
| eca2d92791 | |||
| 6778e19710 | |||
| 25f25275cd | |||
| 7e746ad2a6 | |||
| 6ffa2b01e1 | |||
| ed6ca0d7fa | |||
| 8e2a3c1d2f | |||
| 7f6dcc2745 | |||
| 76e34d6f2c | |||
| e613b17c05 | |||
| 5ba9a089e1 | |||
| f2d5d6d24e | |||
| a1ec4ea3a9 | |||
| 0fe7420638 | |||
| b304730225 | |||
| 4801526f35 | |||
| f1857030b5 | |||
| b5b3f4e1c6 | |||
| 172bb7887c | |||
| 60228d30d1 | |||
| 9592537840 | |||
| 8768a80242 | |||
| d5f73f89d8 | |||
| 19bbe6c67d | |||
| aebb65e983 | |||
| 5e327af327 | |||
| bc1f8813c2 | |||
| 80d9f624d0 | |||
| e9c46f38fc | |||
| ecfbaa267d | |||
| c25fd3349b | |||
| c3e27bcf87 | |||
| a5894f3e6b | |||
| 4db3a388dd | |||
| 6fd1a2ef52 | |||
| fe2a259eb1 | |||
| 1ba7c2f276 | |||
| 649f747f8a | |||
| 05dbaf7672 | |||
| 742a08229e | |||
| 5602d2c7bb | |||
| f3e0479a8f | |||
| a1143c4ea0 | |||
| 0314d1dd01 | |||
| 751b3f502d | |||
| bf5e09d5ab | |||
| 14e4a10312 | |||
| 53b89e1ee4 | |||
| 370f878a36 | |||
| 6e4d61c1fd | |||
| f6fe5c07f6 | |||
| c685293297 | |||
| 0e6a2c0491 | |||
| c2209ad5e4 | |||
| 5f249a3e67 | |||
| 76fb3652fc | |||
| 92925e846d | |||
| 43c04c29ce | |||
| 06b74c87da | |||
| 7f075b0b15 | |||
| c5a86c22a4 | |||
| 3621c6234c | |||
| 80c2fefc43 | |||
| a47952146a | |||
| a55950865e | |||
| ab181ac329 | |||
| db172d1053 | |||
| 523c3cd50b | |||
| 631126c77a | |||
| c68fec7e97 | |||
| 61d7d67c39 |
@@ -34,11 +34,11 @@ This is a template helping you to create an issue which can be processed as quic
|
||||
- [ ] I report the issue, it's not a question
|
||||
<!--
|
||||
OpenCV team works with forum.opencv.org, Stack Overflow and other communities
|
||||
to discuss problems. Tickets with question without real issue statement will be
|
||||
to discuss problems. Tickets with questions without a real issue statement will be
|
||||
closed.
|
||||
-->
|
||||
- [ ] I checked the problem with documentation, FAQ, open issues,
|
||||
forum.opencv.org, Stack Overflow, etc and have not found solution
|
||||
forum.opencv.org, Stack Overflow, etc and have not found any solution
|
||||
<!--
|
||||
Places to check:
|
||||
* OpenCV documentation: https://docs.opencv.org
|
||||
@@ -47,11 +47,11 @@ This is a template helping you to create an issue which can be processed as quic
|
||||
* OpenCV issue tracker: https://github.com/opencv/opencv/issues?q=is%3Aissue
|
||||
* Stack Overflow branch: https://stackoverflow.com/questions/tagged/opencv
|
||||
-->
|
||||
- [ ] I updated to latest OpenCV version and the issue is still there
|
||||
- [ ] I updated to the latest OpenCV version and the issue is still there
|
||||
<!--
|
||||
master branch for OpenCV 4.x and 3.4 branch for OpenCV 3.x releases.
|
||||
OpenCV team supports only latest release for each branch.
|
||||
The ticket is closed, if the problem is not reproduced with modern version.
|
||||
OpenCV team supports only the latest release for each branch.
|
||||
The ticket is closed if the problem is not reproduced with the modern version.
|
||||
-->
|
||||
- [ ] There is reproducer code and related data files: videos, images, onnx, etc
|
||||
<!--
|
||||
@@ -61,9 +61,9 @@ This is a template helping you to create an issue which can be processed as quic
|
||||
to reduce attachment size
|
||||
* Use PNG for images, if you report some CV related bug, but not image reader
|
||||
issue
|
||||
* Attach the image as archive to the ticket, if you report some reader issue.
|
||||
* Attach the image as an archive to the ticket, if you report some reader issue.
|
||||
Image hosting services compress images and it breaks the repro code.
|
||||
* Provide ONNX file for some public model or ONNX file with with random weights,
|
||||
* Provide ONNX file for some public model or ONNX file with random weights,
|
||||
if you report ONNX parsing or handling issue. Architecture details diagram
|
||||
from netron tool can be very useful too. See https://lutzroeder.github.io/netron/
|
||||
-->
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
|
||||
|
||||
- [ ] I agree to contribute to the project under Apache 2 License.
|
||||
- [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
|
||||
- [ ] The PR is proposed to proper branch
|
||||
- [ ] There is reference to original bug report and related work
|
||||
- [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
|
||||
- [ ] The PR is proposed to the proper branch
|
||||
- [ ] There is a reference to the original bug report and related work
|
||||
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
|
||||
Patch to opencv_extra has the same branch name.
|
||||
- [ ] The feature is well documented and sample code can be built with the project CMake
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
name: PR:4.x
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 4.x
|
||||
|
||||
jobs:
|
||||
ARM64:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-ARM64.yaml@main
|
||||
|
||||
U20:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-U20.yaml@main
|
||||
|
||||
W10:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-W10.yaml@main
|
||||
|
||||
TIM-VX:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-timvx-backend-tests-4.x.yml@main
|
||||
Vendored
+5
-5
@@ -1,8 +1,8 @@
|
||||
# Binaries branch name: ffmpeg/4.x_20211220
|
||||
# Binaries were created for OpenCV: 0e274fc4bed8a64ba4f1c201a21304286e217afc
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "4d348507d156ec797a88a887cfa7f9129a35afac")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "eece4ec8304188117ffc7d5dfd0fc0ae")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "20deefbfe023c8b8d11a52e5a6527c6a")
|
||||
# Binaries branch name: ffmpeg/4.x_20220524
|
||||
# Binaries were created for OpenCV: d6e9616256b46bd59be0a93d397f6ab958d39cd2
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "65ec04d4573dcdfa4531f0b9e67f35d8ffff873e")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "5573e2262ad1298e603122b7759fc2f6")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "5f9e2b2e04c15f080f40e844de80c867")
|
||||
ocv_update(FFMPEG_FILE_HASH_CMAKE "8862c87496e2e8c375965e1277dee1c7")
|
||||
|
||||
function(download_win_ffmpeg script_var)
|
||||
|
||||
Vendored
+1
@@ -54,6 +54,7 @@ set_target_properties(${ITT_LIBRARY} PROPERTIES
|
||||
)
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wsign-compare)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wstrict-prototypes) # clang15
|
||||
|
||||
if(ENABLE_SOLUTION_FOLDERS)
|
||||
set_target_properties(${ITT_LIBRARY} PROPERTIES FOLDER "3rdparty")
|
||||
|
||||
Vendored
+5
-1
@@ -77,7 +77,11 @@ endif(MSVC)
|
||||
add_library(${PNG_LIBRARY} STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL} ${lib_srcs} ${lib_hdrs})
|
||||
target_link_libraries(${PNG_LIBRARY} ${ZLIB_LIBRARIES})
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wcast-align -Wimplicit-fallthrough -Wunused-parameter -Wsign-compare)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wcast-align -Wimplicit-fallthrough -Wunused-parameter -Wsign-compare
|
||||
-Wmaybe-uninitialized
|
||||
-Wnull-pointer-subtraction # clang15
|
||||
-Wunused-but-set-variable # clang15
|
||||
)
|
||||
|
||||
set_target_properties(${PNG_LIBRARY}
|
||||
PROPERTIES OUTPUT_NAME ${PNG_LIBRARY}
|
||||
|
||||
Vendored
+3
-1
@@ -452,8 +452,10 @@ ocv_warnings_disable(CMAKE_C_FLAGS -Wno-unused-but-set-variable -Wmissing-protot
|
||||
-Wcast-align -Wshadow -Wno-maybe-uninitialized -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast
|
||||
-Wmisleading-indentation
|
||||
-Wimplicit-fallthrough
|
||||
-Wunused-parameter # clang
|
||||
-Warray-parameter
|
||||
-Wstrict-prototypes # clang15
|
||||
)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter) # clang
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations -Wunused-parameter -Wmissing-prototypes
|
||||
-Wundef # tiffiop.h: #if __clang_major__ >= 4
|
||||
)
|
||||
|
||||
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
set(TIMVX_COMMIT_HASH "1d9c7ab941b3d8d9c4d28d80058402725731e3d6")
|
||||
set(OCV_TIMVX_DIR "${OpenCV_BINARY_DIR}/3rdparty/libtim-vx")
|
||||
set(OCV_TIMVX_SOURCE_PATH "${OCV_TIMVX_DIR}/TIM-VX-${TIMVX_COMMIT_HASH}")
|
||||
|
||||
# Download TIM-VX source code
|
||||
if(EXISTS "${OCV_TIMVX_SOURCE_PATH}")
|
||||
message(STATUS "TIM-VX: Use cache of TIM-VX source code at ${OCV_TIMVX_SOURCE_PATH}")
|
||||
set(TIMVX_FOUND ON)
|
||||
else()
|
||||
set(OCV_TIMVX_FILENAME "${TIMVX_COMMIT_HASH}.zip")
|
||||
set(OCV_TIMVX_URL "https://github.com/VeriSilicon/TIM-VX/archive/")
|
||||
set(timvx_zip_md5sum 92619cc4498014ac7a09834d5e33ebd5)
|
||||
|
||||
ocv_download(FILENAME ${OCV_TIMVX_FILENAME}
|
||||
HASH ${timvx_zip_md5sum}
|
||||
URL "${OCV_TIMVX_URL}"
|
||||
DESTINATION_DIR "${OCV_TIMVX_DIR}"
|
||||
ID "TIM-VX"
|
||||
STATUS res
|
||||
UNPACK RELATIVE_URL)
|
||||
if(res)
|
||||
set(TIMVX_FOUND ON)
|
||||
message(STATUS "TIM-VX: Source code downloaded at ${OCV_TIMVX_SOURCE_PATH}.")
|
||||
else()
|
||||
set(TIMVX_FOUND OFF)
|
||||
message(STATUS "TIM-VX: Failed to download source code from github. Turning off TIMVX_FOUND")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# set VIVANTE SDK especially for x86_64 which comes along with TIM-VX source code
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64)
|
||||
set(VIVANTE_SDK_DIR "${OCV_TIMVX_SOURCE_PATH}/prebuilt-sdk/x86_64_linux")
|
||||
message(STATUS "TIM-VX: Build from source using prebuilt x86_64 VIVANTE SDK.")
|
||||
endif()
|
||||
|
||||
# Verify if requested VIVANTE SDK libraries are all found
|
||||
find_vivante_sdk_libs(missing ${VIVANTE_SDK_DIR})
|
||||
if(missing)
|
||||
message(STATUS "TIM-VX: Failed to find ${missing} in ${VIVANTE_SDK_DIR}/lib. Turning off TIMVX_VIV_FOUND")
|
||||
set(TIMVX_VIV_FOUND OFF)
|
||||
else()
|
||||
message(STATUS "TIM-VX: dependent VIVANTE SDK libraries are found at ${VIVANTE_SDK_DIR}/lib.")
|
||||
set(TIMVX_VIV_FOUND ON)
|
||||
endif()
|
||||
|
||||
if(TIMVX_VIV_FOUND)
|
||||
# vars used by TIM-VX CMake scripts
|
||||
set(EXTERNAL_VIV_SDK "${VIVANTE_SDK_DIR}" CACHE INTERNAL "" FORCE)
|
||||
set(VIV_SDK_DRIVER_PREFIX "lib" CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
|
||||
if(TIMVX_FOUND AND TIMVX_VIV_FOUND)
|
||||
set(BUILD_TIMVX ON)
|
||||
else()
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(BUILD_TIMVX)
|
||||
set(HAVE_TIMVX 1)
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wstrict-prototypes -Wundef -Wsign-compare -Wmissing-prototypes -Wmissing-declarations -Wstrict-aliasing -Wunused-but-set-variable -Wmaybe-uninitialized -Wshadow -Wsuggest-override -Wswitch)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-parameter -Wstrict-prototypes -Wundef -Wsign-compare -Wunused-but-set-variable -Wshadow -Wsuggest-override -Wmissing-declarations -Wswitch)
|
||||
|
||||
set(TIMVX_INC_DIR "${OCV_TIMVX_SOURCE_PATH}/include" CACHE INTERNAL "TIM-VX include directory")
|
||||
if(EXISTS "${OCV_TIMVX_SOURCE_PATH}/CMakeLists.txt")
|
||||
add_subdirectory("${OCV_TIMVX_SOURCE_PATH}" "${OCV_TIMVX_DIR}/build")
|
||||
else()
|
||||
message(WARNING "TIM-VX: Missing 'CMakeLists.txt' in the source code: ${OCV_TIMVX_SOURCE_PATH}")
|
||||
endif()
|
||||
ocv_install_target(tim-vx EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)
|
||||
set(TIMVX_LIB "tim-vx")
|
||||
endif()
|
||||
Vendored
+1
@@ -45,6 +45,7 @@ ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-variable -Wunused-function -Wshadow
|
||||
-Wmissing-prototypes # clang
|
||||
-Wmissing-declarations # gcc
|
||||
-Wimplicit-fallthrough
|
||||
-Wunused-but-set-variable # clang15
|
||||
)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS /wd4244 /wd4267) # vs2005
|
||||
|
||||
|
||||
Vendored
+1
@@ -13,6 +13,7 @@ project(openjpeg C)
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS
|
||||
-Wimplicit-const-int-float-conversion # clang
|
||||
-Wunused-but-set-variable # clang15
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
Vendored
+1
-1
@@ -77,7 +77,7 @@ E.g. external ref-counting is implemented for 1.0 version and native OpenVX one
|
||||
|
||||
Also there are some **C++ 11** features are used (e.g. rvalue ref-s) when their availability is detected at ***compile time***.
|
||||
|
||||
C++ exceptions are used for errors indication instead of return codes. There are two types of exceptions are defined: `RuntimeError` is thrown when OpenVX C call returned unsuccessful result and `WrapperError` is thrown when a problem is occured in the wrappers code. Both exception calsses are derived from `std::exception` (actually from its inheritants).
|
||||
C++ exceptions are used for errors indication instead of return codes. There are two types of exceptions are defined: `RuntimeError` is thrown when OpenVX C call returned unsuccessful result and `WrapperError` is thrown when a problem is occurred in the wrappers code. Both exception calsses are derived from `std::exception` (actually from its inheritants).
|
||||
|
||||
The so called **OpenVX objects** (e.g. `vx_image`) are represented as C++ classes in wrappers.
|
||||
All these classes use automatic ref-counting that allows development of exception-safe code.
|
||||
|
||||
Vendored
+1
-1
@@ -37,7 +37,7 @@ libtiff Tag Image File Format (TIFF) Software
|
||||
WITH_TIFF CMake option must be ON to add libtiff & zlib support to imgcodecs.
|
||||
------------------------------------------------------------------------------------
|
||||
zlib General purpose LZ77 compression library
|
||||
Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
|
||||
Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler.
|
||||
See zlib home page http://www.zlib.net
|
||||
for details and links to the source code
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
Vendored
+1
@@ -83,6 +83,7 @@ ocv_warnings_disable(CMAKE_C_FLAGS -Wshorten-64-to-32 -Wattributes -Wstrict-prot
|
||||
-Wundef # _LFS64_LARGEFILE is not defined
|
||||
/wd4267 # MSVS 2015 (x64) + zlib 1.2.11
|
||||
-Wimplicit-fallthrough
|
||||
/wd4244 # MSVS + zlib 1.2.12: warning C4244: '=': conversion from 'ush' to 'uchf', possible loss of data
|
||||
)
|
||||
|
||||
set_target_properties(${ZLIB_LIBRARY} PROPERTIES
|
||||
|
||||
Vendored
+112
-49
@@ -1,6 +1,69 @@
|
||||
|
||||
ChangeLog file for zlib
|
||||
|
||||
Changes in 1.2.12 (27 Mar 2022)
|
||||
- Cygwin does not have _wopen(), so do not create gzopen_w() there
|
||||
- Permit a deflateParams() parameter change as soon as possible
|
||||
- Limit hash table inserts after switch from stored deflate
|
||||
- Fix bug when window full in deflate_stored()
|
||||
- Fix CLEAR_HASH macro to be usable as a single statement
|
||||
- Avoid a conversion error in gzseek when off_t type too small
|
||||
- Have Makefile return non-zero error code on test failure
|
||||
- Avoid some conversion warnings in gzread.c and gzwrite.c
|
||||
- Update use of errno for newer Windows CE versions
|
||||
- Small speedup to inflate [psumbera]
|
||||
- Return an error if the gzputs string length can't fit in an int
|
||||
- Add address checking in clang to -w option of configure
|
||||
- Don't compute check value for raw inflate if asked to validate
|
||||
- Handle case where inflateSync used when header never processed
|
||||
- Avoid the use of ptrdiff_t
|
||||
- Avoid an undefined behavior of memcpy() in gzappend()
|
||||
- Avoid undefined behaviors of memcpy() in gz*printf()
|
||||
- Avoid an undefined behavior of memcpy() in _tr_stored_block()
|
||||
- Make the names in functions declarations identical to definitions
|
||||
- Remove old assembler code in which bugs have manifested
|
||||
- Fix deflateEnd() to not report an error at start of raw deflate
|
||||
- Add legal disclaimer to README
|
||||
- Emphasize the need to continue decompressing gzip members
|
||||
- Correct the initialization requirements for deflateInit2()
|
||||
- Fix a bug that can crash deflate on some input when using Z_FIXED
|
||||
- Assure that the number of bits for deflatePrime() is valid
|
||||
- Use a structure to make globals in enough.c evident
|
||||
- Use a macro for the printf format of big_t in enough.c
|
||||
- Clean up code style in enough.c, update version
|
||||
- Use inline function instead of macro for index in enough.c
|
||||
- Clarify that prefix codes are counted in enough.c
|
||||
- Show all the codes for the maximum tables size in enough.c
|
||||
- Add gznorm.c example, which normalizes gzip files
|
||||
- Fix the zran.c example to work on a multiple-member gzip file
|
||||
- Add tables for crc32_combine(), to speed it up by a factor of 200
|
||||
- Add crc32_combine_gen() and crc32_combine_op() for fast combines
|
||||
- Speed up software CRC-32 computation by a factor of 1.5 to 3
|
||||
- Use atomic test and set, if available, for dynamic CRC tables
|
||||
- Don't bother computing check value after successful inflateSync()
|
||||
- Correct comment in crc32.c
|
||||
- Add use of the ARMv8 crc32 instructions when requested
|
||||
- Use ARM crc32 instructions if the ARM architecture has them
|
||||
- Explicitly note that the 32-bit check values are 32 bits
|
||||
- Avoid adding empty gzip member after gzflush with Z_FINISH
|
||||
- Fix memory leak on error in gzlog.c
|
||||
- Fix error in comment on the polynomial representation of a byte
|
||||
- Clarify gz* function interfaces, referring to parameter names
|
||||
- Change macro name in inflate.c to avoid collision in VxWorks
|
||||
- Correct typo in blast.c
|
||||
- Improve portability of contrib/minizip
|
||||
- Fix indentation in minizip's zip.c
|
||||
- Replace black/white with allow/block. (theresa-m)
|
||||
- minizip warning fix if MAXU32 already defined. (gvollant)
|
||||
- Fix unztell64() in minizip to work past 4GB. (Daniël Hörchner)
|
||||
- Clean up minizip to reduce warnings for testing
|
||||
- Add fallthrough comments for gcc
|
||||
- Eliminate use of ULL constants
|
||||
- Separate out address sanitizing from warnings in configure
|
||||
- Remove destructive aspects of make distclean
|
||||
- Check for cc masquerading as gcc or clang in configure
|
||||
- Fix crc32.c to compile local functions only if used
|
||||
|
||||
Changes in 1.2.11 (15 Jan 2017)
|
||||
- Fix deflate stored bug when pulling last block from window
|
||||
- Permit immediate deflateParams changes before any deflate input
|
||||
@@ -511,7 +574,7 @@ Changes in 1.2.3.5 (8 Jan 2010)
|
||||
- Don't use _vsnprintf on later versions of MSVC [Lowman]
|
||||
- Add CMake build script and input file [Lowman]
|
||||
- Update contrib/minizip to 1.1 [Svensson, Vollant]
|
||||
- Moved nintendods directory from contrib to .
|
||||
- Moved nintendods directory from contrib to root
|
||||
- Replace gzio.c with a new set of routines with the same functionality
|
||||
- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above
|
||||
- Update contrib/minizip to 1.1b
|
||||
@@ -685,7 +748,7 @@ Changes in 1.2.2.4 (11 July 2005)
|
||||
- Be more strict on incomplete code sets in inflate_table() and increase
|
||||
ENOUGH and MAXD -- this repairs a possible security vulnerability for
|
||||
invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
|
||||
discovering the vulnerability and providing test cases.
|
||||
discovering the vulnerability and providing test cases
|
||||
- Add ia64 support to configure for HP-UX [Smith]
|
||||
- Add error return to gzread() for format or i/o error [Levin]
|
||||
- Use malloc.h for OS/2 [Necasek]
|
||||
@@ -721,7 +784,7 @@ Changes in 1.2.2.2 (30 December 2004)
|
||||
- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
|
||||
- Add updated make_vms.com [Coghlan], update README
|
||||
- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
|
||||
fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
|
||||
fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html
|
||||
- Add FAQ entry and comments in deflate.c on uninitialized memory access
|
||||
- Add Solaris 9 make options in configure [Gilbert]
|
||||
- Allow strerror() usage in gzio.c for STDC
|
||||
@@ -792,7 +855,7 @@ Changes in 1.2.1.1 (9 January 2004)
|
||||
- Fix a big fat bug in inftrees.c that prevented decoding valid
|
||||
dynamic blocks with only literals and no distance codes --
|
||||
Thanks to "Hot Emu" for the bug report and sample file
|
||||
- Add a note to puff.c on no distance codes case.
|
||||
- Add a note to puff.c on no distance codes case
|
||||
|
||||
Changes in 1.2.1 (17 November 2003)
|
||||
- Remove a tab in contrib/gzappend/gzappend.c
|
||||
@@ -1036,14 +1099,14 @@ Changes in 1.2.0 (9 March 2003)
|
||||
- Add contrib/puff/ simple inflate for deflate format description
|
||||
|
||||
Changes in 1.1.4 (11 March 2002)
|
||||
- ZFREE was repeated on same allocation on some error conditions.
|
||||
- ZFREE was repeated on same allocation on some error conditions
|
||||
This creates a security problem described in
|
||||
http://www.zlib.org/advisory-2002-03-11.txt
|
||||
- Returned incorrect error (Z_MEM_ERROR) on some invalid data
|
||||
- Avoid accesses before window for invalid distances with inflate window
|
||||
less than 32K.
|
||||
less than 32K
|
||||
- force windowBits > 8 to avoid a bug in the encoder for a window size
|
||||
of 256 bytes. (A complete fix will be available in 1.1.5).
|
||||
of 256 bytes. (A complete fix will be available in 1.1.5)
|
||||
|
||||
Changes in 1.1.3 (9 July 1998)
|
||||
- fix "an inflate input buffer bug that shows up on rare but persistent
|
||||
@@ -1117,7 +1180,7 @@ Changes in 1.1.1 (27 Feb 98)
|
||||
- remove block truncation heuristic which had very marginal effect for zlib
|
||||
(smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
|
||||
compression ratio on some files. This also allows inlining _tr_tally for
|
||||
matches in deflate_slow.
|
||||
matches in deflate_slow
|
||||
- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
|
||||
|
||||
Changes in 1.1.0 (24 Feb 98)
|
||||
@@ -1162,7 +1225,7 @@ Changes in 1.0.8 (27 Jan 1998)
|
||||
- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
|
||||
- use constant arrays for the static trees in trees.c instead of computing
|
||||
them at run time (thanks to Ken Raeburn for this suggestion). To create
|
||||
trees.h, compile with GEN_TREES_H and run "make test".
|
||||
trees.h, compile with GEN_TREES_H and run "make test"
|
||||
- check return code of example in "make test" and display result
|
||||
- pass minigzip command line options to file_compress
|
||||
- simplifying code of inflateSync to avoid gcc 2.8 bug
|
||||
@@ -1201,12 +1264,12 @@ Changes in 1.0.6 (19 Jan 1998)
|
||||
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
|
||||
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
|
||||
- Fix a deflate bug occurring only with compression level 0 (thanks to
|
||||
Andy Buckler for finding this one).
|
||||
- In minigzip, pass transparently also the first byte for .Z files.
|
||||
Andy Buckler for finding this one)
|
||||
- In minigzip, pass transparently also the first byte for .Z files
|
||||
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
|
||||
- check Z_FINISH in inflate (thanks to Marc Schluper)
|
||||
- Implement deflateCopy (thanks to Adam Costello)
|
||||
- make static libraries by default in configure, add --shared option.
|
||||
- make static libraries by default in configure, add --shared option
|
||||
- move MSDOS or Windows specific files to directory msdos
|
||||
- suppress the notion of partial flush to simplify the interface
|
||||
(but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
|
||||
@@ -1218,7 +1281,7 @@ Changes in 1.0.6 (19 Jan 1998)
|
||||
- added Makefile.nt (thanks to Stephen Williams)
|
||||
- added the unsupported "contrib" directory:
|
||||
contrib/asm386/ by Gilles Vollant <info@winimage.com>
|
||||
386 asm code replacing longest_match().
|
||||
386 asm code replacing longest_match()
|
||||
contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
A C++ I/O streams interface to the zlib gz* functions
|
||||
contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||
@@ -1226,7 +1289,7 @@ Changes in 1.0.6 (19 Jan 1998)
|
||||
contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
|
||||
A very simple tar.gz file extractor using zlib
|
||||
contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
|
||||
How to use compress(), uncompress() and the gz* functions from VB.
|
||||
How to use compress(), uncompress() and the gz* functions from VB
|
||||
- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
|
||||
level) in minigzip (thanks to Tom Lane)
|
||||
|
||||
@@ -1235,8 +1298,8 @@ Changes in 1.0.6 (19 Jan 1998)
|
||||
- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
|
||||
- add undocumented function zError to convert error code to string
|
||||
(for Tim Smithers)
|
||||
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
|
||||
- Use default memcpy for Symantec MSDOS compiler.
|
||||
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code
|
||||
- Use default memcpy for Symantec MSDOS compiler
|
||||
- Add EXPORT keyword for check_func (needed for Windows DLL)
|
||||
- add current directory to LD_LIBRARY_PATH for "make test"
|
||||
- create also a link for libz.so.1
|
||||
@@ -1249,7 +1312,7 @@ Changes in 1.0.6 (19 Jan 1998)
|
||||
- allow compilation with ANSI keywords only enabled for TurboC in large model
|
||||
- avoid "versionString"[0] (Borland bug)
|
||||
- add NEED_DUMMY_RETURN for Borland
|
||||
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
|
||||
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch)
|
||||
- allow compilation with CC
|
||||
- defined STDC for OS/2 (David Charlap)
|
||||
- limit external names to 8 chars for MVS (Thomas Lund)
|
||||
@@ -1259,7 +1322,7 @@ Changes in 1.0.6 (19 Jan 1998)
|
||||
- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
|
||||
- added makelcc.bat for lcc-win32 (Tom St Denis)
|
||||
- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
|
||||
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
|
||||
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion
|
||||
- check for unistd.h in configure (for off_t)
|
||||
- remove useless check parameter in inflate_blocks_free
|
||||
- avoid useless assignment of s->check to itself in inflate_blocks_new
|
||||
@@ -1280,7 +1343,7 @@ Changes in 1.0.5 (3 Jan 98)
|
||||
Changes in 1.0.4 (24 Jul 96)
|
||||
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
|
||||
bit, so the decompressor could decompress all the correct data but went
|
||||
on to attempt decompressing extra garbage data. This affected minigzip too.
|
||||
on to attempt decompressing extra garbage data. This affected minigzip too
|
||||
- zlibVersion and gzerror return const char* (needed for DLL)
|
||||
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
|
||||
- use z_error only for DEBUG (avoid problem with DLLs)
|
||||
@@ -1310,7 +1373,7 @@ Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
|
||||
- fix array overlay in deflate.c which sometimes caused bad compressed data
|
||||
- fix inflate bug with empty stored block
|
||||
- fix MSDOS medium model which was broken in 0.99
|
||||
- fix deflateParams() which could generate bad compressed data.
|
||||
- fix deflateParams() which could generate bad compressed data
|
||||
- Bytef is define'd instead of typedef'ed (work around Borland bug)
|
||||
- added an INDEX file
|
||||
- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
|
||||
@@ -1331,7 +1394,7 @@ Changes in 0.99 (27 Jan 96)
|
||||
- allow preset dictionary shared between compressor and decompressor
|
||||
- allow compression level 0 (no compression)
|
||||
- add deflateParams in zlib.h: allow dynamic change of compression level
|
||||
and compression strategy.
|
||||
and compression strategy
|
||||
- test large buffers and deflateParams in example.c
|
||||
- add optional "configure" to build zlib as a shared library
|
||||
- suppress Makefile.qnx, use configure instead
|
||||
@@ -1373,30 +1436,30 @@ Changes in 0.99 (27 Jan 96)
|
||||
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
|
||||
- use Z_BINARY instead of BINARY
|
||||
- document that gzclose after gzdopen will close the file
|
||||
- allow "a" as mode in gzopen.
|
||||
- allow "a" as mode in gzopen
|
||||
- fix error checking in gzread
|
||||
- allow skipping .gz extra-field on pipes
|
||||
- added reference to Perl interface in README
|
||||
- put the crc table in FAR data (I dislike more and more the medium model :)
|
||||
- added get_crc_table
|
||||
- added a dimension to all arrays (Borland C can't count).
|
||||
- added a dimension to all arrays (Borland C can't count)
|
||||
- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
|
||||
- guard against multiple inclusion of *.h (for precompiled header on Mac)
|
||||
- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
|
||||
- Watcom C pretends to be Microsoft C small model even in 32 bit mode
|
||||
- don't use unsized arrays to avoid silly warnings by Visual C++:
|
||||
warning C4746: 'inflate_mask' : unsized array treated as '__far'
|
||||
(what's wrong with far data in far model?).
|
||||
(what's wrong with far data in far model?)
|
||||
- define enum out of inflate_blocks_state to allow compilation with C++
|
||||
|
||||
Changes in 0.95 (16 Aug 95)
|
||||
- fix MSDOS small and medium model (now easier to adapt to any compiler)
|
||||
- inlined send_bits
|
||||
- fix the final (:-) bug for deflate with flush (output was correct but
|
||||
not completely flushed in rare occasions).
|
||||
not completely flushed in rare occasions)
|
||||
- default window size is same for compression and decompression
|
||||
(it's now sufficient to set MAX_WBITS in zconf.h).
|
||||
(it's now sufficient to set MAX_WBITS in zconf.h)
|
||||
- voidp -> voidpf and voidnp -> voidp (for consistency with other
|
||||
typedefs and because voidnp was not near in large model).
|
||||
typedefs and because voidnp was not near in large model)
|
||||
|
||||
Changes in 0.94 (13 Aug 95)
|
||||
- support MSDOS medium model
|
||||
@@ -1405,12 +1468,12 @@ Changes in 0.94 (13 Aug 95)
|
||||
- added support for VMS
|
||||
- allow a compression level in gzopen()
|
||||
- gzflush now calls fflush
|
||||
- For deflate with flush, flush even if no more input is provided.
|
||||
- For deflate with flush, flush even if no more input is provided
|
||||
- rename libgz.a as libz.a
|
||||
- avoid complex expression in infcodes.c triggering Turbo C bug
|
||||
- work around a problem with gcc on Alpha (in INSERT_STRING)
|
||||
- don't use inline functions (problem with some gcc versions)
|
||||
- allow renaming of Byte, uInt, etc... with #define.
|
||||
- allow renaming of Byte, uInt, etc... with #define
|
||||
- avoid warning about (unused) pointer before start of array in deflate.c
|
||||
- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
|
||||
- avoid reserved word 'new' in trees.c
|
||||
@@ -1429,7 +1492,7 @@ Changes in 0.92 (3 May 95)
|
||||
- no memcpy on Pyramid
|
||||
- suppressed inftest.c
|
||||
- optimized fill_window, put longest_match inline for gcc
|
||||
- optimized inflate on stored blocks.
|
||||
- optimized inflate on stored blocks
|
||||
- untabify all sources to simplify patches
|
||||
|
||||
Changes in 0.91 (2 May 95)
|
||||
@@ -1447,7 +1510,7 @@ Changes in 0.9 (1 May 95)
|
||||
- let again gzread copy uncompressed data unchanged (was working in 0.71)
|
||||
- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
|
||||
- added a test of inflateSync in example.c
|
||||
- moved MAX_WBITS to zconf.h because users might want to change that.
|
||||
- moved MAX_WBITS to zconf.h because users might want to change that
|
||||
- document explicitly that zalloc(64K) on MSDOS must return a normalized
|
||||
pointer (zero offset)
|
||||
- added Makefiles for Microsoft C, Turbo C, Borland C++
|
||||
@@ -1456,7 +1519,7 @@ Changes in 0.9 (1 May 95)
|
||||
Changes in 0.8 (29 April 95)
|
||||
- added fast inflate (inffast.c)
|
||||
- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
|
||||
is incompatible with previous versions of zlib which returned Z_OK.
|
||||
is incompatible with previous versions of zlib which returned Z_OK
|
||||
- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
|
||||
(actually that was not a compiler bug, see 0.81 above)
|
||||
- gzread no longer reads one extra byte in certain cases
|
||||
@@ -1466,50 +1529,50 @@ Changes in 0.8 (29 April 95)
|
||||
|
||||
Changes in 0.71 (14 April 95)
|
||||
- Fixed more MSDOS compilation problems :( There is still a bug with
|
||||
TurboC large model.
|
||||
TurboC large model
|
||||
|
||||
Changes in 0.7 (14 April 95)
|
||||
- Added full inflate support.
|
||||
- Added full inflate support
|
||||
- Simplified the crc32() interface. The pre- and post-conditioning
|
||||
(one's complement) is now done inside crc32(). WARNING: this is
|
||||
incompatible with previous versions; see zlib.h for the new usage.
|
||||
incompatible with previous versions; see zlib.h for the new usage
|
||||
|
||||
Changes in 0.61 (12 April 95)
|
||||
- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
|
||||
- workaround for a bug in TurboC. example and minigzip now work on MSDOS
|
||||
|
||||
Changes in 0.6 (11 April 95)
|
||||
- added minigzip.c
|
||||
- added gzdopen to reopen a file descriptor as gzFile
|
||||
- added transparent reading of non-gziped files in gzread.
|
||||
- added transparent reading of non-gziped files in gzread
|
||||
- fixed bug in gzread (don't read crc as data)
|
||||
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
|
||||
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose)
|
||||
- don't allocate big arrays in the stack (for MSDOS)
|
||||
- fix some MSDOS compilation problems
|
||||
|
||||
Changes in 0.5:
|
||||
- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
|
||||
not yet Z_FULL_FLUSH.
|
||||
not yet Z_FULL_FLUSH
|
||||
- support decompression but only in a single step (forced Z_FINISH)
|
||||
- added opaque object for zalloc and zfree.
|
||||
- added opaque object for zalloc and zfree
|
||||
- added deflateReset and inflateReset
|
||||
- added a variable zlib_version for consistency checking.
|
||||
- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
|
||||
Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
|
||||
- added a variable zlib_version for consistency checking
|
||||
- renamed the 'filter' parameter of deflateInit2 as 'strategy'
|
||||
Added Z_FILTERED and Z_HUFFMAN_ONLY constants
|
||||
|
||||
Changes in 0.4:
|
||||
- avoid "zip" everywhere, use zlib instead of ziplib.
|
||||
- avoid "zip" everywhere, use zlib instead of ziplib
|
||||
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
|
||||
if compression method == 8.
|
||||
if compression method == 8
|
||||
- added adler32 and crc32
|
||||
- renamed deflateOptions as deflateInit2, call one or the other but not both
|
||||
- added the method parameter for deflateInit2.
|
||||
- added the method parameter for deflateInit2
|
||||
- added inflateInit2
|
||||
- simplied considerably deflateInit and inflateInit by not supporting
|
||||
user-provided history buffer. This is supported only in deflateInit2
|
||||
and inflateInit2.
|
||||
and inflateInit2
|
||||
|
||||
Changes in 0.3:
|
||||
- prefix all macro names with Z_
|
||||
- use Z_FINISH instead of deflateEnd to finish compression.
|
||||
- use Z_FINISH instead of deflateEnd to finish compression
|
||||
- added Z_HUFFMAN_ONLY
|
||||
- added gzerror()
|
||||
|
||||
Vendored
+7
-4
@@ -1,6 +1,6 @@
|
||||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.11 is a general purpose data compression library. All the code is
|
||||
zlib 1.2.12 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
|
||||
@@ -31,7 +31,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
||||
issue of Dr. Dobb's Journal; a copy of the article is available at
|
||||
http://marknelson.us/1997/01/01/zlib-engine/ .
|
||||
|
||||
The changes made in version 1.2.11 are documented in the file ChangeLog.
|
||||
The changes made in version 1.2.12 are documented in the file ChangeLog.
|
||||
|
||||
Unsupported third party contributions are provided in directory contrib/ .
|
||||
|
||||
@@ -84,7 +84,7 @@ Acknowledgments:
|
||||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
(C) 1995-2022 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -108,7 +108,10 @@ Copyright notice:
|
||||
If you use the zlib library in a product, we would appreciate *not* receiving
|
||||
lengthy legal documents to sign. The sources are provided for free but without
|
||||
warranty of any kind. The library has been entirely written by Jean-loup
|
||||
Gailly and Mark Adler; it does not include third-party code.
|
||||
Gailly and Mark Adler; it does not include third-party code. We make all
|
||||
contributions to and distributions of this project solely in our personal
|
||||
capacity, and are not conveying any rights to any intellectual property of
|
||||
any third parties.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include in
|
||||
the file ChangeLog history information documenting your changes. Please read
|
||||
|
||||
Vendored
+984
-310
File diff suppressed because it is too large
Load Diff
Vendored
+9441
-436
File diff suppressed because it is too large
Load Diff
Vendored
+78
-30
@@ -1,5 +1,5 @@
|
||||
/* deflate.c -- compress data using the deflation algorithm
|
||||
* Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
* Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
#include "deflate.h"
|
||||
|
||||
const char deflate_copyright[] =
|
||||
" deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
|
||||
" deflate 1.2.12 Copyright 1995-2022 Jean-loup Gailly and Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
@@ -190,8 +190,11 @@ local const config configuration_table[10] = {
|
||||
* prev[] will be initialized on the fly.
|
||||
*/
|
||||
#define CLEAR_HASH(s) \
|
||||
s->head[s->hash_size-1] = NIL; \
|
||||
zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
|
||||
do { \
|
||||
s->head[s->hash_size-1] = NIL; \
|
||||
zmemzero((Bytef *)s->head, \
|
||||
(unsigned)(s->hash_size-1)*sizeof(*s->head)); \
|
||||
} while (0)
|
||||
|
||||
/* ===========================================================================
|
||||
* Slide the hash table when sliding the window down (could be avoided with 32
|
||||
@@ -252,11 +255,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
||||
int wrap = 1;
|
||||
static const char my_version[] = ZLIB_VERSION;
|
||||
|
||||
ushf *overlay;
|
||||
/* We overlay pending_buf and d_buf+l_buf. This works since the average
|
||||
* output size for (length,distance) codes is <= 24 bits.
|
||||
*/
|
||||
|
||||
if (version == Z_NULL || version[0] != my_version[0] ||
|
||||
stream_size != sizeof(z_stream)) {
|
||||
return Z_VERSION_ERROR;
|
||||
@@ -326,9 +324,47 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
||||
|
||||
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
|
||||
|
||||
overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
|
||||
s->pending_buf = (uchf *) overlay;
|
||||
s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
|
||||
/* We overlay pending_buf and sym_buf. This works since the average size
|
||||
* for length/distance pairs over any compressed block is assured to be 31
|
||||
* bits or less.
|
||||
*
|
||||
* Analysis: The longest fixed codes are a length code of 8 bits plus 5
|
||||
* extra bits, for lengths 131 to 257. The longest fixed distance codes are
|
||||
* 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
|
||||
* possible fixed-codes length/distance pair is then 31 bits total.
|
||||
*
|
||||
* sym_buf starts one-fourth of the way into pending_buf. So there are
|
||||
* three bytes in sym_buf for every four bytes in pending_buf. Each symbol
|
||||
* in sym_buf is three bytes -- two for the distance and one for the
|
||||
* literal/length. As each symbol is consumed, the pointer to the next
|
||||
* sym_buf value to read moves forward three bytes. From that symbol, up to
|
||||
* 31 bits are written to pending_buf. The closest the written pending_buf
|
||||
* bits gets to the next sym_buf symbol to read is just before the last
|
||||
* code is written. At that time, 31*(n-2) bits have been written, just
|
||||
* after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at
|
||||
* 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1
|
||||
* symbols are written.) The closest the writing gets to what is unread is
|
||||
* then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and
|
||||
* can range from 128 to 32768.
|
||||
*
|
||||
* Therefore, at a minimum, there are 142 bits of space between what is
|
||||
* written and what is read in the overlain buffers, so the symbols cannot
|
||||
* be overwritten by the compressed data. That space is actually 139 bits,
|
||||
* due to the three-bit fixed-code block header.
|
||||
*
|
||||
* That covers the case where either Z_FIXED is specified, forcing fixed
|
||||
* codes, or when the use of fixed codes is chosen, because that choice
|
||||
* results in a smaller compressed block than dynamic codes. That latter
|
||||
* condition then assures that the above analysis also covers all dynamic
|
||||
* blocks. A dynamic-code block will only be chosen to be emitted if it has
|
||||
* fewer bits than a fixed-code block would for the same set of symbols.
|
||||
* Therefore its average symbol length is assured to be less than 31. So
|
||||
* the compressed data for a dynamic block also cannot overwrite the
|
||||
* symbols from which it is being constructed.
|
||||
*/
|
||||
|
||||
s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
|
||||
s->pending_buf_size = (ulg)s->lit_bufsize * 4;
|
||||
|
||||
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
|
||||
s->pending_buf == Z_NULL) {
|
||||
@@ -337,8 +373,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
||||
deflateEnd (strm);
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
|
||||
s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
|
||||
s->sym_buf = s->pending_buf + s->lit_bufsize;
|
||||
s->sym_end = (s->lit_bufsize - 1) * 3;
|
||||
/* We avoid equality with lit_bufsize*3 because of wraparound at 64K
|
||||
* on 16 bit machines and because stored blocks are restricted to
|
||||
* 64K-1 bytes.
|
||||
*/
|
||||
|
||||
s->level = level;
|
||||
s->strategy = strategy;
|
||||
@@ -488,13 +528,13 @@ int ZEXPORT deflateResetKeep (strm)
|
||||
#ifdef GZIP
|
||||
s->wrap == 2 ? GZIP_STATE :
|
||||
#endif
|
||||
s->wrap ? INIT_STATE : BUSY_STATE;
|
||||
INIT_STATE;
|
||||
strm->adler =
|
||||
#ifdef GZIP
|
||||
s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
|
||||
#endif
|
||||
adler32(0L, Z_NULL, 0);
|
||||
s->last_flush = Z_NO_FLUSH;
|
||||
s->last_flush = -2;
|
||||
|
||||
_tr_init(s);
|
||||
|
||||
@@ -549,7 +589,8 @@ int ZEXPORT deflatePrime (strm, bits, value)
|
||||
|
||||
if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
s = strm->state;
|
||||
if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
|
||||
if (bits < 0 || bits > 16 ||
|
||||
s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
|
||||
return Z_BUF_ERROR;
|
||||
do {
|
||||
put = Buf_size - s->bi_valid;
|
||||
@@ -587,12 +628,12 @@ int ZEXPORT deflateParams(strm, level, strategy)
|
||||
func = configuration_table[s->level].func;
|
||||
|
||||
if ((strategy != s->strategy || func != configuration_table[level].func) &&
|
||||
s->high_water) {
|
||||
s->last_flush != -2) {
|
||||
/* Flush the last buffer: */
|
||||
int err = deflate(strm, Z_BLOCK);
|
||||
if (err == Z_STREAM_ERROR)
|
||||
return err;
|
||||
if (strm->avail_out == 0)
|
||||
if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
|
||||
return Z_BUF_ERROR;
|
||||
}
|
||||
if (s->level != level) {
|
||||
@@ -811,6 +852,8 @@ int ZEXPORT deflate (strm, flush)
|
||||
}
|
||||
|
||||
/* Write the header */
|
||||
if (s->status == INIT_STATE && s->wrap == 0)
|
||||
s->status = BUSY_STATE;
|
||||
if (s->status == INIT_STATE) {
|
||||
/* zlib header */
|
||||
uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
|
||||
@@ -1108,7 +1151,6 @@ int ZEXPORT deflateCopy (dest, source)
|
||||
#else
|
||||
deflate_state *ds;
|
||||
deflate_state *ss;
|
||||
ushf *overlay;
|
||||
|
||||
|
||||
if (deflateStateCheck(source) || dest == Z_NULL) {
|
||||
@@ -1128,8 +1170,7 @@ int ZEXPORT deflateCopy (dest, source)
|
||||
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
|
||||
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
|
||||
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
|
||||
overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
|
||||
ds->pending_buf = (uchf *) overlay;
|
||||
ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
|
||||
|
||||
if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
|
||||
ds->pending_buf == Z_NULL) {
|
||||
@@ -1143,8 +1184,7 @@ int ZEXPORT deflateCopy (dest, source)
|
||||
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
|
||||
|
||||
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
|
||||
ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
|
||||
ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
|
||||
ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
|
||||
|
||||
ds->l_desc.dyn_tree = ds->dyn_ltree;
|
||||
ds->d_desc.dyn_tree = ds->dyn_dtree;
|
||||
@@ -1513,6 +1553,8 @@ local void fill_window(s)
|
||||
s->match_start -= wsize;
|
||||
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
|
||||
s->block_start -= (long) wsize;
|
||||
if (s->insert > s->strstart)
|
||||
s->insert = s->strstart;
|
||||
slide_hash(s);
|
||||
more += wsize;
|
||||
}
|
||||
@@ -1742,6 +1784,7 @@ local block_state deflate_stored(s, flush)
|
||||
s->matches = 2; /* clear hash */
|
||||
zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
|
||||
s->strstart = s->w_size;
|
||||
s->insert = s->strstart;
|
||||
}
|
||||
else {
|
||||
if (s->window_size - s->strstart <= used) {
|
||||
@@ -1750,12 +1793,14 @@ local block_state deflate_stored(s, flush)
|
||||
zmemcpy(s->window, s->window + s->w_size, s->strstart);
|
||||
if (s->matches < 2)
|
||||
s->matches++; /* add a pending slide_hash() */
|
||||
if (s->insert > s->strstart)
|
||||
s->insert = s->strstart;
|
||||
}
|
||||
zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
|
||||
s->strstart += used;
|
||||
s->insert += MIN(used, s->w_size - s->insert);
|
||||
}
|
||||
s->block_start = s->strstart;
|
||||
s->insert += MIN(used, s->w_size - s->insert);
|
||||
}
|
||||
if (s->high_water < s->strstart)
|
||||
s->high_water = s->strstart;
|
||||
@@ -1770,7 +1815,7 @@ local block_state deflate_stored(s, flush)
|
||||
return block_done;
|
||||
|
||||
/* Fill the window with any remaining input. */
|
||||
have = s->window_size - s->strstart - 1;
|
||||
have = s->window_size - s->strstart;
|
||||
if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
|
||||
/* Slide the window down. */
|
||||
s->block_start -= s->w_size;
|
||||
@@ -1779,12 +1824,15 @@ local block_state deflate_stored(s, flush)
|
||||
if (s->matches < 2)
|
||||
s->matches++; /* add a pending slide_hash() */
|
||||
have += s->w_size; /* more space now */
|
||||
if (s->insert > s->strstart)
|
||||
s->insert = s->strstart;
|
||||
}
|
||||
if (have > s->strm->avail_in)
|
||||
have = s->strm->avail_in;
|
||||
if (have) {
|
||||
read_buf(s->strm, s->window + s->strstart, have);
|
||||
s->strstart += have;
|
||||
s->insert += MIN(have, s->w_size - s->insert);
|
||||
}
|
||||
if (s->high_water < s->strstart)
|
||||
s->high_water = s->strstart;
|
||||
@@ -1912,7 +1960,7 @@ local block_state deflate_fast(s, flush)
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
@@ -2043,7 +2091,7 @@ local block_state deflate_slow(s, flush)
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
@@ -2118,7 +2166,7 @@ local block_state deflate_rle(s, flush)
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
@@ -2157,7 +2205,7 @@ local block_state deflate_huff(s, flush)
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
||||
Vendored
+12
-15
@@ -1,5 +1,5 @@
|
||||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2016 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2018 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -217,7 +217,7 @@ typedef struct internal_state {
|
||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf *l_buf; /* buffer for literals or lengths */
|
||||
uchf *sym_buf; /* buffer for distances and literals/lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
@@ -239,13 +239,8 @@ typedef struct internal_state {
|
||||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf *d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
uInt sym_next; /* running index in sym_buf */
|
||||
uInt sym_end; /* symbol table full when sym_next reaches this */
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
@@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
|
||||
|
||||
# define _tr_tally_lit(s, c, flush) \
|
||||
{ uch cc = (c); \
|
||||
s->d_buf[s->last_lit] = 0; \
|
||||
s->l_buf[s->last_lit++] = cc; \
|
||||
s->sym_buf[s->sym_next++] = 0; \
|
||||
s->sym_buf[s->sym_next++] = 0; \
|
||||
s->sym_buf[s->sym_next++] = cc; \
|
||||
s->dyn_ltree[cc].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
flush = (s->sym_next == s->sym_end); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ uch len = (uch)(length); \
|
||||
ush dist = (ush)(distance); \
|
||||
s->d_buf[s->last_lit] = dist; \
|
||||
s->l_buf[s->last_lit++] = len; \
|
||||
s->sym_buf[s->sym_next++] = dist; \
|
||||
s->sym_buf[s->sym_next++] = dist >> 8; \
|
||||
s->sym_buf[s->sym_next++] = len; \
|
||||
dist--; \
|
||||
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
flush = (s->sym_next == s->sym_end); \
|
||||
}
|
||||
#else
|
||||
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
||||
|
||||
Vendored
+3
-2
@@ -1,5 +1,5 @@
|
||||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
|
||||
* Copyright (C) 2004-2019 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#if defined(_WIN32)
|
||||
# define WIDECHAR
|
||||
#endif
|
||||
|
||||
@@ -190,6 +190,7 @@ typedef struct {
|
||||
/* just for writing */
|
||||
int level; /* compression level */
|
||||
int strategy; /* compression strategy */
|
||||
int reset; /* true if a reset is pending after a Z_FINISH */
|
||||
/* seek request */
|
||||
z_off64_t skip; /* amount to skip (already rewound if backwards) */
|
||||
int seek; /* true if seek request pending */
|
||||
|
||||
Vendored
+5
-3
@@ -1,11 +1,11 @@
|
||||
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
||||
* Copyright (C) 2004-2017 Mark Adler
|
||||
* Copyright (C) 2004-2019 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
|
||||
#if defined(_WIN32) && !defined(__BORLANDC__)
|
||||
# define LSEEK _lseeki64
|
||||
#else
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
@@ -81,6 +81,8 @@ local void gz_reset(state)
|
||||
state->past = 0; /* have not read past end yet */
|
||||
state->how = LOOK; /* look for gzip header */
|
||||
}
|
||||
else /* for writing ... */
|
||||
state->reset = 0; /* no deflateReset pending */
|
||||
state->seek = 0; /* no seek request pending */
|
||||
gz_error(state, Z_OK, NULL); /* clear error */
|
||||
state->x.pos = 0; /* no uncompressed data yet */
|
||||
@@ -397,7 +399,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence)
|
||||
/* if within raw area while reading, just go there */
|
||||
if (state->mode == GZ_READ && state->how == COPY &&
|
||||
state->x.pos + offset >= 0) {
|
||||
ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
|
||||
ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
state->x.have = 0;
|
||||
|
||||
Vendored
+5
-7
@@ -1,5 +1,5 @@
|
||||
/* gzread.c -- zlib functions for reading gzip files
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
|
||||
* Copyright (C) 2004-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -314,9 +314,9 @@ local z_size_t gz_read(state, buf, len)
|
||||
got = 0;
|
||||
do {
|
||||
/* set n to the maximum amount of len that fits in an unsigned int */
|
||||
n = -1;
|
||||
n = (unsigned)-1;
|
||||
if (n > len)
|
||||
n = (int)len;
|
||||
n = (unsigned)len;
|
||||
|
||||
/* first just try copying data from the output buffer */
|
||||
if (state->x.have) {
|
||||
@@ -397,7 +397,7 @@ int ZEXPORT gzread(file, buf, len)
|
||||
}
|
||||
|
||||
/* read len or fewer bytes to buf */
|
||||
len = (int)gz_read(state, buf, len);
|
||||
len = (unsigned)gz_read(state, buf, len);
|
||||
|
||||
/* check for an error */
|
||||
if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
|
||||
@@ -447,7 +447,6 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file)
|
||||
int ZEXPORT gzgetc(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[1];
|
||||
gz_statep state;
|
||||
|
||||
@@ -469,8 +468,7 @@ int ZEXPORT gzgetc(file)
|
||||
}
|
||||
|
||||
/* nothing there -- try gz_read() */
|
||||
ret = (int)gz_read(state, buf, 1);
|
||||
return ret < 1 ? -1 : buf[0];
|
||||
return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
|
||||
}
|
||||
|
||||
int ZEXPORT gzgetc_(file)
|
||||
|
||||
Vendored
+25
-13
@@ -1,5 +1,5 @@
|
||||
/* gzwrite.c -- zlib functions for writing gzip files
|
||||
* Copyright (C) 2004-2017 Mark Adler
|
||||
* Copyright (C) 2004-2019 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -97,6 +97,15 @@ local int gz_comp(state, flush)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for a pending reset */
|
||||
if (state->reset) {
|
||||
/* don't start a new gzip member unless there is data to write */
|
||||
if (strm->avail_in == 0)
|
||||
return 0;
|
||||
deflateReset(strm);
|
||||
state->reset = 0;
|
||||
}
|
||||
|
||||
/* run deflate() on provided input until it produces no more output */
|
||||
ret = Z_OK;
|
||||
do {
|
||||
@@ -134,7 +143,7 @@ local int gz_comp(state, flush)
|
||||
|
||||
/* if that completed a deflate stream, allow another to start */
|
||||
if (flush == Z_FINISH)
|
||||
deflateReset(strm);
|
||||
state->reset = 1;
|
||||
|
||||
/* all done, no errors */
|
||||
return 0;
|
||||
@@ -209,7 +218,7 @@ local z_size_t gz_write(state, buf, len)
|
||||
state->in);
|
||||
copy = state->size - have;
|
||||
if (copy > len)
|
||||
copy = (int)len;
|
||||
copy = (unsigned)len;
|
||||
memcpy(state->in + have, buf, copy);
|
||||
state->strm.avail_in += copy;
|
||||
state->x.pos += copy;
|
||||
@@ -229,7 +238,7 @@ local z_size_t gz_write(state, buf, len)
|
||||
do {
|
||||
unsigned n = (unsigned)-1;
|
||||
if (n > len)
|
||||
n = (int)len;
|
||||
n = (unsigned)len;
|
||||
state->strm.avail_in = n;
|
||||
state->x.pos += n;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
@@ -349,12 +358,11 @@ int ZEXPORT gzputc(file, c)
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzputs(file, str)
|
||||
int ZEXPORT gzputs(file, s)
|
||||
gzFile file;
|
||||
const char *str;
|
||||
const char *s;
|
||||
{
|
||||
int ret;
|
||||
z_size_t len;
|
||||
z_size_t len, put;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
@@ -367,9 +375,13 @@ int ZEXPORT gzputs(file, str)
|
||||
return -1;
|
||||
|
||||
/* write string */
|
||||
len = strlen(str);
|
||||
ret = (int)gz_write(state, str, len);
|
||||
return ret == 0 && len != 0 ? -1 : ret;
|
||||
len = strlen(s);
|
||||
if ((int)len < 0 || (unsigned)len != len) {
|
||||
gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
|
||||
return -1;
|
||||
}
|
||||
put = gz_write(state, s, len);
|
||||
return put < len ? -1 : (int)len;
|
||||
}
|
||||
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
@@ -441,7 +453,7 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
|
||||
strm->avail_in = state->size;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return state->err;
|
||||
memcpy(state->in, state->in + state->size, left);
|
||||
memmove(state->in, state->in + state->size, left);
|
||||
strm->next_in = state->in;
|
||||
strm->avail_in = left;
|
||||
}
|
||||
@@ -540,7 +552,7 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
||||
strm->avail_in = state->size;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return state->err;
|
||||
memcpy(state->in, state->in + state->size, left);
|
||||
memmove(state->in, state->in + state->size, left);
|
||||
strm->next_in = state->in;
|
||||
strm->avail_in = left;
|
||||
}
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,5 @@
|
||||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* Copyright (C) 1995-2022 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -477,6 +477,7 @@ void FAR *out_desc;
|
||||
}
|
||||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN;
|
||||
/* fallthrough */
|
||||
|
||||
case LEN:
|
||||
/* use inflate_fast() if we have enough input and output */
|
||||
|
||||
Vendored
+14
-14
@@ -70,7 +70,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
code const FAR *dcode; /* local strm->distcode */
|
||||
unsigned lmask; /* mask for first level of length codes */
|
||||
unsigned dmask; /* mask for first level of distance codes */
|
||||
code here; /* retrieved table entry */
|
||||
code const *here; /* retrieved table entry */
|
||||
unsigned op; /* code bits, operation, extra bits, or */
|
||||
/* window position, window bytes to copy */
|
||||
unsigned len; /* match length, unused bytes */
|
||||
@@ -107,20 +107,20 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = lcode[hold & lmask];
|
||||
here = lcode + (hold & lmask);
|
||||
dolen:
|
||||
op = (unsigned)(here.bits);
|
||||
op = (unsigned)(here->bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here.op);
|
||||
op = (unsigned)(here->op);
|
||||
if (op == 0) { /* literal */
|
||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
*out++ = (unsigned char)(here.val);
|
||||
"inflate: literal 0x%02x\n", here->val));
|
||||
*out++ = (unsigned char)(here->val);
|
||||
}
|
||||
else if (op & 16) { /* length base */
|
||||
len = (unsigned)(here.val);
|
||||
len = (unsigned)(here->val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (op) {
|
||||
if (bits < op) {
|
||||
@@ -138,14 +138,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = dcode[hold & dmask];
|
||||
here = dcode + (hold & dmask);
|
||||
dodist:
|
||||
op = (unsigned)(here.bits);
|
||||
op = (unsigned)(here->bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here.op);
|
||||
op = (unsigned)(here->op);
|
||||
if (op & 16) { /* distance base */
|
||||
dist = (unsigned)(here.val);
|
||||
dist = (unsigned)(here->val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
@@ -264,7 +264,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level distance code */
|
||||
here = dcode[here.val + (hold & ((1U << op) - 1))];
|
||||
here = dcode + here->val + (hold & ((1U << op) - 1));
|
||||
goto dodist;
|
||||
}
|
||||
else {
|
||||
@@ -274,7 +274,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level length code */
|
||||
here = lcode[here.val + (hold & ((1U << op) - 1))];
|
||||
here = lcode + here->val + (hold & ((1U << op) - 1));
|
||||
goto dolen;
|
||||
}
|
||||
else if (op & 32) { /* end-of-block */
|
||||
|
||||
Vendored
+39
-8
@@ -1,5 +1,5 @@
|
||||
/* inflate.c -- zlib decompression
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* Copyright (C) 1995-2022 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -130,6 +130,7 @@ z_streamp strm;
|
||||
state->mode = HEAD;
|
||||
state->last = 0;
|
||||
state->havedict = 0;
|
||||
state->flags = -1;
|
||||
state->dmax = 32768U;
|
||||
state->head = Z_NULL;
|
||||
state->hold = 0;
|
||||
@@ -448,10 +449,10 @@ unsigned copy;
|
||||
|
||||
/* check function to use adler32() for zlib or crc32() for gzip */
|
||||
#ifdef GUNZIP
|
||||
# define UPDATE(check, buf, len) \
|
||||
# define UPDATE_CHECK(check, buf, len) \
|
||||
(state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
|
||||
#else
|
||||
# define UPDATE(check, buf, len) adler32(check, buf, len)
|
||||
# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
|
||||
#endif
|
||||
|
||||
/* check macros for header crc */
|
||||
@@ -671,7 +672,6 @@ int flush;
|
||||
state->mode = FLAGS;
|
||||
break;
|
||||
}
|
||||
state->flags = 0; /* expect zlib header */
|
||||
if (state->head != Z_NULL)
|
||||
state->head->done = -1;
|
||||
if (!(state->wrap & 1) || /* check if zlib header allowed */
|
||||
@@ -698,6 +698,7 @@ int flush;
|
||||
break;
|
||||
}
|
||||
state->dmax = 1U << len;
|
||||
state->flags = 0; /* indicate zlib header */
|
||||
Tracev((stderr, "inflate: zlib header ok\n"));
|
||||
strm->adler = state->check = adler32(0L, Z_NULL, 0);
|
||||
state->mode = hold & 0x200 ? DICTID : TYPE;
|
||||
@@ -723,6 +724,7 @@ int flush;
|
||||
CRC2(state->check, hold);
|
||||
INITBITS();
|
||||
state->mode = TIME;
|
||||
/* fallthrough */
|
||||
case TIME:
|
||||
NEEDBITS(32);
|
||||
if (state->head != Z_NULL)
|
||||
@@ -731,6 +733,7 @@ int flush;
|
||||
CRC4(state->check, hold);
|
||||
INITBITS();
|
||||
state->mode = OS;
|
||||
/* fallthrough */
|
||||
case OS:
|
||||
NEEDBITS(16);
|
||||
if (state->head != Z_NULL) {
|
||||
@@ -741,6 +744,7 @@ int flush;
|
||||
CRC2(state->check, hold);
|
||||
INITBITS();
|
||||
state->mode = EXLEN;
|
||||
/* fallthrough */
|
||||
case EXLEN:
|
||||
if (state->flags & 0x0400) {
|
||||
NEEDBITS(16);
|
||||
@@ -754,6 +758,7 @@ int flush;
|
||||
else if (state->head != Z_NULL)
|
||||
state->head->extra = Z_NULL;
|
||||
state->mode = EXTRA;
|
||||
/* fallthrough */
|
||||
case EXTRA:
|
||||
if (state->flags & 0x0400) {
|
||||
copy = state->length;
|
||||
@@ -776,6 +781,7 @@ int flush;
|
||||
}
|
||||
state->length = 0;
|
||||
state->mode = NAME;
|
||||
/* fallthrough */
|
||||
case NAME:
|
||||
if (state->flags & 0x0800) {
|
||||
if (have == 0) goto inf_leave;
|
||||
@@ -797,6 +803,7 @@ int flush;
|
||||
state->head->name = Z_NULL;
|
||||
state->length = 0;
|
||||
state->mode = COMMENT;
|
||||
/* fallthrough */
|
||||
case COMMENT:
|
||||
if (state->flags & 0x1000) {
|
||||
if (have == 0) goto inf_leave;
|
||||
@@ -817,6 +824,7 @@ int flush;
|
||||
else if (state->head != Z_NULL)
|
||||
state->head->comment = Z_NULL;
|
||||
state->mode = HCRC;
|
||||
/* fallthrough */
|
||||
case HCRC:
|
||||
if (state->flags & 0x0200) {
|
||||
NEEDBITS(16);
|
||||
@@ -840,6 +848,7 @@ int flush;
|
||||
strm->adler = state->check = ZSWAP32(hold);
|
||||
INITBITS();
|
||||
state->mode = DICT;
|
||||
/* fallthrough */
|
||||
case DICT:
|
||||
if (state->havedict == 0) {
|
||||
RESTORE();
|
||||
@@ -847,8 +856,10 @@ int flush;
|
||||
}
|
||||
strm->adler = state->check = adler32(0L, Z_NULL, 0);
|
||||
state->mode = TYPE;
|
||||
/* fallthrough */
|
||||
case TYPE:
|
||||
if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
|
||||
/* fallthrough */
|
||||
case TYPEDO:
|
||||
if (state->last) {
|
||||
BYTEBITS();
|
||||
@@ -899,8 +910,10 @@ int flush;
|
||||
INITBITS();
|
||||
state->mode = COPY_;
|
||||
if (flush == Z_TREES) goto inf_leave;
|
||||
/* fallthrough */
|
||||
case COPY_:
|
||||
state->mode = COPY;
|
||||
/* fallthrough */
|
||||
case COPY:
|
||||
copy = state->length;
|
||||
if (copy) {
|
||||
@@ -936,6 +949,7 @@ int flush;
|
||||
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||
state->have = 0;
|
||||
state->mode = LENLENS;
|
||||
/* fallthrough */
|
||||
case LENLENS:
|
||||
while (state->have < state->ncode) {
|
||||
NEEDBITS(3);
|
||||
@@ -957,6 +971,7 @@ int flush;
|
||||
Tracev((stderr, "inflate: code lengths ok\n"));
|
||||
state->have = 0;
|
||||
state->mode = CODELENS;
|
||||
/* fallthrough */
|
||||
case CODELENS:
|
||||
while (state->have < state->nlen + state->ndist) {
|
||||
for (;;) {
|
||||
@@ -1040,8 +1055,10 @@ int flush;
|
||||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN_;
|
||||
if (flush == Z_TREES) goto inf_leave;
|
||||
/* fallthrough */
|
||||
case LEN_:
|
||||
state->mode = LEN;
|
||||
/* fallthrough */
|
||||
case LEN:
|
||||
if (have >= 6 && left >= 258) {
|
||||
RESTORE();
|
||||
@@ -1091,6 +1108,7 @@ int flush;
|
||||
}
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
state->mode = LENEXT;
|
||||
/* fallthrough */
|
||||
case LENEXT:
|
||||
if (state->extra) {
|
||||
NEEDBITS(state->extra);
|
||||
@@ -1101,6 +1119,7 @@ int flush;
|
||||
Tracevv((stderr, "inflate: length %u\n", state->length));
|
||||
state->was = state->length;
|
||||
state->mode = DIST;
|
||||
/* fallthrough */
|
||||
case DIST:
|
||||
for (;;) {
|
||||
here = state->distcode[BITS(state->distbits)];
|
||||
@@ -1128,6 +1147,7 @@ int flush;
|
||||
state->offset = (unsigned)here.val;
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
state->mode = DISTEXT;
|
||||
/* fallthrough */
|
||||
case DISTEXT:
|
||||
if (state->extra) {
|
||||
NEEDBITS(state->extra);
|
||||
@@ -1144,6 +1164,7 @@ int flush;
|
||||
#endif
|
||||
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
||||
state->mode = MATCH;
|
||||
/* fallthrough */
|
||||
case MATCH:
|
||||
if (left == 0) goto inf_leave;
|
||||
copy = out - left;
|
||||
@@ -1203,7 +1224,7 @@ int flush;
|
||||
state->total += out;
|
||||
if ((state->wrap & 4) && out)
|
||||
strm->adler = state->check =
|
||||
UPDATE(state->check, put - out, out);
|
||||
UPDATE_CHECK(state->check, put - out, out);
|
||||
out = left;
|
||||
if ((state->wrap & 4) && (
|
||||
#ifdef GUNZIP
|
||||
@@ -1219,10 +1240,11 @@ int flush;
|
||||
}
|
||||
#ifdef GUNZIP
|
||||
state->mode = LENGTH;
|
||||
/* fallthrough */
|
||||
case LENGTH:
|
||||
if (state->wrap && state->flags) {
|
||||
NEEDBITS(32);
|
||||
if (hold != (state->total & 0xffffffffUL)) {
|
||||
if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
|
||||
strm->msg = (char *)"incorrect length check";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
@@ -1232,6 +1254,7 @@ int flush;
|
||||
}
|
||||
#endif
|
||||
state->mode = DONE;
|
||||
/* fallthrough */
|
||||
case DONE:
|
||||
ret = Z_STREAM_END;
|
||||
goto inf_leave;
|
||||
@@ -1241,6 +1264,7 @@ int flush;
|
||||
case MEM:
|
||||
return Z_MEM_ERROR;
|
||||
case SYNC:
|
||||
/* fallthrough */
|
||||
default:
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
@@ -1266,7 +1290,7 @@ int flush;
|
||||
state->total += out;
|
||||
if ((state->wrap & 4) && out)
|
||||
strm->adler = state->check =
|
||||
UPDATE(state->check, strm->next_out - out, out);
|
||||
UPDATE_CHECK(state->check, strm->next_out - out, out);
|
||||
strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
|
||||
(state->mode == TYPE ? 128 : 0) +
|
||||
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
|
||||
@@ -1402,6 +1426,7 @@ int ZEXPORT inflateSync(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
unsigned len; /* number of bytes to look at or looked at */
|
||||
int flags; /* temporary to save header status */
|
||||
unsigned long in, out; /* temporary to save total_in and total_out */
|
||||
unsigned char buf[4]; /* to restore bit buffer to byte string */
|
||||
struct inflate_state FAR *state;
|
||||
@@ -1434,9 +1459,15 @@ z_streamp strm;
|
||||
|
||||
/* return no joy or set up to restart inflate() on a new block */
|
||||
if (state->have != 4) return Z_DATA_ERROR;
|
||||
if (state->flags == -1)
|
||||
state->wrap = 0; /* if no header yet, treat as raw */
|
||||
else
|
||||
state->wrap &= ~4; /* no point in computing a check value now */
|
||||
flags = state->flags;
|
||||
in = strm->total_in; out = strm->total_out;
|
||||
inflateReset(strm);
|
||||
strm->total_in = in; strm->total_out = out;
|
||||
state->flags = flags;
|
||||
state->mode = TYPE;
|
||||
return Z_OK;
|
||||
}
|
||||
@@ -1532,7 +1563,7 @@ int check;
|
||||
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
if (check)
|
||||
if (check && state->wrap)
|
||||
state->wrap |= 4;
|
||||
else
|
||||
state->wrap &= ~4;
|
||||
|
||||
Vendored
+3
-2
@@ -1,5 +1,5 @@
|
||||
/* inflate.h -- internal inflate state definition
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* Copyright (C) 1995-2019 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -86,7 +86,8 @@ struct inflate_state {
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
|
||||
bit 2 true to validate check value */
|
||||
int havedict; /* true if dictionary provided */
|
||||
int flags; /* gzip header method and flags (0 if zlib) */
|
||||
int flags; /* gzip header method and flags, 0 if zlib, or
|
||||
-1 if raw or no header yet */
|
||||
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
||||
unsigned long check; /* protected copy of check value */
|
||||
unsigned long total; /* protected copy of output count */
|
||||
|
||||
Vendored
+3
-3
@@ -1,5 +1,5 @@
|
||||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2017 Mark Adler
|
||||
* Copyright (C) 1995-2022 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
|
||||
" inflate 1.2.12 Copyright 1995-2022 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
@@ -62,7 +62,7 @@ unsigned short FAR *work;
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
|
||||
Vendored
+27
-48
@@ -1,5 +1,5 @@
|
||||
/* trees.c -- output deflated data using Huffman coding
|
||||
* Copyright (C) 1995-2017 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2021 Jean-loup Gailly
|
||||
* detect_data_type() function provided freely by Cosmin Truta, 2006
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
@@ -149,7 +149,7 @@ local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
|
||||
local void compress_block OF((deflate_state *s, const ct_data *ltree,
|
||||
const ct_data *dtree));
|
||||
local int detect_data_type OF((deflate_state *s));
|
||||
local unsigned bi_reverse OF((unsigned value, int length));
|
||||
local unsigned bi_reverse OF((unsigned code, int len));
|
||||
local void bi_windup OF((deflate_state *s));
|
||||
local void bi_flush OF((deflate_state *s));
|
||||
|
||||
@@ -416,7 +416,7 @@ local void init_block(s)
|
||||
|
||||
s->dyn_ltree[END_BLOCK].Freq = 1;
|
||||
s->opt_len = s->static_len = 0L;
|
||||
s->last_lit = s->matches = 0;
|
||||
s->sym_next = s->matches = 0;
|
||||
}
|
||||
|
||||
#define SMALLEST 1
|
||||
@@ -870,7 +870,8 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
|
||||
bi_windup(s); /* align on byte boundary */
|
||||
put_short(s, (ush)stored_len);
|
||||
put_short(s, (ush)~stored_len);
|
||||
zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
|
||||
if (stored_len)
|
||||
zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
|
||||
s->pending += stored_len;
|
||||
#ifdef ZLIB_DEBUG
|
||||
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
|
||||
@@ -947,7 +948,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
||||
|
||||
Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
|
||||
opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
|
||||
s->last_lit));
|
||||
s->sym_next / 3));
|
||||
|
||||
if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
|
||||
|
||||
@@ -1016,8 +1017,9 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
|
||||
unsigned dist; /* distance of matched string */
|
||||
unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
|
||||
{
|
||||
s->d_buf[s->last_lit] = (ush)dist;
|
||||
s->l_buf[s->last_lit++] = (uch)lc;
|
||||
s->sym_buf[s->sym_next++] = dist;
|
||||
s->sym_buf[s->sym_next++] = dist >> 8;
|
||||
s->sym_buf[s->sym_next++] = lc;
|
||||
if (dist == 0) {
|
||||
/* lc is the unmatched char */
|
||||
s->dyn_ltree[lc].Freq++;
|
||||
@@ -1032,30 +1034,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
|
||||
s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
|
||||
s->dyn_dtree[d_code(dist)].Freq++;
|
||||
}
|
||||
|
||||
#ifdef TRUNCATE_BLOCK
|
||||
/* Try to guess if it is profitable to stop the current block here */
|
||||
if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
|
||||
/* Compute an upper bound for the compressed length */
|
||||
ulg out_length = (ulg)s->last_lit*8L;
|
||||
ulg in_length = (ulg)((long)s->strstart - s->block_start);
|
||||
int dcode;
|
||||
for (dcode = 0; dcode < D_CODES; dcode++) {
|
||||
out_length += (ulg)s->dyn_dtree[dcode].Freq *
|
||||
(5L+extra_dbits[dcode]);
|
||||
}
|
||||
out_length >>= 3;
|
||||
Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
|
||||
s->last_lit, in_length, out_length,
|
||||
100L - out_length*100L/in_length));
|
||||
if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
|
||||
}
|
||||
#endif
|
||||
return (s->last_lit == s->lit_bufsize-1);
|
||||
/* We avoid equality with lit_bufsize because of wraparound at 64K
|
||||
* on 16 bit machines and because stored blocks are restricted to
|
||||
* 64K-1 bytes.
|
||||
*/
|
||||
return (s->sym_next == s->sym_end);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
@@ -1068,13 +1047,14 @@ local void compress_block(s, ltree, dtree)
|
||||
{
|
||||
unsigned dist; /* distance of matched string */
|
||||
int lc; /* match length or unmatched char (if dist == 0) */
|
||||
unsigned lx = 0; /* running index in l_buf */
|
||||
unsigned sx = 0; /* running index in sym_buf */
|
||||
unsigned code; /* the code to send */
|
||||
int extra; /* number of extra bits to send */
|
||||
|
||||
if (s->last_lit != 0) do {
|
||||
dist = s->d_buf[lx];
|
||||
lc = s->l_buf[lx++];
|
||||
if (s->sym_next != 0) do {
|
||||
dist = s->sym_buf[sx++] & 0xff;
|
||||
dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
|
||||
lc = s->sym_buf[sx++];
|
||||
if (dist == 0) {
|
||||
send_code(s, lc, ltree); /* send a literal byte */
|
||||
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
|
||||
@@ -1099,11 +1079,10 @@ local void compress_block(s, ltree, dtree)
|
||||
}
|
||||
} /* literal or match pair ? */
|
||||
|
||||
/* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
|
||||
Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
|
||||
"pendingBuf overflow");
|
||||
/* Check that the overlay between pending_buf and sym_buf is ok: */
|
||||
Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
|
||||
|
||||
} while (lx < s->last_lit);
|
||||
} while (sx < s->sym_next);
|
||||
|
||||
send_code(s, END_BLOCK, ltree);
|
||||
}
|
||||
@@ -1112,9 +1091,9 @@ local void compress_block(s, ltree, dtree)
|
||||
* Check if the data type is TEXT or BINARY, using the following algorithm:
|
||||
* - TEXT if the two conditions below are satisfied:
|
||||
* a) There are no non-portable control characters belonging to the
|
||||
* "black list" (0..6, 14..25, 28..31).
|
||||
* "block list" (0..6, 14..25, 28..31).
|
||||
* b) There is at least one printable character belonging to the
|
||||
* "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
|
||||
* "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
|
||||
* - BINARY otherwise.
|
||||
* - The following partially-portable control characters form a
|
||||
* "gray list" that is ignored in this detection algorithm:
|
||||
@@ -1124,19 +1103,19 @@ local void compress_block(s, ltree, dtree)
|
||||
local int detect_data_type(s)
|
||||
deflate_state *s;
|
||||
{
|
||||
/* black_mask is the bit mask of black-listed bytes
|
||||
/* block_mask is the bit mask of block-listed bytes
|
||||
* set bits 0..6, 14..25, and 28..31
|
||||
* 0xf3ffc07f = binary 11110011111111111100000001111111
|
||||
*/
|
||||
unsigned long black_mask = 0xf3ffc07fUL;
|
||||
unsigned long block_mask = 0xf3ffc07fUL;
|
||||
int n;
|
||||
|
||||
/* Check for non-textual ("black-listed") bytes. */
|
||||
for (n = 0; n <= 31; n++, black_mask >>= 1)
|
||||
if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
|
||||
/* Check for non-textual ("block-listed") bytes. */
|
||||
for (n = 0; n <= 31; n++, block_mask >>= 1)
|
||||
if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
|
||||
return Z_BINARY;
|
||||
|
||||
/* Check for textual ("white-listed") bytes. */
|
||||
/* Check for textual ("allow-listed") bytes. */
|
||||
if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
|
||||
|| s->dyn_ltree[13].Freq != 0)
|
||||
return Z_TEXT;
|
||||
@@ -1144,7 +1123,7 @@ local int detect_data_type(s)
|
||||
if (s->dyn_ltree[n].Freq != 0)
|
||||
return Z_TEXT;
|
||||
|
||||
/* There are no "black-listed" or "white-listed" bytes:
|
||||
/* There are no "block-listed" or "allow-listed" bytes:
|
||||
* this stream either is empty or has tolerated ("gray-listed") bytes only.
|
||||
*/
|
||||
return Z_BINARY;
|
||||
|
||||
Vendored
+123
-100
@@ -1,7 +1,7 @@
|
||||
/* zlib.h -- interface of the 'zlib' general purpose compression library
|
||||
version 1.2.11, January 15th, 2017
|
||||
version 1.2.12, March 11th, 2022
|
||||
|
||||
Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -37,11 +37,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ZLIB_VERSION "1.2.11"
|
||||
#define ZLIB_VERNUM 0x12b0
|
||||
#define ZLIB_VERSION "1.2.12"
|
||||
#define ZLIB_VERNUM 0x12c0
|
||||
#define ZLIB_VER_MAJOR 1
|
||||
#define ZLIB_VER_MINOR 2
|
||||
#define ZLIB_VER_REVISION 11
|
||||
#define ZLIB_VER_REVISION 12
|
||||
#define ZLIB_VER_SUBREVISION 0
|
||||
|
||||
/*
|
||||
@@ -543,8 +543,7 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
|
||||
int strategy));
|
||||
|
||||
This is another version of deflateInit with more compression options. The
|
||||
fields next_in, zalloc, zfree and opaque must be initialized before by the
|
||||
caller.
|
||||
fields zalloc, zfree and opaque must be initialized before by the caller.
|
||||
|
||||
The method parameter is the compression method. It must be Z_DEFLATED in
|
||||
this version of the library.
|
||||
@@ -712,11 +711,12 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
|
||||
used to switch between compression and straight copy of the input data, or
|
||||
to switch to a different kind of input data requiring a different strategy.
|
||||
If the compression approach (which is a function of the level) or the
|
||||
strategy is changed, and if any input has been consumed in a previous
|
||||
deflate() call, then the input available so far is compressed with the old
|
||||
level and strategy using deflate(strm, Z_BLOCK). There are three approaches
|
||||
for the compression levels 0, 1..3, and 4..9 respectively. The new level
|
||||
and strategy will take effect at the next call of deflate().
|
||||
strategy is changed, and if there have been any deflate() calls since the
|
||||
state was initialized or reset, then the input available so far is
|
||||
compressed with the old level and strategy using deflate(strm, Z_BLOCK).
|
||||
There are three approaches for the compression levels 0, 1..3, and 4..9
|
||||
respectively. The new level and strategy will take effect at the next call
|
||||
of deflate().
|
||||
|
||||
If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
|
||||
not have enough output space to complete, then the parameter change will not
|
||||
@@ -865,9 +865,11 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
|
||||
detection, or add 16 to decode only the gzip format (the zlib format will
|
||||
return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
|
||||
CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
|
||||
below), inflate() will not automatically decode concatenated gzip streams.
|
||||
inflate() will return Z_STREAM_END at the end of the gzip stream. The state
|
||||
would need to be reset to continue decoding a subsequent gzip stream.
|
||||
below), inflate() will *not* automatically decode concatenated gzip members.
|
||||
inflate() will return Z_STREAM_END at the end of the gzip member. The state
|
||||
would need to be reset to continue decoding a subsequent gzip member. This
|
||||
*must* be done if there is more data after a gzip member, in order for the
|
||||
decompression to be compliant with the gzip standard (RFC 1952).
|
||||
|
||||
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
|
||||
@@ -1302,14 +1304,14 @@ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
|
||||
/*
|
||||
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
|
||||
|
||||
Opens a gzip (.gz) file for reading or writing. The mode parameter is as
|
||||
in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
|
||||
a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
|
||||
compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
|
||||
for fixed code compression as in "wb9F". (See the description of
|
||||
deflateInit2 for more information about the strategy parameter.) 'T' will
|
||||
request transparent writing or appending with no compression and not using
|
||||
the gzip format.
|
||||
Open the gzip (.gz) file at path for reading and decompressing, or
|
||||
compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
|
||||
but can also include a compression level ("wb9") or a strategy: 'f' for
|
||||
filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
|
||||
'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
|
||||
as in "wb9F". (See the description of deflateInit2 for more information
|
||||
about the strategy parameter.) 'T' will request transparent writing or
|
||||
appending with no compression and not using the gzip format.
|
||||
|
||||
"a" can be used instead of "w" to request that the gzip stream that will
|
||||
be written be appended to the file. "+" will result in an error, since
|
||||
@@ -1339,9 +1341,9 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
|
||||
|
||||
ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
|
||||
/*
|
||||
gzdopen associates a gzFile with the file descriptor fd. File descriptors
|
||||
are obtained from calls like open, dup, creat, pipe or fileno (if the file
|
||||
has been previously opened with fopen). The mode parameter is as in gzopen.
|
||||
Associate a gzFile with the file descriptor fd. File descriptors are
|
||||
obtained from calls like open, dup, creat, pipe or fileno (if the file has
|
||||
been previously opened with fopen). The mode parameter is as in gzopen.
|
||||
|
||||
The next call of gzclose on the returned gzFile will also close the file
|
||||
descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
|
||||
@@ -1362,13 +1364,13 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
|
||||
|
||||
ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
|
||||
/*
|
||||
Set the internal buffer size used by this library's functions. The
|
||||
default buffer size is 8192 bytes. This function must be called after
|
||||
gzopen() or gzdopen(), and before any other calls that read or write the
|
||||
file. The buffer memory allocation is always deferred to the first read or
|
||||
write. Three times that size in buffer space is allocated. A larger buffer
|
||||
size of, for example, 64K or 128K bytes will noticeably increase the speed
|
||||
of decompression (reading).
|
||||
Set the internal buffer size used by this library's functions for file to
|
||||
size. The default buffer size is 8192 bytes. This function must be called
|
||||
after gzopen() or gzdopen(), and before any other calls that read or write
|
||||
the file. The buffer memory allocation is always deferred to the first read
|
||||
or write. Three times that size in buffer space is allocated. A larger
|
||||
buffer size of, for example, 64K or 128K bytes will noticeably increase the
|
||||
speed of decompression (reading).
|
||||
|
||||
The new buffer size also affects the maximum length for gzprintf().
|
||||
|
||||
@@ -1378,9 +1380,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
|
||||
|
||||
ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
|
||||
/*
|
||||
Dynamically update the compression level or strategy. See the description
|
||||
of deflateInit2 for the meaning of these parameters. Previously provided
|
||||
data is flushed before the parameter change.
|
||||
Dynamically update the compression level and strategy for file. See the
|
||||
description of deflateInit2 for the meaning of these parameters. Previously
|
||||
provided data is flushed before applying the parameter changes.
|
||||
|
||||
gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
|
||||
opened for writing, Z_ERRNO if there is an error writing the flushed data,
|
||||
@@ -1389,7 +1391,7 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
|
||||
|
||||
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
|
||||
/*
|
||||
Reads the given number of uncompressed bytes from the compressed file. If
|
||||
Read and decompress up to len uncompressed bytes from file into buf. If
|
||||
the input file is not in gzip format, gzread copies the given number of
|
||||
bytes into the buffer directly from the file.
|
||||
|
||||
@@ -1420,11 +1422,11 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
|
||||
ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
|
||||
gzFile file));
|
||||
/*
|
||||
Read up to nitems items of size size from file to buf, otherwise operating
|
||||
as gzread() does. This duplicates the interface of stdio's fread(), with
|
||||
size_t request and return types. If the library defines size_t, then
|
||||
z_size_t is identical to size_t. If not, then z_size_t is an unsigned
|
||||
integer type that can contain a pointer.
|
||||
Read and decompress up to nitems items of size size from file into buf,
|
||||
otherwise operating as gzread() does. This duplicates the interface of
|
||||
stdio's fread(), with size_t request and return types. If the library
|
||||
defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
|
||||
is an unsigned integer type that can contain a pointer.
|
||||
|
||||
gzfread() returns the number of full items read of size size, or zero if
|
||||
the end of the file was reached and a full item could not be read, or if
|
||||
@@ -1443,18 +1445,16 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
|
||||
file, reseting and retrying on end-of-file, when size is not 1.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
|
||||
voidpc buf, unsigned len));
|
||||
ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
|
||||
/*
|
||||
Writes the given number of uncompressed bytes into the compressed file.
|
||||
gzwrite returns the number of uncompressed bytes written or 0 in case of
|
||||
error.
|
||||
Compress and write the len uncompressed bytes at buf to file. gzwrite
|
||||
returns the number of uncompressed bytes written or 0 in case of error.
|
||||
*/
|
||||
|
||||
ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
|
||||
z_size_t nitems, gzFile file));
|
||||
/*
|
||||
gzfwrite() writes nitems items of size size from buf to file, duplicating
|
||||
Compress and write nitems items of size size from buf to file, duplicating
|
||||
the interface of stdio's fwrite(), with size_t request and return types. If
|
||||
the library defines size_t, then z_size_t is identical to size_t. If not,
|
||||
then z_size_t is an unsigned integer type that can contain a pointer.
|
||||
@@ -1467,22 +1467,22 @@ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
|
||||
|
||||
ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
|
||||
/*
|
||||
Converts, formats, and writes the arguments to the compressed file under
|
||||
control of the format string, as in fprintf. gzprintf returns the number of
|
||||
Convert, format, compress, and write the arguments (...) to file under
|
||||
control of the string format, as in fprintf. gzprintf returns the number of
|
||||
uncompressed bytes actually written, or a negative zlib error code in case
|
||||
of error. The number of uncompressed bytes written is limited to 8191, or
|
||||
one less than the buffer size given to gzbuffer(). The caller should assure
|
||||
that this limit is not exceeded. If it is exceeded, then gzprintf() will
|
||||
return an error (0) with nothing written. In this case, there may also be a
|
||||
buffer overflow with unpredictable consequences, which is possible only if
|
||||
zlib was compiled with the insecure functions sprintf() or vsprintf()
|
||||
zlib was compiled with the insecure functions sprintf() or vsprintf(),
|
||||
because the secure snprintf() or vsnprintf() functions were not available.
|
||||
This can be determined using zlibCompileFlags().
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
|
||||
/*
|
||||
Writes the given null-terminated string to the compressed file, excluding
|
||||
Compress and write the given null-terminated string s to file, excluding
|
||||
the terminating null character.
|
||||
|
||||
gzputs returns the number of characters written, or -1 in case of error.
|
||||
@@ -1490,11 +1490,12 @@ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
|
||||
|
||||
ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
|
||||
/*
|
||||
Reads bytes from the compressed file until len-1 characters are read, or a
|
||||
newline character is read and transferred to buf, or an end-of-file
|
||||
condition is encountered. If any characters are read or if len == 1, the
|
||||
string is terminated with a null character. If no characters are read due
|
||||
to an end-of-file or len < 1, then the buffer is left untouched.
|
||||
Read and decompress bytes from file into buf, until len-1 characters are
|
||||
read, or until a newline character is read and transferred to buf, or an
|
||||
end-of-file condition is encountered. If any characters are read or if len
|
||||
is one, the string is terminated with a null character. If no characters
|
||||
are read due to an end-of-file or len is less than one, then the buffer is
|
||||
left untouched.
|
||||
|
||||
gzgets returns buf which is a null-terminated string, or it returns NULL
|
||||
for end-of-file or in case of error. If there was an error, the contents at
|
||||
@@ -1503,13 +1504,13 @@ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
|
||||
|
||||
ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
|
||||
/*
|
||||
Writes c, converted to an unsigned char, into the compressed file. gzputc
|
||||
Compress and write c, converted to an unsigned char, into file. gzputc
|
||||
returns the value that was written, or -1 in case of error.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
|
||||
/*
|
||||
Reads one byte from the compressed file. gzgetc returns this byte or -1
|
||||
Read and decompress one byte from file. gzgetc returns this byte or -1
|
||||
in case of end of file or error. This is implemented as a macro for speed.
|
||||
As such, it does not do all of the checking the other functions do. I.e.
|
||||
it does not check to see if file is NULL, nor whether the structure file
|
||||
@@ -1518,8 +1519,8 @@ ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
|
||||
|
||||
ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
|
||||
/*
|
||||
Push one character back onto the stream to be read as the first character
|
||||
on the next read. At least one character of push-back is allowed.
|
||||
Push c back onto the stream for file to be read as the first character on
|
||||
the next read. At least one character of push-back is always allowed.
|
||||
gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
|
||||
fail if c is -1, and may fail if a character has been pushed but not read
|
||||
yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
|
||||
@@ -1530,9 +1531,9 @@ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
|
||||
|
||||
ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
|
||||
/*
|
||||
Flushes all pending output into the compressed file. The parameter flush
|
||||
is as in the deflate() function. The return value is the zlib error number
|
||||
(see function gzerror below). gzflush is only permitted when writing.
|
||||
Flush all pending output to file. The parameter flush is as in the
|
||||
deflate() function. The return value is the zlib error number (see function
|
||||
gzerror below). gzflush is only permitted when writing.
|
||||
|
||||
If the flush parameter is Z_FINISH, the remaining data is written and the
|
||||
gzip stream is completed in the output. If gzwrite() is called again, a new
|
||||
@@ -1547,8 +1548,8 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
|
||||
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
|
||||
z_off_t offset, int whence));
|
||||
|
||||
Sets the starting position for the next gzread or gzwrite on the given
|
||||
compressed file. The offset represents a number of bytes in the
|
||||
Set the starting position to offset relative to whence for the next gzread
|
||||
or gzwrite on file. The offset represents a number of bytes in the
|
||||
uncompressed data stream. The whence parameter is defined as in lseek(2);
|
||||
the value SEEK_END is not supported.
|
||||
|
||||
@@ -1565,18 +1566,18 @@ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
|
||||
|
||||
ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
|
||||
/*
|
||||
Rewinds the given file. This function is supported only for reading.
|
||||
Rewind file. This function is supported only for reading.
|
||||
|
||||
gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
|
||||
gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
|
||||
*/
|
||||
|
||||
/*
|
||||
ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
|
||||
|
||||
Returns the starting position for the next gzread or gzwrite on the given
|
||||
compressed file. This position represents a number of bytes in the
|
||||
uncompressed data stream, and is zero when starting, even if appending or
|
||||
reading a gzip stream from the middle of a file using gzdopen().
|
||||
Return the starting position for the next gzread or gzwrite on file.
|
||||
This position represents a number of bytes in the uncompressed data stream,
|
||||
and is zero when starting, even if appending or reading a gzip stream from
|
||||
the middle of a file using gzdopen().
|
||||
|
||||
gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
|
||||
*/
|
||||
@@ -1584,22 +1585,22 @@ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
|
||||
/*
|
||||
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
|
||||
|
||||
Returns the current offset in the file being read or written. This offset
|
||||
includes the count of bytes that precede the gzip stream, for example when
|
||||
appending or when using gzdopen() for reading. When reading, the offset
|
||||
does not include as yet unused buffered input. This information can be used
|
||||
for a progress indicator. On error, gzoffset() returns -1.
|
||||
Return the current compressed (actual) read or write offset of file. This
|
||||
offset includes the count of bytes that precede the gzip stream, for example
|
||||
when appending or when using gzdopen() for reading. When reading, the
|
||||
offset does not include as yet unused buffered input. This information can
|
||||
be used for a progress indicator. On error, gzoffset() returns -1.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzeof OF((gzFile file));
|
||||
/*
|
||||
Returns true (1) if the end-of-file indicator has been set while reading,
|
||||
false (0) otherwise. Note that the end-of-file indicator is set only if the
|
||||
read tried to go past the end of the input, but came up short. Therefore,
|
||||
just like feof(), gzeof() may return false even if there is no more data to
|
||||
read, in the event that the last read request was for the exact number of
|
||||
bytes remaining in the input file. This will happen if the input file size
|
||||
is an exact multiple of the buffer size.
|
||||
Return true (1) if the end-of-file indicator for file has been set while
|
||||
reading, false (0) otherwise. Note that the end-of-file indicator is set
|
||||
only if the read tried to go past the end of the input, but came up short.
|
||||
Therefore, just like feof(), gzeof() may return false even if there is no
|
||||
more data to read, in the event that the last read request was for the exact
|
||||
number of bytes remaining in the input file. This will happen if the input
|
||||
file size is an exact multiple of the buffer size.
|
||||
|
||||
If gzeof() returns true, then the read functions will return no more data,
|
||||
unless the end-of-file indicator is reset by gzclearerr() and the input file
|
||||
@@ -1608,7 +1609,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
|
||||
|
||||
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
|
||||
/*
|
||||
Returns true (1) if file is being copied directly while reading, or false
|
||||
Return true (1) if file is being copied directly while reading, or false
|
||||
(0) if file is a gzip stream being decompressed.
|
||||
|
||||
If the input file is empty, gzdirect() will return true, since the input
|
||||
@@ -1629,8 +1630,8 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
|
||||
|
||||
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
|
||||
/*
|
||||
Flushes all pending output if necessary, closes the compressed file and
|
||||
deallocates the (de)compression state. Note that once file is closed, you
|
||||
Flush all pending output for file, if necessary, close file and
|
||||
deallocate the (de)compression state. Note that once file is closed, you
|
||||
cannot call gzerror with file, since its structures have been deallocated.
|
||||
gzclose must not be called more than once on the same file, just as free
|
||||
must not be called more than once on the same allocation.
|
||||
@@ -1654,10 +1655,10 @@ ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
|
||||
|
||||
ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
|
||||
/*
|
||||
Returns the error message for the last error which occurred on the given
|
||||
compressed file. errnum is set to zlib error number. If an error occurred
|
||||
in the file system and not in the compression library, errnum is set to
|
||||
Z_ERRNO and the application may consult errno to get the exact error code.
|
||||
Return the error message for the last error which occurred on file.
|
||||
errnum is set to zlib error number. If an error occurred in the file system
|
||||
and not in the compression library, errnum is set to Z_ERRNO and the
|
||||
application may consult errno to get the exact error code.
|
||||
|
||||
The application must not modify the returned string. Future calls to
|
||||
this function may invalidate the previously returned string. If file is
|
||||
@@ -1670,7 +1671,7 @@ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
|
||||
|
||||
ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
|
||||
/*
|
||||
Clears the error and end-of-file flags for file. This is analogous to the
|
||||
Clear the error and end-of-file flags for file. This is analogous to the
|
||||
clearerr() function in stdio. This is useful for continuing to read a gzip
|
||||
file that is being written concurrently.
|
||||
*/
|
||||
@@ -1688,8 +1689,9 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
|
||||
ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
|
||||
/*
|
||||
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
|
||||
return the updated checksum. If buf is Z_NULL, this function returns the
|
||||
required initial value for the checksum.
|
||||
return the updated checksum. An Adler-32 value is in the range of a 32-bit
|
||||
unsigned integer. If buf is Z_NULL, this function returns the required
|
||||
initial value for the checksum.
|
||||
|
||||
An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
|
||||
much faster.
|
||||
@@ -1722,12 +1724,13 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
|
||||
negative, the result has no meaning or utility.
|
||||
*/
|
||||
|
||||
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
|
||||
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
|
||||
/*
|
||||
Update a running CRC-32 with the bytes buf[0..len-1] and return the
|
||||
updated CRC-32. If buf is Z_NULL, this function returns the required
|
||||
initial value for the crc. Pre- and post-conditioning (one's complement) is
|
||||
performed within this function so it shouldn't be done by the application.
|
||||
updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
|
||||
If buf is Z_NULL, this function returns the required initial value for the
|
||||
crc. Pre- and post-conditioning (one's complement) is performed within this
|
||||
function so it shouldn't be done by the application.
|
||||
|
||||
Usage example:
|
||||
|
||||
@@ -1739,7 +1742,7 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
|
||||
if (crc != original_crc) error();
|
||||
*/
|
||||
|
||||
ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,
|
||||
ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf,
|
||||
z_size_t len));
|
||||
/*
|
||||
Same as crc32(), but with a size_t length.
|
||||
@@ -1755,6 +1758,20 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
|
||||
len2.
|
||||
*/
|
||||
|
||||
/*
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
|
||||
|
||||
Return the operator corresponding to length len2, to be used with
|
||||
crc32_combine_op().
|
||||
*/
|
||||
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
|
||||
/*
|
||||
Give the same result as crc32_combine(), using op in place of len2. op is
|
||||
is generated from len2 by crc32_combine_gen(). This will be faster than
|
||||
crc32_combine() if the generated op is used more than once.
|
||||
*/
|
||||
|
||||
|
||||
/* various hacks, don't look :) */
|
||||
|
||||
@@ -1842,6 +1859,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
||||
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t));
|
||||
#endif
|
||||
|
||||
#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
|
||||
@@ -1852,6 +1870,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
||||
# define z_gzoffset z_gzoffset64
|
||||
# define z_adler32_combine z_adler32_combine64
|
||||
# define z_crc32_combine z_crc32_combine64
|
||||
# define z_crc32_combine_gen z_crc32_combine_gen64
|
||||
# else
|
||||
# define gzopen gzopen64
|
||||
# define gzseek gzseek64
|
||||
@@ -1859,6 +1878,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
||||
# define gzoffset gzoffset64
|
||||
# define adler32_combine adler32_combine64
|
||||
# define crc32_combine crc32_combine64
|
||||
# define crc32_combine_gen crc32_combine_gen64
|
||||
# endif
|
||||
# ifndef Z_LARGE64
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
@@ -1867,6 +1887,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
||||
ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
|
||||
# endif
|
||||
#else
|
||||
ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
|
||||
@@ -1875,12 +1896,14 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
||||
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
|
||||
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
|
||||
#endif
|
||||
|
||||
#else /* Z_SOLO */
|
||||
|
||||
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
|
||||
|
||||
#endif /* !Z_SOLO */
|
||||
|
||||
@@ -1893,7 +1916,7 @@ ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int));
|
||||
ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp));
|
||||
ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
|
||||
ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
|
||||
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)
|
||||
#if defined(_WIN32) && !defined(Z_SOLO)
|
||||
ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
|
||||
const char *mode));
|
||||
#endif
|
||||
|
||||
Vendored
+1
-1
@@ -137,7 +137,7 @@ const char * ZEXPORT zError(err)
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
/* The Microsoft C Run-Time Library for Windows CE doesn't have
|
||||
/* The older Microsoft C Run-Time Library for Windows CE doesn't have
|
||||
* errno. We define it as a global variable to simplify porting.
|
||||
* Its value is always 0 and should not be used.
|
||||
*/
|
||||
|
||||
Vendored
+13
-12
@@ -1,5 +1,5 @@
|
||||
/* zutil.h -- internal interface and configuration of the compression library
|
||||
* Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
|
||||
* Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
@@ -29,10 +29,6 @@
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef Z_SOLO
|
||||
typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
@@ -46,6 +42,17 @@ typedef unsigned short ush;
|
||||
typedef ush FAR ushf;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
|
||||
# include <limits.h>
|
||||
# if (ULONG_MAX == 0xffffffffffffffff)
|
||||
# define Z_U8 unsigned long
|
||||
# elif (ULLONG_MAX == 0xffffffffffffffff)
|
||||
# define Z_U8 unsigned long long
|
||||
# elif (UINT_MAX == 0xffffffffffffffff)
|
||||
# define Z_U8 unsigned
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
/* (size given to avoid silly warnings with Visual C++) */
|
||||
|
||||
@@ -169,13 +176,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
|
||||
# if defined(_WIN32_WCE)
|
||||
# if _WIN32_WCE < 0x800
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# ifndef _PTRDIFF_T_DEFINED
|
||||
typedef int ptrdiff_t;
|
||||
# define _PTRDIFF_T_DEFINED
|
||||
# endif
|
||||
# endif
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# else
|
||||
# define fdopen(fd,type) _fdopen(fd,type)
|
||||
# endif
|
||||
|
||||
+75
-55
@@ -243,7 +243,7 @@ OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O (iOS/Mac)" ON
|
||||
OCV_OPTION(WITH_CAP_IOS "Enable iOS video capture" ON
|
||||
VISIBLE_IF IOS
|
||||
VERIFY HAVE_CAP_IOS)
|
||||
OCV_OPTION(WITH_CAROTENE "Use NVidia carotene acceleration library for ARM platform" ON
|
||||
OCV_OPTION(WITH_CAROTENE "Use NVidia carotene acceleration library for ARM platform" (NOT CV_DISABLE_OPTIMIZATION)
|
||||
VISIBLE_IF (ARM OR AARCH64) AND NOT IOS)
|
||||
OCV_OPTION(WITH_CPUFEATURES "Use cpufeatures Android library" ON
|
||||
VISIBLE_IF ANDROID
|
||||
@@ -290,12 +290,10 @@ OCV_OPTION(WITH_HALIDE "Include Halide support" OFF
|
||||
OCV_OPTION(WITH_VULKAN "Include Vulkan support" OFF
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY HAVE_VULKAN)
|
||||
OCV_OPTION(WITH_INF_ENGINE "Include Intel Inference Engine support" OFF
|
||||
# replacement for deprecated options: WITH_INF_ENGINE, WITH_NGRAPH
|
||||
OCV_OPTION(WITH_OPENVINO "Include Intel OpenVINO toolkit support" (WITH_INF_ENGINE)
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY INF_ENGINE_TARGET)
|
||||
OCV_OPTION(WITH_NGRAPH "Include nGraph support" WITH_INF_ENGINE
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY TARGET ngraph::ngraph)
|
||||
VERIFY TARGET ocv.3rdparty.openvino)
|
||||
OCV_OPTION(WITH_WEBNN "Include WebNN support" OFF
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY HAVE_WEBNN)
|
||||
@@ -455,6 +453,9 @@ OCV_OPTION(WITH_TENGINE "Include Arm Inference Tengine support" OFF
|
||||
OCV_OPTION(WITH_ONNX "Include Microsoft ONNX Runtime support" OFF
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY HAVE_ONNX)
|
||||
OCV_OPTION(WITH_TIMVX "Include Tim-VX support" OFF
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY HAVE_TIMVX)
|
||||
|
||||
# OpenCV build components
|
||||
# ===================================================
|
||||
@@ -735,6 +736,9 @@ include(cmake/OpenCVFindProtobuf.cmake)
|
||||
if(WITH_TENGINE)
|
||||
include(cmake/OpenCVFindTengine.cmake)
|
||||
endif()
|
||||
if(WITH_TIMVX)
|
||||
include(cmake/OpenCVFindTIMVX.cmake)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Detect other 3rd-party libraries/tools
|
||||
@@ -802,7 +806,7 @@ if(WITH_WEBNN)
|
||||
endif()
|
||||
|
||||
# --- Inference Engine ---
|
||||
if(WITH_INF_ENGINE)
|
||||
if(WITH_INF_ENGINE OR WITH_OPENVINO)
|
||||
include(cmake/OpenCVDetectInferenceEngine.cmake)
|
||||
endif()
|
||||
|
||||
@@ -1537,55 +1541,61 @@ if(WITH_HALIDE OR HAVE_HALIDE)
|
||||
status(" Halide:" HAVE_HALIDE THEN "YES (${HALIDE_LIBRARIES} ${HALIDE_INCLUDE_DIRS})" ELSE NO)
|
||||
endif()
|
||||
|
||||
if(WITH_INF_ENGINE OR INF_ENGINE_TARGET)
|
||||
if(INF_ENGINE_TARGET)
|
||||
list(GET INF_ENGINE_TARGET 0 ie_target)
|
||||
set(__msg "YES (${INF_ENGINE_RELEASE} / ${INF_ENGINE_VERSION})")
|
||||
ocv_get_imported_target(ie_target "${ie_target}")
|
||||
get_target_property(_lib ${ie_target} IMPORTED_LOCATION)
|
||||
get_target_property(_lib_imp_rel ${ie_target} IMPORTED_IMPLIB_RELEASE)
|
||||
get_target_property(_lib_imp_dbg ${ie_target} IMPORTED_IMPLIB_DEBUG)
|
||||
get_target_property(_lib_rel ${ie_target} IMPORTED_LOCATION_RELEASE)
|
||||
get_target_property(_lib_dbg ${ie_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 ${ie_target} INTERFACE_INCLUDE_DIRECTORIES)
|
||||
status(" Inference Engine:" "${__msg}")
|
||||
status(" * libs:" "${_lib}")
|
||||
status(" * includes:" "${_inc}")
|
||||
else()
|
||||
status(" Inference Engine:" "NO")
|
||||
if(HAVE_OPENVINO
|
||||
OR (WITH_OPENVINO AND NOT WITH_INF_ENGINE AND NOT INF_ENGINE_TARGET)
|
||||
)
|
||||
status(" OpenVINO:" TARGET openvino::runtime THEN "YES (${OpenVINO_VERSION})" ELSE "NO")
|
||||
else()
|
||||
if(WITH_INF_ENGINE OR INF_ENGINE_TARGET)
|
||||
if(INF_ENGINE_TARGET)
|
||||
list(GET INF_ENGINE_TARGET 0 ie_target)
|
||||
set(__msg "YES (${INF_ENGINE_RELEASE} / ${INF_ENGINE_VERSION})")
|
||||
ocv_get_imported_target(ie_target "${ie_target}")
|
||||
get_target_property(_lib ${ie_target} IMPORTED_LOCATION)
|
||||
get_target_property(_lib_imp_rel ${ie_target} IMPORTED_IMPLIB_RELEASE)
|
||||
get_target_property(_lib_imp_dbg ${ie_target} IMPORTED_IMPLIB_DEBUG)
|
||||
get_target_property(_lib_rel ${ie_target} IMPORTED_LOCATION_RELEASE)
|
||||
get_target_property(_lib_dbg ${ie_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 ${ie_target} INTERFACE_INCLUDE_DIRECTORIES)
|
||||
status(" Inference Engine:" "${__msg}")
|
||||
status(" * libs:" "${_lib}")
|
||||
status(" * includes:" "${_inc}")
|
||||
else()
|
||||
status(" Inference Engine:" "NO")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(WITH_NGRAPH OR HAVE_NGRAPH)
|
||||
if(HAVE_NGRAPH)
|
||||
ocv_get_imported_target(__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")
|
||||
if(WITH_NGRAPH OR HAVE_NGRAPH)
|
||||
if(HAVE_NGRAPH)
|
||||
ocv_get_imported_target(__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()
|
||||
endif()
|
||||
|
||||
@@ -1641,6 +1651,16 @@ if(WITH_WEBNN OR HAVE_WEBNN)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_TIMVX)
|
||||
status("")
|
||||
status(" Tim-VX:" HAVE_TIMVX THEN "YES" ELSE "NO")
|
||||
if(HAVE_TIMVX)
|
||||
status(" Include path" TIMVX_INCLUDE_DIR THEN "${TIMVX_INCLUDE_DIR}" ELSE "NO")
|
||||
status(" Link libraries:" TIMVX_LIBRARY THEN "${TIMVX_LIBRARY}" ELSE "NO")
|
||||
status(" VIVANTE SDK path" VIVANTE_SDK_DIR THEN "${VIVANTE_SDK_DIR}" ELSE "NO")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_OPENCL OR HAVE_OPENCL)
|
||||
ocv_build_features_string(opencl_features
|
||||
IF HAVE_OPENCL_SVM THEN "SVM"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
Copyright (C) 2000-2021, Intel Corporation, all rights reserved.
|
||||
Copyright (C) 2000-2022, Intel Corporation, all rights reserved.
|
||||
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
|
||||
Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved.
|
||||
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
|
||||
Copyright (C) 2015-2021, OpenCV Foundation, all rights reserved.
|
||||
Copyright (C) 2015-2022, OpenCV Foundation, all rights reserved.
|
||||
Copyright (C) 2008-2016, Itseez Inc., all rights reserved.
|
||||
Copyright (C) 2019-2021, Xperience AI, all rights reserved.
|
||||
Copyright (C) 2019-2021, Shenzhen Institute of Artificial Intelligence and
|
||||
Copyright (C) 2019-2022, Xperience AI, all rights reserved.
|
||||
Copyright (C) 2019-2022, Shenzhen Institute of Artificial Intelligence and
|
||||
Robotics for Society, all rights reserved.
|
||||
|
||||
Third party copyrights are property of their respective owners.
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
## In-Depth Stitching Tool for experiments and research
|
||||
## MOVED: opencv_stitching_tool
|
||||
|
||||
Visit [opencv_stitching_tutorial](https://github.com/lukasalexanderweber/opencv_stitching_tutorial) for a detailed Tutorial
|
||||
As the stitching package is now available on [PyPI](https://pypi.org/project/stitching/) the tool and belonging package are now maintained [here](https://github.com/lukasalexanderweber/stitching). The Tutorial is maintained [here](https://github.com/lukasalexanderweber/stitching_tutorial).
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# python binary files
|
||||
*.pyc
|
||||
__pycache__
|
||||
.pylint*
|
||||
@@ -1,48 +0,0 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Blender:
|
||||
|
||||
BLENDER_CHOICES = ('multiband', 'feather', 'no',)
|
||||
DEFAULT_BLENDER = 'multiband'
|
||||
DEFAULT_BLEND_STRENGTH = 5
|
||||
|
||||
def __init__(self, blender_type=DEFAULT_BLENDER,
|
||||
blend_strength=DEFAULT_BLEND_STRENGTH):
|
||||
self.blender_type = blender_type
|
||||
self.blend_strength = blend_strength
|
||||
self.blender = None
|
||||
|
||||
def prepare(self, corners, sizes):
|
||||
dst_sz = cv.detail.resultRoi(corners=corners, sizes=sizes)
|
||||
blend_width = (np.sqrt(dst_sz[2] * dst_sz[3]) *
|
||||
self.blend_strength / 100)
|
||||
|
||||
if self.blender_type == 'no' or blend_width < 1:
|
||||
self.blender = cv.detail.Blender_createDefault(
|
||||
cv.detail.Blender_NO
|
||||
)
|
||||
|
||||
elif self.blender_type == "multiband":
|
||||
self.blender = cv.detail_MultiBandBlender()
|
||||
self.blender.setNumBands((np.log(blend_width) /
|
||||
np.log(2.) - 1.).astype(np.int))
|
||||
|
||||
elif self.blender_type == "feather":
|
||||
self.blender = cv.detail_FeatherBlender()
|
||||
self.blender.setSharpness(1. / blend_width)
|
||||
|
||||
self.blender.prepare(dst_sz)
|
||||
|
||||
def feed(self, img, mask, corner):
|
||||
"""https://docs.opencv.org/4.x/d6/d4a/classcv_1_1detail_1_1Blender.html#a64837308bcf4e414a6219beff6cbe37a""" # noqa
|
||||
self.blender.feed(cv.UMat(img.astype(np.int16)), mask, corner)
|
||||
|
||||
def blend(self):
|
||||
"""https://docs.opencv.org/4.x/d6/d4a/classcv_1_1detail_1_1Blender.html#aa0a91ce0d6046d3a63e0123cbb1b5c00""" # noqa
|
||||
result = None
|
||||
result_mask = None
|
||||
result, result_mask = self.blender.blend(result, result_mask)
|
||||
result = cv.convertScaleAbs(result)
|
||||
return result
|
||||
@@ -1,49 +0,0 @@
|
||||
from collections import OrderedDict
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
from .stitching_error import StitchingError
|
||||
|
||||
|
||||
class CameraAdjuster:
|
||||
"""https://docs.opencv.org/4.x/d5/d56/classcv_1_1detail_1_1BundleAdjusterBase.html""" # noqa
|
||||
|
||||
CAMERA_ADJUSTER_CHOICES = OrderedDict()
|
||||
CAMERA_ADJUSTER_CHOICES['ray'] = cv.detail_BundleAdjusterRay
|
||||
CAMERA_ADJUSTER_CHOICES['reproj'] = cv.detail_BundleAdjusterReproj
|
||||
CAMERA_ADJUSTER_CHOICES['affine'] = cv.detail_BundleAdjusterAffinePartial
|
||||
CAMERA_ADJUSTER_CHOICES['no'] = cv.detail_NoBundleAdjuster
|
||||
|
||||
DEFAULT_CAMERA_ADJUSTER = list(CAMERA_ADJUSTER_CHOICES.keys())[0]
|
||||
DEFAULT_REFINEMENT_MASK = "xxxxx"
|
||||
|
||||
def __init__(self,
|
||||
adjuster=DEFAULT_CAMERA_ADJUSTER,
|
||||
refinement_mask=DEFAULT_REFINEMENT_MASK):
|
||||
|
||||
self.adjuster = CameraAdjuster.CAMERA_ADJUSTER_CHOICES[adjuster]()
|
||||
self.set_refinement_mask(refinement_mask)
|
||||
self.adjuster.setConfThresh(1)
|
||||
|
||||
def set_refinement_mask(self, refinement_mask):
|
||||
mask_matrix = np.zeros((3, 3), np.uint8)
|
||||
if refinement_mask[0] == 'x':
|
||||
mask_matrix[0, 0] = 1
|
||||
if refinement_mask[1] == 'x':
|
||||
mask_matrix[0, 1] = 1
|
||||
if refinement_mask[2] == 'x':
|
||||
mask_matrix[0, 2] = 1
|
||||
if refinement_mask[3] == 'x':
|
||||
mask_matrix[1, 1] = 1
|
||||
if refinement_mask[4] == 'x':
|
||||
mask_matrix[1, 2] = 1
|
||||
self.adjuster.setRefinementMask(mask_matrix)
|
||||
|
||||
def adjust(self, features, pairwise_matches, estimated_cameras):
|
||||
b, cameras = self.adjuster.apply(features,
|
||||
pairwise_matches,
|
||||
estimated_cameras)
|
||||
if not b:
|
||||
raise StitchingError("Camera parameters adjusting failed.")
|
||||
|
||||
return cameras
|
||||
@@ -1,27 +0,0 @@
|
||||
from collections import OrderedDict
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
from .stitching_error import StitchingError
|
||||
|
||||
|
||||
class CameraEstimator:
|
||||
|
||||
CAMERA_ESTIMATOR_CHOICES = OrderedDict()
|
||||
CAMERA_ESTIMATOR_CHOICES['homography'] = cv.detail_HomographyBasedEstimator
|
||||
CAMERA_ESTIMATOR_CHOICES['affine'] = cv.detail_AffineBasedEstimator
|
||||
|
||||
DEFAULT_CAMERA_ESTIMATOR = list(CAMERA_ESTIMATOR_CHOICES.keys())[0]
|
||||
|
||||
def __init__(self, estimator=DEFAULT_CAMERA_ESTIMATOR, **kwargs):
|
||||
self.estimator = CameraEstimator.CAMERA_ESTIMATOR_CHOICES[estimator](
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def estimate(self, features, pairwise_matches):
|
||||
b, cameras = self.estimator.apply(features, pairwise_matches, None)
|
||||
if not b:
|
||||
raise StitchingError("Homography estimation failed.")
|
||||
for cam in cameras:
|
||||
cam.R = cam.R.astype(np.float32)
|
||||
return cameras
|
||||
@@ -1,28 +0,0 @@
|
||||
from collections import OrderedDict
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
|
||||
class WaveCorrector:
|
||||
"""https://docs.opencv.org/4.x/d7/d74/group__stitching__rotation.html#ga83b24d4c3e93584986a56d9e43b9cf7f""" # noqa
|
||||
WAVE_CORRECT_CHOICES = OrderedDict()
|
||||
WAVE_CORRECT_CHOICES['horiz'] = cv.detail.WAVE_CORRECT_HORIZ
|
||||
WAVE_CORRECT_CHOICES['vert'] = cv.detail.WAVE_CORRECT_VERT
|
||||
WAVE_CORRECT_CHOICES['auto'] = cv.detail.WAVE_CORRECT_AUTO
|
||||
WAVE_CORRECT_CHOICES['no'] = None
|
||||
|
||||
DEFAULT_WAVE_CORRECTION = list(WAVE_CORRECT_CHOICES.keys())[0]
|
||||
|
||||
def __init__(self, wave_correct_kind=DEFAULT_WAVE_CORRECTION):
|
||||
self.wave_correct_kind = WaveCorrector.WAVE_CORRECT_CHOICES[
|
||||
wave_correct_kind
|
||||
]
|
||||
|
||||
def correct(self, cameras):
|
||||
if self.wave_correct_kind is not None:
|
||||
rmats = [np.copy(cam.R) for cam in cameras]
|
||||
rmats = cv.detail.waveCorrect(rmats, self.wave_correct_kind)
|
||||
for idx, cam in enumerate(cameras):
|
||||
cam.R = rmats[idx]
|
||||
return cameras
|
||||
return cameras
|
||||
@@ -1,40 +0,0 @@
|
||||
from collections import OrderedDict
|
||||
import cv2 as cv
|
||||
|
||||
|
||||
class ExposureErrorCompensator:
|
||||
|
||||
COMPENSATOR_CHOICES = OrderedDict()
|
||||
COMPENSATOR_CHOICES['gain_blocks'] = cv.detail.ExposureCompensator_GAIN_BLOCKS # noqa
|
||||
COMPENSATOR_CHOICES['gain'] = cv.detail.ExposureCompensator_GAIN
|
||||
COMPENSATOR_CHOICES['channel'] = cv.detail.ExposureCompensator_CHANNELS
|
||||
COMPENSATOR_CHOICES['channel_blocks'] = cv.detail.ExposureCompensator_CHANNELS_BLOCKS # noqa
|
||||
COMPENSATOR_CHOICES['no'] = cv.detail.ExposureCompensator_NO
|
||||
|
||||
DEFAULT_COMPENSATOR = list(COMPENSATOR_CHOICES.keys())[0]
|
||||
DEFAULT_NR_FEEDS = 1
|
||||
DEFAULT_BLOCK_SIZE = 32
|
||||
|
||||
def __init__(self,
|
||||
compensator=DEFAULT_COMPENSATOR,
|
||||
nr_feeds=DEFAULT_NR_FEEDS,
|
||||
block_size=DEFAULT_BLOCK_SIZE):
|
||||
|
||||
if compensator == 'channel':
|
||||
self.compensator = cv.detail_ChannelsCompensator(nr_feeds)
|
||||
elif compensator == 'channel_blocks':
|
||||
self.compensator = cv.detail_BlocksChannelsCompensator(
|
||||
block_size, block_size, nr_feeds
|
||||
)
|
||||
else:
|
||||
self.compensator = cv.detail.ExposureCompensator_createDefault(
|
||||
ExposureErrorCompensator.COMPENSATOR_CHOICES[compensator]
|
||||
)
|
||||
|
||||
def feed(self, *args):
|
||||
"""https://docs.opencv.org/4.x/d2/d37/classcv_1_1detail_1_1ExposureCompensator.html#ae6b0cc69a7bc53818ddea53eddb6bdba""" # noqa
|
||||
self.compensator.feed(*args)
|
||||
|
||||
def apply(self, *args):
|
||||
"""https://docs.opencv.org/4.x/d2/d37/classcv_1_1detail_1_1ExposureCompensator.html#a473eaf1e585804c08d77c91e004f93aa""" # noqa
|
||||
return self.compensator.apply(*args)
|
||||
@@ -1,44 +0,0 @@
|
||||
from collections import OrderedDict
|
||||
import cv2 as cv
|
||||
|
||||
|
||||
class FeatureDetector:
|
||||
DETECTOR_CHOICES = OrderedDict()
|
||||
try:
|
||||
cv.xfeatures2d_SURF.create() # check if the function can be called
|
||||
DETECTOR_CHOICES['surf'] = cv.xfeatures2d_SURF.create
|
||||
except (AttributeError, cv.error):
|
||||
print("SURF not available")
|
||||
|
||||
# if SURF not available, ORB is default
|
||||
DETECTOR_CHOICES['orb'] = cv.ORB.create
|
||||
|
||||
try:
|
||||
DETECTOR_CHOICES['sift'] = cv.SIFT_create
|
||||
except AttributeError:
|
||||
print("SIFT not available")
|
||||
|
||||
try:
|
||||
DETECTOR_CHOICES['brisk'] = cv.BRISK_create
|
||||
except AttributeError:
|
||||
print("BRISK not available")
|
||||
|
||||
try:
|
||||
DETECTOR_CHOICES['akaze'] = cv.AKAZE_create
|
||||
except AttributeError:
|
||||
print("AKAZE not available")
|
||||
|
||||
DEFAULT_DETECTOR = list(DETECTOR_CHOICES.keys())[0]
|
||||
|
||||
def __init__(self, detector=DEFAULT_DETECTOR, **kwargs):
|
||||
self.detector = FeatureDetector.DETECTOR_CHOICES[detector](**kwargs)
|
||||
|
||||
def detect_features(self, img, *args, **kwargs):
|
||||
return cv.detail.computeImageFeatures2(self.detector, img,
|
||||
*args, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def draw_keypoints(img, features, **kwargs):
|
||||
kwargs.setdefault('color', (0, 255, 0))
|
||||
keypoints = features.getKeypoints()
|
||||
return cv.drawKeypoints(img, keypoints, None, **kwargs)
|
||||
@@ -1,98 +0,0 @@
|
||||
import math
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
|
||||
class FeatureMatcher:
|
||||
|
||||
MATCHER_CHOICES = ('homography', 'affine')
|
||||
DEFAULT_MATCHER = 'homography'
|
||||
DEFAULT_RANGE_WIDTH = -1
|
||||
|
||||
def __init__(self,
|
||||
matcher_type=DEFAULT_MATCHER,
|
||||
range_width=DEFAULT_RANGE_WIDTH,
|
||||
**kwargs):
|
||||
|
||||
if matcher_type == "affine":
|
||||
"""https://docs.opencv.org/4.x/d3/dda/classcv_1_1detail_1_1AffineBestOf2NearestMatcher.html""" # noqa
|
||||
self.matcher = cv.detail_AffineBestOf2NearestMatcher(**kwargs)
|
||||
elif range_width == -1:
|
||||
"""https://docs.opencv.org/4.x/d4/d26/classcv_1_1detail_1_1BestOf2NearestMatcher.html""" # noqa
|
||||
self.matcher = cv.detail.BestOf2NearestMatcher_create(**kwargs)
|
||||
else:
|
||||
"""https://docs.opencv.org/4.x/d8/d72/classcv_1_1detail_1_1BestOf2NearestRangeMatcher.html""" # noqa
|
||||
self.matcher = cv.detail.BestOf2NearestRangeMatcher_create(
|
||||
range_width, **kwargs
|
||||
)
|
||||
|
||||
def match_features(self, features, *args, **kwargs):
|
||||
pairwise_matches = self.matcher.apply2(features, *args, **kwargs)
|
||||
self.matcher.collectGarbage()
|
||||
return pairwise_matches
|
||||
|
||||
@staticmethod
|
||||
def draw_matches_matrix(imgs, features, matches, conf_thresh=1,
|
||||
inliers=False, **kwargs):
|
||||
matches_matrix = FeatureMatcher.get_matches_matrix(matches)
|
||||
for idx1, idx2 in FeatureMatcher.get_all_img_combinations(len(imgs)):
|
||||
match = matches_matrix[idx1, idx2]
|
||||
if match.confidence < conf_thresh:
|
||||
continue
|
||||
if inliers:
|
||||
kwargs['matchesMask'] = match.getInliers()
|
||||
yield idx1, idx2, FeatureMatcher.draw_matches(
|
||||
imgs[idx1], features[idx1],
|
||||
imgs[idx2], features[idx2],
|
||||
match,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def draw_matches(img1, features1, img2, features2, match1to2, **kwargs):
|
||||
kwargs.setdefault('flags', cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
keypoints1 = features1.getKeypoints()
|
||||
keypoints2 = features2.getKeypoints()
|
||||
matches = match1to2.getMatches()
|
||||
|
||||
return cv.drawMatches(
|
||||
img1, keypoints1, img2, keypoints2, matches, None, **kwargs
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_matches_matrix(pairwise_matches):
|
||||
return FeatureMatcher.array_in_sqare_matrix(pairwise_matches)
|
||||
|
||||
@staticmethod
|
||||
def get_confidence_matrix(pairwise_matches):
|
||||
matches_matrix = FeatureMatcher.get_matches_matrix(pairwise_matches)
|
||||
match_confs = [[m.confidence for m in row] for row in matches_matrix]
|
||||
match_conf_matrix = np.array(match_confs)
|
||||
return match_conf_matrix
|
||||
|
||||
@staticmethod
|
||||
def array_in_sqare_matrix(array):
|
||||
matrix_dimension = int(math.sqrt(len(array)))
|
||||
rows = []
|
||||
for i in range(0, len(array), matrix_dimension):
|
||||
rows.append(array[i:i+matrix_dimension])
|
||||
return np.array(rows)
|
||||
|
||||
def get_all_img_combinations(number_imgs):
|
||||
ii, jj = np.triu_indices(number_imgs, k=1)
|
||||
for i, j in zip(ii, jj):
|
||||
yield i, j
|
||||
|
||||
@staticmethod
|
||||
def get_match_conf(match_conf, feature_detector_type):
|
||||
if match_conf is None:
|
||||
match_conf = \
|
||||
FeatureMatcher.get_default_match_conf(feature_detector_type)
|
||||
return match_conf
|
||||
|
||||
@staticmethod
|
||||
def get_default_match_conf(feature_detector_type):
|
||||
if feature_detector_type == 'orb':
|
||||
return 0.3
|
||||
return 0.65
|
||||
@@ -1,94 +0,0 @@
|
||||
import cv2 as cv
|
||||
|
||||
from .megapix_downscaler import MegapixDownscaler
|
||||
from .stitching_error import StitchingError
|
||||
|
||||
class ImageHandler:
|
||||
|
||||
DEFAULT_MEDIUM_MEGAPIX = 0.6
|
||||
DEFAULT_LOW_MEGAPIX = 0.1
|
||||
DEFAULT_FINAL_MEGAPIX = -1
|
||||
|
||||
def __init__(self,
|
||||
medium_megapix=DEFAULT_MEDIUM_MEGAPIX,
|
||||
low_megapix=DEFAULT_LOW_MEGAPIX,
|
||||
final_megapix=DEFAULT_FINAL_MEGAPIX):
|
||||
|
||||
if medium_megapix < low_megapix:
|
||||
raise StitchingError("Medium resolution megapix need to be "
|
||||
"greater or equal than low resolution "
|
||||
"megapix")
|
||||
|
||||
self.medium_scaler = MegapixDownscaler(medium_megapix)
|
||||
self.low_scaler = MegapixDownscaler(low_megapix)
|
||||
self.final_scaler = MegapixDownscaler(final_megapix)
|
||||
|
||||
self.scales_set = False
|
||||
self.img_names = []
|
||||
self.img_sizes = []
|
||||
|
||||
def set_img_names(self, img_names):
|
||||
self.img_names = img_names
|
||||
|
||||
def resize_to_medium_resolution(self):
|
||||
return self.read_and_resize_imgs(self.medium_scaler)
|
||||
|
||||
def resize_to_low_resolution(self, medium_imgs=None):
|
||||
if medium_imgs and self.scales_set:
|
||||
return self.resize_medium_to_low(medium_imgs)
|
||||
return self.read_and_resize_imgs(self.low_scaler)
|
||||
|
||||
def resize_to_final_resolution(self):
|
||||
return self.read_and_resize_imgs(self.final_scaler)
|
||||
|
||||
def read_and_resize_imgs(self, scaler):
|
||||
for img, size in self.input_images():
|
||||
yield self.resize_img_by_scaler(scaler, size, img)
|
||||
|
||||
def resize_medium_to_low(self, medium_imgs):
|
||||
for img, size in zip(medium_imgs, self.img_sizes):
|
||||
yield self.resize_img_by_scaler(self.low_scaler, size, img)
|
||||
|
||||
@staticmethod
|
||||
def resize_img_by_scaler(scaler, size, img):
|
||||
desired_size = scaler.get_scaled_img_size(size)
|
||||
return cv.resize(img, desired_size,
|
||||
interpolation=cv.INTER_LINEAR_EXACT)
|
||||
|
||||
def input_images(self):
|
||||
self.img_sizes = []
|
||||
for name in self.img_names:
|
||||
img = self.read_image(name)
|
||||
size = self.get_image_size(img)
|
||||
self.img_sizes.append(size)
|
||||
self.set_scaler_scales()
|
||||
yield img, size
|
||||
|
||||
@staticmethod
|
||||
def get_image_size(img):
|
||||
"""(width, height)"""
|
||||
return (img.shape[1], img.shape[0])
|
||||
|
||||
@staticmethod
|
||||
def read_image(img_name):
|
||||
img = cv.imread(img_name)
|
||||
if img is None:
|
||||
raise StitchingError("Cannot read image " + img_name)
|
||||
return img
|
||||
|
||||
def set_scaler_scales(self):
|
||||
if not self.scales_set:
|
||||
first_img_size = self.img_sizes[0]
|
||||
self.medium_scaler.set_scale_by_img_size(first_img_size)
|
||||
self.low_scaler.set_scale_by_img_size(first_img_size)
|
||||
self.final_scaler.set_scale_by_img_size(first_img_size)
|
||||
self.scales_set = True
|
||||
|
||||
def get_medium_to_final_ratio(self):
|
||||
return self.final_scaler.scale / self.medium_scaler.scale
|
||||
|
||||
def get_medium_to_low_ratio(self):
|
||||
return self.low_scaler.scale / self.medium_scaler.scale
|
||||
|
||||
def get_final_to_low_ratio(self):
|
||||
return self.low_scaler.scale / self.final_scaler.scale
|
||||
@@ -1,12 +0,0 @@
|
||||
from .megapix_scaler import MegapixScaler
|
||||
|
||||
|
||||
class MegapixDownscaler(MegapixScaler):
|
||||
|
||||
@staticmethod
|
||||
def force_downscale(scale):
|
||||
return min(1.0, scale)
|
||||
|
||||
def set_scale(self, scale):
|
||||
scale = self.force_downscale(scale)
|
||||
super().set_scale(scale)
|
||||
@@ -1,27 +0,0 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
class MegapixScaler:
|
||||
def __init__(self, megapix):
|
||||
self.megapix = megapix
|
||||
self.is_scale_set = False
|
||||
self.scale = None
|
||||
|
||||
def set_scale_by_img_size(self, img_size):
|
||||
self.set_scale(
|
||||
self.get_scale_by_resolution(img_size[0] * img_size[1])
|
||||
)
|
||||
|
||||
def set_scale(self, scale):
|
||||
self.scale = scale
|
||||
self.is_scale_set = True
|
||||
|
||||
def get_scale_by_resolution(self, resolution):
|
||||
if self.megapix > 0:
|
||||
return np.sqrt(self.megapix * 1e6 / resolution)
|
||||
return 1.0
|
||||
|
||||
def get_scaled_img_size(self, img_size):
|
||||
width = int(round(img_size[0] * self.scale))
|
||||
height = int(round(img_size[1] * self.scale))
|
||||
return (width, height)
|
||||
@@ -1,27 +0,0 @@
|
||||
import statistics
|
||||
|
||||
|
||||
def estimate_final_panorama_dimensions(cameras, warper, img_handler):
|
||||
medium_to_final_ratio = img_handler.get_medium_to_final_ratio()
|
||||
|
||||
panorama_scale_determined_on_medium_img = \
|
||||
estimate_panorama_scale(cameras)
|
||||
|
||||
panorama_scale = (panorama_scale_determined_on_medium_img *
|
||||
medium_to_final_ratio)
|
||||
panorama_corners = []
|
||||
panorama_sizes = []
|
||||
|
||||
for size, camera in zip(img_handler.img_sizes, cameras):
|
||||
width, height = img_handler.final_scaler.get_scaled_img_size(size)
|
||||
roi = warper.warp_roi(width, height, camera, panorama_scale, medium_to_final_ratio)
|
||||
panorama_corners.append(roi[0:2])
|
||||
panorama_sizes.append(roi[2:4])
|
||||
|
||||
return panorama_scale, panorama_corners, panorama_sizes
|
||||
|
||||
|
||||
def estimate_panorama_scale(cameras):
|
||||
focals = [cam.focal for cam in cameras]
|
||||
panorama_scale = statistics.median(focals)
|
||||
return panorama_scale
|
||||
@@ -1,127 +0,0 @@
|
||||
from collections import OrderedDict
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
from .blender import Blender
|
||||
|
||||
|
||||
class SeamFinder:
|
||||
"""https://docs.opencv.org/4.x/d7/d09/classcv_1_1detail_1_1SeamFinder.html""" # noqa
|
||||
SEAM_FINDER_CHOICES = OrderedDict()
|
||||
SEAM_FINDER_CHOICES['dp_color'] = cv.detail_DpSeamFinder('COLOR')
|
||||
SEAM_FINDER_CHOICES['dp_colorgrad'] = cv.detail_DpSeamFinder('COLOR_GRAD')
|
||||
SEAM_FINDER_CHOICES['voronoi'] = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM) # noqa
|
||||
SEAM_FINDER_CHOICES['no'] = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO) # noqa
|
||||
|
||||
DEFAULT_SEAM_FINDER = list(SEAM_FINDER_CHOICES.keys())[0]
|
||||
|
||||
def __init__(self, finder=DEFAULT_SEAM_FINDER):
|
||||
self.finder = SeamFinder.SEAM_FINDER_CHOICES[finder]
|
||||
|
||||
def find(self, imgs, corners, masks):
|
||||
"""https://docs.opencv.org/4.x/d0/dd5/classcv_1_1detail_1_1DpSeamFinder.html#a7914624907986f7a94dd424209a8a609""" # noqa
|
||||
imgs_float = [img.astype(np.float32) for img in imgs]
|
||||
return self.finder.find(imgs_float, corners, masks)
|
||||
|
||||
@staticmethod
|
||||
def resize(seam_mask, mask):
|
||||
dilated_mask = cv.dilate(seam_mask, None)
|
||||
resized_seam_mask = cv.resize(dilated_mask, (mask.shape[1],
|
||||
mask.shape[0]),
|
||||
0, 0, cv.INTER_LINEAR_EXACT)
|
||||
return cv.bitwise_and(resized_seam_mask, mask)
|
||||
|
||||
@staticmethod
|
||||
def draw_seam_mask(img, seam_mask, color=(0, 0, 0)):
|
||||
seam_mask = cv.UMat.get(seam_mask)
|
||||
overlayed_img = np.copy(img)
|
||||
overlayed_img[seam_mask == 0] = color
|
||||
return overlayed_img
|
||||
|
||||
@staticmethod
|
||||
def draw_seam_polygons(panorama, blended_seam_masks, alpha=0.5):
|
||||
return add_weighted_image(panorama, blended_seam_masks, alpha)
|
||||
|
||||
@staticmethod
|
||||
def draw_seam_lines(panorama, blended_seam_masks,
|
||||
linesize=1, color=(0, 0, 255)):
|
||||
seam_lines = \
|
||||
SeamFinder.exctract_seam_lines(blended_seam_masks, linesize)
|
||||
panorama_with_seam_lines = panorama.copy()
|
||||
panorama_with_seam_lines[seam_lines == 255] = color
|
||||
return panorama_with_seam_lines
|
||||
|
||||
@staticmethod
|
||||
def exctract_seam_lines(blended_seam_masks, linesize=1):
|
||||
seam_lines = cv.Canny(np.uint8(blended_seam_masks), 100, 200)
|
||||
seam_indices = (seam_lines == 255).nonzero()
|
||||
seam_lines = remove_invalid_line_pixels(
|
||||
seam_indices, seam_lines, blended_seam_masks
|
||||
)
|
||||
kernelsize = linesize + linesize - 1
|
||||
kernel = np.ones((kernelsize, kernelsize), np.uint8)
|
||||
return cv.dilate(seam_lines, kernel)
|
||||
|
||||
@staticmethod
|
||||
def blend_seam_masks(seam_masks, corners, sizes, colors=[
|
||||
(255, 000, 000), # Blue
|
||||
(000, 000, 255), # Red
|
||||
(000, 255, 000), # Green
|
||||
(000, 255, 255), # Yellow
|
||||
(255, 000, 255), # Magenta
|
||||
(128, 128, 255), # Pink
|
||||
(128, 128, 128), # Gray
|
||||
(000, 000, 128), # Brown
|
||||
(000, 128, 255)] # Orange
|
||||
):
|
||||
|
||||
blender = Blender("no")
|
||||
blender.prepare(corners, sizes)
|
||||
|
||||
for idx, (seam_mask, size, corner) in enumerate(
|
||||
zip(seam_masks, sizes, corners)):
|
||||
if idx+1 > len(colors):
|
||||
raise ValueError("Not enough default colors! Pass additional "
|
||||
"colors to \"colors\" parameter")
|
||||
one_color_img = create_img_by_size(size, colors[idx])
|
||||
blender.feed(one_color_img, seam_mask, corner)
|
||||
|
||||
return blender.blend()
|
||||
|
||||
|
||||
def create_img_by_size(size, color=(0, 0, 0)):
|
||||
width, height = size
|
||||
img = np.zeros((height, width, 3), np.uint8)
|
||||
img[:] = color
|
||||
return img
|
||||
|
||||
|
||||
def add_weighted_image(img1, img2, alpha):
|
||||
return cv.addWeighted(
|
||||
img1, alpha, img2, (1.0 - alpha), 0.0
|
||||
)
|
||||
|
||||
|
||||
def remove_invalid_line_pixels(indices, lines, mask):
|
||||
for x, y in zip(*indices):
|
||||
if check_if_pixel_or_neighbor_is_black(mask, x, y):
|
||||
lines[x, y] = 0
|
||||
return lines
|
||||
|
||||
|
||||
def check_if_pixel_or_neighbor_is_black(img, x, y):
|
||||
check = [is_pixel_black(img, x, y),
|
||||
is_pixel_black(img, x+1, y), is_pixel_black(img, x-1, y),
|
||||
is_pixel_black(img, x, y+1), is_pixel_black(img, x, y-1)]
|
||||
return any(check)
|
||||
|
||||
|
||||
def is_pixel_black(img, x, y):
|
||||
return np.all(get_pixel_value(img, x, y) == 0)
|
||||
|
||||
|
||||
def get_pixel_value(img, x, y):
|
||||
try:
|
||||
return img[x, y]
|
||||
except IndexError:
|
||||
pass
|
||||
@@ -1,207 +0,0 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
from .image_handler import ImageHandler
|
||||
from .feature_detector import FeatureDetector
|
||||
from .feature_matcher import FeatureMatcher
|
||||
from .subsetter import Subsetter
|
||||
from .camera_estimator import CameraEstimator
|
||||
from .camera_adjuster import CameraAdjuster
|
||||
from .camera_wave_corrector import WaveCorrector
|
||||
from .warper import Warper
|
||||
from .panorama_estimation import estimate_final_panorama_dimensions
|
||||
from .exposure_error_compensator import ExposureErrorCompensator
|
||||
from .seam_finder import SeamFinder
|
||||
from .blender import Blender
|
||||
from .timelapser import Timelapser
|
||||
from .stitching_error import StitchingError
|
||||
|
||||
|
||||
class Stitcher:
|
||||
DEFAULT_SETTINGS = {
|
||||
"medium_megapix": ImageHandler.DEFAULT_MEDIUM_MEGAPIX,
|
||||
"detector": FeatureDetector.DEFAULT_DETECTOR,
|
||||
"nfeatures": 500,
|
||||
"matcher_type": FeatureMatcher.DEFAULT_MATCHER,
|
||||
"range_width": FeatureMatcher.DEFAULT_RANGE_WIDTH,
|
||||
"try_use_gpu": False,
|
||||
"match_conf": None,
|
||||
"confidence_threshold": Subsetter.DEFAULT_CONFIDENCE_THRESHOLD,
|
||||
"matches_graph_dot_file": Subsetter.DEFAULT_MATCHES_GRAPH_DOT_FILE,
|
||||
"estimator": CameraEstimator.DEFAULT_CAMERA_ESTIMATOR,
|
||||
"adjuster": CameraAdjuster.DEFAULT_CAMERA_ADJUSTER,
|
||||
"refinement_mask": CameraAdjuster.DEFAULT_REFINEMENT_MASK,
|
||||
"wave_correct_kind": WaveCorrector.DEFAULT_WAVE_CORRECTION,
|
||||
"warper_type": Warper.DEFAULT_WARP_TYPE,
|
||||
"low_megapix": ImageHandler.DEFAULT_LOW_MEGAPIX,
|
||||
"compensator": ExposureErrorCompensator.DEFAULT_COMPENSATOR,
|
||||
"nr_feeds": ExposureErrorCompensator.DEFAULT_NR_FEEDS,
|
||||
"block_size": ExposureErrorCompensator.DEFAULT_BLOCK_SIZE,
|
||||
"finder": SeamFinder.DEFAULT_SEAM_FINDER,
|
||||
"final_megapix": ImageHandler.DEFAULT_FINAL_MEGAPIX,
|
||||
"blender_type": Blender.DEFAULT_BLENDER,
|
||||
"blend_strength": Blender.DEFAULT_BLEND_STRENGTH,
|
||||
"timelapse": Timelapser.DEFAULT_TIMELAPSE}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.initialize_stitcher(**kwargs)
|
||||
|
||||
def initialize_stitcher(self, **kwargs):
|
||||
self.settings = Stitcher.DEFAULT_SETTINGS.copy()
|
||||
self.validate_kwargs(kwargs)
|
||||
self.settings.update(kwargs)
|
||||
|
||||
args = SimpleNamespace(**self.settings)
|
||||
self.img_handler = ImageHandler(args.medium_megapix,
|
||||
args.low_megapix,
|
||||
args.final_megapix)
|
||||
self.detector = \
|
||||
FeatureDetector(args.detector, nfeatures=args.nfeatures)
|
||||
match_conf = \
|
||||
FeatureMatcher.get_match_conf(args.match_conf, args.detector)
|
||||
self.matcher = FeatureMatcher(args.matcher_type, args.range_width,
|
||||
try_use_gpu=args.try_use_gpu,
|
||||
match_conf=match_conf)
|
||||
self.subsetter = \
|
||||
Subsetter(args.confidence_threshold, args.matches_graph_dot_file)
|
||||
self.camera_estimator = CameraEstimator(args.estimator)
|
||||
self.camera_adjuster = \
|
||||
CameraAdjuster(args.adjuster, args.refinement_mask)
|
||||
self.wave_corrector = WaveCorrector(args.wave_correct_kind)
|
||||
self.warper = Warper(args.warper_type)
|
||||
self.compensator = \
|
||||
ExposureErrorCompensator(args.compensator, args.nr_feeds,
|
||||
args.block_size)
|
||||
self.seam_finder = SeamFinder(args.finder)
|
||||
self.blender = Blender(args.blender_type, args.blend_strength)
|
||||
self.timelapser = Timelapser(args.timelapse)
|
||||
|
||||
def stitch(self, img_names):
|
||||
self.initialize_registration(img_names)
|
||||
|
||||
imgs = self.resize_medium_resolution()
|
||||
features = self.find_features(imgs)
|
||||
matches = self.match_features(features)
|
||||
imgs, features, matches = self.subset(imgs, features, matches)
|
||||
cameras = self.estimate_camera_parameters(features, matches)
|
||||
cameras = self.refine_camera_parameters(features, matches, cameras)
|
||||
cameras = self.perform_wave_correction(cameras)
|
||||
panorama_scale, panorama_corners, panorama_sizes = \
|
||||
self.estimate_final_panorama_dimensions(cameras)
|
||||
|
||||
self.initialize_composition(panorama_corners, panorama_sizes)
|
||||
|
||||
imgs = self.resize_low_resolution(imgs)
|
||||
imgs = self.warp_low_resolution_images(imgs, cameras, panorama_scale)
|
||||
self.estimate_exposure_errors(imgs)
|
||||
seam_masks = self.find_seam_masks(imgs)
|
||||
|
||||
imgs = self.resize_final_resolution()
|
||||
imgs = self.warp_final_resolution_images(imgs, cameras, panorama_scale)
|
||||
imgs = self.compensate_exposure_errors(imgs)
|
||||
seam_masks = self.resize_seam_masks(seam_masks)
|
||||
self.blend_images(imgs, seam_masks)
|
||||
|
||||
return self.create_final_panorama()
|
||||
|
||||
def initialize_registration(self, img_names):
|
||||
self.img_handler.set_img_names(img_names)
|
||||
|
||||
def resize_medium_resolution(self):
|
||||
return list(self.img_handler.resize_to_medium_resolution())
|
||||
|
||||
def find_features(self, imgs):
|
||||
return [self.detector.detect_features(img) for img in imgs]
|
||||
|
||||
def match_features(self, features):
|
||||
return self.matcher.match_features(features)
|
||||
|
||||
def subset(self, imgs, features, matches):
|
||||
names, sizes, imgs, features, matches = \
|
||||
self.subsetter.subset(self.img_handler.img_names,
|
||||
self.img_handler.img_sizes,
|
||||
imgs, features, matches)
|
||||
self.img_handler.img_names, self.img_handler.img_sizes = names, sizes
|
||||
return imgs, features, matches
|
||||
|
||||
def estimate_camera_parameters(self, features, matches):
|
||||
return self.camera_estimator.estimate(features, matches)
|
||||
|
||||
def refine_camera_parameters(self, features, matches, cameras):
|
||||
return self.camera_adjuster.adjust(features, matches, cameras)
|
||||
|
||||
def perform_wave_correction(self, cameras):
|
||||
return self.wave_corrector.correct(cameras)
|
||||
|
||||
def estimate_final_panorama_dimensions(self, cameras):
|
||||
return estimate_final_panorama_dimensions(cameras, self.warper,
|
||||
self.img_handler)
|
||||
|
||||
def initialize_composition(self, corners, sizes):
|
||||
if self.timelapser.do_timelapse:
|
||||
self.timelapser.initialize(corners, sizes)
|
||||
else:
|
||||
self.blender.prepare(corners, sizes)
|
||||
|
||||
def resize_low_resolution(self, imgs=None):
|
||||
return list(self.img_handler.resize_to_low_resolution(imgs))
|
||||
|
||||
def warp_low_resolution_images(self, imgs, cameras, final_scale):
|
||||
camera_aspect = self.img_handler.get_medium_to_low_ratio()
|
||||
scale = final_scale * self.img_handler.get_final_to_low_ratio()
|
||||
return list(self.warp_images(imgs, cameras, scale, camera_aspect))
|
||||
|
||||
def warp_final_resolution_images(self, imgs, cameras, scale):
|
||||
camera_aspect = self.img_handler.get_medium_to_final_ratio()
|
||||
return self.warp_images(imgs, cameras, scale, camera_aspect)
|
||||
|
||||
def warp_images(self, imgs, cameras, scale, aspect=1):
|
||||
self._masks = []
|
||||
self._corners = []
|
||||
for img_warped, mask_warped, corner in \
|
||||
self.warper.warp_images_and_image_masks(
|
||||
imgs, cameras, scale, aspect
|
||||
):
|
||||
self._masks.append(mask_warped)
|
||||
self._corners.append(corner)
|
||||
yield img_warped
|
||||
|
||||
def estimate_exposure_errors(self, imgs):
|
||||
self.compensator.feed(self._corners, imgs, self._masks)
|
||||
|
||||
def find_seam_masks(self, imgs):
|
||||
return self.seam_finder.find(imgs, self._corners, self._masks)
|
||||
|
||||
def resize_final_resolution(self):
|
||||
return self.img_handler.resize_to_final_resolution()
|
||||
|
||||
def compensate_exposure_errors(self, imgs):
|
||||
for idx, img in enumerate(imgs):
|
||||
yield self.compensator.apply(idx, self._corners[idx],
|
||||
img, self._masks[idx])
|
||||
|
||||
def resize_seam_masks(self, seam_masks):
|
||||
for idx, seam_mask in enumerate(seam_masks):
|
||||
yield SeamFinder.resize(seam_mask, self._masks[idx])
|
||||
|
||||
def blend_images(self, imgs, masks):
|
||||
for idx, (img, mask) in enumerate(zip(imgs, masks)):
|
||||
if self.timelapser.do_timelapse:
|
||||
self.timelapser.process_and_save_frame(
|
||||
self.img_handler.img_names[idx], img, self._corners[idx]
|
||||
)
|
||||
else:
|
||||
self.blender.feed(img, mask, self._corners[idx])
|
||||
|
||||
def create_final_panorama(self):
|
||||
if not self.timelapser.do_timelapse:
|
||||
return self.blender.blend()
|
||||
|
||||
@staticmethod
|
||||
def validate_kwargs(kwargs):
|
||||
for arg in kwargs:
|
||||
if arg not in Stitcher.DEFAULT_SETTINGS:
|
||||
raise StitchingError("Invalid Argument: " + arg)
|
||||
|
||||
def collect_garbage(self):
|
||||
del self.img_handler.img_names, self.img_handler.img_sizes,
|
||||
del self._corners, self._masks
|
||||
@@ -1,2 +0,0 @@
|
||||
class StitchingError(Exception):
|
||||
pass
|
||||
@@ -1,95 +0,0 @@
|
||||
from itertools import chain
|
||||
import math
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
from .feature_matcher import FeatureMatcher
|
||||
from .stitching_error import StitchingError
|
||||
|
||||
|
||||
class Subsetter:
|
||||
|
||||
DEFAULT_CONFIDENCE_THRESHOLD = 1
|
||||
DEFAULT_MATCHES_GRAPH_DOT_FILE = None
|
||||
|
||||
def __init__(self,
|
||||
confidence_threshold=DEFAULT_CONFIDENCE_THRESHOLD,
|
||||
matches_graph_dot_file=DEFAULT_MATCHES_GRAPH_DOT_FILE):
|
||||
self.confidence_threshold = confidence_threshold
|
||||
self.save_file = matches_graph_dot_file
|
||||
|
||||
def subset(self, img_names, img_sizes, imgs, features, matches):
|
||||
self.save_matches_graph_dot_file(img_names, matches)
|
||||
indices = self.get_indices_to_keep(features, matches)
|
||||
|
||||
img_names = Subsetter.subset_list(img_names, indices)
|
||||
img_sizes = Subsetter.subset_list(img_sizes, indices)
|
||||
imgs = Subsetter.subset_list(imgs, indices)
|
||||
features = Subsetter.subset_list(features, indices)
|
||||
matches = Subsetter.subset_matches(matches, indices)
|
||||
return img_names, img_sizes, imgs, features, matches
|
||||
|
||||
def save_matches_graph_dot_file(self, img_names, pairwise_matches):
|
||||
if self.save_file:
|
||||
with open(self.save_file, 'w') as filehandler:
|
||||
filehandler.write(self.get_matches_graph(img_names,
|
||||
pairwise_matches)
|
||||
)
|
||||
|
||||
def get_matches_graph(self, img_names, pairwise_matches):
|
||||
return cv.detail.matchesGraphAsString(img_names, pairwise_matches,
|
||||
self.confidence_threshold)
|
||||
|
||||
def get_indices_to_keep(self, features, pairwise_matches):
|
||||
indices = cv.detail.leaveBiggestComponent(features,
|
||||
pairwise_matches,
|
||||
self.confidence_threshold)
|
||||
indices_as_list = [int(idx) for idx in list(indices[:, 0])]
|
||||
|
||||
if len(indices_as_list) < 2:
|
||||
raise StitchingError("No match exceeds the "
|
||||
"given confidence theshold.")
|
||||
|
||||
return indices_as_list
|
||||
|
||||
@staticmethod
|
||||
def subset_list(list_to_subset, indices):
|
||||
return [list_to_subset[i] for i in indices]
|
||||
|
||||
@staticmethod
|
||||
def subset_matches(pairwise_matches, indices):
|
||||
indices_to_delete = Subsetter.get_indices_to_delete(
|
||||
math.sqrt(len(pairwise_matches)),
|
||||
indices
|
||||
)
|
||||
|
||||
matches_matrix = FeatureMatcher.get_matches_matrix(pairwise_matches)
|
||||
matches_matrix_subset = Subsetter.subset_matrix(matches_matrix,
|
||||
indices_to_delete)
|
||||
matches_subset = Subsetter.matrix_rows_to_list(matches_matrix_subset)
|
||||
|
||||
return matches_subset
|
||||
|
||||
@staticmethod
|
||||
def get_indices_to_delete(nr_elements, indices_to_keep):
|
||||
return list(set(range(int(nr_elements))) - set(indices_to_keep))
|
||||
|
||||
@staticmethod
|
||||
def subset_matrix(matrix_to_subset, indices_to_delete):
|
||||
for idx, idx_to_delete in enumerate(indices_to_delete):
|
||||
matrix_to_subset = Subsetter.delete_index_from_matrix(
|
||||
matrix_to_subset,
|
||||
idx_to_delete-idx # matrix shape reduced by one at each step
|
||||
)
|
||||
|
||||
return matrix_to_subset
|
||||
|
||||
@staticmethod
|
||||
def delete_index_from_matrix(matrix, idx):
|
||||
mask = np.ones(matrix.shape[0], bool)
|
||||
mask[idx] = 0
|
||||
return matrix[mask, :][:, mask]
|
||||
|
||||
@staticmethod
|
||||
def matrix_rows_to_list(matrix):
|
||||
return list(chain.from_iterable(matrix.tolist()))
|
||||
@@ -1,13 +0,0 @@
|
||||
# Ignore everything
|
||||
*
|
||||
|
||||
# But not these files...
|
||||
!.gitignore
|
||||
!test_matcher.py
|
||||
!test_stitcher.py
|
||||
!test_megapix_scaler.py
|
||||
!test_registration.py
|
||||
!test_composition.py
|
||||
!test_performance.py
|
||||
!stitching_detailed.py
|
||||
!SAMPLE_IMAGES_TO_DOWNLOAD.txt
|
||||
@@ -1,5 +0,0 @@
|
||||
https://github.com/opencv/opencv_extra/tree/4.x/testdata/stitching
|
||||
|
||||
s1.jpg s2.jpg
|
||||
boat1.jpg boat2.jpg boat3.jpg boat4.jpg boat5.jpg boat6.jpg
|
||||
budapest1.jpg budapest2.jpg budapest3.jpg budapest4.jpg budapest5.jpg budapest6.jpg
|
||||
@@ -1,406 +0,0 @@
|
||||
"""
|
||||
Stitching sample (advanced)
|
||||
===========================
|
||||
Show how to use Stitcher API from python.
|
||||
"""
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
from types import SimpleNamespace
|
||||
from collections import OrderedDict
|
||||
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
EXPOS_COMP_CHOICES = OrderedDict()
|
||||
EXPOS_COMP_CHOICES['gain_blocks'] = cv.detail.ExposureCompensator_GAIN_BLOCKS
|
||||
EXPOS_COMP_CHOICES['gain'] = cv.detail.ExposureCompensator_GAIN
|
||||
EXPOS_COMP_CHOICES['channel'] = cv.detail.ExposureCompensator_CHANNELS
|
||||
EXPOS_COMP_CHOICES['channel_blocks'] = cv.detail.ExposureCompensator_CHANNELS_BLOCKS
|
||||
EXPOS_COMP_CHOICES['no'] = cv.detail.ExposureCompensator_NO
|
||||
|
||||
BA_COST_CHOICES = OrderedDict()
|
||||
BA_COST_CHOICES['ray'] = cv.detail_BundleAdjusterRay
|
||||
BA_COST_CHOICES['reproj'] = cv.detail_BundleAdjusterReproj
|
||||
BA_COST_CHOICES['affine'] = cv.detail_BundleAdjusterAffinePartial
|
||||
BA_COST_CHOICES['no'] = cv.detail_NoBundleAdjuster
|
||||
|
||||
FEATURES_FIND_CHOICES = OrderedDict()
|
||||
try:
|
||||
cv.xfeatures2d_SURF.create() # check if the function can be called
|
||||
FEATURES_FIND_CHOICES['surf'] = cv.xfeatures2d_SURF.create
|
||||
except (AttributeError, cv.error) as e:
|
||||
print("SURF not available")
|
||||
# if SURF not available, ORB is default
|
||||
FEATURES_FIND_CHOICES['orb'] = cv.ORB.create
|
||||
try:
|
||||
FEATURES_FIND_CHOICES['sift'] = cv.xfeatures2d_SIFT.create
|
||||
except AttributeError:
|
||||
print("SIFT not available")
|
||||
try:
|
||||
FEATURES_FIND_CHOICES['brisk'] = cv.BRISK_create
|
||||
except AttributeError:
|
||||
print("BRISK not available")
|
||||
try:
|
||||
FEATURES_FIND_CHOICES['akaze'] = cv.AKAZE_create
|
||||
except AttributeError:
|
||||
print("AKAZE not available")
|
||||
|
||||
SEAM_FIND_CHOICES = OrderedDict()
|
||||
SEAM_FIND_CHOICES['dp_color'] = cv.detail_DpSeamFinder('COLOR')
|
||||
SEAM_FIND_CHOICES['dp_colorgrad'] = cv.detail_DpSeamFinder('COLOR_GRAD')
|
||||
SEAM_FIND_CHOICES['voronoi'] = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM)
|
||||
SEAM_FIND_CHOICES['no'] = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO)
|
||||
|
||||
ESTIMATOR_CHOICES = OrderedDict()
|
||||
ESTIMATOR_CHOICES['homography'] = cv.detail_HomographyBasedEstimator
|
||||
ESTIMATOR_CHOICES['affine'] = cv.detail_AffineBasedEstimator
|
||||
|
||||
WARP_CHOICES = (
|
||||
'spherical',
|
||||
'plane',
|
||||
'affine',
|
||||
'cylindrical',
|
||||
'fisheye',
|
||||
'stereographic',
|
||||
'compressedPlaneA2B1',
|
||||
'compressedPlaneA1.5B1',
|
||||
'compressedPlanePortraitA2B1',
|
||||
'compressedPlanePortraitA1.5B1',
|
||||
'paniniA2B1',
|
||||
'paniniA1.5B1',
|
||||
'paniniPortraitA2B1',
|
||||
'paniniPortraitA1.5B1',
|
||||
'mercator',
|
||||
'transverseMercator',
|
||||
)
|
||||
|
||||
WAVE_CORRECT_CHOICES = OrderedDict()
|
||||
WAVE_CORRECT_CHOICES['horiz'] = cv.detail.WAVE_CORRECT_HORIZ
|
||||
WAVE_CORRECT_CHOICES['no'] = None
|
||||
WAVE_CORRECT_CHOICES['vert'] = cv.detail.WAVE_CORRECT_VERT
|
||||
|
||||
BLEND_CHOICES = ('multiband', 'feather', 'no',)
|
||||
|
||||
def get_matcher(args):
|
||||
try_cuda = args.try_cuda
|
||||
matcher_type = args.matcher
|
||||
if args.match_conf is None:
|
||||
if args.features == 'orb':
|
||||
match_conf = 0.3
|
||||
else:
|
||||
match_conf = 0.65
|
||||
else:
|
||||
match_conf = args.match_conf
|
||||
range_width = args.rangewidth
|
||||
if matcher_type == "affine":
|
||||
matcher = cv.detail_AffineBestOf2NearestMatcher(False, try_cuda, match_conf)
|
||||
elif range_width == -1:
|
||||
matcher = cv.detail.BestOf2NearestMatcher_create(try_cuda, match_conf)
|
||||
else:
|
||||
matcher = cv.detail.BestOf2NearestRangeMatcher_create(range_width, try_cuda, match_conf)
|
||||
return matcher
|
||||
|
||||
|
||||
def get_compensator(args):
|
||||
expos_comp_type = EXPOS_COMP_CHOICES[args.expos_comp]
|
||||
expos_comp_nr_feeds = args.expos_comp_nr_feeds
|
||||
expos_comp_block_size = args.expos_comp_block_size
|
||||
# expos_comp_nr_filtering = args.expos_comp_nr_filtering
|
||||
if expos_comp_type == cv.detail.ExposureCompensator_CHANNELS:
|
||||
compensator = cv.detail_ChannelsCompensator(expos_comp_nr_feeds)
|
||||
# compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
|
||||
elif expos_comp_type == cv.detail.ExposureCompensator_CHANNELS_BLOCKS:
|
||||
compensator = cv.detail_BlocksChannelsCompensator(
|
||||
expos_comp_block_size, expos_comp_block_size,
|
||||
expos_comp_nr_feeds
|
||||
)
|
||||
# compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
|
||||
else:
|
||||
compensator = cv.detail.ExposureCompensator_createDefault(expos_comp_type)
|
||||
return compensator
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
args = {
|
||||
"img_names":["boat5.jpg", "boat2.jpg",
|
||||
"boat3.jpg", "boat4.jpg",
|
||||
"boat1.jpg", "boat6.jpg"],
|
||||
"try_cuda": False,
|
||||
"work_megapix": 0.6,
|
||||
"features": "orb",
|
||||
"matcher": "homography",
|
||||
"estimator": "homography",
|
||||
"match_conf": None,
|
||||
"conf_thresh": 1.0,
|
||||
"ba": "ray",
|
||||
"ba_refine_mask": "xxxxx",
|
||||
"wave_correct": "horiz",
|
||||
"save_graph": None,
|
||||
"warp": "spherical",
|
||||
"seam_megapix": 0.1,
|
||||
"seam": "dp_color",
|
||||
"compose_megapix": 3,
|
||||
"expos_comp": "gain_blocks",
|
||||
"expos_comp_nr_feeds": 1,
|
||||
"expos_comp_nr_filtering": 2,
|
||||
"expos_comp_block_size": 32,
|
||||
"blend": "multiband",
|
||||
"blend_strength": 5,
|
||||
"output": "time_test.jpg",
|
||||
"timelapse": None,
|
||||
"rangewidth": -1
|
||||
}
|
||||
|
||||
args = SimpleNamespace(**args)
|
||||
img_names = args.img_names
|
||||
work_megapix = args.work_megapix
|
||||
seam_megapix = args.seam_megapix
|
||||
compose_megapix = args.compose_megapix
|
||||
conf_thresh = args.conf_thresh
|
||||
ba_refine_mask = args.ba_refine_mask
|
||||
wave_correct = WAVE_CORRECT_CHOICES[args.wave_correct]
|
||||
if args.save_graph is None:
|
||||
save_graph = False
|
||||
else:
|
||||
save_graph = True
|
||||
warp_type = args.warp
|
||||
blend_type = args.blend
|
||||
blend_strength = args.blend_strength
|
||||
result_name = args.output
|
||||
if args.timelapse is not None:
|
||||
timelapse = True
|
||||
if args.timelapse == "as_is":
|
||||
timelapse_type = cv.detail.Timelapser_AS_IS
|
||||
elif args.timelapse == "crop":
|
||||
timelapse_type = cv.detail.Timelapser_CROP
|
||||
else:
|
||||
print("Bad timelapse method")
|
||||
exit()
|
||||
else:
|
||||
timelapse = False
|
||||
finder = FEATURES_FIND_CHOICES[args.features]()
|
||||
seam_work_aspect = 1
|
||||
full_img_sizes = []
|
||||
features = []
|
||||
images = []
|
||||
is_work_scale_set = False
|
||||
is_seam_scale_set = False
|
||||
is_compose_scale_set = False
|
||||
for name in img_names:
|
||||
full_img = cv.imread(cv.samples.findFile(name))
|
||||
if full_img is None:
|
||||
print("Cannot read image ", name)
|
||||
exit()
|
||||
full_img_sizes.append((full_img.shape[1], full_img.shape[0]))
|
||||
if work_megapix < 0:
|
||||
img = full_img
|
||||
work_scale = 1
|
||||
is_work_scale_set = True
|
||||
else:
|
||||
if is_work_scale_set is False:
|
||||
work_scale = min(1.0, np.sqrt(work_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1])))
|
||||
is_work_scale_set = True
|
||||
img = cv.resize(src=full_img, dsize=None, fx=work_scale, fy=work_scale, interpolation=cv.INTER_LINEAR_EXACT)
|
||||
if is_seam_scale_set is False:
|
||||
seam_scale = min(1.0, np.sqrt(seam_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1])))
|
||||
seam_work_aspect = seam_scale / work_scale
|
||||
is_seam_scale_set = True
|
||||
img_feat = cv.detail.computeImageFeatures2(finder, img)
|
||||
features.append(img_feat)
|
||||
img = cv.resize(src=full_img, dsize=None, fx=seam_scale, fy=seam_scale, interpolation=cv.INTER_LINEAR_EXACT)
|
||||
images.append(img)
|
||||
|
||||
matcher = get_matcher(args)
|
||||
p = matcher.apply2(features)
|
||||
matcher.collectGarbage()
|
||||
|
||||
if save_graph:
|
||||
with open(args.save_graph, 'w') as fh:
|
||||
fh.write(cv.detail.matchesGraphAsString(img_names, p, conf_thresh))
|
||||
|
||||
indices = cv.detail.leaveBiggestComponent(features, p, conf_thresh)
|
||||
img_subset = []
|
||||
img_names_subset = []
|
||||
full_img_sizes_subset = []
|
||||
for i in range(len(indices)):
|
||||
img_names_subset.append(img_names[indices[i, 0]])
|
||||
img_subset.append(images[indices[i, 0]])
|
||||
full_img_sizes_subset.append(full_img_sizes[indices[i, 0]])
|
||||
images = img_subset
|
||||
img_names = img_names_subset
|
||||
full_img_sizes = full_img_sizes_subset
|
||||
num_images = len(img_names)
|
||||
if num_images < 2:
|
||||
print("Need more images")
|
||||
exit()
|
||||
|
||||
estimator = ESTIMATOR_CHOICES[args.estimator]()
|
||||
b, cameras = estimator.apply(features, p, None)
|
||||
if not b:
|
||||
print("Homography estimation failed.")
|
||||
exit()
|
||||
for cam in cameras:
|
||||
cam.R = cam.R.astype(np.float32)
|
||||
|
||||
adjuster = BA_COST_CHOICES[args.ba]()
|
||||
adjuster.setConfThresh(1)
|
||||
refine_mask = np.zeros((3, 3), np.uint8)
|
||||
if ba_refine_mask[0] == 'x':
|
||||
refine_mask[0, 0] = 1
|
||||
if ba_refine_mask[1] == 'x':
|
||||
refine_mask[0, 1] = 1
|
||||
if ba_refine_mask[2] == 'x':
|
||||
refine_mask[0, 2] = 1
|
||||
if ba_refine_mask[3] == 'x':
|
||||
refine_mask[1, 1] = 1
|
||||
if ba_refine_mask[4] == 'x':
|
||||
refine_mask[1, 2] = 1
|
||||
adjuster.setRefinementMask(refine_mask)
|
||||
b, cameras = adjuster.apply(features, p, cameras)
|
||||
if not b:
|
||||
print("Camera parameters adjusting failed.")
|
||||
exit()
|
||||
focals = []
|
||||
for cam in cameras:
|
||||
focals.append(cam.focal)
|
||||
focals.sort()
|
||||
if len(focals) % 2 == 1:
|
||||
warped_image_scale = focals[len(focals) // 2]
|
||||
else:
|
||||
warped_image_scale = (focals[len(focals) // 2] + focals[len(focals) // 2 - 1]) / 2
|
||||
if wave_correct is not None:
|
||||
rmats = []
|
||||
for cam in cameras:
|
||||
rmats.append(np.copy(cam.R))
|
||||
rmats = cv.detail.waveCorrect(rmats, wave_correct)
|
||||
for idx, cam in enumerate(cameras):
|
||||
cam.R = rmats[idx]
|
||||
corners = []
|
||||
masks_warped = []
|
||||
images_warped = []
|
||||
sizes = []
|
||||
masks = []
|
||||
for i in range(0, num_images):
|
||||
um = cv.UMat(255 * np.ones((images[i].shape[0], images[i].shape[1]), np.uint8))
|
||||
masks.append(um)
|
||||
|
||||
warper = cv.PyRotationWarper(warp_type, warped_image_scale * seam_work_aspect) # warper could be nullptr?
|
||||
for idx in range(0, num_images):
|
||||
K = cameras[idx].K().astype(np.float32)
|
||||
swa = seam_work_aspect
|
||||
K[0, 0] *= swa
|
||||
K[0, 2] *= swa
|
||||
K[1, 1] *= swa
|
||||
K[1, 2] *= swa
|
||||
corner, image_wp = warper.warp(images[idx], K, cameras[idx].R, cv.INTER_LINEAR, cv.BORDER_REFLECT)
|
||||
corners.append(corner)
|
||||
sizes.append((image_wp.shape[1], image_wp.shape[0]))
|
||||
images_warped.append(image_wp)
|
||||
p, mask_wp = warper.warp(masks[idx], K, cameras[idx].R, cv.INTER_NEAREST, cv.BORDER_CONSTANT)
|
||||
masks_warped.append(mask_wp.get())
|
||||
|
||||
images_warped_f = []
|
||||
for img in images_warped:
|
||||
imgf = img.astype(np.float32)
|
||||
images_warped_f.append(imgf)
|
||||
|
||||
compensator = get_compensator(args)
|
||||
compensator.feed(corners=corners, images=images_warped, masks=masks_warped)
|
||||
|
||||
seam_finder = SEAM_FIND_CHOICES[args.seam]
|
||||
masks_warped = seam_finder.find(images_warped_f, corners, masks_warped)
|
||||
compose_scale = 1
|
||||
corners = []
|
||||
sizes = []
|
||||
blender = None
|
||||
timelapser = None
|
||||
# https://github.com/opencv/opencv/blob/4.x/samples/cpp/stitching_detailed.cpp#L725 ?
|
||||
for idx, name in enumerate(img_names):
|
||||
full_img = cv.imread(name)
|
||||
if not is_compose_scale_set:
|
||||
if compose_megapix > 0:
|
||||
compose_scale = min(1.0, np.sqrt(compose_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1])))
|
||||
is_compose_scale_set = True
|
||||
compose_work_aspect = compose_scale / work_scale
|
||||
warped_image_scale *= compose_work_aspect
|
||||
warper = cv.PyRotationWarper(warp_type, warped_image_scale)
|
||||
for i in range(0, len(img_names)):
|
||||
cameras[i].focal *= compose_work_aspect
|
||||
cameras[i].ppx *= compose_work_aspect
|
||||
cameras[i].ppy *= compose_work_aspect
|
||||
sz = (int(round(full_img_sizes[i][0] * compose_scale)),
|
||||
int(round(full_img_sizes[i][1] * compose_scale)))
|
||||
K = cameras[i].K().astype(np.float32)
|
||||
roi = warper.warpRoi(sz, K, cameras[i].R)
|
||||
corners.append(roi[0:2])
|
||||
sizes.append(roi[2:4])
|
||||
if abs(compose_scale - 1) > 1e-1:
|
||||
img = cv.resize(src=full_img, dsize=None, fx=compose_scale, fy=compose_scale,
|
||||
interpolation=cv.INTER_LINEAR_EXACT)
|
||||
else:
|
||||
img = full_img
|
||||
_img_size = (img.shape[1], img.shape[0])
|
||||
K = cameras[idx].K().astype(np.float32)
|
||||
corner, image_warped = warper.warp(img, K, cameras[idx].R, cv.INTER_LINEAR, cv.BORDER_REFLECT)
|
||||
mask = 255 * np.ones((img.shape[0], img.shape[1]), np.uint8)
|
||||
p, mask_warped = warper.warp(mask, K, cameras[idx].R, cv.INTER_NEAREST, cv.BORDER_CONSTANT)
|
||||
compensator.apply(idx, corners[idx], image_warped, mask_warped)
|
||||
image_warped_s = image_warped.astype(np.int16)
|
||||
dilated_mask = cv.dilate(masks_warped[idx], None)
|
||||
seam_mask = cv.resize(dilated_mask, (mask_warped.shape[1], mask_warped.shape[0]), 0, 0, cv.INTER_LINEAR_EXACT)
|
||||
mask_warped = cv.bitwise_and(seam_mask, mask_warped)
|
||||
if blender is None and not timelapse:
|
||||
blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
|
||||
dst_sz = cv.detail.resultRoi(corners=corners, sizes=sizes)
|
||||
blend_width = np.sqrt(dst_sz[2] * dst_sz[3]) * blend_strength / 100
|
||||
if blend_width < 1:
|
||||
blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
|
||||
elif blend_type == "multiband":
|
||||
blender = cv.detail_MultiBandBlender()
|
||||
blender.setNumBands((np.log(blend_width) / np.log(2.) - 1.).astype(np.int64))
|
||||
elif blend_type == "feather":
|
||||
blender = cv.detail_FeatherBlender()
|
||||
blender.setSharpness(1. / blend_width)
|
||||
blender.prepare(dst_sz)
|
||||
elif timelapser is None and timelapse:
|
||||
timelapser = cv.detail.Timelapser_createDefault(timelapse_type)
|
||||
timelapser.initialize(corners, sizes)
|
||||
if timelapse:
|
||||
ma_tones = np.ones((image_warped_s.shape[0], image_warped_s.shape[1]), np.uint8)
|
||||
timelapser.process(image_warped_s, ma_tones, corners[idx])
|
||||
pos_s = img_names[idx].rfind("/")
|
||||
if pos_s == -1:
|
||||
fixed_file_name = "fixed_" + img_names[idx]
|
||||
else:
|
||||
fixed_file_name = img_names[idx][:pos_s + 1] + "fixed_" + img_names[idx][pos_s + 1:]
|
||||
cv.imwrite(fixed_file_name, timelapser.getDst())
|
||||
else:
|
||||
blender.feed(cv.UMat(image_warped_s), mask_warped, corners[idx])
|
||||
if not timelapse:
|
||||
result = None
|
||||
result_mask = None
|
||||
result, result_mask = blender.blend(result, result_mask)
|
||||
# cv.imwrite(result_name, result)
|
||||
return result
|
||||
# zoom_x = 600.0 / result.shape[1]
|
||||
# dst = cv.normalize(src=result, dst=None, alpha=255., norm_type=cv.NORM_MINMAX, dtype=cv.CV_8U)
|
||||
# dst = cv.resize(dst, dsize=None, fx=zoom_x, fy=zoom_x)
|
||||
# cv.imshow(result_name, dst)
|
||||
# cv.waitKey()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import tracemalloc
|
||||
import time
|
||||
tracemalloc.start()
|
||||
start = time.time()
|
||||
result = main()
|
||||
current, peak = tracemalloc.get_traced_memory()
|
||||
print(f"Current memory usage is {current / 10**6}MB; Peak was {peak / 10**6}MB")
|
||||
tracemalloc.stop()
|
||||
end = time.time()
|
||||
print(end - start)
|
||||
@@ -1,67 +0,0 @@
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..', '..')))
|
||||
|
||||
from opencv_stitching.stitcher import Stitcher
|
||||
|
||||
|
||||
class TestImageComposition(unittest.TestCase):
|
||||
|
||||
# visual test: look especially in the sky
|
||||
def test_exposure_compensation(self):
|
||||
img = cv.imread("s1.jpg")
|
||||
img = increase_brightness(img, value=25)
|
||||
cv.imwrite("s1_bright.jpg", img)
|
||||
|
||||
stitcher = Stitcher(compensator="no", blender_type="no")
|
||||
result = stitcher.stitch(["s1_bright.jpg", "s2.jpg"])
|
||||
|
||||
cv.imwrite("without_exposure_comp.jpg", result)
|
||||
|
||||
stitcher = Stitcher(blender_type="no")
|
||||
result = stitcher.stitch(["s1_bright.jpg", "s2.jpg"])
|
||||
|
||||
cv.imwrite("with_exposure_comp.jpg", result)
|
||||
|
||||
def test_timelapse(self):
|
||||
stitcher = Stitcher(timelapse='as_is')
|
||||
_ = stitcher.stitch(["s1.jpg", "s2.jpg"])
|
||||
frame1 = cv.imread("fixed_s1.jpg")
|
||||
|
||||
max_image_shape_derivation = 3
|
||||
np.testing.assert_allclose(frame1.shape[:2],
|
||||
(700, 1811),
|
||||
atol=max_image_shape_derivation)
|
||||
|
||||
left = cv.cvtColor(frame1[:, :1300, ], cv.COLOR_BGR2GRAY)
|
||||
right = cv.cvtColor(frame1[:, 1300:, ], cv.COLOR_BGR2GRAY)
|
||||
|
||||
self.assertGreater(cv.countNonZero(left), 800000)
|
||||
self.assertEqual(cv.countNonZero(right), 0)
|
||||
|
||||
|
||||
def increase_brightness(img, value=30):
|
||||
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
|
||||
h, s, v = cv.split(hsv)
|
||||
|
||||
lim = 255 - value
|
||||
v[v > lim] = 255
|
||||
v[v <= lim] += value
|
||||
|
||||
final_hsv = cv.merge((h, s, v))
|
||||
img = cv.cvtColor(final_hsv, cv.COLOR_HSV2BGR)
|
||||
return img
|
||||
|
||||
|
||||
def starttest():
|
||||
unittest.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
starttest()
|
||||
@@ -1,47 +0,0 @@
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..', '..')))
|
||||
|
||||
from opencv_stitching.feature_matcher import FeatureMatcher
|
||||
# %%
|
||||
|
||||
|
||||
class TestMatcher(unittest.TestCase):
|
||||
|
||||
def test_array_in_sqare_matrix(self):
|
||||
array = np.zeros(9)
|
||||
|
||||
matrix = FeatureMatcher.array_in_sqare_matrix(array)
|
||||
|
||||
np.testing.assert_array_equal(matrix, np.array([[0., 0., 0.],
|
||||
[0., 0., 0.],
|
||||
[0., 0., 0.]]))
|
||||
|
||||
def test_get_all_img_combinations(self):
|
||||
nimgs = 3
|
||||
|
||||
combinations = list(FeatureMatcher.get_all_img_combinations(nimgs))
|
||||
|
||||
self.assertEqual(combinations, [(0, 1), (0, 2), (1, 2)])
|
||||
|
||||
def test_get_match_conf(self):
|
||||
explicit_match_conf = FeatureMatcher.get_match_conf(1, 'orb')
|
||||
implicit_match_conf_orb = FeatureMatcher.get_match_conf(None, 'orb')
|
||||
implicit_match_conf_other = FeatureMatcher.get_match_conf(None, 'surf')
|
||||
|
||||
self.assertEqual(explicit_match_conf, 1)
|
||||
self.assertEqual(implicit_match_conf_orb, 0.3)
|
||||
self.assertEqual(implicit_match_conf_other, 0.65)
|
||||
|
||||
|
||||
def starttest():
|
||||
unittest.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
starttest()
|
||||
@@ -1,59 +0,0 @@
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
|
||||
import cv2 as cv
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..', '..')))
|
||||
|
||||
from opencv_stitching.megapix_scaler import MegapixScaler
|
||||
from opencv_stitching.megapix_downscaler import MegapixDownscaler
|
||||
#%%
|
||||
|
||||
|
||||
class TestScaler(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.img = cv.imread("s1.jpg")
|
||||
self.size = (self.img.shape[1], self.img.shape[0])
|
||||
|
||||
def test_get_scale_by_resolution(self):
|
||||
scaler = MegapixScaler(0.6)
|
||||
|
||||
scale = scaler.get_scale_by_resolution(1_200_000)
|
||||
|
||||
self.assertEqual(scale, 0.7071067811865476)
|
||||
|
||||
def test_get_scale_by_image(self):
|
||||
scaler = MegapixScaler(0.6)
|
||||
|
||||
scaler.set_scale_by_img_size(self.size)
|
||||
|
||||
self.assertEqual(scaler.scale, 0.8294067854101966)
|
||||
|
||||
def test_get_scaled_img_size(self):
|
||||
scaler = MegapixScaler(0.6)
|
||||
scaler.set_scale_by_img_size(self.size)
|
||||
|
||||
size = scaler.get_scaled_img_size(self.size)
|
||||
self.assertEqual(size, (1033, 581))
|
||||
# 581*1033 = 600173 px = ~0.6 MP
|
||||
|
||||
def test_force_of_downscaling(self):
|
||||
normal_scaler = MegapixScaler(2)
|
||||
downscaler = MegapixDownscaler(2)
|
||||
|
||||
normal_scaler.set_scale_by_img_size(self.size)
|
||||
downscaler.set_scale_by_img_size(self.size)
|
||||
|
||||
self.assertEqual(normal_scaler.scale, 1.5142826857233715)
|
||||
self.assertEqual(downscaler.scale, 1.0)
|
||||
|
||||
|
||||
def starttest():
|
||||
unittest.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
starttest()
|
||||
@@ -1,65 +0,0 @@
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import tracemalloc
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..', '..')))
|
||||
|
||||
from opencv_stitching.stitcher import Stitcher
|
||||
from stitching_detailed import main
|
||||
# %%
|
||||
|
||||
|
||||
class TestStitcher(unittest.TestCase):
|
||||
|
||||
def test_performance(self):
|
||||
|
||||
print("Run new Stitcher class:")
|
||||
|
||||
start = time.time()
|
||||
tracemalloc.start()
|
||||
|
||||
stitcher = Stitcher(final_megapix=3)
|
||||
stitcher.stitch(["boat5.jpg", "boat2.jpg",
|
||||
"boat3.jpg", "boat4.jpg",
|
||||
"boat1.jpg", "boat6.jpg"])
|
||||
stitcher.collect_garbage()
|
||||
|
||||
_, peak_memory = tracemalloc.get_traced_memory()
|
||||
tracemalloc.stop()
|
||||
end = time.time()
|
||||
time_needed = end - start
|
||||
|
||||
print(f"Peak was {peak_memory / 10**6} MB")
|
||||
print(f"Time was {time_needed} s")
|
||||
|
||||
print("Run original stitching_detailed.py:")
|
||||
|
||||
start = time.time()
|
||||
tracemalloc.start()
|
||||
|
||||
main()
|
||||
|
||||
_, peak_memory_detailed = tracemalloc.get_traced_memory()
|
||||
tracemalloc.stop()
|
||||
end = time.time()
|
||||
time_needed_detailed = end - start
|
||||
|
||||
print(f"Peak was {peak_memory_detailed / 10**6} MB")
|
||||
print(f"Time was {time_needed_detailed} s")
|
||||
|
||||
self.assertLessEqual(peak_memory / 10**6,
|
||||
peak_memory_detailed / 10**6)
|
||||
uncertainty_based_on_run = 0.25
|
||||
self.assertLessEqual(time_needed - uncertainty_based_on_run,
|
||||
time_needed_detailed)
|
||||
|
||||
|
||||
def starttest():
|
||||
unittest.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
starttest()
|
||||
@@ -1,100 +0,0 @@
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..', '..')))
|
||||
|
||||
from opencv_stitching.feature_detector import FeatureDetector
|
||||
from opencv_stitching.feature_matcher import FeatureMatcher
|
||||
from opencv_stitching.subsetter import Subsetter
|
||||
|
||||
|
||||
class TestImageRegistration(unittest.TestCase):
|
||||
|
||||
def test_feature_detector(self):
|
||||
img1 = cv.imread("s1.jpg")
|
||||
|
||||
default_number_of_keypoints = 500
|
||||
detector = FeatureDetector("orb")
|
||||
features = detector.detect_features(img1)
|
||||
self.assertEqual(len(features.getKeypoints()),
|
||||
default_number_of_keypoints)
|
||||
|
||||
other_keypoints = 1000
|
||||
detector = FeatureDetector("orb", nfeatures=other_keypoints)
|
||||
features = detector.detect_features(img1)
|
||||
self.assertEqual(len(features.getKeypoints()), other_keypoints)
|
||||
|
||||
def test_feature_matcher(self):
|
||||
img1, img2 = cv.imread("s1.jpg"), cv.imread("s2.jpg")
|
||||
|
||||
detector = FeatureDetector("orb")
|
||||
features = [detector.detect_features(img1),
|
||||
detector.detect_features(img2)]
|
||||
|
||||
matcher = FeatureMatcher()
|
||||
pairwise_matches = matcher.match_features(features)
|
||||
self.assertEqual(len(pairwise_matches), len(features)**2)
|
||||
self.assertGreater(pairwise_matches[1].confidence, 2)
|
||||
|
||||
matches_matrix = FeatureMatcher.get_matches_matrix(pairwise_matches)
|
||||
self.assertEqual(matches_matrix.shape, (2, 2))
|
||||
conf_matrix = FeatureMatcher.get_confidence_matrix(pairwise_matches)
|
||||
self.assertTrue(np.array_equal(
|
||||
conf_matrix > 2,
|
||||
np.array([[False, True], [True, False]])
|
||||
))
|
||||
|
||||
def test_subsetting(self):
|
||||
img1, img2 = cv.imread("s1.jpg"), cv.imread("s2.jpg")
|
||||
img3, img4 = cv.imread("boat1.jpg"), cv.imread("boat2.jpg")
|
||||
img5 = cv.imread("boat3.jpg")
|
||||
img_names = ["s1.jpg", "s2.jpg", "boat1.jpg", "boat2.jpg", "boat3.jpg"]
|
||||
|
||||
detector = FeatureDetector("orb")
|
||||
features = [detector.detect_features(img1),
|
||||
detector.detect_features(img2),
|
||||
detector.detect_features(img3),
|
||||
detector.detect_features(img4),
|
||||
detector.detect_features(img5)]
|
||||
matcher = FeatureMatcher()
|
||||
pairwise_matches = matcher.match_features(features)
|
||||
subsetter = Subsetter(confidence_threshold=1,
|
||||
matches_graph_dot_file="dot_graph.txt") # view in https://dreampuf.github.io # noqa
|
||||
|
||||
indices = subsetter.get_indices_to_keep(features, pairwise_matches)
|
||||
indices_to_delete = subsetter.get_indices_to_delete(len(img_names),
|
||||
indices)
|
||||
|
||||
self.assertEqual(indices, [2, 3, 4])
|
||||
self.assertEqual(indices_to_delete, [0, 1])
|
||||
|
||||
subsetted_image_names = subsetter.subset_list(img_names, indices)
|
||||
self.assertEqual(subsetted_image_names,
|
||||
['boat1.jpg', 'boat2.jpg', 'boat3.jpg'])
|
||||
|
||||
matches_subset = subsetter.subset_matches(pairwise_matches, indices)
|
||||
# FeatureMatcher.get_confidence_matrix(pairwise_matches)
|
||||
# FeatureMatcher.get_confidence_matrix(subsetted_matches)
|
||||
self.assertEqual(pairwise_matches[13].confidence,
|
||||
matches_subset[1].confidence)
|
||||
|
||||
graph = subsetter.get_matches_graph(img_names, pairwise_matches)
|
||||
self.assertTrue(graph.startswith("graph matches_graph{"))
|
||||
|
||||
subsetter.save_matches_graph_dot_file(img_names, pairwise_matches)
|
||||
with open('dot_graph.txt', 'r') as file:
|
||||
graph = file.read()
|
||||
self.assertTrue(graph.startswith("graph matches_graph{"))
|
||||
|
||||
|
||||
def starttest():
|
||||
unittest.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
starttest()
|
||||
@@ -1,108 +0,0 @@
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..', '..')))
|
||||
|
||||
from opencv_stitching.stitcher import Stitcher
|
||||
# %%
|
||||
|
||||
|
||||
class TestStitcher(unittest.TestCase):
|
||||
|
||||
def test_stitcher_aquaduct(self):
|
||||
stitcher = Stitcher(n_features=250)
|
||||
result = stitcher.stitch(["s1.jpg", "s2.jpg"])
|
||||
cv.imwrite("result.jpg", result)
|
||||
|
||||
max_image_shape_derivation = 3
|
||||
np.testing.assert_allclose(result.shape[:2],
|
||||
(700, 1811),
|
||||
atol=max_image_shape_derivation)
|
||||
|
||||
@unittest.skip("skip boat test (high resuolution ran >30s)")
|
||||
def test_stitcher_boat1(self):
|
||||
settings = {"warper_type": "fisheye",
|
||||
"wave_correct_kind": "no",
|
||||
"finder": "dp_colorgrad",
|
||||
"compensator": "no",
|
||||
"conf_thresh": 0.3}
|
||||
|
||||
stitcher = Stitcher(**settings)
|
||||
result = stitcher.stitch(["boat5.jpg", "boat2.jpg",
|
||||
"boat3.jpg", "boat4.jpg",
|
||||
"boat1.jpg", "boat6.jpg"])
|
||||
|
||||
cv.imwrite("boat_fisheye.jpg", result)
|
||||
|
||||
max_image_shape_derivation = 600
|
||||
np.testing.assert_allclose(result.shape[:2],
|
||||
(14488, 7556),
|
||||
atol=max_image_shape_derivation)
|
||||
|
||||
@unittest.skip("skip boat test (high resuolution ran >30s)")
|
||||
def test_stitcher_boat2(self):
|
||||
settings = {"warper_type": "compressedPlaneA2B1",
|
||||
"finder": "dp_colorgrad",
|
||||
"compensator": "channel_blocks",
|
||||
"conf_thresh": 0.3}
|
||||
|
||||
stitcher = Stitcher(**settings)
|
||||
result = stitcher.stitch(["boat5.jpg", "boat2.jpg",
|
||||
"boat3.jpg", "boat4.jpg",
|
||||
"boat1.jpg", "boat6.jpg"])
|
||||
|
||||
cv.imwrite("boat_plane.jpg", result)
|
||||
|
||||
max_image_shape_derivation = 600
|
||||
np.testing.assert_allclose(result.shape[:2],
|
||||
(7400, 12340),
|
||||
atol=max_image_shape_derivation)
|
||||
|
||||
def test_stitcher_boat_aquaduct_subset(self):
|
||||
settings = {"final_megapix": 1}
|
||||
|
||||
stitcher = Stitcher(**settings)
|
||||
result = stitcher.stitch(["boat5.jpg",
|
||||
"s1.jpg", "s2.jpg",
|
||||
"boat2.jpg",
|
||||
"boat3.jpg", "boat4.jpg",
|
||||
"boat1.jpg", "boat6.jpg"])
|
||||
cv.imwrite("subset_low_res.jpg", result)
|
||||
|
||||
max_image_shape_derivation = 100
|
||||
np.testing.assert_allclose(result.shape[:2],
|
||||
(839, 3384),
|
||||
atol=max_image_shape_derivation)
|
||||
|
||||
def test_stitcher_budapest(self):
|
||||
settings = {"matcher_type": "affine",
|
||||
"estimator": "affine",
|
||||
"adjuster": "affine",
|
||||
"warper_type": "affine",
|
||||
"wave_correct_kind": "no",
|
||||
"confidence_threshold": 0.3}
|
||||
|
||||
stitcher = Stitcher(**settings)
|
||||
result = stitcher.stitch(["budapest1.jpg", "budapest2.jpg",
|
||||
"budapest3.jpg", "budapest4.jpg",
|
||||
"budapest5.jpg", "budapest6.jpg"])
|
||||
|
||||
cv.imwrite("budapest.jpg", result)
|
||||
|
||||
max_image_shape_derivation = 50
|
||||
np.testing.assert_allclose(result.shape[:2],
|
||||
(1155, 2310),
|
||||
atol=max_image_shape_derivation)
|
||||
|
||||
|
||||
def starttest():
|
||||
unittest.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
starttest()
|
||||
@@ -1,50 +0,0 @@
|
||||
import os
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Timelapser:
|
||||
|
||||
TIMELAPSE_CHOICES = ('no', 'as_is', 'crop',)
|
||||
DEFAULT_TIMELAPSE = 'no'
|
||||
|
||||
def __init__(self, timelapse=DEFAULT_TIMELAPSE):
|
||||
self.do_timelapse = True
|
||||
self.timelapse_type = None
|
||||
self.timelapser = None
|
||||
|
||||
if timelapse == "as_is":
|
||||
self.timelapse_type = cv.detail.Timelapser_AS_IS
|
||||
elif timelapse == "crop":
|
||||
self.timelapse_type = cv.detail.Timelapser_CROP
|
||||
else:
|
||||
self.do_timelapse = False
|
||||
|
||||
if self.do_timelapse:
|
||||
self.timelapser = cv.detail.Timelapser_createDefault(
|
||||
self.timelapse_type
|
||||
)
|
||||
|
||||
def initialize(self, *args):
|
||||
"""https://docs.opencv.org/4.x/dd/dac/classcv_1_1detail_1_1Timelapser.html#aaf0f7c4128009f02473332a0c41f6345""" # noqa
|
||||
self.timelapser.initialize(*args)
|
||||
|
||||
def process_and_save_frame(self, img_name, img, corner):
|
||||
self.process_frame(img, corner)
|
||||
cv.imwrite(self.get_fixed_filename(img_name), self.get_frame())
|
||||
|
||||
def process_frame(self, img, corner):
|
||||
mask = np.ones((img.shape[0], img.shape[1]), np.uint8)
|
||||
img = img.astype(np.int16)
|
||||
self.timelapser.process(img, mask, corner)
|
||||
|
||||
def get_frame(self):
|
||||
frame = self.timelapser.getDst()
|
||||
frame = np.float32(cv.UMat.get(frame))
|
||||
frame = cv.convertScaleAbs(frame)
|
||||
return frame
|
||||
|
||||
@staticmethod
|
||||
def get_fixed_filename(img_name):
|
||||
dirname, filename = os.path.split(img_name)
|
||||
return os.path.join(dirname, "fixed_" + filename)
|
||||
@@ -1,71 +0,0 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Warper:
|
||||
|
||||
WARP_TYPE_CHOICES = ('spherical', 'plane', 'affine', 'cylindrical',
|
||||
'fisheye', 'stereographic', 'compressedPlaneA2B1',
|
||||
'compressedPlaneA1.5B1',
|
||||
'compressedPlanePortraitA2B1',
|
||||
'compressedPlanePortraitA1.5B1',
|
||||
'paniniA2B1', 'paniniA1.5B1', 'paniniPortraitA2B1',
|
||||
'paniniPortraitA1.5B1', 'mercator',
|
||||
'transverseMercator')
|
||||
|
||||
DEFAULT_WARP_TYPE = 'spherical'
|
||||
|
||||
def __init__(self, warper_type=DEFAULT_WARP_TYPE, scale=1):
|
||||
self.warper_type = warper_type
|
||||
self.warper = cv.PyRotationWarper(warper_type, scale)
|
||||
self.scale = scale
|
||||
|
||||
def warp_images_and_image_masks(self, imgs, cameras, scale=None, aspect=1):
|
||||
self.update_scale(scale)
|
||||
for img, camera in zip(imgs, cameras):
|
||||
yield self.warp_image_and_image_mask(img, camera, scale, aspect)
|
||||
|
||||
def warp_image_and_image_mask(self, img, camera, scale=None, aspect=1):
|
||||
self.update_scale(scale)
|
||||
corner, img_warped = self.warp_image(img, camera, aspect)
|
||||
mask = 255 * np.ones((img.shape[0], img.shape[1]), np.uint8)
|
||||
_, mask_warped = self.warp_image(mask, camera, aspect, mask=True)
|
||||
return img_warped, mask_warped, corner
|
||||
|
||||
def warp_image(self, image, camera, aspect=1, mask=False):
|
||||
if mask:
|
||||
interp_mode = cv.INTER_NEAREST
|
||||
border_mode = cv.BORDER_CONSTANT
|
||||
else:
|
||||
interp_mode = cv.INTER_LINEAR
|
||||
border_mode = cv.BORDER_REFLECT
|
||||
|
||||
corner, warped_image = self.warper.warp(image,
|
||||
Warper.get_K(camera, aspect),
|
||||
camera.R,
|
||||
interp_mode,
|
||||
border_mode)
|
||||
return corner, warped_image
|
||||
|
||||
def warp_roi(self, width, height, camera, scale=None, aspect=1):
|
||||
self.update_scale(scale)
|
||||
roi = (width, height)
|
||||
K = Warper.get_K(camera, aspect)
|
||||
return self.warper.warpRoi(roi, K, camera.R)
|
||||
|
||||
def update_scale(self, scale):
|
||||
if scale is not None and scale != self.scale:
|
||||
self.warper = cv.PyRotationWarper(self.warper_type, scale) # setScale not working: https://docs.opencv.org/4.x/d5/d76/classcv_1_1PyRotationWarper.html#a90b000bb75f95294f9b0b6ec9859eb55
|
||||
self.scale = scale
|
||||
|
||||
@staticmethod
|
||||
def get_K(camera, aspect=1):
|
||||
K = camera.K().astype(np.float32)
|
||||
""" Modification of intrinsic parameters needed if cameras were
|
||||
obtained on different scale than the scale of the Images which should
|
||||
be warped """
|
||||
K[0, 0] *= aspect
|
||||
K[0, 2] *= aspect
|
||||
K[1, 1] *= aspect
|
||||
K[1, 2] *= aspect
|
||||
return K
|
||||
@@ -1,232 +0,0 @@
|
||||
"""
|
||||
Stitching sample (advanced)
|
||||
===========================
|
||||
|
||||
Show how to use Stitcher API from python.
|
||||
"""
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
from opencv_stitching.stitcher import Stitcher
|
||||
|
||||
from opencv_stitching.image_handler import ImageHandler
|
||||
from opencv_stitching.feature_detector import FeatureDetector
|
||||
from opencv_stitching.feature_matcher import FeatureMatcher
|
||||
from opencv_stitching.subsetter import Subsetter
|
||||
from opencv_stitching.camera_estimator import CameraEstimator
|
||||
from opencv_stitching.camera_adjuster import CameraAdjuster
|
||||
from opencv_stitching.camera_wave_corrector import WaveCorrector
|
||||
from opencv_stitching.warper import Warper
|
||||
from opencv_stitching.exposure_error_compensator import ExposureErrorCompensator # noqa
|
||||
from opencv_stitching.seam_finder import SeamFinder
|
||||
from opencv_stitching.blender import Blender
|
||||
from opencv_stitching.timelapser import Timelapser
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="opencv_stitching_tool.py",
|
||||
description="Rotation model images stitcher"
|
||||
)
|
||||
parser.add_argument(
|
||||
'img_names', nargs='+',
|
||||
help="Files to stitch", type=str
|
||||
)
|
||||
parser.add_argument(
|
||||
'--medium_megapix', action='store',
|
||||
default=ImageHandler.DEFAULT_MEDIUM_MEGAPIX,
|
||||
help="Resolution for image registration step. "
|
||||
"The default is %s Mpx" % ImageHandler.DEFAULT_MEDIUM_MEGAPIX,
|
||||
type=float, dest='medium_megapix'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--detector', action='store',
|
||||
default=FeatureDetector.DEFAULT_DETECTOR,
|
||||
help="Type of features used for images matching. "
|
||||
"The default is '%s'." % FeatureDetector.DEFAULT_DETECTOR,
|
||||
choices=FeatureDetector.DETECTOR_CHOICES.keys(),
|
||||
type=str, dest='detector'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--nfeatures', action='store',
|
||||
default=500,
|
||||
help="Type of features used for images matching. "
|
||||
"The default is 500.",
|
||||
type=int, dest='nfeatures'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--matcher_type', action='store', default=FeatureMatcher.DEFAULT_MATCHER,
|
||||
help="Matcher used for pairwise image matching. "
|
||||
"The default is '%s'." % FeatureMatcher.DEFAULT_MATCHER,
|
||||
choices=FeatureMatcher.MATCHER_CHOICES,
|
||||
type=str, dest='matcher_type'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--range_width', action='store',
|
||||
default=FeatureMatcher.DEFAULT_RANGE_WIDTH,
|
||||
help="uses range_width to limit number of images to match with.",
|
||||
type=int, dest='range_width'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--try_use_gpu',
|
||||
action='store',
|
||||
default=False,
|
||||
help="Try to use CUDA. The default value is no. "
|
||||
"All default values are for CPU mode.",
|
||||
type=bool, dest='try_use_gpu'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--match_conf', action='store',
|
||||
help="Confidence for feature matching step. "
|
||||
"The default is 0.3 for ORB and 0.65 for other feature types.",
|
||||
type=float, dest='match_conf'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--confidence_threshold', action='store',
|
||||
default=Subsetter.DEFAULT_CONFIDENCE_THRESHOLD,
|
||||
help="Threshold for two images are from the same panorama confidence. "
|
||||
"The default is '%s'." % Subsetter.DEFAULT_CONFIDENCE_THRESHOLD,
|
||||
type=float, dest='confidence_threshold'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--matches_graph_dot_file', action='store',
|
||||
default=Subsetter.DEFAULT_MATCHES_GRAPH_DOT_FILE,
|
||||
help="Save matches graph represented in DOT language to <file_name> file.",
|
||||
type=str, dest='matches_graph_dot_file'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--estimator', action='store',
|
||||
default=CameraEstimator.DEFAULT_CAMERA_ESTIMATOR,
|
||||
help="Type of estimator used for transformation estimation. "
|
||||
"The default is '%s'." % CameraEstimator.DEFAULT_CAMERA_ESTIMATOR,
|
||||
choices=CameraEstimator.CAMERA_ESTIMATOR_CHOICES.keys(),
|
||||
type=str, dest='estimator'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--adjuster', action='store',
|
||||
default=CameraAdjuster.DEFAULT_CAMERA_ADJUSTER,
|
||||
help="Bundle adjustment cost function. "
|
||||
"The default is '%s'." % CameraAdjuster.DEFAULT_CAMERA_ADJUSTER,
|
||||
choices=CameraAdjuster.CAMERA_ADJUSTER_CHOICES.keys(),
|
||||
type=str, dest='adjuster'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--refinement_mask', action='store',
|
||||
default=CameraAdjuster.DEFAULT_REFINEMENT_MASK,
|
||||
help="Set refinement mask for bundle adjustment. It looks like 'x_xxx', "
|
||||
"where 'x' means refine respective parameter and '_' means don't "
|
||||
"refine, and has the following format:<fx><skew><ppx><aspect><ppy>. "
|
||||
"The default mask is '%s'. "
|
||||
"If bundle adjustment doesn't support estimation of selected "
|
||||
"parameter then the respective flag is ignored."
|
||||
"" % CameraAdjuster.DEFAULT_REFINEMENT_MASK,
|
||||
type=str, dest='refinement_mask'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--wave_correct_kind', action='store',
|
||||
default=WaveCorrector.DEFAULT_WAVE_CORRECTION,
|
||||
help="Perform wave effect correction. "
|
||||
"The default is '%s'" % WaveCorrector.DEFAULT_WAVE_CORRECTION,
|
||||
choices=WaveCorrector.WAVE_CORRECT_CHOICES.keys(),
|
||||
type=str, dest='wave_correct_kind'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--warper_type', action='store', default=Warper.DEFAULT_WARP_TYPE,
|
||||
help="Warp surface type. The default is '%s'." % Warper.DEFAULT_WARP_TYPE,
|
||||
choices=Warper.WARP_TYPE_CHOICES,
|
||||
type=str, dest='warper_type'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--low_megapix', action='store', default=ImageHandler.DEFAULT_LOW_MEGAPIX,
|
||||
help="Resolution for seam estimation and exposure estimation step. "
|
||||
"The default is %s Mpx." % ImageHandler.DEFAULT_LOW_MEGAPIX,
|
||||
type=float, dest='low_megapix'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--compensator', action='store',
|
||||
default=ExposureErrorCompensator.DEFAULT_COMPENSATOR,
|
||||
help="Exposure compensation method. "
|
||||
"The default is '%s'." % ExposureErrorCompensator.DEFAULT_COMPENSATOR,
|
||||
choices=ExposureErrorCompensator.COMPENSATOR_CHOICES.keys(),
|
||||
type=str, dest='compensator'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--nr_feeds', action='store',
|
||||
default=ExposureErrorCompensator.DEFAULT_NR_FEEDS,
|
||||
help="Number of exposure compensation feed.",
|
||||
type=np.int32, dest='nr_feeds'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--block_size', action='store',
|
||||
default=ExposureErrorCompensator.DEFAULT_BLOCK_SIZE,
|
||||
help="BLock size in pixels used by the exposure compensator. "
|
||||
"The default is '%s'." % ExposureErrorCompensator.DEFAULT_BLOCK_SIZE,
|
||||
type=np.int32, dest='block_size'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--finder', action='store', default=SeamFinder.DEFAULT_SEAM_FINDER,
|
||||
help="Seam estimation method. "
|
||||
"The default is '%s'." % SeamFinder.DEFAULT_SEAM_FINDER,
|
||||
choices=SeamFinder.SEAM_FINDER_CHOICES.keys(),
|
||||
type=str, dest='finder'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--final_megapix', action='store',
|
||||
default=ImageHandler.DEFAULT_FINAL_MEGAPIX,
|
||||
help="Resolution for compositing step. Use -1 for original resolution. "
|
||||
"The default is %s" % ImageHandler.DEFAULT_FINAL_MEGAPIX,
|
||||
type=float, dest='final_megapix'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--blender_type', action='store', default=Blender.DEFAULT_BLENDER,
|
||||
help="Blending method. The default is '%s'." % Blender.DEFAULT_BLENDER,
|
||||
choices=Blender.BLENDER_CHOICES,
|
||||
type=str, dest='blender_type'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--blend_strength', action='store', default=Blender.DEFAULT_BLEND_STRENGTH,
|
||||
help="Blending strength from [0,100] range. "
|
||||
"The default is '%s'." % Blender.DEFAULT_BLEND_STRENGTH,
|
||||
type=np.int32, dest='blend_strength'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--timelapse', action='store', default=Timelapser.DEFAULT_TIMELAPSE,
|
||||
help="Output warped images separately as frames of a time lapse movie, "
|
||||
"with 'fixed_' prepended to input file names. "
|
||||
"The default is '%s'." % Timelapser.DEFAULT_TIMELAPSE,
|
||||
choices=Timelapser.TIMELAPSE_CHOICES,
|
||||
type=str, dest='timelapse'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--output', action='store', default='result.jpg',
|
||||
help="The default is 'result.jpg'",
|
||||
type=str, dest='output'
|
||||
)
|
||||
|
||||
__doc__ += '\n' + parser.format_help()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(__doc__)
|
||||
args = parser.parse_args()
|
||||
args_dict = vars(args)
|
||||
|
||||
# Extract In- and Output
|
||||
img_names = args_dict.pop("img_names")
|
||||
img_names = [cv.samples.findFile(img_name) for img_name in img_names]
|
||||
output = args_dict.pop("output")
|
||||
|
||||
stitcher = Stitcher(**args_dict)
|
||||
panorama = stitcher.stitch(img_names)
|
||||
|
||||
cv.imwrite(output, panorama)
|
||||
|
||||
zoom_x = 600.0 / panorama.shape[1]
|
||||
preview = cv.resize(panorama, dsize=None, fx=zoom_x, fy=zoom_x)
|
||||
|
||||
cv.imshow(output, preview)
|
||||
cv.waitKey()
|
||||
cv.destroyAllWindows()
|
||||
@@ -252,7 +252,7 @@ bool CvCascadeClassifier::train( const string _cascadeDirName,
|
||||
fs << "}";
|
||||
}
|
||||
// save current stage
|
||||
char buf[10];
|
||||
char buf[32];
|
||||
sprintf(buf, "%s%d", "stage", i );
|
||||
string stageFilename = dirName + buf + ".xml";
|
||||
FileStorage fs( stageFilename, FileStorage::WRITE );
|
||||
|
||||
@@ -119,12 +119,12 @@ if(CV_GCC OR CV_CLANG)
|
||||
# we want.
|
||||
add_extra_compiler_option(-Wall)
|
||||
endif()
|
||||
add_extra_compiler_option(-Werror=return-type)
|
||||
add_extra_compiler_option(-Werror=non-virtual-dtor)
|
||||
add_extra_compiler_option(-Werror=address)
|
||||
add_extra_compiler_option(-Werror=sequence-point)
|
||||
add_extra_compiler_option(-Wreturn-type)
|
||||
add_extra_compiler_option(-Wnon-virtual-dtor)
|
||||
add_extra_compiler_option(-Waddress)
|
||||
add_extra_compiler_option(-Wsequence-point)
|
||||
add_extra_compiler_option(-Wformat)
|
||||
add_extra_compiler_option(-Werror=format-security -Wformat)
|
||||
add_extra_compiler_option(-Wformat-security -Wformat)
|
||||
add_extra_compiler_option(-Wmissing-declarations)
|
||||
add_extra_compiler_option(-Wmissing-prototypes)
|
||||
add_extra_compiler_option(-Wstrict-prototypes)
|
||||
@@ -314,6 +314,10 @@ if(MSVC)
|
||||
set(OPENCV_EXTRA_C_FLAGS "${OPENCV_EXTRA_C_FLAGS} /FS")
|
||||
set(OPENCV_EXTRA_CXX_FLAGS "${OPENCV_EXTRA_CXX_FLAGS} /FS")
|
||||
endif()
|
||||
|
||||
if(AARCH64 AND NOT MSVC_VERSION LESS 1930)
|
||||
set(OPENCV_EXTRA_FLAGS "${OPENCV_EXTRA_FLAGS} /D _ARM64_DISTINCT_NEON_TYPES")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(PROJECT_NAME STREQUAL "OpenCV")
|
||||
@@ -367,6 +371,22 @@ if(NOT OPENCV_SKIP_LINK_AS_NEEDED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Apply "-Wl,--no-undefined" linker flags: https://github.com/opencv/opencv/pull/21347
|
||||
if(NOT OPENCV_SKIP_LINK_NO_UNDEFINED)
|
||||
if(UNIX AND (NOT APPLE OR NOT CMAKE_VERSION VERSION_LESS "3.2"))
|
||||
set(_option "-Wl,--no-undefined")
|
||||
set(_saved_CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_option}") # requires CMake 3.2+ and CMP0056
|
||||
ocv_check_compiler_flag(CXX "" HAVE_LINK_NO_UNDEFINED)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${_saved_CMAKE_EXE_LINKER_FLAGS}")
|
||||
if(HAVE_LINK_NO_UNDEFINED)
|
||||
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} ${_option}")
|
||||
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} ${_option}")
|
||||
set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} ${_option}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# combine all "extra" options
|
||||
if(NOT OPENCV_SKIP_EXTRA_COMPILER_FLAGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_C_FLAGS}")
|
||||
|
||||
@@ -1,101 +1,38 @@
|
||||
# The script detects Intel(R) Inference Engine installation
|
||||
#
|
||||
# Cache variables:
|
||||
# INF_ENGINE_RELEASE - a number reflecting IE source interface (linked with OpenVINO release)
|
||||
#
|
||||
# Detect parameters:
|
||||
# 1. Native cmake IE package:
|
||||
# - environment variable InferenceEngine_DIR is set to location of cmake module
|
||||
# 2. Custom location:
|
||||
# - INF_ENGINE_INCLUDE_DIRS - headers search location
|
||||
# - INF_ENGINE_LIB_DIRS - library search location
|
||||
# 3. OpenVINO location:
|
||||
# - environment variable INTEL_OPENVINO_DIR is set to location of OpenVINO installation dir
|
||||
# - INF_ENGINE_PLATFORM - part of name of library directory representing its platform
|
||||
# The script detects Intel(R) OpenVINO(TM) runtime installation
|
||||
#
|
||||
# Result:
|
||||
# INF_ENGINE_TARGET - set to name of imported library target representing InferenceEngine
|
||||
#
|
||||
# - target ocv.3rdparty.openvino
|
||||
|
||||
|
||||
macro(ocv_ie_find_extra_libraries find_prefix find_suffix)
|
||||
file(GLOB libraries "${INF_ENGINE_LIB_DIRS}/${find_prefix}inference_engine*${find_suffix}")
|
||||
foreach(full_path IN LISTS libraries)
|
||||
get_filename_component(library "${full_path}" NAME_WE)
|
||||
string(REPLACE "${find_prefix}" "" library "${library}")
|
||||
if(library STREQUAL "inference_engine" OR library STREQUAL "inference_engined")
|
||||
# skip
|
||||
else()
|
||||
add_library(${library} UNKNOWN IMPORTED)
|
||||
set_target_properties(${library} PROPERTIES
|
||||
IMPORTED_LOCATION "${full_path}")
|
||||
list(APPEND custom_libraries ${library})
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
function(add_custom_ie_build _inc _lib _lib_rel _lib_dbg _msg)
|
||||
if(NOT _inc OR NOT (_lib OR _lib_rel OR _lib_dbg))
|
||||
if(WITH_OPENVINO)
|
||||
find_package(OpenVINO QUIET)
|
||||
if(OpenVINO_FOUND)
|
||||
message(STATUS "OpenVINO FOUND: ${OpenVINO_VERSION}")
|
||||
math(EXPR ver "${OpenVINO_VERSION_MAJOR} * 1000000 + ${OpenVINO_VERSION_MINOR} * 10000 + ${OpenVINO_VERSION_PATCH} * 100")
|
||||
ocv_add_external_target(openvino "" "openvino::runtime" "INF_ENGINE_RELEASE=${ver};HAVE_NGRAPH;HAVE_DNN_NGRAPH;HAVE_INF_ENGINE")
|
||||
set(HAVE_OPENVINO 1)
|
||||
return()
|
||||
endif()
|
||||
if(NOT _lib)
|
||||
if(_lib_rel)
|
||||
set(_lib "${_lib_rel}")
|
||||
else()
|
||||
set(_lib "${_lib_dbg}")
|
||||
endif()
|
||||
endif()
|
||||
add_library(inference_engine UNKNOWN IMPORTED)
|
||||
set_target_properties(inference_engine PROPERTIES
|
||||
IMPORTED_LOCATION "${_lib}"
|
||||
IMPORTED_IMPLIB_RELEASE "${_lib_rel}"
|
||||
IMPORTED_IMPLIB_DEBUG "${_lib_dbg}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_inc}"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(custom_libraries "")
|
||||
set(__prefixes "${CMAKE_FIND_LIBRARY_PREFIXES}")
|
||||
if(NOT __prefixes)
|
||||
set(__prefixes "_empty_")
|
||||
endif()
|
||||
foreach(find_prefix ${__prefixes})
|
||||
if(find_prefix STREQUAL "_empty_") # foreach doesn't iterate over empty elements
|
||||
set(find_prefix "")
|
||||
endif()
|
||||
if(NOT DEFINED INFERENCE_ENGINE_FIND_LIBRARY_SUFFIXES) # allow custom override
|
||||
set(INFERENCE_ENGINE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
if(APPLE)
|
||||
ocv_list_filterout(INFERENCE_ENGINE_FIND_LIBRARY_SUFFIXES "^.so$") # skip plugins (can't be linked)
|
||||
endif()
|
||||
endif()
|
||||
foreach(find_suffix ${INFERENCE_ENGINE_FIND_LIBRARY_SUFFIXES})
|
||||
ocv_ie_find_extra_libraries("${find_prefix}" "${find_suffix}")
|
||||
endforeach()
|
||||
if(NOT CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||
ocv_ie_find_extra_libraries("${find_prefix}" "")
|
||||
endif()
|
||||
endforeach()
|
||||
# ======================
|
||||
|
||||
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)
|
||||
message(WARNING "OpenMP for IE have not been found. Set INF_ENGINE_OMP_DIR variable if you experience build errors.")
|
||||
endif()
|
||||
if(WITH_OPENVINO)
|
||||
find_package(OpenVINO QUIET)
|
||||
if(OpenVINO_FOUND)
|
||||
message(STATUS "OpenVINO FOUND: ${OpenVINO_VERSION}")
|
||||
math(EXPR ver "${OpenVINO_VERSION_MAJOR} * 1000000 + ${OpenVINO_VERSION_MINOR} * 10000 + ${OpenVINO_VERSION_PATCH} * 100")
|
||||
ocv_add_external_target(openvino "" "openvino::runtime" "INF_ENGINE_RELEASE=${ver};HAVE_NGRAPH;HAVE_DNN_NGRAPH;HAVE_INF_ENGINE")
|
||||
set(HAVE_OPENVINO 1)
|
||||
return()
|
||||
endif()
|
||||
if(EXISTS "${INF_ENGINE_OMP_LIBRARY}")
|
||||
set_target_properties(inference_engine PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES "${INF_ENGINE_OMP_LIBRARY}")
|
||||
endif()
|
||||
set(INF_ENGINE_VERSION "Unknown" CACHE STRING "")
|
||||
set(INF_ENGINE_TARGET "inference_engine;${custom_libraries}" PARENT_SCOPE)
|
||||
message(STATUS "Detected InferenceEngine: ${_msg}")
|
||||
endfunction()
|
||||
endif()
|
||||
|
||||
# ======================
|
||||
|
||||
find_package(InferenceEngine QUIET)
|
||||
if(InferenceEngine_FOUND)
|
||||
set(INF_ENGINE_TARGET ${InferenceEngine_LIBRARIES})
|
||||
set(INF_ENGINE_VERSION "${InferenceEngine_VERSION}" CACHE STRING "")
|
||||
set(INF_ENGINE_VERSION "${InferenceEngine_VERSION}")
|
||||
message(STATUS "Detected InferenceEngine: cmake package (${InferenceEngine_VERSION})")
|
||||
endif()
|
||||
|
||||
@@ -113,47 +50,19 @@ elseif(DEFINED INF_ENGINE_RELEASE)
|
||||
endif()
|
||||
set(INF_ENGINE_RELEASE "${INF_ENGINE_RELEASE_INIT}" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2020.1.0.2 -> 2020010002)")
|
||||
|
||||
if(NOT INF_ENGINE_TARGET AND INF_ENGINE_LIB_DIRS AND INF_ENGINE_INCLUDE_DIRS)
|
||||
find_path(ie_custom_inc "inference_engine.hpp" PATHS "${INF_ENGINE_INCLUDE_DIRS}" NO_DEFAULT_PATH)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
find_library(ie_custom_lib_dbg "inference_engined" PATHS "${INF_ENGINE_LIB_DIRS}" NO_DEFAULT_PATH) # Win32 and MacOSX
|
||||
endif()
|
||||
find_library(ie_custom_lib "inference_engine" PATHS "${INF_ENGINE_LIB_DIRS}" NO_DEFAULT_PATH)
|
||||
find_library(ie_custom_lib_rel "inference_engine" PATHS "${INF_ENGINE_LIB_DIRS}/Release" NO_DEFAULT_PATH)
|
||||
find_library(ie_custom_lib_dbg "inference_engine" PATHS "${INF_ENGINE_LIB_DIRS}/Debug" NO_DEFAULT_PATH)
|
||||
add_custom_ie_build("${ie_custom_inc}" "${ie_custom_lib}" "${ie_custom_lib_rel}" "${ie_custom_lib_dbg}" "INF_ENGINE_{INCLUDE,LIB}_DIRS")
|
||||
endif()
|
||||
|
||||
set(_loc "$ENV{INTEL_OPENVINO_DIR}")
|
||||
if(NOT _loc AND DEFINED ENV{INTEL_CVSDK_DIR})
|
||||
set(_loc "$ENV{INTEL_CVSDK_DIR}") # OpenVINO 2018.x
|
||||
endif()
|
||||
if(NOT INF_ENGINE_TARGET AND _loc)
|
||||
if(NOT INF_ENGINE_RELEASE VERSION_GREATER "2018050000")
|
||||
set(INF_ENGINE_PLATFORM_DEFAULT "ubuntu_16.04")
|
||||
else()
|
||||
set(INF_ENGINE_PLATFORM_DEFAULT "")
|
||||
endif()
|
||||
set(INF_ENGINE_PLATFORM "${INF_ENGINE_PLATFORM_DEFAULT}" CACHE STRING "InferenceEngine platform (library dir)")
|
||||
find_path(ie_custom_env_inc "inference_engine.hpp" PATHS "${_loc}/deployment_tools/inference_engine/include" NO_DEFAULT_PATH)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
find_library(ie_custom_env_lib_dbg "inference_engined" PATHS "${_loc}/deployment_tools/inference_engine/lib/${INF_ENGINE_PLATFORM}/intel64" NO_DEFAULT_PATH)
|
||||
endif()
|
||||
find_library(ie_custom_env_lib "inference_engine" PATHS "${_loc}/deployment_tools/inference_engine/lib/${INF_ENGINE_PLATFORM}/intel64" NO_DEFAULT_PATH)
|
||||
find_library(ie_custom_env_lib_rel "inference_engine" PATHS "${_loc}/deployment_tools/inference_engine/lib/intel64/Release" NO_DEFAULT_PATH)
|
||||
find_library(ie_custom_env_lib_dbg "inference_engine" PATHS "${_loc}/deployment_tools/inference_engine/lib/intel64/Debug" NO_DEFAULT_PATH)
|
||||
add_custom_ie_build("${ie_custom_env_inc}" "${ie_custom_env_lib}" "${ie_custom_env_lib_rel}" "${ie_custom_env_lib_dbg}" "OpenVINO (${_loc})")
|
||||
endif()
|
||||
set(tgts)
|
||||
set(defs)
|
||||
|
||||
# Add more features to the target
|
||||
|
||||
if(INF_ENGINE_TARGET)
|
||||
set_target_properties(${INF_ENGINE_TARGET} PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
|
||||
)
|
||||
list(APPEND tgts ${INF_ENGINE_TARGET})
|
||||
list(APPEND defs "INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}" "HAVE_INF_ENGINE")
|
||||
endif()
|
||||
|
||||
if(WITH_NGRAPH)
|
||||
if(WITH_NGRAPH OR NOT DEFINED WITH_NGRAPH)
|
||||
find_package(ngraph QUIET)
|
||||
if(ngraph_FOUND)
|
||||
ocv_assert(TARGET ngraph::ngraph)
|
||||
@@ -162,5 +71,9 @@ if(WITH_NGRAPH)
|
||||
endif()
|
||||
message(STATUS "Detected ngraph: cmake package (${ngraph_VERSION})")
|
||||
set(HAVE_NGRAPH ON)
|
||||
list(APPEND tgts ngraph::ngraph)
|
||||
list(APPEND defs "HAVE_NGRAPH" "HAVE_DNN_NGRAPH")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ocv_add_external_target(openvino "" "${tgts}" "${defs}")
|
||||
|
||||
@@ -37,6 +37,50 @@ file(WRITE "${OPENCV_DOWNLOAD_LOG}" "#use_cache \"${OPENCV_DOWNLOAD_PATH}\"\n")
|
||||
file(REMOVE "${OPENCV_DOWNLOAD_WITH_CURL}")
|
||||
file(REMOVE "${OPENCV_DOWNLOAD_WITH_WGET}")
|
||||
|
||||
ocv_check_environment_variables(OPENCV_DOWNLOAD_MIRROR_ID)
|
||||
|
||||
function(ocv_init_download_mirror)
|
||||
if(NOT DEFINED OPENCV_DOWNLOAD_MIRROR_ID)
|
||||
# Run `git remote get-url origin` to get remote source
|
||||
execute_process(
|
||||
COMMAND
|
||||
git remote get-url origin
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_SOURCE_DIR}
|
||||
RESULT_VARIABLE
|
||||
RESULT_STATUS
|
||||
OUTPUT_VARIABLE
|
||||
OCV_GIT_ORIGIN_URL_OUTPUT
|
||||
ERROR_QUIET
|
||||
)
|
||||
# if non-git, OCV_GIT_ORIGIN_URL_OUTPUT is empty
|
||||
if(NOT OCV_GIT_ORIGIN_URL_OUTPUT)
|
||||
message(STATUS "ocv_init_download: OpenCV source tree is not fetched as git repository. 3rdparty resources will be downloaded from github.com by default.")
|
||||
return()
|
||||
else()
|
||||
# Check if git origin is github.com
|
||||
string(FIND "${OCV_GIT_ORIGIN_URL_OUTPUT}" "github.com" _found_github)
|
||||
if(NOT ${_found_github} EQUAL -1)
|
||||
set(OPENCV_DOWNLOAD_MIRROR_ID "github" CACHE STRING "")
|
||||
endif()
|
||||
# Check if git origin is gitcode.net
|
||||
string(FIND "${OCV_GIT_ORIGIN_URL_OUTPUT}" "gitcode.net" _found_gitcode)
|
||||
if(NOT ${_found_gitcode} EQUAL -1)
|
||||
set(OPENCV_DOWNLOAD_MIRROR_ID "gitcode" CACHE STRING "")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(OPENCV_DOWNLOAD_MIRROR_ID STREQUAL "gitcode" OR OPENCV_DOWNLOAD_MIRROR_ID STREQUAL "custom")
|
||||
message(STATUS "ocv_init_download: Using ${OPENCV_DOWNLOAD_MIRROR_ID}-hosted mirror to download 3rdparty components.")
|
||||
ocv_cmake_hook_append(OPENCV_DOWNLOAD_PRE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/mirrors/${OPENCV_DOWNLOAD_MIRROR_ID}.cmake")
|
||||
elseif(OPENCV_DOWNLOAD_MIRROR_ID STREQUAL "github")
|
||||
return()
|
||||
else()
|
||||
message(STATUS "ocv_init_download: Unable to recognize git server of OpenCV source code. Using github.com to download 3rdparty components.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ocv_download)
|
||||
cmake_parse_arguments(DL "UNPACK;RELATIVE_URL" "FILENAME;HASH;DESTINATION_DIR;ID;STATUS" "URL" ${ARGN})
|
||||
|
||||
@@ -67,6 +111,8 @@ function(ocv_download)
|
||||
set(${DL_STATUS} TRUE PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
ocv_cmake_hook(OPENCV_DOWNLOAD_PRE)
|
||||
|
||||
# Check CMake cache for already processed tasks
|
||||
string(FIND "${DL_DESTINATION_DIR}" "${CMAKE_BINARY_DIR}" DL_BINARY_PATH_POS)
|
||||
if(DL_BINARY_PATH_POS EQUAL 0)
|
||||
@@ -115,7 +161,7 @@ function(ocv_download)
|
||||
if(DL_ID)
|
||||
set(__msg_prefix "${DL_ID}: ")
|
||||
endif()
|
||||
message(STATUS "${__msg_prefix}Download: ${DL_FILENAME}")
|
||||
message(STATUS "${__msg_prefix}Downloading ${DL_FILENAME} from ${DL_URL}")
|
||||
|
||||
# Copy mode: check if copy destination exists and is correct
|
||||
if(NOT DL_UNPACK)
|
||||
@@ -252,3 +298,8 @@ ${OPENCV_DOWNLOAD_LOG}
|
||||
set(${OCV_DOWNLOAD_HASH_NAME} "${DL_HASH}" CACHE INTERNAL "")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Initialize download in case mirror is used
|
||||
# ----------------------------------------------------------------------------
|
||||
ocv_init_download_mirror()
|
||||
|
||||
@@ -17,8 +17,10 @@ else()
|
||||
unset(_zlib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||
endif()
|
||||
if(ZLIB_FOUND AND ANDROID)
|
||||
if(ZLIB_LIBRARIES MATCHES "/usr/lib.*/libz.so$")
|
||||
if(ZLIB_LIBRARY MATCHES "/usr/lib.*/libz.so$")
|
||||
set(ZLIB_LIBRARY z)
|
||||
set(ZLIB_LIBRARIES z)
|
||||
set(ZLIB_LIBRARY_RELEASE z)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
set(TIMVX_INSTALL_DIR "" CACHE PATH "Path to libtim-vx installation")
|
||||
set(VIVANTE_SDK_DIR "" CACHE PATH "Path to VIVANTE SDK needed by TIM-VX.")
|
||||
set(VIVANTE_SDK_LIB_CANDIDATES "OpenVX;VSC;GAL;ArchModelSw;NNArchPerf" CACHE STRING "VIVANTE SDK library candidates")
|
||||
|
||||
# Ensure VIVANTE SDK library candidates are present in given search path
|
||||
function(find_vivante_sdk_libs _viv_notfound _viv_search_path)
|
||||
foreach(one ${VIVANTE_SDK_LIB_CANDIDATES})
|
||||
#NO_DEFAULT_PATH is used to ensure VIVANTE SDK libs are from one only source
|
||||
find_library(VIV_${one}_LIB ${one} PATHS "${_viv_search_path}/lib" NO_DEFAULT_PATH)
|
||||
if(NOT VIV_${one}_LIB)
|
||||
list(APPEND _viv_notfound_list ${one})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${_viv_notfound} ${_viv_notfound_list} PARENT_SCOPE)
|
||||
endfunction()
|
||||
# Default value for VIVANTE_SDK_DIR: /usr
|
||||
if(NOT VIVANTE_SDK_DIR)
|
||||
set(VIVANTE_SDK_DIR "/usr")
|
||||
endif()
|
||||
# Environment variable VIVANTE_SDK_DIR overrides the one in this script
|
||||
if(DEFINED ENV{VIVANTE_SDK_DIR})
|
||||
set(VIVANTE_SDK_DIR $ENV{VIVANTE_SDK_DIR})
|
||||
message(STATUS "TIM-VX: Load VIVANTE_SDK_DIR from system environment: ${VIVANTE_SDK_DIR}")
|
||||
endif()
|
||||
|
||||
|
||||
# Compile with pre-installed TIM-VX; Or compile together with TIM-VX from source
|
||||
if(TIMVX_INSTALL_DIR AND NOT BUILD_TIMVX)
|
||||
message(STATUS "TIM-VX: Use binaries at ${TIMVX_INSTALL_DIR}")
|
||||
set(BUILD_TIMVX OFF)
|
||||
|
||||
set(TIMVX_INC_DIR "${TIMVX_INSTALL_DIR}/include" CACHE INTERNAL "TIM-VX include directory")
|
||||
find_library(TIMVX_LIB "tim-vx" PATHS "${TIMVX_INSTALL_DIR}/lib")
|
||||
if(TIMVX_LIB)
|
||||
set(TIMVX_FOUND ON)
|
||||
else()
|
||||
set(TIMVX_FOUND OFF)
|
||||
endif()
|
||||
|
||||
# Verify if requested VIVANTE SDK libraries are all found
|
||||
find_vivante_sdk_libs(missing ${VIVANTE_SDK_DIR})
|
||||
if(missing)
|
||||
message(STATUS "TIM-VX: Failed to find ${missing} in ${VIVANTE_SDK_DIR}/lib. Turning off TIMVX_VIV_FOUND")
|
||||
set(TIMVX_VIV_FOUND OFF)
|
||||
else()
|
||||
message(STATUS "TIM-VX: dependent VIVANTE SDK libraries are found at ${VIVANTE_SDK_DIR}/lib.")
|
||||
set(TIMVX_VIV_FOUND ON)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "TIM-VX: Build from source")
|
||||
include("${OpenCV_SOURCE_DIR}/3rdparty/libtim-vx/tim-vx.cmake")
|
||||
endif()
|
||||
|
||||
if(TIMVX_FOUND AND TIMVX_VIV_FOUND)
|
||||
set(HAVE_TIMVX 1)
|
||||
|
||||
message(STATUS "TIM-VX: Found TIM-VX includes: ${TIMVX_INC_DIR}")
|
||||
message(STATUS "TIM-VX: Found TIM-VX library: ${TIMVX_LIB}")
|
||||
set(TIMVX_LIBRARY ${TIMVX_LIB})
|
||||
set(TIMVX_INCLUDE_DIR ${TIMVX_INC_DIR})
|
||||
|
||||
message(STATUS "TIM-VX: Found VIVANTE SDK libraries: ${VIVANTE_SDK_DIR}/lib")
|
||||
link_directories(${VIVANTE_SDK_DIR}/lib)
|
||||
endif()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
TIMVX_INC_DIR
|
||||
TIMVX_LIB
|
||||
)
|
||||
@@ -78,10 +78,17 @@ function(ocv_create_plugin module default_name dependency_target dependency_targ
|
||||
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES PREFIX "${OPENCV_PLUGIN_MODULE_PREFIX}")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
||||
elseif(WIN32)
|
||||
# Hack for Windows only, Linux/MacOS uses global symbol table (without exact .so binding)
|
||||
if(WIN32 OR NOT APPLE)
|
||||
set(OPENCV_PLUGIN_NO_LINK FALSE CACHE BOOL "")
|
||||
else()
|
||||
set(OPENCV_PLUGIN_NO_LINK TRUE CACHE BOOL "")
|
||||
endif()
|
||||
|
||||
if(OPENCV_PLUGIN_NO_LINK)
|
||||
if(APPLE)
|
||||
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
||||
endif()
|
||||
else()
|
||||
find_package(OpenCV REQUIRED ${module} ${OPENCV_PLUGIN_DEPS})
|
||||
target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${OpenCV_LIBRARIES})
|
||||
endif()
|
||||
|
||||
@@ -1619,6 +1619,7 @@ function(ocv_add_external_target name inc link def)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# Returns the first non-interface target
|
||||
function(ocv_get_imported_target imported interface)
|
||||
set(__result "${interface}")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
# define _ARM64_DISTINCT_NEON_TYPES
|
||||
# include <Intrin.h>
|
||||
# include <arm_neon.h>
|
||||
# define CV_NEON 1
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
# Gitlab-style mirror
|
||||
# CMake scripts look for opencv/opencv_3rdparty,
|
||||
# OAID/Tengine, 01org/tbb(oneAPI/oneTBB), opencv/ade
|
||||
# from OPENCV_DOWNLOAD_MIRROR
|
||||
ocv_update(OPENCV_DOWNLOAD_MIRROR_URL "")
|
||||
|
||||
######
|
||||
# Download via commit id
|
||||
######
|
||||
# Tengine
|
||||
ocv_update(TENGINE_PKG_MD5_CUSTOM "")
|
||||
ocv_update(TENGINE_PKG_MD5_ORIGINAL 23f61ebb1dd419f1207d8876496289c5) # same as tengine_md5sum for TENGINE commit of e89cf8870de2ff0a80cfe626c0b52b2a16fb302e
|
||||
# NVIDIA_OPTICAL_FLOW
|
||||
ocv_update(NVIDIA_OPTICAL_FLOW_PKG_MD5_GITCODE "")
|
||||
ocv_update(NVIDIA_OPTICAL_FLOW_PKG_MD5_ORIGINAL a73cd48b18dcc0cc8933b30796074191)
|
||||
# TIM-VX
|
||||
ocv_update(TIM-VX_PKG_MD5_GITCODE "")
|
||||
ocv_update(TIM-VX_PKG_MD5_ORIGINAL 92619cc4498014ac7a09834d5e33ebd5)
|
||||
|
||||
######
|
||||
# Download from release page
|
||||
#####
|
||||
# TBB
|
||||
ocv_update(TBB_RELEASE_CUSTOM "")
|
||||
ocv_update(TBB_PKG_NAME_CUSTOM "")
|
||||
ocv_update(TBB_PKG_MD5_CUSTOM "")
|
||||
ocv_update(TBB_PKG_MD5_ORIGINAL 5af6f6c2a24c2043e62e47205e273b1f) # same as OPENCV_TBB_RELEASE_MD5 for TBB release of v2020.2
|
||||
# ADE
|
||||
ocv_update(ADE_RELEASE_CUSTOM "")
|
||||
ocv_update(ADE_PKG_NAME_CUSTOM "")
|
||||
ocv_update(ADE_PKG_MD5_CUSTOM "")
|
||||
ocv_update(ADE_PKG_MD5_ORIGINAL b624b995ec9c439cbc2e9e6ee940d3a2) # same as ade_md5 for ADE release of v0.1.1f
|
||||
|
||||
macro(ocv_download_url_custom_usercontent OWNER)
|
||||
string(REPLACE "/" ";" DL_URL_split ${DL_URL})
|
||||
list(GET DL_URL_split 5 __COMMIT_ID)
|
||||
list(GET DL_URL_split 6 __PKG_NAME)
|
||||
set(DL_URL "https://${OPENCV_DOWNLOAD_MIRROR_URL}/${OWNER}/opencv_3rdparty/-/raw/${__COMMIT_ID}/${__PKG_NAME}/")
|
||||
endmacro()
|
||||
macro(ocv_download_url_custom_archive_commit_id)
|
||||
if("m${${DL_ID}_PKG_MD5_CUSTOM}" STREQUAL "m")
|
||||
message(WARNING "ocv_download: specify ${DL_ID}_PKG_MD5_CUSTOM to download ${DL_ID} from custom source.")
|
||||
elseif(${DL_ID}_PKG_MD5_ORIGINAL STREQUAL "${DL_HASH}")
|
||||
string(REPLACE "/" ";" DL_URL_split ${DL_URL})
|
||||
list(GET DL_URL_split 3 __OWNER)
|
||||
list(GET DL_URL_split 4 __REPO_NAME)
|
||||
set(DL_URL "https://${OPENCV_DOWNLOAD_MIRROR_URL}/${__OWNER}/${__REPO_NAME}/-/archive/")
|
||||
set(DL_HASH "${${DL_ID}_PKG_MD5_CUSTOM}")
|
||||
else()
|
||||
message(WARNING "No information about mirrors for downloading ${DL_FILENAME} from URL='${DL_URL}' and MD5=${DL_HASH}.")
|
||||
endif()
|
||||
endmacro()
|
||||
macro(ocv_download_url_custom_archive_release)
|
||||
if("m${${DL_ID}_RELEASE_CUSTOM}" STREQUAL "m")
|
||||
message(WARNING "ocv_download: specify ${DL_ID}_RELEASE_CUSTOM to download ${DL_ID} from custom source.")
|
||||
return()
|
||||
endif()
|
||||
if("m${${DL_ID}_PKG_NAME_CUSTOM}" STREQUAL "m")
|
||||
message(WARNING "ocv_download: specify ${DL_ID}_PKG_NAME_CUSTOM to download ${DL_ID} from custom source.")
|
||||
return()
|
||||
endif()
|
||||
if("m${${DL_ID}_PKG_MD5_CUSTOM}" STREQUAL "m")
|
||||
message(WARNING "ocv_download: specify ${DL_ID}_PKG_MD5_CUSTOM to download ${DL_ID} from custom source.")
|
||||
return()
|
||||
endif()
|
||||
string(REPLACE "/" ";" DL_URL_split ${DL_URL})
|
||||
list(GET DL_URL_split 3 __OWNER)
|
||||
list(GET DL_URL_split 4 __REPO_NAME)
|
||||
set(DL_URL "https://${OPENCV_DOWNLOAD_MIRROR_URL}/${__OWNER}/${__REPO_NAME}/-/archive/${${DL_ID}_RELEASE_CUSTOM}/${__REPO_NAME}-")
|
||||
set(DL_HASH "${${DL_ID}_PKG_MD5_CUSTOM}")
|
||||
endmacro()
|
||||
|
||||
if("m${OPENCV_DOWNLOAD_MIRROR_URL}" STREQUAL "m")
|
||||
message(WARNING "ocv_download: specify OPENCV_DOWNLOAD_MIRROR_URL to use custom mirror.")
|
||||
else()
|
||||
if((DL_ID STREQUAL "FFMPEG") OR (DL_ID STREQUAL "IPPICV") OR (DL_ID STREQUAL "data") OR (DL_ID STREQUAL "xfeatures2d/boostdesc") OR (DL_ID STREQUAL "xfeatures2d/vgg"))
|
||||
ocv_download_url_custom_usercontent(opencv)
|
||||
elseif(DL_ID STREQUAL "wechat_qrcode")
|
||||
ocv_download_url_gitcode_usercontent(WeChatCV)
|
||||
elseif((DL_ID STREQUAL "TENGINE") OR (DL_ID STREQUAL "NVIDIA_OPTICAL_FLOW") OR (DL_ID STREQUAL "TIM-VX"))
|
||||
ocv_download_url_custom_archive_commit_id()
|
||||
elseif(DL_ID STREQUAL "TBB")
|
||||
ocv_download_url_custom_archive_release()
|
||||
set(OPENCV_TBB_SUBDIR "${TBB_PKG_NAME_CUSTOM}" PARENT_SCOPE)
|
||||
elseif(DL_ID STREQUAL "ADE")
|
||||
ocv_download_url_custom_archive_release()
|
||||
set(ade_subdir "${ADE_PKG_NAME_CUSTOM}" PARENT_SCOPE)
|
||||
else()
|
||||
message(STATUS "ocv_download: Unknown download ID ${DL_ID} for using mirror ${OPENCV_DOWNLOAD_MIRROR_URL}. Use original source instead.")
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,86 @@
|
||||
######
|
||||
# Download via commit id
|
||||
######
|
||||
# Tengine
|
||||
ocv_update(TENGINE_PKG_MD5_GITCODE 1b5908632b557275cd6e85b0c03f9690)
|
||||
ocv_update(TENGINE_PKG_MD5_ORIGINAL 23f61ebb1dd419f1207d8876496289c5) # same as tengine_md5sum for TENGINE commit of e89cf8870de2ff0a80cfe626c0b52b2a16fb302e
|
||||
# NVIDIA_OPTICAL_FLOW
|
||||
ocv_update(NVIDIA_OPTICAL_FLOW_PKG_MD5_GITCODE 8d5b7eeb24d6ca9c6bcfdff4196d5b47)
|
||||
ocv_update(NVIDIA_OPTICAL_FLOW_PKG_MD5_ORIGINAL a73cd48b18dcc0cc8933b30796074191)
|
||||
# TIM-VX
|
||||
ocv_update(TIM-VX_PKG_MD5_GITCODE 3f2a548b40b170668aaa60d4f60ba40b)
|
||||
ocv_update(TIM-VX_PKG_MD5_ORIGINAL 92619cc4498014ac7a09834d5e33ebd5)
|
||||
|
||||
######
|
||||
# Download from release page
|
||||
#####
|
||||
# TBB
|
||||
ocv_update(TBB_RELEASE_GITCODE "v2020.2")
|
||||
ocv_update(TBB_PKG_NAME_GITCODE "tbb-${TBB_RELEASE_GITCODE}")
|
||||
ocv_update(TBB_PKG_MD5_GITCODE 4eeafdf16a90cb66e39a31c8d6c6804e)
|
||||
ocv_update(TBB_PKG_MD5_ORIGINAL 5af6f6c2a24c2043e62e47205e273b1f) # same as OPENCV_TBB_RELEASE_MD5 for TBB release of v2020.2
|
||||
# ADE
|
||||
ocv_update(ADE_RELEASE_GITCODE "v0.1.1f")
|
||||
ocv_update(ADE_PKG_NAME_GITCODE "ade-${ADE_RELEASE_GITCODE}")
|
||||
ocv_update(ADE_PKG_MD5_GITCODE c12909e0ccfa93138c820ba91ff37b3c)
|
||||
ocv_update(ADE_PKG_MD5_ORIGINAL b624b995ec9c439cbc2e9e6ee940d3a2) # same as ade_md5 for ADE release of v0.1.1f
|
||||
|
||||
#
|
||||
# Replace download links for packages in opencv/opencv_3rdparty:
|
||||
# 1. Extract repo owner and repo name from DL_URL.
|
||||
# 2. Put repo owner and repo name into the placeholders of new DL_URL.
|
||||
#
|
||||
macro(ocv_download_url_gitcode_usercontent OWNER)
|
||||
string(REPLACE "/" ";" DL_URL_split ${DL_URL})
|
||||
list(GET DL_URL_split 5 __COMMIT_ID)
|
||||
list(GET DL_URL_split 6 __PKG_NAME)
|
||||
set(DL_URL "https://gitcode.net/${OWNER}/opencv_3rdparty/-/raw/${__COMMIT_ID}/")
|
||||
if(__PKG_NAME)
|
||||
set(DL_URL "${DL_URL}${__PKG_NAME}/")
|
||||
endif()
|
||||
endmacro()
|
||||
#
|
||||
# Replace download links and checksums for archives/releases in other repositories:
|
||||
# 1. Check if versions matched. If not matched, download from github instead.
|
||||
# 2. Extract repo owner and repo name from DL_URL.
|
||||
# 3. Put repo owner and repo name into the placeholders of new DL_URL.
|
||||
# 4. Replace DL_HASH with the one downloaded from gitcode.net.
|
||||
#
|
||||
macro(ocv_download_url_gitcode_archive_commit_id)
|
||||
if(DL_HASH STREQUAL "${${DL_ID}_PKG_MD5_ORIGINAL}")
|
||||
string(REPLACE "/" ";" DL_URL_split ${DL_URL})
|
||||
list(GET DL_URL_split 3 __OWNER)
|
||||
list(GET DL_URL_split 4 __REPO_NAME)
|
||||
set(DL_URL "https://gitcode.net/mirrors/${__OWNER}/${__REPO_NAME}/-/archive/")
|
||||
set(DL_HASH "${${DL_ID}_PKG_MD5_GITCODE}")
|
||||
else()
|
||||
message(WARNING "Package ${DL_ID} from mirror gitcode.net is outdated and will be downloaded from github.com instead.")
|
||||
endif()
|
||||
endmacro()
|
||||
macro(ocv_download_url_gitcode_archive_release)
|
||||
if(DL_HASH STREQUAL "${${DL_ID}_PKG_MD5_ORIGINAL}")
|
||||
string(REPLACE "/" ";" DL_URL_split ${DL_URL})
|
||||
list(GET DL_URL_split 3 __OWNER)
|
||||
list(GET DL_URL_split 4 __REPO_NAME)
|
||||
set(DL_URL "https://gitcode.net/${__OWNER}/${__REPO_NAME}/-/archive/${${DL_ID}_RELEASE_GITCODE}/${__REPO_NAME}-")
|
||||
set(DL_HASH "${${DL_ID}_PKG_MD5_GITCODE}")
|
||||
else()
|
||||
message(WARNING "Package ${DL_ID} from mirror gitcode.net is outdated and will be downloaded from github.com instead.")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
if((DL_ID STREQUAL "FFMPEG") OR (DL_ID STREQUAL "IPPICV") OR (DL_ID STREQUAL "data") OR (DL_ID STREQUAL "xfeatures2d/boostdesc") OR (DL_ID STREQUAL "xfeatures2d/vgg"))
|
||||
ocv_download_url_gitcode_usercontent(opencv)
|
||||
elseif(DL_ID STREQUAL "wechat_qrcode")
|
||||
ocv_download_url_gitcode_usercontent(mirrors/WeChatCV)
|
||||
elseif((DL_ID STREQUAL "TENGINE") OR (DL_ID STREQUAL "NVIDIA_OPTICAL_FLOW") OR (DL_ID STREQUAL "TIM-VX"))
|
||||
ocv_download_url_gitcode_archive_commit_id()
|
||||
elseif(DL_ID STREQUAL "TBB")
|
||||
ocv_download_url_gitcode_archive_release()
|
||||
set(OPENCV_TBB_SUBDIR "${TBB_PKG_NAME_GITCODE}" PARENT_SCOPE)
|
||||
elseif(DL_ID STREQUAL "ADE")
|
||||
ocv_download_url_gitcode_archive_release()
|
||||
set(ade_subdir "${ADE_PKG_NAME_GITCODE}" PARENT_SCOPE)
|
||||
else()
|
||||
message(STATUS "ocv_download: Unknown download ID ${DL_ID} for using mirror gitcode.net. Use original source instead.")
|
||||
endif()
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "image_classification",
|
||||
"version": "0.0.1",
|
||||
"description": "An Electon.js example of image_classification using webnn-native",
|
||||
"description": "An Electron.js example of image_classification using webnn-native",
|
||||
"main": "main.js",
|
||||
"author": "WebNN-native Authors",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -52,7 +52,7 @@ Try it
|
||||
|
||||
### 2. Dilation
|
||||
|
||||
It is just opposite of erosion. Here, a pixel element is '1' if atleast one pixel under the kernel
|
||||
It is just opposite of erosion. Here, a pixel element is '1' if at least one pixel under the kernel
|
||||
is '1'. So it increases the white region in the image or size of foreground object increases.
|
||||
Normally, in cases like noise removal, erosion is followed by dilation. Because, erosion removes
|
||||
white noises, but it also shrinks our object. So we dilate it. Since noise is gone, they won't come
|
||||
|
||||
@@ -223,7 +223,7 @@ Before the example, is worth consider first how files are handled in emscripten
|
||||
|
||||
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.
|
||||
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 explains how to 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 ###
|
||||
|
||||
|
||||
@@ -97,10 +97,10 @@ Building OpenCV.js from Source
|
||||
@endcode
|
||||
|
||||
@note
|
||||
The loader is implemented as a js file in the path `<opencv_js_dir>/bin/loader.js`. The loader utilizes the [WebAssembly Feature Detection](https://github.com/GoogleChromeLabs/wasm-feature-detect) to detect the features of the broswer and load corresponding OpenCV.js automatically. To use it, you need to use the UMD version of [WebAssembly Feature Detection](https://github.com/GoogleChromeLabs/wasm-feature-detect) and introduce the `loader.js` in your Web application.
|
||||
The loader is implemented as a js file in the path `<opencv_js_dir>/bin/loader.js`. The loader utilizes the [WebAssembly Feature Detection](https://github.com/GoogleChromeLabs/wasm-feature-detect) to detect the features of the browser and load corresponding OpenCV.js automatically. To use it, you need to use the UMD version of [WebAssembly Feature Detection](https://github.com/GoogleChromeLabs/wasm-feature-detect) and introduce the `loader.js` in your Web application.
|
||||
|
||||
Example Code:
|
||||
@code{.javascipt}
|
||||
@code{.javascript}
|
||||
// Set paths configuration
|
||||
let pathsConfig = {
|
||||
wasm: "../../build_wasm/opencv.js",
|
||||
@@ -173,7 +173,7 @@ This snippet and the following require [Node.js](https://nodejs.org) to be insta
|
||||
|
||||
### 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)
|
||||
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 Continuous integration like travis CI, etc)
|
||||
|
||||
@code{.sh}
|
||||
cd build_js/bin
|
||||
@@ -229,7 +229,7 @@ node tests.js
|
||||
The simd optimization is experimental as wasm simd is still in development.
|
||||
|
||||
@note
|
||||
Now only emscripten LLVM upstream backend supports wasm simd, refering to https://emscripten.org/docs/porting/simd.html. So you need to setup upstream backend environment with the following command first:
|
||||
Now only emscripten LLVM upstream backend supports wasm simd, referring to https://emscripten.org/docs/porting/simd.html. So you need to setup upstream backend environment with the following command first:
|
||||
@code{.bash}
|
||||
./emsdk update
|
||||
./emsdk install latest-upstream
|
||||
|
||||
@@ -122,11 +122,14 @@ imgElement.onload = function() {
|
||||
mat.delete();
|
||||
};
|
||||
|
||||
function onOpenCvReady() {
|
||||
document.getElementById('status').innerHTML = 'OpenCV.js is ready.';
|
||||
}
|
||||
var Module = {
|
||||
// https://emscripten.org/docs/api_reference/module.html#Module.onRuntimeInitialized
|
||||
onRuntimeInitialized() {
|
||||
document.getElementById('status').innerHTML = 'OpenCV.js is ready.';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script async src="opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
|
||||
<script async src="opencv.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
@endcode
|
||||
|
||||
@@ -1348,3 +1348,13 @@
|
||||
year={1991},
|
||||
publisher={IEEE Computer Society}
|
||||
}
|
||||
@article{Kannala2006,
|
||||
author = {Kannala, Juho and Brandt, Sami},
|
||||
year = {2006},
|
||||
month = {09},
|
||||
pages = {1335-40},
|
||||
title = {A Generic Camera Model and Calibration Method for Conventional, Wide-Angle, and Fish-Eye Lenses},
|
||||
volume = {28},
|
||||
journal = {IEEE transactions on pattern analysis and machine intelligence},
|
||||
doi = {10.1109/TPAMI.2006.153}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ is sufficient to find the object exactly on the trainImage.
|
||||
|
||||
For that, we can use a function from calib3d module, ie **cv.findHomography()**. If we pass the set
|
||||
of points from both the images, it will find the perspective transformation of that object. Then we
|
||||
can use **cv.perspectiveTransform()** to find the object. It needs atleast four correct points to
|
||||
can use **cv.perspectiveTransform()** to find the object. It needs at least four correct points to
|
||||
find the transformation.
|
||||
|
||||
We have seen that there can be some possible errors while matching which may affect the result. To
|
||||
@@ -64,7 +64,7 @@ for m,n in matches:
|
||||
if m.distance < 0.7*n.distance:
|
||||
good.append(m)
|
||||
@endcode
|
||||
Now we set a condition that atleast 10 matches (defined by MIN_MATCH_COUNT) are to be there to
|
||||
Now we set a condition that at least 10 matches (defined by MIN_MATCH_COUNT) are to be there to
|
||||
find the object. Otherwise simply show a message saying not enough matches are present.
|
||||
|
||||
If enough matches are found, we extract the locations of matched keypoints in both the images. They
|
||||
|
||||
@@ -48,7 +48,7 @@ Result:
|
||||
|
||||
### 2. Dilation
|
||||
|
||||
It is just opposite of erosion. Here, a pixel element is '1' if atleast one pixel under the kernel
|
||||
It is just opposite of erosion. Here, a pixel element is '1' if at least one pixel under the kernel
|
||||
is '1'. So it increases the white region in the image or size of foreground object increases.
|
||||
Normally, in cases like noise removal, erosion is followed by dilation. Because, erosion removes
|
||||
white noises, but it also shrinks our object. So we dilate it. Since noise is gone, they won't come
|
||||
|
||||
@@ -244,9 +244,9 @@ Samples:
|
||||
There are three new sample files in opencv/samples directory.
|
||||
|
||||
1. `epipolar_lines.cpp` – input arguments of `main` function are two
|
||||
pathes to images. Then correspondences are found using
|
||||
paths to images. Then correspondences are found using
|
||||
SIFT detector. Fundamental matrix is found using RANSAC from
|
||||
tentaive correspondences and epipolar lines are plot.
|
||||
tentative correspondences and epipolar lines are plot.
|
||||
|
||||
2. `essential_mat_reconstr.cpp` – input arguments are path to data file
|
||||
containing image names and single intrinsic matrix and directory
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ We then fill value to the corresponding pixel in the dst image.
|
||||
|
||||
### Parallel implementation
|
||||
|
||||
When looking at the sequential implementation, we can notice that each pixel depends on multiple neighbouring pixels but only one pixel is edited at a time. Thus, to optimize the computation, we can split the image into stripes and parallely perform convolution on each, by exploiting the multi-core architecture of modern processor. The OpenCV @ref cv::parallel_for_ framework automatically decides how to split the computation efficiently and does most of the work for us.
|
||||
When looking at the sequential implementation, we can notice that each pixel depends on multiple neighbouring pixels but only one pixel is edited at a time. Thus, to optimize the computation, we can split the image into stripes and parallelly perform convolution on each, by exploiting the multi-core architecture of modern processor. The OpenCV @ref cv::parallel_for_ framework automatically decides how to split the computation efficiently and does most of the work for us.
|
||||
|
||||
@note Although values of a pixel in a particular stripe may depend on pixel values outside the stripe, these are only read only operations and hence will not cause undefined behaviour.
|
||||
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
| | |
|
||||
| -: | :- |
|
||||
| Original Author | Chengrui Wang, Yuantao Feng |
|
||||
| Compatibility | OpenCV >= 4.5.1 |
|
||||
| Compatibility | OpenCV >= 4.5.4 |
|
||||
|
||||
## Introduction
|
||||
|
||||
In this section, we introduce the DNN-based module for face detection and face recognition. Models can be obtained in [Models](#Models). The usage of `FaceDetectorYN` and `FaceRecognizerSF` are presented in [Usage](#Usage).
|
||||
In this section, we introduce cv::FaceDetectorYN class for face detection and cv::FaceRecognizerSF class for face recognition.
|
||||
|
||||
## Models
|
||||
|
||||
There are two models (ONNX format) pre-trained and required for this module:
|
||||
- [Face Detection](https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx):
|
||||
- Size: 337KB
|
||||
- [Face Detection](https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet):
|
||||
- Size: 338KB
|
||||
- Results on WIDER Face Val set: 0.830(easy), 0.824(medium), 0.708(hard)
|
||||
- [Face Recognition](https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view?usp=sharing)
|
||||
- [Face Recognition](https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface)
|
||||
- Size: 36.9MB
|
||||
- Results:
|
||||
|
||||
@@ -32,9 +32,7 @@ There are two models (ONNX format) pre-trained and required for this module:
|
||||
| AgeDB-30 | 94.90% | 1.202 | 0.277 |
|
||||
| CFP-FP | 94.80% | 1.253 | 0.212 |
|
||||
|
||||
## Usage
|
||||
|
||||
### DNNFaceDetector
|
||||
## Code
|
||||
|
||||
@add_toggle_cpp
|
||||
- **Downloadable code**: Click
|
||||
|
||||
@@ -70,7 +70,7 @@ Sometimes networks built using blocked structure that means some layer are
|
||||
identical or quite similar. If you want to apply the same scheduling for
|
||||
different layers accurate to tiling or vectorization factors, define scheduling
|
||||
patterns in section `patterns` at the beginning of scheduling file.
|
||||
Also, your patters may use some parametric variables.
|
||||
Also, your patterns may use some parametric variables.
|
||||
@code
|
||||
# At the beginning of the file
|
||||
patterns:
|
||||
|
||||
@@ -29,8 +29,8 @@ Before recognition, you should `setVocabulary` and `setDecodeType`.
|
||||
- "CTC-prefix-beam-search", the output of the text recognition model should be a probability matrix same with "CTC-greedy".
|
||||
- The algorithm is proposed at Hannun's [paper](https://arxiv.org/abs/1408.2873).
|
||||
- `setDecodeOptsCTCPrefixBeamSearch` could be used to control the beam size in search step.
|
||||
- To futher optimize for big vocabulary, a new option `vocPruneSize` is introduced to avoid iterate the whole vocbulary
|
||||
but only the number of `vocPruneSize` tokens with top probabilty.
|
||||
- To further optimize for big vocabulary, a new option `vocPruneSize` is introduced to avoid iterate the whole vocbulary
|
||||
but only the number of `vocPruneSize` tokens with top probability.
|
||||
|
||||
@ref cv::dnn::TextRecognitionModel::recognize() is the main function for text recognition.
|
||||
- The input image should be a cropped text image or an image with `roiRects`
|
||||
|
||||
+2
-2
@@ -142,7 +142,7 @@ being a Graph API, doesn't force its users to do that.
|
||||
However, a graph is still built implicitly when a cv::GComputation
|
||||
object is defined. It may be useful to inspect how the resulting graph
|
||||
looks like to check if it is generated correctly and if it really
|
||||
represents our alrogithm. It is also useful to learn the structure of
|
||||
represents our algorithm. It is also useful to learn the structure of
|
||||
the graph to see if it has any redundancies.
|
||||
|
||||
G-API allows to dump generated graphs to `.dot` files which then
|
||||
@@ -295,7 +295,7 @@ and specify it to G-API:
|
||||
|
||||
In G-API, kernels (or operation implementations) are objects. Kernels are
|
||||
organized into collections, or _kernel packages_, represented by class
|
||||
cv::gapi::GKernelPackage. The main purpose of a kernel package is to
|
||||
cv::GKernelPackage. The main purpose of a kernel package is to
|
||||
capture which kernels we would like to use in our graph, and pass it
|
||||
as a _graph compilation option_:
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ pipeline is compiled for streaming:
|
||||
cv::GComputation::compileStreaming() triggers a special video-oriented
|
||||
form of graph compilation where G-API is trying to optimize
|
||||
throughput. Result of this compilation is an object of special type
|
||||
cv::GStreamingCompiled -- in constract to a traditional callable
|
||||
cv::GStreamingCompiled -- in contrast to a traditional callable
|
||||
cv::GCompiled, these objects are closer to media players in their
|
||||
semantics.
|
||||
|
||||
|
||||
@@ -81,11 +81,11 @@ The image we used can be found [here](https://raw.githubusercontent.com/opencv/o
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py load
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java load
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java load
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py load
|
||||
@end_toggle
|
||||
|
||||
#### Convert it to grayscale:
|
||||
@@ -95,11 +95,11 @@ The image we used can be found [here](https://raw.githubusercontent.com/opencv/o
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py convert_to_gray
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java convert_to_gray
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java convert_to_gray
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py convert_to_gray
|
||||
@end_toggle
|
||||
|
||||
#### Apply a Median blur to reduce noise and avoid false circle detection:
|
||||
@@ -109,11 +109,11 @@ The image we used can be found [here](https://raw.githubusercontent.com/opencv/o
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py reduce_noise
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java reduce_noise
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java reduce_noise
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py reduce_noise
|
||||
@end_toggle
|
||||
|
||||
#### Proceed to apply Hough Circle Transform:
|
||||
@@ -123,11 +123,11 @@ The image we used can be found [here](https://raw.githubusercontent.com/opencv/o
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py houghcircles
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java houghcircles
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java houghcircles
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py houghcircles
|
||||
@end_toggle
|
||||
|
||||
- with the arguments:
|
||||
@@ -151,11 +151,11 @@ The image we used can be found [here](https://raw.githubusercontent.com/opencv/o
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py draw
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java draw
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java draw
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py draw
|
||||
@end_toggle
|
||||
|
||||
You can see that we will draw the circle(s) on red and the center(s) with a small green dot
|
||||
@@ -167,11 +167,11 @@ You can see that we will draw the circle(s) on red and the center(s) with a smal
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py display
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java display
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java display
|
||||
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py display
|
||||
@end_toggle
|
||||
|
||||
Result
|
||||
|
||||
@@ -130,7 +130,7 @@ Get image from [here](https://raw.githubusercontent.com/opencv/opencv/4.x/doc/tu
|
||||
|
||||
#### Output images
|
||||
|
||||
Now we are ready to apply morphological operations in order to extract the horizontal and vertical lines and as a consequence to separate the the music notes from the music sheet, but first let's initialize the output images that we will use for that reason:
|
||||
Now we are ready to apply morphological operations in order to extract the horizontal and vertical lines and as a consequence to separate the music notes from the music sheet, but first let's initialize the output images that we will use for that reason:
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp init
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ The main function is rather simple, as follows from the comments we do the follo
|
||||
In general callback functions are used to react to some kind of signal, in our
|
||||
case it's trackbar's state change.
|
||||
Explicit one-time call of `thresh_callback` is necessary to display
|
||||
the "Contours" window simultaniously with the "Source" window.
|
||||
the "Contours" window simultaneously with the "Source" window.
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp trackbar
|
||||
|
||||
@@ -240,7 +240,7 @@ taken:
|
||||
Hello OpenCV Sample
|
||||
-------------------
|
||||
|
||||
Here are basic steps to guide you trough the process of creating a simple OpenCV-centric
|
||||
Here are basic steps to guide you through the process of creating a simple OpenCV-centric
|
||||
application. It will be capable of accessing camera output, processing it and displaying the result.
|
||||
|
||||
-# Open Eclipse IDE, create a new clean workspace, create a new Android project
|
||||
|
||||
@@ -476,9 +476,10 @@ OpenCV have own DNN inference module which have own build-in engine, but can als
|
||||
| `BUILD_PROTOBUF` | _ON_ | Build own copy of _protobuf_. Must be disabled if you want to use external library. |
|
||||
| `PROTOBUF_UPDATE_FILES` | _OFF_ | Re-generate all .proto files. _protoc_ compiler compatible with used version of _protobuf_ must be installed. |
|
||||
| `OPENCV_DNN_OPENCL` | _ON_ | Enable built-in OpenCL inference backend. |
|
||||
| `WITH_INF_ENGINE` | _OFF_ | Enables [Intel Inference Engine (IE)](https://github.com/openvinotoolkit/openvino) backend. Allows to execute networks in IE format (.xml + .bin). Inference Engine must be installed either as part of [OpenVINO toolkit](https://en.wikipedia.org/wiki/OpenVINO), either as a standalone library built from sources. |
|
||||
| `INF_ENGINE_RELEASE` | _2020040000_ | Defines version of Inference Engine library which is tied to OpenVINO toolkit version. Must be a 10-digit string, e.g. _2020040000_ for OpenVINO 2020.4. |
|
||||
| `WITH_NGRAPH` | _OFF_ | Enables Intel NGraph library support. This library is part of Inference Engine backend which allows executing arbitrary networks read from files in multiple formats supported by OpenCV: Caffe, TensorFlow, PyTorch, Darknet, etc.. NGraph library must be installed, it is included into Inference Engine. |
|
||||
| `WITH_INF_ENGINE` | _OFF_ | **Deprecated since OpenVINO 2022.1** Enables [Intel Inference Engine (IE)](https://github.com/openvinotoolkit/openvino) backend. Allows to execute networks in IE format (.xml + .bin). Inference Engine must be installed either as part of [OpenVINO toolkit](https://en.wikipedia.org/wiki/OpenVINO), either as a standalone library built from sources. |
|
||||
| `INF_ENGINE_RELEASE` | _2020040000_ | **Deprecated since OpenVINO 2022.1** Defines version of Inference Engine library which is tied to OpenVINO toolkit version. Must be a 10-digit string, e.g. _2020040000_ for OpenVINO 2020.4. |
|
||||
| `WITH_NGRAPH` | _OFF_ | **Deprecated since OpenVINO 2022.1** Enables Intel NGraph library support. This library is part of Inference Engine backend which allows executing arbitrary networks read from files in multiple formats supported by OpenCV: Caffe, TensorFlow, PyTorch, Darknet, etc.. NGraph library must be installed, it is included into Inference Engine. |
|
||||
| `WITH_OPENVINO` | _OFF_ | Enable Intel OpenVINO Toolkit support. Should be used for OpenVINO>=2022.1 instead of `WITH_INF_ENGINE` and `WITH_NGRAPH`. |
|
||||
| `OPENCV_DNN_CUDA` | _OFF_ | Enable CUDA backend. [CUDA](https://en.wikipedia.org/wiki/CUDA), CUBLAS and [CUDNN](https://developer.nvidia.com/cudnn) must be installed. |
|
||||
| `WITH_HALIDE` | _OFF_ | Use experimental [Halide](https://en.wikipedia.org/wiki/Halide_(programming_language)) backend which can generate optimized code for dnn-layers at runtime. Halide must be installed. |
|
||||
| `WITH_VULKAN` | _OFF_ | Enable experimental [Vulkan](https://en.wikipedia.org/wiki/Vulkan_(API)) backend. Does not require additional dependencies, but can use external Vulkan headers (`VULKAN_INCLUDE_DIRS`). |
|
||||
|
||||
@@ -46,14 +46,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/4.5.5
|
||||
TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.6.0
|
||||
@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/4.5.5
|
||||
./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.6.0
|
||||
@endcode
|
||||
|
||||
Doxygen can now use the information from the tag file to link to the OpenCV
|
||||
|
||||
+3
-3
@@ -20,7 +20,7 @@ This pretty-printer can show element type, `is_continuous`, `is_submatrix` flags
|
||||
|
||||
# Installation {#tutorial_linux_gdb_pretty_printer_installation}
|
||||
|
||||
Move into `opencv/samples/gdb/`. Place `mat_pretty_printer.py` in a convinient place, rename `gdbinit` to `.gdbinit` and move it into your home folder. Change 'source' line of `.gdbinit` to point to your `mat_pretty_printer.py` path.
|
||||
Move into `opencv/samples/gdb/`. Place `mat_pretty_printer.py` in a convenient place, rename `gdbinit` to `.gdbinit` and move it into your home folder. Change 'source' line of `.gdbinit` to point to your `mat_pretty_printer.py` path.
|
||||
|
||||
In order to check version of python bundled with your gdb, use the following commands from the gdb shell:
|
||||
|
||||
@@ -34,5 +34,5 @@ If the version of python 3 installed in your system doesn't match the version in
|
||||
|
||||
# Usage {#tutorial_linux_gdb_pretty_printer_usage}
|
||||
|
||||
The fields in a debugger prefixed with `view_` are pseudo-fields added for convinience, the rest are left as is.
|
||||
If you feel that the number of elements in truncated view is too low, you can edit `mat_pretty_printer.py` - `np.set_printoptions` controlls everything matrix display-related.
|
||||
The fields in a debugger prefixed with `view_` are pseudo-fields added for convenience, the rest are left as is.
|
||||
If you feel that the number of elements in truncated view is too low, you can edit `mat_pretty_printer.py` - `np.set_printoptions` controls everything matrix display-related.
|
||||
|
||||
@@ -22,7 +22,7 @@ Introduction
|
||||
In *OpenCV* all the image processing operations are usually carried out on the *Mat* structure. In
|
||||
iOS however, to render an image on screen it have to be an instance of the *UIImage* class. To
|
||||
convert an *OpenCV Mat* to an *UIImage* we use the *Core Graphics* framework available in iOS. Below
|
||||
is the code needed to covert back and forth between Mat's and UIImage's.
|
||||
is the code needed to convert back and forth between Mat's and UIImage's.
|
||||
@code{.m}
|
||||
- (cv::Mat)cvMatFromUIImage:(UIImage *)image
|
||||
{
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#define OPENCV_CALIB3D_HPP
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/core/types.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
#include "opencv2/core/affine.hpp"
|
||||
|
||||
@@ -429,6 +430,9 @@ R & t \\
|
||||
\f[u = f_x (x' + \alpha y') + c_x \\
|
||||
v = f_y y' + c_y\f]
|
||||
|
||||
Summary:
|
||||
Generic camera model @cite Kannala2006 with perspective projection and without distortion correction
|
||||
|
||||
@defgroup calib3d_c C API
|
||||
|
||||
@}
|
||||
@@ -3721,6 +3725,21 @@ void undistortPoints(InputArray src, OutputArray dst,
|
||||
InputArray cameraMatrix, InputArray distCoeffs,
|
||||
InputArray R, InputArray P, TermCriteria criteria);
|
||||
|
||||
/**
|
||||
* @brief Compute undistorted image points position
|
||||
*
|
||||
* @param src Observed points position, 2xN/Nx2 1-channel or 1xN/Nx1 2-channel (CV_32FC2 or
|
||||
CV_64FC2) (or vector\<Point2f\> ).
|
||||
* @param dst Output undistorted points position (1xN/Nx1 2-channel or vector\<Point2f\> ).
|
||||
* @param cameraMatrix Camera matrix \f$\vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ .
|
||||
* @param distCoeffs Distortion coefficients
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void undistortImagePoints(InputArray src, OutputArray dst, InputArray cameraMatrix,
|
||||
InputArray distCoeffs,
|
||||
TermCriteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5,
|
||||
0.01));
|
||||
|
||||
//! @} calib3d
|
||||
|
||||
/** @brief The methods in this namespace use a so-called fisheye camera model.
|
||||
@@ -3783,8 +3802,7 @@ namespace fisheye
|
||||
@param distorted Output array of image points, 1xN/Nx1 2-channel, or vector\<Point2f\> .
|
||||
|
||||
Note that the function assumes the camera intrinsic matrix of the undistorted points to be identity.
|
||||
This means if you want to transform back points undistorted with #fisheye::undistortPoints you have to
|
||||
multiply them with \f$P^{-1}\f$.
|
||||
This means if you want to distort image points you have to multiply them with \f$K^{-1}\f$.
|
||||
*/
|
||||
CV_EXPORTS_W void distortPoints(InputArray undistorted, OutputArray distorted, InputArray K, InputArray D, double alpha = 0);
|
||||
|
||||
@@ -3797,10 +3815,12 @@ namespace fisheye
|
||||
@param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3
|
||||
1-channel or 1x1 3-channel
|
||||
@param P New camera intrinsic matrix (3x3) or new projection matrix (3x4)
|
||||
@param criteria Termination criteria
|
||||
@param undistorted Output array of image points, 1xN/Nx1 2-channel, or vector\<Point2f\> .
|
||||
*/
|
||||
CV_EXPORTS_W void undistortPoints(InputArray distorted, OutputArray undistorted,
|
||||
InputArray K, InputArray D, InputArray R = noArray(), InputArray P = noArray());
|
||||
InputArray K, InputArray D, InputArray R = noArray(), InputArray P = noArray(),
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 1e-8));
|
||||
|
||||
/** @brief Computes undistortion and rectification maps for image transform by #remap. If D is empty zero
|
||||
distortion is used, if R or P is empty identity matrixes are used.
|
||||
@@ -3866,7 +3886,7 @@ namespace fisheye
|
||||
CV_EXPORTS_W void estimateNewCameraMatrixForUndistortRectify(InputArray K, InputArray D, const Size &image_size, InputArray R,
|
||||
OutputArray P, double balance = 0.0, const Size& new_size = Size(), double fov_scale = 1.0);
|
||||
|
||||
/** @brief Performs camera calibaration
|
||||
/** @brief Performs camera calibration
|
||||
|
||||
@param objectPoints vector of vectors of calibration pattern points in the calibration pattern
|
||||
coordinate space.
|
||||
|
||||
@@ -27,4 +27,36 @@ PERF_TEST(Undistort, DISABLED_InitInverseRectificationMap)
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(Undistort, fisheye_undistortPoints_100k_10iter)
|
||||
{
|
||||
const int pointsNumber = 100000;
|
||||
const Size imageSize(1280, 800);
|
||||
|
||||
/* Set camera matrix */
|
||||
const Matx33d K(558.478087865323, 0, 620.458515360843,
|
||||
0, 560.506767351568, 381.939424848348,
|
||||
0, 0, 1);
|
||||
|
||||
/* Set distortion coefficients */
|
||||
const Matx14d D(2.81e-06, 1.31e-06, -4.42e-06, -1.25e-06);
|
||||
|
||||
/* Create two-channel points matrix */
|
||||
Mat xy[2] = {};
|
||||
xy[0].create(pointsNumber, 1, CV_64F);
|
||||
theRNG().fill(xy[0], RNG::UNIFORM, 0, imageSize.width); // x
|
||||
xy[1].create(pointsNumber, 1, CV_64F);
|
||||
theRNG().fill(xy[1], RNG::UNIFORM, 0, imageSize.height); // y
|
||||
|
||||
Mat points;
|
||||
merge(xy, 2, points);
|
||||
|
||||
/* Set fixed iteration number to check only c++ code, not algo convergence */
|
||||
TermCriteria termCriteria(TermCriteria::MAX_ITER, 10, 0);
|
||||
|
||||
Mat undistortedPoints;
|
||||
TEST_CYCLE() fisheye::undistortPoints(points, undistortedPoints, K, D, noArray(), noArray(), termCriteria);
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user