주의, 사내에서 출력되는 데이터를 가지고 진행하였기 때문에
일반적인 경우와는 전혀 다를 수 있습니다.
다음은 현재 사내에서 나오는 pcd 출력물 형태 입니다.
보시다시피 현재 pcd 와 관계 없이 cuboid를 출력하고 있습니다.
시뮬레이션에서 정보를 뽑아 오다 보니 pcd에서 cuboid를 뽑아온게 아니라
각 사물들의 위치를 모두 알고 있는 상태에서, cuboid 별도, pcd 별도로 뽑아와서 이렇게 된 것 같은데요.
저는 pointpillars 를 학습 하기 위해 각각의 객체의 cuboid와 그 안의 points를 모델이 input할 계획이기 때문에
points 가 없는 cuboid는 제거해주어야 할 것 같습니다.
현재 정부 과제 사업을 위해 시뮬레이션에서 데이터를 출력하는 시간 또한 매우 중요한 상황이기 때문에
위 내용은 후처리로 진행해야할 듯 싶습니다.
전략
1. objTag가 객체의 클래스를 나타내는 값이라는 것을 알았습니다.
2. objTag와 Cuboid 좌표를 이용하여, 각 Cuboid 안에서 points들의 갯수를 셀 것입니다.
3. points 갯수가 적은 Cuboid에 대하여 출력을 하지 않을 것입니다.
단순히 pcd를 그리는 것이라면 아래와 같이 o3d를 사용할 수 있습니다.
import open3d as o3d
import numpy as np
def show_open3d_pcd(pcd, show_origin=True, origin_size=3, show_grid=True):
cloud = o3d.geometry.PointCloud()
v3d = o3d.utility.Vector3dVector
if isinstance(pcd, type(cloud)):
pass
elif isinstance(pcd, np.ndarray):
cloud.points = v3d(pcd)
coord = o3d.geometry.TriangleMesh().create_coordinate_frame(size=origin_size, origin=np.array([0.0, 0.0, 0.0]))
# set front, lookat, up, zoom to change initial view
o3d.visualization.draw_geometries([cloud, coord])
pcd_path = './gtprogram_ver.0.0.11/PCD/1674782460103.pcd'
pcd = o3d.io.read_point_cloud(pcd_path,format="xyz")
pcd = np.asarray(pcd.points)
show_open3d_pcd(pcd)
o3d.io.read_point_cloud는 단순히 x, y, z값 만 뽑아내는 것 같더라구요.
문제 해결
PCD를 Visualize 하는 코드
import open3d as o3d
import numpy as np
import json
import cv2
import open3d as o3d
import os
def show_open3d_pcd(pcd, show_origin=True, origin_size=3, show_grid=True):
cloud = o3d.geometry.PointCloud()
v3d = o3d.utility.Vector3dVector
if isinstance(pcd, type(cloud)):
pass
elif isinstance(pcd, np.ndarray):
cloud.points = v3d(pcd)
coord = o3d.geometry.TriangleMesh().create_coordinate_frame(size=origin_size, origin=np.array([0.0, 0.0, 0.0]))
# set front, lookat, up, zoom to change initial view
o3d.visualization.draw_geometries([cloud, coord])
Cuboid 오버레이 하는 코드
COLORS = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0]]
COLORS_IMG = [[0, 0, 255], [0, 255, 0], [255, 0, 0], [0, 255, 255]]
LINES = [
[0, 1],
[1, 2],
[2, 3],
[3, 0],
[4, 5],
[5, 6],
[6, 7],
[7, 4],
[2, 6],
[7, 3],
[1, 5],
[4, 0]
]
def npy2ply(npy):
ply = o3d.geometry.PointCloud()
ply.points = o3d.utility.Vector3dVector(npy[:, :3])
density = npy[:, 3]
colors = [[item, item, item] for item in density]
ply.colors = o3d.utility.Vector3dVector(colors)
return ply
def ply2npy(ply):
return np.array(ply.points)
def bbox_obj(points, color=[1, 0, 0]):
colors = [color for i in range(len(LINES))]
line_set = o3d.geometry.LineSet(
points=o3d.utility.Vector3dVector(points),
lines=o3d.utility.Vector2iVector(LINES),
)
line_set.colors = o3d.utility.Vector3dVector(colors)
return line_set
def vis_core(plys):
vis = o3d.visualization.Visualizer()
vis.create_window()
ctr = vis.get_view_control()
param = o3d.io.read_pinhole_camera_parameters('./viewpoint.json')
for ply in plys:
vis.add_geometry(ply)
ctr.convert_from_pinhole_camera_parameters(param)
vis.run()
# param = vis.get_view_control().convert_to_pinhole_camera_parameters()
# o3d.io.write_pinhole_camera_parameters(os.path.join(PAR, 'viewpoint.json'), param)
vis.destroy_window()
def vis_pc(pc, bboxes=None, labels=None):
'''
pc: ply or np.ndarray (N, 4)
bboxes: np.ndarray, (n, 7) or (n, 8, 3)
labels: (n, )
'''
if isinstance(pc, np.ndarray):
pc = npy2ply(pc)
mesh_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(
size=10, origin=[0, 0, 0])
if bboxes is None:
vis_core([pc, mesh_frame])
return
vis_objs = [pc, mesh_frame]
for i in range(len(bboxes)):
bbox = bboxes[i]
if labels is None:
color = [1, 0, 0]
else:
if labels[i] >= 0 and labels[i] < 3:
color = COLORS[labels[i]]
else:
color = COLORS[-1]
vis_objs.append(bbox_obj(bbox, color=color))
vis_core(vis_objs)
Cuboid 좌표 값 출력
def cuboid_word_list(json_path):
## json 파일 경로
with open(json_path, "r") as json_file :
data_info = json.load(json_file)
for i in range(len(data_info['gt_data']['label_data']['cuboid_world'])):
if i == 0 :
lidar_bboxes_points = np.array([[[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['back']['right']['bottom'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['back']['right']['top'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['back']['left']['top'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['back']['left']['bottom'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['front']['right']['bottom'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['front']['right']['top'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['front']['left']['top'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['front']['left']['bottom'].values()],
]])
else :
lidar_bboxes_points = np.append(lidar_bboxes_points,
np.array([[
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['back']['right']['bottom'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['back']['right']['top'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['back']['left']['top'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['back']['left']['bottom'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['front']['right']['bottom'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['front']['right']['top'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['front']['left']['top'].values()],
[x for x in data_info['gt_data']['label_data']['cuboid_world'][i]['front']['left']['bottom'].values()],
]])
, axis = 0)
return lidar_bboxes_points
필터링 한 Cuboid
- np.loadtxt 를 이용해 pcd를 출력하여 가져왔습니다.
- pcd 안의 속성 중 OBJTag 를 이용하여, 객체에 대한 PCD 값 만을 가져왔습니다.
- Cuboid x, y, z 값 내부의 points 들의 점을 셌습니다.
- points가 10보다 작을 경우 제외하였습니다.
def filter_cuboid_list(pcd_path, json_path):
# load txt, skiprows를 통해 윗 줄 10줄 빼고 가져왔습니다.
pcd_array = np.loadtxt(pcd_path, dtype=np.float32, skiprows=10, delimiter=' ')
# OBJTag : pcd_array[:,-1] 가 0보다 크면 instance (OBJTag는 마지막 열에 있음)
instance_pcd = pcd_array[np.where(pcd_array[:,-1]>0)]
# Cuboid list를 가져옴 (n, 8, 3) 형태
cuboid_list = cuboid_word_list(json_path)
# 점의 갯수가 적은거 필터링 할꺼
filter_cuboid_list = []
for idx, obj in enumerate(cuboid_list):
# points_idx는 cuboid 범위 안의 points들 index
points_count = sum ( (min(obj[:,0]) <= instance_pcd[:,0]) & (instance_pcd[:,0] <= max(obj[:,0]))
& (min(obj[:,1]) <= instance_pcd[:,1]) & (instance_pcd[:,1] <= max(obj[:,1]))
& (min(obj[:,2]) <= instance_pcd[:,2]) & (instance_pcd[:,2] <= max(obj[:,2]))
)
# 점의 갯수가 10개보다 작으면 필터링
if points_count < 10 :
# 디버그를 위한 프린트
# print(len(points_idx))
continue
else :
filter_cuboid_list.append(idx)
return cuboid_list[filter_cuboid_list]
출력
- 출력 결과는 위의 이미지와 같습니다.
- 필터링 전 Cuboid는 점이 없음에도 출력되나, 필터링 이후 Cuboid는 점이 있는 Cuboid만을 출력합니다.
json_path = "./gtprogram_ver.0.0.11/outputJson/1674782462239.json"
pcd_path = "./gtprogram_ver.0.0.11/PCD/1674782462239.pcd"
pcd = o3d.io.read_point_cloud(pcd_path,format="xyz")
cuboids = filter_cuboid_list(pcd_path, json_path)
# pcd_print = np.asarray(pcd.points)
vis_pc(pcd, cuboids)
'Project' 카테고리의 다른 글
[MMDetection3D] ply to bin, obj to ply (0) | 2023.02.09 |
---|---|
[Pointpillars] MMDetection3D 세팅 및 데모 확인 (0) | 2023.02.09 |
MaskRCNN 가이드 (0) | 2022.12.14 |
[Pointpillars] Kitty Dataset #2 (0) | 2022.12.05 |
[Pointpillars] Kitti Dataset (0) | 2022.12.05 |