将OpenCV Mat导入C++ Tensorflow而不进行复制

Pau*_*aul 10 c++ opencv ros tensorflow

我的目标是实时运行TensorFlow模型,从学习模型中控制车辆.我们的车辆系统使用与OpenCV紧密相连的ROS(机器人操作系统).所以,我收到一个包含ROS感兴趣图像的OpenCV Mat.

    cv::Mat cameraImg;
Run Code Online (Sandbox Code Playgroud)

我想直接从这个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();
Run Code Online (Sandbox Code Playgroud)

但是,使用这种方法,复制到张量的时间在80ms到130ms之间,而整个前向传递(对于10层卷积网络)只需要25ms.

查看tensorflow文档,看起来有一个Tensor构造函数需要一个分配器.但是,我无法找到与此功能相关的任何Tensorflow或Eigen文档或与Tensors相关的Eigen Map类.

有没有人知道如何加速这段代码,理想情况下重新使用我的OpenCV内存?

编辑: 我已经成功实现了@mrry建议的内容,并且可以重用OpenCV分配的内存.我打开了github问题8033,请求将其添加到tensorflow源树.我的方法不是那么漂亮,但它有效.

编译外部库并将其链接到libtensorflow.so库仍然非常困难.潜在的tensorflow CMake的库将解决这个问题,我还没有尝试过.

小智 14

我知道它是旧线程,但使用现有的C++ API有一个零拷贝解决方案:我用我的解决方案更新了你的github问题.tensorflow /问题/ 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);
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助

  • 对具有一批图像的张量执行此操作的任何方法?例如。`Tensor inputImg(DT_FLOAT,TensorShape({4,inputHeight,inputWidth,3}));`由于张量不可下标,我想您会为每个图像创建张量,将`cv :: Mat`加载到其中,并以某种方式组合它们以破坏“ inputImg”。如果是这样,是否有一种方法来组合张量? (2认同)

mrr*_*rry 9

TensorFlow C API(与C++ API相对)导出TF_NewTensor()函数,该函数允许您从指针和长度创建张量,并且可以将结果对象传递给TF_Run()函数.

目前,这是从预先分配的缓冲区创建TensorFlow张量的唯一公共API.没有支持的方法来转换TF_Tensor*为a tensorflow::Tensor但是如果你看一下实现,那么有一个friend可以访问的私有API 可以做到这一点.如果您尝试使用此功能,并且可以显示可观的加速,我们会考虑将此功能添加到公共API 的功能请求.