You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
smokeboxidentification/src/CameraControl.cpp

722 lines
18 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#pragma execution_character_set("utf-8")
#include "CameraControl.h"
#include <QDebug>
CameraControl::CameraControl()
{
m_calib1 = ILCalibNPointsPtr(__uuidof(LCalibNPoints));
m_calib1->FixImageMode = LPVFixImageMode::LPVFixImageUndistortAndUntilt;
m_calib2 = ILCalibNPointsPtr(__uuidof(LCalibNPoints));
m_calib2->FixImageMode = LPVFixImageMode::LPVFixImageUndistortAndUntilt;
qRegisterMetaType<QVector<ImageInfo> >("QVector<ImageInfo>");
m_pobjThread = new QThread;
moveToThread(m_pobjThread);
connect(m_pobjThread, &QThread::started, this, &CameraControl::onOpen);
connect(m_pobjThread, &QThread::finished,
this, &QObject::deleteLater);
m_pobjThread->start();
}
CameraControl::~CameraControl()
{
if (m_pobjThread)
{
m_pobjThread->quit();
m_pobjThread->wait();
m_pobjThread = nullptr;
}
for each (Camera* pCamera in m_vecPCamera)
{
DELETE_POINTER(pCamera);
}
m_vecPCamera.clear();
}
Q_SLOT void CameraControl::onOpen()
{
QString filePath = QCoreApplication::applicationDirPath() + CAMERA_CONFIG;
if (readCameraConfig(filePath))
{
m_bCamerasInit = initCamera();
}
}
bool CameraControl::readCameraConfig(QString filePath)
{
m_mapIdCameraInfoSide.clear();
m_mapIdCameraInfoTop.clear();
exposureRowMap.clear();
m_mapSerialNumberIdSide.clear();
m_mapSerialNumberIdTop.clear();
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qWarning() << "打开文件失败!";
return false;
}
QByteArray arr = file.readAll();
file.close();
if (arr.isEmpty())
{
qWarning() << "内容为空";
return false;
}
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(arr, &err);
if (doc.isEmpty())
{
qWarning() <<"[QJsonDocument]: "<< err.errorString(); //打印失败信息
return false;
}
QJsonObject jsonObj = doc.object();
auto getCameraType = [](int type)-> CameraType
{
CameraType cameraType;
switch (type)
{
case 100:
cameraType = CameraType::Virtual;
break;
case 140:
cameraType = CameraType::Hik;
break;
case 190:
cameraType = CameraType::Basler;
break;
case 210:
cameraType = CameraType::LXTof;
break;
default:
break;
}
return cameraType;
};
QJsonObject topObj = jsonObj.value("top").toObject();
int topStartId, topEndId;
if (!topObj.isEmpty())
{
topStartId = topObj.value("startID").toInt();
topEndId = topObj.value("endID").toInt();
}
else
{
qWarning() << "top id error";
return false;
}
QJsonObject sideObj = jsonObj.value("side").toObject();
int sideStartId, sideEndId;
if (!sideObj.isEmpty())
{
sideStartId = sideObj.value("startID").toInt();
sideEndId = sideObj.value("endID").toInt();
}
else
{
qWarning() << "side id error";
return false;
}
//根据文档读取,没有则采用默认值如下
//现在1和2巷道都是用的下三层1-3层曝光值250000ms/增益20
//中三层4-6层曝光值150000ms/增益20
//上三层7-9层曝光值50000ms/增益20
QJsonObject exposureRowObj = jsonObj.value("exposureRowMap").toObject();
if (!exposureRowObj.isEmpty())
{
for each (QString key in exposureRowObj.keys()) {
exposureRowMap[key.toInt()] = exposureRowObj.value(key).toInt();
}
}
else
{
for (int floor = 1; floor <= 9; floor++) {
int exposure = 2500;
if (floor >= 1 && floor <= 3)
{
exposure = 250000;
}
else if (floor >= 7 && floor <= 9)
{
exposure = 50000;
}
else
{
exposure = 150000;
}
exposureRowMap[floor] = exposure;
}
}
QJsonObject devicesObj = jsonObj.value("devices").toObject();
if (!devicesObj.isEmpty()) {
QStringList devicesLabelList = devicesObj.keys();
for each (QString deviceLabel in devicesLabelList)
{
CameraInfo cameraInfo;
cameraInfo.cameraLabel = deviceLabel;
QStringList strList = deviceLabel.split(' ');
if (strList.length() != 2)
{
qWarning() << "Device label: " << deviceLabel << " syntax error!";
continue;
}
cameraInfo.modelName = strList.at(0);
cameraInfo.serialNumber = strList.at(1);
QJsonObject deviceObj = devicesObj.value(deviceLabel).toObject();
if (!deviceObj.isEmpty())
{
cameraInfo.cameraType = getCameraType(deviceObj.value("type").toInt());
cameraInfo.exposure = deviceObj.value("exposure").toDouble();
cameraInfo.imageHeight = deviceObj.value("height").toInt();
cameraInfo.imageWidth = deviceObj.value("width").toInt();
cameraInfo.location = deviceObj.value("location").toInt();
m_cameraStockLocation.insert(cameraInfo.serialNumber, cameraInfo.location);
if (deviceObj.contains("calib_file"))
{
cameraInfo.calibFile = deviceObj.value("calib_file").toString();
if (cameraInfo.location == 1)
{
m_calib1->Load(cameraInfo.calibFile.toStdString().c_str());
}
else
{
m_calib2->Load(cameraInfo.calibFile.toStdString().c_str());
}
}
cameraInfo.saveImgSuffix = deviceObj.value("save_img_suffix").toString();
int id = deviceObj.value("id").toInt();
if (deviceObj.contains("rotation_angle"))
{
cameraInfo.rotationAngle = deviceObj.value("rotation_angle").toInt();
}
if (id >= topStartId && id <= topEndId)
{
m_mapIdCameraInfoTop[id] = cameraInfo;
m_mapSerialNumberIdTop[cameraInfo.serialNumber] = id;
}
else if (id >= sideStartId && id <= sideEndId)
{
m_mapIdCameraInfoSide[id] = cameraInfo;
m_mapSerialNumberIdSide.append(qMakePair(cameraInfo.serialNumber,id));
//m_mapSerialNumberIdSide[cameraInfo.serialNumber] = id;
}
}
}
}
return true;
}
bool CameraControl::initCamera()
{
QList<CameraInfo> cameraInfoList = m_mapIdCameraInfoSide.values();
cameraInfoList.append(m_mapIdCameraInfoTop.values());
if (!loadCamera(cameraInfoList))
{
qWarning() << "Load camera failed";
return false;
}
else
{
QStringList serialNumberList = m_mapSNIndex.keys();
for each (const QString& serialNumber in serialNumberList)
{
if (!openCamera(serialNumber))
{
qWarning() << "Open camera: " << serialNumber << " failed";
continue;
}
else
{
qDebug() << "Open camera: " << serialNumber << " successed";
if (!startCamera(serialNumber))
{
qWarning() << "Start camera: " << serialNumber << " failed";
continue;
}
else
{
qDebug() << "Start camera: " << serialNumber << " successed";
if (!setSoftwareTrigger(serialNumber))
{
qWarning() << "Set camera: " << serialNumber << " software trigger failed";
}
else
{
qDebug() << "Set camera: " << serialNumber << " software trigger successed";
}
}
}
}
}
return true;
}
bool CameraControl::loadCamera(const QList<CameraInfo>& cameraInfoList)
{
bool flag = false;
for each (Camera* pCamera in m_vecPCamera)
{
DELETE_POINTER(pCamera);
}
m_vecPCamera.clear();
m_mapSNIndex.clear();
for each(CameraInfo cameraInfo in cameraInfoList)
{
qDebug() << "serialNumber[" << cameraInfo.serialNumber << "]:" << cameraInfo.cameraType;
QString serialNumber = cameraInfo.serialNumber;
CameraType cameraType = cameraInfo.cameraType;
if (cameraType == CameraType::Hik)
{
for (int i = 0; i < 500; i++) {
Camera* pHikCamera = new HikCamera();
if (pHikCamera->initCamera(serialNumber))
{
m_vecPCamera.push_back(pHikCamera);
m_mapSNIndex[serialNumber] = m_vecPCamera.size() - 1;
flag = true;
break;
}
else
{
qWarning() << "SerialNumber: " << serialNumber << " init failed ;count " <<i;
DELETE_POINTER(pHikCamera);
Sleep(1000);
//flag = false;
}
}
}
else if (cameraType == CameraType::LXTof)
{
for (int i = 0; i < 500; i++) {
Camera* pLXCamera = new LXCamera();
if (pLXCamera->initCamera(serialNumber))
{
m_vecPCamera.push_back(pLXCamera);
m_mapSNIndex[serialNumber] = m_vecPCamera.size() - 1;
flag = true;
break;
}
else
{
qWarning() << "SerialNumber: " << serialNumber << " init failed ;count " << i;
DELETE_POINTER(pLXCamera);
Sleep(1000);
//flag = false;
}
}
}
}
qDebug() << "m_vecPCamera size: " << m_vecPCamera.size();
return flag;
}
bool CameraControl::openCamera(const QStringList& serialNumberList)
{
bool flag = true;
for each (QString serialNumber in serialNumberList)
{
if (!openCamera(serialNumber))
{
qWarning() << "Open " << serialNumber << "failed!";
flag = false;
}
else
{
qDebug() << "Open " << serialNumber << " successed";
}
}
return flag;
}
bool CameraControl::closeCamera(const QStringList& serialNumberList)
{
bool flag = true;
for each (QString serialNumber in serialNumberList)
{
if (!closeCamera(serialNumber))
{
qWarning() << "Close " << serialNumber << "failed!";
flag = false;
}
else
{
qDebug() << "Close " << serialNumber << " successed";
}
}
return flag;
}
bool CameraControl::startCamera(const QStringList& serialNumberList)
{
bool flag = true;
for each (QString serialNumber in serialNumberList)
{
if (!startCamera(serialNumber))
{
qWarning() << "Start " << serialNumber << "failed!";
flag = false;
}
else
{
qDebug() << "Start " << serialNumber << " successed";
}
}
return flag;
}
bool CameraControl::stopCamera(const QStringList& serialNumberList)
{
bool flag = true;
for each (QString serialNumber in serialNumberList)
{
if (!stopCamera(serialNumber))
{
qWarning() << "Stop " << serialNumber << "failed!";
flag = false;
}
else
{
qDebug() << "Stop " << serialNumber << " successed";
}
}
return flag;
}
bool CameraControl::setSoftwareTrigger(const QStringList& serialNumberList)
{
bool flag = true;
for each (QString serialNumber in serialNumberList)
{
if (!setSoftwareTrigger(serialNumber))
{
qWarning() << "Set " << serialNumber << " software trigger failed!";
flag = false;
}
else
{
qDebug() << "Set " << serialNumber << " software trigger successed";
}
}
return flag;
}
bool CameraControl::openCamera(const QString& serialNumber)
{
QMap<QString, int>::iterator iter = m_mapSNIndex.find(serialNumber);
qInfo() << "openCamera sid: " << serialNumber << " index:" << iter.value();
if (iter == m_mapSNIndex.end())
{
qWarning() << "Do not find " << serialNumber;
return false;
}
int index = iter.value();
return m_vecPCamera[index]->openCamera();
}
bool CameraControl::closeCamera(const QString& serialNumber)
{
QMap<QString, int>::iterator iter = m_mapSNIndex.find(serialNumber);
if (iter == m_mapSNIndex.end())
{
qWarning() << "Do not find " << serialNumber;
return false;
}
int index = iter.value();
return m_vecPCamera[index]->closeCamera();
}
bool CameraControl::startCamera(const QString& serialNumber)
{
QMap<QString, int>::iterator iter = m_mapSNIndex.find(serialNumber);
if (iter == m_mapSNIndex.end())
{
qWarning() << "Do not find " << serialNumber;
return false;
}
int index = iter.value();
return m_vecPCamera[index]->startCamera();
}
bool CameraControl::stopCamera(const QString& serialNumber)
{
QMap<QString, int>::iterator iter = m_mapSNIndex.find(serialNumber);
if (iter == m_mapSNIndex.end())
{
qWarning() << "Do not find " << serialNumber;
return false;
}
int index = iter.value();
return m_vecPCamera[index]->stopCamera();
}
bool CameraControl::setSoftwareTrigger(const QString& serialNumber)
{
QMap<QString, int>::iterator iter = m_mapSNIndex.find(serialNumber);
if (iter == m_mapSNIndex.end())
{
qWarning() << "Do not find " << serialNumber;
return false;
}
int index = iter.value();
return m_vecPCamera[index]->setTriggerSource(SOFTWARE);
}
int CameraControl::getDeviceId(const QString& serialNumber) {
for (int i = 0; i < m_mapSerialNumberIdSide.size(); ++i) {
if (m_mapSerialNumberIdSide[i].first == serialNumber) {
return i;
}
}
//return -1;
//return m_mapSerialNumberIdSide.value(serialNumber);
}
bool CameraControl::setExposure(const QString& serialNumber, int exposure)
{
QMap<QString, int>::iterator iter = m_mapSNIndex.find(serialNumber);
if (iter == m_mapSNIndex.end())
{
qWarning() << "Do not find " << serialNumber;
return false;
}
int index = iter.value();
return m_vecPCamera[index]->setExposure(exposure);
}
bool CameraControl::capture(const QString& serialNumber, cv::Mat& img, cv::Mat& img3D, int exposure)
{
QMap<QString, int>::iterator iter = m_mapSNIndex.find(serialNumber);
if (iter == m_mapSNIndex.end())
{
qWarning() << "Do not find " << serialNumber;
return false;
}
int index = iter.value();
m_vecPCamera[index]->setExposure(exposure);
int localMap = m_cameraStockLocation.find(serialNumber).value();
m_vecPCamera[index]->takeAPic(img, img3D, localMap);
if (img.empty())
{
qWarning() << serialNumber << " capture empty";
}
return true;
}
bool CameraControl::getSaveImgNameInfo(QString serialNumber, FileInfo& fileInfo)
{
QString imgSaveBaseName;
//auto iter = getDeviceId(serialNumber);
//auto iter = m_mapSerialNumberIdSide.find(serialNumber);
// 查找serialNumber在m_listSerialNumberIdSide中的位置
auto iter = std::find_if(m_mapSerialNumberIdSide.begin(), m_mapSerialNumberIdSide.end(),
[&](const QPair<QString, int>& pair) { return pair.first == serialNumber; });
if (iter == m_mapSerialNumberIdSide.end())
{
/*iter = m_mapSerialNumberIdTop.find(serialNumber);
if (iter != m_mapSerialNumberIdTop.end())
{
int id = iter.value();
QString suffix = m_mapIdCameraInfoTop.value(id).saveImgSuffix;
fileInfo.suffix = suffix;
fileInfo.strId = QString::number(id);
fileInfo.name = fileInfo.strId + suffix;
}
else
{
qWarning() << "Can not find " << serialNumber;
return false;
}*/
}
else
{
int id = iter->second;
QString suffix = m_mapIdCameraInfoSide.value(id).saveImgSuffix;
fileInfo.suffix = suffix;
fileInfo.strId = QString::number(id);
fileInfo.name = fileInfo.strId + suffix;
}
return true;
}
Q_SLOT void CameraControl::onCapture(int cameraLocation,int location, int floor)
{
QStringList serialNumList;
switch (cameraLocation)
{
case eCameraLocation::emTop:
m_eCameraLocation = emTop;
#if IMAGEDRAWING == LPV
for (auto iter = m_mapSerialNumberIdTop.begin(); iter != m_mapSerialNumberIdTop.end(); iter++)
{
if (m_cameraStockLocation[iter.key()] == location)
{
serialNumList << iter.key();
}
}
#elif IMAGEDRAWING == OPENCV
serialNumList = m_mapSerialNumberIdTop.keys();
#endif
break;
case eCameraLocation::emSide:
m_eCameraLocation = emSide;
#if IMAGEDRAWING == LPV
for (auto iter = m_mapSerialNumberIdSide.begin(); iter != m_mapSerialNumberIdSide.end(); iter++)
{
//if (m_cameraStockLocation[iter->first] == location)
//直接保存所有图片
{
serialNumList << iter->first;
}
}
#elif IMAGEDRAWING == OPENCV
serialNumList = m_mapSerialNumberIdSide.keys();
#endif // IMAGEDRAWING == LPV
break;
default:
break;
}
if (serialNumList.length() != 0)
{
qInfo() << "Captured SerialNumList = " << serialNumList;
//进行拍照
capture(serialNumList, location, floor);
}
}
void CameraControl::capture(const QStringList& serialNumberList, int location, int floor)
{
int len = serialNumberList.length();
//qDebug() << "start capture, length: " << len;
QVector<ImageInfo> vecImageInfo;
for (int i = 0; i < len; ++i)
{
QString serialNumber = serialNumberList.at(i);
if (!m_mapSNIndex.contains(serialNumber))
{
qWarning() << "m_vecPCamera does not have camera: " << serialNumber;
continue;
}
ImageInfo imgInfo;
FileInfo saveImgInfo;
saveImgInfo.location = location;
getSaveImgNameInfo(serialNumber, saveImgInfo);
imgInfo.saveImgInfo = saveImgInfo;
int id = saveImgInfo.strId.toInt();
int rotationAngle = 0;
if (m_mapIdCameraInfoTop.contains(id))
{
rotationAngle = m_mapIdCameraInfoTop.value(id).rotationAngle;
}
else if (m_mapIdCameraInfoSide.contains(id))
{
rotationAngle = m_mapIdCameraInfoSide.value(id).rotationAngle;
}
//现在1和2巷道都是用的下三层1-3层曝光值250000ms/增益20
//中三层4-6层曝光值150000ms/增益20
//上三层7-9层曝光值50000ms/增益20
int exposure = exposureRowMap[floor];
setExposure(serialNumber, exposure);
if (!capture(serialNumber, imgInfo.image, imgInfo.image3D, location))
{
vecImageInfo.push_back(imgInfo);
continue;
}
flipImg(imgInfo.image, imgInfo.image, rotationAngle);
imgInfo.cameraSn = serialNumber;
// 2D相机操作
if (imgInfo.imageOrigin == nullptr)
{
imgInfo.imageOrigin = ILImagePtr(__uuidof(LImage));
imgInfo.imageFixed = ILImagePtr(__uuidof(LImage));
}
imgInfo.imageOrigin->SetImageData(imgInfo.image.cols, imgInfo.image.rows, (void*)imgInfo.image.data, imgInfo.image.step, 0);
//if (serialNumber == "00787720450")
//{
// imgInfo.imageOrigin->Load("C:/Users/LENOVO/Downloads/0108/310102.bmp");
//}
//else if (serialNumber == "00J49540865")
//{
// imgInfo.imageOrigin->Load("C:/Users/LENOVO/Downloads/0108/320111.bmp");
//}
//else
//{
// imgInfo.imageOrigin->SetImageData(imgInfo.image.cols, imgInfo.image.rows, (void*)imgInfo.image.data, imgInfo.image.step, 0);
//}
if (imgInfo.image3D.empty()) //表面用的是2D相机
{
imgInfo.bIs2D = true;
if (location == 1 && m_calib1->IsCalibrated())
{
m_calib1->FixImage(imgInfo.imageOrigin, imgInfo.imageFixed);
}
else if (location == 2 && m_calib2->IsCalibrated())
{
m_calib2->FixImage(imgInfo.imageOrigin, imgInfo.imageFixed);
}
}
else
{
imgInfo.bIs2D = false;
}
vecImageInfo.push_back(imgInfo);
}
emit sgCapturedImage(vecImageInfo, m_eCameraLocation);
}
void CameraControl::flipImg(const cv::Mat& imgSrc, cv::Mat& imgDst, int rotationAngle)
{
if (imgSrc.empty())
{
qWarning() << "imgSrc is empty";
return;
}
switch (rotationAngle)
{
case 90:
cv::transpose(imgSrc, imgDst);
cv::flip(imgDst, imgDst, 1);
qDebug() << " 旋转90度";
break;
case 180:
cv::flip(imgSrc, imgDst, -1);
qDebug() << " 旋转180度";
break;
case 270:
cv::transpose(imgSrc, imgDst);
cv::flip(imgDst, imgDst, 0);
qDebug() << " 旋转270度";
break;
default:
imgDst = imgSrc;
qDebug() << " 不旋转";
break;
}
}