중간점검: 포인트 클라우드(Point Cloud) 모르는 단어 정리하고 넘어가기
오늘은 예고대로 포인트 클라우드(Point Cloud)에 대해 공부하다가 나왔던 모르는 용어나 개념, 파일 형식 등에 대해 알아보고자 한다. 오늘 알아볼 것은 다음과 같다.
오늘 알아보기
구조화된 광
ICP
RANSAC알고리즘
DBSCAN알고리즘
.las
.laz
구조화된 광 (Structured Light)
구조화된 광은 3D 스캐닝 기술 중 하나로, 패턴화된 광(선, 격자, 점무늬등)을 물체에 투사한 후 카메라로 촬영하여 깊이 정보를 추출하는 방식이다.
삼각측량 원리를 기반으로 하며, 스테레오 카메라보다 정밀도가 높지만 동적인 물체에는 약하다.
ICP (Iterative Closest Point)
- 두 개의 3D 포인트 클라우드를 정렬(등록, Registration)하는 알고리즘으로, 한 포인트 클라우드(소스)를 다른 포인트 클라우드(타겟)에 정렬시키는 과정에서 가장 가까운 점을 찾고 반복적으로 변환 행렬(회전 + 이동)을 계산하여 최적 정렬을 찾는다.
파이썬 코드 예시 (Open3D 사용)
import open3d as o3d
# 두 개의 포인트 클라우드 불러오기
source = o3d.io.read_point_cloud("source.ply")
target = o3d.io.read_point_cloud("target.ply")
# ICP를 실행
threshold = 0.02 # 거리 임계값
transformation = o3d.pipelines.registration.registration_icp(
source, target, threshold, np.eye(4),
o3d.pipelines.registration.TransformationEstimationPointToPoint()
)
# 변환을 적용 및 시각화하기
source.transform(transformation.transformation)
o3d.visualization.draw_geometries([source, target])
RANSAC (Random Sample Consensus) 알고리즘
이상치(Outlier)가 많은 데이터에서 모델을 찾기 위한 기법으로, 여러 번 샘플을 무작위로 선택하여 모델을 생성하고 가장 많은 인라이어(Inlier)를 포함하는 모델을 최종 선택한다.
사용 사례:
- 평면 검출 (예: 포인트 클라우드에서 지면 검출)
- 직선/원 검출 (예: 이미지에서 도로선 감지)
- 카메라 포즈 추정 (PnP 문제)
예시: 평면 검출 (Open3D 사용)
import open3d as o3d
# 포인트 클라우드 로드
pcd = o3d.io.read_point_cloud("pointcloud.ply")
# RANSAC을 사용한 평면 검출
plane_model, inliers = pcd.segment_plane(distance_threshold=0.01,
ransac_n=3,
num_iterations=1000)
# 인라이어 (평면에 속하는 점)만 시각화
inlier_cloud = pcd.select_by_index(inliers)
inlier_cloud.paint_uniform_color([1.0, 0, 0]) # 빨간색 표시
o3d.visualization.draw_geometries([inlier_cloud])
DBSCAN (Density-Based Spatial Clustering of Applications with Noise) 알고리즘
밀도 기반 클러스터링 알고리즘으로, 군집 내 점들이 서로 가까운 거리 내에 존재해야 한다는 가정을 한다.
K-Means와 다르게 클러스터 개수를 미리 지정할 필요가 없고, 노이즈를 자동으로 분리하는 특징이 있다.
사용 사례:
- 포인트 클라우드에서 객체 분리 (예: 자동차, 보행자 클러스터링)
- LiDAR 데이터 처리
예시: Open3D를 사용한 DBSCAN 클러스터링
import numpy as np
import open3d as o3d
# 포인트 클라우드 로드
pcd = o3d.io.read_point_cloud("pointcloud.ply")
# DBSCAN 클러스터링 실행 (eps: 반경, min_points: 최소 포인트 개수)
labels = np.array(pcd.cluster_dbscan(eps=0.02, min_points=10, print_progress=True))
# 클러스터링 결과 시각화
max_label = labels.max()
colors = np.random.rand(max_label + 1, 3)
colors = np.vstack([colors, [0, 0, 0]]) # 노이즈(라벨 -1)는 검정색
pcd.colors = o3d.utility.Vector3dVector(colors[labels])
o3d.visualization.draw_geometries([pcd])
.las 파일
LAS(LiDAR Data Exchange Format)는 LiDAR(레이저 스캐닝) 데이터를 저장하는 표준 포맷이다.
메타데이터(예: GPS 시간, 반사 강도, 분류 정보)와 함께 포인트 클라우드를 저장할 수 있다.
사용 사례: 항공 LiDAR, 지형 매핑, 건축물 3D 모델링 등에서 활용된다.
라이브러리를 사용하여 .las 파일 읽기 (laspy 사용):
import laspy
# .las 파일 열기
las = laspy.read("pointcloud.las")
# 포인트 데이터 가져오기
x, y, z = las.x, las.y, las.z
print(f"총 포인트 개수: {len(x)}")
.laz 파일
.laz는 LAS 포맷의 압축 버전이다.
일반적인 LAS 파일보다 저장 공간을 절약할 수 있어 대규모 LiDAR 데이터에 적합하다.
사용 사례: 동일한 LAS 파일과 같지만, 저장 공간이 중요한 프로젝트에서 선호된다.
LAStools를 사용한 .laz 변환 예시:
laszip -i input.laz -o output.las