pilbox / annotate_cli.py
John Ho
Add mask annotation to Annotate tab, colored to match boxes
93754f2
Raw
History Blame Contribute Delete
2.14 kB
"""Typer CLI to annotate an image with bounding boxes from a JSON file.
Run with uv, e.g.::
uv run python annotate_cli.py assets/example_0_in.jpg assets/example_0.json
The JSON must be a list of object dicts, each with a pascal_voc ``boundingBox``
(``{x0, y0, x1, y1}``); see ``assets/example_0.json``.
"""
from pathlib import Path
from typing import Optional
import typer
from loguru import logger
import pilbox
app = typer.Typer(add_completion=False, help=__doc__)
@app.command()
def main(
image: Path = typer.Argument(
..., exists=True, dir_okay=False, readable=True, help="Source image path."
),
annotations: Path = typer.Argument(
..., exists=True, dir_okay=False, readable=True, help="JSON annotations path."
),
output: Optional[Path] = typer.Option(
None, "--output", "-o", help="Output path (default: <image>_out.jpg)."
),
label_key: str = typer.Option(
"object_id", "--label-key", help="Object key drawn as each box's label."
),
color_key: str = typer.Option(
"object_id", "--color-key", help="Object key used to color-group boxes."
),
mask_key: str = typer.Option(
"b64_mask",
"--mask-key",
help="Object key holding a base64 PNG mask (empty disables masks).",
),
mask_alpha: float = typer.Option(
0.5, "--mask-alpha", help="Mask overlay opacity in [0, 1]."
),
width: int = typer.Option(3, "--width", help="Box outline width in pixels."),
font_size: int = typer.Option(20, "--font-size", help="Label font size."),
):
"""Draw bounding boxes from ANNOTATIONS onto IMAGE and save the result."""
out_path = output or image.with_name(f"{image.stem}_out.jpg")
logger.info(f"annotating {image} with {annotations} -> {out_path}")
pilbox.annotate_file(
str(image),
str(annotations),
str(out_path),
label_key=label_key,
color_key=color_key,
mask_key=mask_key,
mask_alpha=mask_alpha,
width=width,
font_size=font_size,
)
logger.info(f"saved {out_path}")
if __name__ == "__main__":
app()