I’ve a CSV file that contains a camera matrix that I need to map it to another software.
The CSV looks like that:
#name,x,y,alt,heading,pitch,roll,f,px,py,k1,k2,k3,k4,t1,t2
camera_0020.tif,2.371975426772057,-17.51430477597763,19.62992166149979,37.08279395642879,40.19497402275861,4.146620726754774e-002,15.38092716325015,-4.423256910906985e-003,-1.042365089223924e-002,-0.2682368670222757,0,0,0,0,0
camera_0001.tif,0.4550744748810949,-14.44994359438743,24.26002186520737,13.53948750224983,86.38511424956049,10.94431598131952,15.4441195498044,5.057678048976863e-003,-2.699245933956375e-003,-0.2526878098900552,0,0,0,0,0
camera_0002.tif,0.4496050184275551,-14.9937828817004,22.22046940780972,3.12604637771316,69.81988114779678,-1.222169623604721,15.40454825741273,3.841696896266326e-003,-1.178897362839387e-003,-0.2525195747759605,0,0,0,0,0
camera_0003.tif,2.355330648358418,-14.99096287469795,23.76312204743729,26.79229752774734,81.672587968005,5.891080326992676,15.52727517886148,-6.22761067917695e-003,-1.69584216411211e-003,-0.2616460998696853,0,0,0,0,0
camera_0004.tif,1.546507310932276,-14.78202534344803,26.02305388437421,-166.2798300936984,77.14608479200562,180,15.51808680061585,-9.186717826939439e-003,4.996968380160719e-003,-0.2552357879282769,0,0,0,0,0
camera_0005.tif,-0.8362467604611648,-14.66208759852425,25.96608421657756,175.1341998612653,78.12753850784819,-179.1277673270909,15.53648391119513,4.689995308220197e-003,4.690084757325292e-003,-0.2507379581692302,0,0,0,0,0
camera_0006.tif,-1.546379557427013,-14.71603274994062,23.63303629757082,-16.13718077915269,83.38291661459724,-4.431169792640662,15.52889434096247,3.902597411524155e-003,4.502849801501728e-003,-0.2560076950729412,0,0,0,0,0
camera_0007.tif,-1.719299311265238,-15.71896245277732,21.42149314612842,-13.75806496959873,61.20731561545728,3.105379357877772,15.59543541050956,1.810240362473985e-003,-1.428573281188742e-002,-0.2640401842576073,0,0,0,0,0
camera_0008.tif,0.4289012830916219,-16.19697022921764,20.28010207638949,7.297421767550315,46.45238611996521,1.074821218693282,15.38050254240411,-1.534387703374967e-003,-1.004828279608292e-002,-0.2528131441852077,0,0,0,0,0
camera_0009.tif,2.534362496988599,-15.89493737550143,21.47154386794976,28.82365628603107,61.216603018742,2.577983445550129,15.45227081764455,-8.366531811804653e-003,-8.905055663904196e-003,-0.2638915205073019,0,0,0,0,0
camera_0010.tif,4.177354614819992,-16.29711910426084,23.22895445155243,42.45754747256356,78.74237421168935,0,15.70604341681638,-1.547518954470675e-003,7.184575015295033e-003,-0.2800412069920387,0,0,0,0,0
camera_0011.tif,3.679421527707523,-15.77070011322708,25.64488088523134,-143.0655856088402,78.66585396213777,-178.2724438853675,15.70967692168096,-9.452741819514483e-003,2.015530922633477e-003,-0.2755846363018593,0,0,0,0,0
camera_0012.tif,2.4850603474096,-15.67976462602108,27.77862554155067,-151.790130619524,61.30456564279869,-177.6905949781956,15.88422175431408,-1.616709179334519e-002,1.923345641534785e-002,-0.282827670234801,0,0,0,0,0
camera_0013.tif,0.2863924886497258,-15.30863784286961,27.99275002431877,-173.6044419838188,60.64052495479823,-178.5586451879813,15.58465685308827,2.05849126647946e-003,8.945047137213329e-003,-0.2610895900288455,0,0,0,0,0
camera_0014.tif,-2.135994814022403,-15.29234633305117,27.60596193394009,161.6145614601078,64.67430766070056,-179.688848185898,15.6325592278898,1.029817913895836e-002,9.411437014047801e-003,-0.2665564174404224,0,0,0,0,0
camera_0015.tif,-3.096721569805296,-15.15646616276826,25.37002962759982,175.6302638245308,84.21982014486119,-157.6619753971617,15.56234229667276,1.379842716679913e-003,8.272432386262135e-003,-0.2635180442545396,0,0,0,0,0
camera_0016.tif,-3.55157486951623,-15.65816914675139,22.99618009298709,-31.14264691855625,75.23313870277335,3.57199292507687,15.58097778084085,1.350551712833198e-003,6.532401440099761e-003,-0.2762182189592525,0,0,0,0,0
camera_0017.tif,-3.646827851535212,-17.00988353566829,20.95534648076939,-45.12054803567322,55.43852864157912,0.5574499320729041,15.53277628971579,-1.812044776181569e-004,-9.574809986992469e-004,-0.2799706179998054,0,0,0,0,0
camera_0018.tif,-1.654124000216397,-17.27179059205472,19.60599922757982,-26.21419705513603,38.8719175326,0.3447689860024756,15.52815999265176,4.344674671185323e-003,-1.320228135445355e-002,-0.2645781768343101,0,0,0,0,0
camera_0019.tif,0.2981337848635832,-17.893181662175,19.07314382615053,4.304905491192091,27.50116966808682,-1.280446915203736,15.48520204473929,-4.351955162873873e-003,-1.350641375772765e-002,-0.2548799483972014,0,0,0,0,0
and the Expected output as Json:
{
"frames_data": [
{
"cam_model": "rectilinear",
"cx": 1287.6002479456447,
"cy": 926.6329701005438,
"fx": 1111.294795364706,
"fy": 1111.294795364706,
"radial_distortion": [
0.09643954938777596,
-0.016861986960182873,
0.0
],
"width": 2560,
"height": 1920,
"image_filename": "camera_0001",
"timestamp": 0,
"world_from_cam": [
0.9990035620585193,
-0.033809526359390864,
0.02913415387039758,
0.0,
0.03464496400756332,
0.9989885273263922,
-0.02866441590475588,
0.0,
-0.0281355551447806,
0.02964520530540873,
0.9991644270784941,
0.0,
0.004656272268761068,
-0.0009031649267875787,
0.4233474275953534,
1.0
]
},
{
"cam_model": "rectilinear",
"cx": 1284.9078104078935,
"cy": 944.3389112439777,
"fx": 1108.4039347566033,
"fy": 1108.4039347566033,
"radial_distortion": [
0.09685322319376144,
-0.017084392117429063,
0.0
],
"width": 2560,
"height": 1920,
"image_filename": "camera_0002",
"timestamp": 0,
"world_from_cam": [
0.9998511197430567,
-0.017218240683482045,
-0.0011271806958531151,
0.0,
0.0168921737082222,
0.9634034338144656,
0.2675228554383862,
0.0,
-0.0035203431603562374,
-0.2675020670990453,
0.9635508555762748,
0.0,
0.003068686129372091,
-0.15765348989006275,
0.3981930279312456,
1.0
]
},
{
"cam_model": "rectilinear",
"cx": 1264.8904710402298,
"cy": 938.732930577206,
"fx": 1110.369453028256,
"fy": 1110.369453028256,
"radial_distortion": [
0.09808324872746717,
-0.017875076565965053,
0.0
],
"width": 2560,
"height": 1920,
"image_filename": "camera_0003",
"timestamp": 0,
"world_from_cam": [
0.9550442755435179,
-0.06050177918959951,
-0.2902239936091599,
0.0,
0.07852489257471079,
0.9956143691955728,
0.05085144144890752,
0.0,
0.285874575640589,
-0.07135518597967835,
0.9556066996605446,
0.0,
0.14818947672194419,
-0.04493354298971388,
0.40072910198990613,
1.0
]
},
{
"cam_model": "rectilinear",
"cx": 1255.7545827597828,
"cy": 937.9917821797003,
"fx": 1108.6941282606042,
"fy": 1108.6941282606042,
"radial_distortion": [
0.09754013777927134,
-0.017166615929261983,
0.0
],
"width": 2560,
"height": 1920,
"image_filename": "camera_0004",
"timestamp": 0,
"world_from_cam": [
0.9852871341908113,
-0.03823392748580402,
-0.1665755984142582,
0.0,
-0.015888207065353342,
0.949943468049955,
-0.3120175834556002,
0.0,
0.1701670593102743,
0.3100734982197516,
0.9353596087214047,
0.0,
0.09224187668829188,
0.12882855330953472,
0.39683195983457,
1.0
]
},
I tried for several hours to decompose the matrices, reformat it, but I can’t get the expected output at all,
Here is my trial using python:
import numpy as np
import pandas as pd
from scipy.spatial.transform import Rotation
import json
def convert_to_radians(degrees):
"""Convert degrees to radians."""
return np.deg2rad(degrees)
def parse_realview_csv(csv_path):
"""Load RealView CSV file and return as a pandas DataFrame."""
df = pd.read_csv(csv_path)
return df
def convert_realview_to_tinynerf(csv_path, output_json_path, num_cameras):
# Load the CSV data
df = parse_realview_csv(csv_path)
output_data = {'frames_data': []}
cam_num = 0
for index, row in df.iterrows():
if cam_num >= num_cameras:
break
# Extract camera parameters from CSV
image_filename = row['#name'] # Adjusted column name with leading '#' as per CSV format
x, y, z = row['x'], row['y'], row['alt']
heading = convert_to_radians(row['heading'])
pitch = convert_to_radians(row['pitch'])
roll = convert_to_radians(row['roll'])
f = row['f']
cx, cy = row['px'], row['py']
radial_distortion = [row['k1'], row['k2'], row['k3']]
width, height = 2560, 1920 # Assuming fixed width and height (adjust based on your data)
# Convert position and orientation to a rotation matrix
position = np.array([y, x, z])
rotation = Rotation.from_euler('yxz', [heading, pitch, roll])
R_mat = rotation.as_matrix()
t = position[:, np.newaxis]
extrinsics = np.concatenate((R_mat, np.dot(R_mat, t)), axis=1)
cam_from_world = np.vstack((extrinsics, np.array([0, 0, 0, 1])))
world_from_cam = np.linalg.inv(cam_from_world)
# Adjust coordinate system to match TinyNerf
mirror_and_flip = np.array([
[1, 0, 0, 0],
[0, -1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
#world_from_cam = np.dot(mirror_and_flip, world_from_cam)
# world_from_cam[:3, 1] = -world_from_cam[:3, 1]
# Prepare the output data for TinyNerf
output_data['frames_data'].append({
"cam_model": "rectilinear",
"cx": cx,
"cy": cy,
"fx": f,
"fy": f,
"radial_distortion": radial_distortion,
"width": width,
"height": height,
"image_filename": image_filename,
"timestamp": 0,
"world_from_cam": world_from_cam.flatten(order='F').tolist(),
})
cam_num += 1
# Save the output data to a JSON file
with open(output_json_path, 'w') as output_file:
json.dump(output_data, output_file, indent=4)
convert_realview_to_tinynerf("input_realitycapture.csv", r"C:UsersxgameOneDriveDesktopcamerasourcetinynerf_output.json", 20)