feat(video): base of video refactoring

This commit is contained in:
2026-06-18 02:23:25 +05:30
parent d7c4027328
commit c6894bfea0
20 changed files with 432 additions and 1412 deletions

View File

@@ -1,106 +0,0 @@
import { DETECTION_TYPES } from '@/constants/detectionModeConfig';
/**
* Color mapping for detection types
*/
export const DETECTION_COLORS: Record<string, string> = Object.keys(
DETECTION_TYPES,
).reduce(
(acc, key) => {
acc[key] = DETECTION_TYPES[key].color;
return acc;
},
{} as Record<string, string>,
);
// Cache for resolved colors to avoid DOM access in every frame
const resolvedColorCache = new Map<string, string>();
/**
* Resolves a color string that might contain CSS variables or modern color formats
* into an RGB string that HTML5 Canvas understands.
*/
function resolveCanvasColor(colorStr: string): string {
if (typeof window === 'undefined') return colorStr;
// Return from cache if already resolved
if (resolvedColorCache.has(colorStr)) {
return resolvedColorCache.get(colorStr)!;
}
// Use a temporary element to let the browser resolve the color (handles var(), oklch(), etc.)
try {
const temp = document.createElement('div');
temp.style.color = colorStr;
temp.style.display = 'none';
document.body.appendChild(temp);
const resolved = getComputedStyle(temp).color;
document.body.removeChild(temp);
if (resolved && resolved !== 'transparent') {
resolvedColorCache.set(colorStr, resolved);
return resolved;
}
} catch (e) {
console.warn('Failed to resolve color:', colorStr, e);
}
return colorStr;
}
export const drawBoundingBoxes = (
ctx: CanvasRenderingContext2D,
detections: any[],
canvasWidth: number,
canvasHeight: number,
videoWidth: number,
videoHeight: number,
) => {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
if (!detections || detections.length === 0) return;
const scaleX = canvasWidth / videoWidth;
const scaleY = canvasHeight / videoHeight;
detections.forEach((detection) => {
const bbox = detection.bbox;
if (!bbox) return;
const x1 = bbox.x1 * scaleX;
const y1 = bbox.y1 * scaleY;
const x2 = bbox.x2 * scaleX;
const y2 = bbox.y2 * scaleY;
const type = (detection.type || detection._detType || '').toLowerCase();
const rawColor = DETECTION_COLORS[type] || '#3b82f6';
const boxColor = resolveCanvasColor(rawColor);
// 1. Draw Border (Always Solid)
ctx.globalAlpha = 1.0;
ctx.strokeStyle = boxColor;
ctx.lineWidth = 3;
ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
// 2. Draw Fill (Transparent/Light - using globalAlpha for maximum compatibility)
ctx.globalAlpha = 0.1; // 10% Opacity correctly shows the road
ctx.fillStyle = boxColor;
ctx.fillRect(x1, y1, x2 - x1, y2 - y1);
// 3. Draw Label
const id =
detection.pothole_id ?? detection.signboard_id ?? detection.detection_id;
const label = `${type.replace(/_/g, ' ')} #${id} ${(detection.confidence * 100).toFixed(0)}%`;
ctx.font = 'bold 12px sans-serif';
const metrics = ctx.measureText(label);
// Label Background (Solid for readability)
ctx.globalAlpha = 1.0;
ctx.fillStyle = boxColor;
ctx.fillRect(x1, y1 - 20, metrics.width + 10, 20);
// Label Text (Solid White)
ctx.fillStyle = '#fff';
ctx.fillText(label, x1 + 5, y1 - 6);
});
};