Skip to content

Commit 0e14ce2

Browse files
enemy1205zhouzaida
authored andcommitted
[Feature] Add C++ implementation for bbox_overlaps (open-mmlab#2477)
* add ops bbox_overlaps * format code * Return the pytorch version * Intermediate modification * Solve problems in parameter passing * revise bug * "add test case"
1 parent bc10b5f commit 0e14ce2

File tree

3 files changed

+82
-17
lines changed

3 files changed

+82
-17
lines changed

mmcv/ops/bbox.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -106,25 +106,17 @@ def bbox_overlaps(bboxes1: torch.Tensor,
106106

107107
rows = bboxes1.size(0)
108108
cols = bboxes2.size(0)
109+
109110
if aligned:
110111
assert rows == cols
112+
ious = bboxes1.new_zeros(rows)
113+
else:
114+
ious = bboxes1.new_zeros((rows, cols))
111115

112116
if rows * cols == 0:
113-
return bboxes1.new(rows, 1) if aligned else bboxes1.new(rows, cols)
114-
115-
if bboxes1.device.type == 'cpu':
116-
return _bbox_overlaps_cpu(
117-
bboxes1, bboxes2, mode=mode, aligned=aligned, offset=offset)
118-
else:
119-
if aligned:
120-
ious = bboxes1.new_zeros(rows)
121-
else:
122-
ious = bboxes1.new_zeros((rows, cols))
123-
ext_module.bbox_overlaps(
124-
bboxes1,
125-
bboxes2,
126-
ious,
127-
mode=mode_flag,
128-
aligned=aligned,
129-
offset=offset)
130117
return ious
118+
119+
ext_module.bbox_overlaps(
120+
bboxes1, bboxes2, ious, mode=mode_flag, aligned=aligned, offset=offset)
121+
122+
return ious
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright(c) OpenMMLab.All rights reserved.
2+
#include "pytorch_cpp_helper.hpp"
3+
#include "pytorch_device_registry.hpp"
4+
5+
using torch::indexing::None;
6+
using torch::indexing::Slice;
7+
8+
void bbox_overlaps_cpu_kernel(const Tensor boxes1, const Tensor boxes2,
9+
Tensor ious, const int mode_flag,
10+
const bool aligned, const int offset) {
11+
Tensor temp_ious;
12+
if (aligned) {
13+
Tensor lt = torch::max(boxes1.index({Slice(None), Slice({None, 2})}),
14+
boxes2.index({Slice(None), Slice({None, 2})}));
15+
Tensor rb = torch::min(boxes1.index({Slice(None), Slice(2)}),
16+
boxes2.index({Slice(None), Slice(2)}));
17+
Tensor wh = (rb - lt + offset).clamp(0.f, INT_MAX * 1.f);
18+
Tensor overlap = wh.index({Slice(None), 0}) * wh.index({Slice(None), 1});
19+
Tensor area1 = (boxes1.index({Slice(None), 2}) -
20+
boxes1.index({Slice(None), 0}) + offset) *
21+
(boxes1.index({Slice(None), 3}) -
22+
boxes1.index({Slice(None), 1}) + offset);
23+
if (mode_flag == 0) {
24+
Tensor area2 = (boxes2.index({Slice(None), 2}) -
25+
boxes2.index({Slice(None), 0}) + offset) *
26+
(boxes2.index({Slice(None), 3}) -
27+
boxes2.index({Slice(None), 1}) + offset);
28+
temp_ious = overlap / (area1 + area2 - overlap);
29+
} else {
30+
temp_ious = overlap / area1;
31+
}
32+
} else {
33+
Tensor lt = torch::max(boxes1.index({Slice(None), None, Slice({None, 2})}),
34+
boxes2.index({Slice(None), Slice({None, 2})}));
35+
Tensor rb = torch::min(boxes1.index({Slice(None), None, Slice(2)}),
36+
boxes2.index({Slice(None), Slice(2)}));
37+
Tensor wh = (rb - lt + offset).clamp(0.f, INT_MAX * 1.f);
38+
Tensor overlap = wh.index({"...", 0}) * wh.index({"...", 1});
39+
Tensor area1 = (boxes1.index({Slice(None), 2}) -
40+
boxes1.index({Slice(None), 0}) + offset) *
41+
(boxes1.index({Slice(None), 3}) -
42+
boxes1.index({Slice(None), 1}) + offset);
43+
if (mode_flag == 0) {
44+
Tensor area2 = (boxes2.index({Slice(None), 2}) -
45+
boxes2.index({Slice(None), 0}) + offset) *
46+
(boxes2.index({Slice(None), 3}) -
47+
boxes2.index({Slice(None), 1}) + offset);
48+
temp_ious =
49+
overlap / (area1.index({Slice(None), None}) + area2 - overlap);
50+
} else {
51+
temp_ious = overlap / area1.index({Slice(None), None});
52+
}
53+
}
54+
ious.copy_(temp_ious);
55+
}
56+
57+
void bbox_overlaps_cpu(const Tensor boxes1, const Tensor boxes2, Tensor ious,
58+
const int mode, const bool aligned, const int offset) {
59+
bbox_overlaps_cpu_kernel(boxes1, boxes2, ious, mode, aligned, offset);
60+
}
61+
62+
void bbox_overlaps_impl(const Tensor boxes1, const Tensor boxes2, Tensor ious,
63+
const int mode, const bool aligned, const int offset);
64+
65+
REGISTER_DEVICE_IMPL(bbox_overlaps_impl, CPU, bbox_overlaps_cpu);

tests/test_ops/test_bbox.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ def _test_bbox_overlaps(self, device='cpu', dtype=torch.float):
3535
out = bbox_overlaps(b1, b2, offset=1)
3636
assert np.allclose(out.cpu().numpy(), should_output, 1e-2)
3737

38+
b1 = torch.tensor([[10.0 + i, 10.0 + i, 30.0 + i, 30.0 + i]
39+
for i in range(1000)]).to(device).type(dtype)
40+
b2 = torch.tensor([[20.0 + i, 20.0 + i, 40.0 + i, 40.0 + i]
41+
for i in range(1000)]).to(device).type(dtype)
42+
should_output = np.array([1 / 7] * 1000)
43+
out = bbox_overlaps(b1, b2, aligned=True)
44+
assert np.allclose(out.cpu().numpy(), should_output, 1e-2)
45+
3846
@pytest.mark.parametrize('device', [
3947
'cpu',
4048
pytest.param(

0 commit comments

Comments
 (0)