레이블이 공간정보인 게시물을 표시합니다. 모든 게시물 표시
레이블이 공간정보인 게시물을 표시합니다. 모든 게시물 표시

2026년 7월 8일 수요일

3DGS 가우시안 스플리터 기반 건물 인프라 3차원 모델 생성 기술 분석

이 글은 3DGS 가우시안 스플리터 기반 건물 인프라 3차원 모델 생성 기술 분석 내용을 나눔한다.

개요
건물, 교량, 도로 등 대형 인프라 시설의 효율적인 유지관리 및 디지털 트윈 구성을 위해서는 현장의 3차원 형상을 정밀하게 복원하는 기술이 필수적이다. 기존의 Structure from Motion(SfM) 및 Multi-View Stereo(MVS) 기반 포인트 클라우드 생성 방식은 연산 시간이 대단히 길고 복잡한 그래픽 메시를 다루어야 한다는 한계가 있었다. 이후 등장한 NeRF(Neural Radiance Fields) 또한 정밀한 렌더링은 가능하나 훈련 및 추론 속도가 느리다는 단점이 존재했다.

최근 고속 렌더링 기술로 주목받는 3D Gaussian Splatting (3DGS) 기술은 타일 기반 래스터화를 통해 실시간 3D 복원을 가능하게 했다. 오픈소스 프로젝트 EOGS2 (Efficient & Optimal Gaussian Splatting for Infrastructure Structure) 프로젝트는 이러한 3DGS 알고리즘을 확장 및 최적화하여, 실외 건물 및 대규모 인프라 구조물 복원에 특화된 3D 모델링 파이프라인을 제시한다.

핵심 기술 요소 및 시스템 구조
EOGS2 프로젝트의 핵심은 정밀도 높은 위치 정보(주로 UAV 드론 촬영 데이터 및 COLMAP 경로 데이터)와 결합하여 가우시안 타일 생성을 최적화하는 기법에 있다.

1) 3D 가우시안 스플래팅 (3DGS) 기반 최적화
  • 공간 표현: 공간의 개별 점을 단순 점(Point)이 아닌 공간적 범위, 방향, 색상, 투명도를 갖는 3D 가우시안(Ellipsoid) 집합으로 표현한다.
  • 학습 파라미터: 각 가우시안 타일의 중심 위치(Position, XYZ), 척도(Scale, S), 회전(Rotation, R), 불투명도(Opacity), 색상 표현을 위한 구면 조화 함수(Spherical Harmonics, SH) 계수를 기디언트 하강법으로 학습한다.
  • 인프라 맞춤 밀도 제어 (Density Control): 평평한 벽면, 창문 프레임, 복잡한 교량 입체 구조 등 건물 인프라의 특성에 맞춰 가우시안 타일을 분할(Split)하거나 복제(Clone)하여 디테일을 정밀하게 살린다.
2) 대규모 인프라 데이터셋 및 카메라 포즈 통합
드론(UAV)이나 육상 카메라로 촬영된 고해상도 영상을 기반으로 COLMAP 기법을 사전 구동하여 초깃값 포인트 클라우드 및 카메라 외부 파라미터(Extrinsics)를 확보한다.
건물 외벽의 텍스처 반복 패턴이나 기하학적 가장자리(Edge) 부분에서의 기하학적 왜곡을 줄이기 위해 최적화 손실 함수(Loss Function)에 L1 Loss와 D-SSIM(Structural Similarity)을 병합 사용한다.

건물 인프라 모델링 관점에서의 주요 장점
1) 실시간 복원 및 고속 렌더링
실제 구축된 가우시안 모델은 CUDA 래스터라이저를 통해 초당 100~200 FPS 이상의 실시간 속도로 뷰포트 전환 및 카메라 시점 변경을 지원한다. 이는 대형 건물이나 설비 점검 시 실시간 3D 인터랙티브 관제가 가능함을 의미한다.

2) 미세 구조물 및 경계 표현력 향상
기존 Mesh 변환 방식에서 흔히 발생하는 에지(Edge) 무너짐이나 텍스처 뭉개짐 현상이 대폭 개선된다. 건물 외벽의 균열, 배관, 철골 구조 등 인프라 안전점검에 필수적인 미세 요소를 효과적으로 복원한다.

3) 대용량 파이프라인의 효율성
NeRF 대비 학습 속도가 수십 배 이상 빠르며, 메시(Mesh) 재구성 없이 가우시안 타일 포맷(`.ply`)으로 직관적인 대용량 3D 데이터 저장이 가능한다.

한계점 및 향후 발전 방향
1) 동적 정적 객체 분리
건물 주변을 지나는 차량, 사람 등 동적 장애물이 촬영 영상에 포함될 경우 가우시안 잔상이 남아 모델 품질이 저하될 수 있다. 사전 튜닝 파이프라인(Masking) 결합이 요구된다.

2) 물리적 메시(Mesh) 변환의 필요성
3DGS는 시각적 렌더링에 최적화되어 있어, 시뮬레이션이나 충돌 감지(Physics/Collision Test)를 활용하려면 가우시안 타일을 Polygon Mesh로 전환하는 후처리 알고리즘(TSDF, Marching Cubes 연계 등)이 필요한다.

마무리
EOGS2 프로젝트는 3DGS 기술을 건축 및 인프라 영역으로 확장하여 고품질의 3D 공간 복원을 가능하게 만든 우수한 연구 사례이다. 향후 스마트 시티, 디지털 트윈 기반 시설물 유지관리, VR/AR 시뮬레이터 및 드론 자율주행용 3D Map 구축 기술의 핵심 프레임워크로 폭넓게 활용될 것으로 기대된다.

