imagebaker 0.0.50__tar.gz → 0.0.53__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.
- {imagebaker-0.0.50 → imagebaker-0.0.53}/.gitignore +1 -0
- imagebaker-0.0.53/CONTRIBUTING +5 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/PKG-INFO +24 -11
- {imagebaker-0.0.50 → imagebaker-0.0.53}/README.md +24 -11
- imagebaker-0.0.53/docs/index.md +136 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/examples/loaded_models.py +26 -26
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/core/configs/configs.py +17 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/core/defs/defs.py +10 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/layers/annotable_layer.py +93 -16
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/layers/base_layer.py +9 -1
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/layers/canvas_layer.py +29 -6
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/list_views/annotation_list.py +4 -2
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/list_views/image_list.py +26 -8
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/list_views/layer_settings.py +29 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/tabs/baker_tab.py +49 -1
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/tabs/layerify_tab.py +275 -49
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/utils/image.py +9 -6
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/utils/state_utils.py +1 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/window/main_window.py +77 -6
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/workers/baker_worker.py +22 -3
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker.egg-info/PKG-INFO +24 -11
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker.egg-info/SOURCES.txt +1 -0
- imagebaker-0.0.50/docs/index.md +0 -87
- {imagebaker-0.0.50 → imagebaker-0.0.53}/.github/workflows/black-formatter.yml +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/.github/workflows/pypi.yml +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/CHANGELOG.md +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/LICENSE +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/TODO.md +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/demo/annotated_veg_smiley.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/demo/annotation_page.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/demo/baker_page.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/demo/drawing.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/demo/options.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/demo.gif +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/desk.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/favicon_io/README.md +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/favicon_io/android-chrome-192x192.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/favicon_io/android-chrome-512x512.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/favicon_io/apple-touch-icon.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/favicon_io/favicon-16x16.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/favicon_io/favicon-32x32.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/favicon_io/favicon.ico +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/favicon_io/site.webmanifest +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/me.jpg +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/pen.png +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/assets/veg_smiley.jpg +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/docs/api-reference.md +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/examples/app.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/examples/example_config.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/examples/rtdetr_v2.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/examples/sam_model.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/examples/segmentation.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/experiments/expt.ipynb +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/core/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/core/configs/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/core/defs/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/core/plugins/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/core/plugins/base_plugin.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/core/plugins/cosine_plugin.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/layers/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/list_views/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/list_views/canvas_list.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/list_views/layer_list.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/models/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/models/base_model.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/tabs/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/utils/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/utils/transform_mask.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/utils/utils.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/utils/vis.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/window/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/window/app.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/workers/__init__.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/workers/layerify_worker.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker/workers/model_worker.py +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker.egg-info/dependency_links.txt +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker.egg-info/entry_points.txt +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker.egg-info/requires.txt +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/imagebaker.egg-info/top_level.txt +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/mkdocs.yml +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/requirements.txt +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/setup.cfg +0 -0
- {imagebaker-0.0.50 → imagebaker-0.0.53}/setup.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: imagebaker
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.53
|
4
4
|
Summary: A package for baking images.
|
5
5
|
Home-page: https://github.com/q-viper/Image-Baker
|
6
6
|
Author: Ramkrishna Acharya
|
@@ -24,7 +24,7 @@ License-File: LICENSE
|
|
24
24
|
[](https://pypi.org/imagebaker/)
|
25
25
|
|
26
26
|
<p align="center">
|
27
|
-
<img src="assets/demo.gif" alt="Centered Demo" />
|
27
|
+
<img src="https://github.com/q-viper/image-baker/blob/main/assets/demo.gif?raw=true" alt="Centered Demo" />
|
28
28
|
</p>
|
29
29
|
|
30
30
|
|
@@ -62,27 +62,28 @@ Run the following command to launch the GUI:
|
|
62
62
|
|
63
63
|
`imagebaker`
|
64
64
|
|
65
|
-
By default, the above command will not run any models on the backend. So please take a look into the example of model definition at [examples/loaded_models.py](examples/loaded_models.py). Then we need to pass it as:
|
65
|
+
By default, the above command will not run any models on the backend. So please take a look into the example of model definition at [examples/loaded_models.py](https://github.com/q-viper/image-baker/blob/main/examples/loaded_models.py). Then we need to pass it as:
|
66
66
|
|
67
67
|
`imagebaker --models-file examples/loaded_models.py`
|
68
68
|
|
69
69
|
For more options, please do: `imagebaker --help` It should give the following options.
|
70
70
|
|
71
|
-

|
71
|
+

|
72
72
|
|
73
73
|
|
74
|
-
* **`--configs-file`** allows us to define custom configs. The custom configs have to inherit LayerConfig and CanvasConfig defined at [imagebaker/core/configs/configs.py](imagebaker/core/configs/configs.py). An example is available at [examples](examples/).
|
74
|
+
* **`--configs-file`** allows us to define custom configs. The custom configs have to inherit LayerConfig and CanvasConfig defined at [imagebaker/core/configs/configs.py](https://github.com/q-viper/image-baker/blob/main/imagebaker/core/configs/configs.py). An example is available at [examples](https://github.com/q-viper/image-baker/blob/main/examples/).
|
75
75
|
|
76
76
|
After cloning and going to the project directory, the following code should work.
|
77
77
|
`imagebaker --models-file examples/loaded_models.py --configs-file examples/example_config.py`
|
78
78
|
|
79
79
|
## Features
|
80
80
|
- **Annotating Images**: Load a folder of images and annotate them using bounding boxes or polygons.
|
81
|
-
- **Model Testing**: Define models for detection, segmentation, and prompts (e.g., points or rectangles) by following the base model structure in [imagebaker/models/base_model.py](imagebaker/models/base_model.py). See [examples/loaded_models.py](examples/loaded_models.py) for a working example.
|
81
|
+
- **Model Testing**: Define models for detection, segmentation, and prompts (e.g., points or rectangles) by following the base model structure in [imagebaker/models/base_model.py](https://github.com/q-viper/image-baker/blob/main/imagebaker/models/base_model.py). See [examples/loaded_models.py](https://github.com/q-viper/image-baker/blob/main/examples/loaded_models.py) for a working example.
|
82
82
|
- **Layerifying**: Crop images based on annotations to create reusable layers. Each cropped image represents a single layer.
|
83
83
|
- **Baking States**: Arrange layers to create image variations by dragging, rotating, adjusting opacity, and more. Save the state using the Save State button or Ctrl + S.
|
84
84
|
- **Playing States**: Replay saved states, export them locally, or use them for further predictions.
|
85
85
|
- **Exporting States**: Export the final annotated JSON and the baked multilayer image.
|
86
|
+
- **Drawing On Layers**: First select a layer then draw upon it. Only selected layer will be drawn. And if no layers are selected, then the drawing will not be exported.
|
86
87
|
|
87
88
|
### Shortcuts
|
88
89
|
* **Ctrl + C**: Copy selected annotation/layer.
|
@@ -91,34 +92,44 @@ After cloning and going to the project directory, the following code should work
|
|
91
92
|
* **Left Click**: Select an annotation/layer on mouse position.
|
92
93
|
* **Left Click + Drag**: Drag a selected annotation/layer.
|
93
94
|
* **Double Left Click**: When using polygon annotation, completes the polygon.
|
94
|
-
* **Right Click**:
|
95
|
+
* **Right Click**: Unselect an annotation/layer. While annotating the polygon, undo the last point.
|
95
96
|
* **Ctrl + Mouse Wheel**: Zoom In/Out on the mouse position, i.e., resize the viewport.
|
96
97
|
* **Ctrl + Drag**: If done on the background, the viewport is panned.
|
97
98
|
* **Ctrl + S**: Save State on Baker Tab.
|
98
99
|
* **Ctrl + D**: Draw Mode on Baker Tab. Drawing can happen on a selected or main layer.
|
99
100
|
* **Ctrl + E**: Erase Mode on Baker Tab.
|
101
|
+
* **Ctrl + H**: Opens a help window.
|
100
102
|
* **Wheel**: Change the size of the drawing pointer.
|
103
|
+
* **Q**: Point mode on annotation.
|
104
|
+
* **W**: Polygon mode on annotation. Moves selected layer one step up in layer lists in baker.
|
105
|
+
* **S**: Moves selected layer one step down in layer list in baker.
|
106
|
+
* **E**: Rectangle mode on annotation.
|
107
|
+
* **H**: Hides/un-hides selected annotation/layer.
|
108
|
+
* **L**: Creates layer from an annotation. If any annotation selected, creates only its, else creates layers from all visible annotations.
|
109
|
+
* **C**: If any annotation is selected, a input box for Caption is created. It can be edited on baker tab as well and is state aware.
|
110
|
+
* **Numerics**: Selecting number 1, 2, till 9 selects label. If not available, asks for a new label.
|
111
|
+
* **Escape**: Closes the application.
|
101
112
|
|
102
113
|
## Demo
|
103
114
|
### Annotation Page
|
104
115
|
This is where the loading of the image folder and annotation, connection with the model running in the backend, and layerifying happen.
|
105
116
|
|
106
|
-

|
117
|
+

|
107
118
|
|
108
119
|
### Baker Page
|
109
120
|
This is where the layer baking happens. And the extraction of the layers as well.
|
110
121
|
|
111
|
-

|
122
|
+

|
112
123
|
|
113
124
|
An example of drawing:
|
114
125
|
|
115
|
-

|
126
|
+

|
116
127
|
|
117
128
|
### Annotated
|
118
129
|
|
119
130
|
The JSON and the baked image will be exported to the local folder, and in debug mode, the annotations and the mask for each layer will be exported too.
|
120
131
|
|
121
|
-

|
132
|
+

|
122
133
|
|
123
134
|
### Demo Video
|
124
135
|
|
@@ -137,3 +148,5 @@ Click on the image above to play the video on YouTube.
|
|
137
148
|
Contributions are welcome!
|
138
149
|
|
139
150
|
Do you find this project to be useful and are you looking for some features that are not implemented yet? Feel free to open issues or submit pull requests to improve the project.
|
151
|
+
|
152
|
+
For more please visit [CONTRIBUTING](CONTRIBUTING).
|
@@ -8,7 +8,7 @@
|
|
8
8
|
[](https://pypi.org/imagebaker/)
|
9
9
|
|
10
10
|
<p align="center">
|
11
|
-
<img src="assets/demo.gif" alt="Centered Demo" />
|
11
|
+
<img src="https://github.com/q-viper/image-baker/blob/main/assets/demo.gif?raw=true" alt="Centered Demo" />
|
12
12
|
</p>
|
13
13
|
|
14
14
|
|
@@ -46,27 +46,28 @@ Run the following command to launch the GUI:
|
|
46
46
|
|
47
47
|
`imagebaker`
|
48
48
|
|
49
|
-
By default, the above command will not run any models on the backend. So please take a look into the example of model definition at [examples/loaded_models.py](examples/loaded_models.py). Then we need to pass it as:
|
49
|
+
By default, the above command will not run any models on the backend. So please take a look into the example of model definition at [examples/loaded_models.py](https://github.com/q-viper/image-baker/blob/main/examples/loaded_models.py). Then we need to pass it as:
|
50
50
|
|
51
51
|
`imagebaker --models-file examples/loaded_models.py`
|
52
52
|
|
53
53
|
For more options, please do: `imagebaker --help` It should give the following options.
|
54
54
|
|
55
|
-

|
55
|
+

|
56
56
|
|
57
57
|
|
58
|
-
* **`--configs-file`** allows us to define custom configs. The custom configs have to inherit LayerConfig and CanvasConfig defined at [imagebaker/core/configs/configs.py](imagebaker/core/configs/configs.py). An example is available at [examples](examples/).
|
58
|
+
* **`--configs-file`** allows us to define custom configs. The custom configs have to inherit LayerConfig and CanvasConfig defined at [imagebaker/core/configs/configs.py](https://github.com/q-viper/image-baker/blob/main/imagebaker/core/configs/configs.py). An example is available at [examples](https://github.com/q-viper/image-baker/blob/main/examples/).
|
59
59
|
|
60
60
|
After cloning and going to the project directory, the following code should work.
|
61
61
|
`imagebaker --models-file examples/loaded_models.py --configs-file examples/example_config.py`
|
62
62
|
|
63
63
|
## Features
|
64
64
|
- **Annotating Images**: Load a folder of images and annotate them using bounding boxes or polygons.
|
65
|
-
- **Model Testing**: Define models for detection, segmentation, and prompts (e.g., points or rectangles) by following the base model structure in [imagebaker/models/base_model.py](imagebaker/models/base_model.py). See [examples/loaded_models.py](examples/loaded_models.py) for a working example.
|
65
|
+
- **Model Testing**: Define models for detection, segmentation, and prompts (e.g., points or rectangles) by following the base model structure in [imagebaker/models/base_model.py](https://github.com/q-viper/image-baker/blob/main/imagebaker/models/base_model.py). See [examples/loaded_models.py](https://github.com/q-viper/image-baker/blob/main/examples/loaded_models.py) for a working example.
|
66
66
|
- **Layerifying**: Crop images based on annotations to create reusable layers. Each cropped image represents a single layer.
|
67
67
|
- **Baking States**: Arrange layers to create image variations by dragging, rotating, adjusting opacity, and more. Save the state using the Save State button or Ctrl + S.
|
68
68
|
- **Playing States**: Replay saved states, export them locally, or use them for further predictions.
|
69
69
|
- **Exporting States**: Export the final annotated JSON and the baked multilayer image.
|
70
|
+
- **Drawing On Layers**: First select a layer then draw upon it. Only selected layer will be drawn. And if no layers are selected, then the drawing will not be exported.
|
70
71
|
|
71
72
|
### Shortcuts
|
72
73
|
* **Ctrl + C**: Copy selected annotation/layer.
|
@@ -75,34 +76,44 @@ After cloning and going to the project directory, the following code should work
|
|
75
76
|
* **Left Click**: Select an annotation/layer on mouse position.
|
76
77
|
* **Left Click + Drag**: Drag a selected annotation/layer.
|
77
78
|
* **Double Left Click**: When using polygon annotation, completes the polygon.
|
78
|
-
* **Right Click**:
|
79
|
+
* **Right Click**: Unselect an annotation/layer. While annotating the polygon, undo the last point.
|
79
80
|
* **Ctrl + Mouse Wheel**: Zoom In/Out on the mouse position, i.e., resize the viewport.
|
80
81
|
* **Ctrl + Drag**: If done on the background, the viewport is panned.
|
81
82
|
* **Ctrl + S**: Save State on Baker Tab.
|
82
83
|
* **Ctrl + D**: Draw Mode on Baker Tab. Drawing can happen on a selected or main layer.
|
83
84
|
* **Ctrl + E**: Erase Mode on Baker Tab.
|
85
|
+
* **Ctrl + H**: Opens a help window.
|
84
86
|
* **Wheel**: Change the size of the drawing pointer.
|
87
|
+
* **Q**: Point mode on annotation.
|
88
|
+
* **W**: Polygon mode on annotation. Moves selected layer one step up in layer lists in baker.
|
89
|
+
* **S**: Moves selected layer one step down in layer list in baker.
|
90
|
+
* **E**: Rectangle mode on annotation.
|
91
|
+
* **H**: Hides/un-hides selected annotation/layer.
|
92
|
+
* **L**: Creates layer from an annotation. If any annotation selected, creates only its, else creates layers from all visible annotations.
|
93
|
+
* **C**: If any annotation is selected, a input box for Caption is created. It can be edited on baker tab as well and is state aware.
|
94
|
+
* **Numerics**: Selecting number 1, 2, till 9 selects label. If not available, asks for a new label.
|
95
|
+
* **Escape**: Closes the application.
|
85
96
|
|
86
97
|
## Demo
|
87
98
|
### Annotation Page
|
88
99
|
This is where the loading of the image folder and annotation, connection with the model running in the backend, and layerifying happen.
|
89
100
|
|
90
|
-

|
101
|
+

|
91
102
|
|
92
103
|
### Baker Page
|
93
104
|
This is where the layer baking happens. And the extraction of the layers as well.
|
94
105
|
|
95
|
-

|
106
|
+

|
96
107
|
|
97
108
|
An example of drawing:
|
98
109
|
|
99
|
-

|
110
|
+

|
100
111
|
|
101
112
|
### Annotated
|
102
113
|
|
103
114
|
The JSON and the baked image will be exported to the local folder, and in debug mode, the annotations and the mask for each layer will be exported too.
|
104
115
|
|
105
|
-

|
116
|
+

|
106
117
|
|
107
118
|
### Demo Video
|
108
119
|
|
@@ -120,4 +131,6 @@ Click on the image above to play the video on YouTube.
|
|
120
131
|
|
121
132
|
Contributions are welcome!
|
122
133
|
|
123
|
-
Do you find this project to be useful and are you looking for some features that are not implemented yet? Feel free to open issues or submit pull requests to improve the project.
|
134
|
+
Do you find this project to be useful and are you looking for some features that are not implemented yet? Feel free to open issues or submit pull requests to improve the project.
|
135
|
+
|
136
|
+
For more please visit [CONTRIBUTING](CONTRIBUTING).
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# Image-Baker
|
2
|
+

|
3
|
+

|
4
|
+

|
5
|
+

|
6
|
+
<!--  -->
|
7
|
+

|
8
|
+
[](https://pypi.org/imagebaker/)
|
9
|
+
|
10
|
+
<p align="center">
|
11
|
+
<img src="https://github.com/q-viper/image-baker/blob/main/assets/demo.gif?raw=true" alt="Centered Demo" />
|
12
|
+
</p>
|
13
|
+
|
14
|
+
|
15
|
+
*An example of baked images. (Each object is a layer and an annotation will also be extracted for all layers.)*
|
16
|
+
|
17
|
+
Let's bake an image.
|
18
|
+
|
19
|
+
## Why is it relevant?
|
20
|
+
|
21
|
+
When training computer vision models (especially for detection and segmentation), labeling large amounts of data is crucial for better model performance. Often, the process involves multiple cycles of labeling, training, and evaluation. By generating multiple realistic labeled datasets from a single image, the time spent on labeling can be significantly reduced.
|
22
|
+
|
23
|
+
## What's up with the name?
|
24
|
+
The concept involves extracting portions of an image (e.g., objects of interest) using tools like polygons or models such as Segment Anything. These extractions are treated as layers, which can then be copied, pasted, and manipulated to create multiple instances of the desired object. By combining these layers step by step, a new labeled image with annotations in JSON format is created. The term "baking" refers to the process of merging these layers into a single cohesive image.
|
25
|
+
|
26
|
+
## Getting Started
|
27
|
+
### Installation
|
28
|
+
#### Using PIP
|
29
|
+
This project is also available on the PyPI server.
|
30
|
+
|
31
|
+
```bash
|
32
|
+
pip install imagebaker
|
33
|
+
```
|
34
|
+
|
35
|
+
#### Developing
|
36
|
+
Please, clone this repository and install it locally:
|
37
|
+
|
38
|
+
```bash
|
39
|
+
git clone https://github.com/q-viper/image-baker.git
|
40
|
+
cd image-baker
|
41
|
+
pip install -e .
|
42
|
+
```
|
43
|
+
|
44
|
+
### First Run
|
45
|
+
Run the following command to launch the GUI:
|
46
|
+
|
47
|
+
`imagebaker`
|
48
|
+
|
49
|
+
By default, the above command will not run any models on the backend. So please take a look into the example of model definition at [examples/loaded_models.py](https://github.com/q-viper/image-baker/blob/main/examples/loaded_models.py). Then we need to pass it as:
|
50
|
+
|
51
|
+
`imagebaker --models-file examples/loaded_models.py`
|
52
|
+
|
53
|
+
For more options, please do: `imagebaker --help` It should give the following options.
|
54
|
+
|
55
|
+

|
56
|
+
|
57
|
+
|
58
|
+
* **`--configs-file`** allows us to define custom configs. The custom configs have to inherit LayerConfig and CanvasConfig defined at [imagebaker/core/configs/configs.py](https://github.com/q-viper/image-baker/blob/main/imagebaker/core/configs/configs.py). An example is available at [examples](https://github.com/q-viper/image-baker/blob/main/examples/).
|
59
|
+
|
60
|
+
After cloning and going to the project directory, the following code should work.
|
61
|
+
`imagebaker --models-file examples/loaded_models.py --configs-file examples/example_config.py`
|
62
|
+
|
63
|
+
## Features
|
64
|
+
- **Annotating Images**: Load a folder of images and annotate them using bounding boxes or polygons.
|
65
|
+
- **Model Testing**: Define models for detection, segmentation, and prompts (e.g., points or rectangles) by following the base model structure in [imagebaker/models/base_model.py](https://github.com/q-viper/image-baker/blob/main/imagebaker/models/base_model.py). See [examples/loaded_models.py](https://github.com/q-viper/image-baker/blob/main/examples/loaded_models.py) for a working example.
|
66
|
+
- **Layerifying**: Crop images based on annotations to create reusable layers. Each cropped image represents a single layer.
|
67
|
+
- **Baking States**: Arrange layers to create image variations by dragging, rotating, adjusting opacity, and more. Save the state using the Save State button or Ctrl + S.
|
68
|
+
- **Playing States**: Replay saved states, export them locally, or use them for further predictions.
|
69
|
+
- **Exporting States**: Export the final annotated JSON and the baked multilayer image.
|
70
|
+
- **Drawing On Layers**: First select a layer then draw upon it. Only selected layer will be drawn. And if no layers are selected, then the drawing will not be exported.
|
71
|
+
|
72
|
+
### Shortcuts
|
73
|
+
* **Ctrl + C**: Copy selected annotation/layer.
|
74
|
+
* **Ctrl + V**: Paste copied annotation/layer in its parent image/layer if it is currently open.
|
75
|
+
* **Delete**: Delete selected annotation/layer.
|
76
|
+
* **Left Click**: Select an annotation/layer on mouse position.
|
77
|
+
* **Left Click + Drag**: Drag a selected annotation/layer.
|
78
|
+
* **Double Left Click**: When using polygon annotation, completes the polygon.
|
79
|
+
* **Right Click**: Unselect an annotation/layer. While annotating the polygon, undo the last point.
|
80
|
+
* **Ctrl + Mouse Wheel**: Zoom In/Out on the mouse position, i.e., resize the viewport.
|
81
|
+
* **Ctrl + Drag**: If done on the background, the viewport is panned.
|
82
|
+
* **Ctrl + S**: Save State on Baker Tab.
|
83
|
+
* **Ctrl + D**: Draw Mode on Baker Tab. Drawing can happen on a selected or main layer.
|
84
|
+
* **Ctrl + E**: Erase Mode on Baker Tab.
|
85
|
+
* **Ctrl + H**: Opens a help window.
|
86
|
+
* **Wheel**: Change the size of the drawing pointer.
|
87
|
+
* **Q**: Point mode on annotation.
|
88
|
+
* **W**: Polygon mode on annotation. Moves selected layer one step up in layer lists in baker.
|
89
|
+
* **S**: Moves selected layer one step down in layer list in baker.
|
90
|
+
* **E**: Rectangle mode on annotation.
|
91
|
+
* **H**: Hides/un-hides selected annotation/layer.
|
92
|
+
* **L**: Creates layer from an annotation. If any annotation selected, creates only its, else creates layers from all visible annotations.
|
93
|
+
* **C**: If any annotation is selected, a input box for Caption is created. It can be edited on baker tab as well and is state aware.
|
94
|
+
* **Numerics**: Selecting number 1, 2, till 9 selects label. If not available, asks for a new label.
|
95
|
+
* **Escape**: Closes the application.
|
96
|
+
|
97
|
+
## Demo
|
98
|
+
### Annotation Page
|
99
|
+
This is where the loading of the image folder and annotation, connection with the model running in the backend, and layerifying happen.
|
100
|
+
|
101
|
+

|
102
|
+
|
103
|
+
### Baker Page
|
104
|
+
This is where the layer baking happens. And the extraction of the layers as well.
|
105
|
+
|
106
|
+

|
107
|
+
|
108
|
+
An example of drawing:
|
109
|
+
|
110
|
+

|
111
|
+
|
112
|
+
### Annotated
|
113
|
+
|
114
|
+
The JSON and the baked image will be exported to the local folder, and in debug mode, the annotations and the mask for each layer will be exported too.
|
115
|
+
|
116
|
+

|
117
|
+
|
118
|
+
### Demo Video
|
119
|
+
|
120
|
+
To see the tool in action, check out the demo video below:
|
121
|
+
|
122
|
+
|
123
|
+
[](https://youtu.be/WckMT0r-2Lc)
|
124
|
+
|
125
|
+
|
126
|
+
Click on the image above to play the video on YouTube.
|
127
|
+
|
128
|
+
|
129
|
+
## Contributions
|
130
|
+
|
131
|
+
|
132
|
+
Contributions are welcome!
|
133
|
+
|
134
|
+
Do you find this project to be useful and are you looking for some features that are not implemented yet? Feel free to open issues or submit pull requests to improve the project.
|
135
|
+
|
136
|
+
For more please visit [CONTRIBUTING](CONTRIBUTING).
|
@@ -14,13 +14,13 @@ from imagebaker.models.base_model import BaseDetectionModel
|
|
14
14
|
from imagebaker import logger
|
15
15
|
|
16
16
|
# Import models from the examples folder
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
from examples.rtdetr_v2 import RTDetrModelConfig, RTDetrDetectionModel
|
18
|
+
from examples.segmentation import (
|
19
|
+
YoloSegmentationModel,
|
20
|
+
YoloSegmentationModelConfig,
|
21
|
+
)
|
22
22
|
|
23
|
-
|
23
|
+
from examples.sam_model import SegmentAnythingModel, SAMModelConfig
|
24
24
|
|
25
25
|
|
26
26
|
class ClassificationModel(BaseClassificationModel):
|
@@ -40,22 +40,22 @@ class DetectionModel(BaseDetectionModel):
|
|
40
40
|
|
41
41
|
|
42
42
|
return_annotated_image = True
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
43
|
+
detector = RTDetrDetectionModel(
|
44
|
+
RTDetrModelConfig(return_annotated_image=return_annotated_image)
|
45
|
+
)
|
46
|
+
|
47
|
+
classification = ClassificationModel(
|
48
|
+
DefaultModelConfig(
|
49
|
+
model_type=ModelType.CLASSIFICATION,
|
50
|
+
return_annotated_image=return_annotated_image,
|
51
|
+
)
|
52
|
+
)
|
53
|
+
segmentation = YoloSegmentationModel(
|
54
|
+
YoloSegmentationModelConfig(return_annotated_image=return_annotated_image)
|
55
|
+
)
|
56
|
+
prompt = SegmentAnythingModel(
|
57
|
+
SAMModelConfig(return_annotated_image=return_annotated_image)
|
58
|
+
)
|
59
59
|
dummy_detector = DetectionModel(
|
60
60
|
DefaultModelConfig(
|
61
61
|
model_type=ModelType.DETECTION, return_annotated_image=return_annotated_image
|
@@ -65,10 +65,10 @@ dummy_detector = DetectionModel(
|
|
65
65
|
|
66
66
|
LOADED_MODELS = {
|
67
67
|
"DummyDetectionModel": dummy_detector,
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
"PromptModel": prompt,
|
69
|
+
"SegmentationModel": segmentation,
|
70
|
+
"RTDetrV2": detector,
|
71
|
+
"ClassificationModel": classification,
|
72
72
|
}
|
73
73
|
|
74
74
|
logger.info(f"Loaded models: {LOADED_MODELS}")
|
@@ -74,6 +74,22 @@ class BaseConfig(BaseModel):
|
|
74
74
|
logger.info(f"Created assets folder at {asset_dir}")
|
75
75
|
return asset_dir
|
76
76
|
|
77
|
+
@property
|
78
|
+
def cache_dir(self):
|
79
|
+
cache_dir = self.project_dir / ".imagebaker" / "cache"
|
80
|
+
if not cache_dir.exists():
|
81
|
+
cache_dir.mkdir(parents=True)
|
82
|
+
logger.info(f"Created cache folder at {cache_dir}")
|
83
|
+
return cache_dir
|
84
|
+
|
85
|
+
@property
|
86
|
+
def bake_dir(self):
|
87
|
+
bake_dir = self.project_dir / ".imagebaker" / "bake"
|
88
|
+
if not bake_dir.exists():
|
89
|
+
bake_dir.mkdir(parents=True)
|
90
|
+
logger.info(f"Created bake folder at {bake_dir}")
|
91
|
+
return bake_dir
|
92
|
+
|
77
93
|
class Config:
|
78
94
|
arbitrary_types_allowed = True
|
79
95
|
|
@@ -96,6 +112,7 @@ class LayerConfig(BaseConfig):
|
|
96
112
|
)
|
97
113
|
# whether to search image in subfolders as well
|
98
114
|
full_search: bool = False
|
115
|
+
cleanup_on_exit: bool = False
|
99
116
|
|
100
117
|
def get_label_color(self, label):
|
101
118
|
for lbl in self.predefined_labels:
|
@@ -78,6 +78,7 @@ class LayerState:
|
|
78
78
|
drawing_states: list[DrawingState] = field(default_factory=list)
|
79
79
|
edge_opacity: int = 100
|
80
80
|
edge_width: int = 10
|
81
|
+
caption: str = ""
|
81
82
|
|
82
83
|
def copy(self):
|
83
84
|
return LayerState(
|
@@ -109,6 +110,7 @@ class LayerState:
|
|
109
110
|
],
|
110
111
|
edge_opacity=self.edge_opacity,
|
111
112
|
edge_width=self.edge_width,
|
113
|
+
caption=self.caption,
|
112
114
|
)
|
113
115
|
|
114
116
|
|
@@ -138,6 +140,7 @@ class Annotation:
|
|
138
140
|
file_path: Path = field(default_factory=lambda: Path("Runtime"))
|
139
141
|
is_model_generated: bool = False
|
140
142
|
model_name: str = None
|
143
|
+
caption: str = ""
|
141
144
|
|
142
145
|
def copy(self):
|
143
146
|
ann = Annotation(
|
@@ -156,6 +159,7 @@ class Annotation:
|
|
156
159
|
file_path=self.file_path,
|
157
160
|
is_model_generated=self.is_model_generated,
|
158
161
|
model_name=self.model_name,
|
162
|
+
caption=self.caption,
|
159
163
|
)
|
160
164
|
ann.is_selected = False
|
161
165
|
return ann
|
@@ -200,6 +204,7 @@ class Annotation:
|
|
200
204
|
"file_path": str(annotation.file_path),
|
201
205
|
"is_model_generated": annotation.is_model_generated,
|
202
206
|
"model_name": annotation.model_name,
|
207
|
+
"caption": annotation.caption,
|
203
208
|
}
|
204
209
|
annotations_dict.append(data)
|
205
210
|
|
@@ -210,6 +215,10 @@ class Annotation:
|
|
210
215
|
def load_from_json(path: str):
|
211
216
|
import json
|
212
217
|
|
218
|
+
# if path does not exist, return empty list
|
219
|
+
if not Path(path).exists():
|
220
|
+
return []
|
221
|
+
|
213
222
|
with open(path, "r") as f:
|
214
223
|
data = json.load(f)
|
215
224
|
|
@@ -230,6 +239,7 @@ class Annotation:
|
|
230
239
|
file_path=Path(d.get("file_path", "Runtime")),
|
231
240
|
is_model_generated=d.get("is_model_generated", False),
|
232
241
|
model_name=d.get("model_name", None),
|
242
|
+
caption=d.get("caption", ""),
|
233
243
|
)
|
234
244
|
|
235
245
|
# Handle points safely
|