drawbox-cv 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,145 @@
1
+ Metadata-Version: 2.4
2
+ Name: drawbox-cv
3
+ Version: 0.1.0
4
+ Summary: A modular, interactive bounding box frame labeler with zoom and pan support.
5
+ License: MIT
6
+ Requires-Python: >=3.8
7
+ Requires-Dist: numpy>=1.20.0
8
+ Requires-Dist: opencv-python>=4.8.0.0
9
+ Requires-Dist: pillow>=10.0.0
10
+ Description-Content-Type: text/markdown
11
+
12
+ # DrawBox-CV
13
+
14
+ A modular, cross-platform, Tkinter-based interactive frame annotator for computer vision datasets.
15
+
16
+ This tool is designed to work like a desktop-based, lightweight **Roboflow** editor, enabling real-time frame-by-frame labeling with mouse zoom and pan, dynamic color mapping, unlimited custom classes, and multi-format labels export.
17
+
18
+ ---
19
+
20
+ ## Key Features
21
+
22
+ - **Tkinter GUI Engine**: Replaces raw OpenCV windows with a robust Tkinter interface that natively supports resizing to fit any monitor resolution.
23
+ - **Dynamic Zoom & Pan**:
24
+ - **Zoom**: Scroll wheel (zoom is centered directly around your mouse cursor).
25
+ - **Pan**: Middle-mouse drag (click and drag the wheel).
26
+ - **Roboflow-Style Editing**: Always in editing mode! No need to toggle modes.
27
+ - **Draw**: Left-click and drag on an empty area.
28
+ - **Move**: Left-click and drag inside an existing box.
29
+ - **Resize**: Left-click and drag the white corner handles.
30
+ - **Delete**: Right-click any box, or press `Delete`/`Backspace` key on selected box.
31
+ - **Undo**: Press `Ctrl+Z` to undo the last drawn box.
32
+ - **Unlimited Custom Classes**: Neglects the old 0-9 class limit. You can add new classes dynamically via the sidebar.
33
+ - **Dynamic Color Assignments**: Automatically generates visually distinct, high-contrast colors using the Golden Ratio in HSV space for every new class.
34
+ - **Flexible Multi-Format Exports**: Saves bounding box annotations to any combination of formats simultaneously:
35
+ - **YOLO**: Saves as standard `.txt` files with normalized `[class_id, x_center, y_center, width, height]` format.
36
+ - **COCO**: Updates a single unified `annotations.json` file inside the COCO subdirectory.
37
+ - **Pascal VOC**: Saves standard XML annotation documents.
38
+ - **TF**: Saves custom normalized `[class_id, xmin, ymin, xmax, ymax]` text files.
39
+ - **Optional Object Cropping**: Crop bounding boxes and save them into directories categorized by class names.
40
+
41
+ ---
42
+
43
+ ## Professional Package Structure
44
+
45
+ This library uses the industry-standard `src` layout for Python packaging:
46
+
47
+ ```
48
+ New/
49
+ ├── pyproject.toml # Build backend and dependencies (using >= versions)
50
+ ├── README.md # Installation & usage guide
51
+ └── src/
52
+ └── drawbox/ # Package root for 'import drawbox'
53
+ ├── __init__.py # Package entry points
54
+ ├── __main__.py # Interactive CLI runner
55
+ ├── app.py # Tkinter main GUI window
56
+ ├── canvas.py # Zoom/Pan interactive canvas
57
+ ├── dataset.py # Images/crops dataset orchestrator
58
+ ├── box.py # Bounding box coordinates translation
59
+ ├── classes.py # ClassRegistry management
60
+ ├── config.py # Custom output path configuration
61
+ ├── colors.py # Golden ratio HSV color generator
62
+ └── formats/ # Exporters subpackage
63
+ ├── __init__.py # Registry and registry helpers
64
+ ├── base.py # Abstract base format class
65
+ ├── coco_format.py # COCO dataset writer
66
+ ├── tf_format.py # TF layout exporter
67
+ ├── voc_format.py # Pascal VOC XML exporter
68
+ └── yolo_format.py # YOLO annotation exporter
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Installation & Setup
74
+
75
+ Ensure you have Python 3.8 or newer installed on your system.
76
+
77
+ ### 1. Install System Prerequisites (Linux Only)
78
+ On Linux systems (e.g., Ubuntu/Debian), Tkinter requires system-level libraries. Install them via your package manager:
79
+ ```bash
80
+ sudo apt update
81
+ sudo apt install python3-tk
82
+ ```
83
+ *(Windows and macOS include Tkinter by default during Python installation).*
84
+
85
+ ### 2. Install from Local Code
86
+ Navigate to the root directory where `pyproject.toml` is located (the `New/` directory) and run:
87
+ ```bash
88
+ pip install .
89
+ ```
90
+ This automatically installs the package `drawbox-cv` along with all necessary dependencies (`opencv-python`, `pillow`, `numpy`) matching version compatibility (`>=`).
91
+
92
+ For development (changes in code will reflect immediately), install it in editable mode:
93
+ ```bash
94
+ pip install -e .
95
+ ```
96
+
97
+ ---
98
+
99
+ ## How to Run
100
+
101
+ Once installed, you can launch the app from any folder in your terminal simply by typing:
102
+ ```bash
103
+ drawbox
104
+ ```
105
+
106
+ Alternatively, you can run the package directly from source without installation:
107
+ ```bash
108
+ python -m src.drawbox
109
+ ```
110
+
111
+ ### Walkthrough of Interactive Prompts:
112
+ 1. **Input frames directory path**: Path to the folder containing your source images (`.jpg`, `.png`, etc.).
113
+ 2. **Base output directory path**: Path to where you want all results to be saved (e.g., `output`). Default is `output`.
114
+ 3. **Starting frame index**: Frame number to start labeling from (default: `0`).
115
+ 4. **Initial label file path**: If you have a file with initial labels (e.g., `temp.txt`), provide the path. Press Enter to skip.
116
+ 5. **Output format(s)**: Comma-separated list of formats you wish to save. For example, `yolo,coco` or `tf,yolo,voc`. Default is `yolo`.
117
+ 6. **Carry over edited labels**: Carry labels from the previous frame to the next (`y`/`n`).
118
+ 7. **Save cropped bounding boxes**: Crop objects and save them under separate subdirectories for each class (`y`/`n`).
119
+
120
+ ---
121
+
122
+ ## Output Layout
123
+
124
+ All files are structured inside your specified base output directory (e.g. `output`):
125
+ - `output/classes.txt`: Contains your class list ordered by class ID.
126
+ - `output/<format_name>/`: Specific folder for each selected label format containing the annotations (e.g., `output/yolo/`, `output/voc/`). Labels match your original frame file names (e.g. `image_1.txt`, `image_1.xml`).
127
+ - `Crops folder` (either `output/crops/` or your custom folder): Subfolders (e.g. `0_class_0/`) containing crop PNGs.
128
+
129
+ ---
130
+
131
+ ## Keyboard Shortcuts Map
132
+
133
+ | Key | Description |
134
+ | --- | --- |
135
+ | **`s` / `S`** / **`Enter`** | Save labels and move to **Next** frame |
136
+ | **`k` / `K`** / **`Right Arrow`** / **`Down Arrow`** | Skip current frame without saving, and move to **Next** frame |
137
+ | **`a` / **`Left Arrow`** / **`Up Arrow`** | Move back to **Previous** frame |
138
+ | **`f` / `F`** | Center and fit the image to the window size |
139
+ | **`Ctrl + Z`** | Undo the last change |
140
+ | **`Ctrl + Shift + Z`** | Redo the last change |
141
+ | **`r`** | Copy previous frame's labels to current frame |
142
+ | **`Ctrl + Left Click`** | Select bounding box and its class label (draws box inside box easily) |
143
+ | **`Delete` / `Backspace`** | Delete the currently selected bounding box |
144
+ | **`0` – `9`** | Quick-select corresponding class IDs |
145
+ | **`q` / `Esc`** | Close window and exit app |
@@ -0,0 +1,134 @@
1
+ # DrawBox-CV
2
+
3
+ A modular, cross-platform, Tkinter-based interactive frame annotator for computer vision datasets.
4
+
5
+ This tool is designed to work like a desktop-based, lightweight **Roboflow** editor, enabling real-time frame-by-frame labeling with mouse zoom and pan, dynamic color mapping, unlimited custom classes, and multi-format labels export.
6
+
7
+ ---
8
+
9
+ ## Key Features
10
+
11
+ - **Tkinter GUI Engine**: Replaces raw OpenCV windows with a robust Tkinter interface that natively supports resizing to fit any monitor resolution.
12
+ - **Dynamic Zoom & Pan**:
13
+ - **Zoom**: Scroll wheel (zoom is centered directly around your mouse cursor).
14
+ - **Pan**: Middle-mouse drag (click and drag the wheel).
15
+ - **Roboflow-Style Editing**: Always in editing mode! No need to toggle modes.
16
+ - **Draw**: Left-click and drag on an empty area.
17
+ - **Move**: Left-click and drag inside an existing box.
18
+ - **Resize**: Left-click and drag the white corner handles.
19
+ - **Delete**: Right-click any box, or press `Delete`/`Backspace` key on selected box.
20
+ - **Undo**: Press `Ctrl+Z` to undo the last drawn box.
21
+ - **Unlimited Custom Classes**: Neglects the old 0-9 class limit. You can add new classes dynamically via the sidebar.
22
+ - **Dynamic Color Assignments**: Automatically generates visually distinct, high-contrast colors using the Golden Ratio in HSV space for every new class.
23
+ - **Flexible Multi-Format Exports**: Saves bounding box annotations to any combination of formats simultaneously:
24
+ - **YOLO**: Saves as standard `.txt` files with normalized `[class_id, x_center, y_center, width, height]` format.
25
+ - **COCO**: Updates a single unified `annotations.json` file inside the COCO subdirectory.
26
+ - **Pascal VOC**: Saves standard XML annotation documents.
27
+ - **TF**: Saves custom normalized `[class_id, xmin, ymin, xmax, ymax]` text files.
28
+ - **Optional Object Cropping**: Crop bounding boxes and save them into directories categorized by class names.
29
+
30
+ ---
31
+
32
+ ## Professional Package Structure
33
+
34
+ This library uses the industry-standard `src` layout for Python packaging:
35
+
36
+ ```
37
+ New/
38
+ ├── pyproject.toml # Build backend and dependencies (using >= versions)
39
+ ├── README.md # Installation & usage guide
40
+ └── src/
41
+ └── drawbox/ # Package root for 'import drawbox'
42
+ ├── __init__.py # Package entry points
43
+ ├── __main__.py # Interactive CLI runner
44
+ ├── app.py # Tkinter main GUI window
45
+ ├── canvas.py # Zoom/Pan interactive canvas
46
+ ├── dataset.py # Images/crops dataset orchestrator
47
+ ├── box.py # Bounding box coordinates translation
48
+ ├── classes.py # ClassRegistry management
49
+ ├── config.py # Custom output path configuration
50
+ ├── colors.py # Golden ratio HSV color generator
51
+ └── formats/ # Exporters subpackage
52
+ ├── __init__.py # Registry and registry helpers
53
+ ├── base.py # Abstract base format class
54
+ ├── coco_format.py # COCO dataset writer
55
+ ├── tf_format.py # TF layout exporter
56
+ ├── voc_format.py # Pascal VOC XML exporter
57
+ └── yolo_format.py # YOLO annotation exporter
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Installation & Setup
63
+
64
+ Ensure you have Python 3.8 or newer installed on your system.
65
+
66
+ ### 1. Install System Prerequisites (Linux Only)
67
+ On Linux systems (e.g., Ubuntu/Debian), Tkinter requires system-level libraries. Install them via your package manager:
68
+ ```bash
69
+ sudo apt update
70
+ sudo apt install python3-tk
71
+ ```
72
+ *(Windows and macOS include Tkinter by default during Python installation).*
73
+
74
+ ### 2. Install from Local Code
75
+ Navigate to the root directory where `pyproject.toml` is located (the `New/` directory) and run:
76
+ ```bash
77
+ pip install .
78
+ ```
79
+ This automatically installs the package `drawbox-cv` along with all necessary dependencies (`opencv-python`, `pillow`, `numpy`) matching version compatibility (`>=`).
80
+
81
+ For development (changes in code will reflect immediately), install it in editable mode:
82
+ ```bash
83
+ pip install -e .
84
+ ```
85
+
86
+ ---
87
+
88
+ ## How to Run
89
+
90
+ Once installed, you can launch the app from any folder in your terminal simply by typing:
91
+ ```bash
92
+ drawbox
93
+ ```
94
+
95
+ Alternatively, you can run the package directly from source without installation:
96
+ ```bash
97
+ python -m src.drawbox
98
+ ```
99
+
100
+ ### Walkthrough of Interactive Prompts:
101
+ 1. **Input frames directory path**: Path to the folder containing your source images (`.jpg`, `.png`, etc.).
102
+ 2. **Base output directory path**: Path to where you want all results to be saved (e.g., `output`). Default is `output`.
103
+ 3. **Starting frame index**: Frame number to start labeling from (default: `0`).
104
+ 4. **Initial label file path**: If you have a file with initial labels (e.g., `temp.txt`), provide the path. Press Enter to skip.
105
+ 5. **Output format(s)**: Comma-separated list of formats you wish to save. For example, `yolo,coco` or `tf,yolo,voc`. Default is `yolo`.
106
+ 6. **Carry over edited labels**: Carry labels from the previous frame to the next (`y`/`n`).
107
+ 7. **Save cropped bounding boxes**: Crop objects and save them under separate subdirectories for each class (`y`/`n`).
108
+
109
+ ---
110
+
111
+ ## Output Layout
112
+
113
+ All files are structured inside your specified base output directory (e.g. `output`):
114
+ - `output/classes.txt`: Contains your class list ordered by class ID.
115
+ - `output/<format_name>/`: Specific folder for each selected label format containing the annotations (e.g., `output/yolo/`, `output/voc/`). Labels match your original frame file names (e.g. `image_1.txt`, `image_1.xml`).
116
+ - `Crops folder` (either `output/crops/` or your custom folder): Subfolders (e.g. `0_class_0/`) containing crop PNGs.
117
+
118
+ ---
119
+
120
+ ## Keyboard Shortcuts Map
121
+
122
+ | Key | Description |
123
+ | --- | --- |
124
+ | **`s` / `S`** / **`Enter`** | Save labels and move to **Next** frame |
125
+ | **`k` / `K`** / **`Right Arrow`** / **`Down Arrow`** | Skip current frame without saving, and move to **Next** frame |
126
+ | **`a` / **`Left Arrow`** / **`Up Arrow`** | Move back to **Previous** frame |
127
+ | **`f` / `F`** | Center and fit the image to the window size |
128
+ | **`Ctrl + Z`** | Undo the last change |
129
+ | **`Ctrl + Shift + Z`** | Redo the last change |
130
+ | **`r`** | Copy previous frame's labels to current frame |
131
+ | **`Ctrl + Left Click`** | Select bounding box and its class label (draws box inside box easily) |
132
+ | **`Delete` / `Backspace`** | Delete the currently selected bounding box |
133
+ | **`0` – `9`** | Quick-select corresponding class IDs |
134
+ | **`q` / `Esc`** | Close window and exit app |
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "drawbox-cv"
7
+ version = "0.1.0"
8
+ description = "A modular, interactive bounding box frame labeler with zoom and pan support."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = {text = "MIT"}
12
+ dependencies = [
13
+ "opencv-python>=4.8.0.0",
14
+ "pillow>=10.0.0",
15
+ "numpy>=1.20.0",
16
+ ]
17
+
18
+ [project.scripts]
19
+ drawbox = "drawbox.__main__:main"
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ packages = ["src/drawbox"]
@@ -0,0 +1,7 @@
1
+ from .app import AnnotatorApp
2
+ from .config import AnnotatorConfig
3
+ from .dataset import Dataset
4
+ from .box import BoundingBox
5
+ from .classes import ClassRegistry
6
+
7
+ __all__ = ["AnnotatorApp", "AnnotatorConfig", "Dataset", "BoundingBox", "ClassRegistry"]
@@ -0,0 +1,67 @@
1
+ from __future__ import annotations
2
+ import sys
3
+ from .app import AnnotatorApp
4
+ from .config import AnnotatorConfig
5
+
6
+ def main():
7
+ # Prompt the user for parameters like the original script
8
+ frames_dir = input("Enter input frames directory path: ").strip()
9
+ if not frames_dir:
10
+ print("Error: Input frames directory path is required.")
11
+ sys.exit(1)
12
+
13
+ output_dir = input("Enter base output directory path (default: output): ").strip()
14
+ if not output_dir:
15
+ output_dir = "output"
16
+
17
+ start_frame = input("Enter starting frame index (default: 0): ").strip()
18
+ start_frame = int(start_frame) if start_frame.isdigit() else 0
19
+
20
+ init_lbl = input("Enter initial label file path (optional, press Enter to skip): ").strip()
21
+ init_fmt = "tf"
22
+ if init_lbl:
23
+ init_fmt = input("Enter format of initial label (tf, yolo, coco, voc) (default: tf): ").strip().lower()
24
+ if not init_fmt:
25
+ init_fmt = "tf"
26
+
27
+ # Flexible multi-format selection
28
+ formats_in = input("Enter output format(s) comma-separated (tf, yolo, coco, voc) (default: yolo): ").strip().lower()
29
+ if not formats_in:
30
+ formats = ["yolo"]
31
+ else:
32
+ formats = [f.strip() for f in formats_in.split(",") if f.strip()]
33
+
34
+ # Validate selected formats
35
+ valid_formats = {"tf", "yolo", "coco", "voc"}
36
+ invalid_formats = [f for f in formats if f not in valid_formats]
37
+ if invalid_formats:
38
+ print(f"Error: Invalid format(s) selected: {', '.join(invalid_formats)}")
39
+ print(f"Supported formats are: {', '.join(valid_formats)}")
40
+ sys.exit(1)
41
+
42
+ carry_over = input("Carry over edited labels to subsequent frames? (y/n) (default: y): ").strip().lower() != "n"
43
+ save_crops = input("Save cropped bounding boxes? (y/n) (default: n): ").strip().lower() == "y"
44
+
45
+ crops_dir = None
46
+ if save_crops:
47
+ crops_dir = input("Enter directory path to save crops (default: output/crops): ").strip()
48
+ if not crops_dir:
49
+ crops_dir = None
50
+
51
+ config = AnnotatorConfig(
52
+ frames_dir=frames_dir,
53
+ output_dir=output_dir,
54
+ start_frame=start_frame,
55
+ initial_label_file=init_lbl,
56
+ initial_label_format=init_fmt,
57
+ formats=formats,
58
+ save_crops=save_crops,
59
+ crops_out_dir=crops_dir,
60
+ carry_over_labels=carry_over,
61
+ )
62
+
63
+ app = AnnotatorApp(config)
64
+ app.mainloop()
65
+
66
+ if __name__ == "__main__":
67
+ main()