Merge github.com:talvarez/node-opencv

Conflicts:
	src/Matrix.cc
	src/Matrix.h
Esse commit está contido em:
Tomas Alvarez
2012-06-19 14:53:52 -03:00
58 arquivos alterados com 844 adições e 181 exclusões
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
+1 -1
Ver Arquivo
@@ -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 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/
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo executável
+6
Ver Arquivo
@@ -0,0 +1,6 @@
#!/bin/bash
node-waf configure build &&
cd examples &&
#node face_detection.js
node $1
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo executável
+61
Ver Arquivo
@@ -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.
Arquivo executável
+16
Ver Arquivo
@@ -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");
});
});
Arquivo executável
+13
Ver Arquivo
@@ -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);
Arquivo executável
+36
Ver Arquivo
@@ -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');
});
Arquivo executável
+18
Ver Arquivo
@@ -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");
});
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo executável
+18
Ver Arquivo
@@ -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');
});
});
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 112 KiB

Arquivo executável
BIN
Ver Arquivo
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 518 KiB

Arquivo executável
BIN
Ver Arquivo
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 5.4 KiB

Arquivo executável
+27
Ver Arquivo
@@ -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);
}
}
}
Arquivo executável
BIN
Ver Arquivo
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 186 KiB

Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
+1 -1
Ver Arquivo
@@ -1,5 +1,5 @@
var Stream = require('stream').Stream var Stream = require('stream').Stream
, Buffers = require('buffers') , Buffers = require('buffer')
, util = require('util'); , util = require('util');
var bindings = require('./bindings') var bindings = require('./bindings')
Arquivo normal → Arquivo executável
Ver Arquivo
+1 -1
Ver Arquivo
@@ -14,4 +14,4 @@ var cv = require('./lib/opencv')
im.save('./out.jpg'); im.save('./out.jpg');
}); });
}) })
Arquivo normal → Arquivo executável
+24 -15
Ver Arquivo
@@ -3,6 +3,8 @@
#include "Matrix.h" #include "Matrix.h"
void AsyncDetectMultiScale(uv_work_t *req);
void AfterAsyncDetectMultiScale(uv_work_t *req);
Persistent<FunctionTemplate> CascadeClassifierWrap::constructor; Persistent<FunctionTemplate> CascadeClassifierWrap::constructor;
@@ -61,6 +63,8 @@ struct classifier_baton_t {
int minh; int minh;
int sleep_for; int sleep_for;
std::vector<cv::Rect> res; std::vector<cv::Rect> res;
uv_work_t request;
}; };
@@ -102,42 +106,47 @@ CascadeClassifierWrap::DetectMultiScale(const v8::Arguments& args){
baton->minw = minw; baton->minw = minw;
baton->minh = minh; baton->minh = minh;
baton->sleep_for = 1; baton->sleep_for = 1;
self->Ref(); baton->request.data = baton;
// self->Ref();
eio_custom(EIO_DetectMultiScale, EIO_PRI_DEFAULT, EIO_AfterDetectMultiScale, baton); // eio_custom(EIO_DetectMultiScale, EIO_PRI_DEFAULT, EIO_AfterDetectMultiScale, baton);
ev_ref(EV_DEFAULT_UC); // ev_ref(EV_DEFAULT_UC);
uv_queue_work(uv_default_loop(), &baton->request, AsyncDetectMultiScale, AfterAsyncDetectMultiScale);
return Undefined(); return Undefined();
} }
void void AsyncDetectMultiScale(uv_work_t *req) {
CascadeClassifierWrap::EIO_DetectMultiScale(eio_req *req){
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data); classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);
sleep(baton->sleep_for); // sleep(baton->sleep_for);
std::vector<cv::Rect> objects; std::vector<cv::Rect> objects;
cv::Mat gray; cv::Mat gray;
cvtColor( baton->im->mat, gray, CV_BGR2GRAY ); if(baton->im->mat.channels() != 1)
equalizeHist( gray, gray); 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->cc->cc.detectMultiScale(gray, objects, baton->scale, baton->neighbors, 0, cv::Size(baton->minw, baton->minh));
baton->res = objects; baton->res = objects;
} }
int void AfterAsyncDetectMultiScale(uv_work_t *req) {
CascadeClassifierWrap::EIO_AfterDetectMultiScale(eio_req *req){
HandleScope scope; HandleScope scope;
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data); classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);
ev_unref(EV_DEFAULT_UC); // ev_unref(EV_DEFAULT_UC);
baton->cc->Unref(); // baton->cc->Unref();
Local<Value> argv[2]; Local<Value> argv[2];
@@ -169,6 +178,6 @@ CascadeClassifierWrap::EIO_AfterDetectMultiScale(eio_req *req){
delete baton; delete baton;
return 0; // return 0;
} }
Arquivo normal → Arquivo executável
+1 -1
Ver Arquivo
@@ -16,4 +16,4 @@ class CascadeClassifierWrap: public node::ObjectWrap {
static void EIO_DetectMultiScale(eio_req *req); static void EIO_DetectMultiScale(eio_req *req);
static int EIO_AfterDetectMultiScale(eio_req *req); static int EIO_AfterDetectMultiScale(eio_req *req);
}; };
Arquivo executável
+73
Ver Arquivo
@@ -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]))));
}
Arquivo executável
+18
Ver Arquivo
@@ -0,0 +1,18 @@
#include "OpenCV.h"
class Contour: public node::ObjectWrap {
public:
cv::Mat mat;
vector<vector<cv::Point> > contours;
static Persistent<FunctionTemplate> constructor;
static void Init(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
Contour();
//JSFUNC(Size)
static Handle<Value> Size(const v8::Arguments&);
static Handle<Value> Area(const v8::Arguments&);
};
Arquivo normal → Arquivo executável
+383 -129
Ver Arquivo
@@ -1,162 +1,199 @@
#include "Contours.h"
#include "Matrix.h" #include "Matrix.h"
#include "OpenCV.h" #include "OpenCV.h"
v8::Persistent<FunctionTemplate> Matrix::constructor; v8::Persistent<FunctionTemplate> Matrix::constructor;
cv::Scalar setColor(Local<Object> objColor);
//
void void
Matrix::Init(Handle<Object> target) { Matrix::Init(Handle<Object> target) {
HandleScope scope; HandleScope scope;
//Class //Class
v8::Local<v8::FunctionTemplate> m = v8::FunctionTemplate::New(New); v8::Local<v8::FunctionTemplate> m = v8::FunctionTemplate::New(New);
m->SetClassName(v8::String::NewSymbol("Matrix")); m->SetClassName(v8::String::NewSymbol("Matrix"));
// Constructor // Constructor
constructor = Persistent<FunctionTemplate>::New(m); constructor = Persistent<FunctionTemplate>::New(m);
constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("Matrix")); constructor->SetClassName(String::NewSymbol("Matrix"));
// Prototype // Prototype
Local<ObjectTemplate> proto = constructor->PrototypeTemplate(); Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
NODE_SET_PROTOTYPE_METHOD(constructor, "row", Row); NODE_SET_PROTOTYPE_METHOD(constructor, "row", Row);
NODE_SET_PROTOTYPE_METHOD(constructor, "col", Col); NODE_SET_PROTOTYPE_METHOD(constructor, "col", Col);
NODE_SET_PROTOTYPE_METHOD(constructor, "pixelRow", PixelRow); NODE_SET_PROTOTYPE_METHOD(constructor, "pixelRow", PixelRow);
NODE_SET_PROTOTYPE_METHOD(constructor, "pixelCol", PixelCol); NODE_SET_PROTOTYPE_METHOD(constructor, "pixelCol", PixelCol);
NODE_SET_PROTOTYPE_METHOD(constructor, "empty", Empty); NODE_SET_PROTOTYPE_METHOD(constructor, "empty", Empty);
NODE_SET_PROTOTYPE_METHOD(constructor, "get", Get); NODE_SET_PROTOTYPE_METHOD(constructor, "get", Get);
NODE_SET_PROTOTYPE_METHOD(constructor, "set", Set); NODE_SET_PROTOTYPE_METHOD(constructor, "set", Set);
NODE_SET_PROTOTYPE_METHOD(constructor, "width", Width); NODE_SET_PROTOTYPE_METHOD(constructor, "width", Width);
NODE_SET_PROTOTYPE_METHOD(constructor, "height", Height); NODE_SET_PROTOTYPE_METHOD(constructor, "height", Height);
NODE_SET_PROTOTYPE_METHOD(constructor, "size", Size); NODE_SET_PROTOTYPE_METHOD(constructor, "size", Size);
NODE_SET_PROTOTYPE_METHOD(constructor, "toBuffer", ToBuffer); NODE_SET_PROTOTYPE_METHOD(constructor, "toBuffer", ToBuffer);
NODE_SET_PROTOTYPE_METHOD(constructor, "ellipse", Ellipse); NODE_SET_PROTOTYPE_METHOD(constructor, "ellipse", Ellipse);
NODE_SET_PROTOTYPE_METHOD(constructor, "save", Save); NODE_SET_PROTOTYPE_METHOD(constructor, "save", Save);
NODE_SET_PROTOTYPE_METHOD(constructor, "resize", Resize); NODE_SET_PROTOTYPE_METHOD(constructor, "resize", Resize);
NODE_SET_PROTOTYPE_METHOD(constructor, "channels", Channels);
NODE_SET_METHOD(constructor, "Eye", Eye); NODE_SET_PROTOTYPE_METHOD(constructor, "convertGrayscale", ConvertGrayscale);
NODE_SET_PROTOTYPE_METHOD(constructor, "convertHSVscale", ConvertHSVscale);
NODE_SET_PROTOTYPE_METHOD(constructor, "copy", Copy);
NODE_SET_PROTOTYPE_METHOD(constructor, "ptr", Ptr);
NODE_SET_PROTOTYPE_METHOD(constructor, "addWeighted", AddWeighted);
NODE_SET_PROTOTYPE_METHOD(constructor, "split", Split);
NODE_SET_PROTOTYPE_METHOD(constructor, "bla", Bla);
NODE_SET_PROTOTYPE_METHOD(constructor, "canny", Canny);
NODE_SET_PROTOTYPE_METHOD(constructor, "dilate", Dilate);
NODE_SET_PROTOTYPE_METHOD(constructor, "findContours", FindContours);
NODE_SET_PROTOTYPE_METHOD(constructor, "drawContour", DrawContour);
NODE_SET_PROTOTYPE_METHOD(constructor, "drawAllContours", DrawAllContours);
NODE_SET_METHOD(constructor, "Eye", Eye);
target->Set(String::NewSymbol("Matrix"), m->GetFunction()); target->Set(String::NewSymbol("Matrix"), m->GetFunction());
}; };
Handle<Value> Handle<Value>
Matrix::New(const Arguments &args) { Matrix::New(const Arguments &args) {
HandleScope scope; HandleScope scope;
if (args.This()->InternalFieldCount() == 0) if (args.This()->InternalFieldCount() == 0)
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot instantiate without new"))); return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot instantiate without new")));
Matrix *mat; Matrix *mat;
if (args.Length() == 0){ if (args.Length() == 0){
mat = new Matrix; mat = new Matrix;
} else if (args.Length() == 2 && args[0]->IsInt32() && args[1]->IsInt32()){ } else if (args.Length() == 2 && args[0]->IsInt32() && args[1]->IsInt32()){
mat = new Matrix(args[0]->IntegerValue(), args[1]->IntegerValue()); mat = new Matrix(args[0]->IntegerValue(), args[1]->IntegerValue());
} }
mat->Wrap(args.Holder());
return scope.Close(args.Holder()); mat->Wrap(args.Holder());
return scope.Close(args.Holder());
} }
Matrix::Matrix(): ObjectWrap() { Matrix::Matrix(): ObjectWrap() {
mat = cv::Mat(); mat = cv::Mat();
} }
Matrix::Matrix(int w, int h): ObjectWrap() { Matrix::Matrix(int w, int h): ObjectWrap() {
mat = cv::Mat(w, h, CV_32FC3); mat = cv::Mat(w, h, CV_32FC3);
//TODO:Parametrizar esto
//mat = cv::Mat(h, w, CV_8UC3);
} }
Handle<Value>
Handle<Value>
Matrix::Empty(const Arguments& args){ Matrix::Empty(const Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
return scope.Close(Boolean::New(self->mat.empty())); return scope.Close(Boolean::New(self->mat.empty()));
} }
Handle<Value> Handle<Value>
Matrix::Get(const Arguments& args){ Matrix::Get(const Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
int i = args[0]->IntegerValue(); int i = args[0]->IntegerValue();
int j = args[1]->IntegerValue(); int j = args[1]->IntegerValue();
return scope.Close(Number::New(self->mat.at<double>(i,j))); return scope.Close(Number::New(self->mat.at<double>(i,j)));
} }
Handle<Value> Handle<Value>
Matrix::Set(const Arguments& args){ Matrix::Set(const Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
int i = args[0]->IntegerValue(); int i = args[0]->IntegerValue();
int j = args[1]->IntegerValue(); int j = args[1]->IntegerValue();
double val = args[2]->NumberValue(); double val = args[2]->NumberValue();
self->mat.at<double>(i,j) = val; if(args.Length() == 4) {
self->mat.at<cv::Vec3b>(i,j)[args[3]->NumberValue()] = val;
return scope.Close(Undefined()); } else if(args.Length() == 3) {
self->mat.at<cv::Vec3b>(i,j)[0] = val;
self->mat.at<cv::Vec3b>(i,j)[1] = val;
self->mat.at<cv::Vec3b>(i,j)[2] = val;
} else {
return ThrowException(Exception::TypeError(String::New("Invalid number of arguments")));
}
return scope.Close(Undefined());
} }
Handle<Value> Handle<Value>
Matrix::Size(const Arguments& args){ Matrix::Size(const Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
v8::Local<v8::Array> arr = v8::Array::New(2); v8::Local<v8::Array> arr = v8::Array::New(2);
arr->Set(0, Number::New(self->mat.size().height)); arr->Set(0, Number::New(self->mat.size().height));
arr->Set(1, Number::New(self->mat.size().width)); arr->Set(1, Number::New(self->mat.size().width));
return scope.Close(arr); return scope.Close(arr);
} }
Handle<Value> Handle<Value>
Matrix::Row(const Arguments& args){ Matrix::Row(const Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
int width = self->mat.size().width; int width = self->mat.size().width;
int y = args[0]->IntegerValue(); int y = args[0]->IntegerValue();
v8::Local<v8::Array> arr = v8::Array::New(width); v8::Local<v8::Array> arr = v8::Array::New(width);
for (int x=0; x<width; x++){ for (int x=0; x<width; x++){
double v = 0; double v = 0;
if (self->mat.channels() == 1){ if (self->mat.channels() == 1){
v = self->mat.at<float>(y, x); v = self->mat.at<float>(y, x);
} else { } else {
// Assume 3 channel RGB // Assume 3 channel RGB
unsigned int val = 0; unsigned int val = 0;
cv::Vec3b pixel = self->mat.at<cv::Vec3b>(y, x); cv::Vec3b pixel = self->mat.at<cv::Vec3b>(y, x);
val &= (uchar) pixel.val[2]; val &= (uchar) pixel.val[2];
val &= ((uchar) pixel.val[1]) << 8; val &= ((uchar) pixel.val[1]) << 8;
val &= ((uchar) pixel.val[0]) << 16; val &= ((uchar) pixel.val[0]) << 16;
v = (double) val; v = (double) val;
} }
arr->Set(x, Number::New(v)); arr->Set(x, Number::New(v));
} }
return scope.Close(arr);
return scope.Close(arr);
} }
Handle<Value> Handle<Value>
Matrix::PixelRow(const Arguments& args){ Matrix::PixelRow(const Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
int width = self->mat.size().width; int width = self->mat.size().width;
int y = args[0]->IntegerValue(); int y = args[0]->IntegerValue();
v8::Local<v8::Array> arr = v8::Array::New(width * 3); v8::Local<v8::Array> arr = v8::Array::New(width * 3);
for (int x=0; x<width; x++){ for (int x=0; x<width; x++){
cv::Vec3b pixel = self->mat.at<cv::Vec3b>(y, x); cv::Vec3b pixel = self->mat.at<cv::Vec3b>(y, x);
int offset = x * 3; int offset = x * 3;
arr->Set(offset , Number::New((double)pixel.val[0])); arr->Set(offset , Number::New((double)pixel.val[0]));
arr->Set(offset + 1, Number::New((double)pixel.val[1])); arr->Set(offset + 1, Number::New((double)pixel.val[1]));
arr->Set(offset + 2, Number::New((double)pixel.val[2])); arr->Set(offset + 2, Number::New((double)pixel.val[2]));
} }
return scope.Close(arr);
return scope.Close(arr);
} }
Handle<Value> Handle<Value>
@@ -206,46 +243,51 @@ Matrix::PixelCol(const Arguments& args){
Handle<Value> Handle<Value>
Matrix::Width(const Arguments& args){ Matrix::Width(const Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
return scope.Close(Number::New(self->mat.size().width)); return scope.Close(Number::New(self->mat.size().width));
} }
Handle<Value> Handle<Value>
Matrix::Height(const Arguments& args){ Matrix::Height(const Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
return scope.Close(Number::New(self->mat.size().height)); return scope.Close(Number::New(self->mat.size().height));
} }
Handle<Value>
Matrix::Channels(const Arguments& args){
SETUP_FUNCTION(Matrix)
return scope.Close(Number::New(self->mat.channels()));
}
Handle<Value> Handle<Value>
Matrix::ToBuffer(const v8::Arguments& args){ Matrix::ToBuffer(const v8::Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
std::vector<uchar> vec(0);
std::vector<int> params(0);//CV_IMWRITE_JPEG_QUALITY 90
cv::imencode(".jpg", self->mat, vec, params); std::vector<uchar> vec(0);
std::vector<int> params(0);//CV_IMWRITE_JPEG_QUALITY 90
node::Buffer *buf = node::Buffer::New(vec.size()); cv::imencode(".jpg", self->mat, vec, params);
uchar* data = (uchar*) Buffer::Data(buf);
memcpy(data, &vec[0], vec.size());
v8::Local<v8::Object> globalObj = v8::Context::GetCurrent()->Global(); node::Buffer *buf = node::Buffer::New(vec.size());
v8::Local<v8::Function> bufferConstructor = v8::Local<v8::Function>::Cast(globalObj->Get(v8::String::New("Buffer"))); uchar* data = (uchar*) Buffer::Data(buf);
v8::Handle<v8::Value> constructorArgs[3] = {buf->handle_, v8::Integer::New(vec.size()), v8::Integer::New(0)}; memcpy(data, &vec[0], vec.size());
v8::Local<v8::Object> actualBuffer = bufferConstructor->NewInstance(3, constructorArgs);
return scope.Close(actualBuffer); v8::Local<v8::Object> globalObj = v8::Context::GetCurrent()->Global();
} v8::Local<v8::Function> bufferConstructor = v8::Local<v8::Function>::Cast(globalObj->Get(v8::String::New("Buffer")));
v8::Handle<v8::Value> constructorArgs[3] = {buf->handle_, v8::Integer::New(vec.size()), v8::Integer::New(0)};
v8::Local<v8::Object> actualBuffer = bufferConstructor->NewInstance(3, constructorArgs);
return scope.Close(actualBuffer);
}
// ellipse(x, y, wid, height, angle, startangle, endangle, color, thickness, linetype, shift)
Handle<Value> Handle<Value>
Matrix::Ellipse(const v8::Arguments& args){ Matrix::Ellipse(const v8::Arguments& args){
SETUP_FUNCTION(Matrix) SETUP_FUNCTION(Matrix)
int x = args[0]->Uint32Value(); int x = args[0]->Uint32Value();
int y = args[1]->Uint32Value(); int y = args[1]->Uint32Value();
@@ -256,38 +298,250 @@ Matrix::Ellipse(const v8::Arguments& args){
cv::ellipse(self->mat, cv::Point(x, y), cv::Size(width, height), 0, 0, 360, cv::ellipse(self->mat, cv::Point(x, y), cv::Size(width, height), 0, 0, 360,
cv::Scalar( (color >> 16) & 0xff , (color >> 8) & 0xff, color & 0xff ), 4, 8, 0); cv::Scalar( (color >> 16) & 0xff , (color >> 8) & 0xff, color & 0xff ), 4, 8, 0);
return scope.Close(v8::Null()); return scope.Close(v8::Null());
} }
Handle<Value> Handle<Value>
Matrix::Save(const v8::Arguments& args){ Matrix::Save(const v8::Arguments& args){
HandleScope scope; HandleScope scope;
if (!args[0]->IsString()) if (!args[0]->IsString())
return ThrowException(Exception::TypeError(String::New("filename required"))); return ThrowException(Exception::TypeError(String::New("filename required")));
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This()); Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
String::AsciiValue filename(args[0]); String::AsciiValue filename(args[0]);
int res = cv::imwrite(*filename, self->mat); int res = cv::imwrite(*filename, self->mat);
return scope.Close(Number::New(res)); return scope.Close(Number::New(res));
} }
Handle<Value> Handle<Value>
Matrix::Eye(const v8::Arguments& args){ Matrix::Eye(const v8::Arguments& args){
HandleScope scope; HandleScope scope;
int w = args[0]->Uint32Value(); int w = args[0]->Uint32Value();
int h = args[1]->Uint32Value(); int h = args[1]->Uint32Value();
Local<Object> im_h = Matrix::constructor->GetFunction()->NewInstance(); Local<Object> im_h = Matrix::constructor->GetFunction()->NewInstance();
Matrix *img = ObjectWrap::Unwrap<Matrix>(im_h); Matrix *img = ObjectWrap::Unwrap<Matrix>(im_h);
cv::Mat mat = cv::Mat::eye(w, h, CV_32F); cv::Mat mat = cv::Mat::eye(w, h, CV_64FC1);
img->mat = mat; img->mat = mat;
return scope.Close(im_h); return scope.Close(im_h);
} }
Handle<Value>
Matrix::ConvertGrayscale(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
if(self->mat.channels() != 3)
return ThrowException(String::New("Image is no 3-channel"));
cv::Mat gray;
cv::cvtColor(self->mat, gray, CV_BGR2GRAY);
gray.copyTo(self->mat);
return scope.Close(v8::Null());
}
Handle<Value>
Matrix::ConvertHSVscale(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
if(self->mat.channels() != 3)
return ThrowException(String::New("Image is no 3-channel"));
cv::Mat hsv;
cv::cvtColor(self->mat, hsv, CV_BGR2HSV);
hsv.copyTo(self->mat);
return scope.Close(v8::Null());
}
Handle<Value>
Matrix::Copy(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
Local<Object> img_to_return = Matrix::constructor->GetFunction()->NewInstance();
Matrix *img = ObjectWrap::Unwrap<Matrix>(img_to_return);
self->mat.copyTo(img->mat);
return scope.Close(img_to_return);
}
Handle<Value>
Matrix::Ptr(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
int line = args[0]->Uint32Value();
char* data = self->mat.ptr<char>(line);
//uchar* data = self->mat.data;
/*
char *mydata = "Random raw data\0";
*/
node::Buffer *return_buffer = Buffer::New((char *)data, self->mat.step);
return scope.Close( return_buffer->handle_ );
// return Undefined();
}
Handle<Value>
Matrix::Bla(const v8::Arguments& args) {
HandleScope scope;
int i = args[1]->Uint32Value();
int div = 64;
if (Buffer::HasInstance(args[0])){
char *buf = (char *) Buffer::Data(args[0]->ToObject());
unsigned len = Buffer::Length(args[0]->ToObject());
}
return Undefined();
}
Handle<Value>
Matrix::AddWeighted(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
Matrix *src1 = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
Matrix *src2 = ObjectWrap::Unwrap<Matrix>(args[2]->ToObject());
float alpha = args[1]->NumberValue();
float beta = args[3]->NumberValue();
int gamma = 0;
cv::addWeighted(src1->mat, alpha, src2->mat, beta, gamma, self->mat);
return scope.Close(v8::Null());
}
Handle<Value>
Matrix::Split(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
return scope.Close(v8::Null());
}
Handle<Value>
Matrix::Canny(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
int lowThresh = args[0]->NumberValue();
int highThresh = args[1]->NumberValue();
cv::Canny(self->mat, self->mat, lowThresh, highThresh);
return scope.Close(v8::Null());
}
Handle<Value>
Matrix::Dilate(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
int niters = args[0]->NumberValue();
cv::dilate(self->mat, self->mat, cv::Mat(), cv::Point(-1, -1), niters);
return scope.Close(v8::Null());
}
Handle<Value>
Matrix::FindContours(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
Local<Object> conts_to_return= Contour::constructor->GetFunction()->NewInstance();
Contour *contours = ObjectWrap::Unwrap<Contour>(conts_to_return);
cv::findContours(self->mat, contours->contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
return scope.Close(conts_to_return);
}
Handle<Value>
Matrix::DrawContour(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
Contour *cont = ObjectWrap::Unwrap<Contour>(args[0]->ToObject());
int pos = args[1]->NumberValue();
cv::Scalar color(0, 0, 255);
if(args[2]->IsArray()) {
Local<Object> objColor = args[2]->ToObject();
color = setColor(objColor);
}
cv::drawContours(self->mat, cont->contours, pos, color, 1);
return Undefined();
}
Handle<Value>
Matrix::DrawAllContours(const v8::Arguments& args) {
HandleScope scope;
Matrix *self = ObjectWrap::Unwrap<Matrix>(args.This());
Contour *cont = ObjectWrap::Unwrap<Contour>(args[0]->ToObject());
cv::Scalar color(0, 0, 255);
if(args[1]->IsArray()) {
Local<Object> objColor = args[1]->ToObject();
color = setColor(objColor);
}
cv::drawContours(self->mat, cont->contours, -1, color, 1);
return Undefined();
}
cv::Scalar setColor(Local<Object> objColor) {
Local<Value> valB = objColor->Get(0);
Local<Value> valG = objColor->Get(1);
Local<Value> valR = objColor->Get(2);
cv::Scalar color = cv::Scalar(valB->IntegerValue(), valG->IntegerValue(), valR->IntegerValue());
return color;
}
Handle<Value> Handle<Value>
Matrix::Resize(const v8::Arguments& args){ Matrix::Resize(const v8::Arguments& args){
Arquivo normal → Arquivo executável
+14
Ver Arquivo
@@ -61,6 +61,7 @@ class Matrix: public node::ObjectWrap {
JSFUNC(Size) JSFUNC(Size)
JSFUNC(Width) JSFUNC(Width)
JSFUNC(Height) JSFUNC(Height)
JSFUNC(Channels)
JSFUNC(ToBuffer) JSFUNC(ToBuffer)
JSFUNC(Ellipse) JSFUNC(Ellipse)
JSFUNC(Empty) JSFUNC(Empty)
@@ -68,6 +69,19 @@ class Matrix: public node::ObjectWrap {
JSFUNC(Resize) JSFUNC(Resize)
JSFUNC(ConvertGrayscale)
JSFUNC(ConvertHSVscale)
JSFUNC(Copy)
JSFUNC(Ptr)
JSFUNC(Bla)
JSFUNC(AddWeighted)
JSFUNC(Split)
JSFUNC(Canny)
JSFUNC(Dilate)
JSFUNC(FindContours)
JSFUNC(DrawContour)
JSFUNC(DrawAllContours)
}; };
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
+1
Ver Arquivo
@@ -10,6 +10,7 @@
#include <highgui.h> #include <highgui.h>
#include <string.h> #include <string.h>
using namespace v8; using namespace v8;
using namespace node; using namespace node;
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
+82 -32
Ver Arquivo
@@ -2,64 +2,114 @@
#include "Matrix.h" #include "Matrix.h"
#include "OpenCV.h" #include "OpenCV.h"
void AsyncRead(uv_work_t *req);
void AfterAsyncRead(uv_work_t *req);
v8::Persistent<FunctionTemplate> VideoCaptureWrap::constructor; v8::Persistent<FunctionTemplate> VideoCaptureWrap::constructor;
struct videocapture_baton {
Persistent<Function> cb;
VideoCaptureWrap *vc;
Matrix *im;
uv_work_t request;
};
void void
VideoCaptureWrap::Init(Handle<Object> target) { VideoCaptureWrap::Init(Handle<Object> target) {
HandleScope scope; HandleScope scope;
// Constructor // Constructor
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(VideoCaptureWrap::New)); constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(VideoCaptureWrap::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("VideoCapture")); constructor->SetClassName(String::NewSymbol("VideoCapture"));
// Prototype // Prototype
Local<ObjectTemplate> proto = constructor->PrototypeTemplate(); Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
NODE_SET_PROTOTYPE_METHOD(constructor, "getFrame", GetFrame);
target->Set(String::NewSymbol("VideoCapture"), constructor->GetFunction()); NODE_SET_PROTOTYPE_METHOD(constructor, "read", Read);
target->Set(String::NewSymbol("VideoCapture"), constructor->GetFunction());
}; };
Handle<Value> Handle<Value>
VideoCaptureWrap::New(const Arguments &args) { VideoCaptureWrap::New(const Arguments &args) {
HandleScope scope; HandleScope scope;
if (args.This()->InternalFieldCount() == 0) if (args.This()->InternalFieldCount() == 0)
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot Instantiate without new"))); return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot Instantiate without new")));
VideoCaptureWrap *v; VideoCaptureWrap *v;
if (args[0]->IsNumber()){ if (args[0]->IsNumber()){
v = new VideoCaptureWrap(args[0]->NumberValue()); v = new VideoCaptureWrap(args[0]->NumberValue());
} else {} } else {}
v->Wrap(args.This());
return args.This();
v->Wrap(args.This());
return args.This();
} }
VideoCaptureWrap::VideoCaptureWrap(int device){ VideoCaptureWrap::VideoCaptureWrap(int device){
HandleScope scope;
cv::VideoCapture cap(device); HandleScope scope;
cap.open(device);
if(!cap.isOpened()){ if(!cap.isOpened()){
ThrowException(Exception::Error(String::New("Camera could not be opened"))); ThrowException(Exception::Error(String::New("Camera could not be opened")));
} }
} }
Handle<Value> Handle<Value>
VideoCaptureWrap::GetFrame(const Arguments &args) { VideoCaptureWrap::Read(const Arguments &args) {
SETUP_FUNCTION(VideoCaptureWrap)
cv::Mat frame; HandleScope scope;
self->cap.retrieve(frame); VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
REQ_FUN_ARG(0, cb);
videocapture_baton *baton = new videocapture_baton();
baton->vc = v;
baton->cb = Persistent<Function>::New(cb);
baton->im = new Matrix();
baton->request.data = baton;
uv_queue_work(uv_default_loop(), &baton->request, AsyncRead, AfterAsyncRead);
return Undefined();
Local<Object> im_h = Matrix::constructor->GetFunction()->NewInstance();
Matrix *im = ObjectWrap::Unwrap<Matrix>(im_h);
im->mat = frame;
return scope.Close(im_h);
} }
void AsyncRead(uv_work_t *req) {
videocapture_baton *baton = static_cast<videocapture_baton *>(req->data);
baton->vc->cap.read(baton->im->mat);
}
void AfterAsyncRead(uv_work_t *req) {
HandleScope scope;
videocapture_baton *baton = static_cast<videocapture_baton *>(req->data);
Local<Object> im_to_return= Matrix::constructor->GetFunction()->NewInstance();
Matrix *img = ObjectWrap::Unwrap<Matrix>(im_to_return);
cv::Mat mat;
mat = baton->im->mat;
img->mat = mat;
Local<Value> argv[1];
argv[0] = im_to_return;
baton->cb->Call(Context::GetCurrent()->Global(), 1, argv);
baton->cb.Dispose();
delete baton;
}
Arquivo normal → Arquivo executável
+3 -1
Ver Arquivo
@@ -11,7 +11,9 @@ class VideoCaptureWrap: public node::ObjectWrap {
VideoCaptureWrap(const std::string& filename); VideoCaptureWrap(const std::string& filename);
VideoCaptureWrap(int device); VideoCaptureWrap(int device);
static Handle<Value> GetFrame(const v8::Arguments&); static Handle<Value> Read(const v8::Arguments&);
static Handle<Value> GetFrameAt(const v8::Arguments&); static Handle<Value> GetFrameAt(const v8::Arguments&);
}; };
Arquivo normal → Arquivo executável
+2
Ver Arquivo
@@ -3,6 +3,7 @@
#include "Matrix.h" #include "Matrix.h"
#include "CascadeClassifierWrap.h" #include "CascadeClassifierWrap.h"
#include "VideoCaptureWrap.h" #include "VideoCaptureWrap.h"
#include "Contours.h"
extern "C" void extern "C" void
@@ -13,4 +14,5 @@ init(Handle<Object> target) {
Matrix::Init(target); Matrix::Init(target);
CascadeClassifierWrap::Init(target); CascadeClassifierWrap::Init(target);
VideoCaptureWrap::Init(target); VideoCaptureWrap::Init(target);
Contour::Init(target);
}; };
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo executável
+45
Ver Arquivo
@@ -0,0 +1,45 @@
im.calcHistograms(function(err, hist){})
im.calcHistograms(mask, function(err, hist){})
## Face recognition TODO
// Load Database
// TODO<
cv.loadImage('test.jpg', function(err, im){
im.detectObject("front-face.xml", {}, function(err, faces){
_.each(faces, function(v){
// TODO {
var section = im.slice(v.x, v.y, v.x + v.width, v.y + v.height);
section.convertGrayscale()
section.resize(WID, HEIGHT);
section.equaliseHistogram();
// } TODO
})
})
})
-----
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/
Arquivo normal → Arquivo executável
Ver Arquivo