mirror of
https://github.com/peterbraden/node-opencv.git
synced 2025-12-08 19:45:55 +00:00
merge compare with piercus's master branch
This commit is contained in:
commit
6de971d0e8
@ -20,7 +20,8 @@
|
||||
"src/Calib3D.cc",
|
||||
"src/ImgProc.cc",
|
||||
"src/Stereo.cc",
|
||||
"src/LDAWrap.cc"
|
||||
"src/LDAWrap.cc",
|
||||
"src/Histogram.cc",
|
||||
],
|
||||
|
||||
"libraries": [
|
||||
|
||||
67
examples/calc-hist.js
Normal file
67
examples/calc-hist.js
Normal file
@ -0,0 +1,67 @@
|
||||
var cv = require('../lib/opencv');
|
||||
|
||||
// (B)lue, (G)reen, (R)ed
|
||||
var histSize = 256;
|
||||
|
||||
cv.readImage('./files/car1.jpg', function(err, im) {
|
||||
if (err) throw err;
|
||||
if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size');
|
||||
|
||||
var bgrPlanes = im.split();
|
||||
|
||||
var size = 256,
|
||||
range = [0, 256],
|
||||
uniform = true,
|
||||
histFile = 'files/chart2.png';
|
||||
|
||||
|
||||
/// Compute a 3 dimension histogram
|
||||
var hist64 = cv.histogram.calcHist( im, [0, 1, 2], [4, 4, 4], [[0, 256], [0, 256], [0, 256]], uniform);
|
||||
|
||||
/// Compute 3 histograms
|
||||
var bHist = cv.histogram.calcHist( im, [0], [size], [range], uniform);
|
||||
var gHist = cv.histogram.calcHist( im, [1], [size], [range], uniform);
|
||||
var rHist = cv.histogram.calcHist( im, [2], [size], [range], uniform);
|
||||
|
||||
//////
|
||||
// Uncommentand run `npm install chartjs-node` to draw the histogram !
|
||||
///
|
||||
/*
|
||||
var ChartjsNode = require('chartjs-node');
|
||||
var chartNode = new ChartjsNode(1200, 1200);
|
||||
chartNode.drawChart({
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: bHist.map(function(a,i){return i.toString()}),
|
||||
datasets : [{
|
||||
data : bHist,
|
||||
backgroundColor : "#4183c4",
|
||||
borderColor : "#0c4b8a",
|
||||
label : 'Blue'
|
||||
},{
|
||||
data : gHist,
|
||||
backgroundColor : "#83c441",
|
||||
borderColor : "#0c4b8a",
|
||||
label : 'Green'
|
||||
},{
|
||||
data : rHist,
|
||||
backgroundColor : "#c44183",
|
||||
borderColor : "#0c4b8a",
|
||||
label : 'Red'
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'RGB Histograms'
|
||||
}
|
||||
}
|
||||
}).then(function(){
|
||||
return chartNode.writeImageToFile('image/png', histFile);
|
||||
}).then(function(){
|
||||
console.log("result has been written in "+histFile)
|
||||
}).catch(function(e){
|
||||
console.log("error",e)
|
||||
});
|
||||
*/
|
||||
});
|
||||
161
examples/emd.js
Normal file
161
examples/emd.js
Normal file
@ -0,0 +1,161 @@
|
||||
var cv = require('../lib/opencv');
|
||||
|
||||
//
|
||||
// Example of use of EMD distance using histograms
|
||||
// 1. Build 2 histograms from images using calcHist
|
||||
// 2. Transform each histogram to a 64 x 4 (hist, b, g, r) x 1 normalized signatures in BGR space
|
||||
// 3. Compute the cost matrix (64 x 64 x 1), calculating the cost in LUV space
|
||||
// 4. Run EMD algorithm
|
||||
//
|
||||
|
||||
/// Useful flatten function for step 2
|
||||
|
||||
function flatten(array, accu) {
|
||||
if(!accu){
|
||||
accu = [];
|
||||
}
|
||||
array.forEach(function(a){
|
||||
if(Array.isArray(a)) {
|
||||
flatten(a, accu)
|
||||
} else {
|
||||
accu.push(a)
|
||||
}
|
||||
});
|
||||
return accu
|
||||
};
|
||||
|
||||
cv.readImage('./files/car1.jpg', function(err, im1) {
|
||||
if (err) throw err;
|
||||
if (im1.width() < 1 || im1.height() < 1) throw new Error('Image has no size');
|
||||
cv.readImage('./files/car2.jpg', function(err, im2) {
|
||||
if (err) throw err;
|
||||
if (im2.width() < 1 || im2.height() < 1) throw new Error('Image has no size');
|
||||
|
||||
///////////////////
|
||||
// 1. Build 2 histograms from images using calcHist
|
||||
//////////////////
|
||||
|
||||
var size = [4, 4, 4],
|
||||
channels = [0, 1, 2],
|
||||
range = [[0, 256], [0, 256], [0, 256]],
|
||||
uniform = true,
|
||||
accumulate = true,
|
||||
histFile = 'files/chart2.png';
|
||||
|
||||
/// Compute 64 (=4^3) histograms:
|
||||
var firstImageHist64 = cv.histogram.calcHist(im1, channels, size, range, uniform);
|
||||
var secondImageHist64 = cv.histogram.calcHist(im2, channels, size, range, uniform);
|
||||
|
||||
//////////////
|
||||
// 2. Transform each histogram to a 64 x 4 (hist, b, g, r) x 1 normalized signatures in BGR space
|
||||
////////////////
|
||||
|
||||
var step = 256/4;
|
||||
var halfStep = Math.round(step/2);
|
||||
|
||||
var sum1 = 0;
|
||||
var sum2 = 0;
|
||||
|
||||
firstImageHist64.map(function(bHist, bIndex){
|
||||
return bHist.map(function(bgHist, gIndex){
|
||||
return bgHist.map(function(bgrHist, rIndex){
|
||||
sum1 += bgrHist;
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
var sig1 = flatten(firstImageHist64.map(function(bHist, bIndex){
|
||||
return bHist.map(function(bgHist, gIndex){
|
||||
return bgHist.map(function(bgrHist, rIndex){
|
||||
return {
|
||||
data :[
|
||||
[bgrHist/sum1],
|
||||
[bIndex*step + halfStep],
|
||||
[gIndex*step + halfStep],
|
||||
[rIndex*step + halfStep]
|
||||
]
|
||||
}
|
||||
})
|
||||
})
|
||||
})).map(function(a){
|
||||
// trick to avoid flattening and get a 64 x 4 x 1 image as needed
|
||||
return a.data;
|
||||
});
|
||||
|
||||
secondImageHist64.map(function(bHist, bIndex){
|
||||
return bHist.map(function(bgHist, gIndex){
|
||||
return bgHist.map(function(bgrHist, rIndex){
|
||||
sum2 += bgrHist;
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
var sig2 = flatten(secondImageHist64.map(function(bHist, bIndex){
|
||||
return bHist.map(function(bgHist, gIndex){
|
||||
return bgHist.map(function(bgrHist, rIndex){
|
||||
return {
|
||||
data : [
|
||||
[bgrHist/sum2],
|
||||
[bIndex*step + halfStep],
|
||||
[gIndex*step + halfStep],
|
||||
[rIndex*step + halfStep]
|
||||
]
|
||||
};
|
||||
})
|
||||
})
|
||||
})).map(function(a){
|
||||
// trick to avoid flattening and get a 64 x 4 x 1 image as needed
|
||||
return a.data;
|
||||
});
|
||||
|
||||
/////////////
|
||||
// 3. Compute the cost matrix (64 x 64 x 1), calculating the cost in LUV space
|
||||
/////////////
|
||||
|
||||
//middles is a 1 x 64 x 3 array of the middles positions in RGB used to change to LUV
|
||||
var middles = [flatten(firstImageHist64.map(function(bHist, bIndex){
|
||||
return bHist.map(function(bgHist, gIndex){
|
||||
return bgHist.map(function(bgrHist, rIndex){
|
||||
return {
|
||||
data : [
|
||||
bIndex*step + halfStep,
|
||||
gIndex*step + halfStep,
|
||||
rIndex*step + halfStep
|
||||
]
|
||||
}
|
||||
})
|
||||
})
|
||||
})).map(function(a){
|
||||
// trick to avoid flattening and get a 1 x 64 x 3 image as needed
|
||||
return a.data;
|
||||
})];
|
||||
|
||||
var mat = cv.Matrix.fromArray(middles, cv.Constants.CV_8UC3);
|
||||
mat.cvtColor("CV_BGR2Luv");
|
||||
|
||||
//luvValues is a 1 x 64 x 3 array of the middles positions in LUV
|
||||
var luvMiddles = mat.toArray();
|
||||
|
||||
var distance = function(luv1, luv2){
|
||||
return Math.sqrt((luv1[0]-luv2[0])*(luv1[0]-luv2[0]) + (luv1[1]-luv2[1])*(luv1[1]-luv2[1]) + (luv1[2]-luv2[2])*(luv1[2]-luv2[2]));
|
||||
};
|
||||
|
||||
var costs = luvMiddles[0].map(function(luvMiddle1){
|
||||
return luvMiddles[0].map(function(luvMiddle2){
|
||||
return [distance(luvMiddle1, luvMiddle2)];
|
||||
})
|
||||
});
|
||||
|
||||
//////
|
||||
// 4. Run EMD algorithm
|
||||
/////
|
||||
|
||||
var matCosts = cv.Matrix.fromArray(costs, cv.Constants.CV_32FC1);
|
||||
var matSig1 = cv.Matrix.fromArray(sig1, cv.Constants.CV_32FC1);
|
||||
var matSig2 = cv.Matrix.fromArray(sig2, cv.Constants.CV_32FC1);
|
||||
|
||||
var dist = cv.Constants.CV_DIST_L2;
|
||||
var emd = cv.histogram.emd(matSig1, matSig2, dist);//, matCosts);
|
||||
console.log("EMD is ", emd)
|
||||
});
|
||||
});
|
||||
20
examples/mat-array-conversion.js
Normal file
20
examples/mat-array-conversion.js
Normal file
@ -0,0 +1,20 @@
|
||||
var cv = require('../lib/opencv');
|
||||
|
||||
cv.readImage("./files/mona.png", function(err, orig) {
|
||||
if (err) throw err;
|
||||
|
||||
var a = orig.toArray();
|
||||
var type = orig.type();
|
||||
var doubleConversion = cv.Matrix.fromArray(a, type).toArray();
|
||||
|
||||
for(var i = 0 ; i < a.length; i++){
|
||||
for(var j = 0 ; j < a[i].length; j++){
|
||||
for(var k = 0 ; k < a[i][j].length; k++){
|
||||
if(a[i][j][k] !== doubleConversion[i][j][k]){
|
||||
throw(new Error("double conversion is not equal to original"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
120
lib/opencv.js
120
lib/opencv.js
@ -1,7 +1,8 @@
|
||||
var Stream = require('stream').Stream
|
||||
, Buffers = require('buffers')
|
||||
, util = require('util')
|
||||
, path = require('path');
|
||||
, path = require('path')
|
||||
, os = require('os');
|
||||
|
||||
var cv = module.exports = require('./bindings');
|
||||
|
||||
@ -33,6 +34,120 @@ Matrix.prototype.inspect = function(){
|
||||
return "[ Matrix " + size + " ]";
|
||||
}
|
||||
|
||||
// we use the Opencv constants naming convention to extract the number of bytes (8, 16, 32, 64), and the number of channels from constants names
|
||||
var getNumberOfBytesAndChannelsPerType = function(type){
|
||||
var regExp = /CV_([0-9]+)([A-Z]+)([0-9]+)/;
|
||||
for(var k in cv.Constants) if(cv.Constants.hasOwnProperty(k) && k.match(regExp) && cv.Constants[k] === type){
|
||||
var bytes, channels, dataType;
|
||||
k.replace(regExp, function(all, b, l, c){
|
||||
bytes = b;
|
||||
channels = c;
|
||||
dataType = l[0]
|
||||
});
|
||||
|
||||
return {
|
||||
bytes : parseInt(bytes),
|
||||
channels : !isNaN(parseInt(channels)) && parseInt(channels),
|
||||
dataType : dataType,
|
||||
label : k
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var getBufferMethodName = function(bytes, dataType, endianness, read){
|
||||
var fnName;
|
||||
|
||||
if(read){
|
||||
fnName = "read";
|
||||
} else {
|
||||
fnName = "write";
|
||||
}
|
||||
|
||||
if (bytes === 32 && (dataType === "F" || dataType === "S")){
|
||||
if(dataType === "F"){
|
||||
fnName += "Float"+endianness;
|
||||
} else {//dataType === "S"
|
||||
fnName += "Int32"+endianness;
|
||||
}
|
||||
} else if(bytes === 8){
|
||||
fnName += (dataType === "U" ? "U" : "")+"Int8";
|
||||
} else if(bytes === 16){
|
||||
fnName += (dataType === "U" ? "U" : "")+"Int16"+endianness;
|
||||
} else {
|
||||
throw("This matrix type (CV_"+bytes+dataType+") is not compatible with fromArray/toArray")
|
||||
}
|
||||
return fnName;
|
||||
};
|
||||
|
||||
Matrix.fromArray = function(arr, type){
|
||||
var n_bytes;
|
||||
|
||||
var bytesAndChannels = getNumberOfBytesAndChannelsPerType(type);
|
||||
var bytes = bytesAndChannels.bytes;
|
||||
var channels = bytesAndChannels.channels;
|
||||
var dataType = bytesAndChannels.dataType;
|
||||
var label = bytesAndChannels.label;
|
||||
|
||||
if(!Array.isArray(arr) ||!Array.isArray(arr[0]) || !Array.isArray(arr[0][0]) || (channels && arr[0][0].length !== channels)) {
|
||||
throw(new Error("Input array must be a 3-level array/matrix with size rows x cols x channels corresponding to dataType ("+label+")"));
|
||||
}
|
||||
|
||||
if(!channels){
|
||||
channels = 1;
|
||||
}
|
||||
|
||||
var rows = arr.length;
|
||||
var cols = arr[0].length;
|
||||
|
||||
var mat = new cv.Matrix(rows, cols, type);
|
||||
|
||||
var n_bytes = bytes/8;
|
||||
var buf = new Buffer(rows * cols * channels * n_bytes);
|
||||
|
||||
buf.fill(0);
|
||||
|
||||
var fnName = getBufferMethodName(bytes, dataType, os.endianness(), false)
|
||||
|
||||
for(var i=0;i<rows * cols * channels;i++){
|
||||
var c = i%channels;
|
||||
var r = Math.floor(i/channels);
|
||||
var y = r%cols;
|
||||
var x = Math.floor(r/cols);
|
||||
buf[fnName](arr[x][y][c], i*n_bytes);
|
||||
}
|
||||
|
||||
mat.put(buf);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
Matrix.prototype.toArray = function(){
|
||||
var size = this.size();
|
||||
var buf = this.getData();
|
||||
var type = this.type();
|
||||
var bytesAndChannels = getNumberOfBytesAndChannelsPerType(type);
|
||||
var bytes = bytesAndChannels.bytes;
|
||||
var channels = bytesAndChannels.channels || this.channels();
|
||||
var dataType = bytesAndChannels.dataType;
|
||||
|
||||
var n_bytes = bytes/8;
|
||||
var fnName = getBufferMethodName(bytes, dataType, os.endianness(), true)
|
||||
|
||||
var res = []
|
||||
for(var i = 0; i < size[0]; i++){
|
||||
var row = [];
|
||||
for(var j = 0; j < size[1]; j++){
|
||||
var channelsValues = [];
|
||||
for(var k = 0; k < channels; k++){
|
||||
var index = (i*size[1]+j)*channels+k;
|
||||
channelsValues.push(buf[fnName](index*n_bytes));
|
||||
}
|
||||
row.push(channelsValues);
|
||||
}
|
||||
res.push(row);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
ImageStream = cv.ImageStream = function(){
|
||||
this.writable = true;
|
||||
@ -148,6 +263,3 @@ var CASCADES = {
|
||||
Object.keys(CASCADES).forEach(function(k){
|
||||
cv[k] = path.resolve(__dirname, '../data', CASCADES[k])
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
@ -96,6 +96,7 @@ void Constants::Init(Local<Object> target) {
|
||||
CONST_INT(CV_DIST_C);
|
||||
CONST_INT(CV_DIST_L1);
|
||||
CONST_INT(CV_DIST_L2);
|
||||
CONST_INT(CV_DIST_USER);
|
||||
|
||||
CONST_INT(CV_DIST_MASK_3);
|
||||
CONST_INT(CV_DIST_MASK_5);
|
||||
|
||||
135
src/Histogram.cc
Normal file
135
src/Histogram.cc
Normal file
@ -0,0 +1,135 @@
|
||||
#include "Histogram.h"
|
||||
#include "Matrix.h"
|
||||
|
||||
void Histogram::Init(Local<Object> target) {
|
||||
Nan::Persistent<Object> inner;
|
||||
Local<Object> obj = Nan::New<Object>();
|
||||
inner.Reset(obj);
|
||||
|
||||
Nan::SetMethod(obj, "calcHist", CalcHist);
|
||||
Nan::SetMethod(obj, "emd", Emd);
|
||||
|
||||
target->Set(Nan::New("histogram").ToLocalChecked(), obj);
|
||||
}
|
||||
|
||||
NAN_METHOD(Histogram::CalcHist) {
|
||||
Nan::EscapableHandleScope scope;
|
||||
|
||||
try {
|
||||
// Arg 0 is the image
|
||||
Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
|
||||
cv::Mat inputImage = m0->mat;
|
||||
|
||||
// Arg 1 is the channel
|
||||
Local<Array> nodeChannels = Local<Array>::Cast(info[1]->ToObject());
|
||||
const unsigned int dims = nodeChannels->Length();
|
||||
int channels[dims];
|
||||
for (unsigned int i = 0; i < dims; i++) {
|
||||
channels[i] = nodeChannels->Get(i)->IntegerValue();
|
||||
}
|
||||
|
||||
// Arg 2 is histogram sizes in each dimension
|
||||
Local<Array> nodeHistSizes = Local<Array>::Cast(info[2]->ToObject());
|
||||
int histSize[dims];
|
||||
for (unsigned int i = 0; i < dims; i++) {
|
||||
histSize[i] = nodeHistSizes->Get(i)->IntegerValue();
|
||||
}
|
||||
|
||||
// Arg 3 is array of the histogram bin boundaries in each dimension
|
||||
Local<Array> nodeRanges = Local<Array>::Cast(info[3]->ToObject());
|
||||
/// Set the ranges ( for B,G,R) )
|
||||
float histRanges[dims][2];
|
||||
const float* ranges[dims];
|
||||
|
||||
for (unsigned int i = 0; i < dims; i++) {
|
||||
Local<Array> nodeRange = Local<Array>::Cast(nodeRanges->Get(i)->ToObject());
|
||||
float lower = nodeRange->Get(0)->NumberValue();
|
||||
float higher = nodeRange->Get(1)->NumberValue();
|
||||
histRanges[i][0] = lower;
|
||||
histRanges[i][1] = higher;
|
||||
ranges[i] = histRanges[i];
|
||||
}
|
||||
|
||||
// Arg 4 is uniform flag
|
||||
bool uniform = info[4]->BooleanValue();
|
||||
|
||||
// Make a mat to hold the result image
|
||||
cv::Mat outputHist;
|
||||
|
||||
// Perform calcHist
|
||||
cv::calcHist(&inputImage, 1, channels, cv::Mat(), outputHist, dims, histSize, ranges, uniform);
|
||||
|
||||
v8::Local<v8::Array> arr = Nan::New<Array>(histSize[0]);
|
||||
|
||||
if(dims < 1 || dims > 3){
|
||||
return Nan::ThrowTypeError("OPENCV nodejs binding error : only dimensions from 1 to 3 are allowed");
|
||||
}
|
||||
|
||||
for (unsigned int i=0; i < (unsigned int) histSize[0]; i++) {
|
||||
if(dims <= 1){
|
||||
arr->Set(i, Nan::New<Number>(outputHist.at<float>(i)));
|
||||
} else {
|
||||
v8::Local<v8::Array> arr2 = Nan::New<Array>(dims);
|
||||
for (unsigned int j=0; j < (unsigned int) histSize[1]; j++) {
|
||||
if(dims <= 2){
|
||||
arr2->Set(j, Nan::New<Number>(outputHist.at<float>(i,j)));
|
||||
} else {
|
||||
v8::Local<v8::Array> arr3 = Nan::New<Array>(dims);
|
||||
for (unsigned int k=0; k < (unsigned int) histSize[1]; k++) {
|
||||
arr3->Set(k, Nan::New<Number>(outputHist.at<float>(i,j,k)));
|
||||
}
|
||||
arr2->Set(j, arr3);
|
||||
}
|
||||
}
|
||||
arr->Set(i, arr2);
|
||||
}
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(arr);
|
||||
} catch (cv::Exception &e) {
|
||||
const char *err_msg = e.what();
|
||||
Nan::ThrowError(err_msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// cv::distanceTransform
|
||||
NAN_METHOD(Histogram::Emd) {
|
||||
Nan::EscapableHandleScope scope;
|
||||
|
||||
try {
|
||||
// Arg 0 is the first signature
|
||||
//std::vector<std::vector<float>> sig1 = nodeArrayToVec(info[0]->ToObject());
|
||||
Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
|
||||
cv::Mat sig1 = m0->mat;
|
||||
|
||||
// Arg 1 is the second signature
|
||||
//std::vector<std::vector<float>> sig2 = nodeArrayToVec(info[1]->ToObject());
|
||||
Matrix* m1 = Nan::ObjectWrap::Unwrap<Matrix>(info[1]->ToObject());
|
||||
cv::Mat sig2 = m1->mat;
|
||||
|
||||
// Arg 2 is the distance type
|
||||
int distType = info[2]->IntegerValue();
|
||||
|
||||
float emd;
|
||||
|
||||
// Arg 3 is the cost matrix
|
||||
if (info.Length() > 3) {
|
||||
Matrix* m3 = Nan::ObjectWrap::Unwrap<Matrix>(info[3]->ToObject());
|
||||
cv::Mat costs = m3->mat;
|
||||
|
||||
emd = cv::EMD(sig1, sig2, distType, costs);
|
||||
info.GetReturnValue().Set(emd);
|
||||
} else {
|
||||
emd = cv::EMD(sig1, sig2, distType);
|
||||
}
|
||||
|
||||
//printf("similarity %5.5f %%\n, DistanceType is %i\n", (1-emd)*100, distType);
|
||||
info.GetReturnValue().Set(emd);
|
||||
|
||||
} catch (cv::Exception &e) {
|
||||
const char *err_msg = e.what();
|
||||
Nan::ThrowError(err_msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
16
src/Histogram.h
Normal file
16
src/Histogram.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __NODE_HISTOGRAM_H
|
||||
#define __NODE_HISTOGRAM_H
|
||||
|
||||
#include "OpenCV.h"
|
||||
|
||||
/**
|
||||
* Implementation of histogram.hpp functions
|
||||
*/
|
||||
class Histogram: public Nan::ObjectWrap {
|
||||
public:
|
||||
static void Init(Local<Object> target);
|
||||
static NAN_METHOD(CalcHist);
|
||||
static NAN_METHOD(Emd);
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -117,6 +117,7 @@ void Matrix::Init(Local<Object> target) {
|
||||
Nan::SetPrototypeMethod(ctor, "release", Release);
|
||||
Nan::SetPrototypeMethod(ctor, "subtract", Subtract);
|
||||
Nan::SetPrototypeMethod(ctor, "compare", Compare);
|
||||
Nan::SetPrototypeMethod(ctor, "mul", Mul);
|
||||
|
||||
target->Set(Nan::New("Matrix").ToLocalChecked(), ctor->GetFunction());
|
||||
};
|
||||
@ -2853,7 +2854,23 @@ NAN_METHOD(Matrix::Compare) {
|
||||
cv::Mat res = cv::Mat(width, height, CV_8UC1);
|
||||
|
||||
cv::compare(self->mat, other->mat, res, cmpop);
|
||||
|
||||
Local<Object> out = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
|
||||
Matrix *m_out = Nan::ObjectWrap::Unwrap<Matrix>(out);
|
||||
m_out->mat = res;
|
||||
|
||||
info.GetReturnValue().Set(out);
|
||||
return;
|
||||
}
|
||||
NAN_METHOD(Matrix::Mul) {
|
||||
SETUP_FUNCTION(Matrix)
|
||||
|
||||
if (info.Length() < 1) {
|
||||
Nan::ThrowTypeError("Invalid number of arguments");
|
||||
}
|
||||
|
||||
Matrix *other = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
|
||||
|
||||
cv::Mat res = self->mat.mul(other->mat);
|
||||
Local<Object> out = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
|
||||
Matrix *m_out = Nan::ObjectWrap::Unwrap<Matrix>(out);
|
||||
m_out->mat = res;
|
||||
|
||||
@ -135,6 +135,7 @@ public:
|
||||
|
||||
JSFUNC(Subtract)
|
||||
JSFUNC(Compare)
|
||||
JSFUNC(Mul)
|
||||
/*
|
||||
static Handle<Value> Val(const Arguments& info);
|
||||
static Handle<Value> RowRange(const Arguments& info);
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include "Stereo.h"
|
||||
#include "BackgroundSubtractor.h"
|
||||
#include "LDAWrap.h"
|
||||
#include "Histogram.h"
|
||||
|
||||
extern "C" void init(Local<Object> target) {
|
||||
Nan::HandleScope scope;
|
||||
@ -30,6 +31,7 @@ extern "C" void init(Local<Object> target) {
|
||||
Constants::Init(target);
|
||||
Calib3D::Init(target);
|
||||
ImgProc::Init(target);
|
||||
Histogram::Init(target);
|
||||
#if CV_MAJOR_VERSION < 3
|
||||
StereoBM::Init(target);
|
||||
StereoSGBM::Init(target);
|
||||
|
||||
34
test/unit.js
34
test/unit.js
@ -398,15 +398,16 @@ test('Mean', function(assert) {
|
||||
});
|
||||
|
||||
test('Compare', function(assert) {
|
||||
var b = new cv.Matrix.Zeros(2, 2, cv.Constants.CV_8UC1);
|
||||
var a = new cv.Matrix.Zeros(2, 2, cv.Constants.CV_8UC1);
|
||||
var a = cv.Matrix.fromArray([[[0],[-20]],[[2],[-18]]], cv.Constants.CV_8SC1);
|
||||
var b = cv.Matrix.fromArray([[[3],[-20]],[[0],[-16]]], cv.Constants.CV_8SC1);
|
||||
|
||||
a.set(0, 0, 3);
|
||||
var compare1 = a.compare(b, cv.Constants.CMP_EQ);
|
||||
var compare2 = a.compare(b, cv.Constants.CMP_GT);
|
||||
var compare3 = a.compare(b, cv.Constants.CMP_LE);
|
||||
|
||||
var compare = a.compare(b, cv.Constants.CMP_EQ);
|
||||
var buf = compare.getData();
|
||||
compare.save("./test.png");
|
||||
console.log(compare.norm());
|
||||
assert.deepEqual(compare1.toArray(), [[[0],[255]],[[0],[0]]]);
|
||||
assert.deepEqual(compare2.toArray(), [[[0],[0]],[[255],[0]]]);
|
||||
assert.deepEqual(compare3.toArray(), [[[255],[255]],[[0],[255]]]);
|
||||
|
||||
assert.end();
|
||||
});
|
||||
@ -463,5 +464,24 @@ test('setColor works will alpha channels', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('toArray/fromArray working in both ways', function(assert) {
|
||||
var cv = require('../lib/opencv');
|
||||
|
||||
cv.readImage("./examples/files/mona.png", function(err, orig) {
|
||||
if (err) throw err;
|
||||
|
||||
var a = orig.toArray();
|
||||
var type = orig.type();
|
||||
var doubleConversion = cv.Matrix.fromArray(a, type).toArray();
|
||||
|
||||
var randomI = Math.floor(Math.random()*a.length)
|
||||
var randomJ = Math.floor(Math.random()*a[randomI].length)
|
||||
var randomK = Math.floor(Math.random()*a[randomI][randomJ].length)
|
||||
|
||||
assert.equal(a[randomI][randomJ][randomK], doubleConversion[randomI][randomJ][randomK]);
|
||||
assert.end();
|
||||
});
|
||||
});
|
||||
|
||||
// Test the examples folder.
|
||||
require('./examples')()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user