1. 程式人生 > >caffe 提取特徵C++介面

caffe 提取特徵C++介面

一、前言

     以下為使用caffe的C++介面提取某層的特徵向量,作下記錄,一下兩種方式耗時基本相同。

二、方式一

//CaffeExFeat.h
#ifndef CAFFEEXFEAT_H 
#define CAFFEEXFEAT_H

#include "caffe/caffe.hpp"
#include <string>
#include <vector>
#include "opencv2/opencv.hpp"


using namespace caffe;

class CaffeExFeat
{
	public:
		 explicit CaffeExFeat(std::string proto,std::string model,char* nameLayer,std::string meanFile,float scale=-1);
		 explicit CaffeExFeat(std::string proto,std::string model,char* nameLayer,float v1=0.0,float v2=0.0,float v3=0.0,float scale=-1);
		 ~CaffeExFeat();

		double*extractFeat(const cv::Mat& img);
		double calSimilarity(const cv::Mat& img1 ,const cv::Mat& img2);
	private:
		unsigned int blob_id_;
		boost::shared_ptr< Net<float> > net_;
		cv::Size input_geometry_;
		int num_channels_;
		cv::Mat mean_;
		Blob<float>* input_blobs_;
		unsigned int featNum_;
		float scale_;

		void init(std::string proto,std::string model,float scale);
	    void getMeanData(std::string mean_file);
	    void getMeanData(float v1,float v2,float v3 );
		unsigned int get_blob_index( char *query_blob_name);
		void wrapInputLayer(std::vector<cv::Mat>* input_channels);
		void preprocess(const cv::Mat& img,std::vector<cv::Mat>* input_channels);

};

#endif
//CaffeExFeat.cpp
#include "CaffeExFeat.h"

CaffeExFeat::CaffeExFeat(std::string proto,std::string model, char* nLayer,std::string meanFile,
	float scale)
{
	init(proto,model,scale);
	getMeanData(meanFile);
    blob_id_ = get_blob_index(nLayer);
}

CaffeExFeat::CaffeExFeat(std::string proto,std::string model, char* nLayer,float v1,float v2,float v3,
	float scale)
{
	init(proto,model,scale);
	getMeanData(v1,v2,v3);
    blob_id_ = get_blob_index(nLayer);
}

void CaffeExFeat::init(std::string proto,std::string model,float scale)
{
	scale_=scale;
	Phase phase = TEST;
	Caffe::set_mode(Caffe::CPU);
	net_ = boost::shared_ptr< Net<float> >(new caffe::Net<float>(proto, phase));
	net_->CopyTrainedLayersFrom(model);

	input_blobs_ = net_->input_blobs()[0];
	num_channels_ = input_blobs_->channels();
	input_geometry_ = cv::Size(input_blobs_->width(),input_blobs_->height());
	input_blobs_->Reshape(1, num_channels_,input_geometry_.height, input_geometry_.width); //難道可輸入多張圖
	
	net_->Reshape();  //維度改變
	
}

CaffeExFeat::~CaffeExFeat()
{
	
}

double* CaffeExFeat::extractFeat(const cv::Mat& img)
{
	std::vector<cv::Mat> input_channels;
	wrapInputLayer(&input_channels);
	preprocess(img, &input_channels);

    net_->ForwardPrefilled();
	boost::shared_ptr<Blob<float> > featBlob = net_->blobs()[blob_id_];
	featNum_ = featBlob->count();
    const float *featData = (const float *) featBlob->cpu_data();
    
    double* out = new double[featNum_];
    for(int k=0;k<featNum_;++k) out[k]=featData[k];

	return out;
}

double CaffeExFeat::calSimilarity(const cv::Mat& img1 ,const cv::Mat& img2)
{
	double* feat_1 = extractFeat(img1);
	double* feat_2 = extractFeat(img2);

	double sim = cblas_ddot(featNum_,feat_1,1,feat_2,1)/(std::sqrt(cblas_ddot(featNum_,feat_1,1,feat_1,1))*std::sqrt(cblas_ddot(featNum_,feat_2,1,feat_2,1)));
    delete []feat_1;
	delete []feat_2;

	return sim;
}

