Instructions to use fundusnap/fundusnap-v1-lesiondet-yolo11m-20m with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- ultralytics
How to use fundusnap/fundusnap-v1-lesiondet-yolo11m-20m with ultralytics:
# Couldn't find a valid YOLO version tag. # Replace XX with the correct version. from ultralytics import YOLOvXX model = YOLOvXX.from_pretrained("fundusnap/fundusnap-v1-lesiondet-yolo11m-20m") source = 'http://images.cocodataset.org/val2017/000000039769.jpg' model.predict(source=source, save=True) - Notebooks
- Google Colab
- Kaggle
๐ข Domain & Email Migration NoticeFrom May 30th, 2026, Fundusnap will transition to new domains as ๐ Website: fundusnap.faizath.com (formerly fundusnap.com) |
AI-assisted diabetic retinopathy screening โ showing where on the retina the findings are.
๐ค Hugging Face โข ๐ GitHub
fundusnap-v1-lesiondet-yolo11m-20m
Retinal lesion detector for colour fundus (retinal) photographs. Given a single fundus image it
returns axis-aligned bounding boxes for twelve findings โ ten pathological (microaneurysms,
haemorrhages, exudates, IRMA, atrophy, scars, capture artefacts) and two anatomical landmarks (optic
disc, fovea) โ each with a class label and a confidence score. The model is an Ultralytics
YOLO11m detector fine-tuned from the COCO-pretrained yolo11m.pt checkpoint at 640ร640 โ
roughly 20M parameters, hence the name: lesiondet (lesion detection) + yolo11m (YOLO11
medium) + 20m (parameter count).
It ships as a stripped Ultralytics best.pt checkpoint, ready for inference or further fine-tuning,
together with the FastAPI service Fundusnap uses to serve it.
Its companion model is fundusnap-v1-severitycls-rn34-22m, which grades overall DR severity. This one answers the follow-up question: where does the grade come from?
โ ๏ธ Intended use โ not for clinical use
This model is released for research and engineering use, and at most as a visualisation and triage aid inside a workflow that a qualified clinician supervises.
- It is not a medical device and has no regulatory clearance (FDA, CE/MDR, or otherwise).
- It must never be the sole basis for a diagnosis, referral, or treatment decision.
- Inside Fundusnap it exists for explainability โ it draws boxes over an image that has already been graded elsewhere. It is not a grader, and the number of boxes it returns is not a severity score.
- Detection quality is modest (mAP@50-95 โ 0.28, recall โ 0.53). Roughly half of the annotated findings in its own validation split are missed. An empty result means "nothing detected", never "nothing there".
- It has not been validated prospectively, on any specific camera or population, or against a reference annotation standard beyond the dataset described below.
Anyone deploying it in a screening context is responsible for their own validation and for keeping a human grader in the loop.
Label scheme
Twelve classes, in model.names order:
| Index | Class | What it is |
|---|---|---|
| 0 | Artefact | Image capture artefact (dust, glare, reflection) โ not retinal pathology |
| 1 | Atrophic Scar | Healed atrophic scarring of the retina/choroid |
| 2 | Atrophy | Retinal or chorioretinal atrophy |
| 3 | Disc | Anatomical landmark โ the optic disc |
| 4 | Flame R-hemorrhage | Flame-shaped retinal haemorrhage (nerve fibre layer) |
| 5 | Fovea | Anatomical landmark โ the fovea / macular centre |
| 6 | H-exudate | Hard exudate (lipid deposit) |
| 7 | IRMA | Intraretinal microvascular abnormality |
| 8 | Laser Scar | Photocoagulation scar from prior laser treatment |
| 9 | Microaneurysm | Microaneurysm โ the earliest visible DR lesion |
| 10 | R-hemorrhage | Retinal haemorrhage (dot/blot) |
| 11 | S-exudate | Soft exudate / cotton-wool spot |
Note that Disc, Fovea, and Artefact are not lesions. Disc and Fovea are normal anatomy
present in essentially every gradable image, and Artefact marks image-quality problems. Any
downstream logic that counts detections as evidence of disease must exclude these three.
Files
| Path | What it is |
|---|---|
models/fundus_artifacts.pt |
The model. Ultralytics best.pt, stripped of optimiser/EMA state (~40 MB, stored via Git LFS). |
main.py |
FastAPI service that loads the checkpoint and exposes JSON and annotated-image endpoints. |
Dockerfile |
Container build for that service (python:3.10-slim, port 8000). |
requirements.txt |
Runtime dependencies for the service. |
Usage
Ultralytics (recommended)
pip install ultralytics
from ultralytics import YOLO
model = YOLO("models/fundus_artifacts.pt")
# conf/iou default to 0.25 / 0.7 โ lower conf if you would rather over-detect than miss lesions.
results = model("fundus.jpg", conf=0.25, iou=0.7, imgsz=640)
for r in results:
for box in r.boxes:
x1, y1, x2, y2 = map(int, box.xyxy[0])
cls_id = int(box.cls[0])
conf = float(box.conf[0])
print(f"{model.names[cls_id]:20s} {conf:.2f} [{x1}, {y1}, {x2}, {y2}]")
# Annotated image as a BGR numpy array (what /visualize/fundus-artifacts/ returns):
annotated = results[0].plot()
Images are letterboxed to 640ร640 internally; coordinates come back in the original image's pixel
space, so no rescaling is needed. Batch by passing a list of paths or an (N, H, W, 3) array.
Exporting
model.export(format="onnx", opset=14, dynamic=True) # also: torchscript, tflite, coreml, engine
Fine-tuning
The checkpoint is stripped (epoch: -1, no optimiser or EMA state), so it resumes as a starting
point, not as a paused run:
model = YOLO("models/fundus_artifacts.pt")
model.train(data="your_dataset/data.yaml", epochs=50, imgsz=640, batch=16)
Your data.yaml must keep the same twelve class names in the same order, or retrain the head.
Training
Data โ an internal 12-class fundus detection set exported in Roboflow layout, referenced in the
run as FUNDUS-3/data.yaml. The dataset itself is not published with this model, and its
provenance was not recorded in the checkpoint โ image counts, split sizes, source cameras,
annotator count, and licensing terms are all unknown from the artefacts in this repository. Treat
every number below as a description of that run, not as an evaluation on any known public benchmark.
The wall-clock time is informative about scale: 35 epochs completed in 258 seconds (โ7.4 s/epoch) at batch 16 on GPU, which implies a small training set โ on the order of a few hundred to a couple of thousand images.
Setup (from the checkpoint's train_args)
| Base model | yolo11m.pt, COCO-pretrained |
| Architecture | yolo11m.yaml, scale m (depth 0.5, width 1.0), nc=12, anchor-free Detect head |
| Input | 640ร640, letterboxed |
| Epochs | 35 (patience=100, so no early stop) |
| Batch size | 16 (nbs=64 nominal) |
| Optimizer | auto, lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005 |
| Warmup | 3 epochs, warmup_momentum=0.8 |
| Loss weights | box 7.5, cls 0.5, dfl 1.5 |
| Augmentation | mosaic 1.0 (disabled for the last 10 epochs), fliplr=0.5, scale=0.5, translate=0.1, HSV (0.015/0.7/0.4), erasing=0.4, RandAugment |
| Not used | flipud, degrees, shear, perspective, mixup, copy_paste |
| Precision | AMP |
| Seed | 0, deterministic=True |
| Ultralytics | 8.3.165 (run object_detection_model_v1, 2025-07-13) |
Run log (abridged โ validation metrics per epoch)
| Epoch | box_loss | cls_loss | dfl_loss | Precision | Recall | mAP@50 | mAP@50-95 |
|---|---|---|---|---|---|---|---|
| 1 | 2.3819 | 3.0624 | 1.4673 | 0.2534 | 0.2641 | 0.2048 | 0.0955 |
| 5 | 1.9664 | 1.4739 | 1.1881 | 0.3955 | 0.4270 | 0.4079 | 0.1925 |
| 10 | 1.8575 | 1.3348 | 1.1310 | 0.4918 | 0.4582 | 0.4587 | 0.2325 |
| 15 | 1.7731 | 1.2301 | 1.1132 | 0.5443 | 0.4606 | 0.4961 | 0.2575 |
| 20 | 1.7162 | 1.1354 | 1.0861 | 0.5211 | 0.5088 | 0.5289 | 0.2639 |
| 27 | โ | โ | โ | 0.5354 | 0.5252 | 0.5343 | 0.2819 |
| 30 | 1.5557 | 0.9660 | 1.0399 | 0.5279 | 0.5054 | 0.5132 | 0.2633 |
| 35 | 1.4925 | 0.8980 | 1.0153 | 0.5573 | 0.5154 | 0.5300 | 0.2744 |
Training losses fall steadily to the last epoch while validation mAP plateaus after ~epoch 20 โ the
run was starting to overfit. Epoch 27 is the best checkpoint by Ultralytics' fitness metric
(0.3071), and that is the epoch shipped as models/fundus_artifacts.pt.
Evaluation
Measured by Ultralytics on the run's own validation split, at the best epoch (27):
| Metric | Value |
|---|---|
| Precision | 0.5354 |
| Recall | 0.5252 |
| mAP@50 | 0.5343 |
| mAP@50-95 | 0.2819 |
Fitness (0.1ยทmAP50 + 0.9ยทmAP50-95) |
0.3071 |
Per-class metrics are not available. The run's results.csv, confusion matrix, and PR curves
were not retained, and the checkpoint stores aggregates only. Since the twelve classes are very
unevenly difficult โ the optic disc is a large, high-contrast, always-present object, while a
microaneurysm is a handful of pixels โ the aggregate almost certainly hides a wide spread, with the
landmark classes propping the average up and the small-lesion classes well below it. Do not read
mAP@50 โ 0.53 as "roughly half-right on lesions".
These figures are self-reported โ produced by the training run itself, not verified by Hugging
Face โ and are mirrored in the model-index metadata at the top of this card, which is why the Hub
labels them as such.
Limitations and bias
- Absolute performance is modest. mAP@50-95 of 0.28 and recall of 0.53 are far below what a clinical detection tool would need. Roughly half the annotated findings are missed even in-distribution.
- Aggregate metrics are flattered by the easy classes. Two of twelve classes (
Disc,Fovea) are large, high-contrast anatomy present in nearly every image, and detecting them is close to trivial. They are pooled into the same mAP as microaneurysms. - Small lesions are the weak point, and they matter most. Microaneurysms and dot haemorrhages are a few pixels wide; at 640ร640 with letterboxing, much of that detail is gone before the model sees it. Those are exactly the lesions that define early, referable DR.
- The run is small. 35 epochs in ~4 minutes of wall clock implies a small dataset; validation mAP had already plateaued while training loss kept falling, i.e. the model was overfitting rather than running out of schedule.
- Unknown data provenance. Dataset size, sources, cameras, populations, and annotation protocol were not recorded. No domain-shift analysis and no subgroup fairness audit is possible from what survives, and none has been done. Expect degradation on different hardware, fields of view, illumination, or demographics.
- Class definitions are non-standard. The label set mixes pathology, anatomy, and image-quality
artefacts, and terms like
AtrophyvsAtrophic ScarorR-hemorrhagevsFlame R-hemorrhagedepend on the annotator's convention rather than a published grading standard. - No ungradable option beyond
Artefact. A blurred, over-exposed, or non-fundus image still yields plausible-looking boxes; theArtefactclass flags local capture problems, not whole-image ungradability. - Confidence is not calibrated. Scores are usable for ranking and thresholding, not as probabilities that a finding is real.
Serving
The FastAPI service in main.py is what the Fundusnap backend calls (FUNDUSNAP_AI_HOST).
Endpoints
| Method | Path | Returns |
|---|---|---|
POST |
/inspect/fundus-artifacts/ |
JSON: filename, model_used, and detections[] with class_name, confidence, and integer box.{x1,y1,x2,y2} |
POST |
/visualize/fundus-artifacts/ |
image/jpeg โ the input with red boxes and labels drawn on |
GET |
/ |
Health check with the list of loaded models |
Both POST endpoints take a multipart/form-data upload under the field name file.
# JSON detection results
curl -X POST "http://localhost:8000/inspect/fundus-artifacts/" \
-H "accept: application/json" \
-F "file=@fundus_image.jpg"
# Annotated image
curl -X POST "http://localhost:8000/visualize/fundus-artifacts/" \
-H "accept: image/jpeg" \
-F "file=@fundus_image.jpg" \
--output detection_result.jpg
Docker
docker build -t fundusnap-lesiondet .
docker run -p 8000:8000 fundusnap-lesiondet
curl http://localhost:8000/
Direct
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8000
Interactive docs are at http://localhost:8000/docs. The model is loaded once at import time; if
models/fundus_artifacts.pt is missing (e.g. Git LFS was not fetched), the service still starts but
both detection endpoints return HTTP 500 โ check GET / for an empty loaded_models.
License
Released under CC BY-NC 4.0 โ attribution required, non-commercial use only.
Note for redistributors: these weights are fine-tuned from Ultralytics YOLO11, and the checkpoint
itself records license: AGPL-3.0 (https://ultralytics.com/license). Ultralytics treats derivative
weights as covered by AGPL-3.0 unless you hold an Ultralytics Enterprise licence, so review
Ultralytics' licensing terms before redistributing or building on
this model. The training data carries its own separate terms, which are not published here.
Citation
@software{fundusnap_lesiondet_yolo11m_20m,
title = {fundusnap-v1-lesiondet-yolo11m-20m: YOLO11m retinal lesion detector},
author = {Fundusnap},
url = {https://huggingface.co/fundusnap/fundusnap-v1-lesiondet-yolo11m-20m},
license = {CC-BY-NC-4.0}
}
- Downloads last month
- 34
Model tree for fundusnap/fundusnap-v1-lesiondet-yolo11m-20m
Base model
Ultralytics/YOLO11Evaluation results
- mAP@50 on FUNDUS-3 (internal 12-class fundus detection export)validation set self-reported0.534
- mAP@50-95 on FUNDUS-3 (internal 12-class fundus detection export)validation set self-reported0.282
- Precision on FUNDUS-3 (internal 12-class fundus detection export)validation set self-reported0.535
- Recall on FUNDUS-3 (internal 12-class fundus detection export)validation set self-reported0.525