Add simple matching method as baseline for comparison tests

- Add find_all_matches() method to DetectLogosDETR that returns all
  logos above similarity threshold without any rejection logic
- Add --matching-method simple option to test script
- Update run_comparison_tests.sh to include simple matching as Test 1
- Update documentation to describe simple matching method
This commit is contained in:
Rick McEwen
2025-12-31 17:36:18 -05:00
parent 197e007591
commit 41bc0c701f
5 changed files with 174 additions and 40 deletions

View File

@ -236,9 +236,10 @@ def main():
parser.add_argument(
"--matching-method",
type=str,
choices=["margin", "multi-ref"],
choices=["simple", "margin", "multi-ref"],
default="margin",
help="Matching method: 'margin' requires confidence margin over 2nd best, "
help="Matching method: 'simple' returns all matches above threshold, "
"'margin' requires confidence margin over 2nd best, "
"'multi-ref' aggregates scores across reference images (default: margin)",
)
parser.add_argument(
@ -431,10 +432,30 @@ def main():
# Match detections against references using selected method
matched_logos: Set[str] = set()
for detection in detections:
match = None
similarity = None
if args.matching_method == "simple":
# Simple matching: return ALL logos above threshold
all_matches = detector.find_all_matches(
detection["embedding"],
reference_embeddings,
similarity_threshold=args.threshold,
)
for label, similarity in all_matches:
matched_logos.add(label)
if args.matching_method == "margin":
# Check if this is a correct match
if label in expected_logos:
true_positives += 1
else:
false_positives += 1
results.append({
"test_image": test_filename,
"matched_logo": label,
"similarity": similarity,
"correct": label in expected_logos,
})
elif args.matching_method == "margin":
# Margin-based matching: requires margin over second-best
match_result = detector.find_best_match_with_margin(
detection["embedding"],
@ -444,7 +465,20 @@ def main():
)
if match_result:
label, similarity = match_result
match = label
matched_logos.add(label)
if label in expected_logos:
true_positives += 1
else:
false_positives += 1
results.append({
"test_image": test_filename,
"matched_logo": label,
"similarity": similarity,
"correct": label in expected_logos,
})
else: # multi-ref
# Multi-ref matching: aggregates scores across reference images
match_result = detector.find_best_match_multi_ref(
@ -457,23 +491,19 @@ def main():
)
if match_result:
label, similarity, num_matching = match_result
match = label
matched_logos.add(label)
if match:
matched_logos.add(match)
if label in expected_logos:
true_positives += 1
else:
false_positives += 1
# Check if this is a correct match
if match in expected_logos:
true_positives += 1
else:
false_positives += 1
results.append({
"test_image": test_filename,
"matched_logo": match,
"similarity": similarity,
"correct": match in expected_logos,
})
results.append({
"test_image": test_filename,
"matched_logo": label,
"similarity": similarity,
"correct": label in expected_logos,
})
# Count missed detections (false negatives)
missed = expected_logos - matched_logos
@ -512,7 +542,8 @@ def main():
print(f" CLIP similarity threshold: {args.threshold}")
print(f" DETR confidence threshold: {args.detr_threshold}")
print(f" Matching method: {args.matching_method}")
print(f" Matching margin: {args.margin}")
if args.matching_method in ("margin", "multi-ref"):
print(f" Matching margin: {args.margin}")
if args.matching_method == "multi-ref":
print(f" Min matching refs: {args.min_matching_refs}")
print(f" Similarity aggregation: {'max' if args.use_max_similarity else 'mean'}")