在我的上一篇博客中caffe实现多标签输入中,介绍了用把图像和label分来,各自做成lmdb,最后把label的lmdb用slice层分开,这篇博客介绍另一种修改源码的方法实现多label,比其他博客改动源码最少

简介

我们都知道ImageDataLayer是直接读取原图进行分类,它的label是单label,文件格式如下

train.txt示例
001.jpg 1
002.jpg 2
003.jpg 3layer {  name: "demo"  type: "ImageData"  top: "data"  top: "label"  include {  phase: TRAIN  }  transform_param {  scale: 0.00390625  mean_value: 128  }  image_data_param {  source: "your path/train.txt"  root_folder: "your image data path"  new_height: xxx new_width: xxx  batch_size: 32  shuffle: true  #每个epoch都会进行shuffle}
}  

修改代码

由于ImageataLayer的限制,我们只能在train.txt中放置单label,现在我们来修改ImageataLayer的代码来实现多label
主要涉及三个文件

  • caffe/src/caffe/proto/caffe.proto
  • caffe/include/caffe/layers/image_data_layer.hpp
  • caffe/src/caffe/layers/image_data_layer.cpp

定位到caffe/src/caffe/proto/caffe.proto中message ImageDataParameter

// 添加一个参数
// Specify the label dim. default 1.
// 有几种label,比如性别、年龄两种label,在网络结构里就把此参数设置为2
optional uint32 label_dim = IDNumber [default = 1];
// IDNumber是和其它参数不冲突的ID数字

定位到caffe/include/caffe/layers/image_data_layer.hpp

// 修改vector<std::pair<std::string, int> > lines_;
// string对应那个train.txt中的图片名称,in对应label,我们把int改为int*,实现多label
vector<std::pair<std::string, int *> > lines_;

定位到caffe/src/caffe/layers/image_data_layer.cpp

// DataLayerSetUp函数
// 原本的加载图片名称和label的代码std::ifstream infile(source.c_str());string line;size_t pos;int label;while (std::getline(infile, line)) {pos = line.find_last_of(' ');label = atoi(line.substr(pos + 1).c_str());lines_.push_back(std::make_pair(line.substr(0, pos), label));}
// 修改为这样
std::ifstream infile(source.c_str());string filename;// 获取label的种类int label_dim = this->layer_param_.image_data_param().label_dim();// 注意这里默认每个label直接以空格隔开,每个图片名称及其label占一行,如果你的格式不同,可自行修改读取方式while (infile >> filename) {int* labels = new int[label_dim];for(int i = 0;i < label_dim;++i){infile >> labels[i];}lines_.push_back(std::make_pair(filename, labels));}
// 原本的输出labelvector<int> label_shape(1, batch_size);top[1]->Reshape(label_shape);for (int i = 0; i < this->prefetch_.size(); ++i) {this->prefetch_[i]->label_.Reshape(label_shape);}
// 修改为这样vector<int> label_shape(2);label_shape[0] = batch_size;label_shape[1] = label_dim;top[1]->Reshape(label_shape); // label的输出shape batch_size*label_dimfor (int i = 0; i < this->PREFETCH_COUNT; ++i) {this->prefetch_[i].label_.Reshape(label_shape);}
// 注意:caffe最新版本prefetch_的结构由之前的Batch<Dtype> prefetch_[PREFETCH_COUNT];
// 改为 vector<shared_ptr<Batch<Dtype> > > prefetch_; 由对象数组改为了存放shared指针的vector。
// 所以此处的this->PREFETCH_COUNT改为this->prefetch_.size();
// 此处的this->prefetch_[i].label_.Reshape(label_shape);
// 改为this->prefetch_[i]->label_.Reshape(label_shape);把.改成指针的->
// load_batch函数
// 在函数一开始先获取下label_dim参数
int label_dim = this->layer_param_.image_data_param().label_dim();
// 原本的预取label
prefetch_label[item_id] = lines_[lines_id_].second;
// 修改为这样
for(int i = 0;i < label_dim;++i){// lines_[lines_id_].second就是最开始改为的int*,多labelprefetch_label[item_id * label_dim + i] = lines_[lines_id_].second[i];
}

最后进行make

示例

train.txt
001.jpg 1 3 2
002.jpg 2 4 7
003.jpg 3 0 9
# trainval.prototxt
layer {name: "data"type: "ImageData"top: "data"top: "label"include {phase: TRAIN}transform_param {mirror: truemean_value: 128mean_value: 128mean_value: 128}image_data_param {mirror: truesource: "your path/train.txt"  root_folder: "your image data path"  new_height: xxx new_width: xxx  batch_size: 32  shuffle: true  #每个epoch都会进行shufflelabel_dim: 3}
}
layer {name: "slice"type: "Slice"bottom: "label"top: "label_1"top: "label_2"top: "label_3"slice_param {axis: 1slice_point:1slice_point:2}
}
......
# 后续代码参考我另一篇caffe实现多label输入的代码

总结

对比其他修改源码的博客,本篇对源码的改动最少,而且兼容原来的版本,最重要的是使用起来最方便,不用生成lmdb之类

caffe实现多label输入(修改源码版)相关推荐

  1. Python 技术篇 - 修改源码解决中文主机名导致的flask、socket服务起不来问题: ‘utf-8‘ codec can‘t decode byte 0xc0 in position...

    由于主机名为中文导致的 flask 服务起不来,报错如下: File "D:\work\python3.9_64\lib\socket.py", line 791, in getf ...

  2. 填坑黑苹果(VMware装MacOS) - 修改 Unlocker 补丁源码版

    最近闲的突然想找点事来折腾一下, 于是随着苹果的发布会就盯上自己手上的 iPhone, 也想弄个 Mac 来搞 IOS. 于是就有了这个填坑故事. 为什么要修改补丁源码: 不再苦苦去寻找和下载 dra ...

  3. yocto(七)——添加layer、添加内核模块、修改源码、制作补丁

    参考官方文档:https://docs.yoctoproject.org/kernel-dev/common.html#working-with-out-of-tree-modules 参考官方文档: ...

  4. 6S大气传输模型修改源码添加、自定义CASI传感器光谱响应

    6S大气传输模型编译以及修改源码添加.自定义CASI传感器光谱响应 在利用6S模型进行CASI影像数据的大气纠正时,发现6S模型中没有对应的光谱响应函数,又不想自己整个输进去,就查资料对源码进行了修改 ...

  5. 6S大气传输模型修改源码添加、自定义卫星光谱响应(以HJ-1B CCD为例)

    6S大气传输模型修改源码添加.自定义卫星光谱响应(以HJ-1B CCD为例) 最近要做国产卫星的大气校正,打算用6s模型模拟气溶胶的查找表,但是发现6s模型中没有国产卫星的相应光谱响应函数,只能在输入 ...

  6. py6s 光谱响应函数_Windows7 64位环境6sv2.1大气传输模型修改源码添加国产高分卫星GF-1 GF-2光谱响应支持...

    下面开始添加国产卫星光谱响应的支持: 以下主要参考文章"6S大气传输模型修改源码添加.自定义卫星光谱响应(以HJ-1B CCD为例)"网址:http://blog.csdn.net ...

  7. 编译安装gcc-4.8.2(编译出错后修改源码 编译成功)

    记录 下载 wget ftp://ftp.gnu.org/gnu/gcc/gcc-4.8.5/gcc-4.8.5.tar.gz 解压 下载依赖 tar zxf gcc-4.8.5.tar.gz cd ...

  8. android系统源码7.1.2_r8下载,编译,运行到nexus5X上,修改源码并编译SDK进行测试

    一,学习android系统源码下载,编译的作用 1,可以自己 DIY 自己的rom系统,从系统层面,宏观的加深理解 android系统 2,编译自己的 userdebug(原生root权限) rom, ...

  9. mybatis-generator修改源码2

    参考: MyBatis Generator系列(三)----修改源码实现中文注释 (包括java.net.MalformedURLException at java.net.URL.<init& ...

最新文章

  1. 破解数据流通痛点,华控清交的隐私计算之道
  2. DARPA盘点2017年最受关注的十大科技新闻
  3. Cannot assign to 'self' outside of a method in the init family
  4. 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 17丨文章浏览 II【难度中等】​
  5. 发布npm包到GitHub Packages
  6. python在建筑施工方面的应用_有哪些关于 Python 在建筑中的应用和教程?
  7. Python编码规范和Python风格规范
  8. 怎样把ue4官方文档下载下来_使用Doxygen生成UE4的chm格式API文档
  9. 2022-09-13 mysql列存储引擎-POC-查询数据错误追踪
  10. C# 中属性PropertyInfo的setvalue用法说明
  11. hdoj3085 / acwing177 Nightmare
  12. 测试的阿萨德萨达阿萨德
  13. 虚拟路由冗余协议(VRRP)
  14. Trie 前缀树的c 实现
  15. SVM要点总结(一)
  16. 前端工程师考核总结_最新前端工程师周工作总结
  17. 生活随记-下周很重要
  18. 微信开放平台创建android应用时怎么获取应用签名
  19. 2022年深圳市国家高新技术企业认定条件、时间、流程
  20. Unity使用UMP插件实现接入海康网络摄像头方法

热门文章

  1. 7-3 学习打卡(11.28)
  2. 第一部分 利用opencv基于hsv颜色的目标提取效果和python代码
  3. 【mongodb】比较符及修改器
  4. C语言分别判断大小写英文字母,空格,数字和其他字符的个数
  5. JAVA毕业设计家政服务管理系统计算机源码+lw文档+系统+调试部署+数据库
  6. 计算机867怎么学,2018年考研湖南大学867计算机系统考试大纲
  7. 重新回到Fcitx5的怀抱
  8. Python彩色图片转手绘风格
  9. C++之模板初阶:甩锅编译器
  10. java applet 在线demo_编写可在线收发E-mail的Java Applet