caffe:使用C++來提取任意一張圖片的特徵

0x00

關於使用C++接口來提取特徵,caffe官方提供了一個extract_features.cpp的例程,可是這個文件的輸入是blob數據,即便輸入層使用的是ImageData,也須要在deploy.prototxt中指定圖片的位置,很不方便。ios

若是想要使用opencv來讀取一個圖片,而後用caffe訓練好的model提取特徵,就須要對輸入層進行改寫。另外官方例程默認的輸出是leveldb格式,咱們也能夠獲取float類型的多維特徵(數組),這樣集成到咱們的項目中更靈活。數組

0x01

首先咱們須要改寫deploy.prototxt的輸入層爲"MemoryData":網絡

layer {
  name: "data"
  type: "MemoryData"
  top: "data"
  top: "label"
  
  memory_data_param{
    batch_size:1
    channels:3
    height:100
    width:100
  }
}

在以前的訓練中可能使用的是"ImageData"、"Data"之類的,如今改爲MemoryData不影響。less

0x02

我準備提取的層的名字是"res5_6",就是"InnerProduct"的前一層,當我想提取"InnerProduct"全鏈接層的輸出時,老是報錯,提示原始參數和網絡參數不匹配(就是訓練好的model和如今deploy的網絡維度不同),因此只好提取前一層了,而且要把全鏈接層屏蔽掉,屏蔽的方法是把prototxt裏相應層的名字改掉就好(相對於caffemodel裏面的名字)。[以上問題暫時還沒解決,留坑]函數

0x03

下面是更改以後的 extract_features.cpp的代碼:測試

#include <stdio.h>  #include <string> #include <vector> #include <iostream> #include <opencv2/opencv.hpp> #include "boost/algorithm/string.hpp" #include "google/protobuf/text_format.h" #include "caffe/blob.hpp" #include "caffe/common.hpp" #include "caffe/net.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" #include "caffe/layers/memory_data_layer.hpp" #define NetTy float  using namespace caffe; using std::cout; using std::endl; using std::string; /* 加載模型函數 */ template <typename Dtype> caffe::Net<Dtype>* loadNet(std::string param_file, std::string pretrained_param_file, caffe::Phase phase) { caffe::Net<Dtype>* net(new caffe::Net<Dtype>(param_file, phase)); net->CopyTrainedLayersFrom(pretrained_param_file); return net; } int main() { cv::Mat src; src = cv::imread("face_example/test.jpg"); // 讀取測試圖片 cv::resize(src, src, cv::Size(100, 100)); // 這裏要將圖片resize到prototxt裏面的輸入層指定的大小 caffe::Net<NetTy>* _net = loadNet<NetTy>("face_example/face_deploy.prototxt", "face_example/face.caffemodel", caffe::TEST); // 加載網絡定義文件和參數模型 caffe::MemoryDataLayer<NetTy> *m_layer = (caffe::MemoryDataLayer<NetTy> *)_net->layers()[0].get(); // 定義個內存數據層指針 std::vector<cv::Mat> dv = { src }; // AddMatVector(const vector<cv::Mat>& mat_vector,const vector<int>& labels) std::vector<int> label = { 0 }; // ------------------------------------------------------------------------- m_layer->AddMatVector(dv, label); // 把圖片和標籤,添加到 MemoryData層 std::vector<caffe::Blob<NetTy>*> input_vec; // 無心義,爲了函數參數須要 _net->Forward(input_vec); // 執行一次前向計算 boost::shared_ptr<caffe::Blob<NetTy>> layerData = _net->blob_by_name("res5_6"); // 得到指定層的輸出 const NetTy* pstart = layerData->cpu_data(); // res5_6->cpu_data()返回的是多維數據(數組) /*-----輸出特徵-----*/ for (int i = 0; i < 30000; i++) { std::cout << *pstart << endl; pstart++; } return 0; }
相關文章
相關標籤/搜索