Node.js and OpenCV - javascript

I am having trouble getting face tracking and detection from the npm opencv package. I'm currently just trying to drawing a circle each face.
I have listed below the error and the files below that. I'm not sure if its just a binding issue, if so what steps should I take to resolve it.
OpenCV (2.4.8.2) was installed via brew FYI - It could be a versions thing I guess
Error:
/Users/gwilliams2/Sites/facetracking/node_modules/opencv/lib/opencv.js:29
var face_cascade = new cv.CascadeClassifier(classifier);
^
TypeError: Error loading file
at Matrix.matrix.detectObject (/Users/gwilliams2/Sites/facetracking/node_modules/opencv/lib/opencv.js:29:23)
at /Users/gwilliams2/Sites/facetracking/server.js:170:8
at Socket.<anonymous> (/Users/gwilliams2/Sites/facetracking/server.js:161:11)
at Socket.EventEmitter.emit [as $emit] (events.js:95:17)
at SocketNamespace.handlePacket (/Users/gwilliams2/Sites/facetracking/node_modules/socket.io/lib/namespace.js:335:22)
at Manager.onClientMessage (/Users/gwilliams2/Sites/facetracking/node_modules/socket.io/lib/manager.js:488:38)
at WebSocket.Transport.onMessage (/Users/gwilliams2/Sites/facetracking/node_modules/socket.io/lib/transport.js:387:20)
at Parser.<anonymous> (/Users/gwilliams2/Sites/facetracking/node_modules/socket.io/lib/transports/websocket/hybi-16.js:39:10)
at Parser.EventEmitter.emit (events.js:95:17)
at finish (/Users/gwilliams2/Sites/facetracking/node_modules/socket.io/lib/transports/websocket/hybi-16.js:288:16)
client.js
var APP = {
// setup the web socket
socket: io.connect('http://gaz.local:3000'),
video: null,
canvas: null,
imgData: null,
init: function (){
// get elements
APP.video = $('#myVideo')[0];
APP.canvas = $('#myCanvas')[0];
// start app
APP.main();
},
main: function(){
// if we can get a webcam
if(APP.hasGetUserMedia()){
navigator.webkitGetUserMedia(
{video:true, audio:false},
APP.videoSuccess,
APP.videoError
);
} else {
alert('Sorry, you do not have webcam access');
}
},
hasGetUserMedia: function (){
return !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
},
videoSuccess: function (stream){
// set the video to stream
APP.video.src = window.URL.createObjectURL(stream);
// set canvas size
APP.canvas.width = APP.video.width;
APP.canvas.height = APP.video.height;
// draw video
var i = 0;
setTimeout(function(){
// darw the image to the canvas
APP.canvas.getContext('2d').drawImage(APP.video, 0, 0);
APP.imgData = APP.canvas.toDataURL('image/jpeg');
APP.imgData = APP.imgData.replace('data:image/jpeg;base64,', '');
// send the file in json format to the server
var jsonData = JSON.stringify({imgData: APP.imgData, count: i});
APP.socket.emit('update', jsonData);
// APP.socket.on('put_down', function (data) {
// console.log(data);
// });
// update the counter
i++;
}, 50);
},
videoError: function (err){
alert('Error: ' + err);
},
};
$(function (){ APP.init(); });
Server.js
/*
Setup a server, RTC and face tracking
Install opencv
brew install opencv
NPM
https://www.npmjs.org/package/fs
https://www.npmjs.org/package/http
https://www.npmjs.org/package/express
https://www.npmjs.org/package/socket.io
https://www.npmjs.org/package/opencv
*/
var APP = {
// include some scripts
server: null,
port: 3000,
express: require('express'),
app: null,
mdb: require('mongodb'),
dbUrl: 'mongodb://127.0.0.1:27017/test',
db: null,
io: null,
cv: require('opencv'),
fs: require("fs"),
init: function (){
// connect stuff up
APP.app = APP.express();
APP.server = require('http').createServer(APP.app).listen(APP.port, '0.0.0.0');
APP.io = require('socket.io').listen(APP.server);
// http routing
APP.routing();
// connect the websocket
APP.io.on('connection', function (socket){
console.log('Server started on port ' + APP.port);
APP.main(socket);
});
},
// open the db
openDB: function (){
APP.mdb.connect(APP.dbURL, function(err, db){
if(err)
throw err;
APP.db = db;
});
},
// close the db
closeDB: function (){
APP.db.close();
},
// insert a file to the db
dbInsert: function (col, data){
// open the db
APP.openDB();
var collection = APP.db.collection(col);
collection.insert(data, function(err, docs){
if(err){
console.warn(err.message);
} else {
console.log('Successfully inserted record');
}
});
// close the db
APP.closeDB();
},
// insert a file to the db
dbUpdate: function (col, crit, data){
// open the db
APP.openDB();
var collection = APP.db.collection(col);
collection.update(crit, {$set: {hi: 'there'}}, {w:1}, function (){
if(err){
console.warn(err.message);
} else {
console.log('Successfully updated record');
}
});
// close the db
APP.closeDB();
},
// find a file in the db
dbFind: function (col){
// open the db
APP.openDB();
var collection = APP.db.collection(col);
collection.find().toArray(function(err, results) {
console.dir(results);
});
// close the db
APP.closeDB();
},
// routing files
routing: function (){
// set directory to use for files prefixed with /library
APP.app.use('/library', APP.express.static(__dirname + '/library'));
// index page
APP.app.get('/*', function (req, res){
// get query
// console.log(req.query);
// get file
res.sendfile(__dirname + '/' + req.route.params);
});
},
main: function (socket){
// APP.io.sockets.emit('put_down', {'fingers': 's'});
socket.on('update', function (data) {
// console.log(data);
// get the data
data = JSON.parse(data);
// create the file
var filename = 'file' + data.count + '.jpg';
APP.fs.writeFile(filename, data.imgData, 'base64', function(err) {
if(err)
console.log(err);
});
// open file with open cv
APP.cv.readImage(filename, function(err, im){
// handle errors
if(err)
return err;
console.log(im);
// /Users/gwilliams2/Sites/facetracking/node_modules/opencv/data/haarcascade_frontalface_default.xml
im.detectObject('./haarcascade_frontalface_default.xml', {}, function(err, faces){
for (var i=0;i<faces.length; i++){
var x = faces[i];
im.ellipse(x.x + x.width/2, x.y + x.height/2, x.width/2, x.height/2);
}
im.save('./out.png');
});
});
});
}
};
// run the script
APP.init();

