メインコンテンツまでスキップ

再構築品質レポート

概要

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. 最適化の提案:レポートメトリクスに基づいてキャプチャと処理パラメータを調整

ヒント:品質レポートは、再構築ワークフローを評価および最適化するための重要なツールです。自動化されたワークフローに統合することをお勧めします。