我想将 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;
}
任何帮助,将不胜感激。
最佳答案
insert
在 flattened_image
多次调整向量的大小。此外,插入可能不如普通 std::copy
快。 (可以在这里完成)。确实,如果 planes[i].begin<T>()
和 planes[i].end<T>()
是微不足道的连续随机迭代器,std::copy
甚至可以memmove
或 memcpy
非常快的内存块。
因此,您可以先尝试使用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/