From 1c558ad388aa8b9d256e90d6640b82f5170e3a18 Mon Sep 17 00:00:00 2001 From: jerrywgz Date: Tue, 22 Jan 2019 12:26:12 +0000 Subject: [PATCH] add gpu kernel for box clip, test=develop --- .../fluid/operators/detection/CMakeLists.txt | 2 +- .../fluid/operators/detection/box_clip_op.cc | 45 +++++++++++-------- .../fluid/operators/detection/box_clip_op.h | 4 +- python/paddle/fluid/layers/detection.py | 42 ++++++++++++----- .../fluid/tests/unittests/test_box_clip_op.py | 4 +- 5 files changed, 63 insertions(+), 34 deletions(-) diff --git a/paddle/fluid/operators/detection/CMakeLists.txt b/paddle/fluid/operators/detection/CMakeLists.txt index b0f023935d2..1c9e8a454c8 100644 --- a/paddle/fluid/operators/detection/CMakeLists.txt +++ b/paddle/fluid/operators/detection/CMakeLists.txt @@ -31,7 +31,7 @@ detection_library(polygon_box_transform_op SRCS polygon_box_transform_op.cc polygon_box_transform_op.cu) detection_library(rpn_target_assign_op SRCS rpn_target_assign_op.cc) detection_library(generate_proposal_labels_op SRCS generate_proposal_labels_op.cc) -detection_library(box_clip_op SRCS box_clip_op.cc) +detection_library(box_clip_op SRCS box_clip_op.cc box_clip_op.cu) if(WITH_GPU) detection_library(generate_proposals_op SRCS generate_proposals_op.cc generate_proposals_op.cu DEPS memory cub) diff --git a/paddle/fluid/operators/detection/box_clip_op.cc b/paddle/fluid/operators/detection/box_clip_op.cc index e47027d98c4..15adcdedaed 100644 --- a/paddle/fluid/operators/detection/box_clip_op.cc +++ b/paddle/fluid/operators/detection/box_clip_op.cc @@ -21,51 +21,58 @@ class BoxClipOp : public framework::OperatorWithKernel { protected: void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("InputBox"), - "Input(InputBox) of BoxClipOp should not be null."); + PADDLE_ENFORCE(ctx->HasInput("Input"), + "Input(Input) of BoxClipOp should not be null."); PADDLE_ENFORCE(ctx->HasInput("ImInfo"), "Input(ImInfo) of BoxClipOp should not be null."); - auto input_box_dims = ctx->GetInputDim("InputBox"); + auto input_box_dims = ctx->GetInputDim("Input"); auto im_info_dims = ctx->GetInputDim("ImInfo"); if (ctx->IsRuntime()) { auto input_box_size = input_box_dims.size(); PADDLE_ENFORCE_EQ(input_box_dims[input_box_size - 1], 4, - "The last dimension of InputBox must be 4"); + "The last dimension of Input must be 4"); PADDLE_ENFORCE_EQ(im_info_dims.size(), 2, - "The rank of Input(InputBox) in BoxClipOp must be 2"); + "The rank of Input(Input) in BoxClipOp must be 2"); PADDLE_ENFORCE_EQ(im_info_dims[1], 3, "The last dimension of ImInfo must be 3"); } - ctx->ShareDim("InputBox", /*->*/ "OutputBox"); - ctx->ShareLoD("InputBox", /*->*/ "OutputBox"); - } - - protected: - framework::OpKernelType GetExpectedKernelType( - const framework::ExecutionContext& ctx) const override { - auto data_type = framework::GetDataTypeOfVar(ctx.InputVar("InputBox")); - return framework::OpKernelType(data_type, platform::CPUPlace()); + ctx->ShareDim("Input", /*->*/ "Output"); + ctx->ShareLoD("Input", /*->*/ "Output"); } + /* + protected: + framework::OpKernelType GetExpectedKernelType( + const framework::ExecutionContext& ctx) const override { + auto data_type = framework::GetDataTypeOfVar(ctx.InputVar("Input")); + return framework::OpKernelType(data_type, platform::CPUPlace()); + } + */ }; class BoxClipOpMaker : public framework::OpProtoAndCheckerMaker { public: void Make() override { - AddInput("InputBox", + AddInput("Input", "(LoDTensor) " - "InputBox is a LoDTensor with shape [..., 4] holds 4 points" + "Input is a LoDTensor with shape [..., 4] holds 4 points" "in last dimension in format [xmin, ymin, xmax, ymax]"); AddInput("ImInfo", "(Tensor) Information for image reshape is in shape (N, 3), " "in format (height, width, im_scale)"); - AddOutput("OutputBox", + AddOutput("Output", "(LoDTensor) " - "OutputBox is a LoDTensor with the same shape as InputBox" + "Output is a LoDTensor with the same shape as Input" "and it is the result after clip"); AddComment(R"DOC( - This operator clips input boxes to original input images. +This operator clips input boxes to original input images. + +The formula is given as follows: + + $$height_out = \max(\min(height_loc, im_h), 0)$$ + $$width_out = \max(\min(width_loc, im_w), 0)$$ + )DOC"); } }; diff --git a/paddle/fluid/operators/detection/box_clip_op.h b/paddle/fluid/operators/detection/box_clip_op.h index 88d35d2a88c..74e1f88f8d8 100644 --- a/paddle/fluid/operators/detection/box_clip_op.h +++ b/paddle/fluid/operators/detection/box_clip_op.h @@ -25,9 +25,9 @@ template class BoxClipKernel : public framework::OpKernel { public: void Compute(const framework::ExecutionContext& context) const override { - auto* input_box = context.Input("InputBox"); + auto* input_box = context.Input("Input"); auto* im_info = context.Input("ImInfo"); - auto* output_box = context.Output("OutputBox"); + auto* output_box = context.Output("Output"); auto& dev_ctx = context.template device_context(); output_box->mutable_data(context.GetPlace()); diff --git a/python/paddle/fluid/layers/detection.py b/python/paddle/fluid/layers/detection.py index 477ae67d0bf..3e2882ea3ce 100644 --- a/python/paddle/fluid/layers/detection.py +++ b/python/paddle/fluid/layers/detection.py @@ -31,11 +31,24 @@ import numpy from functools import reduce __all__ = [ - 'prior_box', 'density_prior_box', 'multi_box_head', 'bipartite_match', - 'target_assign', 'detection_output', 'ssd_loss', 'detection_map', - 'rpn_target_assign', 'anchor_generator', 'roi_perspective_transform', - 'generate_proposal_labels', 'generate_proposals', 'iou_similarity', - 'box_coder', 'polygon_box_transform', 'yolov3_loss', 'box_clip' + 'prior_box', + 'density_prior_box', + 'multi_box_head', + 'bipartite_match', + 'target_assign', + 'detection_output', + 'ssd_loss', + 'detection_map', + 'rpn_target_assign', + 'anchor_generator', + 'roi_perspective_transform', + 'generate_proposal_labels', + 'generate_proposals', + 'iou_similarity', + 'box_coder', + 'polygon_box_transform', + 'yolov3_loss', + 'box_clip', ] @@ -1800,13 +1813,22 @@ def generate_proposals(scores, return rpn_rois, rpn_roi_probs -def box_clip(input_box, im_info, inplace=False, name=None): +def box_clip(input, im_info, inplace=False, name=None): """ Clip the box into the size given by im_info + The formula is given as follows: + + .. code-block:: text + + height_out = max(min(height_loc, im_h), 0) + width_out = max(min(width_loc, im_w), 0) Args: input_box(variable): The input box, the last dimension is 4. - im_info(variable): The information of image with shape [N, 3]. + im_info(variable): The information of image with shape [N, 3] with + layout (height, width, scale). height and width + is the input size and scale is the ratio of input + size and original size. inplace(bool): Must use :attr:`False` if :attr:`input_box` is used in multiple operators. If this flag is set :attr:`True`, reuse input :attr:`input_box` to clip, which will @@ -1832,12 +1854,12 @@ def box_clip(input_box, im_info, inplace=False, name=None): """ helper = LayerHelper("box_clip", **locals()) - output = helper.create_variable_for_type_inference(dtype=input_box.dtype) - inputs = {"InputBox": input_box, "ImInfo": im_info} + output = helper.create_variable_for_type_inference(dtype=input.dtype) + inputs = {"Input": input, "ImInfo": im_info} helper.append_op( type="box_clip", inputs=inputs, attrs={"inplace:": inplace}, - outputs={"OutputBox": output}) + outputs={"Output": output}) return output diff --git a/python/paddle/fluid/tests/unittests/test_box_clip_op.py b/python/paddle/fluid/tests/unittests/test_box_clip_op.py index 6cd3f21a6e2..b2b0598f31d 100644 --- a/python/paddle/fluid/tests/unittests/test_box_clip_op.py +++ b/python/paddle/fluid/tests/unittests/test_box_clip_op.py @@ -60,10 +60,10 @@ class TestBoxClipOp(OpTest): output_boxes = batch_box_clip(input_boxes, im_info, lod[0]) self.inputs = { - 'InputBox': (input_boxes.astype('float32'), lod), + 'Input': (input_boxes.astype('float32'), lod), 'ImInfo': im_info.astype('float32'), } - self.outputs = {'OutputBox': output_boxes} + self.outputs = {'Output': output_boxes} if __name__ == '__main__': -- GitLab