레퍼런스

2025년 12월 5일 금요일

독일 뮌헨 공과대학교(TUM) 세계 최대 규모 오픈소스 3D 건물 지도 데이터셋 글로벌 빌딩 아틀라스 기술 개발 이야기

이 글은 독일 뮌헨 공과대학교(TUM) 연구팀이 개발하여 공개한 세계 최대 규모의 3D 건물 지도 데이터셋인 글로벌 빌딩 아틀라스(Global Building Atlas) 프로젝트에 대해 설명한다. 특히, 인공지능과 위성 영상 분석 기술을 결합하여 전 세계에 존재하는 건물을 3차원 모델로 구현한 방법을 기술적 관점에서 이야기나눈다.


이 결과는 오픈소스로 공개되었으며, 기존에 가장 방대하다고 알려진 데이터셋이 포함하던 약 17억 개의 건물 수치를 대폭 상회하는 규모로 개발되었다. 그동안 디지털 지도 데이터에서 소외되었던 아프리카, 남미, 아시아의 농촌 지역 건물들까지 정밀하게 포착해냈다는 점에서 기술적 진보를 보여준다.

개발과정
지도의 기반이 된 데이터는 주로 2019년에 촬영된 플래닛스코프(PlanetScope) 위성 이미지를 활용하였으며, 연구팀은 이를 통해 각 건물의 2D 바닥 면적뿐만 아니라 높이 정보까지 정밀하게 추출했다. 이 지도가 제공하는 높이 데이터의 해상도는 3x3미터 수준으로, 기존의 글로벌 건물 높이 데이터셋들이 주로 90미터 해상도에 그쳤던 것과 비교하면 약 30배 이상 정밀도가 향상된 수치이다. 제공되는 데이터는 건물의 대략적인 형태와 높이를 단순화하여 표현하는 LoD1(Level of Detail 1) 수준의 3D 모델 형식을 따르고 있어, 전 지구적 규모의 방대한 데이터를 다루면서도 활용성을 확보했다.

이 연구는 기존 데이터셋이 가진 커버리지의 한계와 3D 정보의 부재를 해결하기 위해 진행되었으며, 전 세계 약 27억 5천만 개의 건물을 포함하는 방대한 규모의 데이터를 구축하였다. 이는 기존의 가장 포괄적인 데이터베이스보다 10억 개 이상 많은 수치로, 그동안 데이터상에서 누락되었던 전 세계 건물의 약 40% 이상을 메우는 성과이다.

연구팀은 이 데이터셋 구축을 위해 플래닛스코프(PlanetScope) 위성 이미지만을 사용하는 머신러닝 기반 파이프라인을 개발했다.  이 과정은 크게 건물 폴리곤 생성과 높이 추정의 두 단계로 나뉘며, 기존의 오픈소스 건물 데이터(OpenStreetMap, Google, Microsoft 등)와 자체 생성한 데이터를 '품질 기반 융합 전략'을 통해 결합하여 데이터의 완성도를 극대화했다. 이를 통해 완성된 'GBA-Height'는 3x3미터의 공간 해상도를 제공하는데, 이는 기존 글로벌 제품들이 제공하던 90미터 해상도보다 약 30배 더 정밀한 수준이며 이를 통해 지역 및 전 지구 규모에서 신뢰할 수 있는 건물 부피 분석이 가능해졌다.

또한 연구팀은 건물 높이 정보를 포함한 'GBA-LoD1' 모델을 생성하여 약 26억 8천만 건의 건물 인스턴스를 구현했으며, 이는 전체의 97%에 달하는 높은 완성도를 보인다.  높이 추정의 정확도를 나타내는 RMSE(평균제곱근오차)는 대륙별로 1.5미터에서 8.9미터 사이로 나타났으며, 특히 오세아니아와 유럽에서 높은 정확도를 보였다. 데이터 분석 결과, 아시아가 건물 수와 총 부피 면에서 압도적인 비중을 차지하는 반면, 아프리카는 건물 수는 많으나 총 부피가 작아 소규모 또는 비공식 건물이 다수 분포함을 시사했다. 
공개된 GlobalBuildingAtlas LoD1 웹 서비스(선릉역, 뉴욕 근처 생성된 3D건물모델)

AI 모델 개발 접근법
인공지능 모델 개발 및 활용 관점에서 본 GlobalBuildingAtlas(GBA) 프로젝트는 3미터 해상도의 단일 시점(Monocular) 위성 영상인 PlanetScope 데이터를 입력으로 받아 전 지구적 규모의 3D 건물 모델을 생성하는 파이프라인을 구축했다는 점에서 기술적 의미가 있다. 전체 시스템은 크게 2D 건물 폴리곤 생성을 위한 의미론적 분할(Semantic Segmentation) 네트워크와 3D 높이 추정을 위한 단안 높이 추정(Monocular Height Estimation) 네트워크로 이원화되어 설계되었다.

2D 건물 폴리곤 생성 모델의 경우, 연구팀은 UPerNet(Unified Perceptual Parsing Network) 아키텍처를 기반으로 하되 백본(Backbone)으로 ConvNeXt-Tiny를 사용했다.  모델의 성능을 높이기 위해 '추출(Extraction)'과 '정규화(Regularization)'라는 두 단계의 네트워크를 직렬로 구성한 점이 특징이다. 첫 번째 네트워크가 위성 영상에서 1차적인 이진 마스크를 생성하면, 동일한 아키텍처를 가진 두 번째 정규화 네트워크가 이를 입력받아 노이즈를 제거하고 건물 경계를 다듬는다. 특히 정규화 네트워크 학습 시에는 깨끗한 폴리곤 마스크에 인위적인 노이즈를 주입한 것을 입력 데이터로 사용하여, 모델이 거친 마스크를 정제된 형태로 복원하는 일종의 디노이징(Denoising) 기능을 수행하도록 훈련시켰다.

