#include "Features2d.h" #include "Matrix.h" #include #include #if ((CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >=4)) void Features::Init(Local target) { Nan::HandleScope scope; Nan::SetMethod(target, "ImageSimilarity", Similarity); } class AsyncDetectSimilarity: public Nan::AsyncWorker { public: AsyncDetectSimilarity(Nan::Callback *callback, cv::Mat image1, cv::Mat image2) : Nan::AsyncWorker(callback), image1(image1), image2(image2), dissimilarity(0) { } ~AsyncDetectSimilarity() { } void Execute() { cv::Ptr detector = cv::FeatureDetector::create("ORB"); cv::Ptr extractor = cv::DescriptorExtractor::create("ORB"); cv::Ptr matcher = cv::DescriptorMatcher::create( "BruteForce-Hamming"); std::vector matches; cv::Mat descriptors1 = cv::Mat(); cv::Mat descriptors2 = cv::Mat(); std::vector keypoints1; std::vector 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 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; Local argv[2]; argv[0] = Nan::Null(); argv[1] = Nan::New(dissimilarity); callback->Call(2, argv); } private: cv::Mat image1; cv::Mat image2; double dissimilarity; }; NAN_METHOD(Features::Similarity) { Nan::HandleScope scope; REQ_FUN_ARG(2, cb); cv::Mat image1 = Nan::ObjectWrap::Unwrap(info[0]->ToObject())->mat; cv::Mat image2 = Nan::ObjectWrap::Unwrap(info[1]->ToObject())->mat; Nan::Callback *callback = new Nan::Callback(cb.As()); Nan::AsyncQueueWorker( new AsyncDetectSimilarity(callback, image1, image2) ); return; } #endif