From 104e7bedffd85cf724bc708301f88bb58199b049 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:45:41 -0600 Subject: [PATCH 01/13] fix poetry not installing deps out of the box need to explicitly limit python ver to <3.13 to keep pyinstaller v5. not sure if you want to bump that or not --- poetry.lock | 506 +++---------------------------------------------- pyproject.toml | 15 +- 2 files changed, 38 insertions(+), 483 deletions(-) diff --git a/poetry.lock b/poetry.lock index 33e2557..3709f1b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "altgraph" @@ -11,37 +11,6 @@ files = [ {file = "altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406"}, ] -[[package]] -name = "annotated-types" -version = "0.6.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, -] - -[[package]] -name = "anyio" -version = "4.3.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.8" -files = [ - {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, - {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, -] - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" - -[package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] - [[package]] name = "black" version = "22.12.0" @@ -68,6 +37,7 @@ click = ">=8.0.0" mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0" platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} [package.extras] colorama = ["colorama (>=0.4.3)"] @@ -101,87 +71,18 @@ files = [ ] [[package]] -name = "coloredlogs" -version = "15.0.1" -description = "Colored terminal output for Python's logging module" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, - {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, -] - -[package.dependencies] -humanfriendly = ">=9.1" - -[package.extras] -cron = ["capturer (>=2.4)"] - -[[package]] -name = "fastapi" -version = "0.110.0" -description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -optional = false -python-versions = ">=3.8" -files = [ - {file = "fastapi-0.110.0-py3-none-any.whl", hash = "sha256:87a1f6fb632a218222c5984be540055346a8f5d8a68e8f6fb647b1dc9934de4b"}, - {file = "fastapi-0.110.0.tar.gz", hash = "sha256:266775f0dcc95af9d3ef39bad55cff525329a931d5fd51930aadd4f428bf7ff3"}, -] - -[package.dependencies] -pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.36.3,<0.37.0" -typing-extensions = ">=4.8.0" - -[package.extras] -all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] - -[[package]] -name = "flatbuffers" -version = "24.3.7" -description = "The FlatBuffers serialization format for Python" -optional = false -python-versions = "*" -files = [ - {file = "flatbuffers-24.3.7-py2.py3-none-any.whl", hash = "sha256:80c4f5dcad0ee76b7e349671a0d657f2fbba927a0244f88dd3f5ed6a3694e1fc"}, - {file = "flatbuffers-24.3.7.tar.gz", hash = "sha256:0895c22b9a6019ff2f4de2e5e2f7cd15914043e6e7033a94c0c6369422690f22"}, -] - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +name = "exceptiongroup" +version = "1.2.2" +description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "humanfriendly" -version = "10.0" -description = "Human friendly output for text interfaces using Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, - {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] -[package.dependencies] -pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} - -[[package]] -name = "idna" -version = "3.6" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, -] +[package.extras] +test = ["pytest (>=6)"] [[package]] name = "iniconfig" @@ -208,88 +109,6 @@ files = [ [package.dependencies] altgraph = ">=0.17" -[[package]] -name = "mpmath" -version = "1.3.0" -description = "Python library for arbitrary-precision floating-point arithmetic" -optional = false -python-versions = "*" -files = [ - {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, - {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, -] - -[package.extras] -develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"] -docs = ["sphinx"] -gmpy = ["gmpy2 (>=2.1.0a4)"] -tests = ["pytest (>=4.6)"] - -[[package]] -name = "msgpack" -version = "1.0.8" -description = "MessagePack serializer" -optional = false -python-versions = ">=3.8" -files = [ - {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:505fe3d03856ac7d215dbe005414bc28505d26f0c128906037e66d98c4e95868"}, - {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b7842518a63a9f17107eb176320960ec095a8ee3b4420b5f688e24bf50c53c"}, - {file = "msgpack-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:376081f471a2ef24828b83a641a02c575d6103a3ad7fd7dade5486cad10ea659"}, - {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e390971d082dba073c05dbd56322427d3280b7cc8b53484c9377adfbae67dc2"}, - {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e073efcba9ea99db5acef3959efa45b52bc67b61b00823d2a1a6944bf45982"}, - {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d92c773fbc6942a7a8b520d22c11cfc8fd83bba86116bfcf962c2f5c2ecdaa"}, - {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9ee32dcb8e531adae1f1ca568822e9b3a738369b3b686d1477cbc643c4a9c128"}, - {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e3aa7e51d738e0ec0afbed661261513b38b3014754c9459508399baf14ae0c9d"}, - {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69284049d07fce531c17404fcba2bb1df472bc2dcdac642ae71a2d079d950653"}, - {file = "msgpack-1.0.8-cp310-cp310-win32.whl", hash = "sha256:13577ec9e247f8741c84d06b9ece5f654920d8365a4b636ce0e44f15e07ec693"}, - {file = "msgpack-1.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:e532dbd6ddfe13946de050d7474e3f5fb6ec774fbb1a188aaf469b08cf04189a"}, - {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"}, - {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"}, - {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"}, - {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"}, - {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"}, - {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"}, - {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"}, - {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"}, - {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"}, - {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"}, - {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"}, - {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"}, - {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"}, - {file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"}, - {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3"}, - {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc"}, - {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58"}, - {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f"}, - {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04"}, - {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543"}, - {file = "msgpack-1.0.8-cp312-cp312-win32.whl", hash = "sha256:64d0fcd436c5683fdd7c907eeae5e2cbb5eb872fafbc03a43609d7941840995c"}, - {file = "msgpack-1.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:74398a4cf19de42e1498368c36eed45d9528f5fd0155241e82c4082b7e16cffd"}, - {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ceea77719d45c839fd73abcb190b8390412a890df2f83fb8cf49b2a4b5c2f40"}, - {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ab0bbcd4d1f7b6991ee7c753655b481c50084294218de69365f8f1970d4c151"}, - {file = "msgpack-1.0.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cce488457370ffd1f953846f82323cb6b2ad2190987cd4d70b2713e17268d24"}, - {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3923a1778f7e5ef31865893fdca12a8d7dc03a44b33e2a5f3295416314c09f5d"}, - {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22e47578b30a3e199ab067a4d43d790249b3c0587d9a771921f86250c8435db"}, - {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd739c9251d01e0279ce729e37b39d49a08c0420d3fee7f2a4968c0576678f77"}, - {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3420522057ebab1728b21ad473aa950026d07cb09da41103f8e597dfbfaeb13"}, - {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5845fdf5e5d5b78a49b826fcdc0eb2e2aa7191980e3d2cfd2a30303a74f212e2"}, - {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a0e76621f6e1f908ae52860bdcb58e1ca85231a9b0545e64509c931dd34275a"}, - {file = "msgpack-1.0.8-cp38-cp38-win32.whl", hash = "sha256:374a8e88ddab84b9ada695d255679fb99c53513c0a51778796fcf0944d6c789c"}, - {file = "msgpack-1.0.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3709997b228685fe53e8c433e2df9f0cdb5f4542bd5114ed17ac3c0129b0480"}, - {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f51bab98d52739c50c56658cc303f190785f9a2cd97b823357e7aeae54c8f68a"}, - {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73ee792784d48aa338bba28063e19a27e8d989344f34aad14ea6e1b9bd83f596"}, - {file = "msgpack-1.0.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9904e24646570539a8950400602d66d2b2c492b9010ea7e965025cb71d0c86d"}, - {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e75753aeda0ddc4c28dce4c32ba2f6ec30b1b02f6c0b14e547841ba5b24f753f"}, - {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dbf059fb4b7c240c873c1245ee112505be27497e90f7c6591261c7d3c3a8228"}, - {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4916727e31c28be8beaf11cf117d6f6f188dcc36daae4e851fee88646f5b6b18"}, - {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7938111ed1358f536daf311be244f34df7bf3cdedb3ed883787aca97778b28d8"}, - {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:493c5c5e44b06d6c9268ce21b302c9ca055c1fd3484c25ba41d34476c76ee746"}, - {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, - {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, - {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, - {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, -] - [[package]] name = "mypy" version = "1.9.0" @@ -328,6 +147,7 @@ files = [ [package.dependencies] mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = ">=4.1.0" [package.extras] @@ -403,48 +223,6 @@ files = [ {file = "objprint-0.2.3.tar.gz", hash = "sha256:73d0ad5a7c3151fce634c8892e5c2a050ccae3b1a353bf1316f08b7854da863b"}, ] -[[package]] -name = "onnxruntime" -version = "1.17.1" -description = "ONNX Runtime is a runtime accelerator for Machine Learning models" -optional = false -python-versions = "*" -files = [ - {file = "onnxruntime-1.17.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d43ac17ac4fa3c9096ad3c0e5255bb41fd134560212dc124e7f52c3159af5d21"}, - {file = "onnxruntime-1.17.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55b5e92a4c76a23981c998078b9bf6145e4fb0b016321a8274b1607bd3c6bd35"}, - {file = "onnxruntime-1.17.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ebbcd2bc3a066cf54e6f18c75708eb4d309ef42be54606d22e5bdd78afc5b0d7"}, - {file = "onnxruntime-1.17.1-cp310-cp310-win32.whl", hash = "sha256:5e3716b5eec9092e29a8d17aab55e737480487deabfca7eac3cd3ed952b6ada9"}, - {file = "onnxruntime-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:fbb98cced6782ae1bb799cc74ddcbbeeae8819f3ad1d942a74d88e72b6511337"}, - {file = "onnxruntime-1.17.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:36fd6f87a1ecad87e9c652e42407a50fb305374f9a31d71293eb231caae18784"}, - {file = "onnxruntime-1.17.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99a8bddeb538edabc524d468edb60ad4722cff8a49d66f4e280c39eace70500b"}, - {file = "onnxruntime-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd7fddb4311deb5a7d3390cd8e9b3912d4d963efbe4dfe075edbaf18d01c024e"}, - {file = "onnxruntime-1.17.1-cp311-cp311-win32.whl", hash = "sha256:606a7cbfb6680202b0e4f1890881041ffc3ac6e41760a25763bd9fe146f0b335"}, - {file = "onnxruntime-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:53e4e06c0a541696ebdf96085fd9390304b7b04b748a19e02cf3b35c869a1e76"}, - {file = "onnxruntime-1.17.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:40f08e378e0f85929712a2b2c9b9a9cc400a90c8a8ca741d1d92c00abec60843"}, - {file = "onnxruntime-1.17.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac79da6d3e1bb4590f1dad4bb3c2979d7228555f92bb39820889af8b8e6bd472"}, - {file = "onnxruntime-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ae9ba47dc099004e3781f2d0814ad710a13c868c739ab086fc697524061695ea"}, - {file = "onnxruntime-1.17.1-cp312-cp312-win32.whl", hash = "sha256:2dff1a24354220ac30e4a4ce2fb1df38cb1ea59f7dac2c116238d63fe7f4c5ff"}, - {file = "onnxruntime-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:6226a5201ab8cafb15e12e72ff2a4fc8f50654e8fa5737c6f0bd57c5ff66827e"}, - {file = "onnxruntime-1.17.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:cd0c07c0d1dfb8629e820b05fda5739e4835b3b82faf43753d2998edf2cf00aa"}, - {file = "onnxruntime-1.17.1-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:617ebdf49184efa1ba6e4467e602fbfa029ed52c92f13ce3c9f417d303006381"}, - {file = "onnxruntime-1.17.1-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9dae9071e3facdf2920769dceee03b71c684b6439021defa45b830d05e148924"}, - {file = "onnxruntime-1.17.1-cp38-cp38-win32.whl", hash = "sha256:835d38fa1064841679433b1aa8138b5e1218ddf0cfa7a3ae0d056d8fd9cec713"}, - {file = "onnxruntime-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:96621e0c555c2453bf607606d08af3f70fbf6f315230c28ddea91754e17ad4e6"}, - {file = "onnxruntime-1.17.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:7a9539935fb2d78ebf2cf2693cad02d9930b0fb23cdd5cf37a7df813e977674d"}, - {file = "onnxruntime-1.17.1-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45c6a384e9d9a29c78afff62032a46a993c477b280247a7e335df09372aedbe9"}, - {file = "onnxruntime-1.17.1-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e19f966450f16863a1d6182a685ca33ae04d7772a76132303852d05b95411ea"}, - {file = "onnxruntime-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e2ae712d64a42aac29ed7a40a426cb1e624a08cfe9273dcfe681614aa65b07dc"}, - {file = "onnxruntime-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:f7e9f7fb049825cdddf4a923cfc7c649d84d63c0134315f8e0aa9e0c3004672c"}, -] - -[package.dependencies] -coloredlogs = "*" -flatbuffers = "*" -numpy = ">=1.21.6" -packaging = "*" -protobuf = "*" -sympy = "*" - [[package]] name = "opencv-python" version = "4.9.0.80" @@ -462,7 +240,12 @@ files = [ ] [package.dependencies] -numpy = {version = ">=1.23.5", markers = "python_version >= \"3.11\""} +numpy = [ + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, + {version = ">=1.23.5", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, + {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""}, + {version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""}, +] [[package]] name = "packaging" @@ -527,26 +310,6 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "protobuf" -version = "4.25.3" -description = "" -optional = false -python-versions = ">=3.8" -files = [ - {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, - {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, - {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, - {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, - {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, - {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, - {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, - {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, - {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, -] - [[package]] name = "psutil" version = "5.9.8" @@ -575,156 +338,6 @@ files = [ [package.extras] test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] -[[package]] -name = "pydantic" -version = "2.6.3" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"}, - {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"}, -] - -[package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.16.3" -typing-extensions = ">=4.6.1" - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.16.3" -description = "" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"}, - {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"}, - {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"}, - {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"}, - {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"}, - {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"}, - {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"}, - {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"}, - {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"}, - {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"}, - {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"}, - {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"}, - {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"}, - {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"}, - {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"}, - {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"}, - {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"}, - {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"}, - {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"}, - {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"}, - {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"}, - {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"}, - {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"}, - {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"}, - {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"}, - {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"}, - {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"}, - {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"}, - {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"}, - {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"}, - {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"}, - {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"}, - {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pye3d" -version = "0.3.2" -description = "3D eye model" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pye3d-0.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:25875702bfb644171b7e5ffc7c778289e4adf3d57aa3959aa8935b44f9ed81f9"}, - {file = "pye3d-0.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b527a02a3872f8a38f8a74fb2f5b3d2bad677190f13fae6d1997c963be264eb"}, - {file = "pye3d-0.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:01f96d315f218e2a3da27eb6a831eb8d0f1e56a62292ff08f7ca839d0eb98e61"}, - {file = "pye3d-0.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e5b61e47761dc6f455447ffb817a8a2900b0c231f6ac2744cbe77633317a2007"}, - {file = "pye3d-0.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c356f102334b4f0f50bc459c85e556567c6b115a48fb689cd293588ef80ca0e3"}, - {file = "pye3d-0.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:b1577c6081414a07a457d9e8b6bd6920cd3ccc86415eec286f5b92504bb597c0"}, - {file = "pye3d-0.3.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:569bcfb86f29cd7c3f54fcb5849583c8299168e4f4b2bc01616dacd02af7f9c8"}, - {file = "pye3d-0.3.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffe579fdb90491a7ae16e9bf541c0ceab2e940e1502f35e747b441a776d61989"}, - {file = "pye3d-0.3.2-cp36-cp36m-win_amd64.whl", hash = "sha256:3c5ec18e11cc21e44ec438ea86e8d4b79702032eb3738e0272f7104b9d01364a"}, - {file = "pye3d-0.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5cead11165c0936ee12e3021ab9bafa600400981726c2d53c51350a89f74f18d"}, - {file = "pye3d-0.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b785502d21aac56fea97a382227e69ddc8ecbcf9dc31d5025f66e2ca1cb1a998"}, - {file = "pye3d-0.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:0f03a946bb3caa8153e3b22f3464598096396e3038f26f75ea5234cb0b7c43ca"}, - {file = "pye3d-0.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba5f9208736709dbd328122ecb7153324490a885291fd1b0942add179e59a258"}, - {file = "pye3d-0.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ddda0564ec37d6a150222c2c826ba9e1090d5559f7ec1ea5a7dc877f45c7b33"}, - {file = "pye3d-0.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:239cc403748bab8b08b1c682552163dc8eeb3d93a70e1a9a20bba3d429ffe5c5"}, - {file = "pye3d-0.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:aa3a52b9f52ce1b6681b7e49ea870f825a86a1ee82d81d90f1b0079b651e0932"}, - {file = "pye3d-0.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e58f0b8f8cfb7bbe956cd9b7eb4d5cdbfea62138e80158200aa2da52e703374"}, - {file = "pye3d-0.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:50780d21a6d4fdf2758493e855f56c6a7c92912bb938a5eb3df6805ecbf8fce9"}, - {file = "pye3d-0.3.2.tar.gz", hash = "sha256:12793dd0b2926539252d6b2ba9df6b0c1774947a007661b2c1670ef73c905339"}, -] - -[package.dependencies] -msgpack = ">=1.0" -numpy = "*" -sortedcontainers = "*" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx (<4.4)"] -examples = ["opencv-python", "pupil-detectors"] -legacy-sklearn-models = ["joblib", "scikit-learn"] -testing = ["matplotlib", "opencv-python-headless (==4.6.0.66)", "pandas", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "scikit-image"] -with-opencv = ["opencv-python"] - [[package]] name = "pyinstaller" version = "5.13.2" @@ -773,17 +386,6 @@ files = [ packaging = ">=22.0" setuptools = ">=42.0.0" -[[package]] -name = "pyreadline3" -version = "3.4.1" -description = "A python implementation of GNU readline." -optional = false -python-versions = "*" -files = [ - {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"}, - {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, -] - [[package]] name = "pyserial" version = "3.5" @@ -811,9 +413,11 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] @@ -901,58 +505,16 @@ testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[l testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "sortedcontainers" -version = "2.4.0" -description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" -optional = false -python-versions = "*" -files = [ - {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, - {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, -] - -[[package]] -name = "starlette" -version = "0.36.3" -description = "The little ASGI library that shines." -optional = false -python-versions = ">=3.8" -files = [ - {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"}, - {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"}, -] - -[package.dependencies] -anyio = ">=3.4.0,<5" - -[package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] - -[[package]] -name = "sympy" -version = "1.12" -description = "Computer algebra system (CAS) in Python" +name = "tomli" +version = "2.1.0" +description = "A lil' TOML parser" optional = false python-versions = ">=3.8" files = [ - {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"}, - {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"}, + {file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"}, + {file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"}, ] -[package.dependencies] -mpmath = ">=0.19" - [[package]] name = "typing-extensions" version = "4.10.0" @@ -964,24 +526,6 @@ files = [ {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] -[[package]] -name = "uvicorn" -version = "0.20.0" -description = "The lightning-fast ASGI server." -optional = false -python-versions = ">=3.7" -files = [ - {file = "uvicorn-0.20.0-py3-none-any.whl", hash = "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd"}, - {file = "uvicorn-0.20.0.tar.gz", hash = "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8"}, -] - -[package.dependencies] -click = ">=7.0" -h11 = ">=0.8" - -[package.extras] -standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] - [[package]] name = "viztracer" version = "0.15.6" @@ -1074,5 +618,5 @@ watchmedo = ["PyYAML (>=3.10)"] [metadata] lock-version = "2.0" -python-versions = "~3.11.0" -content-hash = "3edf4ffa8dd42d4922b72abe8689db9a75459f3381876220ab0511ae816ff6b6" +python-versions = ">=3.10.0,<3.13" +content-hash = "8253562970f8adbbd8f3debf919fce05c7e8e3fb71e8f4f9082d197db77f481d" diff --git a/pyproject.toml b/pyproject.toml index f6b8aca..42df1b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ license = "GPL v3" repository = "https://github.com/RedHawk989/ETVR-Data-Collection" [tool.poetry.dependencies] -python = ">=3.10.0" +python = ">=3.10.0,<3.13" python-osc = "^1.8.1" opencv-python = "^4.8.0.74" numpy = "^1.23.5" @@ -38,7 +38,18 @@ respect-gitignore = true target-version = "py311" output-format = "grouped" indent-width = 4 -exclude = ["__pycache__", ".ruff_cache", ".vscode", ".idea", ".venv", "build", "dist", ".git", ".env", "venv"] +exclude = [ + "__pycache__", + ".ruff_cache", + ".vscode", + ".idea", + ".venv", + "build", + "dist", + ".git", + ".env", + "venv", +] line-length = 135 [tool.ruff.per-file-ignores] From 1ed0582c1147eb577b48e2cb37223e683036a403 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Tue, 19 Nov 2024 19:14:47 -0600 Subject: [PATCH 02/13] add rejection of similar frames uses cv2 template matching to compare against previous frames and skips saving frames that are too similar --- imganno.py | 90 ++++++++++++++++++++++-------------------------------- 1 file changed, 37 insertions(+), 53 deletions(-) diff --git a/imganno.py b/imganno.py index 2805578..79289e6 100644 --- a/imganno.py +++ b/imganno.py @@ -1,13 +1,15 @@ import cv2 import glob import os -import time import sys +import collections # Constants MAX_POINTS = 7 KEYPOINT_COLOR = (255, 255, 0) -KEYPOINT_ALPHA = 0.30 # Transparency value (0.0 - fully transparent, 1.0 - fully opaque) +KEYPOINT_ALPHA = 0.30 # Transparency value (0.0 - fully transparent, 1.0 - fully opaque) +SIMILARITY_LOOKBACK_COUNT = 10 # Number of previous good frames to check similarity to +SIMILARITY_THRESHOLD = 0.99 last_annotated_index_path = "last_annotated_index.txt" # Variables image_points = [] @@ -30,6 +32,7 @@ def mouse_callback(event, x, y, flags, param): closest_point_index = distances.index(min(distances)) image_points[closest_point_index] = (image_points[closest_point_index][0], x, y) + def load_last_annotated_index(file_path): try: with open(file_path, "r") as file: @@ -37,22 +40,19 @@ def load_last_annotated_index(file_path): except FileNotFoundError: return 0 + # Function to save the last annotated frame index to a file def save_last_annotated_index(file_path, index): with open(file_path, "w") as file: file.write(str(index)) -import os -import cv2 - - def extract_frames(video_path, output_folder): - # Get the base name of the video file without the extension - base_name = os.path.splitext(os.path.basename(video_path))[0] + # # Get the base name of the video file without the extension + # base_name = os.path.splitext(os.path.basename(video_path))[0] # Create the output folder if it doesn't exist - # output_folder = base_name + '_frames' + # output_folder = base_name + '_frames' os.makedirs(output_folder, exist_ok=True) # Open the video file @@ -69,18 +69,28 @@ def extract_frames(video_path, output_folder): print(f"Extracting {frame_count} frames from {video_path} at {fps} FPS") frame_number = 0 + frame_good = 0 + frame_deque = collections.deque(maxlen=SIMILARITY_LOOKBACK_COUNT) while True: try: ret, frame = cap.read() if not ret: - print(f"Finished extracting frames. Total frames extracted: {frame_number}") + print(f"Finished extracting frames. Total frames extracted: {frame_number}, out of which {frame_good} are saved.") break - # Save the frame as a JPEG file - frame_path = os.path.join(output_folder, f"{video_path}_frame_{frame_number:04d}.jpeg") - cv2.imwrite(frame_path, frame) - - print(f"Saved frame {frame_number}") + is_frame_good = True + for frame_number_template, frame_template in frame_deque: + if cv2.matchTemplate(frame, frame_template, cv2.TM_CCOEFF_NORMED).max() >= SIMILARITY_THRESHOLD: + print(f"Frame {frame_number} is too similar to {frame_number_template}, dropping..") + is_frame_good = False + break + if is_frame_good or len(frame_deque) == 0: + # Save the frame as a JPEG file + frame_path = os.path.join(output_folder, f"{video_path}_frame_{frame_number:04d}.jpeg") + cv2.imwrite(frame_path, frame) + frame_deque.append((frame_number, frame)) + frame_good += 1 + print(f"Saved frame {frame_number}") frame_number += 1 @@ -95,12 +105,13 @@ def extract_frames(video_path, output_folder): video_path = input("Give the name of the video you would like to annotate :> ") -output_folder = "output_frames" #input("What would you like to name the output folder, or what is the name of the folder of pre extracted frames :> ") +output_folder = "output_frames" # input("What would you like to name the output folder, or what is the name of the folder of pre extracted frames :> ") -resume_status = input("Resume annotations where you left off? Y/N? (if you are doing a new video type N, this will not work properly if new files have been added) :> ") +resume_status = input( + "Resume annotations where you left off? Y/N? (if you are doing a new video type N, this will not work properly if new files have been added) :> " +) resume_status = resume_status.lower() if resume_status == "y": - image_index = load_last_annotated_index(last_annotated_index_path) print("resuming") @@ -108,7 +119,7 @@ def extract_frames(video_path, output_folder): extract_frames(video_path, output_folder) -print('\n \nKeybinds:') +print("\n \nKeybinds:") print("Press 'r' to clear the keypoints.") print("Press 'w' to save the keypoints and move to the next image.") print("Press 'q' to place the keypoints from the previous image to the current image \n") @@ -119,10 +130,7 @@ def extract_frames(video_path, output_folder): print("Right click to adjust point nearest to cursor to cursor position. \n \n") - - - -image_folder = output_folder # path with .jpg images +image_folder = output_folder # path with .jpg images image_files = glob.glob(image_folder + "/*.jpeg") cv2.namedWindow("Image") @@ -151,8 +159,9 @@ def extract_frames(video_path, output_folder): original_point = (int(point[1]), int(point[2])) cv2.circle(display_image, original_point, 4, (0, 255, 0), -1) - cv2.putText(display_image, str(i + 1), (original_point[0], original_point[1] + 15), - cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) + cv2.putText( + display_image, str(i + 1), (original_point[0], original_point[1] + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1 + ) cv2.imshow("Image", display_image) key = cv2.waitKey(1) & 0xFF @@ -170,16 +179,15 @@ def extract_frames(video_path, output_folder): point_string = ",".join([f"{int(point[1] / scale_factor)},{int(point[2] / scale_factor)}" for point in sorted_points]) point_string = point_string.replace(",", " ") - point_string = f'{point_string} {filen}' - print(f'[INFO] SAVED DATA FOR FRAME {filen}') + point_string = f"{point_string} {filen}" + print(f"[INFO] SAVED DATA FOR FRAME {filen}") file_path = "points.txt" # Replace with path of existing file to save keypoint data to with open(file_path, "a") as file: file.write(point_string + "\n") else: - print(f'[INFO] SKIPPED FRAME {filen}') + print(f"[INFO] SKIPPED FRAME {filen}") break - if key == ord("r"): print("[INFO] CLEARED KEYPOINTS") image_points = [] @@ -194,11 +202,6 @@ def extract_frames(video_path, output_folder): image_points = keypoints_history[-1].copy() # Copy the last set of keypoints from history print("[INFO] Placed keypoints from history") - - - - - # Reset points for the next image image_points = [] @@ -207,22 +210,3 @@ def extract_frames(video_path, output_folder): save_last_annotated_index(last_annotated_index_path, image_index) cv2.destroyAllWindows() - - - - - - - - - - - - - - - - - - - From f2dd2dd8627d8e4b4c6b1c9b7b8a7f1c936e39c3 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:44:58 -0600 Subject: [PATCH 03/13] add point hints and keyboard shortcut footer grabbed the point placement hints from the dev updates post. kboard shortcut hints from the print statement above --- imganno.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/imganno.py b/imganno.py index 79289e6..2dff073 100644 --- a/imganno.py +++ b/imganno.py @@ -1,4 +1,5 @@ import cv2 +import numpy as np import glob import os import sys @@ -10,6 +11,15 @@ KEYPOINT_ALPHA = 0.30 # Transparency value (0.0 - fully transparent, 1.0 - fully opaque) SIMILARITY_LOOKBACK_COUNT = 10 # Number of previous good frames to check similarity to SIMILARITY_THRESHOLD = 0.99 +POINT_HELP_TEXT = [ + "left eyelid corner", + "upper left eyelid", + "upper right eyelid", + "right eyelid corner", + "lower right eyelid", + "lower left eyelid", + "pupil center", +] last_annotated_index_path = "last_annotated_index.txt" # Variables image_points = [] @@ -141,8 +151,12 @@ def extract_frames(video_path, output_folder): while image_index < len(image_files): # Load image print(image_index) + directory_path = os.path.dirname(image_files[image_index]) + file_name = image_files[image_index].replace(directory_path + os.path.sep, "") image = cv2.imread(image_files[image_index]) + image_points = [] + point_id = 0 for keypoints in keypoints_history: for point in keypoints: overlay = image.copy() @@ -153,6 +167,34 @@ def extract_frames(video_path, output_folder): while True: display_image = cv2.resize(image, None, fx=scale_factor, fy=scale_factor) # Scale the image + # Point hint when putting down points + if point_id < MAX_POINTS: + cv2.putText( + display_image, + f"put down {point_id+1}: {POINT_HELP_TEXT[point_id]}", + (5, 14), + cv2.FONT_HERSHEY_SIMPLEX, + 0.5, + (0, 255, 0), + 1, + ) + + # Keyboard shortcuts as footer + text_footer = np.zeros((np.uint8(0.04 * display_image.shape[1]), display_image.shape[0], 3), np.uint8) + cv2.putText( + text_footer, + "r - clear | w - save | q - copy from prev | y - quit", + ( + np.uint8(0.01 * display_image.shape[0]), + np.uint8(text_footer.shape[0] / 2 + 0.009 * display_image.shape[1]), + ), + cv2.FONT_HERSHEY_SIMPLEX, + 0.5, + (229, 229, 229), + 1, + ) + + display_image = cv2.vconcat([display_image, text_footer]) for i, point in enumerate(image_points): # Scale the points back to the original image size @@ -164,28 +206,33 @@ def extract_frames(video_path, output_folder): ) cv2.imshow("Image", display_image) + cv2.setWindowTitle("Image", f"Current image: {file_name}") key = cv2.waitKey(1) & 0xFF if key == ord("w"): directory_path = os.path.dirname(image_files[image_index]) - file_name = os.path.basename(image_files[image_index]) - filen = image_files[image_index].replace(directory_path + os.path.sep, "") + file_name = image_files[image_index].replace(directory_path + os.path.sep, "") if len(image_points) == MAX_POINTS: keypoints_history = [image_points.copy()] sorted_points = sorted(image_points, key=lambda x: x[0]) # Print image points - point_string = ",".join([f"{int(point[1] / scale_factor)},{int(point[2] / scale_factor)}" for point in sorted_points]) + point_string = ",".join( + [ + f"{min(int(point[1] / scale_factor), image.shape[1])},{min(int(point[2] / scale_factor), image.shape[0])}" + for point in sorted_points + ] + ) point_string = point_string.replace(",", " ") - point_string = f"{point_string} {filen}" - print(f"[INFO] SAVED DATA FOR FRAME {filen}") + point_string = f"{point_string} {file_name}" + print(f"[INFO] SAVED DATA FOR FRAME {file_name}") file_path = "points.txt" # Replace with path of existing file to save keypoint data to with open(file_path, "a") as file: file.write(point_string + "\n") else: - print(f"[INFO] SKIPPED FRAME {filen}") + print(f"[INFO] SKIPPED FRAME {file_name}") break if key == ord("r"): @@ -200,6 +247,7 @@ def extract_frames(video_path, output_folder): if key == ord("q"): if len(keypoints_history) > 0: image_points = keypoints_history[-1].copy() # Copy the last set of keypoints from history + point_id = MAX_POINTS print("[INFO] Placed keypoints from history") # Reset points for the next image From e256c9d029949ebc1a25db472d603c7dc718418a Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:06:53 -0600 Subject: [PATCH 04/13] fix off by one error --- imganno.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imganno.py b/imganno.py index 2dff073..3c007cf 100644 --- a/imganno.py +++ b/imganno.py @@ -220,7 +220,7 @@ def extract_frames(video_path, output_folder): # Print image points point_string = ",".join( [ - f"{min(int(point[1] / scale_factor), image.shape[1])},{min(int(point[2] / scale_factor), image.shape[0])}" + f"{min(int(point[1] / scale_factor), image.shape[1]-1)},{min(int(point[2] / scale_factor), image.shape[0]-1)}" for point in sorted_points ] ) From b55003e2b3da76622927eb323d3771366c182090 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Tue, 19 Nov 2024 22:59:31 -0600 Subject: [PATCH 05/13] add ability to move to previous frame i make mistakes a lot when annotating XD --- imganno.py | 65 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/imganno.py b/imganno.py index 3c007cf..ae9e252 100644 --- a/imganno.py +++ b/imganno.py @@ -4,6 +4,7 @@ import os import sys import collections +import re # Constants MAX_POINTS = 7 @@ -21,6 +22,7 @@ "pupil center", ] last_annotated_index_path = "last_annotated_index.txt" +points_path = "points.txt" # Replace with path of existing file to save keypoint data to # Variables image_points = [] image_index = 0 @@ -132,7 +134,8 @@ def extract_frames(video_path, output_folder): print("\n \nKeybinds:") print("Press 'r' to clear the keypoints.") print("Press 'w' to save the keypoints and move to the next image.") -print("Press 'q' to place the keypoints from the previous image to the current image \n") +print("Press 's' to save the keypoints and move to the previous image.") +print("Press 'q' to place the shadow keypoints to the current image \n") print("Press 'y' to close the program \n") print("Mouse Buttons:") @@ -148,15 +151,30 @@ def extract_frames(video_path, output_folder): scale_factor = 2 # Set the desired scale factor -while image_index < len(image_files): +while True: + # Init + image_points = [] + point_id = 0 + # Load image - print(image_index) directory_path = os.path.dirname(image_files[image_index]) file_name = image_files[image_index].replace(directory_path + os.path.sep, "") image = cv2.imread(image_files[image_index]) + print(f"Annotating {file_name}") + + # Load image points + line = None + with open(points_path, "r") as file: + line = re.search(f"(^|\n).*{file_name}.*", file.read()) + if line: + parts = line[0].strip().split() + coords = list(map(int, parts[:-1])) + for i in range(0, len(coords), 2): + x = coords[i] * scale_factor + y = coords[i + 1] * scale_factor + image_points.append((point_id, x, y)) + point_id += 1 - image_points = [] - point_id = 0 for keypoints in keypoints_history: for point in keypoints: overlay = image.copy() @@ -183,7 +201,7 @@ def extract_frames(video_path, output_folder): text_footer = np.zeros((np.uint8(0.04 * display_image.shape[1]), display_image.shape[0], 3), np.uint8) cv2.putText( text_footer, - "r - clear | w - save | q - copy from prev | y - quit", + "r - clear | w - next | s - prev | q - copy KPs | y - quit", ( np.uint8(0.01 * display_image.shape[0]), np.uint8(text_footer.shape[0] / 2 + 0.009 * display_image.shape[1]), @@ -209,10 +227,7 @@ def extract_frames(video_path, output_folder): cv2.setWindowTitle("Image", f"Current image: {file_name}") key = cv2.waitKey(1) & 0xFF - if key == ord("w"): - directory_path = os.path.dirname(image_files[image_index]) - file_name = image_files[image_index].replace(directory_path + os.path.sep, "") - + if key == ord("w") or key == ord("s"): if len(image_points) == MAX_POINTS: keypoints_history = [image_points.copy()] sorted_points = sorted(image_points, key=lambda x: x[0]) @@ -227,13 +242,29 @@ def extract_frames(video_path, output_folder): point_string = point_string.replace(",", " ") point_string = f"{point_string} {file_name}" - print(f"[INFO] SAVED DATA FOR FRAME {file_name}") - file_path = "points.txt" # Replace with path of existing file to save keypoint data to - with open(file_path, "a") as file: + with open(points_path, "r") as file: + file_content = file.read() + line = re.search(f"(^|\n).*{file_name}.*", file_content) + if line: + with open(points_path, "w") as file: + file.write(re.sub(f"(^|\n).*{file_name}.*", "", file_content)) + with open(points_path, "a") as file: file.write(point_string + "\n") + print(f"[INFO] SAVED DATA FOR FRAME {file_name}") + else: print(f"[INFO] SKIPPED FRAME {file_name}") - break + + save_last_annotated_index(last_annotated_index_path, image_index) + + if key == ord("w"): + # Move to the next image + image_index += 1 + break + elif key == ord("s"): + # Move to previous image + image_index -= 1 + break if key == ord("r"): print("[INFO] CLEARED KEYPOINTS") @@ -250,11 +281,5 @@ def extract_frames(video_path, output_folder): point_id = MAX_POINTS print("[INFO] Placed keypoints from history") - # Reset points for the next image - image_points = [] - - # Move to the next image - image_index += 1 - save_last_annotated_index(last_annotated_index_path, image_index) cv2.destroyAllWindows() From d83f359725da706d3005d898537bd8fd51654810 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Tue, 19 Nov 2024 23:27:11 -0600 Subject: [PATCH 06/13] fix can't find points file when it doesn't exist yet --- imganno.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/imganno.py b/imganno.py index ae9e252..6520e4a 100644 --- a/imganno.py +++ b/imganno.py @@ -164,8 +164,11 @@ def extract_frames(video_path, output_folder): # Load image points line = None - with open(points_path, "r") as file: - line = re.search(f"(^|\n).*{file_name}.*", file.read()) + try: + with open(points_path, "r") as file: + line = re.search(f"(^|\n).*{file_name}.*", file.read()) + except FileNotFoundError: + open(points_path, "a").close() if line: parts = line[0].strip().split() coords = list(map(int, parts[:-1])) From 1cfa26a920baf1b4917abecb91862105fa1e36e5 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Wed, 20 Nov 2024 20:19:35 -0600 Subject: [PATCH 07/13] fix out of bounds error --- imganno.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imganno.py b/imganno.py index 6520e4a..b970957 100644 --- a/imganno.py +++ b/imganno.py @@ -263,10 +263,12 @@ def extract_frames(video_path, output_folder): if key == ord("w"): # Move to the next image image_index += 1 + image_index = image_index if image_index < len(image_files) else 0 break elif key == ord("s"): # Move to previous image image_index -= 1 + image_index = image_index if image_index > 0 else len(image_files) - 1 break if key == ord("r"): From 10007b3e4bc55a53770cc488c4a1cb1a96135529 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Wed, 20 Nov 2024 20:34:43 -0600 Subject: [PATCH 08/13] add ability to rotate image while annotating --- imganno.py | 99 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 85 insertions(+), 14 deletions(-) diff --git a/imganno.py b/imganno.py index ae9e252..f4ff712 100644 --- a/imganno.py +++ b/imganno.py @@ -23,19 +23,35 @@ ] last_annotated_index_path = "last_annotated_index.txt" points_path = "points.txt" # Replace with path of existing file to save keypoint data to -# Variables + +# General variables +original_points = [] image_points = [] image_index = 0 keypoints_history = [] point_id = 0 +# Rotation-related variable +scale_factor = 2 # Set the desired scale factor +rotation_degrees = 0 +rotation_increment = 15 +rotation_matrix = np.asarray([[1, 0, 0], [0, 1, 0]]) +rotation_matrix_inv = np.asarray([[1, 0, 0], [0, 1, 0]]) + def mouse_callback(event, x, y, flags, param): - global image_points, point_id + global original_points, image_points, point_id, rotation_matrix_inv if event == cv2.EVENT_LBUTTONDOWN: if len(image_points) < MAX_POINTS: image_points.append((point_id, x, y)) + + # Points in its non-rotated coordinates + original_point = np.asarray([x, y]) + new_point = cv2.transform(original_point.reshape((-1, 1, 2)), rotation_matrix_inv) + new_point = np.uint16(new_point[0][0]) + original_points.append((point_id, new_point[0], new_point[1])) + point_id += 1 elif event == cv2.EVENT_RBUTTONDOWN: @@ -44,6 +60,12 @@ def mouse_callback(event, x, y, flags, param): closest_point_index = distances.index(min(distances)) image_points[closest_point_index] = (image_points[closest_point_index][0], x, y) + # Points in its non-rotated coordinates + original_point = np.asarray([x, y]) + new_point = cv2.transform(original_point.reshape((-1, 1, 2)), rotation_matrix_inv) + new_point = np.uint16(new_point[0][0]) + original_points[closest_point_index] = (image_points[closest_point_index][0], new_point[0], new_point[1]) + def load_last_annotated_index(file_path): try: @@ -136,6 +158,8 @@ def extract_frames(video_path, output_folder): print("Press 'w' to save the keypoints and move to the next image.") print("Press 's' to save the keypoints and move to the previous image.") print("Press 'q' to place the shadow keypoints to the current image \n") +print("Press 'd' to rotate image clockwise") +print("Press 'a' to rotate image counter-clockwise\n") print("Press 'y' to close the program \n") print("Mouse Buttons:") @@ -149,11 +173,11 @@ def extract_frames(video_path, output_folder): cv2.namedWindow("Image") cv2.setMouseCallback("Image", mouse_callback) -scale_factor = 2 # Set the desired scale factor while True: # Init image_points = [] + original_points = [] point_id = 0 # Load image @@ -172,9 +196,15 @@ def extract_frames(video_path, output_folder): for i in range(0, len(coords), 2): x = coords[i] * scale_factor y = coords[i + 1] * scale_factor - image_points.append((point_id, x, y)) + original_points.append((point_id, x, y)) + + original_point = np.asarray([x, y]) + new_point = cv2.transform(original_point.reshape((-1, 1, 2)), rotation_matrix) + new_point = np.uint16(new_point[0][0]) + image_points.append((point_id, new_point[0], new_point[1])) point_id += 1 + # Draw keypoints history on original image for keypoints in keypoints_history: for point in keypoints: overlay = image.copy() @@ -184,7 +214,15 @@ def extract_frames(video_path, output_folder): image = cv2.addWeighted(overlay, KEYPOINT_ALPHA, image, 1 - KEYPOINT_ALPHA, 0) while True: - display_image = cv2.resize(image, None, fx=scale_factor, fy=scale_factor) # Scale the image + # Scale the image + display_image = cv2.resize(image, None, fx=scale_factor, fy=scale_factor) + + # Rotate image + image_center = (display_image.shape[1] // 2, display_image.shape[0] // 2) + rotation_matrix = cv2.getRotationMatrix2D(image_center, rotation_degrees, 1) + rotation_matrix_inv = cv2.getRotationMatrix2D(image_center, -rotation_degrees, 1) + display_image = cv2.warpAffine(display_image, rotation_matrix, display_image.shape[0:-1]) + # Point hint when putting down points if point_id < MAX_POINTS: cv2.putText( @@ -211,16 +249,20 @@ def extract_frames(video_path, output_folder): (229, 229, 229), 1, ) - display_image = cv2.vconcat([display_image, text_footer]) + # Draw image annotations for i, point in enumerate(image_points): - # Scale the points back to the original image size - original_point = (int(point[1]), int(point[2])) - - cv2.circle(display_image, original_point, 4, (0, 255, 0), -1) + draw_point = (point[1], point[2]) + cv2.circle(display_image, draw_point, 4, (0, 255, 0), -1) cv2.putText( - display_image, str(i + 1), (original_point[0], original_point[1] + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1 + display_image, + str(i + 1), + (draw_point[0], draw_point[1] + 15), + cv2.FONT_HERSHEY_SIMPLEX, + 0.5, + (0, 255, 0), + 1, ) cv2.imshow("Image", display_image) @@ -229,8 +271,8 @@ def extract_frames(video_path, output_folder): if key == ord("w") or key == ord("s"): if len(image_points) == MAX_POINTS: - keypoints_history = [image_points.copy()] - sorted_points = sorted(image_points, key=lambda x: x[0]) + keypoints_history = [original_points.copy()] + sorted_points = sorted(original_points, key=lambda x: x[0]) # Print image points point_string = ",".join( @@ -260,10 +302,12 @@ def extract_frames(video_path, output_folder): if key == ord("w"): # Move to the next image image_index += 1 + image_index = image_index if image_index < len(image_files) else 0 break elif key == ord("s"): # Move to previous image image_index -= 1 + image_index = image_index if image_index > 0 else len(image_files) - 1 break if key == ord("r"): @@ -275,9 +319,36 @@ def extract_frames(video_path, output_folder): print("[INFO] CLOSING") exit() + if key == ord("a") or key == ord("d"): + if key == ord("a"): + rotation_degrees += rotation_increment + elif key == ord("d"): + rotation_degrees -= rotation_increment + # Clamp to 0..359 + rotation_degrees = rotation_degrees if rotation_degrees >= 0 else 360 + rotation_degrees + rotation_degrees = rotation_degrees if rotation_degrees < 360 else rotation_degrees - 360 + print(f"Rotation: {rotation_degrees}") + rotation_matrix = cv2.getRotationMatrix2D(image_center, rotation_degrees, 1) + rotation_matrix_inv = cv2.getRotationMatrix2D(image_center, -rotation_degrees, 1) + new_points = [] + for point in original_points: + original_point = np.asarray([point[1], point[2]]) + new_point = cv2.transform(original_point.reshape((-1, 1, 2)), rotation_matrix) + new_point = np.uint16(new_point[0][0]) + new_points.append((point[0], new_point[0], new_point[1])) + image_points = new_points + new_points = [] + if key == ord("q"): if len(keypoints_history) > 0: - image_points = keypoints_history[-1].copy() # Copy the last set of keypoints from history + original_points = keypoints_history[-1].copy() # Copy the last set of keypoints from history + new_points = [] + for point in original_points: + original_point = np.asarray([point[1], point[2]]) + new_point = cv2.transform(original_point.reshape((-1, 1, 2)), rotation_matrix) + new_point = np.uint16(new_point[0][0]) + new_points.append((point[0], new_point[0], new_point[1])) + image_points = new_points point_id = MAX_POINTS print("[INFO] Placed keypoints from history") From 066adda09b0703908e869b7673273c38c289f8f9 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Wed, 20 Nov 2024 20:38:12 -0600 Subject: [PATCH 09/13] fix off by one error -__- yeah i do this a lot --- imganno.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imganno.py b/imganno.py index 437f49b..3e1008d 100644 --- a/imganno.py +++ b/imganno.py @@ -310,7 +310,7 @@ def extract_frames(video_path, output_folder): elif key == ord("s"): # Move to previous image image_index -= 1 - image_index = image_index if image_index > 0 else len(image_files) - 1 + image_index = image_index if image_index >= 0 else len(image_files) - 1 break if key == ord("r"): From c2de56af0f79832227bdf888c1e6ab175cecffcc Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Wed, 20 Nov 2024 20:40:28 -0600 Subject: [PATCH 10/13] change annotation symbol of pupil to red makes it look more intuitive --- imganno.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imganno.py b/imganno.py index 3e1008d..ab8bc0e 100644 --- a/imganno.py +++ b/imganno.py @@ -257,7 +257,7 @@ def extract_frames(video_path, output_folder): # Draw image annotations for i, point in enumerate(image_points): draw_point = (point[1], point[2]) - cv2.circle(display_image, draw_point, 4, (0, 255, 0), -1) + cv2.circle(display_image, draw_point, 4, (0, 255, 0) if i < 6 else (0, 0, 255), -1) cv2.putText( display_image, str(i + 1), From 7bc7522b63f8d81b151df37e86562dff21a58793 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Wed, 20 Nov 2024 21:01:00 -0600 Subject: [PATCH 11/13] input validate points file --- data_validator.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/data_validator.py b/data_validator.py index 01adbd4..6803bf9 100644 --- a/data_validator.py +++ b/data_validator.py @@ -3,20 +3,24 @@ def read_data_file(file_path): - with open(file_path, 'r') as file: + with open(file_path, "r") as file: lines = file.readlines() data = [] for line in lines: parts = line.strip().split() + if len(parts) < 8: + print("Bad data") + continue coords = list(map(int, parts[:-1])) - # print(parts) - image_name = parts[-1] + try: + image_name = parts[-1] + except IndexError: + print("Bad data") + continue data.append((coords, image_name)) return data -import cv2 - def draw_points(image, points): for i in range(0, len(points), 2): x = points[i] @@ -27,14 +31,16 @@ def draw_points(image, points): return image - def main(): # Get the input file path from the user - file_path = "points.txt" #input("Enter the path to the .txt file: ") + file_path = "points.txt" # input("Enter the path to the .txt file: ") data = read_data_file(file_path) + if len(data) == 0: + print("No data to review") + quit() # Set the path to the folder containing images - image_folder = 'output_frames' + image_folder = "output_frames" index = 0 while True: @@ -49,10 +55,10 @@ def main(): image_with_points = draw_points(image, coords) - cv2.imshow('Image with Points', image_with_points) + cv2.imshow("Image with Points", image_with_points) key = cv2.waitKey(0) - if key == ord('q'): + if key == ord("q"): break else: index = (index + 1) % len(data) From 937711aed40220fd34ecdcf27311e8d2f326cfa6 Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Wed, 20 Nov 2024 22:39:12 -0600 Subject: [PATCH 12/13] change behaviour to export all data instead annotator will still only annotates good data --- imganno.py | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/imganno.py b/imganno.py index ab8bc0e..5d1ee23 100644 --- a/imganno.py +++ b/imganno.py @@ -113,18 +113,21 @@ def extract_frames(video_path, output_folder): break is_frame_good = True + filename = f"{video_path}_frame_{frame_number:04d}.jpeg" + frame_path = os.path.join(output_folder, filename) + # Save the frame as a JPEG file + cv2.imwrite(frame_path, frame) + print(f"Saved frame {frame_number}") for frame_number_template, frame_template in frame_deque: if cv2.matchTemplate(frame, frame_template, cv2.TM_CCOEFF_NORMED).max() >= SIMILARITY_THRESHOLD: - print(f"Frame {frame_number} is too similar to {frame_number_template}, dropping..") + print(f"Frame is too similar to {frame_number_template}, excluding to annotate..") is_frame_good = False break if is_frame_good or len(frame_deque) == 0: - # Save the frame as a JPEG file - frame_path = os.path.join(output_folder, f"{video_path}_frame_{frame_number:04d}.jpeg") - cv2.imwrite(frame_path, frame) frame_deque.append((frame_number, frame)) + with open(f"{output_folder}/good_images_list.txt", "a") as file: + file.write(f"{filename}\n") frame_good += 1 - print(f"Saved frame {frame_number}") frame_number += 1 @@ -168,7 +171,26 @@ def extract_frames(video_path, output_folder): image_folder = output_folder # path with .jpg images -image_files = glob.glob(image_folder + "/*.jpeg") +# image_files = glob.glob(image_folder + "/*.jpeg") +image_files = [] +try: + with open(f"{output_folder}/good_images_list.txt", "r") as file: + lines = file.readlines() +except FileNotFoundError: + print("No good images found! Press enter to exit..") + input() + exit() +else: + for line in lines: + image_file = f"{image_folder}/{line.strip()}" + if len(image_file) < len(image_folder): + continue + else: + image_files.append(image_file) +if len(image_files) == 0: + print("No good images found! Press enter to exit..") + input() + exit() cv2.namedWindow("Image") cv2.setMouseCallback("Image", mouse_callback) From a323d0c823e4e69a58045cd202115e568b02047b Mon Sep 17 00:00:00 2001 From: AnTaRes27 <39043966+AnTaRes27@users.noreply.github.com> Date: Thu, 21 Nov 2024 00:08:17 -0600 Subject: [PATCH 13/13] fix recorded filename including wrong path separator bug caused output data to be different than expected/required, unable to be read by data validator --- imganno.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imganno.py b/imganno.py index 5d1ee23..e4f8ad8 100644 --- a/imganno.py +++ b/imganno.py @@ -125,7 +125,7 @@ def extract_frames(video_path, output_folder): break if is_frame_good or len(frame_deque) == 0: frame_deque.append((frame_number, frame)) - with open(f"{output_folder}/good_images_list.txt", "a") as file: + with open(f"{output_folder}{os.path.sep}good_images_list.txt", "a") as file: file.write(f"{filename}\n") frame_good += 1 @@ -174,7 +174,7 @@ def extract_frames(video_path, output_folder): # image_files = glob.glob(image_folder + "/*.jpeg") image_files = [] try: - with open(f"{output_folder}/good_images_list.txt", "r") as file: + with open(f"{output_folder}{os.path.sep}good_images_list.txt", "r") as file: lines = file.readlines() except FileNotFoundError: print("No good images found! Press enter to exit..") @@ -182,7 +182,7 @@ def extract_frames(video_path, output_folder): exit() else: for line in lines: - image_file = f"{image_folder}/{line.strip()}" + image_file = f"{image_folder}{os.path.sep}{line.strip()}" if len(image_file) < len(image_folder): continue else: