File: Histogram.cc

package info (click to toggle)
node-opencv 6.0.0+git20180416.cfc96ba0-3
  • links: PTS, VCS
  • area: main
  • in suites: buster, sid
  • size: 24,632 kB
  • sloc: xml: 476,707; cpp: 5,950; makefile: 114; sh: 59; ansic: 20
file content (140 lines) | stat: -rw-r--r-- 4,402 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#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;
  }
}