Histopathology / app /utils.py
Eyob-Sol's picture
Upload 29 files
5a274ee verified
Raw
History Blame Contribute Delete
2.34 kB
import io
import os
import zipfile
from typing import List, Tuple, Union
import numpy as np
from PIL import Image
# ----------------------------
# I/O helpers
# ----------------------------
BytesLike = Union[bytes, bytearray, io.BytesIO]
def load_image(src: Union[str, BytesLike]) -> Image.Image:
"""Load image from path or in-memory bytes → RGB PIL.Image."""
if isinstance(src, (bytes, bytearray, io.BytesIO)):
return Image.open(io.BytesIO(src)).convert("RGB")
return Image.open(src).convert("RGB")
def unzip_images(file_bytes: bytes, exts=(".png", ".jpg", ".jpeg", ".tif", ".tiff")) -> List[Tuple[str, Image.Image]]:
"""Return [(name, PIL RGB)] from a ZIP bytes blob, filtering by extension."""
out = []
with zipfile.ZipFile(io.BytesIO(file_bytes)) as zf:
for name in zf.namelist():
if name.lower().endswith(exts) and not name.endswith("/"):
with zf.open(name) as fh:
img = Image.open(io.BytesIO(fh.read())).convert("RGB")
out.append((name, img))
return out
def ensure_dir(path: str) -> None:
os.makedirs(path, exist_ok=True)
# ----------------------------
# Array utilities
# ----------------------------
def pil_to_np(img: Image.Image) -> np.ndarray:
"""PIL RGB → np.uint8 [H, W, 3]."""
return np.asarray(img, dtype=np.uint8)
def np_to_pil(arr: np.ndarray) -> Image.Image:
"""np.uint8 [H, W, 3] → PIL RGB."""
if arr.dtype != np.uint8:
arr = np.clip(arr, 0, 255).astype(np.uint8)
return Image.fromarray(arr, mode="RGB")
def normalize01(arr: np.ndarray) -> np.ndarray:
"""Scale array to [0,1] with safe denominator."""
arr = arr.astype(np.float32)
mn = float(arr.min())
mx = float(arr.max())
denom = (mx - mn) if (mx - mn) != 0 else 1.0
return (arr - mn) / denom
# ----------------------------
# Heatmap coloring
# ----------------------------
def colorize_heatmap(attn_grid: np.ndarray) -> Image.Image:
"""
Convert [H,W] float in [0,1] to a colored heatmap RGB PIL image using JET.
"""
import cv2
attn = np.clip(attn_grid, 0.0, 1.0)
grid8 = (attn * 255).astype(np.uint8)
cm_bgr = cv2.applyColorMap(grid8, cv2.COLORMAP_JET)
cm_rgb = cv2.cvtColor(cm_bgr, cv2.COLOR_BGR2RGB)
return Image.fromarray(cm_rgb, mode="RGB")