186 lines
6.3 KiB
HTML
186 lines
6.3 KiB
HTML
<!doctype html>
|
||
<html>
|
||
<head>
|
||
|
||
<title>tracking.js - bounding box with camera</title>
|
||
|
||
<meta charset="utf-8">
|
||
<link rel="stylesheet" href="assets/demo.css">
|
||
|
||
<script src="../build/tracking-min.js"></script>
|
||
<script src="../node_modules/dat.gui/build/dat.gui.min.js"></script>
|
||
<script src="assets/stats.min.js"></script>
|
||
|
||
<style>
|
||
#boundingBox {
|
||
display: none;
|
||
position: absolute;
|
||
background: white;
|
||
border: 1px dashed;
|
||
opacity: .5;
|
||
z-index: 1;
|
||
}
|
||
#video {
|
||
position: absolute;
|
||
top: -1000px;
|
||
cursor: crosshair;
|
||
}
|
||
body {
|
||
-webkit-touch-callout: none;
|
||
-webkit-user-select: none;
|
||
-khtml-user-select: none;
|
||
-moz-user-select: none;
|
||
-ms-user-select: none;
|
||
user-select: none;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="demo-title">
|
||
<p><a href="http://trackingjs.com" target="_parent">tracking.js</a> - Click and drag to select the area to be tracked</p>
|
||
</div>
|
||
|
||
<div id="boundingBox"></div>
|
||
|
||
<div class="demo-frame">
|
||
<div class="demo-container">
|
||
<video id="video" width="393" height="295" preload autoplay loop muted controls></video>
|
||
<canvas id="canvas" width="800" height="530"></canvas>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function() {
|
||
// BoundingBoxTracker ======================================================
|
||
var BoundingBoxTracker = function() {
|
||
BoundingBoxTracker.base(this, 'constructor');
|
||
};
|
||
tracking.inherits(BoundingBoxTracker, tracking.Tracker);
|
||
|
||
BoundingBoxTracker.prototype.templateDescriptors_ = null;
|
||
BoundingBoxTracker.prototype.templateKeypoints_ = null;
|
||
BoundingBoxTracker.prototype.fastThreshold = 60;
|
||
BoundingBoxTracker.prototype.blur = 3;
|
||
|
||
BoundingBoxTracker.prototype.setTemplate = function(pixels, width, height) {
|
||
var blur = tracking.Image.blur(pixels, width, height, 3);
|
||
var grayscale = tracking.Image.grayscale(blur, width, height);
|
||
this.templateKeypoints_ = tracking.Fast.findCorners(grayscale, width, height);
|
||
this.templateDescriptors_ = tracking.Brief.getDescriptors(grayscale, width, this.templateKeypoints_);
|
||
};
|
||
|
||
BoundingBoxTracker.prototype.track = function(pixels, width, height) {
|
||
var blur = tracking.Image.blur(pixels, width, height, this.blur);
|
||
var grayscale = tracking.Image.grayscale(blur, width, height);
|
||
var keypoints = tracking.Fast.findCorners(grayscale, width, height, this.fastThreshold);
|
||
var descriptors = tracking.Brief.getDescriptors(grayscale, width, keypoints);
|
||
this.emit('track', {
|
||
data: tracking.Brief.reciprocalMatch(this.templateKeypoints_, this.templateDescriptors_, keypoints, descriptors)
|
||
});
|
||
};
|
||
|
||
// Track ===================================================================
|
||
var boundingBox = document.getElementById('boundingBox');
|
||
var boxLeft = 403;
|
||
var video = document.getElementById('video');
|
||
var canvas = document.getElementById('canvas');
|
||
var canvasRect = canvas.getBoundingClientRect();
|
||
var context = canvas.getContext('2d');
|
||
var templateImageData;
|
||
var capturing = false;
|
||
var videoHeight = 295;
|
||
var videoWidth = 393;
|
||
|
||
var tracker = new BoundingBoxTracker();
|
||
|
||
tracker.on('track', function(event) {
|
||
stats.end();
|
||
|
||
if (capturing) {
|
||
return;
|
||
}
|
||
// Sorts best matches by confidence.
|
||
event.data.sort(function(a, b) {
|
||
return b.confidence - a.confidence;
|
||
});
|
||
// Re-draws template on canvas.
|
||
context.putImageData(templateImageData, boxLeft, 0);
|
||
|
||
// Plots lines connecting matches.
|
||
for (var i = 0; i < Math.min(10, event.data.length); i++) {
|
||
var template = event.data[i].keypoint1;
|
||
var frame = event.data[i].keypoint2;
|
||
context.beginPath();
|
||
context.strokeStyle = 'magenta';
|
||
context.moveTo(frame[0], frame[1]);
|
||
context.lineTo(boxLeft + template[0], template[1]);
|
||
context.stroke();
|
||
}
|
||
});
|
||
|
||
var trackerTask = tracking.track(video, tracker, { camera: true });
|
||
// Waits for the user to accept the camera.
|
||
trackerTask.stop();
|
||
|
||
// Sync video ============================================================
|
||
function requestFrame() {
|
||
window.requestAnimationFrame(function() {
|
||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||
if (video.readyState === video.HAVE_ENOUGH_DATA) {
|
||
try {
|
||
context.drawImage(video, 0, 0, videoWidth, videoHeight);
|
||
} catch (err) {}
|
||
}
|
||
requestFrame();
|
||
});
|
||
}
|
||
requestFrame();
|
||
|
||
// Bounding box drag =====================================================
|
||
var initialPoint;
|
||
var left;
|
||
var top;
|
||
var width;
|
||
var height;
|
||
canvas.addEventListener('mousedown', function(event) {
|
||
initialPoint = [event.pageX, event.pageY];
|
||
capturing = true;
|
||
});
|
||
canvas.addEventListener('mousemove', function(event) {
|
||
if (capturing) {
|
||
left = Math.min(initialPoint[0], event.pageX);
|
||
top = Math.min(initialPoint[1], event.pageY);
|
||
width = Math.max(initialPoint[0], event.pageX) - left;
|
||
height = Math.max(initialPoint[1], event.pageY) - top;
|
||
boundingBox.style.display = 'block';
|
||
boundingBox.style.left = left + 'px';
|
||
boundingBox.style.top = top + 'px';
|
||
boundingBox.style.width = width + 'px';
|
||
boundingBox.style.height = height + 'px';
|
||
}
|
||
});
|
||
document.addEventListener('mouseup', function() {
|
||
boundingBox.style.display = 'none';
|
||
setTackerTemplate(left, top, width, height);
|
||
capturing = false;
|
||
});
|
||
function setTackerTemplate(left, top, width, height) {
|
||
templateImageData = context.getImageData(left - canvasRect.left, top - canvasRect.top, width, height);
|
||
canvas.width = boxLeft + width;
|
||
context.putImageData(templateImageData, boxLeft, 0);
|
||
trackerTask.stop();
|
||
tracker.setTemplate(templateImageData.data, width, height);
|
||
trackerTask.run();
|
||
}
|
||
|
||
// GUI Controllers
|
||
var gui = new dat.GUI();
|
||
gui.add(tracker, 'fastThreshold', 20, 100).step(5);
|
||
gui.add(tracker, 'blur', 1.1, 5.0).step(0.1);
|
||
}());
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|