image - 将 3 channel 图像转换为 T 型单向量的最快方法

标签 image opencv c++11 optimization c++17

我想将 3 channel RGB 图像展平为 T 类型的单个向量。在我的情况下,我专注于浮点数据类型。我写了一个运行良好的函数。但我想在不到 1MilliSecond 内完成这个操作。在这里,时间成本对我来说确实是一个问题。这是我的代码。

template<typename T>
inline std::vector<T> flatten_temp(cv::Mat frame_image)
{
    assert(!frame_image.empty());
    const int image_depth = frame_image.channels();
    frame_image.convertTo(frame_image, CV_32FC3);
    cv::Mat *planes =  new cv::Mat[image_depth];        
    
    // /** Split into BGR */
    cv::split(frame_image, planes);
    std::vector<T> flattened_image;
    
    flattened_image.assign(planes[0].begin<T>(), planes[0].end<T>());

    for (int i = 1; i < image_depth; ++i) {
        flattened_image.insert(flattened_image.end(), planes[i].begin<T>(), planes[i].end<T>());
    }
    frame_image.release();
    delete [] planes;
    return flattened_image;
}
任何帮助,将不胜感激。

最佳答案

insertflattened_image多次调整向量的大小。此外,插入可能不如普通 std::copy 快。 (可以在这里完成)。确实,如果 planes[i].begin<T>()planes[i].end<T>()是微不足道的连续随机迭代器,std::copy甚至可以memmovememcpy非常快的内存块。
因此,您可以先尝试使用flattened_image.reserve(image_width * image_height * image_depth) .然后,尝试将向量直接分配到合适的大小(用 0 自动填充),然后执行 std::copy(planes[i].begin<T>(), planes[i].end<T>(), flattened_image.begin()) .第二个版本应该快一点。如果 channel 在内存中交错,则此代码不是最有效的,因为输入图像将在内存中多次读取。在这种情况下,最好在交叉 channel 的同时逐行遍历图像。
请注意,如果数据不连续,您还可以利用并行性和 SIMD 指令来使此代码更快(OpenMP 可能是一个好的开始)。一旦优化,这样的计算应该受到内存层次结构速度的限制,因此在几乎所有相对较新的计算机上,1920x1080x4 的计算时间都不到 1 毫秒。

关于image - 将 3 channel 图像转换为 T 型单向量的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63682853/

相关文章:

C++。如何使用 sregex_token_iterator 检测匹配和不匹配的部分?

html - 第一次使用图像贴图

java - 停止循环 GIF 图标

opencv - 编译cv.h时出错 : No such file or directory

image - 检测图像中的比例尺 - 特征检测或模式识别

c++ - 如何在 C++ 中为 sqlite 进行非静态回调?

java - iTextPDF 到 OpenPDF 集成

java - 图像不会出现在 jar 中

python - 如何在Opencv中表示捕获的每个视频帧?

c++ - 将不同的 C++ 标准与 GCC 混合