|
|
<!DOCTYPE html>
|
|
|
<html lang="en">
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<title>🤖 AI Object Scanner</title>
|
|
|
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script>
|
|
|
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd"></script>
|
|
|
|
|
|
<style>
|
|
|
|
|
|
body {
|
|
|
background-color: #0d1117;
|
|
|
color: #00f3ff;
|
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
min-height: 100vh;
|
|
|
margin: 0;
|
|
|
padding: 20px;
|
|
|
}
|
|
|
|
|
|
h1 {
|
|
|
text-shadow: 0 0 15px #00f3ff;
|
|
|
letter-spacing: 2px;
|
|
|
margin-bottom: 5px;
|
|
|
}
|
|
|
|
|
|
p {
|
|
|
color: #ccc;
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
|
|
|
.cam-container {
|
|
|
position: relative;
|
|
|
border: 3px solid #333;
|
|
|
border-radius: 10px;
|
|
|
overflow: hidden;
|
|
|
box-shadow: 0 0 30px rgba(0, 243, 255, 0.2);
|
|
|
background: #000;
|
|
|
min-width: 640px;
|
|
|
min-height: 480px;
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
video {
|
|
|
display: block;
|
|
|
width: 640px;
|
|
|
height: 480px;
|
|
|
}
|
|
|
|
|
|
|
|
|
#box-overlay {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
pointer-events: none;
|
|
|
}
|
|
|
|
|
|
|
|
|
.detection-box {
|
|
|
position: absolute;
|
|
|
border: 2px solid #00f3ff;
|
|
|
background-color: rgba(0, 243, 255, 0.1);
|
|
|
z-index: 10;
|
|
|
}
|
|
|
|
|
|
.detection-label {
|
|
|
position: absolute;
|
|
|
top: -25px;
|
|
|
left: 0;
|
|
|
background-color: #00f3ff;
|
|
|
color: #000;
|
|
|
padding: 2px 8px;
|
|
|
font-size: 14px;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
button {
|
|
|
background-color: #00f3ff;
|
|
|
color: #000;
|
|
|
border: none;
|
|
|
padding: 15px 40px;
|
|
|
font-size: 1.2rem;
|
|
|
font-weight: bold;
|
|
|
cursor: pointer;
|
|
|
border-radius: 50px;
|
|
|
margin-top: 20px;
|
|
|
transition: transform 0.2s;
|
|
|
}
|
|
|
|
|
|
button:hover {
|
|
|
transform: scale(1.05);
|
|
|
box-shadow: 0 0 20px #00f3ff;
|
|
|
}
|
|
|
|
|
|
button:disabled {
|
|
|
background-color: #555;
|
|
|
color: #888;
|
|
|
cursor: wait;
|
|
|
transform: none;
|
|
|
box-shadow: none;
|
|
|
}
|
|
|
|
|
|
.status {
|
|
|
font-family: monospace;
|
|
|
font-size: 1.2rem;
|
|
|
margin-top: 10px;
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
|
|
|
<h1>🤖 AI Vision Lab</h1>
|
|
|
<p>Hold objects up to the camera (cellphone, cup, book, person) to scan them.</p>
|
|
|
|
|
|
<div class="cam-container">
|
|
|
|
|
|
<video id="webcam" autoplay muted playsinline></video>
|
|
|
|
|
|
<div id="box-overlay"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="status" id="statusText">⏳ Initializing Systems...</div>
|
|
|
|
|
|
<button id="startBtn" onclick="enableCam()" disabled>Please Wait...</button>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
|
|
|
const video = document.getElementById('webcam');
|
|
|
const overlay = document.getElementById('box-overlay');
|
|
|
const startBtn = document.getElementById('startBtn');
|
|
|
const statusText = document.getElementById('statusText');
|
|
|
|
|
|
let model = undefined;
|
|
|
|
|
|
|
|
|
|
|
|
cocoSsd.load().then(function (loadedModel) {
|
|
|
model = loadedModel;
|
|
|
statusText.innerText = "✅ System Ready";
|
|
|
startBtn.disabled = false;
|
|
|
startBtn.innerText = "🔴 Activate Scanner";
|
|
|
});
|
|
|
|
|
|
|
|
|
function enableCam() {
|
|
|
if (!model) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
|
|
|
startBtn.style.display = 'none';
|
|
|
statusText.innerText = "👀 Scanning...";
|
|
|
|
|
|
|
|
|
const constraints = {
|
|
|
video: { width: 640, height: 480 }
|
|
|
};
|
|
|
|
|
|
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
|
|
|
video.srcObject = stream;
|
|
|
|
|
|
video.addEventListener('loadeddata', predictWebcam);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
|
|
|
function predictWebcam() {
|
|
|
|
|
|
model.detect(video).then(function (predictions) {
|
|
|
|
|
|
|
|
|
overlay.innerHTML = '';
|
|
|
|
|
|
|
|
|
for (let n = 0; n < predictions.length; n++) {
|
|
|
|
|
|
|
|
|
if (predictions[n].score > 0.66) {
|
|
|
|
|
|
|
|
|
const p = document.createElement('div');
|
|
|
p.classList.add('detection-box');
|
|
|
|
|
|
|
|
|
|
|
|
const x = predictions[n].bbox[0];
|
|
|
const y = predictions[n].bbox[1];
|
|
|
const width = predictions[n].bbox[2];
|
|
|
const height = predictions[n].bbox[3];
|
|
|
|
|
|
|
|
|
p.style.left = x + 'px';
|
|
|
p.style.top = y + 'px';
|
|
|
p.style.width = width + 'px';
|
|
|
p.style.height = height + 'px';
|
|
|
|
|
|
|
|
|
const label = document.createElement('span');
|
|
|
label.classList.add('detection-label');
|
|
|
label.innerText = predictions[n].class.toUpperCase() + ' ' + Math.round(parseFloat(predictions[n].score) * 100) + '%';
|
|
|
|
|
|
|
|
|
p.appendChild(label);
|
|
|
overlay.appendChild(p);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
window.requestAnimationFrame(predictWebcam);
|
|
|
});
|
|
|
}
|
|
|
</script>
|
|
|
</body>
|
|
|
</html>
|
|
|
|