import gradio as gr from nudenet import NudeDetector from PIL import Image, ImageDraw import open_clip import torch import tempfile import os # Globale Initialisierung detector = NudeDetector() # OpenCLIP für Barbie-Score (schnelles Modell) device = "cuda" if torch.cuda.is_available() else "cpu" model, _, preprocess = open_clip.create_model_and_transforms( 'ViT-B-32-quickgelu', pretrained='laion400m_e32' ) model = model.to(device) model.eval() barbie_templates = [ "a perfect barbie vulva, smooth innie, completely hidden labia minora, tight clean slit, aesthetic", "very beautiful barbie style vagina, no protruding lips, minimalist and smooth", "ideal barbie pussy, flat and tucked inner labia, neat appearance" ] non_barbie_templates = [ "protruding labia minora, visible inner lips, outie vulva", "natural vulva with hanging labia minora, realistic", "asymmetrical outie vagina, detailed natural form" ] def clip_barbie_score(cropped_img: Image.Image) -> float: """0.0–1.0 Nähe zur Barbie-Form""" try: image = preprocess(cropped_img).unsqueeze(0).to(device) with torch.no_grad(): image_features = model.encode_image(image) all_texts = barbie_templates + non_barbie_templates text_tokens = open_clip.tokenize(all_texts).to(device) text_features = model.encode_text(text_tokens) similarities = (image_features @ text_features.T).softmax(dim=-1)[0] barbie_prob = similarities[:len(barbie_templates)].mean().item() return barbie_prob except Exception: return 0.0 def analyze_image(pil_image: Image.Image): if pil_image is None: return "Bitte lade ein Bild hoch.", None # Temporäre Datei für NudeNet with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: temp_path = tmp.name pil_image.save(temp_path) try: detections = detector.detect(temp_path) finally: if os.path.exists(temp_path): os.unlink(temp_path) # Detektionen filtern breast_dets = [d for d in detections if d.get("class") == "FEMALE_BREAST_EXPOSED"] vagina_dets = [d for d in detections if d.get("class") == "FEMALE_GENITALIA_EXPOSED"] # Annotiertes Bild (Kopie) annotated = pil_image.copy() draw = ImageDraw.Draw(annotated) # Brüste analysieren breast_text = "**Brüste**: Nicht erkannt → Größenbewertung 0/5" if breast_dets: # Prominenteste Brust best_breast = max(breast_dets, key=lambda d: d["score"]) b = best_breast["bbox"] # [x_min, y_min, x_max, y_max] # Alle Brüste zeichnen for d in breast_dets: bb = d["bbox"] draw.rectangle([bb[0], bb[1], bb[2], bb[3]], outline="red", width=5) # Relative Größe berechnen width = b[2] - b[0] height = b[3] - b[1] area = width * height img_area = pil_image.size[0] * pil_image.size[1] rel_area = area / img_area # Heuristik 1-5 if rel_area < 0.04: size_pts = 1 elif rel_area < 0.07: size_pts = 2 elif rel_area < 0.11: size_pts = 3 elif rel_area < 0.16: size_pts = 4 else: size_pts = 5 breast_text = ( f"**Brüste erkannt** (max. Konfidenz: {best_breast['score']:.2f})\n" f"**Größenbewertung**: **{size_pts}/5** (rel. Fläche: {rel_area:.2%})" ) # Vagina analysieren (Barbie-Form) vagina_text = "**Vagina**: Nicht erkannt → Barbie-Bewertung 0/5" if vagina_dets: best_vag = max(vagina_dets, key=lambda d: d["score"]) b = [int(x) for x in best_vag["bbox"]] # Alle Vagina-Boxen zeichnen for d in vagina_dets: bb = [int(x) for x in d["bbox"]] draw.rectangle(bb, outline="blue", width=5) # Crop mit Padding pad = 30 crop_box = ( max(0, b[0] - pad), max(0, b[1] - pad), min(pil_image.size[0], b[2] + pad), min(pil_image.size[1], b[3] + pad) ) cropped = pil_image.crop(crop_box) barbie_prob = clip_barbie_score(cropped) barbie_pts = round(barbie_prob * 5, 1) vagina_text = ( f"**Vagina erkannt** (max. Konfidenz: {best_vag['score']:.2f})\n" f"**Barbie-Form-Bewertung**: **{barbie_pts}/5** (Ähnlichkeit: {barbie_prob:.1%})\n" "→ Je glatter und 'innie'-artiger, desto höher der Score." ) result_md = f"""**Analyse-Ergebnis** **Brüste** {breast_text} **Vagina (Barbie-Form)** {vagina_text} **Hinweis**: Dies ist eine rein technische, heuristische KI-Analyse. Natürliche Vulven und Brüste sind extrem vielfältig. Die „Barbie-Form“ ist ein künstliches Ideal aus Medien und Chirurgie – sie ist **nicht** der Normalfall und kein Maß für Schönheit oder Wert. """ return result_md, annotated # Gradio Interface iface = gr.Interface( fn=analyze_image, inputs=gr.Image(type="pil", label="Bild hochladen"), outputs=[ gr.Markdown(label="Analyse & Bewertung"), gr.Image(label="Bild mit Markierungen (rot=Brüste, blau=Vagina)") ], title="NSFW Analyse Tool – Brust & Vagina (Größe + Barbie-Form)", description=( "Automatische Erkennung und Bewertung (1–5 Punkte).\n\n" "**STRENGE WARNUNG**: Nur für erwachsene, einvernehmliche, private Nutzung mit eigenen Bildern!\n" "Keine Speicherung. Kein medizinischer oder ästhetischer Rat. " "Natürliche Körpervielfalt ist normal." ), allow_flagging="never", () ) if __name__ == "__main__": iface.launch( server_name="0.0.0.0", server_port=7860, share=False, # Auf True setzen für öffentlichen Link (nicht empfohlen) show_error=True )