import streamlit as st import cv2 import numpy as np import matplotlib.pyplot as plt import seaborn as sns def render_css(): """Injects custom CSS for a professional medical dashboard optimized for horizontal screens.""" st.markdown(""" """, unsafe_allow_html=True) def render_header(app_name, version): st.title(app_name) st.caption(f"Klinik Karar Destek Sistemi | Sürüm: {version}") st.markdown("---") def apply_heatmap_overlay(img_rgb, heatmap_float, colormap=cv2.COLORMAP_JET, alpha=0.6): if np.max(heatmap_float) > 0: heatmap_float = heatmap_float / np.max(heatmap_float) heatmap_uint8 = np.uint8(255 * heatmap_float) heatmap_colored = cv2.applyColorMap(heatmap_uint8, colormap) heatmap_colored = cv2.cvtColor(heatmap_colored, cv2.COLOR_BGR2RGB) if heatmap_colored.shape[:2] != img_rgb.shape[:2]: heatmap_colored = cv2.resize(heatmap_colored, (img_rgb.shape[1], img_rgb.shape[0])) overlay = cv2.addWeighted(img_rgb, 1-alpha, heatmap_colored, alpha, 0) return overlay def render_classification_panel(img_rgb, diagnosis, cls_conf, seg_conf, gradcam_map): st.subheader("1. Tanı ve Model Güven Analizi") col_diag, col_orig, col_xai = st.columns([1.2, 1.4, 1.4]) with col_diag: # Dynamic Styling based on Diagnosis color = "#dc3545" if "Benign" not in diagnosis else "#28a745" st.markdown(f"""

{diagnosis}

Yapay Zeka Nihai Kararı

""", unsafe_allow_html=True) st.markdown("#### Güvenilirlik Metrikleri") c1, c2 = st.columns(2) c1.metric("Teşhis Güveni", f"%{cls_conf*100:.1f}", help="ResNet50 modelinin sınıflandırma kesinliği.") c2.metric("Segmentasyon Güveni", f"%{seg_conf*100:.1f}", help="CIA-Net modelinin hücre tespit kesinliği (Ortalama Piksel Olasılığı).") if cls_conf < 0.70: st.warning("Düşük güven skoru. Lütfen manuel inceleme yapınız.") with col_orig: st.image(img_rgb, caption="Orijinal Görüntü", use_column_width=True) with col_xai: overlay = apply_heatmap_overlay(img_rgb, gradcam_map, alpha=0.5) st.image(overlay, caption="Yapay Zeka Odak Alanları (Grad-CAM)", use_column_width=True) def render_segmentation_panel(img_rgb, nuc_map, uncertainty_map, instance_mask, stats): st.markdown("---") st.subheader("2. Hücresel Morfoloji ve Biyolojik Analiz") tab_seg, tab_unc, tab_data, tab_plots = st.tabs([ "Segmentasyon", "Belirsizlik (Uncertainty)", "Kantitatif Veriler", "Dağılım Grafikleri" ]) with tab_seg: c1, c2 = st.columns(2) with c1: nuc_colored = apply_heatmap_overlay(img_rgb, nuc_map, colormap=cv2.COLORMAP_OCEAN, alpha=0.6) st.image(nuc_colored, caption="Nükleus Olasılık Haritası (AI Çıktısı)", use_column_width=True) with c2: mask_rgb = np.zeros_like(img_rgb) mask_rgb[instance_mask > 0] = [0, 255, 0] # Green overlay = cv2.addWeighted(img_rgb, 0.7, mask_rgb, 0.3, 0) st.image(overlay, caption="Ayrıştırılmış Hücreler (Watershed)", use_column_width=True) with tab_unc: c1, c2 = st.columns([1, 2]) with c1: st.info(""" **Nasıl Okunmalı?** * **Siyah/Koyu Alanlar:** Modelin kararından %100 emin olduğu bölgeler. * **Parlak/Sarı Alanlar:** Modelin kararsız kaldığı ("Burası hücre mi değil mi?") bölgeler. Sarı alanların çokluğu, görüntünün kalitesiz veya dokunun karmaşık olduğunu gösterir. """) with c2: unc_colored = apply_heatmap_overlay(img_rgb, uncertainty_map, colormap=cv2.COLORMAP_INFERNO, alpha=0.7) st.image(unc_colored, caption="Model Entropi (Belirsizlik) Haritası", use_column_width=True) with tab_data: if not stats.empty: m1, m2, m3, m4 = st.columns(4) m1.metric("Toplam Hücre", f"{len(stats)}") m2.metric("Ort. Alan", f"{stats['Area'].mean():.1f} px") m3.metric("Düzensizlik", f"{1 - stats['Circularity'].mean():.2f}", help="0'a yaklaştıkça hücreler daha yuvarlak (sağlıklı) demektir.") m4.metric("Varyasyon", f"{stats['Area'].std():.1f}", help="Yüksek varyasyon (Anizonükleoz) kanser belirtisi olabilir.") st.dataframe( stats.style.background_gradient(cmap='Reds', subset=['Area']) .format("{:.2f}"), width="stretch" ) else: st.warning("Hücre tespit edilemedi.") with tab_plots: if not stats.empty: # HD Graphics Settings - High DPI plt.style.use('seaborn-v0_8-whitegrid') sns.set_context("notebook", font_scale=1.3) sns.set_palette("husl") c1, c2 = st.columns(2) with c1: fig, ax = plt.subplots(figsize=(10, 6), dpi=150) sns.histplot(stats['Area'], kde=True, ax=ax, color='#3498db', fill=True, alpha=0.7, linewidth=2) ax.set_title("Hücre Boyut Dağılımı (Histogram)", fontsize=16, fontweight='bold', pad=20) ax.set_xlabel("Alan (Piksel)", fontsize=13, fontweight='600') ax.set_ylabel("Frekans", fontsize=13, fontweight='600') ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.grid(True, alpha=0.3, linestyle='--') plt.tight_layout() st.pyplot(fig) plt.close() with c2: fig, ax = plt.subplots(figsize=(10, 6), dpi=150) scatter = sns.scatterplot(data=stats, x='Area', y='Circularity', hue='Solidity', ax=ax, palette='viridis', s=100, alpha=0.8, edgecolor='white', linewidth=1.5) ax.set_title("Boyut vs. Şekil Düzensizliği", fontsize=16, fontweight='bold', pad=20) ax.set_xlabel("Alan (Piksel)", fontsize=13, fontweight='600') ax.set_ylabel("Dairesellik", fontsize=13, fontweight='600') ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.grid(True, alpha=0.3, linestyle='--') ax.legend(title='Solidity', title_fontsize=11, fontsize=10, loc='best', frameon=True, fancybox=True, shadow=True, framealpha=0.95) plt.tight_layout() st.pyplot(fig) plt.close()