freinold's picture
Revert to only show outline of bounding boxes.
8652b05
raw
history blame
4 kB
import gradio as gr
from ultralytics import YOLO
import numpy as np
from PIL import Image, ImageDraw, ImageFilter, ImageOps
import torchvision.transforms
import torch
transform = torchvision.transforms.ToPILImage()
seg_model = YOLO("yolov8m-seg.pt")
lp_model = YOLO("yolov8m_lp.pt")
def detect(image):
seg_result = seg_model(image, device="CPU")[0]
seg_masks = seg_result.masks.data
seg_clss = seg_result.boxes.cls
seg_boxes = seg_result.boxes.data
person_indices = torch.where(seg_clss == 0)
person_masks = seg_masks[person_indices]
people_mask = torch.any(person_masks, dim=0).to(torch.uint8) * 255
people_mask = transform(~people_mask)
people_mask = people_mask.resize((image.width, image.height), resample=Image.Resampling.BILINEAR)
vehicle_classes = [2, 3, 5, 7] # Classes: car (2), motorcycle (3), bus (5) and truck (7)
license_plates = list()
vehicle_boxes = []
for seg_box in seg_boxes:
if seg_box[5] in vehicle_classes:
vehicle_box = seg_box[:4].to(torch.int32)
vehicle_boxes.append(vehicle_box)
vehicle_crop = image.crop(vehicle_box.tolist())
imgsz = (vehicle_crop.height, vehicle_crop.width) if vehicle_crop.width < 640 and vehicle_crop.height < 640 else (640, 640)
lp_result = lp_model(vehicle_crop, imgsz=imgsz, device="cpu")[0]
lp_boxes = lp_result.boxes.data[:, :4]
vehicle_offset = torch.cat((vehicle_box[:2], vehicle_box[:2]))
for lp_box in lp_boxes:
license_plates.append(torch.add(lp_box, vehicle_offset))
lp_mask = Image.new(mode="L", size=image.size, color=255)
lp_draw = ImageDraw.Draw(lp_mask)
for license_plate in license_plates:
lp_draw.rectangle(license_plate.tolist(), fill = 0)
vehicle_mask = Image.new(mode="L", size=image.size, color=255)
vehicle_draw = ImageDraw.Draw(vehicle_mask)
for vehicle_box in vehicle_boxes:
vehicle_draw.rectangle(vehicle_box.tolist(), outline = 0, width=5)
person_box_mask = Image.new(mode="L", size=image.size, color=255)
person_box_draw = ImageDraw.Draw(person_box_mask)
for person_box in seg_boxes[person_indices][:, :4]:
person_box_draw.rectangle(person_box.tolist(), outline = 0, width=5)
#TODO: move combination to caller function
combined_mask = Image.fromarray(np.minimum.reduce([np.array(m) for m in [people_mask, lp_mask]]))
return combined_mask, people_mask, lp_mask, vehicle_mask, person_box_mask
def test_comb(image):
mask, people_mask, lp_mask, vm, pbm = detect(image)
blurred = image.filter(ImageFilter.GaussianBlur(30))
anonymized = Image.composite(image, blurred, mask)
## TODO: Tempfile statt einem generischen File
anonymized.save("anon.JPG")
box_list = [(1 - np.asarray(pbm) / 255, "Person (Rahmen)"), (1 - np.asarray(vm) / 255, "Fahrzeug")]
anon_list = [(1 - np.asarray(people_mask) / 255, "Person (Umriss)"), (1 - np.asarray(lp_mask) / 255, "Kennzeichen")]
return "anon.JPG", (image, box_list), (image, anon_list)
css = """
P { text-align: center }
H3 { text-align: center }
"""
description = """
### ML-Prototyp zur Anonymisierung von Bildern
Es werden Personen sowie Kennzeichen zensiert.
Große Bilder können einige Zeit benötigen.
"""
article = """
Nutzt YOLOv8-Modelle zur Erkennung / Segmentierung der Bilder.
Code: https://huggingface.co/spaces/it-at-m/image-anonymizer/tree/main
Ein Prototyp des it@M InnovationLab ([email protected])
"""
demo = gr.Interface(
fn=test_comb,
inputs=gr.Image(type="pil", label="Zu anonymisierendes Bild"),
outputs=[gr.Image(label="Anonymisiertes Bild"), gr.AnnotatedImage(label="Detektierte Umrisse"), gr.AnnotatedImage(label="Erkannte Objekte")],
title="Bild auswählen / hochladen",
allow_flagging="never",
examples="examples",
description=description,
article=article,
css=css,
theme=gr.themes.Soft()
)
demo.launch()