Solved, firstly, I had linked to the xml file incorrectly, as the path was incorrect as suggested in the comments above. I then noticed the buffer for the open file had been close. Since everything is asynchronous, the code in the server for analysing the file needs to be nested in the file saving callback.

Related

Can't Get The Php Variable To My Node Js using npm: exec-php module

Following is the Server.js File, here I am Fetching The Details From Table which working Good. I need to Get a Variable From k.php which is in the Same Folder.Iam using npm exec-php module to get the Values From Php File. But The Variable is Showing Undefined.
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs'),
express=require('express'),
session=require('express-session'),
mysql = require('mysql'),
execPhp = require('exec-php'),
connectionsArray = [],
connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'test',
port: 3306
}),
POLLING_INTERVAL = 3000,
pollingTimer;
// If there is an error connecting to the database
connection.connect(function(err) {
// connected! (unless `err` is set)
if (err) {
console.log(err);
}
});
// creating the server ( localhost:8000 )
app.listen(8000);
// on server started we can load our client.html page
function handler(req, res) {
fs.readFile(__dirname + '/client.php', function(err, data) {
if (err) {
console.log(err);
res.writeHead(500);
return res.end('Error loading client.php');
}
res.writeHead(200);
res.end(data);
});
}
execPhp('k.php', function(error, php, outprint){
// Here I expected The outprint Will be 'One' but it print undefined
console.log(outprint);
php.my_function(1, 2, function(err, result, output, printed){
//this my_function is also showing Error
});
});
var pollingLoop = function() {
// Doing the database query
var query = connection.query('SELECT * FROM users where user_id=1'),
users = []; // this array will contain the result of our db query
// setting the query listeners
query
.on('error', function(err) {
// Handle error, and 'end' event will be emitted after this as well
console.log(err);
updateSockets(err);
})
.on('result', function(user) {
// it fills our array looping on each user row inside the db
users.push(user);
})
.on('end', function() {
// loop on itself only if there are sockets still connected
if (connectionsArray.length) {
pollingTimer = setTimeout(pollingLoop, POLLING_INTERVAL);
updateSockets({
users: users
});
} else {
console.log('The server timer was stopped because there are no more socket connections on the app')
}
});
};
// creating a new websocket to keep the content updated without any AJAX request
io.sockets.on('connection', function(socket) {
console.log('Number of connections:' + connectionsArray.length);
// starting the loop only if at least there is one user connected
if (!connectionsArray.length) {
pollingLoop();
}
socket.on('disconnect', function() {
var socketIndex = connectionsArray.indexOf(socket);
console.log('socketID = %s got disconnected', socketIndex);
if (~socketIndex) {
connectionsArray.splice(socketIndex, 1);
}
});
console.log('A new socket is connected!');
connectionsArray.push(socket);
});
var updateSockets = function(data) {
// adding the time of the last update
data.time = new Date();
console.log('Pushing new data to the clients connected ( connections amount = %s ) - %s', connectionsArray.length , data.time);
// sending new data to all the sockets connected
connectionsArray.forEach(function(tmpSocket) {
tmpSocket.volatile.emit('notification', data);
});
};
console.log('Please use your browser to navigate to http://localhost:8000');
the main Problem is in these Lines
execPhp('k.php', function(error, php, outprint){
// Here I expected The outprint Will be 'One' but it print undefined
console.log(outprint);
php.my_function(1, 2, function(err, result, output, printed){
//this my_function is also showing Error
});
});
The Following is k.php in the same folder
<?php
echo "One";
function my_function($arg1, $arg2){
echo "Two";
return $arg1 + $arg2;
}
?>
This is the Error