3D 높이 추정 모델은 HTC-DC Net(Hybrid Transformer-CNN with Dynamic Classification)을 채택했다. 이는 CNN 계열인 EfficientNet-B5를 백본으로 사용하여 이미지의 특징을 추출하고, 비전 트랜스포머(ViT) 인코더를 결합하여 지역적 특징과 전역적 특징 간의 관계를 학습하는 하이브리드 구조이다. 높이 예측 방식으로는 단순한 회귀(Regression) 대신 '분류-회귀(Classification-Regression)' 패러다임을 적용했다. 이는 높이 범위를 먼저 구간별로 분류(Classification)한 뒤, 해당 구간 내에서 미세 값을 회귀로 조정하는 방식으로, 이를 통해 예측의 안정성을 높였다. 학습 데이터로는 전 세계 168개 도시의 항공 LiDAR 데이터에서 추출한 정규화된 디지털 표면 모델(nDSM)을 정답 레이블(Ground Truth)로 활용했다.

추론(Inference) 및 배포 단계에서는 모델 예측의 불확실성(Uncertainty)을 정량화하기 위해 테스트 시간 증강(TTA, Test Time Augmentation) 기법을 도입했다. 대용량 위성 영상을 처리할 때 슬라이딩 윈도우 방식을 적용하여 겹치는 영역에 대해 픽셀당 최대 4번의 예측을 수행하고, 이 결과값들의 분산을 계산하여 데이터의 신뢰도 지표로 삼았다. 이러한 딥러닝 파이프라인은 기존 오픈소스 데이터가 커버하지 못하는 지역의 데이터를 생성하는 데 핵심적인 역할을 했으나, 아프리카 등 학습 데이터(LiDAR)가 전무한 지역에 대해서는 도메인 적응(Domain Adaptation)의 한계가 존재함을 명시하고 있다.

기술 연구 및 개발 의미
이 연구는 단순한 데이터 구축을 넘어 유엔의 지속가능발전목표(SDG) 11번, 특히 토지 소비율과 인구 증가율의 비율을 모니터링하는 데 있어 단순 면적보다 '건물 부피' 기반 지표가 도시의 개발 상태와 인구 밀도를 더 정확하게 반영함을 입증했다. 1인당 건축 부피와 GDP의 상관관계를 분석한 결과, 부피 기반 지표가 경제 발전 수준을 더 잘 설명하는 것으로 나타났다. 

상관관계 분석 결과

이러한 고해상도 3D 데이터의 공개는 도시 계획, 재난 위험 관리, 기후 변화 대응 연구 분야에 즉각적인 활용이 가능하다. 구체적으로는 홍수나 지진 발생 시 피해 규모를 건물의 높이와 부피에 기반해 정확하게 시뮬레이션하거나, 도시의 건물 밀도와 부피를 분석하여 에너지 소비 효율을 계산하고 인구 과밀 지역의 주거 환경을 파악하는 기초 자료로 쓰일 수 있다. 해당 연구의 방법론과 데이터셋 구축 과정에 대한 상세한 내용은 과학 저널인 Earth System Science Data에 게재되어 학술적 검증을 마쳤으며, 연구팀은 이 데이터를 오픈 소스로 공개하여 전 세계 연구자와 정책 입안자들이 자유롭게 활용할 수 있도록 했다.

마무리
논문의 주 저자들을 보면 알겠지만, 모두 중국인이다(요즘 놀랍지도 않은...). 논문은 매우 기술적이고, AI 사용 접근 방법은 똑똑하다. 글로벌 연구 분야에서 이런 상황들이 최근 몇 년 사이 크게 많아지고 있다. 이들이 접근한 방법들을 보고 있자면 여러가지 생각이 든다. 사실, 국내 연구 학계(산학연 포함)에서 이렇게 대규모의 데이터셋 수집, 구축, 기술 개발, 성능 분석, 연구 과정의 투명한? 오픈소스 공개, 여러 저자들 간의 협력적 연구를 통한 시너지 효과를 발생하는 경우는 매우 드물다. 좋은 연구 결과를 만든 것은 연구자들의 열정과 노력도 중요하겠지만 연구 핵심기술 개발에 대한 선택과 집중이 가능한 연구 환경이 전제 되어야 한다. 이런 환경의 연구기관 인프라는 참 부럽다는 생각이다.

레퍼런스

2024년 10월 4일 금요일

BIM IFC 파일을 Cesium 디지털트윈 플랫폼에 3D tiles로 가시화하는 방법과 구조

이 글은 BIM(Building Information Modeling) 포맷 중 하나인 IFC 파일을 Cesium 플랫폼에 3D tiles로 가시화하는 방법을 간략히 설명한다. 아울러, 마지막 부분에 3D tiles 개념과 구조를 간략히 나눔한다. Cesium에서 개발된 3D tiles는 3D 고속 렌더링을 위한 모델 구조와 렌더링 메커니즘을 제공한다. 이 기술은 현재 공간정보산업표준을 담당하는 OGC(Open Geospatial Consortium)와 유기적 협력을 통해 발전하고 있다.
Cesium 3D tiles 가시화 모습 예시

