13#include <nlohmann/json.hpp>
22 return std::filesystem::exists(basePath +
extension());
26 if (format ==
"mat") {
27 return std::make_unique<MatSerializer>();
28 }
else if (format ==
"bin") {
29 return std::make_unique<BinarySerializer>();
30 }
else if (format ==
"json") {
31 return std::make_unique<JsonSerializer>();
33 throw std::invalid_argument(
"Unknown data format: '" + format +
34 "'. Supported formats: mat, bin, json");
70 }
catch (
const std::exception& e) {
71 LOG_ERROR <<
"BinarySerializer: Failed to save DIC3Dcombined: " << e.what();
80 }
catch (
const std::exception& e) {
81 LOG_ERROR <<
"BinarySerializer: Failed to load DIC3Dcombined: " << e.what();
90 }
catch (
const std::exception& e) {
91 LOG_ERROR <<
"BinarySerializer: Failed to save DIC3DPPresults: " << e.what();
99 std::ofstream ofs(path, std::ios::binary);
100 if (!ofs.is_open())
return false;
103 uint32_t magic = 0x44324450;
104 uint32_t version = 2;
105 ofs.write(
reinterpret_cast<const char*
>(&magic),
sizeof(magic));
106 ofs.write(
reinterpret_cast<const char*
>(&version),
sizeof(version));
109 ofs.write(
reinterpret_cast<const char*
>(&data.
nCamRef),
sizeof(data.
nCamRef));
110 ofs.write(
reinterpret_cast<const char*
>(&data.
nCamDef),
sizeof(data.
nCamDef));
111 ofs.write(
reinterpret_cast<const char*
>(&data.
nImages),
sizeof(data.
nImages));
113 ofs.write(
reinterpret_cast<const char*
>(&npo),
sizeof(npo));
115 ofs.write(
reinterpret_cast<const char*
>(data.
pairOrder.data()),
116 static_cast<std::streamsize
>(npo *
sizeof(
int)));
118 uint8_t pair_forced = data.
pairForced ? 1 : 0;
119 ofs.write(
reinterpret_cast<const char*
>(&pair_forced),
sizeof(pair_forced));
122 size_t nf = data.
Faces.size();
123 ofs.write(
reinterpret_cast<const char*
>(&nf),
sizeof(nf));
124 if (nf > 0) ofs.write(
reinterpret_cast<const char*
>(data.
Faces.data()),
125 static_cast<std::streamsize
>(nf *
sizeof(
int)));
129 ofs.write(
reinterpret_cast<const char*
>(&nc),
sizeof(nc));
130 if (nc > 0) ofs.write(
reinterpret_cast<const char*
>(data.
FaceColors.data()),
131 static_cast<std::streamsize
>(nc *
sizeof(
double)));
134 size_t np = data.
Points.size();
135 ofs.write(
reinterpret_cast<const char*
>(&np),
sizeof(np));
136 for (
const auto& pts : data.
Points) {
137 size_t sz = pts.x.size();
138 ofs.write(
reinterpret_cast<const char*
>(&sz),
sizeof(sz));
140 ofs.write(
reinterpret_cast<const char*
>(pts.x.data()),
static_cast<std::streamsize
>(sz *
sizeof(
double)));
141 ofs.write(
reinterpret_cast<const char*
>(pts.y.data()),
static_cast<std::streamsize
>(sz *
sizeof(
double)));
147 ofs.write(
reinterpret_cast<const char*
>(&ncc),
sizeof(ncc));
149 size_t sz = cc.size();
150 ofs.write(
reinterpret_cast<const char*
>(&sz),
sizeof(sz));
151 if (sz > 0) ofs.write(
reinterpret_cast<const char*
>(cc.data()),
static_cast<std::streamsize
>(sz *
sizeof(
double)));
155 }
catch (
const std::exception& e) {
156 LOG_ERROR <<
"BinarySerializer: Failed to save DIC2DPairResults: " << e.what();
163 std::ifstream ifs(path, std::ios::binary);
164 if (!ifs.is_open())
return false;
166 uint32_t magic, version;
167 ifs.read(
reinterpret_cast<char*
>(&magic),
sizeof(magic));
168 ifs.read(
reinterpret_cast<char*
>(&version),
sizeof(version));
169 if (magic != 0x44324450 || (version != 1 && version != 2))
return false;
171 ifs.read(
reinterpret_cast<char*
>(&data.
nCamRef),
sizeof(data.
nCamRef));
172 ifs.read(
reinterpret_cast<char*
>(&data.
nCamDef),
sizeof(data.
nCamDef));
173 ifs.read(
reinterpret_cast<char*
>(&data.
nImages),
sizeof(data.
nImages));
178 ifs.read(
reinterpret_cast<char*
>(&npo),
sizeof(npo));
181 ifs.read(
reinterpret_cast<char*
>(data.
pairOrder.data()),
182 static_cast<std::streamsize
>(npo *
sizeof(
int)));
184 uint8_t pair_forced = 0;
185 ifs.read(
reinterpret_cast<char*
>(&pair_forced),
sizeof(pair_forced));
190 ifs.read(
reinterpret_cast<char*
>(&nf),
sizeof(nf));
191 data.
Faces.resize(nf);
192 if (nf > 0) ifs.read(
reinterpret_cast<char*
>(data.
Faces.data()),
static_cast<std::streamsize
>(nf *
sizeof(
int)));
195 ifs.read(
reinterpret_cast<char*
>(&nc),
sizeof(nc));
197 if (nc > 0) ifs.read(
reinterpret_cast<char*
>(data.
FaceColors.data()),
static_cast<std::streamsize
>(nc *
sizeof(
double)));
200 ifs.read(
reinterpret_cast<char*
>(&np),
sizeof(np));
202 for (
auto& pts : data.
Points) {
204 ifs.read(
reinterpret_cast<char*
>(&sz),
sizeof(sz));
208 ifs.read(
reinterpret_cast<char*
>(pts.x.data()),
static_cast<std::streamsize
>(sz *
sizeof(
double)));
209 ifs.read(
reinterpret_cast<char*
>(pts.y.data()),
static_cast<std::streamsize
>(sz *
sizeof(
double)));
214 ifs.read(
reinterpret_cast<char*
>(&ncc),
sizeof(ncc));
218 ifs.read(
reinterpret_cast<char*
>(&sz),
sizeof(sz));
220 if (sz > 0) ifs.read(
reinterpret_cast<char*
>(cc.data()),
static_cast<std::streamsize
>(sz *
sizeof(
double)));
224 }
catch (
const std::exception& e) {
225 LOG_ERROR <<
"BinarySerializer: Failed to load DIC2DPairResults: " << e.what();
246 pts.
x = j[
"x"].get<std::vector<double>>();
247 pts.
y = j[
"y"].get<std::vector<double>>();
248 pts.
z = j[
"z"].get<std::vector<double>>();
255 j[
"format"] =
"DIC3Dcombined";
259 j[
"Faces"] = data.
Faces;
265 nlohmann::json pts_array = nlohmann::json::array();
266 for (
const auto& pts : data.
Points3D) {
269 j[
"Points3D"] = pts_array;
288 std::ofstream ofs(path);
289 if (!ofs.is_open())
return false;
290 ofs << j.dump(2) << std::endl;
292 }
catch (
const std::exception& e) {
293 LOG_ERROR <<
"JsonSerializer: Failed to save DIC3Dcombined: " << e.what();
300 std::ifstream ifs(path);
301 if (!ifs.is_open())
return false;
303 nlohmann::json j = nlohmann::json::parse(ifs);
305 data.
pairIndices = j.value(
"pairIndices", std::vector<int>{});
306 data.
Faces = j.value(
"Faces", std::vector<int>{});
307 data.
FaceColors = j.value(
"FaceColors", std::vector<double>{});
308 data.
FacePairInds = j.value(
"FacePairInds", std::vector<int>{});
309 data.
PointPairInds = j.value(
"PointPairInds", std::vector<int>{});
313 if (j.contains(
"Points3D")) {
314 for (
const auto& pt_j : j[
"Points3D"]) {
320 data.
corrComb = j.value(
"corrComb", std::vector<std::vector<double>>{});
321 data.
FaceCorrComb = j.value(
"FaceCorrComb", std::vector<std::vector<double>>{});
322 data.
FaceCentroids = j.value(
"FaceCentroids", std::vector<std::vector<double>>{});
325 if (j.contains(
"Disp")) {
326 data.
Disp.
DispVec = j[
"Disp"].value(
"DispVec", std::vector<std::vector<double>>{});
327 data.
Disp.
DispMgn = j[
"Disp"].value(
"DispMgn", std::vector<std::vector<double>>{});
331 if (j.contains(
"calibration")) {
332 data.
calibration.
DLT_paths = j[
"calibration"].value(
"DLT_paths", std::vector<std::vector<std::string>>{});
333 data.
calibration.
DLT_params = j[
"calibration"].value(
"DLT_params", std::vector<std::vector<std::vector<double>>>{});
337 if (j.contains(
"distortion")) {
343 }
catch (
const std::exception& e) {
344 LOG_ERROR <<
"JsonSerializer: Failed to load DIC3Dcombined: " << e.what();
352 j[
"F11"] = F.
F11; j[
"F12"] = F.
F12; j[
"F13"] = F.
F13;
353 j[
"F21"] = F.
F21; j[
"F22"] = F.
F22; j[
"F23"] = F.
F23;
354 j[
"F31"] = F.
F31; j[
"F32"] = F.
F32; j[
"F33"] = F.
F33;
361 j[
"E11"] = E.
E11; j[
"E12"] = E.
E12; j[
"E13"] = E.
E13;
362 j[
"E21"] = E.
E21; j[
"E22"] = E.
E22; j[
"E23"] = E.
E23;
363 j[
"E31"] = E.
E31; j[
"E32"] = E.
E32; j[
"E33"] = E.
E33;
370 nlohmann::json f_arr = nlohmann::json::array();
374 nlohmann::json s_arr = nlohmann::json::array();
386 j[
"format"] =
"DIC3DPPresults";
393 j[
"Faces"] = data.
Faces;
398 nlohmann::json pts_array = nlohmann::json::array();
399 for (
const auto& pts : data.
Points3D) {
402 j[
"Points3D"] = pts_array;
431 std::ofstream ofs(path);
432 if (!ofs.is_open())
return false;
433 ofs << j.dump(2) << std::endl;
435 }
catch (
const std::exception& e) {
436 LOG_ERROR <<
"JsonSerializer: Failed to save DIC3DPPresults: " << e.what();
444 j[
"format"] =
"DIC2DPairResults";
451 j[
"Faces"] = data.
Faces;
454 nlohmann::json pts_array = nlohmann::json::array();
455 for (
const auto& pts : data.
Points) {
459 pts_array.push_back(pj);
461 j[
"Points"] = pts_array;
465 std::ofstream ofs(path);
466 if (!ofs.is_open())
return false;
467 ofs << j.dump(2) << std::endl;
469 }
catch (
const std::exception& e) {
470 LOG_ERROR <<
"JsonSerializer: Failed to save DIC2DPairResults: " << e.what();
477 std::ifstream ifs(path);
478 if (!ifs.is_open())
return false;
480 nlohmann::json j = nlohmann::json::parse(ifs);
482 data.
nCamRef = j.value(
"nCamRef", 0);
483 data.
nCamDef = j.value(
"nCamDef", 0);
484 data.
nImages = j.value(
"nImages", 0);
485 data.
pairOrder = j.value(
"pairOrder", std::vector<int>{});
486 data.
pairForced = j.value(
"pairForced",
false);
487 data.
Faces = j.value(
"Faces", std::vector<int>{});
488 data.
FaceColors = j.value(
"FaceColors", std::vector<double>{});
491 if (j.contains(
"Points")) {
492 for (
const auto& pj : j[
"Points"]) {
494 pts.
x = pj.value(
"x", std::vector<double>{});
495 pts.
y = pj.value(
"y", std::vector<double>{});
496 data.
Points.push_back(pts);
500 data.
CorCoeffVec = j.value(
"CorCoeffVec", std::vector<std::vector<double>>{});
503 }
catch (
const std::exception& e) {
504 LOG_ERROR <<
"JsonSerializer: Failed to load DIC2DPairResults: " << e.what();
bool saveDIC2DPairResults(const std::string &path, const DIC2DPairResults &data) override
bool loadDIC3Dcombined(const std::string &path, DIC3Dcombined &data) override
bool saveDIC3Dcombined(const std::string &path, const DIC3Dcombined &data) override
bool saveDIC3DPPresults(const std::string &path, const DIC3DPPresults &data) override
bool loadDIC2DPairResults(const std::string &path, DIC2DPairResults &data) override
static std::unique_ptr< DataSerializer > create(const std::string &format)
Create a serializer for the given format string.
virtual std::string extension() const =0
File extension for this format (e.g., ".mat", ".bin", ".json")
bool fileExists(const std::string &basePath) const
bool loadDIC2DPairResults(const std::string &path, DIC2DPairResults &data) override
bool saveDIC2DPairResults(const std::string &path, const DIC2DPairResults &data) override
bool loadDIC3Dcombined(const std::string &path, DIC3Dcombined &data) override
bool saveDIC3DPPresults(const std::string &path, const DIC3DPPresults &data) override
bool saveDIC3Dcombined(const std::string &path, const DIC3Dcombined &data) override
static bool readDIC2DPairResults(const std::string &mat_path, struct DIC2DPairResults &result)
Read DIC2DPairResults structure from MAT file Loads myDIC2DpairResults_C_X_C_Y.mat files.
static bool readDIC3Dcombined(const std::string &mat_path, struct DIC3Dcombined &combined)
Read DIC3Dcombined structure from MAT file.
bool loadDIC3Dcombined(const std::string &path, DIC3Dcombined &data) override
bool saveDIC2DPairResults(const std::string &path, const DIC2DPairResults &data) override
bool loadDIC2DPairResults(const std::string &path, DIC2DPairResults &data) override
bool saveDIC3Dcombined(const std::string &path, const DIC3Dcombined &data) override
bool saveDIC3DPPresults(const std::string &path, const DIC3DPPresults &data) override
static bool writeDIC2DPairResults(const std::string &filename, const DIC2DPairResults &results)
Write myDIC2DpairResults_C_X_C_Y.mat file Contains processed 2D DIC results with triangulation.
static bool write3DCombinedResults(const std::string &filename, const DIC3Dcombined &combined, const std::string &struct_name="DIC3Dcombined")
Write DIC3Dcombined_XPairs_stitched.mat file Contains 3D reconstruction results.
static bool write3DPPresults(const std::string &filename, const DIC3DPPresults &ppresults)
Write DIC3DPPresults_XPairs_Y_v1.mat file Contains deformation and strain analysis results.
Lightweight, dependency-free logging facility for CPPxDIC.
DataSerializer - Abstract base class for format-agnostic DIC data I/O.
static nlohmann::json points3dToJson(const Point3DFrame &pts)
static nlohmann::json deformDataToJson(const DeformData &deform)
static Point3DFrame points3dFromJson(const nlohmann::json &j)
static nlohmann::json strainTensorToJson(const StrainTensor &E)
static nlohmann::json deformGradientToJson(const DeformGradient &F)
std::vector< std::vector< std::string > > DLT_paths
std::vector< std::vector< std::vector< double > > > DLT_params
DIC 2D Pair Results Equivalent to MATLAB's DIC2DpairResults.
std::vector< int > pairOrder
std::vector< Points2D > Points
std::vector< std::vector< double > > CorCoeffVec
std::vector< double > FaceColors
DIC 3D Post-Processing Results Equivalent to MATLAB's DIC3DPPresults.
std::vector< std::vector< double > > FaceIsoInd
std::vector< std::vector< double > > Points3D_ARBM_y
std::vector< std::vector< double > > Points3D_ARBM_x
std::vector< std::vector< double > > Points3D_ARBM_z
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< std::vector< double > > FaceCentroids
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
std::vector< std::vector< double > > TransVec
std::vector< std::vector< double > > RotMat
std::vector< double > E11
std::vector< double > E12
std::vector< double > E13
std::vector< double > E21
std::vector< double > E31
std::vector< double > E32
std::vector< double > E23
std::vector< double > E22
std::vector< double > E33