Caffe中Interp层的使用

最近实验当中借鉴了FPN网络,由于FPN网络对图片shape有要求,采用了两种方式,其一是在data_layer.cpp中,对原图进行padding操作;其二是需要对特征图进行类似crop操作,使得两者进行eltwise操作的时候shape是一致的。

简单说一下添加padding的操作,在data_layer.cpp的DataSetup()和load_batch()函数中添加:

1 //cv_img是读入的原图像,ext_img是填充pad的图像
2 //extRows,extCols是填充的行和列,具体可查opencv中的copyMakeBorder用法
3 copyMakeBorder(cv_img,ext_img,0,extRows,0,extCols,BORDER_CONSTANT);

下面介绍第二种Interp插值操作:

第一步:添加相应的代码,主要代码来源于:https://github.com/hszhao/PSPNet

1.在PSPNet/include/cafffe/layers/interp_layer.hpp添加代码,代码如下:

 1 #ifndef CAFFE_INTERP_LAYER_HPP_
 2 #define CAFFE_INTERP_LAYER_HPP_
 3 
 4 #include <vector>
 5 
 6 #include "caffe/blob.hpp"
 7 #include "caffe/layer.hpp"
 8 #include "caffe/proto/caffe.pb.h"
 9 
10 namespace caffe {
11 /**
12  * @brief Changes the spatial resolution by bi-linear interpolation.
13  *        The target size is specified in terms of pixels. 
14  *        The start and end pixels of the input are mapped to the start
15  *        and end pixels of the output.
16  */
17 template <typename Dtype>
18 class InterpLayer : public Layer<Dtype> {
19  public:
20   explicit InterpLayer(const LayerParameter& param)
21       : Layer<Dtype>(param) {}
22   virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
23       const vector<Blob<Dtype>*>& top);
24   virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
25       const vector<Blob<Dtype>*>& top);
26 
27   virtual inline const char* type() const { return "Interp"; }
28   virtual inline int ExactNumBottomBlobs() const { return 1; }     //此处可以根据需求修改Interp层的输入个数,默认是1;下同
29   virtual inline int ExactNumTopBlobs() const { return 1; }
30 
31  protected:
32   virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
33       const vector<Blob<Dtype>*>& top);
34   virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
35       const vector<Blob<Dtype>*>& top);
36   virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
37       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
38   virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
39       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
40   
41   int num_, channels_;
42   int height_in_, width_in_;
43   int height_out_, width_out_;
44   int pad_beg_, pad_end_;
45   int height_in_eff_, width_in_eff_;
46 };
47 
48 }  // namespace caffe
49 
50 #endif // CAFFE_CONV_LAYER_HPP_

2.在PSPNet/include/caffe/util/interp.hpp中添加代码,代码如下:

 1 #ifndef CAFFE_UTIL_INTERP_H_
 2 #define CAFFE_UTIL_INTERP_H_
 3 
 4 #include <cublas_v2.h>
 5 #include "caffe/proto/caffe.pb.h"
 6 
 7 namespace caffe {
 8 
 9 // Bi-linear interpolation
10 // IN : [channels height1 width1] cropped from a bigger [Height1 Width1] image
11 // OUT: [channels height2 width2] cropped from a bigger [Height2 Width2] image
12 
13 template <typename Dtype, bool packed>
14 void caffe_cpu_interp2(const int channels,
15     const Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
16           Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2);
17 
18 template <typename Dtype, bool packed>
19 void caffe_gpu_interp2(const int channels,
20     const Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
21           Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2);
22 
23 // Backward (adjoint) operation
24 template <typename Dtype, bool packed>
25 void caffe_cpu_interp2_backward(const int channels,
26       Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
27     const Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2);
28 
29 template <typename Dtype, bool packed>
30 void caffe_gpu_interp2_backward(const int channels,
31       Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
32     const Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2);
33 
34 // Create Gaussian pyramid of an image. Assume output space is pre-allocated.
35 // IN : [channels height width]
36 template <typename Dtype, bool packed>
37 void caffe_cpu_pyramid2(const int channels,
38     const Dtype *data, const int height, const int width,
39     Dtype *data_pyr, const int levels);
40 
41 template <typename Dtype, bool packed>
42 void caffe_gpu_pyramid2(const int channels,
43     const Dtype *data, const int height, const int width,
44     Dtype *data_pyr, const int levels);
45 
46   /*
47 template <typename Dtype, bool packed>
48 void caffe_cpu_mosaic(const int channels,
49     const Dtype *data1, const MosaicParameter mosaic_params1,
50     const Dtype *data_pyr, const int levels,
51           Dtype *data2, const MosaicParameter mosaic_params2);
52 template <typename Dtype, bool packed>
53 void caffe_gpu_mosaic(const int channels,
54     const Dtype *data1, const MosaicParameter mosaic_params1,
55     const Dtype *data_pyr, const int levels,
56           Dtype *data2, const MosaicParameter mosaic_params2);
57   */
58 
59 }  // namespace caffe
60 
61 #endif

3.在PSPNet/include/caffe/common.cuh 添加代码,代码如下:

 1 #ifndef CAFFE_COMMON_CUH_
 2 #define CAFFE_COMMON_CUH_
 3 
 4 #include <cuda.h>
 5 
 6 #if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 600   //注意标红需要添加,不然会报错(根据自己服务器CUDA配置需求添加)
 7 
 8 #else
 9 // CUDA: atomicAdd is not defined for doubles
10 static __inline__ __device__ double atomicAdd(double *address, double val) {
11   unsigned long long int* address_as_ull = (unsigned long long int*)address;
12   unsigned long long int old = *address_as_ull, assumed;
13   if (val==0.0)
14     return __longlong_as_double(old);
15   do {
16     assumed = old;
17     old = atomicCAS(address_as_ull, assumed, __double_as_longlong(val +__longlong_as_double(assumed)));
18   } while (assumed != old);
19   return __longlong_as_double(old);
20 }
21 
22 #endif
23 #endif

