Last active
March 24, 2026 18:16
-
-
Save mtayseer/a7743876ee13d9e48a004ddee38aa2fe to your computer and use it in GitHub Desktop.
Measure object dimensions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> | |
| <title>Pixel Measure Pro</title> | |
| <script async src="https://docs.opencv.org/4.10.0/opencv.js" type="text/javascript"></script> | |
| <style> | |
| :root { --green: #00ff41; --dark: #050505; } | |
| body { margin: 0; background: var(--dark); color: var(--green); font-family: 'Roboto Mono', monospace; height: 100vh; display: flex; flex-direction: column; } | |
| /* Fixed Header for Status */ | |
| #ui-layer { padding: 15px; background: #111; border-bottom: 2px solid #222; text-align: center; } | |
| #status { font-size: 13px; margin-bottom: 10px; color: #aaa; } | |
| /* High-Visibility Button */ | |
| #mainBtn { | |
| background: var(--green); color: black; border: none; | |
| padding: 15px 40px; font-size: 16px; font-weight: bold; | |
| border-radius: 5px; width: 100%; max-width: 300px; | |
| } | |
| #mainBtn:disabled { background: #333; color: #666; } | |
| /* Camera Viewport */ | |
| #canvasContainer { flex: 1; position: relative; overflow: hidden; display: flex; justify-content: center; align-items: center; } | |
| canvas { width: 100%; height: 100%; object-fit: contain; } | |
| video { position: absolute; visibility: hidden; width: 1px; height: 1px; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="ui-layer"> | |
| <div id="status">STEP 1: WAITING FOR ENGINE...</div> | |
| <button id="mainBtn" onclick="initSystem()" disabled>LOADING...</button> | |
| </div> | |
| <div id="canvasContainer"> | |
| <canvas id="canvasOutput"></canvas> | |
| </div> | |
| <video id="videoInput" playsinline muted></video> | |
| <script type="text/javascript"> | |
| const video = document.getElementById('videoInput'); | |
| const canvas = document.getElementById('canvasOutput'); | |
| const status = document.getElementById('status'); | |
| const mainBtn = document.getElementById('mainBtn'); | |
| let src, gray, cap, dict, params, ids, corners; | |
| let isRunning = false; | |
| // 1. Monitor OpenCV Loading | |
| function monitorOpenCV() { | |
| if (typeof cv !== 'undefined' && cv.Mat) { | |
| status.innerText = "ENGINE READY: TAP BUTTON"; | |
| status.style.color = "var(--green)"; | |
| mainBtn.innerText = "START CAMERA"; | |
| mainBtn.disabled = false; | |
| } else { | |
| // Keep checking | |
| setTimeout(monitorOpenCV, 500); | |
| } | |
| } | |
| // 2. Start Hardware | |
| async function initSystem() { | |
| status.innerText = "REQUESTING PIXEL CAMERA..."; | |
| mainBtn.style.display = "none"; // Hide button after click to clear view | |
| try { | |
| const stream = await navigator.mediaDevices.getUserMedia({ | |
| video: { facingMode: "environment", width: { ideal: 1280 }, height: { ideal: 720 } } | |
| }); | |
| video.srcObject = stream; | |
| await video.play(); | |
| if (video.videoWidth > 0) setupCV(); | |
| else video.onloadedmetadata = setupCV; | |
| } catch (err) { | |
| status.innerText = "ERROR: " + err.message; | |
| mainBtn.style.display = "block"; | |
| } | |
| } | |
| function setupCV() { | |
| canvas.width = video.videoWidth; | |
| canvas.height = video.videoHeight; | |
| src = new cv.Mat(video.videoHeight, video.videoWidth, cv.CV_8UC4); | |
| gray = new cv.Mat(); | |
| ids = new cv.Mat(); | |
| corners = new cv.MatVector(); | |
| dict = cv.getPredefinedDictionary(cv.DICT_4X4_50); | |
| params = new cv.aruco_DetectorParameters(); | |
| cap = new cv.VideoCapture(video); | |
| status.innerText = "SCANNING FOR ARUCO GRID..."; | |
| isRunning = true; | |
| requestAnimationFrame(processFrame); | |
| } | |
| function processFrame() { | |
| if (!isRunning) return; | |
| try { | |
| cap.read(src); | |
| cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY); | |
| cv.detectMarkers(gray, dict, corners, ids, params); | |
| if (ids.rows > 0) { | |
| cv.drawDetectedMarkers(src, corners, ids); | |
| status.innerText = `MARKERS FOUND: ${ids.rows}/4`; | |
| } | |
| cv.imshow('canvasOutput', src); | |
| } catch (e) { console.error(e); } | |
| requestAnimationFrame(processFrame); | |
| } | |
| // Initialize the monitor on load | |
| window.onload = monitorOpenCV; | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment