# Custom Annotation GUI A simple, **fully customizable** annotation tool built with Gradio (pure Python). ## Features ✅ **Auto-labeling** with your trained RF-DETR model ✅ **Manual annotation** by entering box coordinates ✅ **Edit/delete** annotations easily ✅ **Navigation** between images ✅ **Export** to COCO JSON format ✅ **100% Python** - easy to modify and extend ## Quick Start ### 1. Install dependencies ```bash /home/dillon/_code/saw_mill_knot_detection/.venv/bin/python -m pip install gradio>=4.0.0 ``` ### 2. Run the GUI **With auto-labeling (requires trained model):** ```bash /home/dillon/_code/saw_mill_knot_detection/.venv/bin/python annotation_gui.py \ --images-dir /path/to/images \ --model-weights runs/knot_rfdetr_medium/checkpoint_best_total.pth ``` **Manual annotation only:** ```bash /home/dillon/_code/saw_mill_knot_detection/.venv/bin/python annotation_gui.py \ --images-dir /path/to/images ``` ### 3. Open in browser Opens automatically at http://localhost:7860 ## Usage 1. **Auto-Label**: Click "🤖 Auto-Label" to detect knots with your model 2. **Adjust threshold**: Lower = more detections, Higher = only confident ones 3. **Manual boxes**: Enter coordinates (x1, y1, x2, y2) and click "➕ Add Box" 4. **Delete mistakes**: Click "🗑️ Delete Last" to remove last box 5. **Navigate**: Use "Previous" / "Next" buttons 6. **Export**: Click "💾 Export COCO" when done ## Customization Examples ### Add keyboard shortcuts ```python # In create_ui(), add: image_display.keyboard_shortcuts = { "d": delete_btn.click, # Press 'd' to delete "n": next_btn.click, # Press 'n' for next } ``` ### Add interactive drawing ```python # Replace manual coordinates with image annotator: from gradio_image_annotation import image_annotator annotator = image_annotator( label="Draw boxes", type="numpy" ) ``` ### Change box colors by confidence ```python # In draw_boxes_on_image(): color = "green" if conf > 0.8 else "yellow" if conf > 0.5 else "red" draw.rectangle([x1, y1, x2, y2], outline=color, width=3) ``` ### Add multiple label classes ```python # Add a dropdown: label_choice = gr.Dropdown( choices=["knot", "crack", "hole"], value="knot", label="Label Type" ) # Update box dict: box = { "bbox": [x1, y1, x2, y2], "label": label_choice_value, # from the dropdown "confidence": 1.0 } ``` ### Save checkpoints automatically ```python # In _save_annotations(), add: import shutil backup_path = self.ann_file.with_suffix('.backup.json') shutil.copy(self.ann_file, backup_path) ``` ### Add image filters/preprocessing ```python # Add before annotation: def preprocess_image(img: Image.Image) -> Image.Image: from PIL import ImageEnhance enhancer = ImageEnhance.Contrast(img) return enhancer.enhance(1.5) # Increase contrast ``` ## File Structure ``` annotation_gui.py ├── AnnotationApp # Main logic (easy to extend) │ ├── auto_label_current() # Modify for different models │ ├── add_box_manual() # Customize annotation format │ ├── export_to_coco() # Change export format │ └── draw_boxes_on_image() # Customize visualization └── create_ui() # Gradio interface (add components) ``` ## Advantages vs Label Studio | Feature | Custom GUI | Label Studio | |---------|-----------|--------------| | **Modify code** | ✅ Easy (pure Python) | ❌ Complex (React + Python) | | **Add features** | ✅ ~10-50 lines | ❌ Hundreds of lines | | **Custom models** | ✅ Direct integration | ⚠️ Need ONNX export | | **Learning curve** | ✅ Simple Gradio | ⚠️ Larger codebase | | **Setup** | ✅ pip install | ⚠️ Docker/complex | ## Troubleshooting **Port already in use:** ```bash python annotation_gui.py --images-dir /path --port 7861 ``` **Model not loading:** - Check the weights path exists - Verify it's a valid checkpoint file - Try without `--model-weights` for manual-only mode **Need more features?** - Check Gradio docs: https://www.gradio.app/docs/ - Add custom components easily - Fork and modify the code freely!