4.在PSPNet/src/caffe/layers/interp_layer.cpp 下添加代码,代码如下:

  1 #include <vector>
  2 
  3 #include "caffe/layer.hpp"
  4 #include "caffe/util/math_functions.hpp"
  5 #include "caffe/util/interp.hpp"
  6 #include "caffe/layers/interp_layer.hpp"
  7 
  8 namespace caffe {
  9 
 10 template <typename Dtype>
 11 void InterpLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
 12       const vector<Blob<Dtype>*>& top) {
 13   InterpParameter interp_param = this->layer_param_.interp_param();
 14   pad_beg_ = interp_param.pad_beg();
 15   pad_end_ = interp_param.pad_end();
 16   CHECK_LE(pad_beg_, 0) << "Only supports non-pos padding (cropping) for now";
 17   CHECK_LE(pad_end_, 0) << "Only supports non-pos padding (cropping) for now";
 18 }
 19 
 20 template <typename Dtype>
 21 void InterpLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
 22       const vector<Blob<Dtype>*>& top) {
 23   num_ = bottom[0]->num();
 24   channels_ = bottom[0]->channels();
 25   height_in_ = bottom[0]->height();
 26   width_in_ = bottom[0]->width();
 27   height_in_eff_ = height_in_ + pad_beg_ + pad_end_;
 28   width_in_eff_ = width_in_ + pad_beg_ + pad_end_;
 29   InterpParameter interp_param = this->layer_param_.interp_param();
 30   if (interp_param.has_shrink_factor() &&
 31       !interp_param.has_zoom_factor()) {
 32     const int shrink_factor = interp_param.shrink_factor();
 33     CHECK_GE(shrink_factor, 1) << "Shrink factor must be positive";
 34     height_out_ = (height_in_eff_ - 1) / shrink_factor + 1;
 35     width_out_ = (width_in_eff_ - 1) / shrink_factor + 1;
 36   } else if (interp_param.has_zoom_factor() &&
 37              !interp_param.has_shrink_factor()) {
 38     const int zoom_factor = interp_param.zoom_factor();
 39     CHECK_GE(zoom_factor, 1) << "Zoom factor must be positive";
 40     height_out_ = height_in_eff_ + (height_in_eff_ - 1) * (zoom_factor - 1);
 41     width_out_ = width_in_eff_ + (width_in_eff_ - 1) * (zoom_factor - 1);
 42   } else if (interp_param.has_height() && interp_param.has_width()) {
 43     height_out_  = interp_param.height();
 44     width_out_  = interp_param.width();
 45   } else if (interp_param.has_shrink_factor() &&
 46              interp_param.has_zoom_factor()) {
 47     const int shrink_factor = interp_param.shrink_factor();
 48     const int zoom_factor = interp_param.zoom_factor();
 49     CHECK_GE(shrink_factor, 1) << "Shrink factor must be positive";
 50     CHECK_GE(zoom_factor, 1) << "Zoom factor must be positive";
 51     height_out_ = (height_in_eff_ - 1) / shrink_factor + 1;
 52     width_out_ = (width_in_eff_ - 1) / shrink_factor + 1;
 53     height_out_ = height_out_ + (height_out_ - 1) * (zoom_factor - 1);
 54     width_out_ = width_out_ + (width_out_ - 1) * (zoom_factor - 1);
 55   } else {
 56     LOG(FATAL);
 57   }
 58   CHECK_GT(height_in_eff_, 0) << "height should be positive";
 59   CHECK_GT(width_in_eff_, 0) << "width should be positive";
 60   CHECK_GT(height_out_, 0) << "height should be positive";
 61   CHECK_GT(width_out_, 0) << "width should be positive";
 62   top[0]->Reshape(num_, channels_, height_out_, width_out_);
 63 }
 64 
 65 template <typename Dtype>
 66 void InterpLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
 67       const vector<Blob<Dtype>*>& top) {
 68   caffe_cpu_interp2<Dtype,false>(num_ * channels_,
 69     bottom[0]->cpu_data(), - pad_beg_, - pad_beg_, height_in_eff_, width_in_eff_, height_in_, width_in_,
 70     top[0]->mutable_cpu_data(), 0, 0, height_out_, width_out_, height_out_, width_out_);
 71 }
 72 
 73 template <typename Dtype>
 74 void InterpLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
 75       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
 76   if (!propagate_down[0]) { return; }
 77   caffe_set(bottom[0]->count(), Dtype(0), bottom[0]->mutable_cpu_diff());
 78   caffe_cpu_interp2_backward<Dtype,false>(num_ * channels_,
 79     bottom[0]->mutable_cpu_diff(), - pad_beg_, - pad_beg_, height_in_eff_, width_in_eff_, height_in_, width_in_,
 80     top[0]->cpu_diff(), 0, 0, height_out_, width_out_, height_out_, width_out_);
 81 }
 82 
 83 #ifndef CPU_ONLY
 84 template <typename Dtype>
 85 void InterpLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
 86       const vector<Blob<Dtype>*>& top) {
 87   caffe_gpu_interp2<Dtype,false>(num_ * channels_,
 88     bottom[0]->gpu_data(), - pad_beg_, - pad_beg_, height_in_eff_, width_in_eff_, height_in_, width_in_,
 89     top[0]->mutable_gpu_data(), 0, 0, height_out_, width_out_, height_out_, width_out_);
 90 }
 91 
 92 template <typename Dtype>
 93 void InterpLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
 94       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
 95   if (!propagate_down[0]) { return; }
 96   caffe_gpu_set(bottom[0]->count(), Dtype(0), bottom[0]->mutable_gpu_diff());
 97   caffe_gpu_interp2_backward<Dtype,false>(num_ * channels_,
 98     bottom[0]->mutable_gpu_diff(), - pad_beg_, - pad_beg_, height_in_eff_, width_in_eff_, height_in_, width_in_,
 99     top[0]->gpu_diff(), 0, 0, height_out_, width_out_, height_out_, width_out_);
100 }
101 #endif
102 
103 #ifdef CPU_ONLY
104 STUB_GPU(InterpLayer);
105 #endif
106 
107 INSTANTIATE_CLASS(InterpLayer);
108 REGISTER_LAYER_CLASS(Interp);
109 
110 } // namespace caffe

