CountEx Fine-Grained Counting via Exemplars and Exclusion

Yifeng Huang1  ·  Gia Khanh Nguyen2  ·  Minh Hoai2

1Department of Computer Science, Stony Brook University
2Australian Institute for Machine Learning, Adelaide University

European Conference on Computer Vision (ECCV) 2026

Stony Brook University Adelaide University

Scenes from CoCount. Every one contains two confusable classes, counted independently.

CoCount: every scene contains its own distractor

Class-agnostic counters do well on benchmarks where the only salient repeated object is the target. Real requests are narrower: count the black beans, not every bean; the black coffee candies, not every sweet in the pile. CoCount is built to make that distinction unavoidable: every image contains two confusable classes, each annotated with its own independent set of dots.

10,086annotated frames
20,172counting queries
97category pairs
5supercategories
2-472objects per class
Ten CoCount examples: one per supercategory for each of the INTER and INTRA pairing modes, with positive dots in green and negative dots in red.
One example per supercategory (columns) for each pairing mode (rows). Green = positive-class dots, red = negative-class dots; per-class counts at right. INTER pairs two different object classes (shallot / garlic, screw / nail). INTRA pairs two variants of the same class, differing only in colour, size or marking: Chinese playing black vs brown coffee candy, white vs black chess pieces, long vs short screws. INTRA is the harder case, and it is where class-agnostic counting has nothing to say.

Because both classes are annotated, one frame yields two counting queries: count A while excluding B, then count B while excluding A. The released splits store one record per query, which is why CoCount-train has 14,834 rows over 7,417 distinct frames. Across all three splits: 7,417 train, 1,335 val and 1,334 test frames, for 10,086 in total.

Why the two-class design matters

Because both classes in a scene are annotated, the same image yields two counting problems with the same pixels and different answers. A model that ignores the exemplars and counts "everything small and repeated" is penalised on both. The pairing also gives every positive a matched hard negative for free, with no mining and no synthetic composition.

Scale by supercategory

The CoCount-train split, counted over distinct frames. Points are the sum of both classes, so each frame contributes its positive and negative dots.
SupercategoryCodeFramesPairs INTERINTRAPointsCount range
FoodFOO1,82019920900434,2404-472
GameFUN1,27020578692123,2772-145
HomeHOU1,71020884826244,1644-283
DeskOFF1,72020960760253,1805-312
MiscOTR89718446451104,7754-269
Total7,417973,7883,6291,159,6362-472

Counts are dense, not toy

Cumulative share of classes at or below each object count. Median 53, mean 78.
Objects per class≤10≤25≤50≤100≤200≤400
Cumulative share3.4%18.7%47.8%76.2%93.0%99.5%

Loading it

from datasets import load_dataset

ds = load_dataset("BBVisual/CoCount-train", split="train")
ex = ds[0]
print(ex["pos_caption"], ex["pos_count"], len(ex["pos_points"]))
print(ex["neg_caption"], ex["neg_count"], len(ex["neg_points"]))

Each record carries the image, both class names, both counts, both dot sets in absolute pixel coordinates, and exemplar boxes for each class.

CountEx

CountEx lets a user express both inclusion and exclusion intent (what to count and what to ignore) through natural-language descriptions and optional visual exemplars. At its core is a Discriminative Query Refinement module, which reasons jointly over the two cues: it first identifies visual features the target and the distractor share, then isolates the patterns specific to the exclusion, then applies selective suppression to refine the counting query.

Existing prompt-based counters let you say what to count but give you no way to say what to leave out, so cluttered scenes with confusable categories produce ambiguity and overcounting. Full abstract in the paper.

CountEx architecture. Positive and negative text prompts with optional visual exemplars are encoded into positive and negative query sets. Discriminative Query Refinement then runs Shared Feature Identification to learn common prototypes, Exclusive Feature Extraction to project out and select the most exclusive negative residuals, and Selective Query Refinement to fuse them into the positive queries by gated cross-attention, before the decoder predicts points.
Overview of CountEx. The image and both prompts are encoded into a positive and a negative query set. Shared Feature Identification pools learnable prototypes over both sets to capture what the target and distractor have in common. Exclusive Feature Extraction projects that shared component out of the negative queries and keeps the residuals furthest from it, giving what is distinctive about the distractor alone. Selective Query Refinement then subtracts those residuals from the positive queries through gated cross-attention, repeated N times, so the decoder counts the target without the distractor. The density branch is used only during training.

CountEx on CoCount

Two settings. KC (known-category) trains on all five supercategories and tests on seen categories. NC (novel-category) holds one supercategory out entirely, measuring zero-shot transfer to unseen objects.

Table 2. CoCount test set. All methods are trained on the same data under either setting. Lower is better; best in bold.
Method NC-settingKC-setting
MAERMSEMAERMSE
LLMDet33.2247.6616.8229.23
CAD-GD34.0850.3916.0027.52
GroundingREC29.2942.4317.5427.41
CountGD33.7848.2915.5528.32
CountEx26.6138.8612.7223.99

Generalization to other benchmarks

The same model transfers to counting benchmarks it was not trained on, including PairTally.

