Nils-Treuheit/object_view_selection

This is a tool that decides which image+mask combinations to use from a set of many image+mask samples.

2

stars

58

commits

Python

primary language

Aug 11, 2026

updated

README

Object View Selection

Select the best N image/mask pairs that maximize object identifiability — high-quality, diverse, non-redundant viewpoints of a single object.

Dataset → Auto-Threshold → Pre-Filter → Quality Score → Embeddings → Subset Selection → Outputs
StageWhat it does
Auto-ThresholdTunes legacy filters via dataset statistics; the default blur/artifact pre-filters use static relaxed floors + population-relative outlier rejection
Pre-filter5 conservative filters: empty mask, frame-touching mask, boundary-band Laplacian blur, boundary-band Tenengrad blur, mask artifacts
Quality ScoreWeighted combination of 4 components: boundary-blur, mask-area, mask-artifacts, centerness
EmbeddingsDINOv3 / DINOv2 / SigLIP2 / SigLIP / MoonViT / CLIP / EVA-CLIP features (or classical shape descriptors on CPU)
SelectionGreedy quality+diversity (default), FPS, Facility Location, DPP, Next-Best-View, or top-kMeans-xNN

Installation

git clone <repo> && cd object_view_selection

python3 -m venv .venv && source .venv/bin/activate

uv sync                  # or: pip install -r requirements.txt

Optional extras for learned embeddings: torch torchvision timm, transformers (DINOv3/SigLIP), open-clip-torch (EVA-CLIP), git+https://github.com/openai/CLIP.git.

Usage

Minimum command:

python run.py --data_root /path/to/bottle --num_views 10 --output_dir ./outputs

--data_root must contain images/ and masks/ (binary masks, same filenames), plus optional object_hands/ and depth/:

bottle/
├── images/          # 00000.png, 00001.png, ...
├── masks/           # 00000.png, 00001.png, ...  (binary, same filename)
├── object_hands/    # optional, binary hand occlusion
└── depth/           # optional, copied through to outputs

Key parameters

ArgumentDefaultChoices / notes
--num_views10Number of views to select
--embeddingautoauto, dinov3, dinov2, siglip2, siglip, moonvit, clip, eva_clip
--embedding_modelfacebook/dinov3-vitb16-pretrain-lvd1689mModel name/path; type inferred when --embedding=auto
--selectorquality_diversityfps, quality_diversity, facility_location, dpp, next_best_view, top_kmeans_xnn
--selector_alpha / --selector_beta0.60 / 0.40Quality / diversity weights (GQD)
--selector_diversity_modeminmin, max, prototype — how GQD measures distance to the selected set
--selector_use_descriptorsoffBlend a shape-descriptor divergence (default silhouette) into the GQD diversity term
--selector_descriptor / --selector_descriptor_weightsilhouette / 0.5Descriptor family and its share of the GQD diversity term
--kmeans_initbest_qualityfarthest or best_quality (top_kmeans_xnn)
--kmeans_k--num_viewsk-means clusters; smaller explicit k seeds kMeans-xNN and fills the rest by cluster avg. quality
--kmeans_xnn_k103, 5, or 10 (top_kmeans_xnn)
--use_shape_descriptorsoffCPU shape descriptors (hu, zernike, fourier, shape_context)
--filter_orderconfig defaultComma-separated pre-filter order; runs ONLY the named pre-filters (including soft vincents_area/vincents_motion_blur); legacy border,area,occlusion,confidence,completeness for custom orders only
--auto-thresholdsoffOpt in to data-driven threshold tuning (off by default; static config thresholds used otherwise)
--quality_flooroffOPT-IN: apply the adaptive quality floor before embedding selection (drops the worst tail of the accepted pool; off by default)
--plot / --debugoffGenerate diagnostic plots / verbose per-step stats
--only_pre_filteroffStop after pre-filtering (dump accepted/rejected samples + rejected.json)

Examples:

python run.py --data_root /path/to/bottle --embedding dinov2 --embedding_model dinov2_vitb14_reg
python run.py --data_root /path/to/bottle --selector dpp --num_views 10
python run.py --data_root /path/to/bottle --use_shape_descriptors --shape_descriptor zernike
python run.py --data_root /path/to/bottle --selector quality_diversity --selector_diversity_mode prototype
python run.py --data_root /path/to/bottle --selector quality_diversity --selector_use_descriptors
python run.py --data_root /path/to/bottle --plot --debug

Outputs

