File size: 2,295 Bytes
5b023ff |
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 |
import streamlit as st
from PIL import Image
import numpy as np
import tempfile, os, zipfile
from io_utils import load_slices_from_folder
from infer_anomaly import simple_threshold_mask, mesh_and_mask_from_volume
from io_utils import save_mesh_ply
st.set_page_config(page_title="MEDIVIEW-3D", layout="wide")
st.title("MEDIVIEW-3D — 2D → 3D Reconstruction + Explanation")
uploaded = st.file_uploader("Upload a zip of PNG slices (or skip to use example)", type=["zip"])
use_example = st.button("Use example synthetic slices")
thresh = st.slider("Threshold (for simple anomaly)", 0.0, 1.0, 0.6)
out_mesh = st.text_input("Output mesh path", value="mesh_demo.ply")
def unpack_and_read(zipf):
tmpdir = tempfile.mkdtemp()
with zipfile.ZipFile(zipf) as z:
z.extractall(tmpdir)
vol = load_slices_from_folder(tmpdir, glob_pattern="*.png")
return vol, tmpdir
vol = None
if uploaded:
with tempfile.NamedTemporaryFile(delete=False, suffix=".zip") as tmp:
tmp.write(uploaded.getvalue())
tmp.flush()
vol, tmpdir = unpack_and_read(tmp.name)
elif use_example:
if os.path.isdir("examples/synthetic_phantom"):
vol = load_slices_from_folder("examples/synthetic_phantom", glob_pattern="*.png")
else:
st.error("Example slices not found in examples/synthetic_phantom")
if vol is not None:
st.write("Volume shape (z,y,x):", vol.shape)
mid = vol.shape[0]//2
st.image(Image.fromarray(vol[mid].astype('uint8')), caption=f"Middle slice (index {mid})")
if st.button("Run reconstruction & anomaly detection"):
mask = simple_threshold_mask(vol, threshold=thresh)
verts, faces, normals, colors = mesh_and_mask_from_volume(vol, iso=0.5, spacing=(1.0,1.0,1.0), mask=mask)
save_mesh_ply(verts, faces, out_mesh, normals=normals, colors=colors)
st.success(f"Saved colored mesh to {out_mesh}")
# Generate simple textual explanation
from infer_anomaly import analyze_regions, generate_text_explanation
regions = analyze_regions(mask, min_voxels=20)
expl = generate_text_explanation(regions, vol.shape)
st.subheader('Detected regions explanation')
st.text(expl)
else:
st.info("Upload a slice zip or click 'Use example synthetic slices' to proceed.")
|