commit 72d791566bda52ee454a03b4ac522475138d46bc
Author: ffff:207.243.92.34 <ffff:207.243.92.34@mitosite.powerhouse.wiki> Date: 2025-01-17 17:15:05 +0000 Subject: updated index.scroll diff --git a/index.scroll b/index.scroll index 49dbfec..59b471d 100644 --- a/index.scroll +++ b/index.scroll @@ -3,6 +3,7 @@ buildHtml https://hub.powerhouse.wiki/powerhouse.parsers powerhouseButton +editButton /edit.html code.parsers
commit 4a21245b282e82d0305d2240a2aa47c22f4d6ba0
Author: ffff:207.243.92.34 <ffff:207.243.92.34@mitosite.powerhouse.wiki> Date: 2025-01-17 15:01:27 +0000 Subject: updated index.scroll diff --git a/index.scroll b/index.scroll index 33e1538..49dbfec 100644 --- a/index.scroll +++ b/index.scroll @@ -1,4 +1,9 @@ buildHtml + +https://hub.powerhouse.wiki/powerhouse.parsers + +powerhouseButton + code.parsers style.css
commit 6b7fad5acefa2244163cb75fbfbcdb5c249c382d
Author: root <root@hub.scroll.pub> Date: 2025-01-17 15:01:02 +0000 Subject: Deleted powerhouse.parsers diff --git a/powerhouse.parsers b/powerhouse.parsers deleted file mode 100644 index e69de29..0000000
commit ff589e00ed0f539ce294eeb534cdf8e5bf5667f3
Author: ffff:207.243.92.34 <ffff:207.243.92.34@mitosite.powerhouse.wiki> Date: 2025-01-17 15:00:54 +0000 Subject: created powerhouse.parsers diff --git a/powerhouse.parsers b/powerhouse.parsers new file mode 100644 index 0000000..e69de29
commit dc957463bbc9fea888a94cc0f978b2fc8dc6d6b4
Author: 1 <1@localhost> Date: 2025-01-16 20:08:25 -0800 Subject: updated brev.js diff --git a/brev.js b/brev.js index e69de29..434eda3 100644 --- a/brev.js +++ b/brev.js @@ -0,0 +1,88 @@ +const fs = require("fs"); +const decompress = require("decompress"); + +const nvai_url = + "https://ai.api.nvidia.com/v1/cv/nvidia/retail-object-detection"; +const header_auth = `Bearer $API_KEY_REQUIRED_IF_EXECUTING_OUTSIDE_NGC`; + +async function _upload_asset(input, description) { + const assets_url = "https://api.nvcf.nvidia.com/v2/nvcf/assets"; + + const headers = { + Authorization: header_auth, + "Content-Type": "application/json", + accept: "application/json", + }; + + const s3_headers = { + "x-amz-meta-nvcf-asset-description": description, + "content-type": "video/mp4", + }; + + const payload = { + contentType: "video/mp4", + description: description, + }; + + const response = await fetch(assets_url, { + method: "POST", + body: JSON.stringify(payload), + headers: headers, + }); + + const data = await response.json(); + + const asset_url = data["uploadUrl"]; + const asset_id = data["assetId"]; + + const fileData = fs.readFileSync(input); + + await fetch(asset_url, { + method: "PUT", + body: fileData, + headers: s3_headers, + }); + + return asset_id.toString(); +} + +(async () => { + if (process.argv.length != 4) { + console.log("Usage: node test.js <input_video> <output_dir>"); + process.exit(1); + } + + // Upload specified user asset + const asset_id = await _upload_asset(`${process.argv[2]}`, "Input Video"); + + // Metadata for the request + const inputs = { input_video: asset_id, threshold: 0.9 }; + const asset_list = asset_id; + const headers = { + "Content-Type": "application/json", + "NVCF-INPUT-ASSET-REFERENCES": asset_list, + "NVCF-FUNCTION-ASSET-IDS": asset_list, + Authorization: header_auth, + }; + + // Make the request to nvcf + const response = await fetch(nvai_url, { + method: "POST", + body: JSON.stringify(inputs), + headers: headers, + }); + + // Gather the binary response data + const arrayBuffer = await response.arrayBuffer(); + const buffer = Buffer.from(arrayBuffer); + + const zipname = `${process.argv[3]}.zip`; + fs.writeFileSync(zipname, buffer); + + // Unzip the response synchronously + await decompress(zipname, process.argv[3]); + + // Log the output directory and its contents + console.log(`Response saved to ${process.argv[3]}`); + console.log(fs.readdirSync(process.argv[3])); +})();
commit 75a9fa9e310b7201f149908f7fcbe3bead301cef
Author: 1 <1@localhost> Date: 2025-01-16 20:08:24 -0800 Subject: created brev.js diff --git a/brev.js b/brev.js new file mode 100644 index 0000000..e69de29
commit 25f4f6b833d7b22510b75c8542cdd4c6c5688221
Author: Breck Yunits <breck7@gmail.com> Date: 2025-01-16 20:05:41 -0800 Subject: diff --git a/index.scroll b/index.scroll index e2acb00..33e1538 100644 --- a/index.scroll +++ b/index.scroll @@ -23,7 +23,7 @@ webcam 800 600 hud Current Time type time position top-right - hud Swift SW200DL 400x + hud Swift SW200DL 100x position top-left diff --git a/mitosite.js b/mitosite.js index 5bb92ca..76011ca 100644 --- a/mitosite.js +++ b/mitosite.js @@ -341,11 +341,13 @@ class MitoSiteApp { console.log("Stopped auto drawing") } else { console.log("Started auto drawing") - let max = 53 + let max = 253 data.autoDrawInterval = setInterval(() => { if (max) { this.drawRandomBox(container) max-- + } else { + if (Math.random() > 0.92) this.drawRandomBox(container) } }, 25) // Draw every 500ms } @@ -358,8 +360,8 @@ class MitoSiteApp { const { canvas } = data // Generate random box dimensions within canvas bounds - const minSize = 20 - const maxSize = 50 + const minSize = 10 + const maxSize = 30 const width = Math.random() * (maxSize - minSize) + minSize const height = Math.random() * (maxSize - minSize) + minSize const x = Math.random() * (canvas.width - width)
commit d4160ba5aba631d4c749212613a5148adff966cd
Author: Breck Yunits <breck7@gmail.com> Date: 2025-01-16 19:56:55 -0800 Subject: diff --git a/index.scroll b/index.scroll index 6285316..e2acb00 100644 --- a/index.scroll +++ b/index.scroll @@ -3,8 +3,11 @@ code.parsers style.css -https://cdn.jsdelivr.net/npm/@tensorflow/tfjs -https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd + +<!-- Load TensorFlow.js. This is required to use coco-ssd model. --> +<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"> </script> +<!-- Load the coco-ssd model. --> +<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd"> </script> // lib/tensorflow/coco-ssd.min.js mitosite.js diff --git a/mitosite.js b/mitosite.js index 25809b2..5bb92ca 100644 --- a/mitosite.js +++ b/mitosite.js @@ -1,13 +1,21 @@ class MitoSiteApp { constructor(containerSelector = ".scrollWebcam") { this.containers = document.querySelectorAll(containerSelector) - this.instances = new Map() // Store instance data for each container - - this.init() - console.log() + this.instances = new Map() + this.model = null + this.isDetecting = false } - init() { + async init() { + // Load COCO-SSD model using the official library + try { + // Load the model directly from the CDN + this.model = await cocoSsd.load() + console.log("TensorFlow model loaded successfully") + } catch (err) { + console.error("Error loading TensorFlow model:", err) + } + this.containers.forEach((container) => this.setupContainer(container)) } @@ -27,6 +35,117 @@ class MitoSiteApp { await this.setupWebcam(container) this.setupCanvas(container) this.setupHUD(container) + + // Start detection loop once everything is set up + this.startDetection(container) + } + + async startDetection(container) { + const data = this.instances.get(container) + const { video } = data + + if (!this.model) { + console.error("TensorFlow model not loaded") + return + } + + // Wait for video to be ready + if (video.readyState === 0) { + video.addEventListener("loadeddata", () => this.startDetection(container)) + return + } + + const detectFrame = async () => { + if (!this.isDetecting) return + + // Check if video is ready and has valid dimensions + if ( + video.readyState !== 4 || + video.videoWidth === 0 || + video.videoHeight === 0 + ) { + requestAnimationFrame(() => detectFrame()) + return + } + + try { + // Make sure video dimensions are set + if (video.width !== video.videoWidth) { + video.width = video.videoWidth + } + if (video.height !== video.videoHeight) { + video.height = video.videoHeight + } + + // Perform detection only if video is playing and visible + if (!video.paused && !video.ended && video.style.display !== "none") { + const predictions = await this.model.detect(video) + + // Clear previous boxes + this.clearCanvas(container) + + // Draw AI predictions in a different color without adding to boxes + predictions.forEach((prediction) => { + if (prediction.score > 0.5) { + // Confidence threshold + const [x, y, width, height] = prediction.bbox + + // Draw AI predictions in blue + const { ctx } = data + ctx.strokeStyle = "#0000ff" + ctx.lineWidth = 2 + ctx.strokeRect(x, y, width, height) + + if (prediction.score !== null) { + ctx.fillStyle = "#0000ff" + ctx.font = "12px Arial" + ctx.fillText(`${Math.round(prediction.score * 100)}%`, x, y - 5) + } + } + }) + + // Redraw manual boxes in green + data.boxes.forEach((box) => { + this.drawBox(container, box.x, box.y, box.width, box.height) + }) + } + } catch (err) { + console.error("Detection error:", err) + } + + // Request next frame + requestAnimationFrame(() => detectFrame()) + } + + // Start detection loop + this.isDetecting = true + detectFrame() + } + + drawBox(container, x, y, width, height, score = null) { + const data = this.instances.get(container) + const { ctx } = data + + ctx.strokeStyle = "#00ff00" + ctx.lineWidth = 2 + ctx.strokeRect(x, y, width, height) + + if (score !== null) { + ctx.fillStyle = "#00ff00" + ctx.font = "12px Arial" + ctx.fillText(`${Math.round(score * 100)}%`, x, y - 5) + } + } + + updateCellCount(container) { + const data = this.instances.get(container) + const hud = container.querySelector(".scrollWebcamHud") + const cellCounter = hud.querySelector( + '.scrollWebcamHudElement[data-type="cellCount"]', + ) + if (cellCounter) { + cellCounter.textContent = `Cells Detected: ${data.boxes.length}` + } } async setupWebcam(container) { @@ -39,20 +158,28 @@ class MitoSiteApp { (device) => device.kind === "videoinput", ) - if (videoDevices.length > 1) { - videoDevices.forEach((device) => { - const option = document.createElement("option") - option.value = device.deviceId - option.text = device.label || `Camera ${select.length + 1}` - select.appendChild(option) - }) - select.style.display = "block" - select.addEventListener("change", (e) => - this.startCamera(container, e.target.value), - ) - } else { - select.style.display = "none" - } + // Add demo video option first + const demoOption = document.createElement("option") + demoOption.value = "demo" + demoOption.text = "Demo Video" + select.appendChild(demoOption) + + // Add webcam options + videoDevices.forEach((device) => { + const option = document.createElement("option") + option.value = device.deviceId + option.text = device.label || `Camera ${select.length}` + select.appendChild(option) + }) + + select.style.display = "block" + select.addEventListener("change", (e) => { + if (e.target.value === "demo") { + this.startDemoVideo(container) + } else { + this.startCamera(container, e.target.value) + } + }) await this.startCamera(container) } catch (err) { @@ -61,6 +188,25 @@ class MitoSiteApp { } } + async startDemoVideo(container) { + const data = this.instances.get(container) + const { video, currentStream } = data + + // Stop any existing stream + if (currentStream) { + currentStream.getTracks().forEach((track) => track.stop()) + data.currentStream = null + } + + // Set up video source + video.src = "rbc.mp4" // Make sure this file exists in your project + video.loop = true // Loop the video + video.play().catch((err) => { + console.error("Error playing demo video:", err) + container.innerHTML = "Error: Could not play demo video" + }) + } + async startCamera(container, deviceId = null) { const data = this.instances.get(container) const { video, currentStream } = data @@ -84,7 +230,17 @@ class MitoSiteApp { const stream = await navigator.mediaDevices.getUserMedia(constraints) data.currentStream = stream video.srcObject = stream - video.play() + + // Wait for video to be ready before playing + await new Promise((resolve) => { + video.onloadedmetadata = () => { + video.width = video.videoWidth + video.height = video.videoHeight + resolve() + } + }) + + await video.play() } catch (err) { console.error("Error accessing webcam:", err) container.innerHTML = "Error: Could not access webcam" @@ -97,13 +253,15 @@ class MitoSiteApp { const canvas = document.createElement("canvas") canvas.className = "scrollWebcamCanvas" - canvas.width = video.width - canvas.height = video.height + canvas.width = video.videoWidth || video.width + canvas.height = video.videoHeight || video.height canvas.style.position = "absolute" canvas.style.top = "0" canvas.style.left = "0" canvas.style.zIndex = "1" canvas.style.cursor = "crosshair" + canvas.style.width = "100%" // Make canvas scale with container + canvas.style.height = "100%" container.insertBefore(canvas, container.firstChild.nextSibling) @@ -129,7 +287,6 @@ class MitoSiteApp { cellCounter.style.bottom = "10px" cellCounter.style.left = "10px" cellCounter.style.fontSize = "30px" - //cellCounter.style.color = "#00ff00" cellCounter.style.textShadow = "1px 1px 2px black" hud.appendChild(cellCounter) } @@ -176,10 +333,54 @@ class MitoSiteApp { this.redrawBoxes(container) } else if (e.key === "Delete") { this.clearAllBoxes(container) + } else if (e.key.toLowerCase() === "r") { + // Toggle automatic box drawing + if (data.autoDrawInterval) { + clearInterval(data.autoDrawInterval) + data.autoDrawInterval = null + console.log("Stopped auto drawing") + } else { + console.log("Started auto drawing") + let max = 53 + data.autoDrawInterval = setInterval(() => { + if (max) { + this.drawRandomBox(container) + max-- + } + }, 25) // Draw every 500ms + } } }) } + drawRandomBox(container) { + const data = this.instances.get(container) + const { canvas } = data + + // Generate random box dimensions within canvas bounds + const minSize = 20 + const maxSize = 50 + const width = Math.random() * (maxSize - minSize) + minSize + const height = Math.random() * (maxSize - minSize) + minSize + const x = Math.random() * (canvas.width - width) + const y = Math.random() * (canvas.height - height) + + // Add the box to the collection + data.boxes.push({ x, y, width, height }) + + // Redraw all boxes + this.redrawBoxes(container) + + // Update cell counter + const hud = container.querySelector(".scrollWebcamHud") + const cellCounter = hud.querySelector( + '.scrollWebcamHudElement[data-type="cellCount"]', + ) + if (cellCounter) { + cellCounter.textContent = `Cells Counted: ${data.boxes.length}` + } + } + handleMouseDown(container, e) { const data = this.instances.get(container) const rect = data.canvas.getBoundingClientRect() @@ -237,15 +438,6 @@ class MitoSiteApp { this.redrawBoxes(container) } - drawBox(container, x, y, width, height) { - const data = this.instances.get(container) - const { ctx } = data - - ctx.strokeStyle = "#00ff00" - ctx.lineWidth = 2 - ctx.strokeRect(x, y, width, height) - } - clearCanvas(container) { const data = this.instances.get(container) const { ctx, canvas } = data @@ -277,6 +469,21 @@ class MitoSiteApp { } } -document.addEventListener("DOMContentLoaded", () => { +// Initialize the app when the DOM is loaded +document.addEventListener("DOMContentLoaded", async () => { + // Verify TensorFlow.js and COCO-SSD are loaded + if (typeof tf === "undefined") { + console.error("TensorFlow.js is not loaded") + return + } + if (typeof cocoSsd === "undefined") { + console.error("COCO-SSD model is not loaded") + return + } + + console.log("TensorFlow.js loaded:", typeof tf !== "undefined") + console.log("COCO-SSD loaded:", typeof cocoSsd !== "undefined") + const app = new MitoSiteApp() + await app.init() })
commit c43d642a77172ea7771ae955a7ca0445881f7230
Author: 1 <1@localhost> Date: 2025-01-16 19:45:40 -0800 Subject: updated index.scroll diff --git a/index.scroll b/index.scroll index e44e95d..6285316 100644 --- a/index.scroll +++ b/index.scroll @@ -2,6 +2,11 @@ buildHtml code.parsers style.css + +https://cdn.jsdelivr.net/npm/@tensorflow/tfjs +https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd +// lib/tensorflow/coco-ssd.min.js + mitosite.js center
commit c6fda4c8c7ee923e7344f855a5d1c5a55ffecd2f
Author: 1 <1@localhost> Date: 2025-01-16 19:17:03 -0800 Subject: updated video.scroll diff --git a/video.scroll b/video.scroll index 380cbad..94d9ce1 100644 --- a/video.scroll +++ b/video.scroll @@ -1,3 +1,4 @@ buildHtml rbc.mp4 - autoplay \ No newline at end of file + autoplay + loop \ No newline at end of file