DiMiCount focuses on automated object counting and classification in microscopy images, with particular emphasis on large-scale slide analysis, multimodal image integration, and high-density biological samples. The framework was originally developed for the automated quantification of bivalve larvae in plankton samples, combining bright-field (BF) and fluorescence (FL) microscopy to distinguish mussel larvae from other organisms and to identify developmental stages.
In this context, the analysis workflow differs substantially from conventional object detection pipelines operating on isolated natural images. Microscopy acquisitions are typically performed as tiled scans composed of hundreds or thousands of partially overlapping fields that must later be analysed jointly as a single logical slide. To support this scenario, the framework incorporates dedicated capabilities for 2-D tile stitching, overlap-aware duplicate suppression, cross-tile object reconciliation, and whole-slide reconstruction. These features allow robust counting and localization while preventing duplicate detections at tile borders and maintaining spatial consistency across the complete acquisition.
The framework also supports multimodal image analysis through dual-mode ensemble and fusion strategies. In the original application, BF images provide morphological information, such as larval stage and object boundaries, whereas FL images provide species-specific fluorescent labelling. Since neither modality alone is sufficient for robust classification, the system integrates the outputs of modality-specific object detectors using rule-based multimodal fusion strategies. This enables the combination of complementary optical information into a unified detection and counting pipeline.
Although initially developed for plankton and larval analysis, the architecture is intentionally general and can be adapted to other microscopy and bioimaging tasks where complementary imaging modalities and large reconstructed acquisitions are required for reliable automated quantification. In particular, the 2-D tile stitching pipeline is used not only for slide reconstruction, but also for object-level deduplication during counting, preventing the same organism from being counted multiple times when it appears in overlapping tile regions.
- YOLO-based Classification & Counting: Fast and accurate detection of microscopic objects
- Reproducible Training Pipeline: Multi-model training orchestration with configurable augmentations
- K-Fold Cross-Validation: Systematic model evaluation with fold-based metrics and comparison
- Dual-Model Ensemble: Combined evaluation of models trained on different microscopy modalities with fusion rules
- 2-D Tile Stitching: Reconstruct full-resolution mosaics from tiled acquisition with quality assessment
- Comprehensive Quality Metrics: Pose estimation, constraint analysis, and performance reporting
Before you begin, make sure you have the following programs installed on your system:
- Python ≥ 3.12.3
- PDM (Python Dependency Manager)
- Install with:
pip install pdm - Used for reproducible dependency management and lock files
- Install with:
- Conda: You can install Miniconda or Anaconda:
- conda-lock: A tool for managing Conda lock files to ensure reproducible versions of low-level dependencies
- Install it in your base Conda environment with:
conda install -c conda-forge conda-lock- Python ≥ 3.12.3
- PDM (package manager;
pip install pdm) - (Optional) Conda for GPU support (CUDA drivers, cuDNN)
# Clone the repository
git clone git@github.com:sing-group/DiMiCount.git
cd DiMiCount
# Create a conda environment with GPU support
conda create -n DiMiCount python=3.12
conda activate DiMiCount
# Install CUDA dependencies via conda
conda install -c conda-forge cuda-toolkit cudnn
# Install project dependencies via PDM
pdm install# Clone the repository
git clone git@github.com:sing-group/DiMiCount.git
cd DiMiCount
# Create a Python virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install project dependencies (PDM will resolve CPU-only torch)
pip install pdm
pdm install# Install only production dependencies (no dev tools like pytest, mypy)
pdm install --prod# Check PyTorch installation
python -c "import torch; print(f'PyTorch {torch.__version__}'); print(f'CUDA available: {torch.cuda.is_available()}')"
# Run sample smoke test
pdm run pytest tests/test_public_mini_dataset.py -vVerify the entire pipeline works end-to-end with a real 20-image sample dataset included in the repository:
# 1. Generate synthetic dataset
pdm run python src/dimicount/DatasetGenerator.py \
--conf_file resources/configurations/public_smoke/DatasetMiniConf.json
# 2. Train a model (1 epoch on 20 images)
pdm run python src/dimicount/TrainModel.py \
--conf_file resources/configurations/public_smoke/TrainMiniConf.json
# 3. Run cross-validation (2-fold)
pdm run python src/dimicount/XValidation.py \
--conf_file resources/configurations/public_smoke/XValidationMiniConf.json
# 4. Stitch tiles
pdm run python src/dimicount/RunPlateStitcher.py \
--tiles-dir resources/datasets/test/sample_grid_2x2/images \
--output-dir resources/_local_samples/public_smoke/stitcher_out \
--no-export-mosaic
# 5. Validate model
pdm run python src/dimicount/ValidateModel.py --helpExpected outputs:
resources/_local_samples/public_smoke/train_out/— training metrics and model weightsresources/_local_samples/public_smoke/xvalidation_out/— cross-validation resultsresources/_local_samples/public_smoke/stitcher_out/— stitching alignments
Train YOLO models on your microscopy dataset using TrainModel.py:
python src/dimicount/TrainModel.py \
--config resources/configurations/TrainConf.jsonKey features:
- Automatic dataset splitting (train/validation)
- Data augmentation strategies (configurable)
- Multi-model experiment orchestration
- Real-time training metrics and loss curves
Configuration (TrainConf.json):
- Dataset path, image/annotation directories
- Train/validation split ratio
- Model architecture (YOLO variant)
- Augmentation parameters
- Training hyperparameters (epochs, batch size, learning rate)
Evaluate model robustness using cross-validation with XValidation.py:
python src/dimicount/XValidation.py \
--config resources/configurations/XValidationConf.jsonKey features:
- Configurable k-fold splitting
- Per-fold training and evaluation
- Aggregated cross-validation metrics (mean, std)
- Fold performance comparison
Configuration (XValidationConf.json):
- Dataset path
- Number of folds (k)
- Train/validation parameters per fold
Evaluate trained models on projects using ValidateModel.py:
python src/dimicount/ValidateModel.py \
--eval-name my_evaluation \
--project-dir resources/project_data/ \
--white-model path/to/white_model.pt \
--fluorescence-model path/to/fluorescence_model.ptKey features:
- Per-model predictions and performance metrics
- Ensemble fusion with configurable rules
- Confusion matrices, precision-recall curves, F1 analysis
- Discrepancy detection and root-cause analysis
- Qualitative insights (visualization, comparison)
To avoid duplicate counts at overlapping image borders, an image stitching process is applied to identify repeated annotations of the same specimen between microscope slide tiles and retain only the detection with the highest confidence. This ensures accurate organism counting across large-scale tiled acquisitions.
Reconstruct full-resolution mosaics from tiled microscopy acquisitions using RunPlateStitcher.py:
python src/dimicount/RunPlateStitcher.py \
--tiles-dir 'path/to/tiles' \
--overlap 0.1 \
--template-margin 0.4 \
--min-score 0.2 \
--grid-lambda 0.6 \
--output-dir 'stitching_outputs/' \
--export-mosaicAdvanced stitching example with hierarchical clustering:
python src/dimicount/RunPlateStitcher.py \
--tiles-dir 'resources/DMI6000/tiles' \
--overlap 0.22 \
--matcher-mode loftr \
--enable-ecc \
--use-hierarchical-clustering \
--cluster-size 3 \
--cluster-confidence-threshold 0.7 \
--grid-lambda 5.0 \
--output-dir 'stitching_outputs/clustering_results' \
--evaluate-xml 'resources/DMI6000/reference.xml' \
--export-mosaic| Parameter | Description | Example |
|---|---|---|
--tiles-dir |
Directory containing tile images (tif/png/jpg) | 'resources/tiles' |
--overlap |
Expected per-axis overlap fraction | 0.1 (10%) |
--template-margin |
Additional margin relaxing the search window | 0.4 |
--min-score |
Minimum correlation score for pairwise matches | 0.2 |
--grid-lambda |
Strength of soft grid prior in global solve | 0.6 |
--matcher-mode |
Affinity matcher (default or loftr) |
'loftr' |
--enable-ecc |
Enable Enhanced Correlation Coefficient refinement | ✓ |
--use-hierarchical-clustering |
Enable hierarchical tile clustering | ✓ |
--channel-index |
Select specific channel (multi-channel images) | 0 |
--evaluate-xml |
Path to Leica XML for pose validation | 'path/to/ref.xml' |
--tile-map |
JSON mapping tile IDs to (FieldX, FieldY) | 'tile_map.json' |
--use-ground-truth |
Use XML poses directly (perfect baseline) | ✓ |
--export-mosaic |
Generate mosaic PNG and JPEG preview | ✓ |
The stitching pipeline generates:
- poses.json / poses.csv – Global tile poses and transformation matrices
- neighbors.json / neighbors.csv – Neighbor relationships (up/down/left/right)
- qc_report.json / qc_report.csv – Quality control metrics for each constraint
- evaluation_metrics.json – Pose accuracy vs. Leica XML ground truth
- mosaic.png – Full-resolution stitched mosaic
- mosaic_preview.jpg – Downsampled JPEG preview (~50% of PNG size)
- constraint_count – Number of pairwise constraints. Higher is better; <1.5× tile count suggests missing links.
- constraint_rms_px – RMS of translation residuals (pixels). Target: well below the overlap band.
- constraint_p95_px – 95th percentile residual. Spikes indicate potential mismatches.
- coverage_ratio – Tile area / bounding box area. ≈1 indicates tight coverage.
- avg_neighbor_confidence – Confidence across all neighbors (0–1). Higher is better.
- pose_rmse_px – RMSE of solved poses vs. ground truth XML. Target: tens of pixels.
- pose_median_px – Median absolute pose error (robust to outliers).
- pose_p95_px – 95th percentile pose error. If it exceeds overlap band width, investigate corresponding tiles.
Before you begin, make sure you have the following programs installed on your system:
-
Conda: You can install Miniconda or Anaconda:
-
conda-lock: A tool for managing Conda lock files to ensure reproducible versions of low-level dependencies.
- Install it in your base Conda environment with:
conda install -c conda-forge conda-lock
- Install it in your base Conda environment with:
In order to ensure the reproducibility as much as possible, the project uses conda-lock.yml, as well as pdm.lock.
Here are the steps to create the environment with all libraries in their exact version as the lock files are pointing at.
# Clone the repository
git clone git@github.com:sing-group/DiMiCount.git
cd DiMiCount
# Create the environment with conda-lock (using the conda.lock file)
conda-lock install --name DiMiCount
conda env create -f environment.yml
# Activate the environment
conda activate DiMiCount
# Install Python dependencies with PDM according to pdm.lock
pdm install
# Optional but recommended to run tests locally
pdm install -G optionalalternative mode
conda deactivate
rm -r .venv
rm -r .env
rm -r pdm.lock
conda activate base
conda install -c conda-forge conda-lock -y
conda-lock lock --platform linux-64 # win-64
conda-lock -f environment.yml
conda-lock install -p ./.venv
conda activate $(pwd)/.venv
pdm config venv.in_project false
pdm install
pdm lock
pdm install -G optionalThe project expects YOLO-style split datasets organized by training and validation splits, with images, labels, and a configuration file.
All datasets follow this structure:
dataset_root/
data.yaml # YOLO dataset configuration
train/
images/ # Training images (JPG, PNG, etc.)
labels/ # Training labels (TXT, YOLO format)
val/
images/ # Validation images
labels/ # Validation labels
Key Points:
- Split Strategy: Data is pre-split into
train/(typically 80%) andval/(typically 20%). - YOLO Format: Labels are normalized bounding box coordinates in TXT format:
class_id center_x center_y width height(all normalized to [0, 1]). - data.yaml: Configures class names and paths; required for training and validation pipelines.
The repository includes two small YOLO samples for smoke testing:
Bright Field (BF) Sample
- Path:
resources/sample_datasets/bright-field/ - Images: 4 train + 1 val
- Classes:
Type D,Type U(2 classes) - Use: Training and dataset generation smoke tests
Fluorescence (FL) Sample
- Path:
resources/sample_datasets/fluorescence/ - Images: 4 train + 1 val
- Classes:
Mussel,Other(2 classes) - Use: Cross-validation and dataset processing smoke tests
Example structure:
path: ./resources/sample_datasets/bright-field
train: train/images
val: val/images
nc: 2
names:
0: Type D
1: Type UFields:
path: Absolute or relative base directory of the datasettrain: Path to training images relative topathval: Path to validation images relative topathnc: Total number of object classesnames: Dictionary mapping class indices to human-readable names
Multi-Modality Support:
- BF and FL samples use the same tile/slide identifiers (
s00–s04) across modalities - Each modality is stored as a separate dataset (independent paths)
- Pipelines can process them individually or in tandem for multi-modal analysis
src/dimicount/
├── TrainModel.py # Multi-model training orchestration
├── XValidation.py # K-fold cross-validation pipeline
├── ValidateModel.py # Per-model and ensemble evaluation
├── RunPlateStitcher.py # Tile stitching and mosaication
├── DatasetGenerator.py # Dataset preparation utilities
├── Constants.py # Project constants
│
│
└── stitching/ # Advanced tile stitching algorithms
├── AlignmentMetrics.py # Quality assessment
├── CanvasGeometryManager.py
└── ... (matching, refinement, fusion strategies)
resources/
├── configurations/
│ ├── TrainConf.json # Training configuration template
│ ├── XValidationConf.json # Cross-validation configuration
│ └── DatasetConf.json # Dataset paths and split configuration
└── _local_samples/ # Sample datasets for quick testing
tests/ # Comprehensive test suite
├── test_*.py # Unit and integration tests
└── verify_*.py # Validation scripts
All pipelines are configured via JSON files in resources/configurations/:
{
"dataset_path": "path/to/dataset",
"image_dir": "images",
"labels_dir": "labels",
"train_split": 0.8,
"checkpoint_dir": "out/train",
"model": "yolo11n",
"epochs": 50,
"batch_size": 32,
"augment": true
}{
"dataset_path": "path/to/dataset",
"k_folds": 5,
"model": "yolo11n",
"epochs": 50,
"batch_size": 32,
"output_dir": "out/xvalidation"
}{
"dataset_root": "path/to/dataset",
"splits": {
"train": "train_images_list.txt",
"val": "val_images_list.txt"
}
}Run the comprehensive test suite:
# Ensure test dependencies are available
pdm install -G optional
# Run all tests
./run_tests.sh
# Or use pytest directly
pytest tests/ -v# Regenerate a tiny local sample dataset and config
PYTHONPATH=src pdm run python resources/_local_samples/xvalidation_smoke/generate_sample_dataset.py
# Run 2-fold smoke validation (1 epoch)
PYTHONPATH=src pdm run python src/dimicount/XValidation.py \
--conf_file resources/_local_samples/xvalidation_smoke/xvalidation_smoke_conf.jsonThis repository includes two tiny YOLO samples extracted from the provided slide archive:
resources/sample_datasets/bright-field(bright field)resources/sample_datasets/fluorescence(fluorescence)
Run these commands from the repository root:
# 1) Dataset preparation smoke (DatasetGenerator.py)
PYTHONPATH=src pdm run python src/dimicount/DatasetGenerator.py \
--conf_file resources/configurations/public_smoke/DatasetMiniConf.json
# 2) Minimal training smoke (TrainModel.py, 1 epoch)
PYTHONPATH=src pdm run python src/dimicount/TrainModel.py \
--conf_file resources/configurations/public_smoke/TrainMiniConf.json
# 3) Minimal cross-validation smoke (XValidation.py, 2 folds)
PYTHONPATH=src pdm run python src/dimicount/XValidation.py \
--conf_file resources/configurations/public_smoke/XValidationMiniConf.json
# 4) Minimal stitching smoke (RunPlateStitcher.py)
PYTHONPATH=src pdm run python src/dimicount/RunPlateStitcher.py \
--tiles-dir resources/datasets/test/sample_grid_2x2/images \
--output-dir resources/_local_samples/public_smoke/stitcher_out \
--no-export-mosaic
# 5) ValidateModel CLI check (full evaluation needs model assets configured)
PYTHONPATH=src pdm run python src/dimicount/ValidateModel.py --helpNotes:
- The training smoke output is written under
resources/_local_samples/public_smoke/train_out. - DatasetGenerator smoke output is written under
resources/_local_samples/public_smoke/dataset_out. - The public smoke JSON files use paths relative to their own directory, so they can be reused without hardcoded absolute paths.
TrainMiniConf.jsontargetsbright-field(BF split dataset with 5 images total).XValidationMiniConf.jsontargetsfluorescence(FL split dataset with 5 images total for 2-fold smoke validation).DatasetMiniConf.jsontargetsfluorescence(FL images/labels split dataset with 5 images total).- ValidateModel full run depends on model weights and project-level evaluation inputs configured in
resources.
The test suite covers:
- Dataset loading and augmentation
- Model training and inference
- Cross-validation workflows
- Stitching algorithms and quality metrics
- Ensemble evaluation and fusion
- Label Studio integration
- XML parsing and grid validation
| Component | Technology | Version |
|---|---|---|
| Deep Learning | PyTorch + Ultralytics | 2.5.1 + 8.3.169 |
| Detection | YOLO (nano/small/medium/large/xlarge) | YOLOv8/v11 |
| Augmentation | Albumentations | 1.4.21 |
| Tune Hyperparameters | Optuna + Ray Tune | 4.4.0 + 2.35.0 |
| Visualization | Plotly + Matplotlib | 5.22.0 + 3.8.4 |
| Image Processing | OpenCV + Kornia | 4.11.0 + 0.8.1 |
| Data Analysis | Pandas + Numpy + SciPy | 2.2.2 + 1.26.4 + 1.16.3 |
- ✓ Multi-model experiment orchestration
- ✓ Automatic train/val split with reproducible seeds
- ✓ Configurable augmentation pipelines
- ✓ Real-time training curves and metrics export
- ✓ Model checkpointing and best-weight selection
- ✓ Batch predictions with visualization
- ✓ K-fold split generation with stratification
- ✓ Per-fold training and evaluation
- ✓ Aggregated metrics (mean, std, min, max)
- ✓ Confusion matrices and performance curves per fold
- ✓ CSV export of metrics for downstream analysis
- ✓ Per-model inference on project datasets
- ✓ Dual-model support (white + fluorescence modalities)
- ✓ Ensemble fusion with configurable rules
- ✓ Precision, recall, F1, IoU per class
- ✓ Confusion matrices and precision-recall curves
- ✓ Discrepancy detection and root-cause analysis
- ✓ Batch prediction visualization
- ✓ Multi-matcher support (default correlation, LoFTR)
- ✓ ECC (Enhanced Correlation Coefficient) refinement
- ✓ Hierarchical tile clustering
- ✓ Global optimization with soft grid prior
- ✓ Leica XML ground-truth support for validation
- ✓ Full-resolution mosaic reconstruction
- ✓ Comprehensive quality metrics and reporting
- ✓ Label Studio project integration (upload/download/merge)
- ✓ Image similarity metrics (SSIM, VGG16 embeddings)
- ✓ Video frame extraction
- ✓ XML parsing and grid topology validation
- ✓ Annotation statistics and distribution analysis
# 1. Prepare your dataset in YOLO format (images/ + labels/)
# 2. Update configuration
vim resources/configurations/TrainConf.json
# 3. Train model
python src/dimicount/TrainModel.py --config resources/configurations/TrainConf.json
# 4. Evaluate with cross-validation
python src/dimicount/XValidation.py --config resources/configurations/XValidationConf.json
# 5. Run final evaluation on project data
python src/dimicount/ValidateModel.py \
--eval-name my_eval \
--project-dir resources/project_data/
# 6. (Optional) Stitch microscopy tiles
python src/dimicount/RunPlateStitcher.py \
--tiles-dir path/to/tiles \
--overlap 0.1 \
--output-dir stitching_outputs/Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
This project is licensed under the AGPL-3.0-or-later license.