참고로, 최근 릴리즈된 IFC 직접 로딩하는 기술은 향후에 사용기를 정리하여 공유할 것이다( 아직, IFC를 직접 Cesium으로 임포트하는 기능은 완전하지 않다). 관심있는 분들은 다음 링크를 참고하길 바란다.

개요
Cesium은 구글 어스와 유사한 지구 스케일의 디지털트윈 플랫폼이다. 이를 이용하면, 도시 차원에서 분석하고, 실내 건물을 탐색하는 등의 유스케이스를 개발할 수 있다. 국내 대부분의 3차원 도시 플랫폼 기반 서비스에서 Cesium이 사용되고 있다. Cesium은 디지털트윈 모델을 다루기 위한 저작도구도 함께 제공한다. 개발자는 서비스에 필요한 메뉴 기능, 데쉬보드에 표출한 데이터 처리에만 신경을 쓰면 된다. 
Cesium 저작도구 예시

공간정보 기술을 연구하다 보면, 가끔 BIM 파일 포맷 중 하나 인 IFC(Industry Foundation Classes)를 Cesium위에 가시화해야 하는 경우가 종종 발생할 때가 있다. 하지만, Cesium은 IFC를 직접적으로 지원하지 않는다. 
IFC 추가 에러 발생 모습

Cesium은 IFC를 포함한 모든 3D 모델파일을 3D tiles로 변환해 업로드하도록 하고 있다. 이는 무거운 3D 모델의 가시화 성능을 고려한 것이다. 

3D tiles은 웹에서 가시화하기에 무거운 3D 파일을 공간인덱싱 기법을 이용해 Octree형식으로 표현하고, 각 노트에 분할된 3D 모델의 부분을 담아둔다. 메쉬 간략화 기법을 이용해, 카메라가 모델을 비추는 거리에 따라 적절한 LoD(Level of Detail)의 메쉬를 보여준다. 이는 게임에서 FPS 성능을 올리기 위해 개발된 기법과 매우 유사하다. glTF 20은 3D 타일의 기본 형식이다. 
glTF 2.0 기능(3차원 점군, 텍스쳐, 모델 지원 예시)

Cesium은 다양한 샘플 코드를 sandcastle이란 플랫폼으로 제공하여, 편리한 개발을 지원하고 있다.

3D tile 모델 변환 및 업로드
먼저, 다음 링크를 방문해 Cesium ion 에 가입한다.
이후, 세슘의 API, 어셋(asset)을 관리하는 클라우드, Javascript 기반 예제 등을 무료로 사용할 수 있다. 여기서 어셋이란 플랫폼에서 사용하는 GIS, BIM 등 모든 파일 및 데이터셋을 의미한다. 가입 후, 아래를 클릭해 어셋을 추가해 보자. 
Cesium ion 메뉴 화면

Cesium은 3D 모델을 3차원 타일 형식으로 내부 표현한다. 이 형식을 지원하는 파일 포맷은 다음과 같다. 
IFC를 fbx와 같은 형식으로 변환한 후, My Assets 메뉴(My Assets | Cesium ion)를 이용해 데이터를 추가한다. 추가된 데이터는 고유의 Asset ID가 부여된다. 다음 그림에서 첫 행의 어셋인 2716386은 어셋 ID를 보여준다. 현재 세슘은 5GB 무료 어셋 저장소를 제공한다.

참고로, IFC파일을 다른 형식으로 변환하기 위해서는 Revit 등 상용 모델러를 사용하거나, Blender와 같은 오픈소스 도구에 IFC import 애드인을 설치하고, fbx 포맷 등으로 저장하면 된다. 
Blender에서 IFC to FBX 변환 모습

3차원 모델은 좌표 원점에 표시되므로, 모델의 원점과 각도를 재조정해야 한다. 

다음과 같이 MyAssets 메뉴에 Adjust Tileset Location 메뉴를 클릭한다.

참고로, 만약 모델 원점이 0.0.0이 아니면, 다음 그림과 같이 재조정하기 어렵다. 모델링 할 때 원점을 맞추고 진행한다.

3D Tile Location Editor에서 모델의 위치, 방향을 수정한 후 저장버튼을 클릭한다. 참고로, Click position 버튼을 클릭하면, 현재 커서 위치의 지표면에 맞춰 타일 모델 위치를 자동 입력한다.

앱 서비스 개발
특정 서비스에 3D tile을 사용하고 싶다면, 단순히 primities.add 함수를 사용하여 3D tile을 추가할 수 있다. API를 사용해야 하므로, API 토큰을 생성 한다. 
API 키 토큰 생성 예시

다음 링크를 참고해, API 키 토큰을 생성하고, 이 문자열을 코드의 Token에 할당한다.
HTML를 만들어, 다음 같이 자바스크립트 파일을 입력한다. 어셋 ID를 이용해 fromAssetID에서 어셋을 가져온다.

         Cesium.Ion.defaultAccessToken = '';
         var viewer = new Cesium.Viewer('cesiumContainer', {
            animation: false,
            homeButton: true,
            navigationHelpButton: true
         });

         const tileset = viewer.scene.primitives.add(
            new Cesium.Cesium3DTileset({
               url: Cesium.IonResource.fromAssetId(1378646),
            })
         );

3D tile 코드 사용 예시

이와 관련해 구현된 상세 코드 예시는 다음 github 링크를 참고하길 바란다.
웹 서비스에서 코드 호출한 결과는 다음과 같다. 3D tile이 잘 가시화되는 것을 확인할 수 있다. 

