mirror of
https://github.com/peterbraden/node-opencv.git
synced 2025-12-08 19:45:55 +00:00
Add imageSimilarity method beased on features 2d
This commit is contained in:
parent
d2a918bedc
commit
a7eba6a9e4
@ -1,6 +1,8 @@
|
||||
{
|
||||
"targets": [{
|
||||
"target_name": "opencv",
|
||||
|
||||
"target_name": "opencv",
|
||||
|
||||
"sources": [
|
||||
"src/init.cc",
|
||||
"src/Matrix.cc",
|
||||
@ -12,6 +14,7 @@
|
||||
"src/CamShift.cc",
|
||||
"src/HighGUI.cc",
|
||||
"src/FaceRecognizer.cc",
|
||||
"src/Features2d.cc",
|
||||
"src/BackgroundSubtractor.cc",
|
||||
"src/Constants.cc",
|
||||
"src/Calib3D.cc",
|
||||
|
||||
17
examples/dissimilarity.js
Normal file
17
examples/dissimilarity.js
Normal file
@ -0,0 +1,17 @@
|
||||
var cv = require('../lib/opencv');
|
||||
|
||||
cv.readImage("./examples/files/car1.jpg", function(err, car1) {
|
||||
if (err) throw err;
|
||||
|
||||
cv.readImage("./examples/files/car2.jpg", function(err, car2) {
|
||||
if (err) throw err;
|
||||
|
||||
cv.ImageSimilarity(car1, car2, function (err, dissimilarity) {
|
||||
if (err) throw err;
|
||||
|
||||
console.log('Dissimilarity: ', dissimilarity);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
22
package.json
Executable file → Normal file
22
package.json
Executable file → Normal file
@ -3,18 +3,20 @@
|
||||
"description": "Node Bindings to OpenCV",
|
||||
"author": "Peter Braden <peterbraden@peterbraden.co.uk>",
|
||||
"dependencies": {
|
||||
"node-pre-gyp": "0.5.31",
|
||||
"buffers": "0.1.1",
|
||||
"nan": "1.4.3"
|
||||
"nan": "^1.7.0",
|
||||
"node-pre-gyp": "^0.6.4"
|
||||
},
|
||||
"version": "3.0.1",
|
||||
"devDependencies": {
|
||||
"tape": "^3.0.0",
|
||||
"aws-sdk": "~2.0.21",
|
||||
"glob": "^4.0.6",
|
||||
"request": "^2.45.0"
|
||||
"aws-sdk": "~2.1.20",
|
||||
"glob": "^5.0.3",
|
||||
"request": "^2.44.0"
|
||||
},
|
||||
"bundledDependencies":["node-pre-gyp"],
|
||||
"bundledDependencies": [
|
||||
"node-pre-gyp"
|
||||
],
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "node-gyp build",
|
||||
@ -36,10 +38,10 @@
|
||||
"node": ">=0.10"
|
||||
},
|
||||
"binary": {
|
||||
"module_name" : "opencv",
|
||||
"module_path" : "./build/{module_name}/v{version}/{configuration}/{node_abi}-{platform}-{arch}/",
|
||||
"remote_path" : "./{module_name}/v{version}/{configuration}/",
|
||||
"module_name": "opencv",
|
||||
"module_path": "./build/{module_name}/v{version}/{configuration}/{node_abi}-{platform}-{arch}/",
|
||||
"remote_path": "./{module_name}/v{version}/{configuration}/",
|
||||
"package_name": "{node_abi}-{platform}-{arch}.tar.gz",
|
||||
"host" : "https://node-opencv.s3.amazonaws.com"
|
||||
"host": "https://node-opencv.s3.amazonaws.com"
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ CascadeClassifierWrap::Init(Handle<Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(ctor, "detectMultiScale", DetectMultiScale);
|
||||
|
||||
target->Set(NanNew("CascadeClassifier"), ctor->GetFunction());
|
||||
};
|
||||
};
|
||||
|
||||
NAN_METHOD(CascadeClassifierWrap::New) {
|
||||
NanScope();
|
||||
@ -29,7 +29,7 @@ NAN_METHOD(CascadeClassifierWrap::New) {
|
||||
if (args.This()->InternalFieldCount() == 0)
|
||||
NanThrowTypeError("Cannot instantiate without new");
|
||||
|
||||
CascadeClassifierWrap *pt = new CascadeClassifierWrap(*args[0]);
|
||||
CascadeClassifierWrap *pt = new CascadeClassifierWrap(*args[0]);
|
||||
pt->Wrap(args.This());
|
||||
NanReturnValue( args.This() );
|
||||
}
|
||||
@ -39,10 +39,10 @@ CascadeClassifierWrap::CascadeClassifierWrap(v8::Value* fileName){
|
||||
std::string filename;
|
||||
filename = std::string(*NanAsciiString(fileName->ToString()));
|
||||
|
||||
|
||||
|
||||
if (!cc.load(filename.c_str())){
|
||||
NanThrowTypeError("Error loading file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -63,14 +63,15 @@ class AsyncDetectMultiScale : public NanAsyncWorker {
|
||||
|
||||
equalizeHist( gray, gray);
|
||||
this->cc->cc.detectMultiScale(gray, objects, this->scale, this->neighbors, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(this->minw, this->minh));
|
||||
|
||||
|
||||
res = objects;
|
||||
}
|
||||
|
||||
void HandleOKCallback () {
|
||||
NanScope();
|
||||
// this->matrix->Unref();
|
||||
|
||||
|
||||
Handle<Value> argv[2];
|
||||
v8::Local<v8::Array> arr = NanNew<v8::Array>(this->res.size());
|
||||
|
||||
for(unsigned int i = 0; i < this->res.size(); i++ ){
|
||||
@ -82,20 +83,17 @@ class AsyncDetectMultiScale : public NanAsyncWorker {
|
||||
arr->Set(i, x);
|
||||
}
|
||||
|
||||
//argv[1] = arr;
|
||||
Local<Value> argv[] = {
|
||||
NanNull()
|
||||
, arr
|
||||
};
|
||||
|
||||
argv[0] = NanNull();
|
||||
argv[1] = arr;
|
||||
|
||||
TryCatch try_catch;
|
||||
callback->Call(2, argv);
|
||||
if (try_catch.HasCaught()) {
|
||||
FatalException(try_catch);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
CascadeClassifierWrap *cc;
|
||||
Matrix* im;
|
||||
@ -104,7 +102,7 @@ class AsyncDetectMultiScale : public NanAsyncWorker {
|
||||
int minw;
|
||||
int minh;
|
||||
std::vector<cv::Rect> res;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -114,7 +112,7 @@ NAN_METHOD(CascadeClassifierWrap::DetectMultiScale){
|
||||
NanScope();
|
||||
|
||||
CascadeClassifierWrap *self = ObjectWrap::Unwrap<CascadeClassifierWrap>(args.This());
|
||||
|
||||
|
||||
if (args.Length() < 2){
|
||||
NanThrowTypeError("detectMultiScale takes at least 2 args");
|
||||
}
|
||||
@ -142,5 +140,5 @@ NAN_METHOD(CascadeClassifierWrap::DetectMultiScale){
|
||||
|
||||
NanAsyncQueueWorker( new AsyncDetectMultiScale(callback, self, im, scale, neighbors, minw, minh) );
|
||||
NanReturnUndefined();
|
||||
|
||||
|
||||
}
|
||||
|
||||
105
src/Features2d.cc
Normal file
105
src/Features2d.cc
Normal file
@ -0,0 +1,105 @@
|
||||
#include "Features2d.h"
|
||||
#include "Matrix.h"
|
||||
#include <nan.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
|
||||
|
||||
void
|
||||
Features::Init(Handle<Object> target) {
|
||||
NanScope();
|
||||
|
||||
NODE_SET_METHOD(target, "ImageSimilarity", Similarity);
|
||||
};
|
||||
|
||||
class AsyncDetectSimilarity : public NanAsyncWorker {
|
||||
public:
|
||||
AsyncDetectSimilarity(NanCallback *callback, cv::Mat image1, cv::Mat image2) : NanAsyncWorker(callback), image1(image1), image2(image2), dissimilarity(0) {}
|
||||
~AsyncDetectSimilarity() {}
|
||||
|
||||
void Execute () {
|
||||
|
||||
cv::Ptr<cv::FeatureDetector> detector = cv::FeatureDetector::create("ORB");
|
||||
cv::Ptr<cv::DescriptorExtractor> extractor = cv::DescriptorExtractor::create("ORB");
|
||||
cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
|
||||
|
||||
std::vector<cv::DMatch> matches;
|
||||
|
||||
cv::Mat descriptors1 = cv::Mat();
|
||||
cv::Mat descriptors2 = cv::Mat();
|
||||
|
||||
std::vector<cv::KeyPoint> keypoints1;
|
||||
std::vector<cv::KeyPoint> keypoints2;
|
||||
|
||||
detector->detect(image1, keypoints1);
|
||||
detector->detect(image2, keypoints2);
|
||||
|
||||
extractor->compute(image1, keypoints1, descriptors1);
|
||||
extractor->compute(image2, keypoints2, descriptors2);
|
||||
|
||||
matcher->match(descriptors1, descriptors2, matches);
|
||||
|
||||
double max_dist = 0;
|
||||
double min_dist = 100;
|
||||
|
||||
//-- Quick calculation of max and min distances between keypoints
|
||||
for (int i = 0; i < descriptors1.rows; i++) {
|
||||
double dist = matches[i].distance;
|
||||
if( dist < min_dist ) min_dist = dist;
|
||||
if( dist > max_dist ) max_dist = dist;
|
||||
}
|
||||
|
||||
//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist,
|
||||
//-- or a small arbitary value ( 0.02 ) in the event that min_dist is very
|
||||
//-- small)
|
||||
//-- PS.- radiusMatch can also be used here.
|
||||
std::vector<cv::DMatch> good_matches;
|
||||
double good_matches_sum = 0.0;
|
||||
|
||||
for (int i = 0; i < descriptors1.rows; i++ ) {
|
||||
double distance = matches[i].distance;
|
||||
if (distance <= std::max(2*min_dist, 0.02)) {
|
||||
good_matches.push_back(matches[i]);
|
||||
good_matches_sum += distance;
|
||||
}
|
||||
}
|
||||
|
||||
dissimilarity = (double)good_matches_sum / (double)good_matches.size();
|
||||
|
||||
}
|
||||
|
||||
void HandleOKCallback () {
|
||||
NanScope();
|
||||
|
||||
Handle<Value> argv[2];
|
||||
|
||||
argv[0] = NanNull();
|
||||
argv[1] = NanNew<Number>(dissimilarity);
|
||||
|
||||
callback->Call(2, argv);
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
cv::Mat image1;
|
||||
cv::Mat image2;
|
||||
double dissimilarity;
|
||||
|
||||
};
|
||||
|
||||
NAN_METHOD(Features::Similarity) {
|
||||
NanScope();
|
||||
|
||||
REQ_FUN_ARG(2, cb);
|
||||
|
||||
cv::Mat image1 = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject())->mat;
|
||||
cv::Mat image2 = ObjectWrap::Unwrap<Matrix>(args[1]->ToObject())->mat;
|
||||
|
||||
NanCallback *callback = new NanCallback(cb.As<Function>());
|
||||
|
||||
NanAsyncQueueWorker( new AsyncDetectSimilarity(callback, image1, image2) );
|
||||
NanReturnUndefined();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
16
src/Features2d.h
Normal file
16
src/Features2d.h
Normal file
@ -0,0 +1,16 @@
|
||||
#include "OpenCV.h"
|
||||
|
||||
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/features2d/features2d.hpp>
|
||||
|
||||
class Features: public node::ObjectWrap {
|
||||
public:
|
||||
static Persistent<FunctionTemplate> constructor;
|
||||
static void Init(Handle<Object> target);
|
||||
|
||||
static NAN_METHOD(Similarity);
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -8,6 +8,7 @@
|
||||
#include "CamShift.h"
|
||||
#include "HighGUI.h"
|
||||
#include "FaceRecognizer.h"
|
||||
#include "Features2d.h"
|
||||
#include "Constants.h"
|
||||
#include "Calib3D.h"
|
||||
#include "ImgProc.h"
|
||||
@ -23,7 +24,7 @@ init(Handle<Object> target) {
|
||||
CascadeClassifierWrap::Init(target);
|
||||
VideoCaptureWrap::Init(target);
|
||||
Contour::Init(target);
|
||||
TrackedObject::Init(target);
|
||||
TrackedObject::Init(target);
|
||||
NamedWindow::Init(target);
|
||||
Constants::Init(target);
|
||||
Calib3D::Init(target);
|
||||
@ -34,7 +35,8 @@ init(Handle<Object> target) {
|
||||
|
||||
|
||||
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
|
||||
FaceRecognizerWrap::Init(target);
|
||||
Features::Init(target);
|
||||
FaceRecognizerWrap::Init(target);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user