这就是一篇记录学习Halcon dict 字典在Qt/C++环境中处理数据的笔记总结,以及实际项目中开发遇到的问题延伸汇总。
目录导读
-
- 一、Halcon字典数据的增删查改
-
- 1.创建halcon字段并赋值
- 2.读取字段数据
- 3.删除键值对
- 4.复制HTuple,不限于字典类型
- [5.读取和写入HTuple 结构数据](#5.读取和写入HTuple 结构数据)
- 6.HTuple字典插入元组数据
- 7.HTuple字典元组删除某项
- 8.HTuple字典遍历所有字段
- 9.HTuple字典元组数据遍历
- [10.Tuple 数据转换 QString,int,Double](#10.Tuple 数据转换 QString,int,Double)
- 二、QDataSteam序列化与反序列化结构体
-
- 1.定义一个复杂的结构体
- [2.重写operator <<和>>操作符](#2.重写operator <<和>>操作符)
- [2.从新修改operator 操作符 使用Base64简单加密字符串](#2.从新修改operator 操作符 使用Base64简单加密字符串)
- [使用 QDataSteam 序列化结构体](#使用 QDataSteam 序列化结构体)
- [使用 QDataSteam 反序列化结构体](#使用 QDataSteam 反序列化结构体)
- 三、其他
-
- [1.重写QDebug& operator<<操作符,打印结构体](#1.重写QDebug& operator<<操作符,打印结构体)
一、Halcon字典数据的增删查改
当前示例适用于halcon 24.0左右版本
1.创建halcon字段并赋值
cpp
HTuple hv_DictHandle;
//hv_DictHandle=dict{}
//创建一个空字典`
CreateDict(&hv_DictHandle);
//1. 添加键值对等同于修改
SetDictTuple(hv_DictHandle, "score", 95);
//2.添加图像对象
HObject ho_Image;
ReadImage(&ho_Image, "particle");
SetDictObject(ho_Image, hv_DictHandle, "particle_image");
2.读取字段数据
cpp
HTuple hv_Exists, hv_ScoreValue;
//! 判断是否有当前字段,如果明知有可以直接提取`
GetDictParam(hv_DictHandle, "key_exists", "score", &hv_Exists);
if (0 != hv_Exists)
{
GetDictTuple(hv_DictHandle, "score", &hv_ScoreValue);
//! 或者
hv_ScoreValue=hv_DictHandle.TupleGetDictTuple("epoch") ;
}
3.删除键值对
cpp
RemoveDictKey(hv_DictHandle, "score");
4.复制HTuple,不限于字典类型
直接使用=号赋值,相当于指针引用。
cpp
HTuple hv_DLDataset1;
CopyDict(hv_DictHandle, HTuple(), HTuple(), &hv_DLDataset1);
5.读取和写入HTuple 结构数据
cpp
WriteDict(hv_DictHandle, "Text_DictHandle.hdict", HTuple(), HTuple());
ReadDict("Text_DictHandle.hdict", HTuple(), HTuple(), &hv_DictHandle);
6.HTuple字典插入元组数据
cpp
//替换某处值
SetDictTupleAt(hv_DictHandle, "元组名称", 0, HTuple());
//被替换后重新添加
SetDictTuple(hv_DictHandle, "元组名称", (hv_DictHandle.TupleGetDictTuple("元组名称")).TupleConcat(hv_ImageItem));
7.HTuple字典元组删除某项
cpp
HTuple hv_indexss = -1;
//查找第一个
TupleFindFirst(hv_DictHandle.TupleGetDictTuple("元组名称"), hv_ImageItem, &hv_indexss);
//移除索引项
//tuple_remove (DictHandle.Mapdepot, indexss, Reduced)
TupleRemove(hv_DictHandle.TupleGetDictTuple("元组名称"), hv_indexss, &hv___Tmp_Ctrl_0);
//更新
SetDictTuple(hv_DictHandle, "元组名称", hv___Tmp_Ctrl_0);
8.HTuple字典遍历所有字段
cpp
//! 获取所有键值
GetDictParam(hv_Divide, "keys", HTuple(), &hv_Keys);
HTuple end_val75 = (hv_Keys.TupleLength())-1;
HTuple step_val75 = 1;
for (hv_Index=0; hv_Index.Continue(end_val75, step_val75); hv_Index += step_val75)
{
//! 获取数据类型
GetDictParam(hv_Divide, "key_data_type", HTuple(hv_Keys[hv_Index]), &hv_DataType);
//! 获取数据值
GetDictTuple(hv_Divide, HTuple(hv_Keys[hv_Index]), &hv_Value);
}
9.HTuple字典元组数据遍历
cpp
GetDictTuple(hv_DictHandle, "TrainingModel", &hv_TrainingModel);
qDebug()<<"hv_TrainingModel: "<<(int)hv_TrainingModel.TupleLength();
for (int i = 0; i < hv_TrainingModel.TupleLength(); i++)
{
HTuple TrainingModel=hv_TrainingModel[i];
}
10.Tuple 数据转换 QString,int,Double
从Tuple数据类型转换成QT中常用的数据类型,
如果Tuple中的数据类型与你转换的数据类型不一致,会导致异常需要注意
cpp
QString Train_Name=QString::fromUtf8(hv_DictHandle.TupleGetDictTuple("Train_Name").S());
int Channels=hv_DictHandle.TupleGetDictTuple("Channels").I();
double num_epochs=hv_DictHandle.TupleGetDictTuple("num_epochs").D();
二、QDataSteam序列化与反序列化结构体
一开始我是在项目中使用Tuple 字典保存项目结构,这样也能保存训练的数据和模型数据,而且Tuple自带线程安全,哪怕是在改都可以。
但是当告诉我软件需要兼容其他深度训练框架的时候,就不太适用了
就必须使用结构体来保存项目结构了,这意味着软件后期需要大改,淦。
(╯°Д°)╯︵ ┻━┻
于是仔细研究了下QDataSteam序列化与反序列化结构体,争取尽量减少改动,
于是整理了一下具体实现,┬─┬ ノ('-'ノ)
至于为什么不用sqlite或xml,json来保存...
因为用得多了显得捞...
1.定义一个复杂的结构体
定义一个多个数据,嵌套其他结构的结构体 DictHandData :
用来模拟实际项目的复杂结构。
cpp
struct MapDepot
{
int image_id;
QString image_file_name;
int image_label_id;
QString split;
};
struct Classes
{
QString class_names;
int class_ids;
QString class_color;
QString shortcutkey;
};
struct Splits
{
QString split_name;
int train_num;
int train_percentum;
int validation_num;
int validation_percentum;
int test_num;
int test_percentum;
};
struct TrainInfo
{
double epoch;
double num_epochs;
double num_iterations_per_epoch;
double mean_loss;
int mean_loss_samples;
int start_epoch;
double start_time;
double time_elapsed;
};
struct XProgres
{
QString Natural_Model_Path;
QString ExampleDataDir;
QString DL_Dataset;
QString DL_Preprocess_Param;
QString Current_State;
QString Operating_State;
QList<TrainInfo> TrainInfos;
};
struct Trains
{
QString Train_Name;
QString Natural_Model;
int Image_Width;
int Image_Height;
int Channels;
QString Facility_Name;
int Seed_Rand;
int Num_Epochs;
int Num_Batch;
int Num_Iterations;
double Learning_Rate;
QString Correlation_Splitting;
QString Current_State;
QString Operating_State;
int Current_Schedule;
QString Current_Assessment;
XProgres Progres;
};
//! 自定义多重结构体
struct DictHandData
{
int ProjectType;
QString ProjectName;
QString ProjectPath;
QString ProjectDir;
QString ProjectNode;
//! 图元集合
QList<MapDepot> MapDepotLists;
QList<Classes> ClassessLists;
QList<Splits> SplitItems;
QList<Trains> TrainingModel;
};
2.重写operator <<和>>操作符
通过重写operator <<和 operator >>操作符实现结构体的序列化与反序列化:
注意:操作符函数声明为 inline,防止多重定义:
看着写的多,实际上千篇一律,按照顺序输出,写入就行了。
cpp
//! 操作符函数声明为 inline,防止多重定义:
//! 定义写入MapDepot
inline QDataStream& operator<<(QDataStream& out, const MapDepot& config) {
out << config.image_id << config.image_file_name
<< config.image_label_id << config.split;
return out;
}
//! 定义读取MapDepot
inline QDataStream& operator>>(QDataStream& in, MapDepot& config) {
in >> config.image_id >> config.image_file_name
>> config.image_label_id >> config.split;
return in;
}
//! 定义写入 Classes
inline QDataStream& operator<<(QDataStream& out, const Classes& config) {
out << config.class_names << config.class_ids
<< config.class_color << config.shortcutkey;
return out;
}
//! 定义读取 Classes
inline QDataStream& operator>>(QDataStream& in, Classes& config) {
in >> config.class_names >> config.class_ids
>> config.class_color >> config.shortcutkey;
return in;
}
//! 定义写入 Splits
inline QDataStream& operator<<(QDataStream& out, const Splits& config) {
out << config.split_name
<< config.train_num << config.train_percentum
<< config.validation_num << config.validation_percentum
<< config.test_num << config.test_percentum;
return out;
}
//! 定义读取 Splits
inline QDataStream& operator>>(QDataStream& in, Splits& config) {
in >> config.split_name
>> config.train_num >> config.train_percentum
>> config.validation_num >> config.validation_percentum
>> config.test_num >> config.test_percentum;
return in;
}
//! 定义写入 TrainInfo
inline QDataStream& operator<<(QDataStream& out, const TrainInfo& config) {
out << config.epoch<< config.num_epochs
<< config.num_iterations_per_epoch << config.mean_loss
<< config.mean_loss_samples << config.start_epoch
<< config.start_time << config.time_elapsed;
return out;
}
//! 定义读取 TrainInfo
inline QDataStream& operator>>(QDataStream& in, TrainInfo& config) {
in >> config.epoch >> config.num_epochs
>> config.num_iterations_per_epoch >> config.mean_loss
>> config.mean_loss_samples >> config.start_epoch
>> config.start_time >> config.time_elapsed;
return in;
}
//! 定义写入 XProgres
inline QDataStream& operator<<(QDataStream& out, const XProgres& config) {
out << config.Natural_Model_Path<< config.ExampleDataDir
<< config.DL_Dataset << config.DL_Preprocess_Param
<< config.Current_State << config.Operating_State
<< config.TrainInfos;
return out;
}
//! 定义读取 XProgres
inline QDataStream& operator>>(QDataStream& in, XProgres& config) {
in >> config.Natural_Model_Path >> config.ExampleDataDir
>> config.DL_Dataset >> config.DL_Preprocess_Param
>> config.Current_State >> config.Operating_State
>> config.TrainInfos;
return in;
}
//! 定义写入 Trains
inline QDataStream& operator<<(QDataStream& out, const Trains& config) {
out << config.Train_Name<< config.Natural_Model
<< config.Image_Width << config.Image_Height
<< config.Channels << config.Facility_Name
<< config.Seed_Rand << config.Num_Epochs
<< config.Num_Batch << config.Num_Iterations
<< config.Learning_Rate << config.Correlation_Splitting
<< config.Current_State << config.Operating_State
<< config.Current_Schedule << config.Current_Assessment
<< config.Progres;
return out;
}
//! 定义读取 Trains
inline QDataStream& operator>>(QDataStream& in, Trains& config) {
in >> config.Train_Name >> config.Natural_Model
>> config.Image_Width >> config.Image_Height
>> config.Channels >> config.Facility_Name
>> config.Seed_Rand >> config.Num_Epochs
>> config.Num_Batch >> config.Num_Iterations
>> config.Learning_Rate >> config.Correlation_Splitting
>> config.Current_State >> config.Operating_State
>> config.Current_Schedule >> config.Current_Assessment
>> config.Progres;
return in;
}
//! 定义写入 DictHandData
inline QDataStream& operator<<(QDataStream& out, const DictHandData& config) {
out << config.ProjectType<< config.ProjectName
<< config.ProjectPath << config.ProjectDir
<< config.ProjectNode << config.MapDepotLists
<< config.ClassessLists << config.SplitItems
<< config.TrainingModel;
return out;
}
//! 定义读取 DictHandData
inline QDataStream& operator>>(QDataStream& in, DictHandData& config) {
in >> config.ProjectType >> config.ProjectName
>> config.ProjectPath >> config.ProjectDir
>> config.ProjectNode >> config.MapDepotLists
>> config.ClassessLists >> config.SplitItems
>> config.TrainingModel;
return in;
}
而通过这种方式写入保存的数据,在txt文本中依旧能看到具体的文件路径或名称,这得修改一下,至少内容不可见。
2.从新修改operator 操作符 使用Base64简单加密字符串
使用Base64和utf8简单加密字符串防止出现具体内容。
甚至可以使用其他的加密库实现.这里只介绍了最简单的用法
cpp
//! 使用Base64加密
//! 操作符函数声明为 inline,防止多重定义:
//! 定义写入MapDepot
inline QDataStream& operator<<(QDataStream& out, const MapDepot& config) {
out << config.image_id << config.image_file_name.toUtf8().toBase64()
<< config.image_label_id << config.split.toUtf8().toBase64();
return out;
}
//! 定义读取MapDepot
inline QDataStream& operator>>(QDataStream& in, MapDepot& config) {
QByteArray image_file_name;
QByteArray split;
in >> config.image_id >> image_file_name
>> config.image_label_id >> split;
config.image_file_name=QString::fromUtf8(QByteArray::fromBase64(image_file_name));
config.split=QString::fromUtf8(QByteArray::fromBase64(split));
return in;
}
//! 定义写入 Classes
inline QDataStream& operator<<(QDataStream& out, const Classes& config) {
out << config.class_names.toUtf8().toBase64() << config.class_ids
<< config.class_color.toUtf8().toBase64() << config.shortcutkey.toUtf8().toBase64();
return out;
}
//! 定义读取 Classes
inline QDataStream& operator>>(QDataStream& in, Classes& config) {
QByteArray class_names;
QByteArray class_color;
QByteArray shortcutkey;
in >> class_names >> config.class_ids
>> class_color >> shortcutkey;
config.class_names=QString::fromUtf8(QByteArray::fromBase64(class_names));
config.class_color=QString::fromUtf8(QByteArray::fromBase64(class_color));
config.shortcutkey=QString::fromUtf8(QByteArray::fromBase64(shortcutkey));
return in;
}
//! 定义写入 Splits
inline QDataStream& operator<<(QDataStream& out, const Splits& config) {
out << config.split_name.toUtf8().toBase64()
<< config.train_num << config.train_percentum
<< config.validation_num << config.validation_percentum
<< config.test_num << config.test_percentum;
return out;
}
//! 定义读取 Splits
inline QDataStream& operator>>(QDataStream& in, Splits& config) {
QByteArray split_name;
in >> split_name
>> config.train_num >> config.train_percentum
>> config.validation_num >> config.validation_percentum
>> config.test_num >> config.test_percentum;
config.split_name=QString::fromUtf8(QByteArray::fromBase64(split_name));
return in;
}
//! 定义写入 TrainInfo
inline QDataStream& operator<<(QDataStream& out, const TrainInfo& config) {
out << config.epoch<< config.num_epochs
<< config.num_iterations_per_epoch << config.mean_loss
<< config.mean_loss_samples << config.start_epoch
<< config.start_time << config.time_elapsed;
return out;
}
//! 定义读取 TrainInfo
inline QDataStream& operator>>(QDataStream& in, TrainInfo& config) {
in >> config.epoch >> config.num_epochs
>> config.num_iterations_per_epoch >> config.mean_loss
>> config.mean_loss_samples >> config.start_epoch
>> config.start_time >> config.time_elapsed;
return in;
}
//! 定义写入 XProgres
inline QDataStream& operator<<(QDataStream& out, const XProgres& config) {
out << config.Natural_Model_Path.toUtf8().toBase64()<< config.ExampleDataDir.toUtf8().toBase64()
<< config.DL_Dataset.toUtf8().toBase64() << config.DL_Preprocess_Param.toUtf8().toBase64()
<< config.Current_State.toUtf8().toBase64() << config.Operating_State.toUtf8().toBase64()
<< config.TrainInfos;
return out;
}
//! 定义读取 XProgres
inline QDataStream& operator>>(QDataStream& in, XProgres& config) {
QByteArray Natural_Model_Path;
QByteArray ExampleDataDir;
QByteArray DL_Dataset;
QByteArray DL_Preprocess_Param;
QByteArray Current_State;
QByteArray Operating_State;
in >> Natural_Model_Path >> ExampleDataDir
>> DL_Dataset >> DL_Preprocess_Param
>> Current_State >> Operating_State
>> config.TrainInfos;
config.Natural_Model_Path=QString::fromUtf8(QByteArray::fromBase64(Natural_Model_Path));
config.ExampleDataDir=QString::fromUtf8(QByteArray::fromBase64(ExampleDataDir));
config.DL_Dataset=QString::fromUtf8(QByteArray::fromBase64(DL_Dataset));
config.DL_Preprocess_Param=QString::fromUtf8(QByteArray::fromBase64(DL_Preprocess_Param));
config.Current_State=QString::fromUtf8(QByteArray::fromBase64(Current_State));
config.Operating_State=QString::fromUtf8(QByteArray::fromBase64(Operating_State));
return in;
}
//! 定义写入 Trains
inline QDataStream& operator<<(QDataStream& out, const Trains& config) {
out << config.Train_Name.toUtf8().toBase64()<< config.Natural_Model.toUtf8().toBase64()
<< config.Image_Width << config.Image_Height
<< config.Channels << config.Facility_Name.toUtf8().toBase64()
<< config.Seed_Rand << config.Num_Epochs
<< config.Num_Batch << config.Num_Iterations
<< config.Learning_Rate << config.Correlation_Splitting.toUtf8().toBase64()
<< config.Current_State.toUtf8().toBase64() << config.Operating_State.toUtf8().toBase64()
<< config.Current_Schedule << config.Current_Assessment.toUtf8().toBase64()
<< config.Progres;
return out;
}
//! 定义读取 Trains
inline QDataStream& operator>>(QDataStream& in, Trains& config) {
QByteArray Train_Name;
QByteArray Natural_Model;
QByteArray Facility_Name;
QByteArray Correlation_Splitting;
QByteArray Current_State;
QByteArray Operating_State;
QByteArray Current_Assessment;
in >> Train_Name >> Natural_Model
>> config.Image_Width >> config.Image_Height
>> config.Channels >> Facility_Name
>> config.Seed_Rand >> config.Num_Epochs
>> config.Num_Batch >> config.Num_Iterations
>> config.Learning_Rate >> Correlation_Splitting
>> Current_State >> Operating_State
>> config.Current_Schedule >> Current_Assessment
>> config.Progres;
config.Train_Name=QString::fromUtf8(QByteArray::fromBase64(Train_Name));
config.Natural_Model=QString::fromUtf8(QByteArray::fromBase64(Natural_Model));
config.Facility_Name=QString::fromUtf8(QByteArray::fromBase64(Facility_Name));
config.Correlation_Splitting=QString::fromUtf8(QByteArray::fromBase64(Correlation_Splitting));
config.Current_State=QString::fromUtf8(QByteArray::fromBase64(Current_State));
config.Operating_State=QString::fromUtf8(QByteArray::fromBase64(Operating_State));
config.Current_Assessment=QString::fromUtf8(QByteArray::fromBase64(Current_Assessment));
return in;
}
//! 定义写入 DictHandData
inline QDataStream& operator<<(QDataStream& out, const DictHandData& config) {
out << config.ProjectType<< config.ProjectName.toUtf8().toBase64()
<< config.ProjectPath.toUtf8().toBase64() << config.ProjectDir.toUtf8().toBase64()
<< config.ProjectNode.toUtf8().toBase64() << config.MapDepotLists
<< config.ClassessLists << config.SplitItems
<< config.TrainingModel;
return out;
}
//! 定义读取 DictHandData
inline QDataStream& operator>>(QDataStream& in, DictHandData& config) {
QByteArray ProjectName;
QByteArray ProjectPath;
QByteArray ProjectDir;
QByteArray ProjectNode;
in >> config.ProjectType >> ProjectName
>> ProjectPath >> ProjectDir
>> ProjectNode >> config.MapDepotLists
>> config.ClassessLists >> config.SplitItems
>> config.TrainingModel;
config.ProjectName=QString::fromUtf8(QByteArray::fromBase64(ProjectName));
config.ProjectPath=QString::fromUtf8(QByteArray::fromBase64(ProjectPath));
config.ProjectDir=QString::fromUtf8(QByteArray::fromBase64(ProjectDir));
config.ProjectNode=QString::fromUtf8(QByteArray::fromBase64(ProjectNode));
return in;
}
#endif
使用 QDataSteam 序列化结构体
使用 QDataSteam 序列化结构体快速写入文本文件中:
cpp
QFile file("HandDatas.txt");
DictHandData HandDatas;
//! 确保HandDatas结构体有数据
if (file.open(QIODevice::WriteOnly)) {
QDataStream out(&file);
out.setByteOrder(QDataStream::BigEndian);
out.setVersion(QDataStream::Qt_5_13);
out<<HandDatas;
file.close();
}
使用 QDataSteam 反序列化结构体
使用 QDataSteam 从文件中加载结构体数据:
cpp
QFile file("HandDatas.txt");
DictHandData HandDatas;
if (file.open(QIODevice::ReadOnly)) {
QDataStream out(&file);
out.setByteOrder(QDataStream::BigEndian);
out.setVersion(QDataStream::Qt_5_13);
out>>HandDatas;
file.close();
}
简单,快速,高效!
三、其他
1.重写QDebug& operator<<操作符,打印结构体
为了快速的验证数据经过序列化和反序列化之后有没有问题,
于是又重写 inline QDebug& operator<<(QDebug& out, const 结构体& config)方法
实现直接qDebug()i打印结构体中的数据。
cpp
//! 定义打印输出
inline QDebug& operator<<(QDebug& out, const MapDepot& config) {
QDebugStateSaver saver(out); // 保存调试状态
out.nospace(); // 禁止自动添加空格
out << "MapDepot("
<< "\n image_id: " << config.image_id
<< "\n image_file_name: " << config.image_file_name
<< "\n image_label_id: " << config.image_label_id
<< "\n split: " << config.split
<< "\n)";
return out;
}
inline QDebug& operator<<(QDebug& out, const Classes& config) {
QDebugStateSaver saver(out); // 保存调试状态
out.nospace(); // 禁止自动添加空格
out << "Classes("
<< "\n class_names: " << config.class_names
<< "\n class_ids: " << config.class_ids
<< "\n class_color: " << config.class_color
<< "\n shortcutkey: " << config.shortcutkey
<< "\n)";
return out;
}
inline QDebug& operator<<(QDebug& out, const Splits& config) {
QDebugStateSaver saver(out); // 保存调试状态
out.nospace(); // 禁止自动添加空格
out << "Splits("
<< "\n split_name: " << config.split_name
<< "\n train_num: " << config.train_num
<< "\n train_percentum: " << config.train_percentum
<< "\n validation_num: " << config.validation_num
<< "\n validation_percentum: " << config.validation_percentum
<< "\n test_num: " << config.test_num
<< "\n test_percentum: " << config.test_percentum
<< "\n)";
return out;
}
inline QDebug& operator<<(QDebug& out, const TrainInfo& config) {
QDebugStateSaver saver(out); // 保存调试状态
out.nospace(); // 禁止自动添加空格
out << "TrainInfo("
<< "\n epoch: " << config.epoch
<< "\n num_epochs: " << config.num_epochs
<< "\n num_iterations_per_epoch: " << config.num_iterations_per_epoch
<< "\n mean_loss: " << config.mean_loss
<< "\n mean_loss_samples: " << config.mean_loss_samples
<< "\n start_epoch: " << config.start_epoch
<< "\n start_time: " << config.start_time
<< "\n time_elapsed: " << config.time_elapsed
<< "\n)";
return out;
}
inline QDebug& operator<<(QDebug& out, const XProgres& config) {
QDebugStateSaver saver(out); // 保存调试状态
out.nospace(); // 禁止自动添加空格
out << "XProgres("
<< "\n Natural_Model_Path: " << config.Natural_Model_Path
<< "\n ExampleDataDir: " << config.ExampleDataDir
<< "\n DL_Dataset: " << config.DL_Dataset
<< "\n DL_Preprocess_Param: " << config.DL_Preprocess_Param
<< "\n Current_State: " << config.Current_State
<< "\n Operating_State: " << config.Operating_State
<< "\n TrainInfos: " << config.TrainInfos
<< "\n)";
return out;
}
inline QDebug& operator<<(QDebug& out, const Trains& config) {
QDebugStateSaver saver(out); // 保存调试状态
out.nospace(); // 禁止自动添加空格
out << "Trains("
<< "\n Train_Name: " << config.Train_Name
<< "\n Natural_Model: " << config.Natural_Model
<< "\n Image_Width: " << config.Image_Width
<< "\n Image_Height: " << config.Image_Height
<< "\n Channels: " << config.Channels
<< "\n Facility_Name: " << config.Facility_Name
<< "\n Seed_Rand: " << config.Seed_Rand
<< "\n Num_Epochs: " << config.Num_Epochs
<< "\n Num_Batch: " << config.Num_Batch
<< "\n Num_Iterations: " << config.Num_Iterations
<< "\n Learning_Rate: " << config.Learning_Rate
<< "\n Correlation_Splitting: " << config.Correlation_Splitting
<< "\n Current_State: " << config.Current_State
<< "\n Operating_State: " << config.Operating_State
<< "\n Current_Schedule: " << config.Current_Schedule
<< "\n Current_Assessment: " << config.Current_Assessment
<< "\n Progres: " << config.Progres
<< "\n)";
return out;
}
inline QDebug& operator<<(QDebug& out, const DictHandData& config) {
QDebugStateSaver saver(out); // 保存调试状态
out.nospace(); // 禁止自动添加空格
out << "DictHandData("
<< "\n ProjectType: " << config.ProjectType
<< "\n ProjectName: " << config.ProjectName
<< "\n ProjectPath: " << config.ProjectPath
<< "\n ProjectDir: " << config.ProjectDir
<< "\n ProjectNode: " << config.ProjectNode
<< "\n MapDepotLists: " << config.MapDepotLists
<< "\n ClassessLists: " << config.ClassessLists
<< "\n SplitItems: " << config.SplitItems
<< "\n TrainingModel: " << config.TrainingModel
<< "\n)";
return out;
}
调用
打印所有数据
cpp
//!同HTuple字典数据字段 结构体
DictHandData HandDatas;
qDebug()<<" <- DictHandData -> ";
qDebug().noquote() <<HandDatas;
总结
通过QDataSteam序列化与反序列化项目结构体,能最大的减少当结构体发生改变的时候,重新修改加载和保存函数。减少工作量。