| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>π
Tomato Quality Detection (30 FPS)</title> |
| <style> |
| body { |
| text-align: center; |
| font-family: Arial, sans-serif; |
| background: #f5f5f5; |
| } |
| video, img { |
| width: 90%; |
| max-width: 480px; |
| border-radius: 10px; |
| margin: 10px; |
| box-shadow: 0 0 10px rgba(0,0,0,0.2); |
| } |
| h2 { color: #333; } |
| #status { color: #666; font-size: 14px; } |
| </style> |
| </head> |
| <body> |
| <h2>π
Tomato Quality Detection (Ripe / Unripe / Damaged)</h2> |
|
|
| |
| <video id="video" autoplay playsinline muted></video><br> |
|
|
| |
| <img id="output" alt="Detection Output"/><br> |
|
|
| <div id="status">Initializing camera...</div> |
|
|
| <script> |
| let useFrontCamera = false; |
| let sending = false; |
| |
| async function startCamera() { |
| const video = document.querySelector("#video"); |
| const status = document.querySelector("#status"); |
| |
| try { |
| const stream = await navigator.mediaDevices.getUserMedia({ |
| video: { |
| facingMode: useFrontCamera ? "user" : "environment", |
| frameRate: { ideal: 30, max: 30 } |
| }, |
| audio: false |
| }); |
| video.srcObject = stream; |
| status.textContent = "β
Camera active at 30 FPS"; |
| loopSendFrame(); |
| } catch (err) { |
| console.error("β οΈ Camera access error:", err); |
| status.textContent = "β Camera blocked! Please allow camera or use HTTPS."; |
| alert("Camera access blocked! Please allow it or use HTTPS (ngrok)."); |
| } |
| } |
| |
| async function loopSendFrame() { |
| const video = document.querySelector("#video"); |
| const canvas = document.createElement("canvas"); |
| const ctx = canvas.getContext("2d"); |
| |
| |
| setInterval(async () => { |
| if (sending) return; |
| sending = true; |
| |
| canvas.width = video.videoWidth; |
| canvas.height = video.videoHeight; |
| ctx.drawImage(video, 0, 0, canvas.width, canvas.height); |
| |
| const imageData = canvas.toDataURL("image/jpeg", 0.7); |
| try { |
| const response = await fetch("/detect_frame", { |
| method: "POST", |
| headers: {"Content-Type": "application/json"}, |
| body: JSON.stringify({ image: imageData }) |
| }); |
| |
| const result = await response.json(); |
| if (result.image) { |
| document.getElementById("output").src = result.image; |
| } |
| } catch (err) { |
| console.error("Frame send error:", err); |
| } |
| sending = false; |
| }, 33); |
| } |
| |
| startCamera(); |
| </script> |
| </body> |
| </html> |
|
|