import { useEffect, useRef } from "react"; import styled from "styled-components" import { RoboflowObjectDetection } from "../../services/roboflowModule/roboflowModuleService.types"; import { RoboflowObjectDetectionCanvasProps } from "../RoboflowObjectDetectionCanvas/RoboflowObjectDetectionCanvas.types"; const ObjectDetectionCanvas = styled.canvas` position: absolute; top: 0; left: 0; ` export const RoboflowObjectDetectionCanvas = ( { width, height, objectDetections, mirrored = false }: RoboflowObjectDetectionCanvasProps) => { const canvasRef = useRef(null) useEffect(() => { const canvas = canvasRef?.current if (!canvas) return // adjust the canvas size to match the video adjustCanvas(width, height) const canvasContext = canvas.getContext("2d") if (!canvasContext) return drawBoxes(objectDetections, canvasContext) }, [width, height, objectDetections]); const adjustCanvas = (width: number, height: number) => { const canvas = canvasRef?.current if (!canvas) return canvas.width = width * window.devicePixelRatio canvas.height = height * window.devicePixelRatio canvas.style.width = width + "px" canvas.style.height = height + "px" const canvasContext = canvas.getContext("2d") if (!canvasContext) return canvasContext.scale(window.devicePixelRatio, window.devicePixelRatio) } const drawBoxes = (detections: RoboflowObjectDetection[], canvasContext: CanvasRenderingContext2D) => { const canvas = canvasRef?.current if (!canvas) return canvasContext.clearRect(0, 0, canvas.width, canvas.height) detections.forEach((row: any) => { //video let temp = row.bbox temp.class = row.class temp.color = row.color temp.confidence = row.confidence row = temp if (row.confidence < 0) return //dimensions if(mirrored){ row.x = width - row.x } let x = row.x - row.width / 2 let y = row.y - row.height / 2 let w = row.width let h = row.height //box canvasContext.beginPath() canvasContext.lineWidth = 1 canvasContext.strokeStyle = row.color canvasContext.rect(x, y, w, h) canvasContext.stroke() //shade canvasContext.fillStyle = "black" canvasContext.globalAlpha = 0.2 canvasContext.fillRect(x, y, w, h) canvasContext.globalAlpha = 1.0 //label let fontColor = "black" let fontSize = 12 canvasContext.font = `${fontSize}px monospace` canvasContext.textAlign = "center" let classTxt = row.class let confTxt = (row.confidence * 100).toFixed().toString() + "%" let msgTxt = classTxt + " " + confTxt const textHeight = fontSize let textWidth = canvasContext.measureText(msgTxt).width if (textHeight <= h && textWidth <= w) { canvasContext.strokeStyle = row.color canvasContext.fillStyle = row.color canvasContext.fillRect( x - canvasContext.lineWidth / 2, y - textHeight - canvasContext.lineWidth, textWidth + 2, textHeight + 1 ); canvasContext.stroke() canvasContext.fillStyle = fontColor canvasContext.fillText(msgTxt, x + textWidth / 2 + 1, y - 1) } else { textWidth = canvasContext.measureText(confTxt).width canvasContext.strokeStyle = row.color canvasContext.fillStyle = row.color canvasContext.fillRect( x - canvasContext.lineWidth / 2, y - textHeight - canvasContext.lineWidth, textWidth + 2, textHeight + 1 ) canvasContext.stroke() canvasContext.fillStyle = fontColor canvasContext.fillText(confTxt, x + textWidth / 2 + 1, y - 1) } }) } return ( ) }