郭卫东 发表于 2024-11-4 00:35:25

3d点在立方体内(numpy,不使用for循环)



说明

判定一堆3d点哪些在一堆3d框内,与主流3d目的检测算法一样,立方体只有水平方向上的旋转,没有高度方向上的旋转,就是拍到BEV图像上是一个旋转的矩形

代码优势

基于numpy完成,直接判定一堆点和一堆3d框的包含关系,不使用for循环

算法思绪

团体思绪说白了实在也挺简单的,就是分两步,首先判定点是否在旋转矩形内(本人直接使用凸多边形),然后判定是否在高度范围内
针对numpy焦点的代码思绪是:在加和过程中True为1、False为0,因此同时满足三个条件加和应该为3。以此举行重叠的逻辑判定,末了判定一次取出满足全部条件的索引

工程细节

界说随机点

 lidar_points = np.random.randint(low=0, high=10, size=(10, 3), dtype='int')
界说旋转矩形

界说一个旋转矩形,输入的box为中心点坐标x、y,矩形宽高,和围绕中心点旋转角度
 def get_corners(box):# 这里本人项目yaw [-pi/4, 3*pi/4),需要映射到[0, pi)
   # box = box.detach().cpu().numpy()
   x = box
   y = box
   w = box
   l = box
   yaw = box
   if yaw < 0:# 用来映射
       yaw = yaw + np.pi
 ​
   bev_corners = np.zeros((4, 2), dtype=np.float32)
   cos_yaw = np.cos(yaw)
   sin_yaw = np.sin(yaw)
 ​
   bev_corners = (w / 2) * cos_yaw - (l / 2) * sin_yaw + x
   bev_corners = (w / 2) * sin_yaw + (l / 2) * cos_yaw + y
   bev_corners = (l / 2) * sin_yaw + (w / 2) * cos_yaw + x
   bev_corners = (w / 2) * sin_yaw - (l / 2) * cos_yaw + y
   bev_corners = (-w / 2) * cos_yaw - (-l / 2) * sin_yaw + x
   bev_corners = (-w / 2) * sin_yaw + (-l / 2) * cos_yaw + y
   bev_corners = (-l / 2) * sin_yaw + (-w / 2) * cos_yaw + x
   bev_corners = (-w / 2) * sin_yaw - (-l / 2) * cos_yaw + y
   return bev_corners
 ​
界说空间3d立方体

首先界说旋转矩形,然后为旋转矩形在z轴上赋最大值和最小值,得到的结果就是空间3d的立方体,但是没有高度上的旋转
 def get_3dbox(boxes):
   boxes_3d = []
   for box in boxes:
       bev_corners = get_corners(box[:5])
       down = np.hstack(
            * np.ones((bev_corners.shape, 1))])
       up = np.hstack(
            * np.ones((bev_corners.shape, 1))])
       box_3d = np.vstack()
       boxes_3d.append(box_3d)
   return np.array(boxes_3d)
 boxes_3d = get_3dbox([, ])
点在旋转矩形内

