image - 将 3 通道图像转换为 T 型单向量的最快方法
问题描述
我想将 3 通道 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
on多次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())
. 第二个版本应该快一点。如果通道在内存中交错,则此代码不是最有效的,因为输入图像将在内存中多次读取。在这种情况下,最好在交叉通道的同时逐行遍历图像。
请注意,如果数据不连续,您还可以利用并行性和SIMD 指令来使此代码更快(OpenMP 可能是一个好的开始)。一旦优化,这样的计算应该受到内存层次结构速度的限制,因此在几乎所有相对较新的计算机上,1920x1080x4 的计算时间都不到 1 毫秒。
推荐阅读
- apache-kafka - KTABLE 未检测到相同的键。(插入记录而不是更新)
- javascript - 为什么我不能放线性梯度?
- javascript - Python - 字典的有序列表,有大小限制?
- python - 如何在 Windows 上设置 python 多处理
- c# - 开始游戏前等待按键?
- json - 通过 API 获取 Smartsheet 数据并创建 Wordpress html Post?
- excel - 将空白单元格与条件格式进行比较
- javascript - 我可以使用 AJAX 从不同的文件/视图/页面加载代码,以便可以执行类似于 SPA 的操作吗?
- ios - Swift Firebase 如何向我的用户添加自定义分支?
- java - 计算学生的 GPA