Learning Caffe(10)---自定義網絡層

本文自定義一個使圖片顏色反轉的網絡層,主要幫助我們理解Layer的添加方式,以及caffe的工作方式。
在src/caffe/proto/caffe.proto中加入message:

*// Message that stores parameters used by ReverseLayer
message ReverseParameter {
  optional bool visualize = 3 [default = false];
}*

講該層的參數ID放入layerParameter 中:

// LayerParameter next available layer-specific ID: 147 (last added: recurrent_param)

下一層的有效ID號爲147,最後一次添加的參數ID爲 recurrent_param。

所以需要添加:
optional ReverseParameter reverse_param = 147;
同時修改註釋爲:

LayerParameter next available layer-specific ID: 148 (last added: ReverseParameter)

實現層頭文件:
這裏可以繼承NeuronLayer或者Layer, 選擇不同的基類的時候,要重寫的虛函數不一樣。

#ifndef CAFFE_IMAGE_REVERSE_LAYER_HPP_
#define CAFFE_IMAGE_REVERSE_LAYER_HPP_
#include "caffe/blob.hpp"  
#include "caffe/layer.hpp"  
#include "caffe/proto/caffe.pb.h" 
#include "caffe/layers/neuron_layer.hpp" 

namespace caffe {

/*
 * @brief Reshapes the input Blob into an arbitrary-sized output Blob.
 *
 * Note: similarly to FlattenLayer, this layer does not change the input values
 * (see FlattenLayer, Blob::ShareData and Blob::ShareDiff).
 */
template <typename Dtype>
class ReverseLayer : public NeuronLayer<Dtype> {
 public:
  explicit ReverseLayer(const LayerParameter& param)
      : NeuronLayer<Dtype>(param) {}
  virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);

  virtual inline const char* type() const { return "Reverse"; }

 protected:
  virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);
  virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {};

  int num_images;
  int height_;
  int width_;
  int num_channels_;
  bool visualize_;
};

}  // namespace caffe

#endif

實現C文件

#include <vector>

#include "caffe/layers/reverse_layer.hpp"
#include <opencv2/opencv.hpp>
#include <iostream>

namespace caffe {

template <typename Dtype>
void ReverseLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,  
      const vector<Blob<Dtype>*>& top) {  
  // get parameters  
  const ReverseParameter& param = this->layer_param_.reverse_param();  
  // get the output size  
  visualize_ = param.visualize();  

  // get input size
  num_images = bottom[0]->num();
  height_ = bottom[0]->height();
  width_ = bottom[0]->width();
  num_channels_ = bottom[0]->channels();
  std::cout << num_images  <<height_ <<  width_  << num_channels_ ;

}  

template <typename Dtype>
void ReverseLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {

  const Dtype* bottom_data = bottom[0]->cpu_data();
  Dtype* top_data = top[0]->mutable_cpu_data();

  const int image_size = height_ * width_;
  const int storage_size = image_size * num_channels_;
  cv::Mat dstimage;  
  int image_idx = 0;

  for( int idx_img =0;idx_img < num_images; idx_img ++){
    dstimage = cv::Mat::zeros(height_, width_, CV_32FC1);  

    for(int idx_ch =0; idx_ch < num_channels_; idx_ch ++){
      for(int i =0; i<height_; i++){
        for(int j=0; j<width_; j++){
           top_data[image_idx] =  255 - (float)bottom_data[image_idx] ;
           dstimage.at<float>(i,j) =  (float)top_data[image_idx];
           std::cout << dstimage.at<float>(i,j);
           image_idx ++;// = idx_img * storage_size + image_size * idx_ch + height_ * i + j;
        }
      }
    }
  }

  if(visualize_){
    cv::namedWindow("dst image", CV_WINDOW_AUTOSIZE);  
    cv::imshow("dst image", dstimage);  
    cv::waitKey(0);  
  }
}


INSTANTIATE_CLASS(ReverseLayer);
REGISTER_LAYER_CLASS(Reverse);

}  // namespace caffe

再次編譯

make clean
make all

在deploy.prototxt文件中添加該層

layer {    
  name:"data"    
 type: "Input"    
 top: "data"    
 input_param { shape: { dim: 1 dim: 3 dim: 28 dim: 28 } }    
}    

layer {
  name: "reversed"
  type: "Reverse"
  bottom: "data"
  top: "reversed"
  reverse_param{
    visualize:true
  }
}  

layer {    
 name:"conv1"    
 type: "Convolution"    
 bottom: "reversed"    
 top: "conv1" 
 convolution_param {    
   num_output: 20    
   kernel_size: 5    
   stride: 1    
   weight_filler {    
     type: "xavier"    
   }    
 }    
}    
.......省略

執行測試函數

./build/examples/cpp_classification/classification.bin examples/Reverse/deploy.prototxt examples/mnist/lenet_iter_10000.caffemodel examples/mnist/mean.binaryproto  /home/akuarius/data/mnist/test/labels.txt  examples/mnist/5.png
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章