본문으로 건너뛰기

재구성 품질 보고서

개요

MipMapEngine SDK는 재구성 작업 완료 후 장치 정보, 재구성 효율성, 매개변수 설정 및 결과 품질을 포함하는 상세한 품질 보고서를 생성합니다. 보고서는 JSON 형식으로 report/report.json 파일에 저장되며, 빠른 미리보기를 위한 시각화 썸네일도 함께 제공됩니다.

보고서 구조

1. 장치 정보

재구성에 사용된 하드웨어 구성을 기록합니다:

필드타입설명
cpu_namestringCPU 이름
gpu_namestringGPU 이름

예시:

{
"cpu_name": "Intel(R) Core(TM) i9-10900K CPU @ 3.70GHz",
"gpu_name": "NVIDIA GeForce RTX 3080"
}

2. 재구성 효율성

각 단계의 처리 시간을 기록합니다(분 단위):

필드타입설명
feature_extraction_timefloat특징 추출 시간
feature_match_timefloat특징 매칭 시간
sfm_timefloat번들 조정 시간
at_timefloat총 AT 시간
reconstruction_timefloat총 재구성 시간(AT 제외)

예시:

{
"feature_extraction_time": 12.5,
"feature_match_time": 8.3,
"sfm_time": 15.2,
"at_time": 36.0,
"reconstruction_time": 48.6
}

3. 재구성 매개변수

작업 입력 매개변수 및 구성을 기록합니다:

카메라 매개변수

"initial_camera_parameters": [
{
"camera_name": "DJI_FC6310",
"width": 5472,
"height": 3648,
"id": 0,
"parameters": [3850.5, 2736, 1824, -0.02, 0.05, 0.001, -0.001, 0.01]
}
]

매개변수 배열 순서: [f, cx, cy, k1, k2, p1, p2, k3]

  • f: 초점 거리
  • cx, cy: 주점 좌표
  • k1, k2, k3: 방사 왜곡 계수
  • p1, p2: 접선 왜곡 계수

기타 매개변수

필드타입설명
input_camera_countint입력 카메라 수
input_image_countint입력 이미지 수
reconstruction_levelint재구성 레벨 (1=초고, 2=고, 3=중)
production_typestring제품 유형
max_ramfloat최대 RAM 사용량 (GB)

좌표계 정보

"production_cs_3d": {
"epsg_code": 4326,
"origin_offset": [0, 0, 0],
"type": 2
}

좌표계 유형:

  • 0: LocalENU (로컬 동-북-상)
  • 1: Local (로컬 좌표계)
  • 2: Geodetic (측지 좌표계)
  • 3: Projected (투영 좌표계)
  • 4: ECEF (지구 중심-지구 고정)

4. 재구성 결과

AT 후 카메라 매개변수

최적화된 카메라 내부 매개변수를 기록합니다:

"AT_camera_parameters": [
{
"camera_name": "DJI_FC6310",
"width": 5472,
"height": 3648,
"id": 0,
"parameters": [3852.1, 2735.8, 1823.6, -0.019, 0.048, 0.0008, -0.0009, 0.009]
}
]

이미지 위치 차이

각 이미지의 위치 최적화를 기록합니다:

"image_pos_diff": [
{
"id": 0,
"pos_diff": 0.125
},
{
"id": 1,
"pos_diff": 0.087
}
]

품질 메트릭

필드타입설명
removed_image_countintAT 후 제거된 이미지
residual_rmsefloat이미지 포인트 잔차 RMSE
tie_point_countint타이 포인트 수
scene_areafloat장면 면적 (제곱미터)
scene_gsdfloat지상 샘플 거리 (미터)
flight_heightfloat비행 높이 (미터)
block_countint재구성 블록 수

5. 기타 정보

필드타입설명
sdk_versionstringSDK 버전

시각화 썸네일

보고서 디렉토리의 thumbnail 폴더에는 다음 시각화 파일이 포함됩니다:

1. 카메라 잔차 플롯

camera_{id}_residual.png - 24비트 컬러 이미지

  • 좋은 보정 결과: 잔차가 위치 전반에 걸쳐 비슷한 크기이며 무작위 방향을 보임
  • 나쁜 보정 결과: 큰 잔차와 명확한 방향 패턴을 보임

큰 잔차가 반드시 전체적인 정확도가 낮다는 것을 의미하지는 않습니다. 이것은 카메라 내부 정확도만을 반영합니다. 최종 정확도는 체크포인트 좌표 정확도와 모델 품질을 종합적으로 고려해야 합니다.

2. 중첩 지도

