'use client'; import { useEffect, useRef } from 'react'; import type { DetectionResult } from '@/types/inference'; interface CameraOverlayProps { detections: DetectionResult[]; width: number; height: number; confidenceThreshold: number; } const COLORS = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#98D8C8', '#F7DC6F']; export function CameraOverlay({ detections, width, height, confidenceThreshold }: CameraOverlayProps) { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); if (!ctx) return; ctx.clearRect(0, 0, width, height); const filtered = detections.filter((d) => d.confidence >= confidenceThreshold); filtered.forEach((det, i) => { const color = COLORS[i % COLORS.length]; // Convert normalized coordinates (0-1) to pixel values const px = det.bbox.x * width; const py = det.bbox.y * height; const pw = det.bbox.width * width; const ph = det.bbox.height * height; // Draw bounding box ctx.strokeStyle = color; ctx.lineWidth = 2; ctx.strokeRect(px, py, pw, ph); // Draw label background const label = `${det.label} ${(det.confidence * 100).toFixed(0)}%`; ctx.font = '14px sans-serif'; const textWidth = ctx.measureText(label).width; ctx.fillStyle = color; ctx.fillRect(px, py - 20, textWidth + 8, 20); // Draw label text ctx.fillStyle = '#fff'; ctx.fillText(label, px + 4, py - 5); }); }, [detections, width, height, confidenceThreshold]); return ( ); }