Spaces:
Running on Zero
Running on Zero
| import gradio as gr | |
| import spaces | |
| from roi_predictor import predict_rois | |
| from landmark_predictor import predict_landmark, show_landmarks | |
| from cpak_calculator import calculate_cpak | |
| def predict_rois_gpu(image): | |
| annotated_img, gallery_items, rois = predict_rois(image) | |
| return annotated_img, gallery_items, rois | |
| def predict_landmark_gpu(image, rois): | |
| landmarks = predict_landmark(image, rois) | |
| heatmap_image, heatmap_gallery, landmark_image = show_landmarks(image, rois, landmarks) | |
| cpak_right_dict, cpak_left_dict = calculate_cpak(image, landmarks) | |
| right_text = ( | |
| f"MPTA: {cpak_right_dict['MPTA']:.2f} °\n" | |
| f"LDFA: {cpak_right_dict['LDFA']:.2f} °\n" | |
| f"aHKA: {cpak_right_dict['aHKA']:.2f} ° ({cpak_right_dict['aHKA_label']})\n" | |
| f"JLO: {cpak_right_dict['JLO']:.2f} ° ({cpak_right_dict['JLO_label']})\n\n" | |
| f"CPAK: {cpak_right_dict['CPAK']} \n" | |
| ) | |
| left_text = ( | |
| f"MPTA: {cpak_left_dict['MPTA']:.2f} °\n" | |
| f"LDFA: {cpak_left_dict['LDFA']:.2f} °\n" | |
| f"aHKA: {cpak_left_dict['aHKA']:.2f} ° ({cpak_left_dict['aHKA_label']})\n" | |
| f"JLO: {cpak_left_dict['JLO']:.2f} ° ({cpak_left_dict['JLO_label']})\n\n" | |
| f"CPAK: {cpak_left_dict['CPAK']} \n" | |
| ) | |
| return heatmap_image, heatmap_gallery, landmark_image, right_text, left_text | |
| CUSTOM_CSS = """ | |
| .caption-label {color: #888;} | |
| """ | |
| # Define modern Gradio Blocks interface | |
| with gr.Blocks() as demo: | |
| gr.Markdown( | |
| """ | |
| # 🦴 Knee Landmarks ROI Detector & Analyzer | |
| Upload a knee X-ray image to automatically detect regions of interest (ROIs), predict landmarks, and compute CPAK measurements. | |
| """ | |
| ) | |
| with gr.Row(): | |
| # Left Column: Input and Controls | |
| with gr.Column(scale=1): | |
| with gr.Tabs(): | |
| with gr.TabItem("Input"): | |
| input_image = gr.Image(type="numpy", label="Input Knee X-Ray Image") | |
| detect_roi_btn = gr.Button("Detect ROIs", variant="primary") | |
| predict_landmark_btn = gr.Button("Predict Landmarks", variant="secondary") | |
| # Right Column: Visualizations & Analysis | |
| with gr.Column(scale=2): | |
| with gr.Tabs(): | |
| # Tab 1: ROI Detection Output | |
| with gr.TabItem("1. ROI Detection"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| roi_image = gr.Image(label="Annotated ROIs") | |
| with gr.Column(scale=1): | |
| roi_gallery = gr.Gallery(label="Cropped Regions", columns=3, height="auto") | |
| roi_state = gr.State() | |
| # Tab 2: Landmarks and Heatmaps | |
| with gr.TabItem("2. Landmarks"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| heatmap_image = gr.Image(label="Predicted Heatmap") | |
| with gr.Column(scale=1): | |
| landmark_image = gr.Image(label="Final Landmarks") | |
| gr.Markdown("## Landmark Heatmaps") | |
| heatmap_gallery = gr.Gallery(label="Heatmap Gallery", columns=4, height="auto") | |
| # Tab 3: Clinical Measurements | |
| with gr.TabItem("3. CPAK Measurement"): | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("# Right Side") | |
| cpak_right = gr.Textbox( | |
| value="", | |
| show_label=False, | |
| lines=8, | |
| interactive=False | |
| ) | |
| with gr.Column(): | |
| gr.Markdown("# Left Side") | |
| cpak_left = gr.Textbox( | |
| value="", | |
| show_label=False, | |
| lines=8, | |
| interactive=False | |
| ) | |
| detect_roi_btn.click( | |
| fn=predict_rois_gpu, | |
| inputs=[input_image], | |
| outputs=[roi_image, roi_gallery, roi_state] | |
| ) | |
| predict_landmark_btn.click( | |
| fn=predict_landmark_gpu, | |
| inputs=[input_image, roi_state], | |
| outputs=[heatmap_image, heatmap_gallery, landmark_image, cpak_right, cpak_left] | |
| ) | |
| demo.launch(theme=gr.Theme.from_hub("harsh8001/comic"), css=CUSTOM_CSS, ssr_mode=False) |