ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
iou.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "ml/contrib/IoU.h"
9 
10 #include <Logging.h>
11 
15 #include "pybind/docstring.h"
17 #include "pybind/pybind_utils.h"
18 
19 namespace cloudViewer {
20 namespace ml {
21 namespace contrib {
22 
23 py::array IouBevCPU(py::array boxes_a, py::array boxes_b) {
24  core::Tensor boxes_a_tensor =
25  core::PyArrayToTensor(boxes_a, true).Contiguous();
26  core::AssertTensorDtype(boxes_a_tensor, core::Float32);
27  core::AssertTensorShape(boxes_a_tensor, {utility::nullopt, 5});
28  int64_t num_a = boxes_a_tensor.GetLength();
29 
30  core::Tensor boxes_b_tensor =
31  core::PyArrayToTensor(boxes_b, true).Contiguous();
32  core::AssertTensorDtype(boxes_b_tensor, core::Float32);
33  core::AssertTensorShape(boxes_b_tensor, {utility::nullopt, 5});
34  int64_t num_b = boxes_b_tensor.GetLength();
35 
36  core::Tensor iou_tensor = core::Tensor(
37  {boxes_a_tensor.GetLength(), boxes_b_tensor.GetLength()},
38  core::Float32, core::Device("CPU:0"));
39 
40  IoUBevCPUKernel(boxes_a_tensor.GetDataPtr<float>(),
41  boxes_b_tensor.GetDataPtr<float>(),
42  iou_tensor.GetDataPtr<float>(), num_a, num_b);
43 
44  return core::TensorToPyArray(iou_tensor);
45 }
46 
47 py::array Iou3dCPU(py::array boxes_a, py::array boxes_b) {
48  core::Tensor boxes_a_tensor =
49  core::PyArrayToTensor(boxes_a, true).Contiguous();
50  core::AssertTensorDtype(boxes_a_tensor, core::Float32);
51  core::AssertTensorShape(boxes_a_tensor, {utility::nullopt, 7});
52  int64_t num_a = boxes_a_tensor.GetLength();
53 
54  core::Tensor boxes_b_tensor =
55  core::PyArrayToTensor(boxes_b, true).Contiguous();
56  core::AssertTensorDtype(boxes_b_tensor, core::Float32);
57  core::AssertTensorShape(boxes_b_tensor, {utility::nullopt, 7});
58  int64_t num_b = boxes_b_tensor.GetLength();
59 
60  core::Tensor iou_tensor = core::Tensor(
61  {boxes_a_tensor.GetLength(), boxes_b_tensor.GetLength()},
62  core::Float32, core::Device("CPU:0"));
63 
64  IoU3dCPUKernel(boxes_a_tensor.GetDataPtr<float>(),
65  boxes_b_tensor.GetDataPtr<float>(),
66  iou_tensor.GetDataPtr<float>(), num_a, num_b);
67 
68  return core::TensorToPyArray(iou_tensor);
69 }
70 
71 #ifdef BUILD_CUDA_MODULE
72 py::array IouBevCUDA(py::array boxes_a, py::array boxes_b) {
73  core::Device cuda_device("CUDA:0");
74  core::Tensor boxes_a_tensor =
75  core::PyArrayToTensor(boxes_a, true).Contiguous().To(cuda_device);
76  core::AssertTensorDtype(boxes_a_tensor, core::Float32);
77  core::AssertTensorShape(boxes_a_tensor, {utility::nullopt, 5});
78  int64_t num_a = boxes_a_tensor.GetLength();
79 
80  core::Tensor boxes_b_tensor =
81  core::PyArrayToTensor(boxes_b, true).Contiguous().To(cuda_device);
82  core::AssertTensorDtype(boxes_b_tensor, core::Float32);
83  core::AssertTensorShape(boxes_b_tensor, {utility::nullopt, 5});
84  int64_t num_b = boxes_b_tensor.GetLength();
85 
86  core::Tensor iou_tensor = core::Tensor(
87  {boxes_a_tensor.GetLength(), boxes_b_tensor.GetLength()},
88  core::Float32, cuda_device);
89 
90  IoUBevCUDAKernel(boxes_a_tensor.GetDataPtr<float>(),
91  boxes_b_tensor.GetDataPtr<float>(),
92  iou_tensor.GetDataPtr<float>(), num_a, num_b);
93  return core::TensorToPyArray(iou_tensor.To(core::Device("CPU:0")));
94 }
95 
96 py::array Iou3dCUDA(py::array boxes_a, py::array boxes_b) {
97  core::Device cuda_device("CUDA:0");
98  core::Tensor boxes_a_tensor =
99  core::PyArrayToTensor(boxes_a, true).Contiguous().To(cuda_device);
100  core::AssertTensorDtype(boxes_a_tensor, core::Float32);
101  core::AssertTensorShape(boxes_a_tensor, {utility::nullopt, 7});
102  int64_t num_a = boxes_a_tensor.GetLength();
103 
104  core::Tensor boxes_b_tensor =
105  core::PyArrayToTensor(boxes_b, true).Contiguous().To(cuda_device);
106  core::AssertTensorDtype(boxes_b_tensor, core::Float32);
107  core::AssertTensorShape(boxes_b_tensor, {utility::nullopt, 7});
108  int64_t num_b = boxes_b_tensor.GetLength();
109 
110  core::Tensor iou_tensor = core::Tensor(
111  {boxes_a_tensor.GetLength(), boxes_b_tensor.GetLength()},
112  core::Float32, cuda_device);
113 
114  IoU3dCUDAKernel(boxes_a_tensor.GetDataPtr<float>(),
115  boxes_b_tensor.GetDataPtr<float>(),
116  iou_tensor.GetDataPtr<float>(), num_a, num_b);
117  return core::TensorToPyArray(iou_tensor.To(core::Device("CPU:0")));
118 }
119 #endif
120 
121 void pybind_contrib_iou(py::module& m_contrib) {
122  m_contrib.def("iou_bev_cpu", &IouBevCPU, "boxes_a"_a, "boxes_b"_a);
123  m_contrib.def("iou_3d_cpu", &Iou3dCPU, "boxes_a"_a, "boxes_b"_a);
124 
125 #ifdef BUILD_CUDA_MODULE
126  // These CUDA functions still uses numpy arrays as input and output, i.e.
127  // data will be copy to and from the CUDA device.
128  m_contrib.def("iou_bev_cuda", &IouBevCUDA, "boxes_a"_a, "boxes_b"_a);
129  m_contrib.def("iou_3d_cuda", &Iou3dCUDA, "boxes_a"_a, "boxes_b"_a);
130 #endif
131 }
132 
133 } // namespace contrib
134 } // namespace ml
135 } // namespace cloudViewer
#define AssertTensorDtype(tensor,...)
Definition: TensorCheck.h:21
#define AssertTensorShape(tensor,...)
Definition: TensorCheck.h:61
Tensor Contiguous() const
Definition: Tensor.cpp:772
int64_t GetLength() const
Definition: Tensor.h:1125
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:739
py::array TensorToPyArray(const Tensor &tensor)
Convert Tensor class to py::array (Numpy array).
Tensor PyArrayToTensor(py::array array, bool inplace)
const Dtype Float32
Definition: Dtype.cpp:42
py::array Iou3dCPU(py::array boxes_a, py::array boxes_b)
Definition: iou.cpp:47
py::array IouBevCPU(py::array boxes_a, py::array boxes_b)
Definition: iou.cpp:23
void IoUBevCPUKernel(const float *boxes_a, const float *boxes_b, float *iou, int num_a, int num_b)
Definition: IoU.cpp:18
void pybind_contrib_iou(py::module &m_contrib)
Definition: iou.cpp:121
void IoU3dCPUKernel(const float *boxes_a, const float *boxes_b, float *iou, int num_a, int num_b)
Definition: IoU.cpp:33
constexpr nullopt_t nullopt
Definition: Optional.h:136
Generic file read and write utility for python interface.