이런 방식으로 디지털트윈 플랫폼의 도시 건물 정보 가시화하는 기능을 구현할 수 있다.

3D tile 구조
Cesium의 3D Tiles 데이터 구조는 대규모 3D 지리 데이터를 효율적으로 스트리밍하고 시각화하기 위해 설계되었다. 3D Tiles 구조는 오픈소스로 다음 깃허브 링크에 공개되어 있다. 

타일 데이터셋은 다음과 같다.
  • Tileset
Tileset.json 파일이 3D 타일의 상위 구성 파일 역할을 하며, 타일 계층 구조와 데이터 위치 정보를 담고 있다. 이 파일은 전체 타일셋의 메타데이터와 루트 타일에 대한 참조를 제공한다. 
 {
  "transform": [
     4.843178171884396,   1.2424271388626869, 0,                  0,
    -0.7993325488216595,  3.1159251367235608, 3.8278032889280675, 0,
     0.9511533376784163, -3.7077466670407433, 3.2168186118075526, 0,
     1215001.7612985559, -4736269.697480114,  4081650.708604793,  1
  ],
  "boundingVolume": {
    "box": [
      0,     0,    6.701,
      3.738, 0,    0,
      0,     3.72, 0,
      0,     0,    13.402
    ]
  },
  "geometricError": 32,
  "content": {
    "uri": "building.b3dm"
  },
  "extensions": {
    "VENDOR_collision_volume": {
      "box": [
        0,     0,    6.8,
        3.8,   0,    0,
        0,     3.8,  0,
        0,     0,    13.5
      ]
    }
  }
}
  • 타일 계층 구조
타일 계층은 루트 타일에서 시작해 더 작은 타일로 분할되며, 쿼드트리나 옥트리 구조를 사용한다. 타일들은 자신보다 작은 자식 타일들을 가지며, 각각의 해상도가 다르다.
루트 타일은 대략적인 모델 데이터를 제공하고, 자식 타일은 줌 인할 때 더 높은 해상도를 제공한다.
  • 타일 구성 요소
Bounding Volume (경계 볼륨)은 각 타일이 포함하는 공간 영역을 정의한다. 이 경계는 카메라의 위치에 따라 타일을 로드할지 결정하는 데 사용된다.
Geometric Error (기하학적 오차)는 타일의 해상도와 관련된 값으로, 클라이언트가 어떤 타일을 로드할지 선택하는 데 도움을 준다.
  • 타일 콘텐츠
타일은 다양한 형태의 3D 데이터를 포함할 수 있다.
Batched 3D Model (B3DM)은 여러 개의 3D 객체를 포함한 배치된 모델이다.
Instanced 3D Model (I3DM)은 동일한 3D 모델을 여러 위치에 인스턴스화하여 사용한다.
Point Cloud (PNTS)는 점군 데이터를 포함한다.
Composite (CMPT)는 다양한 콘텐츠를 하나의 타일에 혼합할 수 있다.
  • LOD (Level of Detail)
3D Tiles는 LOD(세부 수준)에 따라 계층 구조를 가지며, 줌 수준에 따라 더 높은 해상도의 타일을 로드하거나, 멀리 있는 객체는 낮은 해상도를 유지함으로써 성능을 최적화한다.
  • 압축 및 최적화
Cesium의 3D Tiles는 데이터를 압축하여 전송 속도와 메모리 효율성을 높인다.
Draco 압축을 사용하여 기하학 데이터를 압축하고 파일 크기를 줄인다.
이처럼 Cesium의 3D Tiles 구조는 대규모 지리 데이터를 효율적으로 처리하고 동적으로 로드하여 성능을 극대화한다.

다음은 앞의 구조를 표현한 그림이다.
이 그림에서 보면, 솔리드 모델, IFC와 같이 3D 모델 형상 정보는 메쉬 형태로 Vertices, Texels 로 변환된다. 이는 동일한 인스턴스를 스케일, 위치, 방향만 다르게 해서 렌더링하는 객체를 GPU 인스턴스로 등록하고(가속 렌더링을 위해), 나머진 형상(FEATURE)로 등록한다. 이 피쳐는 타일 컨텐츠로 등록된다. 

각 타일 컨텐츠는 타일 트리(일종의 공간 인덱싱을 통해 카메라의 거리, 방향에 따라 타일에 포함된 인스턴스의 상세 렌더링 수준을 사전 계산, 결정. 이를 통해, 타일이 보여질 때 가시화 속도를 높이는 역할)에 등록된다. 이때 각 타일은 LoD(Level of detail)을 계산하는 데, 보통, Mesh Simplication 이란 게임엔진에서 사용된 방법을 이용한다. 

각 LoD처리된 타일은 속성정보를 포함하고 있어, 카메라 각도, 거리에 따라 적절한 LoD의 타일 형상과 정보가 보여질 수 있다. 이를 모아 Tileset이라 한다.

마무리
오늘은 BIM IFC 파일을 Cesium 디지털트윈 플랫폼에 3D tiles로 가시화하는 방법과 구조를 간략히 알아보았다. Cesium은 디지털트윈 뿐 아니라 도시 시뮬레이션 가시화 등 많은 곳에서 사용된다. 

