CPPxDIC
C++ Digital Image Correlation library for fingertip 3D reconstruction
Loading...
Searching...
No Matches
dic_structures.cpp
Go to the documentation of this file.
1
5#include "dic_structures.h"
6#include "logging.h"
7#include <fstream>
8#include <stdexcept>
9#include <iostream>
10
11namespace cppxdic {
12
13// Helper functions for binary I/O
14template<typename T>
15void writePOD(std::ofstream& ofs, const T& value) {
16 ofs.write(reinterpret_cast<const char*>(&value), sizeof(T));
17}
18
19template<typename T>
20void readPOD(std::ifstream& ifs, T& value) {
21 ifs.read(reinterpret_cast<char*>(&value), sizeof(T));
22}
23
24template<typename T>
25void writeVector(std::ofstream& ofs, const std::vector<T>& vec) {
26 size_t size = vec.size();
27 writePOD(ofs, size);
28 if (size > 0) {
29 ofs.write(reinterpret_cast<const char*>(vec.data()), static_cast<std::streamsize>(size * sizeof(T)));
30 }
31}
32
33template<typename T>
34void readVector(std::ifstream& ifs, std::vector<T>& vec) {
35 size_t size;
36 readPOD(ifs, size);
37 vec.resize(size);
38 if (size > 0) {
39 ifs.read(reinterpret_cast<char*>(vec.data()), static_cast<std::streamsize>(size * sizeof(T)));
40 }
41}
42
43void writeString(std::ofstream& ofs, const std::string& str) {
44 size_t size = str.size();
45 writePOD(ofs, size);
46 if (size > 0) {
47 ofs.write(str.data(), static_cast<std::streamsize>(size));
48 }
49}
50
51void readString(std::ifstream& ifs, std::string& str) {
52 size_t size;
53 readPOD(ifs, size);
54 str.resize(size);
55 if (size > 0) {
56 ifs.read(&str[0], static_cast<std::streamsize>(size));
57 }
58}
59
60template<typename T>
61void writeVector2D(std::ofstream& ofs, const std::vector<std::vector<T>>& vec) {
62 size_t outer_size = vec.size();
63 writePOD(ofs, outer_size);
64 for (const auto& inner : vec) {
65 writeVector(ofs, inner);
66 }
67}
68
69template<typename T>
70void readVector2D(std::ifstream& ifs, std::vector<std::vector<T>>& vec) {
71 size_t outer_size;
72 readPOD(ifs, outer_size);
73 vec.resize(outer_size);
74 for (auto& inner : vec) {
75 readVector(ifs, inner);
76 }
77}
78
79void writePoints3D(std::ofstream& ofs, const Point3DFrame& pts) {
80 writeVector(ofs, pts.x);
81 writeVector(ofs, pts.y);
82 writeVector(ofs, pts.z);
83}
84
85void readPoints3D(std::ifstream& ifs, Point3DFrame& pts) {
86 readVector(ifs, pts.x);
87 readVector(ifs, pts.y);
88 readVector(ifs, pts.z);
89}
90
91void writeDispData(std::ofstream& ofs, const DispData& disp) {
92 writeVector2D(ofs, disp.DispVec);
93 writeVector2D(ofs, disp.DispMgn);
94}
95
96void readDispData(std::ifstream& ifs, DispData& disp) {
97 readVector2D(ifs, disp.DispVec);
98 readVector2D(ifs, disp.DispMgn);
99}
100
101void writeCalibrationData(std::ofstream& ofs, const CalibrationData& calib) {
102 // Write DLT_paths (2D array of strings)
103 size_t rows = calib.DLT_paths.size();
104 writePOD(ofs, rows);
105 for (const auto& row : calib.DLT_paths) {
106 size_t cols = row.size();
107 writePOD(ofs, cols);
108 for (const auto& path : row) {
109 writeString(ofs, path);
110 }
111 }
112
113 // Write DLT_params (3D array: rows x cols x params)
114 size_t param_rows = calib.DLT_params.size();
115 writePOD(ofs, param_rows);
116 for (const auto& row : calib.DLT_params) {
117 size_t param_cols = row.size();
118 writePOD(ofs, param_cols);
119 for (const auto& params : row) {
120 writeVector(ofs, params);
121 }
122 }
123}
124
125void readCalibrationData(std::ifstream& ifs, CalibrationData& calib) {
126 // Read DLT_paths (2D array of strings)
127 size_t rows;
128 readPOD(ifs, rows);
129 calib.DLT_paths.resize(rows);
130 for (auto& row : calib.DLT_paths) {
131 size_t cols;
132 readPOD(ifs, cols);
133 row.resize(cols);
134 for (auto& path : row) {
135 readString(ifs, path);
136 }
137 }
138
139 // Read DLT_params (3D array)
140 size_t param_rows;
141 readPOD(ifs, param_rows);
142 calib.DLT_params.resize(param_rows);
143 for (auto& row : calib.DLT_params) {
144 size_t param_cols;
145 readPOD(ifs, param_cols);
146 row.resize(param_cols);
147 for (auto& params : row) {
148 readVector(ifs, params);
149 }
150 }
151}
152
153void writeDistortionData(std::ofstream& ofs, const DistortionData& dist) {
154 // Write distortion_models (2D array of strings)
155 size_t rows = dist.distortion_models.size();
156 writePOD(ofs, rows);
157 for (const auto& row : dist.distortion_models) {
158 size_t cols = row.size();
159 writePOD(ofs, cols);
160 for (const auto& model : row) {
161 writeString(ofs, model);
162 }
163 }
164
165 // Write distortion_paths (2D array of strings)
166 size_t path_rows = dist.distortion_paths.size();
167 writePOD(ofs, path_rows);
168 for (const auto& row : dist.distortion_paths) {
169 size_t cols = row.size();
170 writePOD(ofs, cols);
171 for (const auto& path : row) {
172 writeString(ofs, path);
173 }
174 }
175}
176
177void writeStringMap(std::ofstream& ofs, const std::map<std::string, std::string>& map) {
178 size_t size = map.size();
179 writePOD(ofs, size);
180 for (const auto& [key, value] : map) {
181 writeString(ofs, key);
182 writeString(ofs, value);
183 }
184}
185
186void readDistortionData(std::ifstream& ifs, DistortionData& dist) {
187 // Read distortion_models (2D array of strings)
188 size_t rows;
189 readPOD(ifs, rows);
190 dist.distortion_models.resize(rows);
191 for (auto& row : dist.distortion_models) {
192 size_t cols;
193 readPOD(ifs, cols);
194 row.resize(cols);
195 for (auto& model : row) {
196 readString(ifs, model);
197 }
198 }
199
200 // Read distortion_paths (2D array of strings)
201 size_t path_rows;
202 readPOD(ifs, path_rows);
203 dist.distortion_paths.resize(path_rows);
204 for (auto& row : dist.distortion_paths) {
205 size_t cols;
206 readPOD(ifs, cols);
207 row.resize(cols);
208 for (auto& path : row) {
209 readString(ifs, path);
210 }
211 }
212}
213
214void readStringMap(std::ifstream& ifs, std::map<std::string, std::string>& map) {
215 size_t size;
216 readPOD(ifs, size);
217 map.clear();
218 for (size_t i = 0; i < size; ++i) {
219 std::string key, value;
220 readString(ifs, key);
221 readString(ifs, value);
222 map[key] = value;
223 }
224}
225
226// DIC3Dcombined binary serialization
227void DIC3Dcombined::saveBinary(const std::string& filepath) const {
228 std::ofstream ofs(filepath, std::ios::binary);
229 if (!ofs.is_open()) {
230 throw std::runtime_error("Failed to open file for writing: " + filepath);
231 }
232
233 // Write magic number and version for format validation
234 uint32_t magic = 0x44494333; // "DIC3"
235 uint32_t version = 1;
236 writePOD(ofs, magic);
237 writePOD(ofs, version);
238
239 // Write main fields
241
242 // Write Points3D (vector of Points3D)
243 size_t num_frames = Points3D.size();
244 writePOD(ofs, num_frames);
245 for (const auto& pts : Points3D) {
246 writePoints3D(ofs, pts);
247 }
248
249 writeVector(ofs, Faces);
254 writeDispData(ofs, Disp);
259
260 // Note: Not serializing DIC2Dinfo and AllPairsResults for simplicity
261 // They can be added if needed
262 uint8_t has_dic2dinfo = 0;
263 uint8_t has_allpairs = 0;
264 writePOD(ofs, has_dic2dinfo);
265 writePOD(ofs, has_allpairs);
266
267 if (!ofs.good()) {
268 throw std::runtime_error("Error writing binary data to: " + filepath);
269 }
270
271 ofs.close();
272 LOG_DEBUG << "DIC3Dcombined saved to binary: " << filepath;
273}
274
275DIC3Dcombined DIC3Dcombined::loadBinary(const std::string& filepath) {
276 std::ifstream ifs(filepath, std::ios::binary);
277 if (!ifs.is_open()) {
278 throw std::runtime_error("Failed to open file for reading: " + filepath);
279 }
280
281 // Validate magic number and version
282 uint32_t magic, version;
283 readPOD(ifs, magic);
284 readPOD(ifs, version);
285 if (magic != 0x44494333) {
286 throw std::runtime_error("Invalid file format (magic number mismatch): " + filepath);
287 }
288 if (version != 1) {
289 throw std::runtime_error("Unsupported file version: " + std::to_string(version));
290 }
291
292 DIC3Dcombined combined;
293
294 // Read main fields
295 readVector(ifs, combined.pairIndices);
296
297 // Read Points3D (vector of Points3D)
298 size_t num_frames;
299 readPOD(ifs, num_frames);
300 combined.Points3D.resize(num_frames);
301 for (auto& pts : combined.Points3D) {
302 readPoints3D(ifs, pts);
303 }
304
305 readVector(ifs, combined.Faces);
306 readVector(ifs, combined.FaceColors);
307 readVector2D(ifs, combined.corrComb);
308 readVector2D(ifs, combined.FaceCorrComb);
309 readVector2D(ifs, combined.FaceCentroids);
310 readDispData(ifs, combined.Disp);
311 readCalibrationData(ifs, combined.calibration);
312 readDistortionData(ifs, combined.distortion);
313 readVector(ifs, combined.FacePairInds);
314 readVector(ifs, combined.PointPairInds);
315
316 // Check for optional fields
317 uint8_t has_dic2dinfo, has_allpairs;
318 readPOD(ifs, has_dic2dinfo);
319 readPOD(ifs, has_allpairs);
320
321 if (!ifs.good()) {
322 throw std::runtime_error("Error reading binary data from: " + filepath);
323 }
324
325 ifs.close();
326 LOG_DEBUG << "DIC3Dcombined loaded from binary: " << filepath;
327 LOG_DEBUG << " - Frames: " << combined.Points3D.size()
328 << ", Points: " << (combined.Points3D.empty() ? 0 : combined.Points3D[0].x.size())
329 << ", Faces: " << (combined.Faces.size() / 3);
330
331 return combined;
332}
333
334} // namespace cppxdic
Lightweight, dependency-free logging facility for CPPxDIC.
#define LOG_DEBUG
Definition logging.h:169
DataSerializer - Abstract base class for format-agnostic DIC data I/O.
void readVector(std::ifstream &ifs, std::vector< T > &vec)
void writePoints3D(std::ofstream &ofs, const Point3DFrame &pts)
void writeDistortionData(std::ofstream &ofs, const DistortionData &dist)
void readDispData(std::ifstream &ifs, DispData &disp)
void writeDispData(std::ofstream &ofs, const DispData &disp)
void readPoints3D(std::ifstream &ifs, Point3DFrame &pts)
void writeStringMap(std::ofstream &ofs, const std::map< std::string, std::string > &map)
void writeVector(std::ofstream &ofs, const std::vector< T > &vec)
void readCalibrationData(std::ifstream &ifs, CalibrationData &calib)
void writeVector2D(std::ofstream &ofs, const std::vector< std::vector< T > > &vec)
void readVector2D(std::ifstream &ifs, std::vector< std::vector< T > > &vec)
void readPOD(std::ifstream &ifs, T &value)
void writeCalibrationData(std::ofstream &ofs, const CalibrationData &calib)
void writePOD(std::ofstream &ofs, const T &value)
void writeString(std::ofstream &ofs, const std::string &str)
void readString(std::ifstream &ifs, std::string &str)
void readDistortionData(std::ifstream &ifs, DistortionData &dist)
void readStringMap(std::ifstream &ifs, std::map< std::string, std::string > &map)
std::vector< std::vector< std::string > > DLT_paths
std::vector< std::vector< std::vector< double > > > DLT_params
DIC 3D Combined Results Equivalent to MATLAB's DIC3Dcombined This represents stitched results from mu...
std::vector< int > FacePairInds
DistortionData distortion
std::vector< int > PointPairInds
std::vector< Point3DFrame > Points3D
std::vector< int > pairIndices
std::vector< double > FaceColors
std::vector< std::vector< double > > FaceCorrComb
static DIC3Dcombined loadBinary(const std::string &filepath)
std::vector< std::vector< double > > corrComb
void saveBinary(const std::string &filepath) const
CalibrationData calibration
std::vector< int > Faces
std::vector< std::vector< double > > FaceCentroids
Displacement data.
std::vector< std::vector< double > > DispVec
std::vector< std::vector< double > > DispMgn
std::vector< std::vector< std::string > > distortion_models
std::vector< std::vector< std::string > > distortion_paths
3D Points per frame
std::vector< double > z
std::vector< double > x
std::vector< double > y