magiclabel 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rohan Rustagi
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,304 @@
1
+ Metadata-Version: 2.4
2
+ Name: magiclabel
3
+ Version: 0.1.0
4
+ Summary: AI-assisted image annotation CLI for computer vision datasets
5
+ Author: Rohan Rustagi
6
+ License: MIT
7
+ Keywords: annotation,labeling,computer-vision,yolo,dataset,object-detection
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: >=3.8
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: ultralytics>=8.0.0
19
+ Requires-Dist: typer>=0.9.0
20
+ Requires-Dist: rich
21
+ Requires-Dist: opencv-python
22
+ Requires-Dist: gradio
23
+ Requires-Dist: gradio_image_annotation
24
+ Requires-Dist: torch
25
+ Requires-Dist: torchvision
26
+ Dynamic: license-file
27
+
28
+ # MagicLabel
29
+
30
+ > AI‑assisted image labeling CLI — go from raw images to your own trained model, end to end.
31
+
32
+ Good models start with good data, and labeling that data by hand is the slowest part of any computer‑vision project. **MagicLabel** runs the whole loop from one command line:
33
+
34
+ 1. **Auto‑detect** objects in a folder of images — including custom objects you describe in plain words (no training needed).
35
+ 2. **Review & fix** the labels in a browser — draw, move, resize, relabel, delete.
36
+ 3. **Train** a custom YOLO model on your labeled data.
37
+ 4. **Reuse** your named model (`rohan.pt`, `findelon.pt`, …) to auto‑label the next batch — the loop closes.
38
+
39
+ Everything runs **locally and free** — no account, no cloud upload, no Docker.
40
+
41
+ ![Python](https://img.shields.io/badge/python-3.8%2B-blue)
42
+ ![License](https://img.shields.io/badge/license-MIT-green)
43
+
44
+ ---
45
+
46
+ ## Features
47
+
48
+ - 🔍 **Auto‑detect** — label an image folder with a YOLO model (the 80 COCO classes out of the box).
49
+ - 🗣️ **Open‑vocabulary detect** — `--prompt "missile,launcher"` detects *anything you name*, with no training (YOLO‑World).
50
+ - 🖊️ **Visual review** — a Gradio web app to draw / move / resize / relabel / delete boxes and save back to YOLO format. Type **any class name you want**.
51
+ - 🎓 **Train** — fine‑tune a custom model on your labeled data and save it as a named `.pt`.
52
+ - 🔄 **Export** — convert YOLO labels to COCO JSON.
53
+ - 🏷️ **Inspect** — print the class names a YOLO model knows.
54
+
55
+ ---
56
+
57
+ ## Who is this for?
58
+
59
+ Anyone who needs a labeled image dataset and a model to train on it:
60
+
61
+ - **ML engineers & researchers** bootstrapping a dataset from raw images.
62
+ - **Hobbyists & students** learning the full CV pipeline without paying for a labeling service.
63
+ - **Privacy‑sensitive / air‑gapped users** (medical, defense, proprietary data) who can't upload images to a cloud tool.
64
+
65
+ ---
66
+
67
+ ## Requirements
68
+
69
+ - **Python 3.8+**
70
+ - Disk space for model weights (downloaded automatically on first use)
71
+ - Works on **CPU**; a CUDA or Apple‑Silicon (MPS) GPU is used automatically when available and is much faster for training
72
+
73
+ > **Heads‑up:** MagicLabel depends on `torch` and `ultralytics`, so installation pulls ~1 GB of packages. That's normal for a computer‑vision tool.
74
+
75
+ ---
76
+
77
+ ## Installation
78
+
79
+ ### From PyPI
80
+
81
+ ```bash
82
+ pip install magiclabel
83
+ ```
84
+
85
+ ### From source
86
+
87
+ ```bash
88
+ git clone https://github.com/your-username/magiclabel.git
89
+ cd magiclabel
90
+ python -m venv .venv
91
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
92
+ pip install -e .
93
+ ```
94
+
95
+ Verify:
96
+
97
+ ```bash
98
+ magiclabel --help
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Quick start — the full loop
104
+
105
+ ```bash
106
+ # 1. Auto-label a folder of images (closed-set, 80 COCO classes)
107
+ magiclabel detect ./images --output ./labels
108
+
109
+ # …or detect a CUSTOM object by describing it (no training):
110
+ magiclabel detect ./images --prompt "missile, launcher" --output ./labels
111
+
112
+ # 2. Review and fix the labels in your browser
113
+ magiclabel review ./images ./labels
114
+
115
+ # 3. Train your own model on the corrected dataset
116
+ magiclabel train ./images ./labels --name rohan.pt --epochs 50
117
+
118
+ # 4. Reuse your model to auto-label the next batch
119
+ magiclabel detect ./new_images --model rohan.pt --output ./labels2
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Commands
125
+
126
+ Run `magiclabel <command> --help` at any time for the full option list.
127
+
128
+ ### `detect` — auto‑annotate with bounding boxes
129
+
130
+ Runs a model over every image in a directory and writes one YOLO‑format `.txt` per image, plus a `classes.txt` (the class list).
131
+
132
+ ```bash
133
+ magiclabel detect SOURCE [OPTIONS]
134
+ ```
135
+
136
+ | Option | Default | Description |
137
+ | ------------ | ---------------------------------------- | --------------------------------------------------------------------------- |
138
+ | `SOURCE` | _(required)_ | Directory of images (`.jpg`, `.jpeg`, `.png`, `.bmp`, `.tif`) |
139
+ | `--prompt` | _(none)_ | Comma‑separated object names for **open‑vocabulary** detection, e.g. `"missile,launcher"`. No training needed. |
140
+ | `--model` | `yolov8n.pt` / `yolov8s-world.pt` | Model file. Defaults to `yolov8n.pt` (closed‑set), or `yolov8s-world.pt` when `--prompt` is given. Pass your own `.pt` to use a trained model. |
141
+ | `--output` | `./labels_detect` | Output directory for labels + `classes.txt` |
142
+ | `--conf` | `0.25` | Confidence threshold (0–1); higher = fewer, surer boxes |
143
+
144
+ **Examples**
145
+
146
+ ```bash
147
+ # Closed-set: the 80 COCO classes
148
+ magiclabel detect ./images --conf 0.3 --output ./labels
149
+
150
+ # Open-vocabulary: detect objects YOLO has never been trained on
151
+ magiclabel detect ./images --prompt "drone, fixed-wing aircraft" --conf 0.1
152
+
153
+ # Use your own trained model
154
+ magiclabel detect ./images --model rohan.pt --output ./labels
155
+ ```
156
+
157
+ > **Open‑vocabulary is great for common/clear objects and hit‑or‑miss on unusual ones** (it does the easy 70–80%). For hard objects (e.g. missiles), hand‑label a first batch in `review`, `train` a model, then `detect --model your.pt` to auto‑label the rest.
158
+
159
+ ---
160
+
161
+ ### `review` — fix annotations in your browser
162
+
163
+ Launches a local web app (default: <http://127.0.0.1:7860>) to inspect and correct labels.
164
+
165
+ ```bash
166
+ magiclabel review IMAGES_DIR LABELS_DIR [--model yolov8n.pt]
167
+ ```
168
+
169
+ | Argument / Option | Description |
170
+ | ----------------- | --------------------------------------------------------------------------- |
171
+ | `IMAGES_DIR` | Directory of images |
172
+ | `LABELS_DIR` | Directory of YOLO `.txt` labels (and `classes.txt`) |
173
+ | `--model` | Model whose class names label the boxes (default `yolov8n.pt`). Use `--model none` to start a clean custom dataset with no preset names. |
174
+
175
+ **In the UI you can:**
176
+
177
+ - **Draw** a new box — click and drag on the image.
178
+ - **Move / resize** — click a box and drag it or its corner handles.
179
+ - **Set the class** — double‑click a box and **type any class name** (`missile`, `crack`, `logo`), then click the editor's apply/✓ to commit. New names are added automatically.
180
+ - **Delete** — the box's remove button, the <kbd>Delete</kbd> key, or **Clear All Boxes**.
181
+ - **Switch images** — the dropdown at the top (it opens on the first image that already has boxes).
182
+ - **Save Changes** — writes boxes back to the `.txt`; the view then reloads from disk so you can confirm exactly what was saved.
183
+
184
+ **Custom classes & `classes.txt`:** YOLO label files store integer class ids, so MagicLabel keeps a `classes.txt` (one name per line, id = line number) in your labels folder. Whatever name you type is mapped to a stable id behind the scenes, and new names are appended automatically. **That `classes.txt` is the class list you train on.**
185
+
186
+ > Edits live only in the browser until you click **Save Changes**. Saving an image with no boxes writes an empty label file (a valid "no objects" annotation).
187
+
188
+ ---
189
+
190
+ ### `train` — train your own model
191
+
192
+ Fine‑tunes a YOLO model on your labeled dataset and saves it as a named `.pt`.
193
+
194
+ ```bash
195
+ magiclabel train IMAGES_DIR LABELS_DIR [OPTIONS]
196
+ ```
197
+
198
+ | Option | Default | Description |
199
+ | -------------- | ------------- | ------------------------------------------------------ |
200
+ | `IMAGES_DIR` | _(required)_ | Directory of images |
201
+ | `LABELS_DIR` | _(required)_ | Directory of YOLO labels + `classes.txt` |
202
+ | `--name` | `custom.pt` | Output model name, e.g. `rohan.pt` |
203
+ | `--base` | `yolov8n.pt` | Base model to fine‑tune |
204
+ | `--epochs` | `50` | Training epochs |
205
+ | `--imgsz` | `640` | Training image size |
206
+ | `--val-split` | `0.2` | Fraction of images held out for validation |
207
+
208
+ **Example**
209
+
210
+ ```bash
211
+ magiclabel train ./images ./labels --name rohan.pt --epochs 100
212
+ # → rohan.pt (and a rohan_dataset/ folder with the train/val split + data.yaml)
213
+ ```
214
+
215
+ The command builds a proper YOLO dataset (train/val split + `data.yaml`) from your labels, trains, and copies the best weights to your named file. Use it anywhere a model is accepted:
216
+
217
+ ```bash
218
+ magiclabel detect ./new_images --model rohan.pt
219
+ ```
220
+
221
+ > A useful model needs **dozens‑to‑hundreds of labeled images** and enough epochs. On CPU this can be slow — a GPU is much faster. Start small to validate the pipeline, then scale your data.
222
+
223
+ ---
224
+
225
+ ### `yolo2coco` — convert labels to COCO JSON
226
+
227
+ ```bash
228
+ magiclabel yolo2coco IMAGES_DIR LABELS_DIR OUTPUT_JSON --class NAME [--class NAME ...]
229
+ ```
230
+
231
+ | Argument / Option | Description |
232
+ | ----------------- | --------------------------------------------------------- |
233
+ | `IMAGES_DIR` | Directory of images |
234
+ | `LABELS_DIR` | Directory of YOLO detection labels |
235
+ | `OUTPUT_JSON` | Path to write the COCO JSON file |
236
+ | `--class` | Class names **in class‑id order** (0, 1, 2, …), repeated |
237
+
238
+ ```bash
239
+ magiclabel yolo2coco ./images ./labels annotations.json \
240
+ --class person --class bicycle --class car
241
+ ```
242
+
243
+ ---
244
+
245
+ ### `export-classes` — list a model's class names
246
+
247
+ ```bash
248
+ magiclabel export-classes yolov8n.pt
249
+ # 0: person
250
+ # 1: bicycle
251
+ # 2: car
252
+ # ...
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Label format
258
+
259
+ MagicLabel reads and writes the **YOLO detection** format: one `.txt` per image, sharing the image's base name (`dog.jpg` → `dog.txt`). Each line is one box:
260
+
261
+ ```text
262
+ <class_id> <x_center> <y_center> <width> <height>
263
+ ```
264
+
265
+ All four coordinates are **normalized to 0–1** relative to the image size. Example:
266
+
267
+ ```text
268
+ 16 0.593846 0.400000 0.250769 0.258462
269
+ ```
270
+
271
+ A `classes.txt` alongside the labels maps each id to a name (id = line number).
272
+
273
+ ---
274
+
275
+ ## Tips & troubleshooting
276
+
277
+ - **Model downloads:** the first run of a new model downloads its weights into the current directory and reuses them after.
278
+ - **Speed:** detection is fast on CPU; training is much faster on a GPU (PyTorch uses CUDA/MPS automatically).
279
+ - **"No images found":** the source must be a directory containing images with a supported extension (`.jpg`, `.jpeg`, `.png`, `.bmp`, `.tif`, `.tiff`).
280
+ - **Port 7860 already in use:** an old review server is still running. Stop it with:
281
+ ```bash
282
+ kill $(lsof -nP -tiTCP:7860 -sTCP:LISTEN)
283
+ ```
284
+ - **Restart after changes:** the review server does not hot‑reload — stop it (<kbd>Ctrl</kbd>+<kbd>C</kbd>) and run `magiclabel review …` again.
285
+
286
+ ---
287
+
288
+ ## Project structure
289
+
290
+ ```text
291
+ magiclabel/
292
+ ├── cli.py # Typer CLI entry point (detect, review, train, yolo2coco, export-classes)
293
+ ├── annotator.py # YOLO / YOLO-World detection → label files + classes.txt
294
+ ├── review_app.py # Gradio review/annotation web app
295
+ ├── trainer.py # builds the dataset and trains a custom model
296
+ ├── convertor.py # YOLO → COCO conversion
297
+ └── utils.py # image discovery + helpers
298
+ ```
299
+
300
+ ---
301
+
302
+ ## License
303
+
304
+ Released under the [MIT License](LICENSE).
@@ -0,0 +1,277 @@
1
+ # MagicLabel
2
+
3
+ > AI‑assisted image labeling CLI — go from raw images to your own trained model, end to end.
4
+
5
+ Good models start with good data, and labeling that data by hand is the slowest part of any computer‑vision project. **MagicLabel** runs the whole loop from one command line:
6
+
7
+ 1. **Auto‑detect** objects in a folder of images — including custom objects you describe in plain words (no training needed).
8
+ 2. **Review & fix** the labels in a browser — draw, move, resize, relabel, delete.
9
+ 3. **Train** a custom YOLO model on your labeled data.
10
+ 4. **Reuse** your named model (`rohan.pt`, `findelon.pt`, …) to auto‑label the next batch — the loop closes.
11
+
12
+ Everything runs **locally and free** — no account, no cloud upload, no Docker.
13
+
14
+ ![Python](https://img.shields.io/badge/python-3.8%2B-blue)
15
+ ![License](https://img.shields.io/badge/license-MIT-green)
16
+
17
+ ---
18
+
19
+ ## Features
20
+
21
+ - 🔍 **Auto‑detect** — label an image folder with a YOLO model (the 80 COCO classes out of the box).
22
+ - 🗣️ **Open‑vocabulary detect** — `--prompt "missile,launcher"` detects *anything you name*, with no training (YOLO‑World).
23
+ - 🖊️ **Visual review** — a Gradio web app to draw / move / resize / relabel / delete boxes and save back to YOLO format. Type **any class name you want**.
24
+ - 🎓 **Train** — fine‑tune a custom model on your labeled data and save it as a named `.pt`.
25
+ - 🔄 **Export** — convert YOLO labels to COCO JSON.
26
+ - 🏷️ **Inspect** — print the class names a YOLO model knows.
27
+
28
+ ---
29
+
30
+ ## Who is this for?
31
+
32
+ Anyone who needs a labeled image dataset and a model to train on it:
33
+
34
+ - **ML engineers & researchers** bootstrapping a dataset from raw images.
35
+ - **Hobbyists & students** learning the full CV pipeline without paying for a labeling service.
36
+ - **Privacy‑sensitive / air‑gapped users** (medical, defense, proprietary data) who can't upload images to a cloud tool.
37
+
38
+ ---
39
+
40
+ ## Requirements
41
+
42
+ - **Python 3.8+**
43
+ - Disk space for model weights (downloaded automatically on first use)
44
+ - Works on **CPU**; a CUDA or Apple‑Silicon (MPS) GPU is used automatically when available and is much faster for training
45
+
46
+ > **Heads‑up:** MagicLabel depends on `torch` and `ultralytics`, so installation pulls ~1 GB of packages. That's normal for a computer‑vision tool.
47
+
48
+ ---
49
+
50
+ ## Installation
51
+
52
+ ### From PyPI
53
+
54
+ ```bash
55
+ pip install magiclabel
56
+ ```
57
+
58
+ ### From source
59
+
60
+ ```bash
61
+ git clone https://github.com/your-username/magiclabel.git
62
+ cd magiclabel
63
+ python -m venv .venv
64
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
65
+ pip install -e .
66
+ ```
67
+
68
+ Verify:
69
+
70
+ ```bash
71
+ magiclabel --help
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Quick start — the full loop
77
+
78
+ ```bash
79
+ # 1. Auto-label a folder of images (closed-set, 80 COCO classes)
80
+ magiclabel detect ./images --output ./labels
81
+
82
+ # …or detect a CUSTOM object by describing it (no training):
83
+ magiclabel detect ./images --prompt "missile, launcher" --output ./labels
84
+
85
+ # 2. Review and fix the labels in your browser
86
+ magiclabel review ./images ./labels
87
+
88
+ # 3. Train your own model on the corrected dataset
89
+ magiclabel train ./images ./labels --name rohan.pt --epochs 50
90
+
91
+ # 4. Reuse your model to auto-label the next batch
92
+ magiclabel detect ./new_images --model rohan.pt --output ./labels2
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Commands
98
+
99
+ Run `magiclabel <command> --help` at any time for the full option list.
100
+
101
+ ### `detect` — auto‑annotate with bounding boxes
102
+
103
+ Runs a model over every image in a directory and writes one YOLO‑format `.txt` per image, plus a `classes.txt` (the class list).
104
+
105
+ ```bash
106
+ magiclabel detect SOURCE [OPTIONS]
107
+ ```
108
+
109
+ | Option | Default | Description |
110
+ | ------------ | ---------------------------------------- | --------------------------------------------------------------------------- |
111
+ | `SOURCE` | _(required)_ | Directory of images (`.jpg`, `.jpeg`, `.png`, `.bmp`, `.tif`) |
112
+ | `--prompt` | _(none)_ | Comma‑separated object names for **open‑vocabulary** detection, e.g. `"missile,launcher"`. No training needed. |
113
+ | `--model` | `yolov8n.pt` / `yolov8s-world.pt` | Model file. Defaults to `yolov8n.pt` (closed‑set), or `yolov8s-world.pt` when `--prompt` is given. Pass your own `.pt` to use a trained model. |
114
+ | `--output` | `./labels_detect` | Output directory for labels + `classes.txt` |
115
+ | `--conf` | `0.25` | Confidence threshold (0–1); higher = fewer, surer boxes |
116
+
117
+ **Examples**
118
+
119
+ ```bash
120
+ # Closed-set: the 80 COCO classes
121
+ magiclabel detect ./images --conf 0.3 --output ./labels
122
+
123
+ # Open-vocabulary: detect objects YOLO has never been trained on
124
+ magiclabel detect ./images --prompt "drone, fixed-wing aircraft" --conf 0.1
125
+
126
+ # Use your own trained model
127
+ magiclabel detect ./images --model rohan.pt --output ./labels
128
+ ```
129
+
130
+ > **Open‑vocabulary is great for common/clear objects and hit‑or‑miss on unusual ones** (it does the easy 70–80%). For hard objects (e.g. missiles), hand‑label a first batch in `review`, `train` a model, then `detect --model your.pt` to auto‑label the rest.
131
+
132
+ ---
133
+
134
+ ### `review` — fix annotations in your browser
135
+
136
+ Launches a local web app (default: <http://127.0.0.1:7860>) to inspect and correct labels.
137
+
138
+ ```bash
139
+ magiclabel review IMAGES_DIR LABELS_DIR [--model yolov8n.pt]
140
+ ```
141
+
142
+ | Argument / Option | Description |
143
+ | ----------------- | --------------------------------------------------------------------------- |
144
+ | `IMAGES_DIR` | Directory of images |
145
+ | `LABELS_DIR` | Directory of YOLO `.txt` labels (and `classes.txt`) |
146
+ | `--model` | Model whose class names label the boxes (default `yolov8n.pt`). Use `--model none` to start a clean custom dataset with no preset names. |
147
+
148
+ **In the UI you can:**
149
+
150
+ - **Draw** a new box — click and drag on the image.
151
+ - **Move / resize** — click a box and drag it or its corner handles.
152
+ - **Set the class** — double‑click a box and **type any class name** (`missile`, `crack`, `logo`), then click the editor's apply/✓ to commit. New names are added automatically.
153
+ - **Delete** — the box's remove button, the <kbd>Delete</kbd> key, or **Clear All Boxes**.
154
+ - **Switch images** — the dropdown at the top (it opens on the first image that already has boxes).
155
+ - **Save Changes** — writes boxes back to the `.txt`; the view then reloads from disk so you can confirm exactly what was saved.
156
+
157
+ **Custom classes & `classes.txt`:** YOLO label files store integer class ids, so MagicLabel keeps a `classes.txt` (one name per line, id = line number) in your labels folder. Whatever name you type is mapped to a stable id behind the scenes, and new names are appended automatically. **That `classes.txt` is the class list you train on.**
158
+
159
+ > Edits live only in the browser until you click **Save Changes**. Saving an image with no boxes writes an empty label file (a valid "no objects" annotation).
160
+
161
+ ---
162
+
163
+ ### `train` — train your own model
164
+
165
+ Fine‑tunes a YOLO model on your labeled dataset and saves it as a named `.pt`.
166
+
167
+ ```bash
168
+ magiclabel train IMAGES_DIR LABELS_DIR [OPTIONS]
169
+ ```
170
+
171
+ | Option | Default | Description |
172
+ | -------------- | ------------- | ------------------------------------------------------ |
173
+ | `IMAGES_DIR` | _(required)_ | Directory of images |
174
+ | `LABELS_DIR` | _(required)_ | Directory of YOLO labels + `classes.txt` |
175
+ | `--name` | `custom.pt` | Output model name, e.g. `rohan.pt` |
176
+ | `--base` | `yolov8n.pt` | Base model to fine‑tune |
177
+ | `--epochs` | `50` | Training epochs |
178
+ | `--imgsz` | `640` | Training image size |
179
+ | `--val-split` | `0.2` | Fraction of images held out for validation |
180
+
181
+ **Example**
182
+
183
+ ```bash
184
+ magiclabel train ./images ./labels --name rohan.pt --epochs 100
185
+ # → rohan.pt (and a rohan_dataset/ folder with the train/val split + data.yaml)
186
+ ```
187
+
188
+ The command builds a proper YOLO dataset (train/val split + `data.yaml`) from your labels, trains, and copies the best weights to your named file. Use it anywhere a model is accepted:
189
+
190
+ ```bash
191
+ magiclabel detect ./new_images --model rohan.pt
192
+ ```
193
+
194
+ > A useful model needs **dozens‑to‑hundreds of labeled images** and enough epochs. On CPU this can be slow — a GPU is much faster. Start small to validate the pipeline, then scale your data.
195
+
196
+ ---
197
+
198
+ ### `yolo2coco` — convert labels to COCO JSON
199
+
200
+ ```bash
201
+ magiclabel yolo2coco IMAGES_DIR LABELS_DIR OUTPUT_JSON --class NAME [--class NAME ...]
202
+ ```
203
+
204
+ | Argument / Option | Description |
205
+ | ----------------- | --------------------------------------------------------- |
206
+ | `IMAGES_DIR` | Directory of images |
207
+ | `LABELS_DIR` | Directory of YOLO detection labels |
208
+ | `OUTPUT_JSON` | Path to write the COCO JSON file |
209
+ | `--class` | Class names **in class‑id order** (0, 1, 2, …), repeated |
210
+
211
+ ```bash
212
+ magiclabel yolo2coco ./images ./labels annotations.json \
213
+ --class person --class bicycle --class car
214
+ ```
215
+
216
+ ---
217
+
218
+ ### `export-classes` — list a model's class names
219
+
220
+ ```bash
221
+ magiclabel export-classes yolov8n.pt
222
+ # 0: person
223
+ # 1: bicycle
224
+ # 2: car
225
+ # ...
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Label format
231
+
232
+ MagicLabel reads and writes the **YOLO detection** format: one `.txt` per image, sharing the image's base name (`dog.jpg` → `dog.txt`). Each line is one box:
233
+
234
+ ```text
235
+ <class_id> <x_center> <y_center> <width> <height>
236
+ ```
237
+
238
+ All four coordinates are **normalized to 0–1** relative to the image size. Example:
239
+
240
+ ```text
241
+ 16 0.593846 0.400000 0.250769 0.258462
242
+ ```
243
+
244
+ A `classes.txt` alongside the labels maps each id to a name (id = line number).
245
+
246
+ ---
247
+
248
+ ## Tips & troubleshooting
249
+
250
+ - **Model downloads:** the first run of a new model downloads its weights into the current directory and reuses them after.
251
+ - **Speed:** detection is fast on CPU; training is much faster on a GPU (PyTorch uses CUDA/MPS automatically).
252
+ - **"No images found":** the source must be a directory containing images with a supported extension (`.jpg`, `.jpeg`, `.png`, `.bmp`, `.tif`, `.tiff`).
253
+ - **Port 7860 already in use:** an old review server is still running. Stop it with:
254
+ ```bash
255
+ kill $(lsof -nP -tiTCP:7860 -sTCP:LISTEN)
256
+ ```
257
+ - **Restart after changes:** the review server does not hot‑reload — stop it (<kbd>Ctrl</kbd>+<kbd>C</kbd>) and run `magiclabel review …` again.
258
+
259
+ ---
260
+
261
+ ## Project structure
262
+
263
+ ```text
264
+ magiclabel/
265
+ ├── cli.py # Typer CLI entry point (detect, review, train, yolo2coco, export-classes)
266
+ ├── annotator.py # YOLO / YOLO-World detection → label files + classes.txt
267
+ ├── review_app.py # Gradio review/annotation web app
268
+ ├── trainer.py # builds the dataset and trains a custom model
269
+ ├── convertor.py # YOLO → COCO conversion
270
+ └── utils.py # image discovery + helpers
271
+ ```
272
+
273
+ ---
274
+
275
+ ## License
276
+
277
+ Released under the [MIT License](LICENSE).
@@ -0,0 +1,2 @@
1
+ """magiclabel – Open‑source CLI tool for AI‑assisted image annotation."""
2
+ __version__ = "0.1.0"
@@ -0,0 +1,85 @@
1
+ import cv2
2
+ from pathlib import Path
3
+ from typing import List, Optional
4
+
5
+ from rich.progress import Progress
6
+
7
+ DEFAULT_CLOSED_MODEL = "yolov8n.pt" # closed-set: 80 COCO classes
8
+ DEFAULT_OPEN_VOCAB_MODEL = "yolov8s-world.pt" # open-vocabulary: detect anything from text
9
+
10
+
11
+ def detect_images(
12
+ source: Path,
13
+ output: Path,
14
+ conf: float,
15
+ prompt_classes: Optional[List[str]] = None,
16
+ model_name: Optional[str] = None,
17
+ ) -> dict:
18
+ """Auto-annotate every image in `source` with bounding boxes.
19
+
20
+ Two modes:
21
+ * closed-set (default): a normal YOLO model (e.g. yolov8n.pt) detects its
22
+ built-in classes (the 80 COCO objects).
23
+ * open-vocabulary: when `prompt_classes` is given, YOLO-World detects those
24
+ named objects with no training (e.g. ["missile", "launcher"]).
25
+
26
+ Writes one YOLO `.txt` per image plus a `classes.txt` (the class list, in id
27
+ order) into `output`. Returns a summary dict {classes, images, boxes}.
28
+ """
29
+ output = Path(output)
30
+ output.mkdir(parents=True, exist_ok=True)
31
+ images = _get_image_files(source)
32
+ if not images:
33
+ raise FileNotFoundError(f"No images found in {source}")
34
+
35
+ if prompt_classes:
36
+ from ultralytics import YOLOWorld
37
+ detector = YOLOWorld(model_name or DEFAULT_OPEN_VOCAB_MODEL)
38
+ class_names = [c.strip() for c in prompt_classes if c.strip()]
39
+ if not class_names:
40
+ raise ValueError("No class names given in --prompt")
41
+ detector.set_classes(class_names)
42
+ else:
43
+ from ultralytics import YOLO
44
+ detector = YOLO(model_name or DEFAULT_CLOSED_MODEL)
45
+ class_names = [detector.names[i] for i in sorted(detector.names)]
46
+
47
+ total_boxes = 0
48
+ with Progress() as progress:
49
+ task = progress.add_task("Detecting...", total=len(images))
50
+ for img_path in images:
51
+ results = detector.predict(img_path, conf=conf, verbose=False)
52
+ boxes = results[0].boxes
53
+ if boxes is not None and len(boxes) > 0:
54
+ cls_ids = boxes.cls.int().tolist()
55
+ xyxy = boxes.xyxy.tolist()
56
+ abs_boxes = [[x1, y1, x2 - x1, y2 - y1] for x1, y1, x2, y2 in xyxy]
57
+ img = cv2.imread(str(img_path))
58
+ h, w = img.shape[:2]
59
+ _save_yolo_boxes(output / f"{img_path.stem}.txt", abs_boxes, cls_ids, w, h)
60
+ total_boxes += len(abs_boxes)
61
+ progress.advance(task)
62
+
63
+ _write_classes_file(output, class_names)
64
+ return {"classes": class_names, "images": len(images), "boxes": total_boxes}
65
+
66
+
67
+ def _save_yolo_boxes(txt_path, boxes, classes, img_w, img_h):
68
+ with open(txt_path, "w") as f:
69
+ for box, cls in zip(boxes, classes):
70
+ x, y, w_box, h_box = box
71
+ xc = (x + w_box / 2) / img_w
72
+ yc = (y + h_box / 2) / img_h
73
+ nw = w_box / img_w
74
+ nh = h_box / img_h
75
+ f.write(f"{cls} {xc:.6f} {yc:.6f} {nw:.6f} {nh:.6f}\n")
76
+
77
+
78
+ def _write_classes_file(output, class_names):
79
+ """Write the class list (one name per line, id == line index) for review/training."""
80
+ (Path(output) / "classes.txt").write_text("\n".join(class_names) + "\n")
81
+
82
+
83
+ def _get_image_files(source):
84
+ from magiclabel.utils import get_image_files
85
+ return get_image_files(source)