개인적으로는 Cesium 오픈 플랫폼의 개발자이자 개발 최고 책임자인 패트릭 코지(Patrick Cozzi)가 30대 초부터 꾸준히 이 기술을 발전시키고 공유하는 모습이 참 인상적이다. 그는 펜실베니아 주립대를 졸업한 후, 석사를 한 UPen에서 9년간이나 컴퓨터 그래픽스 기술을 가르치며, Cesium 을 개발해 공유했다. 그의 석사 논문은 Cesium의 기본 개념이 담겨 있다. 
Patrick Cozzi 석사 논문 일부(2008, UPen. Cesium 3D Tiles 기술 컨셉이 설명됨)

논문을 살펴보면 그가 OpenGL과 컴퓨터 그래픽스에 얼마나 깊은 이해를 하고 있는 지 알수 있다. 일종의 이 분야 오타구로 보여지는 데, 그는 여기서 그치지 않고, 본인이 도시와 같은 대용량 모델을 실시간으로 가시화할 수 있는 기술을 개발해 사람들이 편리하게 사용할 수 있도록 하는 데까지 나아가려 했다. 

그는 2010년대 부터 컴퓨터 그래픽스에 대한 퍼듀 자문, 크로노스 협회 glTF 표준화 기여, 메타버스 협회 창립 이사를 거친다. 2024년에는 그가 개발을 시작해 창립한 Cesium이 벤틀리에 합병되어 플랫폼 개발 최고 책임자가 된다. 
그의 발자취를 살펴보면, 막대한 국가 R&D를 통해 살림하고 있는 국내 그 수많은 SW 정보 기술 관련 협회, 조직에서 제대로 된 오픈소스 하나 산업계에 꾸준히 공유 발전시킨 적이 있는 지, 그 조직에 이런 전문가들이 있기나 한 것인지 생각해 보지 않을 수 없다. 국내 기술 산업이 아직 선진기술 패키징하는 상황에서 이런 문제가 산업 생태계와 국가 시스템의 문제인지, 아니면, 개인의 문제인지 다시 한번 생각하게 된다. 


부록: glTF 구조도
다음 그림은 3D 타일 공식 포맷인 glTF 2.0의 구조와 개념을 상세히 보여준다. 
레퍼런스

무료 CityGML 3D 도시모델 뷰어 FZK Viewer 와 도시 시뮬레이션 SimStadt 소개

공간정보와 관련된 기술 개발을 하다 보면, CityGML 파일을 확인해야 할 때가 발생한다. 이때 CityGML파일 무료 뷰어를 막상 발견하기 어려운 경우가 종종 있다. 이 글은 라이센스 무료인 FZK Viewer 뷰어를 소개하고 설치 및 사용법을 간략히 소개한다. 아울러, 이 프로그램의 상위 R&D 프로젝트인 도시 시뮬레이션 SimStadt 프로그램도 간략히 나눔한다.
CityGML LoD example

FZK Viewer
슈트르가르트 기술대학에서 개발한 뷰어로, 설치형이다. 설치를 위해 다음 링크를 클릭한다.
다음 화면에서 적색 밑줄 단어를 선택하여 다운로드 후, 압축파일을 푼다. 
다음 exe 파일을 실행한다.

예제 파일(예제 파일 다운로드)을 로딩하고, 텍스쳐를 적용하면 다음과 같이 출력된다. 

CityGML Web Viewer
같은 곳에서 개발한 웹 뷰어가 있다. 사용법은 아래 링크를 선택한 후, CityGML파일을 선택하면 된다. 
실행모습

도시 시뮬레이션 SimStadt R&D
FZK viewer는 SimStadt 프로젝트 중 일부 프로그램이다. SimStadt는 HFT(Hochschule für technik. 기술대학) Stuttgart에서 연구 중인 도시 시뮬레이션 환경 프로젝트로, 2015년에 완료된 프로젝트(SimStadt)를 계속 발전해 온 것이다. 
SimStadt는 건물, 도시 구역, 전체 도시 및 지역의 에너지 분석을 위해 실제 도시 계획 상황 또는 계획 상태의 데이터를 사용할 수 있다. 유스케이스 시나리오는 건물 난방 요구 사항, 태양광 발전 시뮬레이션, 건물 레노베이션, 재생 에너지 공급 시나리오 시뮬레이션에 이르기까지 다양하다. 
시나리오 흐름 분석 시뮬레이션을 지원하는 SimStadt 실행 화면

SimStadt는 건축가, 엔지니어링 사무소, 도시 계획가가 사용할 목적으로 개발되고 있다. 향후, 오픈소스로 공개할 계획이 있다. 

일부 소스코드는 다음 링크에서 발견할 수 있다.

이 R&D 프로젝트는 Dr. Volker Coors, Prof. Bastian Schröter에 의해 주도되고 있다.

자세한 내용은 다음 링크를 참고한다.

2024년 5월 22일 수요일

그래프 데이터베이스 Neo4J 기반 데이터 질의 서비스 개발하기

이 글은 그래프 데이터베이스 Neo4J 기반 데이터 질의 서비스 개발하는 방법을 간략히 설명한다. Neo4j는 ACID(Atomicity,Consistency,Isolation,Durability)의 모든 속성을 지원하는 완전 트랜잭션을 지원하는 그래프 데이터베이스이다. 
Neo4j는 2007년에 노이만 라디칼 시스템즈(Neo Technology)라는 회사에 의해 개발되었다. 그래프 데이터베이스는 관계형 데이터베이스와 달리 데이터를 노드와 엣지(관계)로 구성된 그래프 형태로 저장한다. 이러한 방식은 실제 세계의 복잡한 관계를 모델링하기에 적합하며, 네트워크, 사회 네트워크, 지도 및 추천 시스템 등 다양한 분야에서 유용하게 사용된다. neo4j는 가장 인기 있는 그래프 데이터베이스 중 하나로, 고성능, 확장성 및 질의 언어 지원을 특징으로 한다.

