class Camera:
def __init__(self, calib_json_object):
"""
Loads camera parameters from dictionary.
:param calib_json_object: the dictionary containing camera parameters.
"""
self.image_width = calib_json_object["sensorResolutionWidthPixels"]
self.image_height = calib_json_object["sensorResolutionHeightPixels"]
self.principal_point = (self.image_width/2., self.image_height/2. )
hfov = calib_json_object["horizontalFieldOfViewDegrees"]*np.pi/180.
focal = 2 * self.principal_point[0] / (2 * np.tan(hfov / 2.))
self.xfocal_length = focal
self.yfocal_length = focal
self.calibration = np.array([
[self.xfocal_length, 0, self.principal_point[0]],
[0, self.yfocal_length, self.principal_point[1]],
[0, 0, 1]
], dtype='float')
self.pan = calib_json_object['panDegrees']
self.tilt = calib_json_object['tiltDegrees']
self.roll = calib_json_object['rollDegrees']
pan = calib_json_object['panDegrees'] * np.pi / 180.
tilt = calib_json_object['tiltDegrees'] * np.pi / 180.
roll = calib_json_object['rollDegrees'] * np.pi / 180.
self.rotation = np.array([
[-np.sin(pan) * np.sin(roll) * np.cos(tilt) + np.cos(pan) * np.cos(roll),
np.sin(pan) * np.cos(roll) + np.sin(roll) * np.cos(pan) * np.cos(tilt), np.sin(roll) * np.sin(tilt)],
[-np.sin(pan) * np.cos(roll) * np.cos(tilt) - np.sin(roll) * np.cos(pan),
-np.sin(pan) * np.sin(roll) + np.cos(pan) * np.cos(roll) * np.cos(tilt), np.sin(tilt) * np.cos(roll)],
[np.sin(pan) * np.sin(tilt), -np.sin(tilt) * np.cos(pan), np.cos(tilt)]
], dtype='float')
self.rotation = np.transpose(self.pan_tilt_roll_to_orientation(pan, tilt, roll))
self.position = np.array([
calib_json_object['positionXMeters'],
calib_json_object['positionYMeters'],
calib_json_object['positionZMeters']
], dtype='float')
normalized_radial_distortion_k1 = calib_json_object['normalizedRadialDistortionCoefficients'][0]
normalized_focal = self.image_height / self.yfocal_length
self.radial_distortion_k1 = normalized_radial_distortion_k1 / (normalized_focal ** 2)
def to_json_parameters(self):
return {
"pan_degrees": self.pan,
"tilt_degrees": self.tilt,
"roll_degrees": self.roll,
"x_focal_length": self.calibration[0, 0],
"y_focal_length": self.calibration[1, 1],
"principal_point": [self.principal_point[0], self.principal_point[1]],
"position_meters": [self.position[0], self.position[1], self.position[2]],
"rotation_matrix": [[self.rotation[0, 0], self.rotation[0, 1], self.rotation[0, 2]],
[self.rotation[1, 0], self.rotation[1, 1], self.rotation[1, 2]],
[self.rotation[2, 0], self.rotation[2, 1], self.rotation[2, 2]]],
"radial_distortion": [self.radial_distortion_k1, 0., 0., 0., 0., 0.],
"tangential_distortion": [0., 0.],
"thin_prism_distortion": [0., 0., 0., 0.]
}
def get_look_at_vector(self):
return self.rotation[2]
@staticmethod
def pan_tilt_roll_to_orientation(pan, tilt, roll):
"""
Conversion from euler angles to orientation matrix.
:param pan:
:param tilt:
:param roll:
:return: orientation matrix
"""
Rpan = np.array([
[np.cos(pan), -np.sin(pan), 0],
[np.sin(pan), np.cos(pan), 0],
[0, 0, 1]])
Rroll = np.array([
[np.cos(roll), -np.sin(roll), 0],
[np.sin(roll), np.cos(roll), 0],
[0, 0, 1]])
Rtilt = np.array([
[1, 0, 0],
[0, np.cos(tilt), -np.sin(tilt)],
[0, np.sin(tilt), np.cos(tilt)]])
rotMat = np.dot(Rpan, np.dot(Rtilt, Rroll))
return rotMat
Can’t reproduce SoccerNetGS test results
Description
I’m unable to reproduce the results reported in the paper using the SoccerNetGS 2024 test set and the Jaccard@5 metric from the sn-calibration repository.
Steps to Reproduce
Build the Docker image
docker build . -t broadtrackRun the container (mounting the dataset and scripts)
Install Python and dependencies
apt-get update && apt-get install -y python3 python3-pip pip install -r /root/scripts/requirements.txtFor each video folder:
a. Initial run with camera parameters (X=0, Y=55, Z=-12)
b. Compute tripod parameters
c. Re-run with computed tripod parameters
Convert json to camera params from sn-calibration
Evaluate with sn-calibration
Observed Behavior
compute_tripod.py(to bypass the assertion) because it fails:{ "completeness": 1.0, "meanRecall": 0.44478709, "meanPrecision": 0.10040818, "meanAccuracies": 0.09859953, # Jaccard @ 5 "finalScore": 0.09859953075647354 }Expected Behavior
The reported Jaccard@5 metrics on the SoccerNetGS 2024 test set should match the values presented in the paper.
Environment
Additional Context
Any guidance on required preprocessing, parameter tuning, or code adjustments to reproduce the published results would be greatly appreciated.