4.在PSPNet/src/caffe/util/interp.cpp中添加代码,代码如下:

  1 #include "caffe/common.hpp"
  2 #include "caffe/util/interp.hpp"
  3 #include <algorithm>
  4 #include <cmath>
  5 
  6 namespace caffe {
  7 
  8 // Bi-linear interpolation
  9 // IN : [channels height1 width1] cropped from a bigger [Height1 Width1] image
 10 // OUT: [channels height2 width2] cropped from a bigger [Height2 Width2] image
 11 template <typename Dtype, bool packed>
 12 void caffe_cpu_interp2(const int channels,
 13     const Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
 14     Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2) {
 15   CHECK(x1 >= 0 && y1 >= 0 && height1 > 0 && width1 > 0 && x2 >= 0 && y2 >= 0 && height2 > 0 && width2 > 0);
 16   CHECK(Width1 >= width1 + x1 && Height1 >= height1 + y1 && Width2 >= width2 + x2 && Height2 >= height2 + y2);
 17   // special case: just copy
 18   if (height1 == height2 && width1 == width2) {
 19     for (int h2 = 0; h2 < height2; ++h2) {
 20       const int h1 = h2;
 21       for (int w2 = 0; w2 < width2; ++w2) {
 22     const int w1 = w2;
 23     if (packed) {
 24       const Dtype* pos1 = &data1[channels * ((y1 + h1) * Width1 + (x1 + w1))];
 25       Dtype* pos2 = &data2[channels * ((y2 + h2) * Width2 + (x2 + w2))];
 26       for (int c = 0; c < channels; ++c) {
 27         pos2[0] = pos1[0];
 28         pos1++;
 29         pos2++;
 30       }
 31     }
 32     else {
 33       const Dtype* pos1 = &data1[(y1 + h1) * Width1 + (x1 + w1)];
 34       Dtype* pos2 = &data2[(y2 + h2) * Width2 + (x2 + w2)];
 35       for (int c = 0; c < channels; ++c) {
 36         pos2[0] = pos1[0];
 37         pos1 += Width1 * Height1;
 38         pos2 += Width2 * Height2;
 39       }
 40     }
 41       }
 42     }
 43     return;
 44   }
 45   const float rheight = (height2 > 1) ? static_cast<float>(height1 - 1) / (height2 - 1) : 0.f;
 46   const float rwidth = (width2 > 1) ? static_cast<float>(width1 - 1) / (width2 - 1) : 0.f;
 47   for (int h2 = 0; h2 < height2; ++h2) {
 48     const float h1r = rheight * h2;
 49     const int h1 = h1r;
 50     const int h1p = (h1 < height1 - 1) ? 1 : 0;
 51     const Dtype h1lambda = h1r - h1;
 52     const Dtype h0lambda = Dtype(1.) - h1lambda;
 53     for (int w2 = 0; w2 < width2; ++w2) {
 54       const float w1r = rwidth * w2;
 55       const int w1 = w1r;
 56       const int w1p = (w1 < width1 - 1) ? 1 : 0;
 57       const Dtype w1lambda = w1r - w1;
 58       const Dtype w0lambda = Dtype(1.) - w1lambda;
 59       if (packed) {
 60     const Dtype* pos1 = &data1[channels * ((y1 + h1) * Width1 + (x1 + w1))];
 61     Dtype* pos2 = &data2[channels * ((y2 + h2) * Width2 + (x2 + w2))];
 62     for (int c = 0; c < channels; ++c) {
 63       pos2[0] =
 64         h0lambda * (w0lambda * pos1[0]            + w1lambda * pos1[channels * w1p]) + 
 65         h1lambda * (w0lambda * pos1[channels * h1p * Width1] + w1lambda * pos1[channels * (h1p * Width1 + w1p)]);
 66       pos1++;
 67       pos2++;
 68     }
 69       }
 70       else {
 71     const Dtype* pos1 = &data1[(y1 + h1) * Width1 + (x1 + w1)];
 72     Dtype* pos2 = &data2[(y2 + h2) * Width2 + (x2 + w2)];
 73     for (int c = 0; c < channels; ++c) {
 74       pos2[0] =
 75         h0lambda * (w0lambda * pos1[0]            + w1lambda * pos1[w1p]) + 
 76         h1lambda * (w0lambda * pos1[h1p * Width1] + w1lambda * pos1[h1p * Width1 + w1p]);
 77       pos1 += Width1 * Height1;
 78       pos2 += Width2 * Height2;
 79     }
 80       }
 81     }
 82   }
 83 }
 84 
 85 
 86 // Backward (adjoint) operation 1 <- 2 (accumulates)
 87 template <typename Dtype, bool packed>
 88 void caffe_cpu_interp2_backward(const int channels,
 89     Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
 90     const Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2) {
 91   CHECK(x1 >= 0 && y1 >= 0 && height1 > 0 && width1 > 0 && x2 >= 0 && y2 >= 0 && height2 > 0 && width2 > 0);
 92   CHECK(Width1 >= width1 + x1 && Height1 >= height1 + y1 && Width2 >= width2 + x2 && Height2 >= height2 + y2);
 93   // special case: same-size matching grids
 94   if (height1 == height2 && width1 == width2) {
 95     for (int h2 = 0; h2 < height2; ++h2) {
 96       const int h1 = h2;
 97       for (int w2 = 0; w2 < width2; ++w2) {
 98     const int w1 = w2;
 99     if (packed) {
100       Dtype* pos1 = &data1[channels * ((y1 + h1) * Width1 + (x1 + w1))];
101       const Dtype* pos2 = &data2[channels * ((y2 + h2) * Width2 + (x2 + w2))];
102       for (int c = 0; c < channels; ++c) {
103         pos1[0] += pos2[0];
104         pos1++;
105         pos2++;
106       }
107     }
108     else {
109       Dtype* pos1 = &data1[(y1 + h1) * Width1 + (x1 + w1)];
110       const Dtype* pos2 = &data2[(y2 + h2) * Width2 + (x2 + w2)];
111       for (int c = 0; c < channels; ++c) {
112         pos1[0] += pos2[0];
113         pos1 += Width1 * Height1;
114         pos2 += Width2 * Height2;
115       }
116     }
117       }
118     }
119     return;
120   }
121   const float rheight = (height2 > 1) ? static_cast<float>(height1 - 1) / (height2 - 1) : 0.f;
122   const float rwidth = (width2 > 1) ? static_cast<float>(width1 - 1) / (width2 - 1) : 0.f;
123   for (int h2 = 0; h2 < height2; ++h2) {
124     const float h1r = rheight * h2;
125     const int h1 = h1r;
126     const int h1p = (h1 < height1 - 1) ? 1 : 0;
127     const Dtype h1lambda = h1r - h1;
128     const Dtype h0lambda = Dtype(1.) - h1lambda;
129     for (int w2 = 0; w2 < width2; ++w2) {
130       const float w1r = rwidth * w2;
131       const int w1 = w1r;
132       const int w1p = (w1 < width1 - 1) ? 1 : 0;
133       const Dtype w1lambda = w1r - w1;
134       const Dtype w0lambda = Dtype(1.) - w1lambda;
135       if (packed) {
136     Dtype* pos1 = &data1[channels * ((y1 + h1) * Width1 + (x1 + w1))];
137     const Dtype* pos2 = &data2[channels * ((y2 + h2) * Width2 + (x2 + w2))];
138     for (int c = 0; c < channels; ++c) {
139       pos1[0] += h0lambda * w0lambda * pos2[0];
140       pos1[channels * w1p] += h0lambda * w1lambda * pos2[0];
141       pos1[channels * h1p * Width1] += h1lambda * w0lambda * pos2[0];
142       pos1[channels * (h1p * Width1 + w1p)] += h1lambda * w1lambda * pos2[0];
143       pos1++;
144       pos2++;
145     }
146       }
147       else {
148     Dtype* pos1 = &data1[(y1 + h1) * Width1 + (x1 + w1)];
149     const Dtype* pos2 = &data2[(y2 + h2) * Width2 + (x2 + w2)];
150     for (int c = 0; c < channels; ++c) {
151       pos1[0] += h0lambda * w0lambda * pos2[0];
152       pos1[w1p] += h0lambda * w1lambda * pos2[0];
153       pos1[h1p * Width1] += h1lambda * w0lambda * pos2[0];
154       pos1[h1p * Width1 + w1p] += h1lambda * w1lambda * pos2[0];
155       pos1 += Width1 * Height1;
156       pos2 += Width2 * Height2;
157     }
158       }
159     }
160   }
161 }
162 
163 // Create Gaussian pyramid of an image. Assume output space is pre-allocated.
164 // IN : [channels height width]
165 template <typename Dtype, bool packed>
166 void caffe_cpu_pyramid2(const int channels,
167     const Dtype *data, const int height, const int width,
168     Dtype *data_pyr, const int levels) {
169   CHECK(height > 0 && width > 0 && levels >= 0);
170   int height1 = height, width1 = width;
171   int height2 = height, width2 = width;
172   const Dtype *data1 = data;
173   Dtype *data2 = data_pyr;
174   for (int l = 0; l < levels; ++l) {
175     height2 /= 2;
176     width2 /= 2;
177     if (height2 == 0 || width2 == 0) {
178       break;
179     }
180     for (int h2 = 0; h2 < height2; ++h2) {
181       const int h1 = 2 * h2;
182       for (int w2 = 0; w2 < width2; ++w2) {
183     const int w1 = 2 * w2;
184     if (packed) {
185       const Dtype* pos1 = &data1[channels * (h1 * width1 + w1)];
186       Dtype* pos2 = &data2[channels * (h2 * width2 + w2)];
187       for (int c = 0; c < channels; ++c) {
188         pos2[0] =  static_cast<Dtype>(.25) *
189           (pos1[0]                 + pos1[channels] + 
190            pos1[channels * width1] + pos1[channels * (width1 + 1)]);
191         pos1++;
192         pos2++;
193       }
194     }
195     else {
196       const Dtype* pos1 = &data1[h1 * width1 + w1];
197       Dtype* pos2 = &data2[h2 * width2 + w2];
198       for (int c = 0; c < channels; ++c) {
199         pos2[0] =  static_cast<Dtype>(.25) *
200           (pos1[0]      + pos1[1] + 
201            pos1[width1] + pos1[width1 + 1]);
202         pos1 += width1 * height1;
203         pos2 += width2 * height2;
204       }
205     }
206       }
207     }
208     data1 = data2;
209     height1 = height2;
210     width1 = width2;
211     data2 += channels * height2 * width2;
212   }
213 }
214 
215   /*
216 template <typename Dtype, bool packed>
217 void caffe_cpu_mosaic(const int channels,
218     const Dtype *data1, const MosaicParameter mosaic_params1,
219     const Dtype *data_pyr, const int levels,
220           Dtype *data2, const MosaicParameter mosaic_params2) {
221   const int num1 = mosaic_params1.rects_size();
222   const int num2 = mosaic_params2.rects_size();
223   CHECK(num1 == num2 || (num1 == 1 && num2 > 1) || (num2 == 1 && num1 > 1));
224   const int num = std::max(num1, num2);
225   for (int i = 0; i < num; ++i) {
226     const Rect rect1 = mosaic_params1.rects((i < num1) ? i : 0);
227     const Rect rect2 = mosaic_params2.rects((i < num2) ? i : 0);
228     int level = log2(sqrt((float)rect1.height() * rect1.width() / rect2.height() / rect2.width()));
229     level = std::max(0, std::min(levels, level));
230     if (data_pyr == 0 || level == 0) {
231       caffe_cpu_interp2<Dtype,packed>(channels,
232       data1, rect1.x(), rect1.y(), rect1.height(), rect1.width(), mosaic_params1.height(), mosaic_params1.width(),
233       data2, rect2.x(), rect2.y(), rect2.height(), rect2.width(), mosaic_params2.height(), mosaic_params2.width());
234     }
235     else {
236       const Dtype *data_pyr_l = data_pyr;
237       int factor = 2;
238       for (int l = 1; l < level; ++l) {
239     data_pyr_l += channels * (mosaic_params1.height() / factor) * (mosaic_params1.width() / factor);
240     factor *= 2;
241       }
242       caffe_cpu_interp2<Dtype,packed>(channels,
243       data_pyr_l, rect1.x() / factor, rect1.y() / factor, rect1.height() / factor, rect1.width() / factor, mosaic_params1.height() / factor, mosaic_params1.width() / factor,
244       data2, rect2.x(), rect2.y(), rect2.height(), rect2.width(), mosaic_params2.height(), mosaic_params2.width());      
245     }
246   }
247 }
248 template <typename Dtype, bool packed>
249 void caffe_gpu_mosaic(const int channels,
250     const Dtype *data1, const MosaicParameter mosaic_params1,
251     const Dtype *data_pyr, const int levels,
252           Dtype *data2, const MosaicParameter mosaic_params2) {
253   const int num1 = mosaic_params1.rects_size();
254   const int num2 = mosaic_params2.rects_size();
255   CHECK(num1 == num2 || (num1 == 1 && num2 > 1) || (num2 == 1 && num1 > 1));
256   const int num = std::max(num1, num2);
257   for (int i = 0; i < num; ++i) {
258     const Rect rect1 = mosaic_params1.rects((i < num1) ? i : 0);
259     const Rect rect2 = mosaic_params2.rects((i < num2) ? i : 0);
260     int level = log2(sqrt((float)rect1.height() * rect1.width() / rect2.height() / rect2.width()));
261     level = std::max(0, std::min(levels, level));
262     if (data_pyr == 0 || level == 0) {
263       caffe_gpu_interp2<Dtype,packed>(channels,
264       data1, rect1.x(), rect1.y(), rect1.height(), rect1.width(), mosaic_params1.height(), mosaic_params1.width(),
265       data2, rect2.x(), rect2.y(), rect2.height(), rect2.width(), mosaic_params2.height(), mosaic_params2.width());
266     }
267     else {
268       const Dtype *data_pyr_l = data_pyr;
269       int factor = 2;
270       for (int l = 1; l < level; ++l) {
271     data_pyr_l += channels * (mosaic_params1.height() / factor) * (mosaic_params1.width() / factor);
272     factor *= 2;
273       }
274       caffe_gpu_interp2<Dtype,packed>(channels,
275       data_pyr_l, rect1.x() / factor, rect1.y() / factor, rect1.height() / factor, rect1.width() / factor, mosaic_params1.height() / factor, mosaic_params1.width() / factor,
276       data2, rect2.x(), rect2.y(), rect2.height(), rect2.width(), mosaic_params2.height(), mosaic_params2.width());      
277     }
278   }
279 }
280   */
281 
282 // Explicit instances
283 template void caffe_cpu_interp2<float,false>(const int, const float *, const int, const int, const int, const int, const int, const int, float *, const int, const int, const int, const int, const int, const int);
284 template void caffe_cpu_interp2<float,true>(const int, const float *, const int, const int, const int, const int, const int, const int, float *, const int, const int, const int, const int, const int, const int);
285 template void caffe_cpu_interp2<double,false>(const int, const double *, const int, const int, const int, const int, const int, const int, double *, const int, const int, const int, const int, const int, const int);
286 template void caffe_cpu_interp2<double,true>(const int, const double *, const int, const int, const int, const int, const int, const int, double *, const int, const int, const int, const int, const int, const int);
287 
288 template void caffe_cpu_interp2_backward<float,false>(const int, float *, const int, const int, const int, const int, const int, const int, const float *, const int, const int, const int, const int, const int, const int);
289 template void caffe_cpu_interp2_backward<double,false>(const int, double *, const int, const int, const int, const int, const int, const int, const double *, const int, const int, const int, const int, const int, const int);
290 
291 template void caffe_cpu_pyramid2<float,false>(const int, const float *, const int, const int, float *, const int);
292 template void caffe_cpu_pyramid2<float,true>(const int, const float *, const int, const int, float *, const int);
293 template void caffe_cpu_pyramid2<double,false>(const int, const double *, const int, const int, double *, const int);
294 template void caffe_cpu_pyramid2<double,true>(const int, const double *, const int, const int, double *, const int);
295 
296   /*
297 template void caffe_cpu_mosaic<float,false>(const int, const float *, const MosaicParameter, const float *, const int, float *, const MosaicParameter);
298 template void caffe_cpu_mosaic<float,true>(const int, const float *, const MosaicParameter, const float *, const int, float *, const MosaicParameter);
299 template void caffe_cpu_mosaic<double,false>(const int, const double *, const MosaicParameter, const double *, const int, double *, const MosaicParameter);
300 template void caffe_cpu_mosaic<double,true>(const int, const double *, const MosaicParameter, const double *, const int, double *, const MosaicParameter);
301 template void caffe_gpu_mosaic<float,false>(const int, const float *, const MosaicParameter, const float *, const int, float *, const MosaicParameter);
302 template void caffe_gpu_mosaic<float,true>(const int, const float *, const MosaicParameter, const float *, const int, float *, const MosaicParameter);
303 template void caffe_gpu_mosaic<double,false>(const int, const double *, const MosaicParameter, const double *, const int, double *, const MosaicParameter);
304 template void caffe_gpu_mosaic<double,true>(const int, const double *, const MosaicParameter, const double *, const int, double *, const MosaicParameter);
305   */
306 
307 } // namespace caffe

