Skip to content

sing-group/DiMiCount

Repository files navigation

DiMiCount: Dual Illumination Microscope Counting Pipeline

Project Overview

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.

Core Capabilities

  • 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

Requirements

Before you begin, make sure you have the following programs installed on your system:

  1. Python ≥ 3.12.3
  2. PDM (Python Dependency Manager)
    • Install with: pip install pdm
    • Used for reproducible dependency management and lock files
  3. Conda: You can install Miniconda or Anaconda:
    • Miniconda (lighter)
    • Anaconda (includes more default packages)
    • Recommended for GPU support (CUDA drivers, cuDNN)
  4. 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

Quick Start

Installation

Prerequisites (Quick Reference)

  • Python ≥ 3.12.3
  • PDM (package manager; pip install pdm)
  • (Optional) Conda for GPU support (CUDA drivers, cuDNN)

Option 1: GPU Setup (Recommended for NVIDIA GPUs)

# 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

Option 2: CPU-Only Setup

# 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

Option 3: Minimal Install (Production / Smoke Tests Only)

# Install only production dependencies (no dev tools like pytest, mypy)
pdm install --prod

Verify Installation

# 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 -v

Quick Test: Smoke Pipeline

Verify 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 --help

Expected outputs:

  • resources/_local_samples/public_smoke/train_out/ — training metrics and model weights
  • resources/_local_samples/public_smoke/xvalidation_out/ — cross-validation results
  • resources/_local_samples/public_smoke/stitcher_out/ — stitching alignments

Workflow Components

1. Training Pipeline

Train YOLO models on your microscopy dataset using TrainModel.py:

python src/dimicount/TrainModel.py \
  --config resources/configurations/TrainConf.json

Key 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)

2. K-Fold Cross-Validation

Evaluate model robustness using cross-validation with XValidation.py:

python src/dimicount/XValidation.py \
  --config resources/configurations/XValidationConf.json

Key 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

3. Model Evaluation & Ensemble

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.pt

Key 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)

4. 2-D Tile Stitching & Mosaication

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-mosaic

Advanced 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

Stitching Parameters

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

Stitching Output Artifacts

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)

Key Stitching Quality Metrics

  • 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.

Requirements

Before you begin, make sure you have the following programs installed on your system:

  1. Conda: You can install Miniconda or Anaconda:

  2. 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

Setting Up the Environment

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 optional

alternative 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 optional

Dataset Structure

The project expects YOLO-style split datasets organized by training and validation splits, with images, labels, and a configuration file.

Standard Split Dataset Layout

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%) and val/ (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.

Public Sample Datasets (5 images each)

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

data.yaml Configuration

Example structure:

path: ./resources/sample_datasets/bright-field
train: train/images
val: val/images
nc: 2
names:
  0: Type D
  1: Type U

Fields:

  • path: Absolute or relative base directory of the dataset
  • train: Path to training images relative to path
  • val: Path to validation images relative to path
  • nc: Total number of object classes
  • names: Dictionary mapping class indices to human-readable names

Multi-Modality Support:

  • BF and FL samples use the same tile/slide identifiers (s00s04) across modalities
  • Each modality is stored as a separate dataset (independent paths)
  • Pipelines can process them individually or in tandem for multi-modal analysis

Project Structure

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

Configuration Files

All pipelines are configured via JSON files in resources/configurations/:

TrainConf.json

{
  "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
}

XValidationConf.json

{
  "dataset_path": "path/to/dataset",
  "k_folds": 5,
  "model": "yolo11n",
  "epochs": 50,
  "batch_size": 32,
  "output_dir": "out/xvalidation"
}

DatasetConf.json

{
  "dataset_root": "path/to/dataset",
  "splits": {
    "train": "train_images_list.txt",
    "val": "val_images_list.txt"
  }
}

Testing

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

XValidation Smoke Check (sample local dataset)

# 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.json

Public Smoke Check (4 main scripts + BF/FL mini datasets with 5 images each)

This 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 --help

Notes:

  • 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.json targets bright-field (BF split dataset with 5 images total).
  • XValidationMiniConf.json targets fluorescence (FL split dataset with 5 images total for 2-fold smoke validation).
  • DatasetMiniConf.json targets fluorescence (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

Key Technologies

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

Features & Capabilities

Training

  • ✓ 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

Cross-Validation

  • ✓ 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

Evaluation & Ensemble

  • ✓ 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

Stitching

  • ✓ 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

Utilities

  • ✓ 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

Example Workflow

Complete End-to-End Pipeline

# 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/

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.


License

This project is licensed under the AGPL-3.0-or-later license.


About

Public Counting Model is an open-source end-to-end pipeline for object counting on microscopy and mosaic images. It provides YOLO-compatible dataset generation, training and cross-validation scripts, image stitching and visualization tools, sample datasets, and tests to reproduce and evaluate results.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors