Spaces:
Sleeping
Sleeping
| 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 (itm.innolab@muenchen.de) | |
| """ | |
| 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() | |