349 lines
10 KiB
C++
349 lines
10 KiB
C++
//
|
||
// 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();
|
||
}
|