Возвращение указателя изображения в Erlang

Я пытаюсь использовать 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)

и мой niftest.erl выглядит так:

-module(niftest).

-compile(export_all).

init() ->
erlang:load_nif("./niftest", 0).

get_pic() ->
"NIF library not loaded".

show_pic(F) ->
"NIF library not loaded".

Теперь проблема в том, что когда я вызываю get_pic, я получаю взамен {ok, <<>>} и Указатель не действителен вообще.

когда я cout кадр, прежде чем сделать enif_make_resource у него есть значение, и я вижу его, но оно мне возвращается пустым!

Что я делаю не так?
Я прочитал всю документацию, и я действительно не могу понять это.

ПРИМЕЧАНИЕ: вы можете скомпилировать код с помощью этой команды:

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

а затем запустите оболочку erlang и вызовите функции init и get_pic

0

Решение

NIF — неправильное решение для переноса высокоуровневого графического интерфейса OpenCV.

Тем не менее, чтобы ответить на ваш вопрос: очевидно, пустой двоичный файл в {ok, <<>>} кортеж, который вы получаете, непрозрачен от Эрланга. Это ресурсный объект как указано в erl_nif страница справочника.

Ресурсные объекты удобны для сборщика мусора. Если ни один процесс не ссылается на данный ресурс, вызывается функция очистки. Как правило, они являются правильной структурой для встраивания указателей C или C ++ в ваш NIF.

IplImage* Указатель является идеальным кандидатом для объекта ресурса. Вам, вероятно, не нужно frame_t введите, как вы можете просто привести указатель к IplImage**, Функция очистки должна освободить память и, в вашем примере, вызвать cvReleaseImage.

Так как указатель непрозрачен, вам нужно портировать функции доступа для предоставления данных в Erlang. Это действительно зависит от вида данных, которые вы хотели бы извлечь из изображения. Например, вы можете портировать cvEncodeImage функционировать и конвертировать данные из CvMat* в бинарный файл Erlang, используя enif_make_binary.

Также, как примечание, вместо возврата списка "NIF library not loaded"позвони erlang:nif_error/1,2 в функции заглушки.

Правильный подход к портированию API, такой как High GUI OpenCV будет внешний водитель (или C-узел).

Есть несколько причин, в том числе:

  • NIF звонки должны возвращаться быстро (звонить cvWaitKey является плохим кандидатом на NIF, а также вычисления, которые занимают слишком много времени), так как в противном случае они могли бы запутать планировщик;
  • с помощью NIF или подключенного драйвера управление памятью напрямую влияет на виртуальную машину Erlang, и любой сбой приведет к разрушению всего узла Erlang.

внешний водитель это процесс, который получает данные от stdin (обычно) и отвечает на stdout, Это очень просто спроектировать на C или C ++. Вы можете перенести API OpenCV или более сложные функции в зависимости от ваших потребностей. В этом случае указатели, такие как IplImage* может быть передан в виде непрозрачной серии из 4 или 8 байтов или в качестве ссылочного номера, если вы ведете список всех IplImage* Указатели Эрланг выделил. В отличие от NIF, однако, здесь нет объекта ресурса, и вам придется спроектировать код на стороне Erlang, чтобы обеспечить правильное освобождение памяти.

Вы найдете больше информации и пример кода в Руководство по взаимодействию.

Смотрите также этот вопрос: OpenCV на Эрланге

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]