chore: fix bounding box issue

This commit is contained in:
2026-03-19 18:38:10 +05:30
parent 02c5425fce
commit a2dca13431

View File

@@ -1,5 +1,8 @@
import { DETECTION_TYPES } from '@/constants/detectionModeConfig'; import { DETECTION_TYPES } from '@/constants/detectionModeConfig';
/**
* Color mapping for detection types
*/
export const DETECTION_COLORS: Record<string, string> = Object.keys(DETECTION_TYPES).reduce( export const DETECTION_COLORS: Record<string, string> = Object.keys(DETECTION_TYPES).reduce(
(acc, key) => { (acc, key) => {
acc[key] = DETECTION_TYPES[key].color; acc[key] = DETECTION_TYPES[key].color;
@@ -8,6 +11,41 @@ export const DETECTION_COLORS: Record<string, string> = Object.keys(DETECTION_TY
{} as Record<string, string>, {} 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 = ( export const drawBoundingBoxes = (
ctx: CanvasRenderingContext2D, ctx: CanvasRenderingContext2D,
detections: any[], detections: any[],
@@ -32,27 +70,33 @@ export const drawBoundingBoxes = (
const y2 = bbox.y2 * scaleY; const y2 = bbox.y2 * scaleY;
const type = (detection.type || detection._detType || '').toLowerCase(); const type = (detection.type || detection._detType || '').toLowerCase();
const boxColor = DETECTION_COLORS[type] || '#3b82f6'; const rawColor = DETECTION_COLORS[type] || '#3b82f6';
const boxColor = resolveCanvasColor(rawColor);
// 1. Draw Border (Always Solid)
ctx.globalAlpha = 1.0;
ctx.strokeStyle = boxColor; ctx.strokeStyle = boxColor;
ctx.lineWidth = 3; ctx.lineWidth = 3;
ctx.strokeRect(x1, y1, x2 - x1, y2 - y1); ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
// Transparent fill // 2. Draw Fill (Transparent/Light - using globalAlpha for maximum compatibility)
ctx.fillStyle = boxColor + '20'; ctx.globalAlpha = 0.1; // 10% Opacity correctly shows the road
ctx.fillStyle = boxColor;
ctx.fillRect(x1, y1, x2 - x1, y2 - y1); ctx.fillRect(x1, y1, x2 - x1, y2 - y1);
// 3. Draw Label
const id = detection.pothole_id ?? detection.signboard_id ?? detection.detection_id; const id = detection.pothole_id ?? detection.signboard_id ?? detection.detection_id;
const label = `${type.replace(/_/g, ' ')} #${id} ${(detection.confidence * 100).toFixed(0)}%`; const label = `${type.replace(/_/g, ' ')} #${id} ${(detection.confidence * 100).toFixed(0)}%`;
ctx.font = 'bold 12px sans-serif'; ctx.font = 'bold 12px sans-serif';
const metrics = ctx.measureText(label); const metrics = ctx.measureText(label);
// Label background // Label Background (Solid for readability)
ctx.globalAlpha = 1.0;
ctx.fillStyle = boxColor; ctx.fillStyle = boxColor;
ctx.fillRect(x1, y1 - 20, metrics.width + 10, 20); ctx.fillRect(x1, y1 - 20, metrics.width + 10, 20);
// Label text // Label Text (Solid White)
ctx.fillStyle = '#fff'; ctx.fillStyle = '#fff';
ctx.fillText(label, x1 + 5, y1 - 6); ctx.fillText(label, x1 + 5, y1 - 6);
}); });