Face detection using cascade classifier

This commit is contained in:
Peter Braden 2012-01-18 20:03:00 -08:00
parent 468034d329
commit 23d49455fe
10 changed files with 26308 additions and 17 deletions

19
TODO
View File

@ -1,2 +1,17 @@
- src/OpenCV.c
- Test to see if bindings are working
[X] In C++ get Image to inherit Matrix, to mirror js inherit
- Don't think it's possible :(
- CascadeClassifier::DetectMultiScale
- pass in properties
- Make async
== Image ==
- make image from stream
- make image from node file object
- Image::Ellipse
- pass in color
- pass in thickness

File diff suppressed because it is too large Load Diff

16
package.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "opencv"
, "description": "Node Bindings to OpenCV"
, "author": "Peter Braden <peterbraden@peterbraden.co.uk>"
, "dependencies": {
}
, "version" : "0.0.1"
, "devDependencies": {
"vows": "*"
}
, "engine": "node >= 0.4.1"
, "scripts": {
"preinstall": "node-waf configure build"
}
, "main": "./lib/opencv",
}

View File

@ -1,8 +1,15 @@
var opencv = require('./lib/opencv')
var cv = require('./lib/opencv')
, assert = require('assert')
console.log(opencv.version)
console.log(cv.version)
console.log(new opencv.Matrix().empty())
var im = new cv.Image("./examples/mona.jpg")
, face_cascade = new cv.CascadeClassifier("./examples/haarcascade_frontalface_alt.xml")
console.log(new opencv.Image('./examples/mona.jpg').empty())
var faces = face_cascade.detectMultiScale(im, 1.1, 2, [30, 30])
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');

View File

