javascript - cv::imcode将图像从JS解码到C++(opencv,emscripten)

标签 javascript opencv emscripten

我正在尝试做的是:

  • 用户在html中加载图像
  • opencv用C++接收该图像并对其做一些工作。

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

    https://answers.opencv.org/question/222994/how-to-pass-image-data-from-javascript-to-opencv-c-webassembly/

    这是javascript部分(给定链接的冗长部分):
    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++部分(几乎逐字记录):
    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个数字的列表,例如
    [255, 216, 255, 224, ..., 184, 227, 255, 217]
    

    现在,线
    img_object = cv::imdecode(raw_data, cv::IMREAD_GRAYSCALE);
    

    返回一个空矩阵[]

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

    最佳答案

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

    在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++调用。

    然后在C++方面,直接使用以下信息将图像创建为cv::Mat:
    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已准备好进行操作。

    关于javascript - cv::imcode将图像从JS解码到C++(opencv,emscripten),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61477860/

    相关文章:

    OpenCV SURF,抓取的视频有点滞后是正常的吗?如何加快速度?

    c++ - 使用 OpenCV 在一个窗口中显示 2 个摄像头画面

    opengl-es - 编译着色器后程序停止绘制

    javascript - WebAssembly/脚本 : write files to disk from within browser

    javascript - 将对象数组渲染为树

    javascript - 如何在jquery中按名称选择选项

    javascript - maxDelayTime 太长有什么坏处?

    c++ - 使用列主要 Matlab 样式的数据布局将图像读入 C++?

    xmlhttprequest - Emscripten XMLHttpRequest 调用的 C++ 端是什么?

    javascript - 如何更改传单指令上的默认图标图钉?