void CaffeExFeat::getMeanData(std::string mean_file)
{
  BlobProto blob_proto;  
  ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto);  
  
  /* Convert from BlobProto to Blob<float> */  
  Blob<float> mean_blob;  
  mean_blob.FromProto(blob_proto);  
  
  /* The format of the mean file is planar 32-bit float BGR or grayscale. */  
  std::vector<cv::Mat> channels;  
  float* data = mean_blob.mutable_cpu_data();  
  for (int i = 0; i < num_channels_; ++i) {  
    /* Extract an individual channel. */  
    cv::Mat channel(mean_blob.height(), mean_blob.width(), CV_32FC1, data);  
    channels.push_back(channel);  
    data += mean_blob.height() * mean_blob.width();  
  }  
  
  /* Merge the separate channels into a single image. */  
  cv::Mat mean;  
  cv::merge(channels, mean);  
  
  /* Compute the global mean pixel value and create a mean image 
   * filled with this value. */  
  cv::Scalar channel_mean = cv::mean(mean);  
  mean_ = cv::Mat(input_geometry_, mean.type(), channel_mean);  
}

void CaffeExFeat::getMeanData(float v1,float v2, float v3)
{
	cv::Scalar channel_mean(v1,v2,v3);
	mean_ = cv::Mat(input_geometry_,CV_32FC3,channel_mean );
}

unsigned int CaffeExFeat::get_blob_index( char *query_blob_name)
{
    std::string str_query(query_blob_name);    
    vector< string > const & blob_names = net_->blob_names();
    for( unsigned int i = 0; i != blob_names.size(); ++i ) 
    { 
        if( str_query == blob_names[i] ) 
        { 
            return i;
        } 
    }
    LOG(FATAL) << "Unknown blob name: " << str_query;
}

void CaffeExFeat::wrapInputLayer(std::vector<cv::Mat>* input_channels) {  
  Blob<float>* input_layer = net_->input_blobs()[0];  
  
  int width = input_layer->width();  
  int height = input_layer->height();  
  float* input_data = input_layer->mutable_cpu_data();  
  for (int i = 0; i < input_layer->channels(); ++i) {  
    cv::Mat channel(height, width, CV_32FC1, input_data);  
    input_channels->push_back(channel);  
    input_data += width * height;  
  }  
}

void CaffeExFeat::preprocess(const cv::Mat& img,std::vector<cv::Mat>* input_channels)
{
  cv::Mat sample;  
  if (img.channels() == 3 && num_channels_ == 1)  
    cv::cvtColor(img, sample, CV_BGR2GRAY);  
  else if (img.channels() == 4 && num_channels_ == 1)  
    cv::cvtColor(img, sample, CV_BGRA2GRAY);  
  else if (img.channels() == 4 && num_channels_ == 3)  
    cv::cvtColor(img, sample, CV_BGRA2BGR);  
  else if (img.channels() == 1 && num_channels_ == 3)  
    cv::cvtColor(img, sample, CV_GRAY2BGR);  
  else  
    sample = img; 

  cv::Mat sample_resized;
  if (sample.size() != input_geometry_)  
    cv::resize(sample, sample_resized, input_geometry_);  
  else  
    sample_resized = sample;

  cv::Mat sample_float;
  if (num_channels_ == 3)  
    sample_resized.convertTo(sample_float, CV_32FC3);  
  else  
    sample_resized.convertTo(sample_float, CV_32FC1);

  cv::Mat sample_normalized;  
  cv::subtract(sample_float, mean_, sample_normalized);
  
  if(scale_!=-1){
  	cv::multiply(scale_ ,sample_normalized,sample_normalized);  
  }
  
  cv::split(sample_normalized, *input_channels);
}

三、方式二

#ifndef CAFFEEXFEAT_H 
#define CAFFEEXFEAT_H

#include "caffe/caffe.hpp"
#include <string>
#include <vector>
#include "opencv2/opencv.hpp"


using namespace caffe;

