Skip to content

Commit

Permalink
Merge github.com:talvarez/node-opencv
Browse files Browse the repository at this point in the history
Conflicts:
	src/Matrix.cc
	src/Matrix.h
  • Loading branch information
alvarezgarcia committed Jun 19, 2012
2 parents efbae5b + a030813 commit 4d1ea28
Show file tree
Hide file tree
Showing 58 changed files with 847 additions and 184 deletions.
Empty file modified .gitignore
100644 → 100755
Empty file.
Empty file modified .travis.yml
100644 → 100755
Empty file.
Empty file modified README.md
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion TODO
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ cv.loadImage('test.jpg', function(err, im){

http://www.athile.net/library/wiki/index.php?title=Library/V8/Tutorial#Wrapping_a_Javascript_function_as_a_std::function.3C.3E

https://www.cloudkick.com/blog/2010/aug/23/writing-nodejs-native-extensions/
https://www.cloudkick.com/blog/2010/aug/23/writing-nodejs-native-extensions/
Empty file modified binding.gyp
100644 → 100755
Empty file.
6 changes: 6 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

node-waf configure build &&
cd examples &&
#node face_detection.js
node $1
Empty file modified data/haarcascade_eye.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_eye_tree_eyeglasses.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_frontalface_alt.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_frontalface_alt2.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_frontalface_alt_tree.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_frontalface_default.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_fullbody.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_lefteye_2splits.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_lowerbody.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_mcs_eyepair_big.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_mcs_eyepair_small.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_mcs_lefteye.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_mcs_mouth.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_mcs_nose.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_mcs_righteye.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_mcs_upperbody.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_profileface.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_righteye_2splits.xml
100644 → 100755
Empty file.
Empty file modified data/haarcascade_upperbody.xml
100644 → 100755
Empty file.
61 changes: 61 additions & 0 deletions doc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Examples
Face Detection

cv.readImage("./examples/test.jpg", function(err, im){
im.detectObject("./examples/haarcascade_frontalface_alt.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.jpg');

});
})

API Documentation
Matrix

The matrix is the most useful base datastructure in OpenCV. Things like images are just matrices of pixels.
Creation

new Matrix(width, height)

Or you can use opencv to read in image files. Supported formats are in the OpenCV docs, but jpgs etc are supported.

cv.readImage(filename, function(mat){
...
})

cv.readImage(buffer, function(mat){
...
})

If you need to pipe data into an image, you can use an imagestream:

var s = new cv.ImageStream()

s.on('load', function(matrix){
...
})

fs.createReadStream('./examples/test.jpg').pipe(s);

Accessors

var mat = new cv.Matrix.Eye(4,4); // Create identity matrix

mat.get(0,0) // 1

mat.row(0) // [1,0,0,0]
mat.col(4) // [0,0,0,1]

Image Processing
Object Detection

There is a shortcut method for Viola-Jones Haar Cascade object detection. This can be used for face detection etc.

mat.detectObject(haar_cascade_xml, opts, function(err, matches){})

WIP

This is a WIP. I've never written C++ before so the code may be interesting - if I'm doing stuff wrong please feel free to correct me.
16 changes: 16 additions & 0 deletions examples/addweighted.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
var cv = require('../lib/opencv');


cv.readImage("./mona.png", function(err, orig) {

cv.readImage("./over_text.png", function(err, over_text) {

var result = new cv.Matrix(orig.width(), orig.height());

result.addWeighted(orig, 0.7, over_text, 0.9);
result.save("/tmp/weighted.png");
});

});


13 changes: 13 additions & 0 deletions examples/camera.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var cv = require('../lib/opencv');

var camera = new cv.VideoCapture(0);


setInterval(function() {

camera.read(function(im) {

im.save('/tmp/cam.png');
});

}, 1000);
36 changes: 36 additions & 0 deletions examples/contours.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
var cv = require('../lib/opencv');

var lowThresh = 0;
var highThresh = 100;
var nIters = 2;
var maxArea = 2500;

var GREEN = [0, 255, 0]; //B, G, R
var WHITE = [255, 255, 255]; //B, G, R


cv.readImage('./stuff.png', function(err, im) {

var big = new cv.Matrix(im.width(), im.height());
var all = new cv.Matrix(im.width(), im.height());

im.convertGrayscale();
im_canny = im.copy();

im_canny.canny(lowThresh, highThresh);
im_canny.dilate(nIters);

contours = im_canny.findContours();

for(i = 0; i < contours.size(); i++) {
if(contours.area(i) > maxArea) {
big.drawContour(contours, i, GREEN);
}
}

all.drawAllContours(contours, WHITE);


big.save('/tmp/big.png');
all.save('/tmp/all.png');
});
18 changes: 18 additions & 0 deletions examples/convert_image.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var cv = require('../lib/opencv');


cv.readImage("./mona.png", function(err, im) {

img_hsv = im.copy();
img_gray = im.copy();

img_hsv.convertHSVscale();
img_gray.convertGrayscale();

im.save("/tmp/nor.png");
img_hsv.save("/tmp/hsv.png");
img_gray.save("/tmp/gray.png");

console.log("Guardado");
});

Empty file modified examples/face-proxy.js
100644 → 100755
Empty file.
18 changes: 18 additions & 0 deletions examples/face_detection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var cv = require('../lib/opencv')
, assert = require('assert')
, fs =require('fs')


//console.log(cv.version)
cv.readImage("./mona.png", function(err, im){

im.detectObject("./haarcascade_frontalface_alt.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');
});
});
Binary file removed examples/mona.jpg
Binary file not shown.
Binary file added examples/mona.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/over_text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions examples/salt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
var cv = require('../lib/opencv');


