Video feature centroid detection

by Admiral Potato

HTML

<div class="container">
			<div>
				<div class="form-field">
					<label>
						<span>Video</span>
						<button id="start-button">Start</button>
						<select id="video-select"></select>
					</label>
				</div>
				<div class="form-field">
					<label>
						<span>Data Image Width</span>
						<input
							type="number"
							min="64"
							max="512"
							value="384"
							step="16"
							id="input-width-number"
						/>
						<input
							type="range"
							min="64"
							max="512"
							value="384"
							step="16"
							id="input-width"
						/>
					</label>
				</div>
				<div class="form-field">
					<label>
						<span>Pixel Gap (VERY EXPENSIVE)</span>
						<input
							type="number"
							min="0"
							max="5"
							value="3"
							step="1"
							id="input-gap-number"
						/>
						<input
							type="range"
							min="0"
							max="5"
							value="3"
							step="1"
							id="input-gap"
						/>
					</label>
				</div>
				<div class="form-field">
					<label>
						<span>Threshhold</span>
						<input
							type="number"
							min="0"
							max="765"
							value="382"
							step="1"
							id="input-threshold-number"
						/>
						<input
							type="range"
							min="0"
							max="765"
							value="382"
							step="1"
							id="input-threshold"
						/>
					</label>
				</div>
				<div class="form-field">
					<label>
						<span>Minimum Blob Size</span>
						<input
							type="number"
							min="10"
							max="300"
							value="100"
							step="10"
							id="input-size-number"
						/>
						<input
							type="range"
							min="10"
							max="300"
							value="100"
							step="10"
							id="input-size"
						/>
					</label>
				</div>
				<div class="form-field">
					<label>
						<span>Last frame compute time:</span>
						<input type="number" id="input-time" disabled />
					</label>
				</div>
			</div>
			<div class="io">
				<canvas id="canny" width="384" height="384"></canvas>
				<video...

CSS

* {
				color: #fff;
				font-family: monospace;
				font-size: 16px;
			}
			body {
				background-color: #333;
				text-align: center;
				margin: 0;
				padding: 32px;
			}
			.io {
				line-height: 0;
				font-size: 0;
			}
			.form-field label {
				display: block;
				text-align: left;
			}
			.form-field label span {
				display: block;
			}
			.form-field label input,
			.form-field label button,
			.form-field label select {
				display: inline-block;
				background-color: #0008;
				border: 1px solid #6668;
			}
			.form-field label input[type="number"] {
				width: 5rem;
			}
			.form-field label input[type="range"] {
				width: calc(50% - 10rem);
			}
			canvas,
			video {
				background-color: #000;
				display: inline-block;
				width: 50%;
				max-width: 50%;
			}
			@media (max-width: 640px) {
				canvas,
				video {
					width: 100%;
					max-width: 100%;
				}
				.form-field label input[type="range"] {
					width: calc(100% - 8rem);
				}
			}

JavaScript

const canvas = document.getElementById("canny");
const startButton = document.getElementById("start-button");
const videoSelect = document.getElementById("video-select");
const inputWidthNumber = document.getElementById("input-width-number");
const inputWidth = document.getElementById("input-width");
const inputGapNumber = document.getElementById("input-gap-number");
const inputGap = document.getElementById("input-gap");
const inputThresholdNumber = document.getElementById("input-threshold-number");
const inputThreshold = document.getElementById("input-threshold");
const inputSizeNumber = document.getElementById("input-size-number");
const inputSize = document.getElementById("input-size");
const inputTime = document.getElementById("input-time");
let { width, height } = canvas;
const video = document.getElementById("blobby");
const context = canvas.getContext("2d", { willReadFrequently: true });
context.imageSmoothingEnabled = true;
context.imageSmoothingQuality = "high";
console.log("Context?", context);

const handleWidthInput = (event) => {
	const value = event.target.value * 1 || 64;
	width = value;
	canvas.width = width;
	inputWidth.value = value;
	inputWidthNumber.value = value;
	handleResize();
};
inputWidthNumber.addEventListener("input", handleWidthInput);
inputWidth.addEventListener("input", handleWidthInput);

let maxPixelGap = 3;
const handleGapInput = (event) => {
	const value = event.target.value * 1 || 0;
	maxPixelGap = value;
	inputGap.value = value;
	inputGapNumber.value = value;
};
inputGapNumber.addEventListener("input", handleGapInput);
inputGap.addEventListener("input", handleGapInput);

let threshold = 100;
const handleThreshholdInput = (event) => {
	const value = event.target.value * 1 || 0;
	threshold = value;
	inputThreshold.value = value;
	inputThresholdNumber.value = value;
};
inputThresholdNumber.addEventListener("input", handleThreshholdInput);
inputThreshold.addEventListener("input", handleThreshholdInput);

let minBlobSize =...