This cookbook details how to deploy a localized ophthalmology fundus image analysis engine to segment the optic nerve head (disc) and optic cup, compute vertical Cup-to-Disc Ratio (vCDR), and screen for early-stage glaucoma directly from color fundus photographs without cloud dependence.
Glaucoma is a leading cause of irreversible blindness characterized by progressive optic nerve fiber loss and increased optic cup excavation. In community eye screenings and mobile optometry clinics, instant estimation of vertical cup-to-disc ratio (vCDR > 0.65) and neuroretinal rim thinning accelerates specialist referral.
This engine enables:
[ Color Fundus Photograph / REFUGE Format ]
│
▼
[ GlaucomaNet-CDR-v1 ]
├── Optic Disc Segmentation
└── Optic Cup Segmentation
│
▼
[ Cup-Disc-Ratio-CLI ]
├── Vertical Cup-to-Disc Ratio (vCDR)
└── ISNT Rule Compliance Verification
│
▼
[ Structured Ophthalmic Diagnostic Summary JSON ]
Ensure Python 3.10+, torch, torchvision, scikit-image, and OpenCV are installed:
pip install torch torchvision opencv-python-headless scikit-image numpy
Clone the offline model weights:
git clone https://github.com/OpenPHRorg/glaucomanet-cdr-local.git
cd glaucomanet-cdr-local
Locate the optic nerve head center via brightest region detection and crop a 512x512 region of interest (ROI):
import cv2
import numpy as np
def extract_optic_disc_roi(fundus_path):
img = cv2.imread(fundus_path)
green_channel = img[:, :, 1] # Green channel provides highest contrast for vessel/disc
# Contrast Limited Adaptive Histogram Equalization (CLAHE)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
enhanced_green = clahe.apply(green_channel)
# Blur & locate optic disc centroid (brightest region)
blurred = cv2.GaussianBlur(enhanced_green, (25, 25), 0)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(blurred)
cx, cy = max_loc
# Crop 512x512 ROI around disc center
h, w = green_channel.shape
x1, y1 = max(0, cx - 256), max(0, cy - 256)
x2, y2 = min(w, cx + 256), min(h, cy + 256)
roi_img = img[y1:y2, x1:x2]
roi_resized = cv2.resize(roi_img, (512, 512))
return roi_resized
# Example usage
prep_roi = extract_optic_disc_roi("sample_fundus.jpg")
cv2.imwrite("optic_disc_roi.jpg", prep_roi)
print("Optic disc ROI extraction completed.")
Execute dual-class segmentation and compute glaucoma risk metrics:
import torch
def evaluate_glaucoma_risk(roi_image):
model = torch.hub.load('OpenPHRorg/glaucomanet-cdr-local', 'glaucomanet_v1', pretrained=True)
model.eval()
tensor_input = torch.from_numpy(roi_image).permute(2, 0, 1).unsqueeze(0).float() / 255.0
with torch.no_grad():
disc_mask, cup_mask = model(tensor_input)
disc_binary = (torch.sigmoid(disc_mask) > 0.5).numpy()[0, 0]
cup_binary = (torch.sigmoid(cup_mask) > 0.5).numpy()[0, 0]
# Calculate vertical diameters in pixels
disc_y_indices = np.where(disc_binary.any(axis=1))[0]
cup_y_indices = np.where(cup_binary.any(axis=1))[0]
disc_vertical_height = len(disc_y_indices) if len(disc_y_indices) > 0 else 1
cup_vertical_height = len(cup_y_indices) if len(cup_y_indices) > 0 else 0
vcdr = cup_vertical_height / float(disc_vertical_height)
glaucoma_suspect = vcdr > 0.65
return {
"vertical_cup_to_disc_ratio_vcdr": round(vcdr, 3),
"optic_disc_height_px": disc_vertical_height,
"optic_cup_height_px": cup_vertical_height,
"glaucoma_risk_level": "High Risk (vCDR > 0.65)" if vcdr > 0.65 else "Borderline (vCDR 0.55-0.65)" if vcdr >= 0.55 else "Low Risk / Normal",
"referral_recommended": glaucoma_suspect
}
# Run assessment
result = evaluate_glaucoma_risk(prep_roi)
print(f"Ophthalmic Diagnostic Summary: {result}")
This engine delivers instant, offline glaucoma screening assessments conforming to REFUGE and American Academy of Ophthalmology (AAO) guidelines.