본문 바로가기
On Going/Point Cloud Data

[pcd] 도로 포인트클라우드를 평면으로 정렬하는 4가지 방법: 딥러닝 전처리를 위한 접근(4. PCA기반 평면정렬)

by 에아오요이가야 2025. 4. 14.

포인트클라우드는 자율주행, 디지털 트윈, 스마트시티 등에서 중요한 3D 데이터입니다. 특히 도로 주행 환경을 스캔한 포인트클라우드를 딥러닝에 활용하려면, 도로면을 평면으로 정렬하거나 2D 이미지처럼 표현하는 전처리 과정이 필요합니다.

 

이 글에서는 도로와 같은 경사 있고 굴곡진 포인트클라우드를 projection 하기 위한 4가지 대표적인 방법 중 네 번째를 소개합니다.

 

4. PCA(Principal Component Analysis)

PCA는 데이터의 분산이 가장 큰 방향을 찾아내는 고전적인 통계 기법입니다. 주로 고차원 데이터를 저 차원으로 투영할 때 사용되지만, 3D 포인트 클라우드에서는 다음과 같은 목적에 활용됩니다.

 

입력: 3D 포인트 집합

\( X = \{ \mathbf{x}_1, \mathbf {x}_2, …, \mathbf {x}_n \}, \quad \mathbf {x}_i \in \mathbb {R}^3 \)

 

1단계: 평균 중심화

 

\( \bar{\mathbf{x}} = \frac {1}{n} \sum_{i=1}^{n} \mathbf {x}_i, \quad X_c = X - \bar {\mathbf {x}} \)

 

 2단계: 공분산 행렬 계산

 

\( C = \frac{1}{n} X_c^T X_c \)

 

 

3단계: 고유값 분해 (Eigen Decomposition)

 

\( C \mathbf{v}_i\mathbf {v}_i = \lambda_i \mathbf {v}_i \)

 

  • \mathbf {v}_1, \mathbf {v}_2, \mathbf {v}_3: 서로 직교하는 주성분 방향
  • \lambda_1 \ge \lambda_2 \ge \lambda_3: 각 방향의 분산 크기
  • **가장 작은 분산 방향 \mathbf{v}_3**는 평면의 법선 벡터로 해석
import numpy as np
import open3d as o3d
from scipy.spatial.transform import Rotation as R

# 1. 포인트클라우드 불러오기
pcd = o3d.io.read_point_cloud("road_region.pcd")
points = np.asarray(pcd.points)

# 2. 평균 중심화
mean = points.mean(axis=0)
centered = points - mean

# 3. 공분산 행렬 및 고유값 분해
cov = np.cov(centered.T)
eigvals, eigvecs = np.linalg.eigh(cov)

# 4. 가장 작은 고유값 방향 = 평면의 법선 벡터
normal = eigvecs[:, 0]

# 5. 회전: 법선을 Z축과 정렬
z_axis = np.array([0, 0, 1])
rotation_axis = np.cross(normal, z_axis)
angle = np.arccos(np.clip(np.dot(normal, z_axis), -1.0, 1.0))
rotation = R.from_rotvec(rotation_axis * angle)
rotated_points = rotation.apply(points)

# 6. 정렬된 포인트클라우드 저장 및 시각화
aligned_pcd = o3d.geometry.PointCloud()
aligned_pcd.points = o3d.utility.Vector3dVector(rotated_points)
o3d.visualization.draw_geometries([aligned_pcd])

 

댓글