Spaces:
Running
Running
| /** | |
| * 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 { | |
| console.error("Failed to parse JSON from markdown:", jsonString); | |
| 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)) { | |
| console.warn("drawBoundingBoxesOnCanvas: 'boxes' is not an array or is null/undefined.", boxes); | |
| return; | |
| } | |
| if (boxes.length === 0) { | |
| // console.log("drawBoundingBoxesOnCanvas: 'boxes' array is empty, nothing to draw."); | |
| 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) { | |
| // Adjust text position to ensure visibility, especially if near top edge | |
| ctx.fillText(obj.label, sx1 + 4, sy1 - 4 < 16 ? sy1 + 16 : sy1 - 4); | |
| } | |
| }); | |
| ctx.restore(); | |
| } |