silukman-image-vectorizer 1.0.5__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.
- silukman_image_vectorizer-1.0.5/LICENSE +30 -0
- silukman_image_vectorizer-1.0.5/PKG-INFO +119 -0
- silukman_image_vectorizer-1.0.5/README.md +92 -0
- silukman_image_vectorizer-1.0.5/app/__init__.py +1 -0
- silukman_image_vectorizer-1.0.5/app/cli.py +73 -0
- silukman_image_vectorizer-1.0.5/app/config/__init__.py +1 -0
- silukman_image_vectorizer-1.0.5/app/config/settings.py +40 -0
- silukman_image_vectorizer-1.0.5/app/core/__init__.py +1 -0
- silukman_image_vectorizer-1.0.5/app/core/constants.py +6 -0
- silukman_image_vectorizer-1.0.5/app/core/image_pipeline.py +51 -0
- silukman_image_vectorizer-1.0.5/app/core/paths.py +13 -0
- silukman_image_vectorizer-1.0.5/app/core/vectorization_engine.py +360 -0
- silukman_image_vectorizer-1.0.5/app/core/vectorizer_backend.py +373 -0
- silukman_image_vectorizer-1.0.5/app/main_window.py +1714 -0
- silukman_image_vectorizer-1.0.5/app/resources/__init__.py +1 -0
- silukman_image_vectorizer-1.0.5/app/resources/hero_image.png +0 -0
- silukman_image_vectorizer-1.0.5/app/resources/icon.icns +0 -0
- silukman_image_vectorizer-1.0.5/app/resources/icon.png +0 -0
- silukman_image_vectorizer-1.0.5/app/services/__init__.py +1 -0
- silukman_image_vectorizer-1.0.5/app/services/batch_processor.py +171 -0
- silukman_image_vectorizer-1.0.5/app/services/color_palette.py +110 -0
- silukman_image_vectorizer-1.0.5/app/services/image_loader.py +120 -0
- silukman_image_vectorizer-1.0.5/app/services/svg_exporter.py +191 -0
- silukman_image_vectorizer-1.0.5/app/ui/__init__.py +1 -0
- silukman_image_vectorizer-1.0.5/app/ui/theme.py +316 -0
- silukman_image_vectorizer-1.0.5/pyproject.toml +48 -0
- silukman_image_vectorizer-1.0.5/setup.cfg +4 -0
- silukman_image_vectorizer-1.0.5/silukman_image_vectorizer.egg-info/PKG-INFO +119 -0
- silukman_image_vectorizer-1.0.5/silukman_image_vectorizer.egg-info/SOURCES.txt +31 -0
- silukman_image_vectorizer-1.0.5/silukman_image_vectorizer.egg-info/dependency_links.txt +1 -0
- silukman_image_vectorizer-1.0.5/silukman_image_vectorizer.egg-info/entry_points.txt +2 -0
- silukman_image_vectorizer-1.0.5/silukman_image_vectorizer.egg-info/requires.txt +5 -0
- silukman_image_vectorizer-1.0.5/silukman_image_vectorizer.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Image Vectorizer Developers
|
|
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
|
+
|
|
23
|
+
---
|
|
24
|
+
Third-Party Software Attributions:
|
|
25
|
+
This application bundles and uses the following open-source libraries:
|
|
26
|
+
- PySide6 (LGPL v3) - https://www.qt.io/qt-for-python
|
|
27
|
+
- OpenCV Python (Apache License 2.0) - https://github.com/opencv/opencv-python
|
|
28
|
+
- Pillow (HPND License) - https://github.com/python-pillow/Pillow
|
|
29
|
+
- Numpy (BSD-3-Clause) - https://github.com/numpy/numpy
|
|
30
|
+
- VTracer (MIT License) - https://github.com/visioncortex/vtracer
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: silukman-image-vectorizer
|
|
3
|
+
Version: 1.0.5
|
|
4
|
+
Summary: A PySide6 desktop application for high-quality raster-to-vector (SVG) conversion.
|
|
5
|
+
Author: Lukman-ss
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/lukman-ss/silukman_image_vectorizer
|
|
8
|
+
Project-URL: Bug-Tracker, https://github.com/lukman-ss/silukman_image_vectorizer/issues
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Environment :: X11 Applications :: Qt
|
|
16
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
17
|
+
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: PySide6>=6.0.0
|
|
22
|
+
Requires-Dist: pillow>=9.0.0
|
|
23
|
+
Requires-Dist: opencv-python>=4.5.0
|
|
24
|
+
Requires-Dist: numpy>=1.20.0
|
|
25
|
+
Requires-Dist: vtracer>=0.1.6
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# Image Vectorizer
|
|
29
|
+
|
|
30
|
+

