提交 90ed2004 编写于 作者: W wanghaoshuang

Refine configure option of crop layer

1. change configure content to 'axis, offset, shape'
2. add an optional input to crop layer as cropping reference
上级 013d0a26
...@@ -17,28 +17,27 @@ limitations under the License. */ ...@@ -17,28 +17,27 @@ limitations under the License. */
#include "paddle/function/TensorShape.h" #include "paddle/function/TensorShape.h"
namespace paddle { namespace paddle {
static inline CropConf castToCropConf(const FuncConfig& conf) {
return {conf.get<std::vector<uint32_t>>("crop_corner"),
conf.get<std::vector<uint32_t>>("crop_shape")};
}
template <> template <>
void Crop<DEVICE_TYPE_CPU>(real* outputs, void Crop<DEVICE_TYPE_CPU>(real* outputs,
const real* inputs, const real* inputs,
const TensorShape inShape, const TensorShape inShape,
const CropConf& crop) { const FuncConfig& conf) {
int cCrop = crop.corner[0]; std::vector<uint32_t> crop_corner =
int hCrop = crop.corner[1]; conf.get<std::vector<uint32_t>>("crop_corner");
int wCrop = crop.corner[2]; std::vector<uint32_t> crop_shape =
conf.get<std::vector<uint32_t>>("crop_shape");
int cCrop = crop_corner[1];
int hCrop = crop_corner[2];
int wCrop = crop_corner[3];
int num = inShape[0]; int num = inShape[0];
int inC = inShape[1]; int inC = inShape[1];
int inH = inShape[2]; int inH = inShape[2];
int inW = inShape[3]; int inW = inShape[3];
int outC = crop.shape[0]; int outC = crop_shape[1];
int outH = crop.shape[1]; int outH = crop_shape[2];
int outW = crop.shape[2]; int outW = crop_shape[3];
for (int n = 0; n < num; n++) { for (int n = 0; n < num; n++) {
for (int c = 0; c < outC; c++) { for (int c = 0; c < outC; c++) {
...@@ -55,19 +54,23 @@ template <> ...@@ -55,19 +54,23 @@ template <>
void CropGrad<DEVICE_TYPE_CPU>(const real* inGrad, void CropGrad<DEVICE_TYPE_CPU>(const real* inGrad,
real* outGrad, real* outGrad,
const TensorShape outShape, const TensorShape outShape,
const CropConf& crop) { const FuncConfig& conf) {
int cCrop = crop.corner[0]; std::vector<uint32_t> crop_corner =
int hCrop = crop.corner[1]; conf.get<std::vector<uint32_t>>("crop_corner");
int wCrop = crop.corner[2]; std::vector<uint32_t> crop_shape =
conf.get<std::vector<uint32_t>>("crop_shape");
int cCrop = crop_corner[1];
int hCrop = crop_corner[2];
int wCrop = crop_corner[3];
int num = outShape[0]; int num = outShape[0];
int outC = outShape[1]; int outC = outShape[1];
int outH = outShape[2]; int outH = outShape[2];
int outW = outShape[3]; int outW = outShape[3];
int inC = crop.shape[0]; int inC = crop_shape[1];
int inH = crop.shape[1]; int inH = crop_shape[2];
int inW = crop.shape[2]; int inW = crop_shape[3];
for (int n = 0; n < num; n++) { for (int n = 0; n < num; n++) {
for (int c = 0; c < inC; c++) { for (int c = 0; c < inC; c++) {
...@@ -111,26 +114,21 @@ void CropGrad<DEVICE_TYPE_CPU>(const real* inGrad, ...@@ -111,26 +114,21 @@ void CropGrad<DEVICE_TYPE_CPU>(const real* inGrad,
template <DeviceType Device> template <DeviceType Device>
class CropFunc : public FunctionBase { class CropFunc : public FunctionBase {
public: public:
void init(const FuncConfig& config) override { void init(const FuncConfig& config) override { conf_ = config; }
crop_ = castToCropConf(config);
}
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK_EQ(1UL, inputs.size()); CHECK_EQ(1UL, inputs.size());
CHECK_EQ(1UL, outputs.size()); CHECK_EQ(1UL, outputs.size());
CHECK_EQ(outputs[0].shape()[1], crop_.shape[0]);
CHECK_EQ(outputs[0].shape()[2], crop_.shape[1]);
CHECK_EQ(outputs[0].shape()[3], crop_.shape[2]);
CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO); CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO);
TensorShape inShape = inputs[0].shape(); TensorShape inShape = inputs[0].shape();
Crop<Device>( Crop<Device>(
outputs[0].data<real>(), inputs[0].data<real>(), inShape, crop_); outputs[0].data<real>(), inputs[0].data<real>(), inShape, conf_);
} }
private: private:
CropConf crop_; FuncConfig conf_;
}; };
/** /**
...@@ -145,26 +143,21 @@ private: ...@@ -145,26 +143,21 @@ private:
template <DeviceType Device> template <DeviceType Device>
class CropGradFunc : public FunctionBase { class CropGradFunc : public FunctionBase {
public: public:
void init(const FuncConfig& config) override { void init(const FuncConfig& config) override { conf_ = config; }
crop_ = castToCropConf(config);
}
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override { void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK_EQ(1UL, inputs.size()); CHECK_EQ(1UL, inputs.size());
CHECK_EQ(1UL, outputs.size()); CHECK_EQ(1UL, outputs.size());
CHECK_EQ(inputs[0].shape()[1], crop_.shape[0]);
CHECK_EQ(inputs[0].shape()[2], crop_.shape[1]);
CHECK_EQ(inputs[0].shape()[3], crop_.shape[2]);
CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO); CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO);
TensorShape outShape = outputs[0].shape(); TensorShape outShape = outputs[0].shape();
CropGrad<Device>( CropGrad<Device>(
inputs[0].data<real>(), outputs[0].data<real>(), outShape, crop_); inputs[0].data<real>(), outputs[0].data<real>(), outShape, conf_);
} }
private: private:
CropConf crop_; FuncConfig conf_;
}; };
REGISTER_TYPED_FUNC(Crop, CPU, CropFunc); REGISTER_TYPED_FUNC(Crop, CPU, CropFunc);
......
...@@ -18,13 +18,6 @@ limitations under the License. */ ...@@ -18,13 +18,6 @@ limitations under the License. */
namespace paddle { namespace paddle {
struct CropConf {
/// The upper left corner of croped result
std::vector<uint32_t> corner;
/// The shape of croped result
std::vector<uint32_t> shape;
};
/** /**
* \brief This funtion crops inputs according to the specify start point and * \brief This funtion crops inputs according to the specify start point and
*shape. *shape.
...@@ -32,13 +25,13 @@ struct CropConf { ...@@ -32,13 +25,13 @@ struct CropConf {
* \param[out] outputs save results. * \param[out] outputs save results.
* \param[in] inputs input data. * \param[in] inputs input data.
* \param[in] inShape the shape of input tensor. * \param[in] inShape the shape of input tensor.
* \param[in] crop the cropping config * \param[in] conf the cropping config
*/ */
template <DeviceType Device> template <DeviceType Device>
void Crop(real* outputs, void Crop(real* outputs,
const real* inputs, const real* inputs,
const TensorShape inShape, const TensorShape inShape,
const CropConf& crop); const FuncConfig& conf);
/** /**
* \brief Cropping operation backward. * \brief Cropping operation backward.
...@@ -46,11 +39,11 @@ void Crop(real* outputs, ...@@ -46,11 +39,11 @@ void Crop(real* outputs,
* \param[out] inGrad gradients of previous layer * \param[out] inGrad gradients of previous layer
* \param[in] outGrad output gradient * \param[in] outGrad output gradient
* \param[in] inShape the shape of input tensor. * \param[in] inShape the shape of input tensor.
* \param[in] crop the cropping config * \param[in] conf the cropping config
*/ */
template <DeviceType Device> template <DeviceType Device>
void CropGrad(const real* inGrad, void CropGrad(const real* inGrad,
real* outGrad, real* outGrad,
const TensorShape inShape, const TensorShape inShape,
const CropConf& crop); const FuncConfig& conf);
} // namespace paddle } // namespace paddle
...@@ -37,19 +37,21 @@ template <> ...@@ -37,19 +37,21 @@ template <>
void Crop<DEVICE_TYPE_GPU>(real* outputs, void Crop<DEVICE_TYPE_GPU>(real* outputs,
const real* inputs, const real* inputs,
const TensorShape inShape, const TensorShape inShape,
const CropConf& crop) { const FuncConfig& conf) {
int cropC = crop.corner[0]; std::vector<uint32_t> crop_corner = conf.get<std::vector<uint32_t>>("crop_corner");
int cropH = crop.corner[1]; std::vector<uint32_t> crop_shape = conf.get<std::vector<uint32_t>>("crop_shape");
int cropW = crop.corner[2]; int cropC = crop_corner[1];
int cropH = crop_corner[2];
int cropW = crop_corner[3];
int num = inShape[0]; int num = inShape[0];
int inC = inShape[1]; int inC = inShape[1];
int inH = inShape[2]; int inH = inShape[2];
int inW = inShape[3]; int inW = inShape[3];
int outC = crop.shape[0]; int outC = crop_shape[1];
int outH = crop.shape[1]; int outH = crop_shape[2];
int outW = crop.shape[2]; int outW = crop_shape[3];
size_t nth = num * outC * outH * outW; size_t nth = num * outC * outH * outW;
int blockSize = 1024; int blockSize = 1024;
...@@ -82,19 +84,21 @@ template <> ...@@ -82,19 +84,21 @@ template <>
void CropGrad<DEVICE_TYPE_GPU>(const real* inGrad, void CropGrad<DEVICE_TYPE_GPU>(const real* inGrad,
real* outGrad, real* outGrad,
const TensorShape outShape, const TensorShape outShape,
const CropConf& crop) { const FuncConfig& conf) {
int cropC = crop.corner[0]; std::vector<uint32_t> crop_corner = conf.get<std::vector<uint32_t>>("crop_corner");
int cropH = crop.corner[1]; std::vector<uint32_t> crop_shape = conf.get<std::vector<uint32_t>>("crop_shape");
int cropW = crop.corner[2]; int cropC = crop_corner[1];
int cropH = crop_corner[2];
int cropW = crop_corner[3];
int num = outShape[0]; int num = outShape[0];
int outC = outShape[1]; int outC = outShape[1];
int outH = outShape[2]; int outH = outShape[2];
int outW = outShape[3]; int outW = outShape[3];
int inC = crop.shape[0]; int inC = crop_shape[1];
int inH = crop.shape[1]; int inH = crop_shape[2];
int inW = crop.shape[2]; int inW = crop_shape[3];
size_t nth = num * inC * inH * inW; size_t nth = num * inC * inH * inW;
int blockSize = 1024; int blockSize = 1024;
......
...@@ -28,8 +28,8 @@ TEST(Crop, real) { ...@@ -28,8 +28,8 @@ TEST(Crop, real) {
FunctionCompare compare( FunctionCompare compare(
test_grad ? "CropGrad" : "Crop", test_grad ? "CropGrad" : "Crop",
FuncConfig() FuncConfig()
.set<std::vector<uint32_t>>("crop_corner", {1, 1, 1}) .set<std::vector<uint32_t>>("crop_corner", {0, 1, 1, 1})
.set<std::vector<uint32_t>>("crop_shape", {2, 3, 3})); .set<std::vector<uint32_t>>("crop_shape", {0, 2, 3, 3}));
TensorShape inDims{numSamples, channels, imgSizeH, imgSizeW}; TensorShape inDims{numSamples, channels, imgSizeH, imgSizeW};
TensorShape outDims{numSamples, 2, 3, 3}; TensorShape outDims{numSamples, 2, 3, 3};
compare.addInputs( compare.addInputs(
......
...@@ -25,20 +25,57 @@ bool CropLayer::init(const LayerMap& layerMap, ...@@ -25,20 +25,57 @@ bool CropLayer::init(const LayerMap& layerMap,
Layer::init(layerMap, parameterMap); Layer::init(layerMap, parameterMap);
auto& crop_conf = config_.inputs(0).crop_conf(); auto& crop_conf = config_.inputs(0).crop_conf();
auto& img_conf = crop_conf.image_conf(); crop_axis_ = crop_conf.axis();
CHECK_EQ(config_.inputs_size(), 1); for (int i = 0; i < crop_conf.offset_size(); i++) {
inDims_ = TensorShape( crop_offsets_[i] = crop_conf.offset(i);
{0, }
img_conf.channels(),
img_conf.has_img_size_y() ? img_conf.img_size_y() : img_conf.img_size(), // 1. get input_0 shape
img_conf.img_size()}); auto& input0_img_conf = config_.inputs(0).image_conf();
inDims_ = TensorShape({0,
crop_corner_ = {crop_conf.crop_corner(0), input0_img_conf.channels(),
crop_conf.crop_corner(1), input0_img_conf.has_img_size_y()
crop_conf.crop_corner(2)}; ? input0_img_conf.img_size_y()
crop_shape_ = {crop_conf.crop_shape(0), : input0_img_conf.img_size(),
crop_conf.crop_shape(1), input0_img_conf.img_size()});
crop_conf.crop_shape(2)};
// 2. get output shape from input_1 or crop shap conf
if (config_.inputs_size() == 2) {
auto& input1_img_conf = config_.inputs(1).image_conf();
targetDims_ = TensorShape({0,
input1_img_conf.channels(),
input1_img_conf.has_img_size_y()
? input1_img_conf.img_size_y()
: input1_img_conf.img_size(),
input1_img_conf.img_size()});
} else {
targetDims_ = TensorShape({crop_conf.shape(0),
crop_conf.shape(1),
crop_conf.shape(2),
crop_conf.shape(3)});
}
// 3. get final crop shape
int dimSize = 4;
for (int i = 0; i < dimSize; i++) {
if (i >= crop_axis_) {
crop_shape_[i] = targetDims_[i];
} else {
crop_shape_[i] = inDims_[i];
}
}
// 4. get final crop corner
crop_corner_ = {0, 0, 0, 0};
for (int i = 0; i < dimSize; i++) {
if (i >= crop_axis_) {
if (crop_offsets_.size() > 1) {
crop_corner_[i] = crop_offsets_[i - crop_axis_];
} else {
crop_corner_[i] = crop_offsets_[0];
}
}
}
outDims_ = TensorShape(4); outDims_ = TensorShape(4);
setOutDims(0); setOutDims(0);
...@@ -58,7 +95,7 @@ bool CropLayer::init(const LayerMap& layerMap, ...@@ -58,7 +95,7 @@ bool CropLayer::init(const LayerMap& layerMap,
} }
void CropLayer::setOutDims(const size_t batchSize) { void CropLayer::setOutDims(const size_t batchSize) {
outDims_.reshape({batchSize, crop_shape_[0], crop_shape_[1], crop_shape_[2]}); outDims_.reshape({batchSize, crop_shape_[1], crop_shape_[2], crop_shape_[3]});
} }
void CropLayer::setTensorDim(const size_t batchSize) { void CropLayer::setTensorDim(const size_t batchSize) {
......
...@@ -19,9 +19,13 @@ limitations under the License. */ ...@@ -19,9 +19,13 @@ limitations under the License. */
namespace paddle { namespace paddle {
/** /**
* \brief This layer crop inputs according to the specify corner and shape. * \brief This layer crop input according to the specify conf.
* The input and output is a 4D tensor. Cropping from the 2nd to * input_0: input to be cropped
* the 4th dimenstion. * input_1: optional reference input
* axis: start dimension to be croped
* offset: offset of cropping in each dimension
* shape: if reference input layer was not setted,
* crop input as this shape conf
*/ */
class CropLayer : public Layer { class CropLayer : public Layer {
public: public:
...@@ -38,9 +42,12 @@ protected: ...@@ -38,9 +42,12 @@ protected:
void setOutDims(const size_t batchSize); void setOutDims(const size_t batchSize);
void setTensorDim(const size_t batchSize); void setTensorDim(const size_t batchSize);
int32_t crop_axis_;
std::vector<uint32_t> crop_offsets_;
std::vector<uint32_t> crop_corner_; std::vector<uint32_t> crop_corner_;
std::vector<uint32_t> crop_shape_; std::vector<uint32_t> crop_shape_;
TensorShape inDims_; TensorShape inDims_;
TensorShape targetDims_;
TensorShape outDims_; TensorShape outDims_;
}; };
} // namespace paddle } // namespace paddle
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册