Skip to content

DINOv2 Technical Reference

spatialhub.models.dinov2 provides an ONNX Runtime adapter for DINOv2, extracting global L2-normalized CLS token feature embeddings from images.


Supported Model Variants

The DINOv2Adapter supports 4 Vision Transformer backbone variants via model_variant:

Model Variant (model_variant) ONNX File Parameter Count Embedding Dimension (\(D\)) Architecture & Role
"vits14" dinov2_vits14.onnx ~21M \(D = 384\) ViT-Small/14 backbone (high throughput, minimal memory footprint).
"vitb14" dinov2_vitb14.onnx ~86M \(D = 768\) ViT-Base/14 backbone (balanced descriptor capacity).
"vitl14" (Default) dinov2_vitl14.onnx ~300M \(D = 1024\) ViT-Large/14 backbone (high semantic representation capacity).
"vitg14" dinov2_vitg14.onnx ~1.1B \(D = 1536\) ViT-Giant/14 backbone (maximum representation capacity).

Preprocessing & Post-processing Flow

DINOv2 extracts global feature embeddings from input images through square padding, bilinear resizing, and ImageNet channel normalization.

graph TD
    A["Input Image(s): NumPy / Path / List"] --> B["Square Pad (Preserve Aspect Ratio)"]
    B --> C["Bilinear Resize (target_size x target_size)"]
    C --> D["Scale [0.0, 1.0] & ImageNet Channel Normalization"]
    D --> E["ONNX Runtime Forward Pass"]
    E --> F["Extract Raw CLS Token Embedding (N, D)"]
    F --> G{"l2_normalize=True?"}
    G -- "Yes" --> H["Feature L2 Normalization"]
    G -- "No" --> I["Keep Raw Embeddings"]
    H --> J["FeatureExtractionResult"]
    I --> J

Square Padding & Spatial Resizing

Given an input image with native dimensions \((W, H)\), the image is zero-padded along the shorter dimension to form a square canvas of side \(S = \max(W, H)\), preserving aspect ratio:

\[ x_{\text{offset}} = \left\lfloor \frac{S - W}{2} \right\rfloor, \qquad y_{\text{offset}} = \left\lfloor \frac{S - H}{2} \right\rfloor \]

The square canvas is resized to spatial dimension \(S_{\text{target}} \times S_{\text{target}}\) (target_size, default \(224 \times 224\)), which must be a positive integer multiple of the ViT patch size (\(14\text{ px}\)):

\[ S_{\text{target}} = 14 \cdot k, \quad k \in \mathbb{Z}^+ \]

ImageNet Normalization

Pixel values scaled to \([0.0, 1.0]\) are normalized per channel \(c \in \{R, G, B\}\):

\[ x_{\text{norm}} = \frac{x - \mu_c}{\sigma_c} \]

Where \(\mu = [0.485, 0.456, 0.406]\) and \(\sigma = [0.229, 0.224, 0.225]\).

L2 Feature Normalization

When l2_normalize=True, extracted CLS token embedding vectors \(v \in \mathbb{R}^D\) are normalized to unit Euclidean length:

\[ v_{\text{norm}} = \frac{v}{\max(\|v\|_2,\, 10^{-6})} = \frac{v}{\max\left(\sqrt{\sum_{i=1}^D v_i^2},\, 10^{-6}\right)} \]

Numerical Parity Verification

Numerical parity evaluates mathematical agreement between the original PyTorch Hub reference models (facebookresearch/dinov2) and the SpatialHub ONNX Runtime adapter on \(20\) benchmark images sampled from the COCO 2017 validation dataset (val2017.zip extracted to .cache/images/) at \(224 \times 224\) resolution.

Model Variant Cosine Sim Feature L2 Dist Feature MAE Max Diff Rel Error (%)
vits14 0.999999 0.001066 \(4.32 \times 10^{-5}\) \(3.20 \times 10^{-4}\) 0.11%
vitb14 1.000000 0.000874 \(2.50 \times 10^{-5}\) \(1.38 \times 10^{-4}\) 0.09%
vitl14 1.000000 0.000816 \(2.02 \times 10^{-5}\) \(1.96 \times 10^{-4}\) 0.08%
vitg14 1.000000 0.000305 \(6.19 \times 10^{-6}\) \(3.90 \times 10^{-5}\) 0.03%

To evaluate parity on local sample images:

uv run tools/benchmark/parity_dinov2.py \
    --variant all \
    --data-dir .cache/images \
    --output-file .profile/parity_dinov2.md

Performance Benchmarks

Latency, throughput, and memory footprint measured across \(10\) unmeasured warmup iterations and \(50\) timed measurement iterations at \(224 \times 224\) resolution.

Variant Stage Latency Mean (ms) Median (ms) P95 (ms) Throughput (FPS) Peak RAM Delta Peak VRAM Delta
vits14 Preprocess 1.07 +/- 0.13 1.08 1.29 931.7 +0.6 MB 0.0 MB
Inference 4.73 +/- 0.58 4.61 5.64 211.4 +0.2 MB +6.0 MB
End-to-End 5.44 +/- 0.66 5.38 6.37 183.7 +2.9 MB 0.0 MB
vitb14 Preprocess 1.28 +/- 0.16 1.22 1.56 784.3 +1.1 MB 0.0 MB
Inference 8.50 +/- 0.59 8.28 9.66 117.7 0.0 MB +10.0 MB
End-to-End 9.20 +/- 0.51 9.05 10.35 108.7 +1.1 MB 0.0 MB
vitl14 Preprocess 1.24 +/- 0.15 1.20 1.63 806.4 +1.1 MB 0.0 MB
Inference 29.00 +/- 2.60 29.76 31.70 34.5 0.0 MB +14.0 MB
End-to-End 32.71 +/- 0.98 32.24 34.47 30.6 +1.0 MB 0.0 MB
vitg14 Preprocess 1.17 +/- 0.11 1.13 1.42 854.4 +1.1 MB 0.0 MB
Inference 133.93 +/- 16.64 121.71 156.30 7.5 +0.6 MB +20.0 MB
End-to-End 192.66 +/- 37.56 188.61 277.27 5.2 +2.7 MB 0.0 MB