class CaffeExFeat
{
	public:
		 explicit CaffeExFeat(std::string proto,std::string model,char* nameLayer,std::string meanFile,float scale=1.);
		 explicit CaffeExFeat(std::string proto,std::string model,char* nameLayer,float v1=0.0,float v2=0.0,float v3=0.0,float scale=1.);
		 ~CaffeExFeat();

		double*extractFeat(const cv::Mat& img);
		double calSimilarity(const cv::Mat& img1 ,const cv::Mat& img2);
	private:
		unsigned int blob_id;
		boost::shared_ptr< Net<float> > net;
		Blob<float>* input_blobs;
		int channel,width,height;
		unsigned int featNum;
		float *meanData;
		float scale_;

		void init(std::string proto,std::string model,float scale);
	    void getMeanData(std::string meanFile);
	    void getMeanData(float v1,float v2,float v3 );
		unsigned int get_blob_index( char *query_blob_name);
};

#endif
#include "CaffeExFeat.h"

CaffeExFeat::CaffeExFeat(std::string proto,std::string model, char* nLayer,std::string meanFile,float scale)
{
	init(proto,model,scale);
	getMeanData(meanFile);
    blob_id = get_blob_index(nLayer);
}

CaffeExFeat::CaffeExFeat(std::string proto,std::string model, char* nLayer,float v1,float v2,float v3,float scale)
{
	init(proto,model,scale);
	getMeanData(v1,v2,v3);
    blob_id = get_blob_index(nLayer);
}

void CaffeExFeat::init(std::string proto,std::string model,float scale)
{
	scale_=scale;
	Phase phase = TEST;
	Caffe::set_mode(Caffe::CPU);
	net = boost::shared_ptr< Net<float> >(new caffe::Net<float>(proto, phase));
	net->CopyTrainedLayersFrom(model);

	input_blobs = net->input_blobs()[0];
	channel = input_blobs->channels();
	width = input_blobs->width();
	height = input_blobs->height();
}

CaffeExFeat::~CaffeExFeat()
{
	delete meanData;
}

 double* CaffeExFeat::extractFeat(const cv::Mat& img)
{
	cv::Mat resizedImg;
	cv::resize(img , resizedImg, cv::Size(height,width)); //縮放和去均值
	float *input_data = input_blobs->mutable_cpu_data();
	
	for(int h=0;h<height; ++h){
		const uchar* ptr = img.ptr<uchar>(h);
		int img_index = 0;
		for(int w=0; w<width ;++w){
			for(int c=0;c<channel ;++c){
				int blob_index = (c*height+h)*width +w ;
				input_data[blob_index] =(static_cast<float>(ptr[img_index++])-meanData[blob_index])*scale_;
			}
		}
	}  

	net->ForwardPrefilled();
	boost::shared_ptr<Blob<float> > featBlob = net->blobs()[blob_id];

	featNum = featBlob->count(); 
	const float *featData = (const float *) featBlob->cpu_data();
	
	double* out = new double[featNum];
	for(int k=0;k<featNum;++k) out[k]=featData[k];

	return out;
}

double CaffeExFeat::calSimilarity(const cv::Mat& img1 ,const cv::Mat& img2)
{
	double* feat_1 = extractFeat(img1);
	double* feat_2 = extractFeat(img2);

	double sim = cblas_ddot(featNum,feat_1,1,feat_2,1)/(std::sqrt(cblas_ddot(featNum,feat_1,1,feat_1,1)
				)*std::sqrt(cblas_ddot(featNum,feat_2,1,feat_2,1)));
    delete []feat_1;
	delete []feat_2;

	return sim;
}


void CaffeExFeat::getMeanData(std::string meanFile)
{
	Blob<float> image_mean;  
	BlobProto blob_proto;  
	const float *mean_ptr;  
	unsigned int num_pixel;  
	  
	bool succeed = ReadProtoFromBinaryFile(meanFile, &blob_proto);  
	if (succeed)  
	{  
    	image_mean.FromProto(blob_proto);  
    	num_pixel = image_mean.count(); /* NCHW=1x3x256x256=196608 */  
    	mean_ptr = (const float *) image_mean.cpu_data();  
		meanData = new float[num_pixel];
		memcpy(meanData,mean_ptr,num_pixel*sizeof(float));
	}
}

