File size: 4,273 Bytes
37ee115 cd6697e 37ee115 cd6697e 37ee115 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #!/usr/bin/env python3
"""
Build pair index from 3DMatch evaluation logs
"""
import json
import sys
import os
from pathlib import Path
from collections import defaultdict
def parse_gt_log(log_file):
"""Parse gt.log evaluation file
Format:
source_id target_id ...
r11 r12 r13 tx
r21 r22 r23 ty
r31 r32 r33 tz
0 0 0 1
"""
pairs = []
with open(log_file, 'r') as f:
lines = [line.strip() for line in f.readlines() if line.strip()]
i = 0
while i < len(lines):
# Parse header line
header = lines[i].split()
if len(header) < 2:
i += 1
continue
try:
source_id = int(header[0])
target_id = int(header[1])
except (ValueError, IndexError):
i += 1
continue
# Parse 4x4 transformation matrix
if i + 4 >= len(lines):
break
try:
matrix = []
for j in range(1, 5):
row = [float(x) for x in lines[i + j].split()]
if len(row) != 4:
raise ValueError(f"Invalid row: {lines[i + j]}")
matrix.append(row)
pairs.append({
'source_id': source_id,
'target_id': target_id,
'gt_transform': matrix
})
i += 5
except (ValueError, IndexError) as e:
print(f"Warning: Failed to parse transformation matrix at line {i}: {e}")
i += 1
return pairs
def find_ply_file(scene_dir, fragment_id):
"""Find cloud_bin_<id>.ply file"""
pattern = f"cloud_bin_{fragment_id}.ply"
for root, dirs, files in os.walk(scene_dir):
if pattern in files:
return str(Path(root) / pattern)
return None
def build_pair_index(raw_root, output_file):
"""Build pair index for redkitchen scene"""
raw_root = Path(raw_root)
pairs = []
scene_id = '7-scenes-redkitchen'
scene_dir = raw_root / scene_id
eval_dir = raw_root / f'{scene_id}-evaluation'
print(f"Processing: {scene_id}")
if not scene_dir.exists():
print(f"Error: Scene folder not found: {scene_dir}")
return False
if not eval_dir.exists():
print(f"Error: Evaluation folder not found: {eval_dir}")
return False
# Find gt.log or any .log file
log_file = None
if (eval_dir / 'gt.log').exists():
log_file = eval_dir / 'gt.log'
else:
for f in eval_dir.rglob('*.log'):
log_file = f
break
if not log_file:
print(f"Error: No .log file found in {eval_dir}")
return False
print(f"Parsing: {log_file.relative_to(raw_root)}")
scene_pairs = parse_gt_log(log_file)
# Validate and add source/target paths
added = 0
for pair in scene_pairs:
source_file = find_ply_file(scene_dir, pair['source_id'])
target_file = find_ply_file(scene_dir, pair['target_id'])
if source_file and target_file and pair['source_id'] != pair['target_id']:
pair['scene_id'] = scene_id
pair['source_path'] = source_file
pair['target_path'] = target_file
pairs.append(pair)
added += 1
else:
if not source_file:
print(f" Warning: Source file not found for id {pair['source_id']}")
if not target_file:
print(f" Warning: Target file not found for id {pair['target_id']}")
print(f"Added {added} pairs from {len(scene_pairs)} total in log")
# Save index
output_file = Path(output_file)
output_file.parent.mkdir(parents=True, exist_ok=True)
with open(output_file, 'w') as f:
json.dump(pairs, f, indent=2)
print(f"\nPair index saved: {output_file}")
print(f"Total pairs: {len(pairs)}")
return len(pairs) > 0
if __name__ == '__main__':
raw_root = sys.argv[1] if len(sys.argv) > 1 else 'data/raw/3dmatch'
output_file = sys.argv[2] if len(sys.argv) > 2 else 'data/processed/pair_index.json'
success = build_pair_index(raw_root, output_file)
sys.exit(0 if success else 1)
|