#include
#include
#include
#include
#include
#include "caffe/layer.hpp"
#include "caffe/layers/crop_layer.hpp"
#include "caffe/net.hpp"
namespace caffe {
template
void CropLayer::LayerSetUp(const vector& bottom,
const vector& top) {
// LayerSetup() handles the number of dimensions; Reshape() handles the sizes.
// bottom[0] supplies the data
// bottom[1] supplies the size
const CropParameter& param = this->layer_param_.crop_param();
CHECK_EQ(bottom.size(), 2) num_axes();
const int start_axis = bottom[0]->CanonicalAxisIndex(param.axis());
CHECK_LT(start_axis, input_dim) 1) {
// the number of crop values specified must be equal to the number
// of dimensions following axis
CHECK_EQ(start_axis + param.offset_size(), input_dim)
num_axes();
const int start_axis = bottom[0]->CanonicalAxisIndex(param.axis());
// Initialize offsets to 0 and the new shape to the current shape of the data.
offsets = vector(input_dim, 0);
vector new_shape(bottom[0]->shape());
// Determine crop offsets and the new shape post-crop.
for (int i = 0; i < input_dim; ++i) {
int crop_offset = 0;
int new_size = bottom[0]->shape(i);
if (i >= start_axis) {
new_size = bottom[1]->shape(i);
if (param.offset_size() == 1) {
// If only one offset is given, all crops have the same offset.
crop_offset = param.offset(0);
} else if (param.offset_size() > 1) {
// For several offsets, the number of offsets must be equal to the
// number of dimensions to crop, that is dimensions after the axis.
crop_offset = param.offset(i - start_axis);
}
// Check that the crop and offset are within the dimension's bounds.
CHECK_GE(bottom[0]->shape(i) - crop_offset, bottom[1]->shape(i))
offset(ind_red));
} else {
// in the backwards pass the src_data is top_diff
// and the dest_data is bottom_diff
caffe_copy(top[0]->shape(cur_dim),
src_data + top[0]->offset(ind_red),
dest_data + bottom[0]->offset(ind_off));
}
}
}
template
void CropLayer::Forward_cpu(const vector& bottom,
const vector& top) {
std::vector indices(top[0]->num_axes(), 0);
const Dtype* bottom_data = bottom[0]->cpu_data();
Dtype* top_data = top[0]->mutable_cpu_data();
crop_copy(bottom, top, offsets, indices, 0, bottom_data, top_data, true);
}
template
void CropLayer::Backward_cpu(const vector& top,
const vector& propagate_down, const vector& bottom) {
const Dtype* top_diff = top[0]->cpu_diff();
Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
if (propagate_down[0]) {
caffe_set(bottom[0]->count(), static_cast(0), bottom_diff);
std::vector indices(top[0]->num_axes(), 0);
crop_copy(bottom, top, offsets, indices, 0, top_diff, bottom_diff, false);
}
}
#ifdef CPU_ONLY
STUB_GPU(CropLayer);
#endif
INSTANTIATE_CLASS(CropLayer);
REGISTER_LAYER_CLASS(Crop);
} // namespace caffe