1use nalgebra as na;
5use nalgebra::RealField;
6use nalgebra::core::OMatrix;
7use nalgebra::core::dimension::{U3, U4};
8
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Default, Deserialize, PartialEq)]
12#[serde(rename = "multi_camera_reconstructor", deny_unknown_fields)]
13pub struct FlydraReconstructor<R: RealField + serde::Serialize> {
14 #[serde(rename = "single_camera_calibration")]
15 pub cameras: Vec<SingleCameraCalibration<R>>,
16 #[serde(default)]
18 pub minimum_eccentricity: R,
19 #[serde(default)]
20 pub water: Option<R>,
21 #[serde(default)]
22 pub comment: Option<String>,
23}
24
25#[derive(Debug, Serialize, Deserialize, PartialEq)]
26#[serde(deny_unknown_fields, rename = "single_camera_calibration")]
27pub struct SingleCameraCalibration<R: RealField + serde::Serialize> {
28 pub cam_id: String,
30 #[serde(
31 serialize_with = "serialize_matrix",
32 deserialize_with = "deserialize_matrix"
33 )]
34 pub calibration_matrix: OMatrix<R, U3, U4>,
35 #[serde(
36 serialize_with = "serialize_two_ints",
37 deserialize_with = "deserialize_two_ints"
38 )]
39 pub resolution: (usize, usize),
40 #[serde(default, skip_serializing)]
42 pub scale_factor: Option<R>,
43 pub non_linear_parameters: FlydraDistortionModel<R>,
44}
45
46#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
47#[serde(deny_unknown_fields)]
48pub struct FlydraDistortionModel<R: RealField + serde::Serialize> {
49 pub fc1: R,
50 pub fc2: R,
51 pub cc1: R,
52 pub cc2: R,
53 pub k1: R,
54 pub k2: R,
55 pub p1: R,
56 pub p2: R,
57 #[serde(default, skip_serializing_if = "is_zero")]
58 pub k3: R,
59 pub alpha_c: R,
60 #[serde(default, skip_serializing)]
61 pub fc1p: Option<R>,
62 #[serde(default, skip_serializing)]
63 pub fc2p: Option<R>,
64 #[serde(default, skip_serializing)]
65 pub cc1p: Option<R>,
66 #[serde(default, skip_serializing)]
67 pub cc2p: Option<R>,
68}
69
70impl<R> FlydraDistortionModel<R>
71where
72 R: RealField + serde::Serialize,
73{
74 pub fn linear(pmat: &OMatrix<R, U3, U4>) -> Self {
77 Self {
78 fc1: pmat[(0, 0)].clone(),
79 fc2: pmat[(1, 1)].clone(),
80 cc1: pmat[(0, 2)].clone(),
81 cc2: pmat[(1, 2)].clone(),
82 alpha_c: na::convert(0.0),
83 k1: na::convert(0.0),
84 k2: na::convert(0.0),
85 p1: na::convert(0.0),
86 p2: na::convert(0.0),
87 k3: na::convert(0.0),
88 fc1p: None,
89 fc2p: None,
90 cc1p: None,
91 cc2p: None,
92 }
93 }
94}
95
96fn is_zero<R: RealField>(val: &R) -> bool {
97 let zero: R = na::convert(0.0);
98 val == &zero
99}
100
101fn extra_indent(s: String, prefix: &str) -> String {
105 let mut v = Vec::new();
106 for (i, line) in s.lines().enumerate() {
107 if i == 0 {
108 v.push(line.to_string());
109 } else {
110 v.push(format!("{prefix}{line}"));
111 }
112 }
113 v.join("\n")
114}
115
116pub(crate) fn serialize_recon<R>(
117 recon: &FlydraReconstructor<R>,
118) -> std::result::Result<String, serde_xml_rs::Error>
119where
120 R: RealField + Serialize,
121{
122 let prefix = " ";
127 let s = serde_xml_rs::SerdeXml::new().emitter(
128 xml::EmitterConfig::new()
129 .write_document_declaration(false)
130 .perform_indent(true),
131 );
132 let v: Result<Vec<String>, serde_xml_rs::Error> = recon
133 .cameras
134 .iter()
135 .map(|item| match s.clone().to_string(&item) {
136 Ok(st) => Ok(extra_indent(st, prefix)),
137 Err(e) => Err(e),
138 })
139 .collect();
140 let v: Vec<String> = v?;
141 let v_indented: Vec<String> = v.iter().map(|s| format!("{prefix}{s}")).collect();
142 let cams_buf = v_indented.join("\n");
143
144 let mut v = vec!["<multi_camera_reconstructor>".to_string()];
145 v.push(cams_buf);
146 if let Some(ref w) = recon.water {
147 v.push(format!(" <water>{w}</water>"));
148 }
149 if let Some(ref c) = recon.comment {
150 v.push(format!(" <comment>{c}</comment>"));
151 }
152 v.push("</multi_camera_reconstructor>\n".to_string());
153 let buf = v.join("\n");
154 Ok(buf)
155}
156
157#[rustfmt::skip]
158fn serialize_matrix<S, R>(m: &OMatrix<R,U3,U4>, serializer: S) -> Result<S::Ok, S::Error>
159 where S: serde::Serializer,
160 R: RealField + Serialize,
161{
162 let buf = format!("{} {} {} {}; {} {} {} {}; {} {} {} {}",
163 m[(0,0)], m[(0,1)], m[(0,2)], m[(0,3)],
164 m[(1,0)], m[(1,1)], m[(1,2)], m[(1,3)],
165 m[(2,0)], m[(2,1)], m[(2,2)], m[(2,3)]);
166 serializer.serialize_str(&buf)
167}
168
169fn deserialize_matrix<'de, D, R>(deserializer: D) -> Result<OMatrix<R, U3, U4>, D::Error>
170where
171 D: serde::Deserializer<'de>,
172 R: RealField,
173{
174 use std::str::FromStr;
175
176 let s = String::deserialize(deserializer)?;
177 let rows: Vec<&str> = s.split(';').collect();
178 if rows.len() != 3 {
179 return Err(serde::de::Error::custom("expected exactly 3 rows"));
180 }
181 let mut elements: Vec<R> = Vec::new();
182 for row in rows.iter() {
183 let cols: Vec<&str> = row.split_whitespace().collect();
184 if cols.len() != 4 {
185 return Err(serde::de::Error::custom("expected exactly 4 columns"));
186 }
187 for col in cols.iter() {
188 let element = f64::from_str(col).map_err(serde::de::Error::custom)?;
189 elements.push(na::convert(element));
190 }
191 }
192 Ok(OMatrix::<R, U3, U4>::from_row_slice(elements.as_slice()))
193}
194
195fn serialize_two_ints<S>(two_ints: &(usize, usize), serializer: S) -> Result<S::Ok, S::Error>
196where
197 S: serde::Serializer,
198{
199 let buf = format!("{} {}", two_ints.0, two_ints.1);
200 serializer.serialize_str(&buf)
201}
202
203fn deserialize_two_ints<'de, D>(deserializer: D) -> Result<(usize, usize), D::Error>
204where
205 D: serde::Deserializer<'de>,
206{
207 use std::str::FromStr;
208
209 let s = String::deserialize(deserializer)?;
210 let nums: Vec<&str> = s.split(' ').collect();
211 if nums.len() != 2 {
212 return Err(serde::de::Error::custom("expected exactly 2 numbers"));
213 }
214 Ok((
215 usize::from_str(nums[0]).map_err(serde::de::Error::custom)?,
216 usize::from_str(nums[1]).map_err(serde::de::Error::custom)?,
217 ))
218}