Unable to connect with SQL Server using Node.js

I have created an application using Node.js to connect with SQL Server. Below is the code:
app.get('/SalesStatistics', function (req, res) {
var Connection = require('tedious').Connection;
// config for your database
var config = {
user: "****",
password: "*****",
server: "abc",
database: "xyz"
};
var connection = new Connection(config);
connection.on('connect', function (err) {
// If no error, then good to proceed.
console.log("Connected");
executeStatement();
});
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
function executeStatement() {
request = new Request("select * from employee;", function (err) {
if (err) {
console.log(err);
}
});
var result = "";
request.on('row', function (columns) {
columns.forEach(function (column) {
if (column.value === null) {
console.log('NULL');
} else {
result += column.value + " ";
}
});
console.log(result);
result = "";
});
request.on('done', function (rowCount, more) {
console.log(rowCount + ' rows returned');
});
connection.execSql(request);
}
});
Received the below error in console:
message: 'Requests can only be made in the LoggedIn state, not the Connecting state'
code: EIINVALIDSTATE
Also tried the sample from Github site, but still I could not connect to SQL Server. Please let me know if any other possibility.
I just encountered the same problem awhile ago running the same code above with similar environment.
It turn out that I did not configure the sql server (using Sql Server Management Manager) to accept TCP connection to port (1433). After I done that, everything work fine.

display ssh2 stdout and stderr in textarea

