Files
ximeaAirborneSystem/Source_Files/ximeaimager.cpp
tangchao0503 84882c5edb 1、添加配置文件读、写、解析类Configfile(使用libconfig.h++);
2、打开相机时,通过Configfile读取和解析配置文件,并使用;
3、修复一些代码逻辑bug;
2022-08-01 19:10:25 +08:00

642 lines
19 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.

#include "Header_Files/ximeaimager.h"
XimeaImager::XimeaImager()
{
m_buffer=nullptr;
m_bRecordControl=false;
m_iFrameCounter=0;
m_iImagerState=100;
//connect(this, SIGNAL(recordFinished()),this, SLOT());
m_configfile.setConfigfilePath("ximea.cfg");
m_configfile.parseConfigfile();
// m_configfile.createConfigFile();
}
void XimeaImager::openImger()
{
if(m_iImagerState != 100)//如果相机已经打开或者已经出错,就直接返回
{
emit ximeaImageStatus(m_iImagerState);
return;
}
try
{
//std::cout<<"XimeaImager::openImger111111111111111111111:正在打开相机!"<<std::endl;
m_imager.connect();
int bin=0;
m_configfile.getBin(bin);
bool haha = m_imager.setSpectralBin(bin);
bool haha2 = m_imager.setSpatialBin(bin);
float gain, offset;//用于生成头文件中的波长信息
m_configfile.getGainOffset(gain, offset);
m_imager.setGainOffset(gain, offset);
int width = 0, offsetx = 0, height = 0, offsety = 0;
m_configfile.getEffectiveWindow(width, offsetx, height, offsety);
m_imager.setRoi(offsetx, width, offsety, height);
setFramerate(100);
//经验证frameSizeManual和frameSizeAuto相等
int frameSizeManual = m_imager.get_band_count()*m_imager.get_sample_count()*2;
int frameSizeAuto = m_imager.getBufferSizeOfOneFrame();
m_iFrameSizeInByte = frameSizeAuto;
m_buffer = new unsigned short[m_iFrameSizeInByte];
m_iImagerState = 101;
emit ximeaImageStatus(m_iImagerState);
}
catch(int xiApiErrorCodes)
{
std::cout<<"XimeaImager::openImger----------------:ERROR!"<<std::endl;
processXiApiErrorCodes(xiApiErrorCodes);
}
catch(char const* e1)
{
std::cout<<"char *e---------!"<<std::endl;
}
}
void XimeaImager::closeImger()
{
if(m_iImagerState==100)
{
emit ximeaImageStatus(m_iImagerState);
return;
}
try
{
m_imager.disconnect();
m_iImagerState=100;
emit ximeaImageStatus(m_iImagerState);
}
catch(int xiApiErrorCodes)
{
std::cout<<"XimeaImager::closeImger-------------------!"<<std::endl;
processXiApiErrorCodes(xiApiErrorCodes);
}
}
void XimeaImager::setFramerate(double framerate)
{
try
{
m_imager.set_framerate(framerate);
int maxExposureTimeInUs=1/framerate*1000000*0.8;
setExposureTime(maxExposureTimeInUs);
// setExposureTime(1000);
m_iImagerState=102;
emit ximeaImageStatus(m_iImagerState);
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
}
}
double XimeaImager::getExposureTime()
{
double exposureTime;
try
{
exposureTime=m_imager.get_integration_time();
return exposureTime;
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
return -1;
}
}
double XimeaImager::setExposureTime(float exposureTime_in_us)
{
double integrationTime2Return;
try
{
//计算最大积分时间
float currentFramerate=getFramerate();
float maxExposureTime_in_us=1/currentFramerate*1000000;
//确保设置的积分时间比最大积分时间小
if(exposureTime_in_us<maxExposureTime_in_us)
{
m_imager.set_integration_time(exposureTime_in_us);
}
else
{
m_imager.set_integration_time(maxExposureTime_in_us);
}
//返回设置的积分时间
integrationTime2Return=m_imager.get_integration_time();
return integrationTime2Return;
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
return -1;
}
}
double XimeaImager::autoExposure()
{
double exposureTime;
try
{
//方式1:在曝光时的帧率前提下,从最大曝光时间开始循环采集
int maxValueOfOneFrame;
float suitableMaxValue=4095 * 0.8;
double framerate = m_imager.get_framerate();
double maxExposureTime = 1/framerate*1000000;
exposureTime=setExposureTime(maxExposureTime);
bool bIsAutoExposureOk=false;
while(!bIsAutoExposureOk)
{
m_imager.start();
m_imager.get_frame(m_buffer);
m_imager.stop();
maxValueOfOneFrame=getMaxValueOfOneFrame(m_buffer,m_imager.get_band_count()*m_imager.get_sample_count());
if(maxValueOfOneFrame <= suitableMaxValue)
{
bIsAutoExposureOk=true;
}
else
{
exposureTime = exposureTime*0.95;
exposureTime=setExposureTime(exposureTime);
}
}
// //方式2
// int baseExposureTime_in_us=5000;
// float suitableMaxValue=4095 * 0.8;
// int maxValueOfOneFrame;
// setExposureTime(baseExposureTime_in_us);
// m_imager.start();
// m_imager.get_frame(m_buffer);
// m_imager.stop();
// std::cout<<"1111111111111111111111111111111111!"<<std::endl;
// maxValueOfOneFrame=getMaxValueOfOneFrame(m_buffer,m_imager.get_band_count()*m_imager.get_sample_count());
// std::cout<<"2222222222222222222222222222222222!"<<std::endl;
// float scale=suitableMaxValue/maxValueOfOneFrame;
// float suitableExposureTime=baseExposureTime_in_us * scale;
// exposureTime=setExposureTime(suitableExposureTime);
m_iImagerState=103;
emit ximeaImageStatus(m_iImagerState);
std::cout<<"自动曝光完成!"<<std::endl;
return exposureTime;
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
std::cout<<"自动曝光失败!"<<std::endl;
return -1;
}
}
double XimeaImager::getFramerate()
{
double framerate;
try
{
framerate=m_imager.get_framerate();
return framerate;
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
return -1;
}
}
void XimeaImager::setGain(double gain)
{
try
{
m_imager.set_gain(gain);
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
}
}
double XimeaImager::getGain()
{
try
{
return m_imager.get_gain();
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
return -1;
}
}
int XimeaImager::getSampleCount()
{
try
{
int sampleCount=m_imager.get_sample_count();
return sampleCount;
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
return -1;
}
}
int XimeaImager::getBandCount()
{
int bandCount;
try
{
bandCount=m_imager.get_band_count();
return bandCount;
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
return -1;
}
}
int XimeaImager::getWindowStartBand()
{
int windowStartBand;
try
{
windowStartBand=m_imager.get_start_band();
return windowStartBand;
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
return -1;
}
}
int XimeaImager::getWindowEndBand()
{
int windowEndBand;
try
{
windowEndBand=m_imager.get_end_band();
return windowEndBand;
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
return -1;
}
}
double XimeaImager::geWavelengthAtBand(int x)
{
double wavelengthAtBand;
try
{
wavelengthAtBand=m_imager.get_wavelength_at_band(x);
return wavelengthAtBand;
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
return -1;
}
}
int XimeaImager::getMaxValueOfOneFrame(unsigned short * data, int numberOfPixel)
{
//排序
//bubbleSort(data,1000);
//计算出最大的10%值的平均值
unsigned short maxValue=0;
for(int i=0;i<numberOfPixel;i++)
{
if (data[i]>maxValue)
{
maxValue=data[i];
}
}
printf("本帧最大值为: %d.\n",maxValue);
return maxValue;
}
int XimeaImager::getImagerState() const
{
return m_iImagerState;
}
void XimeaImager::startRecord(double TimeDifferenceBetweensOSAndSbg,QString baseFileName)
{
try
{
if(m_iImagerState <= 99 || m_iImagerState==100 || m_iImagerState==104)
{
emit ximeaImageStatus(m_iImagerState);
return;
}
m_iImagerStateTemp=m_iImagerState;
m_iImagerState=104;
emit ximeaImageStatus(m_iImagerState);
printf("开始采集!\n");
m_iFrameCounter=0;
m_bRecordControl=true;
m_imager.start();
m_baseFileName=baseFileName;
QString imageFileName=m_baseFileName+".bil";
QString timesFileName=m_baseFileName+".times";
//
FILE *hFile=fopen(imageFileName.toStdString().c_str(),"w+b");
FILE *hHimesFile=fopen(timesFileName.toStdString().c_str(),"w+");
using namespace std;
ofstream timesFileHandle(timesFileName.toStdString()+"_ofstream");
struct timeval timeStart, timeEnd;
double runTime=0;
gettimeofday(&timeStart, NULL);
while (m_bRecordControl)
{
unsigned short *x=m_imager.get_frame(m_buffer);
//fwrite(m_buffer,2,getBandCount()*getSampleCount(),hFile);
fwrite(m_buffer,1,m_iFrameSizeInByte,hFile);//*********************************
//fflush(hFile);//只保证了将IO缓冲写入系统缓冲中使IO读操作能成功但系统什么时候写入磁盘由系统决定一般是达到一定量时系统他就写入磁盘。
//sync();//强制系统将系统文件缓冲的内容写入磁盘
m_iFrameCounter+=1;
double sbgTime=getSbgTime(TimeDifferenceBetweensOSAndSbg);
fprintf(hHimesFile,"%f\n",sbgTime);
//fwrite(&sbgTime,sizeof(double),1,hHimesFile);
timesFileHandle << sbgTime << "\n";
// std::cout<<"XimeaImager::startRecord---std::cout: "<<sbgTime<<std::endl;
// //用于测试是否漏帧
// if(m_iFrameCounter==getFramerate()*20)
// {
// break;
// }
// unsigned char pixel = *(unsigned char*)image.bp;//Default value: XI_MONO8
// unsigned short pixel =*(unsigned short*)image.bp;//XI_RAW16
// printf("Image %d (%dx%d) received from camera. First pixel value: %d\n", m_iFrameCounter, (int)image.width, (int)image.height, pixel);
}
gettimeofday(&timeEnd, NULL);
runTime = (timeEnd.tv_sec - timeStart.tv_sec ) + (double)(timeEnd.tv_usec -timeStart.tv_usec)/1000000;
double frameInTheory=runTime * getFramerate();
double frameLossed=frameInTheory - m_iFrameCounter;
double frameLossRate=frameLossed / frameInTheory;
std::cout<<"当前采集文件为: "<<baseFileName.toStdString()<<std::endl;
std::cout<<"采集时间为: "<<runTime<<std::endl;
std::cout<<"理论采集帧数为: "<<frameInTheory<<std::endl;
std::cout<<"实际采集帧数为:"<<m_iFrameCounter<<std::endl;
std::cout<<"丢失帧数为: "<<frameLossed<<std::endl;
std::cout<<"丢帧率为: "<<frameLossRate<<std::endl;
fclose(hFile);
fclose(hHimesFile);
timesFileHandle.close();
printf("Stopping acquisition...\n");
m_imager.stop();
writeHdr();
m_iImagerState=m_iImagerStateTemp;
emit ximeaImageStatus(m_iImagerState);
emit recordFinished();
}
catch(int xiApiErrorCodes)
{
processXiApiErrorCodes(xiApiErrorCodes);
}
}
void XimeaImager::writeHdr()
{
using namespace std;
QString hdrPath=m_baseFileName+".hdr";
ofstream hdrFileHandle(hdrPath.toStdString());
hdrFileHandle << "ENVI\n";
hdrFileHandle << "interleave = bil\n";
hdrFileHandle << "byte order = 0\n";
hdrFileHandle << "data type = 2\n";
//hdrFileHandle << "bit depth = 12\n";
hdrFileHandle << "samples = " << getSampleCount() << "\n";
hdrFileHandle << "bands = " << getBandCount() << "\n";
hdrFileHandle << "lines = " << m_iFrameCounter << "\n";
hdrFileHandle << "sample binning = " << m_imager.getSpatialBin() << "\n";
hdrFileHandle << "spectral binning = " << m_imager.getSpectralBin() << "\n";
hdrFileHandle << "framerate = " << getFramerate() << "\n";
hdrFileHandle << "shutter = " << getExposureTime()/1000 << "\n";
hdrFileHandle << "shutter units = milliseconds\n";
hdrFileHandle << "gain = " << getGain() << "\n";
hdrFileHandle << "wavelength units = nanometers\n";
hdrFileHandle << "wavelength = {";
//hdrFileHandle << std::setprecision(5);
for (int i = getWindowStartBand(); i < getWindowEndBand(); i++)
{
hdrFileHandle << geWavelengthAtBand(i);
if (i < getWindowEndBand() - 1)
hdrFileHandle << ", ";
else
{
printf("头文件中写入了多少个波段:%d\n",i-getWindowStartBand()+1);//???????????????
}
}
hdrFileHandle << "}\n";
hdrFileHandle.close();
}
/*
#define MM40_OK 0 //!< Function call succeeded
#define MM40_INVALID_HANDLE 1 //!< Invalid handle
#define MM40_READREG 2 //!< Register read error
#define MM40_WRITEREG 3 //!< Register write error
#define MM40_FREE_RESOURCES 4 //!< Freeing resources error
#define MM40_FREE_CHANNEL 5 //!< Freeing channel error
#define MM40_FREE_BANDWIDTH 6 //!< Freeing bandwith error
#define MM40_READBLK 7 //!< Read block error
#define MM40_WRITEBLK 8 //!< Write block error
#define MM40_NO_IMAGE 9 //!< No image
#define MM40_TIMEOUT 10 //!< Timeout
#define MM40_INVALID_ARG 11 //!< Invalid arguments supplied
#define MM40_NOT_SUPPORTED 12 //!< Not supported
#define MM40_ISOCH_ATTACH_BUFFERS 13 //!< Attach buffers error
#define MM40_GET_OVERLAPPED_RESULT 14 //!< Overlapped result
#define MM40_MEMORY_ALLOCATION 15 //!< Memory allocation error
#define MM40_DLLCONTEXTISNULL 16 //!< DLL context is NULL
#define MM40_DLLCONTEXTISNONZERO 17 //!< DLL context is non zero
#define MM40_DLLCONTEXTEXIST 18 //!< DLL context exists
#define MM40_TOOMANYDEVICES 19 //!< Too many devices connected
#define MM40_ERRORCAMCONTEXT 20 //!< Camera context error
#define MM40_UNKNOWN_HARDWARE 21 //!< Unknown hardware
#define MM40_INVALID_TM_FILE 22 //!< Invalid TM file
#define MM40_INVALID_TM_TAG 23 //!< Invalid TM tag
#define MM40_INCOMPLETE_TM 24 //!< Incomplete TM
#define MM40_BUS_RESET_FAILED 25 //!< Bus reset error
#define MM40_NOT_IMPLEMENTED 26 //!< Not implemented
#define MM40_SHADING_TOOBRIGHT 27 //!< Shading is too bright
#define MM40_SHADING_TOODARK 28 //!< Shading is too dark
#define MM40_TOO_LOW_GAIN 29 //!< Gain is too low
#define MM40_INVALID_BPL 30 //!< Invalid sensor defect correction list
#define MM40_BPL_REALLOC 31 //!< Error while sensor defect correction list reallocation
#define MM40_INVALID_PIXEL_LIST 32 //!< Invalid pixel list
#define MM40_INVALID_FFS 33 //!< Invalid Flash File System
#define MM40_INVALID_PROFILE 34 //!< Invalid profile
#define MM40_INVALID_CALIBRATION 35 //!< Invalid calibration
#define MM40_INVALID_BUFFER 36 //!< Invalid buffer
#define MM40_INVALID_DATA 38 //!< Invalid data
#define MM40_TGBUSY 39 //!< Timing generator is busy
#define MM40_IO_WRONG 40 //!< Wrong operation open/write/read/close
#define MM40_ACQUISITION_ALREADY_UP 41 //!< Acquisition already started
#define MM40_OLD_DRIVER_VERSION 42 //!< Old version of device driver installed to the system.
#define MM40_GET_LAST_ERROR 43 //!< To get error code please call GetLastError function.
#define MM40_CANT_PROCESS 44 //!< Data cannot be processed
#define MM40_ACQUISITION_STOPED 45 //!< Acquisition is stopped. It needs to be started to perform operation.
#define MM40_ACQUISITION_STOPED_WERR 46 //!< Acquisition has been stopped with an error.
#define MM40_INVALID_INPUT_ICC_PROFILE 47 //!< Input ICC profile missing or corrupted
#define MM40_INVALID_OUTPUT_ICC_PROFILE 48 //!< Output ICC profile missing or corrupted
#define MM40_DEVICE_NOT_READY 49 //!< Device not ready to operate
#define MM40_SHADING_TOOCONTRAST 50 //!< Shading is too contrast
#define MM40_ALREADY_INITIALIZED 51 //!< Module already initialized
#define MM40_NOT_ENOUGH_PRIVILEGES 52 //!< Application does not have enough privileges (one or more app)
#define MM40_NOT_COMPATIBLE_DRIVER 53 //!< Installed driver is not compatible with current software
#define MM40_TM_INVALID_RESOURCE 54 //!< TM file was not loaded successfully from resources
#define MM40_DEVICE_HAS_BEEN_RESETED 55 //!< Device has been reset, abnormal initial state
#define MM40_NO_DEVICES_FOUND 56 //!< No Devices Found
#define MM40_RESOURCE_OR_FUNCTION_LOCKED 57 //!< Resource (device) or function locked by mutex
#define MM40_BUFFER_SIZE_TOO_SMALL 58 //!< Buffer provided by user is too small
#define MM40_COULDNT_INIT_PROCESSOR 59 //!< Could not initialize processor.
#define MM40_NOT_INITIALIZED 60 //!< The object/module/procedure/process being referred to has not been started.
#define MM40_RESOURCE_NOT_FOUND 61 //!< Resource not found(could be processor, file, item...).
*/
void XimeaImager::processXiApiErrorCodes(int xiApiErrorCodes)
{
using namespace std;
switch (xiApiErrorCodes)
{
case 1:
std::cout<<"XimeaImager::processXiApiErrorCodes-----------:Invalid handle!"<<std::endl;
m_iImagerState=xiApiErrorCodes;
emit ximeaImageStatus(m_iImagerState);
break;
case 15:
std::cout<<"XimeaImager::processXiApiErrorCodes-----------:Memory allocation error!"<<std::endl;
m_iImagerState=xiApiErrorCodes;
emit ximeaImageStatus(m_iImagerState);
break;
case 56:
std::cout<<"XimeaImager::processXiApiErrorCodes-----------:NO_DEVICES_FOUND!"<<std::endl;
m_iImagerState=xiApiErrorCodes;
emit ximeaImageStatus(m_iImagerState);
break;
case 57:
std::cout<<"XimeaImager::processXiApiErrorCodes-----------:RESOURCE_OR_FUNCTION_LOCKED!"<<std::endl;
m_iImagerState=xiApiErrorCodes;
emit ximeaImageStatus(m_iImagerState);
break;
default:
QString ximeaError="ximeaError.txt";
ofstream ximeaErrorFile(ximeaError.toStdString().c_str(),ios::app);
ximeaErrorFile<< xiApiErrorCodes << "\n";
ximeaErrorFile.close();
m_iImagerState=99;
emit ximeaImageStatus(m_iImagerState);
break;
}
}
void XimeaImager::stopRecord()
{
//printf("Stop record!\n");
m_bRecordControl=false;
}
int XimeaImager::getFrameCounter()
{
return m_iFrameCounter;
}