File: Features2d.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 (122 lines) | stat: -rw-r--r-- 3,142 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
#include "OpenCV.h"

#if ((CV_MAJOR_VERSION == 2) && (CV_MINOR_VERSION >=4))
#include "Features2d.h"
#include "Matrix.h"
#include <nan.h>
#include <stdio.h>

#ifdef HAVE_OPENCV_FEATURES2D

void Features::Init(Local<Object> target) {
  Nan::HandleScope scope;

  Nan::SetMethod(target, "ImageSimilarity", Similarity);
}

class AsyncDetectSimilarity: public Nan::AsyncWorker {
public:
  AsyncDetectSimilarity(Nan::Callback *callback, Matrix *image1, Matrix *image2) :
      Nan::AsyncWorker(callback),
      image1(new Matrix(image1)),
      image2(new Matrix(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->mat, keypoints1);
    detector->detect(image2->mat, keypoints2);

    extractor->compute(image1->mat, keypoints1, descriptors1);
    extractor->compute(image2->mat, 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() {
    Nan::HandleScope scope;

    delete image1;
    delete image2;
    image1 = NULL;
    image2 = NULL;

    Local<Value> argv[2];

    argv[0] = Nan::Null();
    argv[1] = Nan::New<Number>(dissimilarity);

    callback->Call(2, argv);
  }

private:
  Matrix *image1;
  Matrix *image2;
  double dissimilarity;
};

NAN_METHOD(Features::Similarity) {
  Nan::HandleScope scope;

  REQ_FUN_ARG(2, cb);

  Matrix *image1 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
  Matrix *image2 = Nan::ObjectWrap::Unwrap<Matrix>(info[1]->ToObject());

  Nan::Callback *callback = new Nan::Callback(cb.As<Function>());

  Nan::AsyncQueueWorker( new AsyncDetectSimilarity(callback, image1, image2) );
  return;
}

#endif
#endif