chore: fix bounding box issue
This commit is contained in:
@@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user