Neo4j는 SNS분석, 지도 위치 기반 서비스, IoT 등 그래프형 데이터 관리에 주로 사용된다. 

Neo4j구조는 여러 프로젝트와 프로젝트에 포함된 데이터베이스로 구성된다. 

기본 기능
시작하기
다음 링크에서 프로그램 다운로드 후 설치한다.
설치 후, new project 후 add - local DBMS 선택한다. DB 생성 후 Open 하면 다음같이 브라우저 창을 볼 수 있다. 생성 시 입력 암호를 잘 기억한다.

다음과 같이 neo4j$ 에 명령을 입력해 레코드를 생성해 본다. 
CREATE (john:Person {name: 'John'})
CREATE (joe:Person {name: 'Joe'})
CREATE (steve:Person {name: 'Steve'})
CREATE (sara:Person {name: 'Sara'})
CREATE (maria:Person {name: 'Maria'})
CREATE (john)-[:FRIEND]->(joe)-[:FRIEND]->(steve)
CREATE (john)-[:FRIEND]->(sara)-[:FRIEND]->(maria)
다음 명령을 입력, 실행한다. 
MATCH (n) RETURN n LIMIT 5

결과는 다음과 같이, 질의한 그래프를 표시해준다. 이전 명령이 아래에 표시된 것을 알 수 있다.

http://127.0.0.1:7474/browser 브라우저로 접속해 본다. 초기 ID/PWD는 neo4j, neo4j이다. 여기서, 데스크탑 프로그램과 동일하게 데이터 관리 가능하다.

그래프 DB와 질의어
그래프 DB는 다음 구성요소를 가진다. 
  • Node: 그래프 데이터 레코드
  • Relationship: Node 간의 관계
  • Property: Node의 속성
  • Label: Node를 묶는 단위
Cypher는 그래프 쿼리 언어이다. 문법은 다음과 같다.
CREATE: 노드, 관계 생성
MATCH: 기존 노트, 관계 검색. RETURN이나 WITH로 매칭된 대상 반환.
WHERE: 조건을 지정
MERGE: CREATE와 MATCH를 합친 함수
SET: 노드 LABEL과 PROPERTY를 업데이트 함
DELETE: 노드, 관계를 삭제

Relation 표현은 다음과 같다. 
(node)-[relationship]->(node)

예를 들어, A-[:Knows(since:2020)]->B 경우는 A와 B가 knows 관계가 있으며, since 속성이 2020값을 가진다는 것을 의미한다. 

다음은 cypher언어의 기본 형식을 보여준다. 
Nodes: () 
Relationships: -[:DIRTECTED]->
Pattern: ()-[]-()
         : ()-[]->()
         : ()<-[]-()

다음은 이를 이용한 질의 예이다. 
MATCH (p:Person)-[:ACTED_IN]->(m:Movie),
          (d:Person)-[:DIRECTED]->(m:Movie)
WHERE p.name = 'Tom Hanks' AND p.born = 1956
AND d.name = 'Robert Zemeckis' AND d.born = 1951
RETURN m.title, m.released

파이썬으로 그래프 데이터 관리
이 예에서는 파이썬을 이용해 그래프 데이터를 관리한다. 다음을 설치한다.
pip install neo4j

파이썬에서 드라이버를 설정한다. 
from neo4j import GraphDatabase

uri = "bolt://localhost:7687"
username = "neo4j"
password = "neo4jneo4j"
driver = GraphDatabase.driver(uri, auth=(username, password))
session = driver.session()

쿼리를 실행한다.
q = 'MATCH (n) RETURN n LIMIT 5'
nodes = session.run(q)
for node in nodes:
    print(node)

query = '''
MERGE (n:Person {name: 'Joe'})
RETURN n
'''
results, summary, keys = driver.execute_query(query, database_='neo4j')

그래프 DB RAG 처리 예시
다음은 그래프 DB를 RAG처리하는 간단한 예시를 보여준다. 이 코드는 text를 langchain의 실험적 기능을 이용해 graph로 변환하고, neo4j에 저장한 후, 이를 질의하는 순서로 실행된다. 이를 실행하기 위해선 미리 PC에 neo4j 설치 후 서버로 우선 실행해야 한다. 

text = """  
Marie Curie, born in 1867, was a Polish and naturalised-French physicist and chemist who conducted pioneering research on radioactivity.  
She was the first woman to win a Nobel Prize, the first person to win a Nobel Prize twice, and the only person to win a Nobel Prize in two scientific fields.  
Her husband, Pierre Curie, was a co-winner of her first Nobel Prize, making them the first-ever married couple to win the Nobel Prize and launching the Curie family legacy of five Nobel Prizes.  
She was, in 1906, the first woman to become a professor at the University of Paris.  
"""

# 라이브러리를 임포트한다.
from dotenv import load_dotenv  
from langchain.chains import GraphCypherQAChain  
from langchain_community.graphs import Neo4jGraph  
from langchain_core.documents import Document  
from langchain_experimental.graph_transformers import LLMGraphTransformer  
from langchain_openai import ChatOpenAI  
  
load_dotenv()  
  
# llm을 생성한다.
llm = ChatOpenAI(temperature=0, model_name="gpt-4o", openai_api_key=os.getenv("OPENAI_API_KEY")) # LLM 모델 설정. gpt-4o는 실험적 모델로, 성능이 다를 수 있음
llm_transformer = LLMGraphTransformer(llm=llm) # 실험적 모듈. 언어 모델(LLM)을 사용하여 텍스트 데이터를 그래프 데이터로 변환하는 데 사용

