简体   繁体   English

如何在 C++ 中将 TF_Tensor 转换为 opencv Mat?

[英]How to convert TF_Tensor to opencv Mat in C++?

I am trying to port Python Tensorflow model to C++.我正在尝试将 Python Tensorflow model 移植到 ZF6F87C9FDCF8B3C3F07F93F1EE8。 In process, I need to convert the TF_Tensor class to cv::Mat.在此过程中,我需要将 TF_Tensor class 转换为 cv::Mat。

I created the output tensor as the below.我创建了 output 张量,如下所示。

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

Then I loaded model and the session was completed successfully, but I failed to convert OutputValues to cv::Mat.然后我加载了 model 和 session 成功完成,但我未能将 OutputValues 转换为 cv::Mat。

I obtained a pointer to the data buffer by the code below.我通过下面的代码获得了指向数据缓冲区的指针。

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

But when I tried to create cv::Mat by the code below,但是当我尝试通过下面的代码创建 cv::Mat 时,

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

Image is not generated correctly.图像未正确生成。

I could not find any reference to TF_Tensor data structure, so I am asking for a help.我找不到任何对 TF_Tensor 数据结构的引用,所以我寻求帮助。

try :

cv::Mat mat(width, height, CV_32F);
std::memcpy((void *)mat.data, camBuf , sizeof(TF_Tensor*) * NumOutputs);

By doing:通过做:

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

you are "wrapping" the existing data in a cv::Mat , which avoids a copy.您正在将现有数据“包装”在cv::Mat中,从而避免复制。 Note that the third argument should be CV_32FC(3) (a 32-bit floating point image, with 3 channels).请注意,第三个参数应该是CV_32FC(3) (32 位浮点图像,具有 3 个通道)。 This approach should work if OutputValues is a TF_Tensor** type, and if the underlying TF_Tensor holds appropriate data.如果OutputValuesTF_Tensor**类型,并且基础TF_Tensor包含适当的数据,则此方法应该有效。

However, I don't think that this:但是,我不认为这是:

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

is an appropriate way to allocate a TF_Tensor;是分配 TF_Tensor 的合适方式; I think you should be using TF_AllocateTensor instead.我认为您应该改用TF_AllocateTensor

All that said, if you are using C++, you might consider using tf::Tensor API instead of TF_Tensor (which is used for C, and is less common).综上所述,如果您使用的是 C++,您可以考虑使用tf::Tensor API 而不是TF_Tensor (用于 Z0D61F8370CAD1D412F80B84D143E1257,不太常见)。

You omitted some details, but let's say your tensor is 4-dimensional (as is common), has float32 values, and is laid out as NxHxWxC (In other words, the tensor is holding a collection of float images).您省略了一些细节,但假设您的张量是 4 维的(很常见),具有 float32 值,并且布局为 NxHxWxC(换句话说,张量包含一组浮动图像)。 If you want to convert idx -th element in the batch to a cv::Mat , you can do it like this:如果要将批处理中的idx元素转换为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);                    
    }                                                                         
  }                                                                           
}  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM