///|
fn yaml_value(lines : Array[String], key : String) -> String? {
let prefix = key + ":"
for line in lines {
if line.has_prefix(prefix) {
return Some(line.strip_prefix(prefix).unwrap().trim().to_owned())
}
}
None
}
///|
fn require_yaml_value(
lines : Array[String],
key : String,
) -> String raise VisionFormatError {
match yaml_value(lines, key) {
Some(value) => value
None => raise VisionFormatError::MissingField(key)
}
}
///|
fn parse_yaml_number_list(
lines : Array[String],
key : String,
expected : Int,
) -> Array[Double] raise VisionFormatError {
let raw = require_yaml_value(lines, key)
let clean = raw.replace(old="[", new="").replace(old="]", new="")
let values = Array::new()
for part in clean.split(",") {
let item = part.trim()
if !item.is_empty() {
values.push(parse_double_field(item, key))
}
}
if values.length() != expected {
raise VisionFormatError::InvalidShape(
"\{key} expected \{expected}, got \{values.length()}",
)
}
values
}
///|
pub fn parse_camera_info_yaml(
text : String,
) -> CameraIntrinsics raise VisionFormatError {
let lines = non_empty_lines(text)
if lines.is_empty() {
raise VisionFormatError::EmptyInput
}
{
width: parse_int_field(
require_yaml_value(lines, "image_width")[:],
"image_width",
),
height: parse_int_field(
require_yaml_value(lines, "image_height")[:],
"image_height",
),
distortion_model: require_yaml_value(lines, "distortion_model").replace(
old="\"",
new="",
),
k: parse_yaml_number_list(lines, "camera_matrix", 9),
d: parse_yaml_number_list(lines, "distortion_coefficients", 5),
r: parse_yaml_number_list(lines, "rectification_matrix", 9),
p: parse_yaml_number_list(lines, "projection_matrix", 12),
}
}
///|
pub fn camera_info_to_yaml(camera : CameraIntrinsics) -> String {
[
"image_width: \{camera.width}",
"image_height: \{camera.height}",
"distortion_model: \{camera.distortion_model}",
"camera_matrix: [\{camera.k.map(fn(v) { v.to_string() }).join(", ")}]",
"distortion_coefficients: [\{camera.d.map(fn(v) { v.to_string() }).join(", ")}]",
"rectification_matrix: [\{camera.r.map(fn(v) { v.to_string() }).join(", ")}]",
"projection_matrix: [\{camera.p.map(fn(v) { v.to_string() }).join(", ")}]",
].join("\n")
}
///|
pub fn focal_length_pair(
camera : CameraIntrinsics,
) -> (Double, Double) raise VisionFormatError {
if camera.k.length() != 9 {
raise VisionFormatError::InvalidShape("camera_matrix must contain 9 values")
}
(camera.k[0], camera.k[4])
}