# neo4j에 접속하고, 텍스트를 통해 문서를 만든 후, 문서를 그래프 형식으로 변환한다.
def build_graph():
    graph = Neo4jGraph(url='bolt://localhost:7687', username='neo4j', password='neo4jneo4j') # Neo4j 그래프 데이터베이스에 연결
    documents = [Document(page_content=text)]
    graph_documents = llm_transformer.convert_to_graph_documents(documents)
    graph.add_graph_documents(graph_documents)
    return graph

# 그래프 DB에 질의한다.
def query_graph(graph, query):  
    chain = GraphCypherQAChain.from_llm(graph=graph, llm=llm, verbose=True, validate_cypher=True)  
    response = chain.invoke({"query": query})  
    return response

graph = build_graph()  

response = query_graph(graph, "In what university Marie Curie was professor and when she did it?")  
print(response)

만약, neo4j가 설치되지 않았다면, 다음 도커 명령을 통해 실행 후 시작한다.
docker run --publish=7474:7474 --publish=7687:7687 --volume=neo_data:/data --env=NEO4J_AUTH=neo4j/12345678oo --env NEO4J_PLUGINS='["apoc"]' -d neo4j

공학용 IFC 그래프로 변환
다음은 IFC파일을 그래프 데이터베이스로 변환하는 파이썬 코드이다. 
import ifcopenshell, sys, time
from py2neo import Graph, Node

def typeDict(key):
    f = ifcopenshell.file()
    value = f.create_entity(key).wrapped_data.get_attribute_names()
    return value

ifc_path = "input.ifc"  # 입력파일
nodes = []
edges = []

# 노드 설정
f = ifcopenshell.open(ifc_path)
for el in f:
    if el.is_a() == "IfcOwnerHistory":
        continue
    tid = el.id()
    cls = el.is_a()
    pairs = []
    keys = []
    try:
        keys = [x for x in el.get_info() if x not in ["type", "id", "OwnerHistory"]]
    except RuntimeError:
        pass
    for key in keys:
        val = el.get_info()[key]
        if any(hasattr(val, "is_a") and val.is_a(thisTyp)
               for thisTyp in ["IfcBoolean", "IfcLabel", "IfcText", "IfcReal"]):
            val = val.wrappedValue
        if val and type(val) is tuple and type(val[0]) in (str, bool, float, int):
            val = ",".join(str(x) for x in val)
        if type(val) not in (str, bool, float, int):
            continue
        pairs.append((key, val))
    nodes.append((tid, cls, pairs))

    for i in range(len(el)):
        try:
            el[i]
        except RuntimeError as e:
            if str(e) != "Entity not found":
                print("ID", tid, e, file=sys.stderr)
            continue
        if isinstance(el[i], ifcopenshell.entity_instance):
            if el[i].is_a() == "IfcOwnerHistory":
                continue
            if el[i].id() != 0:
                edges.append((tid, el[i].id(), typeDict(cls)[i]))
                continue
        try:
            iter(el[i])
        except TypeError:
            continue
        destinations = [x.id() for x in el[i] if isinstance(x, ifcopenshell.entity_instance)]
        for connectedTo in destinations:
            edges.append((tid, connectedTo, typeDict(cls)[i]))

if len(nodes) == 0:
    print("no nodes in file", file=sys.stderr)
    sys.exit(1)

# 그래프 데이터베이스 생성
graph = Graph(auth=('neo4j', 'neo4jneo4j'))  # http://localhost:7474
graph.delete_all()

for node in nodes:
    nId, cls, pairs = node
    one_node = Node("IfcNode", ClassName=cls, nid=nId)
    for k, v in pairs:
        one_node[k] = v
    graph.create(one_node)

# graph.run("CREATE INDEX ON :IfcNode(nid)")
print("Node creat prosess done. Take for ", time.time() - start)
print(time.strftime("%Y/%m/%d %H:%M", time.strptime(time.ctime())))

query_rel = """
MATCH (a:IfcNode)
WHERE a.nid = {:d}
MATCH (b:IfcNode)
WHERE b.nid = {:d}
CREATE (a)-[:{:s}]->(b)
"""
for (nId1, nId2, relType) in edges:
    graph.run(query_rel.format(nId1, nId2, relType))

생성 결과는 다음과 같다.
MATCH (n1)-[r]->(n2)
WHERE n1.ClassName = "IfcBuildingStorey"
RETURN r, n1, n2; 

이 기술을 응용하면, IFC의 모든 관계와 요소를 파싱해 그래프 형식 DB로 Neo4j에 저장 관리 및 검색할 수 있다. 
BIM Graph RAG 기반 agent 전문가 개발 결과

변환된 IFC 그래프 Neo4j 데이터베이스(IFC 파일부터 Room 까지 연결된 그래프구조 및 속성을 볼 수 있음)

결론
Neo4j 그래프 데이터베이스는 데이터를 노드와 엣지(관계)로 구성된 그래프 형태로 저장한다. 이러한 방식은 실제 세계의 복잡한 관계를 모델링하기에 적합하며, 네트워크, 사회 네트워크, 지도 및 추천 시스템 등 다양한 분야에서 유용하게 사용된다. 이 글을 통해 그래프 데이터를 질의하고 정보를 생성하는 서비스 개발 방법을 확인해 보았다.

레퍼런스