// trashDetection.tsx /* eslint-disable no-console */ "use client"; import React, { useEffect, useRef, useState, useMemo } from "react"; import { InferenceEngine, CVImage } from "inferencejs"; function RealtimeModel() { const inferEngine = useMemo(() => new InferenceEngine(), []); const [modelWorkerId, setModelWorkerId] = useState(null); const modelWorkerIdRef = useRef(null); const [modelLoading, setModelLoading] = useState(false); const [predictions, setPredictions] = useState([]); const containerRef = useRef(null); const videoRef = useRef(null); const canvasRef = useRef(null); // References to manage media stream and timeouts const mediaStreamRef = useRef(null); const detectFrameTimeoutRef = useRef(null); useEffect(() => { console.log("Component mounted"); setModelLoading(true); inferEngine .startWorker("trash-detection-kkthk", 7, "rf_1nBQDUSClLUApDgPjG78qMbBH602") .then((id) => { setModelWorkerId(id); modelWorkerIdRef.current = id; startWebcam(); }) .catch((error) => { console.error("Error starting model worker:", error); }); // Cleanup function to stop the model worker and webcam when the component unmounts return () => { console.log("Component unmounting, stopping model worker and webcam"); if (modelWorkerIdRef.current) { inferEngine.stopWorker(modelWorkerIdRef.current); console.log(`Stopped model worker with ID: ${modelWorkerIdRef.current}`); } stopWebcam(); if (detectFrameTimeoutRef.current) { clearTimeout(detectFrameTimeoutRef.current); detectFrameTimeoutRef.current = null; console.log("Cleared detectFrameTimeoutRef"); } }; }, [inferEngine]); const startWebcam = () => { const constraints = { audio: false, video: { facingMode: "environment", }, }; navigator.mediaDevices .getUserMedia(constraints) .then((stream) => { mediaStreamRef.current = stream; // Store the stream reference if (videoRef.current && containerRef.current) { videoRef.current.srcObject = stream; videoRef.current.onloadedmetadata = () => { videoRef.current?.play(); }; videoRef.current.onplay = () => { if (canvasRef.current && videoRef.current && containerRef.current) { detectFrame(); } }; } }) .catch((error) => { console.error("Error accessing webcam:", error); }); }; const stopWebcam = () => { if (mediaStreamRef.current) { console.log("Stopping webcam..."); mediaStreamRef.current.getTracks().forEach((track) => { track.stop(); console.log(`Stopped track: ${track.kind}`); }); mediaStreamRef.current = null; } else { console.log("No media stream to stop."); } if (videoRef.current) { videoRef.current.pause(); videoRef.current.srcObject = null; console.log("Video paused and srcObject cleared."); } }; const detectFrame = () => { if (!modelWorkerIdRef.current) { detectFrameTimeoutRef.current = window.setTimeout(detectFrame, 1000 / 3); return; } if (videoRef.current && canvasRef.current) { const img = new CVImage(videoRef.current); inferEngine.infer(modelWorkerIdRef.current, img).then((newPredictions) => { const ctx = canvasRef.current!.getContext("2d")!; // Clear the canvas ctx.clearRect(0, 0, canvasRef.current!.width, canvasRef.current!.height); // Get the scaling factors const scaleX = canvasRef.current!.width / (videoRef.current!.videoWidth ?? 1); const scaleY = canvasRef.current!.height / (videoRef.current!.videoHeight ?? 1); newPredictions.forEach((prediction: any) => { const x = (prediction.bbox.x - prediction.bbox.width / 2) * scaleX; const y = (prediction.bbox.y - prediction.bbox.height / 2) * scaleY; const width = prediction.bbox.width * scaleX; const height = prediction.bbox.height * scaleY; // Draw bounding box ctx.strokeStyle = prediction.color; ctx.lineWidth = 1; ctx.strokeRect(x, y, width, height); }); setPredictions(newPredictions); detectFrameTimeoutRef.current = window.setTimeout(detectFrame, 1000 / 3); }).catch((error) => { console.error("Error during inference:", error); }); } }; return (
{predictions.length > 0 ? ( predictions.map((prediction, index) => (
{`${prediction.class} - ${Math.round(prediction.confidence * 100)}%`}
)) ) : (
No Item Detected
)}
); } export default RealtimeModel;