|
|
|
|
|
|
|
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 {
|
|
|
|
jsonString = markdown.trim();
|
|
}
|
|
try {
|
|
const parsed = JSON.parse(jsonString);
|
|
if (Array.isArray(parsed)) return parsed;
|
|
if (typeof parsed === "object" && parsed !== null) return [parsed];
|
|
return null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
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();
|
|
} |