void CaffeExFeat::getMeanData(float v1,float v2, float v3)
{
	int wh = width*height;
    meanData = new float[channel*wh];

	std::vector<float> vec;
	vec.push_back(v1);
	vec.push_back(v2);
	vec.push_back(v3);

	for(int c=0; c<channel ; ++c){
		for(int k=0;k<wh ;++k){
				meanData[k+c*wh] = vec[c];
		}
	}

}

unsigned int CaffeExFeat::get_blob_index( char *query_blob_name)
{
    std::string str_query(query_blob_name);    
    vector< string > const & blob_names = net->blob_names();
    for( unsigned int i = 0; i != blob_names.size(); ++i ) 
    { 
        if( str_query == blob_names[i] ) 
        { 
            return i;
        } 
    }
    LOG(FATAL) << "Unknown blob name: " << str_query;
}
//main.cpp
#include "CaffeExFeat.h"

#include <iostream>

int main(int argc,char**argv)
{

    caffe::GlobalInit(&argc,&argv);  //關掉Log
    std::string proto = "***.prototxt";
    std::string model = "***.caffemodel";
	
    CaffeExFeat exFeater(proto,model,(char*)"fc5", 127.5,127.5,127.5 ,1./128);

 
    cv::Mat img_1 = cv::imread(path);  
  double* feat = extractFeat(img_1);
   delete[] feat;
   return 0;
}

四、編譯下

g++ CaffeExFeat.cpp main.cpp -o main -D CPU_ONLY -I /home/trainer/Jyang/caffe-intel/include -L /home/trainer/Jyang/caffe-intel/build/lib -lcblas -lpthread  -lcaffe -lboost_system -lglog `pkg-config opencv --libs --cflags`

相關推薦

caffe 提取特徵C++介面

一、前言     以下為使用caffe的C++介面提取某層的特徵向量,作下記錄,一下兩種方式耗時基本相同。二、方式一//CaffeExFeat.h #ifndef CAFFEEXFEAT_H #define CAFFEEXFEAT_H #include "caffe/ca

caffe 提取特徵caffe介面

//CaffeExFeat.h #ifndef CAFFEEXFEAT_H  #define CAFFEEXFEAT_H   #include "caffe/caffe.hpp" #include <string> #include <vector> #i

kaldi中特徵提取C++介面設計