就是判定点在凸多边形内,个人使用的是同侧法,或者叫叉乘法。末了就是判定点和四边形的四个顶点的叉乘是否在同一侧。
 def points_in_rotatingrectangles(lidar_points, boxes):
   boxes_shape = boxes.shape
   Pxy = lidar_points[:, :2].reshape(1, lidar_points.shape, 2)
     
   Axy = boxes[:, 0, :2].reshape(boxes_shape, 1, 2)
   Bxy = boxes[:, 1, :2].reshape(boxes_shape, 1, 2)
   Cxy = boxes[:, 2, :2].reshape(boxes_shape, 1, 2)
   Dxy = boxes[:, 3, :2].reshape(boxes_shape, 1, 2)
 ​
   cross1 = np.cross(Bxy - Axy, Pxy - Axy)
   cross2 = np.cross(Cxy - Bxy, Pxy - Bxy)
   cross3 = np.cross(Dxy - Cxy, Pxy - Cxy)
   cross4 = np.cross(Axy - Dxy, Pxy - Dxy)
   points_concat1 = np.concatenate([(cross1 > 0)[:, :, np.newaxis], (cross2 > 0)[:, :, np.newaxis],
                                   (cross3 > 0)[:, :, np.newaxis], (cross4 > 0)[:, :, np.newaxis]], axis=2)
   points_concat2 = np.concatenate([(cross1 < 0)[:, :, np.newaxis], (cross2 < 0)[:, :, np.newaxis],
                                   (cross3 < 0)[:, :, np.newaxis], (cross4 < 0)[:, :, np.newaxis]], axis=2)
 ​
   points_usability1 = points_concat1.sum(axis=2)
   points_usability2 = points_concat2.sum(axis=2)
   ww = np.concatenate([(points_usability1 == 4)[:, :, np.newaxis], (points_usability1 == 0)[:, :, np.newaxis],
                          (points_usability2 == 4)[:, :, np.newaxis], (points_usability2 == 0)[:, :, np.newaxis]], axis=2)
   mm = ww.sum(axis=2)
   return (mm > 1)[:, :, np.newaxis]
点在3d立方体内

首先不管高度轴判定水平点是否在旋转矩形内,然后判定点的高度是否在立方体内。
 def points_in_cubes(lidar_points, boxes):
   boxes_shape = boxes.shape
   Az = boxes[:, 0, 2]
   Ez = boxes[:, 4, 2]
   Pz = lidar_points[:, 2].reshape(1, -1)
   zmin = np.min(, axis=0).reshape(boxes_shape, -1)
   zmax = np.max(, axis=0).reshape(boxes_shape, -1)
   p_min_z = (Pz > zmin)[:, :, np.newaxis]
   p_max_z = (Pz < zmax)[:, :, np.newaxis]
   p_in_r = points_in_rotatingrectangles(lidar_points, boxes)
   ii = np.concatenate(, axis=2).sum(axis=2)
   usability_sum = np.sum(ii == 3, axis=0)
   return usability_sum > 0
