VASCX Simplify: GPU-Accelerated Vessel Analysis and Fundus Image Processing Toolkit
A PyTorch library for vessel and fundus image analysis, providing GPU-accelerated preprocessing and inference utilities for medical imaging tasks.
Note: This is a simplified rewrite of rtnls_vascx_models by Eyened.
Features
- GPU-Accelerated Preprocessing: Fast fundus image contrast enhancement with mixed precision support
- Sliding Window Inference: Efficient inference for large images
- Ensemble Models: Segmentation, classification, regression, and heatmap-based models
- HuggingFace Integration: Easy model loading from HuggingFace Hub
- Minimal Dependencies: Uses fewer dependency libraries for easier installation and maintenance
Installation
pip install vascx_simplify
From source:
git clone https://github.com/kapong/vascx_simplify.git
cd vascx_simplify
pip install -e .
Requirements
- Python >= 3.12
- PyTorch >= 1.10.0
- kornia >= 0.6.0
- scikit-learn >= 1.0.0
- scipy >= 1.7.0
- numpy >= 1.21.0
- huggingface-hub >= 0.10.0
Usage Examples
Artery/Vein Segmentation
Segment arteries (red), veins (blue), and crossings (green) from fundus images:
from vascx_simplify import EnsembleSegmentation, VASCXTransform, from_huggingface
from PIL import Image
import torch
# Load model
model_path = from_huggingface('Eyened/vascx:artery_vein/av_july24.pt')
model = EnsembleSegmentation(model_path, VASCXTransform())
# Predict
rgb_image = Image.open('fundus.jpg')
prediction = model.predict(rgb_image) # Returns [B, H, W] with class values
Full example: See examples/01_artery_vein.py
Optic Disc Segmentation
Detect and segment the optic disc:
from vascx_simplify import EnsembleSegmentation, VASCXTransform, from_huggingface
from PIL import Image
model_path = from_huggingface('Eyened/vascx:disc/disc_july24.pt')
model = EnsembleSegmentation(model_path, VASCXTransform(512))
rgb_image = Image.open('fundus.jpg')
prediction = model.predict(rgb_image) # Returns [B, H, W] with class values
Full example: See examples/02_disc_segment.py
Fovea Detection
Locate the fovea center using heatmap regression:
from vascx_simplify import HeatmapRegressionEnsemble, VASCXTransform, from_huggingface
from PIL import Image
model_path = from_huggingface('Eyened/vascx:fovea/fovea_july24.pt')
model = HeatmapRegressionEnsemble(model_path, VASCXTransform())
rgb_image = Image.open('fundus.jpg')
prediction = model.predict(rgb_image) # Returns [B, M, 2] with (x, y) coordinates
fovea_x = prediction[0, 0, 0].item()
fovea_y = prediction[0, 0, 1].item()
Full example: See examples/03_fovea_regression.py
Image Quality Assessment
Classify fundus image quality (Reject/Usable/Good):
from vascx_simplify import ClassificationEnsemble, VASCXTransform, from_huggingface
from PIL import Image
model_path = from_huggingface('Eyened/vascx:quality/quality.pt')
model = ClassificationEnsemble(model_path, VASCXTransform(use_ce=False))
rgb_image = Image.open('fundus.jpg')
prediction = model.predict(rgb_image) # Returns [B, 3] with quality scores (already softmaxed)
# Get probabilities (already normalized)
q1_reject, q2_usable, q3_good = prediction[0].tolist()
Full example: See examples/04_quality_classify.py
Contrast Enhancement
Enhance fundus image contrast with GPU-accelerated preprocessing:
from vascx_simplify.preprocess import FundusContrastEnhance
from PIL import Image
import torch
import numpy as np
# Initialize enhancer
enhancer = FundusContrastEnhance(
use_fp16=True, # Use mixed precision for faster processing
square_size=512, # Optional: crop to square size
)
# Load and convert image to tensor
rgb_image = Image.open('fundus.jpg')
img_tensor = torch.from_numpy(np.array(rgb_image)).permute(2, 0, 1).cuda() # you can use CPU/GPU to process
# Apply contrast enhancement
original, enhanced, bounds = enhancer(img_tensor)
# Convert back to numpy for saving/visualization
enhanced_np = enhanced.cpu().permute(1, 2, 0).numpy()
Full example: See examples/07_contrast_enhancement.py for detailed visualization with before/after comparison, zoomed regions, and statistics.
Batch Processing
Process multiple images with automatic batch splitting to prevent out-of-memory errors:
⚠️ Important: Batch processing speed benefit depends on model type:
- Segmentation/Classification/Regression: 2-3x faster than sequential
- Heatmap Regression (fovea): NO speed improvement (due to sliding window complexity)
from vascx_simplify import EnsembleSegmentation, VASCXTransform, from_huggingface
from PIL import Image
# Load model once
model_path = from_huggingface('Eyened/vascx:artery_vein/av_july24.pt')
model = EnsembleSegmentation(model_path, VASCXTransform())
# Load multiple images
images = [Image.open(f'fundus_{i}.jpg') for i in range(10)]
# Batch prediction (much faster for segmentation/classification)
predictions = model.predict(images) # Returns [10, H, W]
# Automatically splits into chunks of 4 (default for segmentation)
# Process each result
for i, pred in enumerate(predictions):
# pred is [H, W] - no need for [0] indexing
save_prediction(pred, f'result_{i}.png')
# For large datasets, automatic splitting prevents OOM
large_images = [Image.open(f'img_{i}.jpg') for i in range(100)]
predictions = model.predict(large_images) # Auto-splits into chunks
# Returns [100, H, W] - seamlessly handles large batches
# Override batch size for your GPU memory
predictions = model.predict(images, batch_size=8) # Process 8 at once
Key Features:
- ️ Automatic OOM prevention - large batches split automatically
- 🔄 100% backward compatible - existing single-image code works unchanged
- ⚙️ Configurable - override batch size per call or use smart defaults
- 📊 Flexible inputs - accepts PIL.Image, torch.Tensor, or lists of either
Default Batch Sizes by Model Type:
- All Models:
batch_size=1(no speed benefit from batching observed in testing)
Usage Patterns:
# Pattern 1: Batch processing a directory
import glob
from pathlib import Path
image_paths = glob.glob('fundus_images/*.jpg')
images = [Image.open(p) for p in image_paths]
predictions = model.predict(images) # Efficient batch processing
# Pattern 2: Process with torch tensors
tensors = [torch.randn(3, 512, 512) for _ in range(20)]
predictions = model.predict(tensors) # Works with tensors too
# Pattern 3: Memory-constrained environment
predictions = model.predict(images, batch_size=2) # Smaller batches
# Pattern 4: High-memory GPU
predictions = model.predict(images, batch_size=16) # Larger batches
Backward Compatibility: All existing single-image code works without modification:
# This still works exactly as before
image = Image.open('fundus.jpg')
pred = model.predict(image) # Returns [1, H, W]
result = pred[0] # Access with [0] as before
Performance Tips:
- Default batch size is set to 1 for all models (no speed benefit observed from batching)
- You can override batch_size parameter for memory management if processing large numbers of images
- Increase batch_size for high-memory GPUs (24GB+) to process more images simultaneously
- Decrease batch_size if you encounter OOM errors
- List of tensors is slightly faster than list of PIL.Images
Full examples:
examples/05_batch_fovea.py- Batch processing for heatmap regressionexamples/06_utils_demo.py- Utility functions demonstration
Citation
If you use this software in your research, please cite both the original paper and this software repository:
Original Paper
@article{quiros2024vascx,
title={VascX Models: Model Ensembles for Retinal Vascular Analysis from Color Fundus Images},
author={Jose Vargas Quiros and Bart Liefers and Karin van Garderen and Jeroen Vermeulen and Eyened Reading Center and Sinergia Consortium and Caroline Klaver},
journal={arXiv preprint arXiv:2409.16016},
year={2024},
url={https://arxiv.org/abs/2409.16016}
}
Software Repository
@software{vascx_simplify2024,
title={VASCX Simplify: GPU-Accelerated Vessel Analysis and Fundus Image Processing Toolkit},
author={Phienphanich, Phongphan},
year={2025},
url={https://github.com/kapong/vascx_simplify},
version={0.1.10}
}
AI Usage Disclaimer
This project was developed with significant assistance from AI tools (GitHub Copilot, ChatGPT, Claude) for code organization, refactoring, documentation, and packaging.
License
GNU Affero General Public License v3.0 (AGPL-3.0) - see LICENSE file for details.
Author
Phongphan Phienphanich garpong@gmail.com
Acknowledgments
This is a simplified rewrite of rtnls_vascx_models by Eyened.
Metadata
Release files for vascx-simplify 0.1.11
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vascx_simplify-0.1.11.tar.gz | 48.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vascx_simplify-0.1.11-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 101.8 kB
Release files / vascx_simplify-0.1.11.tar.gz
| Download URL | vascx_simplify-0.1.11.tar.gz |
|---|---|
| Size | 48.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8e2fc8b76d0bdcc4f7d47717b1240fd778762d62e02a876360bfc565db331b50
|
|
BLAKE2b-256 checksum How to use checksums |
7be2ca6572284f2e56287bc9c12acc92efd1e48261ad94505ac5beef02f4fec1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 25, 2025.
Transparency logRelease files / vascx_simplify-0.1.11-py3-none-any.whl
| Download URL | vascx_simplify-0.1.11-py3-none-any.whl |
|---|---|
| Size | 52.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f0cd7cf8050f21b06f160c0802bf5e10395f52b267d64fa6a66040b4c3c98b7c
|
|
BLAKE2b-256 checksum How to use checksums |
1cb1c6d7f0c2716de85896916090b906b9b4eb4bc46b056325933af2fbc53582
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 25, 2025.
Transparency log