moved_repo_first_update

This commit is contained in:
rpotter6298
2026-02-24 10:39:48 +01:00
commit 9894a23f09
98 changed files with 35387 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
"""Generate ground-truth mask overlays for REFUGE and Papila samples."""
from __future__ import annotations
import argparse
from pathlib import Path
import sys
ROOT = Path(__file__).resolve().parents[1]
sys.path.append(str(ROOT))
import numpy as np
from collections import Counter
from PIL import Image
from PIL.Image import Resampling
from classes.unet_segmenter import UNetSegmenter
REFUGE_ROOT = Path("REFUGE")
DEFAULT_MANIFEST = Path("manifest.csv")
OUTPUT_DIR = Path("temp/gt_test")
def to_mask_colors(disc: np.ndarray, cup: np.ndarray) -> Image.Image:
h, w = disc.shape
canvas = np.ones((h, w, 3), dtype=np.uint8) * 255
disc_mask = disc.astype(bool)
cup_mask = cup.astype(bool)
canvas[disc_mask] = [128, 128, 128]
canvas[cup_mask] = [0, 0, 0]
return Image.fromarray(canvas)
def overlay(
original: Image.Image, mask_rgb: Image.Image, alpha: float = 0.6
) -> Image.Image:
mask_rgba = mask_rgb.convert("RGBA")
updates = np.array(mask_rgba, dtype=np.float32)
updates[..., 3] = alpha * 255 * (updates[..., :3] != 255).any(axis=-1)
base = original.convert("RGBA")
return Image.alpha_composite(
base, Image.fromarray(updates.astype(np.uint8))
).convert("RGB")
def original_mask_to_rgb(mask_path: Path) -> Image.Image:
mask_img = Image.open(mask_path)
arr = np.asarray(mask_img)
h, w = arr.shape[:2]
canvas = np.ones((h, w, 3), dtype=np.uint8) * 255
if arr.ndim == 2:
border = np.concatenate([arr[0, :], arr[-1, :], arr[:, 0], arr[:, -1]])
bg_value = Counter(border.tolist()).most_common(1)[0][0]
disc_mask = arr != bg_value
fg_counts = Counter(arr[arr != bg_value].flatten())
if fg_counts:
# For REFUGE-style masks: cup should be the darkest (minimum value)
cup_value = min(fg_counts.keys())
cup_mask = arr == cup_value
else:
cup_mask = np.zeros_like(arr, dtype=bool)
else:
edges = np.concatenate(
[arr[0, :, :], arr[-1, :, :], arr[:, 0, :], arr[:, -1, :]], axis=0
)
bg_color = Counter(map(tuple, edges)).most_common(1)[0][0]
disc_mask = ~np.all(arr == bg_color, axis=-1)
color_counts = Counter(map(tuple, arr.reshape(-1, arr.shape[2])))
cup_mask = np.zeros((h, w), dtype=bool)
candidates = {}
for color, count in color_counts.items():
if color == bg_color:
continue
mask = np.all(arr == color, axis=-1)
candidates[color] = mask
if candidates:
# For REFUGE-style masks: cup should be the darkest color (closest to black)
cup_color = min(candidates.keys(), key=lambda color: sum(color))
cup_mask = candidates[cup_color]
disc_mask = disc_mask.astype(bool)
cup_mask = cup_mask & disc_mask
canvas[disc_mask] = [128, 128, 128]
canvas[cup_mask] = [0, 0, 0]
return Image.fromarray(canvas)
def process_entries(
segmenter: UNetSegmenter, entries, prefix: str, count: int, dest: Path
) -> None:
for entry in entries[:count]:
img_path = Path(entry.image_path)
if not img_path.exists():
continue
orig = Image.open(img_path).convert("RGB")
image = segmenter.preprocess_image(orig)
disc, cup = segmenter.load_masks(entry)
disc_coords = segmenter._mask_to_coords(disc)
cup_coords = segmenter._mask_to_coords(cup)
print(
f"{entry.sample_id}: disc coords {disc_coords.shape[0] if disc_coords is not None else 0}, "
f"cup coords {cup_coords.shape[0] if cup_coords is not None else 0}"
)
mask_rgb = to_mask_colors(disc, cup)
overlay_img = overlay(image, mask_rgb)
mask_rgb.save(dest / f"{prefix}_{entry.sample_id}_mask.png")
overlay_img.save(dest / f"{prefix}_{entry.sample_id}_overlay.png")
if entry.annotation_type_disc == "mask":
gt_mask_rgb = original_mask_to_rgb(entry.annotation_disc)
gt_overlay = overlay(
orig.resize(gt_mask_rgb.size, Resampling.BILINEAR), gt_mask_rgb
)
gt_mask_rgb.save(dest / f"{prefix}_{entry.sample_id}_gt_mask.png")
gt_overlay.save(dest / f"{prefix}_{entry.sample_id}_gt_overlay.png")
def main() -> None:
parser = argparse.ArgumentParser(
description="Inspect ground-truth masks for REFUGE and Papila"
)
parser.add_argument("--manifest", type=Path, default=DEFAULT_MANIFEST)
parser.add_argument("--output", type=Path, default=OUTPUT_DIR)
parser.add_argument(
"--count", type=int, default=10, help="Number of samples per dataset"
)
args = parser.parse_args()
args.output.mkdir(parents=True, exist_ok=True)
segmenter = UNetSegmenter(args.manifest)
refuge_entries = [e for e in segmenter._manifest if e.dataset == "refuge"]
papila_entries = [e for e in segmenter._manifest if e.dataset == "papila"]
process_entries(segmenter, refuge_entries, "refuge", args.count, args.output)
process_entries(segmenter, papila_entries, "papila", args.count, args.output)
print(f"Saved overlays to {args.output}")
if __name__ == "__main__":
main()