///|
/// Validate an intrinsic calibration against image dimensions.
pub fn intrinsics_is_valid(
intrinsics : CameraIntrinsics,
size : ImageSize,
) -> Bool {
intrinsics.fx > 0.0 &&
intrinsics.fy > 0.0 &&
intrinsics.cx >= 0.0 &&
intrinsics.cy >= 0.0 &&
intrinsics.cx < size.width.to_double() &&
intrinsics.cy < size.height.to_double()
}
///|
pub fn intrinsics_focal_mean(intrinsics : CameraIntrinsics) -> Double {
(intrinsics.fx + intrinsics.fy) / 2.0
}
///|
pub fn intrinsics_aspect_ratio(intrinsics : CameraIntrinsics) -> Double {
if intrinsics.fy <= 0.0 {
0.0
} else {
intrinsics.fx / intrinsics.fy
}
}
///|
pub fn intrinsics_skew_ratio(intrinsics : CameraIntrinsics) -> Double {
if intrinsics.fx.abs() <= 0.000000000001 {
0.0
} else {
intrinsics.skew / intrinsics.fx
}
}
///|
pub fn intrinsics_principal_point(
intrinsics : CameraIntrinsics,
) -> @core.Point2 {
@core.Point2::new(x=intrinsics.cx, y=intrinsics.cy)
}
///|
pub fn intrinsics_is_square_pixel(
intrinsics : CameraIntrinsics,
tolerance : Double,
) -> Bool {
(intrinsics.fx - intrinsics.fy).abs() <= tolerance
}
///|
pub fn intrinsics_distance(
left : CameraIntrinsics,
right : CameraIntrinsics,
) -> Double {
((left.fx - right.fx) * (left.fx - right.fx) +
(left.fy - right.fy) * (left.fy - right.fy) +
(left.cx - right.cx) * (left.cx - right.cx) +
(left.cy - right.cy) * (left.cy - right.cy) +
(left.skew - right.skew) * (left.skew - right.skew)).sqrt()
}
///|
pub fn interpolate_intrinsics(
left : CameraIntrinsics,
right : CameraIntrinsics,
amount : Double,
) -> CameraIntrinsics {
let t = amount.max(0.0).min(1.0)
CameraIntrinsics::new(
fx=left.fx * (1.0 - t) + right.fx * t,
fy=left.fy * (1.0 - t) + right.fy * t,
cx=left.cx * (1.0 - t) + right.cx * t,
cy=left.cy * (1.0 - t) + right.cy * t,
skew=left.skew * (1.0 - t) + right.skew * t,
)
}
///|
pub fn scale_intrinsics(
intrinsics : CameraIntrinsics,
scale : Double,
) -> CameraIntrinsics {
CameraIntrinsics::new(
fx=intrinsics.fx * scale,
fy=intrinsics.fy * scale,
cx=intrinsics.cx * scale,
cy=intrinsics.cy * scale,
skew=intrinsics.skew * scale,
)
}
///|
pub fn shift_intrinsics(
intrinsics : CameraIntrinsics,
shift : @core.Vec2,
) -> CameraIntrinsics {
CameraIntrinsics::new(
fx=intrinsics.fx,
fy=intrinsics.fy,
cx=intrinsics.cx + shift.x,
cy=intrinsics.cy + shift.y,
skew=intrinsics.skew,
)
}
///|
pub fn normalized_principal_point(
intrinsics : CameraIntrinsics,
size : ImageSize,
) -> @core.Point2 {
@core.Point2::new(
x=intrinsics.cx / size.width.to_double(),
y=intrinsics.cy / size.height.to_double(),
)
}
///|
pub fn normalized_focal(
intrinsics : CameraIntrinsics,
size : ImageSize,
) -> @core.Vec2 {
@core.Vec2::new(
x=intrinsics.fx / size.width.to_double(),
y=intrinsics.fy / size.height.to_double(),
)
}
///|
pub fn field_of_view_pair(
intrinsics : CameraIntrinsics,
size : ImageSize,
) -> (Double, Double) raise @core.GeometryError {
(
horizontal_fov(intrinsics, width=size.width.to_double()),
vertical_fov(intrinsics, height=size.height.to_double()),
)
}
///|
pub fn image_diagonal_fov(
intrinsics : CameraIntrinsics,
size : ImageSize,
) -> Double raise @core.GeometryError {
let diagonal = (size.width.to_double() * size.width.to_double() +
size.height.to_double() * size.height.to_double()).sqrt()
horizontal_fov(intrinsics, width=diagonal)
}
///|
pub fn focal_from_horizontal_fov_safe(
size : ImageSize,
fov : Double,
) -> Double raise @core.GeometryError {
focal_from_fov(sensor_extent=size.width.to_double(), fov_radians=fov)
}
///|
pub fn camera_parameter_vector(intrinsics : CameraIntrinsics) -> Array[Double] {
[intrinsics.fx, intrinsics.fy, intrinsics.cx, intrinsics.cy, intrinsics.skew]
}
///|
pub fn camera_parameter_delta(
left : CameraIntrinsics,
right : CameraIntrinsics,
) -> Array[Double] {
let l = camera_parameter_vector(left)
let r = camera_parameter_vector(right)
@core.subtract_scalars(l, r)
}
///|
pub fn camera_parameter_norm(intrinsics : CameraIntrinsics) -> Double {
@core.norm_scalars(camera_parameter_vector(intrinsics))
}
///|
pub fn camera_parameter_clamp(
intrinsics : CameraIntrinsics,
minimum_focal : Double,
maximum_focal : Double,
) -> CameraIntrinsics {
CameraIntrinsics::new(
fx=intrinsics.fx.max(minimum_focal).min(maximum_focal),
fy=intrinsics.fy.max(minimum_focal).min(maximum_focal),
cx=intrinsics.cx.max(0.0),
cy=intrinsics.cy.max(0.0),
skew=intrinsics.skew,
)
}