I'm building a node.js application to manage servers.
In this application, I can create some shell scripts and execute them on a server by clicking on a button.
Here is what I have in my routes.js file for this action :
app.get('/exec', isLoggedIn, function(req, res) {
var url = require('url');
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
var Server = require('../app/models/server');
var Script = require('../app/models/script');
var async = require('async');
var scriptId = query.scriptId;
var userId = query.userId;
var serverId = query.serverId;
var stdout = "";
var stderr = "";
async.parallel({
servers: function(callback){
Server.find({"_id" : serverId}).exec(callback);
},
scripts: function(callback){
Script.find({"_id" : scriptId}).exec(callback);
}
}, function(err, results) {
if (err)
res.send(err);
var selectedServer = results.servers;
var selectedScript = results.scripts;
var serverIp = selectedServer[0].serverDetails.serverAddress;
var serverPort = selectedServer[0].serverDetails.serverPort;
var serverUsername = selectedServer[0].serverDetails.serverUsername;
var scriptContent = selectedScript[0].scriptDetails.scriptContent;
var Connection = require('ssh2');
var conn = new Connection();
conn.on('ready', function() {
//console.log('Connection :: ready');
conn.exec(scriptContent, function(err, stream) {
if (err) throw err;
stream.on('exit', function(code, signal) {
//console.log('Stream :: exit :: code: ' + code + ', signal: ' + signal);
}).on('close', function() {
//console.log('Stream :: close');
conn.end();
}).on('data', function(data_out) {
console.log('STDOUT: \n' + data_out);
stdout = stdout + data_out;
res.render('execresults.ejs', {
stdout : stdout
});
}).stderr.on('data', function(data_err) {
console.log('STDERR: \n' + data_err);
});
});
}).connect({
host: serverIp,
port: serverPort,
username: serverUsername,
privateKey: require('fs').readFileSync('id_rsa')
});
conn.on('error', function(e) { console.log("Connection failed or timed out")});
});
});
It works fine and I have the results of the execution in the console. But I would like to display both stdout and stderr results in two textarea of an ejs page.
The problem is that when I run a simple command like "uptime", it works, I will have the stdout result displayed in my textarea.
But when the shell script returns both stdout and stderr, or if stdout is a large amount of text, I don't have everything passed to my ejs page because of this error I think : Error: Can't set headers after they are sent.
My question is : How can I send both stdout and stderr to my ejs page, only when the script is completely executed ? I tried to build a "stdout" variable by concatenating all stdout output but it doesn't seem to work...
Can someone help me ?
thanks a lot
Assuming the process eventually ends on its own and it does not output a lot of data, you could probably just buffer the data and then render when the process closes:
conn.exec(scriptContent, function(err, stream) {
if (err)
return res.send(err);
var stdout = '',
stderr = '';
stream.on('close', function() {
conn.end();
res.render('execresults.ejs', {
stdout: stdout,
stderr: stderr
});
}).on('data', function(data) {
stdout += data;
}).stderr.on('data', function(data) {
stderr += data;
});
});
Secondly,
if (err)
res.send(err);
should really have a return:
if (err)
return res.send(err);
to prevent further execution on errors.

Storing data stream from POST request in GridFS, express, mongoDB, node.js