overlap_map.png - 8비트 그레이스케일 이미지

  • 픽셀 값 범위: 0-255
  • 중첩 분포를 표시하기 위해 컬러 맵으로 렌더링 가능
  • 비행 경로 설계 및 이미지 커버리지 품질 평가에 사용

3. 측량 영역 썸네일

rgb_thumbnail.jpg - 32비트 컬러 이미지

  • 프로젝트의 빠른 미리보기용
  • 측량 영역 범위와 재구성 결과를 표시

보고서 해석 예시

전체 보고서 예시

{
"cpu_name": "Intel(R) Core(TM) i9-10900K CPU @ 3.70GHz",
"gpu_name": "NVIDIA GeForce RTX 3080",
"feature_extraction_time": 12.5,
"feature_match_time": 8.3,
"sfm_time": 15.2,
"at_time": 36.0,
"reconstruction_time": 48.6,
"initial_camera_parameters": [{
"camera_name": "DJI_FC6310",
"width": 5472,
"height": 3648,
"id": 0,
"parameters": [3850.5, 2736, 1824, -0.02, 0.05, 0.001, -0.001, 0.01]
}],
"input_camera_count": 1,
"input_image_count": 156,
"reconstruction_level": 2,
"production_type": "all",
"production_cs_3d": {
"epsg_code": 4326,
"origin_offset": [0, 0, 0],
"type": 2
},
"production_cs_2d": {
"epsg_code": 3857,
"origin_offset": [0, 0, 0],
"type": 3
},
"max_ram": 28.5,
"AT_camera_parameters": [{
"camera_name": "DJI_FC6310",
"width": 5472,
"height": 3648,
"id": 0,
"parameters": [3852.1, 2735.8, 1823.6, -0.019, 0.048, 0.0008, -0.0009, 0.009]
}],
"removed_image_count": 2,
"residual_rmse": 0.68,
"tie_point_count": 125840,
"scene_area": 850000.0,
"scene_gsd": 0.025,
"flight_height": 120.5,
"block_count": 1,
"sdk_version": "3.0.1"
}

품질 평가 메트릭

우수한 품질 기준

  • residual_rmse < 1.0 픽셀
  • removed_image_count / input_image_count < 5%
  • tie_point_count > 10000
  • 평균 위치 차이 < 0.5 미터

주의가 필요한 상황

  • residual_rmse > 2.0 픽셀: 가능한 체계적 오류
  • removed_image_count > 10%: 이미지 품질 또는 중첩 문제
  • tie_point_count < 5000: 불충분한 특징점, 정확도에 영향

보고서 분석 도구

Python 분석 예시

import json
import numpy as np

def analyze_quality_report(report_path):
with open(report_path, 'r', encoding='utf-8') as f:
report = json.load(f)

# 효율성 메트릭 계산
total_time = report['at_time'] + report['reconstruction_time']
images_per_minute = report['input_image_count'] / total_time

# 품질 메트릭 계산
removal_rate = report['removed_image_count'] / report['input_image_count']
avg_pos_diff = np.mean([item['pos_diff'] for item in report['image_pos_diff']])

# 분석 보고서 생성
analysis = {
'efficiency': {
'total_time_minutes': total_time,
'images_per_minute': images_per_minute,
'area_per_hour': report['scene_area'] / (total_time / 60)
},
'quality': {
'residual_rmse': report['residual_rmse'],
'removal_rate_percent': removal_rate * 100,
'avg_position_diff_meters': avg_pos_diff,
'tie_points_per_image': report['tie_point_count'] / report['input_image_count']
},
'scale': {
'area_sqm': report['scene_area'],
'gsd_cm': report['scene_gsd'] * 100,
'flight_height_m': report['flight_height']
}
}

return analysis

# 사용 예시
analysis = analyze_quality_report('report/report.json')
print(f"처리 효율성: {analysis['efficiency']['images_per_minute']:.1f} 이미지/분")
print(f"평균 잔차: {analysis['quality']['residual_rmse']:.2f} 픽셀")
print(f"지상 해상도: {analysis['scale']['gsd_cm']:.1f} cm")

품질 보고서 시각화

import matplotlib.pyplot as plt
from PIL import Image

def visualize_quality_report(report_dir):
# 보고서 데이터 읽기
with open(f'{report_dir}/report.json', 'r') as f:
report = json.load(f)

# 차트 생성
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# 1. 시간 분포 원형 차트
times = [
report['feature_extraction_time'],
report['feature_match_time'],
report['sfm_time'],
report['reconstruction_time']
]
labels = ['특징 추출', '특징 매칭', '번들 조정', '3D 재구성']
axes[0, 0].pie(times, labels=labels, autopct='%1.1f%%')
axes[0, 0].set_title('처리 시간 분포')

