#include <iostream> #include "tensorflow/cc/ops/const_op.h" #include "tensorflow/cc/ops/image_ops.h" #include "tensorflow/cc/ops/standard_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/platform/env.h" #include "tensorflow/core/platform/init_main.h" #include "tensorflow/core/platform/logging.h" #include "tensorflow/core/platform/types.h" #include "tensorflow/core/public/session.h" #include "tensorflow/core/util/command_line_flags.h" #include <opencv2/opencv.hpp> #include <cv.h> #include <highgui.h> #include <Eigen/Core> #include <Eigen/Dense> using namespace std; using namespace cv; using namespace tensorflow; // 定義一個函數講OpenCV的Mat數據轉化為tensor,python里面只要對cv2.read讀進來的矩陣進行np.reshape之后, // 數據類型就成了一個tensor,即tensor與矩陣一樣,然后就可以輸入到網絡的入口了,但是C++版本,我們網絡開放的入口 // 也需要將輸入圖片轉化成一個tensor,所以如果用OpenCV讀取圖片的話,就是一個Mat,然后就要考慮怎么將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); //歸一化 img.convertTo(img,CV_8UC3); // CV_32FC3 //img=1-img/255; //創建一個指向tensor的內容的指針 uint8 *p = output_tensor->flat<uint8>().data(); //創建一個Mat,與tensor的指針綁定,改變這個Mat的值,就相當於改變tensor的值 cv::Mat tempMat(input_rows, input_cols, CV_8UC3, p); img.convertTo(tempMat,CV_8UC3); // waitKey(0); } int main() { /*--------------------------------配置關鍵信息------------------------------*/ string model_path="../model/coco.pb"; string image_path="../test.jpg"; int input_height = 1000; int input_width = 1000; string input_tensor_name="image_tensor"; vector<string> out_put_nodes; //注意,在object detection中輸出的三個節點名稱為以下三個 out_put_nodes.push_back("detection_scores"); //detection_scores detection_classes detection_boxes out_put_nodes.push_back("detection_classes"); out_put_nodes.push_back("detection_boxes"); /*--------------------------------創建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"; return -1; } Status status_create = session->Create(graphdef); //將模型導入會話Session中; if (!status_create.ok()) { cout << "ERROR: Creating graph in session failed..." << status_create.ToString() << std::endl; return -1; } cout << "<----Successfully created session and load graph.------->"<< endl; /*---------------------------------載入測試圖片-------------------------------------*/ cout<<endl<<"<------------loading test_image-------------->"<<endl; Mat img; img = imread(image_path); cvtColor(img, img, CV_BGR2RGB); if(img.empty()) { cout<<"can't open the image!!!!!!!"<<endl; return -1; } //創建一個tensor作為輸入網絡的接口 Tensor resized_tensor(DT_UINT8, TensorShape({1,input_height,input_width,3})); //DT_FLOAT //將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; Status status_run = session->Run({{input_tensor_name, resized_tensor}}, {out_put_nodes}, {}, &outputs); if (!status_run.ok()) { cout << "ERROR: RUN failed..." << std::endl; cout << status_run.ToString() << "\n"; return -1; } //把輸出值給提取出 cout << "Output tensor size:" << outputs.size() << std::endl; //3 for (int i = 0; i < outputs.size(); i++) { cout << outputs[i].DebugString()<<endl; // [1, 50], [1, 50], [1, 50, 4] } cvtColor(img, img, CV_RGB2BGR); // opencv讀入的是BGR格式輸入網絡前轉為RGB resize(img,img,cv::Size(1000,1000)); // 模型輸入圖像大小 int pre_num = outputs[0].dim_size(1); // 50 模型預測的目標數量 auto tmap_pro = outputs[0].tensor<float, 2>(); //第一個是score輸出shape為[1,50] auto tmap_clas = outputs[1].tensor<float, 2>(); //第二個是class輸出shape為[1,50] auto tmap_coor = outputs[2].tensor<float, 3>(); //第三個是coordinate輸出shape為[1,50,4] float probability = 0.5; //自己設定的score閾值 for (int pre_i = 0; pre_i < pre_num; pre_i++) { if (tmap_pro(0, pre_i) < probability) { break; } cout << "Class ID: " << tmap_clas(0, pre_i) << endl; cout << "Probability: " << tmap_pro(0, pre_i) << endl; string id = to_string(int(tmap_clas(0, pre_i))); int xmin = int(tmap_coor(0, pre_i, 1) * input_width); int ymin = int(tmap_coor(0, pre_i, 0) * input_height); int xmax = int(tmap_coor(0, pre_i, 3) * input_width); int ymax = int(tmap_coor(0, pre_i, 2) * input_height); cout << "Xmin is: " << xmin << endl; cout << "Ymin is: " << ymin << endl; cout << "Xmax is: " << xmax << endl; cout << "Ymax is: " << ymax << endl; rectangle(img, cvPoint(xmin, ymin), cvPoint(xmax, ymax), Scalar(255, 0, 0), 1, 1, 0); putText(img, id, cvPoint(xmin, ymin), FONT_HERSHEY_COMPLEX, 1.0, Scalar(255,0,0), 1); } imshow("1", img); cvWaitKey(0); return 0; }
CMakeLists.txt內容如下
cmake_minimum_required(VERSION 3.0.0) project(tensorflow_cpp) set(CMAKE_CXX_STANDARD 11) find_package(OpenCV 3.0 QUIET) if(NOT OpenCV_FOUND) find_package(OpenCV 2.4.3 QUIET) if(NOT OpenCV_FOUND) message(FATAL_ERROR "OpenCV > 2.4.3 not found.") endif() endif() set(TENSORFLOW_INCLUDES /usr/local/include/tf/ /usr/local/include/tf/bazel-genfiles /usr/local/include/tf/tensorflow/ /usr/local/include/tf/tensorflow/third_party) set(TENSORFLOW_LIBS /usr/local/lib/libtensorflow_cc.so /usr/local/lib//libtensorflow_framework.so) include_directories( ${TENSORFLOW_INCLUDES} ${PROJECT_SOURCE_DIR}/third_party/eigen3 ) add_executable(predict predict.cpp) target_link_libraries(predict ${TENSORFLOW_LIBS} ${OpenCV_LIBS} )
目錄結構如圖所示