|
|
31
|
+
|
|
32
|
+
Last updated: 2026-06-05
|
|
33
|
+
|
|
34
|
+
Image Vectorizer is a Python and PySide6 desktop application foundation for
|
|
35
|
+
working with raster images. The current application supports local image import,
|
|
36
|
+
original and processed previews, image metadata display, and an initial
|
|
37
|
+
grayscale and threshold processing pipeline. It can also detect, simplify, and
|
|
38
|
+
preview color-aware vector paths using configurable quality, background removal,
|
|
39
|
+
and comparison controls. The desktop UI supports accessible Light, Dark, and
|
|
40
|
+
System theme modes, single SVG export, and responsive batch SVG processing.
|
|
41
|
+
|
|
42
|
+
## Install Dependencies
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python -m pip install -r requirements.txt
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Run
|
|
49
|
+
|
|
50
|
+
From the project root:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
python main.py
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Or use the development runner:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python scripts/run_dev.py
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Build & Packaging
|
|
63
|
+
|
|
64
|
+
To bundle the application into a standalone desktop executable for distribution:
|
|
65
|
+
|
|
66
|
+
### On Windows
|
|
67
|
+
```cmd
|
|
68
|
+
.venv\Scripts\python scripts\build_app.py
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### On macOS / Linux
|
|
72
|
+
```bash
|
|
73
|
+
.venv/bin/python scripts/build_app.py
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The script will automatically handle:
|
|
77
|
+
1. Cleaning previous build output folders.
|
|
78
|
+
2. Generating a clean build using the configuration from `image_vectorizer.spec`.
|
|
79
|
+
3. Creating the standalone package in the `dist/` directory.
|
|
80
|
+
4. Auto-detecting the application icon in `app/resources` using the native
|
|
81
|
+
platform icon format when available.
|
|
82
|
+
5. Running a post-build cleanup on temporary compilation artifacts.
|
|
83
|
+
6. Using PyInstaller from `.venv` or the system PATH.
|
|
84
|
+
|
|
85
|
+
## Documentation
|
|
86
|
+
|
|
87
|
+
Project documentation is available in `docs/`.
|
|
88
|
+
|
|
89
|
+
- `docs/architecture/` for system and pipeline architecture.
|
|
90
|
+
- `docs/developer/` for setup, verification, benchmark, and packaging guides.
|
|
91
|
+
- `docs/product/` for project overview, glossary, status, and roadmap.
|
|
92
|
+
- `docs/user/` for UI workflow, performance tips, and troubleshooting.
|
|
93
|
+
|
|
94
|
+
## CI/CD & Release Automation
|
|
95
|
+
|
|
96
|
+
We use GitHub Actions to automate desktop application builds, version tagging, and release publishing.
|
|
97
|
+
|
|
98
|
+
### 1. CI Build Workflow (`build.yml`)
|
|
99
|
+
- Triggered automatically on push or pull requests to the `main` branch, or via manual run (`workflow_dispatch`).
|
|
100
|
+
- Builds standalone application packages for Windows, macOS, and Linux in parallel.
|
|
101
|
+
- Uploads the build outputs as workflow artifacts (`Image-Vectorizer-Windows`, `Image-Vectorizer-macOS`, `Image-Vectorizer-Linux`).
|
|
102
|
+
|
|
103
|
+
### 2. Manual Tag Workflow (`create_tag.yml`)
|
|
104
|
+
- Triggered manually from the Actions tab.
|
|
105
|
+
- Accepts a semantic version tag (e.g. `v1.0.0`) and pushes it to the repository after validating that the format matches `v*.*.*` and the tag does not already exist.
|
|
106
|
+
|
|
107
|
+
### 3. Release Publication Workflow (`release.yml`)
|
|
108
|
+
- Automatically triggered when a new version tag (`v*.*.*`) is pushed.
|
|
109
|
+
- Re-builds the application packages for all target platforms, compiles them, and attaches the archived builds to a newly created GitHub Release using the version number as the release name.
|
|
110
|
+
|
|
111
|
+
### 4. PyPI Publishing Workflow (`publish_pypi.yml`)
|
|
112
|
+
- Triggered automatically when a new version tag (`v*.*.*`) is pushed, or via manual run (`workflow_dispatch`).
|
|
113
|
+
- Compiles the source distribution and wheel packages, validates package metadata using `twine`, and publishes the package to PyPI under the name `silukman-image-vectorizer` using the repository secret `PYPI_API_TOKEN`.
|
|
114
|
+
|
|
115
|
+
### Difference Between Manual and CI Build
|
|
116
|
+
- **Manual Build**: Runs locally via `scripts/build_app.py`. Uses local system libraries, virtual environment compilers, and target architecture. Best for fast local verification.
|
|
117
|
+
- **CI Build**: Runs inside clean, isolated containers on GitHub-hosted runners (Windows, macOS, Linux). Guarantees reproducible builds and doesn't pollute local environments.
|
|
118
|
+
|
|
119
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Image Vectorizer
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Last updated: 2026-06-05
|
|
6
|
+
|
|
7
|
+
Image Vectorizer is a Python and PySide6 desktop application foundation for
|
|
8
|
+
working with raster images. The current application supports local image import,
|
|
9
|
+
original and processed previews, image metadata display, and an initial
|
|
10
|
+
grayscale and threshold processing pipeline. It can also detect, simplify, and
|
|
11
|
+
preview color-aware vector paths using configurable quality, background removal,
|
|
12
|
+
and comparison controls. The desktop UI supports accessible Light, Dark, and
|
|
13
|
+
System theme modes, single SVG export, and responsive batch SVG processing.
|
|
14
|
+
|
|
15
|
+
## Install Dependencies
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
python -m pip install -r requirements.txt
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Run
|
|
22
|
+
|
|
23
|
+
From the project root:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python main.py
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or use the development runner:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python scripts/run_dev.py
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Build & Packaging
|
|
36
|
+
|
|
37
|
+
To bundle the application into a standalone desktop executable for distribution:
|
|
38
|
+
|
|
39
|
+
### On Windows
|
|
40
|
+
```cmd
|
|
41
|
+
.venv\Scripts\python scripts\build_app.py
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### On macOS / Linux
|
|
45
|
+
```bash
|
|
46
|
+
.venv/bin/python scripts/build_app.py
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The script will automatically handle:
|
|
50
|
+
1. Cleaning previous build output folders.
|
|
51
|
+
2. Generating a clean build using the configuration from `image_vectorizer.spec`.
|
|
52
|
+
3. Creating the standalone package in the `dist/` directory.
|
|
53
|
+
4. Auto-detecting the application icon in `app/resources` using the native
|
|
54
|
+
platform icon format when available.
|
|
55
|
+
5. Running a post-build cleanup on temporary compilation artifacts.
|
|
56
|
+
6. Using PyInstaller from `.venv` or the system PATH.
|
|
57
|
+
|
|
58
|
+
## Documentation
|
|
59
|
+
|
|
60
|
+
Project documentation is available in `docs/`.
|
|
61
|
+
|
|
62
|
+
- `docs/architecture/` for system and pipeline architecture.
|
|
63
|
+
- `docs/developer/` for setup, verification, benchmark, and packaging guides.
|
|
64
|
+
- `docs/product/` for project overview, glossary, status, and roadmap.
|
|
65
|
+
- `docs/user/` for UI workflow, performance tips, and troubleshooting.
|
|
66
|
+
|
|
67
|
+
## CI/CD & Release Automation
|
|
68
|
+
|
|
69
|
+
We use GitHub Actions to automate desktop application builds, version tagging, and release publishing.
|
|
70
|
+
|
|
71
|
+
### 1. CI Build Workflow (`build.yml`)
|
|
72
|
+
- Triggered automatically on push or pull requests to the `main` branch, or via manual run (`workflow_dispatch`).
|
|
73
|
+
- Builds standalone application packages for Windows, macOS, and Linux in parallel.
|
|
74
|
+
- Uploads the build outputs as workflow artifacts (`Image-Vectorizer-Windows`, `Image-Vectorizer-macOS`, `Image-Vectorizer-Linux`).
|
|
75
|
+
|
|
76
|
+
### 2. Manual Tag Workflow (`create_tag.yml`)
|
|
77
|
+
- Triggered manually from the Actions tab.
|
|
78
|
+
- Accepts a semantic version tag (e.g. `v1.0.0`) and pushes it to the repository after validating that the format matches `v*.*.*` and the tag does not already exist.
|
|
79
|
+
|
|
80
|
+
### 3. Release Publication Workflow (`release.yml`)
|
|
81
|
+
- Automatically triggered when a new version tag (`v*.*.*`) is pushed.
|
|
82
|
+
- Re-builds the application packages for all target platforms, compiles them, and attaches the archived builds to a newly created GitHub Release using the version number as the release name.
|
|
83
|
+
|
|
84
|
+
### 4. PyPI Publishing Workflow (`publish_pypi.yml`)
|
|
85
|
+
- Triggered automatically when a new version tag (`v*.*.*`) is pushed, or via manual run (`workflow_dispatch`).
|
|
86
|
+
- Compiles the source distribution and wheel packages, validates package metadata using `twine`, and publishes the package to PyPI under the name `silukman-image-vectorizer` using the repository secret `PYPI_API_TOKEN`.
|
|
87
|
+
|
|
88
|
+
### Difference Between Manual and CI Build
|
|
89
|
+
- **Manual Build**: Runs locally via `scripts/build_app.py`. Uses local system libraries, virtual environment compilers, and target architecture. Best for fast local verification.
|
|
90
|
+
- **CI Build**: Runs inside clean, isolated containers on GitHub-hosted runners (Windows, macOS, Linux). Guarantees reproducible builds and doesn't pollute local environments.
|
|
91
|
+
|
|
92
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Image Vectorizer application package."""
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import traceback
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _show_startup_error(title: str, message: str) -> None:
|
|
6
|
+
try:
|
|
7
|
+
from PySide6.QtWidgets import QApplication, QMessageBox
|
|
8
|
+
|
|
9
|
+
app = QApplication.instance()
|
|
10
|
+
created = False
|
|
11
|
+
if app is None:
|
|
12
|
+
app = QApplication(sys.argv)
|
|
13
|
+
created = True
|
|
14
|
+
QMessageBox.critical(None, title, message)
|
|
15
|
+
if created:
|
|
16
|
+
app.processEvents()
|
|
17
|
+
except Exception:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _validate_runtime_environment() -> None:
|
|
22
|
+
from app.core.paths import RESOURCES_DIR
|
|
23
|
+
|
|
24
|
+
required_resources = [
|
|
25
|
+
RESOURCES_DIR,
|
|
26
|
+
RESOURCES_DIR / "icon.png",
|
|
27
|
+
RESOURCES_DIR / "hero_image.png",
|
|
28
|
+
]
|
|
29
|
+
missing_resources = [
|
|
30
|
+
str(path)
|
|
31
|
+
for path in required_resources
|
|
32
|
+
if not path.exists()
|
|
33
|
+
]
|
|
34
|
+
if missing_resources:
|
|
35
|
+
missing = "\n".join(missing_resources)
|
|
36
|
+
raise RuntimeError(f"Missing packaged resource(s):\n{missing}")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def main() -> int:
|
|
40
|
+
try:
|
|
41
|
+
from PySide6.QtWidgets import QApplication
|
|
42
|
+
|
|
43
|
+
from app.main_window import MainWindow
|
|
44
|
+
|
|
45
|
+
_validate_runtime_environment()
|
|
46
|
+
|
|
47
|
+
application = QApplication(sys.argv)
|
|
48
|
+
application.setApplicationName("Image Vectorizer")
|
|
49
|
+
|
|
50
|
+
window = MainWindow()
|
|
51
|
+
window.show()
|
|
52
|
+
return application.exec()
|
|
53
|
+
except ImportError as error:
|
|
54
|
+
msg = (
|
|
55
|
+
f"Failed to start Image Vectorizer: missing dependency ({error}).\n\n"
|
|
56
|
+
"Please ensure all dependencies are installed correctly."
|
|
57
|
+
)
|
|
58
|
+
print(msg, file=sys.stderr)
|
|
59
|
+
_show_startup_error("Dependency Error", msg)
|
|
60
|
+
return 1
|
|
61
|
+
except Exception as error:
|
|
62
|
+
print(f"Failed to start Image Vectorizer: {error}", file=sys.stderr)
|
|
63
|
+
traceback.print_exc()
|
|
64
|
+
|
|
65
|
+
_show_startup_error(
|
|
66
|
+
"Startup Error",
|
|
67
|
+
f"Image Vectorizer could not start:\n{error}",
|
|
68
|
+
)
|
|
69
|
+
return 1
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
sys.exit(main())
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Application configuration package."""
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
DEFAULT_WINDOW_WIDTH = 1200
|
|
4
|
+
DEFAULT_WINDOW_HEIGHT = 760
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class VTracerSettings:
|
|
8
|
+
"""VTracer-specific settings."""
|
|
9
|
+
colormode: str = "color" # color / binary
|
|
10
|
+
hierarchical: str = "stacked" # stacked / cutout
|
|
11
|
+
mode: str = "spline" # spline / polygon / none
|
|
12
|
+
filter_speckle: int = 4 # speckle size filter
|
|
13
|
+
color_precision: int = 6 # 1 to 8 (safer default max 6 to prevent 128 colors)
|
|
14
|
+
layer_difference: int = 16 # color difference threshold
|
|
15
|
+
corner_threshold: int = 60 # angle threshold for corners
|
|
16
|
+
length_threshold: float = 3.5 # curve length threshold
|
|
17
|
+
max_iterations: int = 16 # optimizer max iteration count
|
|
18
|
+
path_precision: int = 8 # SVG path output decimal precision
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class VectorizationSettings:
|
|
22
|
+
"""Settings that control the vectorization process."""
|
|
23
|
+
# Legacy OpenCV settings
|
|
24
|
+
min_area: float = 100.0 # Minimum contour area to keep (pixels)
|
|
25
|
+
approx_tolerance: float = 2.0 # Douglas-Peucker epsilon for approximation
|
|
26
|
+
smoothing_enabled: bool = False # Whether to apply Gaussian smoothing pre-detection
|
|
27
|
+
invert: bool = False # Invert binary image before detection
|
|
28
|
+
color_mode: str = "Unlimited colors"
|
|
29
|
+
color_count: int = 8
|
|
30
|
+
preserve_edges: bool = False
|
|
31
|
+
remove_background: bool = False
|
|
32
|
+
bg_tolerance: float = 20.0
|
|
33
|
+
threshold_val: int = 127 # Threshold value for legacy engine
|
|
34
|
+
palette_replacements: list[tuple[tuple[int, int, int], tuple[int, int, int]]] = field(default_factory=list)
|
|
35
|
+
|
|
36
|
+
# Active engine type: "VTracer" or "OpenCV Legacy"
|
|
37
|
+
engine_type: str = "VTracer"
|
|
38
|
+
|
|
39
|
+
# VTracer settings object
|
|
40
|
+
vtracer: VTracerSettings = field(default_factory=VTracerSettings)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Core application utilities."""
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import cv2
|
|
4
|
+
import numpy as np
|
|
5
|
+
from PySide6.QtGui import QImage
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def process_image_pipeline(file_path: str, threshold_val: int) -> tuple[QImage, np.ndarray]:
|
|
9
|
+
"""Run the image processing pipeline.
|
|
10
|
+
|
|
11
|
+
Stages:
|
|
12
|
+
1. Load image and convert to grayscale.
|
|
13
|
+
2. Apply binary thresholding.
|
|
14
|
+
"""
|
|
15
|
+
if not isinstance(threshold_val, int) or isinstance(threshold_val, bool):
|
|
16
|
+
raise ValueError("Threshold value must be an integer.")
|
|
17
|
+
if not 0 <= threshold_val <= 255:
|
|
18
|
+
raise ValueError("Threshold value must be between 0 and 255.")
|
|
19
|
+
|
|
20
|
+
img = cv2.imread(file_path, cv2.IMREAD_UNCHANGED)
|
|
21
|
+
if img is None:
|
|
22
|
+
raise ValueError("Failed to load image for processing pipeline.")
|
|
23
|
+
|
|
24
|
+
if img.ndim == 2:
|
|
25
|
+
gray = img
|
|
26
|
+
elif img.shape[2] == 4:
|
|
27
|
+
gray = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)
|
|
28
|
+
elif img.shape[2] == 3:
|
|
29
|
+
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
|
30
|
+
else:
|
|
31
|
+
raise ValueError("Unsupported image channel layout.")
|
|
32
|
+
|
|
33
|
+
# Stage 2: Threshold processing
|
|
34
|
+
_, thresholded = cv2.threshold(gray, threshold_val, 255, cv2.THRESH_BINARY)
|
|
35
|
+
|
|
36
|
+
# Convert grayscale/binary numpy array to QImage
|
|
37
|
+
height, width = thresholded.shape
|
|
38
|
+
thresholded = np.ascontiguousarray(thresholded)
|
|
39
|
+
bytes_per_line = thresholded.strides[0]
|
|
40
|
+
|
|
41
|
+
# QImage.Format_Grayscale8 is appropriate for single-channel 8-bit image data
|
|
42
|
+
q_image = QImage(
|
|
43
|
+
thresholded.data,
|
|
44
|
+
width,
|
|
45
|
+
height,
|
|
46
|
+
bytes_per_line,
|
|
47
|
+
QImage.Format.Format_Grayscale8
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Create a copy to ensure memory ownership of the pixel data is transferred to QImage
|
|
51
|
+
return q_image.copy(), thresholded
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
|
|
6
|
+
PROJECT_ROOT = Path(sys._MEIPASS)
|
|
7
|
+
else:
|
|
8
|
+
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
9
|
+
|
|
10
|
+
APP_DIR = PROJECT_ROOT / "app"
|
|
11
|
+
RESOURCES_DIR = APP_DIR / "resources"
|
|
12
|
+
DOCS_DIR = PROJECT_ROOT / "docs"
|
|
13
|
+
SCRIPTS_DIR = PROJECT_ROOT / "scripts"
|