无需复制即可将 OpenCV Mat 导入 C++ Tensorflow
Import OpenCV Mat into C++ Tensorflow without copying
我的目标是 运行 一个实时的 TensorFlow 模型,以根据学习的模型控制车辆。我们的车辆系统使用与 OpenCV 紧密相关的 ROS(机器人操作系统)。因此,我收到了一个包含来自 ROS 的感兴趣图像的 OpenCV Mat。
cv::Mat cameraImg;
我想直接从这个 OpenCV 矩阵中的数据创建一个 Tensorflow Tensor,以避免逐行复制矩阵的费用。使用 的答案,我已经设法让网络的前向传播与以下代码一起工作:
cameraImg.convertTo(cameraImg, CV_32FC3);
Tensor inputImg(DT_FLOAT, TensorShape({1,inputheight,inputwidth,3}));
auto inputImageMapped = inputImg.tensor<float, 4>();
auto start = std::chrono::system_clock::now();
//Copy all the data over
for (int y = 0; y < inputheight; ++y) {
const float* source_row = ((float*)cameraImg.data) + (y * inputwidth * 3);
for (int x = 0; x < inputwidth; ++x) {
const float* source_pixel = source_row + (x * 3);
inputImageMapped(0, y, x, 0) = source_pixel[2];
inputImageMapped(0, y, x, 1) = source_pixel[1];
inputImageMapped(0, y, x, 2) = source_pixel[0];
}
}
auto end = std::chrono::system_clock::now();
然而,使用这种方法复制到张量需要 80 毫秒到 130 毫秒,而整个正向传递(对于 10 层卷积网络)只需要 25 毫秒。
查看与 Tensors 相关的 the tensorflow documentation, it appears there is a Tensor constructor that takes an allocator. However, I have not been able to find any Tensorflow or Eigen documentation relating to this functionality or the Eigen Map class。
有没有人知道如何加速这段代码,最好是通过重新使用我的 OpenCV 内存?
编辑:
我已经成功地实现了@mrry 的建议,并且可以重新使用 OpenCV 分配的内存。我已经打开 github issue 8033 请求将其添加到 tensorflow 源代码树中。我的方法不是很漂亮,但是很管用。
编译一个外部库并link到libtensorflow.so库还是很困难的。 tensorflow cmake library 可能会对此有所帮助,我还没有尝试过。
TensorFlow C API(相对于 C++ API)导出 TF_NewTensor()
function, which allows you to create a tensor from a pointer and a length, and you can pass the resulting object to the TF_Run()
函数。
目前这是唯一的 public API 用于从预分配缓冲区创建 TensorFlow 张量的方法。没有支持将 TF_Tensor*
转换为 tensorflow::Tensor
的方法,但如果您查看实现,有一个具有 friend
访问权限的私有 API 可以执行此操作。如果您对此进行试验,并且可以显示出明显的加速,我们会考虑 feature request 将其添加到 public API.
我知道这是旧线程,但是使用现有的 C++ API 可以针对您的问题提供零复制解决方案:我用我的解决方案更新了您的 github 问题。 tensorflow/issues/8033
作为记录,我将我的解决方案复制到这里:
// allocate a Tensor
Tensor inputImg(DT_FLOAT, TensorShape({1,inputHeight,inputWidth,3}));
// get pointer to memory for that Tensor
float *p = inputImg.flat<float>().data();
// create a "fake" cv::Mat from it
cv::Mat cameraImg(inputHeight, inputWidth, CV_32FC3, p);
// use it here as a destination
cv::Mat imagePixels = ...; // get data from your video pipeline
imagePixels.convertTo(cameraImg, CV_32FC3);
希望对您有所帮助
我的目标是 运行 一个实时的 TensorFlow 模型,以根据学习的模型控制车辆。我们的车辆系统使用与 OpenCV 紧密相关的 ROS(机器人操作系统)。因此,我收到了一个包含来自 ROS 的感兴趣图像的 OpenCV Mat。
cv::Mat cameraImg;
我想直接从这个 OpenCV 矩阵中的数据创建一个 Tensorflow Tensor,以避免逐行复制矩阵的费用。使用
cameraImg.convertTo(cameraImg, CV_32FC3);
Tensor inputImg(DT_FLOAT, TensorShape({1,inputheight,inputwidth,3}));
auto inputImageMapped = inputImg.tensor<float, 4>();
auto start = std::chrono::system_clock::now();
//Copy all the data over
for (int y = 0; y < inputheight; ++y) {
const float* source_row = ((float*)cameraImg.data) + (y * inputwidth * 3);
for (int x = 0; x < inputwidth; ++x) {
const float* source_pixel = source_row + (x * 3);
inputImageMapped(0, y, x, 0) = source_pixel[2];
inputImageMapped(0, y, x, 1) = source_pixel[1];
inputImageMapped(0, y, x, 2) = source_pixel[0];
}
}
auto end = std::chrono::system_clock::now();
然而,使用这种方法复制到张量需要 80 毫秒到 130 毫秒,而整个正向传递(对于 10 层卷积网络)只需要 25 毫秒。
查看与 Tensors 相关的 the tensorflow documentation, it appears there is a Tensor constructor that takes an allocator. However, I have not been able to find any Tensorflow or Eigen documentation relating to this functionality or the Eigen Map class。
有没有人知道如何加速这段代码,最好是通过重新使用我的 OpenCV 内存?
编辑: 我已经成功地实现了@mrry 的建议,并且可以重新使用 OpenCV 分配的内存。我已经打开 github issue 8033 请求将其添加到 tensorflow 源代码树中。我的方法不是很漂亮,但是很管用。
编译一个外部库并link到libtensorflow.so库还是很困难的。 tensorflow cmake library 可能会对此有所帮助,我还没有尝试过。
TensorFlow C API(相对于 C++ API)导出 TF_NewTensor()
function, which allows you to create a tensor from a pointer and a length, and you can pass the resulting object to the TF_Run()
函数。
目前这是唯一的 public API 用于从预分配缓冲区创建 TensorFlow 张量的方法。没有支持将 TF_Tensor*
转换为 tensorflow::Tensor
的方法,但如果您查看实现,有一个具有 friend
访问权限的私有 API 可以执行此操作。如果您对此进行试验,并且可以显示出明显的加速,我们会考虑 feature request 将其添加到 public API.
我知道这是旧线程,但是使用现有的 C++ API 可以针对您的问题提供零复制解决方案:我用我的解决方案更新了您的 github 问题。 tensorflow/issues/8033
作为记录,我将我的解决方案复制到这里:
// allocate a Tensor
Tensor inputImg(DT_FLOAT, TensorShape({1,inputHeight,inputWidth,3}));
// get pointer to memory for that Tensor
float *p = inputImg.flat<float>().data();
// create a "fake" cv::Mat from it
cv::Mat cameraImg(inputHeight, inputWidth, CV_32FC3, p);
// use it here as a destination
cv::Mat imagePixels = ...; // get data from your video pipeline
imagePixels.convertTo(cameraImg, CV_32FC3);
希望对您有所帮助