@ -1,8 +1,8 @@
#include "OpenCV.h"
#include "CascadeClassifierWrap.h"
#include "OpenCV.h"
#include "Image.h"
v8::Persistent<v8::FunctionTemplate> CascadeClassifierWrap::constructor;
Persistent<FunctionTemplate> CascadeClassifierWrap::constructor;
void
CascadeClassifierWrap::Init(Handle<Object> target) {
@ -16,6 +16,10 @@ CascadeClassifierWrap::Init(Handle<Object> target) {
// Prototype
Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
NODE_SET_PROTOTYPE_METHOD(constructor, "detectMultiScale", DetectMultiScale);
target->Set(String::NewSymbol("CascadeClassifier"), constructor->GetFunction());
};
@ -36,6 +40,45 @@ CascadeClassifierWrap::CascadeClassifierWrap(v8::Value* fileName){
std::string filename;
filename = std::string(*v8::String::AsciiValue(fileName->ToString()));
cc.load(filename.c_str());
if (!cc.load(filename.c_str())){
v8::ThrowException(v8::Exception::TypeError(v8::String::New("Error loading file")));
}
}
Handle<Value>
CascadeClassifierWrap::DetectMultiScale(const v8::Arguments& args){
HandleScope scope;
CascadeClassifierWrap *self = ObjectWrap::Unwrap<CascadeClassifierWrap>(args.This());
Image *im = ObjectWrap::Unwrap<Image>(args[0]->ToObject());
std::vector<cv::Rect> objects;
double scale = 1.1;
int neighbors = 2;
int minw = 30;
int minh = 30;
cv::Mat gray;
cvtColor( im->mat, gray, CV_BGR2GRAY );
equalizeHist( gray, gray);
self->cc.detectMultiScale(gray, objects, scale, neighbors, 0, cv::Size(minw, minh));
v8::Local<v8::Array> arr = v8::Array::New(objects.size());
for(unsigned int i = 0; i < objects.size(); i++ ){
v8::Local<v8::Object> x = v8::Object::New();
x->Set(v8::String::New("x"), v8::Number::New(objects[i].x));
x->Set(v8::String::New("y"), v8::Number::New(objects[i].y));
x->Set(v8::String::New("width"), v8::Number::New(objects[i].width));
x->Set(v8::String::New("height"), v8::Number::New(objects[i].height));
arr->Set(i, x);
}
return scope.Close(arr);
}

View File

@ -4,7 +4,6 @@ class CascadeClassifierWrap: public node::ObjectWrap {
public:
cv::CascadeClassifier cc;
static Persistent<FunctionTemplate> constructor;
static void Init(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
@ -12,4 +11,7 @@ class CascadeClassifierWrap: public node::ObjectWrap {
CascadeClassifierWrap(v8::Value* fileName);
//static Handle<Value> LoadHaarClassifierCascade(const v8::Arguments&);
}
static Handle<Value> DetectMultiScale(const v8::Arguments&);
};

View File

@ -1,5 +1,4 @@
#include "Image.h"
#include "OpenCV.h"
#include "Matrix.h"
v8::Persistent<FunctionTemplate> Image::constructor;
@ -21,6 +20,7 @@ Image::Init(Handle<Object> target) {
proto->SetAccessor(String::NewSymbol("height"), GetHeight);
NODE_SET_PROTOTYPE_METHOD(constructor, "save", Save);
NODE_SET_PROTOTYPE_METHOD(constructor, "ellipse", Ellipse);
/*proto->SetAccessor(String::NewSymbol("source"), GetSource, SetSource);
@ -57,8 +57,7 @@ Image::New(const Arguments &args) {
Image::Image(int width, int height): ObjectWrap() {
Image::Image(int width, int height): ObjectWrap() {
};
@ -68,6 +67,8 @@ Image::Image(v8::Value* fileName): ObjectWrap() {
mat = cv::imread(filename, -1);
};
Image::~Image() {
}
Handle<Value>
Image::GetWidth(Local<String>, const AccessorInfo &info) {
@ -97,3 +98,18 @@ Image::Save(const v8::Arguments& args){
return scope.Close(Number::New(res));
}
// ellipse(x, y, wid, height, angle, startangle, endangle, color, thickness, linetype, shift)
Handle<Value>
Image::Ellipse(const v8::Arguments& args){
HandleScope scope;
Image *self = ObjectWrap::Unwrap<Image>(args.This());
int x = args[0]->Uint32Value();
int y = args[1]->Uint32Value();
int width = args[2]->Uint32Value();
int height = args[3]->Uint32Value();
cv::ellipse(self->mat, cv::Point(x, y), cv::Size(width, height), 0, 0, 360, cv::Scalar( 255, 0, 255 ), 4, 8, 0);
return scope.Close(v8::Null());
}

View File

@ -16,6 +16,11 @@ class Image: public node::ObjectWrap {
static Handle<Value> GetWidth(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetHeight(Local<String> prop, const AccessorInfo &info);
//static Handle<Value> Convert(const v8::Arguments&);
static Handle<Value> Save(const v8::Arguments&);
static Handle<Value> Ellipse(const v8::Arguments&);
private:
~Image();
};

View File

@ -4,6 +4,7 @@
#include "Image.h"
#include "CascadeClassifierWrap.h"
extern "C" void
init(Handle<Object> target) {
HandleScope scope;
@ -12,4 +13,4 @@ init(Handle<Object> target) {
Matrix::Init(target);
Image::Init(target);
CascadeClassifierWrap::Init(target);
}
};

View File

@ -90,5 +90,30 @@ vows.describe('Smoke Tests OpenCV').addBatch({
assert.equal(new cv.Image("./examples/mona.jpg").height, 756)
}
, ".ellipse": function(cv){
assert.equal(new cv.Image("./examples/mona.jpg").ellipse(10, 10, 10, 10), undefined)
}
}
, "CascadeClassifier": {
topic : require('../lib/opencv')
, "constructor" : function(cv){
assert.ok(new cv.CascadeClassifier("./examples/haarcascade_frontalface_alt.xml"))
}
, "face detection": function(cv){
var im = new cv.Image("./examples/mona.jpg")
, face_cascade = new cv.CascadeClassifier("./examples/haarcascade_frontalface_alt.xml")
, faces = face_cascade.detectMultiScale(im, 1.1, 2, [30, 30])
assert.equal(faces.length, 1)
}
}
}).run();