diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9ba3ffe --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ + +{ + "jest.autoRun": "off" +} diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..38a8ec1 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,5 @@ + +module.exports = { + testPathIgnorePatterns: ["/test/data/screenshot/"], + watchPathIgnorePatterns: ["/test/data/screenshot/"] +}; diff --git a/programs/02_build_scene_json.py b/programs/02_build_scene_json.py new file mode 100644 index 0000000..7c0cfb2 --- /dev/null +++ b/programs/02_build_scene_json.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 + +import argparse +import glob +import json +import os +import time +from collections import defaultdict + + +# ------------------------------------------------------------ + +def load_detection_json(path): + + with open(path, 'r', encoding='utf-8') as f: + data = json.load(f) + + return data + + +# ------------------------------------------------------------ + +def find_detection_files(directory, timestamp): + + pattern = os.path.join( + directory, + f'*_{timestamp}_aruco_detection.json' + ) + + files = sorted(glob.glob(pattern)) + + return files + + +# ------------------------------------------------------------ + +def build_scene(detection_files, timestamp): + + scene = { + + "schema_version": "1.0", + + "scene_timestamp": str(timestamp), + + "created_utc": time.strftime( + "%Y-%m-%dT%H:%M:%SZ", + time.gmtime() + ), + + "cameras": {}, + + "markers": {} + } + + marker_map = defaultdict(list) + + # -------------------------------------------------------- + # Read all camera detection jsons + # -------------------------------------------------------- + + for json_file in detection_files: + + data = load_detection_json(json_file) + + cam = data["camera"] + img = data["image"] + + basename = os.path.basename(json_file) + # snapshot_video1_1778819665744_aruco_detection.json + parts = basename.split('_') + video_part = parts[1] # "video1" + camera_id = video_part.replace('video', '') + + # ---------------------------------------------------- + # Camera information + # ---------------------------------------------------- + + scene["cameras"][camera_id] = { + + "camera_id": camera_id, + + "intrinsics_file": cam["intrinsics_file"], + + "camera_matrix": cam["camera_matrix"], + + "distortion_coefficients": + cam["distortion_coefficients"], + + "image": { + + "image_file": img["image_file"], + + "image_sha256": img["image_sha256"], + + "width_px": img["width_px"], + + "height_px": img["height_px"] + } + } + + # ---------------------------------------------------- + # Marker observations + # ---------------------------------------------------- + + for obs in data["observations"]: + + marker_id = str(obs["marker_id"]) + + observation = { + + "camera_id": camera_id, + + "center_px": obs["center_px"], + + "corners_px": obs["corners_px"], + + "bbox_px": obs["bbox_px"], + + "quality": obs["quality"] + } + + marker_map[marker_id].append(observation) + + # -------------------------------------------------------- + # Convert marker map + # -------------------------------------------------------- + + for marker_id, observations in marker_map.items(): + + scene["markers"][marker_id] = { + + "marker_id": int(marker_id), + + "num_observations": len(observations), + + "observations": observations + } + + return scene + + +# ------------------------------------------------------------ + +def main(): + + parser = argparse.ArgumentParser() + + parser.add_argument( + '-timestamp', + required=True, + help='Scene timestamp' + ) + + parser.add_argument( + '-dir', + default='.', + help='Directory containing detection json files' + ) + + parser.add_argument( + '-o', + '--output', + default=None + ) + + args = parser.parse_args() + + detection_files = find_detection_files( + args.dir, + args.timestamp + ) + + if len(detection_files) == 0: + + raise RuntimeError( + f'No detection json files found for timestamp ' + f'{args.timestamp}' + ) + + print('Found detection files:') + + for f in detection_files: + print(' ', f) + + scene = build_scene( + detection_files, + args.timestamp + ) + + # -------------------------------------------------------- + # Output filename + # -------------------------------------------------------- + + if args.output is None: + + out_json = os.path.join( + args.dir, + f'scene_{args.timestamp}.json' + ) + + else: + + out_json = args.output + + with open(out_json, 'w', encoding='utf-8') as f: + + json.dump(scene, f, indent=2) + + print() + print(f'Saved scene: {out_json}') + + +# ------------------------------------------------------------ + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/test/02_build_scene.test.js b/test/02_build_scene.test.js new file mode 100644 index 0000000..2394d97 --- /dev/null +++ b/test/02_build_scene.test.js @@ -0,0 +1,44 @@ +// test/02_build_scene_json.test.js +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +describe('Build Scene JSON Script', () => { + const scriptPath = 'programs/02_build_scene_json.py'; + const timestamp = 1778819665744; + const testDir = './test/data/screenShots'; + + test('should exist and be executable', () => { + expect(fs.existsSync(scriptPath)).toBe(true); + }); + + test('should build scene JSON with timestamp parameter', () => { + // Überprüfe, ob der Test-Ordner existiert + expect(fs.existsSync(testDir)).toBe(true); + + // Führe das Python-Skript mit den korrekten Parametern aus + const cmd = `python ${scriptPath} -timestamp ${timestamp} -dir ${testDir}`; + + try { + //execSync(cmd, { stdio: 'inherit' }); + //execSync(cmd, { stdio: 'pipe' }); + execSync(cmd); + console.log("TEST START", process.pid, Date.now()); + } catch (error) { + throw new Error(`Failed to build scene JSON: ${error.message}`); + } + // Überprüfe, ob die erwartete Ausgabedatei erstellt wurde + const expectedJsonFile = `./test/data/screenShots/scene_${timestamp}.json`; + expect(fs.existsSync(expectedJsonFile)).toBe(true); + + // Prüfe den Inhalt der JSON-Datei + const jsonData = JSON.parse(fs.readFileSync(expectedJsonFile, 'utf8')); + expect(jsonData).toBeDefined(); + expect(typeof jsonData).toBe('object'); + }); + + test('should handle timestamp parameter correctly', () => { + // Überprüfe, ob der Timestamp korrekt verarbeitet wird + expect(timestamp).toBe(1778819665744); + }); +}); \ No newline at end of file