parent
9fdc78a302
commit
391596a1b2
10 changed files with 564 additions and 149 deletions
Binary file not shown.
Binary file not shown.
@ -0,0 +1,202 @@ |
|||||||
|
#include <stdio.h> // for snprintf |
||||||
|
#include <string> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include "boost/algorithm/string.hpp" |
||||||
|
#include "google/protobuf/text_format.h" |
||||||
|
#define CPU_ONLY |
||||||
|
#include "caffe/blob.hpp" |
||||||
|
#include "caffe/common.hpp" |
||||||
|
#include "caffe/net.hpp" |
||||||
|
#include "caffe/proto/caffe.pb.h" |
||||||
|
#include "caffe/util/db.hpp" |
||||||
|
#include "caffe/util/io.hpp" |
||||||
|
#include "caffe/vision_layers.hpp" |
||||||
|
|
||||||
|
using caffe::Blob; |
||||||
|
using caffe::Caffe; |
||||||
|
using caffe::Datum; |
||||||
|
using caffe::Net; |
||||||
|
using boost::shared_ptr; |
||||||
|
using std::string; |
||||||
|
namespace db = caffe::db; |
||||||
|
|
||||||
|
template<typename Dtype> |
||||||
|
int feature_extraction_pipeline(int argc, char** argv); |
||||||
|
int main(int argc, char** argv) { |
||||||
|
return feature_extraction_pipeline<float>(argc, argv); |
||||||
|
// return feature_extraction_pipeline<double>(argc, argv);
|
||||||
|
} |
||||||
|
|
||||||
|
template<typename Dtype> |
||||||
|
int feature_extraction_pipeline(int argc, char** argv) { |
||||||
|
::google::InitGoogleLogging(argv[0]); |
||||||
|
const int num_required_args = 7; |
||||||
|
/*if (argc < num_required_args) {
|
||||||
|
LOG(ERROR)<< |
||||||
|
"This program takes in a trained network and an input data layer, and then" |
||||||
|
" extract features of the input data produced by the net.\n" |
||||||
|
"Usage: extract_features pretrained_net_param" |
||||||
|
" feature_extraction_proto_file extract_feature_blob_name1[,name2,...]" |
||||||
|
" save_feature_dataset_name1[,name2,...] num_mini_batches db_type" |
||||||
|
" [CPU/GPU] [DEVICE_ID=0]\n" |
||||||
|
"Note: you can extract multiple features in one pass by specifying" |
||||||
|
" multiple feature blob names and dataset names seperated by ','." |
||||||
|
" The names cannot contain white space characters and the number of blobs" |
||||||
|
" and datasets must be equal."; |
||||||
|
return 1; |
||||||
|
}*/ |
||||||
|
int arg_pos = num_required_args; |
||||||
|
|
||||||
|
arg_pos = num_required_args; |
||||||
|
//if (argc > arg_pos && strcmp(argv[arg_pos], "GPU") == 0) {
|
||||||
|
if (argc > arg_pos && strcmp("CPU", "GPU") == 0) { |
||||||
|
LOG(ERROR)<< "Using GPU"; |
||||||
|
int device_id = 0; |
||||||
|
if (argc > arg_pos + 1) { |
||||||
|
device_id = atoi(argv[arg_pos + 1]); |
||||||
|
CHECK_GE(device_id, 0); |
||||||
|
} |
||||||
|
LOG(ERROR) << "Using Device_id=" << device_id; |
||||||
|
Caffe::SetDevice(device_id); |
||||||
|
Caffe::set_mode(Caffe::GPU); |
||||||
|
} else { |
||||||
|
LOG(ERROR) << "Using CPU"; |
||||||
|
Caffe::set_mode(Caffe::CPU); |
||||||
|
} |
||||||
|
|
||||||
|
arg_pos = 0; // the name of the executable
|
||||||
|
//std::string pretrained_binary_proto(argv[++arg_pos]);
|
||||||
|
std::string pretrained_binary_proto("/home/wangyida/Desktop/caffe/examples/triplet/3d_triplet_iter_200.caffemodel"); |
||||||
|
|
||||||
|
// Expected prototxt contains at least one data layer such as
|
||||||
|
// the layer data_layer_name and one feature blob such as the
|
||||||
|
// fc7 top blob to extract features.
|
||||||
|
/*
|
||||||
|
layers { |
||||||
|
name: "data_layer_name" |
||||||
|
type: DATA |
||||||
|
data_param { |
||||||
|
source: "/path/to/your/images/to/extract/feature/images_leveldb" |
||||||
|
mean_file: "/path/to/your/image_mean.binaryproto" |
||||||
|
batch_size: 128 |
||||||
|
crop_size: 227 |
||||||
|
mirror: false |
||||||
|
} |
||||||
|
top: "data_blob_name" |
||||||
|
top: "label_blob_name" |
||||||
|
} |
||||||
|
layers { |
||||||
|
name: "drop7" |
||||||
|
type: DROPOUT |
||||||
|
dropout_param { |
||||||
|
dropout_ratio: 0.5 |
||||||
|
} |
||||||
|
bottom: "fc7" |
||||||
|
top: "fc7" |
||||||
|
} |
||||||
|
*/ |
||||||
|
//std::string feature_extraction_proto(argv[++arg_pos]);
|
||||||
|
std::string feature_extraction_proto("/home/wangyida/Desktop/caffe/examples/triplet/3d_triplet.prototxt"); |
||||||
|
boost::shared_ptr<Net<Dtype> > feature_extraction_net( |
||||||
|
new Net<Dtype>(feature_extraction_proto, caffe::TEST)); |
||||||
|
feature_extraction_net->CopyTrainedLayersFrom(pretrained_binary_proto); |
||||||
|
|
||||||
|
//std::string extract_feature_blob_names(argv[++arg_pos]);
|
||||||
|
std::string extract_feature_blob_names("feat"); |
||||||
|
std::vector<std::string> blob_names; |
||||||
|
boost::split(blob_names, extract_feature_blob_names, boost::is_any_of(",")); |
||||||
|
|
||||||
|
//std::string save_feature_dataset_names(argv[++arg_pos]);
|
||||||
|
std::string save_feature_dataset_names("/home/wangyida/Desktop/caffe/examples/triplet/feature_extracted"); |
||||||
|
std::vector<std::string> dataset_names; |
||||||
|
boost::split(dataset_names, save_feature_dataset_names, |
||||||
|
boost::is_any_of(",")); |
||||||
|
CHECK_EQ(blob_names.size(), dataset_names.size()) << |
||||||
|
" the number of blob names and dataset names must be equal"; |
||||||
|
size_t num_features = blob_names.size(); |
||||||
|
|
||||||
|
for (size_t i = 0; i < num_features; i++) { |
||||||
|
CHECK(feature_extraction_net->has_blob(blob_names[i])) |
||||||
|
<< "Unknown feature blob name " << blob_names[i] |
||||||
|
<< " in the network " << feature_extraction_proto; |
||||||
|
} |
||||||
|
|
||||||
|
//int num_mini_batches = atoi(argv[++arg_pos]);
|
||||||
|
int num_mini_batches = atoi("6"); |
||||||
|
|
||||||
|
/*std::vector<shared_ptr<db::DB> > feature_dbs;
|
||||||
|
std::vector<shared_ptr<db::Transaction> > txns; |
||||||
|
const char* db_type = argv[++arg_pos]; |
||||||
|
for (size_t i = 0; i < num_features; ++i) { |
||||||
|
LOG(INFO)<< "Opening dataset " << dataset_names[i]; |
||||||
|
shared_ptr<db::DB> db(db::GetDB(db_type)); |
||||||
|
db->Open(dataset_names.at(i), db::NEW); |
||||||
|
feature_dbs.push_back(db); |
||||||
|
shared_ptr<db::Transaction> txn(db->NewTransaction()); |
||||||
|
txns.push_back(txn); |
||||||
|
}*/ |
||||||
|
std::vector<FILE*> files; |
||||||
|
for (size_t i = 0; i < num_features; ++i) |
||||||
|
{ |
||||||
|
LOG(INFO) << "Opening file " << dataset_names[i]; |
||||||
|
FILE * temp = NULL; |
||||||
|
temp = fopen(dataset_names[i].c_str(), "wb"); |
||||||
|
files.push_back(temp); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
LOG(ERROR)<< "Extacting Features"; |
||||||
|
|
||||||
|
//bool header_flag = true;
|
||||||
|
|
||||||
|
Datum datum; |
||||||
|
//const int kMaxKeyStrLength = 100;
|
||||||
|
//char key_str[kMaxKeyStrLength];
|
||||||
|
std::vector<Blob<float>*> input_vec; |
||||||
|
std::vector<int> image_indices(num_features, 0); |
||||||
|
for (int batch_index = 0; batch_index < num_mini_batches; ++batch_index) { |
||||||
|
feature_extraction_net->Forward(input_vec); |
||||||
|
for (int i = 0; i < num_features; ++i) { |
||||||
|
const boost::shared_ptr<Blob<Dtype> > feature_blob = feature_extraction_net |
||||||
|
->blob_by_name(blob_names[i]); |
||||||
|
int batch_size = feature_blob->num(); |
||||||
|
int dim_features = feature_blob->count() / batch_size; |
||||||
|
if (batch_index == 0) |
||||||
|
{ |
||||||
|
int fea_num = batch_size*num_mini_batches; |
||||||
|
fwrite(&dim_features, sizeof(int), 1, files[i]); |
||||||
|
fwrite(&fea_num, sizeof(int), 1, files[i]); |
||||||
|
//bool header_flag = false;
|
||||||
|
} |
||||||
|
const Dtype* feature_blob_data; |
||||||
|
for (int n = 0; n < batch_size; ++n) { |
||||||
|
|
||||||
|
feature_blob_data = feature_blob->cpu_data() + |
||||||
|
feature_blob->offset(n); |
||||||
|
fwrite(feature_blob_data, sizeof(Dtype), dim_features, files[i]); |
||||||
|
|
||||||
|
++image_indices[i]; |
||||||
|
if (image_indices[i] % 1000 == 0) { |
||||||
|
LOG(ERROR)<< "Extracted features of " << image_indices[i] << |
||||||
|
" query images for feature blob " << blob_names[i]; |
||||||
|
} |
||||||
|
} // for (int n = 0; n < batch_size; ++n)
|
||||||
|
} // for (int i = 0; i < num_features; ++i)
|
||||||
|
} // for (int batch_index = 0; batch_index < num_mini_batches; ++batch_index)
|
||||||
|
// write the last batch
|
||||||
|
for (int i = 0; i < num_features; ++i) { |
||||||
|
/* if (image_indices[i] % 1000 != 0) {
|
||||||
|
txns.at(i)->Commit(); |
||||||
|
} |
||||||
|
LOG(ERROR)<< "Extracted features of " << image_indices[i] << |
||||||
|
" query images for feature blob " << blob_names[i]; |
||||||
|
feature_dbs.at(i)->Close();*/ |
||||||
|
fclose(files[i]); |
||||||
|
} |
||||||
|
|
||||||
|
LOG(ERROR)<< "Successfully extracted the features!"; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
@ -0,0 +1,191 @@ |
|||||||
|
#include <google/protobuf/text_format.h> |
||||||
|
#include <glog/logging.h> |
||||||
|
#include <leveldb/db.h> |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
#include <fstream> // NOLINT(readability/streams) |
||||||
|
#include <string> |
||||||
|
#include <set> |
||||||
|
#include <stdio.h> |
||||||
|
#include <string.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <dirent.h> |
||||||
|
#include <sys/stat.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <sys/types.h> |
||||||
|
#include "caffe/proto/caffe.pb.h" |
||||||
|
#include <opencv2/highgui/highgui.hpp> |
||||||
|
#include <opencv2/highgui/highgui_c.h> |
||||||
|
#include <opencv2/imgproc/imgproc.hpp> |
||||||
|
|
||||||
|
using std::string; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
|
||||||
|
set<string> all_class_name; |
||||||
|
map<string,int> class2id; |
||||||
|
|
||||||
|
void list_dir(const char *path,vector<string>& files,bool r = false) |
||||||
|
{ |
||||||
|
DIR *pDir; |
||||||
|
struct dirent *ent; |
||||||
|
char childpath[512]; |
||||||
|
pDir = opendir(path); |
||||||
|
memset(childpath, 0, sizeof(childpath)); |
||||||
|
while ((ent = readdir(pDir)) != NULL) |
||||||
|
{ |
||||||
|
if (ent->d_type & DT_DIR) |
||||||
|
{ |
||||||
|
|
||||||
|
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) |
||||||
|
{ |
||||||
|
continue; |
||||||
|
} |
||||||
|
if(r) |
||||||
|
{ |
||||||
|
sprintf(childpath, "%s/%s", path, ent->d_name); |
||||||
|
list_dir(childpath,files); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
files.push_back(ent->d_name); |
||||||
|
} |
||||||
|
} |
||||||
|
sort(files.begin(),files.end()); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
string get_classname(string path) |
||||||
|
{ |
||||||
|
int index = path.find_last_of('_'); |
||||||
|
return path.substr(0, index); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int get_labelid(string fileName) |
||||||
|
{ |
||||||
|
string class_name_tmp = get_classname(fileName); |
||||||
|
all_class_name.insert(class_name_tmp); |
||||||
|
map<string,int>::iterator name_iter_tmp = class2id.find(class_name_tmp); |
||||||
|
if (name_iter_tmp == class2id.end()) |
||||||
|
{ |
||||||
|
int id = class2id.size(); |
||||||
|
class2id.insert(name_iter_tmp, std::make_pair(class_name_tmp, id)); |
||||||
|
return id; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return name_iter_tmp->second; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void loadimg(string path,char* buffer) |
||||||
|
{ |
||||||
|
cv::Mat img = cv::imread(path, CV_LOAD_IMAGE_COLOR); |
||||||
|
string val; |
||||||
|
int rows = img.rows; |
||||||
|
int cols = img.cols; |
||||||
|
int pos=0; |
||||||
|
for (int c = 0; c < 3; c++) |
||||||
|
{ |
||||||
|
for (int row = 0; row < rows; row++) |
||||||
|
{ |
||||||
|
for (int col = 0; col < cols; col++) |
||||||
|
{ |
||||||
|
buffer[pos++]=img.at<cv::Vec3b>(row,col)[c]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
void convert(string imgdir,string outputdb,string attachdir,int channel,int width,int height) |
||||||
|
{ |
||||||
|
leveldb::DB* db; |
||||||
|
leveldb::Options options; |
||||||
|
options.create_if_missing = true; |
||||||
|
options.error_if_exists = true; |
||||||
|
caffe::Datum datum; |
||||||
|
datum.set_channels(channel); |
||||||
|
datum.set_height(height); |
||||||
|
datum.set_width(width); |
||||||
|
int image_size = channel*width*height; |
||||||
|
char buffer[image_size]; |
||||||
|
|
||||||
|
string value; |
||||||
|
CHECK(leveldb::DB::Open(options, outputdb, &db).ok()); |
||||||
|
vector<string> filenames; |
||||||
|
list_dir(imgdir.c_str(),filenames); |
||||||
|
string img_log = attachdir+"image_filename"; |
||||||
|
ofstream writefile(img_log.c_str()); |
||||||
|
for(int i=0;i<filenames.size();i++) |
||||||
|
{ |
||||||
|
string path= imgdir; |
||||||
|
path.append(filenames[i]); |
||||||
|
|
||||||
|
loadimg(path,buffer); |
||||||
|
|
||||||
|
int labelid = get_labelid(filenames[i]); |
||||||
|
|
||||||
|
datum.set_label(labelid); |
||||||
|
datum.set_data(buffer,image_size); |
||||||
|
datum.SerializeToString(&value); |
||||||
|
snprintf(buffer, image_size, "%05d", i); |
||||||
|
printf("\nclassid:%d classname:%s abspath:%s",labelid,get_classname(filenames[i]).c_str(),path.c_str()); |
||||||
|
db->Put(leveldb::WriteOptions(),string(buffer),value); |
||||||
|
//printf("%d %s\n",i,fileNames[i].c_str());
|
||||||
|
|
||||||
|
assert(writefile.is_open()); |
||||||
|
writefile<<i<<" "<<filenames[i]<<"\n"; |
||||||
|
|
||||||
|
} |
||||||
|
delete db; |
||||||
|
writefile.close(); |
||||||
|
|
||||||
|
img_log = attachdir+"image_classname"; |
||||||
|
writefile.open(img_log.c_str()); |
||||||
|
set<string>::iterator iter = all_class_name.begin(); |
||||||
|
while(iter != all_class_name.end()) |
||||||
|
{ |
||||||
|
assert(writefile.is_open()); |
||||||
|
writefile<<(*iter)<<"\n"; |
||||||
|
//printf("%s\n",(*iter).c_str());
|
||||||
|
iter++; |
||||||
|
} |
||||||
|
writefile.close(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
int main(int argc, char** argv) |
||||||
|
{ |
||||||
|
if (argc < 6) |
||||||
|
{ |
||||||
|
LOG(ERROR) << "convert_imagedata src_dir dst_dir attach_dir channel width height"; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
//./convert_imagedata.bin /home/linger/imdata/collarTest/ /home/linger/linger/testfile/dbtest/ /home/linger/linger/testfile/test_attachment/ 3 250 250
|
||||||
|
// ./convert_imagedata.bin /home/linger/imdata/collar_train/ /home/linger/linger/testfile/crop_train_db/ /home/linger/linger/testfile/crop_train_attachment/ 3 50 50
|
||||||
|
google::InitGoogleLogging(argv[0]); |
||||||
|
string src_dir = argv[1]; |
||||||
|
string src_dst = argv[2]; |
||||||
|
string attach_dir = argv[3]; |
||||||
|
int channel = atoi(argv[4]); |
||||||
|
int width = atoi(argv[5]); |
||||||
|
int height = atoi(argv[6]); |
||||||
|
|
||||||
|
//for test
|
||||||
|
/*
|
||||||
|
src_dir = "/home/linger/imdata/collarTest/"; |
||||||
|
src_dst = "/home/linger/linger/testfile/dbtest/"; |
||||||
|
attach_dir = "/home/linger/linger/testfile/"; |
||||||
|
channel = 3; |
||||||
|
width = 250; |
||||||
|
height = 250; |
||||||
|
*/ |
||||||
|
|
||||||
|
convert(src_dir,src_dst,attach_dir,channel,width,height); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
Loading…
Reference in new issue