资讯专栏INFORMATION COLUMN

Node Opencv Addon

cgspine / 1219人阅读

摘要:安装使用下载安装包解压进入目录编译需要为系统生成,是基于的。

Opencv Node Addon Opencv 安装使用

下载Opencv安装包: http://opencv.org/releases.html

解压进入Opencv目录

编译Opencv(需要cmake)

mkdir release
cd release
cmake -G "Unix Makefiles" .. (为Unix 系统生成Makefile,Mac OSX是基于Unix的。未安装cmake 可以通过Homebrew安装,未安装Homebrew需安装Homebrew)
make

安装Opencv

make install

安装完成的目录

/usr/local/lib (Opencv库文件)
/usr/local/include (Opencv头文件)
/usr/local/share/ (Opencv xml配置文件)

使用Opencv(C++ Version)

编写CMakeLists.txt文件

project( ORBFeatureAndCompare ) // 项目的名称
cmake_minimum_required(VERSION 2.8) // cmake的版本要求
find_package( OpenCV REQUIRED ) // 查找对应的Opencv依赖库
find_package(Boost COMPONENTS log log_setup thread filesystem system) // 查找对应的Boost依赖库(下文出现Boost的安装方法)
add_executable( ORBFeatureAndCompare ORBFeatureAndCompare )  // 指定可运行的文件
// 引入对应的依赖库文件的位置
target_link_libraries(ORBFeatureAndCompare
    ${OpenCV_LIBS}
    ${Boost_LOG_SETUP_LIBRARY}
    ${Boost_LOG_LIBRARY}
    ${Boost_FILESYSTEM_LIBRARY}
    ${Boost_THREAD_LIBRARY}
    ${Boost_SYSTEM_LIBRARY}
)

编写Opencv的cpp文件

//必要的头文件
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace boost::filesystem;  
namespace newfs = boost::filesystem;
using namespace cv;
using namespace std;

int main () {
  ....
  return 0;
}

创建一个images(其他命名都可以)的资源文件夹

cd images
cmake ..
make
./ORBFeatureAndCompare //编译出的可执行程序

安装使用Boost进行数据序列化

下载Boost安装包: https://dl.bintray.com/boosto...

解压进入Boost目录

编译安装Boost

./bootstrap.sh
./b2

引入Boost库进行数据序列化,同样是在CmakeList中引入文件路径, 在cpp文件中使用

封装cpp程序为Node Addon

依赖安装

全局安装node-gyp

本地安装nan

编写binding.gyp

{
  "targets": [
  {
    "target_name": "feature",
    "sources": [ "./src/feature.cc" ],
    "include_dirs": [
      "

编写node c++ 插件

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace boost::filesystem;
namespace newfs = boost::filesystem;
using namespace v8;
using namespace std;

vector matToString(cv::Mat descriptorMat) {
  vector buf;
  imencode(".png", descriptorMat, buf);
  return buf;
}

vector descriptorMat(cv::Mat image) {
  vector keyPoint;
  cv::Ptr orb = cv::ORB::create(4000, 1.2f, 8, 31, 0, 2,             cv::ORB::HARRIS_SCORE, 31, 20);
  orb->detect(image, keyPoint);
  cv::Mat descriptorMat;
  orb->compute(image, keyPoint, descriptorMat);
  return matToString(descriptorMat);
}

void imageFeature(const FunctionCallbackInfo& args) {
  Isolate* isolate = args.GetIsolate();
  if (args.Length() < 1) {
    isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
    return;
  }
  if (!args[0]->IsString()) {
    isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong arguments")));
    return;
  }
  String::Utf8Value pathValue(Local::Cast(args[0]));
  string path = string(*pathValue);
  cv::Mat image = cv::imread(path, 1);
  if (image.empty()) {
    isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Input image error")));
    return;
  }
  vector descriptorString = descriptorMat(image);
  Local buf = Nan::NewBuffer(descriptorString.size()).ToLocalChecked();
  uchar* data = (uchar*) node::Buffer::Data(buf);
  memcpy(data, &descriptorString[0], descriptorString.size());
  v8::Local globalObj = Nan::GetCurrentContext()->Global();
  v8::Local bufferConstructor = v8::Local::Cast(globalObj->Get(Nan::New("Buffer").ToLocalChecked()));
  v8::Local constructorArgs[3] = {buf, Nan::New((unsigned)descriptorString.size()), Nan::New(0)};
  v8::Local actualBuffer = bufferConstructor->NewInstance(3, constructorArgs);
  args.GetReturnValue().Set(actualBuffer);
}

int bfMatcherCompare (cv::Mat &descriptors1, cv::Mat &descriptors2) {
  cv::BFMatcher matcher(cv::NORM_HAMMING);
  vector matches;
  matcher.match(descriptors1, descriptors2, matches);
  double max_dist = 0;
  double min_dist = 100;
  /*
  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;
  }
  vector good_matches;
  for (int i = 0; i < descriptors1.rows; i++)
  {
    if (matches[i].distance < 3 * min_dist)
      good_matches.push_back(matches[i]);
  }
  return good_matches.size();
  */
  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;
    }
  }
  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;
    }
  }
  return (double) good_matches_sum / (double) good_matches.size();
}

