UNPKG

@webarkit/jsfeat-next

Version:

Typescript version of jsfeat for WebARKit

227 lines (190 loc) 9.05 kB
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="description" content="A JavaScript Computer Vision Library"> <title>JSFeatNext - JavaScript Computer Vision Library.</title> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Droid+Sans:regular,bold|Inconsolata|PT+Sans:400,700"> <link rel="stylesheet" href="css/bootstrap.css"> <link rel="stylesheet" href="css/jsfeat.css"> </head> <body> <video id="webcam" width="640" height="480" style="display:none;"></video> <div style=" width:640px;height:480px;margin: 10px auto;"> <canvas id="canvas" width="640" height="480"></canvas> <div id="no_rtc" class="alert alert-error" style="display:none;"></div> <div id="log" class="alert alert-info"></div> </div> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="../dist/jsfeatNext.js"></script> <script type="text/javascript" src="js/compatibility.js"></script> <script type="text/javascript" src="js/profiler.js"></script> <script type="text/javascript" src="js/dat.gui.min.js"></script> <script type="text/javascript"> $(window).on('load', function () { "use strict"; // lets do some fun var video = document.getElementById('webcam'); var canvas = document.getElementById('canvas'); var jsfeat = jsfeatNext.jsfeatNext; var imgproc = new jsfeat.imgproc(); var optical_flow_lk = new jsfeat.optical_flow_lk(); try { var attempts = 0; var readyListener = function (event) { findVideoSize(); }; var findVideoSize = function () { if (video.videoWidth > 0 && video.videoHeight > 0) { video.removeEventListener('loadeddata', readyListener); onDimensionsReady(video.videoWidth, video.videoHeight); } else { if (attempts < 10) { attempts++; setTimeout(findVideoSize, 200); } else { onDimensionsReady(640, 480); } } }; var onDimensionsReady = function (width, height) { demo_app(width, height); compatibility.requestAnimationFrame(tick); }; video.addEventListener('loadeddata', readyListener); compatibility.getUserMedia({ video: true }, function (stream) { if (video.srcObject !== undefined) { video.srcObject = stream } else { try { video.src = compatibility.URL.createObjectURL(stream); } catch (error) { video.src = stream; } } setTimeout(function () { video.play(); }, 500); }, function (error) { $('#canvas').hide(); $('#log').hide(); $('#no_rtc').html('<h4>WebRTC not available.</h4>'); $('#no_rtc').show(); }); } catch (error) { $('#canvas').hide(); $('#log').hide(); $('#no_rtc').html('<h4>Something goes wrong...</h4>'); $('#no_rtc').show(); } var stat = new profiler(); var gui, options, ctx, canvasWidth, canvasHeight; var curr_img_pyr, prev_img_pyr, point_count, point_status, prev_xy, curr_xy; var demo_opt = function () { this.win_size = 20; this.max_iterations = 30; this.epsilon = 0.01; this.min_eigen = 0.001; } function demo_app(videoWidth, videoHeight) { canvasWidth = canvas.width; canvasHeight = canvas.height; ctx = canvas.getContext('2d', {"willReadFrequently": true}); ctx.fillStyle = "rgb(0,255,0)"; ctx.strokeStyle = "rgb(0,255,0)"; curr_img_pyr = new jsfeat.pyramid_t(3); prev_img_pyr = new jsfeat.pyramid_t(3); curr_img_pyr.allocate(640, 480, jsfeat.U8_t | jsfeat.C1_t); prev_img_pyr.allocate(640, 480, jsfeat.U8_t | jsfeat.C1_t); point_count = 0; point_status = new Uint8Array(100); prev_xy = new Float32Array(100 * 2); curr_xy = new Float32Array(100 * 2); options = new demo_opt(); gui = new dat.GUI(); gui.add(options, 'win_size', 7, 30).step(1); gui.add(options, 'max_iterations', 3, 30).step(1); gui.add(options, 'epsilon', 0.001, 0.1).step(0.0025); gui.add(options, 'min_eigen', 0.001, 0.01).step(0.0025); stat.add("grayscale"); stat.add("build image pyramid"); stat.add("optical flow lk"); } function tick() { compatibility.requestAnimationFrame(tick); stat.new_frame(); if (video.readyState === video.HAVE_ENOUGH_DATA) { ctx.drawImage(video, 0, 0, 640, 480); var imageData = ctx.getImageData(0, 0, 640, 480); // swap flow data var _pt_xy = prev_xy; prev_xy = curr_xy; curr_xy = _pt_xy; var _pyr = prev_img_pyr; prev_img_pyr = curr_img_pyr; curr_img_pyr = _pyr; stat.start("grayscale"); imgproc.grayscale(imageData.data, 640, 480, curr_img_pyr.data[0]); stat.stop("grayscale"); stat.start("build image pyramid"); curr_img_pyr.build(curr_img_pyr.data[0], true); stat.stop("build image pyramid"); stat.start("optical flow lk"); optical_flow_lk.track(prev_img_pyr, curr_img_pyr, prev_xy, curr_xy, point_count, options.win_size | 0, options.max_iterations | 0, point_status, options.epsilon, options.min_eigen); stat.stop("optical flow lk"); prune_oflow_points(ctx); $('#log').html(stat.log() + '<br/>click to add tracking points: ' + point_count); } } function on_canvas_click(e) { var coords = canvas.relMouseCoords(e); if (coords.x > 0 & coords.y > 0 & coords.x < canvasWidth & coords.y < canvasHeight) { curr_xy[point_count << 1] = coords.x; curr_xy[(point_count << 1) + 1] = coords.y; point_count++; } } canvas.addEventListener('click', on_canvas_click, false); function draw_circle(ctx, x, y) { ctx.beginPath(); ctx.arc(x, y, 4, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); } function prune_oflow_points(ctx) { var n = point_count; var i = 0, j = 0; for (; i < n; ++i) { if (point_status[i] == 1) { if (j < i) { curr_xy[j << 1] = curr_xy[i << 1]; curr_xy[(j << 1) + 1] = curr_xy[(i << 1) + 1]; } draw_circle(ctx, curr_xy[j << 1], curr_xy[(j << 1) + 1]); ++j; } } point_count = j; } function relMouseCoords(event) { var totalOffsetX = 0, totalOffsetY = 0, canvasX = 0, canvasY = 0; var currentElement = this; do { totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft; totalOffsetY += currentElement.offsetTop - currentElement.scrollTop; } while (currentElement = currentElement.offsetParent) canvasX = event.pageX - totalOffsetX; canvasY = event.pageY - totalOffsetY; return { x: canvasX, y: canvasY } } HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords; $(window).on('unload', function () { video.pause(); video.src = null; }); }); </script> </body> </html>