如何在caffe中使用c ++从多个层获取特征
How to get features from several layers using c++ in caffe
如何在使用 C++ 进行一次前向传递后在 caffe 中同时获得 4096 暗特征层和 1000 暗特征层 class?
我试图在 extract_features.cpp
中查找它,但它使用了一些奇怪的 datum
对象,所以我无法真正理解它是如何工作的。
到目前为止,我只是将 prototxt
文件裁剪到我想要提取和使用的图层
[...]
net->ForwardPrefilled();
Blob<float> *output_layer = net->output_blobs()[0];
const float *begin = output_layer->cpu_data();
const float *end = begin + output_layer->channels();
return vector<float>(begin, end);
但如果我想同时提取两个特定层(例如 "prob" 和 "fc7"),那将不起作用。
更新
extract_feature.cpp
的简单工作流程(假设你在c++中有一个shared_ptr<Net<float> > net
对象):
执行净转发以处理输入:net->Forward()
。
在这一步中,net
中有一个Data
层来读取输入图像。因此,如果在您自己的 app/code 中,您希望将图像读入 cv::Mat image
并将其输入 net
,您可以编写如下代码:
// for data preprocess
shared_ptr<caffe::DataTransformer<float> > data_transformer;
caffe::TransformationParameter trans_para;
// set mean
trans_para.set_mean_file("/path/to/image_mean.binaryproto");
// set crop size, e.g.here is cropping 227x227
trans_para.set_crop_size(227);
// instantiate a DataTransformer using trans_para for image preprocess
data_transformer.reset(new caffe::DataTransformer<float>(trans_para, caffe::TEST));
const std::vector<caffe::Blob<float> *> net_input = net->input_blobs();
// maybe you need to resize image before this step
data_transformer->Transform(image, *net_input[0]);
net->Forward();
而 net.prototxt
应该有一个 Input
层作为第一层,例如这个deploy.prototxt。
- 根据名称获取特征块:
const boost::shared_ptr<Blob<Dtype> > feature_blob = net->blob_by_name(blob_names[i])
从你进入你想要的结构的 blob 中提取特征数据,例如一个arry,一个简单的示例代码可以是:
count = feature_blob->channels() * feature_blob->height() *
feature_blob->width();
float* feature_array = new float[count];
const float* feature_blob_data = feature_blob->cpu_data() +
feature_blob->offset(n); // feature data generated from
// the nth input image within a batch
memcpy(feature_array, feature_blob_data, count * sizeof(float));
...// other operations
delete [] feature_array;
请注意,从 feature_blob_data
存储的数据位于 row-major order。
extract_feature.cpp
的用法对于您的任务应该是这样的:
path/to/extract_features your_pretrained_model.caffemodel \
net.prototxt 4096_dim_feature_blob_name,1000_dim_class_feature_blob_name \
saved_4096_dim_feature_database,saved_1000_dim_class_feature_database \
num_mini_batches(times for forward pass) lmdb(or leveldb) GPU(or CPU)
net.prototxt
应该包含一个可以读取输入图像数据的数据层。
而当运行时,它会先从数据层读取net.prototxt
以内的图像数据,进行num_mini_batches
次forward pass,提取出2个二元特征blob [= 28=、1000_dim_class_feature_blob_name
的数据变成Datum
类型的结构,然后序列化保存到saved_4096_dim_feature_database
、saved_1000_dim_class_feature_database
类型的lmdb
数据库中] 或 leveldb
。
完成后,您可以分别使用net.prototxt
中的数据层从saved_4096_dim_feature_database
、saved_1000_dim_class_feature_database
读取保存的要素数据。
BTW,datum
是一个结构体,最多可以存储4D数据,以及数据的形状和标签信息等。它在caffe.proto
中定义,使用google protobuf生成方便caffe和数据库之间的数据交换,如LMDB
和LEVELDB
.
如何在使用 C++ 进行一次前向传递后在 caffe 中同时获得 4096 暗特征层和 1000 暗特征层 class?
我试图在 extract_features.cpp
中查找它,但它使用了一些奇怪的 datum
对象,所以我无法真正理解它是如何工作的。
到目前为止,我只是将 prototxt
文件裁剪到我想要提取和使用的图层
[...]
net->ForwardPrefilled();
Blob<float> *output_layer = net->output_blobs()[0];
const float *begin = output_layer->cpu_data();
const float *end = begin + output_layer->channels();
return vector<float>(begin, end);
但如果我想同时提取两个特定层(例如 "prob" 和 "fc7"),那将不起作用。
更新
extract_feature.cpp
的简单工作流程(假设你在c++中有一个shared_ptr<Net<float> > net
对象):
执行净转发以处理输入:
net->Forward()
。 在这一步中,net
中有一个Data
层来读取输入图像。因此,如果在您自己的 app/code 中,您希望将图像读入cv::Mat image
并将其输入net
,您可以编写如下代码:// for data preprocess shared_ptr<caffe::DataTransformer<float> > data_transformer; caffe::TransformationParameter trans_para; // set mean trans_para.set_mean_file("/path/to/image_mean.binaryproto"); // set crop size, e.g.here is cropping 227x227 trans_para.set_crop_size(227); // instantiate a DataTransformer using trans_para for image preprocess data_transformer.reset(new caffe::DataTransformer<float>(trans_para, caffe::TEST)); const std::vector<caffe::Blob<float> *> net_input = net->input_blobs(); // maybe you need to resize image before this step data_transformer->Transform(image, *net_input[0]); net->Forward();
而
net.prototxt
应该有一个Input
层作为第一层,例如这个deploy.prototxt。- 根据名称获取特征块:
const boost::shared_ptr<Blob<Dtype> > feature_blob = net->blob_by_name(blob_names[i])
从你进入你想要的结构的 blob 中提取特征数据,例如一个arry,一个简单的示例代码可以是:
count = feature_blob->channels() * feature_blob->height() * feature_blob->width(); float* feature_array = new float[count]; const float* feature_blob_data = feature_blob->cpu_data() + feature_blob->offset(n); // feature data generated from // the nth input image within a batch memcpy(feature_array, feature_blob_data, count * sizeof(float)); ...// other operations delete [] feature_array;
请注意,从 feature_blob_data
存储的数据位于 row-major order。
extract_feature.cpp
的用法对于您的任务应该是这样的:
path/to/extract_features your_pretrained_model.caffemodel \
net.prototxt 4096_dim_feature_blob_name,1000_dim_class_feature_blob_name \
saved_4096_dim_feature_database,saved_1000_dim_class_feature_database \
num_mini_batches(times for forward pass) lmdb(or leveldb) GPU(or CPU)
net.prototxt
应该包含一个可以读取输入图像数据的数据层。
而当运行时,它会先从数据层读取net.prototxt
以内的图像数据,进行num_mini_batches
次forward pass,提取出2个二元特征blob [= 28=、1000_dim_class_feature_blob_name
的数据变成Datum
类型的结构,然后序列化保存到saved_4096_dim_feature_database
、saved_1000_dim_class_feature_database
类型的lmdb
数据库中] 或 leveldb
。
完成后,您可以分别使用net.prototxt
中的数据层从saved_4096_dim_feature_database
、saved_1000_dim_class_feature_database
读取保存的要素数据。
BTW,datum
是一个结构体,最多可以存储4D数据,以及数据的形状和标签信息等。它在caffe.proto
中定义,使用google protobuf生成方便caffe和数据库之间的数据交换,如LMDB
和LEVELDB
.