I am trying to figure out how I can post an image directly to GridFS without storing it anywhere on the server as a temporary file first.
I am using Postman (chrome ext.) to post a file, and I manage to store this post as a file using:
req.pipe(fs.createWriteStream('./test.png'));
I am also able to store directly to GridFS from a readStream when the readStream is created from a file on the server. (see code)
I have the following files, saveFromReq.js which listens for the POST and basically just passes this on to the savePic.js.
saveFromReq.js:
var express = require('express');
var app = express();
var savePic = require('./savePic');
var fs = require('fs');
var GridStore = require('mongodb').GridStore;
var pic = './square.png';
var picID;
//When the following
//var pic = fs.createReadStream('./square.png', {autoClose: true});
//is not commented out, and 'req' is replaced with 'pic' in the savePic function,
//the file square.png is stored correctly to GridFS
app.post('/picture', function(req, res){
savePic(req, function(id){});
res.writeHead(200, {'Content-Type': 'text' });
res.end("Sucsess!\n");
});
app.listen(process.env.PORT || 3413);
savePic.js:
var savePic = function(req, callback){
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
ReplSetServers = require('mongodb').ReplSetServers,
ObjectID = require('mongodb').ObjectID,
Binary = require('mongodb').Binary,
GridStore = require('mongodb').GridStore,
Grid = require('mongodb').Grid,
Code = require('mongodb').Code,
BSON = require('mongodb').pure().BSON,
assert = require('assert');
fs = require('fs');
//When the following
//req.pipe(fs.createWriteStream('./test.png'));
//is not commented out, the correct image is stored to test.png, and
//the sequence after req.on("data"... starts
//(That sequence does not start at all when this is commented out..)
var fileId = new ObjectID();
var db = new Db('testDB', new Server('localhost', 27017));
// Establish connection to db
db.open(function(err, db) {
var gridStore = new GridStore(db, 'test', 'w');
//open
gridStore.open(function(err, gridStore) {
console.log("opened");
req.on("data", function (data) {
console.log("data recieved");
gridStore.write(data, function (err, gridStore) {
if (err) {
console.log("error writing file");
}
});
});
req.on("end", function () {
gridStore.close(function (err, gridStore) {
if (!err) {
console.log("The file has been stored to database.");
db.close();
}
});
});
req.pipe(gridStore);
});
});
callback(fileId);
};
module.exports = savePic;
Any help would be greatly appreciated!
gridfs-stream makes that pretty easy:
// `gfs` is a gridfs-stream instance
app.post('/picture', function(req, res) {
req.pipe(gfs.createWriteStream({
filename: 'test'
}));
res.send("Success!");
});
while #robertklep's answer is correct, I would like to add something to his answer. This code shows how you can send back the stored file's metadata.
app.post('/picture', function(req, res) {
req.pipe(gfs.createWriteStream({
filename: 'test'
}).on('close', function(savedFile){
console.log('file saved', savedFile);
return res.json({file: savedFile});
}));
})
This worked for me with mongoose:
var gfs = Grid(mongoose.connection.db, mongoose.mongo);
var writeStream = gfs.createWriteStream({
filename: name,
mode: 'w',
content_type: 'video/mp4'
});
writeStream.on('close', function() {
console.log('close event');
});
fs.createReadStream('uploads/' + name + '/' + name + '.mp4').pipe(writeStream);
console.log('stream.write: ' + name + '/' + name + '.mp4');
I am struggling a couple of days with getting the video on client side browser. That is what I tried so far:
var readstream = gfs.createReadStream({
filename: file.filename
});
readstream.on('data', function(data) {
res.write(data);
console.log(data);
});
readstream.on('end', function() {
res.end();
});
readstream.on('error', function (err) {
console.log('An error occurred!', err);
throw err;
});
My Data on MongoDB side looks like:
db.fs.chunks.find()
{ "_id" : ObjectId("5757e76df14741bf0391aaca"), "files_id" : ObjectId("5757e76df14741bf0391aac8"), "n" : 0, "data" : BinData(0,"AAAAIGZ0eXBpc29....
And the contentType is 'video/mp4':
logging on browser side prints this:
Object { 0: "�", 1: "�", 2: "�", 3: " ", 4: "f", 5: "t", 6: "y", 7: "p", 8: "i", 9: "s", 85003 more… }
Could someone please save my live? I hope you do not see my post as not convenient in this place.
Complete code to insert the txtfile in mongodb using gridfs in nodejs.This works well `
var mongoose=require("mongoose");
var gridfsstream=require("gridfs-stream");
var fs=require("fs");
mongoose.connect("mongodb://localhost:27017/testimage");
var conn=mongoose.connection;
gridfsstream.mongo=mongoose.mongo;
conn.once("open",function()
{
console.log("database connected successfully");
var gfs=gridfsstream(conn.db);
var writestream=gfs.createWriteStream({
filename:"danger.txt"
});
fs.createReadStream("sivakasi.txt").pipe(writestream);
writestream.on("close",function(file)
{
console.log(file.filename +"stored successfully into mongodb using gridfs");
});
writestream.on("error",function(file)
{
console.log(file.filename +"not stored into mongodb using gridfs");
});
});
conn.on("error",function()
{
console.log("database not connected try again!!!");
});
`
complete code to post the image from html to nodejs store that image in mongodb using gridfs system and display that image in server.This code works well.
var express=require("express");
var bodyparser=require("body-parser");
var multer=require("multer");
var app=express();
var upload = multer({ dest: '/tmp/'});
app.use(bodyparser.urlencoded({extended:false}));
app.post("/uploadimage",upload.single("file"),function(request,response)
{
var mongoose=require("mongoose");
var gridfsstream=require("gridfs-stream");
var fs=require("fs");
mongoose.connect("mongodb://localhost:27017/testimage");
var con=mongoose.connection;
gridfsstream.mongo=mongoose.mongo;
con.once("open",function()
{
console.log("test image database connected successfully");
var gfs=gridfsstream(con.db);
var readstream=fs.createReadStream(request.file.originalname);
var writestream=gfs.createWriteStream({
filename:"mentorpicthree.jpg"
});
readstream.pipe(writestream);
writestream.on("close",function()
{
console.log("image stored in mongodb database successfully");
fs.readFile(request.file.originalname,function(err,data)
{
if(err)
{
response.writeHead(404,{"Content-Type":"text/plain"});
console.log("error");
}
else
{
response.writeHead(200,{"Content-Type":"image/jpg"});
response.end(data);
}
});
});
writestream.on("error",function()
{
console.log("image not stored in mongodb database");
});
});
con.on("error",function()
{
console.log("database not connected try again!!!");
});
});
app.listen(8086,function()
{
console.log("server running on port 8086");
});
<html>
<head>
<title>FILE UPLOAD</title>
</head>
<body>
<p>Ryan Dhal</p>
<form action="http://127.0.0.1:8086/uploadimage" method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<br>
<input type="submit" value="UPLOAD">
</form>
</body>
</html>

Expressjs: ENOENT when uploading image

I have written some middleware for uploading an avatar, like this:
var gm = require('gm'),
mkdirp = require('mkdirp'),
fs = require('fs');
uploadAvatar = function(req, res, next) {
var img, path, user;
if (req.files.avatar_image) {
user = req.user;
img = req.files.avatar_image;
path = __dirname + "/../../public/avatar/" + (user.name.parameterize()) + ".png";
mkdirp.sync(__dirname + "/../../public/avatar/");
fs.createReadStream(img.path).pipe(fs.createWriteStream(path));
gm(path).resize(250, 250).autoOrient().quality(90).write(path, function(err) {
if (err != null) {
req.flash('error', err);
} else {
user.avatar = "/avatar/" + (user.name.parameterize()) + ".png";
user.save(function(err) {
if (err != null) {
req.flash('error', err);
}
next();
});
}
});
} else {
next();
}
};
// Usage
app.post('/upload', ensureAuthenticated, uploadAvatar, handleUpload);
When I now try to upload an image, node crashed with the incredibly helpful error message:
events.js:72
throw er; // Unhandled 'error' event
^
Error: ENOENT, open '/tmp/1126846a248af5c584770b07de649f9b.png'
I have tried copying the file before using gm on it, too. I suspect that express deletes the file before I can even touch it, as a "security".
Can anyone help me here?
EDIT: Full source
First of all copy temp file to your avatar directory, and second make sure that you have permissions on avatar as well as temp directory and files.
As well piping read to write stream is not sync operation, and you will try to pipe straight after initialising read handle, that might lead to some problems.
You need to add events and wait till file get copied:
var complete = function(err) {
if (!err) {
// process your gm
} else {
console.log(err);
}
}
var read = fs.createReadStream(sourcePath);
read.on('error', function(err) {
complete(err);
});
var write = fs.createWriteStream(targetPath);
write.on('error', function(err) {
complete(err);
});
write.on('close', function() {
complete();
});
read.pipe(write);

Categories

Resources