diff --git a/paddle/fluid/operators/detection/box_coder_op.cc b/paddle/fluid/operators/detection/box_coder_op.cc index 2ce844669bd0e0ec904971565bd66c83a79d353e..f89f87663b9062c552b50c3f262c7f08d32b9c6e 100644 --- a/paddle/fluid/operators/detection/box_coder_op.cc +++ b/paddle/fluid/operators/detection/box_coder_op.cc @@ -32,7 +32,7 @@ class BoxCoderOp : public framework::OperatorWithKernel { if (ctx->IsRuntime()) { PADDLE_ENFORCE_EQ(prior_box_dims.size(), 2, - "The rank of Input of PriorBox must be 2"); + "The rank of Input PriorBox must be 2"); PADDLE_ENFORCE_EQ(prior_box_dims[1], 4, "The shape of PriorBox is [N, 4]"); if (ctx->HasInput("PriorBoxVar")) { @@ -58,7 +58,7 @@ class BoxCoderOp : public framework::OperatorWithKernel { int axis = ctx->Attrs().Get("axis"); if (code_type == BoxCodeType::kEncodeCenterSize) { PADDLE_ENFORCE_EQ(target_box_dims.size(), 2, - "The rank of Input of TargetBox must be 2"); + "The rank of Input TargetBox must be 2"); PADDLE_ENFORCE_EQ(target_box_dims[1], 4, "The shape of TargetBox is [M, 4]"); ctx->SetOutputDim( @@ -66,7 +66,7 @@ class BoxCoderOp : public framework::OperatorWithKernel { framework::make_ddim({target_box_dims[0], prior_box_dims[0], 4})); } else if (code_type == BoxCodeType::kDecodeCenterSize) { PADDLE_ENFORCE_EQ(target_box_dims.size(), 3, - "The rank of Input of TargetBox must be 3"); + "The rank of Input TargetBox must be 3"); if (axis == 0) { PADDLE_ENFORCE_EQ(target_box_dims[1], prior_box_dims[0]); } else if (axis == 1) { @@ -126,8 +126,11 @@ class BoxCoderOpMaker : public framework::OpProtoAndCheckerMaker { "whether treat the priorbox as a noramlized box") .SetDefault(true); AddAttr("axis", - "(int, default 1)" - "which axis to broadcast for box decode, it is only valid" + "(int, default 0)" + "which axis in PriorBox to broadcast for box decode," + "for example, if axis is 0 and TargetBox has shape" + "[N, M, 4] and PriorBox has shape [M, 4], then PriorBox " + "will broadcast to [N, M, 4] for decoding. It is only valid" "when code type is decode_center_size") .SetDefault(0) .InEnum({0, 1}); diff --git a/paddle/fluid/operators/detection/box_coder_op.cu b/paddle/fluid/operators/detection/box_coder_op.cu index ca62afd8edfc8ed8f682c8998818050f00524807..0b64224e1ea5fd9a7bb20b4c88a00de0446b7d82 100644 --- a/paddle/fluid/operators/detection/box_coder_op.cu +++ b/paddle/fluid/operators/detection/box_coder_op.cu @@ -79,10 +79,7 @@ __global__ void DecodeCenterSizeKernel(const T* prior_box_data, if (idx < row * col) { const int col_idx = idx % col; const int row_idx = idx / col; - if (axis == 0) - prior_box_offset = col_idx * len; - else if (axis == 1) - prior_box_offset = row_idx * len; + prior_box_offset = axis == 0 ? col_idx * len : row_idx * len; T prior_box_width = prior_box_data[prior_box_offset + 2] - prior_box_data[prior_box_offset] + (normalized == false); @@ -98,10 +95,7 @@ __global__ void DecodeCenterSizeKernel(const T* prior_box_data, if (prior_box_var_data) { int prior_var_offset = 0; if (prior_box_var_size == 2) { - if (axis == 0) - prior_var_offset = col_idx * len; - else if (axis == 1) - prior_var_offset = row_idx * len; + prior_var_offset = axis == 0 ? col_idx * len : row_idx * len; } target_box_width = exp(prior_box_var_data[prior_var_offset + 2] * target_box_data[idx * len + 2]) * diff --git a/python/paddle/fluid/layers/detection.py b/python/paddle/fluid/layers/detection.py index c844050c5db28bc42006338a6d5054c4b27a30a6..8c8a6c62232423d547a8a07949992374eaaa75c8 100644 --- a/python/paddle/fluid/layers/detection.py +++ b/python/paddle/fluid/layers/detection.py @@ -342,8 +342,8 @@ def box_coder(prior_box, target_box, code_type="encode_center_size", box_normalized=True, - axis=0, - name=None): + name=None, + axis=0): """ ${comment} diff --git a/python/paddle/fluid/tests/unittests/test_box_coder_op.py b/python/paddle/fluid/tests/unittests/test_box_coder_op.py index b6f6bc1450fb3a19883a21f9a296292a8b66df0a..6f7930c921166ff44f16bb74175bd3c7267d436d 100644 --- a/python/paddle/fluid/tests/unittests/test_box_coder_op.py +++ b/python/paddle/fluid/tests/unittests/test_box_coder_op.py @@ -21,121 +21,80 @@ import math from op_test import OpTest -def box_coder(target_box, - prior_box, - prior_box_var, - output_box, - code_type, - box_normalized, - axis=0): - prior_box_width = prior_box[:, 2] - prior_box[:, 0] + \ - (box_normalized==False) - prior_box_height = prior_box[:, 3] - prior_box[:, 1] + \ - (box_normalized==False) - prior_box_x = prior_box_width * 0.5 + prior_box[:, 0] - prior_box_y = prior_box_height * 0.5 + prior_box[:, 1] - if axis == 0: - prior_box_width = prior_box_width.reshape(1, prior_box.shape[0]) - prior_box_height = prior_box_height.reshape(1, prior_box.shape[0]) - prior_box_x = prior_box_x.reshape(1, prior_box.shape[0]) - prior_box_y = prior_box_y.reshape(1, prior_box.shape[0]) +def box_decoder(t_box, p_box, pb_v, output_box, norm, axis=0): + pb_w = p_box[:, 2] - p_box[:, 0] + (norm == False) + pb_h = p_box[:, 3] - p_box[:, 1] + (norm == False) + pb_x = pb_w * 0.5 + p_box[:, 0] + pb_y = pb_h * 0.5 + p_box[:, 1] + shape = (1, p_box.shape[0]) if axis == 0 else (p_box.shape[0], 1) + + pb_w = pb_w.reshape(shape) + pb_h = pb_h.reshape(shape) + pb_x = pb_x.reshape(shape) + pb_y = pb_y.reshape(shape) + + if pb_v.ndim == 2: + pb_v = pb_v.reshape(1, pb_v.shape[0], pb_v.shape[1]) + if pb_v.ndim == 1: + tb_x = pb_v[0] * t_box[:, :, 0] * pb_w + pb_x + tb_y = pb_v[1] * t_box[:, :, 1] * pb_h + pb_y + tb_w = np.exp(pb_v[2] * t_box[:, :, 2]) * pb_w + tb_h = np.exp(pb_v[3] * t_box[:, :, 3]) * pb_h else: - prior_box_width = prior_box_width.reshape(prior_box.shape[0], 1) - prior_box_height = prior_box_height.reshape(prior_box.shape[0], 1) - prior_box_x = prior_box_x.reshape(prior_box.shape[0], 1) - prior_box_y = prior_box_y.reshape(prior_box.shape[0], 1) - if prior_box_var.ndim == 2: - prior_box_var = prior_box_var.reshape(1, prior_box_var.shape[0], - prior_box_var.shape[1]) - if (code_type == "EncodeCenterSize"): - target_box_x = ((target_box[:, 2] + target_box[:, 0]) / 2).reshape( - target_box.shape[0], 1) - target_box_y = ((target_box[:, 3] + target_box[:, 1]) / 2).reshape( - target_box.shape[0], 1) - target_box_width = ((target_box[:, 2] - target_box[:, 0])).reshape( - target_box.shape[0], 1) - target_box_height = ((target_box[:, 3] - target_box[:, 1])).reshape( - target_box.shape[0], 1) - if not box_normalized: - target_box_height = target_box_height + 1 - target_box_width = target_box_width + 1 - if prior_box_var.ndim == 1: - output_box[:,:,0] = (target_box_x - prior_box_x) / \ - prior_box_width / \ - prior_box_var[0] - output_box[:,:,1] = (target_box_y - prior_box_y) / \ - prior_box_height / \ - prior_box_var[1] - output_box[:,:,2] = np.log(np.fabs(target_box_width / \ - prior_box_width)) / \ - prior_box_var[2] - output_box[:,:,3] = np.log(np.fabs(target_box_height / \ - prior_box_height)) / \ - prior_box_var[3] - else: - output_box[:,:,0] = (target_box_x - prior_box_x) / \ - prior_box_width / \ - prior_box_var[:,:,0] - output_box[:,:,1] = (target_box_y - prior_box_y) / \ - prior_box_height / \ - prior_box_var[:,:,1] - output_box[:,:,2] = np.log(np.fabs(target_box_width / \ - prior_box_width)) / \ - prior_box_var[:,:,2] - output_box[:,:,3] = np.log(np.fabs(target_box_height / \ - prior_box_height)) / \ - prior_box_var[:,:,3] - - elif (code_type == "DecodeCenterSize"): - if prior_box_var.ndim == 1: - target_box_x = prior_box_var[0] * target_box[:,:,0] * \ - prior_box_width + prior_box_x - target_box_y = prior_box_var[1] * target_box[:,:,1] * \ - prior_box_height + prior_box_y - target_box_width = np.exp(prior_box_var[2] * target_box[:,:,2]) * \ - prior_box_width - target_box_height = np.exp(prior_box_var[3] * target_box[:,:,3]) * \ - prior_box_height - else: - target_box_x = prior_box_var[:,:,0] * target_box[:,:,0] * \ - prior_box_width + prior_box_x - target_box_y = prior_box_var[:,:,1] * target_box[:,:,1] * \ - prior_box_height + prior_box_y - target_box_width = np.exp(prior_box_var[:,:,2] * \ - target_box[:,:,2]) * prior_box_width - target_box_height = np.exp(prior_box_var[:,:,3] * \ - target_box[:,:,3]) * prior_box_height - output_box[:, :, 0] = target_box_x - target_box_width / 2 - output_box[:, :, 1] = target_box_y - target_box_height / 2 - output_box[:, :, 2] = target_box_x + target_box_width / 2 - output_box[:, :, 3] = target_box_y + target_box_height / 2 - if not box_normalized: - output_box[:, :, 2] = output_box[:, :, 2] - 1 - output_box[:, :, 3] = output_box[:, :, 3] - 1 - - -def batch_box_coder(prior_box, - prior_box_var, - target_box, - lod, - code_type, - box_normalized, - axis=0): - n = target_box.shape[0] - m = prior_box.shape[0] + tb_x = pb_v[:, :, 0] * t_box[:, :, 0] * pb_w + pb_x + tb_y = pb_v[:, :, 1] * t_box[:, :, 1] * pb_h + pb_y + tb_w = np.exp(pb_v[:, :, 2] * t_box[:, :, 2]) * pb_w + tb_h = np.exp(pb_v[:, :, 3] * t_box[:, :, 3]) * pb_h + output_box[:, :, 0] = tb_x - tb_w / 2 + output_box[:, :, 1] = tb_y - tb_h / 2 + output_box[:, :, 2] = tb_x + tb_w / 2 - (not norm) + output_box[:, :, 3] = tb_y + tb_h / 2 - (not norm) + + +def box_encoder(t_box, p_box, pb_v, output_box, norm): + pb_w = p_box[:, 2] - p_box[:, 0] + (norm == False) + pb_h = p_box[:, 3] - p_box[:, 1] + (norm == False) + pb_x = pb_w * 0.5 + p_box[:, 0] + pb_y = pb_h * 0.5 + p_box[:, 1] + shape = (1, p_box.shape[0]) + + pb_w = pb_w.reshape(shape) + pb_h = pb_h.reshape(shape) + pb_x = pb_x.reshape(shape) + pb_y = pb_y.reshape(shape) + + if pb_v.ndim == 2: + pb_v = pb_v.reshape(1, pb_v.shape[0], pb_v.shape[1]) + tb_x = ((t_box[:, 2] + t_box[:, 0]) / 2).reshape(t_box.shape[0], 1) + tb_y = ((t_box[:, 3] + t_box[:, 1]) / 2).reshape(t_box.shape[0], 1) + tb_w = (t_box[:, 2] - t_box[:, 0]).reshape(t_box.shape[0], 1) + (not norm) + tb_h = (t_box[:, 3] - t_box[:, 1]).reshape(t_box.shape[0], 1) + (not norm) + if pb_v.ndim == 1: + output_box[:, :, 0] = (tb_x - pb_x) / pb_w / pb_v[0] + output_box[:, :, 1] = (tb_y - pb_y) / pb_h / pb_v[1] + output_box[:, :, 2] = np.log(np.fabs(tb_w / pb_w)) / pb_v[2] + output_box[:, :, 3] = np.log(np.fabs(tb_h / pb_h)) / pb_v[3] + else: + output_box[:, :, 0] = (tb_x - pb_x) / pb_w / pb_v[:, :, 0] + output_box[:, :, 1] = (tb_y - pb_y) / pb_h / pb_v[:, :, 1] + output_box[:, :, 2] = np.log(np.fabs(tb_w / pb_w)) / pb_v[:, :, 2] + output_box[:, :, 3] = np.log(np.fabs(tb_h / pb_h)) / pb_v[:, :, 3] + + +def batch_box_coder(p_box, pb_v, t_box, lod, code_type, norm, axis=0): + n = t_box.shape[0] + m = p_box.shape[0] if code_type == "DecodeCenterSize": - m = target_box.shape[1] + m = t_box.shape[1] output_box = np.zeros((n, m, 4), dtype=np.float32) cur_offset = 0 for i in range(len(lod)): if (code_type == "EncodeCenterSize"): - box_coder(target_box[cur_offset:(cur_offset + lod[i]), :], - prior_box, prior_box_var, - output_box[cur_offset:(cur_offset + lod[i]), :, :], - code_type, box_normalized) + box_encoder(t_box[cur_offset:(cur_offset + lod[i]), :], p_box, pb_v, + output_box[cur_offset:(cur_offset + lod[i]), :, :], + norm) elif (code_type == "DecodeCenterSize"): - box_coder(target_box, prior_box, prior_box_var, output_box, - code_type, box_normalized, axis) + box_decoder(t_box, p_box, pb_v, output_box, norm, axis) cur_offset += lod[i] return output_box