annoviz 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.
- annoviz-0.1.0/PKG-INFO +243 -0
- annoviz-0.1.0/README.md +229 -0
- annoviz-0.1.0/annoviz/__init__.py +3 -0
- annoviz-0.1.0/annoviz/__main__.py +5 -0
- annoviz-0.1.0/annoviz/app.py +167 -0
- annoviz-0.1.0/annoviz/editor.py +881 -0
- annoviz-0.1.0/annoviz/geometry.py +111 -0
- annoviz-0.1.0/annoviz/io_utils.py +92 -0
- annoviz-0.1.0/annoviz/render.py +385 -0
- annoviz-0.1.0/annoviz/web/app.js +641 -0
- annoviz-0.1.0/annoviz/web/index.html +36 -0
- annoviz-0.1.0/annoviz/web/styles.css +107 -0
- annoviz-0.1.0/annoviz/web_editor.py +251 -0
- annoviz-0.1.0/annoviz.egg-info/PKG-INFO +243 -0
- annoviz-0.1.0/annoviz.egg-info/SOURCES.txt +20 -0
- annoviz-0.1.0/annoviz.egg-info/dependency_links.txt +1 -0
- annoviz-0.1.0/annoviz.egg-info/entry_points.txt +2 -0
- annoviz-0.1.0/annoviz.egg-info/requires.txt +9 -0
- annoviz-0.1.0/annoviz.egg-info/top_level.txt +1 -0
- annoviz-0.1.0/pyproject.toml +3 -0
- annoviz-0.1.0/setup.cfg +37 -0
annoviz-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: annoviz
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local YOLO annotation viewer and editor
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: pywebview>=5.0
|
|
8
|
+
Requires-Dist: pyobjc-core<12; sys_platform == "darwin" and python_version < "3.10"
|
|
9
|
+
Requires-Dist: pyobjc-framework-Cocoa<12; sys_platform == "darwin" and python_version < "3.10"
|
|
10
|
+
Requires-Dist: pyobjc-framework-Quartz<12; sys_platform == "darwin" and python_version < "3.10"
|
|
11
|
+
Requires-Dist: pyobjc-framework-Security<12; sys_platform == "darwin" and python_version < "3.10"
|
|
12
|
+
Requires-Dist: pyobjc-framework-UniformTypeIdentifiers<12; sys_platform == "darwin" and python_version < "3.10"
|
|
13
|
+
Requires-Dist: pyobjc-framework-WebKit<12; sys_platform == "darwin" and python_version < "3.10"
|
|
14
|
+
|
|
15
|
+
# Anno Viz
|
|
16
|
+
|
|
17
|
+
Anno Viz is a local YOLO annotation viewer and editor for image datasets. It opens a native desktop window backed by a web UI, shows the current image with editable bounding boxes, and includes a thumbnail timeline for moving through the dataset quickly.
|
|
18
|
+
|
|
19
|
+
## Screenshot
|
|
20
|
+
|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
## Dataset Layout
|
|
24
|
+
|
|
25
|
+
Anno Viz expects a dataset directory with this structure:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
dataset/
|
|
29
|
+
images/
|
|
30
|
+
image_001.jpg
|
|
31
|
+
image_002.jpg
|
|
32
|
+
labels/
|
|
33
|
+
image_001.txt
|
|
34
|
+
image_002.txt
|
|
35
|
+
classes.txt
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Labels use standard YOLO text format:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
class_id x_center y_center width height
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The coordinate values are normalized from `0` to `1`.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
Create and activate a virtual environment if you want to keep dependencies isolated:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
python3 -m venv .venv
|
|
52
|
+
source .venv/bin/activate
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Install Anno Viz and its dependencies from the project root:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
python3 -m pip install .
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This installs the `annoviz` command. If you install outside a virtual environment and your shell cannot find `annoviz`, add your Python user scripts directory to `PATH`. On macOS with the system/Xcode Python this is often:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
export PATH="$HOME/Library/Python/3.9/bin:$PATH"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
For active development, install it in editable mode:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python3 -m pip install -e .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`pywebview` is required because the editor opens in a native desktop window. On macOS with Python 3.9, `requirements.txt` pins the PyObjC packages below version 12 because PyObjC 12 may try to build from source and fail on that toolchain.
|
|
74
|
+
|
|
75
|
+
## Configure Dataset Directory
|
|
76
|
+
|
|
77
|
+
Set the default dataset directory for the current workspace:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
annoviz --set-dataset-dir /path/to/dataset
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
This creates a local workspace config file named `anno_viz_config`. It is ignored by git, so each workspace can point at its own dataset.
|
|
84
|
+
|
|
85
|
+
You can also use the underscore alias:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
annoviz --set_dataset_dir /path/to/dataset
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Run
|
|
92
|
+
|
|
93
|
+
After setting the dataset directory:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
annoviz
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
You can also run from source without installing through the compatibility wrappers:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python3 app.py
|
|
103
|
+
python3 anno_viz.py
|
|
104
|
+
python3 -m annoviz
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
To temporarily open a different dataset without changing the saved workspace config:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
annoviz --dataset-dir /path/to/other/dataset
|
|
111
|
+
annoviz -dataset_dir /path/to/other/dataset
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Optional Paths
|
|
115
|
+
|
|
116
|
+
Use these when your dataset does not follow the default `images/`, `labels/`, `classes.txt` layout:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
annoviz \
|
|
120
|
+
--images-dir /path/to/images \
|
|
121
|
+
--labels-dir /path/to/labels \
|
|
122
|
+
--classes-file /path/to/classes.txt
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Other useful options:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
annoviz --start-index 25
|
|
129
|
+
annoviz --port 8765
|
|
130
|
+
annoviz --save-dir /path/to/rendered/previews
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Controls
|
|
134
|
+
|
|
135
|
+
Control
|
|
136
|
+
|
|
137
|
+
Action
|
|
138
|
+
|
|
139
|
+
`n`, Right Arrow
|
|
140
|
+
|
|
141
|
+
Next image
|
|
142
|
+
|
|
143
|
+
`b`, Left Arrow
|
|
144
|
+
|
|
145
|
+
Previous image
|
|
146
|
+
|
|
147
|
+
`c`
|
|
148
|
+
|
|
149
|
+
Move back 5 images
|
|
150
|
+
|
|
151
|
+
`v`
|
|
152
|
+
|
|
153
|
+
Move forward 2 images
|
|
154
|
+
|
|
155
|
+
`x`
|
|
156
|
+
|
|
157
|
+
Move back 10 images
|
|
158
|
+
|
|
159
|
+
`a`
|
|
160
|
+
|
|
161
|
+
Toggle add-annotation mode
|
|
162
|
+
|
|
163
|
+
Drag box
|
|
164
|
+
|
|
165
|
+
Move or resize an annotation
|
|
166
|
+
|
|
167
|
+
`Tab`
|
|
168
|
+
|
|
169
|
+
Select next box
|
|
170
|
+
|
|
171
|
+
`+`, `-`
|
|
172
|
+
|
|
173
|
+
Change selected/add class
|
|
174
|
+
|
|
175
|
+
`0` to `9`
|
|
176
|
+
|
|
177
|
+
Set selected/add class id
|
|
178
|
+
|
|
179
|
+
Delete, Backspace
|
|
180
|
+
|
|
181
|
+
Remove selected box from the label
|
|
182
|
+
|
|
183
|
+
`s`
|
|
184
|
+
|
|
185
|
+
Save label edits
|
|
186
|
+
|
|
187
|
+
`d`
|
|
188
|
+
|
|
189
|
+
Mark current image for deletion
|
|
190
|
+
|
|
191
|
+
Click a red thumbnail
|
|
192
|
+
|
|
193
|
+
Undo pending delete for that image
|
|
194
|
+
|
|
195
|
+
Apply Deletes
|
|
196
|
+
|
|
197
|
+
Delete all marked images and matching label files
|
|
198
|
+
|
|
199
|
+
`q`, Escape, Close
|
|
200
|
+
|
|
201
|
+
Close the editor
|
|
202
|
+
|
|
203
|
+
## Delete Flow
|
|
204
|
+
|
|
205
|
+
Press `d` to mark the current image for deletion. Marked thumbnails are shown in red.
|
|
206
|
+
|
|
207
|
+
Deletion is not applied immediately. You can undo a pending delete by clicking the red thumbnail. To permanently remove all marked images and their label files, click `Apply Deletes`.
|
|
208
|
+
|
|
209
|
+
When closing from `q`, Escape, or the `Close` button with pending deletes, Anno Viz asks whether to apply the pending deletes before closing.
|
|
210
|
+
|
|
211
|
+
## Config
|
|
212
|
+
|
|
213
|
+
The workspace config file is:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
anno_viz_config
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
It stores JSON like:
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"dataset_dir": "/path/to/dataset"
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
This file is intentionally ignored by git because it is machine/workspace-specific.
|
|
228
|
+
|
|
229
|
+
## Troubleshooting
|
|
230
|
+
|
|
231
|
+
If the editor says the dataset directory is not set, run:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
annoviz --set-dataset-dir /path/to/dataset
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
If `pywebview` is missing, run:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
python3 -m pip install .
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
If no images appear, check that your image files are inside the configured `images/` directory. Supported extensions are handled by the local image collector in `io_utils.py`.
|
annoviz-0.1.0/README.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Anno Viz
|
|
2
|
+
|
|
3
|
+
Anno Viz is a local YOLO annotation viewer and editor for image datasets. It opens a native desktop window backed by a web UI, shows the current image with editable bounding boxes, and includes a thumbnail timeline for moving through the dataset quickly.
|
|
4
|
+
|
|
5
|
+
## Screenshot
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Dataset Layout
|
|
10
|
+
|
|
11
|
+
Anno Viz expects a dataset directory with this structure:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
dataset/
|
|
15
|
+
images/
|
|
16
|
+
image_001.jpg
|
|
17
|
+
image_002.jpg
|
|
18
|
+
labels/
|
|
19
|
+
image_001.txt
|
|
20
|
+
image_002.txt
|
|
21
|
+
classes.txt
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Labels use standard YOLO text format:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
class_id x_center y_center width height
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The coordinate values are normalized from `0` to `1`.
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
Create and activate a virtual environment if you want to keep dependencies isolated:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
python3 -m venv .venv
|
|
38
|
+
source .venv/bin/activate
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Install Anno Viz and its dependencies from the project root:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python3 -m pip install .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This installs the `annoviz` command. If you install outside a virtual environment and your shell cannot find `annoviz`, add your Python user scripts directory to `PATH`. On macOS with the system/Xcode Python this is often:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
export PATH="$HOME/Library/Python/3.9/bin:$PATH"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For active development, install it in editable mode:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
python3 -m pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`pywebview` is required because the editor opens in a native desktop window. On macOS with Python 3.9, `requirements.txt` pins the PyObjC packages below version 12 because PyObjC 12 may try to build from source and fail on that toolchain.
|
|
60
|
+
|
|
61
|
+
## Configure Dataset Directory
|
|
62
|
+
|
|
63
|
+
Set the default dataset directory for the current workspace:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
annoviz --set-dataset-dir /path/to/dataset
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This creates a local workspace config file named `anno_viz_config`. It is ignored by git, so each workspace can point at its own dataset.
|
|
70
|
+
|
|
71
|
+
You can also use the underscore alias:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
annoviz --set_dataset_dir /path/to/dataset
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Run
|
|
78
|
+
|
|
79
|
+
After setting the dataset directory:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
annoviz
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
You can also run from source without installing through the compatibility wrappers:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python3 app.py
|
|
89
|
+
python3 anno_viz.py
|
|
90
|
+
python3 -m annoviz
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
To temporarily open a different dataset without changing the saved workspace config:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
annoviz --dataset-dir /path/to/other/dataset
|
|
97
|
+
annoviz -dataset_dir /path/to/other/dataset
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Optional Paths
|
|
101
|
+
|
|
102
|
+
Use these when your dataset does not follow the default `images/`, `labels/`, `classes.txt` layout:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
annoviz \
|
|
106
|
+
--images-dir /path/to/images \
|
|
107
|
+
--labels-dir /path/to/labels \
|
|
108
|
+
--classes-file /path/to/classes.txt
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Other useful options:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
annoviz --start-index 25
|
|
115
|
+
annoviz --port 8765
|
|
116
|
+
annoviz --save-dir /path/to/rendered/previews
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Controls
|
|
120
|
+
|
|
121
|
+
Control
|
|
122
|
+
|
|
123
|
+
Action
|
|
124
|
+
|
|
125
|
+
`n`, Right Arrow
|
|
126
|
+
|
|
127
|
+
Next image
|
|
128
|
+
|
|
129
|
+
`b`, Left Arrow
|
|
130
|
+
|
|
131
|
+
Previous image
|
|
132
|
+
|
|
133
|
+
`c`
|
|
134
|
+
|
|
135
|
+
Move back 5 images
|
|
136
|
+
|
|
137
|
+
`v`
|
|
138
|
+
|
|
139
|
+
Move forward 2 images
|
|
140
|
+
|
|
141
|
+
`x`
|
|
142
|
+
|
|
143
|
+
Move back 10 images
|
|
144
|
+
|
|
145
|
+
`a`
|
|
146
|
+
|
|
147
|
+
Toggle add-annotation mode
|
|
148
|
+
|
|
149
|
+
Drag box
|
|
150
|
+
|
|
151
|
+
Move or resize an annotation
|
|
152
|
+
|
|
153
|
+
`Tab`
|
|
154
|
+
|
|
155
|
+
Select next box
|
|
156
|
+
|
|
157
|
+
`+`, `-`
|
|
158
|
+
|
|
159
|
+
Change selected/add class
|
|
160
|
+
|
|
161
|
+
`0` to `9`
|
|
162
|
+
|
|
163
|
+
Set selected/add class id
|
|
164
|
+
|
|
165
|
+
Delete, Backspace
|
|
166
|
+
|
|
167
|
+
Remove selected box from the label
|
|
168
|
+
|
|
169
|
+
`s`
|
|
170
|
+
|
|
171
|
+
Save label edits
|
|
172
|
+
|
|
173
|
+
`d`
|
|
174
|
+
|
|
175
|
+
Mark current image for deletion
|
|
176
|
+
|
|
177
|
+
Click a red thumbnail
|
|
178
|
+
|
|
179
|
+
Undo pending delete for that image
|
|
180
|
+
|
|
181
|
+
Apply Deletes
|
|
182
|
+
|
|
183
|
+
Delete all marked images and matching label files
|
|
184
|
+
|
|
185
|
+
`q`, Escape, Close
|
|
186
|
+
|
|
187
|
+
Close the editor
|
|
188
|
+
|
|
189
|
+
## Delete Flow
|
|
190
|
+
|
|
191
|
+
Press `d` to mark the current image for deletion. Marked thumbnails are shown in red.
|
|
192
|
+
|
|
193
|
+
Deletion is not applied immediately. You can undo a pending delete by clicking the red thumbnail. To permanently remove all marked images and their label files, click `Apply Deletes`.
|
|
194
|
+
|
|
195
|
+
When closing from `q`, Escape, or the `Close` button with pending deletes, Anno Viz asks whether to apply the pending deletes before closing.
|
|
196
|
+
|
|
197
|
+
## Config
|
|
198
|
+
|
|
199
|
+
The workspace config file is:
|
|
200
|
+
|
|
201
|
+
```text
|
|
202
|
+
anno_viz_config
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
It stores JSON like:
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"dataset_dir": "/path/to/dataset"
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
This file is intentionally ignored by git because it is machine/workspace-specific.
|
|
214
|
+
|
|
215
|
+
## Troubleshooting
|
|
216
|
+
|
|
217
|
+
If the editor says the dataset directory is not set, run:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
annoviz --set-dataset-dir /path/to/dataset
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
If `pywebview` is missing, run:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
python3 -m pip install .
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
If no images appear, check that your image files are inside the configured `images/` directory. Supported extensions are handled by the local image collector in `io_utils.py`.
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import argparse
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
CONFIG_FILE = "anno_viz_config"
|
|
7
|
+
LEGACY_DATASET_PATH_FILE = "anno_viz_datasetpath.txt"
|
|
8
|
+
|
|
9
|
+
DATASET_DIR_INSTRUCTIONS = """Dataset directory is not set.
|
|
10
|
+
|
|
11
|
+
Set a default dataset directory for this workspace:
|
|
12
|
+
annoviz --set-dataset-dir /path/to/dataset
|
|
13
|
+
|
|
14
|
+
Or temporarily visualize a different dataset for one run:
|
|
15
|
+
annoviz --dataset-dir /path/to/dataset
|
|
16
|
+
annoviz -dataset_dir /path/to/dataset
|
|
17
|
+
|
|
18
|
+
The dataset directory should contain:
|
|
19
|
+
images/
|
|
20
|
+
labels/
|
|
21
|
+
classes.txt
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def workspace_config_file():
|
|
26
|
+
return Path.cwd() / CONFIG_FILE
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def workspace_legacy_config_file():
|
|
30
|
+
return Path.cwd() / LEGACY_DATASET_PATH_FILE
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def is_git_workspace(workspace_dir):
|
|
34
|
+
return (workspace_dir / ".git").exists()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def ensure_config_gitignored(workspace_dir):
|
|
38
|
+
if not is_git_workspace(workspace_dir):
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
gitignore_path = workspace_dir / ".gitignore"
|
|
42
|
+
entry = CONFIG_FILE
|
|
43
|
+
|
|
44
|
+
if not gitignore_path.exists():
|
|
45
|
+
gitignore_path.write_text(f"{entry}\n", encoding="utf-8")
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
content = gitignore_path.read_text(encoding="utf-8")
|
|
49
|
+
lines = [line.strip() for line in content.splitlines()]
|
|
50
|
+
if entry in lines:
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
separator = "" if content.endswith("\n") or not content else "\n"
|
|
54
|
+
with gitignore_path.open("a", encoding="utf-8") as gitignore:
|
|
55
|
+
gitignore.write(f"{separator}{entry}\n")
|
|
56
|
+
return True
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def normalize_dataset_dir(path):
|
|
60
|
+
path = Path(path).expanduser()
|
|
61
|
+
if not path.is_absolute():
|
|
62
|
+
path = Path.cwd() / path
|
|
63
|
+
return path.resolve()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def write_workspace_config(config_file, dataset_dir):
|
|
67
|
+
config = {
|
|
68
|
+
"dataset_dir": str(dataset_dir),
|
|
69
|
+
}
|
|
70
|
+
config_file.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def read_dataset_path_text(path_file):
|
|
74
|
+
raw_path = path_file.read_text(encoding="utf-8").strip()
|
|
75
|
+
if not raw_path:
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
path = Path(raw_path).expanduser()
|
|
79
|
+
if not path.is_absolute():
|
|
80
|
+
path = path_file.parent / path
|
|
81
|
+
return path.resolve()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def read_workspace_dataset_dir(config_file):
|
|
85
|
+
if config_file.exists():
|
|
86
|
+
raw_config = config_file.read_text(encoding="utf-8").strip()
|
|
87
|
+
if not raw_config:
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
config = json.loads(raw_config)
|
|
92
|
+
except json.JSONDecodeError:
|
|
93
|
+
return read_dataset_path_text(config_file)
|
|
94
|
+
|
|
95
|
+
dataset_dir = config.get("dataset_dir")
|
|
96
|
+
if not dataset_dir:
|
|
97
|
+
return None
|
|
98
|
+
|
|
99
|
+
path = Path(dataset_dir).expanduser()
|
|
100
|
+
if not path.is_absolute():
|
|
101
|
+
path = config_file.parent / path
|
|
102
|
+
return path.resolve()
|
|
103
|
+
|
|
104
|
+
legacy_path_file = workspace_legacy_config_file()
|
|
105
|
+
if legacy_path_file.exists():
|
|
106
|
+
return read_dataset_path_text(legacy_path_file)
|
|
107
|
+
|
|
108
|
+
return None
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def main():
|
|
112
|
+
parser = argparse.ArgumentParser(description="View/edit YOLO annotations on generated images")
|
|
113
|
+
parser.add_argument(
|
|
114
|
+
"--set-dataset-dir",
|
|
115
|
+
"--set_dataset_dir",
|
|
116
|
+
dest="set_dataset_dir",
|
|
117
|
+
default=None,
|
|
118
|
+
type=Path,
|
|
119
|
+
help=f"Save the default dataset root to {CONFIG_FILE} in the current workspace.",
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
"--dataset-dir",
|
|
123
|
+
"--dataset_dir",
|
|
124
|
+
"-dataset_dir",
|
|
125
|
+
dest="dataset_dir",
|
|
126
|
+
default=None,
|
|
127
|
+
type=Path,
|
|
128
|
+
help="Dataset root for this run.",
|
|
129
|
+
)
|
|
130
|
+
parser.add_argument("--images-dir", default=None, type=Path)
|
|
131
|
+
parser.add_argument("--labels-dir", default=None, type=Path)
|
|
132
|
+
parser.add_argument("--classes-file", default=None, type=Path)
|
|
133
|
+
parser.add_argument("--save-dir", default=None, type=Path)
|
|
134
|
+
parser.add_argument("--start-index", default=0, type=int)
|
|
135
|
+
parser.add_argument("--port", default=0, type=int, help="Local web UI port. Defaults to a free port.")
|
|
136
|
+
|
|
137
|
+
args = parser.parse_args()
|
|
138
|
+
config_file = workspace_config_file()
|
|
139
|
+
if args.set_dataset_dir is not None:
|
|
140
|
+
dataset_dir = normalize_dataset_dir(args.set_dataset_dir)
|
|
141
|
+
write_workspace_config(config_file, dataset_dir)
|
|
142
|
+
print(f"saved dataset directory to {config_file}: {dataset_dir}")
|
|
143
|
+
legacy_path_file = workspace_legacy_config_file()
|
|
144
|
+
if legacy_path_file.exists():
|
|
145
|
+
legacy_path_file.unlink()
|
|
146
|
+
ensure_config_gitignored(config_file.parent)
|
|
147
|
+
return
|
|
148
|
+
|
|
149
|
+
dataset_dir = args.dataset_dir.expanduser() if args.dataset_dir is not None else read_workspace_dataset_dir(config_file)
|
|
150
|
+
if dataset_dir is None:
|
|
151
|
+
parser.exit(2, f"error: {DATASET_DIR_INSTRUCTIONS}\n")
|
|
152
|
+
|
|
153
|
+
dataset_dir = normalize_dataset_dir(dataset_dir)
|
|
154
|
+
from .web_editor import visualize
|
|
155
|
+
|
|
156
|
+
visualize(
|
|
157
|
+
images_dir=args.images_dir or dataset_dir / "images",
|
|
158
|
+
labels_dir=args.labels_dir or dataset_dir / "labels",
|
|
159
|
+
classes_file=args.classes_file or dataset_dir / "classes.txt",
|
|
160
|
+
save_dir=args.save_dir,
|
|
161
|
+
start_index=args.start_index,
|
|
162
|
+
port=args.port,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
main()
|