Results are written to --output_dir: report.json, quality.csv, rejected.json, rejected_metrics.csv, embeddings.npy (+ selected_indices.npy, selection_pool_ids.npy), selected_samples/, rejected_samples/, accepted_samples/ (--debug), visualization.png, and optional plots/, bad_examples/, embedded_samples/. See docs/pipeline.md for the full structure.

# Diagnostic plots from a previous run (or --plot during the run)
python -m plotting_process.wrapper --input_dir ./outputs

# Interactive 3D explorer of the kMeans + xNN selection pool
python -m embedding_explorer_tool.webapp --output_dir ./outputs

# Tune the pre-filter thresholds on a dataset, preview the accept/reject
# outcome, then run the embedding (feeds the explorer's snapshot).
# Runs the default run.py filter set; --filter_order swaps in other filters.
python -m embedding_explorer_tool.prefilter_app

# Or start both together (tuner on 8520, explorer on 8510)
python run_webapps.py -i /path/to/dataset -o ./outputs_embedding_explorer

Testing

Run all correctness tests (synthetic data) and smoke tests (real dataset):

python test_correctness.py        # or: python tests/run_correctness.py
python test_smoke.py --data_root /path/to/bottle   # or: tests/run_smoke.py

See docs/testing.md for details and counts.

Project Structure

object_view_selection/
├── run.py                  # Pipeline entry point (argparse)
├── config.py               # All configuration dataclasses
├── data_io/                # Observation/dataset loaders + metrics
├── preprocessing/          # Pre-filters: ScoreFilter/OutlierFilter rejection + legacy
├── quality/                # 4-component weighted quality scorer
├── embeddings/             # Learned embedding models + crop helpers
├── descriptors/            # CPU shape descriptors (hu/zernike/fourier/shape_context)
├── selection/              # 6 subset-selection algorithms
├── utils/                  # Threshold tuner, visualization helpers
├── plotting_process/       # Diagnostic plotting (run.py + standalone wrapper)
├── embedding_explorer_tool/# kMeans/xNN explorer (web) + pre-filter threshold tuner (web)
├── tests/                  # Correctness + smoke test suites
└── docs/                   # Reference documentation (see below)

Documentation

Contributors

Nils-Treuheit

54 commits

vincirist

4 commits

Nils-Treuheit/object_view_selection

This is a tool that decides which image+mask combinations to use from a set of many image+mask samples.

2

stars

58

commits

Python

primary language

Aug 11, 2026

updated

README

Object View Selection

Select the best N image/mask pairs that maximize object identifiability — high-quality, diverse, non-redundant viewpoints of a single object.

Dataset → Auto-Threshold → Pre-Filter → Quality Score → Embeddings → Subset Selection → Outputs
StageWhat it does
Auto-ThresholdTunes legacy filters via dataset statistics; the default blur/artifact pre-filters use static relaxed floors + population-relative outlier rejection
Pre-filter5 conservative filters: empty mask, frame-touching mask, boundary-band Laplacian blur, boundary-band Tenengrad blur, mask artifacts
Quality ScoreWeighted combination of 4 components: boundary-blur, mask-area, mask-artifacts, centerness
EmbeddingsDINOv3 / DINOv2 / SigLIP2 / SigLIP / MoonViT / CLIP / EVA-CLIP features (or classical shape descriptors on CPU)
SelectionGreedy quality+diversity (default), FPS, Facility Location, DPP, Next-Best-View, or top-kMeans-xNN

Installation

git clone <repo> && cd object_view_selection

python3 -m venv .venv && source .venv/bin/activate

uv sync                  # or: pip install -r requirements.txt

Optional extras for learned embeddings: torch torchvision timm, transformers (DINOv3/SigLIP), open-clip-torch (EVA-CLIP), git+https://github.com/openai/CLIP.git.

Usage

Minimum command:

python run.py --data_root /path/to/bottle --num_views 10 --output_dir ./outputs

--data_root must contain images/ and masks/ (binary masks, same filenames), plus optional object_hands/ and depth/:

bottle/
├── images/          # 00000.png, 00001.png, ...
├── masks/           # 00000.png, 00001.png, ...  (binary, same filename)
├── object_hands/    # optional, binary hand occlusion
└── depth/           # optional, copied through to outputs

Key parameters

