diff --git a/.github/ISSUE_TEMPLATE/bug-or-crash-report.md b/.github/ISSUE_TEMPLATE/bug-or-crash-report.md index 2768b096..e769f040 100644 --- a/.github/ISSUE_TEMPLATE/bug-or-crash-report.md +++ b/.github/ISSUE_TEMPLATE/bug-or-crash-report.md @@ -39,6 +39,7 @@ If AutoSplit showed an exception traceback, please paste it here: ### Version (please complete the following information) - OS: [e.g. Windows 10.0.19045] +- Architecture: [x64 or ARM64] - AutoSplit: [e.g. v2.0.0] ### AutoSplit Profile and Split Images diff --git a/.github/workflows/lint-and-build.yml b/.github/workflows/lint-and-build.yml index 428f8639..0c5eb7f5 100644 --- a/.github/workflows/lint-and-build.yml +++ b/.github/workflows/lint-and-build.yml @@ -75,12 +75,13 @@ jobs: fail-fast: false # Only the Python version we plan on shipping matters. matrix: - os: [windows-latest, ubuntu-22.04] + # OpenCV doesn't support windows-11-arm yet https://github.com/opencv/opencv-python/issues/806 + os: [windows-latest, ubuntu-22.04, ubuntu-22.04-arm] python-version: ["3.13"] steps: - uses: actions/checkout@v4 - # region https://github.com/pyinstaller/pyinstaller/issues/9012 - - name: Set up Python for PyInstaller tk issue + # region pyinstaller/pyinstaller#9012 + astral-sh/uv#12906 + - name: Set up Python for PyInstaller tk and ARM64 issue if: ${{ startsWith(matrix.os, 'ubuntu') }} uses: actions/setup-python@v5 with: diff --git a/README.md b/README.md index 5cac6719..22e472dc 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,10 @@ To understand how to use AutoSplit and how it works in-depth, please read the [t ### Compatibility -- Windows 10 and 11. +- Windows 10 and 11. (x64 only) - Linux (still in early development) - - Should work on Ubuntu 20.04+ (Only tested on Ubuntu 22.04) + - Both x64 and ARM64 architectures \* (see [Known Limitations](#known-limitations) for ARM64) + - Should work on Ubuntu 22.04+ - Wayland is not currently supported - WSL2/WSLg requires an additional Desktop Environment, external X11 server, and/or systemd - If you'd like to run the project directly in Python from the source code, refer to the [build instructions](/docs/build%20instructions.md). @@ -73,6 +74,7 @@ See the [installation instructions](https://github.com/Toufool/LiveSplit.AutoSpl - Linux support is incomplete and we're [looking for contributors](../../issues?q=is%3Aissue+is%3Aopen+label%3A"help+wanted"+label%3ALinux+). - Incompatible with LiveSplitOne on Linux (see ) - Antivirus false positives. Please read +- The Perceptual Hash Comparison Method similarity may differ by 3.125% on ARM64. (this will be solved eventually, we have to use a fallback method for now) ## Resources diff --git a/pyproject.toml b/pyproject.toml index 654fbfc3..ca4b16b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,15 +8,19 @@ dependencies = [ "PyAutoGUI >=0.9.52", "PyWinCtl >=0.0.42", # py.typed "keyboard @ git+https://github.com/boppreh/keyboard.git", # Fix install on macos and linux-ci https://github.com/boppreh/keyboard/pull/568 - "numpy >=2.1", # Python 3.13 support - "opencv-python-headless >=4.10", # NumPy 2 support + "numpy >=2.3", # Windows ARM64 wheels "packaging >=20.0", # py.typed # When needed, dev builds can be found at https://download.qt.io/snapshots/ci/pyside/dev?C=M;O=D - "PySide6-Essentials <6.8.1", # Has typing issue with QMessageBox.warning https://bugreports.qt.io/browse/PYSIDE-2939 - # "PySide6-Essentials >=6.8.2", # Fixed typing issue with QMessageBox.warning - "scipy >=1.14.1", # Python 3.13 support + "PySide6-Essentials", # Let package resolution find the minimum for wheels (>=6.9.0 on Windows ARM64; <6.8.1 on ubuntu-22.04-arm (glibc 2.39)) "tomli-w >=1.1.0", # Typing fixes + # scipy is used for pHash calculation as a smaller, but still fast implementation. + # However, scipy is not available on all environments yet. + # In those cases, we're falling back to opencv-contrib-python's cv2.img_hash + "opencv-contrib-python-headless >=4.10; platform_machine == 'aarch64'", # NumPy 2 support + "opencv-python-headless >=4.10; platform_machine != 'aarch64'", # NumPy 2 support + "scipy >=1.14.1; platform_machine != 'aarch64'", # Python 3.13 support + # # Build and compile resources "pyinstaller >=6.14.0", # Mitigate issues with pkg_resources deprecation warning @@ -55,6 +59,7 @@ dev = [ "ruff >=0.11.13", # # Types + "opencv-contrib-python-headless", "scipy-stubs >=1.14.1.1", "types-PyAutoGUI", "types-PyScreeze; sys_platform == 'linux'", diff --git a/src/compare.py b/src/compare.py index 52ef3bcd..feb581bf 100644 --- a/src/compare.py +++ b/src/compare.py @@ -5,7 +5,6 @@ import Levenshtein import numpy as np from cv2.typing import MatLike -from scipy import fft from utils import ( BGRA_CHANNEL_COUNT, @@ -90,27 +89,40 @@ def compare_template(source: MatLike, capture: MatLike, mask: MatLike | None = N return 1 - (min_val / max_error) -def __cv2_phash(image: MatLike, hash_size: int = 8, highfreq_factor: int = 4): - """Implementation copied from https://github.com/JohannesBuchner/imagehash/blob/38005924fe9be17cfed145bbc6d83b09ef8be025/imagehash/__init__.py#L260 .""" # noqa: E501 - # OpenCV has its own pHash comparison implementation in `cv2.img_hash`, - # but it requires contrib/extra modules and is inaccurate - # unless we precompute the size with a specific interpolation. - # See: https://github.com/opencv/opencv_contrib/issues/3295#issuecomment-1172878684 - # - # pHash = cv2.img_hash.PHash.create() - # source = cv2.resize(source, (8, 8), interpolation=cv2.INTER_AREA) - # capture = cv2.resize(capture, (8, 8), interpolation=cv2.INTER_AREA) - # source_hash = pHash.compute(source) - # capture_hash = pHash.compute(capture) - # hash_diff = pHash.compare(source_hash, capture_hash) - - img_size = hash_size * highfreq_factor - image = cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY) - image = cv2.resize(image, (img_size, img_size), interpolation=cv2.INTER_AREA) - dct = fft.dct(fft.dct(image, axis=0), axis=1) - dct_low_frequency = dct[:hash_size, :hash_size] - median = np.median(dct_low_frequency) - return dct_low_frequency > median +try: + from scipy import fft + + def __cv2_scipy_compute_phash(image: MatLike, hash_size: int, highfreq_factor: int = 4): + """Implementation copied from https://github.com/JohannesBuchner/imagehash/blob/38005924fe9be17cfed145bbc6d83b09ef8be025/imagehash/__init__.py#L260 .""" # noqa: E501 + img_size = hash_size * highfreq_factor + image = cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY) + image = cv2.resize(image, (img_size, img_size), interpolation=cv2.INTER_AREA) + dct = fft.dct(fft.dct(image, axis=0), axis=1) + dct_low_frequency = dct[:hash_size, :hash_size] + median = np.median(dct_low_frequency) + return dct_low_frequency > median + + def __cv2_phash(source: MatLike, capture: MatLike, hash_size: int = 8): # pyright: ignore[reportRedeclaration] + source_hash = __cv2_scipy_compute_phash(source, hash_size) + capture_hash = __cv2_scipy_compute_phash(capture, hash_size) + hash_diff = np.count_nonzero(source_hash != capture_hash) + return 1 - (hash_diff / 64.0) + +except ModuleNotFoundError: + + def __cv2_phash(source: MatLike, capture: MatLike, hash_size: int = 8): + # OpenCV has its own pHash comparison implementation in `cv2.img_hash`, + # but it requires contrib/extra modules and is inaccurate + # unless we precompute the size with a specific interpolation. + # See: https://github.com/opencv/opencv_contrib/issues/3295#issuecomment-1172878684 + # + phash = cv2.img_hash.PHash.create() + source = cv2.resize(source, (hash_size, hash_size), interpolation=cv2.INTER_AREA) + capture = cv2.resize(capture, (hash_size, hash_size), interpolation=cv2.INTER_AREA) + source_hash = phash.compute(source) + capture_hash = phash.compute(capture) + hash_diff = phash.compare(source_hash, capture_hash) + return 1 - (hash_diff / 64.0) def compare_phash(source: MatLike, capture: MatLike, mask: MatLike | None = None): @@ -130,11 +142,7 @@ def compare_phash(source: MatLike, capture: MatLike, mask: MatLike | None = None source = cv2.bitwise_and(source, source, mask=mask) capture = cv2.bitwise_and(capture, capture, mask=mask) - source_hash = __cv2_phash(source) - capture_hash = __cv2_phash(capture) - hash_diff = np.count_nonzero(source_hash != capture_hash) - - return 1 - (hash_diff / 64.0) + return __cv2_phash(source, capture) def extract_and_compare_text(capture: MatLike, texts: Iterable[str], methods_index: Iterable[int]): diff --git a/uv.lock b/uv.lock index bb5a782a..8280f505 100644 --- a/uv.lock +++ b/uv.lock @@ -36,18 +36,20 @@ dependencies = [ { name = "keyboard", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "levenshtein", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "numpy", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "opencv-python-headless", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "opencv-contrib-python-headless", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'aarch64' and sys_platform == 'win32')" }, + { name = "opencv-python-headless", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_machine != 'aarch64' and sys_platform == 'win32')" }, { name = "packaging", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "pillow", marker = "sys_platform == 'linux'" }, { name = "pyautogui", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "pygrabber", marker = "sys_platform == 'win32'" }, { name = "pyinstaller", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "pyscreeze", marker = "sys_platform == 'linux'" }, - { name = "pyside6-essentials", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pyside6-essentials", version = "6.8.0.2", source = { registry = "https://pypi.org/simple" }, marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" }, + { name = "pyside6-essentials", version = "6.9.1", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or sys_platform == 'win32'" }, { name = "python-xlib", marker = "sys_platform == 'linux'" }, { name = "pywin32", marker = "sys_platform == 'win32'" }, { name = "pywinctl", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "scipy", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "scipy", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_machine != 'aarch64' and sys_platform == 'win32')" }, { name = "tomli-w", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typed-d3dshot", extra = ["numpy"], marker = "sys_platform == 'win32'" }, { name = "winrt-windows-foundation", marker = "sys_platform == 'win32'" }, @@ -64,6 +66,7 @@ dependencies = [ dev = [ { name = "dprint-py", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "mypy", extra = ["faster-cache"], marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "opencv-contrib-python-headless", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "pyright", extra = ["nodejs"], marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "qt6-applications", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "ruff", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -80,19 +83,20 @@ dev = [ requires-dist = [ { name = "keyboard", git = "https://github.com/boppreh/keyboard.git" }, { name = "levenshtein", specifier = ">=0.25" }, - { name = "numpy", specifier = ">=2.1" }, - { name = "opencv-python-headless", specifier = ">=4.10" }, + { name = "numpy", specifier = ">=2.3" }, + { name = "opencv-contrib-python-headless", marker = "platform_machine == 'aarch64'", specifier = ">=4.10" }, + { name = "opencv-python-headless", marker = "platform_machine != 'aarch64'", specifier = ">=4.10" }, { name = "packaging", specifier = ">=20.0" }, { name = "pillow", marker = "sys_platform == 'linux'", specifier = ">=11.0" }, { name = "pyautogui", specifier = ">=0.9.52" }, { name = "pygrabber", marker = "sys_platform == 'win32'", specifier = ">=0.2" }, { name = "pyinstaller", specifier = ">=6.14.0" }, { name = "pyscreeze", marker = "sys_platform == 'linux'", specifier = ">=1.0.0" }, - { name = "pyside6-essentials", specifier = "<6.8.1" }, + { name = "pyside6-essentials" }, { name = "python-xlib", marker = "sys_platform == 'linux'", specifier = ">=0.33" }, { name = "pywin32", marker = "sys_platform == 'win32'", specifier = ">=307" }, { name = "pywinctl", specifier = ">=0.0.42" }, - { name = "scipy", specifier = ">=1.14.1" }, + { name = "scipy", marker = "platform_machine != 'aarch64'", specifier = ">=1.14.1" }, { name = "tomli-w", specifier = ">=1.1.0" }, { name = "typed-d3dshot", extras = ["numpy"], marker = "sys_platform == 'win32'", specifier = ">=1.0.1" }, { name = "winrt-windows-foundation", marker = "sys_platform == 'win32'", specifier = ">=2.2.0" }, @@ -109,6 +113,7 @@ requires-dist = [ dev = [ { name = "dprint-py", specifier = ">=0.50.0.0" }, { name = "mypy", extras = ["faster-cache"], specifier = ">=1.16" }, + { name = "opencv-contrib-python-headless" }, { name = "pyright", extras = ["nodejs"], specifier = ">=1.1.400" }, { name = "qt6-applications", specifier = ">=6.5.0" }, { name = "ruff", specifier = ">=0.11.13" }, @@ -238,31 +243,48 @@ wheels = [ [[package]] name = "numpy" -version = "2.2.4" +version = "2.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e1/78/31103410a57bc2c2b93a3597340a8119588571f6a4539067546cb9a0bfac/numpy-2.2.4.tar.gz", hash = "sha256:9ba03692a45d3eef66559efe1d1096c4b9b75c0986b5dff5530c378fb8331d4f", size = 20270701, upload-time = "2025-03-16T18:27:00.648Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/db/8e12381333aea300890829a0a36bfa738cac95475d88982d538725143fd9/numpy-2.3.0.tar.gz", hash = "sha256:581f87f9e9e9db2cba2141400e160e9dd644ee248788d6f90636eeb8fd9260a6", size = 20382813, upload-time = "2025-06-07T14:54:32.608Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/73/41b7b27f169ecf368b52533edb72e56a133f9e86256e809e169362553b49/numpy-2.2.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f527d8fdb0286fd2fd97a2a96c6be17ba4232da346931d967a0630050dfd298", size = 14081422, upload-time = "2025-03-16T18:14:54.83Z" }, - { url = "https://files.pythonhosted.org/packages/4b/04/e208ff3ae3ddfbafc05910f89546382f15a3f10186b1f56bd99f159689c2/numpy-2.2.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bce43e386c16898b91e162e5baaad90c4b06f9dcbe36282490032cec98dc8ae7", size = 16132202, upload-time = "2025-03-16T18:15:22.035Z" }, - { url = "https://files.pythonhosted.org/packages/fe/bc/2218160574d862d5e55f803d88ddcad88beff94791f9c5f86d67bd8fbf1c/numpy-2.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31504f970f563d99f71a3512d0c01a645b692b12a63630d6aafa0939e52361e6", size = 15573131, upload-time = "2025-03-16T18:15:48.546Z" }, - { url = "https://files.pythonhosted.org/packages/a5/78/97c775bc4f05abc8a8426436b7cb1be806a02a2994b195945600855e3a25/numpy-2.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:81413336ef121a6ba746892fad881a83351ee3e1e4011f52e97fba79233611fd", size = 17894270, upload-time = "2025-03-16T18:16:20.274Z" }, - { url = "https://files.pythonhosted.org/packages/b9/eb/38c06217a5f6de27dcb41524ca95a44e395e6a1decdc0c99fec0832ce6ae/numpy-2.2.4-cp313-cp313-win32.whl", hash = "sha256:f486038e44caa08dbd97275a9a35a283a8f1d2f0ee60ac260a1790e76660833c", size = 6308141, upload-time = "2025-03-16T18:20:15.297Z" }, - { url = "https://files.pythonhosted.org/packages/52/17/d0dd10ab6d125c6d11ffb6dfa3423c3571befab8358d4f85cd4471964fcd/numpy-2.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:207a2b8441cc8b6a2a78c9ddc64d00d20c303d79fba08c577752f080c4007ee3", size = 12636885, upload-time = "2025-03-16T18:20:36.982Z" }, - { url = "https://files.pythonhosted.org/packages/41/78/96dddb75bb9be730b87c72f30ffdd62611aba234e4e460576a068c98eff6/numpy-2.2.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f05d4198c1bacc9124018109c5fba2f3201dbe7ab6e92ff100494f236209c960", size = 14051725, upload-time = "2025-03-16T18:18:11.904Z" }, - { url = "https://files.pythonhosted.org/packages/00/06/5306b8199bffac2a29d9119c11f457f6c7d41115a335b78d3f86fad4dbe8/numpy-2.2.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f085ce2e813a50dfd0e01fbfc0c12bbe5d2063d99f8b29da30e544fb6483b8", size = 16101638, upload-time = "2025-03-16T18:18:40.749Z" }, - { url = "https://files.pythonhosted.org/packages/fa/03/74c5b631ee1ded596945c12027649e6344614144369fd3ec1aaced782882/numpy-2.2.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:92bda934a791c01d6d9d8e038363c50918ef7c40601552a58ac84c9613a665bc", size = 15571717, upload-time = "2025-03-16T18:19:04.512Z" }, - { url = "https://files.pythonhosted.org/packages/cb/dc/4fc7c0283abe0981e3b89f9b332a134e237dd476b0c018e1e21083310c31/numpy-2.2.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ee4d528022f4c5ff67332469e10efe06a267e32f4067dc76bb7e2cddf3cd25ff", size = 17879998, upload-time = "2025-03-16T18:19:32.52Z" }, - { url = "https://files.pythonhosted.org/packages/e5/2b/878576190c5cfa29ed896b518cc516aecc7c98a919e20706c12480465f43/numpy-2.2.4-cp313-cp313t-win32.whl", hash = "sha256:05c076d531e9998e7e694c36e8b349969c56eadd2cdcd07242958489d79a7286", size = 6366896, upload-time = "2025-03-16T18:19:43.55Z" }, - { url = "https://files.pythonhosted.org/packages/3e/05/eb7eec66b95cf697f08c754ef26c3549d03ebd682819f794cb039574a0a6/numpy-2.2.4-cp313-cp313t-win_amd64.whl", hash = "sha256:188dcbca89834cc2e14eb2f106c96d6d46f200fe0200310fc29089657379c58d", size = 12739119, upload-time = "2025-03-16T18:20:03.94Z" }, + { url = "https://files.pythonhosted.org/packages/62/aa/fca4bf8de3396ddb59544df9b75ffe5b73096174de97a9492d426f5cd4aa/numpy-2.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:df470d376f54e052c76517393fa443758fefcdd634645bc9c1f84eafc67087f0", size = 14258658, upload-time = "2025-06-07T14:45:10.156Z" }, + { url = "https://files.pythonhosted.org/packages/1c/12/734dce1087eed1875f2297f687e671cfe53a091b6f2f55f0c7241aad041b/numpy-2.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:87717eb24d4a8a64683b7a4e91ace04e2f5c7c77872f823f02a94feee186168f", size = 16628765, upload-time = "2025-06-07T14:45:35.076Z" }, + { url = "https://files.pythonhosted.org/packages/48/03/ffa41ade0e825cbcd5606a5669962419528212a16082763fc051a7247d76/numpy-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fa264d56882b59dcb5ea4d6ab6f31d0c58a57b41aec605848b6eb2ef4a43e8", size = 15564335, upload-time = "2025-06-07T14:45:58.797Z" }, + { url = "https://files.pythonhosted.org/packages/07/58/869398a11863310aee0ff85a3e13b4c12f20d032b90c4b3ee93c3b728393/numpy-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e651756066a0eaf900916497e20e02fe1ae544187cb0fe88de981671ee7f6270", size = 18360608, upload-time = "2025-06-07T14:46:25.687Z" }, + { url = "https://files.pythonhosted.org/packages/2f/8a/5756935752ad278c17e8a061eb2127c9a3edf4ba2c31779548b336f23c8d/numpy-2.3.0-cp313-cp313-win32.whl", hash = "sha256:e43c3cce3b6ae5f94696669ff2a6eafd9a6b9332008bafa4117af70f4b88be6f", size = 6310005, upload-time = "2025-06-07T14:50:13.138Z" }, + { url = "https://files.pythonhosted.org/packages/08/60/61d60cf0dfc0bf15381eaef46366ebc0c1a787856d1db0c80b006092af84/numpy-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:81ae0bf2564cf475f94be4a27ef7bcf8af0c3e28da46770fc904da9abd5279b5", size = 12729093, upload-time = "2025-06-07T14:50:31.82Z" }, + { url = "https://files.pythonhosted.org/packages/66/31/2f2f2d2b3e3c32d5753d01437240feaa32220b73258c9eef2e42a0832866/numpy-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:c8738baa52505fa6e82778580b23f945e3578412554d937093eac9205e845e6e", size = 9885689, upload-time = "2025-06-07T14:50:47.888Z" }, + { url = "https://files.pythonhosted.org/packages/84/89/f76f93b06a03177c0faa7ca94d0856c4e5c4bcaf3c5f77640c9ed0303e1c/numpy-2.3.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:8b51ead2b258284458e570942137155978583e407babc22e3d0ed7af33ce06f8", size = 14330701, upload-time = "2025-06-07T14:47:59.113Z" }, + { url = "https://files.pythonhosted.org/packages/aa/f5/4858c3e9ff7a7d64561b20580cf7cc5d085794bd465a19604945d6501f6c/numpy-2.3.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:aaf81c7b82c73bd9b45e79cfb9476cb9c29e937494bfe9092c26aece812818ad", size = 16692983, upload-time = "2025-06-07T14:48:24.196Z" }, + { url = "https://files.pythonhosted.org/packages/08/17/0e3b4182e691a10e9483bcc62b4bb8693dbf9ea5dc9ba0b77a60435074bb/numpy-2.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f420033a20b4f6a2a11f585f93c843ac40686a7c3fa514060a97d9de93e5e72b", size = 15641435, upload-time = "2025-06-07T14:48:47.712Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d5/463279fda028d3c1efa74e7e8d507605ae87f33dbd0543cf4c4527c8b882/numpy-2.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d344ca32ab482bcf8735d8f95091ad081f97120546f3d250240868430ce52555", size = 18433798, upload-time = "2025-06-07T14:49:14.866Z" }, + { url = "https://files.pythonhosted.org/packages/0e/1e/7a9d98c886d4c39a2b4d3a7c026bffcf8fbcaf518782132d12a301cfc47a/numpy-2.3.0-cp313-cp313t-win32.whl", hash = "sha256:48a2e8eaf76364c32a1feaa60d6925eaf32ed7a040183b807e02674305beef61", size = 6438632, upload-time = "2025-06-07T14:49:25.67Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ab/66fc909931d5eb230107d016861824f335ae2c0533f422e654e5ff556784/numpy-2.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ba17f93a94e503551f154de210e4d50c5e3ee20f7e7a1b5f6ce3f22d419b93bb", size = 12868491, upload-time = "2025-06-07T14:49:44.898Z" }, + { url = "https://files.pythonhosted.org/packages/ee/e8/2c8a1c9e34d6f6d600c83d5ce5b71646c32a13f34ca5c518cc060639841c/numpy-2.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f14e016d9409680959691c109be98c436c6249eaf7f118b424679793607b5944", size = 9935345, upload-time = "2025-06-07T14:50:02.311Z" }, ] [[package]] -name = "opencv-python-headless" +name = "opencv-contrib-python-headless" version = "4.11.0.86" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/53/cc/295e9a4e783ca71ba1b8fbd34e51bc603eba4611afcfc7de1b09b2d6ed8d/opencv-contrib-python-headless-4.11.0.86.tar.gz", hash = "sha256:839319098a73264c580c97cb1ca835f7fce3d30e4fa9fa6d4d0618fff551be0b", size = 150579288, upload-time = "2025-01-16T13:54:11.763Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/ec/b3fb322e8bac7b797f98676c34599827920b3972e4d664bbdf8de84d7fca/opencv_contrib_python_headless-4.11.0.86-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8dc2f4109904ffa55967bf9ceb1521ce46d66c333e2f6261dfa1f957a1dbde0", size = 35122073, upload-time = "2025-01-16T13:52:07.72Z" }, + { url = "https://files.pythonhosted.org/packages/7a/80/26c4ad9459498fc9213dea7254c8d6cb7717b279306b070588a2781559d4/opencv_contrib_python_headless-4.11.0.86-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e7a86bf02e8157a2d9fce26d44eaafd31113fc21fc8b4f44ff56c28ab32fdba", size = 56078660, upload-time = "2025-01-16T13:53:56.436Z" }, + { url = "https://files.pythonhosted.org/packages/c0/38/2ce4259eca6ca356e3757b596d7d583b4ab0be4a482c9f4dacaa3eb688d1/opencv_contrib_python_headless-4.11.0.86-cp37-abi3-win32.whl", hash = "sha256:d2c10564c01f6c308ded345a3b37359714e694361e593e515c148465eda09c2a", size = 35092082, upload-time = "2025-01-16T13:53:06.296Z" }, + { url = "https://files.pythonhosted.org/packages/49/c1/c7600136283a2d4d3327968bdd895ba917a033d5a5498b6c7ffcd78c772c/opencv_contrib_python_headless-4.11.0.86-cp37-abi3-win_amd64.whl", hash = "sha256:2671a828e5c8ec9d237dd8506a9e0268487d37e07625725f1a6de5fa973ea7fa", size = 46095689, upload-time = "2025-01-16T13:53:12.934Z" }, +] + +[[package]] +name = "opencv-python-headless" +version = "4.11.0.86" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or sys_platform == 'win32'" }, +] sdist = { url = "https://files.pythonhosted.org/packages/36/2f/5b2b3ba52c864848885ba988f24b7f105052f68da9ab0e693cc7c25b0b30/opencv-python-headless-4.11.0.86.tar.gz", hash = "sha256:996eb282ca4b43ec6a3972414de0e2331f5d9cda2b41091a49739c19fb843798", size = 95177929, upload-time = "2025-01-16T13:53:40.22Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/45/be/1438ce43ebe65317344a87e4b150865c5585f4c0db880a34cdae5ac46881/opencv_python_headless-4.11.0.86-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6efabcaa9df731f29e5ea9051776715b1bdd1845d7c9530065c7951d2a2899eb", size = 29487060, upload-time = "2025-01-16T13:51:59.625Z" }, @@ -444,13 +466,32 @@ sdist = { url = "https://files.pythonhosted.org/packages/ee/f0/cb456ac4f1a73723d name = "pyside6-essentials" version = "6.8.0.2" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "platform_machine == 'aarch64' and sys_platform == 'linux'", +] dependencies = [ - { name = "shiboken6", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "shiboken6", version = "6.8.0.2", source = { registry = "https://pypi.org/simple" }, marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/34/72/6ef2f32e5ae5681cdd10cc7e627c453fcd389889fbc6a76d4e400a27af87/PySide6_Essentials-6.8.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7df6d6c1da4858dbdea77c74d7270d9c68e8d1bbe3362892abd1a5ade3815a50", size = 95184060, upload-time = "2024-10-24T12:07:42.215Z" }, { url = "https://files.pythonhosted.org/packages/6f/ee/9023d3851054db24c28312744de8bdb80dcf8de20bd583b6520da416484f/PySide6_Essentials-6.8.0.2-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:cf490145d18812a6cff48b0b0afb0bfaf7066744bfbd09eb071c3323f1d6d00d", size = 92322477, upload-time = "2024-10-24T12:07:53.078Z" }, - { url = "https://files.pythonhosted.org/packages/c7/24/57b5b10b4c641bf26e5fda3d71e2e14cbc796b334ef566b017d7b58c13cd/PySide6_Essentials-6.8.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:d2f029b8c9f0106f57b26aa8c435435d7f509c80525075343e07177b283f862e", size = 72518805, upload-time = "2024-10-24T12:08:03.274Z" }, +] + +[[package]] +name = "pyside6-essentials" +version = "6.9.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "platform_machine != 'aarch64' and sys_platform == 'linux'", + "sys_platform == 'win32'", +] +dependencies = [ + { name = "shiboken6", version = "6.9.1", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or sys_platform == 'win32'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/6a/ea0db68d40a1c487fd255634896f4e37b6560e3ef1f57ca5139bf6509b1f/PySide6_Essentials-6.9.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:e5da48883f006c6206ef85874db74ddebcdf69b0281bd4f1642b1c5ac1d54aea", size = 96416183, upload-time = "2025-06-03T13:12:48.945Z" }, + { url = "https://files.pythonhosted.org/packages/5b/2f/4243630d1733522638c4967d36018c38719d8b84f5246bf3d4c010e0aa9d/PySide6_Essentials-6.9.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:e46a2801c9c6098025515fd0af6c594b9e9c951842f68b8f6f3da9858b9b26c2", size = 94171343, upload-time = "2025-06-03T13:12:59.426Z" }, + { url = "https://files.pythonhosted.org/packages/0d/a9/a8e0209ba9116f2c2db990cfb79f2edbd5a3a428013be2df1f1cddd660a9/PySide6_Essentials-6.9.1-cp39-abi3-win_amd64.whl", hash = "sha256:ad1ac94011492dba33051bc33db1c76a7d6f815a81c01422cb6220273b369145", size = 72435676, upload-time = "2025-06-03T13:13:08.805Z" }, + { url = "https://files.pythonhosted.org/packages/d0/e4/23268c57e775a1a4d2843d288a9583a47f2e4b3977a9ae93cb9ded1a4ea5/PySide6_Essentials-6.9.1-cp39-abi3-win_arm64.whl", hash = "sha256:35c2c2bb4a88db74d11e638cf917524ff35785883f10b439ead07960a5733aa4", size = 49483707, upload-time = "2025-06-03T13:13:16.399Z" }, ] [[package]] @@ -572,7 +613,7 @@ name = "scipy" version = "1.15.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "numpy", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b7/b9/31ba9cd990e626574baf93fbc1ac61cf9ed54faafd04c479117517661637/scipy-1.15.2.tar.gz", hash = "sha256:cd58a314d92838f7e6f755c8a2167ead4f27e1fd5c1251fd54289569ef3495ec", size = 59417316, upload-time = "2025-02-17T00:42:24.791Z" } wheels = [ @@ -613,10 +654,26 @@ wheels = [ name = "shiboken6" version = "6.8.0.2" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "platform_machine == 'aarch64' and sys_platform == 'linux'", +] wheels = [ - { url = "https://files.pythonhosted.org/packages/42/73/6344e02a6734e17a86c5781df41293fa15245e4d7454992c1d82e77d49a9/shiboken6-6.8.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:fa7d411c3c67b4296847b3f5f572268e219d947d029ff9d8bce72fe6982d92bc", size = 200711, upload-time = "2024-10-24T12:06:54.725Z" }, { url = "https://files.pythonhosted.org/packages/13/cd/e9a6d0aa8794f777627a9fb3cffed0ac8449881b33e2325b5bcff10c36bc/shiboken6-6.8.0.2-cp39-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:1aaa8b7f9138818322ef029b2c487d1c6e00dc3f53084e62e1d11bdea47e47c2", size = 189864, upload-time = "2024-10-24T12:06:56.563Z" }, - { url = "https://files.pythonhosted.org/packages/46/1f/4323ee8fdca5c441b349cd5569934d53a1fd9e3695d53089e18e20ef3611/shiboken6-6.8.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:b11e750e696bb565d897e0f5836710edfb86bd355f87b09988bd31b2aad404d3", size = 1146649, upload-time = "2024-10-24T12:06:58.305Z" }, +] + +[[package]] +name = "shiboken6" +version = "6.9.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "platform_machine != 'aarch64' and sys_platform == 'linux'", + "sys_platform == 'win32'", +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/07/53b2532ecd42ff925feb06b7bb16917f5f99f9c3470f0815c256789d818b/shiboken6-6.9.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efcdfa8655d34aaf8d7a0c7724def3440bd46db02f5ad3b1785db5f6ccb0a8ff", size = 206756, upload-time = "2025-06-03T13:16:46.528Z" }, + { url = "https://files.pythonhosted.org/packages/5e/b0/75b86ee3f7b044e6a87fbe7abefd1948ca4ae5fcde8321f4986a1d9eaa5e/shiboken6-6.9.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:efcf75d48a29ae072d0bf54b3cd5a59ae91bb6b3ab7459e17c769355486c2e0b", size = 203233, upload-time = "2025-06-03T13:16:48.264Z" }, + { url = "https://files.pythonhosted.org/packages/30/56/00af281275aab4c79e22e0ea65feede0a5c6da3b84e86b21a4a0071e0744/shiboken6-6.9.1-cp39-abi3-win_amd64.whl", hash = "sha256:209ccf02c135bd70321143dcbc5023ae0c056aa4850a845955dd2f9b2ff280a9", size = 1153587, upload-time = "2025-06-03T13:16:50.454Z" }, + { url = "https://files.pythonhosted.org/packages/de/ce/6ccd382fbe1a96926c5514afa6f2c42da3a9a8482e61f8dfc6068a9ca64f/shiboken6-6.9.1-cp39-abi3-win_arm64.whl", hash = "sha256:2a39997ce275ced7853defc89d3a1f19a11c90991ac6eef3435a69bb0b7ff1de", size = 1831623, upload-time = "2025-06-03T13:16:52.468Z" }, ] [[package]]