Spaces:
Running
Running
File size: 5,804 Bytes
e4a7008 d487db0 70fca4b d487db0 70fca4b d487db0 e4a7008 d487db0 70fca4b d487db0 70fca4b d487db0 e4a7008 70fca4b e4a7008 94fee7e 70fca4b 94fee7e 70fca4b 94fee7e 70fca4b e4a7008 70fca4b e4a7008 70fca4b e4a7008 d487db0 e4a7008 d487db0 e4a7008 94fee7e e4a7008 70fca4b d487db0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | """Neuron Quantification using AI — MedCLIPSeg variant.
Applies the MedCLIPSeg (CVPR 2026) vision-language approach: a text prompt
describes the target ("nerve fibers ..."), a frozen CLIP backbone produces a
fiber-probability map, and that map is traced into a skeleton. The app reports a
white-on-black **tracked skeleton** and its **total trace length** in microns.
Zero-shot general CLIP is only a coarse prior on this domain — train the bundled
model (reference_medclipseg/) on a GPU with masks for real segmentation quality.
"""
import traceback
import gradio as gr
import processing as P
import medclipseg as MC
def analyze(file_obj, fg_prompt, threshold):
if file_obj is None:
return None, None, "Upload a CZI or TIFF z-stack."
try:
img = P.load_image(file_obj)
nf, _ = P.guess_channels(img)
nf_mip = P.channel_preview(img.data[nf])
if fg_prompt and fg_prompt.strip():
MC.FG_PROMPTS = [p.strip() for p in fg_prompt.split("|") if p.strip()]
# --- MedCLIP text-prompted region prior -> raw-signal fiber geometry ---
prob, _ = MC.segment_best(nf_mip)
trace = P.trace_fibers_medclip_gated(nf_mip, prob, img.voxel,
gate_threshold=float(threshold),
prune_um=3.0)
m = P.compute_metrics(trace, "MedCLIP", min_fiber_um=5.0)
skel_img = P.skeleton_image(trace.skeleton, dilate=1) # white on black
model = ("few-shot trained decoder" if MC.has_trained_model()
else "zero-shot CLIP prior")
status = (f"**MedCLIP total trace length: "
f"{m.total_length_um:,.1f} µm.**\n\n"
f"Fiber geometry traced from the raw neurofilament signal "
f"(Sato tubeness), gated by the MedCLIP region prior "
f"({model}, text-prompted) at semantic gate "
f"{float(threshold):.2f}. "
f"Prompt(s): *{', '.join(MC.FG_PROMPTS)}*.")
return nf_mip, skel_img, status
except Exception as e: # noqa: BLE001
return None, None, f"Error:\n{e}\n{traceback.format_exc()}"
HEADER_HTML = """
<div style="text-align:center; margin: 0.2rem 0 0.7rem;">
<h1 style="font-size:2.1rem; font-weight:750; letter-spacing:-0.01em;
margin:0 0 0.4rem;">Neuron Quantification using AI</h1>
<div style="font-weight:700; font-size:1.15rem; color:#1a1a1a;">
Iman Sabir Ezzat, Randa K Ismail, Ayden Chavez, Marisa Zallocchi, PhD, Steven Fernandes, PhD
</div>
<div style="font-weight:600; font-size:0.95rem; color:#4b5563; margin-top:0.25rem;">
MedCLIPSeg variant — text-prompted vision-language fiber tracking
</div>
</div>
"""
THEME = gr.themes.Base(
primary_hue=gr.themes.colors.slate, secondary_hue=gr.themes.colors.slate,
neutral_hue=gr.themes.colors.gray,
font=["system-ui", "-apple-system", "Segoe UI", "Roboto", "sans-serif"],
).set(
body_background_fill="#ffffff", body_text_color="#1a1a1a",
background_fill_primary="#ffffff", background_fill_secondary="#f7f7f8",
block_background_fill="#ffffff", block_border_color="#e5e7eb",
block_label_text_color="#1a1a1a", block_title_text_color="#1a1a1a",
border_color_primary="#e5e7eb", button_primary_background_fill="#1f2937",
button_primary_text_color="#ffffff", input_background_fill="#ffffff",
input_border_color="#c0c5cc",
body_background_fill_dark="#ffffff", body_text_color_dark="#1a1a1a",
background_fill_primary_dark="#ffffff", background_fill_secondary_dark="#f7f7f8",
block_background_fill_dark="#ffffff", block_border_color_dark="#e5e7eb",
block_label_text_color_dark="#1a1a1a", block_title_text_color_dark="#1a1a1a",
panel_background_fill_dark="#ffffff", border_color_primary_dark="#e5e7eb",
button_primary_background_fill_dark="#1f2937",
button_primary_text_color_dark="#ffffff", input_background_fill_dark="#ffffff",
)
CSS = """
.gradio-container { max-width: 1200px !important; margin: 0 auto !important; }
:root, .dark {
color-scheme: light; --body-background-fill:#ffffff;
--background-fill-primary:#ffffff; --block-background-fill:#ffffff;
--body-text-color:#1a1a1a; --block-label-text-color:#1a1a1a;
--block-title-text-color:#1a1a1a; --border-color-primary:#e5e7eb;
--input-background-fill:#ffffff; --neutral-950:#1a1a1a;
}
body, gradio-app, .gradio-container, .dark { background:#ffffff !important; color:#1a1a1a !important; }
"""
with gr.Blocks(title="Neuron Quantification using AI — MedCLIPSeg",
theme=THEME, css=CSS) as demo:
gr.HTML(HEADER_HTML)
with gr.Row():
with gr.Column(scale=1):
file_in = gr.File(label="Neurofilament z-stack (.czi / .tif)",
type="filepath")
prompt = gr.Textbox(
label="Text prompt(s) for the target (separate with | )",
value="a fluorescence microscopy image of nerve fibers | "
"neurofilament nerve fibers and axons")
thresh = gr.Slider(0.2, 0.8, value=0.4, step=0.05,
label="MedCLIP semantic gate (region prior) — "
"lower = include more of the band")
btn = gr.Button("Analyze", variant="primary")
with gr.Column(scale=2):
status = gr.Markdown()
with gr.Row():
out_orig = gr.Image(label="Neurofilament (MIP)", height=280)
out_skel = gr.Image(label="Tracked skeleton (white on black)",
height=280)
btn.click(analyze, [file_in, prompt, thresh],
[out_orig, out_skel, status])
if __name__ == "__main__":
demo.launch()
|