# 2. 위치 차이 히스토그램
pos_diffs = [item['pos_diff'] for item in report['image_pos_diff']]
axes[0, 1].hist(pos_diffs, bins=20, edgecolor='black')
axes[0, 1].set_xlabel('위치 차이 (미터)')
axes[0, 1].set_ylabel('이미지 수')
axes[0, 1].set_title('이미지 위치 최적화 분포')

# 3. 중첩 지도
overlap_img = Image.open(f'{report_dir}/thumbnail/overlap_map.png')
axes[1, 0].imshow(overlap_img, cmap='jet')
axes[1, 0].set_title('이미지 중첩 분포')
axes[1, 0].axis('off')

# 4. 주요 메트릭 텍스트
metrics_text = f"""
입력 이미지: {report['input_image_count']}
제거된 이미지: {report['removed_image_count']}
잔차 RMSE: {report['residual_rmse']:.2f} px
타이 포인트: {report['tie_point_count']:,}
장면 면적: {report['scene_area']/10000:.1f} 헥타르
지상 해상도: {report['scene_gsd']*100:.1f} cm
"""
axes[1, 1].text(0.1, 0.5, metrics_text, fontsize=12,
verticalalignment='center', family='monospace')
axes[1, 1].set_title('주요 품질 메트릭')
axes[1, 1].axis('off')

plt.tight_layout()
plt.savefig('quality_report_summary.png', dpi=150)
plt.show()

자동 품질 검사

품질 임계값 구성

QUALITY_THRESHOLDS = {
'excellent': {
'residual_rmse': 0.5,
'removal_rate': 0.02,
'tie_points_per_image': 1000,
'pos_diff_avg': 0.1
},
'good': {
'residual_rmse': 1.0,
'removal_rate': 0.05,
'tie_points_per_image': 500,
'pos_diff_avg': 0.5
},
'acceptable': {
'residual_rmse': 2.0,
'removal_rate': 0.10,
'tie_points_per_image': 200,
'pos_diff_avg': 1.0
}
}

def assess_quality(report):
"""재구성 품질 수준을 자동으로 평가"""

# 메트릭 계산
removal_rate = report['removed_image_count'] / report['input_image_count']
tie_points_per_image = report['tie_point_count'] / report['input_image_count']
pos_diff_avg = np.mean([item['pos_diff'] for item in report['image_pos_diff']])

# 수준 평가
for level, thresholds in QUALITY_THRESHOLDS.items():
if (report['residual_rmse'] <= thresholds['residual_rmse'] and
removal_rate <= thresholds['removal_rate'] and
tie_points_per_image >= thresholds['tie_points_per_image'] and
pos_diff_avg <= thresholds['pos_diff_avg']):
return level

return 'poor'

보고서 통합 애플리케이션

배치 처리 품질 모니터링

def batch_quality_monitor(project_dirs):
"""배치 프로젝트 품질 모니터링"""

results = []

for project_dir in project_dirs:
report_path = os.path.join(project_dir, 'report/report.json')

if os.path.exists(report_path):
with open(report_path, 'r') as f:
report = json.load(f)

quality_level = assess_quality(report)

results.append({
'project': project_dir,
'images': report['input_image_count'],
'area': report['scene_area'],
'gsd': report['scene_gsd'],
'rmse': report['residual_rmse'],
'quality': quality_level,
'time': report['at_time'] + report['reconstruction_time']
})

# 요약 보고서 생성
df = pd.DataFrame(results)
df.to_csv('batch_quality_report.csv', index=False)

# 통계
print(f"전체 프로젝트: {len(results)}")
print(f"우수: {len(df[df['quality'] == 'excellent'])}")
print(f"양호: {len(df[df['quality'] == 'good'])}")
print(f"허용 가능: {len(df[df['quality'] == 'acceptable'])}")
print(f"불량: {len(df[df['quality'] == 'poor'])}")

return df

모범 사례

  1. 정기적인 보고서 확인: 각 재구성 후 품질 메트릭 검토
  2. 기준선 설정: 일반적인 프로젝트의 품질 메트릭을 참조로 기록
  3. 이상 경고: 비정상적인 메트릭을 감지하는 자동화된 스크립트 설정
  4. 추세 분석: 시간 경과에 따른 품질 메트릭 추세 추적
  5. 최적화 제안: 보고서 메트릭에 따라 캡처 및 처리 매개변수 조정

팁: 품질 보고서는 재구성 워크플로우를 평가하고 최적화하는 중요한 도구입니다. 자동화된 워크플로우에 통합하는 것이 좋습니다.