Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将图像指针返回到Erlang_C++_Opencv_Pointers_Erlang_Erlang Nif - Fatal编程技术网

C++ 将图像指针返回到Erlang

C++ 将图像指针返回到Erlang,c++,opencv,pointers,erlang,erlang-nif,C++,Opencv,Pointers,Erlang,Erlang Nif,我正在尝试将openCV与Erlang NIF结合使用。 所以我想做一件基本的事情,那就是读取一张图片并将指针发送回erlang。 并且能够再次将收到的指针发送回C,并显示图片 因此niftest.cpp如下所示: /* niftest.cpp */ #include "erl_nif.h" #include <opencv/highgui.h> #include <opencv/cv.h> using namespace cv; using namespace std

我正在尝试将openCV与Erlang NIF结合使用。 所以我想做一件基本的事情,那就是读取一张图片并将指针发送回erlang。 并且能够再次将收到的指针发送回C,并显示图片

因此niftest.cpp如下所示:

/* niftest.cpp */

#include "erl_nif.h"
#include <opencv/highgui.h>
#include <opencv/cv.h>
using namespace cv;
using namespace std;


static ErlNifResourceType* frame_res = NULL;


typedef struct _frame_t {
IplImage* _frame;
} frame_t;

//------------------------------------------------------------------------------
// NIF callbacks
//------------------------------------------------------------------------------

static void frame_cleanup(ErlNifEnv* env, void* arg) {
enif_free(arg);
}

static int load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
{

ErlNifResourceFlags flags = (ErlNifResourceFlags) (ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER);
frame_res = enif_open_resource_type(env, "niftest", "ocv_frame",
                      &frame_cleanup,
                      flags, 0);
return 0;
}


static ERL_NIF_TERM get_pic(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{

IplImage* src = cvLoadImage("/home/khashayar/Downloads/pic.png");

cout << src->width << endl;

IplImage* gray = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
cvCvtColor(src, gray, CV_RGB2GRAY);

frame_t* frame = (frame_t*)enif_alloc_resource(frame_res, sizeof(frame_t));
frame->_frame = gray ;

ERL_NIF_TERM term = enif_make_resource(env, frame);
enif_release_resource(frame);
return enif_make_tuple2(env, enif_make_atom(env, "ok"), term); 

}


static ERL_NIF_TERM show_pic(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]){

frame_t* frame;
 if (!enif_get_resource(env, argv[0], frame_res, (void**) &frame)) {
   return enif_make_badarg(env);
 }

 cvShowImage("YOOHOO", frame->_frame);

 cvWaitKey(30);

 return enif_make_atom(env, "ok");
}

static ErlNifFunc nif_funcs[] =
  {
    {"show_pic", 1, show_pic},
    {"get_pic", 0, get_pic}
  };

ERL_NIF_INIT(niftest,nif_funcs,load,NULL,NULL,NULL)
所以现在的问题是,当我调用get_pic时,我得到的是
{ok,}
,指针根本无效

当我
cout
生成
enif\u make\u资源之前的帧时,它有一个值,我可以看到它,但它返回给我为空

我做错了什么? 我已经阅读了所有的文档,但我真的不明白这一点

注意:您可以使用以下命令编译代码:

g++ -fPIC -shared -o niftest.so niftest.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui -I /usr/lib64/erlang/usr/include/

然后运行erlang shell并调用init和get_pic函数

NIF是移植OpenCV高级GUI的错误解决方案。

然而,为了回答您的问题:您得到的
{ok,}
元组中显然是空的二进制文件在Erlang中是不透明的。这是一个资源对象,如手册页中所述

资源对象是垃圾收集器友好的。如果没有进程引用给定的资源,则将调用cleanup函数。它们通常是在nIF中嵌入C或C++指针的适当结构。
IplImage*
指针是资源对象的完美候选对象。您可能不需要
frame\t
类型,因为您可以简单地将指针投射到
IplImage**
。cleanup函数应该释放内存,并且在您的示例中调用

由于指针是不透明的,因此需要移植访问器函数以向Erlang提供数据。这实际上取决于要从图像中提取的数据类型。例如,您可以移植函数并使用将数据从
CvMat*
转换为erlang二进制文件

另外,作为补充说明,您应该调用存根函数,而不是返回列表
“NIF library not loaded”

移植API(如OpenCV的High GUI)的正确方法是使用外部驱动程序(或C节点)

有几个原因,包括:

  • NIF调用应该很快返回(调用
    cvWaitKey
    不适合NIF,并且计算时间太长),否则会混淆调度程序
  • 使用NIF或链接的in驱动程序,内存管理会直接影响Erlang的虚拟机,任何崩溃都会导致整个Erlang节点崩溃
外部驱动程序是一个从
stdin
(通常)获取数据并在
stdout
上回复的过程。这是非常简单的设计,在C或C++。您可以移植OpenCV的API,也可以根据需要移植更复杂的函数。在这种情况下,诸如
IplImage*
之类的指针可以作为4或8字节的不透明序列传输,或者作为参考号传输,前提是您维护Erlang已分配的所有
IplImage*
指针的列表。然而,与NIFs不同的是,没有资源对象,您必须设计Erlang端代码以确保正确释放内存

您将在中找到更多信息和示例代码


另请参见此问题:

我认为您对我的代码中的详细信息非常关注,这里对其进行了简化,因此更易于阅读。我当然已经阅读了您建议的文档。相信我,我正在为此工作一段时间,而不仅仅是在这里发布一些东西。谢谢你的回复
g++ -fPIC -shared -o niftest.so niftest.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui -I /usr/lib64/erlang/usr/include/