node-opencv/src/Histogram.cc

141 lines
4.3 KiB
C++

#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());
// vs does not like this const, no need for it?
/*const */unsigned int dims = nodeChannels->Length();
if(dims < 1 || dims > 3){
return Nan::ThrowTypeError("OPENCV nodejs binding error : only dimensions from 1 to 3 are allowed");
}
// in vs, can't create an array of non-constant size; but since we have dims<3, just use 3..
int channels[3];
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[3];
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[3][2];
const float* ranges[3];
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]);
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;
}
}