Files
HPPA/HPPA/JinspFiberImager.cpp
tangchao0503 6b63d28d2c add,山地所贡嘎山7:
优化
2026-07-22 10:31:12 +08:00

349 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by 73505 on 2023/5/7.
//
#include <algorithm>
#include "JinspFiberImager.h"
JinspFiberImager::JinspFiberImager(bool bIsUSBMode, std::string ucPortNumber, std::string strDeviceName)
{
m_FiberSpectrometer = NULL;
mUcPortNumber=ucPortNumber;
m_record = false;
m_captureIntervalMilliseconds = 1 * 1000;
qRegisterMetaType<DeviceAttribute>("DeviceAttribute");
qRegisterMetaType<DataFrame>("DataFrame");
}
JinspFiberImager::~JinspFiberImager()
{
}
void JinspFiberImager::connectFiberSpectrometer(QString& SN, QString& pixelCount, QString& wavelengthInfo)
{
using namespace std;
m_FiberSpectrometer = new JinspSpectralmeterControl();
m_FiberSpectrometer->Initialize(false, mUcPortNumber, "OPTOSKY");
DeviceInfo deviceInfo;//
DeviceAttribute deviceAttribute;
m_FiberSpectrometer->GetDeviceInfo(deviceInfo);
m_FiberSpectrometer->GetDeviceAttribute(deviceAttribute);//?????
SN = QString::fromStdString(deviceInfo.strSN);
pixelCount = QString::number(deviceAttribute.iPixels);
wavelengthInfo = QString::number(deviceAttribute.fWaveLengthInNM[0]) + "--" + QString::number(deviceAttribute.fWaveLengthInNM[deviceAttribute.iPixels - 1]);
m_FiberSpectrometer->SetDeviceTemperature(-10);
//设置dn值的最大值(和位深相关)
string qepro = "QEP";//?????????????????????????????????????????????????????????????????????????????????????????
string flame = "FLMS";//?????????????????????????????????????????????????????????????????????????????????????????
if (deviceInfo.strSN.find(qepro) != string::npos)
{
m_MaxValueOfFiberSpectrometer = 200000;
}
else if (deviceInfo.strSN.find(flame) != string::npos)
{
m_MaxValueOfFiberSpectrometer = 65535;
}
else//没有找到匹配的仪器来设置 dn值的最大值
{
m_MaxValueOfFiberSpectrometer = 65535;
}
}
void JinspFiberImager::disconnectFiberSpectrometer()
{
m_record = false;
}
void JinspFiberImager::getDeviceAttribute(DeviceAttribute& deviceAttribute)
{
m_FiberSpectrometer->GetDeviceAttribute(deviceAttribute);
}
void JinspFiberImager::getDeviceInfo(DeviceInfo& deviceInfo)
{
m_FiberSpectrometer->GetDeviceInfo(deviceInfo);
}
void JinspFiberImager::setExposureTime(int iExposureTimeInMS)
{
m_FiberSpectrometer->SetExposureTime(iExposureTimeInMS);
}
void JinspFiberImager::getExposureTime(int &iExposureTimeInMS)
{
m_FiberSpectrometer->GetExposureTime(iExposureTimeInMS);
}
void JinspFiberImager::getDeviceTemperature(float &fTemperature)
{
m_FiberSpectrometer->GetDeviceTemperature(fTemperature);
}
void JinspFiberImager::singleShot(DataFrame &dfData)
{
m_FiberSpectrometer->SingleShot(dfData);
}
void JinspFiberImager::getNonlinearityCoeffs(coeffsFrame &coeffs)
{
printf("This is JinspFiberImager.\n");
}
void JinspFiberImager::recordDark(QString path)
{
//获取设备信息
DeviceAttribute attribute;
DeviceInfo deviceInfo;
getDeviceAttribute(attribute);
getDeviceInfo(deviceInfo);
//采集暗帧
singleShot(m_DarkData);
//输出到csv
QDateTime curDateTime = QDateTime::currentDateTime();
QString currentTime = curDateTime.toString("yyyy_MM_dd_hh_mm_ss");
QString fileName = path + "/" + currentTime + "_" + QString::fromStdString(deviceInfo.strSN) + "_darkSpectral_dn.csv";
std::ofstream outfile(fileName.toStdString().c_str());
for (int i = 0; i < attribute.iPixels; i++)
{
if (i==0)
{
outfile << m_DarkData.usExposureTimeInMS << std::endl;
}
outfile << attribute.fWaveLengthInNM[i] << "," << m_DarkData.lData[i] << std::endl;
}
outfile.close();
}
void JinspFiberImager::recordTarget(int recordTimes, QString path)
{
//获取设备信息
DeviceAttribute attribute;
DeviceInfo deviceInfo;
getDeviceAttribute(attribute);
getDeviceInfo(deviceInfo);
DataFrame integratingSphereData_tmp;
for (int i = 0; i < recordTimes; i++)
{
singleShot(integratingSphereData_tmp);
if (i == 0)//将integratingSphereData_tmp中的曝光时间、温度等信息传给m_IntegratingSphereData
{
m_IntegratingSphereData = integratingSphereData_tmp;
}
else
{
for (int i = 0; i < attribute.iPixels; i++)
{
m_IntegratingSphereData.lData[i] += integratingSphereData_tmp.lData[i];
}
}
}
for (int i = 0; i < attribute.iPixels; i++)
{
m_IntegratingSphereData.lData[i] = m_IntegratingSphereData.lData[i] / recordTimes;
}
//将m_IntegratingSphereData通过信号发送
emit spectalCaptured(attribute, m_IntegratingSphereData);
//输出到csv
QDateTime curDateTime = QDateTime::currentDateTime();
QString currentTime = curDateTime.toString("yyyy_MM_dd_hh_mm_ss");
QString fileName = path + "/" + currentTime + "_" + m_posInfo + "_" + QString::fromStdString(deviceInfo.strSN) + "_integratingSphereSpectral_dn.csv";
std::ofstream outfile(fileName.toStdString().c_str());
for (int i = 0; i < attribute.iPixels; i++)
{
if (i==0)
{
outfile << m_IntegratingSphereData.usExposureTimeInMS << "," << getNanosecondsSinceMidnight() << std::endl;
}
outfile << attribute.fWaveLengthInNM[i] << "," << m_IntegratingSphereData.lData[i] << std::endl;
}
outfile.close();
}
void JinspFiberImager::autoExpose()
{
int allowMaxExposure = 6000;
DeviceAttribute attribute;
getDeviceAttribute(attribute);
const ZZ_U32 maxPixelValue = m_MaxValueOfFiberSpectrometer;
const double targetMinRatio = 0.80;
const double targetMaxRatio = 0.90;
const ZZ_U32 targetMin = maxPixelValue * targetMinRatio;
const ZZ_U32 targetMax = maxPixelValue * targetMaxRatio;
ZZ_U32 thresholdLow = targetMin;
ZZ_U32 thresholdHigh = targetMax;
// 自适应初始曝光时间:先快速探测亮度水平
int exposureTime = 10;
setExposureTime(exposureTime);
DataFrame dataFrame;
singleShot(dataFrame);
ZZ_S32 maxValue = GetMaxValue(dataFrame.lData, attribute.iPixels);
// 探测阶段:快速逼近目标区间
if (maxValue > 0)
{
// 预测达到目标区间所需的曝光时间
ZZ_U32 targetValue = (targetMin + targetMax) / 2;
double predictedRatio = static_cast<double>(targetValue) / maxValue;
// 曝光时间与亮度为对数关系,使用对数预测更准确
double logRatio = log(static_cast<double>(targetValue) / maxValue + 0.001);
int predictedExposure = static_cast<int>(exposureTime * pow(predictedRatio, 0.7));
if (predictedExposure < 1)
predictedExposure = 1;
if (predictedExposure > allowMaxExposure)
predictedExposure = allowMaxExposure;
//predictedExposure = std::clamp(predictedExposure, 1, allowMaxExposure);
exposureTime = predictedExposure;
setExposureTime(exposureTime);
singleShot(dataFrame);
maxValue = GetMaxValue(dataFrame.lData, attribute.iPixels);
}
emit sendExposureTimeSignal(exposureTime);
// 二分查找阶段:在目标区间内精确查找
int lowExposure = 1;
int highExposure = allowMaxExposure;
int iterations = 0;
const int maxIterations = 10;
while (iterations < maxIterations)
{
// 检查是否已在目标区间内
if (maxValue >= thresholdLow && maxValue <= thresholdHigh)
{
std::cout << "自动曝光完成 - 曝光时间:" << exposureTime
<< "ms, 最大值:" << maxValue << std::endl;
break;
}
// 获取当前曝光时间
m_FiberSpectrometer->GetExposureTime(exposureTime);
if (maxValue < thresholdLow)
{
// 曝光不足,增大曝光时间 - 使用二分策略
lowExposure = exposureTime;
int newExposure = (exposureTime + highExposure) / 2;
if (newExposure <= exposureTime)
{
newExposure = exposureTime * 2;
}
exposureTime = std::min(newExposure, allowMaxExposure);
std::cout << "自动曝光 +++ (" << iterations << ") 曝光时间:"
<< exposureTime << "ms, 最大值:" << maxValue << std::endl;
}
else
{
// 曝光过度,减小曝光时间 - 使用二分策略
highExposure = exposureTime;
int newExposure = (lowExposure + exposureTime) / 2;
if (newExposure >= exposureTime) {
newExposure = exposureTime / 2;
}
exposureTime = std::max(newExposure, 1);
std::cout << "自动曝光 --- (" << iterations << ") 曝光时间:"
<< exposureTime << "ms, 最大值:" << maxValue << std::endl;
}
setExposureTime(exposureTime);
singleShot(dataFrame);
maxValue = GetMaxValue(dataFrame.lData, attribute.iPixels);
emit sendExposureTimeSignal(exposureTime);
iterations++;
}
if (iterations >= maxIterations) {
std::cout << "自动曝光达到最大迭代次数,最终曝光时间:"
<< exposureTime << "ms, 最大值:" << maxValue << std::endl;
}
m_iExposureTime = exposureTime;
}
ZZ_S32 JinspFiberImager::GetMaxValue(ZZ_S32 * dark, int number)
{
ZZ_S32 max = 0;
//std::cout << "本帧最大值为" << max << std::endl;
for (size_t i = 0; i < number; i++)
{
// std::cout << dark[i] << std::endl;
if(dark[i]>65535)
continue;
if (dark[i] > max)
{
max = dark[i];
}
}
//std::cout << "本帧最大值为" << max << std::endl;
return max;
}
void JinspFiberImager::setCaptureInterval(int captureIntervalSeconds)
{
m_captureIntervalMilliseconds = captureIntervalSeconds * 1000;
}
void JinspFiberImager::OpenFiberImagerAndRecord(QString posInfo)
{
m_posInfo = posInfo;
//连接光谱仪
QString SN;
QString pixelCount;
QString wavelengthInfo;
connectFiberSpectrometer(SN, pixelCount, wavelengthInfo);
//曝光
emit startExposureSignal();
autoExpose();
emit exposureCompleteSignal(m_iExposureTime);
//采集
m_record = true;
while (m_record)
{
recordTarget(1, AppSettings::instance().FiberImagerDataFolder());
QThread::msleep(m_captureIntervalMilliseconds);
}
std::cout << "close.........." << std::endl;
m_FiberSpectrometer->Close();
}