FEMfcc.h class FEMFCC { public: FEMFCC(); ~FEMFCC(); //Initialze int Init(); void Uninit(); int ProcessP

caffe提取特徵時,需要注意

提取特徵時注意: 1、將mirror關閉 2、最後一層刪掉(計算損失,準確率的) 3、輸入改成dim:1那種 其中feature_extraction_file.bat裡的E:/caffe-windows/caffe_learn/model/S.txt 13233

使用深度學習Caffe框架的C++介面進行物體分類

實現目標: 1、載入一張圖片,應用深度學習框架Caffe訓練好的模型分類圖片,顯示圖片的類別,輸出到控制檯; 2、載入一個資料夾,分類所有資料夾內的圖片,非圖片檔案選擇無視,生成同名txt儲存所屬類別。 3、工程project實現 一、/home/name/ca

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

0x00 關於使用C++介面來提取特徵,caffe官方提供了一個extract_features.cpp的例程,但是這個檔案的輸入是blob資料,即使輸入層使用的是ImageData,也需要在deploy.prototxt中指定圖片的位置,很不方便。 如果想要使用opencv來讀取

Caffe Python介面多程序提取特徵

原文地址:http://yongyuan.name/blog/caffe-python-extract-feature-parallel.html https://thief.one/2016/11/24/Multiprocessing-Pool/ https://jing

利用Clion呼叫caffec++介面

之前簡單學習了一下CMake的知識,現在就應用到caffe裡. CLION呼叫caffe關鍵是CMakeLists.txt檔案的編寫,涉及到一些CMake的知識. 首先用CLion建立一個caffeReadImgClassify工程,這時候發現工程目錄下有main.cpp和CmakeLi

caffe提取某層特徵進行人臉識別原始碼

在上一篇博文Classifier的c++類的基礎上進行擴充套件,其中標頭檔案Classifier.h如下: #include <caffe/caffe.hpp> #ifdef USE_OPENCV #include <opencv2/core

Windows Caffe 學習筆記(二)提取特徵

這次的筆記是記錄如何從預先訓練的模型中提取特徵。仍然是由於Windows版本Caffe的問題,繞了一些彎路。 正文如下: 1.選擇執行的資料 在examples/下新建一個資料夾,命名為_te

Caffe提取任意層特徵並進行視覺化

原圖 conv1層視覺化結果 (96個filter得到的結果) 資料模型與準備 安裝好Caffe後,在examples/images資料夾下有兩張示例影象,本文即在這兩張影象上,用Caffe提供的預訓練模型,進行特徵提取,並進行視覺化。 1. 進入

caffe提取任意層深度特徵

一.資料模型與準備 (1) 進入caffe根目錄,建立臨時資料夾,用於存放所需要的臨時檔案 cd caffe mkdir examples/_temp 我們首先生成temp.txt(帶標籤)檔案 接下來我們要建立一個sh指令碼檔案,手動建立並命名

CaffeC++介面學習(一)

Segnet-Caffe C++ 學習筆記 從之前的Segnet-Slam程式碼中設定斷點進行除錯: // OpenCV #include <opencv2/core/core.hpp> #include <opencv2

Windows下 Caffe C++介面的呼叫

Tips:此處是 Windows 下,新增 CPU 版 Caffe 原始碼的 C++ 工程,分為帶原始碼版(學習原始碼)和不帶原始碼版(直接用的),如果不是學習原始碼建議直接看B部分,不用拷貝原始碼過去。並且在安裝過程中如果是連結庫的問題,直接按照報錯提示增刪就

Windows下基於VS2013呼叫caffeC++介面

   同事用VGG16訓練了一個人臉識別的網路,我想試試C++介面,這裡做一下記錄。    參考文章如下:    按照參考文章的步驟,先用VS2013新建一個工程,將D:\caffe-master\examples\cpp_classification\classificat

caffe使用ctrl-c不能保存模型

_id solver caf sig txt pro 輸出 log ctrl caffe使用Ctrl-c 不能保存模型:   是因為使用的是 tee輸出日誌   解決方法:kill -s SIGINT <proc_id>   或者使用

SQLite - C/C++介面 API(二)

  1、開啟資料庫 SQLITE_API int sqlite3_open16(   const void *filename, /* Database filename (UTF-16) */   sqlite3 **ppDb /* OUT: SQLite db handle */);SQLI

win10編譯tensorflow C++介面

首先,我覺得這是一個比較DT的活,因為,tensorflow支援最好的程式語言應該是python(應該說大部分深度學習框架支援的最好的語言都是Python),tensorflow的底層說是C/C++編寫的,但是,感覺它對C/C++真的很不友好,有關Python的資料一查一大把,有關C/C++的一

Ubuntu16.04編譯tensorflow的C++介面

之前有一篇介紹到在windows下利用VS2015編譯tensorflow的C++介面,接下來這篇就介紹下在Ubuntu下編譯tensorflow的C++介面。 先說一下我的電腦配置,首先是Ubuntu16.04,anaconda用的是3.4.2,CUDA用的是9.0的,cudnn用的是7.

為什麼 qt 成為 c++ 介面程式設計的第一選擇?

為什麼qt成為c++介面程式設計的第一選擇 一、前言 為什麼現在QT越來越成為介面程式設計的第一選擇,筆者從事qt介面程式設計已經有接近8年,在這之前我做C++介面都是基於MFC,也做過5年左右。當時為什麼會從MFC轉到QT,主要原因是MFC開發介面想做得好看一些十分困難,引用第三方基於