您的位置:首页 > 编程语言 > C语言/C++

Caffe C++API 提取任意一张图片的特征系列一----ImageData

2015-12-01 10:11 531 查看
最近由于工作需要需要直接使用Caffe C++接口,查了很多资料后,问题终于解决。其中出现了很多问题,在这里和大家分享!今天首先介绍第一种方法用IamgeData!(这种方法相对简单)

第一个问题:在VS2013中建立好工程后,运行时提示:卷积层没有注册!

解决方法:把你的工程建立在happynear大神建立的buildVS2013工程中,因为要在工程属性中配置。右击工程->属性->通用属性->引用->caffelib->项目引用属性中全部选择True。这样在编译工程时,就没有错误提示了。但是这样的缺点是,工程不好移植,后面会继续改进。如果你有好的方法,请与我分享!大笑

第二个问题:工程建立好后,下面是网络配置文件的改写,因为这里用到了ImageData数据,是把图片做为输入数据直接输入。




我们看到ImageData层与Data层没什么太大差别,是参数有变化。

1)均值输入方式,我们当然可以使用均值文件做为均值输入。也可以使用上面的方法。上面的方法是每个通道的均值,当然还是训练数据的均值。

2)source参数,不再是训练数据的源,而是测试阶段,也就是你想要提取特征的图片的路径和标签,标签最好注明(可随便标,因为没有用到,标注只是为了避免程序出错)

最重要的一点就尺寸,crop_size,new_height,new_width 一定要和论文中给出的一直,我吃了大亏!谨记!

第三个问题:网络配置文件写好,最后一步就是代码了。


#include <string>
#include <vector>
#include "boost/algorithm/string.hpp"
#include "caffe/caffe.hpp"
using boost::shared_ptr;
using std::string;
using namespace caffe;
using namespace std;

#define MAX_FEAT_NUM 16

int main()
{
char *deploy_net = "C:\\Users\\Administrator\\Desktop\\caffe_C++\\vgg_face\\vgg_face_deploy.prototxt";
char *model = "C:\\Users\\Administrator\\Desktop\\caffe_C++\\vgg_face\\VGG_FACE.caffemodel";
int iter = 1;
std::string Blob_names = "prob";
std::string S_filename = "C:\\Users\\Administrator\\Desktop\\caffe_C++\\result\\features";

Phase phase = TEST;//测试模式
LOG(ERROR) << "Using CPU";
Caffe::set_mode(Caffe::CPU);

boost::shared_ptr<Net<float> > feature_net;//定义一个网络实例
feature_net.reset(new Net<float>(deploy_net, phase));//第一个参数 网络配置文件deploy.prototxt
feature_net->CopyTrainedLayersFrom(model);//第二个参数,模型文件,从.caffemodel文件加载网络参数

int total_iter = iter;//第三个参数,总迭代次数
LOG(ERROR) << "Running " << total_iter << " iterations.";

std::string feature_blob_names(Blob_names);//第四个参数,要提取的特征块的名字,比如fc7,fc8
std::vector<std::string> blob_names;
boost::split(blob_names, feature_blob_names, boost::is_any_of(","));//分割操作,分割规则,将feature_blob_names字符串分割,
//存储到blob_names
std::string save_file_names(S_filename);//第五个参数,保存文件名字
std::vector<std::string> file_names;
boost::split(file_names, save_file_names, boost::is_any_of(","));//file_names保存着 文件名(保存)
CHECK_EQ(blob_names.size(), file_names.size()) <<
" the number of feature blob names and save file names must be equal";

size_t num_features = blob_names.size();//块的数量,从名字开始统计
for (size_t i = 0; i < num_features; i++)
{
CHECK(feature_net->has_blob(blob_names[i]))//检查网络中是否有该块,blob_names[i]块的名字
<< "Unknown feature blob name " << blob_names[i] << " in the network";
}

FILE *fp[MAX_FEAT_NUM];
for (size_t i = 0; i < num_features; i++)
{
fp[i] = fopen(file_names[i].c_str(), "wb");//建立多个保存文件,以写的方式
}

for (int i = 0; i < total_iter; ++i)//进入total_iter次总循环
{
feature_net->ForwardPrefilled();//执行一次前向过程
for (int j = 0; j < num_features; ++j)
{
const boost::shared_ptr<Blob<float> > feature_blob = feature_net->blob_by_name(blob_names[j]);//net的blob指的是特征图
float num_imgs = feature_blob->num() * total_iter;//特征块*总的循环次数=总的特征块数量
cout << num_imgs << endl;
float feat_dim = feature_blob->count() / feature_blob->num();//计算特征维度
cout << feat_dim << endl;
const float* data_ptr = (const float *)feature_blob->cpu_data();//特征块数据
cout << *data_ptr << endl;

if (i == 0)
{
fwrite(&feat_dim, sizeof(float), 1, fp[j]);
fwrite(&num_imgs, sizeof(float), 1, fp[j]);
}
fwrite(data_ptr, sizeof(float), feature_blob->count(), fp[j]);
}
}

for (size_t i = 0; i < num_features; i++)
{
fclose(fp[i]);
}
return 0;
}

这个程序是引用的https://github.com/shicai/Caffe_Manual 我只是做了简单的修改和一些中文注释。

到此为止,一个应用


ImageData层,提取一张图片的特征的程序就完成了。此方法的缺点是,输入的图片只能在网络配置文件里修改,减少了程序的灵活性。本篇博客还有很多地方没有写到,以后会补上。下一篇我将介绍使用MemoryData层方法,敬请期待!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Caffe