How to use C++ to extract features from any image (read data from memory)
- 2020-05-19 05:15:56
- OfStack
Regarding the use of C++ interface to extract features, caffe officially provides a routine of extract_features.cpp. However, the input of this file is blob data. Even if the input layer USES ImageData, it needs to specify the location of the image in deploy.prototxt, which is very inconvenient.
If you want to read an image using opencv and extract features using caffe trained model, you need to rewrite the input layer. In addition, the default output of the official routine is in leveldb format, and we can also get multi-dimensional features (arrays) of type float, which is more flexible to integrate into our project.
01
First we need to rewrite deploy. The input layer of prototxt is "MemoryData" :
layer {
name: "data"
type: "MemoryData"
top: "data"
top: "label"
memory_data_param{
batch_size:1
channels:3
height:100
width:100
}
}
"ImageData", "Data" and so on May have been used in the previous training, but the change to "MemoryData" does not affect it.
02
I'm ready to extract the name of the layer is "res5_6", is "InnerProduct" 1 layer before, when I want to extract the "InnerProduct" the output of the whole connection layer, is always an error, prompt initial parameters and network parameters does not match (that is, trained model and now deploy network dimension is not 1), so I had to extract 1 layer before, and to connect the whole layer block, shield method is the name of the corresponding level in the prototxt break is good (relative to the caffemodel name). [the above problems have not been solved for the time being.
03
The following is the code of extract_features.cpp after the change:
#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;
/* Load model function */
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"); // Read test picture
cv::resize(src, src, cv::Size(100, 100)); // I'm going to put a picture here resize to prototxt The input layer inside the specified size
caffe::Net<NetTy>* _net = loadNet<NetTy>("face_example/face_deploy.prototxt", "face_example/face.caffemodel", caffe::TEST); // Load the network definition file and the parameter model
caffe::MemoryDataLayer<NetTy> *m_layer = (caffe::MemoryDataLayer<NetTy> *)_net->layers()[0].get(); // Define an in-memory data layer pointer
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); // Add pictures and tags to MemoryData layer
std::vector<caffe::Blob<NetTy>*> input_vec; // Nonsense for function arguments
_net->Forward(input_vec); // perform 1 Second forward calculation
boost::shared_ptr<caffe::Blob<NetTy>> layerData = _net->blob_by_name("res5_6"); // Gets the output of the specified layer
const NetTy* pstart = layerData->cpu_data(); // res5_6->cpu_data() It's a multi-dimensional data (array)
/*----- The output characteristics -----*/
for (int i = 0; i < 30000; i++)
{
std::cout << *pstart << endl;
pstart++;
}
return 0;
}