【问题标题】:How to convert TF_Tensor to opencv Mat in C++?如何在 C++ 中将 TF_Tensor 转换为 opencv Mat?
【发布时间】:2020-08-13 06:00:43
【问题描述】:

我正在尝试将 Python TensorFlow 模型移植到 C++。 在此过程中,我需要将 TF_Tensor 类转换为 cv::Mat。

我创建了如下的输出张量。

TF_Tensor** OutputValues = (TF_Tensor**)malloc(sizeof(TF_Tensor*) * NumOutputs);

然后我加载了模型,会话成功完成,但是我未能将 OutputValues 转换为 cv::Mat。

我通过下面的代码获得了指向数据缓冲区的指针。

const float* camBuf = (float*)TF_TensorData(*OutputValues);

但是当我尝试通过下面的代码创建 cv::Mat 时,

cv::Mat testInputImage(
        80,
        80,
        3,
        TF_TensorData(*OutputValues)
    );

图像未正确生成。

我找不到任何对 TF_Tensor 数据结构的引用,所以我寻求帮助。

【问题讨论】:

    标签: c++ tensorflow opencv


    【解决方案1】:
    try :
    
    cv::Mat mat(width, height, CV_32F);
    std::memcpy((void *)mat.data, camBuf , sizeof(TF_Tensor*) * NumOutputs);
    

    【讨论】:

    • 您好!虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
    • 这个方法我已经试过了。我想问题是图像数据类型问题。不过还是谢谢你。
    【解决方案2】:

    通过做:

    cv::Mat testInputImage(80, 80, CV_32FC(3), TF_TensorData(*OutputValues));
    

    您正在将现有数据“包装”在cv::Mat 中,从而避免复制。请注意,第三个参数应为CV_32FC(3)(32 位浮点图像,具有 3 个通道)。 如果OutputValuesTF_Tensor** 类型,并且底层TF_Tensor 包含适当的数据,则此方法应该有效。

    但是,我不认为这是:

    TF_Tensor** OutputValues = (TF_Tensor**)malloc(sizeof(TF_Tensor*) * NumOutputs);
    

    是分配 TF_Tensor 的合适方式;我认为您应该改用TF_AllocateTensor

    综上所述,如果您使用 C++,您可能会考虑使用 tf::Tensor API 而不是 TF_Tensor(用于 C,并且不太常见)。

    您省略了一些细节,但假设您的张量是 4 维的(很常见),具有 float32 值,并且布局为 NxHxWxC(换句话说,张量包含浮动图像的集合)。 如果要将批处理中的idx-th 元素转换为cv::Mat,可以这样做:

    tf::Tensor tensor = /* tensor from somewhere */;
    int idx = /* index of the image in the batch */;
    
    int batch_size = tensor.dim_size(0);
    int rows = tensor.dim_size(1);                                                
    int cols = tensor.dim_size(2);                                                
    int channels = tensor.dim_size(3);                                            
    int row_size = channels * cols * sizeof(float);                               
                                                                                    
    cv::Mat image(rows, cols, CV_32FC(channels));                                
    auto tensor_mapped = tensor.tensor<float, 4>();                       
    for (int r = 0; r < rows; ++r) {                                              
      float* row = reinterpret_cast<float*>(mat.data + r * row_size);            
      for (int c = 0; c < cols; ++c) {                                  
        for (int k = 0; k < channels; ++k) {                                      
          row[k + c * channels] = tensor_mapped(idx, r, c, k);                    
        }                                                                         
      }                                                                           
    }  
    

    【讨论】:

      猜你喜欢
      • 2022-06-25
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      • 2017-02-10
      • 1970-01-01
      • 2017-06-03
      • 1970-01-01
      • 2011-09-12
      相关资源
      最近更新 更多