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呼叫caffe的c++介面
之前簡單學習了一下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指令碼檔案,手動建立並命名
Caffe 的 C++介面學習(一)
Segnet-Caffe C++ 學習筆記 從之前的Segnet-Slam程式碼中設定斷點進行除錯: // OpenCV #include <opencv2/core/core.hpp> #include <opencv2
Windows下 Caffe C++介面的呼叫
Tips:此處是 Windows 下,新增 CPU 版 Caffe 原始碼的 C++ 工程,分為帶原始碼版(學習原始碼)和不帶原始碼版(直接用的),如果不是學習原始碼建議直接看B部分,不用拷貝原始碼過去。並且在安裝過程中如果是連結庫的問題,直接按照報錯提示增刪就
Windows下基於VS2013呼叫caffe的C++介面
同事用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開發介面想做得好看一些十分困難,引用第三方基於