(16)caffe总结之自定义数据输入层
来源:互联网 发布:mysql gt lt 大于小于 编辑:程序博客网 时间:2024/05/22 14:45
以下的操作就是读入此图片,然后进行训练:
1.创建新定义的头文件include/caffe/layers/my_data_layer.hpp
重新Layer名的方法:virtual inline const char* type() const {return "MyData";}
#ifndef CAFFE_MY_DATA_LAYER_HPP_#define CAFFE_MY_DATA_LAYER_HPP_#include <string>#include <utility>#include <vector>#include <algorithm> // std::random_shuffle#include <vector> // std::vector#include <ctime> // std::time#include "caffe/blob.hpp"#include "caffe/data_transformer.hpp"#include "caffe/internal_thread.hpp"#include "caffe/layer.hpp"#include "caffe/layers/base_data_layer.hpp"#include "caffe/proto/caffe.pb.h"namespace caffe {template <typename Dtype>class MyDataLayer : public BasePrefetchingDataLayer<Dtype> { public: explicit MyDataLayer(const LayerParameter& param): BasePrefetchingDataLayer<Dtype>(param){} virtual ~MyDataLayer(); virtual void DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top); virtual inline const char* type() const { return "MyData";} virtual inline int ExactNumBottomBlobs() const { return 0; } virtual inline int ExactNumTopBlobs() const { return 2; } protected: shared_ptr<Caffe::RNG> prefetch_rng_; virtual void ShuffleImages(); virtual void load_batch(Batch<Dtype>* batch); inline cv::Mat get_one_sample(cv::Mat whole_img,int pos_x,int pos_y,int width,int height){ return source_image_(cv::Rect(pos_x,pos_y,width,height)).clone(); } vector<std::pair<cv::Mat, int> > samples_; int lines_id_; string image_address_; int start_col_; int end_col_; int sample_width_; int sample_height_; cv::Mat source_image_;};} // namespace caffe#endif // CAFFE_MY_DATA_LAYER_HPP_
2.重写LayerSetUp,ShuffleImage,load_batch(见代码my_data_layer.cpp)
#ifdef USE_OPENCV#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <fstream> // NOLINT(readability/streams)#include <iostream> // NOLINT(readability/streams)#include <string>#include <utility>#include <vector>#include <stdio.h>#include "caffe/data_transformer.hpp"#include "caffe/layers/base_data_layer.hpp"#include "caffe/layers/my_data_layer.hpp"#include "caffe/util/benchmark.hpp"#include "caffe/util/io.hpp"#include "caffe/util/math_functions.hpp"#include "caffe/util/rng.hpp"namespace caffe {template <typename Dtype>MyDataLayer<Dtype>::~MyDataLayer<Dtype>() { this->StopInternalThread();}template <typename Dtype>void MyDataLayer<Dtype>::DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top){ // Init private variables. image_address_ = this->layer_param_.my_data_param().image_address(); start_col_= this->layer_param_.my_data_param().start_col(); end_col_ = this->layer_param_.my_data_param().end_col(); sample_width_ = this->layer_param_.my_data_param().sample_width(); sample_height_= this->layer_param_.my_data_param().sample_height(); lines_id_ = 0; int label,x,y; cv::Mat image; source_image_ = cv::imread(image_address_); for(int i=0 ; i< 50 ; i++){ label = (int)(i/5); for(int j=start_col_ ; j<end_col_ ; j++){ y=20*i; x=20*j; image = get_one_sample(source_image_,x,y,20,20); samples_.push_back(std::make_pair(image,label)); } } CHECK(!samples_.empty()) << "Data is empty"; // Shuffle images if(this->layer_param_.my_data_param().shuffle()){ LOG(INFO) << "Shuffling data"; ShuffleImages(); } // Save images if(this->layer_param_.my_data_param().is_save()){LOG(INFO) << "Saving images "; for(int i=0;i<samples_.size();i++){ string save_folder = this->layer_param_.my_data_param().save_folder(); char img_name[128]; sprintf(img_name,"%s/%d.jpg",save_folder.c_str(),i); cv::imwrite(img_name,samples_[i].first); } } // Read an image, and use it to initialize the top blob cv::Mat cv_img = samples_[lines_id_].first; CHECK(cv_img.data) << "Could not load first image"; // Use data_transformer to infer the expected blob shape from a cv_image vector<int> top_shape = this->data_transformer_->InferBlobShape(cv_img); this->transformed_data_.Reshape(top_shape); //Reshape prefetch_data and top[0] according to the batch_size. const int batch_size = this->layer_param_.my_data_param().batch_size(); top_shape[0] = batch_size; for (int i = 0; i < this->prefetch_.size(); ++i) { this->prefetch_[i]->data_.Reshape(top_shape); } top[0]->Reshape(top_shape); LOG(INFO) << "output data size: " << top[0]->num() << "," << top[0]->channels() << "," << top[0]->height() << "," << top[0]->width(); // label vector<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); }}template <typename Dtype>void MyDataLayer<Dtype>::ShuffleImages(){ std::srand ( unsigned ( std::time(0) ) ); std::random_shuffle(samples_.begin(),samples_.end());}template <typename Dtype>void MyDataLayer<Dtype>::load_batch(Batch<Dtype>* batch){ CPUTimer batch_timer; batch_timer.Start(); double read_time = 0; double trans_time = 0; CPUTimer timer; CHECK(batch->data_.count()); CHECK(this->transformed_data_.count()); MyDataParameter my_data_param = this-> layer_param_.my_data_param(); // Get batch size const int batch_size = my_data_param.batch_size(); // Reshape according to the first image of each batch // on single input batches allows for inputs of varying dimension cv::Mat cv_img = samples_[lines_id_].first; CHECK(cv_img.data) << "Could not load "<<lines_id_<<" sample"; // Use data_transformer to infer the expected blob shape from a cv_img vector<int> top_shape = this->data_transformer_->InferBlobShape(cv_img); this->transformed_data_.Reshape(top_shape); // Reshape batch according to the batch_size top_shape[0] = batch_size; batch->data_.Reshape(top_shape); Dtype* prefetch_data = batch->data_.mutable_cpu_data(); Dtype* prefetch_label= batch->label_.mutable_cpu_data(); // datum scales int samples_size = samples_.size(); for(int item_id=0;item_id<batch_size;++item_id){ // get a blob timer.Start(); CHECK_GT(samples_size, lines_id_); cv::Mat sample = samples_[lines_id_].first; CHECK(sample.data) << "Could not load "<<lines_id_<<" sample"; read_time += timer.MicroSeconds(); timer.Start(); // apply transformations to the image int offset = batch->data_.offset(item_id); this->transformed_data_.set_cpu_data(prefetch_data + offset); this->data_transformer_->Transform(sample,&(this->transformed_data_)); trans_time += timer.MicroSeconds(); prefetch_label[item_id] = samples_[lines_id_].second; // got the the next iter lines_id_++; if(lines_id_>=samples_size){ // We have reached the end. restart from the first. DLOG(INFO) << "Restarting data prefetching from start."; lines_id_=0; if(my_data_param.shuffle()){ ShuffleImages(); } } } batch_timer.Stop(); DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << " ms."; DLOG(INFO) << " Read time: " << read_time / 1000 << " ms."; DLOG(INFO) << "Transform time: " << trans_time / 1000 << " ms.";}INSTANTIATE_CLASS(MyDataLayer);REGISTER_LAYER_CLASS(MyData);} // namespaces caffe#endif // USE_OPENCV
3.proto/caffe.proto注册新的Layer
message LayerParameter {... // My new data layer for infer image data++optional MyDataParameter my_data_param = 150;}message V1LayerParameter {... // My new data parameter ++optional MyDataParameter my_data_param = 50;...}...// Message that stores parameters used to apply a new data layer// to infer image datamessage MyDataParameter{ // Image address optional string image_address = 1; // Start column for calculation // Traning and testing use different columns optional int32 start_col = 2; // End column for computing optional int32 end_col = 3; // Height of each image optional int32 sample_height = 4 [default = 0]; // Width of each image optional int32 sample_width = 5 [default = 0]; // Shuffle or not optional bool shuffle = 6; // Batch size for each computing optional int32 batch_size = 7; // Gray or color (equals to single channel or 3 channels) optional bool is_color = 8 [default = false]; // Save the image seperated from the image address or not optional bool is_save = 9 [default = false]; // If save, use this save folder optional string save_folder = 10;}
测试新定义的数据层,使用原来的LeNet网络,把输入层做修改,其他的不变化
name: "LeNet"layer { name: "mnist" type: "MyData" top: "data" top: "label" include { phase: TRAIN } transform_param { scale: 0.00390625 } my_data_param { image_address: "/home/xyl/caffe/lesson2/lesson2-1/digits.png" batch_size: 64 start_col:0 end_col:70 shuffle:true sample_width:20 sample_height:20 is_save:true save_folder: "/home/xyl/caffe/lesson2/lesson2-1/img" }}layer { name: "mnist" type: "MyData" top: "data" top: "label" include { phase: TEST } transform_param { scale: 0.00390625 } my_data_param { image_address: "/home/xyl/caffe/lesson2/lesson2-1/digits.png" batch_size:32 start_col:70 end_col:100 sample_width:20 sample_height:20 shuffle:true }}最后新建一个mydata.sh文件
#!/usr/bin/env shset -e./build/tools/caffe train --solver=lesson2/lesson2-1/mydata_lenet_solver.prototxt $@运行此文件来做测试,结果如图:
1 0
- (16)caffe总结之自定义数据输入层
- Caffe 自定义数据输入层
- Caffe源码解读(十二):自定义数据输入层
- 【caffe】标准数据层输入
- 自定义数据输入层
- 【深度学习框架Caffe学习与应用】第五课 自定义神经层和数据输入层
- (3)caffe总结之数据层及参数
- caffe源码 之 数据层
- caffe之SoftmaxWithLoss层 自定义实现
- Caffe中mnist例子(一)自定义输入层
- caffe系列之数据层及参数
- Caffe学习之数据层及参数设置
- caffe 利用Python API 做数据输入层
- caffe自定义层
- caffe自定义Neuron层
- caffe自定义神经层
- caffe各层总结
- caffe各层总结
- 深度学习算法之过拟合、局部最小值和梯度弥散·
- [程序员面试宝典]链表中倒数第K个节点
- 迭代器模拟实现STL中的list
- 使用jedis连接单机和集群redis的两种方式
- python中的is、==和cmp()比较字符串
- (16)caffe总结之自定义数据输入层
- Git详解(1)——Git起步
- Leetcode -- 35. Search Insert Position
- css3 images
- Android 得到函数耗时多少的方法
- js打开新窗口并且POST传入参数
- case用法(枚举条件选择)
- sass变量详解——你所不知道的sass
- 基于Spring、springmvc、mybatis框架开发的小后台系统附有源码