V20260127-2.3.11
存图时会缓存创建文件夹的路径以防重复创建。 悬停在右侧缺陷柱状图时会出现具体缺陷名, 部分逻辑以及保护优化。
This commit is contained in:
+2
-2
@@ -11,7 +11,7 @@
|
||||
#include <QDir>
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
const std::string softwareVersion = "20260122-2.3.10";
|
||||
const std::string softwareVersion = "20260127-2.3.11";
|
||||
const std::string euiJsonVersion = "1.0.6";
|
||||
#define GigaByte 1073741824
|
||||
#define globalDatabasePth "./sqlDatabase/eui_db.db" //全局数据库路径
|
||||
@@ -22,7 +22,7 @@ const std::string euiJsonVersion = "1.0.6";
|
||||
#define imgSaveTreadMaxCount 4 //最大存图线程数
|
||||
#define jsonRpcEnable false //是否启用JSON RPC服务器
|
||||
#define minimumWindowSize 1280, 720//最小窗口大小
|
||||
#define histogramLabelTiltAngle 30 //柱状图标签倾斜角度
|
||||
#define histogramLabelTiltFontSize 8 //柱状图标签字体大小
|
||||
#define windowMoveFreshRate 60//窗口移动每秒的刷新率
|
||||
#define sColor_Blue "51, 56, 69"
|
||||
#define sColor_BlueWithWhite "64, 68, 81"
|
||||
|
||||
+25
-22
@@ -107,12 +107,16 @@ public:
|
||||
virtual void putText(cv::Mat& image, const std::string& text, cv::Point org, cv::Scalar color = cv::Scalar(255, 0, 0)) = 0;
|
||||
};
|
||||
|
||||
class TextRendererZH : public TextRendererBase {
|
||||
class TextRendererZH{
|
||||
public:
|
||||
TextRendererZH(const TextRendererZH&) = delete;
|
||||
TextRendererZH& operator=(const TextRendererZH&) = delete;
|
||||
|
||||
TextRendererZH(TextRendererZH&&) noexcept = default;
|
||||
TextRendererZH& operator=(TextRendererZH&&) noexcept = default;
|
||||
TextRendererZH(int width, int height, int fontSize = 20, const std::wstring& fontName = L"微软雅黑")
|
||||
: width_(width), height_(height), fontSize_(fontSize), fontName_(fontName)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
screenDC_ = GetDC(nullptr);
|
||||
if (!screenDC_) {
|
||||
throw std::runtime_error("Failed to get screen DC");
|
||||
@@ -121,12 +125,11 @@ public:
|
||||
}
|
||||
|
||||
~TextRendererZH() {
|
||||
QMutexLocker locker(&mutex_);
|
||||
releaseResources();
|
||||
if (screenDC_) ReleaseDC(nullptr, screenDC_);
|
||||
}
|
||||
|
||||
void putText(cv::Mat& image, const std::string& text, cv::Point org, cv::Scalar color = cv::Scalar(255, 0, 0)) override {
|
||||
void putText(cv::Mat& image, const std::string& text, cv::Point org, cv::Scalar color = cv::Scalar(255, 0, 0)) {
|
||||
QMutexLocker locker(&mutex_);
|
||||
|
||||
if (image.channels() != 3)
|
||||
@@ -182,45 +185,45 @@ public:
|
||||
struct contourPaintJob {
|
||||
std::vector<cv::Point> contour;
|
||||
cv::Scalar color;
|
||||
int thikness;
|
||||
int thickness;
|
||||
};
|
||||
void appendPaintJob(std::vector<cv::Point> contour, cv::Scalar color, int thikness) {
|
||||
void appendPaintJob(std::vector<cv::Point> contour, cv::Scalar color, int thickness) {
|
||||
QMutexLocker locker(&mutex_);
|
||||
contourPaintJobs.push_back(contourPaintJob{ contour,color,thikness });
|
||||
contourPaintJobs.push_back(contourPaintJob{ contour,color,thickness });
|
||||
}
|
||||
|
||||
struct linePaintJob {
|
||||
cv::Point p1;
|
||||
cv::Point p2;
|
||||
cv::Scalar color;
|
||||
int thikness;
|
||||
int thickness;
|
||||
};
|
||||
void appendPaintJob(cv::Point p1, cv::Point p2, cv::Scalar color, int thikness) {
|
||||
void appendPaintJob(cv::Point p1, cv::Point p2, cv::Scalar color, int thickness) {
|
||||
QMutexLocker locker(&mutex_);
|
||||
linePaintJobs.push_back(linePaintJob{ p1,p2,color,thikness });
|
||||
linePaintJobs.push_back(linePaintJob{ p1,p2,color,thickness });
|
||||
}
|
||||
|
||||
struct circleAndCorssPaintJob {
|
||||
cv::Point center;
|
||||
double radius;
|
||||
cv::Scalar color;
|
||||
int thikness;
|
||||
int thickness;
|
||||
int type;
|
||||
};
|
||||
//type0 圆 type1 十字
|
||||
void appendPaintJob(cv::Point center, double radius,cv::Scalar color, int thikness,int type) {
|
||||
void appendPaintJob(cv::Point center, double radius,cv::Scalar color, int thickness,int type) {
|
||||
QMutexLocker locker(&mutex_);
|
||||
circleAndCorssPaintJobs.push_back(circleAndCorssPaintJob{ center,radius,color,thikness,type });
|
||||
circleAndCorssPaintJobs.push_back(circleAndCorssPaintJob{ center,radius,color,thickness,type });
|
||||
}
|
||||
|
||||
struct rectPaintJob {
|
||||
cv::Rect rect;
|
||||
cv::Scalar color;
|
||||
int thikness;
|
||||
int thickness;
|
||||
};
|
||||
void appendPaintJob(cv::Rect rect, cv::Scalar color,int thikness) {
|
||||
void appendPaintJob(cv::Rect rect, cv::Scalar color,int thickness) {
|
||||
QMutexLocker locker(&mutex_);
|
||||
rectPaintJobs.push_back(rectPaintJob{ rect,color,thikness });
|
||||
rectPaintJobs.push_back(rectPaintJob{ rect,color,thickness });
|
||||
}
|
||||
|
||||
struct textPaintJob {
|
||||
@@ -233,7 +236,7 @@ public:
|
||||
textPaintJobs.push_back(textPaintJob{ text,p,color });
|
||||
}
|
||||
|
||||
void excusePaintJobs(cv::Mat& image,double resizeRate = 1.0) {
|
||||
void executePaintJobs(cv::Mat& image,double resizeRate = 1.0) {
|
||||
QMutexLocker locker(&mutex_);
|
||||
|
||||
if (textPaintJobs.empty() && pointPaintJobs.empty() && circleAndCorssPaintJobs.empty() && rectPaintJobs.empty() && contourPaintJobs.empty() && linePaintJobs.empty()) return;
|
||||
@@ -253,24 +256,24 @@ public:
|
||||
// 绘制圆或十字
|
||||
for (const auto& job : circleAndCorssPaintJobs) {
|
||||
if(job.type == 0)
|
||||
cv::circle(image, job.center, job.radius, job.color, job.thikness);
|
||||
cv::circle(image, job.center, job.radius, job.color, job.thickness);
|
||||
else
|
||||
cv::drawMarker(image, job.center, job.color, cv::MARKER_CROSS, job.radius, job.thikness);
|
||||
cv::drawMarker(image, job.center, job.color, cv::MARKER_CROSS, job.radius, job.thickness);
|
||||
}
|
||||
|
||||
// 绘制点集
|
||||
for (const auto& job : contourPaintJobs) {
|
||||
cv::drawContours(image, { job.contour }, 0, job.color, job.thikness);
|
||||
cv::drawContours(image, { job.contour }, 0, job.color, job.thickness);
|
||||
}
|
||||
|
||||
// 绘制线段
|
||||
for (const auto& job : linePaintJobs) {
|
||||
cv::line(image, job.p1, job.p2, job.color, job.thikness);
|
||||
cv::line(image, job.p1, job.p2, job.color, job.thickness);
|
||||
}
|
||||
|
||||
// 绘制矩形
|
||||
for (const auto& job : rectPaintJobs) {
|
||||
cv::rectangle(image, job.rect, job.color, job.thikness);
|
||||
cv::rectangle(image, job.rect, job.color, job.thickness);
|
||||
}
|
||||
|
||||
// 绘制文本(需要GDI处理)
|
||||
|
||||
+1
-1
@@ -150,10 +150,10 @@ public:
|
||||
camera->clearCache();//清除缓存
|
||||
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
|
||||
QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包
|
||||
data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图"));
|
||||
data->saveObjectName = saveObjectName;
|
||||
camera->captureImage(data);//拍照
|
||||
generalDet->asyncProcess(data, address[batteryOffset], ("D" + address[batteryOffset].completeAddr + "_1"));//处理算法 并在取到图片后发送完成信号
|
||||
data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图"));
|
||||
}
|
||||
private:
|
||||
QString saveObjectName = "";
|
||||
|
||||
+1
-2
@@ -290,11 +290,10 @@ public:
|
||||
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
|
||||
QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包
|
||||
data->saveObjectName = saveObjectName;
|
||||
|
||||
data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图"));
|
||||
camera->captureImage(data);//拍照
|
||||
|
||||
generalDet->asyncProcess(data, address[batteryOffset]);//处理算法
|
||||
data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图"));
|
||||
_serviceManager->_triggerManager->writeShort("D" + address[batteryOffset].completeAddr + "_1");//完成信号 根据偏移发送
|
||||
}
|
||||
private:
|
||||
|
||||
@@ -290,11 +290,10 @@ public:
|
||||
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
|
||||
QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包
|
||||
data->saveObjectName = saveObjectName;
|
||||
|
||||
data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图"));
|
||||
camera->captureImage(data);//拍照
|
||||
|
||||
generalDet->asyncProcess(data, address[batteryOffset]);//处理算法
|
||||
data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图"));
|
||||
_serviceManager->_triggerManager->writeShort("D" + address[batteryOffset].completeAddr + "_1");//完成信号 根据偏移发送
|
||||
}
|
||||
private:
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
#include <paramSyncManager.h>
|
||||
class Backend : public IBackend {
|
||||
public:
|
||||
DataRecorder* _dataRecorder = nullptr;
|
||||
missionResultHandle* _missionResultHandle = nullptr;
|
||||
ServiceManager _serviceManager;
|
||||
paramSyncManager* _paramSyncManager = nullptr;//供客户在UI修改/查看
|
||||
DataRecorder* _dataRecorder = nullptr;// 数据记录器
|
||||
missionResultHandle* _missionResultHandle = nullptr;// 任务结果处理器
|
||||
ServiceManager _serviceManager;//服务类接口
|
||||
paramSyncManager* _paramSyncManager = nullptr;//检测参数同步类//供客户在UI修改/查看
|
||||
CLIManager* _cliManager; // 命令行接口管理器
|
||||
#if jsonRpcEnable
|
||||
rpc::JsonRpcServer _rpcServer;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cctype>
|
||||
#include <stdexcept>
|
||||
#include <detData.h>
|
||||
#include <paramSyncManager.h>
|
||||
#include <global.h>
|
||||
@@ -43,7 +44,7 @@ public:
|
||||
for (int i = 0; i < data->resultSaveText.size(); i++) {
|
||||
processResult.append("_" + data->resultSaveText[i]);
|
||||
}
|
||||
result.replace("{processResult}", processResult);
|
||||
result.replace("{processResult}", QString::fromStdString(repairWindowsFileName(processResult.toStdString())));
|
||||
|
||||
// 替换SN/设备信息占位符
|
||||
QString snCode = (data->SNcode.size() > 0 && data->SNcode.size() < 50)
|
||||
@@ -167,6 +168,7 @@ public:
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QString defaultPath = "{imgSaveRootDir}/{yyyy-MM-dd}/{saveObjectName}{imageType}/{HH}H/{processResult}/{SN}/";
|
||||
@@ -174,8 +176,8 @@ private:
|
||||
};
|
||||
struct saveJob {
|
||||
saveJob(std::string jobNameIn) :jobName(jobNameIn) {}
|
||||
std::string jobName;
|
||||
QQueue<std::pair<std::string, cv::Mat>> imgQueue;
|
||||
std::string jobName;// 任务名称
|
||||
QQueue<std::pair<std::string, cv::Mat>> imgQueue;// 图片队列
|
||||
};
|
||||
|
||||
// 数据库存储线程类
|
||||
@@ -283,7 +285,6 @@ private:
|
||||
QMutex queueMutex;
|
||||
std::atomic<int> pendingCount = 0;
|
||||
};
|
||||
|
||||
class imgSaveThread : public QThread {
|
||||
|
||||
public:
|
||||
@@ -314,20 +315,18 @@ public:
|
||||
if (job == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
#if saveImgEnable
|
||||
imgRemainCount -= job->imgQueue.size();
|
||||
qDebug() << "saveJob start" << QString::fromStdString(job->jobName) << "remain" << imgRemainCount;
|
||||
localQueue.swap(job->imgQueue);
|
||||
// 批量保存
|
||||
while (!localQueue.isEmpty()) {
|
||||
auto data = std::move(localQueue.dequeue());
|
||||
#if saveImgEnable
|
||||
cv::imwrite(data.first, data.second);
|
||||
QMutexLocker locker(&threadBufferSizeMutex);
|
||||
threadBufferSize -= data.second.total() * data.second.elemSize();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
qDebug() << "saveJob end " << QString::fromStdString(job->jobName);
|
||||
}
|
||||
}
|
||||
@@ -381,6 +380,90 @@ private:
|
||||
int threadIndex = 0, threadBufferSize = 0, imgRemainCount = 0;
|
||||
QMutex queueMutex, threadBufferSizeMutex;
|
||||
};
|
||||
|
||||
//用于缓存需要创建的文件夹路径,防止重复创建
|
||||
class LRUCache {
|
||||
public:
|
||||
explicit LRUCache(int capacity) : maxCapacity(capacity) {
|
||||
if (capacity <= 0) {
|
||||
throw std::invalid_argument("LRU缓存容量必须大于0");
|
||||
}
|
||||
}
|
||||
|
||||
// 检查字符串是否在缓存中
|
||||
bool contains(const QString& value) {
|
||||
QMutexLocker locker(&mutex);
|
||||
int index = cacheList.indexOf(value);
|
||||
if (index != -1) {
|
||||
// 移动到列表头部(最近使用)
|
||||
cacheList.move(index, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 添加字符串到缓存
|
||||
void put(const QString& value) {
|
||||
QMutexLocker locker(&mutex);
|
||||
if (value.isEmpty()) {
|
||||
return; // 不缓存空字符串
|
||||
}
|
||||
|
||||
int index = cacheList.indexOf(value);
|
||||
if (index != -1) {
|
||||
// 已存在,移动到头部
|
||||
cacheList.move(index, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// 不存在,需要添加
|
||||
if (cacheList.size() >= maxCapacity) {
|
||||
// 缓存已满,移除最久未使用的元素(尾部)
|
||||
cacheList.removeLast();
|
||||
}
|
||||
|
||||
// 添加新元素到头部
|
||||
cacheList.prepend(value);
|
||||
}
|
||||
|
||||
// 移除指定元素
|
||||
bool remove(const QString& value) {
|
||||
QMutexLocker locker(&mutex);
|
||||
int index = cacheList.indexOf(value);
|
||||
if (index != -1) {
|
||||
cacheList.removeAt(index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取缓存大小
|
||||
int size() const {
|
||||
return cacheList.size();
|
||||
}
|
||||
|
||||
// 获取最大容量
|
||||
int capacity() const {
|
||||
return maxCapacity;
|
||||
}
|
||||
|
||||
// 检查是否为空
|
||||
bool isEmpty() const {
|
||||
return cacheList.isEmpty();
|
||||
}
|
||||
|
||||
// 清空缓存
|
||||
void clear() {
|
||||
QMutexLocker locker(&mutex);
|
||||
cacheList.clear();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QMutex mutex;
|
||||
int maxCapacity;
|
||||
QStringList cacheList; // QStringList,头部是最近使用的,尾部是最久未使用的
|
||||
};
|
||||
class imgSaveThreadManager {
|
||||
public:
|
||||
imgSaveThreadManager(std::string pathIn, paramSyncManager* paramSyncManagerIn)
|
||||
@@ -391,7 +474,6 @@ public:
|
||||
saveRes = _paramSyncManager->get("通用设置", "存储结果图", true).toBool();
|
||||
saveSeg = _paramSyncManager->get("通用设置", "存储Seg图", true).toBool();
|
||||
saveCls = _paramSyncManager->get("通用设置", "存储Cls图", true).toBool();
|
||||
|
||||
//初始化存图线程
|
||||
QMutexLocker locker(&saveThreadMutexVec);
|
||||
saveThreads.emplace_back(std::make_unique<imgSaveThread>(saveThreads.size()));
|
||||
@@ -446,12 +528,32 @@ public:
|
||||
}
|
||||
}
|
||||
try {
|
||||
std::shared_ptr<saveJob> oriJob(new saveJob("[ORI_JOB]" + data->SNcode));
|
||||
std::shared_ptr<saveJob> resJob(new saveJob("[RES_JOB]" + data->SNcode));
|
||||
std::shared_ptr<saveJob> oriJob(new saveJob("[ORI_JOB]" + data->SNcode));
|
||||
|
||||
QString resSavePath = _ImageSavePathFormatter.genPath(data, "结果图", data->customPath, data->customImageSaveTemplateParams);//获取文件夹名
|
||||
if (saveRes == true) {
|
||||
if (createPathCache.contains(resSavePath) == false) {//不存在此文件夹则创建
|
||||
createDirectoryIfNotExists(resSavePath);
|
||||
allDirectoryPaths.push_back(resSavePath);//记录文件夹路径
|
||||
createPathCache.put(resSavePath);//加入缓存
|
||||
}
|
||||
|
||||
//结果图保存
|
||||
if (data->getResultImgSize() != 0) {
|
||||
std::vector<std::string>fileNames = _ImageSavePathFormatter.genFileNames(data, ImageSavePathFormatter::resImg, data->getResultImgVec());//按规则为文件创建命名
|
||||
packageData(resJob->imgQueue, resSavePath.toLocal8Bit().toStdString(), fileNames, data->getResultImgVec());//打包数据
|
||||
}
|
||||
}
|
||||
|
||||
QString oriSavePath = _ImageSavePathFormatter.genPath(data, "原图", data->customPath, data->customImageSaveTemplateParams);//获取文件夹名
|
||||
if (saveOri == true || saveSeg == true || saveCls == true) {
|
||||
createDirectoryIfNotExists(oriSavePath);//不存在此文件夹则创建
|
||||
allDirectoryPaths.push_back(oriSavePath);//记录文件夹路径
|
||||
|
||||
if (createPathCache.contains(oriSavePath) == false) {//不存在此文件夹则创建
|
||||
createDirectoryIfNotExists(oriSavePath);
|
||||
allDirectoryPaths.push_back(oriSavePath);//记录文件夹路径
|
||||
createPathCache.put(oriSavePath);//加入缓存
|
||||
}
|
||||
if (data->getOriImgSize() != 0 && saveOri == true) {
|
||||
std::vector<std::string>fileNames = _ImageSavePathFormatter.genFileNames(data, ImageSavePathFormatter::oriImg, data->getOriImgVec());//按规则为文件创建命名
|
||||
packageData(oriJob->imgQueue, oriSavePath.toLocal8Bit().toStdString(), fileNames, data->getOriImgVec());//打包数据
|
||||
@@ -468,22 +570,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString resSavePath = _ImageSavePathFormatter.genPath(data, "结果图", data->customPath, data->customImageSaveTemplateParams);//获取文件夹名
|
||||
if (saveRes == true) {
|
||||
createDirectoryIfNotExists(resSavePath);//不存在此文件夹则创建
|
||||
allDirectoryPaths.push_back(resSavePath);//记录文件夹路径
|
||||
//结果图保存
|
||||
if (data->getResultImgSize() != 0) {
|
||||
std::vector<std::string>fileNames = _ImageSavePathFormatter.genFileNames(data, ImageSavePathFormatter::resImg, data->getResultImgVec());//按规则为文件创建命名
|
||||
packageData(resJob->imgQueue, resSavePath.toLocal8Bit().toStdString(), fileNames, data->getResultImgVec());//打包数据
|
||||
}
|
||||
}
|
||||
|
||||
if (oriJob->imgQueue.size() != 0)
|
||||
getSaveThread()->addJob(oriJob);
|
||||
if (resJob->imgQueue.size() != 0)
|
||||
getSaveThread()->addJob(resJob, imgSaveThread::priority);
|
||||
if (oriJob->imgQueue.size() != 0)
|
||||
getSaveThread()->addJob(oriJob);
|
||||
|
||||
#pragma region 将存储目录写入数据库中
|
||||
#if savePathToDataBase
|
||||
@@ -522,11 +612,12 @@ public:
|
||||
return saveThreads.back().get();
|
||||
}
|
||||
private:
|
||||
LRUCache createPathCache{ 200 };//用于缓存已经创建过的文件夹路径,防止重复创建
|
||||
std::unique_ptr<dbSaveThread> dbThread; // 数据库存储线程
|
||||
QMutex paramTimerMutex; // 保护参数计时器的互斥锁
|
||||
int maxSaveThreadCount = imgSaveTreadMaxCount;
|
||||
QMutex saveThreadMutexVec;
|
||||
std::vector<std::unique_ptr<imgSaveThread>> saveThreads;
|
||||
std::vector<std::unique_ptr<imgSaveThread>> saveThreads;//存图线程池
|
||||
bool saveOri = true, saveRes = true, saveSeg = true, saveCls = true;
|
||||
QElapsedTimer getParamTimer;//防止加锁次数过多导致卡顿
|
||||
paramSyncManager* _paramSyncManager;
|
||||
|
||||
@@ -103,11 +103,14 @@ void triggerManager::receiveCommand() {
|
||||
|
||||
for (auto& _struct : readAllCmds) {
|
||||
QByteArray readByte = _struct.readAllCmd;
|
||||
mutex.lock();
|
||||
if (!reciveFinsMsg(readByte))
|
||||
qCritical() << "[TCP] " << " finstcp_ptr readData error!";
|
||||
mutex.unlock();
|
||||
//接收数据
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
if (!reciveFinsMsg(readByte))
|
||||
qCritical() << "[TCP] " << " finstcp readData error!";
|
||||
}
|
||||
tLocker[_struct.readAllCmd].reFreshLocker(readByte);//经过检查后再触发
|
||||
//解析数据
|
||||
decodeCameraCMD(_struct,readByte);
|
||||
}
|
||||
|
||||
@@ -147,10 +150,10 @@ void triggerManager::decodeCameraCMD(readAllStruct& _struct, QByteArray byte)
|
||||
else if (isConnected == false) {
|
||||
emit bridge->setPlcConnectionOk();
|
||||
isConnected = true;
|
||||
qDebug() << "掉线时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒";
|
||||
std::cout << "重连成功,经过时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒" << std::endl;
|
||||
qDebug() << "重连成功,经过时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒";
|
||||
std::cout << "重连成功,经过时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒" << std::endl;
|
||||
}
|
||||
checkCallback(_struct,byte);
|
||||
checkCallback(_struct, byte);
|
||||
checkUnionCallback(_struct, byte);
|
||||
checkPlcValueViewer(_struct, byte);
|
||||
}
|
||||
@@ -162,18 +165,17 @@ void triggerManager::checkCallback(readAllStruct _struct, QByteArray& byteArray)
|
||||
if (checkTrigger(callback.triggerAddress, callback.triggerValue, _struct, byteArray) == true)
|
||||
{
|
||||
qDebug() << "func:" << QString::fromStdString(callback.funcName) << "->已触发 " << callback.triggerValue;
|
||||
std::async(std::launch::async, [callback, byteArray]() mutable {
|
||||
try {
|
||||
callback.func(callback.triggerAddress, callback.triggerValue, byteArray); // 执行回调函数
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
qCritical() << "Error in callback " << QString::fromStdString(callback.funcName) << ": " << QString::fromStdString(e.what());
|
||||
}
|
||||
catch (...) {
|
||||
qCritical() << "Error in callback : unexpected" << QString::fromStdString(callback.funcName);
|
||||
}
|
||||
});
|
||||
try {
|
||||
callback.func(callback.triggerAddress, callback.triggerValue, byteArray); // 执行回调函数
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
qCritical() << "Error in callback " << QString::fromStdString(callback.funcName) << ": " << QString::fromStdString(e.what());
|
||||
}
|
||||
catch (...) {
|
||||
qCritical() << "Error in callback : unexpected" << QString::fromStdString(callback.funcName);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,17 +218,15 @@ void triggerManager::checkUnionCallback(readAllStruct& _struct, QByteArray& byte
|
||||
}
|
||||
}
|
||||
qDebug() << "Union func:" << QString::fromStdString(cb.funcName) << "->已触发 ("<< triggerSource <<")";
|
||||
std::async(std::launch::async, [cb, copyByte = byteArray, triggerSource]() mutable {
|
||||
try {
|
||||
cb.func(triggerSource, copyByte);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
qCritical() << "Error in union callback " << QString::fromStdString(cb.funcName) << ": " << QString::fromStdString(e.what()) ;
|
||||
}
|
||||
catch (...) {
|
||||
qCritical() << "Error in union callback : unexpected" << QString::fromStdString(cb.funcName);
|
||||
}
|
||||
});
|
||||
try {
|
||||
cb.func(triggerSource, byteArray);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
qCritical() << "Error in union callback " << QString::fromStdString(cb.funcName) << ": " << QString::fromStdString(e.what()) ;
|
||||
}
|
||||
catch (...) {
|
||||
qCritical() << "Error in union callback : unexpected" << QString::fromStdString(cb.funcName);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPainter>
|
||||
#include <QToolTip>
|
||||
#include <QCursor>
|
||||
#include <QGraphicsSimpleTextItem>
|
||||
#include <QtCharts/QChart>
|
||||
#include <QtCharts/QChartView>
|
||||
@@ -111,7 +113,7 @@ private:
|
||||
chartView->setRenderHint(QPainter::Antialiasing);
|
||||
mainLayout->addWidget(chartView);
|
||||
|
||||
setStyleSheet("QLabel { color: white; }");
|
||||
setStyleSheet("QLabel { color: white; } QToolTip { color: white; background-color: rgb(40, 45, 50); border: 1px solid rgb(80, 85, 90); }");
|
||||
}
|
||||
|
||||
void initChart() {
|
||||
@@ -119,6 +121,20 @@ private:
|
||||
barSet->setColor(QColor(255, 0, 0)); // 红色柱体
|
||||
barSet->setBorderColor(QColor(255, 255, 255)); // 白色边框
|
||||
|
||||
connect(barSet, &QBarSet::hovered, this, [this](bool status, int index) {
|
||||
QMutexLocker locker(&mutex);
|
||||
if (!status) {
|
||||
QToolTip::hideText();
|
||||
return;
|
||||
}
|
||||
if (index < 0 || index >= categories.size())
|
||||
return;
|
||||
const QString text = QString::fromUtf8("%1\n数量: %2")
|
||||
.arg(categories.at(index))
|
||||
.arg(barSet->at(index));
|
||||
QToolTip::showText(QCursor::pos(), text, chartView, QRect(), 30000);
|
||||
});
|
||||
|
||||
series = new QBarSeries();
|
||||
series->append(barSet);
|
||||
|
||||
@@ -130,7 +146,6 @@ private:
|
||||
|
||||
axisX = new QBarCategoryAxis();
|
||||
axisX->setLabelsBrush(QBrush(Qt::white));
|
||||
axisX->setLabelsAngle(histogramLabelTiltAngle); // 设置标签倾斜
|
||||
chart->addAxis(axisX, Qt::AlignBottom);
|
||||
series->attachAxis(axisX);
|
||||
|
||||
@@ -142,7 +157,7 @@ private:
|
||||
series->attachAxis(axisY);
|
||||
|
||||
chartView->setChart(chart);
|
||||
chart->setMargins(QMargins(0, 0, 0, 0));
|
||||
chart->setMargins(QMargins(0, 0, 0, 0));
|
||||
chart->setBackgroundBrush(QColor(50, 55, 60));
|
||||
chartView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
chartView->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -151,7 +166,7 @@ private:
|
||||
|
||||
void updateValueLabels() {
|
||||
QFont font;
|
||||
font.setPointSize(10);
|
||||
font.setPointSize(histogramLabelTiltFontSize);
|
||||
font.setBold(true);
|
||||
|
||||
// 删除旧标签
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "qtLogRediretor.h"
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
// 全局指针,用于消息处理函数
|
||||
static qtRediretor* qtRediretor_Ptr = nullptr;
|
||||
@@ -22,7 +25,7 @@ static void qtMessageHandler(QtMsgType type, const QMessageLogContext& context,
|
||||
typeText = "ERROR";
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
typeText = "ERROR";
|
||||
typeText = "FATAL";
|
||||
break;
|
||||
default:
|
||||
typeText = "INFO";
|
||||
|
||||
+27
-4
@@ -7,6 +7,7 @@
|
||||
#include <QSharedMemory>
|
||||
#include <QMessageLogger>//日志
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include <qmessagebox.h>
|
||||
#include <qpushbutton.h>
|
||||
#include <qlineedit.h>
|
||||
@@ -102,9 +103,10 @@ static bool dumpCallback(const wchar_t* dump_path,
|
||||
bool succeeded) {
|
||||
|
||||
QString dumpFile = QString::fromWCharArray(dump_path) + "\\" + QString::fromWCharArray(minidump_id) + ".dmp";
|
||||
QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
|
||||
|
||||
if (succeeded) {
|
||||
qDebug() << "========== 程序崩溃 ==========";
|
||||
qDebug() << "========== 程序崩溃 ==========" << timestamp;
|
||||
qDebug() << "崩溃转储文件已生成:" << dumpFile;
|
||||
|
||||
if (exinfo && exinfo->ExceptionRecord) {
|
||||
@@ -125,19 +127,33 @@ static bool dumpCallback(const wchar_t* dump_path,
|
||||
default: exceptionType = "未知异常"; break;
|
||||
}
|
||||
qDebug() << "异常类型:" << exceptionType;
|
||||
|
||||
// 记录更多上下文信息
|
||||
if (exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
|
||||
exinfo->ExceptionRecord->NumberParameters >= 2) {
|
||||
ULONG_PTR operation = exinfo->ExceptionRecord->ExceptionInformation[0];
|
||||
ULONG_PTR address = exinfo->ExceptionRecord->ExceptionInformation[1];
|
||||
QString operationType = (operation == 0) ? "读取" : (operation == 1) ? "写入" : "执行";
|
||||
qDebug() << "访问类型:" << operationType << "地址:" << Qt::hex << Qt::showbase << address;
|
||||
}
|
||||
}
|
||||
|
||||
// 记录当前线程ID
|
||||
qDebug() << "崩溃线程ID:" << GetCurrentThreadId();
|
||||
qDebug() << "==============================";
|
||||
|
||||
// 程序崩溃后自动重启
|
||||
qDebug() << "程序即将自动重启...";
|
||||
|
||||
|
||||
} else {
|
||||
qDebug() << "========== 崩溃转储失败 ==========" << timestamp;
|
||||
qDebug() << "生成崩溃转储文件失败!";
|
||||
qDebug() << "程序即将自动重启...";
|
||||
|
||||
|
||||
qDebug() << "==============================";
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
restartProgram(false, true, 5000);
|
||||
return succeeded;
|
||||
}
|
||||
@@ -317,6 +333,12 @@ int main(int argc, char* argv[])
|
||||
std::cout << "程序将在五秒后重启..." << std::endl;
|
||||
restartProgram(false,true,5000);
|
||||
}
|
||||
qDebug() << "程序退出,返回值" << qtRes;
|
||||
if (qtRes != 0) {
|
||||
qDebug() << "返回值不为0,非正常退出,即将重启程序";
|
||||
restartProgram(false, true, 5000);
|
||||
}
|
||||
QThread::msleep(200);
|
||||
return qtRes;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
@@ -343,4 +365,5 @@ int main(int argc, char* argv[])
|
||||
restartProgram(false, true, 5000);
|
||||
return -2;
|
||||
}
|
||||
return -99;
|
||||
}
|
||||
@@ -131,7 +131,7 @@ halconResult dituo(std::shared_ptr <detData> data, cv::Mat& src, cv::Mat& Paint,
|
||||
|
||||
}
|
||||
//释放存储画图文字
|
||||
textPainterdefect.excusePaintJobs(Paint);
|
||||
textPainterdefect.executePaintJobs(Paint);
|
||||
}
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
|
||||
@@ -514,8 +514,8 @@ bool ALGO_BaoMoHouCeMian(std::shared_ptr <detData> data, baoMoHouDaMianDetParams
|
||||
}
|
||||
else
|
||||
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
|
||||
textPainter.excusePaintJobs(Paint);
|
||||
textPainterCls.excusePaintJobs(Paint);
|
||||
textPainter.executePaintJobs(Paint);
|
||||
textPainterCls.executePaintJobs(Paint);
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, defects);
|
||||
int Rate = (Paint.rows > Paint.cols ? Paint.cols : Paint.rows) / 20;
|
||||
TextRendererZH textPainter1(Paint.cols, Paint.rows, Rate);
|
||||
|
||||
@@ -162,7 +162,7 @@ static bool yuHanQian3D(std::shared_ptr <detData> data, detParams* _detParams, y
|
||||
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, defects);
|
||||
Paint = HObject2Mat(out_DisplayImage);
|
||||
textPainter.excusePaintJobs(Paint);
|
||||
textPainter.executePaintJobs(Paint);
|
||||
int rate = MIN(Paint.rows, Paint.cols) / 20;
|
||||
TextRendererZH textPainter1(Paint.cols, Paint.rows, rate);
|
||||
textPainter1.putText(Paint, "当前条码:" + data->SNcode, cv::Point(50, Paint.rows - (rate * 2)), cv::Scalar(0, 255, 255));
|
||||
|
||||
@@ -195,7 +195,7 @@ bool DianJiaoJianCe(std::shared_ptr <detData> data, dianJiaoParams* _detParams,
|
||||
_detParams->batteryIsNg = (_detParams->lastResultIsNg == true || plcResult == "2");
|
||||
_detParams->lastResultIsNg = false;
|
||||
|
||||
textPainter.excusePaintJobs(Paint);
|
||||
textPainter.executePaintJobs(Paint);
|
||||
Paint.copyTo(_detParams->lastDetImg);
|
||||
}
|
||||
else if (address.triggerValue == 4) {
|
||||
@@ -209,7 +209,7 @@ bool DianJiaoJianCe(std::shared_ptr <detData> data, dianJiaoParams* _detParams,
|
||||
_detParams->lastResultIsNg = false;
|
||||
_detParams->batteryIsNg = false;
|
||||
|
||||
textPainter.excusePaintJobs(Paint);
|
||||
textPainter.executePaintJobs(Paint);
|
||||
if (_detParams->lastDetImg.empty() == false)
|
||||
cv::hconcat(_detParams->lastDetImg, Paint, Paint);
|
||||
data->insertResultImg(Paint);
|
||||
@@ -320,8 +320,8 @@ bool TieJiaoJianCe(std::shared_ptr <detData> data, tieJiaoParams* _detParams, sx
|
||||
if (plcResult == "2")
|
||||
_detParams->lastResultIsNg = true;
|
||||
}
|
||||
textPainter.excusePaintJobs(Paint);
|
||||
textPainter2.excusePaintJobs(Paint);
|
||||
textPainter.executePaintJobs(Paint);
|
||||
textPainter2.executePaintJobs(Paint);
|
||||
data->insertResultImg(Paint);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -193,9 +193,9 @@ bool HanQianDingWei(std::shared_ptr <detData> data, hanQianDingWeiParams* _detPa
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, defects);
|
||||
|
||||
textPainter.excusePaintJobs(Paint);
|
||||
textPainter2.excusePaintJobs(Paint);
|
||||
textPainter3.excusePaintJobs(Paint);
|
||||
textPainter.executePaintJobs(Paint);
|
||||
textPainter2.executePaintJobs(Paint);
|
||||
textPainter3.executePaintJobs(Paint);
|
||||
TextRendererZH textPainterx(Paint.cols, Paint.rows, 160);
|
||||
textPainterx.putText(Paint, "SN:" + data->SNcode, cv::Point(3000,0), cv::Scalar(0, 255, 0));
|
||||
textPainterx.putText(Paint, QDateTime::currentDateTime().toString().toStdString(), cv::Point(3000, 80), cv::Scalar(0, 255, 0));
|
||||
@@ -215,7 +215,9 @@ struct halconResult_2D {
|
||||
bool halconOK = false;
|
||||
};
|
||||
halconResult_2D HanHou2D_halconEvaluate(const cv::Mat& sourceImg,const cv::Mat& segImg, TextRendererZH* textPainter, int times,
|
||||
double tongXingDuLimitHigh, double tongXingDuLimitLow, bool tongXingDuLimitEnable) {
|
||||
double tongXingDuLimitHigh, double tongXingDuLimitLow, bool tongXingDuLimitEnable,
|
||||
double neiYuanPianYiTongXinDuLimitHigh, double neiYuanPianYiTongXinDuLimitLow, bool neiYuanPianYiTongXinDuEnable,
|
||||
double waiYuanPianYiTongXinDuLimitHigh, double waiYuanPianYiTongXinDuLimitLow, bool waiYuanPianYiTongXinDuEnable) {
|
||||
halconResult_2D result;
|
||||
|
||||
HDevEngineCpp::HDevProcedure proc("_3_Cal_HY_CC_Distance");
|
||||
@@ -253,7 +255,15 @@ halconResult_2D HanHou2D_halconEvaluate(const cv::Mat& sourceImg,const cv::Mat&
|
||||
y1Text = y1Text.substr(0, y1Text.find(".") + 4);
|
||||
std::string txd1Text = std::to_string(result.neiYuanTongXinDu);
|
||||
txd1Text = txd1Text.substr(0, txd1Text.find(".") + 4);
|
||||
textPainter->appendPaintJob("内圆偏移X:" + x1Text + "mm Y:" + y1Text + "mm 同心度" + txd1Text, cv::Point(0, 250), cv::Scalar(0, 255, 0));
|
||||
if (result.neiYuanTongXinDu > neiYuanPianYiTongXinDuLimitHigh || result.neiYuanTongXinDu < neiYuanPianYiTongXinDuLimitLow) {
|
||||
textPainter->appendPaintJob("内圆偏移X:" + x1Text + "mm Y:" + y1Text + "mm 同心度" + txd1Text, cv::Point(0, 250), cv::Scalar(0, 255, 0));
|
||||
result.halconOK = false;
|
||||
if (waiYuanPianYiTongXinDuEnable == true)
|
||||
result.isNg = true;
|
||||
}
|
||||
else
|
||||
textPainter->appendPaintJob("内圆偏移X:" + x1Text + "mm Y:" + y1Text + "mm 同心度" + txd1Text, cv::Point(0, 250), cv::Scalar(0, 255, 0));
|
||||
|
||||
|
||||
result.waiYuanPianYi_X = OuterCircle_offset[0].D();
|
||||
result.waiYuanPianYi_Y = OuterCircle_offset[1].D();
|
||||
@@ -265,7 +275,14 @@ halconResult_2D HanHou2D_halconEvaluate(const cv::Mat& sourceImg,const cv::Mat&
|
||||
y2Text = y2Text.substr(0, y2Text.find(".") + 4);
|
||||
std::string txd2Text = std::to_string(result.waiYuanTongXinDu);
|
||||
txd2Text = txd2Text.substr(0, txd2Text.find(".") + 4);
|
||||
textPainter->appendPaintJob("外圆偏移X:" + x2Text + "mm Y:" + y2Text + "mm 同心度:" + txd2Text, cv::Point(0, 450), cv::Scalar(0, 255, 0));
|
||||
if (result.waiYuanTongXinDu > waiYuanPianYiTongXinDuLimitHigh || result.waiYuanTongXinDu < waiYuanPianYiTongXinDuLimitLow) {
|
||||
textPainter->appendPaintJob("外圆偏移X:" + x2Text + "mm Y:" + y2Text + "mm 同心度:" + txd2Text, cv::Point(0, 450), cv::Scalar(0, 0, 255));
|
||||
result.halconOK = false;
|
||||
if (waiYuanPianYiTongXinDuEnable == true)
|
||||
result.isNg = true;
|
||||
}
|
||||
else
|
||||
textPainter->appendPaintJob("外圆偏移X:" + x2Text + "mm Y:" + y2Text + "mm 同心度:" + txd2Text, cv::Point(0, 450), cv::Scalar(0, 255, 0));
|
||||
|
||||
for (int i = 0; i < out_Circle.Length() / 3; i++) {
|
||||
textPainter->appendPaintJob(cv::Point(out_Circle[i * 3 + 1].D(), out_Circle[i * 3].D()), out_Circle[i * 3 + 2].D(), cv::Scalar(0, 255, 0), 15,0);
|
||||
@@ -340,6 +357,17 @@ QByteArray getHanHouJianCe2DSendResult(bool isNg1,bool isNg2) {
|
||||
bool HanHouJianCe2D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx_581_address address){
|
||||
try
|
||||
{
|
||||
double tongXingDuLimitHigh = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(上限)", 1.8).toDouble();
|
||||
double tongXingDuLimitLow = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(下限)", 0).toDouble();
|
||||
bool tongXingDuLimitEnable = data->service->_paramSyncManager->get("焊后", "焊后同心度判定启用", true).toBool();
|
||||
|
||||
double neiYuanPianYiTongXinDuLimitHigh = data->service->_paramSyncManager->get("焊后", "内圆偏移同心度mm(上限)", 2.0).toDouble();
|
||||
double neiYuanPianYiTongXinDuLimitLow = data->service->_paramSyncManager->get("焊后", "内圆偏移同心度mm(下限)", 0).toDouble();
|
||||
bool neiYuanPianYiTongXinDuEnable = data->service->_paramSyncManager->get("焊后", "内圆偏移同心度判定启用", false).toBool();
|
||||
|
||||
double waiYuanPianYiTongXinDuLimitHigh = data->service->_paramSyncManager->get("焊后", "外圆偏移同心度mm(上限)", 1.0).toDouble();
|
||||
double waiYuanPianYiTongXinDuLimitLow = data->service->_paramSyncManager->get("焊后", "外圆偏移同心度mm(下限)", 0).toDouble();
|
||||
bool waiYuanPianYiTongXinDuEnable = data->service->_paramSyncManager->get("焊后", "外圆偏移同心度判定启用", false).toBool();
|
||||
#pragma region 错误处理
|
||||
|
||||
if (data->getOriImgSize() < 2) {
|
||||
@@ -414,11 +442,13 @@ bool HanHouJianCe2D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx
|
||||
data->insertResultImg(PaintSum);
|
||||
return true;
|
||||
}
|
||||
double tongXingDuLimitHigh = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(上限)", 1.8).toDouble();
|
||||
double tongXingDuLimitLow = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(下限)", 0).toDouble();
|
||||
bool tongXingDuLimitEnable = data->service->_paramSyncManager->get("焊后", "焊后同心度判定启用", true).toBool();
|
||||
auto futrue1 = std::async(std::launch::async, &HanHou2D_halconEvaluate, src1, seg1Ori, &textPainter1, 0, tongXingDuLimitHigh, tongXingDuLimitLow, tongXingDuLimitEnable);
|
||||
auto futrue2 = std::async(std::launch::async, &HanHou2D_halconEvaluate, src2, seg2Ori, &textPainter2, 2, tongXingDuLimitHigh, tongXingDuLimitLow, tongXingDuLimitEnable);
|
||||
|
||||
auto futrue1 = std::async(std::launch::async, &HanHou2D_halconEvaluate, src1, seg1Ori, &textPainter1, 0, tongXingDuLimitHigh, tongXingDuLimitLow, tongXingDuLimitEnable,
|
||||
neiYuanPianYiTongXinDuLimitHigh, neiYuanPianYiTongXinDuLimitLow, neiYuanPianYiTongXinDuEnable,
|
||||
waiYuanPianYiTongXinDuLimitHigh, waiYuanPianYiTongXinDuLimitLow, waiYuanPianYiTongXinDuEnable);
|
||||
auto futrue2 = std::async(std::launch::async, &HanHou2D_halconEvaluate, src2, seg2Ori, &textPainter2, 2, tongXingDuLimitHigh, tongXingDuLimitLow, tongXingDuLimitEnable,
|
||||
neiYuanPianYiTongXinDuLimitHigh, neiYuanPianYiTongXinDuLimitLow, neiYuanPianYiTongXinDuEnable,
|
||||
waiYuanPianYiTongXinDuLimitHigh, waiYuanPianYiTongXinDuLimitLow, waiYuanPianYiTongXinDuEnable);
|
||||
auto futrue3 = std::async(std::launch::async, &HanHou2D_handleAiEvaluate, data, _detParams, src1, &textPainter1, _detParams->seg_rljHanZha1, _detParams->cls_rljHanZha1);
|
||||
auto futrue4 = std::async(std::launch::async, &HanHou2D_handleAiEvaluate, data, _detParams, src2, &textPainter2, _detParams->seg_rljHanZha2, _detParams->cls_rljHanZha2);
|
||||
|
||||
@@ -488,8 +518,8 @@ bool HanHouJianCe2D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx
|
||||
data->insertClsOriginImg(hanYinClsImg);
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, defects);
|
||||
|
||||
textPainter1.excusePaintJobs(Paint1);
|
||||
textPainter2.excusePaintJobs(Paint2);
|
||||
textPainter1.executePaintJobs(Paint1);
|
||||
textPainter2.executePaintJobs(Paint2);
|
||||
//拼装结果图
|
||||
cv::Mat PaintSum;
|
||||
cv::vconcat(Paint1, Paint2, PaintSum);
|
||||
@@ -525,9 +555,9 @@ bool HanHouJianCe2D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx
|
||||
struct halconResult_3D {
|
||||
bool isNg = false;
|
||||
double hanPanGaoDu = -99;
|
||||
cv::Point ellipseCenter;
|
||||
double angle;
|
||||
cv::Size ellipseSize;
|
||||
cv::Point ellipseCenter = cv::Point(0,0);
|
||||
double angle = 0;
|
||||
cv::Size ellipseSize = cv::Size(0,0);
|
||||
bool halconOK = false;
|
||||
};
|
||||
halconResult_3D HanHou3D_halconEvaluate(const cv::Mat& heightImg, const double& xResolution, const double& yResolution, const double& zResolution
|
||||
@@ -542,30 +572,42 @@ halconResult_3D HanHou3D_halconEvaluate(const cv::Mat& heightImg, const double&
|
||||
procedureCall.SetInputCtrlParamTuple("in_XResolution", xResolution);
|
||||
procedureCall.SetInputCtrlParamTuple("in_YResolution", yResolution);
|
||||
procedureCall.SetInputCtrlParamTuple("in_ZResolution", zResolution);
|
||||
procedureCall.SetInputCtrlParamTuple("in_FliePath", "./halconFiles/");
|
||||
procedureCall.SetInputCtrlParamTuple("in_FilePath", "./halconFiles/hanhou3D/");
|
||||
procedureCall.Execute();//执行halcon程序
|
||||
HalconCpp::HTuple out_Height = procedureCall.GetOutputCtrlParamTuple("out_Height");//获取输出控制类变量
|
||||
HalconCpp::HTuple out_Ellipse = procedureCall.GetOutputCtrlParamTuple("out_Ellipse");//获取输出控制类变量
|
||||
HalconCpp::HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量
|
||||
HalconCpp::HTuple out_NGDetails = procedureCall.GetOutputCtrlParamTuple("out_NGDetails");//获取输出控制类变量
|
||||
qDebug() << "testFlag0";
|
||||
int flag = out_Flag.D();
|
||||
if (flag == 1) {
|
||||
|
||||
qDebug() << "testFlag1";
|
||||
double height = out_Height.D();
|
||||
textPainter->appendPaintJob("焊盘高度:" + std::to_string(height), cv::Point(0, 50), cv::Scalar(0, 255, 0));
|
||||
result.ellipseCenter = cv::Point(out_Ellipse[0].D(), out_Ellipse[1].D());
|
||||
result.angle = out_Ellipse[2].D();
|
||||
result.ellipseSize = cv::Point(out_Ellipse[3].D(), out_Ellipse[4].D());
|
||||
textPainter->appendPaintJob("焊盘高度:" + std::to_string(height), cv::Point(0, 110), cv::Scalar(0, 255, 0));
|
||||
qDebug() << "testFlag2";
|
||||
if (out_Ellipse.Length() == 5) {
|
||||
result.ellipseCenter = cv::Point(out_Ellipse[0].D(), out_Ellipse[1].D());
|
||||
result.angle = out_Ellipse[2].D();
|
||||
result.ellipseSize = cv::Point(out_Ellipse[3].D(), out_Ellipse[4].D());
|
||||
}
|
||||
else {
|
||||
qDebug() << "无椭圆数据 size"<< out_Ellipse.Length();
|
||||
}
|
||||
qDebug() << "testFlag3";
|
||||
}
|
||||
else {
|
||||
textPainter->appendPaintJob("算法NG:" + std::to_string(out_NGDetails[0].D()), cv::Point(10, 50), cv::Scalar(0, 0, 255));
|
||||
qDebug() << "testFlag4";
|
||||
textPainter->appendPaintJob("算法NG:" + gbkToUtf8(out_NGDetails.ToString().Text()), cv::Point(10, 50), cv::Scalar(0, 0, 255));
|
||||
result.isNg = true;
|
||||
result.halconOK = false;
|
||||
qDebug() << "testFlag5";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
bool HanHouJianCe3D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx_581_address address) {
|
||||
try {
|
||||
bool enable = data->service->_paramSyncManager->get("焊后3D", "焊后3D结果判定启用", false).toBool();;
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
|
||||
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
|
||||
std::vector < std::string> defects = { };
|
||||
@@ -590,13 +632,13 @@ bool HanHouJianCe3D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx
|
||||
cv::Mat height1 = data->getOriImg(1);//高度图1
|
||||
cv::Mat src2 = data->getOriImg(2);//亮度图2
|
||||
cv::Mat height2 = data->getOriImg(3);//高度图2
|
||||
TextRendererZH textPainter1(src1.cols, src1.rows, 300), textPainter2(src2.cols, src2.rows, 300);
|
||||
auto futrue1 = std::async(std::launch::async, &HanHou3D_halconEvaluate, height1,
|
||||
TextRendererZH textPainter1(src1.cols, src1.rows, 100), textPainter2(src2.cols, src2.rows, 100);
|
||||
auto result1 = HanHou3D_halconEvaluate(height1,
|
||||
data->service->_paramSyncManager->get("3D相机1精度","x向精度",0.005).toDouble(),
|
||||
data->service->_paramSyncManager->get("3D相机1精度", "y向精度", 0.02).toDouble(),
|
||||
data->service->_paramSyncManager->get("3D相机1精度", "z向精度", 0.0008).toDouble(),
|
||||
&textPainter1);
|
||||
auto futrue2 = std::async(std::launch::async, &HanHou3D_halconEvaluate, height1,
|
||||
auto result2 = HanHou3D_halconEvaluate(height2,
|
||||
data->service->_paramSyncManager->get("3D相机2精度", "x向精度", 0.005).toDouble(),
|
||||
data->service->_paramSyncManager->get("3D相机2精度", "y向精度", 0.02).toDouble(),
|
||||
data->service->_paramSyncManager->get("3D相机2精度", "z向精度", 0.0008).toDouble(),
|
||||
@@ -608,10 +650,16 @@ bool HanHouJianCe3D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx
|
||||
cv::cvtColor(Paint1, Paint1, cv::COLOR_GRAY2BGR);
|
||||
if (Paint2.channels() != 3)
|
||||
cv::cvtColor(Paint2, Paint2, cv::COLOR_GRAY2BGR);
|
||||
|
||||
if(result1.ellipseCenter.x != 0)
|
||||
cv::ellipse(Paint1, result1.ellipseCenter, result1.ellipseSize, result1.angle, 0, 360, cv::Scalar(0, 255, 0), 3);
|
||||
|
||||
if (result2.ellipseCenter.x != 0)
|
||||
cv::ellipse(Paint2, result2.ellipseCenter, result2.ellipseSize, result2.angle, 0, 360, cv::Scalar(0, 255, 0), 3);
|
||||
textPainter1.putText(Paint1, "OK", cv::Point(10, 10), cv::Scalar(0, 255, 0));
|
||||
textPainter1.excusePaintJobs(Paint1);
|
||||
textPainter1.executePaintJobs(Paint1);
|
||||
textPainter2.putText(Paint2, "OK", cv::Point(10, 10), cv::Scalar(0, 255, 0));
|
||||
textPainter1.excusePaintJobs(Paint2);
|
||||
textPainter2.executePaintJobs(Paint2);
|
||||
cv::vconcat(Paint1, Paint2, PaintSum);
|
||||
putSnAndDetTime(PaintSum, data->SNcode, 60);
|
||||
|
||||
|
||||
@@ -125,10 +125,9 @@ bool ALGO_maJiaReRong(std::shared_ptr <detData> data, maJiaParam* _detParams, sx
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送异常结果
|
||||
return false;
|
||||
}
|
||||
bool ALGO_hanQianDingWei(std::shared_ptr <detData> data, detParams* _detParams, sx_581_address address) {
|
||||
static bool ALGO_hanQianDingWei(std::shared_ptr <detData> data, detParams* _detParams, sx_581_address address) {
|
||||
try {
|
||||
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
|
||||
data->service->_triggerManager->writeShort("D100_1_1");
|
||||
///////////////////取图//处理//////////////////
|
||||
if (data->getOriImgSize() < 1)
|
||||
{
|
||||
@@ -137,6 +136,8 @@ bool ALGO_hanQianDingWei(std::shared_ptr <detData> data, detParams* _detParams,
|
||||
}
|
||||
auto sourceImg = data->getOriImg(0);
|
||||
sourceImg = cv::imread("D:\\testImage\\601\\hanqian.bmp", -1);
|
||||
QThread::msleep(200);
|
||||
|
||||
if (sourceImg.rows == 100) {
|
||||
cv::Mat Paint;
|
||||
sourceImg.copyTo(Paint);
|
||||
@@ -145,31 +146,35 @@ bool ALGO_hanQianDingWei(std::shared_ptr <detData> data, detParams* _detParams,
|
||||
}
|
||||
cv::Mat Paint;
|
||||
sourceImg.copyTo(Paint);
|
||||
HDevEngineCpp::HDevProcedure proc("HQDW_Color_Inspection");
|
||||
HDevEngineCpp::HDevProcedureCall procedureCall(proc);
|
||||
|
||||
HObject inputImage = MatToHObject(sourceImg);
|
||||
HTuple in_Resolution(0.040766), in_FilePath("./halconFiles/");
|
||||
|
||||
|
||||
double HeightLeft_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前左侧Y向高度差", 2.0).toDouble();
|
||||
double HeightRight_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前右侧Y向高度差", 2.0).toDouble();
|
||||
double SlantAngle_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前盖板上下边缘膜的角度", 0.6).toDouble();
|
||||
|
||||
procedureCall.SetInputIconicParamObject("in_Image", inputImage);
|
||||
procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution);
|
||||
procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath);
|
||||
procedureCall.Execute();//执行halcon程序
|
||||
HTuple out_ColorType, out_Distance, make, out_SlantAngle, out_Height;;
|
||||
HTuple out_ColorType, out_Distance, make;
|
||||
HObject out_DisplayImage;
|
||||
//out_LinePoint = procedureCall.GetOutputCtrlParamTuple("out_LinePoint");//获取输出控制类变量
|
||||
out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出控制类变量
|
||||
//out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");//获取输出控制类变量
|
||||
out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance");//获取输出控制类变量
|
||||
out_Height = procedureCall.GetOutputCtrlParamTuple("out_Height");//获取输出控制类变量
|
||||
out_SlantAngle = procedureCall.GetOutputCtrlParamTuple("out_SlantAngle");//获取输出控制类变量
|
||||
make = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量
|
||||
out_DisplayImage = procedureCall.GetOutputIconicParamObject("out_DisplayImage");//获取输出控制类变量
|
||||
{
|
||||
HDevEngineCpp::HDevProcedure proc("HQDW_Color_Inspection");
|
||||
HDevEngineCpp::HDevProcedureCall procedureCall(proc);
|
||||
|
||||
HObject inputImage = MatToHObject(sourceImg);
|
||||
HTuple in_Resolution(0.040766), in_FilePath("./halconFiles/");
|
||||
|
||||
|
||||
double HeightLeft_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前左侧Y向高度差", 2.0).toDouble();
|
||||
double HeightRight_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前右侧Y向高度差", 2.0).toDouble();
|
||||
double SlantAngle_jsonvlaue = data->service->_paramSyncManager->get("焊前定位", "焊前盖板上下边缘膜的角度", 0.6).toDouble();
|
||||
|
||||
procedureCall.SetInputIconicParamObject("in_Image", inputImage);
|
||||
procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution);
|
||||
procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath);
|
||||
procedureCall.Execute();//执行halcon程序
|
||||
|
||||
|
||||
//out_LinePoint = procedureCall.GetOutputCtrlParamTuple("out_LinePoint");//获取输出控制类变量
|
||||
out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出控制类变量
|
||||
//out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");//获取输出控制类变量
|
||||
out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance");//获取输出控制类变量
|
||||
//out_Height = procedureCall.GetOutputCtrlParamTuple("out_Height");//获取输出控制类变量
|
||||
//out_SlantAngle = procedureCall.GetOutputCtrlParamTuple("out_SlantAngle");//获取输出控制类变量
|
||||
make = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量
|
||||
out_DisplayImage = procedureCall.GetOutputIconicParamObject("out_DisplayImage");//获取输出控制类变量
|
||||
}
|
||||
int flag = make.D();
|
||||
QString tmpFlag = "1";
|
||||
// Output(HTuple): out_ColorType, 1, 铜; 2,铝</c>
|
||||
@@ -187,29 +192,29 @@ bool ALGO_hanQianDingWei(std::shared_ptr <detData> data, detParams* _detParams,
|
||||
Paint = HObject2Mat(out_DisplayImage);
|
||||
textPainter.appendPaintJob("膜上边到注液孔:" + std::to_string(out_Distance[0].D()), cv::Point(800, 50), cv::Scalar(0, 255, 0));
|
||||
textPainter.appendPaintJob("膜下边到注液孔:" + std::to_string(out_Distance[1].D()), cv::Point(800, 350), cv::Scalar(0, 255, 0));
|
||||
textPainter.excusePaintJobs(Paint);
|
||||
if (out_Height[0].D() > HeightLeft_jsonvlaue)
|
||||
textPainter.executePaintJobs(Paint);
|
||||
/* if (out_Height[0].D() > HeightLeft_jsonvlaue)
|
||||
{
|
||||
HeightLeftFlag = 2;
|
||||
textPainter.putText(Paint, "左侧Y向高度差:" + std::to_string(out_Height[0].D()), cv::Point(800, 650), cv::Scalar(0, 0, 255));
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "左侧Y向高度差:" + std::to_string(out_Height[0].D()), cv::Point(800, 650), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "左侧Y向高度差:" + std::to_string(out_Height[0].D()), cv::Point(800, 650), cv::Scalar(0, 255, 0));*/
|
||||
|
||||
if (out_Height[1].D() > HeightRight_jsonvlaue)
|
||||
{
|
||||
HeightRightFlag = 2;
|
||||
textPainter.putText(Paint, "右侧Y向高度差:" + std::to_string(out_Height[1].D()), cv::Point(800, 950), cv::Scalar(0, 0, 255));
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "右侧Y向高度差:" + std::to_string(out_Height[1].D()), cv::Point(800, 950), cv::Scalar(0, 255, 0));
|
||||
if (out_SlantAngle.D() > SlantAngle_jsonvlaue)
|
||||
{
|
||||
AlgelFlag = 2;
|
||||
textPainter.putText(Paint, "盖板上下边缘膜的角度:" + std::to_string(out_SlantAngle.D()), cv::Point(800, 1250), cv::Scalar(0, 0, 255));
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "盖板上下边缘膜的角度:" + std::to_string(out_SlantAngle.D()), cv::Point(800, 1250), cv::Scalar(0, 255, 0));
|
||||
//if (out_Height[1].D() > HeightRight_jsonvlaue)
|
||||
//{
|
||||
// HeightRightFlag = 2;
|
||||
// textPainter.putText(Paint, "右侧Y向高度差:" + std::to_string(out_Height[1].D()), cv::Point(800, 950), cv::Scalar(0, 0, 255));
|
||||
//}
|
||||
//else
|
||||
// textPainter.putText(Paint, "右侧Y向高度差:" + std::to_string(out_Height[1].D()), cv::Point(800, 950), cv::Scalar(0, 255, 0));
|
||||
//if (out_SlantAngle.D() > SlantAngle_jsonvlaue)
|
||||
//{
|
||||
// AlgelFlag = 2;
|
||||
// textPainter.putText(Paint, "盖板上下边缘膜的角度:" + std::to_string(out_SlantAngle.D()), cv::Point(800, 1250), cv::Scalar(0, 0, 255));
|
||||
//}
|
||||
//else
|
||||
// textPainter.putText(Paint, "盖板上下边缘膜的角度:" + std::to_string(out_SlantAngle.D()), cv::Point(800, 1250), cv::Scalar(0, 255, 0));
|
||||
int left = out_ColorType[0].D();
|
||||
if (left == 2)
|
||||
textPainter.putText(Paint, "铜", cv::Point(0, 3100), cv::Scalar(0, 0, 255));
|
||||
@@ -244,12 +249,8 @@ bool ALGO_hanQianDingWei(std::shared_ptr <detData> data, detParams* _detParams,
|
||||
plcResult = "2";
|
||||
}
|
||||
|
||||
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//发送异常结果
|
||||
if (plcResult == "2")
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, { "焊前NG" });
|
||||
else
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, { });
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, { "焊前NG" + data->SNcode});
|
||||
cv::resize(Paint, Paint, cv::Size(), 0.25, 0.25);
|
||||
|
||||
data->insertResultImg(Paint);
|
||||
|
||||
@@ -14,7 +14,7 @@ struct hanQianDingWeiSubresult {
|
||||
double Out_Vale_L_centerUp = -1;//铝(负)极连接片中心的和上极耳水平边缘距离(mm)
|
||||
double Out_Vale_L_centerDown = -1;//铝(负)极连接片中心的和下极耳水平边缘距离(mm)
|
||||
double extremumValue = -1;
|
||||
|
||||
|
||||
cv::Point circleCenter;
|
||||
double radius = 1;
|
||||
std::vector<double> lines;
|
||||
|
||||
@@ -144,8 +144,8 @@ bool hanhou2D(std::shared_ptr <detData> data, hanHou2dParam* _detParams, sx_581_
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, defects);
|
||||
futrue3.wait();
|
||||
futrue4.wait();
|
||||
textPainter1.excusePaintJobs(Paint1);
|
||||
textPainter2.excusePaintJobs(Paint2);
|
||||
textPainter1.executePaintJobs(Paint1);
|
||||
textPainter2.executePaintJobs(Paint2);
|
||||
cv::Mat PaintSum;
|
||||
cv::vconcat(Paint1, Paint2, PaintSum);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user