Open3D (C++ API)  0.17.0
IoUImpl.h
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// - Open3D: www.open3d.org -
3// ----------------------------------------------------------------------------
4// Copyright (c) 2018-2023 www.open3d.org
5// SPDX-License-Identifier: MIT
6// ----------------------------------------------------------------------------
7
8#pragma once
9
10#include <math.h>
11
12#include "open3d/Macro.h"
14
15namespace open3d {
16namespace ml {
17namespace contrib {
18
19constexpr int NMS_BLOCK_SIZE = sizeof(uint64_t) * 8;
20constexpr float EPS = static_cast<float>(1e-8);
21
22struct Point {
24 OPEN3D_HOST_DEVICE Point(float x, float y) : x_(x), y_(y) {}
25 OPEN3D_HOST_DEVICE void set(float x, float y) {
26 x_ = x;
27 y_ = y;
28 }
30 return Point(x_ + b.x_, y_ + b.y_);
31 }
33 return Point(x_ - b.x_, y_ - b.y_);
34 }
35 float x_ = 0.0f;
36 float y_ = 0.0f;
37};
38
39OPEN3D_HOST_DEVICE inline float Cross(const Point &a, const Point &b) {
40 return a.x_ * b.y_ - a.y_ * b.x_;
41}
42
43OPEN3D_HOST_DEVICE inline float Cross(const Point &p1,
44 const Point &p2,
45 const Point &p0) {
46 return (p1.x_ - p0.x_) * (p2.y_ - p0.y_) -
47 (p2.x_ - p0.x_) * (p1.y_ - p0.y_);
48}
49
51 const Point &p2,
52 const Point &q1,
53 const Point &q2) {
54 int ret = fmin(p1.x_, p2.x_) <= fmax(q1.x_, q2.x_) &&
55 fmin(q1.x_, q2.x_) <= fmax(p1.x_, p2.x_) &&
56 fmin(p1.y_, p2.y_) <= fmax(q1.y_, q2.y_) &&
57 fmin(q1.y_, q2.y_) <= fmax(p1.y_, p2.y_);
58 return ret;
59}
60
61OPEN3D_HOST_DEVICE inline int CheckInBox2D(const float *box, const Point &p) {
62 // box (5): [x1, y1, x2, y2, angle].
63 const float MARGIN = static_cast<float>(1e-5);
64
65 float center_x = (box[0] + box[2]) / 2;
66 float center_y = (box[1] + box[3]) / 2;
67 // Rotate the point in the opposite direction of box.
68 float angle_cos = cos(-box[4]), angle_sin = sin(-box[4]);
69 float rot_x = (p.x_ - center_x) * angle_cos +
70 (p.y_ - center_y) * angle_sin + center_x;
71 float rot_y = -(p.x_ - center_x) * angle_sin +
72 (p.y_ - center_y) * angle_cos + center_y;
73 return (rot_x > box[0] - MARGIN && rot_x < box[2] + MARGIN &&
74 rot_y > box[1] - MARGIN && rot_y < box[3] + MARGIN);
75}
76
78 const Point &p0,
79 const Point &q1,
80 const Point &q0,
81 Point &ans) {
82 // Fast exclusion.
83 if (CheckRectCross(p0, p1, q0, q1) == 0) return 0;
84
85 // Check Cross standing
86 float s1 = Cross(q0, p1, p0);
87 float s2 = Cross(p1, q1, p0);
88 float s3 = Cross(p0, q1, q0);
89 float s4 = Cross(q1, p1, q0);
90
91 if (!(s1 * s2 > 0 && s3 * s4 > 0)) return 0;
92
93 // Calculate Intersection of two lines.
94 float s5 = Cross(q1, p1, p0);
95 if (fabs(s5 - s1) > EPS) {
96 ans.x_ = (s5 * q0.x_ - s1 * q1.x_) / (s5 - s1);
97 ans.y_ = (s5 * q0.y_ - s1 * q1.y_) / (s5 - s1);
98
99 } else {
100 float a0 = p0.y_ - p1.y_, b0 = p1.x_ - p0.x_,
101 c0 = p0.x_ * p1.y_ - p1.x_ * p0.y_;
102 float a1 = q0.y_ - q1.y_, b1 = q1.x_ - q0.x_,
103 c1 = q0.x_ * q1.y_ - q1.x_ * q0.y_;
104 float D = a0 * b1 - a1 * b0;
105
106 ans.x_ = (b0 * c1 - b1 * c0) / D;
107 ans.y_ = (a1 * c0 - a0 * c1) / D;
108 }
109
110 return 1;
111}
112
114 const float angle_cos,
115 const float angle_sin,
116 Point &p) {
117 float new_x = (p.x_ - center.x_) * angle_cos +
118 (p.y_ - center.y_) * angle_sin + center.x_;
119 float new_y = -(p.x_ - center.x_) * angle_sin +
120 (p.y_ - center.y_) * angle_cos + center.y_;
121 p.set(new_x, new_y);
122}
123
125 const Point &b,
126 const Point &center) {
127 return atan2(a.y_ - center.y_, a.x_ - center.x_) >
128 atan2(b.y_ - center.y_, b.x_ - center.x_);
129}
130
131OPEN3D_HOST_DEVICE inline float BoxOverlap(const float *box_a,
132 const float *box_b) {
133 // box_a (5) [x1, y1, x2, y2, angle].
134 // box_b (5) [x1, y1, x2, y2, angle].
135 float a_x1 = box_a[0], a_y1 = box_a[1], a_x2 = box_a[2], a_y2 = box_a[3],
136 a_angle = box_a[4];
137 float b_x1 = box_b[0], b_y1 = box_b[1], b_x2 = box_b[2], b_y2 = box_b[3],
138 b_angle = box_b[4];
139
140 Point center_a((a_x1 + a_x2) / 2, (a_y1 + a_y2) / 2);
141 Point center_b((b_x1 + b_x2) / 2, (b_y1 + b_y2) / 2);
142
143 Point box_a_corners[5];
144 box_a_corners[0].set(a_x1, a_y1);
145 box_a_corners[1].set(a_x2, a_y1);
146 box_a_corners[2].set(a_x2, a_y2);
147 box_a_corners[3].set(a_x1, a_y2);
148
149 Point box_b_corners[5];
150 box_b_corners[0].set(b_x1, b_y1);
151 box_b_corners[1].set(b_x2, b_y1);
152 box_b_corners[2].set(b_x2, b_y2);
153 box_b_corners[3].set(b_x1, b_y2);
154
155 // Get oriented corners.
156 float a_angle_cos = cos(a_angle), a_angle_sin = sin(a_angle);
157 float b_angle_cos = cos(b_angle), b_angle_sin = sin(b_angle);
158
159 for (int k = 0; k < 4; k++) {
160 RotateAroundCenter(center_a, a_angle_cos, a_angle_sin,
161 box_a_corners[k]);
162 RotateAroundCenter(center_b, b_angle_cos, b_angle_sin,
163 box_b_corners[k]);
164 }
165
166 box_a_corners[4] = box_a_corners[0];
167 box_b_corners[4] = box_b_corners[0];
168
169 // Get Intersection of lines.
170 Point cross_points[16];
171 Point poly_center;
172 int cnt = 0, flag = 0;
173
174 poly_center.set(0, 0);
175 for (int i = 0; i < 4; i++) {
176 for (int j = 0; j < 4; j++) {
177 flag = Intersection(box_a_corners[i + 1], box_a_corners[i],
178 box_b_corners[j + 1], box_b_corners[j],
179 cross_points[cnt]);
180 if (flag) {
181 poly_center = poly_center + cross_points[cnt];
182 cnt++;
183 }
184 }
185 }
186
187 // Check corners.
188 for (int k = 0; k < 4; k++) {
189 if (CheckInBox2D(box_a, box_b_corners[k])) {
190 poly_center = poly_center + box_b_corners[k];
191 cross_points[cnt] = box_b_corners[k];
192 cnt++;
193 }
194 if (CheckInBox2D(box_b, box_a_corners[k])) {
195 poly_center = poly_center + box_a_corners[k];
196 cross_points[cnt] = box_a_corners[k];
197 cnt++;
198 }
199 }
200
201 OPEN3D_ASSERT(cnt != 0 && "Invalid value: cnt==0.");
202
203 poly_center.x_ /= cnt;
204 poly_center.y_ /= cnt;
205
206 // Sort the points of polygon.
207 Point temp;
208 for (int j = 0; j < cnt - 1; j++) {
209 for (int i = 0; i < cnt - j - 1; i++) {
210 if (PointCmp(cross_points[i], cross_points[i + 1], poly_center)) {
211 temp = cross_points[i];
212 cross_points[i] = cross_points[i + 1];
213 cross_points[i + 1] = temp;
214 }
215 }
216 }
217
218 // Get the overlap areas.
219 float area = 0;
220 for (int k = 0; k < cnt - 1; k++) {
221 area += Cross(cross_points[k] - cross_points[0],
222 cross_points[k + 1] - cross_points[0]);
223 }
224
225 return static_cast<float>(fabs(area)) / 2.0f;
226}
227
230 const float *box_a,
231 const float *box_b,
232 bool intersection_only = false) {
233 // params: box_a (5) [x1, y1, x2, y2, angle].
234 // params: box_b (5) [x1, y1, x2, y2, angle].
235 float sa = (box_a[2] - box_a[0]) * (box_a[3] - box_a[1]);
236 float sb = (box_b[2] - box_b[0]) * (box_b[3] - box_b[1]);
237 float s_overlap = BoxOverlap(box_a, box_b);
238 if (intersection_only) {
239 return s_overlap;
240 } else {
241 return s_overlap / fmaxf(sa + sb - s_overlap, EPS);
242 }
243}
244
247 const float *box_a,
248 const float *box_b,
249 bool intersection_only = false) {
250 float box_a_new[5];
251 box_a_new[0] = box_a[0] - box_a[2] / 2;
252 box_a_new[1] = box_a[1] - box_a[3] / 2;
253 box_a_new[2] = box_a[0] + box_a[2] / 2;
254 box_a_new[3] = box_a[1] + box_a[3] / 2;
255 box_a_new[4] = box_a[4];
256
257 float box_b_new[5];
258 box_b_new[0] = box_b[0] - box_b[2] / 2;
259 box_b_new[1] = box_b[1] - box_b[3] / 2;
260 box_b_new[2] = box_b[0] + box_b[2] / 2;
261 box_b_new[3] = box_b[1] + box_b[3] / 2;
262 box_b_new[4] = box_b[4];
263 return IoUBev2DWithMinAndMax(box_a_new, box_b_new, intersection_only);
264}
265
267OPEN3D_HOST_DEVICE inline float IoU3DWithCenterAndSize(const float *box_a,
268 const float *box_b) {
269 float box_a_2d[5];
270 box_a_2d[0] = box_a[0];
271 box_a_2d[1] = box_a[2];
272 box_a_2d[2] = box_a[3];
273 box_a_2d[3] = box_a[5];
274 box_a_2d[4] = box_a[6];
275
276 float box_b_2d[5];
277 box_b_2d[0] = box_b[0];
278 box_b_2d[1] = box_b[2];
279 box_b_2d[2] = box_b[3];
280 box_b_2d[3] = box_b[5];
281 box_b_2d[4] = box_b[6];
282 float intersection_2d = IoUBev2DWithCenterAndSize(box_a_2d, box_b_2d, true);
283
284 float y_a_min = box_a[1] - box_a[4];
285 float y_a_max = box_a[1];
286 float y_b_min = box_b[1] - box_b[4];
287 float y_b_max = box_b[1];
288 float iw = (y_a_max < y_b_max ? y_a_max : y_b_max) -
289 (y_a_min > y_b_min ? y_a_min : y_b_min);
290 float iou_3d = 0;
291 if (iw > 0) {
292 float intersection_3d = intersection_2d * iw;
293 float volume_a = box_a[3] * box_a[4] * box_a[5];
294 float volume_b = box_b[3] * box_b[4] * box_b[5];
295 float union_3d = volume_a + volume_b - intersection_3d;
296 iou_3d = intersection_3d / union_3d;
297 }
298 return iou_3d;
299}
300
301} // namespace contrib
302} // namespace ml
303} // namespace open3d
Common CUDA utilities.
#define OPEN3D_HOST_DEVICE
Definition: CUDAUtils.h:44
#define OPEN3D_ASSERT(...)
Definition: Macro.h:48
double area
Definition: PointCloudPlanarPatchDetection.cpp:508
const char const char value recording_handle imu_sample recording_handle uint8_t size_t data_size k4a_record_configuration_t config target_format k4a_capture_t capture_handle k4a_imu_sample_t imu_sample uint64_t
Definition: K4aPlugin.cpp:343
constexpr int NMS_BLOCK_SIZE
Definition: IoUImpl.h:19
OPEN3D_HOST_DEVICE float BoxOverlap(const float *box_a, const float *box_b)
Definition: IoUImpl.h:131
OPEN3D_HOST_DEVICE int Intersection(const Point &p1, const Point &p0, const Point &q1, const Point &q0, Point &ans)
Definition: IoUImpl.h:77
constexpr float EPS
Definition: IoUImpl.h:20
OPEN3D_HOST_DEVICE void RotateAroundCenter(const Point &center, const float angle_cos, const float angle_sin, Point &p)
Definition: IoUImpl.h:113
OPEN3D_HOST_DEVICE int CheckRectCross(const Point &p1, const Point &p2, const Point &q1, const Point &q2)
Definition: IoUImpl.h:50
OPEN3D_HOST_DEVICE int PointCmp(const Point &a, const Point &b, const Point &center)
Definition: IoUImpl.h:124
OPEN3D_HOST_DEVICE float Cross(const Point &a, const Point &b)
Definition: IoUImpl.h:39
OPEN3D_HOST_DEVICE float IoUBev2DWithCenterAndSize(const float *box_a, const float *box_b, bool intersection_only=false)
(x_center, z_center, x_size, z_size, y_rotate)
Definition: IoUImpl.h:246
OPEN3D_HOST_DEVICE int CheckInBox2D(const float *box, const Point &p)
Definition: IoUImpl.h:61
OPEN3D_HOST_DEVICE float IoUBev2DWithMinAndMax(const float *box_a, const float *box_b, bool intersection_only=false)
(x_min, z_min, x_max, z_max, y_rotate)
Definition: IoUImpl.h:229
OPEN3D_HOST_DEVICE float IoU3DWithCenterAndSize(const float *box_a, const float *box_b)
(x_center, y_max, z_center, x_size, y_size, z_size, y_rotate)
Definition: IoUImpl.h:267
Definition: PinholeCameraIntrinsic.cpp:16
Definition: IoUImpl.h:22
OPEN3D_HOST_DEVICE Point operator+(const Point &b) const
Definition: IoUImpl.h:29
OPEN3D_HOST_DEVICE Point operator-(const Point &b) const
Definition: IoUImpl.h:32
float x_
Definition: IoUImpl.h:35
float y_
Definition: IoUImpl.h:36
OPEN3D_HOST_DEVICE Point()
Definition: IoUImpl.h:23
OPEN3D_HOST_DEVICE void set(float x, float y)
Definition: IoUImpl.h:25
OPEN3D_HOST_DEVICE Point(float x, float y)
Definition: IoUImpl.h:24