diff --git a/paddle/fluid/operators/detection/multiclass_nms_op.cc b/paddle/fluid/operators/detection/multiclass_nms_op.cc index 0cfb79b358b364d6669bd835fb75ea2d90c2961d..744e588bcb94b1923d392105fe35d9acdf4745d7 100644 --- a/paddle/fluid/operators/detection/multiclass_nms_op.cc +++ b/paddle/fluid/operators/detection/multiclass_nms_op.cc @@ -26,12 +26,9 @@ class MultiClassNMSOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("BBoxes"), - "Input(BBoxes) of MultiClassNMS should not be null."); - PADDLE_ENFORCE(ctx->HasInput("Scores"), - "Input(Scores) of MultiClassNMS should not be null."); - PADDLE_ENFORCE(ctx->HasOutput("Out"), - "Output(Out) of MultiClassNMS should not be null."); + OP_INOUT_CHECK(ctx->HasInput("BBoxes"), "Input", "BBoxes", "MultiClassNMS"); + OP_INOUT_CHECK(ctx->HasInput("Scores"), "Input", "Scores", "MultiClassNMS"); + OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", "MultiClassNMS"); auto box_dims = ctx->GetInputDim("BBoxes"); auto score_dims = ctx->GetInputDim("Scores"); @@ -41,7 +38,10 @@ class MultiClassNMSOp : public framework::OperatorWithKernel { PADDLE_ENFORCE(score_size == 2 || score_size == 3, "The rank of Input(Scores) must be 2 or 3"); PADDLE_ENFORCE_EQ(box_dims.size(), 3, - "The rank of Input(BBoxes) must be 3"); + platform::errors::InvalidArgument( + "The rank of Input(BBoxes) must be 3" + "But receive box_dims size(%s)", + box_dims.size())); if (score_size == 3) { PADDLE_ENFORCE(box_dims[2] == 4 || box_dims[2] == 8 || box_dims[2] == 16 || box_dims[2] == 24 || @@ -55,16 +55,26 @@ class MultiClassNMSOp : public framework::OperatorWithKernel { "16 points: [xi, yi] i= 1,2,...,16"); PADDLE_ENFORCE_EQ( box_dims[1], score_dims[2], - "The 2nd dimension of Input(BBoxes) must be equal to " - "last dimension of Input(Scores), which represents the " - "predicted bboxes."); + platform::errors::InvalidArgument( + "The 2nd dimension of Input(BBoxes) must be equal to " + "last dimension of Input(Scores), which represents the " + "predicted bboxes." + "But received box_dims[1](%s) != socre_dims[2](%s)", + box_dims[1], score_dims[2])); } else { - PADDLE_ENFORCE(box_dims[2] == 4, - "The last dimension of Input(BBoxes) must be 4"); + PADDLE_ENFORCE_EQ(box_dims[2], 4, + platform::errors::InvalidArgument( + "The last dimension of Input(BBoxes) must be 4" + "But received box_dims[2](%s).", + box_dims[2])); PADDLE_ENFORCE_EQ(box_dims[1], score_dims[1], - "The 2nd dimension of Input(BBoxes)" - "must be equal to the 2nd dimension" - " of Input(Scores)"); + platform::errors::InvalidArgument( + "The 2nd dimension of Input(BBoxes)" + "must be equal to the 2nd dimension" + " of Input(Scores)" + "But received box_dims[1](%s) != " + "score_dims[1](%s)", + box_dims[1], score_dims[1])); } } // Here the box_dims[0] is not the real dimension of output. diff --git a/paddle/fluid/operators/detection/yolo_box_op.cc b/paddle/fluid/operators/detection/yolo_box_op.cc index 7090601dacf3bae97b337d4710b00fa2598bdce3..f6c32a1332cc8e1a63673b0b025437be9074f6f2 100644 --- a/paddle/fluid/operators/detection/yolo_box_op.cc +++ b/paddle/fluid/operators/detection/yolo_box_op.cc @@ -21,14 +21,10 @@ class YoloBoxOp : public framework::OperatorWithKernel { public: using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), - "Input(X) of YoloBoxOp should not be null."); - PADDLE_ENFORCE(ctx->HasInput("ImgSize"), - "Input(ImgSize) of YoloBoxOp should not be null."); - PADDLE_ENFORCE(ctx->HasOutput("Boxes"), - "Output(Boxes) of YoloBoxOp should not be null."); - PADDLE_ENFORCE(ctx->HasOutput("Scores"), - "Output(Scores) of YoloBoxOp should not be null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "YoloBoxOp"); + OP_INOUT_CHECK(ctx->HasInput("ImgSize"), "Input", "ImgSize", "YoloBoxOp"); + OP_INOUT_CHECK(ctx->HasOutput("Boxes"), "Output", "Boxes", "YoloBoxOp"); + OP_INOUT_CHECK(ctx->HasOutput("Scores"), "Output", "Scores", "YoloBoxOp"); auto dim_x = ctx->GetInputDim("X"); auto dim_imgsize = ctx->GetInputDim("ImgSize"); @@ -36,26 +32,49 @@ class YoloBoxOp : public framework::OperatorWithKernel { int anchor_num = anchors.size() / 2; auto class_num = ctx->Attrs().Get("class_num"); - PADDLE_ENFORCE_EQ(dim_x.size(), 4, "Input(X) should be a 4-D tensor."); + PADDLE_ENFORCE_EQ(dim_x.size(), 4, platform::errors::InvalidArgument( + "Input(X) should be a 4-D tensor." + "But received X dimension(%s)", + dim_x.size())); PADDLE_ENFORCE_EQ( dim_x[1], anchor_num * (5 + class_num), - "Input(X) dim[1] should be equal to (anchor_mask_number * (5 " - "+ class_num))."); + platform::errors::InvalidArgument( + "Input(X) dim[1] should be equal to (anchor_mask_number * (5 " + "+ class_num))." + "But received dim[1](%s) != (anchor_mask_number * " + "(5+class_num)(%s).", + dim_x[1], anchor_num * (5 + class_num))); PADDLE_ENFORCE_EQ(dim_imgsize.size(), 2, - "Input(ImgSize) should be a 2-D tensor."); + platform::errors::InvalidArgument( + "Input(ImgSize) should be a 2-D tensor." + "But received Imgsize size(%s)", + dim_imgsize.size())); if ((dim_imgsize[0] > 0 && dim_x[0] > 0) || ctx->IsRuntime()) { PADDLE_ENFORCE_EQ( dim_imgsize[0], dim_x[0], platform::errors::InvalidArgument( "Input(ImgSize) dim[0] and Input(X) dim[0] should be same.")); } - PADDLE_ENFORCE_EQ(dim_imgsize[1], 2, "Input(ImgSize) dim[1] should be 2."); + PADDLE_ENFORCE_EQ( + dim_imgsize[1], 2, + platform::errors::InvalidArgument("Input(ImgSize) dim[1] should be 2." + "But received imgsize dim[1](%s).", + dim_imgsize[1])); PADDLE_ENFORCE_GT(anchors.size(), 0, - "Attr(anchors) length should be greater than 0."); + platform::errors::InvalidArgument( + "Attr(anchors) length should be greater than 0." + "But received anchors length(%s).", + anchors.size())); PADDLE_ENFORCE_EQ(anchors.size() % 2, 0, - "Attr(anchors) length should be even integer."); + platform::errors::InvalidArgument( + "Attr(anchors) length should be even integer." + "But received anchors length (%s)", + anchors.size())); PADDLE_ENFORCE_GT(class_num, 0, - "Attr(class_num) should be an integer greater than 0."); + platform::errors::InvalidArgument( + "Attr(class_num) should be an integer greater than 0." + "But received class_num (%s)", + class_num)); int box_num = dim_x[2] * dim_x[3] * anchor_num; std::vector dim_boxes({dim_x[0], box_num, 4}); diff --git a/paddle/fluid/operators/detection/yolov3_loss_op.cc b/paddle/fluid/operators/detection/yolov3_loss_op.cc index dad955d6d23c359e2e3c76815d0e305ff04d90ef..ad13f334dae3659b183cdbba25d59cacef39c200 100644 --- a/paddle/fluid/operators/detection/yolov3_loss_op.cc +++ b/paddle/fluid/operators/detection/yolov3_loss_op.cc @@ -23,19 +23,15 @@ class Yolov3LossOp : public framework::OperatorWithKernel { public: using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), - "Input(X) of Yolov3LossOp should not be null."); - PADDLE_ENFORCE(ctx->HasInput("GTBox"), - "Input(GTBox) of Yolov3LossOp should not be null."); - PADDLE_ENFORCE(ctx->HasInput("GTLabel"), - "Input(GTLabel) of Yolov3LossOp should not be null."); - PADDLE_ENFORCE(ctx->HasOutput("Loss"), - "Output(Loss) of Yolov3LossOp should not be null."); - PADDLE_ENFORCE( - ctx->HasOutput("ObjectnessMask"), - "Output(ObjectnessMask) of Yolov3LossOp should not be null."); - PADDLE_ENFORCE(ctx->HasOutput("GTMatchMask"), - "Output(GTMatchMask) of Yolov3LossOp should not be null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "Yolov3LossOp"); + OP_INOUT_CHECK(ctx->HasInput("GTBox"), "Input", "GTBox", "Yolov3LossOp"); + OP_INOUT_CHECK(ctx->HasInput("GTLabel"), "Input", "GTLabel", + "Yolov3LossOp"); + OP_INOUT_CHECK(ctx->HasOutput("Loss"), "Output", "Loss", "Yolov3LossOp"); + OP_INOUT_CHECK(ctx->HasOutput("ObjectnessMask"), "Output", "ObjectnessMask", + "Yolov3LossOp"); + OP_INOUT_CHECK(ctx->HasOutput("GTMatchMask"), "Output", "GTMatchMask", + "Yolov3LossOp"); auto dim_x = ctx->GetInputDim("X"); auto dim_gtbox = ctx->GetInputDim("GTBox"); @@ -46,44 +42,96 @@ class Yolov3LossOp : public framework::OperatorWithKernel { int mask_num = anchor_mask.size(); auto class_num = ctx->Attrs().Get("class_num"); - PADDLE_ENFORCE_EQ(dim_x.size(), 4, "Input(X) should be a 4-D tensor."); + PADDLE_ENFORCE_EQ(dim_x.size(), 4, + platform::errors::InvalidArgument( + "Input(X) should be a 4-D tensor. But received " + "X dimension size(%s)", + dim_x.size())); PADDLE_ENFORCE_EQ(dim_x[2], dim_x[3], - "Input(X) dim[3] and dim[4] should be euqal."); + platform::errors::InvalidArgument( + "Input(X) dim[3] and dim[4] should be euqal." + "But received dim[3](%s) != dim[4](%s)", + dim_x[2], dim_x[3])); PADDLE_ENFORCE_EQ( dim_x[1], mask_num * (5 + class_num), - "Input(X) dim[1] should be equal to (anchor_mask_number * (5 " - "+ class_num))."); + platform::errors::InvalidArgument( + "Input(X) dim[1] should be equal to (anchor_mask_number * (5 " + "+ class_num))." + "But received dim[1](%s) != (anchor_mask_number * " + "(5+class_num)(%s).", + dim_x[1], mask_num * (5 + class_num))); PADDLE_ENFORCE_EQ(dim_gtbox.size(), 3, - "Input(GTBox) should be a 3-D tensor"); - PADDLE_ENFORCE_EQ(dim_gtbox[2], 4, "Input(GTBox) dim[2] should be 5"); - PADDLE_ENFORCE_EQ(dim_gtlabel.size(), 2, - "Input(GTLabel) should be a 2-D tensor"); - PADDLE_ENFORCE_EQ(dim_gtlabel[0], dim_gtbox[0], - "Input(GTBox) and Input(GTLabel) dim[0] should be same"); - PADDLE_ENFORCE_EQ(dim_gtlabel[1], dim_gtbox[1], - "Input(GTBox) and Input(GTLabel) dim[1] should be same"); + platform::errors::InvalidArgument( + "Input(GTBox) should be a 3-D tensor, but " + "received gtbox dimension size(%s)", + dim_gtbox.size())); + PADDLE_ENFORCE_EQ(dim_gtbox[2], 4, + platform::errors::InvalidArgument( + "Input(GTBox) dim[2] should be 4", + "But receive dim[2](%s) != 5. ", dim_gtbox[2])); + PADDLE_ENFORCE_EQ( + dim_gtlabel.size(), 2, + platform::errors::InvalidArgument( + "Input(GTLabel) should be a 2-D tensor," + "But received Input(GTLabel) dimension size(%s) != 2.", + dim_gtlabel.size())); + PADDLE_ENFORCE_EQ( + dim_gtlabel[0], dim_gtbox[0], + platform::errors::InvalidArgument( + "Input(GTBox) dim[0] and Input(GTLabel) dim[0] should be same," + "But received Input(GTLabel) dim[0](%s) != " + "Input(GTBox) dim[0](%s)", + dim_gtlabel[0], dim_gtbox[0])); + PADDLE_ENFORCE_EQ( + dim_gtlabel[1], dim_gtbox[1], + platform::errors::InvalidArgument( + "Input(GTBox) and Input(GTLabel) dim[1] should be same," + "But received Input(GTBox) dim[1](%s) != Input(GTLabel) " + "dim[1](%s)", + dim_gtbox[1], dim_gtlabel[1])); PADDLE_ENFORCE_GT(anchors.size(), 0, - "Attr(anchors) length should be greater then 0."); + platform::errors::InvalidArgument( + "Attr(anchors) length should be greater then 0." + "But received anchors length(%s)", + anchors.size())); PADDLE_ENFORCE_EQ(anchors.size() % 2, 0, - "Attr(anchors) length should be even integer."); + platform::errors::InvalidArgument( + "Attr(anchors) length should be even integer." + "But received anchors length(%s)", + anchors.size())); for (size_t i = 0; i < anchor_mask.size(); i++) { PADDLE_ENFORCE_LT( anchor_mask[i], anchor_num, - "Attr(anchor_mask) should not crossover Attr(anchors)."); + platform::errors::InvalidArgument( + "Attr(anchor_mask) should not crossover Attr(anchors)." + "But received anchor_mask[i](%s) > anchor_num(%s)", + anchor_mask[i], anchor_num)); } PADDLE_ENFORCE_GT(class_num, 0, - "Attr(class_num) should be an integer greater then 0."); + platform::errors::InvalidArgument( + "Attr(class_num) should be an integer greater then 0." + "But received class_num(%s) < 0", + class_num)); if (ctx->HasInput("GTScore")) { auto dim_gtscore = ctx->GetInputDim("GTScore"); PADDLE_ENFORCE_EQ(dim_gtscore.size(), 2, - "Input(GTScore) should be a 2-D tensor"); + platform::errors::InvalidArgument( + "Input(GTScore) should be a 2-D tensor" + "But received GTScore dimension(%s)", + dim_gtbox.size())); PADDLE_ENFORCE_EQ( dim_gtscore[0], dim_gtbox[0], - "Input(GTBox) and Input(GTScore) dim[0] should be same"); + platform::errors::InvalidArgument( + "Input(GTBox) and Input(GTScore) dim[0] should be same" + "But received GTBox dim[0](%s) != GTScore dim[0](%s)", + dim_gtbox[0], dim_gtscore[0])); PADDLE_ENFORCE_EQ( dim_gtscore[1], dim_gtbox[1], - "Input(GTBox) and Input(GTScore) dim[1] should be same"); + platform::errors::InvalidArgument( + "Input(GTBox) and Input(GTScore) dim[1] should be same" + "But received GTBox dim[1](%s) != GTScore dim[1](%s)", + dim_gtscore[1], dim_gtbox[1])); } std::vector dim_out({dim_x[0]}); @@ -245,9 +293,12 @@ class Yolov3LossOpGrad : public framework::OperatorWithKernel { public: using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) should not be null"); - PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("Loss")), - "Input(Loss@GRAD) should not be null"); + PADDLE_ENFORCE_EQ( + ctx->HasInput("X"), true, + platform::errors::NotFound("Input(X) should not be null")); + PADDLE_ENFORCE_EQ( + ctx->HasInput(framework::GradVarName("Loss")), true, + platform::errors::NotFound("Input(Loss@GRAD) should not be null")); auto dim_x = ctx->GetInputDim("X"); if (ctx->HasOutput(framework::GradVarName("X"))) { ctx->SetOutputDim(framework::GradVarName("X"), dim_x); diff --git a/python/paddle/fluid/layers/detection.py b/python/paddle/fluid/layers/detection.py index ed98860645f6425be438d5e1d105e18ac38336cb..01d792430c3e219a9a94e63fc39f76ef1f007d99 100644 --- a/python/paddle/fluid/layers/detection.py +++ b/python/paddle/fluid/layers/detection.py @@ -3178,6 +3178,18 @@ def multiclass_nms(bboxes, keep_top_k=200, normalized=False) """ + check_variable_and_dtype(bboxes, 'BBoxes', ['float32', 'float64'], + 'multiclass_nms') + check_variable_and_dtype(scores, 'Scores', ['float32', 'float64'], + 'multiclass_nms') + check_type(score_threshold, 'score_threshold', float, 'multicalss_nms') + check_type(nms_top_k, 'nums_top_k', int, 'multiclass_nms') + check_type(keep_top_k, 'keep_top_k', int, 'mutliclass_nms') + check_type(nms_threshold, 'nms_threshold', float, 'multiclass_nms') + check_type(normalized, 'normalized', bool, 'multiclass_nms') + check_type(nms_eta, 'nms_eta', float, 'multiclass_nms') + check_type(background_label, 'background_label', int, 'multiclass_nms') + helper = LayerHelper('multiclass_nms', **locals()) output = helper.create_variable_for_type_inference(dtype=bboxes.dtype) @@ -3192,7 +3204,6 @@ def multiclass_nms(bboxes, 'nms_threshold': nms_threshold, 'nms_eta': nms_eta, 'keep_top_k': keep_top_k, - 'nms_eta': nms_eta, 'normalized': normalized }, outputs={'Out': output}) diff --git a/python/paddle/fluid/tests/unittests/test_multiclass_nms_op.py b/python/paddle/fluid/tests/unittests/test_multiclass_nms_op.py index a7240bc65f1b86597c0e1563fe50165a1a3de0fe..ab58d4bc88ef9823a8cf31666a784f858aa936fd 100644 --- a/python/paddle/fluid/tests/unittests/test_multiclass_nms_op.py +++ b/python/paddle/fluid/tests/unittests/test_multiclass_nms_op.py @@ -17,6 +17,8 @@ import unittest import numpy as np import copy from op_test import OpTest +import paddle.fluid as fluid +from paddle.fluid import Program, program_guard def softmax(x): @@ -487,5 +489,36 @@ class TestMulticlassNMS2LoDNoOutput(TestMulticlassNMS2LoDInput): self.score_threshold = 2.0 +class TestMulticlassNMSError(unittest.TestCase): + def test_errors(self): + with program_guard(Program(), Program()): + M = 1200 + N = 7 + C = 21 + BOX_SIZE = 4 + + boxes_np = np.random.random((M, C, BOX_SIZE)).astype('float32') + scores = np.random.random((N * M, C)).astype('float32') + scores = np.apply_along_axis(softmax, 1, scores) + scores = np.reshape(scores, (N, M, C)) + scores_np = np.transpose(scores, (0, 2, 1)) + + boxes_data = fluid.data( + name='bboxes', shape=[M, C, BOX_SIZE], dtype='float32') + scores_data = fluid.data( + name='scores', shape=[N, C, M], dtype='float32') + + def test_bboxes_Variable(): + # the bboxes type must be Variable + fluid.layers.multiclass_nms(bboxes=boxes_np, scores=scores_data) + + def test_scores_Variable(): + # the bboxes type must be Variable + fluid.layers.multiclass_nms(bboxes=boxes_data, scores=scores_np) + + self.assertRaises(TypeError, test_bboxes_Variable) + self.assertRaises(TypeError, test_scores_Variable) + + if __name__ == '__main__': unittest.main()