5.在PSPNet/src/caffe/util/interp.cu中添加代码,代码如下:

  1 #include "caffe/common.hpp"
  2 #include "caffe/common.cuh"
  3 #include "caffe/util/interp.hpp"
  4 
  5 namespace caffe {
  6 
  7 // Bi-linear interpolation
  8 // IN : [channels height1 width1] cropped from a bigger [Height1 Width1] image
  9 // OUT: [channels height2 width2] cropped from a bigger [Height2 Width2] image
 10 template <typename Dtype, bool packed>
 11 __global__ void caffe_gpu_interp2_kernel(const int n, const float rheight, const float rwidth,
 12     const int channels,
 13     const Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
 14     Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2) {
 15   int index = threadIdx.x + blockIdx.x * blockDim.x;
 16   if (index < n) {
 17     const int w2 = index % width2; // 0:width2-1
 18     const int h2 = index / width2; // 0:height2-1
 19     // special case: just copy
 20     if (height1 == height2 && width1 == width2) {
 21       const int h1 = h2;
 22       const int w1 = w2;
 23       if (packed) {
 24     const Dtype* pos1 = &data1[channels * ((y1 + h1) * Width1 + (x1 + w1))];
 25     Dtype* pos2 = &data2[channels * ((y2 + h2) * Width2 + (x2 + w2))];
 26     for (int c = 0; c < channels; ++c) {
 27       pos2[0] = pos1[0];
 28       pos1++;
 29       pos2++;
 30     }
 31       }
 32       else {
 33     const Dtype* pos1 = &data1[(y1 + h1) * Width1 + (x1 + w1)];
 34     Dtype* pos2 = &data2[(y2 + h2) * Width2 + (x2 + w2)];
 35     for (int c = 0; c < channels; ++c) {
 36     pos2[0] = pos1[0];
 37     pos1 += Width1 * Height1;
 38     pos2 += Width2 * Height2;
 39     }
 40       }
 41       return;
 42     }
 43     //
 44     const float h1r = rheight * h2;
 45     const int h1 = h1r;
 46     const int h1p = (h1 < height1 - 1) ? 1 : 0;
 47     const Dtype h1lambda = h1r - h1;
 48     const Dtype h0lambda = Dtype(1.) - h1lambda;
 49     //
 50     const float w1r = rwidth * w2;
 51     const int w1 = w1r;
 52     const int w1p = (w1 < width1 - 1) ? 1 : 0;
 53     const Dtype w1lambda = w1r - w1;
 54     const Dtype w0lambda = Dtype(1.) - w1lambda;
 55     //
 56     if (packed) {
 57       const Dtype* pos1 = &data1[channels * ((y1 + h1) * Width1 + (x1 + w1))];
 58       Dtype* pos2 = &data2[channels * ((y2 + h2) * Width2 + (x2 + w2))];
 59       for (int c = 0; c < channels; ++c) {
 60     pos2[0] =
 61       h0lambda * (w0lambda * pos1[0]            + w1lambda * pos1[channels * w1p]) + 
 62       h1lambda * (w0lambda * pos1[channels * h1p * Width1] + w1lambda * pos1[channels * (h1p * Width1 + w1p)]);
 63     pos1++;
 64     pos2++;
 65       }
 66     }
 67     else {
 68       const Dtype* pos1 = &data1[(y1 + h1) * Width1 + (x1 + w1)];
 69       Dtype* pos2 = &data2[(y2 + h2) * Width2 + (x2 + w2)];
 70       for (int c = 0; c < channels; ++c) {
 71     pos2[0] =
 72       h0lambda * (w0lambda * pos1[0]            + w1lambda * pos1[w1p]) + 
 73       h1lambda * (w0lambda * pos1[h1p * Width1] + w1lambda * pos1[h1p * Width1 + w1p]);
 74     pos1 += Width1 * Height1;
 75     pos2 += Width2 * Height2;
 76       }
 77     }
 78   }
 79 }
 80 
 81 template <typename Dtype, bool packed>
 82 void caffe_gpu_interp2(const int channels,
 83     const Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
 84     Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2) {
 85   CHECK(x1 >= 0 && y1 >= 0 && height1 > 0 && width1 > 0 && x2 >= 0 && y2 >= 0 && height2 > 0 && width2 > 0);
 86   CHECK(Width1 >= width1 + x1 && Height1 >= height1 + y1 && Width2 >= width2 + x2 && Height2 >= height2 + y2);
 87   const float rheight = (height2 > 1) ? static_cast<float>(height1 - 1) / (height2 - 1) : 0.f;
 88   const float rwidth = (width2 > 1) ? static_cast<float>(width1 - 1) / (width2 - 1) : 0.f;
 89   const int num_kernels = height2 * width2;
 90   caffe_gpu_interp2_kernel<Dtype,packed><<<CAFFE_GET_BLOCKS(num_kernels), CAFFE_CUDA_NUM_THREADS>>>
 91     (num_kernels, rheight, rwidth, channels,
 92      data1, x1, y1, height1, width1, Height1, Width1,
 93      data2, x2, y2, height2, width2, Height2, Width2);
 94   CUDA_POST_KERNEL_CHECK;
 95 }
 96 
 97 // Backward (adjoint) operation 1 <- 2 (accumulates)
 98 template <typename Dtype, bool packed>
 99 __global__ void caffe_gpu_interp2_kernel_backward(const int n, const float rheight, const float rwidth,
100     const int channels,
101     Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
102     const Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2) {
103   int index = threadIdx.x + blockIdx.x * blockDim.x;
104   if (index < n) {
105     const int w2 = index % width2; // 0:width2-1
106     const int h2 = index / width2; // 0:height2-1
107     // special case: just copy
108     if (height1 == height2 && width1 == width2) {
109       const int h1 = h2;
110       const int w1 = w2;
111       if (packed) {
112     Dtype* pos1 = &data1[channels * ((y1 + h1) * Width1 + (x1 + w1))];
113     const Dtype* pos2 = &data2[channels * ((y2 + h2) * Width2 + (x2 + w2))];
114     for (int c = 0; c < channels; ++c) {
115       pos1[0] += pos2[0];
116       pos1++;
117       pos2++;
118     }
119       }
120       else {
121     Dtype* pos1 = &data1[(y1 + h1) * Width1 + (x1 + w1)];
122     const Dtype* pos2 = &data2[(y2 + h2) * Width2 + (x2 + w2)];
123     for (int c = 0; c < channels; ++c) {
124       pos1[0] += pos2[0];
125       pos1 += Width1 * Height1;
126       pos2 += Width2 * Height2;
127     }
128       }
129       return;
130     }
131     //
132     const float h1r = rheight * h2;
133     const int h1 = h1r;
134     const int h1p = (h1 < height1 - 1) ? 1 : 0;
135     const Dtype h1lambda = h1r - h1;
136     const Dtype h0lambda = Dtype(1.) - h1lambda;
137     //
138     const float w1r = rwidth * w2;
139     const int w1 = w1r;
140     const int w1p = (w1 < width1 - 1) ? 1 : 0;
141     const Dtype w1lambda = w1r - w1;
142     const Dtype w0lambda = Dtype(1.) - w1lambda;
143     //
144     if (packed) {
145       Dtype* pos1 = &data1[channels * ((y1 + h1) * Width1 + (x1 + w1))];
146       const Dtype* pos2 = &data2[channels * ((y2 + h2) * Width2 + (x2 + w2))];
147       for (int c = 0; c < channels; ++c) {
148     atomicAdd(&pos1[0], h0lambda * w0lambda * pos2[0]);
149     atomicAdd(&pos1[channels * w1p], h0lambda * w1lambda * pos2[0]);
150     atomicAdd(&pos1[channels * h1p * Width1], h1lambda * w0lambda * pos2[0]);
151     atomicAdd(&pos1[channels * (h1p * Width1 + w1p)], h1lambda * w1lambda * pos2[0]);
152     pos1++;
153     pos2++;
154       }
155     }
156     else {
157       Dtype* pos1 = &data1[(y1 + h1) * Width1 + (x1 + w1)];
158       const Dtype* pos2 = &data2[(y2 + h2) * Width2 + (x2 + w2)];
159       for (int c = 0; c < channels; ++c) {
160     atomicAdd(&pos1[0], h0lambda * w0lambda * pos2[0]);
161     atomicAdd(&pos1[w1p], h0lambda * w1lambda * pos2[0]);
162     atomicAdd(&pos1[h1p * Width1], h1lambda * w0lambda * pos2[0]);
163     atomicAdd(&pos1[h1p * Width1 + w1p], h1lambda * w1lambda * pos2[0]);
164     pos1 += Width1 * Height1;
165     pos2 += Width2 * Height2;
166       }
167     }
168   }
169 }
170 
171 template <typename Dtype, bool packed>
172 void caffe_gpu_interp2_backward(const int channels,
173     Dtype *data1, const int x1, const int y1, const int height1, const int width1, const int Height1, const int Width1,
174     const Dtype *data2, const int x2, const int y2, const int height2, const int width2, const int Height2, const int Width2) {
175   CHECK(x1 >= 0 && y1 >= 0 && height1 > 0 && width1 > 0 && x2 >= 0 && y2 >= 0 && height2 > 0 && width2 > 0);
176   CHECK(Width1 >= width1 + x1 && Height1 >= height1 + y1 && Width2 >= width2 + x2 && Height2 >= height2 + y2);
177   const float rheight = (height2 > 1) ? static_cast<float>(height1 - 1) / (height2 - 1) : 0.f;
178   const float rwidth = (width2 > 1) ? static_cast<float>(width1 - 1) / (width2 - 1) : 0.f;
179   const int num_kernels = height2 * width2;
180   caffe_gpu_interp2_kernel_backward<Dtype,packed><<<CAFFE_GET_BLOCKS(num_kernels), CAFFE_CUDA_NUM_THREADS>>>
181     (num_kernels, rheight, rwidth, channels,
182      data1, x1, y1, height1, width1, Height1, Width1,
183      data2, x2, y2, height2, width2, Height2, Width2);
184   CUDA_POST_KERNEL_CHECK;
185 }
186 
187 
188 // Create Gaussian pyramid of an image. Assume output space is pre-allocated.
189 // IN : [channels height width]
190 template <typename Dtype, bool packed>
191 __global__ void caffe_gpu_pyramid2_kernel(const int n, const int channels,
192     const Dtype *data1, const int height1, const int width1,
193     Dtype *data2, const int height2, const int width2) {
194   int index = threadIdx.x + blockIdx.x * blockDim.x;
195   if (index < n) {
196     const int w2 = index % width2; // 0:width2-1
197     const int h2 = index / width2; // 0:height2-1
198     const int w1 = 2 * w2;
199     const int h1 = 2 * h2;
200     if (packed) {
201       const Dtype* pos1 = &data1[channels * (h1 * width1 + w1)];
202       Dtype* pos2 = &data2[channels * (h2 * width2 + w2)];
203       for (int c = 0; c < channels; ++c) {
204     pos2[0] =  static_cast<Dtype>(.25) *
205       (pos1[0]                 + pos1[channels] + 
206        pos1[channels * width1] + pos1[channels * (width1 + 1)]);
207     pos1++;
208     pos2++;
209       }
210     }
211     else {
212       const Dtype* pos1 = &data1[h1 * width1 + w1];
213       Dtype* pos2 = &data2[h2 * width2 + w2];
214       for (int c = 0; c < channels; ++c) {
215     pos2[0] =  static_cast<Dtype>(.25) *
216       (pos1[0]      + pos1[1] + 
217        pos1[width1] + pos1[width1 + 1]);
218     pos1 += width1 * height1;
219     pos2 += width2 * height2;
220       }
221     }
222   }
223 }
224 
225 template <typename Dtype, bool packed>
226 void caffe_gpu_pyramid2(const int channels,
227     const Dtype *data, const int height, const int width,
228     Dtype *data_pyr, const int levels) {
229   CHECK(height > 0 && width > 0 && levels >= 0);
230   int height1 = height, width1 = width;
231   int height2 = height, width2 = width;
232   const Dtype *data1 = data;
233   Dtype *data2 = data_pyr;
234   for (int l = 0; l < levels; ++l) {
235     height2 /= 2;
236     width2 /= 2;
237     if (height2 == 0 || width2 == 0) {
238       break;
239     }
240     const int num_kernels = height2 * width2;
241     caffe_gpu_pyramid2_kernel<Dtype,packed><<<CAFFE_GET_BLOCKS(num_kernels), CAFFE_CUDA_NUM_THREADS>>>
242       (num_kernels, channels, data1, height1, width1, data2, height2, width2);
243     CUDA_POST_KERNEL_CHECK;
244     data1 = data2;
245     height1 = height2;
246     width1 = width2;
247     data2 += channels * height2 * width2;
248   }
249 }
250 
251 
252 // Explicit instances
253 template void caffe_gpu_interp2<float,false>(const int, const float *, const int, const int, const int, const int, const int, const int, float *, const int, const int, const int, const int, const int, const int);
254 template void caffe_gpu_interp2<float,true>(const int, const float *, const int, const int, const int, const int, const int, const int, float *, const int, const int, const int, const int, const int, const int);
255 template void caffe_gpu_interp2<double,false>(const int, const double *, const int, const int, const int, const int, const int, const int, double *, const int, const int, const int, const int, const int, const int);
256 template void caffe_gpu_interp2<double,true>(const int, const double *, const int, const int, const int, const int, const int, const int, double *, const int, const int, const int, const int, const int, const int);
257 
258 template void caffe_gpu_interp2_backward<float,false>(const int, float *, const int, const int, const int, const int, const int, const int, const float *, const int, const int, const int, const int, const int, const int);
259 template void caffe_gpu_interp2_backward<double,false>(const int, double *, const int, const int, const int, const int, const int, const int, const double *, const int, const int, const int, const int, const int, const int);
260 
261 template void caffe_gpu_pyramid2<float,false>(const int, const float *, const int, const int, float *, const int);
262 template void caffe_gpu_pyramid2<float,true>(const int, const float *, const int, const int, float *, const int);
263 template void caffe_gpu_pyramid2<double,false>(const int, const double *, const int, const int, double *, const int);
264 template void caffe_gpu_pyramid2<double,true>(const int, const double *, const int, const int, double *, const int);
265 
266 } // namespace caffe

