533 lines
20 KiB
C++
533 lines
20 KiB
C++
#include "Logic_camera_thread.h"
|
||
|
||
//QMap<QString, bool> Logic_camera_thread::Map_getImageflag;
|
||
//获取时间字符串
|
||
std::string getCurrentDateTime_2() {
|
||
|
||
// 获取当前时间点
|
||
auto now = std::chrono::system_clock::now();
|
||
|
||
// 转换为字符串
|
||
auto currentTime = std::chrono::system_clock::to_time_t(now);
|
||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
|
||
std::tm* localTime = std::localtime(¤tTime);
|
||
std::stringstream ss;
|
||
ss << std::put_time(localTime, "%H-%M-%S") << "-" << std::setfill('0') << std::setw(3) << ms.count();
|
||
return ss.str();
|
||
}
|
||
void Logic_camera_thread::adddataIntegrationThread(Logic_hdataintegration* mythread)
|
||
{
|
||
mydataIntegrationThread.enqueue( mythread);
|
||
ifMissImage_mutex = new QMutex;
|
||
}
|
||
|
||
Logic_camera_thread::~Logic_camera_thread()
|
||
{
|
||
Sleep(100);
|
||
wait(100);
|
||
exit();
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " delete thread success! ";
|
||
}
|
||
//设置相机key、取图超时、模块、拍照面描述、触发方式
|
||
bool Logic_camera_thread::setModule( QString station_name,MyModule module,QJsonObject obj)
|
||
{
|
||
//相机SN或usrID
|
||
m_name = obj.value("相机key").toString();
|
||
m_type = "camera";// camera_obj.value("camera_type").toString();
|
||
getImgTimeout = obj.value("取图超时").toString().toInt();
|
||
if (m_name.isEmpty() || m_type.isEmpty())
|
||
{
|
||
qCritical() << "[Error] " << " camera_key or camera_type is null";
|
||
return false;
|
||
}
|
||
QJsonArray SurfaceArray = obj.value("拍照面描述").toArray();
|
||
for (int i = 0; i < SurfaceArray.size(); i++)
|
||
cameraProductSurface.enqueue(SurfaceArray[i].toString());
|
||
|
||
if (getImgTimeout < 10)
|
||
getImgTimeout = 1000;
|
||
//m_name = name;
|
||
// m_type = type;
|
||
m_Module = module;
|
||
m_moduleobj = obj;
|
||
m_stationName = station_name;
|
||
// getImgTimeout = ImgTimeout;
|
||
m_missImgae_add = obj.value("缺图时,补图宽高-张数-图像格式").toString();
|
||
if ( m_type == "camera" )
|
||
{
|
||
m_triggermodel = m_moduleobj.value("触发方式").toString();
|
||
if ( m_triggermodel.isEmpty() )
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " trigger_mod is null ! ";
|
||
return false;
|
||
}
|
||
}
|
||
|
||
QJsonArray read_sn_format = m_moduleobj.value("获取SN方式列表").toArray();
|
||
for (int i = 0; i < read_sn_format.size(); i++)
|
||
{
|
||
QJsonObject obj = read_sn_format.at(i).toObject();
|
||
QString read_sn_area_index = obj.value("读哪个上料通道的SN").toString();
|
||
QString trggier_signals_access = obj.value("触发信号").toString();
|
||
//触发信号检查
|
||
if (!trggier_signals_access.isEmpty())//&& !read_sn_start_data_queue.isEmpty())
|
||
{
|
||
SN_signalList.append(trggier_signals_access);
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
//设置ifMissImage;Logic_myiothread要进行设置,加锁
|
||
void Logic_camera_thread::set_ifMissImage(bool flage)
|
||
{
|
||
QMutexLocker locker(ifMissImage_mutex); // 加锁
|
||
ifMissImage = flage;
|
||
}
|
||
|
||
void Logic_camera_thread::set_m_stoprun(bool val)
|
||
{
|
||
QMutexLocker locker(ifMissImage_mutex); // 加锁
|
||
m_stoprun = val;
|
||
}
|
||
clock_t maxTime_start, maxTime_stop;
|
||
void Logic_camera_thread::run()
|
||
{
|
||
while (ifRun)
|
||
{
|
||
Sleep(2);
|
||
if (getImgNums == 0)
|
||
continue;
|
||
m_stoprun = false;
|
||
getImg_faileNums = 0;
|
||
ifsaveImage = false;
|
||
set_ifMissImage(false);
|
||
cu_runNum = 0;
|
||
int last_addImageNums = addImageNums;
|
||
maxTime_start = clock();
|
||
try
|
||
{
|
||
//QString tmpDate = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "runCameraModule::" << runCameraModuleNums++ << " cameraKey::"<< m_Module.module_key <<" getImgNums::"<< getImgNums;
|
||
if (m_type == "camera")
|
||
{
|
||
for (int i = 0; i < getImgNums; i++)
|
||
{
|
||
if (!runCameraModule())
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "runCameraModule run failed! ";
|
||
getImg_faileNums++;
|
||
//return;
|
||
}
|
||
maxTime_stop = clock();
|
||
if (maxTime_stop - maxTime_start > maxCheckTime)
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "maxTime_stop - maxTime_start > maxCheckTime! " << m_Module.module_key;
|
||
std::cout << "maxTime_stop - maxTime_start > maxCheckTime! " << m_Module.module_key.toStdString() << std::endl;
|
||
break;
|
||
}
|
||
}
|
||
|
||
//qCritical() << "camera_name::" << m_name << " addImageNums::" << addImageNums <<" thisNums::"<< addImageNums- last_addImageNums ;
|
||
//判断有无取图失败情况
|
||
if (addImageNums - last_addImageNums < getImgNums)
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " err add Img::" << m_Module.module_key << " " << addImageNums - last_addImageNums;
|
||
for (int i = 0; i < mydataIntegrationThread.size(); i++)
|
||
{
|
||
mydataIntegrationThread[i]->wait();
|
||
}
|
||
trigger_signal = "";
|
||
getImgNums = 0;
|
||
std::vector<cv::Mat> vec_mat; //无数据,拿来充函数的参数
|
||
if (send_byte.split('_').size() < 2) //为空分割size为1,不崩溃
|
||
{
|
||
//一个开始拍照对应多个相机的,回复的信号只保留一个,后面的不发了。
|
||
if (send_byte != "pass")
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "feedback_signal err: " << send_byte;
|
||
}
|
||
else
|
||
{
|
||
QMutexLocker locker(m_iomutex);
|
||
if (!finstcp_ptr->writeData(vec_mat, send_byte))
|
||
{
|
||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "feedback_signal: " << send_byte;
|
||
}
|
||
}
|
||
send_byte.clear();
|
||
//break;
|
||
}
|
||
}
|
||
catch (QString ev)
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "catch ev:" << ev;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
int Logic_camera_thread::matType(QString qstype)
|
||
{
|
||
int baseN = -1;
|
||
if (qstype.contains("CV_8U"))
|
||
baseN = 0;
|
||
else if (qstype.contains("CV_8S"))
|
||
baseN = 1;
|
||
else if (qstype.contains("CV_16U"))
|
||
baseN = 2;
|
||
else if (qstype.contains("CV_16S"))
|
||
baseN = 3;
|
||
else if (qstype.contains("CV_32S"))
|
||
baseN = 4;
|
||
else if (qstype.contains("CV_32F"))
|
||
baseN = 5;
|
||
else if (qstype.contains("CV_64F"))
|
||
baseN = 6;
|
||
else if (qstype.contains("CV_16F"))
|
||
baseN = 7;
|
||
int lastN = 0;
|
||
if (qstype.contains("C1"))
|
||
lastN = 1;
|
||
else if (qstype.contains("C2"))
|
||
lastN = 2;
|
||
else if (qstype.contains("C3"))
|
||
lastN = 3;
|
||
else if (qstype.contains("C4"))
|
||
lastN = 4;
|
||
|
||
if (baseN == -1 || lastN == 0)
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "type err:" << m_missImgae_add;
|
||
return (lastN - 1) * 8 + baseN;
|
||
}
|
||
|
||
//缺图补图
|
||
void Logic_camera_thread::missImgae_addImage(std::vector<cv::Mat>& camera_mat)
|
||
{
|
||
set_ifMissImage(true);
|
||
//"100*100*2*CV_8SC1#CV_8SC3",
|
||
QStringList missList = m_missImgae_add.split("*");
|
||
if (missList.size() < 4)
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "data err:" << m_missImgae_add;
|
||
return;
|
||
}
|
||
if(missList[3].split("#").size()< missList[2].toInt())
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "data3 err:" << m_missImgae_add;
|
||
return;
|
||
}
|
||
for (int i = 0; i < missList[2].toInt(); i++)
|
||
{
|
||
cv::Mat tmpType;
|
||
int type = matType(missList[3].split("#")[i]);
|
||
if (type < 0)
|
||
return;
|
||
tmpType = cv::Mat::zeros(cv::Size(missList[0].toInt(), missList[1].toInt()), type);
|
||
camera_mat.push_back(tmpType);
|
||
}
|
||
}
|
||
|
||
|
||
bool Logic_camera_thread::runCameraModule()
|
||
{
|
||
clock_t start, stop;
|
||
start = clock();
|
||
// 判断触发模式
|
||
if ( m_triggermodel.contains("software") )
|
||
{
|
||
QByteArray task_name;
|
||
std::vector<cv::Mat> camera_mat;
|
||
if ( m_Module.module_ptr->run() ){
|
||
if ( !m_Module.module_ptr->readData(camera_mat,task_name) )
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " camera_mat is error! ";
|
||
missImgae_addImage(camera_mat);
|
||
}
|
||
}else{
|
||
qCritical() << __FUNCTION__ << " line:"<< __LINE__ << " m_name:" << m_name << " get image is error failed!";
|
||
missImgae_addImage(camera_mat);
|
||
}
|
||
//stop = clock();
|
||
//qDebug() << "m_Module.module_key::" << m_Module.module_key << " runCameraModule get image Time ::" << stop - start;
|
||
if ( camera_mat.empty() )
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " camera_mat is null! ";
|
||
missImgae_addImage(camera_mat);
|
||
}
|
||
//int de = camera_mat[0].rows * camera_mat[0].cols * camera_mat[0].channels() * camera_mat[0].depth() / 8;
|
||
//图像检查
|
||
for (int i = 0; i < camera_mat.size(); i++)
|
||
if ((camera_mat[i].dataend - camera_mat[i].datastart) < camera_mat[i].rows * camera_mat[i].cols * camera_mat[i].channels()) //尝试能否解决mtx内容异常问题
|
||
{
|
||
camera_mat[i] = cv::Mat::zeros(camera_mat[i].rows, camera_mat[i].cols, camera_mat[i].type());
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " camera_mat[i] data err! zeros";
|
||
}
|
||
//保存图片到容器,并运行对应的条件判断
|
||
saveImage(camera_mat); //最大耗时30-40ms;
|
||
|
||
// 界面传输图片来显示
|
||
if (ifshowSoureImg == true) //task_thread_num < 1 没有检测任务时,显示原图
|
||
if ((camera_mat.at(0).cols > 0) && (camera_mat.at(0).rows > 0) )
|
||
{
|
||
sendDataCommond(m_type, camera_mat.at(0), "");
|
||
}
|
||
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " m_name: " << m_name << " software get mat is success! camera_mat len:" << camera_mat.size();
|
||
camera_mat.clear();
|
||
return true;
|
||
}
|
||
else if ( m_triggermodel.contains("hardware") ) // 硬触发 hardware_trigger
|
||
{
|
||
myTime = 0;
|
||
while (true)
|
||
{
|
||
if (CommunicationProcessLevel == 2)
|
||
{
|
||
maxTime_stop = clock();
|
||
if (maxTime_stop - maxTime_start > maxCheckTime)
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "maxCheckTime! hardware" << m_Module.module_key;
|
||
std::cout << " maxCheckTime! " << m_Module.module_key.toStdString() << std::endl;
|
||
return true;
|
||
}
|
||
}
|
||
if (!ifRun || m_stoprun == true)
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " !ifRun || m_stoprun == true"<< m_Module.module_key;
|
||
return true;
|
||
}
|
||
|
||
QMutexLocker locker(ifMissImage_mutex); // 加锁
|
||
QByteArray task_name;
|
||
std::vector<cv::Mat> camera_mat;
|
||
if (m_Module.module_ptr->run())
|
||
{
|
||
if (!m_Module.module_ptr->readData(camera_mat, task_name))
|
||
{
|
||
Sleep(10);
|
||
qApp->processEvents();
|
||
myTime += 10;
|
||
if (myTime*10 > getImgTimeout)
|
||
{
|
||
if (CommunicationProcessLevel == 2)
|
||
{
|
||
missImgae_addImage(camera_mat);
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " get image is getImgTimeout failed!";
|
||
}
|
||
}
|
||
else continue;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (CommunicationProcessLevel == 2)
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " get image is error failed!";
|
||
missImgae_addImage(camera_mat);
|
||
}
|
||
}
|
||
if (camera_mat.empty())
|
||
{
|
||
Sleep(2);
|
||
continue;
|
||
}
|
||
//图像检查
|
||
for (int i = 0; i < camera_mat.size(); i++)
|
||
if ((camera_mat[i].dataend - camera_mat[i].datastart) < camera_mat[i].rows * camera_mat[i].cols * camera_mat[i].channels()) //尝试能否解决mtx内容异常问题;camera_mat[i].depth()不是8的倍数
|
||
{
|
||
camera_mat[i] = cv::Mat::zeros(camera_mat[i].rows, camera_mat[i].cols, camera_mat[i].type());
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " camera_mat[i] data err! zeros";
|
||
}
|
||
|
||
//保存图片到容器,并运行对应的条件判断
|
||
saveImage(camera_mat);
|
||
if (ifshowSoureImg == true) //task_thread_num < 1 没有检测任务时,显示原图
|
||
if ((camera_mat.at(0).cols > 0) && (camera_mat.at(0).rows > 0))
|
||
{
|
||
sendDataCommond(m_type, camera_mat.at(0), "");
|
||
}
|
||
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " m_name: " << m_name << " hardware get mat is success! get_mat len:" << camera_mat.size();
|
||
camera_mat.clear();
|
||
m_stoprun = false;
|
||
if (CommunicationProcessLevel == 2)//标准通信流程
|
||
break;//注意,硬触发有开始信号的,取图完返回;
|
||
else if(m_Module.moduleName.contains("readImage"))
|
||
Sleep(1000);
|
||
else
|
||
Sleep(2);
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
//保存图片到容器,并运行对应的条件判断
|
||
bool Logic_camera_thread::saveImage(std::vector<cv::Mat> camera_mat)
|
||
{
|
||
|
||
////// 保存图片文件夹
|
||
QString Qpath = m_saveImage;
|
||
|
||
clock_t start, stop;
|
||
start = clock();
|
||
HCameraData *cameraPtr = station_list.value(m_stationName)->getCameraData(m_name);
|
||
if ( cameraPtr )
|
||
{
|
||
// 获取当前相机容器的下标
|
||
int camera_index = cameraPtr->getCameraIndex();//addImageData函数camera_index加一
|
||
// 根据相机下标获取sn码容器中的sn码
|
||
QVector<QString> vector_sn = getSnData(camera_index);
|
||
QString channel_index = nullptr;
|
||
|
||
//还缺时间加白夜班和SN码
|
||
|
||
std::string Path;
|
||
Path = Qpath.toLocal8Bit();
|
||
std::string SPath = std::string(Path);
|
||
|
||
cv::imwrite(SPath + "\\" + "0.bmp", camera_mat[0]);
|
||
|
||
//拍照面描述
|
||
QString Surface;
|
||
if(cameraProductSurface.size()>0)
|
||
Surface = cameraProductSurface[camera_index% cameraProductSurface.size()];
|
||
//camera_index,0,1,2;cameraProductSurface,tp1,tp2;对应,tp1,tp2,tp1;
|
||
//qDebug() << "m_Module.module_key::" << m_Module.module_key << " saveImage getCameraData Time ::" << stop - start;
|
||
//添加到容器SnCameraData
|
||
cameraPtr->addImageData(channel_index,vector_sn,camera_mat,Surface);
|
||
|
||
for (int i = 0; i < mydataIntegrationThread.size(); i++)
|
||
{
|
||
mydataIntegrationThread[i]->run();//一个mydataIntegrationThread对应多个相机
|
||
}
|
||
stop = clock();
|
||
//if((stop - start)>20)
|
||
// qDebug() << "m_Module.module_key::" << m_Module.module_key << " saveImage mydataIntegrationThread Time ::" << stop - start;
|
||
start = clock();
|
||
addImageNums++;
|
||
//std::cout <<"camera_name::" << m_name.toStdString() << " addImageNums::" << addImageNums++ << std::endl;
|
||
|
||
}else{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " cameraPtr is null saveImage failed!";
|
||
return false;
|
||
}
|
||
ifsaveImage = true;
|
||
camera_mat.clear();
|
||
return true;
|
||
}
|
||
//index为图片序号
|
||
QVector<QString> Logic_camera_thread::getSnData(int index)
|
||
{
|
||
HSnData* m_sndata = nullptr;
|
||
QString m_sn_key = nullptr; // 获取下标对应的sn key
|
||
//QString read_sn_num = nullptr; // 读取sn的方式
|
||
QString my_read_sn_area_index = nullptr; // 属于哪个区域的sn
|
||
QString delete_sn = nullptr; // 是否删除sn 931 -3 使用
|
||
//m_moduleobj为当前相机的配置文件
|
||
QJsonArray read_sn_format = m_moduleobj.value("获取SN方式列表").toArray();
|
||
for ( int i = 0; i < read_sn_format.size(); i++ )
|
||
{
|
||
QJsonObject obj = read_sn_format.at(i).toObject();
|
||
QString read_sn_area_index = obj.value("读哪个上料通道的SN").toString();
|
||
QString trggier_signals_access = obj.value("触发信号").toString();
|
||
//触发信号检查
|
||
if (!trggier_signals_access.isEmpty())//&& !read_sn_start_data_queue.isEmpty())
|
||
{
|
||
if (trggier_signals_access != SN_signal)
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
QJsonArray sn_data_array = obj.value("SN数据列表").toArray();
|
||
for (int vvv = 0; vvv < sn_data_array.size(); vvv++)
|
||
{
|
||
QJsonObject sn_obj = sn_data_array.at(vvv).toObject();
|
||
QString sn_key = sn_obj.value("哪个SN").toString(); // 下标对应的 sn key
|
||
QJsonArray sn_vaule_array = sn_obj.value("第几张图").toArray();
|
||
for (int ggg = 0; ggg < sn_vaule_array.size(); ggg++)
|
||
{
|
||
QString value = sn_vaule_array.at(ggg).toString();
|
||
if (!value.isEmpty())
|
||
{
|
||
if (value.toInt() == index) //相机第几张图,对应sn_data的value值,
|
||
{
|
||
my_read_sn_area_index = read_sn_area_index;
|
||
m_sn_key = sn_key;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!my_read_sn_area_index.isEmpty()){
|
||
m_sndata = station_list.value(m_stationName)->getSnInfoData(my_read_sn_area_index.toInt()); // 获取相应区域SN
|
||
}else{
|
||
m_sndata = station_list.value(m_stationName)->getSnInfoData(0); // 默认只有一个区域
|
||
}
|
||
QVector<QString> vector_sn;
|
||
if ( m_sndata )
|
||
{
|
||
if (!m_sn_key.isEmpty())
|
||
{
|
||
int sn_index = 0;
|
||
QString snsnsn = m_sn_key.split("sn")[1]; //5-2:sn1,sn2
|
||
if (!snsnsn.isEmpty())
|
||
{
|
||
sn_index = m_sn_key.split("sn")[1].toInt();
|
||
}
|
||
QVector<QString> mVec_sn = m_sndata->getFirstValue();
|
||
if (sn_index - 1 < mVec_sn.size() && sn_index > 0)
|
||
{
|
||
vector_sn.push_back(mVec_sn.at(sn_index - 1));
|
||
}
|
||
}
|
||
}
|
||
return vector_sn;
|
||
}
|
||
|
||
void Logic_camera_thread::setMutex(QMutex *mutex)
|
||
{
|
||
if (m_mutex == nullptr)
|
||
m_mutex = new QMutex;// mutex;
|
||
}
|
||
|
||
bool Logic_camera_thread::sendDataCommond( QString m_type,cv::Mat mat,QByteArray byte )
|
||
{
|
||
QMutexLocker locker(m_mutex);
|
||
dataPack m_pack;
|
||
m_pack.mat = mat;
|
||
m_pack.byte = byte;
|
||
m_pack.retFlag = m_type;
|
||
m_pack.cameraName = m_name;
|
||
|
||
if (ifshowSoureImg == true) //task_thread_num < 1 没有检测任务时,显示原图
|
||
{
|
||
// 界面显示包
|
||
camera_ImageDataPack.enqueue(m_pack);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void Logic_camera_thread::degressSnIndex()
|
||
{
|
||
QMutexLocker locker(m_mutex);
|
||
if (m_sn_index == 0)
|
||
return;
|
||
m_sn_index--;
|
||
}
|
||
|
||
//获取一个数据包,并删除列表的头一个
|
||
dataPack Logic_camera_thread::getdataPack()
|
||
{
|
||
QMutexLocker locker(m_mutex); // 加锁
|
||
dataPack m_pack = camera_ImageDataPack.dequeue();
|
||
return m_pack;
|
||
}
|
||
|
||
int Logic_camera_thread::dataPack_size()
|
||
{
|
||
QMutexLocker locker(m_mutex); // 加锁
|
||
return camera_ImageDataPack.size();
|
||
} |