cv.readImage("./mona.png", function(err, im) {
salt(im, 3000);
im.save("/tmp/salt.png");
});



function salt(img, n) {


if (img.channels() == 1) {

console.log("1 Canales");
} else if (img.channels() == 3) {

for(k = 0; k < n; k ++) {
i = Math.random() * img.width();
j = Math.random() * img.height();

img.set(j, i, 255);
}
}

}
Binary file added examples/stuff.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified index.html
100644 → 100755
Empty file.
Empty file modified lib/bindings.js
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion lib/opencv.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var Stream = require('stream').Stream
, Buffers = require('buffers')
, Buffers = require('buffer')
, util = require('util');

var bindings = require('./bindings')
Expand Down
Empty file modified package.json
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion smoketest.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ var cv = require('./lib/opencv')
im.save('./out.jpg');

});
})
})
39 changes: 24 additions & 15 deletions src/CascadeClassifierWrap.cc
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "Matrix.h"


void AsyncDetectMultiScale(uv_work_t *req);
void AfterAsyncDetectMultiScale(uv_work_t *req);

Persistent<FunctionTemplate> CascadeClassifierWrap::constructor;

Expand Down Expand Up @@ -61,6 +63,8 @@ struct classifier_baton_t {
int minh;
int sleep_for;
std::vector<cv::Rect> res;

uv_work_t request;
};


Expand Down Expand Up @@ -102,42 +106,47 @@ CascadeClassifierWrap::DetectMultiScale(const v8::Arguments& args){
baton->minw = minw;
baton->minh = minh;
baton->sleep_for = 1;
self->Ref();
baton->request.data = baton;
// self->Ref();

// eio_custom(EIO_DetectMultiScale, EIO_PRI_DEFAULT, EIO_AfterDetectMultiScale, baton);
// ev_ref(EV_DEFAULT_UC);

eio_custom(EIO_DetectMultiScale, EIO_PRI_DEFAULT, EIO_AfterDetectMultiScale, baton);
ev_ref(EV_DEFAULT_UC);
uv_queue_work(uv_default_loop(), &baton->request, AsyncDetectMultiScale, AfterAsyncDetectMultiScale);

return Undefined();


}


void
CascadeClassifierWrap::EIO_DetectMultiScale(eio_req *req){
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);

sleep(baton->sleep_for);
void AsyncDetectMultiScale(uv_work_t *req) {
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);

// sleep(baton->sleep_for);

std::vector<cv::Rect> objects;

cv::Mat gray;

cvtColor( baton->im->mat, gray, CV_BGR2GRAY );
equalizeHist( gray, gray);
if(baton->im->mat.channels() != 1)
cvtColor(baton->im->mat, gray, CV_BGR2GRAY);


equalizeHist( gray, gray);
baton->cc->cc.detectMultiScale(gray, objects, baton->scale, baton->neighbors, 0, cv::Size(baton->minw, baton->minh));

baton->res = objects;


}

int
CascadeClassifierWrap::EIO_AfterDetectMultiScale(eio_req *req){
void AfterAsyncDetectMultiScale(uv_work_t *req) {

HandleScope scope;
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);
ev_unref(EV_DEFAULT_UC);
baton->cc->Unref();
// ev_unref(EV_DEFAULT_UC);
// baton->cc->Unref();

Local<Value> argv[2];

Expand Down Expand Up @@ -169,6 +178,6 @@ CascadeClassifierWrap::EIO_AfterDetectMultiScale(eio_req *req){

delete baton;

return 0;
// return 0;
}

2 changes: 1 addition & 1 deletion src/CascadeClassifierWrap.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ class CascadeClassifierWrap: public node::ObjectWrap {
static void EIO_DetectMultiScale(eio_req *req);
static int EIO_AfterDetectMultiScale(eio_req *req);

};
};
73 changes: 73 additions & 0 deletions src/Contours.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "Contours.h"
#include "OpenCV.h"

#include <iostream>

v8::Persistent<FunctionTemplate> Contour::constructor;


void
Contour::Init(Handle<Object> target) {
HandleScope scope;

//Class
v8::Local<v8::FunctionTemplate> m = v8::FunctionTemplate::New(New);
m->SetClassName(v8::String::NewSymbol("Contours"));

// Constructor
constructor = Persistent<FunctionTemplate>::New(m);
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("Contours"));

// Prototype
Local<ObjectTemplate> proto = constructor->PrototypeTemplate();


NODE_SET_PROTOTYPE_METHOD(constructor, "size", Size);
NODE_SET_PROTOTYPE_METHOD(constructor, "area", Area);
target->Set(String::NewSymbol("Contours"), m->GetFunction());
};


Handle<Value>
Contour::New(const Arguments &args) {
HandleScope scope;

if (args.This()->InternalFieldCount() == 0)
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot instantiate without new")));

Contour *contours;
contours = new Contour;

contours->Wrap(args.Holder());
return scope.Close(args.Holder());
}


Contour::Contour(): ObjectWrap() {
}


Handle<Value>
Contour::Size(const Arguments &args) {
HandleScope scope;

Contour *self = ObjectWrap::Unwrap<Contour>(args.This());

return scope.Close(Number::New(self->contours.size()));

}


Handle<Value>
Contour::Area(const Arguments &args) {
HandleScope scope;

Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();

//return scope.Close(Number::New(contourArea(self->contours)));
return scope.Close(Number::New(contourArea(cv::Mat(self->contours[pos]))));


}
Loading

0 comments on commit 4d1ea28

Please sign in to comment.