CoolFace
Apppublic

HBDing/LayoutPainter

sourceHugging Faceapache-2.0updated 1y agoView on Hugging Face
1likes
README.md559 linesDownload Raw Back to src
1 2# `gradio_image_annotation`3<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>  4 5A Gradio component that can be used to annotate images with bounding boxes.6 7## Installation8 9```bash10pip install gradio_image_annotation11```12 13## Usage14 15```python16import gradio as gr17from gradio_image_annotation import image_annotator18 19 20example_annotation = {21    "image": "https://gradio-builds.s3.amazonaws.com/demo-files/base.png",22    "boxes": [23        {24            "xmin": 636,25            "ymin": 575,26            "xmax": 801,27            "ymax": 697,28            "label": "Vehicle",29            "color": (255, 0, 0)30        },31        {32            "xmin": 360,33            "ymin": 615,34            "xmax": 386,35            "ymax": 702,36            "label": "Person",37            "color": (0, 255, 0)38        }39    ]40}41 42examples_crop = [43    {44        "image": "https://raw.githubusercontent.com/gradio-app/gradio/main/guides/assets/logo.png",45        "boxes": [46            {47                "xmin": 30,48                "ymin": 70,49                "xmax": 530,50                "ymax": 500,51                "color": (100, 200, 255),52            }53        ],54    },55    {56        "image": "https://gradio-builds.s3.amazonaws.com/demo-files/base.png",57        "boxes": [58            {59                "xmin": 636,60                "ymin": 575,61                "xmax": 801,62                "ymax": 697,63                "color": (255, 0, 0),64            },65        ],66    },67]68 69 70def crop(annotations):71    if annotations["boxes"]:72        box = annotations["boxes"][0]73        return annotations["image"][74            box["ymin"]:box["ymax"],75            box["xmin"]:box["xmax"]76        ]77    return None78 79 80def get_boxes_json(annotations):81    return annotations["boxes"]82 83 84with gr.Blocks() as demo:85    with gr.Tab("Object annotation", id="tab_object_annotation"):86        annotator = image_annotator(87            example_annotation,88            label_list=["Person", "Vehicle"],89            label_colors=[(0, 255, 0), (255, 0, 0)],90        )91        button_get = gr.Button("Get bounding boxes")92        json_boxes = gr.JSON()93        button_get.click(get_boxes_json, annotator, json_boxes)94 95    with gr.Tab("Crop", id="tab_crop"):96        with gr.Row():97            annotator_crop = image_annotator(98                examples_crop[0],99                image_type="numpy",100                disable_edit_boxes=True,101                single_box=True,102            )103            image_crop = gr.Image()104        button_crop = gr.Button("Crop")105        button_crop.click(crop, annotator_crop, image_crop)106 107        gr.Examples(examples_crop, annotator_crop)108 109if __name__ == "__main__":110    demo.launch()111 112```113 114## `image_annotator`115 116### Initialization117 118<table>119<thead>120<tr>121<th align="left">name</th>122<th align="left" style="width: 25%;">type</th>123<th align="left">default</th>124<th align="left">description</th>125</tr>126</thead>127<tbody>128<tr>129<td align="left"><code>value</code></td>130<td align="left" style="width: 25%;">131 132```python133dict | None134```135 136</td>137<td align="left"><code>None</code></td>138<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>139</tr>140 141<tr>142<td align="left"><code>boxes_alpha</code></td>143<td align="left" style="width: 25%;">144 145```python146float | None147```148 149</td>150<td align="left"><code>None</code></td>151<td align="left">Opacity of the bounding boxes 0 and 1.</td>152</tr>153 154<tr>155<td align="left"><code>label_list</code></td>156<td align="left" style="width: 25%;">157 158```python159list[str] | None160```161 162</td>163<td align="left"><code>None</code></td>164<td align="left">List of valid labels.</td>165</tr>166 167<tr>168<td align="left"><code>label_colors</code></td>169<td align="left" style="width: 25%;">170 171```python172list[str] | None173```174 175</td>176<td align="left"><code>None</code></td>177<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>178</tr>179 180<tr>181<td align="left"><code>box_min_size</code></td>182<td align="left" style="width: 25%;">183 184```python185int | None186```187 188</td>189<td align="left"><code>None</code></td>190<td align="left">Minimum valid bounding box size.</td>191</tr>192 193<tr>194<td align="left"><code>handle_size</code></td>195<td align="left" style="width: 25%;">196 197```python198int | None199```200 201</td>202<td align="left"><code>None</code></td>203<td align="left">Size of the bounding box resize handles.</td>204</tr>205 206<tr>207<td align="left"><code>box_thickness</code></td>208<td align="left" style="width: 25%;">209 210```python211int | None212```213 214</td>215<td align="left"><code>None</code></td>216<td align="left">Thickness of the bounding box outline.</td>217</tr>218 219<tr>220<td align="left"><code>box_selected_thickness</code></td>221<td align="left" style="width: 25%;">222 223```python224int | None225```226 227</td>228<td align="left"><code>None</code></td>229<td align="left">Thickness of the bounding box outline when it is selected.</td>230</tr>231 232<tr>233<td align="left"><code>disable_edit_boxes</code></td>234<td align="left" style="width: 25%;">235 236```python237bool | None238```239 240</td>241<td align="left"><code>None</code></td>242<td align="left">Disables the ability to set and edit the label and color of the boxes.</td>243</tr>244 245<tr>246<td align="left"><code>single_box</code></td>247<td align="left" style="width: 25%;">248 249```python250bool251```252 253</td>254<td align="left"><code>False</code></td>255<td align="left">If True, at most one box can be drawn.</td>256</tr>257 258<tr>259<td align="left"><code>height</code></td>260<td align="left" style="width: 25%;">261 262```python263int | str | None264```265 266</td>267<td align="left"><code>None</code></td>268<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>269</tr>270 271<tr>272<td align="left"><code>width</code></td>273<td align="left" style="width: 25%;">274 275```python276int | str | None277```278 279</td>280<td align="left"><code>None</code></td>281<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>282</tr>283 284<tr>285<td align="left"><code>image_mode</code></td>286<td align="left" style="width: 25%;">287 288```python289"1"290    | "L"291    | "P"292    | "RGB"293    | "RGBA"294    | "CMYK"295    | "YCbCr"296    | "LAB"297    | "HSV"298    | "I"299    | "F"300```301 302</td>303<td align="left"><code>"RGB"</code></td>304<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>305</tr>306 307<tr>308<td align="left"><code>sources</code></td>309<td align="left" style="width: 25%;">310 311```python312list["upload" | "webcam" | "clipboard"] | None313```314 315</td>316<td align="left"><code>["upload", "webcam", "clipboard"]</code></td>317<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>318</tr>319 320<tr>321<td align="left"><code>image_type</code></td>322<td align="left" style="width: 25%;">323 324```python325"numpy" | "pil" | "filepath"326```327 328</td>329<td align="left"><code>"numpy"</code></td>330<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>331</tr>332 333<tr>334<td align="left"><code>label</code></td>335<td align="left" style="width: 25%;">336 337```python338str | None339```340 341</td>342<td align="left"><code>None</code></td>343<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>344</tr>345 346<tr>347<td align="left"><code>container</code></td>348<td align="left" style="width: 25%;">349 350```python351bool352```353 354</td>355<td align="left"><code>True</code></td>356<td align="left">If True, will place the component in a container - providing some extra padding around the border.</td>357</tr>358 359<tr>360<td align="left"><code>scale</code></td>361<td align="left" style="width: 25%;">362 363```python364int | None365```366 367</td>368<td align="left"><code>None</code></td>369<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>370</tr>371 372<tr>373<td align="left"><code>min_width</code></td>374<td align="left" style="width: 25%;">375 376```python377int378```379 380</td>381<td align="left"><code>160</code></td>382<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>383</tr>384 385<tr>386<td align="left"><code>interactive</code></td>387<td align="left" style="width: 25%;">388 389```python390bool | None391```392 393</td>394<td align="left"><code>True</code></td>395<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>396</tr>397 398<tr>399<td align="left"><code>visible</code></td>400<td align="left" style="width: 25%;">401 402```python403bool404```405 406</td>407<td align="left"><code>True</code></td>408<td align="left">If False, component will be hidden.</td>409</tr>410 411<tr>412<td align="left"><code>elem_id</code></td>413<td align="left" style="width: 25%;">414 415```python416str | None417```418 419</td>420<td align="left"><code>None</code></td>421<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>422</tr>423 424<tr>425<td align="left"><code>elem_classes</code></td>426<td align="left" style="width: 25%;">427 428```python429list[str] | str | None430```431 432</td>433<td align="left"><code>None</code></td>434<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>435</tr>436 437<tr>438<td align="left"><code>render</code></td>439<td align="left" style="width: 25%;">440 441```python442bool443```444 445</td>446<td align="left"><code>True</code></td>447<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>448</tr>449 450<tr>451<td align="left"><code>show_label</code></td>452<td align="left" style="width: 25%;">453 454```python455bool | None456```457 458</td>459<td align="left"><code>None</code></td>460<td align="left">if True, will display label.</td>461</tr>462 463<tr>464<td align="left"><code>show_download_button</code></td>465<td align="left" style="width: 25%;">466 467```python468bool469```470 471</td>472<td align="left"><code>True</code></td>473<td align="left">If True, will show a button to download the image.</td>474</tr>475 476<tr>477<td align="left"><code>show_share_button</code></td>478<td align="left" style="width: 25%;">479 480```python481bool | None482```483 484</td>485<td align="left"><code>None</code></td>486<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>487</tr>488 489<tr>490<td align="left"><code>show_clear_button</code></td>491<td align="left" style="width: 25%;">492 493```python494bool | None495```496 497</td>498<td align="left"><code>True</code></td>499<td align="left">If True, will show a button to clear the current image.</td>500</tr>501 502<tr>503<td align="left"><code>show_remove_button</code></td>504<td align="left" style="width: 25%;">505 506```python507bool | None508```509 510</td>511<td align="left"><code>None</code></td>512<td align="left">If True, will show a button to remove the selected bounding box.</td>513</tr>514 515<tr>516<td align="left"><code>handles_cursor</code></td>517<td align="left" style="width: 25%;">518 519```python520bool | None521```522 523</td>524<td align="left"><code>True</code></td>525<td align="left">If True, the cursor will change when hovering over box handles in drag mode. Can be CPU-intensive.</td>526</tr>527</tbody></table>528 529 530### Events531 532| name | description |533|:-----|:------------|534| `clear` | This listener is triggered when the user clears the image_annotator using the clear button for the component. |535| `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. |536| `upload` | This listener is triggered when the user uploads a file into the image_annotator. |537 538 539 540### User function541 542The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).543 544- When used as an Input, the component only impacts the input signature of the user function.545- When used as an output, the component only impacts the return signature of the user function.546 547The code snippet below is accurate in cases where the component is used as both an input and an output.548 549- **As output:** Is passed, a dict with the image and boxes or None.550- **As input:** Should return, a dict with an image and an optional list of boxes or None.551 552 ```python553 def predict(554     value: dict | None555 ) -> dict | None:556     return value557 ```558 559