Initial Code Commit
This commit is contained in:
175
Project/components/trashDetection.tsx
Executable file
175
Project/components/trashDetection.tsx
Executable file
@@ -0,0 +1,175 @@
|
||||
// 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<string | null>(null);
|
||||
const modelWorkerIdRef = useRef<string | null>(null);
|
||||
const [modelLoading, setModelLoading] = useState(false);
|
||||
const [predictions, setPredictions] = useState<any[]>([]);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
// References to manage media stream and timeouts
|
||||
const mediaStreamRef = useRef<MediaStream | null>(null);
|
||||
const detectFrameTimeoutRef = useRef<number | null>(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 (
|
||||
<div ref={containerRef} className="w-full h-screen relative overflow-hidden">
|
||||
<div className="absolute inset-0">
|
||||
<video
|
||||
ref={videoRef}
|
||||
muted
|
||||
playsInline
|
||||
className="absolute top-0 left-0 w-full h-full transform scale-x-[-1]"
|
||||
>
|
||||
<track kind="captions" />
|
||||
</video>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="absolute top-0 left-0 w-full h-full transform scale-x-[-1]"
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 w-11/12 max-w-2xl">
|
||||
<div className="bg-black bg-opacity-50 backdrop-filter backdrop-blur-md rounded-xl p-4 text-white text-center">
|
||||
{predictions.length > 0 ? (
|
||||
predictions.map((prediction, index) => (
|
||||
<div key={index} className="text-lg">
|
||||
{`${prediction.class} - ${Math.round(prediction.confidence * 100)}%`}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-lg">No Item Detected</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default RealtimeModel;
|
||||
Reference in New Issue
Block a user