From 12b7aac1a0de9dc61eb8fa499842924e7a94722a Mon Sep 17 00:00:00 2001
From: Alexander Smorkalov <alexander.smorkalov@xperience.ai>
Date: Wed, 14 Feb 2024 15:17:01 +0300
Subject: [PATCH] Dump board poses human-readable and machine-readable format.

---
 .../calibration_generator.py                   | 18 ++++++++++++++++--
 apps/python-calibration-generator/utils.py     | 14 ++++++++------
 2 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/apps/python-calibration-generator/calibration_generator.py b/apps/python-calibration-generator/calibration_generator.py
index e76cb6c788..81b465ef36 100644
--- a/apps/python-calibration-generator/calibration_generator.py
+++ b/apps/python-calibration-generator/calibration_generator.py
@@ -2,6 +2,11 @@
 # It is subject to the license terms in the LICENSE file found in the top-level directory
 # of this distribution and at http://opencv.org/license.html.
 
+# The script generates synthetic data for multi-camera calibration assessment
+# Input: cameras configuration. See config_cv_test.yaml
+# Output: generated object points (3d), image points (2d) for calibration and
+#         board poses ground truth (R, t) for check
+
 import argparse
 import numpy as np
 import math
@@ -10,6 +15,8 @@ from drawer import animation2D, animation3D
 from utils import RandGen, insideImage, eul2rot, saveKDRT, areAllInsideImage, insideImageMask, projectCamera, export2JSON, writeMatrix
 from pathlib import Path
 from board import CheckerBoard
+import os
+import json
 
 class Camera:
     def __init__(self, idx, img_width, img_height, fx_limit, euler_limit, t_limit, is_fisheye, fy_deviation=None, skew=None,
@@ -337,8 +344,15 @@ def main(cfg_name, save_folder):
 
         file = open(save_folder + "gt.txt", "a")
         for i in range(R_used.shape[0]):
-            writeMatrix(file, R_used[i])
-            writeMatrix(file, t_used[i])
+            writeMatrix(file, 'R_%d' % i, R_used[i])
+            writeMatrix(file, 'T_%d' % i, t_used[i])
+
+        poses = dict()
+        for idx in range(len(R_used)):
+            poses['frame_%d' % idx] = {'R': R_used[idx].tolist(), 'T': t_used[idx].tolist()}
+
+        with open(os.path.join(save_folder, "gt_poses.json"), 'wt') as gt:
+            gt.write(json.dumps(poses, indent=4))
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser()
diff --git a/apps/python-calibration-generator/utils.py b/apps/python-calibration-generator/utils.py
index 69f2d78424..80a74c2bfd 100644
--- a/apps/python-calibration-generator/utils.py
+++ b/apps/python-calibration-generator/utils.py
@@ -46,18 +46,20 @@ def insideImage(pts, w, h):
 def areAllInsideImage(pts, w, h):
     return insideImageMask(pts, w, h).all()
 
-def writeMatrix(file, M):
+def writeMatrix(file, label, M):
+    file.write("%s:\n" % label)
     for i in range(M.shape[0]):
         for j in range(M.shape[1]):
             file.write(str(M[i,j]) + ('\n' if j == M.shape[1]-1 else ' '))
 
 def saveKDRT(cameras, fname):
     file = open(fname, 'w')
-    for cam in cameras:
-        writeMatrix(file, cam.K)
-        writeMatrix(file, cam.distortion)
-        writeMatrix(file, cam.R)
-        writeMatrix(file, cam.t)
+    for idx, cam in enumerate(cameras):
+        file.write("camera_%d:\n" % idx)
+        writeMatrix(file, "K", cam.K)
+        writeMatrix(file, "distortion", cam.distortion)
+        writeMatrix(file, "R", cam.R)
+        writeMatrix(file, "T", cam.t)
 
 def export2JSON(pattern_points, image_points, image_sizes, is_fisheye, json_file):
     image_points = image_points.transpose(1,0,3,2)