排障增加全部触发以及全部清零按钮。

修改三协头文件传参类型。
优化存图打印日志数量。
This commit is contained in:
2025-10-14 01:27:20 +08:00
parent 2a6cdba36d
commit 1b7451ba07
14 changed files with 896 additions and 155 deletions
+5 -5
View File
@@ -25,7 +25,7 @@
struct sx_581_address {
int triggerAddr = -1;
int triggerValue = -1;
int snAddr = -1;
int snAddr;
QByteArray completeAddr = "-1";
QByteArray resultAddr = "-1";
int valueOffsetAddr = -1;
@@ -83,7 +83,7 @@ template <typename paramTemplte>
//例触发地址有4个,输入信号为 1 0 0 1 则按顺序触发1和4的地址拍照检测,2和3不做处理
class _581_SX_Single_triggerTemplate {
public:
paramTemplte _detParams;
paramTemplte* _detParams;
detCallbackChain<paramTemplte, sx_581_address>* generalDet;
std::string cameraName;
QString viewerName;
@@ -102,7 +102,7 @@ public:
/// <param name="_processAlgoCallback">算法函数</param>
/// <param name="resultHandlerIn"></param>
void init(std::string cameraNameIn, QString viewerNameIN, std::vector<sx_581_address> addressIN, int oneTriggerCaptrueTimes,
paramTemplte& detParamsIn, ServiceManager* _serviceManagerIn, qtFuncBridge* bridgeIn,
paramTemplte* detParamsIn, ServiceManager* _serviceManagerIn, qtFuncBridge* bridgeIn,
typename detCallbackChain<paramTemplte, sx_581_address>::processAlgoCallback _processAlgoCallback,
QString saveObjectNameIN = "") {
viewerName = viewerNameIN;
@@ -112,12 +112,12 @@ public:
bridge = bridgeIn;
address = addressIN;
saveObjectName = saveObjectNameIN;
generalDet = new detCallbackChain<paramTemplte, sx_581_address>(_serviceManager, &_detParams, bridge);
generalDet = new detCallbackChain<paramTemplte, sx_581_address>(_serviceManager, _detParams, bridge);
generalDet->registerProcessAlgoCallback(_processAlgoCallback);
//单次触发器条件
for (int i = 0; i < addressIN.size(); i++) {
//注册单触发器 触发地址置1时触发
_serviceManager->_triggerManager->registerCallback(address[i].triggerAddr, 1, [this, i](int triggerPos, int triggerValue, QByteArray& byteArray) {
_serviceManager->_triggerManager->registerCallback(address[i].triggerAddr, address[i].triggerValue, [this, i](int triggerPos, int triggerValue, QByteArray& byteArray) {
evaluate(i, byteArray);}, "");
}
+119 -81
View File
@@ -5,109 +5,99 @@
#include <backStruct.h>
#include <detData.h>
enum imgSaveThreadType
{
enum imgSaveThreadType {
oriImg,
resImg,
segImg,
clsImg,
tiffOriImg
};
class imgSaveThread : public QThread
{
struct saveJob {
saveJob(std::string jobNameIn) :jobName(jobNameIn) {}
std::string jobName;
QQueue<std::pair<std::string, cv::Mat>> imgQueue;
};
class imgSaveThread : public QThread {
public:
enum type{
enum type {
normal,
priority
};
QMutex mutex;
std::vector<int> compressionParams{ cv::IMWRITE_PNG_COMPRESSION ,9};
QQueue<std::pair<std::string, cv::Mat>>priorityQueue;
QQueue<std::pair<std::string, cv::Mat>>imgQueue;
void run()
{
while (true)
{
QQueue<std::pair<std::string, cv::Mat>> localQueue;
std::vector<int> compressionParams{ cv::IMWRITE_PNG_COMPRESSION ,9 };
QQueue< std::shared_ptr<saveJob>>priorityQueue;
QQueue< std::shared_ptr<saveJob>>defaultQueue;
int imgRemainCount = 0;
void run() {
while (true) {
QQueue<std::pair<std::string, cv::Mat>> localQueue;
std::shared_ptr<saveJob> job = nullptr;
// 优先处理 priorityQueue
{
QMutexLocker locker(&mutex);
if (!priorityQueue.isEmpty()) {
localQueue.swap(priorityQueue);
job = priorityQueue.dequeue();
}
else if (!imgQueue.isEmpty()) {
localQueue.swap(imgQueue);
else if (!defaultQueue.isEmpty()) {
job = defaultQueue.dequeue();
}
}
// 没有任务就跳出
if (localQueue.isEmpty()) {
if (job == nullptr) {
break;
}
qDebug() << "saveJob start" << QString::fromStdString(job->jobName) << "remain" << imgRemainCount;
localQueue.swap(job->imgQueue);
imgRemainCount -= job->imgQueue.size();
// 批量保存
while (!localQueue.isEmpty()) {
auto data = std::move(localQueue.dequeue());
qDebug() << "saving img " << QString::fromStdString(data.first);
#if saveImgEnable
cv::imwrite(data.first, data.second);
#endif
}
qDebug() << "saveJob end " << QString::fromStdString(job->jobName);
}
}
void addData(std::string str, cv::Mat& mat,type type_ = normal)
{
try
{
if (mat.data == nullptr || &mat == nullptr)
{
qDebug() << "在存图线程中发现无效图像";
return;
}
}
catch(...)
{
qDebug() << "在存图线程中发现无效图像";
return;
}
mutex.lock();
cv::Mat img;
mat.copyTo(img);
void addJob(std::shared_ptr<saveJob> job, type type_ = normal) {
QMutexLocker locker(&mutex);
switch (type_) {
case normal:
imgQueue.append(std::make_pair(str, img));
defaultQueue.append(job);
break;
case priority:
priorityQueue.append(std::make_pair(str, img));
priorityQueue.append(job);
break;
}
qDebug() << "img enqueue" << QString::fromStdString(str)<<"current size"<< priorityQueue.size()<<","<< imgQueue.size();
mutex.unlock();
imgRemainCount += job->imgQueue.size();
qDebug() << "savejob enqueue" << QString::fromStdString(job->jobName) << "queue size" << priorityQueue.size() << "|" << defaultQueue.size() << " imgRemain" << imgRemainCount;
this->start();
}
int queueSize()
{
mutex.lock();
int size = imgQueue.size();
mutex.unlock();
int queueSize() {
QMutexLocker locker(&mutex);
int size = defaultQueue.size();
return size;
}
};
class imgSaveThreadManager
{
class imgSaveThreadManager {
public:
imgSaveThreadManager(std::string pathIn) {
path = QString::fromStdString(pathIn);
}
~imgSaveThreadManager() {};
void setPath(QString pathIn){
void setPath(QString pathIn) {
path = pathIn;
}
imgSaveThread saveThread;
QString genDirName(std::shared_ptr<detData> data, imgSaveThreadType type, saveMode mode){
QString genDirName(std::shared_ptr<detData> data, imgSaveThreadType type, saveMode mode) {
// 一级目录(根路径)
const QString basePath = path;
@@ -137,18 +127,18 @@ public:
// 拼接路径
QDir dir(basePath);
dir = QDir(dir.filePath(imgTypeDir));
if (data->saveObjectName != "")
if (data->saveObjectName != "")
dir = QDir(dir.filePath(data->saveObjectName));
dir = QDir(dir.filePath(dateDir));
dir = QDir(dir.filePath(hourDir));
dir = QDir(dir.filePath(resultDir));
if (mode != oneFile)
if (mode != oneFile)
dir = QDir(dir.filePath(detailName));
return dir.path() + "/";
}
std::vector<std::string> genFileNames(std::shared_ptr <detData> data, imgSaveThreadType type, std::string format = "")
{
std::vector<std::string> genFileNames(std::shared_ptr <detData> data, imgSaveThreadType type, std::string format = "") {
std::vector<std::string> resultFileNames;
std::string fileName;
if (data->SNcode.length() != 0 && data->SNcode.length() < 50)
@@ -162,7 +152,7 @@ public:
case oriImg:
for (int i = 0; i < data->oriImgs.size(); i++)
{
if (i < data->oriFormat.size() )
if (i < data->oriFormat.size())
resultFileNames.push_back(fileName + getCurrentDateTime() + "_Count" + std::to_string(i) + "." + data->oriFormat[i]);
else
resultFileNames.push_back(fileName + getCurrentDateTime() + "_Count" + std::to_string(i) + ".bmp");
@@ -183,36 +173,84 @@ public:
}
return resultFileNames;
}
void packageData(QQueue<std::pair<std::string, cv::Mat>>& jobQueue, std::vector<std::string> fileNames, std::vector<cv::Mat>& mats) {
if (fileNames.size() != mats.size())
qWarning() << "检测到存图文件名数量与图片数量不符";
void saveOri(std::shared_ptr <detData> data) {
QString fileSavePath = genDirName(data, oriImg, data->_saveMode);//获取文件夹名
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
std::vector<std::string>fileNames = genFileNames(data, oriImg);
for (int index = 0; index < fileNames.size() && index < mats.size(); index++) {
try {
for (int index = 0; index < fileNames.size(); index++)
saveThread.addData(fileSavePath.toLocal8Bit().toStdString() + fileNames[index], data->oriImgs[index]);
int queueSize = saveThread.queueSize();
if (queueSize > 10)
qDebug() << "queueSize " << queueSize;
if (mats[index].data == nullptr || &mats[index] == nullptr) {
qDebug() << "在存图线程中发现无效图像";
continue;
}
}
catch (...) {
qDebug() << "在存图线程中发现无效图像";
continue;
}
cv::Mat img;
mats[index].copyTo(img);
jobQueue.enqueue(std::make_pair(fileNames[index], img));
}
}
void saveRes(std::shared_ptr <detData> data){
QString fileSavePath = genDirName(data, resImg,data->_saveMode);//获取文件夹名
void packageData(QQueue<std::pair<std::string, cv::Mat>>& jobQueue, std::vector<std::string> fileNames, std::vector<std::pair<std::string, cv::Mat>>& mats) {
if (fileNames.size() != mats.size())
qWarning() << "检测到存图文件名数量与图片数量不符";
for (int index = 0; index < fileNames.size() && index < mats.size(); index++) {
try {
if (mats[index].second.data == nullptr || &mats[index].second == nullptr) {
qDebug() << "在存图线程中发现无效图像";
continue;
}
}
catch (...) {
qDebug() << "在存图线程中发现无效图像";
continue;
}
cv::Mat img;
mats[index].second.copyTo(img);
jobQueue.enqueue(std::make_pair(fileNames[index], img));
}
}
void saveOri(std::shared_ptr <detData> data) {
if (data->oriImgs.size() != 0) {
QString fileSavePath = genDirName(data, oriImg, data->_saveMode);//获取文件夹名
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
std::vector<std::string>fileNames = genFileNames(data, oriImg);//按规则为文件创建命名
std::shared_ptr<saveJob> job (new saveJob("[ORI_JOB]+ data->SNcode"));
packageData(job->imgQueue, fileNames, data->oriImgs);//打包数据
saveThread.addJob(job);
}
}
void saveRes(std::shared_ptr <detData> data) {
QString fileSavePath = genDirName(data, resImg, data->_saveMode);//获取文件夹名
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
std::shared_ptr<saveJob> job(new saveJob("[RES_JOB]"+ data->SNcode));
//结果图保存
std::vector<std::string>resFileNames = genFileNames(data, resImg);
for (int index = 0; index < resFileNames.size(); index++)
saveThread.addData(fileSavePath.toLocal8Bit().toStdString() + resFileNames[index], data->resultImgs[index], imgSaveThread::priority);
//seg
std::vector<std::string>segFileNames = genFileNames(data, segImg);
for (int index = 0; index < segFileNames.size(); index++)
saveThread.addData(fileSavePath.toLocal8Bit().toStdString() + segFileNames[index], data->segOriginImgs[index]);
//cls
std::vector<std::string>clsFileNames = genFileNames(data, clsImg);
for (int index = 0; index < clsFileNames.size(); index++)
saveThread.addData(fileSavePath.toLocal8Bit().toStdString() + clsFileNames[index], data->clsOriginImgs[index].second);
if (data->resultImgs.size() != 0) {
std::vector<std::string>fileNames = genFileNames(data, resImg);//按规则为文件创建命名
packageData(job->imgQueue, fileNames, data->resultImgs);//打包数据
}
//SEG原图
if (data->segOriginImgs.size() != 0) {
std::vector<std::string>fileNames = genFileNames(data, segImg);//按规则为文件创建命名
packageData(job->imgQueue, fileNames, data->segOriginImgs);//打包数据
}
//CLS原图
if (data->clsOriginImgs.size() != 0) {
std::vector<std::string>fileNames = genFileNames(data, clsImg);//按规则为文件创建命名
packageData(job->imgQueue, fileNames, data->clsOriginImgs);//打包数据
}
saveThread.addJob(job, imgSaveThread::priority);
//额外储存NG文件夹
//std::string additionalSaveNgImgPath = genDirName(data, additionalSaveNgImg);
//std::vector<std::string>additionalSaveNgImgNames = genFileNames(data, additionalSaveNgImg);
@@ -237,7 +275,7 @@ public:
}
private:
QString path = "";
};
#pragma once
+1 -1
View File
@@ -79,7 +79,7 @@ bool triggerManager::connectHost(){
initFailure = trigger->initParas(QByteArray());
#endif
emit bridge->loadingWindow_appendInitLog(triggerFileName + "连接到" + IpAndPort,QColor("white"));
emit bridge->loadingWindow_appendInitLog(triggerFileName + "连接到" + IpAndPort,"white");
}
+60 -12
View File
@@ -54,22 +54,24 @@ public:
}
void initBasicPreset(mission* _missionIn) {
//初始化单触发测试按钮
for (auto& data : _serviceManager->_triggerManager->triggerCallbackFuncs) {
for (auto& callbacks : data.second) {
if (callbacks.funcName.find(avoid) != std::string::npos) {
continue;
}
QString uuid = QUuid::createUuid().toString();;
auto commands = basicTriggerPresetGenerate(callbacks.triggerAddress);
auto commands = basicTriggerPresetGenerate(callbacks.triggerAddress, callbacks.triggerValue);
QString tips;
for(auto& cmd : commands) {
tips += cmd + "\n";
}
emit bridge->runCommand_addBtn(
QString::fromStdString(callbacks.funcName),tips,uuid);
QString::fromStdString(callbacks.funcName + "_" + std::to_string(callbacks.triggerAddress) + "_" + std::to_string(callbacks.triggerValue)), tips, uuid);
presets[uuid] = commands;
}
}
//初始化联合触发测试按钮
for (auto& data : _serviceManager->_triggerManager->unionTriggerCallbackFuncs) {
for (auto& callbacks : data.second) {
if (callbacks.funcName.find(avoid) != std::string::npos) {
@@ -86,19 +88,65 @@ public:
presets[uuid] = commands;
}
}
QString uuid = QUuid::createUuid().toString();;
QStringList commands = { "reloadConfig" };
QString tips = "reloadConfig";
emit bridge->runCommand_addBtn(
QString::fromStdString("重新加载算法文件"), tips, uuid);
presets[uuid] = commands;
_mission = _missionIn;
//初始化重新加载配置文件按钮
{
QString uuid = QUuid::createUuid().toString();;
QStringList commands = { "reloadConfig" };
QString tips = "reloadConfig";
emit bridge->runCommand_addBtn(
QString::fromStdString("重新加载算法文件"), tips, uuid);
presets[uuid] = commands;
_mission = _missionIn;
}
//初始化全触发按钮
{
QStringList commands;
QString tips;
QStringList setZeroCommands;
QString setZeroTips;
for (auto& data : _serviceManager->_triggerManager->triggerCallbackFuncs) {
for (auto& callbacks : data.second) {
if (callbacks.funcName.find(avoid) != std::string::npos) {
continue;
}
commands.append("fins#write_short_D" + QString::number(callbacks.triggerAddress) + "_" + QString::number(callbacks.triggerValue));
tips += "fins#write_short_D" + QString::number(callbacks.triggerAddress) + "_" + QString::number(callbacks.triggerValue) + "\n";
setZeroCommands.append("fins#write_short_D" + QString::number(callbacks.triggerAddress) + "_0");
setZeroTips += "fins#write_short_D" + QString::number(callbacks.triggerAddress) + "_0" + "\n";
}
}
for (auto& data : _serviceManager->_triggerManager->unionTriggerCallbackFuncs) {
for (auto& unionCallbacks : data.second) {
if (unionCallbacks.funcName.find(avoid) != std::string::npos) {
continue;
}
for (auto& callbacks : unionCallbacks.triggerAddressAndValue) {
commands.append("fins#write_short_D" + QString::number(callbacks.first) + "_" + QString::number(callbacks.second));
tips += "fins#write_short_D" + QString::number(callbacks.second) + "_" + QString::number(callbacks.second) + "\n";
setZeroCommands.append("fins#write_short_D" + QString::number(callbacks.first) + "_0");
setZeroTips += "fins#write_short_D" + QString::number(callbacks.first) + "_0" + "\n";
}
}
}
QString allTriggerUuid = QUuid::createUuid().toString();
commands.append("waitMs#500");
commands.append(setZeroCommands);
presets[allTriggerUuid] = commands;
tips.append("waitMs#500\n");
tips.append(setZeroTips);
emit bridge->runCommand_addBtn("全部触发", tips, allTriggerUuid);
QString allClearUuid = QUuid::createUuid().toString();
emit bridge->runCommand_addBtn("全部清零", setZeroTips, allClearUuid);
presets[allClearUuid] = setZeroCommands;
}
}
QStringList basicTriggerPresetGenerate(int& triggerAddress) {
QStringList basicTriggerPresetGenerate(int& triggerAddress,int triggerValue) {
QString triggerAddressStr = QString::number(triggerAddress);
QString triggerValueStr = QString::number(triggerValue);
return {
"fins#write_short_D"+ triggerAddressStr +"_1",
"fins#write_short_D"+ triggerAddressStr +"_" + triggerValueStr,
"waitMs#500",
"fins#write_short_D" + triggerAddressStr + "_0",
};
@@ -292,11 +292,8 @@ bool hanHouDown(std::shared_ptr <detData> data, yuHanHanHouParams* _detParams, s
}
mission* createMission() {
return new _581_YuHan_hanqian();
return new _581_YuHan_hanhou();
}
void destroyMission(mission* _mission) {
delete _mission;
+30 -43
View File
@@ -30,7 +30,7 @@ bool hanHouDown(std::shared_ptr <detData> data, yuHanHanHouParams* _detParams, s
namespace hanhou45{
}
class _581_YuHan_hanqian : public mission {
class _581_YuHan_hanhou : public mission {
public:
_581_SX_Single_triggerTemplate< yuHanHanHouParams> lv_top90_1;
_581_SX_Single_triggerTemplate< yuHanHanHouParams> lv_down90_2;
@@ -41,39 +41,26 @@ public:
_581_SX_Single_triggerTemplate< yuHanHanHouParams> lv_down45_6;
_581_SX_Single_triggerTemplate< yuHanHanHouParams> tong_top45_7;
_581_SX_Single_triggerTemplate< yuHanHanHouParams> tong_down45_8;
std::vector < yuHanHanHouParams> tongDetParams;
std::vector < yuHanHanHouParams> lvDetParams;
std::vector < yuHanHanHouParams> tongDetParams = std::vector < yuHanHanHouParams>(4);
std::vector < yuHanHanHouParams> lvDetParams = std::vector < yuHanHanHouParams>(4);
bool initOnce = false;
void onConfigReloaded() {
HDevEngineCpp::HDevEngine myEngine;
myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl");
/*tongDetParams.segHanYinZhuaQu = _serviceManager->_handleAiModelManager->getSegModel("segTongHanYinZhuaQu_GPU1");
tongDetParams.segYuHanDingWei = _serviceManager->_handleAiModelManager->getSegModel("segTongYuHanDingWei_GPU1");
tongDetParams.segHanHou = _serviceManager->_handleAiModelManager->getSegModel("segTongHanHou_GPU1");
tongDetParams.clsHanHou = _serviceManager->_handleAiModelManager->getClsModel("clsTongHanHou_GPU1");
lvDetParams.segHanYinZhuaQu = _serviceManager->_handleAiModelManager->getSegModel("segLvHanYinZhuaQu_GPU0");
lvDetParams.segYuHanDingWei = _serviceManager->_handleAiModelManager->getSegModel("segLvYuHanDingWei_GPU0");
lvDetParams.segHanHou = _serviceManager->_handleAiModelManager->getSegModel("segLvHanHou_GPU0");
lvDetParams.clsHanHou = _serviceManager->_handleAiModelManager->getClsModel("clsLvHanHou_GPU0");*/
if (initOnce == false) {
for (int i = 0; i < 4; i++) {
yuHanHanHouParams tong;
tong.segHanYinZhuaQu = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-hanYinZhuaQu-T.BHD", 64, 0);
tong.segYuHanDingWei = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-yuHanDingWei-T.BHD", 64, 0);
tong.segHanHou = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-yuHanhanHou-T.BHD", 64, 0);
tong.clsHanHou = handdleAI::CreateClsObjV3("./handleaiModels/yuhan_hanhou/cls-yuHanhanHou-T.BHD", 0, 1);
tongDetParams.push_back(tong);
for (auto& params : tongDetParams) {
params.segHanYinZhuaQu = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-hanYinZhuaQu-T.BHD", 64, 0);
params.segYuHanDingWei = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-yuHanDingWei-T.BHD", 64, 0);
params.segHanHou = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-yuHanhanHou-T.BHD", 64, 0);
params.clsHanHou = handdleAI::CreateClsObjV3("./handleaiModels/yuhan_hanhou/cls-yuHanhanHou-T.BHD", 0, 1);
}
yuHanHanHouParams lv;
lv.segHanYinZhuaQu = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-hanYinZhuaQu-L.BHD", 64, 1);
lv.segYuHanDingWei = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-yuHanDingWei-L.BHD", 64, 1);
lv.segHanHou = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-yuHanhanHou-L.BHD", 64, 1);
lv.clsHanHou = handdleAI::CreateClsObjV3("./handleaiModels/yuhan_hanhou/cls-yuHanhanHou-L.BHD", 1, 1);
lv.isTong = false;
lvDetParams.push_back(lv);
for (auto& params : lvDetParams) {
params.segHanYinZhuaQu = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-hanYinZhuaQu-L.BHD", 64, 1);
params.segYuHanDingWei = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-yuHanDingWei-L.BHD", 64, 1);
params.segHanHou = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanhou/seg-yuHanhanHou-L.BHD", 64, 1);
params.clsHanHou = handdleAI::CreateClsObjV3("./handleaiModels/yuhan_hanhou/cls-yuHanhanHou-L.BHD", 1, 1);
}
initOnce = true;
}
@@ -81,26 +68,26 @@ public:
bool initCustom() {
#pragma region 注册触发器回调
if (_configMap["hanhou"] == "OUT") {
lv_top90_1.init("Camera1", "极耳尺寸-外-铝-相机1(顶部90°)", { { 522, 1,540,"523","530",820} }, 1, lvDetParams[0], _serviceManager, bridge, hanHouCeLiang);
lv_down90_2.init("Camera2", "极耳尺寸-外-铝-相机2(底部90°)", { { 524, 1,540,"525","532",-1} }, 1, lvDetParams[1], _serviceManager, bridge, hanHouDown);
tong_top90_3.init("Camera3", "极耳尺寸-外-铜-相机3(顶部90°)", { { 526,1,540,"527","534",800} }, 1, tongDetParams[0], _serviceManager, bridge, hanHouCeLiang);
tong_down90_4.init("Camera4", "极耳尺寸-外-铜-相机4(底部90°)", { { 528, 1,540,"529","536",-1} }, 1, tongDetParams[1], _serviceManager, bridge, hanHouDown);
lv_top90_1.init("Camera1", "极耳尺寸-外-铝-相机1(顶部90°)", { { 522, 1,540,"523","530",820} }, 1, &lvDetParams[0], _serviceManager, bridge, hanHouCeLiang);
lv_down90_2.init("Camera2", "极耳尺寸-外-铝-相机2(底部90°)", { { 524, 1,540,"525","532",-1} }, 1, &lvDetParams[1], _serviceManager, bridge, hanHouDown);
tong_top90_3.init("Camera3", "极耳尺寸-外-铜-相机3(顶部90°)", { { 526,1,540,"527","534",800} }, 1, &tongDetParams[0], _serviceManager, bridge, hanHouCeLiang);
tong_down90_4.init("Camera4", "极耳尺寸-外-铜-相机4(底部90°)", { { 528, 1,540,"529","536",-1} }, 1, &tongDetParams[1], _serviceManager, bridge, hanHouDown);
lv_top45_5.init("Camera5", "底部撕裂-外-铝-相机5(顶部45°)", { { 562,1,540,"563","570",-1} }, 1, lvDetParams[2], _serviceManager, bridge, hanHouDown);
lv_down45_6.init("Camera6", "底部撕裂-外-铝-相机6(底部45°)", { { 564, 1,540,"565","572",-1} }, 1, lvDetParams[3], _serviceManager, bridge, hanHouDown);
tong_top45_7.init("Camera7", "底部撕裂-外-铜-相机7(顶部45°)", { { 566, 1,540,"567","574",-1} }, 1, tongDetParams[2], _serviceManager, bridge, hanHouDown);
tong_down45_8.init("Camera8", "底部撕裂-外-铜-相机8(底部45°)", { { 568, 1,540,"569","576",-1} }, 1, tongDetParams[3], _serviceManager, bridge, hanHouDown);
lv_top45_5.init("Camera5", "底部撕裂-外-铝-相机5(顶部45°)", { { 562,1,540,"563","570",-1} }, 1, &lvDetParams[2], _serviceManager, bridge, hanHouDown);
lv_down45_6.init("Camera6", "底部撕裂-外-铝-相机6(底部45°)", { { 564, 1,540,"565","572",-1} }, 1, &lvDetParams[3], _serviceManager, bridge, hanHouDown);
tong_top45_7.init("Camera7", "底部撕裂-外-铜-相机7(顶部45°)", { { 566, 1,540,"567","574",-1} }, 1, &tongDetParams[2], _serviceManager, bridge, hanHouDown);
tong_down45_8.init("Camera8", "底部撕裂-外-铜-相机8(底部45°)", { { 568, 1,540,"569","576",-1} }, 1, &tongDetParams[3], _serviceManager, bridge, hanHouDown);
}
else {
lv_top90_1.init("Camera1", "极耳尺寸-内-铝-相机1(顶部90°)", { { 602, 1,580,"603","610",860} }, 1, lvDetParams[0], _serviceManager, bridge, hanHouCeLiang);
lv_down90_2.init("Camera2", "极耳尺寸-内-铝-相机2(底部90°)", { { 604, 1,580,"605","612",-1} }, 1, lvDetParams[1], _serviceManager, bridge, hanHouDown);
tong_top90_3.init("Camera3", "极耳尺寸-内-铜-相机3(顶部90°)", { { 606,1,580,"607","614",840} }, 1, tongDetParams[0], _serviceManager, bridge, hanHouCeLiang);
tong_down90_4.init("Camera4", "极耳尺寸-内-铜-相机4(底部90°)", { { 608, 1,580,"609","616",-1} }, 1, tongDetParams[1], _serviceManager, bridge, hanHouDown);
lv_top90_1.init("Camera1", "极耳尺寸-内-铝-相机1(顶部90°)", { { 602, 1,580,"603","610",860} }, 1, &lvDetParams[0], _serviceManager, bridge, hanHouCeLiang);
lv_down90_2.init("Camera2", "极耳尺寸-内-铝-相机2(底部90°)", { { 604, 1,580,"605","612",-1} }, 1, &lvDetParams[1], _serviceManager, bridge, hanHouDown);
tong_top90_3.init("Camera3", "极耳尺寸-内-铜-相机3(顶部90°)", { { 606,1,580,"607","614",840} }, 1, &tongDetParams[0], _serviceManager, bridge, hanHouCeLiang);
tong_down90_4.init("Camera4", "极耳尺寸-内-铜-相机4(底部90°)", { { 608, 1,580,"609","616",-1} }, 1, &tongDetParams[1], _serviceManager, bridge, hanHouDown);
lv_top45_5.init("Camera5", "底部撕裂-内-铝-相机5(顶部45°)", { { 642,1,580,"643","650",-1} }, 1, lvDetParams[2], _serviceManager, bridge, hanHouDown);
lv_down45_6.init("Camera6", "底部撕裂-内-铝-相机6(底部45°)", { { 644, 1,580,"645","652",-1} }, 1, lvDetParams[3], _serviceManager, bridge, hanHouDown);
tong_top45_7.init("Camera7", "底部撕裂-内-铜-相机7(顶部45°)", { { 646, 1,580,"647","654",-1} }, 1, tongDetParams[2], _serviceManager, bridge, hanHouDown);
tong_down45_8.init("Camera8", "底部撕裂-内-铜-相机8(底部45°)", { { 648, 1,580,"649","656",-1} }, 1, tongDetParams[3], _serviceManager, bridge, hanHouDown);
lv_top45_5.init("Camera5", "底部撕裂-内-铝-相机5(顶部45°)", { { 642,1,580,"643","650",-1} }, 1, &lvDetParams[2], _serviceManager, bridge, hanHouDown);
lv_down45_6.init("Camera6", "底部撕裂-内-铝-相机6(底部45°)", { { 644, 1,580,"645","652",-1} }, 1, &lvDetParams[3], _serviceManager, bridge, hanHouDown);
tong_top45_7.init("Camera7", "底部撕裂-内-铜-相机7(顶部45°)", { { 646, 1,580,"647","654",-1} }, 1, &tongDetParams[2], _serviceManager, bridge, hanHouDown);
tong_down45_8.init("Camera8", "底部撕裂-内-铜-相机8(底部45°)", { { 648, 1,580,"649","656",-1} }, 1, &tongDetParams[3], _serviceManager, bridge, hanHouDown);
}
#pragma endregion
return true;
@@ -242,15 +242,15 @@ public:
}
bool initCustom() {
#pragma region 注册触发器回调
in_lv_top_1.init("Camera1", "极耳翻折-铝-内-相机1(顶部)", { { 682, 1,760,"683","670",-1} }, 1, lvDetParams[0], _serviceManager, bridge, jiErFanZhe);
in_lv_down_2.init("Camera2", "极耳翻折-铝-内-相机2(底部)", { { 684, 1,760,"685","672",-1} }, 1, lvDetParams[1], _serviceManager, bridge, jiErFanZhe);
in_tong_top_3.init("Camera3", "极耳翻折-铜-内-相机3(顶部)", { { 686,1,760,"687","674",-1} }, 1, tongDetParams[0], _serviceManager, bridge, jiErFanZhe);
in_tong_down_4.init("Camera4", "极耳翻折-铜-内-相机4(底部)", { { 688, 1,760,"689","676",-1} }, 1, tongDetParams[1], _serviceManager, bridge, jiErFanZhe);
in_lv_top_1.init("Camera1", "极耳翻折-铝-内-相机1(顶部)", { { 682, 1,760,"683","670",-1} }, 1, &lvDetParams[0], _serviceManager, bridge, jiErFanZhe);
in_lv_down_2.init("Camera2", "极耳翻折-铝-内-相机2(底部)", { { 684, 1,760,"685","672",-1} }, 1, &lvDetParams[1], _serviceManager, bridge, jiErFanZhe);
in_tong_top_3.init("Camera3", "极耳翻折-铜-内-相机3(顶部)", { { 686,1,760,"687","674",-1} }, 1, &tongDetParams[0], _serviceManager, bridge, jiErFanZhe);
in_tong_down_4.init("Camera4", "极耳翻折-铜-内-相机4(底部)", { { 688, 1,760,"689","676",-1} }, 1, &tongDetParams[1], _serviceManager, bridge, jiErFanZhe);
out_lv_top_5.init("Camera5", "极耳翻折-铝-外-相机5(顶部)", { { 702,1,720,"703","710",-1} }, 1, lvDetParams[2], _serviceManager, bridge, jiErFanZhe);
out_lv_down_6.init("Camera6", "极耳翻折-铝-外-相机6(底部)", { { 704, 1,720,"705","712",-1} }, 1, lvDetParams[3], _serviceManager, bridge, jiErFanZhe);
out_tong_top_7.init("Camera7", "极耳翻折-铜-外-相机7(顶部)", { { 706, 1,720,"707","714",-1} }, 1, tongDetParams[2], _serviceManager, bridge, jiErFanZhe);
out_tong_down_8.init("Camera8", "极耳翻折-铜-外-相机8(底部)", { { 708, 1,720,"709","716",-1} }, 1, tongDetParams[3], _serviceManager, bridge, jiErFanZhe);
out_lv_top_5.init("Camera5", "极耳翻折-铝-外-相机5(顶部)", { { 702,1,720,"703","710",-1} }, 1, &lvDetParams[2], _serviceManager, bridge, jiErFanZhe);
out_lv_down_6.init("Camera6", "极耳翻折-铝-外-相机6(底部)", { { 704, 1,720,"705","712",-1} }, 1, &lvDetParams[3], _serviceManager, bridge, jiErFanZhe);
out_tong_top_7.init("Camera7", "极耳翻折-铜-外-相机7(顶部)", { { 706, 1,720,"707","714",-1} }, 1, &tongDetParams[2], _serviceManager, bridge, jiErFanZhe);
out_tong_down_8.init("Camera8", "极耳翻折-铜-外-相机8(底部)", { { 708, 1,720,"709","716",-1} }, 1, &tongDetParams[3], _serviceManager, bridge, jiErFanZhe);
#pragma endregion
return true;
}
@@ -0,0 +1,8 @@
#include <581_ZhongHan_hanhou.h>
mission* createMission() {
return new _581_ZhongHan_hanhou();
}
void destroyMission(mission* _mission) {
delete _mission;
}
@@ -0,0 +1,189 @@
#include <missionBase.hpp>
#include <sxGlobal.h>
#pragma region 算法
#include <simpleAlgo.h>
#include <hdevengine/HDevEngineCpp.h>
#include <opencvPaintAlgo.hpp>
using namespace HDevEngineCpp;
#pragma endregion
class zhongHanParams {
public:
handdleAI::pSegmentation* seg_hanHouDingWei = nullptr;
bool isTong = true;
};
bool zhongHan_hanHouCeLiang(std::shared_ptr <detData> data, zhongHanParams* _detParams, sx_581_address address) {
try
{
#if 0
/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓调试用↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
plcResult = "1";
QString resultTag = "OK";
cv::Mat resultImage = img2D.clone();
putTextHusky(resultImage, utf8_to_gbk("OK").c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500);
cv::resize(resultImage, resultImage, cv::Size(), 0.5, 0.5);
resMat.push_back(resultImage);
if (resMat.size() > 0)
{
addImgToSaveStruct(resMat[0], "0", getResSaveFormat(SN, resultTag));//保存结果图
}
return true;
/*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑调试用↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/
#endif
QByteArray plcResult = "2";
//img2D = cv::imread("D:\\终焊CCD存图\\焊后正面测量CCD\\2025-07-28\\原图\\21H\\errSN\\ORI0_errSN_DA1806128_0_21-34-01-10.bmp", -1);
cv::Mat sourceImg = data->oriImgs[0];
cv::Rect cutRect;
if (_detParams->isTong == true) {
cutRect = cv::Rect(2000, 0, 3000, 3648);
}
if (_detParams->isTong == true) {
cutRect = cv::Rect(400, 0, 3000, 3648);
}
cv::Mat cutImage = sourceImg(cutRect & (cv::Rect(0, 0, sourceImg.cols, sourceImg.rows)));
cv::Mat Paint;
cutImage.copyTo(Paint);
if (Paint.channels() == 1)
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
cv::Mat segProcessMat;
float resizeRate = 5.0;
cv::resize(cutImage, segProcessMat, cv::Size(), 1 / resizeRate, 1 / resizeRate);
cv::Mat segResult = _detParams->seg_hanHouDingWei->Evaluate(segProcessMat);
data->segOriginImgs.push_back(segProcessMat);
data->segOriginImgs.push_back(cutImage);
HDevEngineCpp::HDevProcedure proc("_2_Cal_Welding_Distance");
HDevEngineCpp::HDevProcedureCall procedureCall(proc);
HalconCpp::HObject in_Image = MatToHObject(cutImage);
HalconCpp::HObject in_ImageSeg = MatToHObject(segResult);
HTuple in_Resolution(0.0346699);
HTuple in_FilePath("./halconFiles/");
procedureCall.SetInputIconicParamObject("in_Image", in_Image);
procedureCall.SetInputIconicParamObject("in_ImageSeg", in_ImageSeg);
procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution);
procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath);
procedureCall.Execute();
HTuple out_BaseLineCor, out_LineCor,
out_Distance1, out_Distance2, out_Distance3, out_Distance4,
out_ColorType, out_Flag;
out_BaseLineCor = procedureCall.GetOutputCtrlParamTuple("out_BaseLineCor");
out_LineCor = procedureCall.GetOutputCtrlParamTuple("out_LineCor");
out_Distance1 = procedureCall.GetOutputCtrlParamTuple("out_Distance1");
out_Distance2 = procedureCall.GetOutputCtrlParamTuple("out_Distance2");
out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");
TextRendererZH textPainter(Paint.cols, Paint.rows, 120);
if (out_Flag.D() == 1)
{
{
int out_BaseLineCor_L = out_BaseLineCor.Length();
for (auto i = 0; i < out_BaseLineCor_L / 4; i++)
cv::line(Paint, cv::Point(out_BaseLineCor[i * 4 + 1].D(), out_BaseLineCor[i * 4].D()),
cv::Point(out_BaseLineCor[i * 4 + 3].D(), out_BaseLineCor[i * 4 + 2].D()),
cv::Scalar(0, 255, 0), 20);
int out_LineCor_L = out_LineCor.Length();
for (auto i = 0; i < out_LineCor_L / 4; i++)
cv::line(Paint, cv::Point(out_LineCor[i * 4 + 1].D(), out_LineCor[i * 4].D()),
cv::Point(out_LineCor[i * 4 + 3].D(), out_LineCor[i * 4 + 2].D()),
cv::Scalar(0, 255, 0), 20);
}
//1
{
textPainter.putText(Paint, "水平间距:" + std::to_string(out_Distance1[0].D()), cv::Point(50, 25), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "竖直间距:" + std::to_string(out_Distance1[1].D()), cv::Point(50, 25), cv::Scalar(0, 255, 0));
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + QByteArray::number(out_Distance1[1].D()));
}
//2
{
textPainter.putText(Paint, "水平间距:" + std::to_string(out_Distance2[0].D()), cv::Point(50, 450), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "竖直间距:" + std::to_string(out_Distance2[1].D()), cv::Point(50, 675), cv::Scalar(0, 255, 0));
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + QByteArray::number(out_Distance2[1].D()));
}
}
else
{
textPainter.putText(Paint, "NG", cv::Point(100, 50), cv::Scalar(0, 255, 0));
data->halconOK = false;
plcResult = "2";
}
plcResult = "1";//强制OK
data->resultImgs.push_back(Paint);
sourceImg.release();
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
return true;
}
CATCH_EXCEPTIONS
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode);
cv::Mat Paint;
data->oriImgs[0].copyTo(Paint);
if (Paint.channels() == 1)
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
TextRendererZH textPainter(Paint.cols, Paint.rows, 15);
textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0));
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
data->resultImgs.push_back(Paint);
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//结果反馈
return true;
}
class _581_ZhongHan_hanhou : public mission {
public:
_581_SX_Single_triggerTemplate< zhongHanParams> lv_top_1;
_581_SX_Single_triggerTemplate< zhongHanParams> lv_left45_2;
_581_SX_Single_triggerTemplate< zhongHanParams> lv_right45_3;
_581_SX_Single_triggerTemplate< zhongHanParams> _3D_1;
_581_SX_Single_triggerTemplate< zhongHanParams> tong_top_5;
_581_SX_Single_triggerTemplate< zhongHanParams> tong_left45_6;
_581_SX_Single_triggerTemplate< zhongHanParams> tong_right45_7;
_581_SX_Single_triggerTemplate< zhongHanParams> _3D_2;
zhongHanParams tongDetParams;
zhongHanParams lvDetParams;
bool initOnce = false;
void onConfigReloaded() {
HDevEngineCpp::HDevEngine myEngine;
myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_628_1.hdpl");
if (initOnce == false) {
//for (auto& params : tongDetParams) {
// params.segDingWei = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanqian/60_2_hanqian_dingwei_seg.BHD", 64, 0);
// params.segJiErFanZhe = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanqian/60_2_hanqian_segT.BHD", 64, 0);
// params.clsJiErFanZhe = handdleAI::CreateClsObjV3("./handleaiModels/yuhan_hanqian/60_2_hanqian_clsT.BHD", 0, 1);
//}
//for (auto& params : lvDetParams) {
// params.segDingWei = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanqian/60_2_hanqian_dingwei_seg.BHD", 64, 1);
// params.segJiErFanZhe = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanqian/60_2_hanqian_segL.BHD", 64, 1);
// params.clsJiErFanZhe = handdleAI::CreateClsObjV3("./handleaiModels/yuhan_hanqian/60_2_hanqian_clsL.BHD", 1, 1);
// params.isTong = false;
//}
tongDetParams.isTong = true;
lvDetParams.isTong = false;
initOnce = true;
}
}
bool initCustom() {
#pragma region 注册触发器回调
lv_top_1.init("Camera1", "焊印检测-内-铜-相机1(90°)", { { 5360, 1,5340,"5362","5364",-1} }, 1, &lvDetParams, _serviceManager, bridge, zhongHan_hanHouCeLiang);
lv_left45_2.init("Camera2", "翻折撕裂-内-铜-相机2(45°)", { { 5370, 1,5340,"5372","5374",-1} }, 1, &lvDetParams, _serviceManager, bridge, zhongHan_hanHouCeLiang);
lv_right45_3.init("Camera3", "翻折撕裂-内-铜-相机3(45°)", { { 5380,1,5340,"5382","5384",-1} }, 1, &tongDetParams, _serviceManager, bridge, zhongHan_hanHouCeLiang);
_3D_1.init("Camera4", "焊后检测-3D相机1" , { { 5400, 1,5340,"5402","5404",-1} }, 1, & tongDetParams, _serviceManager, bridge, zhongHan_hanHouCeLiang);
tong_top_5.init("Camera5", "焊印检测-外-铝-相机5(90°)", { { 5440, 1,5420,"5442","5444",-1} }, 1, &tongDetParams, _serviceManager, bridge, zhongHan_hanHouCeLiang);
tong_left45_6.init("Camere6", "翻折撕裂-外-铝-相机6(45°)", { { 5450,1,5420,"5452","5454",-1} }, 1, &lvDetParams, _serviceManager, bridge, zhongHan_hanHouCeLiang);
tong_right45_7.init("Camera7", "翻折撕裂-外-铝-相机7(45°)", { { 5460, 1,5420,"5462","5464",-1} }, 1, &lvDetParams, _serviceManager, bridge, zhongHan_hanHouCeLiang);
_3D_2.init("Camera8", "焊后检测-3D相机2", { { 5480, 1,5420,"5482","5484",-1} }, 1, &tongDetParams, _serviceManager, bridge, zhongHan_hanHouCeLiang);
#pragma endregion
return true;
}
};
#pragma once
@@ -0,0 +1,78 @@
# 获取获取当前目录名
get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(TIMESTAMP RUN_TIME)
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
set(DLL_NAMES "opencv" "halcon" "handdleAI")
foreach(child ${DLL_NAMES})
LIST(APPEND ENV_INCLUDE ${${child}_include})
LIST(APPEND ENV_LIB ${${child}_lib})
LIST(APPEND ENV_TARGET ${${child}_target_link})
endforeach()
message(" ENV_INCLUDE : " ${ENV_INCLUDE} )
message(" ENV_LIB : " ${ENV_LIB} )
message(" ENV_TARGET : " ${ENV_TARGET} )
include_directories(
${PROJECT_ROOT_PATH}/src/core
${PROJECT_ROOT_PATH}/src/core/handleAi
${PROJECT_ROOT_PATH}/src/core/back
${PROJECT_ROOT_PATH}/src/core/sql
${ENV_INCLUDE}
)
link_directories (
${ENV_LIB}
)
add_compile_options(/utf-8)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
FILE(GLOB HEAD_FILES "*.h" )
FILE(GLOB SRC_FILES "./*.cpp")
FILE(GLOB UI_FILES "./*.ui")
#find_package(Qt5 COMPONENTS Core REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network Sql REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network Sql REQUIRED)
add_library(${CURRENT_FOLDER} SHARED
${HEAD_FILES}
${SRC_FILES}
${UI_FILES}
${PROJECT_ROOT_PATH}/include/qtBridge.h
)
set_target_properties(${CURRENT_FOLDER} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
)
target_link_libraries(${CURRENT_FOLDER} PRIVATE
${ENV_TARGET}
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::Sql
)
# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY)
string(TIMESTAMP RUN_TIME)
message( " modelx end : " ${CURRENT_FOLDER}:${RUN_TIME})
message( " header files "${HEAD_FILES})
@@ -0,0 +1,8 @@
#include <581_ZhongHan_hanqian.h>
mission* createMission() {
return new _581_YuHan_hanqian();
}
void destroyMission(mission* _mission) {
delete _mission;
}
@@ -0,0 +1,310 @@
#include <missionBase.hpp>
#include <sxGlobal.h>
#include <simpleAlgo.h>
#include <hdevengine/HDevEngineCpp.h>
#include <Halcon.h>
#include <HalconCpp.h>
#include <qmutex.h>
#include <qqueue.h>
#include <opencvPaintAlgo.hpp>
using namespace HDevEngineCpp;
using namespace HalconCpp;
struct hanQianDingWeiSubresult {
double Out_Vale_L_1 = -1;//铝(负)极的包膜距离(mm)
double Out_Vale_L_2 = -1;//铝(负)极连接片中心的和上极耳水平边缘距离(mm)
double Out_Vale_L_3 = -1;//铝(负)极连接片中心的和下极耳水平边缘距离(mm)
double extremum_Value = -1;
cv::Point circleCenter;
double radius = 1;
std::vector<double> lines;
bool algoFailed = false;
};
class zhongHanHanQianParams {
public:
QMutex* mutex = new QMutex();
QQueue<hanQianDingWeiSubresult> resultQueue;
QQueue<HalconCpp::HObject> mats;
~zhongHanHanQianParams() {
delete mutex;
}
int waitMs = 3000;
void insertImg(HObject& input) {
QMutexLocker locker(mutex);
if (mats.size() > 0) {
qWarning() << "焊前定位有遗留的图像,已清除";
mats.clear();
}
mats.enqueue(input);//发送检测数据到主线程
}
bool waitImage(HObject& out) {
int cnt = 0;
while (mats.size() == 0 && cnt < waitMs) {
QThread::msleep(2);
cnt += 2;
}
if (mats.size() != 0) {
QMutexLocker locker(mutex);
out = mats.dequeue();
return true;
}
return false;
}
void insertResult(hanQianDingWeiSubresult input) {
QMutexLocker locker(mutex);
if (resultQueue.size() > 0) {
qWarning() << "焊前定位有遗留的结果,已清除";
resultQueue.clear();
}
resultQueue.enqueue(input);//发送检测数据到主线程
}
bool waitResult(hanQianDingWeiSubresult& out) {
int cnt = 0;
while (resultQueue.size() == 0 && cnt < waitMs) {
QThread::msleep(2);
cnt += 2;
}
if (resultQueue.size() != 0) {
QMutexLocker locker(mutex);
out = resultQueue.dequeue();
resultQueue.clear();
return true;
}
return false;
}
};
bool hanQianCeLiang_Main(std::shared_ptr <detData> data, zhongHanHanQianParams* _detParams, sx_581_address address) {
try{
QByteArray plcResult = "2";
#if 0
/*img2D = cv::imread("./testImages/CU_1.png", -1);
sourceImg = img2D.clone();*/
img2D = cv::imread("./testImages/CU.bmp", -1);
sourceImg = img2D(cutROI & cv::Rect(0, 0, img2D.cols, img2D.rows)).clone();
#endif
cv::Mat sourceImg = data->oriImgs[0];
cv::Mat Paint;
sourceImg.copyTo(Paint);
if (Paint.channels() == 1)
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
HDevEngineCpp::HDevProcedure proc("_2_Cal_ZH_LJP_Distance");
HDevProcedureCall procedureCall(proc);
//vs+halcon联调debug
/*myEngine.StartDebugServer();
procedureCall.SetWaitForDebugConnection(true);*/
HalconCpp::HObject ho_Image_T;
HalconCpp::HObject ho_Image_L;
HalconCpp::HTuple in_Resolution = 0.0337797;
HalconCpp::HTuple in_FilePath = "./halconFiles/ZH_HanYin/";
HalconCpp::HTuple in_LineType = "602";
ho_Image_T = MatToHObject(sourceImg);
//等待副线程传入图像
bool getImgResult = _detParams->waitImage(ho_Image_L);
procedureCall.SetInputIconicParamObject("in_Image1", ho_Image_T);
procedureCall.SetInputIconicParamObject("in_Image2", ho_Image_L);
procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution);
procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath);
procedureCall.SetInputCtrlParamTuple("in_LineType", in_LineType);
procedureCall.Execute();//执行halcon程序
HalconCpp::HTuple out_Distance;
HalconCpp::HTuple out_LinePoint;
HalconCpp::HTuple out_Circle;
HalconCpp::HTuple out_Flag;
HalconCpp::HTuple out_NGTails;
out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance");//获取输出控制类变量
out_LinePoint = procedureCall.GetOutputCtrlParamTuple("out_LinePoint");//获取输出控制类变量
out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");//获取输出控制类变量
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量
out_NGTails = procedureCall.GetOutputCtrlParamTuple("out_NGTails");
int flag = out_Flag.D();
TextRendererZH textPainter(Paint.cols, Paint.rows, 120);
if (flag == 1)
{
double Out_Vale_T_1 = out_Distance[0].D();//铜(正)极的包膜距离(mm)
double Out_Vale_T_2 = out_Distance[1].D();//铜(正)极连接片中心的和上极耳水平边缘距离(mm)
double Out_Vale_T_3 = out_Distance[2].D();//铜(正)极连接片中心的和下极耳水平边缘距离(mm)
double Out_Vale_L_1 = out_Distance[3].D();//铝(负)极的包膜距离(mm)
double Out_Vale_L_2 = out_Distance[4].D();//铝(负)极连接片中心的和上极耳水平边缘距离(mm)
double Out_Vale_L_3 = out_Distance[5].D();//铝(负)极连接片中心的和下极耳水平边缘距离(mm)
double extremum_Value = out_Distance[6].D();
//发送到另一算法线程
hanQianDingWeiSubresult _calResult;
_calResult.Out_Vale_L_1 = Out_Vale_L_1;
_calResult.Out_Vale_L_2 = Out_Vale_L_2;
_calResult.Out_Vale_L_3 = Out_Vale_L_3;
_calResult.extremum_Value = extremum_Value;
if (out_Circle.Length() > 4) {
_calResult.circleCenter = cv::Point(out_Circle[4].D(), out_Circle[3].D());
_calResult.radius = out_Circle[5].D();
}
if (out_LinePoint.Length() > 38) {
for (int i = 20; i < 40; i++) {
_calResult.lines.push_back(out_LinePoint[i].D());
}
}
_detParams->insertResult(_calResult);
textPainter.putText(Paint, "铜(正)极的包膜距离:" + std::to_string(Out_Vale_T_1), cv::Point(50, 50), cv::Scalar(0, 255, 0));
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(Out_Vale_T_1));//数据1
textPainter.putText(Paint, "铜(正)极连接片中心的和上极耳水平边缘距离:" + std::to_string(Out_Vale_T_2), cv::Point(50, 200), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "铜(正)极连接片中心的和下极耳水平边缘距离:" + std::to_string(Out_Vale_T_3), cv::Point(50, 350), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "铜(正)极和铝(负)极的中心距离:" + std::to_string(extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0));
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(extremum_Value));//数据2
for (int i = 0; i < 5; i++){
cv::line(Paint, cv::Point(out_LinePoint[i * 4 + 1].D(), out_LinePoint[i * 4].D()),
cv::Point(out_LinePoint[i * 4 + 3].D(), out_LinePoint[i * 4 + 2].D()),
cv::Scalar(0, 255, 0), 10, cv::LINE_4);
}
if (out_Circle.Length() > 2){
cv::drawMarker(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), cv::Scalar(0, 255, 0), cv::MARKER_CROSS, 200, 5);
cv::circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 5);
}
}
else{
std::string errTails = out_NGTails.S().Text();
hanQianDingWeiSubresult _calResult;
_calResult.algoFailed = true;
_detParams->insertResult(_calResult);
textPainter.putText(Paint, "NG" + errTails, cv::Point(0, 50), cv::Scalar(0, 255, 0));
data->halconOK = false;
}
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
plcResult = "1";//强制OK
data->resultImgs.push_back(Paint);
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
return true;
}
CATCH_EXCEPTIONS
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode);
cv::Mat Paint;
data->oriImgs[0].copyTo(Paint);
if (Paint.channels() == 1)
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
TextRendererZH textPainter(Paint.cols, Paint.rows, 15);
textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0));
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
data->resultImgs.push_back(Paint);
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
return true;
}
bool hanQianCeLiang_Sub(std::shared_ptr <detData> data, zhongHanHanQianParams* _detParams, sx_581_address address) {
try {
//测试算法用
QByteArray plcResult = "2";
{
#if 0
//img2D = cv::imread("./testImages/AL_1.png", -1);
//sourceImg = img2D.clone();
img2D = cv::imread("./testImages/AL.bmp", -1);
sourceImg = img2D(cutROI & cv::Rect(0, 0, img2D.cols, img2D.rows)).clone();
#endif
}
cv::Mat sourceImg = data->oriImgs[0];
cv::Mat Paint;
sourceImg.copyTo(Paint);
if (Paint.channels() == 1)
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
HObject image = MatToHObject(sourceImg);
//发送图片
_detParams->insertImg(image);
TextRendererZH textPainter(Paint.cols, Paint.rows, 120);
//等待结果
hanQianDingWeiSubresult _calResult;
bool waitResultResult = _detParams->waitResult(_calResult);
if (waitResultResult == false) {
data->halconOK = false;
textPainter.putText(Paint, "NG:TimeOut", cv::Point(0, 50), cv::Scalar(0, 255, 0));
plcResult = "2";
data->resultImgs.push_back(Paint);
return false;
}
if (_calResult.algoFailed == false) {
textPainter.putText(Paint, "铝(负)极的包膜距离:" + std::to_string(_calResult.Out_Vale_L_1), cv::Point(50, 50), cv::Scalar(0, 255, 0));
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(_calResult.Out_Vale_L_1));//数据1
textPainter.putText(Paint, "铝(负)极连接片中心的和上极耳水平边缘距离:" + std::to_string(_calResult.Out_Vale_L_2), cv::Point(50, 200), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "铝(负)极连接片中心的和下极耳水平边缘距离:" + std::to_string(_calResult.Out_Vale_L_3), cv::Point(50, 350), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "铜(正)极和铝(负)极的中心距离:" + std::to_string(_calResult.extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0));
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(_calResult.extremum_Value));//数据2
for (int i = 0; i < 5; i++) {
cv::line(Paint, cv::Point(_calResult.lines[i * 4 + 1], _calResult.lines[i * 4]),
cv::Point(_calResult.lines[i * 4 + 3], _calResult.lines[i * 4 + 2]),
cv::Scalar(0, 255, 0), 10, cv::LINE_4);
}
cv::drawMarker(Paint, cv::Point(_calResult.circleCenter.x, _calResult.circleCenter.y), cv::Scalar(0, 255, 0), cv::MARKER_CROSS, 200, 5);
cv::circle(Paint, cv::Point(_calResult.circleCenter.x, _calResult.circleCenter.y), _calResult.radius, cv::Scalar(0, 255, 0), 5);
}
else {
data->halconOK = false;
textPainter.putText(Paint, "NG:algoError", cv::Point(0, 50), cv::Scalar(0, 255, 0));
plcResult = "2";
}
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
plcResult = "1";//强制OK
data->resultImgs.push_back(Paint);
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
return true;
}
CATCH_EXCEPTIONS
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode);
cv::Mat Paint;
data->oriImgs[0].copyTo(Paint);
if (Paint.channels() == 1)
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
TextRendererZH textPainter(Paint.cols, Paint.rows, 15);
textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0));
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
data->resultImgs.push_back(Paint);
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
return true;
}
class _581_YuHan_hanqian : public mission {
public:
_581_SX_Single_triggerTemplate<zhongHanHanQianParams> tong_1;
_581_SX_Single_triggerTemplate<zhongHanHanQianParams> lv_1;
zhongHanHanQianParams detParams;
bool initOnce = false;
void onConfigReloaded() {
HDevEngineCpp::HDevEngine myEngine;
myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl");
if (initOnce == false) {
initOnce = true;
}
}
bool initCustom() {
#pragma region 注册触发器回调
tong_1.init("Camera1", "焊前定位-相机1", { { 5060, 1,{5070},"5062","5064",5066} }, 1, &detParams, _serviceManager, bridge, hanQianCeLiang_Main);
lv_1.init("Camera1", "焊前定位-相机2", { { 5090, 1,{5100},"5092","5094",5096} }, 1, &detParams, _serviceManager, bridge, hanQianCeLiang_Sub);
#pragma endregion
return true;
}
};
#pragma once
@@ -0,0 +1,78 @@
# 获取获取当前目录名
get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(TIMESTAMP RUN_TIME)
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
set(DLL_NAMES "opencv" "halcon" "handdleAI")
foreach(child ${DLL_NAMES})
LIST(APPEND ENV_INCLUDE ${${child}_include})
LIST(APPEND ENV_LIB ${${child}_lib})
LIST(APPEND ENV_TARGET ${${child}_target_link})
endforeach()
message(" ENV_INCLUDE : " ${ENV_INCLUDE} )
message(" ENV_LIB : " ${ENV_LIB} )
message(" ENV_TARGET : " ${ENV_TARGET} )
include_directories(
${PROJECT_ROOT_PATH}/src/core
${PROJECT_ROOT_PATH}/src/core/handleAi
${PROJECT_ROOT_PATH}/src/core/back
${PROJECT_ROOT_PATH}/src/core/sql
${ENV_INCLUDE}
)
link_directories (
${ENV_LIB}
)
add_compile_options(/utf-8)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
FILE(GLOB HEAD_FILES "*.h" )
FILE(GLOB SRC_FILES "./*.cpp")
FILE(GLOB UI_FILES "./*.ui")
#find_package(Qt5 COMPONENTS Core REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network Sql REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network Sql REQUIRED)
add_library(${CURRENT_FOLDER} SHARED
${HEAD_FILES}
${SRC_FILES}
${UI_FILES}
${PROJECT_ROOT_PATH}/include/qtBridge.h
)
set_target_properties(${CURRENT_FOLDER} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
)
target_link_libraries(${CURRENT_FOLDER} PRIVATE
${ENV_TARGET}
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::Sql
)
# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY)
string(TIMESTAMP RUN_TIME)
message( " modelx end : " ${CURRENT_FOLDER}:${RUN_TIME})
message( " header files "${HEAD_FILES})
@@ -77,7 +77,7 @@ bool Hd_VirtualCamera::run()//�����
}
else {
vector<cv::Mat> mats;
mats.push_back(cv::Mat(4096,3200,CV_8UC3,cv::Scalar(0,255,0)));
mats.push_back(cv::Mat(20960,3200,CV_8UC3,cv::Scalar(0,255,0)));
queuePic.enqueue(mats);
}
n_mutex->unlock();