cv :: imcode将图像从JS解码为C ++(opencv,emscripten) [英] cv::imdecode an image from JS to C++ (opencv, emscripten)

查看:77
本文介绍了cv :: imcode将图像从JS解码为C ++(opencv,emscripten)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要做什么:

  • 用户使用html加载图像
  • opencv用C ++接收该图像并对其进行一些工作.

我所做的与此处描述的大致相同:

What I've done is more or less the same as described here :

这是javascript部分(给定链接中的冗词):

Here is the javascript part (verbatim from the given link):

var openFile = function (e) {
    const fileReader = new FileReader();
    fileReader.onload = (event) => {
        const uint8Arr = new Uint8Array(event.target.result);
        passToWasm(uint8Arr);
    };
    fileReader.readAsArrayBuffer(e.target.files[0]);
};

function passToWasm(uint8ArrData) {
    // copying the uint8ArrData to the heap
    const numBytes = uint8ArrData.length * uint8ArrData.BYTES_PER_ELEMENT;
    const dataPtr = Module._malloc(numBytes);
    const dataOnHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, numBytes);
    dataOnHeap.set(uint8ArrData);
    // calling the Wasm function
    console.log(dataOnHeap.byteOffset);
    const res = Module._image_input(dataOnHeap.byteOffset, uint8ArrData.length);

    Module._free(dataPtr);
}

这是C ++部分(几乎逐字记录):

And here is the C++ part (almost verbatim):

int image_input(int offset, size_t size) //query image input
    {
      uint8_t* pos;
       pos = reinterpret_castw<uint8_t*>(offset);
        cv::Mat raw_data = cv::Mat(1, size, CV_8UC1, pos);
         cout << raw_data << endl;
        img_object = cv::imdecode(raw_data, cv::IMREAD_GRAYSCALE);
        cout << img_object << endl;
    }

当我测试一些jpg图像时,C ++部分上的 raw_data 和JS部分上的 uint8ArrData 包含相同的信息:即15253个数字的列表喜欢

When I test with some jpg images, the raw_data on the C++ part and the uint8ArrData on the JS part contain the same information: that is a list of 15253 numbers like

[255, 216, 255, 224, ..., 184, 227, 255, 217]

现在,一行

img_object = cv::imdecode(raw_data, cv::IMREAD_GRAYSCALE);

返回一个空矩阵 [] .

我做错了什么?我必须在JS端进行一些预处理吗?

What do I do wrong ? Do I have to make some pre-processing on the JS side ?

推荐答案

如提供的链接中所述,解决方案是使用画布并将像素列表(以4x480x640的数字为例)发送到C ++.

As said in the provided link, the solution is to use a canvas and send to C++ the list of pixels (4x480x640 numbers as an example).

您在JS方面

function sendCanvas(canvas, baseImage) {
    const context = canvas.getContext('2d');
    context.drawImage(baseImage, 0, 0, baseImage.width, baseImage.height);
    const { width } = canvas;
    const { height } = canvas;
    const imgData = context.getImageData(0, 0, canvas.width, canvas.height);
    const uint8ArrData = new Uint8Array(imgData.data);

     // pass the width and height too !!
    passToWasm(uint8ArrData, width, height);
}

 const baseImage = new Image();
    baseImage.src = 'test.jpg';
    baseImage.onload = () => sendCanvas(canvas, baseImage);

您必须使函数 passToWasm 适应其他两个参数(宽度和高度),并将它们传递给C ++调用.

You have to adapt the function passToWasm to take two more arguments (width and height) and pass them to the C++ call.

然后在C ++方面,直接使用以下信息将图像创建为 cv :: Mat :

Then on the C++ side, you create the image as a cv::Mat directly with these informations:

void image_input(int offset, size_t size, int width, int height) {
  // People in the doc do not need this cast trick. Why ???
  uint8_t *pos;
  pos = reinterpret_cast<uint8_t *>(offset);
  auto cv_image = cv::Mat(width, height, CV_8UC4, pos);
}

矩阵 cv_image 已准备好进行操作.

The matrix cv_image is ready for manipulations.

这篇关于cv :: imcode将图像从JS解码为C ++(opencv,emscripten)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