Spaces:
Sleeping
Sleeping
| # app.py | |
| import gradio as gr | |
| import cv2 | |
| from periodontitis_detection import SimpleDentalSegmentationNoEnhance | |
| # ========================== | |
| # 1️⃣ Load models once | |
| # ========================== | |
| model = SimpleDentalSegmentationNoEnhance( | |
| unet_model_path="unet.keras", # same filenames as your repo | |
| yolo_model_path="best2.pt" | |
| ) | |
| # ========================== | |
| # 2️⃣ Define wrapper for Gradio | |
| # ========================== | |
| def detect_periodontitis(image_np): | |
| """ | |
| Gradio sends image as a NumPy RGB array. | |
| We temporarily save it to a file path since analyze_image() needs a path. | |
| """ | |
| temp_path = "temp_input.jpg" | |
| cv2.imwrite(temp_path, cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)) | |
| # Run full pipeline | |
| results = model.analyze_image(temp_path) | |
| # Convert OpenCV BGR → RGB for Gradio display | |
| combined_rgb = cv2.cvtColor(results["combined"], cv2.COLOR_BGR2RGB) | |
| # Optional: summarize measurements for text output | |
| summaries = [] | |
| for tooth in results["distance_analyses"]: | |
| tooth_id = tooth["tooth_id"] | |
| analysis = tooth["analysis"] | |
| if analysis: | |
| mean_d = analysis["mean_distance"] | |
| summaries.append(f"Tooth {tooth_id}: mean={mean_d:.2f}px") | |
| else: | |
| summaries.append(f"Tooth {tooth_id}: no valid CEJ–ABC measurement") | |
| summary_text = "\n".join(summaries) if summaries else "No detections found." | |
| return combined_rgb, summary_text | |
| # ========================== | |
| # 3️⃣ Build Gradio Interface | |
| # ========================== | |
| demo = gr.Interface( | |
| fn=detect_periodontitis, | |
| inputs=gr.Image(type="numpy", label="Upload Dental X-Ray"), | |
| outputs=[ | |
| gr.Image(label="Final Annotated Image (YOLO + CEJ–ABC)"), | |
| gr.Textbox(label="Analysis Summary"), | |
| ], | |
| title="🦷 Periodontitis Detection & Analysis", | |
| description=( | |
| "Automatically detects teeth (YOLOv8), segments CEJ/ABC (U-Net), " | |
| "and measures CEJ–ABC distances per tooth to assess bone loss." | |
| ), | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True) | |