├── .dockerignore ├── .gitignore ├── CMakeLists.txt ├── Dockerfile ├── LICENSE.md ├── example.py ├── input.jpg ├── pybind11 └── CMakeLists.txt ├── readme.md ├── requirements.txt ├── result.jpg ├── swt_python3.cpp └── test_input.jpg /.dockerignore: -------------------------------------------------------------------------------- 1 | lib 2 | cmake-build-debug 3 | cmake-build-release 4 | Dockerfile 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/clion,python,pycharm 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=clion,python,pycharm 4 | 5 | ### CLion ### 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 8 | 9 | # User-specific stuff 10 | .idea/**/workspace.xml 11 | .idea/**/tasks.xml 12 | .idea/**/usage.statistics.xml 13 | .idea/**/dictionaries 14 | .idea/**/shelf 15 | 16 | # Generated files 17 | .idea/**/contentModel.xml 18 | 19 | # Sensitive or high-churn files 20 | .idea/**/dataSources/ 21 | .idea/**/dataSources.ids 22 | .idea/**/dataSources.local.xml 23 | .idea/**/sqlDataSources.xml 24 | .idea/**/dynamic.xml 25 | .idea/**/uiDesigner.xml 26 | .idea/**/dbnavigator.xml 27 | 28 | # Gradle 29 | .idea/**/gradle.xml 30 | .idea/**/libraries 31 | 32 | # Gradle and Maven with auto-import 33 | # When using Gradle or Maven with auto-import, you should exclude module files, 34 | # since they will be recreated, and may cause churn. Uncomment if using 35 | # auto-import. 36 | # .idea/artifacts 37 | # .idea/compiler.xml 38 | # .idea/jarRepositories.xml 39 | # .idea/modules.xml 40 | # .idea/*.iml 41 | # .idea/modules 42 | # *.iml 43 | # *.ipr 44 | 45 | # CMake 46 | cmake-build-*/ 47 | 48 | # Mongo Explorer plugin 49 | .idea/**/mongoSettings.xml 50 | 51 | # File-based project format 52 | *.iws 53 | 54 | # IntelliJ 55 | out/ 56 | 57 | # mpeltonen/sbt-idea plugin 58 | .idea_modules/ 59 | 60 | # JIRA plugin 61 | atlassian-ide-plugin.xml 62 | 63 | # Cursive Clojure plugin 64 | .idea/replstate.xml 65 | 66 | # Crashlytics plugin (for Android Studio and IntelliJ) 67 | com_crashlytics_export_strings.xml 68 | crashlytics.properties 69 | crashlytics-build.properties 70 | fabric.properties 71 | 72 | # Editor-based Rest Client 73 | .idea/httpRequests 74 | 75 | # Android studio 3.1+ serialized cache file 76 | .idea/caches/build_file_checksums.ser 77 | 78 | ### CLion Patch ### 79 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 80 | 81 | # *.iml 82 | # modules.xml 83 | # .idea/misc.xml 84 | # *.ipr 85 | 86 | # Sonarlint plugin 87 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 88 | .idea/**/sonarlint/ 89 | 90 | # SonarQube Plugin 91 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 92 | .idea/**/sonarIssues.xml 93 | 94 | # Markdown Navigator plugin 95 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 96 | .idea/**/markdown-navigator.xml 97 | .idea/**/markdown-navigator-enh.xml 98 | .idea/**/markdown-navigator/ 99 | 100 | # Cache file creation bug 101 | # See https://youtrack.jetbrains.com/issue/JBR-2257 102 | .idea/$CACHE_FILE$ 103 | 104 | # CodeStream plugin 105 | # https://plugins.jetbrains.com/plugin/12206-codestream 106 | .idea/codestream.xml 107 | 108 | ### PyCharm ### 109 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 110 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 111 | 112 | # User-specific stuff 113 | 114 | # Generated files 115 | 116 | # Sensitive or high-churn files 117 | 118 | # Gradle 119 | 120 | # Gradle and Maven with auto-import 121 | # When using Gradle or Maven with auto-import, you should exclude module files, 122 | # since they will be recreated, and may cause churn. Uncomment if using 123 | # auto-import. 124 | # .idea/artifacts 125 | # .idea/compiler.xml 126 | # .idea/jarRepositories.xml 127 | # .idea/modules.xml 128 | # .idea/*.iml 129 | # .idea/modules 130 | # *.iml 131 | # *.ipr 132 | 133 | # CMake 134 | 135 | # Mongo Explorer plugin 136 | 137 | # File-based project format 138 | 139 | # IntelliJ 140 | 141 | # mpeltonen/sbt-idea plugin 142 | 143 | # JIRA plugin 144 | 145 | # Cursive Clojure plugin 146 | 147 | # Crashlytics plugin (for Android Studio and IntelliJ) 148 | 149 | # Editor-based Rest Client 150 | 151 | # Android studio 3.1+ serialized cache file 152 | 153 | ### PyCharm Patch ### 154 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 155 | 156 | # *.iml 157 | # modules.xml 158 | # .idea/misc.xml 159 | # *.ipr 160 | 161 | # Sonarlint plugin 162 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 163 | 164 | # SonarQube Plugin 165 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 166 | 167 | # Markdown Navigator plugin 168 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 169 | 170 | # Cache file creation bug 171 | # See https://youtrack.jetbrains.com/issue/JBR-2257 172 | 173 | # CodeStream plugin 174 | # https://plugins.jetbrains.com/plugin/12206-codestream 175 | 176 | ### Python ### 177 | # Byte-compiled / optimized / DLL files 178 | __pycache__/ 179 | *.py[cod] 180 | *$py.class 181 | 182 | # C extensions 183 | *.so 184 | 185 | # Distribution / packaging 186 | .Python 187 | build/ 188 | develop-eggs/ 189 | dist/ 190 | downloads/ 191 | eggs/ 192 | .eggs/ 193 | lib/ 194 | lib64/ 195 | parts/ 196 | sdist/ 197 | var/ 198 | wheels/ 199 | pip-wheel-metadata/ 200 | share/python-wheels/ 201 | *.egg-info/ 202 | .installed.cfg 203 | *.egg 204 | MANIFEST 205 | 206 | # PyInstaller 207 | # Usually these files are written by a python script from a template 208 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 209 | *.manifest 210 | *.spec 211 | 212 | # Installer logs 213 | pip-log.txt 214 | pip-delete-this-directory.txt 215 | 216 | # Unit test / coverage reports 217 | htmlcov/ 218 | .tox/ 219 | .nox/ 220 | .coverage 221 | .coverage.* 222 | .cache 223 | nosetests.xml 224 | coverage.xml 225 | *.cover 226 | *.py,cover 227 | .hypothesis/ 228 | .pytest_cache/ 229 | pytestdebug.log 230 | 231 | # Translations 232 | *.mo 233 | *.pot 234 | 235 | # Django stuff: 236 | *.log 237 | local_settings.py 238 | db.sqlite3 239 | db.sqlite3-journal 240 | 241 | # Flask stuff: 242 | instance/ 243 | .webassets-cache 244 | 245 | # Scrapy stuff: 246 | .scrapy 247 | 248 | # Sphinx documentation 249 | docs/_build/ 250 | doc/_build/ 251 | 252 | # PyBuilder 253 | target/ 254 | 255 | # Jupyter Notebook 256 | .ipynb_checkpoints 257 | 258 | # IPython 259 | profile_default/ 260 | ipython_config.py 261 | 262 | # pyenv 263 | .python-version 264 | 265 | # pipenv 266 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 267 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 268 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 269 | # install all needed dependencies. 270 | #Pipfile.lock 271 | 272 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 273 | __pypackages__/ 274 | 275 | # Celery stuff 276 | celerybeat-schedule 277 | celerybeat.pid 278 | 279 | # SageMath parsed files 280 | *.sage.py 281 | 282 | # Environments 283 | .env 284 | .venv 285 | env/ 286 | venv/ 287 | ENV/ 288 | env.bak/ 289 | venv.bak/ 290 | pythonenv* 291 | 292 | # Spyder project settings 293 | .spyderproject 294 | .spyproject 295 | 296 | # Rope project settings 297 | .ropeproject 298 | 299 | # mkdocs documentation 300 | /site 301 | 302 | # mypy 303 | .mypy_cache/ 304 | .dmypy.json 305 | dmypy.json 306 | 307 | # Pyre type checker 308 | .pyre/ 309 | 310 | # pytype static type analyzer 311 | .pytype/ 312 | 313 | # profiling data 314 | .prof 315 | .idea 316 | # End of https://www.toptal.com/developers/gitignore/api/clion,python,pycharm -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.17) 2 | project(swt_python3) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_CXX_FLAGS "-O3") 6 | set(CMAKE_CXX_FLAGS_DEBUG "-g -O3") 7 | 8 | find_library(CCV ccv lib) 9 | find_package(JPEG REQUIRED) 10 | find_package(PNG REQUIRED) 11 | #find_package(PythonLibs) 12 | include_directories(${PYTHON_INCLUDE_DIRS}) 13 | 14 | add_subdirectory(pybind11) 15 | pybind11_add_module(swt_python3) 16 | target_sources(swt_python3 PRIVATE swt_python3.cpp) 17 | target_link_libraries(swt_python3 PRIVATE ${CCV} ${JPEG_LIBRARIES} ${PNG_LIBRARIES}) 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9.1-buster as base 2 | RUN apt-get update && apt-get install -y libjpeg-dev libpng-dev libatlas-base-dev libblas-dev && \ 3 | rm -rf /var/lib/apt/lists/* 4 | 5 | FROM base AS build 6 | # INSTALL CMAKE 7 | WORKDIR /cmake 8 | RUN wget https://github.com/Kitware/CMake/releases/download/v3.19.2/cmake-3.19.2-Linux-x86_64.sh && \ 9 | mkdir -p /opt/cmake && \ 10 | bash cmake-3.19.2-Linux-x86_64.sh --prefix=/opt/cmake --skip-license && \ 11 | ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake 12 | 13 | # BUILD CCV library 14 | RUN mkdir /ccv && \ 15 | git clone --single-branch --branch stable --depth 1 https://github.com/marrrcin/ccv.git /ccv && \ 16 | cd /ccv/lib && ./configure && \ 17 | # sed -i 's/O3/O0/g' makefile && \ # UNCOMENT THIS FOR FASTER DEBUG-PURPOSE BUILDS 18 | make libccv.a 19 | 20 | # BUILD WRAPPER 21 | RUN mkdir -p /swt-python/lib 22 | COPY . /swt-python 23 | RUN cp /ccv/lib/ccv.h /swt-python/lib/ccv.h && cp /ccv/lib/libccv.a /swt-python/lib/libccv.a 24 | WORKDIR /swt-python 25 | RUN cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_INCLUDE_DIRS=/usr/local/include/python3.9 . && make 26 | 27 | FROM base as runtime 28 | RUN mkdir /swt-python 29 | WORKDIR /swt-python 30 | COPY --from=build /swt-python/*.so /swt-python 31 | COPY example.py /swt-python 32 | COPY requirements.txt /swt-python 33 | RUN pip install --no-cache-dir -r requirements.txt 34 | COPY input.jpg /swt-python 35 | ENTRYPOINT ["python", "example.py"] 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2021 [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from swt_python3 import swt 4 | 5 | from skimage import draw 6 | from skimage.io import imread, imshow, imsave 7 | 8 | 9 | def rectangle_perimeter(r0, c0, width, height, shape=None, clip=False): 10 | rr, cc = [r0, r0 + width, r0 + width, r0], [c0, c0, c0 + height, c0 + height] 11 | 12 | return draw.polygon_perimeter(rr, cc, shape=shape, clip=clip) 13 | 14 | 15 | if __name__ == "__main__": 16 | image_name = "input.jpg" 17 | buffer = open(image_name, "rb").read() 18 | import time 19 | 20 | start = time.time() 21 | swt_result: List[dict] = swt(buffer, len(buffer)) 22 | end = time.time() 23 | image = imread(image_name) 24 | for item in swt_result: 25 | x, y, width, height = [item[key] for key in ("x", "y", "width", "height")] 26 | print(x, y, width, height) 27 | for i in range(0, 3): # just to make lines thicker 28 | rr, cc = rectangle_perimeter( 29 | y + i, x + i, height, width, shape=image.shape, clip=True 30 | ) 31 | image[rr, cc] = (255, 0, 0) 32 | 33 | imsave("result.jpg", image) 34 | # from matplotlib import pyplot as plt 35 | # imshow(image) 36 | # plt.show() 37 | print(f"SWT time: {end-start:0.4f}s") 38 | -------------------------------------------------------------------------------- /input.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marrrcin/swt-python/86a7553d1861f4dd7114c01b6ae512090d7ee14f/input.jpg -------------------------------------------------------------------------------- /pybind11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | 3 | FetchContent_Declare( 4 | pybind11 5 | URL "https://github.com/pybind/pybind11/archive/v2.6.1.tar.gz" 6 | ) 7 | 8 | FetchContent_MakeAvailable(pybind11) 9 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Fast Stroke Width Transform for Python 2 | This repo contains wrapper for libccv's SWT algorithm for use in Python 3. 3 | It's compatible with Linux, macOS and Docker. 4 | 5 | For more information, see my blog post: http://zablo.net/blog/post/stroke-width-transform-swt-python-3.9 6 | 7 | ## Usage 8 | 9 | ```python 10 | from swt_python3 import swt 11 | 12 | buffer = open("input.jpg", "rb").read() 13 | swt_result: List[dict] = swt(buffer, len(buffer)) 14 | for item in swt_result: 15 | x, y, width, height = [item[key] for key in ("x", "y", "width", "height")] 16 | print(x, y, width, height) 17 | ``` 18 | 19 | See `example.py` for details. 20 | 21 | ## Docker image 22 | ```bash 23 | docker pull marrrcin/swt-python3-ccv:20210111 24 | docker run --rm -it --entrypoint bash marrrcin/swt-python3-ccv:20210111 25 | ``` -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | scikit-image==0.18.1 2 | -------------------------------------------------------------------------------- /result.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marrrcin/swt-python/86a7553d1861f4dd7114c01b6ae512090d7ee14f/result.jpg -------------------------------------------------------------------------------- /swt_python3.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | #include "lib/ccv.h" 3 | } 4 | 5 | #include 6 | 7 | namespace py = pybind11; 8 | 9 | 10 | py::list swt(char *bytes, int array_length){ 11 | py::list result; 12 | ccv_enable_default_cache(); 13 | ccv_dense_matrix_t* image = 0; 14 | ccv_enable_default_cache(); 15 | ccv_read((void*)bytes, &image, CCV_IO_GRAY | CCV_IO_ANY_STREAM, array_length); 16 | if(image != 0) { 17 | ccv_array_t *words = ccv_swt_detect_words(image, ccv_swt_default_params); 18 | if (words) { 19 | int i; 20 | for (i = 0; i < words->rnum; i++) { 21 | ccv_rect_t *rect = (ccv_rect_t *) ccv_array_get(words, i); 22 | py::dict item; 23 | item["x"] = rect->x; 24 | item["y"] = rect->y; 25 | item["width"] = rect->width; 26 | item["height"] = rect->height; 27 | result.append(item); 28 | } 29 | ccv_array_free(words); 30 | } 31 | ccv_matrix_free(image); 32 | } 33 | 34 | return result; 35 | } 36 | 37 | 38 | PYBIND11_MODULE(swt_python3, m) { 39 | m.doc() = "Python 3 compatible SWT (Stroke-Width-Transform) binding to libccv by Marcin Zabłocki"; 40 | m.def("swt", &swt, "Apply Stroke-Width-Transform on input byte stream"); 41 | } -------------------------------------------------------------------------------- /test_input.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marrrcin/swt-python/86a7553d1861f4dd7114c01b6ae512090d7ee14f/test_input.jpg --------------------------------------------------------------------------------