ArgumentDefaultChoices / notes
--num_views10Number of views to select
--embeddingautoauto, dinov3, dinov2, siglip2, siglip, moonvit, clip, eva_clip
--embedding_modelfacebook/dinov3-vitb16-pretrain-lvd1689mModel name/path; type inferred when --embedding=auto
--selectorquality_diversityfps, quality_diversity, facility_location, dpp, next_best_view, top_kmeans_xnn
--selector_alpha / --selector_beta0.60 / 0.40Quality / diversity weights (GQD)
--selector_diversity_modeminmin, max, prototype — how GQD measures distance to the selected set
--selector_use_descriptorsoffBlend a shape-descriptor divergence (default silhouette) into the GQD diversity term
--selector_descriptor / --selector_descriptor_weightsilhouette / 0.5Descriptor family and its share of the GQD diversity term
--kmeans_initbest_qualityfarthest or best_quality (top_kmeans_xnn)
--kmeans_k--num_viewsk-means clusters; smaller explicit k seeds kMeans-xNN and fills the rest by cluster avg. quality
--kmeans_xnn_k103, 5, or 10 (top_kmeans_xnn)
--use_shape_descriptorsoffCPU shape descriptors (hu, zernike, fourier, shape_context)
--filter_orderconfig defaultComma-separated pre-filter order; runs ONLY the named pre-filters (including soft vincents_area/vincents_motion_blur); legacy border,area,occlusion,confidence,completeness for custom orders only
--auto-thresholdsoffOpt in to data-driven threshold tuning (off by default; static config thresholds used otherwise)
--quality_flooroffOPT-IN: apply the adaptive quality floor before embedding selection (drops the worst tail of the accepted pool; off by default)
--plot / --debugoffGenerate diagnostic plots / verbose per-step stats
--only_pre_filteroffStop after pre-filtering (dump accepted/rejected samples + rejected.json)

Examples:

python run.py --data_root /path/to/bottle --embedding dinov2 --embedding_model dinov2_vitb14_reg
python run.py --data_root /path/to/bottle --selector dpp --num_views 10
python run.py --data_root /path/to/bottle --use_shape_descriptors --shape_descriptor zernike
python run.py --data_root /path/to/bottle --selector quality_diversity --selector_diversity_mode prototype
python run.py --data_root /path/to/bottle --selector quality_diversity --selector_use_descriptors
python run.py --data_root /path/to/bottle --plot --debug

Outputs

Results are written to --output_dir: report.json, quality.csv, rejected.json, rejected_metrics.csv, embeddings.npy (+ selected_indices.npy, selection_pool_ids.npy), selected_samples/, rejected_samples/, accepted_samples/ (--debug), visualization.png, and optional plots/, bad_examples/, embedded_samples/. See docs/pipeline.md for the full structure.

# Diagnostic plots from a previous run (or --plot during the run)
python -m plotting_process.wrapper --input_dir ./outputs

# Interactive 3D explorer of the kMeans + xNN selection pool
python -m embedding_explorer_tool.webapp --output_dir ./outputs

# Tune the pre-filter thresholds on a dataset, preview the accept/reject
# outcome, then run the embedding (feeds the explorer's snapshot).
# Runs the default run.py filter set; --filter_order swaps in other filters.
python -m embedding_explorer_tool.prefilter_app

# Or start both together (tuner on 8520, explorer on 8510)
python run_webapps.py -i /path/to/dataset -o ./outputs_embedding_explorer

Testing

Run all correctness tests (synthetic data) and smoke tests (real dataset):

python test_correctness.py        # or: python tests/run_correctness.py
python test_smoke.py --data_root /path/to/bottle   # or: tests/run_smoke.py

See docs/testing.md for details and counts.

Project Structure

object_view_selection/
├── run.py                  # Pipeline entry point (argparse)
├── config.py               # All configuration dataclasses
├── data_io/                # Observation/dataset loaders + metrics
├── preprocessing/          # Pre-filters: ScoreFilter/OutlierFilter rejection + legacy
├── quality/                # 4-component weighted quality scorer
├── embeddings/             # Learned embedding models + crop helpers
├── descriptors/            # CPU shape descriptors (hu/zernike/fourier/shape_context)
├── selection/              # 6 subset-selection algorithms
├── utils/                  # Threshold tuner, visualization helpers
├── plotting_process/       # Diagnostic plotting (run.py + standalone wrapper)
├── embedding_explorer_tool/# kMeans/xNN explorer (web) + pre-filter threshold tuner (web)
├── tests/                  # Correctness + smoke test suites
└── docs/                   # Reference documentation (see below)

Documentation

Contributors

Nils-Treuheit

54 commits

vincirist

4 commits

Languages

Python

96.8%

HTML

2.6%