Table 4. PairTally. Best in bold. NAE is the normalised absolute error.
ModelMAENAE
InterIntraInterIntra
Pre-trained specialist counting models
DAVE46.2746.750.7790.797
GeCo45.0554.800.7770.935
LoCA71.8957.451.1770.950
FamNet66.9774.751.3631.440
CountGD39.7856.540.6730.906
CountGD (text)50.2353.930.7120.841
LLMDet78.72142.080.6611.060
Pre-trained large vision-language models
Ovis256.8774.240.7110.736
Qwen2.5-VL46.3567.860.5980.712
LLaMA-3.249.1458.730.7300.740
InternVL355.8971.470.6670.721
Models trained on CoCount
LLMDet18.7821.060.2250.368
CAD-GD19.4716.980.2430.259
GroundingREC19.7117.910.2600.349
CountGD19.6715.670.2630.318
CountEx15.6112.570.1970.229
Table 3. LOOKALIKES. * denotes training on CoCount before zero-shot evaluation. CountEx is the best zero-shot method. D’Alessandro et al. reach a lower MAE but require per-category synthetic data generation and test-time adaptation, at 5-7 minutes per category, so it is not a zero-shot comparison.
MethodMAERMSE
Per-category synthetic data generation and adaptation
D’Alessandro et al.10.0016.95
Zero-shot, no training or adaptation
OWLv237.2555.01
GroundingDINO33.8959.51
PseCo59.8272.79
DAVE56.1073.34
CountGD22.3433.90
LLMDet*22.8633.29
CAD-GD*28.1441.30
GroundingREC*27.2441.57
CountGD*23.5536.89
CountEx*18.5330.46

What each part contributes

Table 5. Combinations of multimodal prompts, on the CoCount test set. T = text prompt, E = visual exemplars.
PromptNC-settingKC-setting
TposEposTnegEneg MAERMSEMAERMSE
✓32.2248.3815.9628.76
✓✓31.5746.7315.7527.59
✓✓26.6739.0013.2226.23
✓✓✓✓26.6138.8612.7223.99

The exclusion prompt is what moves the needle: adding Tneg to a positive-only prompt cuts NC MAE from 32.22 to 26.67, a far larger gain than adding positive exemplars alone (31.57). The paper also reports that a mismatched negative (asking to exclude "red" in a scene of black and brown candies) still helps, reaching 28.43 - worse than a relevant negative, but better than none at all.

Table 6. Loss components. Both the density loss and the prototype losses contribute.
LdenLproto NC-settingKC-setting
MAERMSEMAERMSE
30.7542.8415.2028.33
✓29.2141.6113.0025.22
✓✓26.6138.8612.7223.99

Corrected test annotations

We found an annotation issue in the test-set evaluation labels and corrected it. The issue is confined to evaluation labels and does not touch the training annotations CountEx learns from, since training uses dot annotations. The released dataset now ships the corrected labels; the paper was submitted beforehand and reports the originals. Both are below; differences are small and the conclusions are unchanged.

Lower is better. The pre-correction labels remain downloadable as BBVisual/CoCount-test_reported_in_paper for exact reproduction of the paper.
SplitCorrected imgsMAE (paper)MAE (corrected) ΔRMSE (paper)RMSE (corrected)Δ
Food3037.0437.400.3650.5851.300.72
Home024.1624.160.0034.8734.870.00
Desk1831.1827.893.2951.9046.475.43
Misc7223.8222.970.8532.6831.880.80
Game3016.8416.840.0024.2624.260.00
KC (overall)15012.7211.201.5223.9920.323.67

For Game, 30 frames were updated but the corrected counts land very close to the originals, so MAE and RMSE are unchanged after rounding.

Prior work: PairTally

This work follows directly from PairTally (DICTA 2025), by the same authors, which asked whether current models can count what we mean, not what they see. PairTally established the problem as a benchmark: 681 controlled images, each pairing two confusable categories over the same five supercategories used here, with 50 inter-category and 47 intra-category pairs. Evaluating ten models across three counting paradigms, it found that none reliably honours a fine-grained intent.

PairTally is diagnostic and evaluation-only, and at 681 images too small to train on. CountEx takes the next two steps: CoCount scales the same paired design to 10,086 annotated frames over 97 category pairs, enough to train on, and CountEx supplies a method for the exclusion intent PairTally showed was missing. CountEx is also evaluated on PairTally, where it outperforms pre-trained specialist counters, general vision-language models, and detectors trained on CoCount (paper, Table 4).

Benchmark and code: PairTally_Benchmark

Code and checkpoints

git clone https://github.com/bbvisual/CountEx.git
cd CountEx
bash src/eval_env_setup.sh          # conda env + deps (bf16 → Ampere or newer)

export HF_TOKEN=your_token_here
cd src
bash scripts/eval/kc.sh             # known-category
bash scripts/eval/nc_food.sh        # novel-category, Food held out

Checkpoints download from the Hub automatically: BBVisual/CountEX-KC for the KC setting and BBVisual/CountEX-NC-{Food,Home,Desk,Misc,Game} for each novel-category fold. Full instructions, training recipes and the split-code mapping are in the repository README.

BibTeX

@inproceedings{countex2026,
  title     = {CountEx: Fine-Grained Counting via Exemplars and Exclusion},
  author    = {Huang, Yifeng and Nguyen, Gia Khanh and Hoai, Minh},
  booktitle = {European Conference on Computer Vision (ECCV)},
  year      = {2026}
}

If you use CoCount or build on the fine-grained counting setting, please also cite PairTally, which introduced it:

@inproceedings{nguyen2025pairtally,
  title     = {Can Current AI Models Count What We Mean, Not What They See?
               A Benchmark and Systematic Evaluation},
  author    = {Nguyen, Gia Khanh and Huang, Yifeng and Hoai, Minh},
  booktitle = {Digital Image Computing: Techniques and Applications (DICTA)},
  year      = {2025}
}