tensorflow是个强大的数值计算工具,同时也是强大的深度学习工具.当我们在用c++ api做推理的时候,如何将数据输入tensorflow, 有时候会感到迷惑,本文以图像分类为例子,做简单的说明:
我们还是以tensorflow examples中的label_image为例子进行说明.在例子中,main.cc用了ReadTensorFromImageFile函数从jpeg文件中解码并赋值给input tensor, 函数中,构建了一个file_reader的graph,让人感到很陌生和别扭,只是一个解码嘛,弄得这么封闭,其实大可不必,有两点不方便的地方吧:
1. 实际工程部署中,许多已经在用的解码器,比如opencv,libjpeg, libjpg-turbo, nvidia-codec等,不方便替换成tensorflow的这种形式;
2. 当解码视频等文件时,tensorflow又不支持这种operators
基于以上两点,下面以opencv为例子做说明,主要函数如下:
void mat2tensor(cv::Mat &img, Tensor *tensor, int batch, int height, int width, float mean, float std)
{
cv::resize(img, img, cv::Size(height, width));
cv::Mat image(height, width, CV_32FC3);
img.convertTo(image, CV_32FC3);
image -= mean;
image /= std;
// 注意tensorflow默认输入通道顺序NHWC
auto tensor_data = tensor->tensor();
// 简单的用一张图片赋值给多个batch
for(int b = 0; b < batch; b++)
{
for(int j = 0; j < height; j++)
{
for(int i = 0; i < width; i++)
{
cv::Vec3f pixel = image.at(j, i);
{
tensor_data(b, j, i, 0) = pixel[2]; //注意tensorflow默认的输入为RGB, 而opencv的输出为BGR
tensor_data(b, j, i, 1) = pixel[1];
tensor_data(b, j, i, 2) = pixel[0];
}
}
}
}
}
可以这样调用:
void ReadTensorFromImageFile(const string& file_name, int batch, const int input_height,
const int input_width, const float input_mean,
const float input_std,
std::vector* out_tensors)
{
Tensor t(tensorflow::DT_FLOAT, tensorflow::TensorShape({batch, input_height, input_width, 3}));
cv::Mat img = cv::imread(file_name.c_str());
mat2tensor(img, &t, batch, input_height, input_width, input_mean, input_std);
out_tensors->push_back(t);
}
一个推理的例子:
std::vector resized_tensors;
string image_path = "**";
ReadTensorFromVideoFile(image_path, 32, input_height, input_width, input_mean,
input_std, &resized_tensors);
string input_layer = "input";
string output_layer = "InceptionV3/Predictions/Reshape_1";
const Tensor& resized_tensor = resized_tensors[0];
std::vector outputs;
session->Run({{input_layer, resized_tensor}},{output_layer}, {}, &outputs);