Clarify overlay comparison visualization
This commit is contained in:
58
app.py
58
app.py
@@ -229,16 +229,29 @@ def checkerboard(fixed_slice: np.ndarray, warped_slice: np.ndarray, tile: int =
|
||||
return np.where(mask, fixed_norm, warped_norm)
|
||||
|
||||
|
||||
def alpha_overlay(fixed_slice: np.ndarray, warped_slice: np.ndarray, alpha: float = 0.45) -> np.ndarray:
|
||||
def gray_fusion(fixed_slice: np.ndarray, warped_slice: np.ndarray, alpha: float = 0.5) -> np.ndarray:
|
||||
fixed_norm = normalize_slice(fixed_slice)
|
||||
warped_norm = normalize_slice(warped_slice)
|
||||
return np.clip(fixed_norm * (1.0 - alpha) + warped_norm * alpha, 0.0, 1.0)
|
||||
|
||||
|
||||
def color_difference_overlay(fixed_slice: np.ndarray, warped_slice: np.ndarray, alpha: float = 0.65) -> np.ndarray:
|
||||
fixed_norm = normalize_slice(fixed_slice)
|
||||
warped_norm = normalize_slice(warped_slice)
|
||||
base = fixed_norm * (1.0 - alpha) + warped_norm * alpha
|
||||
rgb = np.zeros((*fixed_norm.shape, 3), dtype=np.float32)
|
||||
rgb[..., 0] = warped_norm
|
||||
rgb[..., 1] = fixed_norm * (1.0 - alpha) + warped_norm * alpha
|
||||
rgb[..., 2] = fixed_norm
|
||||
rgb[..., 0] = np.maximum(base, warped_norm * alpha)
|
||||
rgb[..., 1] = base
|
||||
rgb[..., 2] = np.maximum(base, fixed_norm * alpha)
|
||||
return np.clip(rgb, 0.0, 1.0)
|
||||
|
||||
|
||||
def signed_difference(fixed_slice: np.ndarray, warped_slice: np.ndarray) -> np.ndarray:
|
||||
fixed_norm = normalize_slice(fixed_slice)
|
||||
warped_norm = normalize_slice(warped_slice)
|
||||
return warped_norm - fixed_norm
|
||||
|
||||
|
||||
def ddf_magnitude(ddf_xyz: np.ndarray) -> np.ndarray:
|
||||
if ddf_xyz.ndim != 4 or ddf_xyz.shape[-1] != 3:
|
||||
raise ValueError("DDF 应为 (X, Y, Z, 3)。")
|
||||
@@ -291,6 +304,20 @@ def render_rgb(image: np.ndarray, caption: str, plane: str = "Axial") -> None:
|
||||
plt.close(fig)
|
||||
|
||||
|
||||
def render_signed_difference(image: np.ndarray, caption: str, plane: str = "Axial") -> None:
|
||||
fig, ax = plt.subplots(figsize=(4.8, 4.8), dpi=120)
|
||||
diff = orient_for_display(image, plane)
|
||||
finite = diff[np.isfinite(diff)]
|
||||
vmax = float(np.percentile(np.abs(finite), 99.0)) if finite.size else 1.0
|
||||
vmax = max(vmax, 1e-6)
|
||||
im = ax.imshow(diff, cmap="coolwarm", vmin=-vmax, vmax=vmax, interpolation="nearest")
|
||||
ax.set_title(caption, fontsize=10)
|
||||
ax.axis("off")
|
||||
fig.colorbar(im, ax=ax, fraction=0.046, pad=0.02)
|
||||
st.pyplot(fig, width="stretch")
|
||||
plt.close(fig)
|
||||
|
||||
|
||||
def render_heatmap_overlay(
|
||||
base_slice: np.ndarray,
|
||||
mag_slice: np.ndarray,
|
||||
@@ -363,9 +390,20 @@ def render_three_way_views(fixed_xyz: np.ndarray, moving_xyz: np.ndarray, warped
|
||||
|
||||
def render_overlay_views(fixed_xyz: np.ndarray, warped_xyz: np.ndarray) -> None:
|
||||
fixed_xyz, warped_xyz = crop_to_common_shape(fixed_xyz, warped_xyz)
|
||||
mode = st.radio("对比模式", ["Alpha 融合", "棋盘格"], horizontal=True)
|
||||
alpha = st.slider("透明度", 0.0, 1.0, 0.45, 0.05)
|
||||
tile = st.slider("棋盘格尺寸", 8, 64, 24, 4)
|
||||
mode = st.radio("对比模式", ["灰度融合", "红蓝差异", "差异热图", "棋盘格"], horizontal=True)
|
||||
if mode in {"灰度融合", "红蓝差异"}:
|
||||
alpha = st.slider("配准后图像权重", 0.0, 1.0, 0.5, 0.05)
|
||||
else:
|
||||
alpha = 0.5
|
||||
if mode == "棋盘格":
|
||||
tile = st.slider("棋盘格尺寸", 8, 64, 24, 4)
|
||||
else:
|
||||
tile = 24
|
||||
|
||||
if mode == "红蓝差异":
|
||||
st.caption("红/金色偏向配准后图像,蓝色偏向固定图像;白灰区域表示两者灰度接近。")
|
||||
elif mode == "差异热图":
|
||||
st.caption("差异热图显示配准后图像减固定图像的灰度差,色条以当前切片的 99% 绝对差自动缩放。")
|
||||
|
||||
columns = st.columns(3)
|
||||
planes = [("Axial", "轴状面"), ("Coronal", "冠状面"), ("Sagittal", "矢状面")]
|
||||
@@ -377,8 +415,12 @@ def render_overlay_views(fixed_xyz: np.ndarray, warped_xyz: np.ndarray) -> None:
|
||||
warped_slice = get_slice(warped_xyz, plane, index)
|
||||
if mode == "棋盘格":
|
||||
render_image(checkerboard(fixed_slice, warped_slice, tile=tile), f"{cn_name} 棋盘格 #{index}", plane=plane)
|
||||
elif mode == "红蓝差异":
|
||||
render_rgb(color_difference_overlay(fixed_slice, warped_slice, alpha=alpha), f"{cn_name} 红蓝差异 #{index}", plane=plane)
|
||||
elif mode == "差异热图":
|
||||
render_signed_difference(signed_difference(fixed_slice, warped_slice), f"{cn_name} 差异热图 #{index}", plane=plane)
|
||||
else:
|
||||
render_rgb(alpha_overlay(fixed_slice, warped_slice, alpha=alpha), f"{cn_name} 融合 #{index}", plane=plane)
|
||||
render_image(gray_fusion(fixed_slice, warped_slice, alpha=alpha), f"{cn_name} 灰度融合 #{index}", plane=plane)
|
||||
|
||||
|
||||
def render_ddf_views(fixed_xyz: np.ndarray, ddf_xyz: np.ndarray) -> None:
|
||||
|
||||
Reference in New Issue
Block a user