HBDing commited on
Commit
ea90efd
·
1 Parent(s): 4e514a6
Files changed (3) hide show
  1. README.md +571 -8
  2. __init__.py +0 -0
  3. requirements.txt +2 -2
README.md CHANGED
@@ -1,12 +1,575 @@
1
  ---
2
- title: LayoutPainter
3
- emoji: 🖼
4
- colorFrom: purple
5
- colorTo: red
6
- sdk: gradio
7
- sdk_version: 5.25.2
8
- app_file: app.py
 
 
 
 
9
  pinned: false
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ tags:
3
+ - gradio-custom-component
4
+ - gradio-template-Image
5
+ - bounding box
6
+ - annotator
7
+ - annotate
8
+ - boxes
9
+ title: gradio_image_annotation V0.2.6
10
+ colorFrom: yellow
11
+ colorTo: green
12
+ sdk: docker
13
  pinned: false
14
+ license: apache-2.0
15
+ short_description: A Gradio component for image annotation
16
  ---
17
 
18
+
19
+ # `gradio_image_annotation`
20
+ <a href="https://pypi.org/project/gradio_image_annotation/" target="_blank"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/gradio_image_annotation"></a>
21
+
22
+ A Gradio component that can be used to annotate images with bounding boxes.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install gradio_image_annotation
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```python
33
+ import gradio as gr
34
+ from gradio_image_annotation import image_annotator
35
+
36
+
37
+ example_annotation = {
38
+ "image": "https://gradio-builds.s3.amazonaws.com/demo-files/base.png",
39
+ "boxes": [
40
+ {
41
+ "xmin": 636,
42
+ "ymin": 575,
43
+ "xmax": 801,
44
+ "ymax": 697,
45
+ "label": "Vehicle",
46
+ "color": (255, 0, 0)
47
+ },
48
+ {
49
+ "xmin": 360,
50
+ "ymin": 615,
51
+ "xmax": 386,
52
+ "ymax": 702,
53
+ "label": "Person",
54
+ "color": (0, 255, 0)
55
+ }
56
+ ]
57
+ }
58
+
59
+ examples_crop = [
60
+ {
61
+ "image": "https://raw.githubusercontent.com/gradio-app/gradio/main/guides/assets/logo.png",
62
+ "boxes": [
63
+ {
64
+ "xmin": 30,
65
+ "ymin": 70,
66
+ "xmax": 530,
67
+ "ymax": 500,
68
+ "color": (100, 200, 255),
69
+ }
70
+ ],
71
+ },
72
+ {
73
+ "image": "https://gradio-builds.s3.amazonaws.com/demo-files/base.png",
74
+ "boxes": [
75
+ {
76
+ "xmin": 636,
77
+ "ymin": 575,
78
+ "xmax": 801,
79
+ "ymax": 697,
80
+ "color": (255, 0, 0),
81
+ },
82
+ ],
83
+ },
84
+ ]
85
+
86
+
87
+ def crop(annotations):
88
+ if annotations["boxes"]:
89
+ box = annotations["boxes"][0]
90
+ return annotations["image"][
91
+ box["ymin"]:box["ymax"],
92
+ box["xmin"]:box["xmax"]
93
+ ]
94
+ return None
95
+
96
+
97
+ def get_boxes_json(annotations):
98
+ return annotations["boxes"]
99
+
100
+
101
+ with gr.Blocks() as demo:
102
+ with gr.Tab("Object annotation", id="tab_object_annotation"):
103
+ annotator = image_annotator(
104
+ example_annotation,
105
+ label_list=["Person", "Vehicle"],
106
+ label_colors=[(0, 255, 0), (255, 0, 0)],
107
+ )
108
+ button_get = gr.Button("Get bounding boxes")
109
+ json_boxes = gr.JSON()
110
+ button_get.click(get_boxes_json, annotator, json_boxes)
111
+
112
+ with gr.Tab("Crop", id="tab_crop"):
113
+ with gr.Row():
114
+ annotator_crop = image_annotator(
115
+ examples_crop[0],
116
+ image_type="numpy",
117
+ disable_edit_boxes=True,
118
+ single_box=True,
119
+ )
120
+ image_crop = gr.Image()
121
+ button_crop = gr.Button("Crop")
122
+ button_crop.click(crop, annotator_crop, image_crop)
123
+
124
+ gr.Examples(examples_crop, annotator_crop)
125
+
126
+ if __name__ == "__main__":
127
+ demo.launch()
128
+
129
+ ```
130
+
131
+ ## `image_annotator`
132
+
133
+ ### Initialization
134
+
135
+ <table>
136
+ <thead>
137
+ <tr>
138
+ <th align="left">name</th>
139
+ <th align="left" style="width: 25%;">type</th>
140
+ <th align="left">default</th>
141
+ <th align="left">description</th>
142
+ </tr>
143
+ </thead>
144
+ <tbody>
145
+ <tr>
146
+ <td align="left"><code>value</code></td>
147
+ <td align="left" style="width: 25%;">
148
+
149
+ ```python
150
+ dict | None
151
+ ```
152
+
153
+ </td>
154
+ <td align="left"><code>None</code></td>
155
+ <td align="left">A dict or None. The dictionary must contain a key 'image' with either an URL to an image, a numpy image or a PIL image. Optionally it may contain a key 'boxes' with a list of boxes. Each box must be a dict wit the keys: 'xmin', 'ymin', 'xmax' and 'ymax' with the absolute image coordinates of the box. Optionally can also include the keys 'label' and 'color' describing the label and color of the box. Color must be a tuple of RGB values (e.g. `(255,255,255)`).</td>
156
+ </tr>
157
+
158
+ <tr>
159
+ <td align="left"><code>boxes_alpha</code></td>
160
+ <td align="left" style="width: 25%;">
161
+
162
+ ```python
163
+ float | None
164
+ ```
165
+
166
+ </td>
167
+ <td align="left"><code>None</code></td>
168
+ <td align="left">Opacity of the bounding boxes 0 and 1.</td>
169
+ </tr>
170
+
171
+ <tr>
172
+ <td align="left"><code>label_list</code></td>
173
+ <td align="left" style="width: 25%;">
174
+
175
+ ```python
176
+ list[str] | None
177
+ ```
178
+
179
+ </td>
180
+ <td align="left"><code>None</code></td>
181
+ <td align="left">List of valid labels.</td>
182
+ </tr>
183
+
184
+ <tr>
185
+ <td align="left"><code>label_colors</code></td>
186
+ <td align="left" style="width: 25%;">
187
+
188
+ ```python
189
+ list[str] | None
190
+ ```
191
+
192
+ </td>
193
+ <td align="left"><code>None</code></td>
194
+ <td align="left">Optional list of colors for each label when `label_list` is used. Colors must be a tuple of RGB values (e.g. `(255,255,255)`).</td>
195
+ </tr>
196
+
197
+ <tr>
198
+ <td align="left"><code>box_min_size</code></td>
199
+ <td align="left" style="width: 25%;">
200
+
201
+ ```python
202
+ int | None
203
+ ```
204
+
205
+ </td>
206
+ <td align="left"><code>None</code></td>
207
+ <td align="left">Minimum valid bounding box size.</td>
208
+ </tr>
209
+
210
+ <tr>
211
+ <td align="left"><code>handle_size</code></td>
212
+ <td align="left" style="width: 25%;">
213
+
214
+ ```python
215
+ int | None
216
+ ```
217
+
218
+ </td>
219
+ <td align="left"><code>None</code></td>
220
+ <td align="left">Size of the bounding box resize handles.</td>
221
+ </tr>
222
+
223
+ <tr>
224
+ <td align="left"><code>box_thickness</code></td>
225
+ <td align="left" style="width: 25%;">
226
+
227
+ ```python
228
+ int | None
229
+ ```
230
+
231
+ </td>
232
+ <td align="left"><code>None</code></td>
233
+ <td align="left">Thickness of the bounding box outline.</td>
234
+ </tr>
235
+
236
+ <tr>
237
+ <td align="left"><code>box_selected_thickness</code></td>
238
+ <td align="left" style="width: 25%;">
239
+
240
+ ```python
241
+ int | None
242
+ ```
243
+
244
+ </td>
245
+ <td align="left"><code>None</code></td>
246
+ <td align="left">Thickness of the bounding box outline when it is selected.</td>
247
+ </tr>
248
+
249
+ <tr>
250
+ <td align="left"><code>disable_edit_boxes</code></td>
251
+ <td align="left" style="width: 25%;">
252
+
253
+ ```python
254
+ bool | None
255
+ ```
256
+
257
+ </td>
258
+ <td align="left"><code>None</code></td>
259
+ <td align="left">Disables the ability to set and edit the label and color of the boxes.</td>
260
+ </tr>
261
+
262
+ <tr>
263
+ <td align="left"><code>single_box</code></td>
264
+ <td align="left" style="width: 25%;">
265
+
266
+ ```python
267
+ bool
268
+ ```
269
+
270
+ </td>
271
+ <td align="left"><code>False</code></td>
272
+ <td align="left">If True, at most one box can be drawn.</td>
273
+ </tr>
274
+
275
+ <tr>
276
+ <td align="left"><code>height</code></td>
277
+ <td align="left" style="width: 25%;">
278
+
279
+ ```python
280
+ int | str | None
281
+ ```
282
+
283
+ </td>
284
+ <td align="left"><code>None</code></td>
285
+ <td align="left">The height of the displayed image, specified in pixels if a number is passed, or in CSS units if a string is passed.</td>
286
+ </tr>
287
+
288
+ <tr>
289
+ <td align="left"><code>width</code></td>
290
+ <td align="left" style="width: 25%;">
291
+
292
+ ```python
293
+ int | str | None
294
+ ```
295
+
296
+ </td>
297
+ <td align="left"><code>None</code></td>
298
+ <td align="left">The width of the displayed image, specified in pixels if a number is passed, or in CSS units if a string is passed.</td>
299
+ </tr>
300
+
301
+ <tr>
302
+ <td align="left"><code>image_mode</code></td>
303
+ <td align="left" style="width: 25%;">
304
+
305
+ ```python
306
+ "1"
307
+ | "L"
308
+ | "P"
309
+ | "RGB"
310
+ | "RGBA"
311
+ | "CMYK"
312
+ | "YCbCr"
313
+ | "LAB"
314
+ | "HSV"
315
+ | "I"
316
+ | "F"
317
+ ```
318
+
319
+ </td>
320
+ <td align="left"><code>"RGB"</code></td>
321
+ <td align="left">"RGB" if color, or "L" if black and white. See https://pillow.readthedocs.io/en/stable/handbook/concepts.html for other supported image modes and their meaning.</td>
322
+ </tr>
323
+
324
+ <tr>
325
+ <td align="left"><code>sources</code></td>
326
+ <td align="left" style="width: 25%;">
327
+
328
+ ```python
329
+ list["upload" | "webcam" | "clipboard"] | None
330
+ ```
331
+
332
+ </td>
333
+ <td align="left"><code>["upload", "webcam", "clipboard"]</code></td>
334
+ <td align="left">List of sources for the image. "upload" creates a box where user can drop an image file, "webcam" allows user to take snapshot from their webcam, "clipboard" allows users to paste an image from the clipboard. If None, defaults to ["upload", "webcam", "clipboard"].</td>
335
+ </tr>
336
+
337
+ <tr>
338
+ <td align="left"><code>image_type</code></td>
339
+ <td align="left" style="width: 25%;">
340
+
341
+ ```python
342
+ "numpy" | "pil" | "filepath"
343
+ ```
344
+
345
+ </td>
346
+ <td align="left"><code>"numpy"</code></td>
347
+ <td align="left">The format the image is converted before being passed into the prediction function. "numpy" converts the image to a numpy array with shape (height, width, 3) and values from 0 to 255, "pil" converts the image to a PIL image object, "filepath" passes a str path to a temporary file containing the image. If the image is SVG, the `type` is ignored and the filepath of the SVG is returned.</td>
348
+ </tr>
349
+
350
+ <tr>
351
+ <td align="left"><code>label</code></td>
352
+ <td align="left" style="width: 25%;">
353
+
354
+ ```python
355
+ str | None
356
+ ```
357
+
358
+ </td>
359
+ <td align="left"><code>None</code></td>
360
+ <td align="left">The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.</td>
361
+ </tr>
362
+
363
+ <tr>
364
+ <td align="left"><code>container</code></td>
365
+ <td align="left" style="width: 25%;">
366
+
367
+ ```python
368
+ bool
369
+ ```
370
+
371
+ </td>
372
+ <td align="left"><code>True</code></td>
373
+ <td align="left">If True, will place the component in a container - providing some extra padding around the border.</td>
374
+ </tr>
375
+
376
+ <tr>
377
+ <td align="left"><code>scale</code></td>
378
+ <td align="left" style="width: 25%;">
379
+
380
+ ```python
381
+ int | None
382
+ ```
383
+
384
+ </td>
385
+ <td align="left"><code>None</code></td>
386
+ <td align="left">relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.</td>
387
+ </tr>
388
+
389
+ <tr>
390
+ <td align="left"><code>min_width</code></td>
391
+ <td align="left" style="width: 25%;">
392
+
393
+ ```python
394
+ int
395
+ ```
396
+
397
+ </td>
398
+ <td align="left"><code>160</code></td>
399
+ <td align="left">minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.</td>
400
+ </tr>
401
+
402
+ <tr>
403
+ <td align="left"><code>interactive</code></td>
404
+ <td align="left" style="width: 25%;">
405
+
406
+ ```python
407
+ bool | None
408
+ ```
409
+
410
+ </td>
411
+ <td align="left"><code>True</code></td>
412
+ <td align="left">if True, will allow users to upload and annotate an image; if False, can only be used to display annotated images.</td>
413
+ </tr>
414
+
415
+ <tr>
416
+ <td align="left"><code>visible</code></td>
417
+ <td align="left" style="width: 25%;">
418
+
419
+ ```python
420
+ bool
421
+ ```
422
+
423
+ </td>
424
+ <td align="left"><code>True</code></td>
425
+ <td align="left">If False, component will be hidden.</td>
426
+ </tr>
427
+
428
+ <tr>
429
+ <td align="left"><code>elem_id</code></td>
430
+ <td align="left" style="width: 25%;">
431
+
432
+ ```python
433
+ str | None
434
+ ```
435
+
436
+ </td>
437
+ <td align="left"><code>None</code></td>
438
+ <td align="left">An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.</td>
439
+ </tr>
440
+
441
+ <tr>
442
+ <td align="left"><code>elem_classes</code></td>
443
+ <td align="left" style="width: 25%;">
444
+
445
+ ```python
446
+ list[str] | str | None
447
+ ```
448
+
449
+ </td>
450
+ <td align="left"><code>None</code></td>
451
+ <td align="left">An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.</td>
452
+ </tr>
453
+
454
+ <tr>
455
+ <td align="left"><code>render</code></td>
456
+ <td align="left" style="width: 25%;">
457
+
458
+ ```python
459
+ bool
460
+ ```
461
+
462
+ </td>
463
+ <td align="left"><code>True</code></td>
464
+ <td align="left">If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.</td>
465
+ </tr>
466
+
467
+ <tr>
468
+ <td align="left"><code>show_label</code></td>
469
+ <td align="left" style="width: 25%;">
470
+
471
+ ```python
472
+ bool | None
473
+ ```
474
+
475
+ </td>
476
+ <td align="left"><code>None</code></td>
477
+ <td align="left">if True, will display label.</td>
478
+ </tr>
479
+
480
+ <tr>
481
+ <td align="left"><code>show_download_button</code></td>
482
+ <td align="left" style="width: 25%;">
483
+
484
+ ```python
485
+ bool
486
+ ```
487
+
488
+ </td>
489
+ <td align="left"><code>True</code></td>
490
+ <td align="left">If True, will show a button to download the image.</td>
491
+ </tr>
492
+
493
+ <tr>
494
+ <td align="left"><code>show_share_button</code></td>
495
+ <td align="left" style="width: 25%;">
496
+
497
+ ```python
498
+ bool | None
499
+ ```
500
+
501
+ </td>
502
+ <td align="left"><code>None</code></td>
503
+ <td align="left">If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.</td>
504
+ </tr>
505
+
506
+ <tr>
507
+ <td align="left"><code>show_clear_button</code></td>
508
+ <td align="left" style="width: 25%;">
509
+
510
+ ```python
511
+ bool | None
512
+ ```
513
+
514
+ </td>
515
+ <td align="left"><code>True</code></td>
516
+ <td align="left">If True, will show a button to clear the current image.</td>
517
+ </tr>
518
+
519
+ <tr>
520
+ <td align="left"><code>show_remove_button</code></td>
521
+ <td align="left" style="width: 25%;">
522
+
523
+ ```python
524
+ bool | None
525
+ ```
526
+
527
+ </td>
528
+ <td align="left"><code>None</code></td>
529
+ <td align="left">If True, will show a button to remove the selected bounding box.</td>
530
+ </tr>
531
+
532
+ <tr>
533
+ <td align="left"><code>handles_cursor</code></td>
534
+ <td align="left" style="width: 25%;">
535
+
536
+ ```python
537
+ bool | None
538
+ ```
539
+
540
+ </td>
541
+ <td align="left"><code>True</code></td>
542
+ <td align="left">If True, the cursor will change when hovering over box handles in drag mode. Can be CPU-intensive.</td>
543
+ </tr>
544
+ </tbody></table>
545
+
546
+
547
+ ### Events
548
+
549
+ | name | description |
550
+ |:-----|:------------|
551
+ | `clear` | This listener is triggered when the user clears the image_annotator using the clear button for the component. |
552
+ | `change` | Triggered when the value of the image_annotator changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input. |
553
+ | `upload` | This listener is triggered when the user uploads a file into the image_annotator. |
554
+
555
+
556
+
557
+ ### User function
558
+
559
+ The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
560
+
561
+ - When used as an Input, the component only impacts the input signature of the user function.
562
+ - When used as an output, the component only impacts the return signature of the user function.
563
+
564
+ The code snippet below is accurate in cases where the component is used as both an input and an output.
565
+
566
+ - **As output:** Is passed, a dict with the image and boxes or None.
567
+ - **As input:** Should return, a dict with an image and an optional list of boxes or None.
568
+
569
+ ```python
570
+ def predict(
571
+ value: dict | None
572
+ ) -> dict | None:
573
+ return value
574
+ ```
575
+
__init__.py ADDED
File without changes
requirements.txt CHANGED
@@ -1,7 +1,7 @@
 
1
  accelerate
2
  diffusers
3
  invisible_watermark
4
  torch
5
  transformers
6
- xformers
7
- gradio_image_annotation
 
1
+ gradio_image_annotation==0.2.6
2
  accelerate
3
  diffusers
4
  invisible_watermark
5
  torch
6
  transformers
7
+ xformers