diff --git a/HPPA/AppSettings.cpp b/HPPA/AppSettings.cpp new file mode 100644 index 0000000..c0cb737 --- /dev/null +++ b/HPPA/AppSettings.cpp @@ -0,0 +1,25 @@ +#include "AppSettings.h" + +const QString AppSettings::kDefaultDataFolder = QStringLiteral("C:\\HPPA_image"); + +AppSettings::AppSettings() + : m_settings(QSettings::IniFormat, QSettings::UserScope, + QStringLiteral("IRIS"), QStringLiteral("HPPA")) +{ +} + +AppSettings& AppSettings::instance() +{ + static AppSettings s; + return s; +} + +QString AppSettings::dataFolder() const +{ + return m_settings.value("General/DataFolder", kDefaultDataFolder).toString(); +} + +void AppSettings::setDataFolder(const QString& path) +{ + m_settings.setValue("General/DataFolder", path); +} diff --git a/HPPA/AppSettings.h b/HPPA/AppSettings.h new file mode 100644 index 0000000..68d0891 --- /dev/null +++ b/HPPA/AppSettings.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +class AppSettings +{ +public: + static AppSettings& instance(); + + // 数据路径 + QString dataFolder() const; + void setDataFolder(const QString& path); + + // 在此处添加更多参数的 getter/setter ... + +private: + AppSettings(); + AppSettings(const AppSettings&) = delete; + AppSettings& operator=(const AppSettings&) = delete; + + QSettings m_settings; + + // 默认值 + static const QString kDefaultDataFolder; +}; diff --git a/HPPA/HPPA.vcxproj b/HPPA/HPPA.vcxproj index 2a12430..6c532eb 100644 --- a/HPPA/HPPA.vcxproj +++ b/HPPA/HPPA.vcxproj @@ -108,6 +108,7 @@ + @@ -204,6 +205,7 @@ + diff --git a/HPPA/HPPA.vcxproj.filters b/HPPA/HPPA.vcxproj.filters index e3c9832..3d53621 100644 --- a/HPPA/HPPA.vcxproj.filters +++ b/HPPA/HPPA.vcxproj.filters @@ -202,6 +202,9 @@ Source Files + + Source Files + @@ -371,6 +374,9 @@ Header Files + + Header Files + diff --git a/HPPA/ImagerOperationBase.cpp b/HPPA/ImagerOperationBase.cpp index 6c7b345..2b6e6d9 100644 --- a/HPPA/ImagerOperationBase.cpp +++ b/HPPA/ImagerOperationBase.cpp @@ -1,4 +1,4 @@ -#include "ImagerOperationBase.h" +#include "ImagerOperationBase.h" ImagerOperationBase::ImagerOperationBase() { @@ -44,11 +44,11 @@ void ImagerOperationBase::connect_imager(int frameNumber) double ImagerOperationBase::auto_exposure() { - //һعʱΪڵǰ֡ - double x = 1 / getFramerate() * 1000;//ȡعʱ + //第一步:先设置曝光时间为在当前帧率情况下最大 + double x = 1 / getFramerate() * 1000;//获取最大毫秒曝光时间 setIntegrationTime(x); - //ڶͨѭѰعʱ + //第二步:通过循环寻找最佳曝光时间 imagerStartCollect(); while (true) @@ -57,7 +57,7 @@ double ImagerOperationBase::auto_exposure() if (GetMaxValue(buffer, m_FrameSize) >= 4094) { setIntegrationTime(getIntegrationTime() * 0.95); - std::cout << "Զع-----------" << std::endl; + std::cout << "自动曝光-----------" << std::endl; } else { @@ -69,7 +69,7 @@ double ImagerOperationBase::auto_exposure() emit autoExposureSignal(); - //std::cout << "Զع⣺" << getIntegrationTime() << std::endl; + //std::cout << "自动曝光:" << getIntegrationTime() << std::endl; return getIntegrationTime(); } @@ -79,7 +79,7 @@ void ImagerOperationBase::focus() m_iFocusFramesNumber = 0; m_iFocusFrameCounter = 1; - //std::cout << "-----------" << std::endl; + //std::cout << "调焦-----------" << std::endl; double tmpFrmerate = getFramerate(); double tmpIntegrationTime = getIntegrationTime(); @@ -87,7 +87,7 @@ void ImagerOperationBase::focus() setFramerate(5); auto_exposure(); - std::cout << "õعʱΪ" << getIntegrationTime() << std::endl; + std::cout << "调焦获得的曝光时间为:" << getIntegrationTime() << std::endl; int iWidth, iHeight; GetFrameSize(iWidth, iHeight); @@ -99,7 +99,7 @@ void ImagerOperationBase::focus() m_bFocusControlState = true; while (m_bFocusControlState) { - ////֡ƽ֡ + ////多帧平均,减弱单帧跳动 //memset((void*)buffer, 0, m_FrameSize * sizeof(unsigned short)); //int fn = 5; //for (int i = 0; i < fn; i++) @@ -123,7 +123,7 @@ void ImagerOperationBase::focus() double focusIndex = calcFocusIndexSobelPrivate(buffer); emit FocusIndexSobelSignal(focusIndex); - std::cout << "focusIndex" << focusIndex << std::endl; + std::cout << "focusIndex:" << focusIndex << std::endl; emit SpectralSignal(1); @@ -140,7 +140,7 @@ void ImagerOperationBase::focus() void ImagerOperationBase::record_dark() { - std::cout << "ɼ" << std::endl; + std::cout << "采集暗电流!!!!!!!!!" << std::endl; imagerStartCollect(); unsigned int* dark_tmp = new unsigned int[m_FrameSize]; @@ -172,7 +172,7 @@ void ImagerOperationBase::record_dark() void ImagerOperationBase::record_white() { - std::cout << "ɼװ壡" << std::endl; + std::cout << "采集白板!!!!!!!!!" << std::endl; imagerStartCollect(); unsigned int* white_tmp = new unsigned int[m_FrameSize]; @@ -197,7 +197,7 @@ void ImagerOperationBase::record_white() imagerStopCollect(); - //װ۰ + //白板扣暗电流 if (m_HasDark) { for (size_t i = 0; i < m_FrameSize; i++) @@ -225,17 +225,17 @@ void ImagerOperationBase::start_record() //std::cout << "------------------------------------------------------" << std::endl; m_iFrameCounter = 0; - m_RgbImage->m_iFrameCounter = 0;//rgbͼĵ0 + m_RgbImage->m_iFrameCounter = 0;//设置填充rgb图像的第0行 m_bRecordControlState = true; - //жڴbufferǷ + //判断内存buffer是否正常分配 if (buffer == 0) { std::cerr << "Error: memory could not be allocated for datacube"; exit(EXIT_FAILURE); } - // ڿʼɼʱļϢUI д MapLayer + // 在开始采集时仅发出文件信息,UI 层自行创建 MapLayer 并管理生命周期 // prepare file name that will be used for saving m_FileName2Save2 = m_FileName2Save + "_" + std::to_string(m_FileSavedCounter) + ".bil"; QString baseName = QString::fromStdString(getFileNameFromPath(m_FileName2Save2)); @@ -258,7 +258,7 @@ void ImagerOperationBase::start_record() getFrame(buffer); long long timeOs = getNanosecondsSinceMidnight(); - //ȥӦΪbufferdarkunsigned shortԵdark>bufferʱbuffer-dark=65535 + //减去暗电流,应为buffer和dark都是unsigned short,所以当dark>buffer时,buffer-dark=65535 if (m_HasDark) { for (size_t i = 0; i < m_FrameSize; i++) @@ -276,12 +276,12 @@ void ImagerOperationBase::start_record() } - //ת + //转反射率 if (m_HasWhite) { for (size_t i = 0; i < m_FrameSize; i++) { - //װ壩Ϊ0 + //处理除数(白板)为0的情况 if (white[i] != 0) { pixelValueTmp = buffer[i]; @@ -299,12 +299,12 @@ void ImagerOperationBase::start_record() x = fwrite(buffer, 2, m_FrameSize, m_fImage); fprintf(hTimesFile, "%d\n", timeOs); - //rgbȡԱڽʾ + //将rgb波段提取出来,以便在界面中显示 m_RgbImage->FillRgbImage(buffer);//?????????????????????????????????????????????????????????????????????????????????????????????????????? - //std::cout << "" << m_iFrameCounter << "֡д" << x << "unsigned short" << std::endl; + //std::cout << "第" << m_iFrameCounter << "帧写了" << x << "个unsigned short。" << std::endl; - //ÿ1sһνͼλ + //每隔1s进行一次界面图形绘制 if (m_iFrameCounter % (int)getFramerate() == 0) { emit PlotSignal(m_FileSavedCounter, m_iFrameCounter, filePath); @@ -318,15 +318,15 @@ void ImagerOperationBase::start_record() } imagerStopCollect(); - //һλͼǰҪһ + //在最后一次画图前需要进行一次拉伸 //m_RgbImage emit PlotSignal(m_FileSavedCounter, -1, filePath); m_bRecordControlState = false; WriteHdr(); - // ImageFileSaved źţ֪ͨ UI Ѹļͼ - // m_FileName2Save2 ˱д .bil ļ "tmp_image_0.bil" + // 发射 ImageFileSaved 信号,通知 UI 层把该文件加入图层管理器 + // m_FileName2Save2 保存了本次写入的 .bil 文件名(例如 "tmp_image_0.bil") emit ImageFileSaved(QString::fromStdString(m_FileName2Save2), m_FileSavedCounter); m_FileSavedCounter++; @@ -397,7 +397,7 @@ double ImagerOperationBase::calcFocusIndexSobelPrivate(void* pvData) unsigned short* psData; psData = (unsigned short*)pvData; - cv::Mat gray(iHeight, iWidth, CV_16UC1, psData);//֤gray.dataݺpsDataһ + cv::Mat gray(iHeight, iWidth, CV_16UC1, psData);//经验证,gray.data的数据和psData一样; /*string rgbFilePathNoStrech = "E:\\hppa\\delete\\focusImg_"; string tmp1 = std::to_string(m_iFocusFramesNumber); string tmp2 = ".png";*/ @@ -407,7 +407,7 @@ double ImagerOperationBase::calcFocusIndexSobelPrivate(void* pvData) //cv::imwrite(rgbFilePathNoStrech, gray); m_iFocusFramesNumber++; - //˲ + //进行滤波 //cv::Mat outputImage; //cv::Size kernelSize(5, 5); //double sigmaX = 1.5; @@ -417,7 +417,7 @@ double ImagerOperationBase::calcFocusIndexSobelPrivate(void* pvData) cv::Mat gradX, gradY, absGradX, absGradY; - cv::Sobel(outputImage, gradX, CV_32F, 1, 0);//ΪCV_16Scv::magnitude + cv::Sobel(outputImage, gradX, CV_32F, 1, 0);//如果参数为CV_16S,则函数cv::magnitude报错 cv::Sobel(outputImage, gradY, CV_32F, 0, 1); cv::convertScaleAbs(gradX, absGradX); cv::convertScaleAbs(gradY, absGradY); @@ -426,7 +426,7 @@ double ImagerOperationBase::calcFocusIndexSobelPrivate(void* pvData) cv::Mat magnitude, direction; cv::magnitude(gradX, gradY, magnitude);// - cv::phase(gradX, gradY, direction, true); // trueʾؽǶȶǻ + cv::phase(gradX, gradY, direction, true); // true表示返回角度而非弧度 return cv::mean(magnitude)[0]; @@ -479,23 +479,23 @@ int ImagerOperationBase::getFocusFrameCounter() const void ImagerOperationBase::set_buffer() { - // + //如果 if (buffer != nullptr) { - std::cout << "ͷŶڴ" << std::endl; + std::cout << "释放堆上内存" << std::endl; free(buffer); } m_FrameSize = getBandCount() * getSampleCount(); - //std::cout << "m_FrameSizeСΪ" << m_FrameSize << std::endl; + //std::cout << "m_FrameSize大小为" << m_FrameSize << std::endl; buffer = new unsigned short[m_FrameSize]; dark = new unsigned short[m_FrameSize]; white = new unsigned short[m_FrameSize]; - std::cout << "bufferڴַ" << buffer << std::endl; - std::cout << "darkڴַ" << dark << std::endl; - std::cout << "whiteڴַ" << white << std::endl; + std::cout << "buffer内存地址" << buffer << std::endl; + std::cout << "dark内存地址" << dark << std::endl; + std::cout << "white内存地址" << white << std::endl; } void ImagerOperationBase::WriteHdr() @@ -540,6 +540,6 @@ unsigned short ImagerOperationBase::GetMaxValue(unsigned short* dark, int number max = dark[i]; } } - //std::cout << "ֵ֡Ϊ" << max << std::endl; + //std::cout << "本帧最大值为" << max << std::endl; return max; } diff --git a/HPPA/ImagerOperationBase.h b/HPPA/ImagerOperationBase.h index d5f94d5..ea9054d 100644 --- a/HPPA/ImagerOperationBase.h +++ b/HPPA/ImagerOperationBase.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -49,7 +49,7 @@ public: int getFrameCounter() const; int getFocusFrameCounter() const; - unsigned short* buffer;//洢ɼӰмһд뵽Ӳ + unsigned short* buffer;//存储采集到的影像的中间变量,下一步写入到硬盘中 void set_buffer(); void setFileName2Save(string FileName); @@ -60,25 +60,25 @@ public: protected: - CImage* m_RgbImage;//ʾrgbͼ - bool m_bRecordControlState;//ɼ״ִֹ̬ͣɼ - int m_iFrameCounter;//¼ɼ֡ - int m_iFocusFrameCounter;//¼ʱɼ֡ - int m_FrameSize;//ʾһ֡жٸֵm_FrameSize = m_imager.get_band_count()*m_imager.get_sample_count(); - int m_iFrameNumber;//Ҫɼ֡ + CImage* m_RgbImage;//显示的rgb图像 + bool m_bRecordControlState;//采集状态;可用于执行停止采集操作 + int m_iFrameCounter;//记录采集的帧数 + int m_iFocusFrameCounter;//记录调焦时采集的帧数 + int m_FrameSize;//表示一帧代表有多少个数值:m_FrameSize = m_imager.get_band_count()*m_imager.get_sample_count(); + int m_iFrameNumber;//需要采集的总帧数 - //ڸӰļ - string m_FileName2Save;//Ӱļ + //以下两个参数用于给保存的影像文件命名 + string m_FileName2Save;//保存的影像文件名 string m_FileName2Save2; - int m_FileSavedCounter;//˼Ӱļ + int m_FileSavedCounter;//保存了几个影像文件 - bool m_HasDark;//ɼ˰֮Ϊtrue - bool m_HasWhite;//ɼ˰װ֮Ϊtrue + bool m_HasDark;//当采集了暗电流之后,设置为true + bool m_HasWhite;//当采集了白板之后,设置为true - unsigned short* dark;//洢 - unsigned short* white;//洢װ + unsigned short* dark;//存储暗电流 + unsigned short* white;//存储白板 - bool m_bFocusControlState;//Ƶ + bool m_bFocusControlState;//控制调焦结束 @@ -92,7 +92,7 @@ private: double calcFocusIndexSobelPrivate(void* pvData); public slots: - virtual void connect_imager(int frameNumber);//ٻ + virtual void connect_imager(int frameNumber);//连接相机、开辟缓存 virtual double auto_exposure(); virtual void focus(); virtual void start_record(); @@ -102,10 +102,10 @@ public slots: void getFocusIndexSobel(); signals: - void PlotSignal(int, int, QString);//ӰźţһڼӰ񣻵ڶɼ֡-1˴βɼһλ - void RecordFinishedSignal_WhenFrameNumberMeet();//ɼźţҪɼ֡m_iFrameNumberɼ - void RecordFinishedSignal_WhenFrameNumberNotMeet();//ɼźţҪɼ֡m_iFrameNumberûвɼɣ;ֹͣɼ - void SpectralSignal(int);//1ڵƹף0ʾɣ + void PlotSignal(int, int, QString);//绘制影像信号,第一个参数:第几个影像;第二个参数:采集到的帧数,-1代表此次采集的最后一次绘制 + void RecordFinishedSignal_WhenFrameNumberMeet();//采集完成信号:需要采集的总帧数(m_iFrameNumber)采集完成 + void RecordFinishedSignal_WhenFrameNumberNotMeet();//采集完成信号:需要采集的总帧数(m_iFrameNumber)没有采集完成,中途停止采集 + void SpectralSignal(int);//发射1代表正在调焦,绘制光谱,发射0表示调焦完成; void RecordWhiteFinishSignal(); void RecordDarlFinishSignal(); @@ -113,12 +113,12 @@ signals: void FocusIndexSobelSignal(double); - void testImagerStatus();//ʾԲ״̬Ƿӣӳ + void testImagerStatus();//表示可以测试相机连接状态:是否连接,并反映到界面上 void autoExposureSignal(); - // һӰļ.bil/.hdrдɺ󷢳Ӳɼ̷߳Qt queued connection + // 新增:当一组影像文件(.bil/.hdr)写入完成后发出(会从采集线程发出,Qt 会做 queued connection) void ImageFileSaved(const QString& path, int fileIndex); - // ޸ģֱӷ MapLayer*Ƿļļ·UI 㸺𴴽 MapLayer 󲢹 + // 修改:不再直接发送 MapLayer*,而是发送文件名与文件路径,UI 层负责创建 MapLayer 对象并管理生命周期 void LayerFileCreated(const QString& baseName, const QString& filePath, int fileIndex); }; diff --git a/HPPA/fileOperation.cpp b/HPPA/fileOperation.cpp index 8c82ed5..79916be 100644 --- a/HPPA/fileOperation.cpp +++ b/HPPA/fileOperation.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "fileOperation.h" +#include "AppSettings.h" FileOperation::FileOperation() { @@ -27,6 +28,11 @@ string FileOperation::getDirectoryOfExe() string FileOperation::getDirectoryFromString(string directory) { + if (directory.empty()) + { + directory = AppSettings::instance().dataFolder().toStdString(); + } + QString tmp = QString::fromStdString(directory); QDir dir; if (!dir.exists(tmp)) @@ -41,7 +47,7 @@ bool FileOperation::copyFile(QString source, QString target) { string source1 = source.toStdString(); string target1 = target.toStdString(); - + char buffer[256]; int n; diff --git a/HPPA/fileOperation.h b/HPPA/fileOperation.h index 784d23d..44adf3c 100644 --- a/HPPA/fileOperation.h +++ b/HPPA/fileOperation.h @@ -17,7 +17,7 @@ public: ~FileOperation(); string getDirectoryOfExe();//getDirectoryOfExe - string getDirectoryFromString(string directory="C:\\HPPA_image"); + string getDirectoryFromString(string directory=""); diff --git a/HPPA/set.ui b/HPPA/set.ui index f7ffd06..93f8510 100644 --- a/HPPA/set.ui +++ b/HPPA/set.ui @@ -10,7 +10,7 @@ 0 0 486 - 401 + 229 @@ -234,42 +234,25 @@ QPushButton:pressed - - - - 20 - 60 - 54 - 12 - - - - 数据路径 - - - - - - 80 - 50 - 113 - 30 - - - - - - - 210 - 50 - 101 - 31 - - - - ... - - + + + + + 数据路径 + + + + + + + + + + ... + + + + diff --git a/HPPA/setWindow.cpp b/HPPA/setWindow.cpp index 03a64b2..9ed9ad5 100644 --- a/HPPA/setWindow.cpp +++ b/HPPA/setWindow.cpp @@ -1,27 +1,49 @@ #include "setWindow.h" +#include "AppSettings.h" #include -#include +#include +#include setWindow::setWindow(QWidget* parent) { ui.setupUi(this); - //Qt::WindowFlags flags = 0; - ////flags |= Qt::WindowMinimizeButtonHint; - //flags |= Qt::WindowCloseButtonHint; - //flags |= Qt::MSWindowsFixedSizeDialogHint; - //setWindowFlags(flags); setWindowFlags(Qt::FramelessWindowHint); connect(this->ui.closeBtn, SIGNAL(released()), this, SLOT(onExit())); + connect(this->ui.dataFolderBtn, SIGNAL(clicked()), this, SLOT(onSelectDataFolder())); + + loadSettings(); } setWindow::~setWindow() { +} +void setWindow::loadSettings() +{ + ui.dataFolderLineEdit->setText(AppSettings::instance().dataFolder()); +} + +void setWindow::saveSettings() +{ + AppSettings::instance().setDataFolder(ui.dataFolderLineEdit->text()); +} + +void setWindow::onSelectDataFolder() +{ + QString dir = QFileDialog::getExistingDirectory(this, + QString::fromLocal8Bit("选择数据保存路径"), + ui.dataFolderLineEdit->text()); + + if (!dir.isEmpty()) + { + ui.dataFolderLineEdit->setText(dir); + } } void setWindow::onExit() { + saveSettings(); this->close(); } diff --git a/HPPA/setWindow.h b/HPPA/setWindow.h index 15bf78e..ffe9c16 100644 --- a/HPPA/setWindow.h +++ b/HPPA/setWindow.h @@ -2,25 +2,25 @@ #include #include - #include "ui_set.h" class setWindow :public QDialog { Q_OBJECT - public: setWindow(QWidget* parent = Q_NULLPTR); ~setWindow(); - - private: Ui::setDialog ui; + void loadSettings(); + void saveSettings(); + public Q_SLOTS: void onExit(); + void onSelectDataFolder(); signals: