备份 性能优化

This commit is contained in:
2025-07-11 02:02:09 +08:00
parent f389a31389
commit 288b4a7f00
14 changed files with 521 additions and 354 deletions
+149 -52
View File
@@ -31,65 +31,162 @@ static std::wstring utf8ToWstring(const std::string& utf8Str) {
}
// 在图像上绘制中文(仅 Windows,使用 GDI)
static void putTextZH(cv::Mat& image, const std::string& text, cv::Point org, int fontSize = 20, cv::Scalar color = cv::Scalar(255, 0, 0)) {
// 创建兼容的位图
cv::Mat img;
if (image.channels() == 1)
cv::cvtColor(image, img, cv::COLOR_GRAY2BGRA);
else if (image.channels() == 3)
cv::cvtColor(image, img, cv::COLOR_BGR2BGRA);
else if (image.channels() == 4)
img = image.clone();
else
throw std::runtime_error("Unsupported number of channels");
if (image.channels() != 3)
throw std::runtime_error("Only supports 3-channel images");
// 创建 Windows 位图信息
HDC hdc = GetDC(nullptr);
HDC memDC = CreateCompatibleDC(hdc);
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = img.cols;
bmi.bmiHeader.biHeight = -img.rows; // top-down
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
// 转为 BGRA
cv::Mat img;
cv::cvtColor(image, img, cv::COLOR_BGR2BGRA);
void* pBits = nullptr;
HBITMAP hBitmap = CreateDIBSection(memDC, &bmi, DIB_RGB_COLORS, &pBits, nullptr, 0);
SelectObject(memDC, hBitmap);
memcpy(pBits, img.data, img.total() * img.elemSize());
HDC hdc = GetDC(nullptr);
HDC memDC = CreateCompatibleDC(hdc);
// 设置字体
HFONT hFont = CreateFontW(
fontSize, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_SWISS, L"微软雅黑");
SelectObject(memDC, hFont);
BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = img.cols;
bmi.bmiHeader.biHeight = -img.rows;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
// 设置颜色和背景
SetBkMode(memDC, TRANSPARENT);
SetTextColor(memDC, RGB(color[2], color[1], color[0]));
void* pBits = nullptr;
HBITMAP hBitmap = CreateDIBSection(memDC, &bmi, DIB_RGB_COLORS, &pBits, nullptr, 0);
SelectObject(memDC, hBitmap);
memcpy(pBits, img.data, img.total() * img.elemSize());
// 输出文字
std::wstring wtext = utf8ToWstring(text);
TextOutW(memDC, org.x, org.y, wtext.c_str(), static_cast<int>(wtext.length()));
HFONT hFont = CreateFontW(fontSize, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_SWISS, L"微软雅黑");
SelectObject(memDC, hFont);
// 拷贝回来
GetDIBits(memDC, hBitmap, 0, img.rows, img.data, &bmi, DIB_RGB_COLORS);
SetBkMode(memDC, TRANSPARENT);
SetTextColor(memDC, RGB(color[2], color[1], color[0]));
// 转换回原始图像格式
if (image.channels() == 1)
cv::cvtColor(img, image, cv::COLOR_BGRA2GRAY);
else if (image.channels() == 3)
cv::cvtColor(img, image, cv::COLOR_BGRA2BGR);
else if (image.channels() == 4)
image = img.clone();
TextOutW(memDC, org.x, org.y, utf8ToWstring(text).c_str(), static_cast<int>(utf8ToWstring(text).length()));
// 清理
DeleteObject(hFont);
DeleteObject(hBitmap);
DeleteDC(memDC);
ReleaseDC(nullptr, hdc);
}
GetDIBits(memDC, hBitmap, 0, img.rows, img.data, &bmi, DIB_RGB_COLORS);
cv::cvtColor(img, image, cv::COLOR_BGRA2BGR);
DeleteObject(hFont);
DeleteObject(hBitmap);
DeleteDC(memDC);
ReleaseDC(nullptr, hdc);
}
class TextRendererBase {
public:
virtual ~TextRendererBase() = default;
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 {
public:
TextRendererZH(int width, int height, int fontSize = 20, const std::wstring& fontName = L"微软雅黑")
: width_(width), height_(height), fontSize_(fontSize), fontName_(fontName)
{
screenDC_ = GetDC(nullptr);
createResources();
}
~TextRendererZH() {
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 {
if (image.channels() != 3)
throw std::runtime_error("TextRendererZH only supports 3-channel BGR images.");
if (image.cols != width_ || image.rows != height_) {
resize(image.cols, image.rows);
}
cv::Mat img;
cv::cvtColor(image, img, cv::COLOR_BGR2BGRA);
memcpy(pBits_, img.data, img.total() * img.elemSize());
SetBkMode(memDC_, TRANSPARENT);
SetTextColor(memDC_, RGB(color[2], color[1], color[0]));
std::wstring wtext = utf8ToWstring(text);
TextOutW(memDC_, org.x, org.y, wtext.c_str(), (int)wtext.length());
GetDIBits(memDC_, hBitmap_, 0, height_, img.data, &bmi_, DIB_RGB_COLORS);
cv::cvtColor(img, image, cv::COLOR_BGRA2BGR);
}
void resize(int width, int height) {
if (width == width_ && height == height_) return;
releaseResources();
width_ = width;
height_ = height;
createResources();
}
private:
void createResources() {
memDC_ = CreateCompatibleDC(screenDC_);
memset(&bmi_, 0, sizeof(bmi_));
bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi_.bmiHeader.biWidth = width_;
bmi_.bmiHeader.biHeight = -height_;
bmi_.bmiHeader.biPlanes = 1;
bmi_.bmiHeader.biBitCount = 32;
bmi_.bmiHeader.biCompression = BI_RGB;
hBitmap_ = CreateDIBSection(memDC_, &bmi_, DIB_RGB_COLORS, &pBits_, nullptr, 0);
SelectObject(memDC_, hBitmap_);
hFont_ = CreateFontW(
fontSize_, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_SWISS, fontName_.c_str());
SelectObject(memDC_, hFont_);
}
void releaseResources() {
if (hFont_) {
DeleteObject(hFont_);
hFont_ = nullptr;
}
if (hBitmap_) {
DeleteObject(hBitmap_);
hBitmap_ = nullptr;
pBits_ = nullptr;
}
if (memDC_) {
DeleteDC(memDC_);
memDC_ = nullptr;
}
}
// UTF8 转宽字符串
static std::wstring utf8ToWstring(const std::string& str) {
if (str.empty()) return {};
int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
private:
int width_;
int height_;
int fontSize_;
std::wstring fontName_;
HDC screenDC_ = nullptr;
HDC memDC_ = nullptr;
HBITMAP hBitmap_ = nullptr;
void* pBits_ = nullptr;
BITMAPINFO bmi_{};
HFONT hFont_ = nullptr;
};
#pragma endregion
BIN
View File
Binary file not shown.
+2 -4
View File
@@ -47,9 +47,9 @@ void camera::run()
int queueSize = requestQueue.size() ;
if (queueSize >0)
{
mutex.lock();
QMutexLocker locker(&mutex);
std::shared_ptr <detData>data = requestQueue.dequeue();
data->oriImgMutex.lock();
QMutexLocker locker2(&data->oriImgMutex);
while(1){
getCameraImg(data->oriImgs, data->imgAmountMin);
if (data->oriImgs.size() >= data->imgAmountMin){
@@ -76,8 +76,6 @@ void camera::run()
showLost++;
qDebug() << cameraModulePtr.dllPath << "Lost show";
}
data->oriImgMutex.unlock();
mutex.unlock();
break;
}
QThread::msleep(1);
+1
View File
@@ -38,6 +38,7 @@ public:
void getImgQueueSize();
void captureImage(std::shared_ptr <detData> dataIn)
{
QMutexLocker locker(&mutex);
requestQueue.enqueue(dataIn);
std::thread([this]() {trigger();}).detach();
-1
View File
@@ -114,7 +114,6 @@ public:
if (dataPtr == nullptr)
qDebug() << "创建新容器失败";
qDebug() << "创建新容器成功";
return dataPtr;
}
std::shared_ptr <detData> getDetData(QString uuid)
+53 -69
View File
@@ -9,7 +9,6 @@ enum imgSaveThreadType
resImg,
segImg,
clsImg,
additionalSaveNgImg,
tiffOriImg
};
class imgSaveThread : public QThread
@@ -25,32 +24,36 @@ public:
QQueue<std::pair<std::string, cv::Mat>>imgQueue;
void run()
{
while (imgQueue.size() > 0 || priorityQueue.size() > 0)
while (true)
{
if (priorityQueue.size() > 0) {
mutex.lock();
std::pair<std::string, cv::Mat> data = priorityQueue.dequeue();
mutex.unlock();
qDebug() << "saving priority img " << QString::fromStdString(data.first);
cv::imwrite(data.first, data.second);
data.second.release();
QQueue<std::pair<std::string, cv::Mat>> localQueue;
// 优先处理 priorityQueue
{
QMutexLocker locker(&mutex);
if (!priorityQueue.isEmpty()) {
localQueue.swap(priorityQueue);
}
else if (!imgQueue.isEmpty()) {
localQueue.swap(imgQueue);
}
}
else if (imgQueue.size() > 0) {
mutex.lock();
std::pair<std::string, cv::Mat> data = imgQueue.dequeue();
mutex.unlock();
// 没有任务就跳出
if (localQueue.isEmpty()) {
break;
}
// 批量保存
while (!localQueue.isEmpty()) {
auto data = std::move(localQueue.dequeue());
qDebug() << "saving img " << QString::fromStdString(data.first);
if (data.first.find(".png") != std::string::npos){
cv::resize(data.second, data.second, cv::Size(), 0.25, 0.25);
cv::imwrite(data.first, data.second, compressionParams);
}
else {
cv::imwrite(data.first, data.second);
}
data.second.release();
cv::imwrite(data.first, data.second);
// 不需要手动 release(), cv::Mat 会自动析构
}
}
}
void addData(std::string str, cv::Mat& mat,type type_ = normal)
{
try
@@ -107,7 +110,8 @@ public:
std::string imgTypeDirStr;//二级目录,图片类型决定 sample "Result"
std::string dateDirStr;//三级目录,日期决定 sample"2024-6-8"
std::string hourDirStr;//四级目录,小时段决定 sample "14H"
std::string detailNameStr;//五级目录 主要是SN,如没有sn则可能是相机名称
std::string okNgStr;//五级目录,OK/NG决定 sample "OK"
std::string detailNameStr;//六级目录 主要是SN,如没有sn则可能是相机名称
#pragma region 赋值
//imgTypeDirStr
switch (type)
@@ -118,9 +122,6 @@ public:
case resImg:
imgTypeDirStr = "Result";
break;
case additionalSaveNgImg:
imgTypeDirStr = "NGIMG";
break;
default:
imgTypeDirStr = "error";
}
@@ -130,7 +131,10 @@ public:
dateDirStr = currentDateTime.toString("yyyy-MM-dd").toStdString();
hourDirStr = std::to_string(currentDateTime.time().hour()) + "H//";
}
if(data->aiDetOK == true && data->halconOK == true)
okNgStr = "OK";
else
okNgStr = "NG";
//detailNameStr
if ((data->SNcode).length() != 0)
detailNameStr = data->SNcode;
@@ -141,6 +145,7 @@ public:
imgTypeDirStr + "/" +
dateDirStr + "/" +
hourDirStr + "/" +
okNgStr + "/" +
detailNameStr + "/");
}
std::vector<std::string> genFileNames(std::shared_ptr <detData> data, imgSaveThreadType type, std::string format = "")
@@ -173,22 +178,6 @@ public:
for (int i = 0; i < data->clsOriginImgs.size(); i++)
resultFileNames.push_back(fileName + "CLS_RES" + getCurrentDateTime() + "_" + data->clsOriginImgs[i].first + "_Count" + std::to_string(i) + ".bmp");
break;
case additionalSaveNgImg:
if (data->aiDetOK == false || data->halconOK == false)
{
for (int i = 0; i < data->segOriginImgs.size(); i++)
resultFileNames.push_back(fileName + "NGIMG_segOriginImgs_" + getCurrentDateTime() + "_" + std::to_string(i) + ".png");
for (int i = 0; i < data->oriImgs.size(); i++)
{
if(data->oriImgs[i].depth() == 2)
resultFileNames.push_back(fileName + "NGIMG_oriImgs_" + getCurrentDateTime() + "_" + std::to_string(i) + ".tiff");
else
resultFileNames.push_back(fileName + "NGIMG_oriImgs_" + getCurrentDateTime() + "_" + std::to_string(i) + ".png");
}
for (int i = 0; i < data->resultImgs.size(); i++)
resultFileNames.push_back(fileName + "NGIMG_resultImgs_" + getCurrentDateTime() + "_" + std::to_string(i) + ".jpg");
}
break;
}
return resultFileNames;
}
@@ -211,44 +200,39 @@ public:
//结果图保存
std::vector<std::string>resFileNames = genFileNames(data, resImg);
for (int index = 0; index < resFileNames.size(); index++)
{
saveThread.addData(fileSavePath + resFileNames[index], data->resultImgs[index], imgSaveThread::priority);
}
//seg
std::string segAndClsPath = fileSavePath + "detImgs//" + getCurrentDateTime() + "//";
std::vector<std::string>segFileNames = genFileNames(data, segImg);
if (segFileNames.size() > 0)
createDirectoryIfNotExists(segAndClsPath);//不存在此文件夹则创建
for (int index = 0; index < segFileNames.size(); index++)
saveThread.addData(segAndClsPath + segFileNames[index], data->segOriginImgs[index]);
saveThread.addData(fileSavePath + segFileNames[index], data->segOriginImgs[index]);
//cls
std::vector<std::string>clsFileNames = genFileNames(data, clsImg);
for (int index = 0; index < clsFileNames.size(); index++)
saveThread.addData(segAndClsPath + clsFileNames[index], data->clsOriginImgs[index].second);
saveThread.addData(fileSavePath + clsFileNames[index], data->clsOriginImgs[index].second);
//额外储存NG文件夹
std::string additionalSaveNgImgPath = genDirName(data, additionalSaveNgImg);
std::vector<std::string>additionalSaveNgImgNames = genFileNames(data, additionalSaveNgImg);
if (additionalSaveNgImgNames.size() > 0)
createDirectoryIfNotExists(additionalSaveNgImgPath);//不存在此文件夹则创建
int additionalSaveNgImgNamesIndex = 0;
for (int index = 0; index < data->segOriginImgs.size()&& additionalSaveNgImgNames.size() > additionalSaveNgImgNamesIndex; index++)
{
saveThread.addData(additionalSaveNgImgPath + additionalSaveNgImgNames[additionalSaveNgImgNamesIndex], data->segOriginImgs[index]);
additionalSaveNgImgNamesIndex++;
}
for (int index = 0; index < data->oriImgs.size() && additionalSaveNgImgNames.size() > additionalSaveNgImgNamesIndex; index++)
{
saveThread.addData(additionalSaveNgImgPath + additionalSaveNgImgNames[additionalSaveNgImgNamesIndex], data->oriImgs[index]);
additionalSaveNgImgNamesIndex++;
}
for (int index = 0; index < data->resultImgs.size() && additionalSaveNgImgNames.size() > additionalSaveNgImgNamesIndex; index++)
{
saveThread.addData(additionalSaveNgImgPath + additionalSaveNgImgNames[additionalSaveNgImgNamesIndex], data->resultImgs[index]);
additionalSaveNgImgNamesIndex++;
}
//std::string additionalSaveNgImgPath = genDirName(data, additionalSaveNgImg);
//std::vector<std::string>additionalSaveNgImgNames = genFileNames(data, additionalSaveNgImg);
//if (additionalSaveNgImgNames.size() > 0)
// createDirectoryIfNotExists(additionalSaveNgImgPath);//不存在此文件夹则创建
//int additionalSaveNgImgNamesIndex = 0;
//for (int index = 0; index < data->segOriginImgs.size()&& additionalSaveNgImgNames.size() > additionalSaveNgImgNamesIndex; index++)
//{
// saveThread.addData(additionalSaveNgImgPath + additionalSaveNgImgNames[additionalSaveNgImgNamesIndex], data->segOriginImgs[index]);
// additionalSaveNgImgNamesIndex++;
//}
//for (int index = 0; index < data->oriImgs.size() && additionalSaveNgImgNames.size() > additionalSaveNgImgNamesIndex; index++)
//{
// saveThread.addData(additionalSaveNgImgPath + additionalSaveNgImgNames[additionalSaveNgImgNamesIndex], data->oriImgs[index]);
// additionalSaveNgImgNamesIndex++;
//}
//for (int index = 0; index < data->resultImgs.size() && additionalSaveNgImgNames.size() > additionalSaveNgImgNamesIndex; index++)
//{
// saveThread.addData(additionalSaveNgImgPath + additionalSaveNgImgNames[additionalSaveNgImgNamesIndex], data->resultImgs[index]);
// additionalSaveNgImgNamesIndex++;
//}
}
private:
std::string path = "";
+1 -1
View File
@@ -208,7 +208,7 @@ public:
{
if (checkTrigger(callback.triggerAddress, callback.triggerValue, byteArray) == true)
{
std::cout << "func:" << callback.funcName << "->triggered" << std::endl;
qDebug() << "func:" << QString::fromStdString(callback.funcName) << "->triggered";
std::thread([callback, byteArray]() mutable {
try {
callback.func(byteArray); // 执行回调函数
+56 -13
View File
@@ -16,11 +16,40 @@ public:
detCallbackChain(imgSaveThreadManager* imgSaveThreadManager = nullptr,
handleAiModelsTemplate* _handleAiModelsIn = nullptr)
: _imgSaveThreadManager(imgSaveThreadManager), _handleAiModels(_handleAiModelsIn) {
int threadCount = 2 * QThread::idealThreadCount();
QThreadPool::globalInstance()->setMaxThreadCount(threadCount);
}
void ansyncProcess(std::shared_ptr <detData> data) {
QtConcurrent::run([this, data]() {
#pragma region 方法1 较慢
QFuture<void> future = QtConcurrent::run([this, data]() {
process(data);
});
#pragma endregion
#pragma region 方法2 较慢 安全
//QThread* thread = new QThread;
//QObject::connect(thread, &QThread::started, [this, data]() {
// process(data);
// });
//QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);
//thread->start();
//thread->setPriority(QThread::TimeCriticalPriority);
#pragma endregion
#pragma region 方法3 不安全
/* std::async(std::launch::async, [this, data]() {
process(data);
});*/
#pragma endregion
#pragma region 方法4
//std::thread([this, data]() {
// process(data);
// }).detach();
#pragma endregion
#pragma region 方法5
//QThreadPool::globalInstance()->start([this, data]() {
// process(data);
// });
#pragma endregion
}
void process(std::shared_ptr <detData> data) {
@@ -28,11 +57,13 @@ public:
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
//等待图片满足要求后,储存原图,异步执行算法函数
std::async(std::launch::async, &imgSaveThreadManager::saveOri, _imgSaveThreadManager, data);
algoEvaluate(data, _handleAiModels);
//执行完毕后异步获取储存使用结果
resultHandle(data);
// 确保线程安全退出
qDebug() << "Processing finished for data with UUID:" << data->uuid;
QThread::currentThread()->quit();
}
bool algoEvaluate(std::shared_ptr <detData> data, handleAiModelsTemplate* model) {
@@ -67,28 +98,39 @@ public:
}
void resultHandle(std::shared_ptr <detData> data){
for (auto func : resultHandleCallbacks)
func(data);
detectionResultHandle(data);
std::shared_ptr <detData> dataPtr = data;
detDataManager* dManager = data->dManager;
data->dManager->deleteDetData(data->uuid);
try {
detectionResultHandle(data);
for (auto func : resultHandleCallbacks)
func(data);
}
catch (const std::exception& e)
{
std::cout << "Caught exception: " << e.what() << std::endl;
qDebug() << "Caught exception: " << e.what();
}
catch (...) {
qDebug() << "Caught exception: ";
}
// 删除数据释放资源
}
// 通用的检测结果处理
void detectionResultHandle(std::shared_ptr<detData> data) {
//计算处理总耗时(CT)
QString totalCtStr = QString::fromStdString(data->SNcode) + QString::fromStdString(data->cameraKeyName) + "\n";
totalCtStr += "algoCT->" + QString::number(data->algoTime) + "ms";
QString totalCtStr = "algoCT->" + QString::number(data->algoTime) + "ms";
qDebug() << totalCtStr;
std::cout << totalCtStr.toStdString() << std::endl;
//std::cout << totalCtStr.toStdString() << std::endl;
// 将耗时数据保存入数据库或日志
// data->sqlVec.push_back({ "SN", data->SNcode });
// data->sqlVec.push_back({ "totalCt", std::to_string(totalCt.count()) + "ms" });
// 异步保存检测图像
std::async(std::launch::async, &imgSaveThreadManager::saveOri, _imgSaveThreadManager, data);
std::async(std::launch::async, &imgSaveThreadManager::saveRes, _imgSaveThreadManager, data);
// 删除数据释放资源
detDataManager* dManager = data->dManager;
data->dManager->deleteDetData(data->uuid);
}
#pragma region 注册回调函数
@@ -107,5 +149,6 @@ private:
std::vector< resultHandleCallback>resultHandleCallbacks;
processAlgoCallback _processAlgoCallback;
//std::vector<QFuture<void>> futures; // 用于存储异步处理的结果
};
#pragma once
+106 -113
View File
@@ -17,136 +17,129 @@
#include <QDate>
#include <QString>
#include <qline>
class logWidget :public QWidget
{
//行数上限
const int MAX_LOGWIDGET_LINES = 1000;
class logWidget : public QWidget {
public:
enum logType
{
stdConsle,
qtConsle
};
QVBoxLayout* Layout;
QHBoxLayout* btnLayout;
std::vector<gradientButton*>btns;
QLabel* icon, * Title;
QStackedWidget* widgets;
QTextEdit stdConsoleOutput;
QTextEdit qtConsoleOutput;
logWidget()
{
QPalette palette;
palette.setColor(QPalette::WindowText, Qt::white);
QFont font("微软雅黑", 24, QFont::Bold);
enum logType {
stdConsle,
qtConsle
};
QVBoxLayout* Layout;
QHBoxLayout* btnLayout;
std::vector<gradientButton*> btns;
QLabel* icon, * Title;
QStackedWidget* widgets;
QPlainTextEdit stdConsoleOutput;
QPlainTextEdit qtConsoleOutput;
widgets = new QStackedWidget();
widgets->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
widgets->setMaximumSize(9999, 9999);
logWidget() {
QPalette palette;
palette.setColor(QPalette::WindowText, Qt::white);
QFont font("微软雅黑", 24, QFont::Bold);
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
this->setMaximumSize(9999, 9999);
this->setObjectName("configSettingWidget");
//this->setStyleSheet(QString("QWidget {background-color: rgb(%1)}").arg(sColor_Gold));
//this->showMaximized();
Layout = new QVBoxLayout(this);
Layout->setContentsMargins(0, 0, 0, 0);
Layout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
widgets = new QStackedWidget();
widgets->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
Title = new QLabel(u8"日志");
Title->setFont(font);
Title->setPalette(palette);
Title->setAlignment(Qt::AlignLeft);
Layout->addWidget(Title);
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
this->setObjectName("configSettingWidget");
btnLayout = new QHBoxLayout();
btnLayout->setContentsMargins(0, 0, 0, 0);
btnLayout->setAlignment(Qt::AlignLeft);
Layout = new QVBoxLayout(this);
Layout->setContentsMargins(0, 0, 0, 0);
Layout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
Layout->addLayout(btnLayout);
Title = new QLabel(u8"日志");
Title->setFont(font);
Title->setPalette(palette);
Title->setAlignment(Qt::AlignLeft);
Layout->addWidget(Title);
stdConsoleOutput.setReadOnly(true);
qtConsoleOutput.setReadOnly(true);
addLogWidget(u8"控制台", &stdConsoleOutput, logType::stdConsle);
addLogWidget(u8"QT日志", &qtConsoleOutput, logType::qtConsle);
btns[0]->pressed();
btnLayout = new QHBoxLayout();
btnLayout->setContentsMargins(0, 0, 0, 0);
btnLayout->setAlignment(Qt::AlignLeft);
Layout->addLayout(btnLayout);
Layout->addWidget(widgets);
}
void addLogWidget(QString btnText,QTextEdit* textWidget, logType type)
{
QPalette palette;
palette.setColor(QPalette::WindowText, Qt::white);
QFont font("微软雅黑", 13, QFont::Bold);
QFont font2("微软雅黑", 8);
QFont font3("微软雅黑", 16, QFont::Bold);
stdConsoleOutput.setReadOnly(true);
qtConsoleOutput.setReadOnly(true);
stdConsoleOutput.setMaximumBlockCount(MAX_LOGWIDGET_LINES);
qtConsoleOutput.setMaximumBlockCount(MAX_LOGWIDGET_LINES);
stdConsoleOutput.setStyleSheet("background-color: rgb(30,30,30); color: white;");
qtConsoleOutput.setStyleSheet("background-color: rgb(30,30,30); color: white;");
//切换配置页面
int index = btns.size();
gradientButton* btn = new gradientButton(160, 50, btnText, "");
btnLayout->addWidget(btn);
btns.push_back(btn);
connect(btn, &QPushButton::clicked, [=]()
{
for (auto btnPtr : btns)
btnPtr->toDefault();
btn->pressed();
widgets->setCurrentIndex(index);
});
addLogWidget(u8"控制台", &stdConsoleOutput, logType::stdConsle);
addLogWidget(u8"QT日志", &qtConsoleOutput, logType::qtConsle);
btns[0]->pressed();
//页面widget
QWidget* widget = new QWidget();
widgets->addWidget(widget);
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
Layout->addWidget(widgets);
}
QVBoxLayout* widgetLayout = new QVBoxLayout(widget);
widgetLayout->setContentsMargins(0, 0, 0, 0);
widgetLayout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
void addLogWidget(QString btnText, QPlainTextEdit* textWidget, logType type) {
QPalette palette;
palette.setColor(QPalette::WindowText, Qt::white);
QFont font2("微软雅黑", 8);
QHBoxLayout* toolHLayout = new QHBoxLayout();
widgetLayout->addLayout(toolHLayout);
int index = btns.size();
gradientButton* btn = new gradientButton(160, 50, btnText, "");
btnLayout->addWidget(btn);
btns.push_back(btn);
connect(btn, &QPushButton::clicked, [=]() {
for (auto btnPtr : btns)
btnPtr->toDefault();
btn->pressed();
widgets->setCurrentIndex(index);
});
QLabel* toolName = new QLabel(u8"过滤器");
toolName->setFont(font2);
toolName->setPalette(palette);
toolHLayout->addWidget(toolName);
QWidget* widget = new QWidget();
widgets->addWidget(widget);
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QStringList options = { "Debug","Info","Warning" };
QComboBox* filterSelector = new QComboBox();
filterSelector->addItems(options);
toolHLayout->addWidget(filterSelector);
QVBoxLayout* widgetLayout = new QVBoxLayout(widget);
widgetLayout->setContentsMargins(0, 0, 0, 0);
widgetLayout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
QLabel* toolName2 = new QLabel(u8" 正则匹配");
toolName2->setFont(font2);
toolName2->setPalette(palette);
toolHLayout->addWidget(toolName2);
QHBoxLayout* toolHLayout = new QHBoxLayout();
widgetLayout->addLayout(toolHLayout);
QLineEdit* lineedit = new QLineEdit();
toolHLayout->addWidget(lineedit);
QLabel* toolName = new QLabel(u8"过滤器");
toolName->setFont(font2);
toolName->setPalette(palette);
toolHLayout->addWidget(toolName);
QStringList options = { "Debug","Info","Warning" };
QComboBox* filterSelector = new QComboBox();
filterSelector->addItems(options);
toolHLayout->addWidget(filterSelector);
QLabel* toolName2 = new QLabel(u8" 正则匹配");
toolName2->setFont(font2);
toolName2->setPalette(palette);
toolHLayout->addWidget(toolName2);
QLineEdit* lineedit = new QLineEdit();
toolHLayout->addWidget(lineedit);
widgetLayout->addWidget(textWidget);
}
QString getCurrentDate() {
return QDate::currentDate().toString("yyyy-MM-dd");
}
QString getCurrentTime() {
return QTime::currentTime().toString("HH:mm:ss.zzz");
}
widgetLayout->addWidget(textWidget);
textWidget->setStyleSheet("background-color: rgb(30,30,30);");
}
QString getCurrentDate() {
QDate currentDate = QDate::currentDate();
return currentDate.toString("yyyy-MM-dd");
}
QString getCurrentTime() {
QTime currentTime = QTime::currentTime();
return currentTime.toString("HH:mm:ss.zzz");
}
public slots:
void recvStdLogMsg(QString logMsg)
{
QString text = "<span style='color: yellow;'>" + getCurrentDate() + "</span> "
"<span style='color: yellow;'>" + getCurrentTime() + "</span> "
"<span style='color: white;'>" + logMsg + "</span> ";
stdConsoleOutput.append(text);
}
void recvQtLogMsg(QString logMsg)
{
QString text = "<span style='color: yellow;'>" + getCurrentDate() + "</span> "
"<span style='color: yellow;'>" + getCurrentTime() + "</span> "
"<span style='color: white;'>" + logMsg + "</span> ";
qtConsoleOutput.append(text);
}
void recvStdLogMsg(QString logMsg) {
QString text = getCurrentDate() + " " + getCurrentTime() + " " + logMsg;
stdConsoleOutput.appendPlainText(text);
}
void recvQtLogMsg(QString logMsg) {
QString text = getCurrentDate() + " " + getCurrentTime() + " " + logMsg;
qtConsoleOutput.appendPlainText(text);
}
};
#pragma once
@@ -19,8 +19,8 @@ public:
m_plot(new QCustomPlot(this))
{
QString title = QString::fromStdString(json.value("key", "默认标题"));
double limitHigh = json.value("limitHigh", 100.0);
double limitLow = json.value("limitLow", 0.0);
m_limitHigh = json.value("limitHigh", 100.0);
m_limitLow = json.value("limitLow", 0.0);
m_maxPoints = json.value("maxPoints", 50);
QFont font("微软雅黑", 24, QFont::Bold);
@@ -40,29 +40,81 @@ public:
m_mainLayout->addWidget(m_plot);
m_plot->setBackground(Qt::transparent);
// 主蓝色曲线
m_plot->addGraph();
m_plot->graph(0)->setPen(QPen(Qt::blue, 2));
m_plot->graph(0)->setScatterStyle(QCPScatterStyle::ssNone);
m_plot->yAxis->setRange(-1,3);
addLimitLines(limitHigh, limitLow);
// 新增红色点图层
m_plot->addGraph();
m_plot->graph(1)->setLineStyle(QCPGraph::lsNone);
m_plot->graph(1)->setScatterStyle(
QCPScatterStyle(QCPScatterStyle::ssDisc, QPen(Qt::red), QBrush(Qt::red), 6)
);
m_plot->xAxis->setBasePen(QPen(Qt::white, 2)); // 坐标轴线
m_plot->yAxis->setBasePen(QPen(Qt::white, 2));
m_plot->xAxis->setTickPen(QPen(Qt::white)); // 刻度线
m_plot->yAxis->setTickPen(QPen(Qt::white));
m_plot->xAxis->setSubTickPen(QPen(Qt::white)); // 次刻度
m_plot->yAxis->setSubTickPen(QPen(Qt::white));
m_plot->xAxis->setTickLabelColor(Qt::white); // 数字标签
m_plot->yAxis->setTickLabelColor(Qt::white);
m_plot->xAxis->setLabelColor(Qt::white); // "时间" / "数值" 文字
m_plot->yAxis->setLabelColor(Qt::white);
m_plot->yAxis->setRange(m_limitLow - 1, m_limitHigh + 1);
addLimitLines(m_limitHigh, m_limitLow);
}
void appendData(double value) {
m_xData.append(m_timeCounter);
m_yData.append(value);
// 如果超限,添加到红点数据并添加文本
if (value > m_limitHigh || value < m_limitLow) {
m_xOverLimit.append(m_timeCounter);
m_yOverLimit.append(value);
auto* textItem = new QCPItemText(m_plot);
textItem->setPositionAlignment(Qt::AlignLeft | Qt::AlignVCenter);
textItem->position->setType(QCPItemPosition::ptPlotCoords);
textItem->position->setCoords(m_timeCounter, value);
textItem->setText(QString::number(value, 'f', 2));
textItem->setColor(Qt::yellow);
textItem->setFont(QFont("微软雅黑", 8, QFont::Bold));
m_textItems.append(textItem);
}
++m_timeCounter;
// 保持窗口大小
if (m_xData.size() > m_maxPoints) {
m_xData.removeFirst();
m_yData.removeFirst();
}
if (m_xOverLimit.size() > m_maxPoints) {
m_xOverLimit.removeFirst();
m_yOverLimit.removeFirst();
}
// 清理超出窗口范围的文本
while (!m_textItems.isEmpty() && m_textItems.first()->position->key() < m_timeCounter - m_maxPoints) {
m_plot->removeItem(m_textItems.first());
m_textItems.removeFirst();
}
m_plot->graph(0)->setData(m_xData, m_yData);
m_plot->graph(1)->setData(m_xOverLimit, m_yOverLimit);
m_plot->xAxis->setRange(qMax(0.0, m_timeCounter - m_maxPoints), m_timeCounter);
m_plot->replot();
}
protected:
void contextMenuEvent(QContextMenuEvent* event) override {
QMenu menu(this);
@@ -84,20 +136,31 @@ private slots:
private:
void applyJsonParams() {
m_maxPoints = m_json.value("maxPoints", m_maxPoints);
m_limitHigh = m_json.value("limitHigh", m_limitHigh);
m_limitLow = m_json.value("limitLow", m_limitLow);
m_title->setText(QString::fromStdString(m_json.value("key", m_title->text().toStdString())));
m_plot->clearItems();
addLimitLines(m_json.value("limitHigh", 100.0), m_json.value("limitLow", 0.0));
addLimitLines(m_limitHigh, m_limitLow);
// 更新坐标范围
m_plot->yAxis->setRange(m_limitLow - 2, m_limitHigh + 2);
// 清空超限数据
m_xOverLimit.clear();
m_yOverLimit.clear();
m_plot->replot();
}
void addLimitLines(double high, double low) {
auto* line1 = new QCPItemStraightLine(m_plot);
line1->setPen(QPen(Qt::red, 3, Qt::DashLine));
line1->setPen(QPen(Qt::green, 1, Qt::DashLine));
line1->point1->setCoords(0, high);
line1->point2->setCoords(1, high);
auto* line2 = new QCPItemStraightLine(m_plot);
line2->setPen(QPen(Qt::red, 3, Qt::DashLine));
line2->setPen(QPen(Qt::green, 1, Qt::DashLine));
line2->point1->setCoords(0, low);
line2->point2->setCoords(1, low);
}
@@ -106,12 +169,15 @@ private:
QVBoxLayout* m_mainLayout;
QLabel* m_title;
QCustomPlot* m_plot;
QList<QCPItemText*> m_textItems;
QVector<double> m_xData, m_yData;
QVector<double> m_xOverLimit, m_yOverLimit; // 新增用于红色点
int m_maxPoints = 50;
double m_timeCounter = 0;
double m_limitHigh = -1, m_limitLow = 2;
};
class SummuaryDataPage :public QWidget {
Q_OBJECT
public:
-1
View File
@@ -35,5 +35,4 @@ logService::~logService()
{
delete _stdConsoleRedirector;
delete _qtRediretor;
spdlog::shutdown();
}
+10 -14
View File
@@ -5,40 +5,36 @@
#include <spdlog/async.h>
#include <spdlog/async_logger.h>
#include <spdlog/sinks/daily_file_sink.h>
#define LOG_DEBUG(logger, msg) \
(logger).LogDebug((msg), __FILE__, __LINE__);
class SpdLogger {
public:
SpdLogger(const std::string& file_path, const std::string& file_name) {
SpdLogger(std::string& file_path, std::string file_name) {
try {
// 使用同步的 daily_logger_st
logger_ = spdlog::daily_logger_st(
file_name, file_path + "/" + file_name + ".log", 0, 0);
logger_->set_level(spdlog::level::debug);
spdlog::flush_every(std::chrono::seconds(1));
spdlog::init_thread_pool(8192, 5); // 初始化线程池
logger_ = spdlog::daily_logger_mt<spdlog::async_factory>(
file_name, file_path + "/" + file_name + ".log", 0, 0); // 日志按天保存
logger_->set_level(spdlog::level::debug); // 设置日志级别为 Debug
spdlog::flush_every(std::chrono::seconds(1));//每秒写入一次
logger_->set_pattern("[%Y-%m-%d %H:%M:%S] [Thread %t] [%l] %v");
}
catch (const std::exception& ex) {
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
void LogDebug(const std::string& msg) {
if (logger_) {
logger_->debug(msg);
}
}
~SpdLogger() {
// 不再需要显式调用 shutdown(),因为使用的是同步模式
~SpdLogger()
{
spdlog::shutdown();
}
private:
std::shared_ptr<spdlog::logger> logger_;
std::shared_ptr<spdlog::logger> logger_; // 日志器实例
};
#pragma once
+65 -75
View File
@@ -42,45 +42,46 @@ public:
#include <hdevengine/HDevEngineCpp.h>
#include <opencvPaintAlgo.hpp>
using namespace HDevEngineCpp;
static bool _952_15_H_25D_ALGO_HuaShangAI(cv::Mat& img, handleAIModels* _handleAiModels, cv::Mat& Paint, QMutex& paintMutex) {
static bool _952_15_H_25D_ALGO_HuaShangAI(std::shared_ptr <detData> data,cv::Mat& img, handleAIModels* _handleAiModels, cv::Mat& Paint, QMutex& paintMutex) {
cv::Mat segImg = ~_handleAiModels->SEG_25D->Evaluate(img);
std::vector<std::vector<cv::Point>> contours;
cv::findContours(segImg, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
bool isNg = false;
bool isOK = true;
for (int i = 0; i < contours.size(); i++) {
cv::Rect rect = cv::boundingRect(contours[i]);
if (rect.width < _handleAiModels->handleAI_WIDTH || rect.height < _handleAiModels->handleAI_HEIGHT) continue; // 过滤掉小轮廓
if (rect.width < _handleAiModels->handleAI_WIDTH && rect.height < _handleAiModels->handleAI_HEIGHT) continue; // 过滤掉小轮廓
auto clsImgs = cutImg2ClsVec(rect, img);
bool clsIsNg = false;
for (auto& clsImg : clsImgs) {
int clsResult = _handleAiModels->CLS_25D->Evaluate(clsImg);
if (clsResult == 1) { // 假设1表示NG
clsIsNg = true;
break;
data->clsOriginImgs.push_back({ std::to_string(i),clsImg });
}
}
cv::Scalar color = cv::Scalar(0, 255, 0);
if (clsIsNg == true) {
color = cv::Scalar(0, 0, 255);
isNg = true;
cv::approxPolyDP(contours[i], contours[i], 3, true); // 多边形拟合
QMutexLocker locker(&paintMutex);
isOK = true;
cv::Mat imgTmp;
cv::cvtColor(img(rect), imgTmp, cv::COLOR_GRAY2BGR);
imgTmp.copyTo(Paint(rect));
QMutexLocker locker(&paintMutex);
//imgTmp.copyTo(Paint(rect));
cv::drawContours(Paint, contours, i, color, 2);
cv::putText(Paint, "NG"+std::to_string(i), cv::Point(rect.x + 10, rect.y - 20), cv::FONT_HERSHEY_SIMPLEX, 0.8, color, 2);
}
else {
QMutexLocker locker(&paintMutex);
cv::Mat imgTmp;
cv::cvtColor(img(rect), imgTmp, cv::COLOR_GRAY2BGR);
QMutexLocker locker(&paintMutex);
imgTmp.copyTo(Paint(rect));
cv::rectangle(Paint, rect, color, 3);
}
putTextZH(Paint, "NG", cv::Point(rect.x + 10, rect.y - 20), 25, color);
//putTextZH(Paint, "NG", cv::Point(rect.x + 10, rect.y - 20), 25, color);
}
return isNg;
return isOK;
}
static bool _952_15_H_Algo(std::shared_ptr <detData> data, handleAIModels* _handleAIModels)
@@ -103,63 +104,59 @@ static bool _952_15_H_Algo(std::shared_ptr <detData> data, handleAIModels* _hand
cv::Mat src1 = data->oriImgs[1];
cv::Mat src2 = data->oriImgs[0];
cv::Mat src3 = data->oriImgs[2];
data->oriImgs[1].copyTo(Paint);
if (Paint.channels() != 3)
cv::cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
cv::cvtColor(src2, Paint, cv::COLOR_GRAY2BGR);
else
src2.copyTo(Paint);
QMutex paintMutex;
std::future <bool> future = std::async(std::launch::async, _952_15_H_25D_ALGO_HuaShangAI, data->oriImgs[2], _handleAIModels, std::ref(Paint), std::ref(paintMutex));
HObject in_Image1 = MatToHObject(src1);
HObject in_Image2 = MatToHObject(src2);
HObject in_Image3 = MatToHObject(src3);
procedureCall.SetInputIconicParamObject("in_Image1", in_Image1);
procedureCall.SetInputIconicParamObject("in_Image2", in_Image2);
procedureCall.SetInputIconicParamObject("in_Image3", in_Image3);
procedureCall.SetInputCtrlParamTuple("in_xResolution", HTuple(_handleAIModels->in_xResolution));
procedureCall.SetInputCtrlParamTuple("in_yResolution", HTuple(_handleAIModels->in_yResolution));
procedureCall.Execute();
std::future <bool> future = std::async(std::launch::async, _952_15_H_25D_ALGO_HuaShangAI, data, data->oriImgs[2], _handleAIModels, std::ref(Paint), std::ref(paintMutex));
HTuple out_Distance, out_ResultRows, out_ResultCols, out_Flag, out_LinePonit;
{
HObject in_Image1 = MatToHObject(src1);
HObject in_Image2 = MatToHObject(src2);
HObject in_Image3 = MatToHObject(src3);
procedureCall.SetInputIconicParamObject("in_Image1", in_Image1);
procedureCall.SetInputIconicParamObject("in_Image2", in_Image2);
procedureCall.SetInputIconicParamObject("in_Image3", in_Image3);
procedureCall.SetInputCtrlParamTuple("in_xResolution", HTuple(_handleAIModels->in_xResolution));
procedureCall.SetInputCtrlParamTuple("in_yResolution", HTuple(_handleAIModels->in_yResolution));
procedureCall.Execute();
out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance");
//out_RightDistance = procedureCall.GetOutputCtrlParamTuple("out_RightDistance");
out_ResultRows = procedureCall.GetOutputCtrlParamTuple("out_ResultRows");
out_ResultCols = procedureCall.GetOutputCtrlParamTuple("out_ResultCols");
out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance");
//out_RightDistance = procedureCall.GetOutputCtrlParamTuple("out_RightDistance");
out_ResultRows = procedureCall.GetOutputCtrlParamTuple("out_ResultRows");
out_ResultCols = procedureCall.GetOutputCtrlParamTuple("out_ResultCols");
//out_Angle = procedureCall.GetOutputCtrlParamTuple("out_Angle");
out_LinePonit = procedureCall.GetOutputCtrlParamTuple("out_LinePonit");
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");
//out_Angle = procedureCall.GetOutputCtrlParamTuple("out_Angle");
out_LinePonit = procedureCall.GetOutputCtrlParamTuple("out_LinePonit");
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");
}
TextRendererZH textPainter(Paint.cols, Paint.rows, 150);
int algoFlag = out_Flag.D();
double LT_Distance = -1, RT_Distance = -1, LD_Distance = -1, RD_Distance = -1, L_Duiqidu = -1, R_Duiqidu = -1;
if (algoFlag == 1) // 算法OK
{
QMutexLocker locker(&paintMutex);
LT_Distance = out_Distance[0].D() + 0.86;//左上
putTextZH(Paint, "左上留白:" + std::to_string(LT_Distance), cv::Point(100, 200), 150, cv::Scalar(0, 255, 0));
RT_Distance = out_Distance[1].D() + 0.52;//右上
putTextZH(Paint, "右上留白:" + std::to_string(RT_Distance), cv::Point(100, 350), 150, cv::Scalar(0, 255, 0));
LD_Distance = out_Distance[2].D() + 0.86;//左下
putTextZH(Paint, "左下留白:" + std::to_string(LD_Distance), cv::Point(100, 500), 150, cv::Scalar(0, 255, 0));
RD_Distance = out_Distance[3].D() + 0.52;//右下
putTextZH(Paint, "右下留白:" + std::to_string(RD_Distance), cv::Point(100, 650), 150, cv::Scalar(0, 255, 0));
L_Duiqidu = std::abs(LT_Distance - LD_Distance);
R_Duiqidu = std::abs(RT_Distance - RD_Distance);
textPainter.putText(Paint, "左上留白:" + std::to_string(LT_Distance), cv::Point(0, 200), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "右上留白:" + std::to_string(RT_Distance), cv::Point(0, 350), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "左下留白:" + std::to_string(LD_Distance), cv::Point(0, 500), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "右下留白:" + std::to_string(RD_Distance), cv::Point(0, 650), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "左对齐度:" + std::to_string(L_Duiqidu), cv::Point(0, 800), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "右对齐度:" + std::to_string(R_Duiqidu), cv::Point(0, 950), cv::Scalar(0, 255, 0));
int outPointRowsLength = out_ResultRows.Length();
for (int i = 0; i < outPointRowsLength; i++)
Cross(Paint,
cv::Point(out_ResultCols[i].D(), out_ResultRows[i].D()),
3, 2, cv::Scalar(0, 0, 255));
//duiqidu = out_Angle.D();
L_Duiqidu = std::abs(LT_Distance - LD_Distance);
putTextZH(Paint, "左对齐度:" + std::to_string(L_Duiqidu), cv::Point(100, 800), 150, cv::Scalar(0, 255, 0));
R_Duiqidu = std::abs(RT_Distance - RD_Distance);
putTextZH(Paint, "右对齐度:" + std::to_string(R_Duiqidu), cv::Point(100, 950), 150, cv::Scalar(0, 255, 0));
int out_LinePonitLength = out_LinePonit.Length() / 4;
for (int i = 0; i < out_LinePonitLength; i++)
line(Paint,
@@ -171,18 +168,11 @@ static bool _952_15_H_Algo(std::shared_ptr <detData> data, handleAIModels* _hand
}
else // 算法异常
{
putTextZH(Paint, "留白算法NG",
cv::Point(100, 200), 200, cv::Scalar(0, 0, 255));
QMutexLocker locker(&paintMutex);
textPainter.putText(Paint, "留白算法NG", cv::Point(0, 200), cv::Scalar(0, 0, 255));
data->halconOK = false;
}
data->resultImgs.push_back(Paint);
//data->resultImgs.push_back(Paint);
// data->sqlVec.push_back({ "Gluewidth",std::to_string(Gluewidth) });
// data->sqlVec.push_back({ "_2dResult",std::to_string(result) });
// qDebug() << "[Debug]2D Data:" << "hv_out_Gluewidth ::" << QString::number(Gluewidth) << ",Result" << QString::number(result);
data->resultData.insert(std::make_pair("LT_Distance", LT_Distance));
data->resultData.insert(std::make_pair("RT_Distance", RT_Distance));
data->resultData.insert(std::make_pair("LD_Distance", LD_Distance));
@@ -191,13 +181,15 @@ static bool _952_15_H_Algo(std::shared_ptr <detData> data, handleAIModels* _hand
data->resultData.insert(std::make_pair("R_Duiqidu", R_Duiqidu));
bool futureResult = future.get();
if (futureResult) {
putTextZH(Paint, "模型检测结果: NG", cv::Point(100, 50), 200, cv::Scalar(0, 0, 255));
if (futureResult) {
textPainter.putText(Paint, "模型检测结果: NG", cv::Point(0, 50), cv::Scalar(0, 0, 255));
}
else {
putTextZH(Paint, "模型检测结果: OK", cv::Point(100, 50), 200, cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "模型检测结果: OK", cv::Point(0, 50), cv::Scalar(0, 255, 0));
}
data->resultData.insert(std::make_pair("aiResultIsNG", futureResult));
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); // 缩小结果图
data->resultImgs.push_back(Paint);
data->aiDetOK = futureResult; // 如果任一检测结果为NG,则整体结果为NG
@@ -247,11 +239,14 @@ public:
bridge = bridgeIn;
_serviceManager = _serviceManagerIN;
parseJson(_missionJson);
#pragma region 初始化外部参数
parseJson(_missionJson);
_handleAIModels.SEG_25D = _serviceManagerIN->_handleAiModelManager->getSegModel("SEG_25D");
_handleAIModels.CLS_25D = _serviceManagerIN->_handleAiModelManager->getClsModel("CLS_25D");
HDevEngineCpp::HDevEngine myEngine;
myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_952.hdpl");
#pragma endregion
#pragma region 获取相机
_25DCamera_1 = _serviceManager->_cameraManager->getCamera("25D-1");
if (_25DCamera_1 == nullptr) {
@@ -279,10 +274,7 @@ public:
HouDuan12ResultHandle(data);
}));
#pragma endregion
_handleAIModels.SEG_25D = _serviceManagerIN->_handleAiModelManager->getSegModel("SEG_25D");
_handleAIModels.CLS_25D = _serviceManagerIN->_handleAiModelManager->getClsModel("CLS_25D");
HDevEngineCpp::HDevEngine myEngine;
myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_952.hdpl");
return true;
}
//9200 1
@@ -295,18 +287,17 @@ public:
"2.5D-H-1",sn, 3, _25DCamera_1->config.oriSaveFormat);//创建数据包
_25DCamera_1->captureImage(data);//拍照
//data->oriImgs.push_back(cv::imread("I:\\952Code\\CODES\\7.07\\7.07\\baoMoHou\\yh\\2025-07-07-1106069567896\\2025-07-07-11060695678962.5D-H-1_10-57-28-51_Count0.bmp", -1));
//data->oriImgs.push_back(cv::imread("I:\\952Code\\CODES\\7.07\\7.07\\baoMoHou\\yh\\2025-07-07-1106069567896\\2025-07-07-11060695678962.5D-H-1_10-57-28-51_Count1.bmp", -1));
// data->oriImgs.push_back(cv::imread("I:\\952Code\\CODES\\7.07\\7.07\\baoMoHou\\yh\\2025-07-07-1106069567896\\2025-07-07-11060695678962.5D-H-1_10-57-28-51_Count1.bmp", -1));
//data->oriImgs.push_back(cv::imread("I:\\952Code\\CODES\\bm\\2025-07-08-09361133675272.5D-H-1_09-27-32-22_Count2.bmp", -1));
algo_liubai->ansyncProcess(data);//处理算法
if(houduan1SecondTime == false)
data->resultImgShowSet.push_back(new showImgPack("后段1-1", "结果图"));
else
data->resultImgShowSet.push_back(new showImgPack("后段1-2", "结果图"));
houduan1SecondTime = !houduan1SecondTime;
algo_liubai->ansyncProcess(data);//处理算法
qDebug() << "[ Station 10 ] " << QString::fromUtf8("2.5D-1 后段检测开始 uuid :") << data->uuid << "SN" << QString::fromStdString(sn);;
std::cout << "通道1 SN:" << sn << "检测开始" << std::endl;
}
//9600 1
@@ -319,16 +310,15 @@ public:
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
"2.5D-H-2", sn, 3, _25DCamera_2->config.oriSaveFormat);//创建数据包
_25DCamera_2->captureImage(data);//拍照
algo_liubai->ansyncProcess(data);//处理算法
if (houduan2SecondTime == false)
data->resultImgShowSet.push_back(new showImgPack("后段2-1", "结果图"));
else
data->resultImgShowSet.push_back(new showImgPack("后段2-2", "结果图"));
houduan2SecondTime = !houduan2SecondTime;
algo_liubai->ansyncProcess(data);//处理算法
qDebug() << "[ Station 10 ] " << QString::fromUtf8("2.5D-2 后段检测开始 uuid :") << data->uuid << "SN" << QString::fromStdString(sn);;
std::cout << "通道2 SN:" << sn << "检测开始" << std::endl;
}
void HouDuan12ResultHandle(std::shared_ptr <detData>data){
@@ -380,7 +370,7 @@ public:
else {
qDebug() << "[ Station 10 ] " << QString::fromUtf8("后段检测结果数据为空 SN:") << QString::fromStdString(data->SNcode);
}
std::cout << "SN:" << data->SNcode << "检测结束 结果获取完成" << std::endl;
qDebug() << "SN:" << QString::fromStdString(data->SNcode) << "检测结束 结果获取完成" ;
}
//9400 1 Summary1
@@ -67,10 +67,11 @@ bool Hd_VirualCamera::initParas(QByteArray&, nlohmann::json& json)
bool Hd_VirualCamera::run()//Èí´¥·¢
{
n_mutex->lock();
if (cameraName == "156112" || cameraName == "162762") {
if (cameraName == "25D-1" || cameraName == "25D-2") {
vector<cv::Mat> mats;
mats.push_back(cv::imread("H:\\testImg\\2.5D-H-1_16-00-14-38_Count0.bmp", -1));
mats.push_back(cv::imread("H:\\testImg\\2.5D-H-1_16-00-14-38_Count1.tiff", -1));
mats.push_back(cv::imread("I:\\952Code\\CODES\\16H\\A2250709-162941554918413\\A2250709-1629415549184132.5D-H-2_16-31-32-65_Count0.bmp", -1));
mats.push_back(cv::imread("I:\\952Code\\CODES\\16H\\A2250709-162941554918413\\A2250709-1629415549184132.5D-H-2_16-31-32-65_Count1.bmp", -1));
mats.push_back(cv::imread("I:\\952Code\\CODES\\16H\\A2250709-162941554918413\\A2250709-1629415549184132.5D-H-2_16-31-32-65_Count2.bmp", -1));
queuePic.enqueue(mats);
}
n_mutex->unlock();