提交 6b9fbcf3 编写于 作者: F FDInSky 提交者: qingqing01

Update iou_similarity op to support non-normalized bbox (#21671)

Update iou_similarity op to support non-normalized bbox
上级 d053561d
...@@ -61,7 +61,10 @@ class IOUSimilarityOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -61,7 +61,10 @@ class IOUSimilarityOpMaker : public framework::OpProtoAndCheckerMaker {
"[xmin, ymin] is the left top coordinate of the box if the " "[xmin, ymin] is the left top coordinate of the box if the "
"input is image feature map, and [xmax, ymax] is the right " "input is image feature map, and [xmax, ymax] is the right "
"bottom coordinate of the box."); "bottom coordinate of the box.");
AddAttr<bool>("box_normalized",
"(bool, default true) "
"whether treat the priorbox as a noramlized box")
.SetDefault(true);
AddOutput("Out", AddOutput("Out",
"(LoDTensor, the lod is same as input X) The output of " "(LoDTensor, the lod is same as input X) The output of "
"iou_similarity op, a tensor with shape [N, M] " "iou_similarity op, a tensor with shape [N, M] "
......
...@@ -18,16 +18,28 @@ limitations under the License. */ ...@@ -18,16 +18,28 @@ limitations under the License. */
template <typename T> template <typename T>
inline HOSTDEVICE T IOUSimilarity(T xmin1, T ymin1, T xmax1, T ymax1, T xmin2, inline HOSTDEVICE T IOUSimilarity(T xmin1, T ymin1, T xmax1, T ymax1, T xmin2,
T ymin2, T xmax2, T ymax2) { T ymin2, T xmax2, T ymax2, bool normalized) {
constexpr T zero = static_cast<T>(0); constexpr T zero = static_cast<T>(0);
T area1 = (ymax1 - ymin1) * (xmax1 - xmin1); T area1;
T area2 = (ymax2 - ymin2) * (xmax2 - xmin2); T area2;
if (!normalized) {
area1 = (ymax1 - ymin1 + 1) * (xmax1 - xmin1 + 1);
area2 = (ymax2 - ymin2 + 1) * (xmax2 - xmin2 + 1);
} else {
area1 = (ymax1 - ymin1) * (xmax1 - xmin1);
area2 = (ymax2 - ymin2) * (xmax2 - xmin2);
}
T inter_xmax = xmax1 > xmax2 ? xmax2 : xmax1; T inter_xmax = xmax1 > xmax2 ? xmax2 : xmax1;
T inter_ymax = ymax1 > ymax2 ? ymax2 : ymax1; T inter_ymax = ymax1 > ymax2 ? ymax2 : ymax1;
T inter_xmin = xmin1 > xmin2 ? xmin1 : xmin2; T inter_xmin = xmin1 > xmin2 ? xmin1 : xmin2;
T inter_ymin = ymin1 > ymin2 ? ymin1 : ymin2; T inter_ymin = ymin1 > ymin2 ? ymin1 : ymin2;
T inter_height = inter_ymax - inter_ymin; T inter_height = inter_ymax - inter_ymin;
T inter_width = inter_xmax - inter_xmin; T inter_width = inter_xmax - inter_xmin;
if (!normalized) {
inter_height = inter_height + 1;
inter_width = inter_width + 1;
}
inter_height = inter_height > zero ? inter_height : zero; inter_height = inter_height > zero ? inter_height : zero;
inter_width = inter_width > zero ? inter_width : zero; inter_width = inter_width > zero ? inter_width : zero;
T inter_area = inter_width * inter_height; T inter_area = inter_width * inter_height;
...@@ -38,8 +50,12 @@ inline HOSTDEVICE T IOUSimilarity(T xmin1, T ymin1, T xmax1, T ymax1, T xmin2, ...@@ -38,8 +50,12 @@ inline HOSTDEVICE T IOUSimilarity(T xmin1, T ymin1, T xmax1, T ymax1, T xmin2,
template <typename T> template <typename T>
struct IOUSimilarityFunctor { struct IOUSimilarityFunctor {
IOUSimilarityFunctor(const T* x, const T* y, T* z, int cols) IOUSimilarityFunctor(const T* x, const T* y, T* z, int cols, bool normalized)
: x_(x), y_(y), z_(z), cols_(static_cast<size_t>(cols)) {} : x_(x),
y_(y),
z_(z),
cols_(static_cast<size_t>(cols)),
normalized_(normalized) {}
inline HOSTDEVICE void operator()(size_t tid) const { inline HOSTDEVICE void operator()(size_t tid) const {
size_t row_id = tid / cols_; size_t row_id = tid / cols_;
...@@ -56,7 +72,7 @@ struct IOUSimilarityFunctor { ...@@ -56,7 +72,7 @@ struct IOUSimilarityFunctor {
T y_max2 = y_[col_id * 4 + 3]; T y_max2 = y_[col_id * 4 + 3];
T sim = IOUSimilarity(x_min1, y_min1, x_max1, y_max1, x_min2, y_min2, T sim = IOUSimilarity(x_min1, y_min1, x_max1, y_max1, x_min2, y_min2,
x_max2, y_max2); x_max2, y_max2, normalized_);
z_[row_id * cols_ + col_id] = sim; z_[row_id * cols_ + col_id] = sim;
} }
...@@ -64,6 +80,7 @@ struct IOUSimilarityFunctor { ...@@ -64,6 +80,7 @@ struct IOUSimilarityFunctor {
const T* y_; const T* y_;
T* z_; T* z_;
const size_t cols_; const size_t cols_;
bool normalized_;
}; };
namespace paddle { namespace paddle {
...@@ -75,12 +92,14 @@ class IOUSimilarityKernel : public framework::OpKernel<T> { ...@@ -75,12 +92,14 @@ class IOUSimilarityKernel : public framework::OpKernel<T> {
void Compute(const framework::ExecutionContext& ctx) const override { void Compute(const framework::ExecutionContext& ctx) const override {
const framework::LoDTensor* in_x = ctx.Input<framework::LoDTensor>("X"); const framework::LoDTensor* in_x = ctx.Input<framework::LoDTensor>("X");
const framework::Tensor* in_y = ctx.Input<framework::Tensor>("Y"); const framework::Tensor* in_y = ctx.Input<framework::Tensor>("Y");
bool normalized = ctx.Attr<bool>("box_normalized");
framework::LoDTensor* out = ctx.Output<framework::LoDTensor>("Out"); framework::LoDTensor* out = ctx.Output<framework::LoDTensor>("Out");
int x_n = in_x->dims()[0]; int x_n = in_x->dims()[0];
int y_n = in_y->dims()[0]; int y_n = in_y->dims()[0];
IOUSimilarityFunctor<T> functor(in_x->data<T>(), in_y->data<T>(), IOUSimilarityFunctor<T> functor(in_x->data<T>(), in_y->data<T>(),
out->mutable_data<T>(ctx.GetPlace()), y_n); out->mutable_data<T>(ctx.GetPlace()), y_n,
normalized);
platform::ForRange<DeviceContext> for_range( platform::ForRange<DeviceContext> for_range(
static_cast<const DeviceContext&>(ctx.device_context()), x_n * y_n); static_cast<const DeviceContext&>(ctx.device_context()), x_n * y_n);
......
...@@ -653,14 +653,15 @@ def detection_output(loc, ...@@ -653,14 +653,15 @@ def detection_output(loc,
@templatedoc() @templatedoc()
def iou_similarity(x, y, name=None): def iou_similarity(x, y, box_normalized=True, name=None):
""" """
${comment} ${comment}
Args: Args:
x (Variable): ${x_comment}.The data type is float32 or float64. x (Variable): ${x_comment}.The data type is float32 or float64.
y (Variable): ${y_comment}.The data type is float32 or float64. y (Variable): ${y_comment}.The data type is float32 or float64.
box_normalized(bool): Whether treat the priorbox as a noramlized box.
Set true by default.
Returns: Returns:
Variable: ${out_comment}.The data type is same with x. Variable: ${out_comment}.The data type is same with x.
...@@ -700,7 +701,7 @@ def iou_similarity(x, y, name=None): ...@@ -700,7 +701,7 @@ def iou_similarity(x, y, name=None):
type="iou_similarity", type="iou_similarity",
inputs={"X": x, inputs={"X": x,
"Y": y}, "Y": y},
attrs={}, attrs={"box_normalized": box_normalized},
outputs={"Out": out}) outputs={"Out": out})
return out return out
......
...@@ -31,27 +31,40 @@ class TestIOUSimilarityOp(OpTest): ...@@ -31,27 +31,40 @@ class TestIOUSimilarityOp(OpTest):
self.boxes1 = random.rand(2, 4).astype('float32') self.boxes1 = random.rand(2, 4).astype('float32')
self.boxes2 = random.rand(3, 4).astype('float32') self.boxes2 = random.rand(3, 4).astype('float32')
self.output = random.rand(2, 3).astype('float32') self.output = random.rand(2, 3).astype('float32')
self.box_normalized = False
# run python iou computation
self._compute_iou()
self.inputs = {'X': self.boxes1, 'Y': self.boxes2}
self.attrs = {"box_normalized": self.box_normalized}
self.outputs = {'Out': self.output}
def _compute_iou(self, ):
for row in range(self.boxes1.shape[0]): for row in range(self.boxes1.shape[0]):
for col in range(self.boxes2.shape[0]): for col in range(self.boxes2.shape[0]):
xmin1, ymin1, xmax1, ymax1 = self.boxes1[row] xmin1, ymin1, xmax1, ymax1 = self.boxes1[row]
xmin2, ymin2, xmax2, ymax2 = self.boxes2[col] xmin2, ymin2, xmax2, ymax2 = self.boxes2[col]
area1 = (ymax1 - ymin1) * (xmax1 - xmin1) if not self.box_normalized:
area2 = (ymax2 - ymin2) * (xmax2 - xmin2) area1 = (ymax1 - ymin1 + 1) * (xmax1 - xmin1 + 1)
area2 = (ymax2 - ymin2 + 1) * (xmax2 - xmin2 + 1)
else:
area1 = (ymax1 - ymin1) * (xmax1 - xmin1)
area2 = (ymax2 - ymin2) * (xmax2 - xmin2)
inter_xmax = min(xmax1, xmax2) inter_xmax = min(xmax1, xmax2)
inter_ymax = min(ymax1, ymax2) inter_ymax = min(ymax1, ymax2)
inter_xmin = max(xmin1, xmin2) inter_xmin = max(xmin1, xmin2)
inter_ymin = max(ymin1, ymin2) inter_ymin = max(ymin1, ymin2)
inter_height = inter_ymax - inter_ymin inter_height = inter_ymax - inter_ymin
inter_width = inter_xmax - inter_xmin inter_width = inter_xmax - inter_xmin
if not self.box_normalized:
inter_height += 1
inter_width += 1
inter_height = max(inter_height, 0) inter_height = max(inter_height, 0)
inter_width = max(inter_width, 0) inter_width = max(inter_width, 0)
inter_area = inter_width * inter_height inter_area = inter_width * inter_height
union_area = area1 + area2 - inter_area union_area = area1 + area2 - inter_area
sim_score = inter_area / union_area sim_score = inter_area / union_area
self.output[row, col] = sim_score self.output[row, col] = sim_score
self.inputs = {'X': self.boxes1, 'Y': self.boxes2}
self.outputs = {'Out': self.output}
class TestIOUSimilarityOpWithLoD(TestIOUSimilarityOp): class TestIOUSimilarityOpWithLoD(TestIOUSimilarityOp):
...@@ -62,8 +75,27 @@ class TestIOUSimilarityOpWithLoD(TestIOUSimilarityOp): ...@@ -62,8 +75,27 @@ class TestIOUSimilarityOpWithLoD(TestIOUSimilarityOp):
super(TestIOUSimilarityOpWithLoD, self).setUp() super(TestIOUSimilarityOpWithLoD, self).setUp()
self.boxes1_lod = [[1, 1]] self.boxes1_lod = [[1, 1]]
self.output_lod = [[1, 1]] self.output_lod = [[1, 1]]
self.box_normalized = False
# run python iou computation
self._compute_iou()
self.inputs = {'X': (self.boxes1, self.boxes1_lod), 'Y': self.boxes2}
self.attrs = {"box_normalized": self.box_normalized}
self.outputs = {'Out': (self.output, self.output_lod)}
class TestIOUSimilarityOpWithBoxNormalized(TestIOUSimilarityOp):
def test_check_output(self):
self.check_output(check_dygraph=False)
def setUp(self):
super(TestIOUSimilarityOpWithBoxNormalized, self).setUp()
self.boxes1_lod = [[1, 1]]
self.output_lod = [[1, 1]]
self.box_normalized = True
# run python iou computation
self._compute_iou()
self.inputs = {'X': (self.boxes1, self.boxes1_lod), 'Y': self.boxes2} self.inputs = {'X': (self.boxes1, self.boxes1_lod), 'Y': self.boxes2}
self.attrs = {"box_normalized": self.box_normalized}
self.outputs = {'Out': (self.output, self.output_lod)} self.outputs = {'Out': (self.output, self.output_lod)}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册