【问题标题】:Processing flutter images with C++ openCV使用 C++ openCV 处理颤振图像
【发布时间】:2022-06-22 05:53:04
【问题描述】:

我正在做一个项目,我想使用 C++ OpenCV 处理我的图像。

为简单起见,我只想将Uint8List 转换为cv::Mat 并返回。

按照this 教程,我设法制作了一个不会使应用程序崩溃的管道。具体来说:

  1. 我在.cpp 中创建了一个函数,它接收指向我的Uint8ListrawBytes 的指针,并将其编码为.jpg
    int encodeIm(int h, int w, uchar *rawBytes, uchar **encodedOutput) {
        cv::Mat img = cv::Mat(h, w, CV_8UC3, rawBytes); //CV_8UC3
        vector<uchar> buf;
        cv:imencode(".jpg", img, buf); // save output into buf. Note that Dart Image.memory can process either .png or .jpg, which is why we're doing this encoding
        *encodedOutput = (unsigned char *) malloc(buf.size());
        for (int i=0; i < buf.size(); i++)
            (*encodedOutput)[i] = buf[i];
        return (int) buf.size();
    }
  1. 然后我在.dart 中编写了一个函数,调用我的c++ encodeIm(int h, int w, uchar *rawBytes, uchar **encodedOutput)
   //allocate memory heap for the image
   Pointer<Uint8> imgPtr = malloc.allocate(imgBytes.lengthInBytes);

   //allocate just 8 bytes to store a pointer that will be malloced in C++ that points to our variably sized encoded image
   Pointer<Pointer<Uint8>> encodedImgPtr = malloc.allocate(8);

   //copy the image data into the memory heap we just allocated
   imgPtr.asTypedList(imgBytes.length).setAll(0, imgBytes);

   //c++ image processing
   //image in memory heap -> processing... -> processed image in memory heap
   int encodedImgLen = _encodeIm(height, width, imgPtr, encodedImgPtr);
   //

   //retrieve the image data from the memory heap
   Pointer<Uint8> cppPointer = encodedImgPtr.elementAt(0).value;
   Uint8List encodedImBytes = cppPointer.asTypedList(encodedImgLen);
   //myImg = Image.memory(encodedImBytes);
   return encodedImBytes;
   //free memory heap
   //malloc.free(imgPtr);
   //malloc.free(cppPointer);
   //malloc.free(encodedImgPtr); // always frees 8 bytes
 }
  1. 然后我通过以下方式将 c++ 与 dart 链接起来:
final DynamicLibrary nativeLib = Platform.isAndroid
    ? DynamicLibrary.open("libnative_opencv.so")
    : DynamicLibrary.process();

final int Function(int height, int width, Pointer<Uint8> bytes, Pointer<Pointer<Uint8>> encodedOutput) 
_encodeIm = nativeLib
        .lookup<NativeFunction<Int32 Function(Int32 height, Int32 width, 
Pointer<Uint8> bytes, Pointer<Pointer<Uint8>> encodedOutput)>>('encodeIm').asFunction();
  1. 最后我通过以下方式在 Flutter 中显示结果:
Image.memory(...)

现在,管道没有崩溃,这意味着我还没有完全搞砸内存处理,但它也没有返回原始图像,这意味着我确实在某个地方搞砸了。

原图:

管道输出:

【问题讨论】:

  • 你从哪里得到imgBytes?我敢打赌它不是 8 位无符号 3 通道。
  • @RichardHeap 这是我使用(await rootBundle .load('assets/images/tmp.jpeg')).buffer.asUint8List()从资产加载的图像
  • 如果是 jpeg,你为什么要告诉 Mat 是 8UC3? cv::Mat(h, w, CV_8UC3, rawBytes); //CV_8UC3
  • 我的意思是,rawBytes 参数和imgBytes 变量是 Uint8List,但是这个 Uint8List 我从存储在我的资产文件夹中的 .jpeg 中恢复。所以我不明白使用 8UC3 的问题,因为 Uint8List 是一个 8 位无符号整数列表,而我的图像有 3 个通道 - RGB
  • 但是 jpeg 是压缩的,你实际上是在告诉 Mat 数据是未压缩的。

标签: c++ flutter dart opencv dart-ffi


【解决方案1】:

感谢 Richard Heap 在 cmets 中的指导,我设法通过更改我的矩阵定义来修复管道

cv::Mat img = cv::Mat(h, w, CV_8UC3, rawBytes);

vector<uint8_t> buffer(rawBytes, rawBytes + inBytesCount);
Mat img = imdecode(buffer, IMREAD_COLOR);

其中inBytesCountimgBytes 的长度。

【讨论】:

    猜你喜欢
    • 2020-07-29
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 2011-01-17
    • 2012-07-20
    • 2015-07-26
    • 2021-09-26
    • 1970-01-01
    相关资源
    最近更新 更多