Merge github.com:talvarez/node-opencv
Conflicts: src/Matrix.cc src/Matrix.h
Esse commit está contido em:
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
+1
-1
@@ -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
Arquivo executável
+6
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
node-waf configure build &&
|
||||||
|
cd examples &&
|
||||||
|
#node face_detection.js
|
||||||
|
node $1
|
||||||
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo executável
+61
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Arquivo executável
+18
@@ -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
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 518 KiB |
Arquivo executável
BIN
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 5.4 KiB |
Arquivo executável
+27
@@ -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
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 186 KiB |
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
+1
-1
@@ -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
+1
-1
@@ -14,4 +14,4 @@ var cv = require('./lib/opencv')
|
|||||||
im.save('./out.jpg');
|
im.save('./out.jpg');
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|||||||
Arquivo normal → Arquivo executável
+24
-15
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Arquivo normal → Arquivo executável
+1
@@ -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
Arquivo normal → Arquivo executável
Arquivo normal → Arquivo executável
+82
-32
@@ -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
@@ -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
@@ -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
Arquivo executável
+45
@@ -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
Referência em uma Nova Issue
Bloquear um usuário