完备代码

 #!/usr/bin/env python # -*- coding: utf-8 -*- ''' @File  :   main.py @Time  :   2024/10/24 20:02:07 @Author:   xudh  @Version :   1.0 @Desc  :   一群空间3d点在一群3d立方体内 code is far away from bug with the animal protecting   ┏┓   ┏┓    ┏┛┻━━━┛┻┓    ┃       ┃    ┃   ━   ┃    ┃ >   <┃    ┃       ┃    ┃  . ⌒ .. ┃    ┃       ┃    ┗━┓   ┏━┛      ┃   ┃ Codes are far away from bugs with the animal protecting      ┃   ┃ 神兽保佑,代码无bug      ┃   ┃      ┃   ┃      ┃   ┃      ┃   ┃      ┃   ┗━━━┓      ┃       ┣┓      ┃       ┏┛      ┗┓┓┏━┳┓┏┛     ┃┫┫ ┃┫┫     ┗┻┛ ┗┻┛ ''' ​ ​ import numpy as np ​ ​ def points_in_rotatingrectangles(lidar_points, boxes):
   boxes_shape = boxes.shape
   Pxy = lidar_points[:, :2].reshape(1, lidar_points.shape, 2)
     
   Axy = boxes[:, 0, :2].reshape(boxes_shape, 1, 2)
   Bxy = boxes[:, 1, :2].reshape(boxes_shape, 1, 2)
   Cxy = boxes[:, 2, :2].reshape(boxes_shape, 1, 2)
   Dxy = boxes[:, 3, :2].reshape(boxes_shape, 1, 2)
 ​
   cross1 = np.cross(Bxy - Axy, Pxy - Axy)
   cross2 = np.cross(Cxy - Bxy, Pxy - Bxy)
   cross3 = np.cross(Dxy - Cxy, Pxy - Cxy)
   cross4 = np.cross(Axy - Dxy, Pxy - Dxy)
   points_concat1 = np.concatenate([(cross1 > 0)[:, :, np.newaxis], (cross2 > 0)[:, :, np.newaxis],
                                   (cross3 > 0)[:, :, np.newaxis], (cross4 > 0)[:, :, np.newaxis]], axis=2)
   points_concat2 = np.concatenate([(cross1 < 0)[:, :, np.newaxis], (cross2 < 0)[:, :, np.newaxis],
                                   (cross3 < 0)[:, :, np.newaxis], (cross4 < 0)[:, :, np.newaxis]], axis=2)
 ​
   points_usability1 = points_concat1.sum(axis=2)
   points_usability2 = points_concat2.sum(axis=2)
   ww = np.concatenate([(points_usability1 == 4)[:, :, np.newaxis], (points_usability1 == 0)[:, :, np.newaxis],
                          (points_usability2 == 4)[:, :, np.newaxis], (points_usability2 == 0)[:, :, np.newaxis]], axis=2)
   mm = ww.sum(axis=2)
   return (mm > 1)[:, :, np.newaxis]      ​ def points_in_cubes(lidar_points, boxes):
   boxes_shape = boxes.shape
   Az = boxes[:, 0, 2]
   Ez = boxes[:, 4, 2]
   Pz = lidar_points[:, 2].reshape(1, -1)
   zmin = np.min(, axis=0).reshape(boxes_shape, -1)
   zmax = np.max(, axis=0).reshape(boxes_shape, -1)
   p_min_z = (Pz > zmin)[:, :, np.newaxis]
   p_max_z = (Pz < zmax)[:, :, np.newaxis]
   p_in_r = points_in_rotatingrectangles(lidar_points, boxes)
   ii = np.concatenate(, axis=2).sum(axis=2)
   usability_sum = np.sum(ii == 3, axis=0)
   return usability_sum > 0 ​ ​ def get_corners(box):     x = box   y = box   w = box   l = box   yaw = box   if yaw < 0:# 用来映射       yaw = yaw + np.pi ​   bev_corners = np.zeros((4, 2), dtype=np.float32)   cos_yaw = np.cos(yaw)   sin_yaw = np.sin(yaw) ​   bev_corners = (w / 2) * cos_yaw - (l / 2) * sin_yaw + x   bev_corners = (w / 2) * sin_yaw + (l / 2) * cos_yaw + y ​   bev_corners = (l / 2) * sin_yaw + (w / 2) * cos_yaw + x   bev_corners = (w / 2) * sin_yaw - (l / 2) * cos_yaw + y ​   bev_corners = (-w / 2) * cos_yaw - (-l / 2) * sin_yaw + x   bev_corners = (-w / 2) * sin_yaw + (-l / 2) * cos_yaw + y ​   bev_corners = (-l / 2) * sin_yaw + (-w / 2) * cos_yaw + x   bev_corners = (-w / 2) * sin_yaw - (-l / 2) * cos_yaw + y ​   return bev_corners ​ ​ def get_3dbox(boxes):   boxes_3d = []   for box in boxes:       bev_corners = get_corners(box[:5])       down = np.hstack(            * np.ones((bev_corners.shape, 1))])       up = np.hstack(            * np.ones((bev_corners.shape, 1))])       box_3d = np.vstack()       boxes_3d.append(box_3d)   return np.array(boxes_3d) ​ ​ if __name__ == '__main__':   lidar_points = np.random.randint(low=0, high=10, size=(10, 3), dtype='int')   print(lidar_points.shape)   boxes_3d = get_3dbox([, ])   print(boxes_3d.shape)   results = points_in_cubes(lidar_points, boxes_3d)   print(results)     
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 3d点在立方体内(numpy,不使用for循环)