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
+138
View File
@@ -0,0 +1,138 @@
"""Build manifest for U-Net segmenter combining REFUGE and Papila annotations."""
from __future__ import annotations
import argparse
import random
from pathlib import Path
from typing import Optional
import sys
import pandas as pd
ROOT = Path(__file__).resolve().parents[1]
sys.path.append(str(ROOT))
from classes.refuge_preprocessing import RefugePreprocessing
REFUGE_ROOT = Path("REFUGE")
PAPILA_IMAGES = Path("FundusImages")
PAPILA_CONTOURS = Path("Papila/ExpertsSegmentations/Contours")
DEFAULT_OUTPUT = Path("Papila/analysis_data/unet_manifest.csv")
def pick_contour(base: str, kind: str) -> Optional[Path]:
"""Return contour path for Papila image (disc/cup)."""
candidates = [
PAPILA_CONTOURS / f"{base}_{kind}_exp2.txt",
PAPILA_CONTOURS / f"{base}_{kind}_exp1.txt",
]
for path in candidates:
if path.exists():
return path
return None
def collect_refuge() -> pd.DataFrame:
pre = RefugePreprocessing(REFUGE_ROOT)
samples = []
for sample in pre.build_manifest(refresh=True):
if sample.mask_path is None:
continue
split = sample.split
if split == "test":
split = "holdout"
samples.append(
{
"sample_id": sample.sample_id,
"dataset": "refuge",
"image_path": sample.image_path.resolve(),
"annotation_disc": sample.mask_path.resolve(),
"annotation_cup": sample.mask_path.resolve(),
"annotation_type_disc": "mask",
"annotation_type_cup": "mask",
"split": split,
}
)
return pd.DataFrame(samples)
def collect_papila() -> pd.DataFrame:
samples = []
if not PAPILA_IMAGES.exists():
return pd.DataFrame(samples)
for img_path in sorted(PAPILA_IMAGES.glob("RET*")):
base = img_path.stem
disc = pick_contour(base, "disc")
cup = pick_contour(base, "cup")
if disc is None or cup is None:
continue
samples.append(
{
"sample_id": f"papila_{base}",
"dataset": "papila",
"image_path": img_path.resolve(),
"annotation_disc": disc.resolve(),
"annotation_cup": cup.resolve(),
"annotation_type_disc": "contour",
"annotation_type_cup": "contour",
}
)
return pd.DataFrame(samples)
def assign_splits(df: pd.DataFrame, holdout_ratio: float, seed: int) -> pd.DataFrame:
rng = random.Random(seed)
df = df.copy()
if "split" not in df.columns:
df["split"] = None
for dataset, group in df.groupby("dataset"):
indices = list(group.index)
# Preserve provided splits (e.g., REFUGE train/val/test); only populate
# missing entries with "train" so downstream code has a default.
split_series = df.loc[indices, "split"]
missing = split_series.isna() | (split_series.astype(str).str.strip() == "")
if missing.any():
df.loc[missing[missing].index, "split"] = "train"
split_series = df.loc[indices, "split"]
if dataset != "papila":
continue
if holdout_ratio <= 0:
continue
desired_holdout = max(1, int(len(indices) * holdout_ratio))
split_series = df.loc[indices, "split"]
current_holdout_mask = split_series == "holdout"
current_holdout = int(current_holdout_mask.sum())
remaining = desired_holdout - current_holdout
if remaining <= 0:
continue
candidate_indices = list(split_series[split_series == "train"].index)
rng.shuffle(candidate_indices)
selected = candidate_indices[:remaining]
df.loc[selected, "split"] = "holdout"
return df
def main() -> None:
parser = argparse.ArgumentParser(description="Build U-Net manifest")
parser.add_argument("--holdout", type=float, default=0.05)
parser.add_argument("--seed", type=int, default=42)
parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
args = parser.parse_args()
refuge_df = collect_refuge()
papila_df = collect_papila()
combined = pd.concat([refuge_df, papila_df], ignore_index=True)
combined = assign_splits(combined, holdout_ratio=args.holdout, seed=args.seed)
combined.to_csv(args.output, index=False)
print(f"Manifest saved to {args.output} with {len(combined)} entries")
if __name__ == "__main__":
main()