从 16UC3 到 8UC3 的高性能 OpenCV 矩阵转换

High performance OpenCV matrix conversion from 16UC3 to 8UC3

我有一个 OpenCV CV_16UC3 矩阵,其中每个通道仅占用较低的 8 位。我想从中创建一个 CV_8UC3。目前我使用这个方法:

cv::Mat mat8uc3_rgb(imgWidth, imgHeight, CV_8UC3);
mat16uc3_rgb.convertTo(mat8uc3_rgb, CV_8UC3);

这达到了预期的结果,但我想知道它是否可以以某种方式更快或更高效。

编辑:

整个处理链仅包含 4 个子步骤(计算时间由 QueryPerformanceCounter 对视频场景的测量确定)

  1. 在 OpenCV-Mat 中挂载原始字节缓冲区: cv::Mat mat16uc1_bayer(imgHeight, RawImageWidth, CV_16UC1, (uint8*)payload);

  2. 去马赛克 -> cv::cvtColor(mat16uc1_bayer, mat16uc3_rgb, cv::COLOR_BayerGR2BGR);
    需要 0.008808[s]

  3. pixel shift(16位只占用了12位,而我们只需要8位) -> 使用 openCV 并行访问使用 mat16uc3_rgb.forEach<>
    的像素 需要 0.004927[s]

  4. 从 CV_16UC3 到 CV_8UC3 的转换 mat16uc3_rgb.convertTo(mat8uc3_rgb, CV_8UC3); 需要 0.006913[s]

我想如果不将原始缓冲区转换为 CvMat 或 demosaiking,我将无法完成。像素偏移可能不会进一步加速(这里已经使用了并行化的 forEach())。我希望当从 CV_8UC3 转换为 CV_16UC3 时,矩阵头信息或类似信息的更新是可能的,因为矩阵数据已经正确并且不必再缩放或类似。

我认为您可以安全地假设 cv::Mat::convertTo 是该操作的最快可能实现。 看到您从一个色彩空间转到另一个色彩空间,这可能不是零成本操作。重新排列需要内存拷贝。

如果您正在设计一个非常高性能的系统,您应该深入分析您的瓶颈,并重新设计您的系统以最小化它们。问问自己:此时真的需要这种转换吗?我可以通过制作一个将多个操作集成在一个自定义函数中来解决它吗?我可以使用 CPU 并行扩展、多线程或 GPU 加速吗?等等