上一节,我讲到了用Session指针的run函数得到网络的输出。形式是
vector<Tensor>
现在我们看一个示范
status = session->Run(inputs, { "post_processing/result" }, {}, &outputs);
if (!status.ok()) {
cout << status.ToString() << "\n";
}
Tensor t = outputs[0]; //从节点取出第一个输出 "node :0"
TensorShape shape = t.shape();
cout << shape.dims() << std::endl; // 2 6
cout << shape.dim_size(0) << " " << shape.dim_size(1) << std::endl;
if (shape.dims() != 2) // num, 6
{
std::cout << "no bbox in this frame!" << std::endl;
}
else {
auto tmap = t.tensor<float, 2>();
int output_dim = shape.dim_size(0);
for (int i = 0; i < output_dim; i++)
{
cv::rectangle(img, cv::Point(tmap(i, 0), tmap(i, 1)), cv::Point(tmap(i, 2), tmap(i, 3)), Scalar(255, 0, 0));
}
}
~~对outputs我们需要使用输出节点的第一个输出(这句话对tensorflow了解的同学应该能明白,一个node的输出是有编号的~
因为我们在session->run中仅需要"post_processing/result"的输出,所以这里用index为0的位置得到这个节点的输出。
然后API提供了查看shape的函数。
重点是这里
auto tmap = t.tensor<float, 2>();
Tensor.tensor能帮助用户获得Tensor类型的数据接口,和OpenCV支持的Mat.data很相似。
然后我们就可以用圆括号来获得我们想获得的值。
在能获得我们想得到的值之前,我们需要对输出的shape有了解。如果输出是一个特征图,则
auto tmap = t.tensor<float, 4>();
如果是向量则,
auto tmap = t.tensor<float, 2>();
Note: 如果你对用到的pb模型不了解,还是先用
TensorShape shape = t.shape();
cout << shape.dims() << std::endl;
来看看输出是几维的。
然后就跟使用numpy一样方便了,
auto tmap = t.tensor<float, 2>();
int output_dim = shape.dim_size(0);
for (int i = 0; i < output_dim; i++)
{
cv::rectangle(img, cv::Point(tmap(i, 0), tmap(i, 1)),
cv::Point(tmap(i, 2), tmap(i, 3)), Scalar(255, 0, 0));
}
tmap就可以当做是sess.run输出的numpy数组了。用圆括号索引。注意output_dim是Batch size维度,就是第一维(index为0)。
比如:
tmap(0,0) 就是在第一行,第一列的值。 当然这是在输出是两维的情况下。即【batch size,classses num】
另外如果tmap(0)的输出是什么值得探讨,是一组float型的数组还是啥?
上面的代码,for循环要做的是,遍历模型输出的数组,得到每一个经过NMS的框,然后用opencv的函数画出来框。