hotgaze 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. hotgaze-0.1.0/.github/workflows/ci.yml +42 -0
  2. hotgaze-0.1.0/.github/workflows/nightly.yml +48 -0
  3. hotgaze-0.1.0/.github/workflows/release.yml +41 -0
  4. hotgaze-0.1.0/.gitignore +46 -0
  5. hotgaze-0.1.0/CHANGELOG.md +19 -0
  6. hotgaze-0.1.0/LICENSE +21 -0
  7. hotgaze-0.1.0/LICENSES-THIRD-PARTY.md +132 -0
  8. hotgaze-0.1.0/PKG-INFO +157 -0
  9. hotgaze-0.1.0/README.md +118 -0
  10. hotgaze-0.1.0/docs/demo.png +0 -0
  11. hotgaze-0.1.0/pyproject.toml +114 -0
  12. hotgaze-0.1.0/scripts/generate_fixtures.py +90 -0
  13. hotgaze-0.1.0/src/hotgaze/__init__.py +3 -0
  14. hotgaze-0.1.0/src/hotgaze/_imageops.py +91 -0
  15. hotgaze-0.1.0/src/hotgaze/_unisal/__init__.py +5 -0
  16. hotgaze-0.1.0/src/hotgaze/_unisal/_cgru.py +441 -0
  17. hotgaze-0.1.0/src/hotgaze/_unisal/_mobilenet.py +239 -0
  18. hotgaze-0.1.0/src/hotgaze/_unisal/_model.py +412 -0
  19. hotgaze-0.1.0/src/hotgaze/attention_map.py +98 -0
  20. hotgaze-0.1.0/src/hotgaze/cli.py +439 -0
  21. hotgaze-0.1.0/src/hotgaze/config.py +53 -0
  22. hotgaze-0.1.0/src/hotgaze/engine.py +197 -0
  23. hotgaze-0.1.0/src/hotgaze/layers/__init__.py +25 -0
  24. hotgaze-0.1.0/src/hotgaze/layers/base.py +31 -0
  25. hotgaze-0.1.0/src/hotgaze/layers/center_bias.py +47 -0
  26. hotgaze-0.1.0/src/hotgaze/layers/contrast.py +51 -0
  27. hotgaze-0.1.0/src/hotgaze/layers/faces.py +85 -0
  28. hotgaze-0.1.0/src/hotgaze/layers/gaze_flow.py +48 -0
  29. hotgaze-0.1.0/src/hotgaze/layers/saliency_deep.py +103 -0
  30. hotgaze-0.1.0/src/hotgaze/layers/saliency_fast.py +68 -0
  31. hotgaze-0.1.0/src/hotgaze/render.py +199 -0
  32. hotgaze-0.1.0/src/hotgaze/schemas/__init__.py +0 -0
  33. hotgaze-0.1.0/src/hotgaze/schemas/score.schema.json +162 -0
  34. hotgaze-0.1.0/src/hotgaze/scoring.py +444 -0
  35. hotgaze-0.1.0/src/hotgaze/weights.py +188 -0
  36. hotgaze-0.1.0/tests/__init__.py +0 -0
  37. hotgaze-0.1.0/tests/conftest.py +44 -0
  38. hotgaze-0.1.0/tests/test_cli.py +196 -0
  39. hotgaze-0.1.0/tests/test_compare.py +223 -0
  40. hotgaze-0.1.0/tests/test_deep.py +162 -0
  41. hotgaze-0.1.0/tests/test_engine.py +180 -0
  42. hotgaze-0.1.0/tests/test_integration.py +94 -0
  43. hotgaze-0.1.0/tests/test_layers.py +214 -0
  44. hotgaze-0.1.0/tests/test_optional.py +220 -0
  45. hotgaze-0.1.0/tests/test_perf.py +29 -0
  46. hotgaze-0.1.0/tests/test_scoring.py +288 -0
  47. hotgaze-0.1.0/tests/test_trivial.py +9 -0
  48. hotgaze-0.1.0/tests/test_weights.py +193 -0