void similarity(const FunctionCallbackInfo& args) {
  Isolate* isolate = args.GetIsolate();
  Local arg1 = args[0]->ToObject();
  int size1 = args[1]->NumberValue();
  Local arg2 = args[2]->ToObject();
  int size2 = args[3]->NumberValue();
  if (args.Length() < 4) {
    isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
    return;
  }
  uchar*buffer1 = (uchar*) node::Buffer::Data(arg1);
  std::vector vec1(buffer1, buffer1 +  (unsigned int) size1);
  cv::Mat img_decode1;
  img_decode1 = cv::imdecode(vec1, CV_8U);
  uchar*buffer2 = (uchar*) node::Buffer::Data(arg2);
  std::vector vec2(buffer2, buffer2 +  (unsigned int) size2);
  cv::Mat img_decode2;
  img_decode2 = cv::imdecode(vec2, CV_8U);
  int similarity = bfMatcherCompare(img_decode1, img_decode2);
  args.GetReturnValue().Set(similarity);
}

void init(Local exports, Local module) {
  NODE_SET_METHOD(exports, "imageFeature", imageFeature);
  NODE_SET_METHOD(exports, "similarity", similarity);
}

NODE_MODULE(addon, init)

编写Js文件

const feature = require("./build/Release/feature");

exports.getImageFeature = (filePath) => {
  return feature.imageFeature(filePath).toString("utf8");
};

exports.getImageSimilarity = (descriptor1, descriptor2) => {
  let matBuffer1 = Buffer.from(descriptor1);
  let matBuffer2 = Buffer.from(descriptor2);
  return feature.similarity(matBuffer1, matBuffer1.length, matBuffer2, matBuffer2.length);
};

编译运行

node-gyp configure build
node test.js

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82576.html

相关文章

  • 干货 | 走进Node.js之启动过程剖析

    摘要:具体调用链路如图函数主要是解析启动参数,并过滤选项传给引擎。查阅文档之后发现,通过指定参数可以设置线程池大小。原来的字节码编译优化还有都是通过多线程完成又继续深入调查,发现环境变量会影响的线程池大小。执行过程如下调用执行。 作者:正龙 (沪江Web前端开发工程师)本文原创,转载请注明作者及出处。 随着Node.js的普及,越来越多的开发者使用Node.js来搭建环境,也有很多公司开始把...

    luck 评论0 收藏0
  • 干货剖析 | 走进Node.js之启动过程

    摘要:具体调用链路如图函数主要是解析启动参数,并过滤选项传给引擎。查阅文档之后发现,通过指定参数可以设置线程池大小。原来的字节码编译优化还有都是通过多线程完成又继续深入调查,发现环境变量会影响的线程池大小。执行过程如下调用执行。 作者:正龙 (沪江Web前端开发工程师)本文原创,转载请注明作者及出处。 随着Node.js的普及,越来越多的开发者使用Node.js来搭建环境,也有很多公司开始把...

    Simon 评论0 收藏0
  • 用NAN写一个nodejs的c++扩展

    摘要:介绍的全称为其表现上是一个包。引用扩展,暴露出方法供上层使用。初次开发扩展的用户需要注意下项目目录中的文件会读取项目中的为表示最后生成的扩展文件名为。累加完成后通过将结果返回出去。 NAN介绍 NAN的全称为Native Abstraction for Node.js, 其表现上是一个Node.js包。安装后,就得到一堆C++头文件,里面是一堆宏。它主要为Node.js和V8跨版本提供...

    魏明 评论0 收藏0
  • Mac下安装node-opencv

    摘要:安装一个包也需要写成文章既然你看到这了你就知道是啥东西就不介绍了啊是在的基础上封装了一层使用时会调用底层的使用编写的来实现图像处理的功能所以不单单的安装一个包各种尝试说实话这块才是最头痛的事如果你搜索安装你能搜到很多结果但是他们好像都串通 安装一个node包也需要写成文章? 既然你看到这了, 你就知道opencv是啥东西, 就不介绍了啊, node-opencv是在opencv的基础上...

    lavor 评论0 收藏0
  • vscode调试node.js c++扩展

    摘要:类似的,如果我们想要调试扩展,我们也需要扩展源文件的调试符号信息。配置安装插件这里我们将用来调试扩展。配置输入配置一个任务,该任务会执行,生成带调试信息的扩展文件。 Debugging NodeJS C++ addons using VS Code 之前笔者写了一篇 用NAN写一个nodejs的c++扩展, 实际开发过程中,肯定是有单步调试的需求。这里简单介绍用如何用vscode调试...

    王伟廷 评论0 收藏0

发表评论

0条评论

cgspine

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<