Skip to content

Calibration

Camera calibration data models.

CameraIntrinsics(fx=1.0, fy=1.0, cx=0.0, cy=0.0, s=0.0) dataclass

Camera intrinsics.

Attributes:

Name Type Description
fx float

\(f_x\): focal length in x.

fy float

\(f_y\): focal length in y.

cx float

\(c_x\): principal point in x.

cy float

\(c_y\): principal point in y.

s float

\(s\): skew.

Examples:

Normalized image coordinates:

>>> intrinsics = CameraIntrinsics()
>>> intrinsics.to_matrix()
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
>>> intrinsics = CameraIntrinsics(fx=1.75, fy=1.35, cx=319.7, cy=241.2, s=0)
>>> intrinsics.to_matrix()
array([[  1.75,   0.  , 319.7 ],
       [  0.  ,   1.35, 241.2 ],
       [  0.  ,   0.  ,   1.  ]])

Initialize from a matrix (\(\texttt{matrix} = I\)):

>>> matrix = np.eye(3)
>>> CameraIntrinsics.from_matrix(matrix)
CameraIntrinsics(fx=np.float64(1.0), fy=np.float64(1.0), cx=np.float64(0.0), cy=np.float64(0.0), s=np.float64(0.0))

from_matrix(matrix) classmethod

Create a camera intrinsics object from a camera matrix.

Parameters:

Name Type Description Default
matrix ndarray

Camera matrix as a 3x3 numpy array.

required

Returns:

Type Description
CameraIntrinsics

Camera intrinsics object.

Source code in src/compas_camcal/models/calibration.py
74
75
76
77
78
79
80
81
82
83
84
85
86
87
@classmethod
def from_matrix(cls, matrix: np.ndarray) -> "CameraIntrinsics":
    """
    Create a camera intrinsics object from a camera matrix.

    Args:
        matrix: Camera matrix as a 3x3 numpy array.

    Returns:
        Camera intrinsics object.
    """
    return cls(
        fx=matrix[0, 0], fy=matrix[1, 1], cx=matrix[0, 2], cy=matrix[1, 2], s=matrix[0, 1]
    )

to_matrix()

Make a camera intrinsic matrix of the form:

\[ \left[\begin{array}{ccc} f_x & s & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{array}\right] \]

Returns:

Type Description
ndarray

Camera matrix as a 3x3 numpy array (float64).

Source code in src/compas_camcal/models/calibration.py
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
def to_matrix(self) -> np.ndarray:
    """
    Make a camera intrinsic matrix of the form:

    $$
    \\left[\\begin{array}{ccc}
    f_x & s & c_x \\\\
    0 & f_y & c_y \\\\
    0 & 0 & 1
    \\end{array}\\right]
    $$

    Returns:
        Camera matrix as a 3x3 numpy array (float64).
    """
    return np.array(
        [[self.fx, self.s, self.cx], [0, self.fy, self.cy], [0, 0, 1]], dtype=np.float64
    )

DistortionCoefficients(k1=0.0, k2=0.0, p1=0.0, p2=0.0, k3=0.0, k4=0.0, k5=0.0, k6=0.0, s1=0.0, s2=0.0, s3=0.0, s4=0.0, tx=0.0, ty=0.0) dataclass

Bases: DistortionCoefficientsBase

Camera distortion coefficients.

For more information, see cv::calibrateCamera and cv::initUndistortRectifyMap.

Attributes:

Name Type Description
k1 float

\(k_1\): radial distortion coefficient 1.

k2 float

\(k_2\): radial distortion coefficient 2.

p1 float

\(p_1\): tangential distortion coefficient 1.

p2 float

\(p_2\): tangential distortion coefficient 2.

k3 float

\(k_3\): radial distortion coefficient 3.

k4 float

\(k_4\): radial distortion coefficient 4 (rational model).

k5 float

\(k_5\): radial distortion coefficient 5 (rational model).

k6 float

\(k_6\): radial distortion coefficient 6 (rational model).

s1 float

\(s_1\): thin prism distortion coefficient 1.

s2 float

\(s_2\): thin prism distortion coefficient 2.

s3 float

\(s_3\): thin prism distortion coefficient 3.

s4 float

\(s_4\): thin prism distortion coefficient 4.

tx float

\(\tau_x\): tilted distortion coefficient 1.

