""" Benchmark Suite for Supermarket Product Classification Compares SURF, ORB, BRISK, and Hybrid methods following MDPI Electronics 2023, 12(17), 3640. """ import os import sys import time import cv2 import numpy as np from typing import Dict, List, Any current_dir = os.path.dirname(os.path.abspath(__file__)) if current_dir not in sys.path: sys.path.insert(0, current_dir) from feature_matcher import ProductFeatureMatcher def run_benchmark(stock_dir: str = "stock", num_runs: int = 3): print("=" * 70) print("RETAIL SHELF PRODUCT RECOGNITION - ALGORITHM BENCHMARK") print("Methods Evaluated: SURF | ORB | BRISK | HYBRID (Paper Method)") print("=" * 70) matcher = ProductFeatureMatcher(stock_dir=stock_dir) templates = matcher.db.templates if not templates: print("[Error] No templates found in stock directory.") return methods = ["surf", "orb", "brisk", "hybrid"] results = {m: {"latencies": [], "inliers": [], "keypoints_query": []} for m in methods} # Test images: We will evaluate using crops synthesized with slight transformations # (scale, rotation, noise) as well as the template images themselves print(f"\nEvaluating across {len(templates)} catalog SKUs (repeat count: {num_runs})...\n") for sku_id, tmpl in templates.items(): original_img = tmpl["image"] h, w = original_img.shape[:2] # Apply synthetic shelf condition (rotation by 10 deg, resize by 0.85) M = cv2.getRotationMatrix2D((w / 2, h / 2), 10, 0.85) query_img = cv2.warpAffine(original_img, M, (w, h)) for method in methods: times = [] for _ in range(num_runs): t0 = time.perf_counter() res = matcher.classify_crop(query_img, method=method) t1 = time.perf_counter() times.append((t1 - t0) * 1000.0) # ms avg_latency = np.mean(times) results[method]["latencies"].append(avg_latency) # Record inliers/score if res.get("status") == "success": top_sku = res["best_sku"] score = res["score"] results[method]["inliers"].append(score) # Summarize metrics summary_rows = [] for method in methods: latencies = results[method]["latencies"] scores = results[method]["inliers"] avg_lat = np.mean(latencies) if latencies else 0.0 p95_lat = np.percentile(latencies, 95) if latencies else 0.0 avg_score = np.mean(scores) if scores else 0.0 # Paper characteristics notes notes = { "surf": "Scale & rotation robust; Hessian gradient features", "orb": "Ultra fast binary descriptor; FAST + BRIEF", "brisk": "Scale-space AGAST; circular pattern descriptor", "hybrid": "Paper fusion (SURF+ORB+BRISK); optimal accuracy/speed" }[method] summary_rows.append([ method.upper(), f"{avg_lat:.2f} ms", f"{p95_lat:.2f} ms", f"{avg_score:.1f}", notes ]) headers = ["Method", "Avg Latency (ms)", "P95 Latency (ms)", "Avg Match Score", "Characteristics / Paper Findings"] print("\n" + "-" * 105) print(f"{headers[0]:<10} | {headers[1]:<18} | {headers[2]:<18} | {headers[3]:<16} | {headers[4]}") print("-" * 105) for row in summary_rows: print(f"{row[0]:<10} | {row[1]:<18} | {row[2]:<18} | {row[3]:<16} | {row[4]}") print("-" * 105) print("\n[Benchmark Complete] All methods operational.") if __name__ == "__main__": run_benchmark()