本文主要使用介绍使用 tensorflow API接口的基本流程,配合OpenCV读取图像数据。
#define COMPILER_MSVC
#define NOMINMAX
#define PLATFORM_WINDOWS
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/cc/ops/standard_ops.h"
#include <tensorflow/core/public/version.h>
#include "tensorflow/cc/ops/const_op.h"
#include "tensorflow/cc/ops/image_ops.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/graph/default_device.h"
#include "tensorflow/core/graph/graph_def_builder.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/stringpiece.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/lib/strings/stringprintf.h"
#include "tensorflow/core/util/command_line_flags.h"
#include "tensorflow/core/platform/init_main.h"
#include "tensorflow/core/platform/types.h"
#include <string.h>
#include <fstream>
#include <utility>
#include <Eigen/Core>
#include <Eigen/Dense>
#include<opencv2/opencv.hpp>
#include <iostream>
using tensorflow::string;
using namespace tensorflow;
using namespace std;
using namespace cv;
// Mat 数据转化为 Tensor
void CVMat_to_Tensor(Mat img, Tensor* output_tensor, int input_rows, int input_cols)
{
//imshow("input image",img);
//图像进行resize处理
// resize(img, img, cv::Size(input_cols, input_rows));
//imshow("resized image",img);
// 遍历 Mat数据结构
//for (int i = 0; i < input_rows; i++)
// for (int j = 0; j < input_cols; j++)
{
// //cout << float((img.at<uchar>(i, j))) << endl; // 直接输出uchar,将无法终端显示
// img.at<float>(i, j) = (float(img.at<uchar>(i, j)) - 2) / (4.0);
// cout << float((img.at<uchar>(i, j))) << endl;
// }
// 利用Opencv计算图像的均值和方差
Mat img_mean, img_std;
cv::meanStdDev(img, img_mean, img_std);
cout << "均值方差:" << img_mean.at<double>(0, 0) << " " << img_std.at<double>(0, 0) << endl;
//创建一个指向tensor的内容的指针
float *p = output_tensor->flat<float>().data();
//创建一个Mat,与tensor的指针绑定,改变这个Mat的值,就相当于改变tensor的值
cv::Mat tempMat(input_rows, input_cols, CV_32FC1, p);
img.convertTo(tempMat, CV_32FC1);
// 图像预处理通常放在 img.convertTo(tempMat, CV_32FC1)之后
tempMat = (tempMat - img_mean.at<double>(0, 0))/(img_std.at<double>(0, 0) + 1e-8);
}
vector<cv::Point> DL_Predict(string modelname)
{
/*--------------------------------配置关键信息------------------------------*/
string model_path = "./model-v4-240.pb";
//string image_path = "./test_data/wenshing3_0.png";
string path = "./test_data/tfile/" + modelname + "_0.png";
cout << "path: " << path << endl;
int input_height = 480;
int input_width = 240;
string input_tensor_name = "image";
string output_tensor_name = "Mconv7_stage6_L2/BiasAdd";
/*--------------------------------创建session------------------------------*/
Session* session;
Status status = NewSession(SessionOptions(), &session); //创建新会话Session
/*--------------------------------从pb文件中读取模型--------------------------------*/
GraphDef graphdef; //Graph Definition for current model
Status status_load = ReadBinaryProto(Env::Default(), model_path, &graphdef); //从pb文件中读取图模型;
if (!status_load.ok()) {
cout << "ERROR: Loading model failed ..." << model_path << std::endl;
cout << status_load.ToString() << "\n";
exit(0);
}
Status status_create = session->Create(graphdef); // 将模型导入会话Session中;
if (!status_create.ok()) {
cout << "ERROR: Creating graph in session failed..." << status_create.ToString() << std::endl;
exit(0);
}
cout << "<----Successfully created session and load graph.------->" << endl;
/*---------------------------------载入测试图片-------------------------------------*/
cout << endl << "<------------loading test_image-------------->" << endl;
Mat img = imread(path, 0);
if (img.empty())
{
cout << "can't open the image!!!!!!!" << endl;
exit(0);
}
//创建一个tensor作为网络输入的接口(接收输入数据)
Tensor resized_tensor(DT_FLOAT, TensorShape({ 1,input_height,input_width,1 }));
//将Opencv的Mat格式的图片存入tensor
CVMat_to_Tensor(img, &resized_tensor, input_height, input_width);
cout << "输入:" << resized_tensor.DebugString() << endl;
/*-----------------------------------用网络进行测试-----------------------------------------*/
cout << endl << "<-------------Running the model with test_image--------------->" << endl;
//前向运行,输出结果一定是一个tensor的vector
vector<tensorflow::Tensor> outputs;
string output_node = output_tensor_name;
Status status_run = session->Run({ { input_tensor_name, resized_tensor } }, { output_node }, {}, &outputs);
if (!status_run.ok()) {
cout << "ERROR: RUN failed..." << std::endl;
cout << status_run.ToString() << "\n";
exit(0);
}
// 获取网络输出的tensor结构,输出预测结果
cout << "Output tensor size:" << outputs.size() << std::endl;
for (std::size_t i = 0; i < outputs.size(); i++) {
cout << outputs[i].DebugString() << endl;
}
Tensor t = outputs[0]; // Fetch the first tenso
auto tmap = t.tensor<float, 4>(); // 输出为特征图,所以shape为4
// 输出预测结果,并后处理
ofstream fout("heapmap.txt");
float max = numeric_limits<float>::min();
float value;
vector<cv::Point> joint;
cv::Point p_joint;
for (int i = 0; i < 8; i++)
{
max = numeric_limits<float>::min();
for (int j = 0; j < 60; j++)
{
for (int k = 0; k < 30; k++)
{
// cout << tmap(0, j, k, i) << " " << std::endl;
// fout << tmap(0, j, k, i) << " ";
value = tmap(0, j, k, i); // 注意tensor的索引[batch, height, width, depth]
if (value > max)
{
max = value;
p_joint.x = k*8;
p_joint.y = j*8;
}
}
}
cout << "坐标值:" << p_joint.x << " " << p_joint.y << endl;
joint.push_back(p_joint);
}
return joint;
}