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

  • 相关阅读:
    检查LigthGBM&XGBoost&Catboost是否支持GPU
    conda 与 pip 混用的问题
    notable禁用更新
    内存管理
    密码学的安全性浅析3
    一次苦逼的SQL注入
    CVE20220847漏洞复现及修复建议
    Kernel pwn 基础教程之 ret2usr 与 bypass_smep
    密码学的安全性浅析2
    SQLMAPTamper之较为通用的双写绕过
  • 原文地址:https://www.cnblogs.com/wmr95/p/8715607.html
Copyright © 2020-2023  润新知