Single-patient cervical image filtering, lesion segmentation, and multimodal diagnosis pipeline
Project description
CervicalDoctor
CervicalDoctor provides one complete single-patient pipeline and four independent tasks:
import CervicalDoctor
CervicalDoctor.pipeline(...)
CervicalDoctor.detect(...)
CervicalDoctor.acetic(...)
CervicalDoctor.seg(...)
CervicalDoctor.classify(...)
The diagnosis class order is always Ca, HSIL, LSIL, Normal. Python reserves the word class, so
the public diagnosis function is named classify.
Installation and model assets
Install the code package from PyPI:
pip install CervicalDoctor
The PyPI wheel intentionally does not contain the approximately 17 GB model bundle. Until the model
bundle is published separately, point the installed package at an existing CervicalDoctor asset
directory whose direct child is ckpt/:
export CERVICALDOCTOR_HOME=/path/to/CervicalDoctor-assets
The source checkout detects its own ckpt/ automatically. Installed builds otherwise look under
~/.cache/cervicaldoctor/. A missing model raises an explicit error showing the expected path.
Input contract
Except for standalone acetic, image_path may be either:
- one
.jpg,.jpeg,.png,.bmp,.dcm, or.dicomfile; or - one folder whose direct image children all belong to the same patient.
Input folders are deliberately not scanned recursively. Standalone acetic requires a folder even
when it contains only one image. A folder containing no supported direct image files is rejected.
Complete pipeline
result = CervicalDoctor.pipeline(
image_path="case_001",
txt_path=None,
filter=True,
conf=0.25,
out_dir=None,
device="cuda",
)
When filter=True, every image is passed through cervix detection and acetic-image classification.
Only original images satisfying both conditions continue:
at least one cervix detection AND acetic top-1 == vinegar
Detection visualizations are never sent to segmentation or diagnosis. When filter=False, both
dirty-data checks are skipped and every original input image continues directly. Segmentation is
mandatory in both modes because the released diagnosis model was trained with binary lesion masks.
If filtering keeps no image, the result has status="no_eligible_images" and no diagnosis is
fabricated.
The default folder-input output is <image_path>/cervicaldoctor_output. A typical result is:
cervicaldoctor_output/
├── detect/
│ ├── image_1.jpg.detected.png
│ ├── image_2.png.detected.png
│ └── detect.json
├── acetic/
│ ├── image_2.png
│ └── acetic.json
├── filtered/
│ └── image_2.png
├── classification/
│ ├── segmentation/
│ │ ├── masks/
│ │ │ └── image_2.png.mask.png
│ │ ├── overlays/
│ │ │ └── image_2.png.overlay.png
│ │ └── segmentation.json
│ └── prediction.json
├── filter.json
└── pipeline_result.json
For a single-file input, the default is a sibling folder such as
image_1_cervicaldoctor_output/. Pass out_dir to choose another location. Existing output is
protected unless overwrite=True is set.
Independent tasks
Cervix detection
result = CervicalDoctor.detect(
image_path="case_001", # file or folder
conf=0.25,
out_dir="detect_output",
device="cuda",
)
Every input image/frame receives a .detected.png visualization, including images with no box.
detect.json and the returned dictionary contain box coordinates, confidence, has_cervix, source
identity, and visualization path.
Acetic-image selection
result = CervicalDoctor.acetic(
image_path="case_001", # folder is required
out_dir="acetic_output",
device="cuda",
)
The output folder contains zero or more original images whose top-1 class is vinegar, plus
acetic.json. This independent task does not require a cervix detection; the intersection rule is
applied only by pipeline(filter=True).
Binary lesion segmentation
result = CervicalDoctor.seg(
image_path="case_001", # file or folder
out_dir="seg_output",
device="cuda",
)
masks/ contains binary PNG masks with 0=background and 255=lesion. overlays/ contains green
mask-on-original visualizations. segmentation.json maps every artifact to its source image/frame.
Patient diagnosis
result = CervicalDoctor.classify(
image_path="case_001", # file or folder; all images are one patient
txt_path="txt.json", # or None
out_dir="classify_output",
device="cuda",
)
classify always invokes the public binary segmenter internally. There is no public switch to skip
segmentation and no external mask_path argument. Multiple images are pooled into one patient-level
diagnosis. The return value includes probabilities, per-image attention, source gates, text gate,
the complete internal segmentation manifest, and the epoch-16 all-data checkpoint identity.
Clinical JSON and cache
txt_path=None means age, HPV, and cytology are all unavailable. Its HealthGPT feature is shipped
as a precomputed release cache, so the 8B text encoder is not loaded.
A clinical JSON contains one patient's data:
{
"age": 45,
"hpv": "HPV16 positive",
"cytology": "HSIL"
}
The legacy keys hpv_standardization and cytology_standardization are also accepted. The JSON is
reread on every call. Cache identity is computed from the normalized prompt content rather than the
file path:
- unchanged content reuses
cache/inference_text/<content-hash>.pt; - changed content generates a different key and feature;
- the first unseen prompt loads HealthGPT; later calls do not.
BMP and DICOM
BMP is decoded as an ordinary RGB raster. DICOM decoding handles:
- uncompressed and supported compressed pixel data;
- grayscale rescale, VOI LUT/windowing, and
MONOCHROME1inversion; - RGB and YBR color conversion;
- single-frame and multi-frame objects.
Each multi-frame DICOM frame is treated as one image belonging to the same patient. A safety limit of 64 frames prevents accidental ingestion of long videos. DICOM is converted to temporary RGB PNG only for model execution; temporary files are removed after the task. Detector and segmentation visualizations are always PNG. Accepted single-frame DICOM files remain DICOM; accepted frames from a multi-frame object are materialized as RGB PNG files so rejected frames cannot re-enter the next stage.
Format support does not make the model clinically calibrated for unrelated grayscale modalities. The released diagnosis model was trained on colposcopy imagery.
Device
The NVIDIA build accepts:
cpu
cuda
cuda:N
auto
Top-level functions default to cuda. auto selects CUDA when torch.cuda.is_available() is true.
Dynamic uncached clinical text is technically supported on CPU but loading HealthGPT-Pro-8B is slow
and memory intensive. txt_path=None avoids that load through the release cache.
An instance can reuse lazy-loaded models:
doctor = CervicalDoctor.CervicalDoctor(device="cuda")
first = doctor.pipeline("case_001", filter=True)
second = doctor.classify("case_002", txt_path=None)
doctor.release()
Active checkpoints
All active runtime assets are under ckpt/:
ckpt/cervicaldc/: cervix detector and acetic-image classifier;ckpt/cervicalseg-v0.2.0/: binary lesion checkpoint used bycervicalseg>=0.2.0;ckpt/cervicaldoctor/weights_full_final_epoch_016.pt: the only active diagnosis weight;ckpt/cervicaldoctor/text_cache/: release cache for missing clinical information;ckpt/dinov3-vits16-pretrain-lvd1689m/: local DINOv3 model;ckpt/healthgpt-pro-8b/: local HealthGPT text encoder.
Patient-split and resumable full-training checkpoints are stored under backups/ and are never
loaded by the public API. CervicalDC's required Ultralytics runtime is integrated under
cervical_doctor/_vendor/; the package does not import the sibling CervicalDC project.
Verification
Run API/model contract tests:
python scripts/run_smoke_tests.py
Verify every declared model asset:
python scripts/verify_assets.py
Training source
The original patient-level training implementation remains available through train.py and
train_full.py. The release diagnosis weight was trained for 16 epochs on the filtered
train+validation+test union after epoch count selection by the preceding patient-split experiment.
The active model uses DINOv3 ViT-S/16, binary CervicalSeg lesion ROI weights, Haar LH/HL/HH sources,
per-image five-source gating, patient attention MIL, and frozen HealthGPT clinical features.
The code package is distributed independently from the large model assets. Hugging Face model publishing and automatic asset download can be added without changing the public inference API.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cervicaldoctor-0.4.0.tar.gz.
File metadata
- Download URL: cervicaldoctor-0.4.0.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88d48eef785b8d932898685b8e0fcc764085cc06c2fbea081fd439fc38d7fa6c
|
|
| MD5 |
9b7faa9841092c94e56578b671d548f1
|
|
| BLAKE2b-256 |
68f81c5a43a8a0ace2e2c4a3c10e157ef39d30736c1ad21bd77a7d7af7e1b0d0
|
File details
Details for the file cervicaldoctor-0.4.0-py3-none-any.whl.
File metadata
- Download URL: cervicaldoctor-0.4.0-py3-none-any.whl
- Upload date:
- Size: 1.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9c8e86c4170008ac3bacdca5c154d24d71394fbde19fedd0f71f642b4d07347
|
|
| MD5 |
61463f7c89584ac601fc3985b4d8761e
|
|
| BLAKE2b-256 |
5b19c8e25cdf80004a9396dd1cac98fde77d615d0c89af6e736fd4899aab730d
|