├── python ├── README.md ├── .python-version ├── requirements.txt ├── constants.py ├── pyproject.toml ├── greeting.py ├── camera_stream.py ├── .gitignore └── uv.lock ├── godot ├── greeting │ ├── greeting.gd.uid │ ├── greeting.tscn │ └── greeting.gd ├── .gitignore ├── camera_stream │ ├── camera_stream.gd.uid │ ├── camera_stream.gd │ └── camera_stream.tscn ├── .gitattributes ├── project.godot ├── icon.svg └── icon.svg.import ├── LICENSE └── README.md /python/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /python/.python-version: -------------------------------------------------------------------------------- 1 | 3.13 2 | -------------------------------------------------------------------------------- /python/requirements.txt: -------------------------------------------------------------------------------- 1 | opencv-python -------------------------------------------------------------------------------- /godot/greeting/greeting.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cno7gcmvkymld 2 | -------------------------------------------------------------------------------- /godot/.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | -------------------------------------------------------------------------------- /godot/camera_stream/camera_stream.gd.uid: -------------------------------------------------------------------------------- 1 | uid://tti6b7mc8te4 2 | -------------------------------------------------------------------------------- /python/constants.py: -------------------------------------------------------------------------------- 1 | SERVER_IP = "127.0.0.1" 2 | SERVER_PORT = 4242 -------------------------------------------------------------------------------- /godot/.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize EOL for all files that Git considers text files. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "python" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.13" 7 | dependencies = [ 8 | "opencv-python>=4.11.0.86", 9 | ] 10 | -------------------------------------------------------------------------------- /godot/greeting/greeting.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dy5ffdxj6t1tg"] 2 | 3 | [ext_resource type="Script" uid="uid://cno7gcmvkymld" path="res://greeting/greeting.gd" id="1_avgf3"] 4 | 5 | [node name="Greeting" type="Node"] 6 | 7 | [node name="UDPServer" type="Node" parent="."] 8 | script = ExtResource("1_avgf3") 9 | -------------------------------------------------------------------------------- /python/greeting.py: -------------------------------------------------------------------------------- 1 | import socket 2 | from constants import SERVER_IP, SERVER_PORT 3 | 4 | client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 5 | client_socket.settimeout(1) 6 | 7 | client_socket.sendto("Hello from Python!".encode(), (SERVER_IP, SERVER_PORT)) 8 | 9 | data, (recv_ip, recv_port) = client_socket.recvfrom(1024) 10 | print(f"Received: '{data.decode()}' {recv_ip}:{recv_port}") 11 | -------------------------------------------------------------------------------- /godot/greeting/greeting.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | var server: UDPServer 4 | 5 | func _ready() -> void: 6 | server = UDPServer.new() 7 | server.listen(4242) 8 | 9 | func _process(_delta: float) -> void: 10 | server.poll() 11 | if server.is_connection_available(): 12 | var peer: PacketPeerUDP = server.take_connection() 13 | var packet = peer.get_packet() 14 | print("Received: '%s' %s:%s" % [packet.get_string_from_utf8(), peer.get_packet_ip(), peer.get_packet_port()]) 15 | 16 | peer.put_packet("Hello from Godot!".to_utf8_buffer()) 17 | -------------------------------------------------------------------------------- /godot/camera_stream/camera_stream.gd: -------------------------------------------------------------------------------- 1 | extends TextureRect 2 | 3 | var server: UDPServer 4 | 5 | func _ready() -> void: 6 | server = UDPServer.new() 7 | server.listen(4242) 8 | 9 | func _decode_image(frame_data: PackedByteArray) -> Image: 10 | var image = Image.new() 11 | image.load_jpg_from_buffer(frame_data) 12 | return image 13 | 14 | func _process(_delta: float) -> void: 15 | server.poll() 16 | if server.is_connection_available(): 17 | var peer = server.take_connection() 18 | var frame_data = peer.get_packet() 19 | var image = _decode_image(frame_data) 20 | texture = ImageTexture.create_from_image(image) 21 | -------------------------------------------------------------------------------- /godot/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="GodotPythonComm" 14 | run/main_scene="res://camera_stream/camera_stream.tscn" 15 | config/features=PackedStringArray("4.4", "GL Compatibility") 16 | config/icon="res://icon.svg" 17 | 18 | [rendering] 19 | 20 | renderer/rendering_method="gl_compatibility" 21 | renderer/rendering_method.mobile="gl_compatibility" 22 | -------------------------------------------------------------------------------- /godot/camera_stream/camera_stream.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dkjodo2hi5yqp"] 2 | 3 | [ext_resource type="Script" uid="uid://tti6b7mc8te4" path="res://camera_stream/camera_stream.gd" id="1_j600m"] 4 | 5 | [node name="CameraStream" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 15 8 | anchor_right = 1.0 9 | anchor_bottom = 1.0 10 | grow_horizontal = 2 11 | grow_vertical = 2 12 | 13 | [node name="CameraStreamTexture" type="TextureRect" parent="."] 14 | layout_mode = 1 15 | anchors_preset = 15 16 | anchor_right = 1.0 17 | anchor_bottom = 1.0 18 | grow_horizontal = 2 19 | grow_vertical = 2 20 | stretch_mode = 5 21 | script = ExtResource("1_j600m") 22 | -------------------------------------------------------------------------------- /godot/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /godot/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://d06ptjlsk2xey" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Florian Trautweiler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Godot + Python Communication with UDP 2 | 3 | This project is a simple demonstration of how a python application can communicate with a Godot game using UDP. This communication channel can for example be used to send encoded image frames from a webcam. 4 | 5 | ![camera_stream_demo_processing](https://github.com/trflorian/godot-python-comm/assets/27728267/62de3c6c-f9a2-4986-9114-9abb37b6a4c8) 6 | 7 | ## ⚡ Quickstart 8 | 9 | ### Greeting 10 | 1. Open the Godot project in the `godot/` directory and run the game scene `greeting/greeting.tscn`. 11 | 2. Run the `greeting.py` script in `python/`. 12 | 13 | ### Camera Stream 14 | 1. Open the Godot project in the `godot/` directory and run the game scene `camera_stream/camera_stream.tscn`. 15 | 2. Install the python requirements for in the `python/` directory by running `pip install -r requirements.txt` from that directory or using `uv sync`. 16 | 3. From the same folder you can then run the `camera_stream.py` script. 17 | 18 | ## Greeting Demo 19 | 20 | ![image](https://github.com/trflorian/godot-python-comm/assets/27728267/ee1576fe-00e3-4d16-b8e4-39df8ae911ad) 21 | ![image](https://github.com/trflorian/godot-python-comm/assets/27728267/6557e6e0-6f8a-4df4-9a1e-36d55d4efa4a) 22 | 23 | 24 | ## 🗞️ Guide 25 | 26 | ### Greeting 27 | https://medium.com/@flip.flo.games/godot-python-3e3f98860e2f 28 | 29 | ### Camera Stream 30 | https://medium.com/@flip.flo.games/godot-python-camera-stream-1866cfb9941f 31 | 32 | ## 🖥️ Versions 33 | - Godot 4.4.1 34 | - Python 3.13 35 | -------------------------------------------------------------------------------- /python/camera_stream.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import cv2 3 | from constants import SERVER_IP, SERVER_PORT 4 | 5 | client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 6 | 7 | cap = cv2.VideoCapture(0) 8 | 9 | while True: 10 | ret, frame = cap.read() 11 | 12 | if not ret: 13 | print("Error: failed to capture image") 14 | break 15 | 16 | frame = cv2.resize(frame, (400, 300)) 17 | frame = cv2.flip(frame, 1) 18 | 19 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 20 | gray = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) 21 | 22 | blur = cv2.GaussianBlur(gray, (5, 5), 0) 23 | 24 | canny = cv2.Canny(blur, 20, 50) 25 | canny = cv2.cvtColor(canny, cv2.COLOR_GRAY2BGR) 26 | 27 | cv2.putText( 28 | frame, 29 | f"OpenCV version: {cv2.__version__}", 30 | (5, 15), 31 | cv2.FONT_HERSHEY_SIMPLEX, 32 | 0.5, 33 | (255, 255, 255), 34 | 1, 35 | ) 36 | 37 | row1 = cv2.hconcat([frame, gray]) 38 | row2 = cv2.hconcat([blur, canny]) 39 | image = cv2.vconcat([row1, row2]) 40 | 41 | image = cv2.resize(image, (400, 300)) 42 | 43 | _, encoded_image = cv2.imencode(".jpg", image) 44 | 45 | if len(encoded_image) <= 65507: 46 | client_socket.sendto(encoded_image, (SERVER_IP, SERVER_PORT)) 47 | else: 48 | print("Frame too large, skipping") 49 | 50 | cv2.imshow("Image", image) 51 | 52 | if cv2.waitKey(1) & 0xFF == ord("q"): 53 | break 54 | 55 | cv2.destroyAllWindows() 56 | 57 | cap.release() 58 | -------------------------------------------------------------------------------- /python/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 110 | .pdm.toml 111 | .pdm-python 112 | .pdm-build/ 113 | 114 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 115 | __pypackages__/ 116 | 117 | # Celery stuff 118 | celerybeat-schedule 119 | celerybeat.pid 120 | 121 | # SageMath parsed files 122 | *.sage.py 123 | 124 | # Environments 125 | .env 126 | .venv 127 | env/ 128 | venv/ 129 | ENV/ 130 | env.bak/ 131 | venv.bak/ 132 | 133 | # Spyder project settings 134 | .spyderproject 135 | .spyproject 136 | 137 | # Rope project settings 138 | .ropeproject 139 | 140 | # mkdocs documentation 141 | /site 142 | 143 | # mypy 144 | .mypy_cache/ 145 | .dmypy.json 146 | dmypy.json 147 | 148 | # Pyre type checker 149 | .pyre/ 150 | 151 | # pytype static type analyzer 152 | .pytype/ 153 | 154 | # Cython debug symbols 155 | cython_debug/ 156 | 157 | # PyCharm 158 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 159 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 160 | # and can be added to the global gitignore or merged into this file. For a more nuclear 161 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 162 | #.idea/ -------------------------------------------------------------------------------- /python/uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 2 3 | requires-python = ">=3.13" 4 | resolution-markers = [ 5 | "sys_platform == 'darwin'", 6 | "platform_machine == 'aarch64' and sys_platform == 'linux'", 7 | "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')", 8 | ] 9 | 10 | [[package]] 11 | name = "numpy" 12 | version = "2.2.6" 13 | source = { registry = "https://pypi.org/simple" } 14 | sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" } 15 | wheels = [ 16 | { url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" }, 17 | { url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" }, 18 | { url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" }, 19 | { url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" }, 20 | { url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" }, 21 | { url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" }, 22 | { url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" }, 23 | { url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" }, 24 | { url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" }, 25 | { url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" }, 26 | { url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" }, 27 | { url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" }, 28 | { url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" }, 29 | { url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" }, 30 | { url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" }, 31 | { url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" }, 32 | { url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" }, 33 | { url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" }, 34 | { url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" }, 35 | { url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" }, 36 | ] 37 | 38 | [[package]] 39 | name = "opencv-python" 40 | version = "4.11.0.86" 41 | source = { registry = "https://pypi.org/simple" } 42 | dependencies = [ 43 | { name = "numpy" }, 44 | ] 45 | sdist = { url = "https://files.pythonhosted.org/packages/17/06/68c27a523103dad5837dc5b87e71285280c4f098c60e4fe8a8db6486ab09/opencv-python-4.11.0.86.tar.gz", hash = "sha256:03d60ccae62304860d232272e4a4fda93c39d595780cb40b161b310244b736a4", size = 95171956, upload-time = "2025-01-16T13:52:24.737Z" } 46 | wheels = [ 47 | { url = "https://files.pythonhosted.org/packages/05/4d/53b30a2a3ac1f75f65a59eb29cf2ee7207ce64867db47036ad61743d5a23/opencv_python-4.11.0.86-cp37-abi3-macosx_13_0_arm64.whl", hash = "sha256:432f67c223f1dc2824f5e73cdfcd9db0efc8710647d4e813012195dc9122a52a", size = 37326322, upload-time = "2025-01-16T13:52:25.887Z" }, 48 | { url = "https://files.pythonhosted.org/packages/3b/84/0a67490741867eacdfa37bc18df96e08a9d579583b419010d7f3da8ff503/opencv_python-4.11.0.86-cp37-abi3-macosx_13_0_x86_64.whl", hash = "sha256:9d05ef13d23fe97f575153558653e2d6e87103995d54e6a35db3f282fe1f9c66", size = 56723197, upload-time = "2025-01-16T13:55:21.222Z" }, 49 | { url = "https://files.pythonhosted.org/packages/f3/bd/29c126788da65c1fb2b5fb621b7fed0ed5f9122aa22a0868c5e2c15c6d23/opencv_python-4.11.0.86-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b92ae2c8852208817e6776ba1ea0d6b1e0a1b5431e971a2a0ddd2a8cc398202", size = 42230439, upload-time = "2025-01-16T13:51:35.822Z" }, 50 | { url = "https://files.pythonhosted.org/packages/2c/8b/90eb44a40476fa0e71e05a0283947cfd74a5d36121a11d926ad6f3193cc4/opencv_python-4.11.0.86-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b02611523803495003bd87362db3e1d2a0454a6a63025dc6658a9830570aa0d", size = 62986597, upload-time = "2025-01-16T13:52:08.836Z" }, 51 | { url = "https://files.pythonhosted.org/packages/fb/d7/1d5941a9dde095468b288d989ff6539dd69cd429dbf1b9e839013d21b6f0/opencv_python-4.11.0.86-cp37-abi3-win32.whl", hash = "sha256:810549cb2a4aedaa84ad9a1c92fbfdfc14090e2749cedf2c1589ad8359aa169b", size = 29384337, upload-time = "2025-01-16T13:52:13.549Z" }, 52 | { url = "https://files.pythonhosted.org/packages/a4/7d/f1c30a92854540bf789e9cd5dde7ef49bbe63f855b85a2e6b3db8135c591/opencv_python-4.11.0.86-cp37-abi3-win_amd64.whl", hash = "sha256:085ad9b77c18853ea66283e98affefe2de8cc4c1f43eda4c100cf9b2721142ec", size = 39488044, upload-time = "2025-01-16T13:52:21.928Z" }, 53 | ] 54 | 55 | [[package]] 56 | name = "python" 57 | version = "0.1.0" 58 | source = { virtual = "." } 59 | dependencies = [ 60 | { name = "opencv-python" }, 61 | ] 62 | 63 | [package.metadata] 64 | requires-dist = [{ name = "opencv-python", specifier = ">=4.11.0.86" }] 65 | --------------------------------------------------------------------------------