Comparar commits
7 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 641f1b12d2 | |||
| 117cbe745e | |||
| 58725f5341 | |||
| dc720a20c2 | |||
| eb2994355d | |||
| 7bfe53f958 | |||
| 247b8582fc |
@@ -1,3 +1,2 @@
|
||||
node_modules
|
||||
.*.swp
|
||||
.DS_Store
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
Get a realtime live video stream from your
|
||||
[Parrot AR Drone 2.0](http://ardrone2.parrot.com/) straight to your browser.
|
||||
|
||||
## Documentation is a little out of date, please check the two examples for now!
|
||||
|
||||
## Requirements
|
||||
|
||||
You'll need a decent and current browser and some cpu horsepower.
|
||||
@@ -47,5 +45,3 @@ is enough to be used as a starting point for your own integration.
|
||||
- Brian Leroux for being not content with the original solution and for
|
||||
cleaning up the predecessor, nodecopter-stream.
|
||||
|
||||
- @karlwestin for picking up where I was to lazy to actually make this usable.
|
||||
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('express')
|
||||
, routes = require('./routes')
|
||||
, http = require('http')
|
||||
, path = require('path')
|
||||
, app = express()
|
||||
, server = http.createServer(app)
|
||||
, WebSocketServer = require('ws').Server
|
||||
, wss = new WebSocketServer({server: server})
|
||||
, sockets = []
|
||||
, Parser = require('./lib/PaVEParser')
|
||||
, arDrone = require('ar-drone')
|
||||
;
|
||||
|
||||
function init() {
|
||||
var tcpVideoStream = new arDrone.Client.PngStream.TcpVideoStream({timeout: 4000})
|
||||
, p = new Parser();
|
||||
|
||||
console.log("Connecting to stream");
|
||||
|
||||
tcpVideoStream.connect(function () {
|
||||
tcpVideoStream.pipe(p);
|
||||
});
|
||||
|
||||
tcpVideoStream.on("error", function(err) {
|
||||
console.log("There was an error: %s", err.message);
|
||||
tcpVideoStream.end();
|
||||
tcpVideoStream.emit("end");
|
||||
init();
|
||||
});
|
||||
|
||||
p.on('data', function (data) {
|
||||
sockets.forEach(function(socket) {
|
||||
socket.send(data, {binary: true});
|
||||
});
|
||||
});
|
||||
}
|
||||
init();
|
||||
|
||||
wss.on('connection', function (socket) {
|
||||
sockets.push(socket);
|
||||
|
||||
socket.on("close", function() {
|
||||
console.log("Closing socket");
|
||||
sockets = sockets.filter(function(el) {
|
||||
return el !== socket;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.configure(function () {
|
||||
app.set('port', process.env.PORT || 3000);
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade', { pretty: true });
|
||||
app.use(express.favicon());
|
||||
app.use(express.logger('dev'));
|
||||
app.use(express.bodyParser());
|
||||
app.use(express.methodOverride());
|
||||
app.use(app.router);
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
});
|
||||
|
||||
app.configure('development', function () {
|
||||
app.use(express.errorHandler());
|
||||
app.locals.pretty = true;
|
||||
});
|
||||
|
||||
|
||||
app.get('/', routes.index);
|
||||
|
||||
if (module.parent) {
|
||||
module.exports = server;
|
||||
} else {
|
||||
server.listen(app.get('port'), function () {
|
||||
console.log("Express server listening on port " + app.get('port'));
|
||||
});
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cat dist/vendor/broadway/sylvester.js dist/vendor/broadway/glUtils.js dist/vendor/broadway/util.js dist/vendor/broadway/avc-codec.js dist/vendor/broadway/avc.js dist/vendor/broadway/canvas.js dist/nodecopter-stream.js > dist/nodecopter-client.js
|
||||
externo
-1162
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -1,33 +0,0 @@
|
||||
var express = require('express')
|
||||
, routes = require('./routes')
|
||||
, app = express()
|
||||
, path = require('path')
|
||||
, server = require("http").createServer(app)
|
||||
;
|
||||
|
||||
|
||||
app.configure(function () {
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade', { pretty: true });
|
||||
app.use(express.favicon());
|
||||
app.use(express.logger('dev'));
|
||||
app.use(app.router);
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
});
|
||||
|
||||
app.configure('development', function () {
|
||||
app.use(express.errorHandler());
|
||||
app.locals.pretty = true;
|
||||
});
|
||||
|
||||
app.get('/', routes.index);
|
||||
|
||||
/*
|
||||
* Important:
|
||||
*
|
||||
* pass in the server object to listen, not the express app
|
||||
* call 'listen' on the server, not the express app
|
||||
*/
|
||||
// should be require("node-dronestream").listen(server)
|
||||
require("../lib/server").listen(server);
|
||||
server.listen(3000);
|
||||
@@ -1,10 +0,0 @@
|
||||
var http = require("http"),
|
||||
drone = require("../../index");
|
||||
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
require("fs").createReadStream(__dirname + "/index.html").pipe(res);
|
||||
});
|
||||
|
||||
drone.listen(server);
|
||||
server.listen(5555);
|
||||
@@ -1,16 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>Stream as module</title>
|
||||
<script src="/dronestream/nodecopter-client.js" type="text/javascript" charset="utf-8"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="heading">Stream through a normal require("http").createServer</h1>
|
||||
<div id="droneStream" style="width: 640px; height: 360px"> </div>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
new NodecopterStream(document.getElementById("droneStream"));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,33 +0,0 @@
|
||||
var express = require('express')
|
||||
, routes = require('./routes')
|
||||
, app = express()
|
||||
, path = require('path')
|
||||
, server = require("http").createServer(app)
|
||||
;
|
||||
|
||||
|
||||
app.configure(function () {
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade', { pretty: true });
|
||||
app.use(express.favicon());
|
||||
app.use(express.logger('dev'));
|
||||
app.use(app.router);
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
});
|
||||
|
||||
app.configure('development', function () {
|
||||
app.use(express.errorHandler());
|
||||
app.locals.pretty = true;
|
||||
});
|
||||
|
||||
app.get('/', routes.index);
|
||||
|
||||
/*
|
||||
* Important:
|
||||
*
|
||||
* pass in the server object to listen, not the express app
|
||||
* call 'listen' on the server, not the express app
|
||||
*/
|
||||
// should be require("node-dronestream").listen(server)
|
||||
require("../../index").listen(server);
|
||||
server.listen(3000);
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "dronestream-example",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"express": "3.0.0rc5",
|
||||
"jade": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node app"
|
||||
},
|
||||
"author": "Bernhard K. Weisshuhn <bkw@codingforce.com>",
|
||||
"license": "BSD"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
extends layout
|
||||
|
||||
block append head
|
||||
script(type='text/javascript', src='/dronestream/nodecopter-client.js')
|
||||
|
||||
-# for developing the client, use those url:s
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/sylvester.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/glUtils.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/util.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/avc-codec.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/avc.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/canvas.js')
|
||||
-# script(type='text/javascript', src='/dronestream/nodecopter-stream.js')
|
||||
-# concatenated version of client
|
||||
|
||||
|
||||
block append bodyscripts
|
||||
script
|
||||
var copterStream = new NodecopterStream(document.querySelector('#dronestream'));
|
||||
|
||||
block content
|
||||
div#dronestream(width=640, height=360)
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "dronestream-example",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"express": "3.0.0rc5",
|
||||
"jade": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node app"
|
||||
},
|
||||
"author": "Bernhard K. Weisshuhn <bkw@codingforce.com>",
|
||||
"license": "BSD"
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*! normalize.css v1.0.1 | MIT License | git.io/normalize */
|
||||
article,aside,details,figcaption,figure,footer,header,hgroup,nav,section,summary{display:block}
|
||||
audio,canvas,video{display:inline-block;*display:inline;*zoom:1}
|
||||
audio:not([controls]){display:none;height:0}
|
||||
[hidden]{display:none}
|
||||
html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}
|
||||
html,button,input,select,textarea{font-family:sans-serif}
|
||||
body{margin:0}
|
||||
a:focus{outline:thin dotted}
|
||||
a:active,a:hover{outline:0}
|
||||
h1{font-size:2em;margin:.67em 0}
|
||||
h2{font-size:1.5em;margin:.83em 0}
|
||||
h3{font-size:1.17em;margin:1em 0}
|
||||
h4{font-size:1em;margin:1.33em 0}
|
||||
h5{font-size:.83em;margin:1.67em 0}
|
||||
h6{font-size:.75em;margin:2.33em 0}
|
||||
abbr[title]{border-bottom:1px dotted}
|
||||
b,strong{font-weight:bold}
|
||||
blockquote{margin:1em 40px}
|
||||
dfn{font-style:italic}
|
||||
mark{background:#ff0;color:#000}
|
||||
p,pre{margin:1em 0}
|
||||
code,kbd,pre,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}
|
||||
pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}
|
||||
q{quotes:none}
|
||||
q:before,q:after{content:'';content:none}
|
||||
small{font-size:80%}
|
||||
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||||
sup{top:-0.5em}
|
||||
sub{bottom:-0.25em}
|
||||
dl,menu,ol,ul{margin:1em 0}
|
||||
dd{margin:0 0 0 40px}
|
||||
menu,ol,ul{padding:0 0 0 40px}
|
||||
nav ul,nav ol{list-style:none;list-style-image:none}
|
||||
img{border:0;-ms-interpolation-mode:bicubic}
|
||||
svg:not(:root){overflow:hidden}
|
||||
figure{margin:0}
|
||||
form{margin:0}
|
||||
fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
|
||||
legend{border:0;padding:0;white-space:normal;*margin-left:-7px}
|
||||
button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}
|
||||
button,input{line-height:normal}
|
||||
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}
|
||||
button[disabled],input[disabled]{cursor:default}
|
||||
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*height:13px;*width:13px}
|
||||
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
|
||||
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
|
||||
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
|
||||
textarea{overflow:auto;vertical-align:top}
|
||||
table{border-collapse:collapse;border-spacing:0}
|
||||
@@ -1,8 +0,0 @@
|
||||
body {
|
||||
padding: 50px;
|
||||
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #00B7FF;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* GET home page.
|
||||
*/
|
||||
|
||||
exports.index = function (req, res) {
|
||||
res.render('index', { title: 'Express' });
|
||||
};
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
extends layout
|
||||
|
||||
block append head
|
||||
script(type='text/javascript', src='/dronestream/nodecopter-client.js')
|
||||
|
||||
-# for developing the client, use those url:s
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/sylvester.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/glUtils.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/util.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/avc-codec.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/avc.js')
|
||||
-# script(type='text/javascript', src='/dronestream/vendor/broadway/canvas.js')
|
||||
-# script(type='text/javascript', src='/dronestream/nodecopter-stream.js')
|
||||
-# concatenated version of client
|
||||
|
||||
|
||||
block append bodyscripts
|
||||
script
|
||||
var copterStream = new NodecopterStream(document.querySelector('#dronestream'));
|
||||
|
||||
block content
|
||||
div#dronestream(width=640, height=360)
|
||||
@@ -1,30 +0,0 @@
|
||||
!!! 5
|
||||
html
|
||||
block head
|
||||
head
|
||||
meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
|
||||
meta(name='viewport', content='width=device-width')
|
||||
title= title
|
||||
link(rel='stylesheet', href='/css/normalize.min.css')
|
||||
link(rel='stylesheet', href='/css/style.css')
|
||||
body
|
||||
div.header-container
|
||||
header.wrapper.clearfix
|
||||
block header
|
||||
nav
|
||||
block navigation
|
||||
|
||||
div.main-container
|
||||
div.main.wrapper.clearfix
|
||||
|
||||
block content
|
||||
|
||||
|
||||
div.footer-container
|
||||
footer.wrapper
|
||||
block footer
|
||||
|
||||
block bodyscripts
|
||||
// script(src='//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js')
|
||||
// script
|
||||
// window.jQuery || document.write('<script src="/js/vendor/h5bp/jquery-1.8.2.min.js"><\\x3C/script>')
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = require("./lib/server");
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Drone Stream listen:
|
||||
* Takes a) a port number or b) a server object (node http or express, etc);
|
||||
*/
|
||||
var staticDir = "dronestream"
|
||||
, check = new RegExp("^/" + staticDir, "i")
|
||||
, dist = __dirname + "/../dist"
|
||||
;
|
||||
|
||||
module.exports.listen = function listen(server) {
|
||||
if(typeof server == "number") {
|
||||
var port = server;
|
||||
server = require("http").createServer();
|
||||
server.listen(port);
|
||||
}
|
||||
|
||||
/*
|
||||
* Serving up the static files needed
|
||||
*/
|
||||
var oldHandlers = server.listeners("request").splice(0);
|
||||
|
||||
server.on("request", function(req, res) {
|
||||
if(handler(req, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(var i = 0; i < oldHandlers.length; i++) {
|
||||
oldHandlers[i].call(server, req, res);
|
||||
}
|
||||
});
|
||||
|
||||
function handler(req, res, next) {
|
||||
if(!check.test(req.url)) {
|
||||
return false;
|
||||
}
|
||||
var path = dist + req.url.replace(check, "");
|
||||
console.log("checking static path: %s", path);
|
||||
var read = require('fs').createReadStream(path);
|
||||
read.pipe(res);
|
||||
read.on("error", function(e) { console.log("Stream error: %s", e.message); });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connecting stream + websocket server
|
||||
*/
|
||||
return require("./stream").attach(server);
|
||||
};
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Sets up a real stream + attaches it to a server
|
||||
*/
|
||||
module.exports.attach = function droneStream(server) {
|
||||
var WebSocketServer = require('ws').Server
|
||||
, wss = new WebSocketServer({server: server})
|
||||
, sockets = []
|
||||
, Parser = require('./PaVEParser')
|
||||
, arDrone = require('ar-drone')
|
||||
;
|
||||
|
||||
function init() {
|
||||
var tcpVideoStream = new arDrone.Client.PngStream.TcpVideoStream({timeout: 4000})
|
||||
, p = new Parser();
|
||||
|
||||
console.log("Connecting to stream");
|
||||
|
||||
tcpVideoStream.connect(function () {
|
||||
tcpVideoStream.pipe(p);
|
||||
});
|
||||
|
||||
tcpVideoStream.on("error", function(err) {
|
||||
console.log("There was an error: %s", err.message);
|
||||
tcpVideoStream.end();
|
||||
tcpVideoStream.emit("end");
|
||||
init();
|
||||
});
|
||||
|
||||
p.on('data', function (data) {
|
||||
sockets.forEach(function(socket) {
|
||||
socket.send(data, {binary: true});
|
||||
});
|
||||
});
|
||||
}
|
||||
init();
|
||||
|
||||
wss.on('connection', function (socket) {
|
||||
sockets.push(socket);
|
||||
|
||||
socket.on("close", function() {
|
||||
console.log("Closing socket");
|
||||
sockets = sockets.filter(function(el) {
|
||||
return el !== socket;
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
+6
-8
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "dronestream",
|
||||
"description": "video live stream from your parrot ar.drone 2.0 to your browser in pure javascript",
|
||||
"version": "1.0.0",
|
||||
"version": "0.2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:bkw/node-dronestream.git"
|
||||
},
|
||||
"main": "index",
|
||||
"keywords": [
|
||||
"drone",
|
||||
"nodecopter",
|
||||
@@ -16,17 +15,16 @@
|
||||
"browser",
|
||||
"x264"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "node app"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "3.0.0rc5",
|
||||
"jade": "*",
|
||||
"ws": "~0.4.22",
|
||||
"ar-drone": "0.0.3",
|
||||
"buffy": "0.0.4"
|
||||
},
|
||||
"author": "Bernhard K. Weisshuhn <bkw@codingforce.com>",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Karl Westin",
|
||||
"email": "karl.westin@gmail.com"
|
||||
}
|
||||
],
|
||||
"license": "BSD"
|
||||
}
|
||||
|
||||
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 5.5 KiB |
@@ -5,7 +5,9 @@
|
||||
var NS,
|
||||
socket,
|
||||
avc,
|
||||
webGLCanvas;
|
||||
webGLCanvas,
|
||||
width,
|
||||
height;
|
||||
|
||||
function setupAvc() {
|
||||
avc = new Avc();
|
||||
@@ -32,9 +34,10 @@
|
||||
}
|
||||
|
||||
function setupCanvas(div) {
|
||||
var width = div.attributes.width ? div.attributes.width.value : 640,
|
||||
height = div.attributes.height ? div.attributes.height.value : 360,
|
||||
canvas = document.createElement('canvas');
|
||||
var canvas = document.createElement('canvas');
|
||||
|
||||
width = div.attributes.width ? div.attributes.width.value : 640;
|
||||
height = div.attributes.height ? div.attributes.height.value : 360;
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
@@ -58,6 +61,24 @@
|
||||
socket.onmessage = handleNalUnits;
|
||||
};
|
||||
|
||||
NS.prototype.getImageData = function (rgbaData) {
|
||||
var gl = webGLCanvas.gl;
|
||||
|
||||
gl.readPixels(
|
||||
0, 0, width, height,
|
||||
gl.RGBA, gl.UNSIGNED_BYTE,
|
||||
rgbaData
|
||||
);
|
||||
// WebGL returns pixels upside down.
|
||||
// Instead of wasting time by vertically flipping it now,
|
||||
// we just leave it like it is and invert the coordinates later:
|
||||
return;
|
||||
};
|
||||
|
||||
NS.prototype.getCanvas = function () {
|
||||
return webGLCanvas.canvas;
|
||||
};
|
||||
|
||||
window.NodecopterStream = NS;
|
||||
|
||||
}(window, document, undefined));
|
||||
@@ -0,0 +1,156 @@
|
||||
/*jshint browser:true */
|
||||
/*global jsfeat:true console:true */
|
||||
(function (window, document, undefined) {
|
||||
'use strict';
|
||||
var NodecopterTrack,
|
||||
lastTime;
|
||||
|
||||
function schedule (callback, element) {
|
||||
var requestAnimationFrame =
|
||||
window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function(callback, element) {
|
||||
var currTime = new Date().getTime(),
|
||||
timeToCall = Math.max(0, 16 - (currTime - lastTime)),
|
||||
id = window.setTimeout(function() {
|
||||
callback(currTime + timeToCall);
|
||||
}, timeToCall);
|
||||
lastTime = currTime + timeToCall;
|
||||
return id;
|
||||
};
|
||||
|
||||
return requestAnimationFrame.call(window, callback, element);
|
||||
}
|
||||
|
||||
|
||||
var relMouseCoords = function (event) {
|
||||
var totalOffsetX = 0,
|
||||
totalOffsetY = 0,
|
||||
canvasX = 0,
|
||||
canvasY = 0,
|
||||
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};
|
||||
};
|
||||
|
||||
|
||||
NodecopterTrack = function (copterStream, imgId) {
|
||||
var tracker = this;
|
||||
this.curr_img_pyr = new jsfeat.pyramid_t(3);
|
||||
this.prev_img_pyr = new jsfeat.pyramid_t(3);
|
||||
this.point_count = 0;
|
||||
this.point_status = new Uint8Array(1);
|
||||
this.prev_xy = new Float32Array(2);
|
||||
this.curr_xy = new Float32Array(2);
|
||||
this.copterStream = copterStream;
|
||||
this.canvas = copterStream.getCanvas();
|
||||
this.rgbaData = new Uint8Array(
|
||||
this.canvas.width * this.canvas.height * 4
|
||||
); // RGBA
|
||||
this.crosshairs = document.querySelector(imgId);
|
||||
|
||||
this.curr_img_pyr.allocate(
|
||||
this.canvas.width, this.canvas.height, jsfeat.U8_t | jsfeat.C1_t
|
||||
);
|
||||
this.prev_img_pyr.allocate(
|
||||
this.canvas.width, this.canvas.height, jsfeat.U8_t | jsfeat.C1_t
|
||||
);
|
||||
|
||||
this.canvas.addEventListener('click', function(event) {
|
||||
tracker.canvasClickHandler(event);
|
||||
}, false);
|
||||
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;
|
||||
// this.canvas.prototype.relMouseCoords = relMouseCoords;
|
||||
|
||||
this.update();
|
||||
};
|
||||
|
||||
NodecopterTrack.prototype.update = function () {
|
||||
var _pt_xy, _pyr,
|
||||
tracker = this;
|
||||
|
||||
schedule(function () {
|
||||
tracker.update();
|
||||
});
|
||||
|
||||
if (! this.point_count) {
|
||||
this.crosshairs.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
_pt_xy = this.prev_xy;
|
||||
_pyr = this.prev_img_pyr;
|
||||
|
||||
this.prev_xy = this.curr_xy;
|
||||
this.curr_xy = _pt_xy;
|
||||
|
||||
this.prev_img_pyr = this.curr_img_pyr;
|
||||
this.curr_img_pyr = _pyr; // reuse old pyramid data structure
|
||||
|
||||
this.copterStream.getImageData(this.rgbaData);
|
||||
jsfeat.imgproc.grayscale(
|
||||
this.rgbaData,
|
||||
this.curr_img_pyr.data[0].data
|
||||
);
|
||||
|
||||
// optional: enhance contrast:
|
||||
jsfeat.imgproc.equalize_histogram(
|
||||
this.curr_img_pyr.data[0].data,
|
||||
this.curr_img_pyr.data[0].data
|
||||
);
|
||||
|
||||
this.curr_img_pyr.build(this.curr_img_pyr.data[0], true);
|
||||
|
||||
jsfeat.optical_flow_lk.track(
|
||||
this.prev_img_pyr,
|
||||
this.curr_img_pyr,
|
||||
this.prev_xy,
|
||||
this.curr_xy,
|
||||
1,
|
||||
50, // win_size
|
||||
30, // max_iterations
|
||||
this.point_status,
|
||||
0.01, // epsilon,
|
||||
0.001 // min_eigen
|
||||
);
|
||||
|
||||
if (this.point_status[0] == 1) {
|
||||
this.crosshairs.style.left = (this.curr_xy[0] - 83) + 'px';
|
||||
this.crosshairs.style.top = (
|
||||
this.canvas.height - 83 - this.curr_xy[1]
|
||||
) + 'px';
|
||||
this.crosshairs.style.display = 'block';
|
||||
} else {
|
||||
this.point_count = 0;
|
||||
console.log('lost target');
|
||||
}
|
||||
};
|
||||
|
||||
NodecopterTrack.prototype.canvasClickHandler = function (e) {
|
||||
var coords = this.canvas.relMouseCoords(e);
|
||||
if (
|
||||
(coords.x > 0) &&
|
||||
(coords.y > 0) &&
|
||||
(coords.x < this.canvas.width) &&
|
||||
(coords.y < this.canvas.height)
|
||||
) {
|
||||
this.curr_xy[0] = coords.x;
|
||||
this.curr_xy[1] = this.canvas.height - coords.y;
|
||||
this.point_count = 1;
|
||||
}
|
||||
console.log('Click:', coords);
|
||||
};
|
||||
|
||||
window.NodecopterTrack = NodecopterTrack;
|
||||
|
||||
}(window, document, undefined));
|
||||
@@ -337,7 +337,7 @@ var WebGLCanvas = (function () {
|
||||
},
|
||||
onInitWebGL: function () {
|
||||
try {
|
||||
this.gl = this.canvas.getContext("experimental-webgl");
|
||||
this.gl = this.canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});
|
||||
} catch(e) {}
|
||||
|
||||
if (!this.gl) {
|
||||
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -0,0 +1,22 @@
|
||||
extends layout
|
||||
|
||||
block append head
|
||||
script(type='text/javascript', src='/js/vendor/broadway/sylvester.js')
|
||||
script(type='text/javascript', src='/js/vendor/broadway/glUtils.js')
|
||||
script(type='text/javascript', src='/js/vendor/broadway/util.js')
|
||||
script(type='text/javascript', src='/js/vendor/broadway/avc-codec.js')
|
||||
script(type='text/javascript', src='/js/vendor/broadway/avc.js')
|
||||
script(type='text/javascript', src='/js/vendor/broadway/canvas.js')
|
||||
script(type='text/javascript', src='/js/vendor/jsfeat/jsfeat-min.js')
|
||||
script(type='text/javascript', src='/js/nodecopter-stream.js')
|
||||
script(type='text/javascript', src='/js/nodecopter-track.js')
|
||||
|
||||
block append bodyscripts
|
||||
script
|
||||
'use strict';
|
||||
var copterStream = new NodecopterStream(document.querySelector('#dronestream'));
|
||||
var tracker = new NodecopterTrack(copterStream, '#sniper');
|
||||
|
||||
block content
|
||||
div#dronestream(width=640, height=360, style="position:relative")
|
||||
img#sniper(src="images/sniper.png", style="position:absolute; opacity:0.6")
|
||||
@@ -7,6 +7,7 @@ html
|
||||
title= title
|
||||
link(rel='stylesheet', href='/css/normalize.min.css')
|
||||
link(rel='stylesheet', href='/css/style.css')
|
||||
script(src='/js/vendor/h5bp/modernizr-2.6.1-respond-1.1.0.min.js')
|
||||
body
|
||||
div.header-container
|
||||
header.wrapper.clearfix
|
||||
Referência em uma Nova Issue
Bloquear um usuário