6.在PSPNet/src/caffe/proto/caffe.proto中添加代码,代码如下:

 1 message LayerParameter {
 2   optional string name = 1; // the layer name
 3   optional string type = 2; // the layer type
 4   repeated string bottom = 3; // the name of each bottom blob
 5   repeated string top = 4; // the name of each top blob
 6 
 7   // The train / test phase for computation.
 8   optional Phase phase = 10;
 9 
10   // The amount of weight to assign each top blob in the objective.
11   // Each layer assigns a default value, usually of either 0 or 1,
12   // to each top blob.
13   repeated float loss_weight = 5;
14 
15   // Specifies training parameters (multipliers on global learning constants,
16   // and the name and other settings used for weight sharing).
17   repeated ParamSpec param = 6;
18 
19   // The blobs containing the numeric parameters of the layer.
20   repeated BlobProto blobs = 7;
21 
22   // Specifies on which bottoms the backpropagation should be skipped.
23   // The size must be either 0 or equal to the number of bottoms.
24   repeated bool propagate_down = 11;
25 
26   // Rules controlling whether and when a layer is included in the network,
27   // based on the current NetState.  You may specify a non-zero number of rules
28   // to include OR exclude, but not both.  If no include or exclude rules are
29   // specified, the layer is always included.  If the current NetState meets
30   // ANY (i.e., one or more) of the specified rules, the layer is
31   // included/excluded.
32   repeated NetStateRule include = 8;
33   repeated NetStateRule exclude = 9;
34 
35   // Parameters for data pre-processing.
36   optional TransformationParameter transform_param = 100;
37 
38   // Parameters shared by loss layers.
39   optional LossParameter loss_param = 101;
40 
41   // Layer type-specific parameters.
42   //
43   // Note: certain layers may have more than one computational engine
44   // for their implementation. These layers include an Engine type and
45   // engine parameter for selecting the implementation.
46   // The default for the engine is set by the ENGINE switch at compile-time.
47   optional AccuracyParameter accuracy_param = 102;
48   optional AdaptiveBiasChannelParameter adaptive_bias_channel_param = 148;
49   optional ArgMaxParameter argmax_param = 103;
50   optional BatchNormParameter batch_norm_param = 139;
51   optional BNParameter bn_param = 152;
52   optional BiasParameter bias_param = 141;
53   optional BiasChannelParameter bias_channel_param = 149;
54   optional ConcatParameter concat_param = 104;
55   optional ContrastiveLossParameter contrastive_loss_param = 105;
56   optional ConvolutionParameter convolution_param = 106;
57   optional DataParameter data_param = 107;
58   optional DenseCRFParameter dense_crf_param = 146;
59   optional DomainTransformParameter domain_transform_param = 147;
60   optional DropoutParameter dropout_param = 108;
61   optional DummyDataParameter dummy_data_param = 109;
62   optional EltwiseParameter eltwise_param = 110;
63   optional ELUParameter elu_param = 140;
64   optional EmbedParameter embed_param = 137;
65   optional ExpParameter exp_param = 111;
66   optional FlattenParameter flatten_param = 135;
67   optional HDF5DataParameter hdf5_data_param = 112;
68   optional HDF5OutputParameter hdf5_output_param = 113;
69   optional HingeLossParameter hinge_loss_param = 114;
70   optional ImageDataParameter image_data_param = 115;
71   optional InfogainLossParameter infogain_loss_param = 116;
72   optional InnerProductParameter inner_product_param = 117;
73   optional InterpParameter interp_param = 143;   //注意143不能和其他的数字重复,可以自己情况调整
74   optional LogParameter log_param = 134;
75   optional LRNParameter lrn_param = 118;
76   optional MatReadParameter mat_read_param = 151;
77   optional MatWriteParameter mat_write_param = 145;
78   optional MemoryDataParameter memory_data_param = 119;
79   optional MVNParameter mvn_param = 120;
80   optional PoolingParameter pooling_param = 121;
81   optional PowerParameter power_param = 122;
82   optional PReLUParameter prelu_param = 131;
83   optional PythonParameter python_param = 130;
84   optional ReductionParameter reduction_param = 136;
85   optional ReLUParameter relu_param = 123;
86   optional ReshapeParameter reshape_param = 133;
87   optional ScaleParameter scale_param = 142;
88   optional SegAccuracyParameter seg_accuracy_param = 144;
89   optional SigmoidParameter sigmoid_param = 124;
90   optional SoftmaxParameter softmax_param = 125;
91   optional SPPParameter spp_param = 132;
92   optional SliceParameter slice_param = 126;
93   optional TanHParameter tanh_param = 127;
94   optional ThresholdParameter threshold_param = 128;
95   optional TileParameter tile_param = 138;
96   optional UniqueLabelParameter unique_label_param = 150;
97   optional WindowDataParameter window_data_param = 129;
98 }
1 message InterpParameter {
2   optional int32 height = 1 [default = 0]; // Height of output
3   optional int32 width = 2 [default = 0]; // Width of output
4   optional int32 zoom_factor = 3 [default = 1]; // zoom factor
5   optional int32 shrink_factor = 4 [default = 1]; // shrink factor
6   optional int32 pad_beg = 5 [default = 0]; // padding at begin of input
7   optional int32 pad_end = 6 [default = 0]; // padding at end of input
8 }

