1041 lines
32 KiB
C++
1041 lines
32 KiB
C++
#include "SARImage/FEKOBaseToolClass.h"
|
||
#include <math.h>
|
||
#include "BaseToolLib/BaseConstVariable.h"
|
||
#include <QMessageBox>
|
||
#include <math.h>
|
||
#include <complex>
|
||
#include "BaseToollib/ImageOperatorBase.h"
|
||
#include <SARBaseToolLib/SARImageBase.h>
|
||
#include "SARBaseToolLib/SARBaseTool.h"
|
||
#include "BaseToollib/FileOperator.h"
|
||
#include <QtXml/qdom.h>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
QString FEKOBase::FEKOImageModeenumToString(FEKOBase::FEKOImageMode mode)
|
||
{
|
||
switch (mode) {
|
||
case Strip:
|
||
return "STRIP";
|
||
case Scane:
|
||
return "SCANE";
|
||
case ISAR:
|
||
return "ISAR";
|
||
case CircleSAR:
|
||
return "CircleSAR";
|
||
}
|
||
// 如果枚举值不匹配任何字符串,则返回一个默认值,或者抛出异常
|
||
return "UNKNOW"; // 默认返回Unknown
|
||
}
|
||
|
||
FEKOBase::FEKOCoordinateSystem FEKOBase::FEKOCoordinateSystemString2Enum(QString str)
|
||
{
|
||
if (str.toUpper() == "SPHERICAL") { return FEKOBase::Spherical; }
|
||
else if (str.toUpper() == "CARTESIAN") { return FEKOBase::Cartesian; }
|
||
else {
|
||
return FEKOBase::UNKONWFEKOCOORDINATESYSTEM;
|
||
}
|
||
|
||
}
|
||
|
||
QString FEKOBase::QString2FEKOCoordinateSystem(FEKOBase::FEKOCoordinateSystem mode)
|
||
{
|
||
switch (mode) {
|
||
case FEKOBase::Spherical:
|
||
return "SPHERICAL";
|
||
case FEKOBase::Cartesian:
|
||
return "CARTESIAN";
|
||
default:
|
||
return "UNKONWFEKOCOORDINATESYSTEM";
|
||
|
||
}
|
||
}
|
||
|
||
FEKOBase::FEKOImageMode FEKOBase::FEKOImageModeString2Enum(QString str)
|
||
{
|
||
if (str.toUpper() == "STRIP") {
|
||
return FEKOBase::FEKOImageMode::Strip;
|
||
}
|
||
else if (str.toUpper() == "SCANE") {
|
||
return FEKOBase::FEKOImageMode::Scane;
|
||
}
|
||
else if (str.toUpper() == "ISAR") {
|
||
return FEKOBase::FEKOImageMode::ISAR;
|
||
}
|
||
else if (str.toUpper() == "CIRCLESAR") {
|
||
return FEKOBase::FEKOImageMode::CircleSAR;
|
||
}
|
||
// 如果输入的字符串不匹配任何枚举值,则返回一个默认值,或者抛出异常
|
||
return FEKOBase::FEKOImageMode::UNKNOW; // 默认返回UNKNOW
|
||
}
|
||
|
||
FEKOBase::freqParams FEKOBase::getFreqSetting(double centerFreq, double resolution, double bandWidth, double scenceRange, bool isResolution) {
|
||
|
||
FEKOBase::freqParams result{ 0,0,0 };
|
||
{
|
||
if (isResolution) {
|
||
bandWidth = 0.299792458 / 2 / resolution; // 计算带宽
|
||
}
|
||
else {
|
||
resolution = 0.299792458 / 2 / bandWidth; // 计算分辨率
|
||
}
|
||
}
|
||
size_t samplePoint = std::ceil((scenceRange) / resolution) + 1;
|
||
result.startfreqs = centerFreq - 0.5 * bandWidth;
|
||
result.endfreqs = centerFreq + 0.5 * bandWidth;
|
||
result.freqpoint = samplePoint;
|
||
return result;
|
||
}
|
||
|
||
FEKOBase::FEKOSatelliteParams FEKOBase::createFEKOSatelliteParams(double Px, double Py, double Pz, double Vx, double Vy, double Vz, double incidenceAngle, double AzAngle, double theta, double phi, bool isRight, size_t PRFIdx)
|
||
{
|
||
FEKOBase::FEKOSatelliteParams result{
|
||
PRFIdx,
|
||
FEKOBase::SatelliteState{
|
||
FEKOBase::SatellitePosition{Px,Py,Pz},
|
||
FEKOBase::SatelliteVelocity{Vx,Vy,Vz}
|
||
},
|
||
incidenceAngle,AzAngle,
|
||
FEKOBase::FEKOantPitionDirect{Px,Py,Pz,theta,phi},
|
||
isRight
|
||
};
|
||
return result;
|
||
}
|
||
|
||
FEKOBase::FEKOSatelliteParams FEKOBase::createFEKOSatelliteParams(SatelliteState pose, double incidenceAngle, double AzAngle, FEKOantPitionDirect antpos, size_t PRFIdx)
|
||
{
|
||
FEKOBase::FEKOSatelliteParams result{
|
||
PRFIdx,pose,incidenceAngle,AzAngle,antpos
|
||
};
|
||
return result;
|
||
}
|
||
|
||
FEKOBase::SatelliteState FEKOBase::FEKOSatelliteParams2SatelliteState(FEKOSatelliteParams parmas)
|
||
{
|
||
return parmas.pose;
|
||
}
|
||
|
||
FEKOBase::FEKOantPitionDirect FEKOBase::FEKOSatelliteParams2FEKOantPitionDirect(FEKOSatelliteParams parmas)
|
||
{
|
||
return parmas.antpos;
|
||
}
|
||
|
||
TopoDS_Shape FEKOBase::SatellitePos2FEKOAntPos(SatelliteState satepos, double incidenceAngle, double AzAngle, bool isRIGHT, FEKOantPitionDirect* antposition_Direct, TopoDS_Shape antModel)
|
||
{
|
||
incidenceAngle = incidenceAngle * M_PI / 180; // 转换为弧度
|
||
AzAngle = AzAngle * M_PI / 180; // 扫描角度转换为弧度
|
||
TopoDS_Shape tempShape;
|
||
if (!antModel.IsNull()) {
|
||
// 创建一个复制
|
||
BRepBuilderAPI_Copy copyBuilder(antModel);
|
||
tempShape = copyBuilder.Shape();
|
||
}
|
||
|
||
double Sx = satepos.pos.Px;
|
||
double Sy = satepos.pos.Py;
|
||
double Sz = satepos.pos.Pz;
|
||
double Vx = satepos.vel.Vx;
|
||
double Vy = satepos.vel.Vy;
|
||
double Vz = satepos.vel.Vz;
|
||
//qDebug() << u8"// 0. 卫星状态矢量";
|
||
gp_Vec SateVelocity(gp_Pnt(0, 0, 0), gp_Pnt(Vx, Vy, Vz)); // 卫星速度矢量
|
||
gp_Vec SatePosition(gp_Pnt(0, 0, 0), gp_Pnt(Sx, Sy, Sz)); // 卫星位置矢量
|
||
gp_Vec sch_X(gp_Pnt(0, 0, 0), gp_Pnt(1.0, 0.0, 0.0));
|
||
gp_Vec sch_Y(gp_Pnt(0, 0, 0), gp_Pnt(0.0, 1.0, 0.0)); // 飞行方向 y
|
||
gp_Vec sch_Z(gp_Pnt(0, 0, 0), gp_Pnt(0.0, 0.0, 1.0)); // 雷达照射方向
|
||
|
||
// qDebug() << u8"// 1. 卫星坐标系 sch -->飞行坐标系 fly 保证Z轴指向不变化";
|
||
gp_Vec sch_X_fly;
|
||
gp_Vec sch_Y_fly; // 飞行向
|
||
gp_Vec sch_Z_fly;
|
||
|
||
{
|
||
CartesianCoordinates Sp_car{ sch_Y.X(),sch_Y.Y(), sch_Y.Z() };
|
||
CartesianCoordinates tp_car{ SateVelocity.X(),SateVelocity.Y(), SateVelocity.Z() };
|
||
|
||
SphericalCoordinates sp_sph = cartesianToSpherical(Sp_car);
|
||
SphericalCoordinates tp_sph = cartesianToSpherical(tp_car);
|
||
|
||
// 计算
|
||
double delta_theta = tp_sph.theta - sp_sph.theta;
|
||
double delta_phi = tp_sph.phi - sp_sph.phi;
|
||
|
||
gp_Trsf rotationTransform_theta;
|
||
rotationTransform_theta.SetRotation(gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(0, 1, 0)), delta_theta); // 绕 y 轴旋转
|
||
sch_X_fly = sch_X.Transformed(rotationTransform_theta);
|
||
sch_Y_fly = sch_Y.Transformed(rotationTransform_theta);
|
||
sch_Z_fly = sch_Z.Transformed(rotationTransform_theta);
|
||
|
||
gp_Trsf rotationTransform_phi;
|
||
rotationTransform_phi.SetRotation(gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), delta_phi); // 绕 z 轴旋转
|
||
sch_X_fly = sch_X_fly.Transformed(rotationTransform_phi);
|
||
sch_Y_fly = sch_Y_fly.Transformed(rotationTransform_phi);
|
||
sch_Z_fly = sch_Z_fly.Transformed(rotationTransform_phi);
|
||
|
||
if (!tempShape.IsNull()) {
|
||
BRepBuilderAPI_Transform shapeTransform_theta(tempShape, rotationTransform_theta);
|
||
tempShape = shapeTransform_theta.Shape();
|
||
BRepBuilderAPI_Transform shapeTransform_phi(tempShape, rotationTransform_phi);
|
||
tempShape = shapeTransform_phi.Shape();
|
||
}
|
||
}
|
||
|
||
// qDebug() << u8"// 2. 根据方位角与俯仰角,调整雷达姿态 --- 此步确定 Y 轴已经调整完毕 ";
|
||
// qDebug() << u8"// 2. a 根据 incidenceAngle 调整 Z 的指向,需要先根据左右视判断出雷达照射方向";
|
||
|
||
{ // 按照 Y 轴进行计算
|
||
incidenceAngle = M_PI - incidenceAngle; // 下Z轴
|
||
Standard_Real ZRotation_angle = 0;
|
||
if (isRIGHT) { // 右视 +
|
||
ZRotation_angle = incidenceAngle;
|
||
}
|
||
else { // 左视 -
|
||
ZRotation_angle = -1 * incidenceAngle;
|
||
}
|
||
gp_Trsf fly_incidence_trsf;
|
||
fly_incidence_trsf.SetRotation(gp_Ax1(gp_Pnt(0, 0, 0), sch_Y_fly), ZRotation_angle); // 计算入射角
|
||
|
||
sch_X_fly = sch_X_fly.Transformed(fly_incidence_trsf);
|
||
sch_Y_fly = sch_Y_fly.Transformed(fly_incidence_trsf);
|
||
sch_Z_fly = sch_Z_fly.Transformed(fly_incidence_trsf); // 此时获取雷达的照射方向
|
||
|
||
if (!tempShape.IsNull()) {
|
||
BRepBuilderAPI_Transform shapeTransform_incidence(tempShape, fly_incidence_trsf); // fly_Z --> incidenceAngle
|
||
tempShape = shapeTransform_incidence.Shape();
|
||
}
|
||
|
||
}
|
||
|
||
// qDebug() << u8"// 2.b 根据 AzAngle 调整 Z 的指向 ";
|
||
// qDebug() << u8"// Az 应该变化在 YoZ, 也就是绕 X 轴 旋转;";
|
||
|
||
{ // 沿Z 轴进行计算
|
||
gp_Trsf fly_AZ_trsf;
|
||
fly_AZ_trsf.SetRotation(gp_Ax1(gp_Pnt(0, 0, 0), sch_X_fly), AzAngle); // 计算方位角变化
|
||
|
||
sch_X_fly = sch_X_fly.Transformed(fly_AZ_trsf);
|
||
sch_Y_fly = sch_Y_fly.Transformed(fly_AZ_trsf);
|
||
sch_Z_fly = sch_Z_fly.Transformed(fly_AZ_trsf); // 此时获取雷达的照射方向
|
||
|
||
if (!tempShape.IsNull()) {
|
||
BRepBuilderAPI_Transform shapeTransform_AZ(tempShape, fly_AZ_trsf); // fly_Z --> incidenceAngle
|
||
tempShape = shapeTransform_AZ.Shape(); // 旋转卫星模型
|
||
}
|
||
|
||
}
|
||
// qDebug() << u8"// 2.c 参数记录 ";
|
||
{
|
||
CartesianCoordinates Sp_car{ 0,0,1 };
|
||
CartesianCoordinates tp_car{ sch_Z_fly.X(),sch_Z_fly.Y(), sch_Z_fly.Z() };
|
||
|
||
SphericalCoordinates sp_sph = cartesianToSpherical(Sp_car);
|
||
SphericalCoordinates tp_sph = cartesianToSpherical(tp_car); // 计算phi角度
|
||
|
||
double delta_theta = tp_sph.theta - sp_sph.theta;
|
||
double delta_phi = tp_sph.phi - sp_sph.phi;
|
||
|
||
antposition_Direct->x = Sx; //-- FEKO 设置
|
||
antposition_Direct->y = Sy; //-- FEKO 设置
|
||
antposition_Direct->z = Sz; //-- FEKO 设置
|
||
antposition_Direct->theta = delta_theta / M_PI * 180; //-- FEKO 设置 theta
|
||
antposition_Direct->phi = delta_phi / M_PI * 180;//--- FEKO 设置 phi
|
||
|
||
}
|
||
// qDebug() << u8"//3. 执行模型平移";
|
||
{
|
||
if (!tempShape.IsNull()) {
|
||
gp_Trsf fly_move_trsf;
|
||
fly_move_trsf.SetTranslation(SatePosition);
|
||
BRepBuilderAPI_Transform shapeTransform_move(tempShape, fly_move_trsf); // fly_Z --> incidenceAngle
|
||
tempShape = shapeTransform_move.Shape(); // 平移卫星模型
|
||
|
||
}
|
||
}
|
||
|
||
qDebug() << QString(u8"雷达坐标与姿态(X,Y,Z,theta,phi): (%1,%2,%3,%4,%5)").arg(antposition_Direct->x)
|
||
.arg(antposition_Direct->y)
|
||
.arg(antposition_Direct->z)
|
||
.arg(antposition_Direct->theta)
|
||
.arg(antposition_Direct->phi);
|
||
|
||
return tempShape;
|
||
}
|
||
|
||
bool FEKOBase::compareElectricFieldDataInFreq(const ElectricFieldData& a, const ElectricFieldData& b)
|
||
{
|
||
return a.frequency < b.frequency;
|
||
}
|
||
|
||
bool FEKOBase::comparePRFPluseDataInPRFIdx(const PRFPluseData& a, const PRFPluseData& b)
|
||
{
|
||
return a.prfidx < b.prfidx;
|
||
}
|
||
|
||
FEKOBase::NearFieldEchoCSVParser::NearFieldEchoCSVParser()
|
||
{
|
||
}
|
||
|
||
FEKOBase::NearFieldEchoCSVParser::~NearFieldEchoCSVParser()
|
||
{
|
||
}
|
||
|
||
bool FEKOBase::NearFieldEchoCSVParser::checkPRFModel()
|
||
{
|
||
|
||
qDebug() << u8"正在检查是否可以采用脉冲计数模式 configuration Name :PRF_{脉冲计数}";
|
||
|
||
QRegExp regex("(\\d+)");
|
||
// 判断是否需要按照脉冲次序排序
|
||
bool usePRFbool = true;
|
||
QMap<QString, size_t> configName_prfidx;
|
||
// 使用迭代器遍历 QMap
|
||
QMap<QString, std::vector<ElectricFieldData>>::const_iterator it;
|
||
for (it = this->electricFieldDataList.constBegin(); it != this->electricFieldDataList.constEnd(); ++it) {
|
||
for (size_t i = 0; i < this->electricFieldDataList[it.key()].size(); i++) {
|
||
QString value = this->electricFieldDataList[it.key()][i].configurationName;
|
||
if (value.indexOf("PRF") != -1) {
|
||
if (regex.indexIn(value) != -1) {
|
||
// 提取匹配到的部分
|
||
QString matchedText = regex.cap(1);
|
||
|
||
size_t PRFidx = matchedText.toInt(&usePRFbool);
|
||
if (usePRFbool) {
|
||
configName_prfidx.insert(this->electricFieldDataList[it.key()][i].configurationName, PRFidx);
|
||
}
|
||
else {
|
||
qDebug() << u8"不能采用脉冲计数模型";
|
||
QMessageBox::information(nullptr, u8"警告", u8"无法根据Configuration Name识别脉冲顺序,按照读取顺序,计数PRF", QMessageBox::Ok);
|
||
this->usePRFCountMode = false;
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
qDebug() << u8"不能采用脉冲计数模型";
|
||
QMessageBox::information(nullptr, u8"警告", u8"无法根据Configuration Name识别脉冲顺序,按照读取顺序,计数PRF", QMessageBox::Ok);
|
||
this->usePRFCountMode = false;
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 更新prfidx
|
||
for (it = this->electricFieldDataList.constBegin(); it != this->electricFieldDataList.constEnd(); ++it) {
|
||
if (!(this->electricFieldDataList[it.key()].size() > 0)) {
|
||
QMessageBox::warning(nullptr, u8"错误", u8"发现空脉冲:" + it.key());
|
||
qWarning() << u8"发现空脉冲:" + it.key();
|
||
return false;
|
||
}
|
||
else {}
|
||
|
||
QString value = this->electricFieldDataList[it.key()][0].configurationName;
|
||
|
||
for (size_t i = 0; i < this->electricFieldDataList[it.key()].size(); i++) {
|
||
if (value != this->electricFieldDataList[it.key()][0].configurationName) {
|
||
QMessageBox::warning(nullptr, u8"错误", u8"脉冲解析错误,名称不一致:" + it.key() + " | " + value);
|
||
qWarning() << u8"脉冲解析错误,名称不一致:" + it.key() + " | " + value;
|
||
}
|
||
else {}
|
||
size_t tempprfidx = configName_prfidx[value];
|
||
this->electricFieldDataList[it.key()][i].prfidx = tempprfidx;
|
||
}
|
||
}
|
||
|
||
qDebug() << u8"结束检查是否可以采用脉冲计数模式 configuration Name :PRF_{脉冲计数}";
|
||
return true;
|
||
}
|
||
|
||
bool FEKOBase::NearFieldEchoCSVParser::resizePRFPluse()
|
||
{
|
||
qDebug() << u8"根据数据文件,重新整理成脉冲形式";
|
||
|
||
QMap<QString, PRFPluseData> prfPluseMap; // 采用字典映射方式
|
||
|
||
qDebug() << u8"QMap<QString, std::vector<ElectricFieldData>> ==> QMap<QString, PRFPluseData>";
|
||
double px; // 2. 计算姿态,近场点坐标
|
||
double py;
|
||
double pz;
|
||
double R;
|
||
double theta; // x0y
|
||
double phi; // y0z
|
||
size_t PRFidx;
|
||
|
||
for (QMap<QString, std::vector<ElectricFieldData>>::const_iterator it = this->electricFieldDataList.constBegin(); it != this->electricFieldDataList.constEnd(); ++it) {
|
||
PRFPluseData temp;
|
||
std::vector<ElectricFieldData> tempData = this->electricFieldDataList[it.key()]; // 脉冲已经排序号
|
||
std::sort(tempData.begin(), tempData.end(), compareElectricFieldDataInFreq);
|
||
temp.electricFieldDataList = tempData; // 按照脉冲排序
|
||
|
||
temp.freqstart = tempData[0].frequency; // 1. 频率
|
||
temp.freqend = tempData[tempData.size() - 1].frequency;
|
||
temp.freqpoints = tempData.size();
|
||
|
||
px = tempData[0].origin.x; // 2. 近场接收点计算姿态,近场点坐标
|
||
py = tempData[0].origin.y;
|
||
pz = tempData[0].origin.z;
|
||
|
||
|
||
R = tempData[0].radius;
|
||
theta = tempData[0].theta; // x0y
|
||
phi = tempData[0].phi; // y0z
|
||
|
||
|
||
|
||
|
||
PRFidx = tempData[0].prfidx;
|
||
qDebug() << u8"分析姿态:" + it.key();
|
||
for (size_t i = 0; i < tempData.size(); i++) {
|
||
if (abs(px - tempData[i].origin.x) > 0.001 || abs(py - tempData[i].origin.y) > 0.001 ||
|
||
abs(pz - tempData[i].origin.z) > 0.001 || abs(R - tempData[i].radius) > 0.001 ||
|
||
abs(theta - tempData[i].theta) > 0.001 || abs(phi - tempData[i].phi) > 0.001)
|
||
{
|
||
qDebug() << u8"发现 configuration Name:" + it.key() + u8" , 发现问题,请检查";
|
||
QMessageBox::warning(nullptr, u8"警告", u8"发现 configuration Name:" + it.key() + u8" , 发现问题,请检查");
|
||
return false;
|
||
}
|
||
else {}
|
||
}
|
||
// 计算增量 R, theta, phi ==> delta_R,delta_theta,delta_phi
|
||
theta = theta * M_PI / 180;
|
||
phi = phi * M_PI / 180;
|
||
|
||
px = px + R * std::sin(theta) * std::cos(phi);
|
||
py = py + R * std::sin(theta) * std::sin(phi);
|
||
pz = pz + R * std::cos(theta);
|
||
|
||
temp.px = px;
|
||
temp.py = py;
|
||
temp.pz = pz;
|
||
temp.prfidx = PRFidx;
|
||
|
||
|
||
prfPluseMap.insert(it.key(), temp);
|
||
}
|
||
|
||
|
||
qDebug() << u8"判断是所有回波均一性";
|
||
this->prfData = std::vector<PRFPluseData>(0);
|
||
size_t freqpointnum = prfPluseMap.first().freqpoints;
|
||
for (QMap<QString, PRFPluseData>::const_iterator it = prfPluseMap.constBegin(); it != prfPluseMap.constEnd(); ++it) {
|
||
if (it.value().freqpoints != freqpointnum) {
|
||
qDebug() << u8"回波数据频点数不一致,无法进行脉冲计数";
|
||
QMessageBox::information(nullptr, u8"警告", u8"回波数据频点数不一致,无法进行脉冲计数", QMessageBox::Ok);
|
||
this->usePRFCountMode = false;
|
||
return false;
|
||
}
|
||
this->prfData.push_back(it.value());
|
||
}
|
||
this->freqPoints = freqpointnum;
|
||
std::sort(this->prfData.begin(), this->prfData.end(), comparePRFPluseDataInPRFIdx);
|
||
|
||
this->freqStart = this->prfData[0].freqstart;
|
||
this->freqEnd = this->prfData[0].freqend;
|
||
qDebug() << u8"根据数据文件,结束整理成脉冲形式";
|
||
return true;
|
||
|
||
}
|
||
|
||
bool FEKOBase::NearFieldEchoCSVParser::parseCSV(const QString& filePath)
|
||
{
|
||
|
||
std::vector<ElectricFieldData> dataList;
|
||
|
||
QFile file(filePath);
|
||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||
QTextStream in(&file);
|
||
|
||
// 读取标题行
|
||
QString headerLine = in.readLine();
|
||
QStringList headers = headerLine.split(QRegularExpression(",(?!\\s)"));
|
||
|
||
while (!in.atEnd()) {
|
||
QString line = in.readLine();
|
||
|
||
QStringList fields = line.split(QRegularExpression(",(?!\\s)"));
|
||
|
||
ElectricFieldData data;
|
||
// 解析数据根据列名
|
||
for (int i = 0; i < headers.size(); ++i) {
|
||
QString header = headers[i].trimmed();
|
||
QString value = fields[i];// .trimmed();
|
||
|
||
if (header == "File Type") {
|
||
data.fileType = value;
|
||
}
|
||
else if (header == "File Format") {
|
||
data.fileFormat = value;
|
||
}
|
||
else if (header == "Source") {
|
||
data.source = value;
|
||
}
|
||
else if (header == "Date") {
|
||
data.date = value;
|
||
}
|
||
else if (header == "Radius") { // 半径
|
||
data.radius = value.toDouble();
|
||
}
|
||
else if (header == "Theta") { // theta 角
|
||
data.theta = value.toDouble();
|
||
}
|
||
else if (header == "Phi") {// phi 角
|
||
data.phi = value.toDouble();
|
||
}
|
||
else if (header == "Re(Er)") {
|
||
data.reEr = value.toDouble();
|
||
}
|
||
else if (header == "Im(Er)") {
|
||
data.imEr = value.toDouble();
|
||
}
|
||
else if (header == "Re(Etheta)") {
|
||
data.reEtheta = value.toDouble();
|
||
}
|
||
else if (header == "Im(Etheta)") {
|
||
data.imEtheta = value.toDouble();
|
||
}
|
||
else if (header == "Re(Ephi)") {
|
||
data.reEphi = value.toDouble();
|
||
}
|
||
else if (header == "Im(Ephi)") {
|
||
data.imEphi = value.toDouble();
|
||
}
|
||
else if (header == "Configuration Name") { // 脉冲次序名称
|
||
data.configurationName = value.trimmed();
|
||
}
|
||
else if (header == "Request Name") {
|
||
data.requestName = value.trimmed();
|
||
}
|
||
else if (header == "Frequency") {
|
||
data.frequency = value.toDouble();
|
||
}
|
||
else if (header == "Coordinate System") {
|
||
data.coordinateSystem = value;
|
||
}
|
||
else if (header == "Origin") { // 坐标参考原点
|
||
QStringList vls = value.replace("\"", "").replace("(", "").replace(")", "").split(",");
|
||
if (vls.length() < 3) {
|
||
qDebug() << "******************** ERROR INFO ******************************************";
|
||
qDebug() << "origin point has error ," << value;
|
||
qDebug() << "line: " << line;
|
||
qDebug() << "head: " << header;
|
||
qDebug() << "***************************************************************************";
|
||
QMessageBox::information(nullptr, u8"警告", u8"无法解析Origin 参数,请检查", QMessageBox::Ok);
|
||
return false;
|
||
}
|
||
data.origin = Point_3d{ vls.at(0).toDouble(),
|
||
vls.at(1).toDouble(),
|
||
vls.at(2).toDouble() };
|
||
}
|
||
else if (header == "Num Radius Samples") {
|
||
data.numRadiusSamples = value.toInt();
|
||
}
|
||
else if (header == "Num Theta Samples") {
|
||
data.numThetaSamples = value.toInt();
|
||
}
|
||
else if (header == "Num Phi Samples") {
|
||
data.numPhiSamples = value.toInt();
|
||
}
|
||
else if (header == "Result Type") {
|
||
data.resultType = value;
|
||
}
|
||
else if (header == "Num Header Lines") {
|
||
data.numHeaderLines = value.toInt();
|
||
}
|
||
// 添加其他字段的解析...
|
||
}
|
||
dataList.push_back(data);
|
||
}
|
||
|
||
file.close();
|
||
}
|
||
else {
|
||
qDebug() << "Failed to open the file:" << file.errorString();
|
||
return false;
|
||
}
|
||
|
||
//this->electricFieldDataList = dataList;
|
||
|
||
qDebug() << u8"文件读取结果,对文件结果进行重新整理与检查";
|
||
//获取脉冲最小值,最大值,如果是 使用软件生产的 configname 应该为 PRF_1 PRF_2 这里通过判断 1,2 来确定脉冲序号
|
||
QSet<QString> configNameSet;
|
||
size_t curPRF = 0;
|
||
for (int i = 0; i < dataList.size(); i++) {
|
||
if (!configNameSet.contains(dataList[i].configurationName)) {
|
||
curPRF = curPRF + 1;
|
||
}
|
||
dataList[i].prfidx = curPRF;
|
||
configNameSet.insert(dataList[i].configurationName);
|
||
}
|
||
|
||
// 初始化
|
||
for (const QString& elementconfigName : configNameSet) {
|
||
this->electricFieldDataList.insert(elementconfigName, std::vector<ElectricFieldData>(0));
|
||
}
|
||
|
||
// 数据初始化
|
||
for (size_t i = 0; i < dataList.size(); i++) {
|
||
this->electricFieldDataList[dataList[i].configurationName].push_back(dataList[i]);
|
||
}
|
||
// 每个Pluse 进行排序,按照频率: 小 -> 大,
|
||
QMap<QString, std::vector<ElectricFieldData>>::const_iterator it;
|
||
for (it = this->electricFieldDataList.constBegin(); it != this->electricFieldDataList.constEnd(); ++it) {
|
||
std::sort(this->electricFieldDataList[it.key()].begin(), this->electricFieldDataList[it.key()].end(), compareElectricFieldDataInFreq);
|
||
}
|
||
|
||
// 检查每个electricFieldDataList 是否按照频率进行排序
|
||
for (it = this->electricFieldDataList.constBegin(); it != this->electricFieldDataList.constEnd(); ++it) {
|
||
for (size_t i = 0; i < this->electricFieldDataList[it.key()].size() - 1; i++) {
|
||
if (this->electricFieldDataList[it.key()][i].frequency > this->electricFieldDataList[it.key()][i + 1].frequency) {
|
||
qDebug() << u8"发现 configuration Name:" + it.key() + u8" , 发现问题,请检查";
|
||
QMessageBox::warning(nullptr, u8"警告", u8"发现 configuration Name:" + it.key() + u8" , 发现问题,请检查");
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if (!this->checkPRFModel() || !this->resizePRFPluse()) {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
|
||
}
|
||
|
||
void FEKOBase::NearFieldEchoCSVParser::toThetapolar(const QString& filePath)
|
||
{
|
||
|
||
this->toEchoData(filePath, 2);
|
||
}
|
||
|
||
void FEKOBase::NearFieldEchoCSVParser::toPhiPolar(const QString& filePath)
|
||
{
|
||
this->toEchoData(filePath, 1);
|
||
}
|
||
|
||
void FEKOBase::NearFieldEchoCSVParser::toRPolar(const QString& filePath)
|
||
{
|
||
this->toEchoData(filePath, 0);
|
||
}
|
||
|
||
void FEKOBase::NearFieldEchoCSVParser::saveCSV(const QString& filePath)
|
||
{
|
||
}
|
||
|
||
/// <summary>
|
||
/// 输出脉冲回波文件
|
||
/// </summary>
|
||
/// <param name="filePath">文件路径</param>
|
||
/// <param name="outDataName">0: R,1: phi,2: theta</param>
|
||
void FEKOBase::NearFieldEchoCSVParser::toEchoData(const QString& filePath, size_t outDataName)
|
||
{
|
||
// 脉冲整理
|
||
Eigen::MatrixXcd echoData = Eigen::MatrixXcd::Zero(this->prfData.size(), this->freqPoints);
|
||
Eigen::MatrixXd antpos = Eigen::MatrixXd::Zero(this->prfData.size(), 5); //x,y,z,theta,phi"
|
||
|
||
for (size_t i = 0; i < this->prfData.size(); i++) {
|
||
antpos(i, 0) = this->prfData[i].px;
|
||
antpos(i, 1) = this->prfData[i].py;
|
||
antpos(i, 2) = this->prfData[i].pz;
|
||
antpos(i, 3) = this->prfData[i].electricFieldDataList[0].theta;
|
||
antpos(i, 4) = this->prfData[i].electricFieldDataList[0].phi;
|
||
for (size_t j = 0; j < this->freqPoints; j++) {
|
||
if (outDataName == 0) {
|
||
echoData(i, j) = std::complex<double>(this->prfData[i].electricFieldDataList[j].reEr, this->prfData[i].electricFieldDataList[j].imEr);
|
||
}
|
||
else if (outDataName == 1) {
|
||
echoData(i, j) = std::complex<double>(this->prfData[i].electricFieldDataList[j].reEphi, this->prfData[i].electricFieldDataList[j].imEphi);
|
||
}
|
||
else {
|
||
echoData(i, j) = std::complex<double>(this->prfData[i].electricFieldDataList[j].reEtheta, this->prfData[i].electricFieldDataList[j].imEtheta);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
EchoDataClass echodataTemp;
|
||
echodataTemp.setAntPos(antpos);
|
||
echodataTemp.setFreqStart(this->freqStart);
|
||
echodataTemp.setFreqEnd(this->freqEnd);
|
||
echodataTemp.setFreqpoints(this->freqPoints);
|
||
echodataTemp.setEchoData(echoData);
|
||
echodataTemp.SaveEchoData(filePath);
|
||
}
|
||
|
||
FEKOBase::EchoDataClass::EchoDataClass(const FEKOBase::EchoDataClass& inecho)
|
||
{
|
||
|
||
this->echoData = inecho.getEchoData();
|
||
this->antPos = inecho.getAntPos();
|
||
this->freqStart = inecho.getFreqStart();
|
||
this->freqEnd = inecho.getFreqEnd();
|
||
this->freqpoints = inecho.getFreqpoints();
|
||
}
|
||
|
||
|
||
|
||
FEKOBase::EchoDataClass::EchoDataClass()
|
||
{
|
||
|
||
}
|
||
|
||
FEKOBase::EchoDataClass::~EchoDataClass()
|
||
{
|
||
}
|
||
|
||
|
||
|
||
|
||
void FEKOBase::EchoDataClass::setEchoData(Eigen::MatrixXcd echoData)
|
||
{
|
||
this->echoData = echoData;
|
||
}
|
||
|
||
Eigen::MatrixXcd FEKOBase::EchoDataClass::getEchoData() const
|
||
{
|
||
return this->echoData;
|
||
}
|
||
|
||
void FEKOBase::EchoDataClass::setAntPos(Eigen::MatrixXd antPos)
|
||
{
|
||
this->antPos = antPos;
|
||
}
|
||
|
||
Eigen::MatrixXd FEKOBase::EchoDataClass::getAntPos() const
|
||
{
|
||
return this->antPos;
|
||
}
|
||
|
||
void FEKOBase::EchoDataClass::setFreqStart(double freqStart)
|
||
{
|
||
this->freqStart = freqStart;
|
||
}
|
||
|
||
double FEKOBase::EchoDataClass::getFreqStart() const
|
||
{
|
||
return this->freqStart;
|
||
}
|
||
|
||
void FEKOBase::EchoDataClass::setFreqEnd(double freqEnd)
|
||
{
|
||
this->freqEnd = freqEnd;
|
||
}
|
||
|
||
double FEKOBase::EchoDataClass::getFreqEnd() const
|
||
{
|
||
return this->freqEnd;
|
||
}
|
||
|
||
void FEKOBase::EchoDataClass::setFreqpoints(int freqpoints)
|
||
{
|
||
this->freqpoints = freqpoints;
|
||
}
|
||
|
||
int FEKOBase::EchoDataClass::getFreqpoints() const
|
||
{
|
||
return this->freqpoints;
|
||
}
|
||
|
||
void FEKOBase::EchoDataClass::loadEchoData(const QString& filePath)
|
||
{
|
||
std::ifstream file(reinterpret_cast<const wchar_t*>(filePath.utf16()), std::ios::binary);
|
||
|
||
if (file.is_open()) {
|
||
// 保存频率变量
|
||
INT32 PRFRow = 0;
|
||
INT32 freqCol = 0;
|
||
// 读取其他成员变量
|
||
file.read(reinterpret_cast<char*>(&freqStart), sizeof(double));
|
||
file.read(reinterpret_cast<char*>(&freqEnd), sizeof(double));
|
||
file.read(reinterpret_cast<char*>(&freqpoints), sizeof(INT32));
|
||
file.read(reinterpret_cast<char*>(&PRFRow), sizeof(INT32));
|
||
file.read(reinterpret_cast<char*>(&freqCol), sizeof(INT32));
|
||
echoData = Eigen::MatrixXcd::Zero(PRFRow, freqCol); // 重新分配内存
|
||
antPos = Eigen::MatrixXd::Zero(PRFRow, 5);
|
||
file.read(reinterpret_cast<char*>(antPos.data()), sizeof(double) * PRFRow * 5); // 保存天线位置
|
||
file.read(reinterpret_cast<char*>(echoData.data()), sizeof(std::complex<double>) * PRFRow * freqCol); // 保存回波数据
|
||
file.close(); // 关闭文件
|
||
|
||
this->freqStart = freqStart;
|
||
this->freqEnd = freqEnd;
|
||
this->freqpoints = freqpoints;
|
||
this->echoData = echoData;
|
||
this->antPos = antPos;
|
||
qDebug() << u8"回波数据加载完成";
|
||
}
|
||
else {
|
||
qWarning() << "Error: Unable to open file for reading.";
|
||
}
|
||
}
|
||
|
||
void FEKOBase::EchoDataClass::SaveEchoData(const QString& filePath)
|
||
{
|
||
if (echoData.rows() != antPos.rows() || antPos.cols() != 5) {
|
||
qDebug() << "Error: antPos.size()!=echoData.rows()*5"
|
||
+ QString::number(echoData.rows()) + u8"!=" + QString::number(antPos.rows())
|
||
+ QString::number(antPos.cols()) + u8"!=5";
|
||
return;
|
||
}
|
||
else {}
|
||
std::ofstream file(reinterpret_cast<const wchar_t*>(filePath.utf16()), std::ios::binary);
|
||
qDebug() << "===================================================================";
|
||
qDebug() << u8"回波脉冲文件格式说明:";
|
||
qDebug() << u8"|freqStart(double),freqEnd(double),freqpoints(int)|PRFROW(int),PRFCol(int)|antPos|echodata|";
|
||
qDebug() << u8"其中antPos: PRFrow*3 double x,y,z,incidence,azangle,theta,phi";
|
||
qDebug() << u8"其中echodata: PRFrow*PRFCol complex<double> ";
|
||
qDebug() << "===================================================================";
|
||
if (file.is_open()) {
|
||
INT32 PRFRow = echoData.rows();
|
||
INT32 freqCol = echoData.cols();
|
||
file.write(reinterpret_cast<const char*>(&freqStart), sizeof(double)); // 保存频率变量
|
||
file.write(reinterpret_cast<const char*>(&freqEnd), sizeof(double));
|
||
file.write(reinterpret_cast<const char*>(&freqpoints), sizeof(INT32));
|
||
file.write(reinterpret_cast<const char*>(&PRFRow), sizeof(INT32));
|
||
file.write(reinterpret_cast<const char*>(&freqCol), sizeof(INT32));
|
||
file.write(reinterpret_cast<const char*>(antPos.data()), sizeof(double) * antPos.size()); // 保存天线位置
|
||
file.write(reinterpret_cast<const char*>(echoData.data()), sizeof(std::complex<double>) * echoData.size()); // 保存回波数据
|
||
file.close(); // 关闭文件
|
||
|
||
}
|
||
else {
|
||
qDebug() << "Error: Unable to open file for writing.";
|
||
}
|
||
}
|
||
|
||
|
||
|
||
Eigen::MatrixXd FEKOBase::WINDOWFun(Eigen::MatrixXcd& echo, ImageAlgWindowFun winfun)
|
||
{
|
||
size_t Nxa = echo.rows();
|
||
size_t Nf = echo.cols();
|
||
Eigen::MatrixXd normw = Eigen::MatrixXd::Zero(Nxa, Nf); // 归一化窗函数
|
||
|
||
if (winfun == ImageAlgWindowFun::HANMMING) {
|
||
normw = Hanning(Nf, Nxa);
|
||
echo = echo.array() * normw.array();
|
||
}
|
||
else {
|
||
normw = normw.array() * 0 + 1 / (Nxa * Nf);
|
||
}
|
||
|
||
return normw;
|
||
}
|
||
|
||
QList<QString> FEKOBase::getFEKOImageAlgorithmList()
|
||
{
|
||
QList<QString> list;
|
||
FEKOImageAlgorithm alg;
|
||
for (alg = FEKOImageAlgorithm::TBP_TIME; alg < FEKOImageAlgorithm::UNKONW; alg = (FEKOImageAlgorithm)(alg + 1)) {
|
||
list.append(FEKOImageAlgorithm2String(alg));
|
||
}
|
||
return list;
|
||
}
|
||
|
||
FEKOBase::FEKOImageAlgorithm FEKOBase::String2FEKOImageAlgorithm(QString str)
|
||
{
|
||
FEKOImageAlgorithm alg;
|
||
for (alg = FEKOImageAlgorithm::TBP_TIME; alg < FEKOImageAlgorithm::UNKONW; alg = (FEKOImageAlgorithm)(alg + 1)) {
|
||
if (str == FEKOImageAlgorithm2String(alg)) {
|
||
return alg;
|
||
}
|
||
else {}
|
||
}
|
||
return alg;
|
||
}
|
||
|
||
QString FEKOBase::FEKOImageAlgorithm2String(FEKOImageAlgorithm alg)
|
||
{
|
||
// 将FEKOImageAlgorithm 枚举转换为字符串
|
||
switch (alg)
|
||
{
|
||
case FEKOBase::TBP_TIME:
|
||
return u8"TBP_TIME";
|
||
case FEKOBase::TBP_FREQ:
|
||
return u8"TBP_FREQ";
|
||
default:
|
||
return u8"UNKONW";
|
||
}
|
||
}
|
||
|
||
// 请仿照FEKOImageAlgorithm枚举的写法,构建QString 与 ImageAlgWindowFun 的转换函数
|
||
|
||
QList<QString> FEKOBase::getImageAlgWindowFunList()
|
||
{
|
||
QList<QString> list;
|
||
ImageAlgWindowFun alg;
|
||
for (alg = ImageAlgWindowFun::NOWINDOWS; alg < ImageAlgWindowFun::UNKONWWINDOW; alg = (ImageAlgWindowFun)(alg + 1)) {
|
||
list.append(ImageAlgWindowFun2String(alg));
|
||
}
|
||
return list;
|
||
}
|
||
|
||
FEKOBase::ImageAlgWindowFun FEKOBase::String2ImageAlgWindowFun(QString str)
|
||
{
|
||
ImageAlgWindowFun alg;
|
||
for (alg = ImageAlgWindowFun::UNKONWWINDOW; alg < ImageAlgWindowFun::UNKONWWINDOW; alg = (ImageAlgWindowFun)(alg + 1)) {
|
||
if (str == ImageAlgWindowFun2String(alg)) {
|
||
return alg;
|
||
}
|
||
else {}
|
||
}
|
||
return alg;
|
||
}
|
||
|
||
QString FEKOBase::ImageAlgWindowFun2String(FEKOBase::ImageAlgWindowFun alg)
|
||
{
|
||
switch (alg)
|
||
{
|
||
case FEKOBase::NOWINDOWS:
|
||
return u8"NOWINDOWS";
|
||
case FEKOBase::HANMMING:
|
||
return u8"HANMMING";
|
||
default:
|
||
return u8"UNKONWWINDOW";
|
||
}
|
||
}
|
||
|
||
|
||
bool FEKOBase::BPImage_TIME(QString& restiffpath, Eigen::MatrixXcd& echoData, Eigen::MatrixXd& antPos, Eigen::MatrixXd& freqmatrix, Eigen::MatrixXd& X, Eigen::MatrixXd& Y, Eigen::MatrixXd& Z, ImageAlgWindowFun winfun)
|
||
{
|
||
// BP成像算法
|
||
const double c = 0.299792458; // 光速
|
||
|
||
return true;
|
||
}
|
||
|
||
bool FEKOBase::FBPImage_FREQ(QString& restiffpath, Eigen::MatrixXcd& echoData, Eigen::MatrixXd& antPos, Eigen::MatrixXd& freqmatrix, Eigen::MatrixXd& X, Eigen::MatrixXd& Y, Eigen::MatrixXd& Z, ImageAlgWindowFun winfun)
|
||
{
|
||
|
||
// BP成像算法
|
||
const double c = 0.299792458; // 光速
|
||
const std::complex<double> j(0, 1); // 虚数单位
|
||
const size_t image_height = X.rows();
|
||
const size_t image_width = X.cols();
|
||
const size_t PRFCount = echoData.rows();
|
||
const size_t frepoints = echoData.cols();
|
||
Eigen::MatrixXcd factorj = Eigen::MatrixXcd::Zero(1, echoData.cols()); // 1 , freqs
|
||
factorj = freqmatrix.array().cast<std::complex<double>>().array() * j * 4 * M_PI / c; // 声明校正矩阵
|
||
Eigen::MatrixXcd im_final = Eigen::MatrixXcd::Zero(image_height, image_width);
|
||
|
||
|
||
|
||
#ifdef __SHOWPROCESS // 进度条展示
|
||
QProgressDialog progressDialog(u8"BP_FREQ成像进度", u8"终止", 0, image_height);
|
||
progressDialog.setWindowTitle(u8"成像中");
|
||
progressDialog.setWindowModality(Qt::WindowModal);
|
||
progressDialog.setAutoClose(true);
|
||
progressDialog.setValue(0);
|
||
progressDialog.setMaximum(image_height);
|
||
progressDialog.setMinimum(0);
|
||
progressDialog.show();
|
||
#endif // __SHOWPROCESS
|
||
|
||
|
||
|
||
#ifdef __SHOWIMAGEPROCESSRESULT // 加窗处理
|
||
Eigen::MatrixXd normw = WINDOWFun(echoData, winfun);
|
||
#endif
|
||
|
||
#ifdef __IMAGEPARALLEL
|
||
#pragma omp parallel for
|
||
for (long ii = 0; ii < image_height; ii++)
|
||
{
|
||
Eigen::MatrixXd im_R = Eigen::MatrixXd::Zero(PRFCount, 1);// 图像到脉冲矩阵 prf*1
|
||
Eigen::MatrixXcd term_R = Eigen::MatrixXcd::Zero(1, frepoints);
|
||
Eigen::MatrixXcd pluse_R = Eigen::MatrixXcd::Zero(PRFCount, 1);
|
||
|
||
for (size_t jj = 0; jj < image_width; jj++) {
|
||
im_R.col(0) = ((antPos.col(0).array() - X(ii, jj)).array().pow(2) +
|
||
(antPos.col(1).array() - Y(ii, jj)).array().pow(2) +
|
||
(antPos.col(2).array() - Z(ii, jj)).array().pow(2))
|
||
.array().sqrt().array(); // 获取目标到天线矩阵 计算 ok
|
||
// im_R PRF_count x 1
|
||
for (size_t tt = 0; tt < PRFCount; tt++) {
|
||
term_R = (im_R(tt, 0) * factorj.array()).array().exp(); // ok
|
||
pluse_R(tt, 0) = (echoData.row(tt).array() * term_R.array()).sum(); // 对每个脉冲校正求和
|
||
}
|
||
im_final(ii, jj) = pluse_R.array().sum(); // 计算图像
|
||
}
|
||
}
|
||
#else
|
||
|
||
Eigen::MatrixXd im_R = Eigen::MatrixXd::Zero(PRFCount, 1);// 图像到脉冲矩阵 prf*1
|
||
Eigen::MatrixXcd term_R = Eigen::MatrixXcd::Zero(1, frepoints);
|
||
Eigen::MatrixXcd pluse_R = Eigen::MatrixXcd::Zero(PRFCount, 1);
|
||
for (long ii = 0; ii < image_height; ii++)
|
||
{
|
||
for (size_t jj = 0; jj < image_width; jj++) {
|
||
im_R.col(0) = ((antPos.col(0).array() - X(ii, jj)).array().pow(2) +
|
||
(antPos.col(1).array() - Y(ii, jj)).array().pow(2) +
|
||
(antPos.col(2).array() - Z(ii, jj)).array().pow(2))
|
||
.array().sqrt().array(); // 获取目标到天线矩阵 计算 ok
|
||
// im_R PRF_count x 1
|
||
for (size_t tt = 0; tt < PRFCount; tt++) {
|
||
term_R = (im_R(tt, 0) * factorj.array()).array().exp(); // ok
|
||
pluse_R(tt, 0) = (echoData.row(tt).array() * term_R.array()).sum(); // 对每个脉冲校正求和
|
||
}
|
||
im_final(ii, jj) = pluse_R.array().sum(); // 计算图像
|
||
}
|
||
#ifdef __SHOWPROCESS
|
||
progressDialog.setValue(ii);
|
||
#endif
|
||
}
|
||
#endif
|
||
|
||
#ifdef __SHOWIMAGEPROCESSRESULT // 加窗处理
|
||
im_final = im_final.array() / (normw.array().sum());
|
||
|
||
#endif
|
||
|
||
|
||
// 3. 保存图像
|
||
|
||
|
||
QString newrestiffpath = restiffpath;
|
||
|
||
|
||
Eigen::MatrixXd gt = Eigen::MatrixXd::Zero(2,3);
|
||
gt(0, 0) = X(0, 0);
|
||
gt(0, 1) = X(0, 1) - X(0, 0);
|
||
gt(0, 2) = 0;
|
||
gt(1, 0) = Y(0, 0);
|
||
gt(1, 1) = 0;
|
||
gt(1, 2) = Y(0, 0) - Y(1, 0);
|
||
std::cout << gt << std::endl;
|
||
gdalImageComplex im_final_gdal = CreategdalImageComplex(restiffpath,im_final.rows(),im_final.cols(),1,gt, QString(u8""), true,true);
|
||
im_final_gdal.setData(im_final);
|
||
im_final_gdal.saveImage();
|
||
|
||
qDebug() << QString(u8"保存文件地址:" + restiffpath);
|
||
#ifdef __SHOWPROCESS
|
||
progressDialog.setWindowTitle(u8"保存文件:" + restiffpath);
|
||
progressDialog.setValue(image_height);
|
||
progressDialog.close();
|
||
#endif
|
||
|
||
// 绘制图像
|
||
#ifdef __SHOWIMAGEPROCESSRESULT
|
||
// 将复数矩阵的幅度转换为实数矩阵
|
||
matplot::figure();
|
||
matplot::vector_2d amplitude_im_final(im_final.rows(), matplot::vector_1d(im_final.cols()));
|
||
for (int i = 0; i < im_final.rows(); ++i) {
|
||
for (int j = 0; j < im_final.cols(); ++j) {
|
||
amplitude_im_final[i][j] = std::abs(im_final(i, j));
|
||
}
|
||
}
|
||
matplot::imagesc(amplitude_im_final);
|
||
matplot::colorbar();
|
||
matplot::show();
|
||
#endif // __SHOWMATPLOTLIBCPP
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
|