Caffe C++API 提取任意一张图片的特征系列一----ImageData
2016-01-07 16:20
495 查看
最近由于工作需要需要直接使用Caffe C++接口,查了很多资料后,问题终于解决。其中出现了很多问题,在这里和大家分享!今天首先介绍第一种方法用IamgeData!(这种方法相对简单)
我们看到ImageData层与Data层没什么太大差别,是参数有变化。
1)均值输入方式,我们当然可以使用均值文件做为均值输入。也可以使用上面的方法。上面的方法是每个通道的均值,当然还是训练数据的均值。
2)source参数,不再是训练数据的源,而是测试阶段,也就是你想要提取特征的图片的路径和标签,标签最好注明(可随便标,因为没有用到,标注只是为了避免程序出错)
最重要的一点就尺寸,crop_size,new_height,new_width 一定要和论文中给出的一直,我吃了大亏!谨记!
ImageData层,提取一张图片的特征的程序就完成了。此方法的缺点是,输入的图片只能在网络配置文件里修改,减少了程序的灵活性。本篇博客还有很多地方没有写到,以后会补上。下一篇我将介绍使用MemoryData层方法,敬请期待!
第一个问题:在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层方法,敬请期待!
相关文章推荐
- C和C++中存储区域详解(栈、堆、全局...)
- C语言:从文本文件中读取输入数据
- 【C++】鸡尾酒算法排序
- java调用c++生成的动态和静态库时遇到的问题
- C语言用igraph读取GML文件
- C++ 编写一个选课系统
- 关于使用Notepad++编译C/C++代码时,dos界面会出现中文乱码现象
- C++中线程的简单使用?
- 【C++专题】static_cast, dynamic_cast, const_cast探讨
- c++引用
- vector C++遍历最快方法
- C语言中的typedef跟define的区别
- C语言写的一个简单的计算器
- 在c++中尾递归,普通递归,循环的效率对比
- 【c/c++】Vector入门
- C语言学习之关键字第六讲
- Sicily 1390. Surprising Strings
- C++语言一个最简单的写入文件操作
- 03.C++类、this指针、static静态变量、构造函数、析构函数
- 【c/c++】探寻C++最快的读取文件的方案