Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions .github/workflows/lint-and-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ env:
GITHUB_HEAD_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }}
GITHUB_EXCLUDE_BUILD_NUMBER: ${{ inputs.excludeBuildNumber }}
UV_NO_SYNC: true # Avoid accidentally pulling in dependency-groups with uv run
# https://github.com/opencv/opencv-python#source-distributions
# Allows building OpenCV on Windows ARM64
# https://github.com/opencv/opencv-python/issues/1092#issuecomment-2862538656
CMAKE_ARGS: "-DBUILD_opencv_dnn=OFF -DENABLE_NEON=OFF"
Comment on lines +34 to +37
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
Expand Down Expand Up @@ -75,14 +79,13 @@ jobs:
fail-fast: false
# Only the Python version we plan on shipping matters.
matrix:
# 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]
os: [windows-latest, windows-11-arm, ubuntu-22.04, ubuntu-22.04-arm]
python-version: ["3.13"]
steps:
- uses: actions/checkout@v4
# region pyinstaller/pyinstaller#9012 + astral-sh/uv#12906
- name: Set up Python for PyInstaller tk and ARM64 issue
if: ${{ startsWith(matrix.os, 'ubuntu') }}
if: matrix.os != 'windows-latest'
uses: actions/setup-python@v5
with:
allow-prereleases: true
Expand All @@ -91,7 +94,7 @@ jobs:
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
python-version: ${{ !startsWith(matrix.os, 'ubuntu') && matrix.python-version || null }}
python-version: ${{ matrix.os == 'windows-latest' && matrix.python-version || null }}
# endregion
- run: scripts/install.ps1
shell: pwsh
Expand All @@ -100,26 +103,27 @@ jobs:
- name: Add empty profile
run: echo "" > dist/settings.toml
- name: Extract AutoSplit version
id: autosplit_version
id: artifact_vars
working-directory: src
run: |
run: | # This also serves as a sanity check for imports
$Env:AUTOSPLIT_VERSION=uv run python -c "import utils; print(utils.AUTOSPLIT_VERSION)"
echo "AUTOSPLIT_VERSION=$Env:AUTOSPLIT_VERSION" >> $Env:GITHUB_OUTPUT
echo "OS=$([System.Runtime.InteropServices.RuntimeInformation]::RuntimeIdentifier)" >> $Env:GITHUB_OUTPUT
shell: pwsh
- name: Upload Build Artifact
uses: actions/upload-artifact@v4
with:
name: >
AutoSplit v${{ steps.autosplit_version.outputs.AUTOSPLIT_VERSION }}
for ${{ matrix.os }} (Python ${{ matrix.python-version }})
AutoSplit v${{ steps.artifact_vars.outputs.AUTOSPLIT_VERSION }}
for ${{ steps.artifact_vars.outputs.OS }} (Python ${{ matrix.python-version }})
path: |
dist/AutoSplit*
dist/settings.toml
if-no-files-found: error
- name: Upload Build logs
uses: actions/upload-artifact@v4
with:
name: Build logs for ${{ matrix.os }} (Python ${{ matrix.python-version }})
name: Build logs for ${{ steps.artifact_vars.outputs.OS }} (Python ${{ matrix.python-version }})
path: |
build/AutoSplit/*.toc
build/AutoSplit/*.txt
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ To understand how to use AutoSplit and how it works in-depth, please read the [t

### Compatibility

- Windows 10 and 11. (x64 only)
- Windows 10 and 11.
- Linux (still in early development)
- 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
- x64 and ARM64 architectures \* (see [Known Limitations](#known-limitations) for ARM64)
- If you'd like to run the project directly in Python from the source code, refer to the [build instructions](/docs/build%20instructions.md).

## Timer Integration
Expand All @@ -75,6 +75,7 @@ See the [installation instructions](https://github.com/Toufool/LiveSplit.AutoSpl
- Incompatible with LiveSplitOne on Linux (see <https://github.com/LiveSplit/LiveSplitOne/issues/1025>)
- Antivirus false positives. Please read <https://github.com/pyinstaller/pyinstaller/blob/develop/.github/ISSUE_TEMPLATE/antivirus.md>
- 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)
- Native ARM64 builds go completely untested. There may be unforseen issues.

## Resources

Expand Down
25 changes: 13 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ dependencies = [
# 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
"opencv-contrib-python-headless; platform_machine == 'ARM64' or platform_machine == 'aarch64'",
"opencv-python-headless; platform_machine != 'ARM64' and platform_machine != 'aarch64'",
"scipy >=1.14.1; platform_machine != 'ARM64' and platform_machine != 'aarch64'", # Python 3.13 support

#
# Build and compile resources
Expand All @@ -32,14 +32,16 @@ dependencies = [
"pygrabber >=0.2; sys_platform == 'win32'", # Completed types
"pywin32 >=307; sys_platform == 'win32'", # Python 3.13 support
"typed-D3DShot[numpy] >=1.0.1; sys_platform == 'win32'",
"winrt-Windows.Foundation >=2.2.0; sys_platform == 'win32'", # Python 3.13 support
"winrt-Windows.Graphics >=2.2.0; sys_platform == 'win32'", # Python 3.13 support
"winrt-Windows.Graphics.Capture >=3.0.0; sys_platform == 'win32'", # Type hints are no longer typing.Optional by default.
"winrt-Windows.Graphics.Capture.Interop >=2.3.0; sys_platform == 'win32'", # Python 3.13 support
"winrt-Windows.Graphics.DirectX >=2.3.0; sys_platform == 'win32'", # Python 3.13 support
"winrt-Windows.Graphics.DirectX.Direct3D11 >=2.3.0; sys_platform == 'win32'", # Python 3.13 support
"winrt-Windows.Graphics.DirectX.Direct3D11.Interop >=2.3.0; sys_platform == 'win32'",
"winrt-Windows.Graphics.Imaging >=2.3.0; sys_platform == 'win32'", # Python 3.13 support
# winrt: winrt-runtime didn't have a working Python 3.14 sdist build until 3.2.0
# TODO: Bump when 3.14 wheels are released
"winrt-Windows.Foundation >=3.2.0; sys_platform == 'win32'",
"winrt-Windows.Graphics >=3.2.0; sys_platform == 'win32'",
"winrt-Windows.Graphics.Capture >=3.2.0; sys_platform == 'win32'",
"winrt-Windows.Graphics.Capture.Interop >=3.2.0; sys_platform == 'win32'",
"winrt-Windows.Graphics.DirectX >=3.2.0; sys_platform == 'win32'",
"winrt-Windows.Graphics.DirectX.Direct3D11 >=3.2.0; sys_platform == 'win32'",
"winrt-Windows.Graphics.DirectX.Direct3D11.Interop >=3.2.0; sys_platform == 'win32'",
"winrt-Windows.Graphics.Imaging >=3.2.0; sys_platform == 'win32'",
#
# Linux-only dependencies
"PyScreeze >=1.0.0; sys_platform == 'linux'",
Expand All @@ -59,7 +61,6 @@ dev = [
"ruff >=0.11.13",
#
# Types
"opencv-contrib-python-headless",
"scipy-stubs >=1.14.1.1",
"types-PyAutoGUI",
"types-PyScreeze; sys_platform == 'linux'",
Expand Down
32 changes: 17 additions & 15 deletions src/compare.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from collections.abc import Iterable
from math import sqrt
from typing import TYPE_CHECKING

import cv2
import Levenshtein
Expand Down Expand Up @@ -102,27 +103,28 @@ def __cv2_scipy_compute_phash(image: MatLike, hash_size: int, highfreq_factor: i
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]
def __cv2_phash(source: MatLike, capture: MatLike, hash_size: int = 8):
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)
if not TYPE_CHECKING: # opencv-contrib-python-headless being installed is based on architecture

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):
Expand Down
Loading