7.在网络结构中添加Interp层,代码如下:

 1 layer{
 2   bottom:"input"
 3   top:"output"
 4   name:"interp_layer"
 5   type:"Interp"
 6   interp_param{        //注意可按需求改为interp_param{height:60 width:60}(即固定特征图的尺寸),也可以不需要这个interp_param参数
 7      shrink_factor:4
 8      zoom_factor:3
 9      pad_beg:0
10      pad_end:0
11  }   
12 }

第二步,添加完相应的代码,则进行编译

1.因为修改过caffe.proto,所以需要重新编译proto,需要先安装protobuf,安装之后需要编译caffe.proto文件,生成caffe.pb.h和caffe.pb.cc文件。编译过程如下:

 1 # 确定protobuf的版本
 2 $ protoc --version
 3 libprotoc 2.5.0
 4 
 5 # 编译caffe.proto,需要先进入src/caffe/proto目录下,也可以不进入,指定路径
 6 $ protoc -I=./ --cpp_out=./ ./caffe.proto
 7 
 8 # 查看编译结果
 9 $ ls
10 caffe.pb.cc  caffe.pb.h  caffe.proto

2.编译caffe,退到caffe路径下,编译:

1 //确保每一步都成功执行
2 make clean
3 make -j8
4 make pycaffe

...大体上是这样一个流程,编译过程中遇到相应问题再百度,有错误的地方欢迎大家指正。

版权声明:

作者:王老头

出处:http://www.cnblogs.com/wmr95/p/8715607.html

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,并在文章页面明显位置给出原文链接,否则,作者将保留追究法律责任的权利。