Hardware Power & Thermal Scaling on vitg14

On vitg14 (~1.1B parameters), isolated inference reflects peak GPU boost clocks (~1575 MHz at 140W TGP, ~133.9 ms). Under continuous sequential load across benchmark stages, GPU thermal management and power limits throttle operating clocks to steady-state frequencies (~1110–1200 MHz at ~89W, ~192.7 ms).

Variant Stage Latency Mean (ms) Median (ms) P95 (ms) Throughput (FPS) Peak RAM Delta
vits14 Preprocess 1.26 +/- 0.14 1.24 1.54 794.6 +1.7 MB
Inference 43.96 +/- 4.27 42.78 52.61 22.7 +1.1 MB
End-to-End 44.94 +/- 1.97 44.79 47.99 22.3 0.0 MB
vitb14 Preprocess 1.38 +/- 0.17 1.36 1.74 722.2 0.0 MB
Inference 141.89 +/- 6.92 140.81 156.49 7.0 +0.1 MB
End-to-End 144.51 +/- 8.15 143.84 153.65 6.9 0.0 MB
vitl14 Preprocess 1.26 +/- 0.04 1.27 1.34 791.5 +1.7 MB
Inference 512.34 +/- 9.32 512.58 530.10 2.0 0.0 MB
End-to-End 521.78 +/- 15.71 520.54 542.00 1.9 0.0 MB
vitg14 Preprocess 1.48 +/- 0.11 1.46 1.69 674.3 +1.9 MB
Inference 1959.85 +/- 38.62 1963.05 2030.01 0.5 +3.2 MB
End-to-End 1916.91 +/- 26.12 1912.71 1967.96 0.5 0.0 MB


SpatialHub Adapter API & Usage

from spatialhub.models.dinov2 import DINOv2Adapter

# Initialize DINOv2 adapter with ViT-L/14 backbone (1024-dim)
with DINOv2Adapter(
    model_variant="vitl14",
    target_size=224,
    providers=["CUDAExecutionProvider", "CPUExecutionProvider"],
) as extractor:
    # Single image input (path or array)
    result_single = extractor.extract_features("sample.jpg", l2_normalize=True)
    print("Single embedding shape:", result_single.features.shape)  # (1, 1024)

    # Batch or collection input (list of images or paths)
    result_batch = extractor.extract_features(["image_0.jpg", "image_1.jpg"], l2_normalize=True)
    print("Batch embedding shape:", result_batch.features.shape)   # (2, 1024)

Tooling & Verification Commands

Export DINOv2 backbone models from PyTorch Hub to ONNX format:

# Export a specific variant
uv run tools/export/export_dinov2.py \
    --variant vitl14 \
    --output-folder onnx_weight \
    --opset 17

# Export all variants
uv run tools/export/export_dinov2.py \
    --variant all \
    --output-folder onnx_weight
Parameter Type Default Description
--variant str "vitl14" Model variant to export (vits14, vitb14, vitl14, vitg14, or all).
--output-folder str "onnx_weight" Destination directory for exported .onnx models.
--width int 224 Input image width in pixels (must be a multiple of 14).
--height int 224 Input image height in pixels (must be a multiple of 14).
--image-size int None Convenience parameter to set square dimensions (width = height = image_size).
--opset int 17 ONNX Operator Set version.

Evaluate numerical parity between PyTorch Hub reference models and SpatialHub ONNX Runtime adapter:

uv run tools/benchmark/parity_dinov2.py \
    --variant all \
    --data-dir .cache/images \
    --output-file .profile/parity_dinov2.md
Parameter Type Default Description
--variant str "all" Model variant to evaluate (vits14, vitb14, vitl14, vitg14, or all).
--data-dir str ".cache/images" Directory containing benchmark image files.
--model-dir str None Optional directory containing local .onnx weight files.
--max-images int 20 Maximum number of images to evaluate.
--output-file str None Optional path to output markdown report file.

Benchmark stage-by-stage latency, throughput, and memory footprint:

uv run tools/benchmark/profile_dinov2.py \
    --variant all \
    --provider all \
    --data-dir .cache/images \
    --warmup 10 \
    --iters 50 \
    --output-file .profile/profile_dinov2.md
Parameter Type Default Description
--variant str "all" Model variant to profile (vits14, vitb14, vitl14, vitg14, or all).
--provider str "all" Target execution provider filter (cuda, cpu, or all).
--data-dir str ".cache/images" Directory containing sample image for profiling.
--model-dir str None Optional directory containing local .onnx weight files.
--warmup int 10 Number of unmeasured warmup iterations.
--iters int 50 Number of timed measurement iterations.
--output-file str None Optional path to save markdown benchmark report.

Returned Result Data Structure

Returns a FeatureExtractionResult dataclass:

Attribute Type Shape Description
images np.ndarray (H, W, 3) or (N, H, W, 3) Original input image array or stacked batch array.
features np.ndarray (N, D) float32 Extracted global CLS token feature embedding vectors.
embedding_type str N/A Feature scope ("global").
l2_normalized bool N/A Flag indicating whether feature embeddings are unit L2-normalized.