FastVLMBoxes / src /components /BoxAnnotator.ts
Quazim0t0's picture
Upload 51 files
96b5215 verified
/**
* Extracts JSON array from a markdown code block (```json ... ``` or ``` ... ```)
*/
export function extractJsonFromMarkdown(markdown: string): any[] | null {
let jsonString = "";
const jsonBlock = markdown.match(/```json([\s\S]*?)```/i) || markdown.match(/```([\s\S]*?)```/i);
if (jsonBlock && jsonBlock[1]) {
jsonString = jsonBlock[1].trim();
} else {
// Fallback: try to parse the whole string
jsonString = markdown.trim();
}
try {
const parsed = JSON.parse(jsonString);
if (Array.isArray(parsed)) return parsed;
if (typeof parsed === "object" && parsed !== null) return [parsed]; // <-- Wrap object in array
return null;
} catch {
return null;
}
}
/**
* Draws bounding boxes and labels on a canvas context.
* @param ctx CanvasRenderingContext2D
* @param boxes Array of { bbox_2d: [x1, y1, x2, y2], label: string }
* @param options Optional: { color, lineWidth, font }
*/
export function drawBoundingBoxesOnCanvas(
ctx: CanvasRenderingContext2D,
boxes: { bbox_2d: number[]; label?: string }[],
options?: { color?: string; lineWidth?: number; font?: string, scaleX?: number, scaleY?: number }
) {
if (!Array.isArray(boxes)) return; // Prevent errors if boxes is undefined/null
const color = options?.color || "#00FF00";
const lineWidth = options?.lineWidth || 2;
const font = options?.font || "16px Arial";
const scaleX = options?.scaleX ?? 1;
const scaleY = options?.scaleY ?? 1;
ctx.save();
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
ctx.font = font;
ctx.fillStyle = color;
boxes.forEach((obj) => {
const [x1, y1, x2, y2] = obj.bbox_2d;
const sx1 = x1 * scaleX;
const sy1 = y1 * scaleY;
const sx2 = x2 * scaleX;
const sy2 = y2 * scaleY;
ctx.beginPath();
ctx.rect(sx1, sy1, sx2 - sx1, sy2 - sy1);
ctx.stroke();
if (obj.label) {
ctx.fillText(obj.label, sx1 + 4, sy1 - 4 < 10 ? sy1 + 16 : sy1 - 4);
}
});
ctx.restore();
}