ty float

\(\tau_y\): tilted distortion coefficient 2.

Examples:

Using \(k_{1-2}, p_{1-2}\) :

>>> coeffs = DistortionCoefficients(k1=1, k2=2, p1=3, p2=4)
>>> coeffs.to_vector()
array([[1.],
       [2.],
       [3.],
       [4.]])

Using \(k_{1-6}, p_{1-2}, s_{1-4}, \tau_x, \tau_y\) :

>>> coeffs = DistortionCoefficients(k1=1, k2=2, tx=3, ty=4)
>>> coeffs.to_vector()
array([[1.],
       [2.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [3.],
       [4.]])

Initializing from a vector:

>>> vec = np.array([1, 2, 3, 4])
>>> DistortionCoefficients.from_vector(vec)
DistortionCoefficients(k1=np.int64(1), k2=np.int64(2), p1=np.int64(3), p2=np.int64(4), k3=0.0, k4=0.0, k5=0.0, k6=0.0, s1=0.0, s2=0.0, s3=0.0, s4=0.0, tx=0.0, ty=0.0)

from_vector(vector) classmethod

Create a distortion coefficients object from a distortion coefficients vector.

Parameters:

Name Type Description Default
vector ndarray

Distortion coefficients as a vector.

required

Returns:

Type Description
DistortionCoefficients

Distortion coefficients object.

Source code in src/compas_camcal/models/calibration.py
255
256
257
258
259
260
261
262
263
264
265
266
@classmethod
def from_vector(cls, vector: np.ndarray) -> "DistortionCoefficients":
    """
    Create a distortion coefficients object from a distortion coefficients vector.

    Args:
        vector: Distortion coefficients as a vector.

    Returns:
        Distortion coefficients object.
    """
    return cls(*vector.ravel())

to_vector()

Make a column vector of distortion coefficients.

Depending on the distortion model, the vector will have a different length:

  • 4: 2 radial + 2 tangential
  • 5: 3 radial + 2 tangential
  • 8: 5 radial + 2 tangential
  • 12: 5 radial + 2 tangential + 4 thin prism
  • 14: 5 radial + 2 tangential + 4 thin prism + 2 tilted
\[ \left[\begin{array}{cccc:c:ccc:cccc:cccc} k_1 & k_2 & p_1 & p_2 & k_3 & k_4 & k_5 & k_6 & s_1 & s_2 & s_3 & s_4 & \tau_x & \tau_y \end{array}\right]^\top \]

Returns:

Type Description
ndarray

Distortion coefficients as a column vector (float64).

Source code in src/compas_camcal/models/calibration.py
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
def to_vector(self) -> np.ndarray:
    """
    Make a column vector of distortion coefficients.

    Depending on the distortion model, the vector will have a different length:

    - **4**: 2 radial + 2 tangential
    - **5**: 3 radial + 2 tangential
    - **8**: 5 radial + 2 tangential
    - **12**: 5 radial + 2 tangential + 4 thin prism
    - **14**: 5 radial + 2 tangential + 4 thin prism + 2 tilted

    $$
    \\left[\\begin{array}{cccc:c:ccc:cccc:cccc}
    k_1 & k_2 & p_1 & p_2 & k_3 & k_4 & k_5 & k_6 & s_1 & s_2 & s_3 & s_4 & \\tau_x & \\tau_y
    \\end{array}\\right]^\\top
    $$

    Returns:
        Distortion coefficients as a column vector (float64).
    """
    # Check which distortion model is used
    use_k3 = self.k3 != 0.0
    use_k4_6 = self.k4 != 0.0 or self.k5 != 0.0 or self.k6 != 0.0
    use_s1_4 = self.s1 != 0.0 or self.s2 != 0.0 or self.s3 != 0.0 or self.s4 != 0.0
    use_tx_ty = self.tx != 0.0 or self.ty != 0.0

    # Collect appropriate coefficients
    values = [self.k1, self.k2, self.p1, self.p2]
    if use_tx_ty:  # Tilted, include everything
        values = values + [
            self.k3,
            self.k4,
            self.k5,
            self.k6,
            self.s1,
            self.s2,
            self.s3,
            self.s4,
            self.tx,
            self.ty,
        ]
    elif use_s1_4:  # Thin prism, include up to s4
        values = values + [
            self.k3,
            self.k4,
            self.k5,
            self.k6,
            self.s1,
            self.s2,
            self.s3,
            self.s4,
        ]
    elif use_k4_6:  # Rational, include up to k6
        values = values + [self.k3, self.k4, self.k5, self.k6]
    elif use_k3:  # Include k3
        values = values + [self.k3]

    # Compose column vector
    return np.array([values], dtype=np.float64).T

DistortionCoefficientsBase() dataclass

Bases: ABC

Abstract class for camera distortion coefficient vector models.

from_vector(vector) abstractmethod classmethod

Create a distortion coefficients object from a vector.

Parameters:

Name Type Description Default
vector ndarray

Vector of distortion coefficients.

required

Returns:

Type Description
DistortionCoefficientsBase

Distortion coefficients object.

Source code in src/compas_camcal/models/calibration.py
107
108
109
110
111
112
113
114
115
116
117
118
119
@classmethod
@abstractmethod
def from_vector(cls, vector: np.ndarray) -> "DistortionCoefficientsBase":
    """
    Create a distortion coefficients object from a vector.

    Args:
        vector: Vector of distortion coefficients.

    Returns:
        Distortion coefficients object.
    """
    raise NotImplementedError

to_vector() abstractmethod

Convert the distortion coefficients to a vector.

Returns:

Type Description
ndarray

Vector of distortion coefficients.

Source code in src/compas_camcal/models/calibration.py
 97
 98
 99
100
101
102
103
104
105
@abstractmethod
def to_vector(self) -> np.ndarray:
    """
    Convert the distortion coefficients to a vector.

    Returns:
        Vector of distortion coefficients.
    """
    raise NotImplementedError

FisheyeDistortionCoefficients(k1=0.0, k2=0.0, k3=0.0, k4=0.0) dataclass

Bases: DistortionCoefficientsBase

Fisheye distortion coefficients. For more information, see cv::fisheye::calibrate and cv::fisheye::initUndistortRectifyMap.

Parameters:

Name Type Description Default
k1 float

\(k_1\): radial distortion coefficient 1.

0.0
k2 float

\(k_2\): radial distortion coefficient 2.

0.0
k3 float

\(k_3\): radial distortion coefficient 3.

0.0
k4 float

\(k_4\): radial distortion coefficient 4.

0.0

Examples:

>>> coeffs = FisheyeDistortionCoefficients(k1=1, k2=2, k3=3, k4=4)
>>> coeffs.to_vector()
array([[1.],
       [2.],
       [3.],
       [4.]])

Initializing from a vector:

>>> vec = np.array([1, 2, 3, 4])
>>> FisheyeDistortionCoefficients.from_vector(vec)
FisheyeDistortionCoefficients(k1=np.int64(1), k2=np.int64(2), k3=np.int64(3), k4=np.int64(4))

from_vector(vector) classmethod

Create a distortion coefficients object from a distortion coefficients vector.

Parameters:

Name Type Description Default
vector ndarray

Distortion coefficients as a vector.

required

Returns:

Type Description
FisheyeDistortionCoefficients

Distortion coefficients object.

Source code in src/compas_camcal/models/calibration.py
315
316
317
318
319
320
321
322
323
324
325
326
@classmethod
def from_vector(cls, vector: np.ndarray) -> "FisheyeDistortionCoefficients":
    """
    Create a distortion coefficients object from a distortion coefficients vector.

    Args:
        vector: Distortion coefficients as a vector.

    Returns:
        Distortion coefficients object.
    """
    return cls(*vector.ravel())

to_vector()

Make a column vector of distortion coefficients.

\[ \left[\begin{array}{cccc} k_1 & k_2 & k_3 & k_4 \end{array}\right]^\top \]

Returns:

Type Description
ndarray

Distortion coefficients as a column vector (float64).

Source code in src/compas_camcal/models/calibration.py
300
301
302
303
304
305
306
307
308
309
310
311
312
313
def to_vector(self) -> np.ndarray:
    """
    Make a column vector of distortion coefficients.

    $$
    \\left[\\begin{array}{cccc}
    k_1 & k_2 & k_3 & k_4
    \\end{array}\\right]^\\top
    $$

    Returns:
        Distortion coefficients as a column vector (float64).
    """
    return np.array([[self.k1, self.k2, self.k3, self.k4]], dtype=np.float64).T