@@ -0,0 +1,42 @@
1
+ # HotGaze CI
2
+
3
+ name: CI
4
+
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ pull_request:
9
+ branches: [main]
10
+
11
+ jobs:
12
+ test:
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ os: [ubuntu-latest, macos-latest]
17
+ python-version: ["3.10", "3.12"]
18
+ runs-on: ${{ matrix.os }}
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+
27
+ - name: Install package with dev deps
28
+ run: |
29
+ python3 -m pip install --upgrade pip
30
+ python3 -m pip install -e ".[dev]"
31
+
32
+ - name: Ruff lint
33
+ run: ruff check src/ tests/
34
+
35
+ - name: Ruff format check
36
+ run: ruff format --check src/ tests/
37
+
38
+ - name: Mypy type check
39
+ run: mypy src/
40
+
41
+ - name: Pytest (no perf, no deep)
42
+ run: pytest -m "not perf and not deep"
@@ -0,0 +1,48 @@
1
+ # HotGaze nightly — deep backend tests
2
+ #
3
+ # Runs pytest -m deep on a schedule. Because UNISAL weights are not yet
4
+ # published (see PROGRESS.md Orchestrator TODOs), deep tests skip with a
5
+ # reason — nightly is expected to be green-by-skip until weights are live.
6
+ # Once weights are published, this workflow will exercise the full deep
7
+ # pipeline nightly.
8
+ #
9
+ # Weight cache is persisted via actions/cache, keyed by the checksums
10
+ # recorded in LICENSES-THIRD-PARTY.md.
11
+
12
+ name: Nightly
13
+
14
+ on:
15
+ schedule:
16
+ - cron: "0 3 * * *" # 3 AM UTC daily
17
+ workflow_dispatch: # allow manual trigger
18
+
19
+ jobs:
20
+ deep:
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ os: [ubuntu-latest, macos-latest]
25
+ python-version: ["3.10", "3.12"]
26
+ runs-on: ${{ matrix.os }}
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+
30
+ - name: Set up Python ${{ matrix.python-version }}
31
+ uses: actions/setup-python@v5
32
+ with:
33
+ python-version: ${{ matrix.python-version }}
34
+
35
+ - name: Cache weight files
36
+ uses: actions/cache@v4
37
+ with:
38
+ path: ~/.cache/hotgaze
39
+ key: hotgaze-weights-${{ hashFiles('LICENSES-THIRD-PARTY.md') }}
40
+ restore-keys: hotgaze-weights-
41
+
42
+ - name: Install package with deep deps
43
+ run: |
44
+ python3 -m pip install --upgrade pip
45
+ python3 -m pip install -e ".[deep,dev]"
46
+
47
+ - name: Pytest deep
48
+ run: pytest -m deep -v
@@ -0,0 +1,41 @@
1
+ # HotGaze release pipeline
2
+ #
3
+ # On tag push (v*), builds sdist + wheel and publishes to PyPI via
4
+ # trusted publishing. No tokens or secrets needed — PyPI trusts this
5
+ # repo + workflow combination after one-time setup by the orchestrator.
6
+ #
7
+ # Prerequisites (orchestrator, do before first tag push):
8
+ # 1. Create the weights-v1 GitHub Release with 4 assets.
9
+ # 2. Configure PyPI trusted publishing:
10
+ # PyPI → Settings → Publishing → Add → repo: suryakosaraju/hotgaze,
11
+ # workflow: release.yml, environment: (leave blank).
12
+ # 3. Push a v* tag (e.g. v0.1.0).
13
+
14
+ name: Release
15
+
16
+ on:
17
+ push:
18
+ tags: ["v*"]
19
+
20
+ jobs:
21
+ build:
22
+ runs-on: ubuntu-latest
23
+ permissions:
24
+ id-token: write # required for trusted publishing
25
+ contents: read
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+
29
+ - name: Set up Python
30
+ uses: actions/setup-python@v5
31
+ with:
32
+ python-version: "3.10"
33
+
34
+ - name: Install build tools
35
+ run: python3 -m pip install --upgrade pip build
36
+
37
+ - name: Build sdist + wheel
38
+ run: python -m build
39
+
40
+ - name: Publish to PyPI
41
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,46 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ *.egg
8
+
9
+ # Virtual environments
10
+ .venv/
11
+ venv/
12
+ env/
13
+ .env
14
+
15
+ # IDE
16
+ .vscode/
17
+ .idea/
18
+ *.swp
19
+ *.swo
20
+ *~
21
+
22
+ # OS
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Coverage
27
+ htmlcov/
28
+ .coverage
29
+ coverage.xml
30
+
31
+ # HotGaze cache (local testing)
32
+ .hotgaze-cache/
33
+
34
+ # Test fixtures (generated on demand by conftest.py)
35
+ tests/fixtures/*.png
36
+
37
+ # Vendored-model backbone weights (downloaded on first use, never committed)
38
+ src/hotgaze/_unisal/weights/
39
+ *.pth.tar
40
+ CLAUDE.md
41
+ DESIGN.md
42
+ PLAN.md
43
+ PROGRESS.md
44
+ CONTRIBUTING.md
45
+ CONTRIBUTING.md
46
+ docs/devlog*.md
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to HotGaze will be documented in this file.
4
+
5
+ ## v0.1.0 (2026-07-16)
6
+
7
+ Initial release.
8
+
9
+ ### Features
10
+ - **Fast heuristic backend**: spectral-residual saliency + Sobel contrast + center-bias prior + F-pattern gaze flow. Zero downloads, fully offline, sub-second on CPU.
11
+ - **Deep saliency backend** (`--backend deep`): UNISAL pretrained model (Apache 2.0), CPU-only, deterministic per-machine. Requires `pip install hotgaze[deep]` and one-time weight download.
12
+ - **Region scoring**: `hotgaze score IMG --region name:x,y,w,h --json` → canonical JSON with attention share, peak value, and rank per region.
13
+ - **A/B comparison**: `hotgaze compare A.png B.png [--region ...]` → per-region attention-share deltas + 3×3 spatial grid + focal-point movement.
14
+ - **Focal points**: local maxima via OpenCV dilate-based max-filter, ranked by attention value.
15
+ - **Faces layer** (`--layers faces`): YuNet face detector (MIT) adds Gaussian attention blobs over detected faces. Default weight 0.50 — tuned so enabling the layer shifts the focal point onto detected faces on portraits; zero effect on faceless UI images.
16
+ - **Canonical JSON**: schema v1, sorted keys, floats rounded to 6 dp, byte-identical across runs on the same machine.
17
+ - **CLI**: `hotgaze run`, `hotgaze score`, `hotgaze compare`, `hotgaze info`.
18
+ - **Weight manager**: download-on-first-use with SHA-256 verification, atomic cache, `click.progressbar`.
19
+ - **Offline-first**: default pipeline works with zero network access; deep backend caches weights after one fetch.
hotgaze-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Surya Kosaraju
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.
@@ -0,0 +1,132 @@
1
+ # Third-Party Licenses
2
+
3
+ This file records every third-party dependency bundled or used by HotGaze,
4
+ as required by the project's license-hygiene policy (see CLAUDE.md).
5
+
6
+ ## Core runtime dependencies
7
+
8
+ | Package | Version (min) | URL | License | Notes |
9
+ |---------|--------------|-----|---------|-------|
10
+ | numpy | 1.24 | https://github.com/numpy/numpy | BSD-3-Clause | Array computation |
11
+ | opencv-python-headless | 4.8 | https://github.com/opencv/opencv-python | Apache-2.0 | Image I/O, base OpenCV (no contrib) |
12
+ | pillow | 10.0 | https://github.com/python-pillow/Pillow | HPND (historical) | Image loading |
13
+ | click | 8.1 | https://github.com/pallets/click | BSD-3-Clause | CLI framework |
14
+ | pydantic | 2.0 | https://github.com/pydantic/pydantic | MIT | Config models, validation |
15
+
16
+ ## Optional runtime dependencies
17
+
18
+ | Package | Version (min) | URL | License | Notes |
19
+ |---------|--------------|-----|---------|-------|
20
+ | torch | 2.0 | https://github.com/pytorch/pytorch | BSD-3-Clause | Deep saliency backend (`hotgaze[deep]`) |
21
+
22
+ ## Development dependencies
23
+
24
+ | Package | Version (min) | URL | License | Notes |
25
+ |---------|--------------|-----|---------|-------|
26
+ | ruff | 0.4 | https://github.com/astral-sh/ruff | MIT | Lint + format |
27
+ | pytest | 8.0 | https://github.com/pytest-dev/pytest | MIT | Test framework |
28
+ | pytest-cov | 5.0 | https://github.com/pytest-dev/pytest-cov | MIT | Coverage reporting |
29
+ | mypy | 1.8 | https://github.com/python/mypy | MIT | Static type checking |
30
+ | scikit-image | 0.22 | https://github.com/scikit-image/scikit-image | BSD-3-Clause | **TEST-ONLY** — astronaut face fixture (BSD). Must never be imported from `src/` |
31
+ | actionlint-py | 1.7 | https://github.com/Mateusz-Grzelinski/actionlint-py | MIT | CI workflow linting |
32
+
33
+ ## Pretrained models
34
+
35
+ No pretrained model weights are bundled in the repository. The deep backend
36
+ downloads weights on first use (cached in `~/.cache/hotgaze/`). Model license
37
+ audit is conducted in T0.3 and will be appended below.
38
+
39
+ ### Model audit (T0.3 — completed 2026-07-11)
40
+
41
+ #### Saliency backends (deep backend candidates)
42
+
43
+ ##### 1. UNISAL — ✅ SELECTED as default deep backend
44
+
45
+ | Field | Value |
46
+ |-------|-------|
47
+ | URL | https://github.com/rdroste/unisal |
48
+ | Code license | Apache License 2.0 |
49
+ | Weights license | Apache License 2.0 (weights are part of the repo, same license) |
50
+ | Weights file 1 | `weights_best.pth` (14.7 MB) — trained on SALICON |
51
+ | Weights file 2 | `weights_ft_mit1003.pth` (14.7 MB) — fine-tuned on MIT1003 |
52
+ | Hosting | GitHub repo (`raw.githubusercontent.com`) — stable URL, not Google Drive |
53
+ | SHA-256 (weights_best) | `4a9157411f1741d588b15670d15295e998805648b8b6348599fe447298338481` |
54
+ | SHA-256 (weights_ft_mit1003) | `a6de8ea27d812cfc3fbc2b8cab59862a8e48aaf4d512e670468d3b6972a81262` |
55
+ | Framework | PyTorch (native) |
56
+ | Redistribution | ✅ YES — Apache 2.0 Section 4 permits reproduction + distribution |
57
+ | **Final verdict** | **OK** — permissive license, stable URL, redistribution-allowed |
58
+
59
+ ##### 2. DeepGaze IIE — ❌ REJECTED (no license)
60
+
61
+ | Field | Value |
62
+ |-------|-------|
63
+ | URL | https://github.com/matthias-k/DeepGaze |
64
+ | Code license | **None** — no LICENSE file; `setup.py` license fields commented out; defaults to "all rights reserved" |
65
+ | Weights license | None (same as code) |
66
+ | Weights URL | GitHub Releases (`v1.0.0` tag) — stable URL |
67
+ | Weights files | `deepgaze2e.pth` (~400 MB), `centerbias_mit1003.npy` (~8 MB) |
68
+ | Framework | PyTorch (native) |
69
+ | Redistribution | ❌ NO — no license grants redistribution rights |
70
+ | **Final verdict** | **needs-author-contact** — contact matthias.kuemmerer@bethgelab.org; GitHub issue #15 (commercial use) unanswered since Oct 2023 |
71
+
72
+ ##### 3. MSI-Net — ✅ OK (fallback, TF → ONNX path)
73
+
74
+ | Field | Value |
75
+ |-------|-------|
76
+ | URL | https://github.com/alexanderkroner/saliency |
77
+ | Code license | MIT |
78
+ | Weights license | MIT (HuggingFace model card confirms) |
79
+ | Weights URL | https://huggingface.co/alexanderkroner/MSI-Net |
80
+ | Framework | TensorFlow (original); foveacast-training provides PyTorch port + ONNX export |
81
+ | Redistribution | ✅ YES — MIT permits use, copy, modify, merge, publish, distribute |
82
+ | **Final verdict** | **OK** — MIT-licensed, but TF dependency adds complexity; eligible only via ONNX export per CLAUDE.md |
83
+
84
+ #### Face detection candidates
85
+
86
+ ##### 1. YuNet — ✅ SELECTED
87
+
88
+ | Field | Value |
89
+ |-------|-------|
90
+ | URL | https://github.com/opencv/opencv_zoo (models/face_detection_yunet) |
91
+ | Code license | MIT |
92
+ | Weights license | MIT |
93
+ | Weights URL | https://huggingface.co/opencv-zoo/face-detection-yunet (227 KB ONNX) |
94
+ | SHA-256 | `8f2383e4dd3cfbb4553ea8718107fc0423210dc964f9f4280604804ed2552fa4` |
95
+ | Integration | Native `cv2.FaceDetectorYN` API (OpenCV ≥ 4.5) |
96
+ | Redistribution | ✅ YES — MIT-licensed |
97
+ | **Final verdict** | **OK** — tiny (232 KB), native OpenCV API, MIT |
98
+
99
+ ##### 2. UltraFace — ✅ OK (fallback)
100
+
101
+ | Field | Value |
102
+ |-------|-------|
103
+ | URL | https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB |
104
+ | Code license | MIT |
105
+ | Weights license | MIT |
106
+ | Weights URL | ONNX weights available (~1.2 MB) |
107
+ | Integration | `cv2.dnn.readNetFromONNX` (standard OpenCV DNN) |
108
+ | Redistribution | ✅ YES — MIT-licensed |
109
+ | **Final verdict** | **OK** — lightweight, standard DNN integration |
110
+
111
+ #### Exclusion notes
112
+
113
+ - **RetinaFace / InsightFace / SCRFD**: Code MIT, but pretrained models carry **non-commercial** restriction explicitly in README → **REJECTED**
114
+ - **DBFace**: No license specified → **REJECTED** (all rights reserved)
115
+ - **BlazeFace**: Apache 2.0 but TFLite format → excluded (no TFLite in deps)
116
+
117
+ #### Hosting plan
118
+
119
+ - UNISAL weights will be re-hosted from our own GitHub Release with pinned SHA-256 checksums (required by CLAUDE.md — original hosting is not Google Drive, but we re-host to control checksumming and availability)
120
+ - YuNet weights will be re-hosted from our own GitHub Release (232 KB, trivial)
121
+ - Download-on-first-use, cached in `~/.cache/hotgaze/` with `HOTGAZE_CACHE` env override
122
+
123
+ #### Default deep backend
124
+
125
+ **UNISAL** — best quality among PyTorch-native models with permissive license (Apache 2.0) AND redistribution rights. PyTorch-native (no TF/ONNX complexity). Two weight variants available (SALICON-trained and MIT1003-fine-tuned).
126
+
127
+ #### Vendored code
128
+
129
+ | Source | Files | License | Commit | Notes |
130
+ |--------|-------|---------|--------|-------|
131
+ | https://github.com/rdroste/unisal | `_unisal/_model.py`, `_unisal/_mobilenet.py`, `_unisal/_cgru.py` | Apache 2.0 | HEAD (2026-07-12) | Inference-only subset; training/dataset code removed. `_model.py` modified to remove training methods and KwConfigClass; `_mobilenet.py` and `_cgru.py` are unmodified except for the license header.
132
+ | https://github.com/rdroste/unisal | `mobilenet_v2.pth.tar` (14,205,652 B, SHA-256 `ecbe2b56…`) | Apache 2.0 | Bundled in UNISAL repo | ImageNet-pretrained MobileNetV2 backbone. Bundled in UNISAL under same Apache 2.0 license; no separate NOTICE in the upstream. Redistribution: ✅ per Apache 2.0.
hotgaze-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: hotgaze
3
+ Version: 0.1.0
4
+ Summary: Predict visual attention on UI screenshots — heatmap overlays and machine-readable attention scores
5
+ Project-URL: Homepage, https://github.com/suryakosaraju/hotgaze
6
+ Project-URL: Repository, https://github.com/suryakosaraju/hotgaze
7
+ Author: Surya Kosaraju
8
+ License: MIT
9
+ License-File: LICENSE
10
+ License-File: LICENSES-THIRD-PARTY.md
11
+ Keywords: attention,eye-tracking,heatmap,saliency,ui,ux
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
22
+ Classifier: Topic :: Scientific/Engineering :: Visualization
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: click>=8.1
25
+ Requires-Dist: numpy>=1.24
26
+ Requires-Dist: opencv-python-headless>=4.8
27
+ Requires-Dist: pillow>=10.0
28
+ Requires-Dist: pydantic>=2.0
29
+ Provides-Extra: deep
30
+ Requires-Dist: torch>=2.0; extra == 'deep'
31
+ Provides-Extra: dev
32
+ Requires-Dist: actionlint-py>=1.7; extra == 'dev'
33
+ Requires-Dist: mypy>=1.8; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
35
+ Requires-Dist: pytest>=8.0; extra == 'dev'
36
+ Requires-Dist: ruff>=0.4; extra == 'dev'
37
+ Requires-Dist: scikit-image>=0.22; extra == 'dev'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # HotGaze ⏿
41
+
42
+ [![CI](https://github.com/suryakosaraju/hotgaze/actions/workflows/ci.yml/badge.svg)](https://github.com/suryakosaraju/hotgaze/actions/workflows/ci.yml)
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/suryakosaraju/hotgaze/blob/main/LICENSE)
44
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://github.com/suryakosaraju/hotgaze/blob/main/pyproject.toml)
45
+
46
+ Attention heatmaps for UI screenshots — with **numeric scores and A/B compare**, not just pretty pictures.
47
+
48
+ Predict where users' eyes land on a design, get a machine-readable attention share for any region, and diff two variants to see which one wins and by how much. Local, offline, MIT-licensed.
49
+
50
+ ![Original design next to its HotGaze attention overlay — headline, CTA, and sidebar items glow hot](https://raw.githubusercontent.com/suryakosaraju/hotgaze/main/docs/demo.png)
51
+
52
+ > **Status: v0.1 alpha.** The fast heuristic backend, region scoring, A/B compare, and deep UNISAL backend are shipping. Faces layer (YuNet) is available via `--layers faces`. API and CLI may change before v1.
53
+
54
+ ## Why this exists
55
+
56
+ Every existing attention-prediction tool — paid ([HeatScope](https://heatscope.space), Attention Insight, EyeQuant) and free ([Foveacast](https://www.allaboutken.com/posts/20260503-foveacast/)) — stops at a colored overlay for a human to eyeball. That's fine for a designer squinting at a mockup. It's useless when you want to:
57
+
58
+ - Compare two design variants and *quantify* which one draws more attention to the CTA.
59
+ - Wire attention checks into CI ("your button just lost 23% of its attention").
60
+ - Script or automate any part of the design-review loop.
61
+
62
+ HotGaze outputs the picture too, but the picture isn't the point. The **numbers** are.
63
+
64
+ ## Install
65
+
66
+ Not on PyPI yet (v0.1 is a working-directory install):
67
+
68
+ ```bash
69
+ git clone https://github.com/suryakosaraju/hotgaze
70
+ cd hotgaze
71
+ pip install -e .
72
+ ```
73
+
74
+ Python 3.10+. Runs on macOS and Linux. No cloud, no API keys, no telemetry.
75
+
76
+ ## Quickstart
77
+
78
+ ```bash
79
+ # Generate an attention overlay
80
+ hotgaze run screenshot.png -o overlay.png
81
+
82
+ # Score a specific region — how much attention does the CTA get?
83
+ hotgaze score screenshot.png --region cta:250,200,200,35 --json
84
+
85
+ # Compare two variants — which one wins?
86
+ hotgaze compare landing_a.png landing_b.png --region cta:250,200,200,35
87
+ ```
88
+
89
+ ## The differentiator: numbers, not just pictures
90
+
91
+ **Score any region.** Attention share, peak value, rank — canonical JSON, deterministic on the same machine:
92
+
93
+ ```bash
94
+ $ hotgaze score design.png --region cta:250,200,200,35 --json
95
+ {
96
+ "schema": 1,
97
+ "regions": [
98
+ {"name": "cta", "share": 0.035, "peak_value": 0.769, "rank": 1}
99
+ ],
100
+ "focal_points": [...]
101
+ }
102
+ ```
103
+
104
+ **Compare two variants.** Per-region deltas, plus a 3×3 spatial grid showing where attention *moved*:
105
+
106
+ ```bash
107
+ $ hotgaze compare landing_a.png landing_b.png --region cta:250,200,200,35 --json
108
+ {
109
+ "compare": {
110
+ "per_region_deltas": [
111
+ {"name": "cta", "share_a": 0.035, "share_b": 0.022, "delta": -0.013}
112
+ ]
113
+ }
114
+ }
115
+ ```
116
+
117
+ Variant B lost 37% of the CTA's attention share. That's an actionable number, not "the heatmap looks about the same."
118
+
119
+ ## What's in the box
120
+
121
+ - **CLI**: `hotgaze run`, `hotgaze score`, `hotgaze compare`, `hotgaze info`.
122
+ - **Fast heuristic backend** (default): spectral-residual saliency + contrast + center bias + F-pattern reading prior. No downloads, works offline, sub-second on CPU.
123
+ - **Deep saliency backend** (`--backend deep`): [UNISAL](https://github.com/rdroste/unisal) (Apache-2.0), CPU-only, deterministic per-machine. Install: `pip install hotgaze[deep]`. Weights download on first use (one-time, ~30 MB).
124
+ - **Faces layer** (`--layers faces`): [YuNet](https://github.com/opencv/opencv_zoo) (MIT) face detection adds attention blobs over detected faces.
125
+ - **Versioned JSON output**: schema v1 covers both score and compare modes so downstream tools don't break on new features.
126
+ - **Deterministic**: same image + same config + same machine → byte-identical JSON.
127
+
128
+ ## Backends
129
+
130
+ | Backend | Default | What it uses | Quality |
131
+ |---------|---------|-------------|---------|
132
+ | `fast` | ✅ | Spectral residual + contrast + center bias + gaze flow | Strong on flat UI screenshots; zero downloads |
133
+ | `deep` | | UNISAL pretrained saliency model (PyTorch) | Better on natural images; on flat UIs the fast backend often matches or exceeds it — the domain gap is real. |
134
+
135
+ `--backend deep` requires `pip install hotgaze[deep]` and a one-time weight download on first use. Both backends are fully offline after the initial fetch.
136
+
137
+ ## What HotGaze isn't
138
+
139
+ - **Not real eye-tracking.** It's a prediction from computer-vision priors. Useful for early design review; not a substitute for a user study.
140
+ - **Not a conversion oracle.** Attention share correlates with visibility, not with conversion — high attention on a bad CTA still doesn't sell.
141
+ - **Not a designer GUI.** It's a scriptable tool for developers. A GUI/Figma plugin is roadmap, not v1.
142
+
143
+ ## Roadmap
144
+
145
+ - **v0.2** — PyPI release, GitHub Action for attention regression testing on PR screenshots.
146
+ - **v0.3+** — UI-tuned text/saliency models, Figma plugin, macOS wrapper, benchmarking against public saliency datasets.
147
+
148
+
149
+ ## License
150
+
151
+ MIT. See [LICENSE](https://github.com/suryakosaraju/hotgaze/blob/main/LICENSE).
152
+
153
+ Third-party models and dependencies are recorded with their licenses and redistribution status in [LICENSES-THIRD-PARTY.md](https://github.com/suryakosaraju/hotgaze/blob/main/LICENSES-THIRD-PARTY.md).
154
+
155
+ ## Credits
156
+
157
+ Predictive saliency stands on decades of vision research. The deep backend builds on [UNISAL](https://github.com/rdroste/unisal) (Droste et al.). The fast backend implements [Hou & Zhang's spectral-residual approach (2007)](https://www.cv-foundation.org/openaccess/content_cvpr_2007/papers/Hou_Saliency_Detection_A_Spectral_Residual_Approach_CVPR_2007_paper.pdf). Face detection uses [YuNet](https://github.com/opencv/opencv_zoo).
@@ -0,0 +1,118 @@
1
+ # HotGaze ⏿
2
+
3
+ [![CI](https://github.com/suryakosaraju/hotgaze/actions/workflows/ci.yml/badge.svg)](https://github.com/suryakosaraju/hotgaze/actions/workflows/ci.yml)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/suryakosaraju/hotgaze/blob/main/LICENSE)
5
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://github.com/suryakosaraju/hotgaze/blob/main/pyproject.toml)
6
+
7
+ Attention heatmaps for UI screenshots — with **numeric scores and A/B compare**, not just pretty pictures.
8
+
9
+ Predict where users' eyes land on a design, get a machine-readable attention share for any region, and diff two variants to see which one wins and by how much. Local, offline, MIT-licensed.
10
+
11
+ ![Original design next to its HotGaze attention overlay — headline, CTA, and sidebar items glow hot](https://raw.githubusercontent.com/suryakosaraju/hotgaze/main/docs/demo.png)
12
+
13
+ > **Status: v0.1 alpha.** The fast heuristic backend, region scoring, A/B compare, and deep UNISAL backend are shipping. Faces layer (YuNet) is available via `--layers faces`. API and CLI may change before v1.
14
+
15
+ ## Why this exists
16
+
17
+ Every existing attention-prediction tool — paid ([HeatScope](https://heatscope.space), Attention Insight, EyeQuant) and free ([Foveacast](https://www.allaboutken.com/posts/20260503-foveacast/)) — stops at a colored overlay for a human to eyeball. That's fine for a designer squinting at a mockup. It's useless when you want to:
18
+
19
+ - Compare two design variants and *quantify* which one draws more attention to the CTA.
20
+ - Wire attention checks into CI ("your button just lost 23% of its attention").
21
+ - Script or automate any part of the design-review loop.
22
+
23
+ HotGaze outputs the picture too, but the picture isn't the point. The **numbers** are.
24
+
25
+ ## Install
26
+
27
+ Not on PyPI yet (v0.1 is a working-directory install):
28
+
29
+ ```bash
30
+ git clone https://github.com/suryakosaraju/hotgaze
31
+ cd hotgaze
32
+ pip install -e .
33
+ ```
34
+
35
+ Python 3.10+. Runs on macOS and Linux. No cloud, no API keys, no telemetry.
36
+
37
+ ## Quickstart
38
+
39
+ ```bash
40
+ # Generate an attention overlay
41
+ hotgaze run screenshot.png -o overlay.png
42
+
43
+ # Score a specific region — how much attention does the CTA get?
44
+ hotgaze score screenshot.png --region cta:250,200,200,35 --json
45
+
46
+ # Compare two variants — which one wins?
47
+ hotgaze compare landing_a.png landing_b.png --region cta:250,200,200,35
48
+ ```
49
+
50
+ ## The differentiator: numbers, not just pictures
51
+
52
+ **Score any region.** Attention share, peak value, rank — canonical JSON, deterministic on the same machine:
53
+
54
+ ```bash
55
+ $ hotgaze score design.png --region cta:250,200,200,35 --json
56
+ {
57
+ "schema": 1,
58
+ "regions": [
59
+ {"name": "cta", "share": 0.035, "peak_value": 0.769, "rank": 1}
60
+ ],
61
+ "focal_points": [...]
62
+ }
63
+ ```
64
+
65
+ **Compare two variants.** Per-region deltas, plus a 3×3 spatial grid showing where attention *moved*:
66
+
67
+ ```bash
68
+ $ hotgaze compare landing_a.png landing_b.png --region cta:250,200,200,35 --json
69
+ {
70
+ "compare": {
71
+ "per_region_deltas": [
72
+ {"name": "cta", "share_a": 0.035, "share_b": 0.022, "delta": -0.013}
73
+ ]
74
+ }
75
+ }
76
+ ```
77
+
78
+ Variant B lost 37% of the CTA's attention share. That's an actionable number, not "the heatmap looks about the same."
79
+
80
+ ## What's in the box
81
+
82
+ - **CLI**: `hotgaze run`, `hotgaze score`, `hotgaze compare`, `hotgaze info`.
83
+ - **Fast heuristic backend** (default): spectral-residual saliency + contrast + center bias + F-pattern reading prior. No downloads, works offline, sub-second on CPU.
84
+ - **Deep saliency backend** (`--backend deep`): [UNISAL](https://github.com/rdroste/unisal) (Apache-2.0), CPU-only, deterministic per-machine. Install: `pip install hotgaze[deep]`. Weights download on first use (one-time, ~30 MB).
85
+ - **Faces layer** (`--layers faces`): [YuNet](https://github.com/opencv/opencv_zoo) (MIT) face detection adds attention blobs over detected faces.
86
+ - **Versioned JSON output**: schema v1 covers both score and compare modes so downstream tools don't break on new features.
87
+ - **Deterministic**: same image + same config + same machine → byte-identical JSON.
88
+
89
+ ## Backends
90
+
91
+ | Backend | Default | What it uses | Quality |
92
+ |---------|---------|-------------|---------|
93
+ | `fast` | ✅ | Spectral residual + contrast + center bias + gaze flow | Strong on flat UI screenshots; zero downloads |
94
+ | `deep` | | UNISAL pretrained saliency model (PyTorch) | Better on natural images; on flat UIs the fast backend often matches or exceeds it — the domain gap is real. |
95
+
96
+ `--backend deep` requires `pip install hotgaze[deep]` and a one-time weight download on first use. Both backends are fully offline after the initial fetch.
97
+
98
+ ## What HotGaze isn't
99
+
100
+ - **Not real eye-tracking.** It's a prediction from computer-vision priors. Useful for early design review; not a substitute for a user study.
101
+ - **Not a conversion oracle.** Attention share correlates with visibility, not with conversion — high attention on a bad CTA still doesn't sell.
102
+ - **Not a designer GUI.** It's a scriptable tool for developers. A GUI/Figma plugin is roadmap, not v1.
103
+
104
+ ## Roadmap
105
+
106
+ - **v0.2** — PyPI release, GitHub Action for attention regression testing on PR screenshots.
107
+ - **v0.3+** — UI-tuned text/saliency models, Figma plugin, macOS wrapper, benchmarking against public saliency datasets.
108
+
109
+
110
+ ## License
111
+
112
+ MIT. See [LICENSE](https://github.com/suryakosaraju/hotgaze/blob/main/LICENSE).
113
+
114
+ Third-party models and dependencies are recorded with their licenses and redistribution status in [LICENSES-THIRD-PARTY.md](https://github.com/suryakosaraju/hotgaze/blob/main/LICENSES-THIRD-PARTY.md).
115
+
116
+ ## Credits
117
+
118
+ Predictive saliency stands on decades of vision research. The deep backend builds on [UNISAL](https://github.com/rdroste/unisal) (Droste et al.). The fast backend implements [Hou & Zhang's spectral-residual approach (2007)](https://www.cv-foundation.org/openaccess/content_cvpr_2007/papers/Hou_Saliency_Detection_A_Spectral_Residual_Approach_CVPR_2007_paper.pdf). Face detection uses [YuNet](https://github.com/opencv/opencv_zoo).
Binary file