diff --git a/include/generalJsonParsing.hpp b/include/generalJsonParsing.hpp index d416e7a..1962509 100644 --- a/include/generalJsonParsing.hpp +++ b/include/generalJsonParsing.hpp @@ -1,5 +1,6 @@ #include #include +#include // 读取json文件,不按顺序 static nlohmann::json readJsonFromPath(std::string path) diff --git a/include/global.h b/include/global.h index 9f029b3..0331dd3 100644 --- a/include/global.h +++ b/include/global.h @@ -8,7 +8,7 @@ #include #include #pragma execution_character_set("utf-8") -const std::string softwareVersion = "V20251029-2.1.0"; +const std::string softwareVersion = "20251108-2.1.8"; const std::string euiJsonVersion = "1.0.6"; #define globalDatabasePth "./sqlDatabase/eui_db.db" //全局数据库路径 #define saveImgEnable 1 diff --git a/include/pluginBase.h b/include/pluginBase.h deleted file mode 100644 index 54ab790..0000000 --- a/include/pluginBase.h +++ /dev/null @@ -1,28 +0,0 @@ - -class Event; -enum pluginState -{ - running, - stop -}; -class IPlugin { -public: - std::string name; - virtual ~IPlugin() {}; - virtual void onEvent(const Event& event) {}; - virtual void init() {}; - virtual bool start() { return true; }; - virtual bool stop() { return true; } - virtual pluginState getState() { return pluginState::running; }; -}; - -class Event { -public: - enum EventType { EVENT_TYPE_A, EVENT_TYPE_B }; - Event(EventType type, int data) : type(type), data(data) {} - EventType type; - int data; -}; - - -#pragma once \ No newline at end of file diff --git a/include/qtBridge.h b/include/qtBridge.h index f90ecd1..d5d4eaf 100644 --- a/include/qtBridge.h +++ b/include/qtBridge.h @@ -111,6 +111,7 @@ signals: void getCameraNames(std::vector* cameraNames); void getAllParams(std::vector>* params); void editParam(QString name, QVariant value); + void saveMissionJson(); private: explicit qtFuncBridge(QObject* parent = nullptr) : QObject(parent) {} ~qtFuncBridge() = default; diff --git a/include/simpleAlgo.h b/include/simpleAlgo.h index 4c5f090..2e15925 100644 --- a/include/simpleAlgo.h +++ b/include/simpleAlgo.h @@ -1,7 +1,11 @@ #include #include #include +#include #include +#include +#include +#include #pragma once using namespace HalconCpp; struct MatchResult { @@ -74,8 +78,42 @@ static cv::Rect findMaxAreaContour(cv::Mat src, int& indexReturn) return cv::boundingRect(contours[maxIndex]); } } -static cv::Mat cutImg2Cls(cv::Rect boundingBox, cv::Mat imgInput, cv::Size targetSize = cv::Size(128, 128)); -static cv::Mat cutImg2Cls(std::vector contour, cv::Mat imgInput, cv::Size targetSize = cv::Size(128, 128)); + +static cv::Mat cutImg2Cls(cv::Rect boundingBox, cv::Mat imgInput, cv::Size targetSize = cv::Size(128, 128)) +{ + if (boundingBox.width <= 0 || boundingBox.height <= 0 || imgInput.empty()) { + std::cerr << "Invalid bounding box or empty input image." << std::endl; + return cv::Mat(); + } + + // 以目标框中心为正方形中心,边长为 max(max(w,h),128) + const cv::Point mid(boundingBox.x + boundingBox.width / 2, boundingBox.y + boundingBox.height / 2); + const int sideLength = getMax(getMax(boundingBox.width, boundingBox.height), 128); + + // 期望在原图上的 ROI(可能越界) + cv::Rect expectRect(mid.x - sideLength / 2, mid.y - sideLength / 2, sideLength, sideLength); + + // 计算需要的边界填充(反射填充) + const int left = getMax(0, -expectRect.x); + const int top = getMax(0, -expectRect.y); + const int right = getMax(0, expectRect.x + expectRect.width - imgInput.cols); + const int bottom = getMax(0, expectRect.y + expectRect.height - imgInput.rows); + + cv::Mat padded; + if (left || top || right || bottom) { + cv::copyMakeBorder(imgInput, padded, top, bottom, left, right, cv::BORDER_REFLECT_101); + } else { + padded = imgInput; + } + + // 在填充后图像上的 ROI(保证不越界) + cv::Rect shifted(expectRect.x + left, expectRect.y + top, expectRect.width, expectRect.height); + + // 最终裁剪并缩放 + cv::Mat squareImage = padded(shifted).clone(); + cv::resize(squareImage, squareImage, targetSize); + return squareImage; +} static std::vector cutImg2ClsVec(cv::Rect boundingBox, cv::Mat imgInput, cv::Size targetSize = cv::Size(128, 128)) { @@ -86,97 +124,47 @@ static std::vector cutImg2ClsVec(cv::Rect boundingBox, cv::Mat imgInput return result; } - int minSide = getMin(boundingBox.width, boundingBox.height); - if (minSide == 0) { + const int w = boundingBox.width; + const int h = boundingBox.height; + const int minSide = getMin(w, h); + if (minSide <= 0) { std::cerr << "Bounding box has zero width or height." << std::endl; return result; } - int splitCount = getMax(1, getMax(boundingBox.width, boundingBox.height) / minSide); + // 沿长边切分为若干个 size=minSide 的方块,覆盖到末端且避免重复最后一块 + const bool splitHoriz = (w > h); // 横向长 -> 沿X方向切 + const int longSide = splitHoriz ? w : h; + const int step = minSide; + const int beginCoord = splitHoriz ? boundingBox.x : boundingBox.y; + const int endCoord = beginCoord + longSide; - if (splitCount > 2) { - if (boundingBox.width > boundingBox.height) { // 横向裁 - for (int i = 0; i < splitCount; i++) { - int x = boundingBox.x + boundingBox.height * i; - if (x + boundingBox.height > boundingBox.x + boundingBox.width) - break; - result.emplace_back(cutImg2Cls(cv::Rect(x, boundingBox.y, boundingBox.height, boundingBox.height), imgInput, targetSize)); - } - // 确保最右边包含 - result.emplace_back(cutImg2Cls(cv::Rect(boundingBox.x + boundingBox.width - boundingBox.height, boundingBox.y, boundingBox.height, boundingBox.height), imgInput, targetSize)); - } - else { // 纵向裁 - for (int i = 0; i < splitCount; i++) { - int y = boundingBox.y + boundingBox.width * i; - if (y + boundingBox.width > boundingBox.y + boundingBox.height) - break; - result.emplace_back(cutImg2Cls(cv::Rect(boundingBox.x, y, boundingBox.width, boundingBox.width), imgInput, targetSize)); - } - result.emplace_back(cutImg2Cls(cv::Rect(boundingBox.x, boundingBox.y + boundingBox.height - boundingBox.width, boundingBox.width, boundingBox.width), imgInput, targetSize)); - } + // 计算切块起点列表 + std::vector starts; + starts.reserve((longSide + step - 1) / step); + for (int s = beginCoord; s + step <= endCoord; s += step) { + starts.emplace_back(s); } - else { - result.emplace_back(cutImg2Cls(boundingBox, imgInput, targetSize)); + // 确保包含末端(避免遗漏),同时避免与最后一个重复 + const int lastStart = endCoord - step; + if (starts.empty() || starts.back() != lastStart) { + starts.emplace_back(lastStart); + } + + result.reserve(starts.size()); + if (splitHoriz) { + for (int x : starts) { + result.emplace_back(cutImg2Cls(cv::Rect(x, boundingBox.y, minSide, minSide), imgInput, targetSize)); + } + } else { + for (int y : starts) { + result.emplace_back(cutImg2Cls(cv::Rect(boundingBox.x, y, minSide, minSide), imgInput, targetSize)); + } } return result; } -static cv::Mat cutImg2Cls(std::vector contour, cv::Mat imgInput, cv::Size targetSize) -{ - if (contour.empty() || imgInput.empty()) { - std::cerr << "Empty contour or input image." << std::endl; - return cv::Mat(); - } - - cv::Rect boundingBox = cv::boundingRect(contour); - return cutImg2Cls(boundingBox, imgInput, targetSize); -} - -static cv::Mat cutImg2Cls(cv::Rect boundingBox, cv::Mat imgInput, cv::Size targetSize) -{ - if (boundingBox.width <= 0 || boundingBox.height <= 0 || imgInput.empty()) { - std::cerr << "Invalid bounding box or empty input image." << std::endl; - return cv::Mat(); - } - - cv::Point mid(boundingBox.x + boundingBox.width / 2, boundingBox.y + boundingBox.height / 2); - int sideLength = getMax(getMax(boundingBox.width, boundingBox.height), 128); - - // 生成一个空的正方形黑图 - cv::Mat squareImage(sideLength, sideLength, imgInput.type(), cv::Scalar(0, 0, 0)); - - // 从原图中取的期望矩形区域 - cv::Rect expectRect(mid.x - sideLength / 2, mid.y - sideLength / 2, sideLength, sideLength); - - int xOffset = 0; - int yOffset = 0; - - // 调整 expectRect 防止越界 - if (expectRect.x < 0) { - expectRect.width += expectRect.x; - xOffset -= expectRect.x; - expectRect.x = 0; - } - if (expectRect.y < 0) { - expectRect.height += expectRect.y; - yOffset -= expectRect.y; - expectRect.y = 0; - } - if (expectRect.x + expectRect.width > imgInput.cols) - expectRect.width = imgInput.cols - expectRect.x; - if (expectRect.y + expectRect.height > imgInput.rows) - expectRect.height = imgInput.rows - expectRect.y; - - if (expectRect.width <= 0 || expectRect.height <= 0) { - std::cerr << "Adjusted region is invalid after clipping." << std::endl; - return cv::Mat(); - } - - imgInput(expectRect).copyTo(squareImage(cv::Rect(xOffset, yOffset, expectRect.width, expectRect.height))); - cv::resize(squareImage, squareImage, targetSize); - return squareImage; -} static cv::Mat HObject2Mat(HObject& Hobj) //HObject类型转Mat类型 { HTuple htCh; @@ -765,3 +753,81 @@ static cv::Mat tiledImages(std::vector& imgs) } return showMat; }; + +/** + * 快速去噪函数 + * + * 说明: + * - 优先使用均值滤波(box filter)实现快速平滑; + * - 对明显的椒盐噪声可开启中值滤波(按通道处理,适用于8U/16U); + * - 指定较大核或需要可控平滑强度时,使用高斯滤波作为兜底。 + * + * 参数: + * - inputMat 输入图像(支持单通道/多通道); + * - outputMat 输出图像; + * - kernelSize 卷积核大小,必须为奇数且>=3(传偶数会自动+1); + * - sigma 高斯滤波标准差,<=0 表示走OpenCV自动推导; + * - useMedian 是否启用中值滤波(更抗椒盐噪声,速度较均值略慢)。 + */ +static void denoiseImage(const cv::Mat& inputMat, cv::Mat& outputMat, int kernelSize = 3, double sigma = 0.0, bool useMedian = false) +{ + if (inputMat.empty()) { + outputMat.release(); + return; + } + + int k = kernelSize; + if (k < 3) k = 3; // 最小有效核大小 + + if ((k & 1) == 0) { + ++k; // 转换为奇数核 + } + + // 快速路径(椒盐噪声):启用中值滤波;多通道按通道分别处理 + if (useMedian && (inputMat.depth() == CV_8U || inputMat.depth() == CV_16U)) { + if (inputMat.channels() == 1) { + cv::medianBlur(inputMat, outputMat, k); + return; + } else { + std::vector ch; + cv::split(inputMat, ch); + for (auto& c : ch) { + cv::medianBlur(c, c, k); + } + cv::merge(ch, outputMat); + return; + } + } + + // 默认快速路径:小核且未指定sigma时使用均值滤波(分离实现,速度快) + if (k <= 5 && sigma <= 0.0) { + cv::blur(inputMat, outputMat, cv::Size(k, k), cv::Point(-1, -1), cv::BORDER_DEFAULT); + return; + } + + // 兜底:使用可分离高斯滤波,适合较大核或需要指定平滑强度的场景 + const double sigmaChecked = getMax(0.0, sigma); + cv::GaussianBlur(inputMat, outputMat, cv::Size(k, k), sigmaChecked, sigmaChecked, cv::BORDER_DEFAULT); +} + +// 字符编码转换:GBK 编码的 std::string 转为 UTF-8 编码的 std::string(基于 Qt 5.14.x) +// 入参:gbkStr - GBK/GB2312/GB18030 字节序列(std::string 仅作为原始字节容器) +// 返回:UTF-8 编码的字节序列(std::string) +static inline std::string gbkToUtf8(const std::string& gbkStr) +{ + // 使用 Qt 的 QTextCodec 进行编码转换 + // 在 Windows 简体中文环境下,本地编码通常是 GBK/GB2312;此处显式指定 "GBK" + QTextCodec* codec = QTextCodec::codecForName("GBK"); + if (!codec) { + // 兜底:如果没有 GBK codec(极少见),退化为直接当作本地 8-bit 解码 + QString tmp = QString::fromLocal8Bit(gbkStr.data(), static_cast(gbkStr.size())); + QByteArray utf8 = tmp.toUtf8(); + return std::string(utf8.constData(), static_cast(utf8.size())); + } + + // 将 GBK 字节解码为 Unicode(QString) + QString unicode = codec->toUnicode(gbkStr.data(), static_cast(gbkStr.size())); + // 再编码为 UTF-8 + QByteArray utf8 = unicode.toUtf8(); + return std::string(utf8.constData(), static_cast(utf8.size())); +} diff --git a/include/simpleTools/windowsCtrl.hpp b/include/simpleTools/windowsCtrl.hpp index b3c40fc..f0b43f3 100644 --- a/include/simpleTools/windowsCtrl.hpp +++ b/include/simpleTools/windowsCtrl.hpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -258,4 +260,82 @@ static QIcon getFileIcon(const QString& filePath, const QSize& size) { QPixmap pixmap = icon.pixmap(size); return QIcon(pixmap); } + +static bool restartProgram(bool asAdmin = false, bool exitCurrent = true, int delayMs = 0) { + wchar_t exePath[MAX_PATH]; + if (GetModuleFileNameW(nullptr, exePath, MAX_PATH) == 0) { + return false; + } + + int argc = 0; + LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); + std::wstring params; + if (argv && argc > 1) { + for (int i = 1; i < argc; ++i) { + const wchar_t* arg = argv[i]; + bool needQuote = wcspbrk(arg, L" \t\"'") != nullptr; + if (i > 1) params.push_back(L' '); + if (needQuote) { + params.push_back(L'"'); + for (const wchar_t* p = arg; *p; ++p) { + if (*p == L'"') params.push_back(L'\\'), params.push_back(L'"'); + else params.push_back(*p); + } + params.push_back(L'"'); + } else { + params.append(arg); + } + } + } + if (argv) LocalFree(argv); + + if (delayMs <= 0) { + SHELLEXECUTEINFOW sei{}; + sei.cbSize = sizeof(sei); + sei.lpVerb = asAdmin ? L"runas" : L"open"; + sei.lpFile = exePath; + sei.lpParameters = params.empty() ? nullptr : params.c_str(); + sei.nShow = SW_SHOWNORMAL; + if (!ShellExecuteExW(&sei)) return false; + if (exitCurrent) ExitProcess(0); + return true; + } else { + std::wstring exeEsc; + for (const wchar_t* p = exePath; *p; ++p) { + if (*p == L'\'') exeEsc.push_back(L'\''); // duplicate single quote for PS literal + exeEsc.push_back(*p); + } + std::wstring argsEsc; + if (!params.empty()) { + for (const wchar_t* p = params.c_str(); *p; ++p) { + if (*p == L'\'') argsEsc.push_back(L'\''); + argsEsc.push_back(*p); + } + } + + std::wstring psParam = L"-NoProfile -WindowStyle Hidden -Command \"Wait-Process -Id "; + psParam += std::to_wstring(GetCurrentProcessId()); + psParam += L"; Start-Sleep -Milliseconds "; + psParam += std::to_wstring(delayMs); + psParam += L"; Start-Process -FilePath '"; + psParam += exeEsc; + psParam += L"'"; + if (!argsEsc.empty()) { + psParam += L" -ArgumentList '"; + psParam += argsEsc; + psParam += L"'"; + } + psParam += L"\""; + + SHELLEXECUTEINFOW sei{}; + sei.cbSize = sizeof(sei); + sei.lpVerb = asAdmin ? L"runas" : L"open"; + sei.lpFile = L"powershell.exe"; + sei.lpParameters = psParam.c_str(); + sei.nShow = SW_HIDE; + if (!ShellExecuteExW(&sei)) return false; + if (exitCurrent) ExitProcess(0); + return true; + } +} #pragma once \ No newline at end of file diff --git a/include/sql/qSqlBase.h b/include/sql/qSqlBase.h index 65d02f5..c97dc05 100644 --- a/include/sql/qSqlBase.h +++ b/include/sql/qSqlBase.h @@ -32,8 +32,8 @@ class SQLiteDB { public: QSqlDatabase db; - // 新增:全局互斥锁,保护所有数据库操作 - mutable QMutex db_mutex; + // 改为递归互斥锁,解决嵌套调用问题 + mutable QRecursiveMutex db_mutex; SQLiteDB(const QString& dbPath) : dbPath(dbPath) { @@ -41,9 +41,8 @@ public: } ~SQLiteDB() { disconnect(); }; - // 所有公有方法加锁保护 - bool execute(const QString& queryStr, const QVariantList& args = {}) { - QMutexLocker lock(&db_mutex); + // 添加内部无锁版本,避免嵌套锁问题 + bool execute_unsafe(const QString& queryStr, const QVariantList& args = {}) { QSqlQuery query(db); query.prepare(queryStr); @@ -59,8 +58,7 @@ public: return true; } - QList> query(const QString& queryStr, const QVariantList& args = {}) { - QMutexLocker lock(&db_mutex); + QList> query_unsafe(const QString& queryStr, const QVariantList& args = {}) { QList> results; QSqlQuery query(db); query.prepare(queryStr); @@ -86,6 +84,17 @@ public: return results; } + // 公有方法保持加锁保护 + bool execute(const QString& queryStr, const QVariantList& args = {}) { + QMutexLocker lock(&db_mutex); + return execute_unsafe(queryStr, args); + } + + QList> query(const QString& queryStr, const QVariantList& args = {}) { + QMutexLocker lock(&db_mutex); + return query_unsafe(queryStr, args); + } + bool createTable(const QString& tableName, const QList>& columns) { QMutexLocker lock(&db_mutex); if (columns.empty()) { @@ -101,22 +110,18 @@ public: QString sql = QString("CREATE TABLE IF NOT EXISTS \"%1\" (%2)") .arg(tableName) .arg(columnDefinitions.join(", ")); - QSqlQuery query(db); - bool res = query.exec(sql); - return res; + + return execute_unsafe(sql); } std::vector getTables() { QMutexLocker lock(&db_mutex); std::vector tables; QString sql = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';"; - QSqlQuery query(db); - if (!query.exec(sql)) { - qDebug() << "getTables failed:" << query.lastError().text(); - return tables; - } - while (query.next()) { - tables.push_back(query.value(0).toString()); + + auto result = query_unsafe(sql); + for (const auto& row : result) { + tables.push_back(row.value("name").toString()); } return tables; } @@ -124,7 +129,7 @@ public: bool dropTable(const QString& tableName) { QMutexLocker lock(&db_mutex); QString sql = QString("DROP TABLE IF EXISTS %1").arg(tableName); - return execute(sql); + return execute_unsafe(sql); } bool addColumn(const QString& tableName, const QString& columnName, const QString& columnType) { @@ -135,12 +140,9 @@ public: } QString sql = QString("ALTER TABLE \"%1\" ADD COLUMN \"%2\" %3").arg(tableName, columnName, columnType); - - QSqlQuery query(db); - query.prepare(sql); - - if (!query.exec()) { - qDebug() << "Add column failed:" << query.lastError().text(); + + if (!execute_unsafe(sql)) { + qDebug() << "Add column failed"; return false; } @@ -152,13 +154,48 @@ public: QMutexLocker lock(&db_mutex); QString sql = QString("SELECT name FROM sqlite_master WHERE type='table' AND name='%1';").arg(tableName); - QList> result = query(sql); + QList> result = query_unsafe(sql); return !result.isEmpty(); } - bool _insert(const QString& tableName, - const std::map& data) { + // 添加批量操作支持,减少锁竞争 + bool batchInsert(const QString& tableName, const std::vector>& dataList) { + if (dataList.empty()) { + qDebug() << "Batch insert failed: data is empty."; + return false; + } + QMutexLocker lock(&db_mutex); + + // 开始事务 + if (!execute_unsafe("BEGIN TRANSACTION;")) { + return false; + } + + bool allSuccess = true; + for (const auto& data : dataList) { + if (!_insert_unsafe(tableName, data)) { + allSuccess = false; + break; + } + } + + if (allSuccess) { + execute_unsafe("COMMIT;"); + } else { + execute_unsafe("ROLLBACK;"); + } + + return allSuccess; + } + + bool _insert(const QString& tableName, const std::map& data) { + QMutexLocker lock(&db_mutex); + return _insert_unsafe(tableName, data); + } + +private: + bool _insert_unsafe(const QString& tableName, const std::map& data) { if (data.empty()) { qDebug() << "Insert failed: data is empty."; return false; @@ -169,53 +206,51 @@ public: return false; } - QStringList columns, values; + QStringList columns, placeholders; + QVariantList values; + for (const auto& pair : data) { columns << pair.first; - values << "'" + pair.second.toString().replace("'", "''") + "'"; + placeholders << "?"; + values << pair.second; } QString sql = QString("INSERT INTO \"%1\" (%2) VALUES (%3)") .arg(tableName) .arg(columns.join(", ")) - .arg(values.join(", ")); + .arg(placeholders.join(", ")); - qDebug() << "Generated SQL: " << sql; - - QSqlQuery query(db); - - if (!db.isOpen()) { - qDebug() << "Database is not open!"; - return false; - } - - if (!query.exec(sql)) { - qDebug() << "Insert failed:" << query.lastError().text(); - return false; - } - - return true; + return execute_unsafe(sql, values); } +public: bool _update(const QString& tableName, const std::map& data, const std::map& conditions) { QMutexLocker lock(&db_mutex); + return _update_unsafe(tableName, data, conditions); + } + +private: + bool _update_unsafe(const QString& tableName, + const std::map& data, + const std::map& conditions) { if (data.empty() || conditions.empty()) { qDebug() << "Update failed: data or conditions are empty."; return false; } - QStringList setClauses; + QStringList setClauses, whereClauses; + QVariantList values; + for (const auto& pair : data) { - QString value = pair.second.toString().replace("'", "''"); - setClauses << QString("%1 = '%2'").arg(pair.first).arg(value); + setClauses << QString("%1 = ?").arg(pair.first); + values << pair.second; } - QStringList whereClauses; for (const auto& pair : conditions) { - QString conditionValue = pair.second.toString().replace("'", "''"); - whereClauses << QString("%1 = '%2'").arg(pair.first).arg(conditionValue); + whereClauses << QString("%1 = ?").arg(pair.first); + values << pair.second; } QString sql = QString("UPDATE \"%1\" SET %2 WHERE %3") @@ -223,175 +258,147 @@ public: .arg(setClauses.join(", ")) .arg(whereClauses.join(" AND ")); - qDebug() << "Generated SQL: " << sql; - - QSqlQuery query(db); - - if (!db.isOpen()) { - qDebug() << "Database is not open!"; - return false; - } - - if (!query.exec(sql)) { - qDebug() << "Update failed:" << query.lastError().text(); - return false; - } - - return true; + return execute_unsafe(sql, values); } - bool _delete(const QString& tableName, - const std::map& conditions) { - QMutexLocker lock(&db_mutex); +public: + bool _delete(const QString& tableName, const std::map& conditions) { + QMutexLocker lock(&db_mutex); + return _delete_unsafe(tableName, conditions); + } + +private: + bool _delete_unsafe(const QString& tableName, const std::map& conditions) { if (conditions.empty()) { qDebug() << "Delete failed: conditions are empty."; return false; } QStringList whereClauses; + QVariantList values; + for (const auto& pair : conditions) { - whereClauses << QString("%1 = :%2").arg(pair.first).arg(pair.first + "_condition"); + whereClauses << QString("%1 = ?").arg(pair.first); + values << pair.second; } QString sql = QString("DELETE FROM \"%1\" WHERE %2") .arg(tableName) .arg(whereClauses.join(" AND ")); - QSqlQuery query(db); - query.prepare(sql); - - for (const auto& pair : conditions) { - query.bindValue(":" + pair.first + "_condition", QVariant::fromValue(pair.second)); - } - - if (!query.exec()) { - qDebug() << "Delete failed:" << query.lastError().text(); - return false; - } - - return true; + return execute_unsafe(sql, values); } +public: std::vector> _search(const QString& tableName, const QStringList& columns, const std::map& conditions = {}) { - QMutexLocker lock(&db_mutex); + QMutexLocker lock(&db_mutex); + return _search_unsafe(tableName, columns, conditions); + } + +private: + std::vector> _search_unsafe(const QString& tableName, + const QStringList& columns, + const std::map& conditions = {}) { + QStringList selectColumns = columns.isEmpty() ? QStringList("*") : columns; - QString sql = QString("SELECT %1 FROM \"%2\"").arg(selectColumns.join(", "), tableName); - + + QVariantList values; if (!conditions.empty()) { QStringList whereClauses; for (const auto& pair : conditions) { - QString value = pair.second.toString().replace("'", "''"); - whereClauses << QString("%1 = '%2'").arg(pair.first).arg(value); + whereClauses << QString("%1 = ?").arg(pair.first); + values << pair.second; } sql += " WHERE " + whereClauses.join(" AND "); } - qDebug() << "Generated SQL: " << sql; - - QSqlQuery query(db); - - if (!db.isOpen()) { - qDebug() << "Database is not open!"; - return {}; - } - - if (!query.exec(sql)) { - qDebug() << "Search failed:" << query.lastError().text(); - return {}; - } - + auto result = query_unsafe(sql, values); std::vector> results; - while (query.next()) { - std::map row; - for (int i = 0; i < query.record().count(); ++i) { - row[query.record().fieldName(i)] = query.value(i); + + for (const auto& row : result) { + std::map rowMap; + for (auto it = row.begin(); it != row.end(); ++it) { + rowMap[it.key()] = it.value(); } - results.push_back(row); + results.push_back(rowMap); } return results; } +public: QList> queryTabelData(const QString& tableName) { - QMutexLocker lock(&db_mutex); + QMutexLocker lock(&db_mutex); QString sql = QString("SELECT * FROM \"%1\"").arg(tableName); - return query(sql); + return query_unsafe(sql); } - bool exportTableToCSV(const QString& tableName, const QString& filePath, std::mutex& _mutex) { - QMutexLocker lock(&db_mutex); + // 移除外部 mutex 参数,避免锁顺序问题 + bool exportTableToCSV(const QString& tableName, const QString& filePath) { + QMutexLocker lock(&db_mutex); using namespace std::chrono; auto start = high_resolution_clock::now(); - QString csvFileName = filePath; QString sql = QString("SELECT * FROM \"%1\"").arg(tableName); - QSqlQuery query(db); - - if (!query.exec(sql)) { - qCritical() << "Query execution failed: " << query.lastError().text(); - return false; - } - - if (!query.next()) { + + auto result = query_unsafe(sql); + if (result.isEmpty()) { qDebug() << "No data found in table" << tableName; return false; } - QFile file(csvFileName); + QFile file(filePath); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - qCritical() << "Failed to open file" << csvFileName; + qCritical() << "Failed to open file" << filePath; return false; } QTextStream out(&file); - QSqlRecord record = query.record(); - QStringList columns; - for (int i = 0; i < record.count(); ++i) { - columns << record.fieldName(i); - } + // 写入表头 + if (!result.isEmpty()) { + QStringList columns = result.first().keys(); + out << columns.join(",") << "\n"; - out << columns.join(",") << "\n"; - - do { - QStringList values; - for (const auto& column : columns) { - values << query.value(column).toString(); + // 写入数据 + for (const auto& row : result) { + QStringList values; + for (const auto& column : columns) { + values << row.value(column).toString(); + } + out << values.join(",") << "\n"; } - out << values.join(",") << "\n"; - } while (query.next()); + } file.close(); auto end = high_resolution_clock::now(); auto duration = duration_cast(end - start); - qDebug() << csvFileName << "EXPORT CSV COST: " << duration.count() << "ms"; + qDebug() << filePath << "EXPORT CSV COST: " << duration.count() << "ms"; return true; } bool setWALMode(bool enableWAL = true, int busyTimeoutMs = 3000) { - QMutexLocker lock(&db_mutex); + QMutexLocker lock(&db_mutex); if (!db.isOpen()) { qWarning() << "Database is not open, cannot set WAL mode."; return false; } - QSqlQuery pragma(db); - QString mode = enableWAL ? "WAL" : "DELETE"; - if (!pragma.exec(QString("PRAGMA journal_mode=%1;").arg(mode))) { - qWarning() << "Failed to set journal_mode:" << pragma.lastError().text(); + if (!execute_unsafe(QString("PRAGMA journal_mode=%1;").arg(mode))) { + qWarning() << "Failed to set journal_mode"; return false; } qDebug() << "SQLite journal_mode set to" << mode; if (enableWAL) { - pragma.exec("PRAGMA synchronous=NORMAL;"); + execute_unsafe("PRAGMA synchronous=NORMAL;"); } - pragma.exec(QString("PRAGMA busy_timeout=%1;").arg(busyTimeoutMs)); + execute_unsafe(QString("PRAGMA busy_timeout=%1;").arg(busyTimeoutMs)); return true; } @@ -416,23 +423,18 @@ private: qDebug() << "Connected to SQLite database:" << dbPath; - { - QSqlQuery pragma(db); - - if (!pragma.exec("PRAGMA journal_mode=WAL;")) { - qWarning() << "Failed to enable WAL mode:" << pragma.lastError().text(); - } - else { - qDebug() << "SQLite WAL mode enabled."; - } - pragma.exec("PRAGMA synchronous=NORMAL;"); - pragma.exec("PRAGMA busy_timeout=3000;"); + // 设置 WAL 模式和其他 PRAGMA + if (!execute_unsafe("PRAGMA journal_mode=WAL;")) { + qWarning() << "Failed to enable WAL mode"; + } else { + qDebug() << "SQLite WAL mode enabled."; } + execute_unsafe("PRAGMA synchronous=NORMAL;"); + execute_unsafe("PRAGMA busy_timeout=3000;"); - createTable("setting", - { - {"id","INTEGER PRIMARY KEY AUTOINCREMENT"} , - }); + createTable("setting", { + {"id","INTEGER PRIMARY KEY AUTOINCREMENT"} + }); return true; } @@ -449,161 +451,91 @@ private: QString dbPath; }; -class CsvWriter : public QThread{ +class CsvWriter : public QThread { public: - CsvWriter(SQLiteDB* dbIn):db(dbIn){ - try{ - m_json = readJsonFromPath("./sqldrivers/sqliteCfg.json"); - for (auto& data : m_json["数据列表"]) { - db_InitColumns.append({ QString::fromStdString(data),"TEXT" }); - } - for (auto& data : m_json["链接到UI表格数据列表"].items()) { - csvAndChartLink[QString::fromStdString(data.key())] = QString::fromStdString(data.value()); - } - if (m_json["新增数据列表"].size() > 0) { - for (auto& data : m_json["新增数据列表"]) { - db_newCol.append({ QString::fromStdString(data),"TEXT" }); - } - m_json["新增数据列表"].clear(); - saveJsonFromPath("./sqldrivers/sqliteCfg.json", m_json); - } - for (auto& data : m_json["判断NG依据数据列表"]) { - isNgDepends.push_back(QString::fromStdString(data)); - } + CsvWriter(SQLiteDB* dbIn) : db(dbIn) {} + ~CsvWriter() { + // 确保线程安全退出 + if (isRunning()) { + quit(); + wait(5000); // 等待最多5秒 } - catch (const std::exception&){ - std::cerr << "readJsonFromPath error" << std::endl; - } - init(); } - ~CsvWriter(){ - //stopAutoExport(); - } - std::mapcsvAndChartLink; + std::map csvAndChartLink; SQLiteDB* db; void addData(QString snCode, std::map data) { if (snCode.isEmpty()) { - qWarning() << "addtData: snCode is empty."; + qWarning() << "addData: snCode is empty."; return; } if (data.empty()) { - qWarning() << "addtData: data is empty."; + qWarning() << "addData: data is empty."; return; } - QMutexLocker locker(&queueLock); - queue.enqueue(std::make_pair(snCode, data)); - this->start(); + + { + QMutexLocker locker(&queueLock); + queue.enqueue(std::make_pair(snCode, data)); + } + + if (!isRunning()) { + start(); + } } bool isNewData(const QString& snCode) { - QMutexLocker locker(&db->db_mutex); - auto res = db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} }); + auto res = db->_search(getCurrentProcessCsvName(), {}, { {"条码", snCode} }); return res.empty(); } + bool isNgData(const QString& snCode) { - QMutexLocker locker(&db->db_mutex); - auto res = db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} }); - if (res.empty() == true) + auto res = db->_search(getCurrentProcessCsvName(), {}, { {"条码", snCode} }); + if (res.empty()) { return false; - for (auto& data : isNgDepends) { - if (res[0][data].toString() == "NG") + } + + for (const auto& data : isNgDepends) { + if (res[0][data].toString() == "NG") { return true; + } } return false; } - void run() override{ - while (queue.size() > 0) { +protected: + void run() override { + while (true) { std::pair> val; + + // 从队列获取数据 { QMutexLocker locker(&queueLock); + if (queue.isEmpty()) { + break; + } val = queue.dequeue(); } + try { - auto snCode = val.first; - auto data = val.second; - QString currentProcessCsvName = getCurrentProcessCsvName(); - if (currentProcessCsvName != currentProcessCsvNameCache) { - QMutexLocker locker(&db->db_mutex); - if (!db->createTable(currentProcessCsvName, db_InitColumns)) { - qWarning() << "addtData: Failed to create table:" << currentProcessCsvName; - return; - } - currentProcessCsvNameCache = currentProcessCsvName; - } - QList tableColumns; - { - QMutexLocker locker(&db->db_mutex); - QSqlQuery colQuery(db->db); - QString colSql = QString("PRAGMA table_info(\"%1\")").arg(currentProcessCsvName); - if (colQuery.exec(colSql)) { - while (colQuery.next()) { - tableColumns.append(colQuery.value(1).toString()); - } - } - } - for (const auto& kv : data) { - if (!tableColumns.contains(kv.first)) { - if (!db->addColumn(currentProcessCsvName, kv.first, "TEXT")) { - qWarning() << "addtData: Failed to add column:" << kv.first << "to table:" << currentProcessCsvName; - } - } - } - std::vector> res; - { - res = db->_search(currentProcessCsvName, {}, { {"条码",snCode} }); - } - QString nowTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); - bool opResult = false; - if (res.empty()) { - std::vector> lastRes; - { - lastRes = db->_search(getLastProcessCsvName(), {}, { {"条码",snCode} }); - } - if (lastRes.empty()) { - std::map insertData = data; - insertData["条码"] = snCode; - insertData["创建时间"] = nowTime; - insertData["修改时间"] = nowTime; - opResult = db->_insert(currentProcessCsvName, insertData); - if (!opResult) { - qWarning() << "addtData: Insert failed for table:" << currentProcessCsvName << "snCode:" << snCode; - } - } - else { - std::map updateData = data; - updateData["修改时间"] = nowTime; - opResult = db->_update(getLastProcessCsvName(), updateData, { {"条码",snCode} }); - if (!opResult) { - qWarning() << "addtData: Update failed for table:" << getLastProcessCsvName() << "snCode:" << snCode; - } - } - } - else { - std::map updateData = data; - updateData["修改时间"] = nowTime; - opResult = db->_update(getCurrentProcessCsvName(), updateData, { {"条码",snCode} }); - if (!opResult) { - qWarning() << "addtData: Update failed for table:" << getCurrentProcessCsvName() << "snCode:" << snCode; - } - } + processData(val.first, val.second); } catch (const std::exception& ex) { - qCritical() << "addtData: Exception caught:" << ex.what(); + qCritical() << "addData: Exception caught:" << ex.what(); } catch (...) { - qCritical() << "addtData: Unknown exception caught."; + qCritical() << "addData: Unknown exception caught."; } } } private: + // 统一锁顺序:先队列锁,再数据库锁 QMutex queueLock; - QQueue>> queue; + QQueue>> queue; std::vector isNgDepends; - QQueue> > addDataCacheQueue; + std::mutex _mutex; int m_intervalMs = 10000; QElapsedTimer timer; @@ -617,19 +549,96 @@ private: {"CT", "TEXT"}, }; - void init(){ + void processData(const QString& snCode, const std::map& data) { + QString currentProcessCsvName = getCurrentProcessCsvName(); + + // 确保表存在 + if (currentProcessCsvName != currentProcessCsvNameCache) { + if (!db->createTable(currentProcessCsvName, db_InitColumns)) { + qWarning() << "addData: Failed to create table:" << currentProcessCsvName; + return; + } + currentProcessCsvNameCache = currentProcessCsvName; + } + + // 检查并添加缺失的列 + ensureColumns(currentProcessCsvName, data); + + QString nowTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); + + // 检查数据是否存在 + auto res = db->_search(currentProcessCsvName, {}, { {"条码", snCode} }); + + if (res.empty()) { + // 检查上一个班次的数据 + auto lastRes = db->_search(getLastProcessCsvName(), {}, { {"条码", snCode} }); + + if (lastRes.empty()) { + // 插入新数据 + std::map insertData = data; + insertData["条码"] = snCode; + insertData["创建时间"] = nowTime; + insertData["修改时间"] = nowTime; + + if (!db->_insert(currentProcessCsvName, insertData)) { + qWarning() << "addData: Insert failed for table:" << currentProcessCsvName << "snCode:" << snCode; + } + } else { + // 更新上一个班次的数据 + std::map updateData = data; + updateData["修改时间"] = nowTime; + + if (!db->_update(getLastProcessCsvName(), updateData, { {"条码", snCode} })) { + qWarning() << "addData: Update failed for table:" << getLastProcessCsvName() << "snCode:" << snCode; + } + } + } else { + // 更新当前数据 + std::map updateData = data; + updateData["修改时间"] = nowTime; + + if (!db->_update(getCurrentProcessCsvName(), updateData, { {"条码", snCode} })) { + qWarning() << "addData: Update failed for table:" << getCurrentProcessCsvName() << "snCode:" << snCode; + } + } + } + + void ensureColumns(const QString& tableName, const std::map& data) { + // 获取当前表的列信息 + QList tableColumns; + auto columnsResult = db->query("PRAGMA table_info(\"" + tableName + "\")"); + + for (const auto& row : columnsResult) { + tableColumns.append(row.value("name").toString()); + } + + // 添加缺失的列 + for (const auto& kv : data) { + if (!tableColumns.contains(kv.first)) { + if (!db->addColumn(tableName, kv.first, "TEXT")) { + qWarning() << "addData: Failed to add column:" << kv.first << "to table:" << tableName; + } + } + } + } + + void init() { std::lock_guard locker(_mutex); + if (!db->createTable(getLastProcessCsvName(), db_InitColumns)) { qDebug() << "Failed to create table " << getLastProcessCsvName(); } + currentProcessCsvNameCache = getCurrentProcessCsvName(); if (!db->createTable(currentProcessCsvNameCache, db_InitColumns)) { qDebug() << "Failed to create table " << currentProcessCsvNameCache; } - for (auto& data : db_newCol) { + + for (const auto& data : db_newCol) { db->addColumn(getLastProcessCsvName(), data.first, data.second); db->addColumn(getCurrentProcessCsvName(), data.first, data.second); } + timer.start(); } @@ -639,52 +648,48 @@ private: int minute = currentDateTime.time().minute(); bool isDayShift = (hour > 8 || (hour == 8 && minute >= 30)) && (hour < 20 || (hour == 20 && minute <= 30)); bool isDayBefore = hour <= 8 || (hour == 8 && minute <= 29); + QString dateStr; - if (isDayBefore == true) + if (isDayBefore) { dateStr = currentDateTime.addDays(-1).toString("yyyy-MM-dd"); - else + } else { dateStr = currentDateTime.toString("yyyy-MM-dd"); - if (isDayShift) { - return (dateStr + "白班"); - } - else { - return (dateStr + "夜班"); } + + return dateStr + (isDayShift ? "白班" : "夜班"); } QString getLastProcessCsvName() { QDateTime currentDateTime = QDateTime::currentDateTime(); int hour = currentDateTime.time().hour(); int minute = currentDateTime.time().minute(); - bool isDayShift = (hour == 8 && minute >= 30) && (hour == 20 && minute <= 30); - bool isDayBefore = hour == 20 && minute <= 30; + bool isDayShift = (hour >= 8 && minute >= 30) && (hour <= 20 && minute <= 30); + bool isDayBefore = hour <= 20 && minute <= 30; + QDateTime lastShiftDateTime; if (isDayBefore) { lastShiftDateTime = currentDateTime.addDays(-1); - } - else + } else { lastShiftDateTime = currentDateTime; + } + QString dateStr = lastShiftDateTime.toString("yyyy-MM-dd"); - if (isDayShift) { - return (dateStr + "夜班"); - } - else { - return (dateStr + "白班"); - } + return dateStr + (isDayShift ? "夜班" : "白班"); } - void exportCsv(){ + void exportCsv() { QString name = getLastProcessCsvName(); - db->exportTableToCSV(name, "./csv/"+ name +".csv", _mutex); + db->exportTableToCSV(name, "./csv/" + name + ".csv"); + name = getCurrentProcessCsvName(); - db->exportTableToCSV(name, "./csv/" + name + ".csv", _mutex); + db->exportTableToCSV(name, "./csv/" + name + ".csv"); + QString currentProcessCsvName = getCurrentProcessCsvName(); - if (currentProcessCsvName != currentProcessCsvNameCache) - if (!db->createTable(currentProcessCsvName, db_InitColumns)) { - return; - } - else + if (currentProcessCsvName != currentProcessCsvNameCache) { + if (db->createTable(currentProcessCsvName, db_InitColumns)) { currentProcessCsvNameCache = currentProcessCsvName; + } + } } }; diff --git a/include/subModuleBase.h b/include/subModuleBase.h index 9f0300a..6d1d391 100644 --- a/include/subModuleBase.h +++ b/include/subModuleBase.h @@ -5,6 +5,8 @@ #include #include #include +#include + class dsModuleBase { public: diff --git a/include/sxGlobal.h b/include/sxGlobal.h index c1785ce..515b08c 100644 --- a/include/sxGlobal.h +++ b/include/sxGlobal.h @@ -25,7 +25,7 @@ struct sx_581_address { int triggerAddr = -1; int triggerValue = -1; - int snAddr; + std::vector snAddr; QByteArray completeAddr = "-1"; QByteArray resultAddr = "-1"; int valueOffsetAddr = -1; @@ -88,6 +88,7 @@ public: std::string cameraName; QString viewerName; std::vectoraddress; + int oneTriggerCaptrueTimes = 1; /// /// 初始化 /// @@ -101,7 +102,7 @@ public: /// 默认 /// 算法函数 /// - void init(std::string cameraNameIn, QString viewerNameIN, std::vector addressIN, int oneTriggerCaptrueTimes, + void init(std::string cameraNameIn, QString viewerNameIN, std::vector addressIN, int oneTriggerCaptrueTimesIN, paramTemplte* detParamsIn, ServiceManager* _serviceManagerIn, qtFuncBridge* bridgeIn, typename detCallbackChain::processAlgoCallback _processAlgoCallback, QString saveObjectNameIN = "") { @@ -112,6 +113,7 @@ public: bridge = bridgeIn; address = addressIN; saveObjectName = saveObjectNameIN; + oneTriggerCaptrueTimes = oneTriggerCaptrueTimesIN; generalDet = new detCallbackChain(_serviceManager, _detParams, bridge); generalDet->registerProcessAlgoCallback(_processAlgoCallback); //单次触发器条件 @@ -133,13 +135,23 @@ public: //获取图片并进行检测 void evaluate(int batteryOffset, QByteArray& byteArray) { _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(address[0].triggerAddr) + "_0");//触发信号清零 - std::string sn = _serviceManager->_triggerManager->readSnFromQByteArray(byteArray, address[batteryOffset].snAddr, false, false, -1); + std::string sn; + + for (auto& snAddr : address[batteryOffset].snAddr) { + sn.append(_serviceManager->_triggerManager->readSnFromQByteArray(byteArray, snAddr, false, false, -1)); + if (snAddr != address[batteryOffset].snAddr.back()) { + sn.append("_"); + } + } + auto camera = _serviceManager->_cameraManager->getCamera(cameraName);//获取相机 camera->clearCache();//清除缓存 std::shared_ptr data = _serviceManager->_detDataManager->createDetData( - QString::fromStdString(cameraName), sn, 1, camera->config.oriSaveFormat);//创建数据包 + QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包 + QString saveObjectName = ""; data->saveObjectName = saveObjectName; - camera->captureImage(data);//拍照 + for (int i = 0; i < oneTriggerCaptrueTimes; i++) + camera->captureImage(data);//拍照 generalDet->ansyncProcess(data, address[batteryOffset], ("D" + address[0].completeAddr + "_1"));//处理算法 并在取到图片后发送完成信号 data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图")); } diff --git a/include/yhGlobal.h b/include/yhGlobal.h index d5ee313..f999c2c 100644 --- a/include/yhGlobal.h +++ b/include/yhGlobal.h @@ -107,6 +107,7 @@ public: std::string cameraName; QString viewerName; std::mapaddress; + int oneTriggerCaptrueTimes = 1; /// /// 初始化 /// @@ -120,7 +121,7 @@ public: /// 默认 /// 算法函数 /// - void init(std::string cameraNameIn, QString viewerNameIN, int startAddr, int triggerCount,int oneTriggerCaptrueTimes, + void init(std::string cameraNameIn, QString viewerNameIN, int startAddr, int triggerCount,int oneTriggerCaptrueTimesIN, paramTemplte* detParamsIn, ServiceManager* _serviceManagerIn, qtFuncBridge* bridgeIn, typename detCallbackChain::processAlgoCallback _processAlgoCallback, QString saveObjectNameIN = "") { @@ -129,6 +130,7 @@ public: _serviceManager = _serviceManagerIn; _detParams = detParamsIn; bridge = bridgeIn; + oneTriggerCaptrueTimes = oneTriggerCaptrueTimesIN; saveObjectName = saveObjectNameIN; generalDet = new detCallbackChain(_serviceManager, _detParams, bridge); @@ -170,9 +172,12 @@ public: auto camera = _serviceManager->_cameraManager->getCamera(cameraName); camera->clearCache(); std::shared_ptr data = _serviceManager->_detDataManager->createDetData( - QString::fromStdString(cameraName), sn, 1, camera->config.oriSaveFormat);//创建数据包 + QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包 data->saveObjectName = saveObjectName; - camera->captureImage(data);//拍照 + + for(int i=0;i< oneTriggerCaptrueTimes;i++) + camera->captureImage(data);//拍照 + generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法 data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图")); } @@ -199,6 +204,7 @@ public: std::string cameraName; QString viewerName; std::mapaddress; + int oneTriggerCaptrueTimes = 1; /// /// 初始化 /// @@ -212,7 +218,7 @@ public: /// 默认 /// 算法函数 /// - void init(std::string cameraNameIn, QString viewerNameIN, int startAddr, int triggerCount, int oneTriggerCaptrueTimes, + void init(std::string cameraNameIn, QString viewerNameIN, int startAddr, int triggerCount, int oneTriggerCaptrueTimesIN, paramTemplte2* detParamsIn, ServiceManager* _serviceManagerIn, qtFuncBridge* bridgeIn, typename detCallbackChain::processAlgoCallback _processAlgoCallback, QString saveObjectNameIN = "") { @@ -221,6 +227,7 @@ public: _serviceManager = _serviceManagerIn; _detParams = detParamsIn; bridge = bridgeIn; + oneTriggerCaptrueTimes = oneTriggerCaptrueTimesIN; saveObjectName = saveObjectNameIN; generalDet = new detCallbackChain(_serviceManager, _detParams, bridge); @@ -253,9 +260,12 @@ public: auto camera = _serviceManager->_cameraManager->getCamera(cameraName); camera->clearCache(); std::shared_ptr data = _serviceManager->_detDataManager->createDetData( - QString::fromStdString(cameraName), sn, 1, camera->config.oriSaveFormat);//创建数据包 + QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包 data->saveObjectName = saveObjectName; - camera->captureImage(data);//拍照 + + for (int i = 0; i < oneTriggerCaptrueTimes; i++) + camera->captureImage(data);//拍照 + generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法 data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图")); } diff --git a/rpcModule/rpc_finsTcp/CMakeLists.txt b/rpcModule/rpc_finsTcp/CMakeLists.txt index 33c8bb1..c7632c9 100644 --- a/rpcModule/rpc_finsTcp/CMakeLists.txt +++ b/rpcModule/rpc_finsTcp/CMakeLists.txt @@ -28,12 +28,11 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "./*.h" ) FILE(GLOB SRC_FILES "./*.cpp") -FILE(GLOB UI_FILES "./*.ui") #find_package(Qt5 COMPONENTS Core REQUIRED) diff --git a/src/Core/CMakeLists.txt b/src/Core/CMakeLists.txt index 9a59a5b..0c31031 100644 --- a/src/Core/CMakeLists.txt +++ b/src/Core/CMakeLists.txt @@ -19,8 +19,6 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/service ${CMAKE_CURRENT_SOURCE_DIR}/front - ${CMAKE_CURRENT_SOURCE_DIR}/handleAi - ${CMAKE_CURRENT_SOURCE_DIR}/additionalFunc ${CMAKE_CURRENT_SOURCE_DIR}/logger ${CMAKE_CURRENT_SOURCE_DIR}/simpleTools ${CMAKE_CURRENT_SOURCE_DIR}/uiModule @@ -38,7 +36,7 @@ add_compile_options(/utf-8) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) find_package(Qt5 COMPONENTS ${qtlist} REQUIRED ) @@ -52,10 +50,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp") FILE(GLOB_RECURSE APP_HEADERPP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" ) FILE(GLOB_RECURSE APP_HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h" ) FILE(GLOB_RECURSE APP_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") -FILE(GLOB_RECURSE APP_UI_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.ui") FILE(GLOB_RECURSE APP_UI_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.cc") -INCLUDE_DIRECTORIES(${CMAEK_CURRENT_BINARY_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) set(RESOURCES_DIR ${CMAKE_SOURCE_DIR}/resources/resources.qrc) set(WIN_RC_DIR ${CMAKE_SOURCE_DIR}/resources/ff.rc) # 生成动态库(DLL/.so/.dylib) diff --git a/src/Core/backendInterface.cpp b/src/Core/backendInterface.cpp index cd1bd61..d0e1666 100644 --- a/src/Core/backendInterface.cpp +++ b/src/Core/backendInterface.cpp @@ -26,13 +26,13 @@ void Backend::init(SQLiteDB* db, qtFuncBridge* bridgeIn, nlohmann::ordered_json& _serviceManager._csvWriter = _csvWriter; _serviceManager._paramSyncManager = _paramSyncManager; //CLI 只在首次初始化创建 - connect(bridge, &qtFuncBridge::restartInit, this, &Backend::restartInit); + //connect(bridge, &qtFuncBridge::restartInit, this, &Backend::restartInit); _cliManager = new CLIManager(&_serviceManager, bridge); initOnce = true; } // 创建/重建需要的服务模块,避免重复创建 if (!_serviceManager._imgSaveThreadManager) { - _serviceManager._imgSaveThreadManager = new imgSaveThreadManager(missionJson["imgSaveBasePath"]); + _serviceManager._imgSaveThreadManager = new imgSaveThreadManager(missionJson["imgSaveBasePath"],_paramSyncManager); } if (!_serviceManager._cameraManager) { _serviceManager._cameraManager = new cameraManager(missionJson, bridge); @@ -58,6 +58,8 @@ void Backend::run() { bool res = _missionLoader.loadMission(missionJson["missionDllPath"]); if (res == false) { emit bridge->loadingWindow_appendInitLog("初始化Mission失败!请检查路径是否正确.", "red"); + emit bridge->initResult(InitFailure); + return; } _missionLoader.getmission(missionJson["missionDllPath"])->initBasic( &_serviceManager, diff --git a/src/Core/basic/cachePool.hpp b/src/Core/basic/cachePool.hpp deleted file mode 100644 index ebbe653..0000000 --- a/src/Core/basic/cachePool.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include -#include -#include - -template -class LRUCache { -public: - LRUCache(size_t capacity) : capacity_(capacity) { - assert(capacity > 0); - } - - std::shared_ptr get(const Key& key) { - auto it = cache_.find(key); - if (it == cache_.end()) { - std::shared_ptr ptr(new Value()); - put(key, ptr); - return ptr; - } - touch(it); - return it->second.first; - } -private: - void put(const Key& key, const std::shared_ptr& value) { - auto it = cache_.find(key); - if (it != cache_.end()) { - touch(it); - it->second.first = value; - } - else { - if (cache_.size() == capacity_) { - cache_.erase(usage_.back()); - usage_.pop_back(); - } - usage_.push_front(key); - cache_[key] = { value, usage_.begin() }; - } - } - typedef typename std::list::iterator ListIt; - std::unordered_map, ListIt>> cache_; - std::list usage_; - size_t capacity_; - - void touch(typename std::unordered_map, ListIt>>::iterator it) { - usage_.erase(it->second.second); - usage_.push_front(it->first); - it->second.second = usage_.begin(); - } -}; - - -#pragma once \ No newline at end of file diff --git a/src/Core/handleAi/handleAiModel.h b/src/Core/handleAi/handleAiModel.h deleted file mode 100644 index 7989118..0000000 --- a/src/Core/handleAi/handleAiModel.h +++ /dev/null @@ -1,264 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include -#include -const bool enableHandleAiModel = true; // 是否启用HandleAI模型 -class handleAiModelSeg { -public: - bool initFlag = false; - std::string path; - int gpuIndex = 0,batchSize = 64; - QMutex gpuMutex; - handleAiModelSeg(std::string pathIn, int gpuIndexIn, int batchSizeIn = 64){ - path = pathIn; - gpuIndex = gpuIndexIn; - batchSize = batchSizeIn; - }; - std::string init() { - segPtr = handdleAI::CreateSegObjS((char*)path.c_str(), batchSize, gpuIndex); - initFlag = true; - return path; - } - bool destroy(){ - if (segPtr == nullptr) - return false; - handdleAI::DestroySegObj(segPtr); - return true; - } - cv::Mat Evaluate(cv::Mat& input){ - QMutexLocker locker(&gpuMutex); - return segPtr->Evaluate(input); - } - handdleAI::pSegmentation* segPtr = nullptr; -}; -class handleAiModelCls{ - -public: - bool initFlag = false; - std::string path; - int gpuIndex = 0, batchSize = 1; - QMutex gpuMutex; - handleAiModelCls(std::string pathIn, int gpuIndexIn, int batchSizeIn = 1){ - path = pathIn; - gpuIndex = gpuIndexIn; - batchSize = batchSizeIn; - }; - std::string init(){ - clsPtr = handdleAI::CreateClsObjV3((char*)path.c_str(), gpuIndex, batchSize); - initFlag = true; - return path; - } - bool destroy(){ - if (clsPtr == nullptr) - return false; - handdleAI::DestroyClsObj(clsPtr); - return true; - } - int Evaluate(cv::Mat& input){ - QMutexLocker locker(&gpuMutex); - return clsPtr->Evaluate(input); - } - handdleAI::pClassification* clsPtr = nullptr; -}; -class handleAiModelDet{ -public: - bool initFlag = false; - std::string path; - int gpuIndex = 0,batchSize = 1; - QMutex gpuMutex; - handleAiModelDet(std::string pathIn, int gpuIndexIn,int batchSizeIn = 1){ - path = pathIn; - gpuIndex = gpuIndexIn; - batchSize = batchSizeIn; - }; - std::string init(){ - detPtr = handdleAI::CreateDetObjS((char*)path.c_str(), batchSize, gpuIndex); - initFlag = true; - return path; - } - bool destroy(){ - if (detPtr == nullptr || path=="") - return false; - handdleAI::DestroyDetObj(detPtr); - return true; - } - bool Evaluate(cv::Mat& input, std::vector& result){ - QMutexLocker locker(&gpuMutex); - result=detPtr->Evaluate(input); - return true; - } - handdleAI::pDetection* detPtr = nullptr; -}; -class handleAiModelManager :public serviceModule{ - -public: - enum type{ - seg, cls, det - }; - std::string basePath; - handleAiModelManager(nlohmann::ordered_json& json, qtFuncBridge* bridgeIn) - :bridge(bridgeIn){ - try { - handleAiJson = json["handleAiModel"]; - nlohmann::json segJson = handleAiJson["seg"]; - for(auto& segModel : segJson.items()){ - std::string keyName = segModel.key(); - std::string modelPath = segModel.value()["modelPath"]; - int gpuIndex = segModel.value()["gpuIndex"]; - insertSegModelPath(keyName, modelPath, gpuIndex); - } - nlohmann::json detJson = handleAiJson["det"]; - for (auto& detModel : detJson.items()){ - std::string keyName = detModel.key(); - std::string modelPath = detModel.value()["modelPath"]; - int gpuIndex = detModel.value()["gpuIndex"]; - insertDetModelPath(keyName, modelPath, gpuIndex); - } - nlohmann::json clsJson = handleAiJson["cls"]; - for (auto& clsModel : clsJson.items()){ - std::string keyName = clsModel.key(); - std::string modelPath = clsModel.value()["modelPath"]; - int gpuIndex = clsModel.value()["gpuIndex"]; - insertClsModelPath(keyName, modelPath, gpuIndex); - } - } - catch (const std::exception& e) { - std::cerr << "handleAiModelManager读取配置文件异常: " << e.what() << std::endl; - } - }; - handleAiModelSeg* insertSegModelPath(std::string keyName,std::string modelPath ,int gpuIndex){ - auto mapResult = segModels.find(keyName); - if (mapResult != segModels.end())//已有数据 - return nullptr; - handleAiModelSeg* segModel = new handleAiModelSeg(modelPath, gpuIndex); - segModels.insert(std::make_pair(keyName, segModel)); - return segModel; - } - handleAiModelDet* insertDetModelPath(std::string keyName, std::string modelPath, int gpuIndex){ - auto mapResult = detModels.find(keyName); - if (mapResult != detModels.end())//已有数据 - return nullptr; - handleAiModelDet* detModel = new handleAiModelDet(modelPath, gpuIndex); - detModels.insert(std::make_pair(keyName, detModel)); - return detModel; - } - handleAiModelCls* insertClsModelPath(std::string keyName, std::string modelPath, int gpuIndex){ - auto mapResult = clsModels.find(keyName); - if (mapResult != clsModels.end())//已有数据 - return nullptr; - handleAiModelCls* clsModel = new handleAiModelCls(modelPath, gpuIndex); - clsModels.insert(std::make_pair(keyName, clsModel)); - return clsModel; - } - // - handleAiModelSeg* getSegModel(std::string modelName){ - auto mapResult = segModels.find(modelName); - if (mapResult == segModels.end())//没有数据 - return nullptr; - return mapResult->second; - } - handleAiModelDet* getDetModel(std::string modelName){ - auto mapResult = detModels.find(modelName); - if (mapResult == detModels.end())//已有数据 - return nullptr; - return mapResult->second; - } - handleAiModelCls* getClsModel(std::string modelName){ - auto mapResult = clsModels.find(modelName); - if (mapResult == clsModels.end())//已有数据 - return nullptr; - return mapResult->second; - } - - //handdleAI::pSegmentation* insertSegModelAndInit(std::string modelPath, int gpuIndex, int batchSize = 64) { - // std::string uuid = QUuid().createUuid().toString().toStdString(); - // handleAiModelSeg* segModel = new handleAiModelSeg(modelPath, gpuIndex, batchSize); - // bridge->loadingWindow_appendInitLog(QString::fromStdString(fileManager::getFileName(modelPath) + "[SEG]检测模型初始化中..."), "white"); - // //segModel->init(); - // bridge->loadingWindow_appendInitLog(QString::fromStdString(fileManager::getFileName(modelPath) + "[SEG]初始化成功..."), "white"); - // segModels.insert(std::make_pair(uuid, segModel)); - // return segModel->segPtr; - //} - //handdleAI::pClassification* insertClsModelAndInit(std::string modelPath, int gpuIndex, int batchSize = 1) { - // std::string uuid = QUuid().createUuid().toString().toStdString(); - // handleAiModelCls* clsModel = new handleAiModelCls(modelPath, gpuIndex, batchSize); - // bridge->loadingWindow_appendInitLog(QString::fromStdString(fileManager::getFileName(modelPath) + "[CLS]检测模型初始化中..."), "white"); - // //clsModel->init(); - // bridge->loadingWindow_appendInitLog(QString::fromStdString(fileManager::getFileName(modelPath) + "[CLS]初始化成功..."), "white"); - // clsModels.insert(std::make_pair(uuid, clsModel)); - // return clsModel->clsPtr; - //} - //handdleAI::pDetection* insertDetModelAndInit(std::string modelPath, int gpuIndex, int batchSize = 1) { - // std::string uuid = QUuid().createUuid().toString().toStdString(); - // handleAiModelDet* detModel = new handleAiModelDet(modelPath, gpuIndex, batchSize); - // bridge->loadingWindow_appendInitLog(QString::fromStdString(fileManager::getFileName(modelPath) + "[DET]检测模型初始化中..."), "white"); - // //detModel->init(); - // bridge->loadingWindow_appendInitLog(QString::fromStdString(fileManager::getFileName(modelPath) + "[DET]初始化成功..."), "white"); - // detModels.insert(std::make_pair(uuid, detModel)); - // return detModel->detPtr; - //} - void run(){ - if (enableHandleAiModel == true) { - std::vector> futures; - for (auto& model : segModels){ - if (model.second->initFlag == true) continue; - futures.push_back(std::async(std::launch::async, &handleAiModelSeg::init, model.second)); - emit bridge->loadingWindow_appendInitLog(QString::fromStdString(fileManager::getFileName(model.second->path) + "检测模型初始化中..."), "white"); - } - for (auto& model : clsModels){ - if (model.second->initFlag == true) continue; - futures.push_back(std::async(std::launch::async, &handleAiModelCls::init, model.second)); - emit bridge->loadingWindow_appendInitLog(QString::fromStdString(fileManager::getFileName(model.second->path) + "检测模型初始化中..."), "white"); - } - for (auto& model : detModels){ - if (model.second->initFlag == true) continue; - futures.push_back(std::async(std::launch::async, &handleAiModelDet::init, model.second)); - emit bridge->loadingWindow_appendInitLog(QString::fromStdString(fileManager::getFileName(model.second->path) + "检测模型初始化中..."), "white"); - } - for (int i = 0; i < futures.size(); i++){ - futures[i].wait(); - std::string result = futures[i].get(); - emit bridge->loadingWindow_appendInitLog( - QString::fromStdString(fileManager::getFileName(result)) + "成功( " + QString::number(i + 1) + "/" + QString::number(futures.size()) + ")", "green"); - qDebug() << QString::fromStdString(fileManager::getFileName(result) + "成功"); - std::cout << fileManager::getFileName(result) + "成功" << std::endl; - } - status = InitOK; - } - else { - status = InitOK; - } - - - - } - ~handleAiModelManager(){ - if (enableHandleAiModel) { - for (auto& model : detModels) - model.second->destroy(); - for (auto& model : segModels) - model.second->destroy(); - for (auto& model : clsModels) - model.second->destroy(); - } - - } -private: - std::unordered_map segModels; - std::unordered_map clsModels; - std::unordered_map detModels; - int gpuCnt = 1;//gpu数量 - nlohmann::json handleAiJson; - qtFuncBridge* bridge; -}; - -#pragma once \ No newline at end of file diff --git a/src/core/additionalFunc/generalDataCollation.h b/src/core/additionalFunc/generalDataCollation.h deleted file mode 100644 index e7310ac..0000000 --- a/src/core/additionalFunc/generalDataCollation.h +++ /dev/null @@ -1,2 +0,0 @@ - -class \ No newline at end of file diff --git a/src/core/additionalFunc/manualDetThread.cpp b/src/core/additionalFunc/manualDetThread.cpp deleted file mode 100644 index 2cadc8a..0000000 --- a/src/core/additionalFunc/manualDetThread.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include - -void manualDetThread::initialization(detProcess* _appCore) -{ - //_detDataManager = &_appCore->_detDataManager; - //_threadManager = &_appCore->_threadManager; -} \ No newline at end of file diff --git a/src/core/additionalFunc/manualDetThread.h b/src/core/additionalFunc/manualDetThread.h deleted file mode 100644 index 5dfe0f7..0000000 --- a/src/core/additionalFunc/manualDetThread.h +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include -#include -//#include -//#include - -class detProcess; -class manualDetThread :public QThread -{ - Q_OBJECT -public: - detDataManager* _detDataManager; - detThreadManager* _threadManager; - //检测参数 - std::vector imgPathStr; - int algoIndex = 0; - int Pos = 0; - manualDetThread() - { - //_appConfig = &_core._appConfig; - } - void initialization(detProcess* _appCore); - void run() - { - //emit _core._qtFunc.uiModuleHistoryListWidget_reset(); - int pathCount = imgPathStr.size(); - std::vector> mats; - std::vector>files(imgPathStr.size(),std::vector());//1层目录 2层文件名 - - for (int index = 0; index < imgPathStr.size(); index++) - { - fileManager::getAllFiles(imgPathStr[index], files[index], "jpg"); - fileManager::getAllFiles(imgPathStr[index], files[index], "bmp"); - fileManager::getAllFiles(imgPathStr[index], files[index], "tiff"); - fileManager::getAllFiles(imgPathStr[index], files[index], "png"); - } - - int filesMax = 0; - for (auto vec : files) - filesMax = getMax(filesMax, (int)vec.size()); - - for (int i = 0 ;i < filesMax;i++) - { - //std::shared_ptr data = _detDataManager->createDetData("Manual", "Manual", 0); - //data->algoThreadIndex = algoIndex; - //data->oriImgMutex.lock(); - //for(int o = 0 ; o < pathCount;o++) - //{ - // if(i >= files[0].size()) - // data->oriImgs.push_back(cv::Mat()); - // else - // data->oriImgs.push_back(cv::imread(files[0][i], cv::IMREAD_UNCHANGED)); - //} - //data->oriImgMutex.unlock(); - //_threadManager->addTask(data);//添加任务 - ////emit _core._qtFunc.uiModuleLocationMap_SetProductSignStatus(Pos, 1); - //Pos++; - //QThread::msleep(500); - } - emit finishImgReadSignal(); - } - void startDet(std::vector path,int index) - { - Pos = 0; - //emit _core._qtFunc.uiModuleLocationMap_ResetToDefault(); - imgPathStr = path; - algoIndex = index; - this->start(); - } -public slots: - void startManualDetSlot(std::vector path, int index) - { - startDet(path, index); - } -signals: - void finishImgReadSignal(); -}; -#pragma once \ No newline at end of file diff --git a/src/core/service/CLIManager.h b/src/core/service/CLIManager.h index 7d7bc5f..1d82ca9 100644 --- a/src/core/service/CLIManager.h +++ b/src/core/service/CLIManager.h @@ -4,23 +4,23 @@ #include #include -class algoManager { -public: - void registerAlgo(const std::string& algoName, std::function, handleAiModelManager*)> algoFunc) { - algoMap[algoName] = algoFunc; - } - void lstAlgos() const { - if(algoMap.empty()) { - std::cout << "No algorithms registered." << std::endl; - return; - } - for (const auto& algo : algoMap) { - std::cout << "Algorithm: " << algo.first << std::endl; - } - } -private: - std::unordered_map,handleAiModelManager*)>> algoMap; -}; +//class algoManager { +//public: +// void registerAlgo(const std::string& algoName, std::function, handleAiModelManager*)> algoFunc) { +// algoMap[algoName] = algoFunc; +// } +// void lstAlgos() const { +// if(algoMap.empty()) { +// std::cout << "No algorithms registered." << std::endl; +// return; +// } +// for (const auto& algo : algoMap) { +// std::cout << "Algorithm: " << algo.first << std::endl; +// } +// } +//private: +// std::unordered_map,handleAiModelManager*)>> algoMap; +//}; class CLIManager { public: diff --git a/src/core/service/backStruct.h b/src/core/service/backStruct.h index f1d29de..510179b 100644 --- a/src/core/service/backStruct.h +++ b/src/core/service/backStruct.h @@ -1,16 +1,17 @@ #include #include -#include -//#include - - +#include static void createDirectoryIfNotExists(const std::string& path) { // 检查路径是否存在 if (!std::filesystem::exists(path)) { // 创建路径 - - std::filesystem::create_directories(path); - //std::cout << "已创建文件夹: " << path << std::endl; + try { + std::filesystem::create_directories(path); + //std::cout << "已创建文件夹: " << path << std::endl; + } + catch (...) { + qCritical() << "创建文件夹失败!" << QString::fromStdString(path); + } } } static void createDirectoryIfNotExists(const QString& path) { diff --git a/src/core/service/cameraManager.cpp b/src/core/service/cameraManager.cpp index 6ad62dd..2b4dc0e 100644 --- a/src/core/service/cameraManager.cpp +++ b/src/core/service/cameraManager.cpp @@ -120,7 +120,7 @@ void cameraManager::run(){ //非海康相机可跳过 MV_CC_DEVICE_INFO_LIST m_stDevList = searchMvDevice(); - QByteArray mvDevices = MV_CC_DeviceInfoListToQByteArray(m_stDevList); + QByteArray mvDevices = "deviceList" + MV_CC_DeviceInfoListToQByteArray(m_stDevList); for (auto i = 0; i < _cameraStructs.size(); i++) { auto& m_module = _cameraStructs[i]; @@ -138,7 +138,7 @@ void cameraManager::run(){ for (int i = 0; i < m_stDevList.nDeviceNum; i++){ std::string userDefineName = static_cast((LPCSTR)m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chUserDefinedName); std::string serialNumber = static_cast((LPCSTR)m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chSerialNumber); - if (!serialNumber.compare(m_module.key) || !userDefineName.compare(m_module.key)){ + if (!serialNumber.compare(m_module.connectionName) || !userDefineName.compare(m_module.connectionName)){ m_module.module_ptr->writeData(vec_mat, mvDevices); break; } diff --git a/src/core/service/detCallbackChain.hpp b/src/core/service/detCallbackChain.hpp index a8c0097..a9ccdcb 100644 --- a/src/core/service/detCallbackChain.hpp +++ b/src/core/service/detCallbackChain.hpp @@ -63,7 +63,24 @@ public: bool algoEvaluate(std::shared_ptr data, handleAiModelsTemplate* model, addressTemplate address = addressTemplate()) { std::chrono::steady_clock::time_point algoStartTime = std::chrono::steady_clock::now(); - bool result = _processAlgoCallback(data, model, address); + bool result; + try { + result = _processAlgoCallback(data, model, address); + } + catch (HDevEngineCpp::HDevEngineException& ex) { + + qDebug() << "detChain catched->HDevEngineException: " << ex.Message(); + } + catch (HalconCpp::HException& ex) { + + qDebug() << "detChain catched->Halcon Exception Caught!"; + qDebug() << "detChain catched->Error Code: " << ex.ErrorCode(); + qDebug() << "detChain catched->Error Message: " << ex.ErrorMessage(); + } + catch (const std::exception& e) { + + qDebug() << "detChain catched->Caught exception: " << e.what(); + } std::chrono::steady_clock::time_point algoEndTime = std::chrono::steady_clock::now(); data->algoTime = std::chrono::duration_cast(algoEndTime - algoStartTime).count(); @@ -74,17 +91,7 @@ public: std::shared_ptr dataPtr = data; detDataManager* dManager = data->dManager; data->dManager->deleteDetData(data->uuid); - try { - detectionResultHandle(data); - } - catch (const std::exception& e) - { - std::cout << "Caught exception: " << e.what() << std::endl; - qDebug() << "Caught exception: " << e.what(); - } - catch (...) { - qDebug() << "Caught exception: "; - } + detectionResultHandle(data); // 删除数据释放资源 } @@ -92,7 +99,7 @@ public: // 通用的检测结果处理 void detectionResultHandle(std::shared_ptr data) { //计算处理总耗时(CT) - QString totalCtStr = "algoCT->" + QString::number(data->algoTime) + "ms"; + QString totalCtStr = "algoCT->" + QString::number(data->algoTime) + "ms|SN" + QString::fromStdString(data->SNcode); qDebug() << totalCtStr; //std::cout << totalCtStr.toStdString() << std::endl; // 将耗时数据保存入数据库或日志 diff --git a/src/core/service/detData.h b/src/core/service/detData.h index 8736fba..0dc126e 100644 --- a/src/core/service/detData.h +++ b/src/core/service/detData.h @@ -5,7 +5,6 @@ #include #include #include -#include #include #include enum saveMode { @@ -17,7 +16,6 @@ class camera; class detData; class detDataManager; class ServiceManager; -using algoEvaluateCallback = std::function,handleAiModelManager*)>; class detData{ public: std::chrono::steady_clock::time_point startTime = std::chrono::high_resolution_clock::now(); diff --git a/src/core/service/imgSaveThreadManager.h b/src/core/service/imgSaveThreadManager.h index e0fe693..220d207 100644 --- a/src/core/service/imgSaveThreadManager.h +++ b/src/core/service/imgSaveThreadManager.h @@ -2,8 +2,13 @@ #include #include #include +#include +#include +#include +#include #include #include +#include enum imgSaveThreadType { oriImg, resImg, @@ -13,7 +18,7 @@ enum imgSaveThreadType { class ImageSavePathFormatter { public: QString rootDir = ""; - std::string genPath(std::shared_ptr data, imgSaveThreadType type, QString customPath = "", std::vector>customParams = std::vector>()){ + QString genPath(std::shared_ptr data, imgSaveThreadType type, QString customPath = "", std::vector>customParams = std::vector>()){ QString pathTemplate = !customPath.isEmpty() ? customPath : defaultPath; QString result = pathTemplate; @@ -43,8 +48,8 @@ public: // 替换SN/设备信息占位符 QString snCode = (data->SNcode.size() > 0 && data->SNcode.size() < 50) - ? QString::fromStdString(data->SNcode) - : QString::fromStdString(data->cameraKeyName); + ? QString::fromStdString(repairWindowsFileName(data->SNcode)) + : QString::fromStdString(repairWindowsFileName(data->cameraKeyName)); result.replace("{SN}", snCode); result.replace("{cameraName}", QString::fromStdString(data->cameraKeyName)); @@ -61,7 +66,7 @@ public: for (auto& pair : customParams) { result.replace(pair.first, pair.second); } - return result.toLocal8Bit().toStdString(); + return result; } std::string genFileName(std::shared_ptr data, imgSaveThreadType type, int index = 0, QString customFileName = "", std::vector> customParams = std::vector>(), const std::string& format = "bmp") { QString fileTemplate = !customFileName.isEmpty() ? customFileName : defaultFileName; @@ -69,8 +74,9 @@ public: // 替换SN/设备信息占位符 QString snCode = (data->SNcode.size() > 0 && data->SNcode.size() < 50) - ? QString::fromStdString(data->SNcode) - : QString::fromStdString(data->cameraKeyName); + ? QString::fromStdString(repairWindowsFileName(data->SNcode)) + : QString::fromStdString(repairWindowsFileName(data->cameraKeyName)); + result.replace("{SN}", snCode); result.replace("{cameraName}", QString::fromStdString(data->cameraKeyName)); @@ -130,9 +136,43 @@ public: } return result; } + + // 清理Windows文件名/文件夹名中不支持的字符 + std::string repairWindowsFileName(const std::string& input) { + std::string result = input; + + // Windows文件名/文件夹名不能包含以下字符: \ / : * ? " < > | + // 以及控制字符(ASCII 0-31) + std::string invalidChars = "\\/:*?\"<>|"; + + // 移除所有不合法字符 + for (char invalidChar : invalidChars) { + result.erase(std::remove(result.begin(), result.end(), invalidChar), result.end()); + } + + // 移除控制字符(ASCII 0-31) + result.erase(std::remove_if(result.begin(), result.end(), + [](char c) { return c >= 0 && c <= 31; }), result.end()); + + // 移除首尾空格和点号 + while (!result.empty() && (result.front() == ' ' || result.front() == '.')) { + result.erase(result.begin()); + } + while (!result.empty() && (result.back() == ' ' || result.back() == '.')) { + result.pop_back(); + } + + // 如果结果为空,提供默认名称 + if (result.empty()) { + result = "unnamed"; + } + + return result; + } + private: - QString defaultPath = "{imgSaveRootDir}/{yyyy-MM-dd}/{saveObjectName}/{HH}H/{imageType}/{processResult}/{SN}/"; - QString defaultFileName = "{SN}_{cameraName}_{index}"; + QString defaultPath = "{imgSaveRootDir}/{yyyy-MM-dd}/{saveObjectName}{imageType}/{HH}H/{processResult}/{SN}/"; + QString defaultFileName = "{SN}_{cameraName}_{index}_{HH-mm-ss}"; }; struct saveJob { saveJob(std::string jobNameIn) :jobName(jobNameIn) {} @@ -211,41 +251,62 @@ public: }; class imgSaveThreadManager { public: - imgSaveThreadManager(std::string pathIn) { + imgSaveThreadManager(std::string pathIn, paramSyncManager* paramSyncManagerIn) { _ImageSavePathFormatter.rootDir = QString::fromStdString(pathIn); + _paramSyncManager = paramSyncManagerIn; + saveOri = _paramSyncManager->get("存储原图", true).toBool(); + saveRes = _paramSyncManager->get("存储结果图", true).toBool(); + saveSeg = _paramSyncManager->get("存储Seg图", true).toBool(); + saveCls = _paramSyncManager->get("存储Cls图", true).toBool(); } ~imgSaveThreadManager() {}; imgSaveThread saveThread; void saveImage(std::shared_ptr data) { - std::string oriSavePath = _ImageSavePathFormatter.genPath(data, oriImg, data->customPath, data->customImageSaveTemplateParams);//获取文件夹名 - createDirectoryIfNotExists(oriSavePath);//不存在此文件夹则创建 - if (data->oriImgs.size() != 0) { - - std::vectorfileNames = _ImageSavePathFormatter.genFileNames(data, oriImg, data->oriImgs);//按规则为文件创建命名 - std::shared_ptr job (new saveJob("[ORI_JOB]" + data->SNcode)); - packageData(job->imgQueue, oriSavePath, fileNames, data->oriImgs);//打包数据 - saveThread.addJob(job); + if (getParamTimer.elapsed() > 5000) { + saveOri = _paramSyncManager->get("存储原图", true).toBool(); + saveRes = _paramSyncManager->get("存储结果图", true).toBool(); + saveSeg = _paramSyncManager->get("存储Seg图", true).toBool(); + saveCls = _paramSyncManager->get("存储Cls图", true).toBool(); + getParamTimer.restart(); } - std::string resSavePath = _ImageSavePathFormatter.genPath(data, resImg, data->customPath, data->customImageSaveTemplateParams);//获取文件夹名 - createDirectoryIfNotExists(resSavePath);//不存在此文件夹则创建 - std::shared_ptr job(new saveJob("[RES_JOB]"+ data->SNcode)); - //结果图保存 - if (data->resultImgs.size() != 0) { - std::vectorfileNames = _ImageSavePathFormatter.genFileNames(data, resImg, data->resultImgs);//按规则为文件创建命名 - packageData(job->imgQueue, resSavePath,fileNames, data->resultImgs);//打包数据 + std::shared_ptr oriJob(new saveJob("[ORI_JOB]" + data->SNcode)); + std::shared_ptr resJob(new saveJob("[RES_JOB]" + data->SNcode)); + + QString oriSavePath = _ImageSavePathFormatter.genPath(data, oriImg, data->customPath, data->customImageSaveTemplateParams);//获取文件夹名 + if (saveOri == true || saveSeg == true || saveCls == true) { + createDirectoryIfNotExists(oriSavePath);//不存在此文件夹则创建 + if (data->oriImgs.size() != 0 && saveOri == true) { + std::vectorfileNames = _ImageSavePathFormatter.genFileNames(data, oriImg, data->oriImgs);//按规则为文件创建命名 + packageData(oriJob->imgQueue, oriSavePath.toLocal8Bit().toStdString(), fileNames, data->oriImgs);//打包数据 + } + //SEG原图 + if (data->segOriginImgs.size() != 0 && saveSeg == true) { + std::vectorfileNames = _ImageSavePathFormatter.genFileNames(data, segImg, data->segOriginImgs);//按规则为文件创建命名 + packageData(resJob->imgQueue, oriSavePath.toLocal8Bit().toStdString(), fileNames, data->segOriginImgs);//打包数据 + } + //CLS原图 + if (data->clsOriginImgs.size() != 0 && saveCls == true) { + std::vectorfileNames = _ImageSavePathFormatter.genClsFileNames(data, clsImg, data->clsOriginImgs);//按规则为文件创建命名 + packageData(resJob->imgQueue, oriSavePath.toLocal8Bit().toStdString(), fileNames, data->clsOriginImgs);//打包数据 + } } - //SEG原图 - if (data->segOriginImgs.size() != 0) { - std::vectorfileNames = _ImageSavePathFormatter.genFileNames(data, segImg, data->segOriginImgs);//按规则为文件创建命名 - packageData(job->imgQueue, oriSavePath, fileNames, data->segOriginImgs);//打包数据 + + + QString resSavePath = _ImageSavePathFormatter.genPath(data, resImg, data->customPath, data->customImageSaveTemplateParams);//获取文件夹名 + if (saveRes == true){ + createDirectoryIfNotExists(resSavePath);//不存在此文件夹则创建 + //结果图保存 + if (data->resultImgs.size() != 0) { + std::vectorfileNames = _ImageSavePathFormatter.genFileNames(data, resImg, data->resultImgs);//按规则为文件创建命名 + packageData(resJob->imgQueue, resSavePath.toLocal8Bit().toStdString(), fileNames, data->resultImgs);//打包数据 + } } - //CLS原图 - if (data->clsOriginImgs.size() != 0) { - std::vectorfileNames = _ImageSavePathFormatter.genClsFileNames(data, clsImg, data->clsOriginImgs);//按规则为文件创建命名 - packageData(job->imgQueue, oriSavePath, fileNames, data->clsOriginImgs);//打包数据 - } - saveThread.addJob(job, imgSaveThread::priority); + + if (oriJob->imgQueue.size() != 0) + saveThread.addJob(oriJob); + if (resJob->imgQueue.size() != 0) + saveThread.addJob(resJob, imgSaveThread::priority); //额外储存NG文件夹 //std::string additionalSaveNgImgPath = genDirName(data, additionalSaveNgImg); //std::vectoradditionalSaveNgImgNames = genFileNames(data, additionalSaveNgImg); @@ -269,6 +330,9 @@ public: //} } private: + bool saveOri = true, saveRes = true, saveSeg = true, saveCls = true; + QElapsedTimer getParamTimer;//防止加锁次数过多导致卡顿 + paramSyncManager* _paramSyncManager; ImageSavePathFormatter _ImageSavePathFormatter; void packageData(QQueue>& jobQueue, std::string imgSavaPath, std::vector fileNames, std::vector& mats) { if (fileNames.size() != mats.size()) @@ -278,7 +342,7 @@ private: try { if (mats[index].data == nullptr) { - qDebug() << "在存图线程中发现无效图像"; + qDebug() << "在存图线程中发现空指针"; continue; } } @@ -300,7 +364,7 @@ private: try { if (mats[index].second.data == nullptr) { - qDebug() << "在存图线程中发现无效图像"; + qDebug() << "在存图线程中发现空指针"; continue; } } diff --git a/src/core/service/missionBase.hpp b/src/core/service/missionBase.hpp index d441eaf..e0f5084 100644 --- a/src/core/service/missionBase.hpp +++ b/src/core/service/missionBase.hpp @@ -1,6 +1,5 @@ #pragma once -//#include -#include +#include #include #include #include @@ -13,231 +12,6 @@ #include class detProcess; -class configMap { -public: - // 构造函数和析构函数 - configMap() = default; - configMap(const configMap& other) { - QMutexLocker locker(&mutex); - QMutexLocker otherLocker(&other.mutex); - data = other.data; - _missionJson = other._missionJson; - } - - configMap& operator=(const configMap& other) { - if (this != &other) { - QMutexLocker locker(&mutex); - QMutexLocker otherLocker(&other.mutex); - data = other.data; - _missionJson = other._missionJson; - } - return *this; - } - - // 插入或更新 - void set(const QString& key, const QVariant& value) { - QMutexLocker locker(&mutex); - data[key] = value; - } - - // 查询(带默认值) - QVariant get(const QString& key, const QVariant& defaultValue = QVariant()) const { - QMutexLocker locker(&mutex); - return data.value(key, defaultValue); - } - - // 类型安全的获取方法 - QString getString(const QString& key, const QString& defaultValue = QString()) const { - return get(key, defaultValue).toString(); - } - - int getInt(const QString& key, int defaultValue = 0) const { - return get(key, defaultValue).toInt(); - } - - bool getBool(const QString& key, bool defaultValue = false) const { - return get(key, defaultValue).toBool(); - } - - double getDouble(const QString& key, double defaultValue = 0.0) const { - return get(key, defaultValue).toDouble(); - } - - // 删除 - bool erase(const QString& key) { - QMutexLocker locker(&mutex); - return data.remove(key) > 0; - } - - // 检查是否包含键 - bool contains(const QString& key) const { - QMutexLocker locker(&mutex); - return data.contains(key); - } - - // 检查是否为空 - bool isEmpty() const { - QMutexLocker locker(&mutex); - return data.isEmpty(); - } - - // 获取大小 - int size() const { - QMutexLocker locker(&mutex); - return data.size(); - } - - // 清空所有数据 - void clear() { - QMutexLocker locker(&mutex); - data.clear(); - } - - // 获取所有键 - QList keys() const { - QMutexLocker locker(&mutex); - return data.keys(); - } - - // 获取所有值 - QList values() const { - QMutexLocker locker(&mutex); - return data.values(); - } - - // 操作符重载 - QVariant& operator[](const QString& key) { - QMutexLocker locker(&mutex); - return data[key]; - } - - const QVariant operator[](const QString& key) const { - QMutexLocker locker(&mutex); - return data.value(key); - } - - // 批量设置 - void setMultiple(const QMap& keyValues) { - QMutexLocker locker(&mutex); - for (auto it = keyValues.begin(); it != keyValues.end(); ++it) { - data[it.key()] = it.value(); - } - } - - // 批量获取 - QMap getMultiple(const QStringList& keys) const { - QMutexLocker locker(&mutex); - QMap result; - for (const QString& key : keys) { - if (data.contains(key)) { - result[key] = data[key]; - } - } - return result; - } - - bool loadFromJson(nlohmann::ordered_json& jsonData) { - QMutexLocker locker(&mutex); - try { - _missionJson = jsonData; - data.clear(); - for (auto it = jsonData.begin(); it != jsonData.end(); ++it) { - QString key = QString::fromStdString(it.key()); - if (it.value().is_string()) { - data[key] = QString::fromStdString(it.value()); - } else if (it.value().is_number_integer()) { - data[key] = static_cast(it.value()); - } else if (it.value().is_boolean()) { - data[key] = static_cast(it.value()); - } else if (it.value().is_number_float()) { - data[key] = static_cast(it.value()); - } else { - data[key] = QString::fromStdString(it.value().dump()); - } - } - return true; - } catch (...) { - return false; - } - return false; - } - - // 从现有的_missionJson加载配置 - void loadFromMissionJson() { - QMutexLocker locker(&mutex); - try { - for (auto it = _missionJson.begin(); it != _missionJson.end(); ++it) { - QString key = QString::fromStdString(it.key()); - if (it.value().is_string()) { - data[key] = QString::fromStdString(it.value()); - } else if (it.value().is_number_integer()) { - data[key] = static_cast(it.value()); - } else if (it.value().is_boolean()) { - data[key] = static_cast(it.value()); - } else if (it.value().is_number_float()) { - data[key] = static_cast(it.value()); - } else { - data[key] = QString::fromStdString(it.value().dump()); - } - } - } catch (...) { - // 处理JSON解析错误 - } - } - - // 将当前配置保存到_missionJson - void saveToMissionJson() { - QMutexLocker locker(&mutex); - try { - _missionJson.clear(); - for (auto it = data.begin(); it != data.end(); ++it) { - QString key = it.key(); - QVariant value = it.value(); - - if (value.type() == QVariant::String) { - _missionJson[key.toStdString()] = value.toString().toStdString(); - } else if (value.type() == QVariant::Int) { - _missionJson[key.toStdString()] = value.toInt(); - } else if (value.type() == QVariant::Bool) { - _missionJson[key.toStdString()] = value.toBool(); - } else if (value.type() == QVariant::Double) { - _missionJson[key.toStdString()] = value.toDouble(); - } else { - _missionJson[key.toStdString()] = value.toString().toStdString(); - } - } - } catch (...) { - // 处理JSON转换错误 - } - } - - // 迭代器支持 - QMap::const_iterator begin() const { - QMutexLocker locker(&mutex); - return data.begin(); - } - - QMap::const_iterator end() const { - QMutexLocker locker(&mutex); - return data.end(); - } - - // 调试输出 - QString toString() const { - QMutexLocker locker(&mutex); - QStringList items; - for (auto it = data.begin(); it != data.end(); ++it) { - items << QString("%1: %2").arg(it.key(), it.value().toString()); - } - return QString("configMap{%1}").arg(items.join(", ")); - } - - nlohmann::ordered_json _missionJson; - -private: - QMap data; - mutable QMutex mutex; -}; class mission { public: @@ -250,13 +24,9 @@ public: initCustom(); return true; }; - virtual bool processAlgo(std::shared_ptr data, handleAiModelManager* _handleAiModelManager) { return true; }; + //virtual bool processAlgo(std::shared_ptr data, handleAiModelManager* _handleAiModelManager) { return true; }; virtual QString command(QString& command) { return "NG"; }; - void reloadConfig(nlohmann::ordered_json& _missionJson) { - _configMap.loadFromJson(_missionJson); - onConfigReloaded(); - } - void reloadConfig() { + void reloadConfig(nlohmann::ordered_json& _missionJson = nlohmann::ordered_json()) { onConfigReloaded(); } protected: @@ -265,7 +35,6 @@ protected: virtual bool initCustom() = 0; qtFuncBridge* bridge = nullptr; ServiceManager* _serviceManager = nullptr; - configMap _configMap; }; static QString snHex(QString sn) { diff --git a/src/core/service/missionLoader.h b/src/core/service/missionLoader.h index 0ee58e5..a252d5c 100644 --- a/src/core/service/missionLoader.h +++ b/src/core/service/missionLoader.h @@ -5,6 +5,8 @@ class MissionLoader { MissionLoader() = default; ~MissionLoader() = default; bool loadMission(const std::string& missionPath) { + if (QFile(QString::fromStdString("./" + missionPath + ".dll")).exists() == false) + return false; hDlls[missionPath] = LoadLibrary(missionPath.c_str()); if (!hDlls[missionPath]) { std::cerr << "Failed to load Misson DLL!" << std::endl; diff --git a/src/core/service/triggerManager.cpp b/src/core/service/triggerManager.cpp index 9e5a157..a1f8935 100644 --- a/src/core/service/triggerManager.cpp +++ b/src/core/service/triggerManager.cpp @@ -73,7 +73,7 @@ bool triggerManager::connectHost(){ if (createFun && releaseFun) { trigger = createFun(); - destory_finstcp = releaseFun; + destoryRpcFunc = releaseFun; trigger->writeData(vec_mat, QByteArray(IpAndPort.toUtf8())); initFailure = trigger->initParas(QByteArray()); emit bridge->loadingWindow_appendInitLog(triggerFileName + "连接到" + IpAndPort,"white"); diff --git a/src/core/service/triggerManager.h b/src/core/service/triggerManager.h index 0f729e9..bee386f 100644 --- a/src/core/service/triggerManager.h +++ b/src/core/service/triggerManager.h @@ -8,7 +8,7 @@ #include #include #include -#include // for std::thread used in async callbacks +#include #define debugTesting 0 using triggerCallback = std::function; @@ -409,11 +409,14 @@ private: int heartBeatIntervalMS = 800; int heartBeatCmdCnt = 0; std::vector heartBeatCmds; - ReleaseRpcModuleBaseFunction destory_finstcp; //释放 rpcModuleBase* trigger = nullptr; bool isConnected = true; bool runFlag = true; bool init = false; std::vector vec_mat;//没啥用,一直保持为空就好 + + typedef rpcModuleBase* (*CreateRpcModuleBaseFunction)(); + typedef void (*ReleaseRpcModuleBaseFunction)(rpcModuleBase* ptr); + ReleaseRpcModuleBaseFunction destoryRpcFunc; //释放 }; #pragma once \ No newline at end of file diff --git a/src/core/struct.h b/src/core/struct.h deleted file mode 100644 index 0805c39..0000000 --- a/src/core/struct.h +++ /dev/null @@ -1,254 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -struct productSignStruct -{ - cv::Rect posRect; - std::string sign; -}; -struct productDataStruct -{ - std::string name; - std::string customerPartNumber; - std::string foxconnPartNumber; - int indexOfArm = 0; - cv::Vec3d basePos; - cv::Vec3d baseRad; - std::string imgPosPath; - int connectorAmout = 0; - int halconAlgoIndex = -1; - bool isBackExist = false; - int backArmIndex = 0; - //int为步骤数 std::string为指令 - std::unordered_map >cameraSetting; - //int为步骤数 第二个int为光源亮度 max255 - std::unordered_maplightSetting; - - //这两个bool值为true时根据codedAlgoIndex的值进到写死的检测代码中 - //启用之后下面的handleAiSimpleDet只会用于初始化模型! - bool disableHandleAiConfig = false; - bool enableCodedAlgo = false; - int codedAlgoIndex = -1; - - std::unordered_map productSign; -}; -struct perConnector -{ - bool aiOk = false,halconOk = false; - double maxPinDetValue = -1; - std::string name; - std::string resultStr; - std::string showStr; - std::string timeStr; -}; -class productCacheBase -{ -public: - productCacheBase() - { - startTimePoint = std::chrono::high_resolution_clock::now(); - //creatTime = getCurrentDateTime(); - } - void writeProductData(std::string SNin, productDataStruct&_productDataStructIn) - { - endTimePoint = std::chrono::high_resolution_clock::now(); - SN = SNin; - connectorAmount = _productDataStructIn.connectorAmout; - partNumber = _productDataStructIn.foxconnPartNumber; - } - void saveData(std::string path) - { - //endTimePoint = std::chrono::high_resolution_clock::now(); - ////测试时间 - //customExcelStruct dataSave(creatTime); - ////"耗时" - //dataSave.nexCols.push_back(customExcelStruct(calculateDuration(startTimePoint, endTimePoint))); - ////"SN" - //dataSave.nexCols[0] - // .nexCols.push_back(customExcelStruct(SN)); - ////"机种槽数" - //dataSave.nexCols[0] - // .nexCols[0] - // .nexCols.push_back(customExcelStruct(std::to_string(connectorAmount))); - ////"Part Number" - //dataSave.nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols.push_back(customExcelStruct(partNumber)); - ////"连接器编号" - //dataSave.nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols.push_back(customExcelStruct(connectorCode)); - ////"不良点数" - //dataSave.nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols.push_back(customExcelStruct(std::to_string(ngCount))); - //for (auto connectorResult : connectorResults) - //{ - // //"Pin编号" - // customExcelStruct connector(connectorResult.name); - // //"Pin结果" - // std::string pinResult; - // if (connectorResult.aiOk == true && connectorResult.halconOk == true) - // pinResult = "OK"; - // else - // { - // if (connectorResult.aiOk == false) - // pinResult += "aiNG;"; - // if (connectorResult.halconOk == false) - // pinResult += "halconNG"; - // } - // connector.nexCols.push_back(customExcelStruct(pinResult)); - // //"Pin测试值" - // connector.nexCols[0] - // .nexCols.push_back(customExcelStruct(std::to_string(connectorResult.maxPinDetValue))); - // //测试结果 - // connector.nexCols[0] - // .nexCols[0] - // .nexCols.push_back(customExcelStruct(connectorResult.resultStr)); - // //汇总 - // dataSave.nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols[0] - // .nexCols.push_back(connector); - //} - //writeExcel(path, "Sheet1", titles, dataSave); - } - std::vector connectorResults; - std::string creatTime; - std::chrono::steady_clock::time_point startTimePoint; - std::chrono::steady_clock::time_point endTimePoint; - std::string SN = "NULL"; - int ngCount = -1; - int ngPinCount = -1; - //从配置文件获取 - int connectorAmount = -1; - std::string partNumber = "NULL"; - std::string connectorCode = "NULL"; - - -private: - std::string calculateDuration(const std::chrono::steady_clock::time_point& start, const std::chrono::steady_clock::time_point& end) { - auto duration = std::chrono::duration_cast(end - start); - auto minutes = std::chrono::duration_cast(duration); - auto seconds = duration - minutes; - - std::ostringstream oss; - oss << minutes.count() << "分:" << std::setw(2) << std::setfill('0') << seconds.count() << "秒"; - - return oss.str(); - } - std::vector titles = { - "测试时间", "耗时", "SN", - "机种槽数", "Part Number", - "连接器编号", "不良点数", "Pin编号", - "Pin结果", "Pin测试值", "测试结果" }; - -}; - - -class switchProductWidgetDataPtr -{ -public: - productDataStruct getCurrentProductData() { - productDataStruct result; - if (mutex == nullptr) - return result; - if (productDatasPtr == nullptr) - return result; - - mutex->lock(); - result = productDatasPtr->at(currentProductIndex); - mutex->unlock(); - return result; - } - std::vector getAllProductData() { - std::vector result; - if (mutex == nullptr) - return result; - if (productDatasPtr == nullptr) - return result; - - mutex->lock(); - result = *productDatasPtr; - mutex->unlock(); - return result; - } - int currentProductIndex = 0;//switchProductWidget - std::vector* productDatasPtr = nullptr;//appConfig - std::mutex* mutex = nullptr;//appConfig -}; -struct lightSourceStruct -{ - std::string deviceName; - std::string comName; - int baudRate; - std::string initStr; -}; -struct triggerStruct -{ - std::string key; - std::string initStr; - std::string heartCmd; - std::string readAllCmd; - std::string moduleName; - int sleepTime; - int readNum; - std::string writeType; - int startPos; -}; - -struct sqlConfigStruct -{ - std::unordered_mapdatas; -}; -struct _952BiaoDingSwitchData -{ - QMutex mutex; - int modeIn;//0 normal 1 biaoding - double in_OutOffset; - double in_InnerOffset; - double _3d_threshold; -}; - -#include -#pragma execution_character_set("utf-8") - -typedef dsModuleBase* (*CreateFunction)(); -typedef void (*ReleaseFunction)(dsModuleBase* animal); -typedef rpcModuleBase* (*CreateRpcModuleBaseFunction)(); -typedef void (*ReleaseRpcModuleBaseFunction)(rpcModuleBase* animal); -typedef struct { - QString m_stationKy; - QString key; // 相机名称 - QString moduleName; // 模块名称 - QString task_thread_index = "-1";// 存储当前算法属于那个任务线程 - QByteArray m_initByte; // 传递初始化参数 - dsModuleBase* module_ptr = nullptr; // 存储模块指针 - ReleaseFunction destory_ptr; // 释放 - int showIndex; -}MyModule; - -typedef struct { - QString retFlag; // 判断结果 Camera 表示图片 AI表示 结果信息: - QString name; // key 示例:camera1 - QString taskName; // 任务名 - cv::Mat mat; - QByteArray byte; - int showIndex; -}dataPack; - -#pragma once \ No newline at end of file diff --git a/src/launcher/CMakeLists.txt b/src/launcher/CMakeLists.txt index d5fdb58..5c476b7 100644 --- a/src/launcher/CMakeLists.txt +++ b/src/launcher/CMakeLists.txt @@ -20,17 +20,10 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/appConfig ${CMAKE_CURRENT_SOURCE_DIR}/appConfig/spdlog - ${CMAKE_CURRENT_SOURCE_DIR}/GUI/algo ${CMAKE_CURRENT_SOURCE_DIR}/GUI/appConfig - ${CMAKE_CURRENT_SOURCE_DIR}/GUI/back - ${CMAKE_CURRENT_SOURCE_DIR}/GUI/front - ${CMAKE_CURRENT_SOURCE_DIR}/GUI/handleAi + ${CMAKE_CURRENT_SOURCE_DIR}/GUI/pages ${CMAKE_CURRENT_SOURCE_DIR}/GUI/halconAlgo - ${CMAKE_CURRENT_SOURCE_DIR}/GUI/simpleTools ${CMAKE_CURRENT_SOURCE_DIR}/GUI/uiModule - ${CMAKE_CURRENT_SOURCE_DIR}/GUI/basic - ${CMAKE_CURRENT_SOURCE_DIR}/GUI/python - ${CMAKE_CURRENT_SOURCE_DIR}/GUI/pluginManager ) link_directories ( @@ -41,7 +34,7 @@ add_compile_options(/utf-8) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) find_package(Qt5 COMPONENTS ${qtlist} REQUIRED ) @@ -55,9 +48,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp") FILE(GLOB_RECURSE APP_HEADERPP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" ) FILE(GLOB_RECURSE APP_HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h" ) FILE(GLOB_RECURSE APP_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") -FILE(GLOB_RECURSE APP_UI_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.ui") -INCLUDE_DIRECTORIES(${CMAEK_CURRENT_BINARY_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) set(RESOURCES_DIR ${CMAKE_SOURCE_DIR}/resources/resources.qrc) set(WIN_RC_DIR ${CMAKE_SOURCE_DIR}/resources/ff.rc) include_directories(${CMAKE_BINARY_DIR}) diff --git a/src/launcher/GUI/base_page.h b/src/launcher/GUI/base_page.h deleted file mode 100644 index c30cef6..0000000 --- a/src/launcher/GUI/base_page.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - - -class BasePage :public QWidget -{ - Q_OBJECT -public: - QVBoxLayout* m_layout = new QVBoxLayout(this); - QLabel* m_title; - QIcon m_toolbarIcon; - BasePage() - { - QPalette palette; - palette.setColor(QPalette::WindowText, Qt::white); - QFont font("微软雅黑", 24, QFont::Bold); - QFont font2("微软雅黑", 108, QFont::Bold); - - this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - this->setMaximumSize(9999, 9999); - this->setObjectName("pageBaseWidget "); - - m_layout->setContentsMargins(0, 0, 0, 0); - m_layout->setAlignment(Qt::AlignLeft | Qt::AlignTop); - - m_title = new QLabel(u8"基础界面"); - m_title->setFont(font); - m_title->setPalette(palette); - m_title->setAlignment(Qt::AlignLeft); - - m_layout->addWidget(m_title); - } -}; \ No newline at end of file diff --git a/src/launcher/GUI/front/loginWindow.cpp b/src/launcher/GUI/front/loginWindow.cpp deleted file mode 100644 index 62283bd..0000000 --- a/src/launcher/GUI/front/loginWindow.cpp +++ /dev/null @@ -1 +0,0 @@ -#include \ No newline at end of file diff --git a/src/launcher/GUI/front/pages/manualDetWidget.h b/src/launcher/GUI/front/pages/manualDetWidget.h deleted file mode 100644 index 785614f..0000000 --- a/src/launcher/GUI/front/pages/manualDetWidget.h +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class manualDetWidget : public QWidget{ - Q_OBJECT - -public: - int componentsWidth = 500; - QVBoxLayout* Layout = new QVBoxLayout(this); - QHBoxLayout* btnLayout = new QHBoxLayout(this); - QHBoxLayout* mainLayout = new QHBoxLayout(this); - QVBoxLayout* leftMainLayout = new QVBoxLayout(this); - QVBoxLayout* rightMainLayout = new QVBoxLayout(this); - - std::vectorbtns; - QLabel* icon, * Title; - QStackedWidget* widgets = new QStackedWidget(); - - QLineEdit* imgPathEdit1 = new QLineEdit(this); - QLineEdit* imgPathEdit2 = new QLineEdit(this); - QComboBox* algoSelect = new QComboBox(this); - QTextEdit* logWidget = new QTextEdit(this); - //manualDetThread* _manualDetThread = new manualDetThread(imgPathEdit, algoSelect, logWidget); - fancyButtonText* startEvaluateBtn = new fancyButtonText("检测",100,60,""); - void titleInit(){ - QPalette palette; - palette.setColor(QPalette::WindowText, Qt::white); - QFont font("微软雅黑", 24, QFont::Bold); - QFont font2("微软雅黑", 108, QFont::Bold); - - widgets->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - widgets->setMaximumSize(9999, 9999); - - this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - this->setMaximumSize(9999, 9999); - this->setObjectName("manualDetWidget"); - - Layout->setContentsMargins(0, 0, 0, 0); - Layout->setAlignment(Qt::AlignLeft | Qt::AlignTop); - - Title = new QLabel(u8"手动检测界面(不支持中文路径"); - Title->setFont(font); - Title->setPalette(palette); - Title->setAlignment(Qt::AlignLeft); - - - Layout->addWidget(Title); - - btnLayout->setContentsMargins(0, 0, 0, 0); - btnLayout->setAlignment(Qt::AlignLeft); - } - void mainWidgetInit(){ - QPalette palette; - palette.setColor(QPalette::WindowText, Qt::white); - QFont font("微软雅黑", 18, QFont::Bold); - QFont font2("微软雅黑", 108, QFont::Bold); - - { - QLabel* strLabel = new QLabel(u8"图片路径1:"); - strLabel->setFont(font); - strLabel->setPalette(palette); - strLabel->setAlignment(Qt::AlignLeft); - leftMainLayout->addWidget(strLabel); - - imgPathEdit1->setFont(font); - imgPathEdit1->setPalette(palette); - imgPathEdit1->setAlignment(Qt::AlignLeft); - imgPathEdit1->setFixedWidth(componentsWidth); - leftMainLayout->addWidget(imgPathEdit1); - } - { - QLabel* strLabel = new QLabel(u8"图片路径2:"); - strLabel->setFont(font); - strLabel->setPalette(palette); - strLabel->setAlignment(Qt::AlignLeft); - leftMainLayout->addWidget(strLabel); - - imgPathEdit2->setFont(font); - imgPathEdit2->setPalette(palette); - imgPathEdit2->setAlignment(Qt::AlignLeft); - imgPathEdit2->setFixedWidth(componentsWidth); - leftMainLayout->addWidget(imgPathEdit2); - } - - - QLabel* strLabel2 = new QLabel(u8"选择算法"); - strLabel2->setFont(font); - strLabel2->setPalette(palette); - strLabel2->setAlignment(Qt::AlignLeft); - leftMainLayout->addWidget(strLabel2); - - algoSelect->setFont(font); - algoSelect->setPalette(palette); - algoSelect->setFixedWidth(componentsWidth); - algoSelect->addItem("2D"); - algoSelect->addItem("3D"); - leftMainLayout->addWidget(algoSelect); - - leftMainLayout->addWidget(startEvaluateBtn); - } - manualDetWidget(){ - titleInit(); - mainWidgetInit(); - logWidget->setReadOnly(true); - rightMainLayout->addWidget(logWidget); - - Layout->addLayout(btnLayout); - Layout->addLayout(mainLayout); - mainLayout->addLayout(leftMainLayout); - leftMainLayout->setAlignment(Qt::AlignTop); - mainLayout->addLayout(rightMainLayout); - - connect(startEvaluateBtn, &QPushButton::clicked, this, [=]() { manualStartSlot(); }); - connect(startEvaluateBtn, &QPushButton::clicked, this, [=]() {startEvaluateBtn->setDisabled(true); }); - //connect(_manualDetThread, &manualDetThread::finishImgReadSignal,this, &manualDetWidget::finishImgReadSlot); - } - ~manualDetWidget() - { - //delete _manualDetThread; - } -public slots: - void manualStartSlot() - { - std::vectorpath; - //if (imgPathEdit1->text().toStdString().compare("")) - path.push_back((imgPathEdit1->text().toStdString())); - //if (imgPathEdit2->text().toStdString().compare("")) - path.push_back((imgPathEdit2->text().toStdString())); - emit startManualDetSignal(path, algoSelect->currentIndex()); - } - void finishImgReadSlot() - { - startEvaluateBtn->setEnabled(true); - } -signals: - void startManualDetSignal(std::vector path, int index); -}; - -#pragma once \ No newline at end of file diff --git a/src/launcher/GUI/front/ui_mainwindow.h b/src/launcher/GUI/front/ui_mainwindow.h deleted file mode 100644 index b97b993..0000000 --- a/src/launcher/GUI/front/ui_mainwindow.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************** -** Form generated from reading UI file 'mainwindow.ui' -** -** Created by: Qt User Interface Compiler version 5.14.2 -** -** WARNING! All changes made in this file will be lost when recompiling UI file! -********************************************************************************/ - -#ifndef UI_MAINWINDOW_H -#define UI_MAINWINDOW_H - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Ui_MainWindow -{ -public: - QWidget *centralwidget; - QGridLayout *gridLayout; - - void setupUi(QMainWindow *MainWindow) - { - if (MainWindow->objectName().isEmpty()) - MainWindow->setObjectName(QString::fromUtf8("MainWindow")); - MainWindow->resize(800, 600); - centralwidget = new QWidget(MainWindow); - centralwidget->setObjectName(QString::fromUtf8("centralwidget")); - gridLayout = new QGridLayout(centralwidget); - gridLayout->setSpacing(0); - gridLayout->setObjectName(QString::fromUtf8("gridLayout")); - gridLayout->setContentsMargins(5, 5, 5, 5); - MainWindow->setCentralWidget(centralwidget); - - retranslateUi(MainWindow); - - QMetaObject::connectSlotsByName(MainWindow); - } // setupUi - - void retranslateUi(QMainWindow *MainWindow) - { - MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr)); - } // retranslateUi - -}; - -namespace Ui { - class MainWindow: public Ui_MainWindow {}; -} // namespace Ui - -QT_END_NAMESPACE - -#endif // UI_MAINWINDOW_H diff --git a/src/launcher/GUI/front/loadingWidget.h b/src/launcher/GUI/loadingWidget.h similarity index 99% rename from src/launcher/GUI/front/loadingWidget.h rename to src/launcher/GUI/loadingWidget.h index c88d05f..e65b5d7 100644 --- a/src/launcher/GUI/front/loadingWidget.h +++ b/src/launcher/GUI/loadingWidget.h @@ -4,7 +4,7 @@ #include #include #include -#include ; +#include #include #include #include diff --git a/src/launcher/GUI/front/loginWindow.h b/src/launcher/GUI/loginWindow.h similarity index 100% rename from src/launcher/GUI/front/loginWindow.h rename to src/launcher/GUI/loginWindow.h diff --git a/src/launcher/GUI/mainwindow.cpp b/src/launcher/GUI/mainwindow.cpp index 9cf588f..490e8e1 100644 --- a/src/launcher/GUI/mainwindow.cpp +++ b/src/launcher/GUI/mainwindow.cpp @@ -1,5 +1,4 @@ #include "mainwindow.h" -#include "ui_mainwindow.h" #include #include #include @@ -11,14 +10,13 @@ MainWindow::MainWindow(appConfig* configIn, qtFuncBridge*bridgeIn, nlohmann::ordered_json& jsonIn) - : ui(new Ui::MainWindow), - bridge(bridgeIn),config(configIn),json(jsonIn), + :bridge(bridgeIn),config(configIn),json(jsonIn), _SummuaryDataPage(configIn,jsonIn["sublUiSetting"]), _loadingWidget(bridgeIn){ + topBar = new topMenuBar(this,configIn,this); leftBar = new leftMenuBar(this); // 将菜单栏添加到MainWindow的布局中 - ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); // 设置无边框的样式 setMouseTracking(true);//鼠标追踪 this->setMinimumSize(1280, 720); diff --git a/src/launcher/GUI/mainwindow.h b/src/launcher/GUI/mainwindow.h index d15fa47..7befdad 100644 --- a/src/launcher/GUI/mainwindow.h +++ b/src/launcher/GUI/mainwindow.h @@ -15,21 +15,16 @@ #include #include "uiModule/components/toolBarButton.h" #include -#include "front/loginWindow.h" +#include #include -#include "front/loadingWidget.h" +#include -#include "front/pages/displayPageWidget.h" -#include "front/pages/settingWidget.h" -#include "front/pages/logPageWidget.h" -#include "front/pages/sqlControlWidget.h" -#include "front/pages/manualDetWidget.h" -#include "front/pages/historyWidget.h" -#include -#include "front/pages/pluginManagerWidget.hpp" -#include "front/pages/summaryDataPage.h" +#include +#include +#include +#include +#include #include -#include #pragma execution_character_set("utf-8") QT_BEGIN_NAMESPACE @@ -284,12 +279,8 @@ public: settingWidget* _settingWidget; logWidget* _logWidget; sqlControlWidget* _sqlControlWidget; - manualDetWidget* _manualDetWidget; - historyWidget* _historyWidget; SummuaryDataPage _SummuaryDataPage; - pluginManagerWidget* _pluginManagerWidget = new pluginManagerWidget(); private: - Ui::MainWindow* ui; qtFuncBridge* bridge = nullptr; appConfig* config; nlohmann::ordered_json json; diff --git a/src/launcher/GUI/mainwindow.ui b/src/launcher/GUI/mainwindow.ui deleted file mode 100644 index 25fa117..0000000 --- a/src/launcher/GUI/mainwindow.ui +++ /dev/null @@ -1,38 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 800 - 600 - - - - MainWindow - - - - - 5 - - - 5 - - - 5 - - - 5 - - - 0 - - - - - - - diff --git a/src/launcher/GUI/front/pages/displayPageWidget.h b/src/launcher/GUI/pages/displayPageWidget.h similarity index 91% rename from src/launcher/GUI/front/pages/displayPageWidget.h rename to src/launcher/GUI/pages/displayPageWidget.h index 3d70325..402643b 100644 --- a/src/launcher/GUI/front/pages/displayPageWidget.h +++ b/src/launcher/GUI/pages/displayPageWidget.h @@ -23,7 +23,7 @@ #include #include #include - +#include class toolBarWidget : public QWidget { Q_OBJECT public: @@ -187,8 +187,6 @@ public: dayNightShiftHistogramWidget* _dayNightShiftHistogramWidget; userSwitch* _userSwitch; softwareDataDisplay* _softwareDataDisplay; - calibration* _calibration; - cameraRealTimeCapture* _cameraRealTimeCapture; runCommandWidget* _runCommandWidget; LogWindow* log = new LogWindow(); displayWidget(appConfig* config) :m_config(config){ @@ -292,15 +290,6 @@ public: QWidget* titleWidget = new QWidget(this); QFont font3("微软雅黑", 10, QFont::Bold); -#pragma region 日志分析按钮 - { - _toolBarWidget->createToolButton(QIcon(":/TongYongUiIcon/TongYongUiIcon/4.LogAnalyze.png"), - QString::fromStdString(trans.translate("Log")), - [=]() { - emit changeStackWidget(2); - }); - } -#pragma endregion #pragma region 打开配置文件按钮 { /*QVBoxLayout* btnLayout = new QVBoxLayout(); @@ -363,34 +352,24 @@ public: } #pragma endregion #pragma region 相机实时取流 - { - _cameraRealTimeCapture = new cameraRealTimeCapture(); - _toolBarWidget->createToolButton(QIcon(":/TongYongUiIcon/TongYongUiIcon/0.cameraModule.png"), - QString::fromStdString("相机实时取流"), - [=]() { - _cameraRealTimeCapture->show(); - }, Auth::UserLevel::ADMIN); - } + //{ + // _cameraRealTimeCapture = new cameraRealTimeCapture(); + // _toolBarWidget->createToolButton(QIcon(":/TongYongUiIcon/TongYongUiIcon/0.cameraModule.png"), + // QString::fromStdString("相机实时取流"), + // [=]() { + // _cameraRealTimeCapture->show(); + // }, Auth::UserLevel::ADMIN); + //} #pragma endregion #pragma region 九点标定引导按钮 - { - _calibration = new calibration(); - _toolBarWidget->createToolButton(QIcon(":/icon/icon/jiuDianBiaoDingBiaoDing.png"), - QString::fromStdString("九点标定"), - [=]() { - _calibration->show(); - }, Auth::UserLevel::ADMIN); - } -#pragma endregion -#pragma region 标定板标定 - { - //_calibration = new calibration(); - _toolBarWidget->createToolButton(QIcon(":/icon/icon/biaoDingBanBiaoDing.png"), - QString::fromStdString("标定板标定"), - [=]() { - //_calibration->show(); - }, Auth::UserLevel::ADMIN); - } + //{ + // _calibration = new calibration(); + // _toolBarWidget->createToolButton(QIcon(":/icon/icon/jiuDianBiaoDingBiaoDing.png"), + // QString::fromStdString("九点标定"), + // [=]() { + // _calibration->show(); + // }, Auth::UserLevel::ADMIN); + //} #pragma endregion #pragma region 读取bin目录下的tools文件夹并展示 { diff --git a/src/launcher/GUI/front/pages/historyWidget.h b/src/launcher/GUI/pages/historyWidget.h similarity index 100% rename from src/launcher/GUI/front/pages/historyWidget.h rename to src/launcher/GUI/pages/historyWidget.h diff --git a/src/launcher/GUI/front/pages/logPageWidget.h b/src/launcher/GUI/pages/logPageWidget.h similarity index 66% rename from src/launcher/GUI/front/pages/logPageWidget.h rename to src/launcher/GUI/pages/logPageWidget.h index 5ef65c2..6056c5c 100644 --- a/src/launcher/GUI/front/pages/logPageWidget.h +++ b/src/launcher/GUI/pages/logPageWidget.h @@ -105,7 +105,7 @@ public: qtConsoleOutput.setStyleSheet(textEditStyle); addLogWidget(u8"控制台", &stdConsoleOutput, logType::stdConsle); - addLogWidget(u8"QT日志", &qtConsoleOutput, logType::qtConsle); + addLogWidget(u8"系统日志", &qtConsoleOutput, logType::qtConsle); btns[0]->pressed(); Layout->addWidget(widgets); @@ -129,6 +129,7 @@ public: btnPtr->toDefault(); btn->pressed(); widgets->setCurrentIndex(index); + processCacheLog(index); }); QWidget* widget = new QWidget(); @@ -205,7 +206,19 @@ public: return QTime::currentTime().toString("HH:mm:ss.zzz"); } + void processCacheLog(int index) { + QMutexLocker globalLocker(&globalMutex); + if (logCache.find(index) == logCache.end()) return; + + FilterState& state = filterStates[index]; + QMutexLocker stateLocker(&state.mutex); + + appendColoredMessagesBatch(state.textWidget, logCache[index]); + logCache[index].clear(); + } + private: + // 用于存储过滤器状态 struct FilterState { //QComboBox* levelFilter; @@ -216,14 +229,14 @@ private: mutable QMutex mutex; // 保护此状态的互斥锁 QStringList pendingMessages; // 待处理的消息队列 }; - + QMap> logCache; std::unordered_map filterStates; // 线程安全和性能优化相关 mutable QMutex globalMutex; // 全局保护锁 QTimer* batchUpdateTimer; // 批量更新定时器 - // 线程安全地添加消息 + // 添加消息 void addMessageSafe(int index, const QString& message) { QMutexLocker globalLocker(&globalMutex); @@ -254,25 +267,6 @@ private: QTextCharFormat whiteFormat; QTextCharFormat redFormat; QTextCharFormat warningFormat; - void appendColoredMessage(QPlainTextEdit* textEdit, const QString& message) { - QTextCursor cursor = textEdit->textCursor(); - cursor.movePosition(QTextCursor::End); - - // 根据关键词设置颜色 - if (message.contains("Error", Qt::CaseInsensitive) || - message.contains("错误", Qt::CaseInsensitive)) { - cursor.setCharFormat(redFormat); - } - else if (message.contains("Warning", Qt::CaseInsensitive) || - message.contains("警告", Qt::CaseInsensitive)) { - cursor.setCharFormat(warningFormat); - } - else - cursor.setCharFormat(whiteFormat); - - cursor.insertText(message + "\n"); - textEdit->setTextCursor(cursor); - } // 滚动到底部 void scrollToBottom(QPlainTextEdit* textEdit) { @@ -284,7 +278,7 @@ private: public slots: void recvStdLogMsg(QString logMsg) { QString text = getCurrentDate() + " " + getCurrentTime() + " " + logMsg; - addMessageSafe(0, text); // 使用线程安全的方法 + addMessageSafe(0, text); } void recvQtLogMsg(QString logMsg) { @@ -294,41 +288,141 @@ public slots: private slots: void processPendingMessages() { - QMutexLocker globalLocker(&globalMutex); - - bool hasUpdates = false; + + QMap pendingByIndex; int currentIndex = widgets->currentIndex(); - - for (auto& pair : filterStates) { - int index = pair.first; - FilterState& state = pair.second; - - QMutexLocker stateLocker(&state.mutex); - - if (!state.pendingMessages.isEmpty()) { - hasUpdates = true; - - // 只更新当前显示的页面,提升性能 - if (index == currentIndex) { - // 增量添加消息而不是重新过滤所有消息 - for (const QString& message : state.pendingMessages) { - appendColoredMessage(state.textWidget, message); - } - - // 自动滚动到底部 - if (state.autoScroll) { - scrollToBottom(state.textWidget); - } + { + QMutexLocker globalLocker(&globalMutex); + for (auto& pair : filterStates) { + int index = pair.first; + FilterState& state = pair.second; + QMutexLocker stateLocker(&state.mutex); + if (!state.pendingMessages.isEmpty()) { + pendingByIndex[index] = state.pendingMessages; + state.pendingMessages.clear(); } - - state.pendingMessages.clear(); } } - - // 如果没有待处理消息,停止定时器 + + bool hasUpdates = false; + + + for (auto it = pendingByIndex.begin(); it != pendingByIndex.end(); ++it) { + int index = it.key(); + const QStringList& msgs = it.value(); + if (msgs.isEmpty()) continue; + hasUpdates = true; + + FilterState& state = filterStates[index]; + + if (index == currentIndex) { + appendColoredMessagesBatch(state.textWidget, msgs); + if (state.autoScroll) { + scrollToBottom(state.textWidget); + } + } else { + // 非当前页缓存时,短暂加锁保护 logCache + QMutexLocker globalLocker(&globalMutex); + for (const auto& log : msgs) { + logCache[index].append(log); + while (logCache[index].size() > MAX_STORED_MESSAGES) + logCache[index].dequeue(); + } + } + } + if (!hasUpdates) { batchUpdateTimer->stop(); } } + +private: + //根据消息选择颜色格式 + const QTextCharFormat& formatFor(const QString& message) const { + if (message.contains("Error", Qt::CaseInsensitive) || + message.contains(QStringLiteral("错误"), Qt::CaseInsensitive)) { + return redFormat; + } else if (message.contains("Warning", Qt::CaseInsensitive) || + message.contains(QStringLiteral("警告"), Qt::CaseInsensitive)) { + return warningFormat; + } + return whiteFormat; + } + + // 批量追 + void appendColoredMessagesBatch(QPlainTextEdit* textEdit, const QStringList& messages) { + if (messages.isEmpty()) return; + + textEdit->setUpdatesEnabled(false); + + QTextCursor cursor(textEdit->document()); + cursor.movePosition(QTextCursor::End); + cursor.beginEditBlock(); + + const QTextCharFormat* currentFmt = &formatFor(messages.first()); + cursor.setCharFormat(*currentFmt); + + QString buffer; + buffer.reserve(256 * messages.size()); // 简单预留,减少 realloc + + auto flush = [&]() { + if (!buffer.isEmpty()) { + cursor.insertText(buffer); + buffer.clear(); + } + }; + + for (const QString& msg : messages) { + const QTextCharFormat* fmt = &formatFor(msg); + if (fmt != currentFmt) { + flush(); + currentFmt = fmt; + cursor.setCharFormat(*currentFmt); + } + buffer += msg; + buffer += QLatin1Char('\n'); + } + flush(); + + cursor.endEditBlock(); + textEdit->setUpdatesEnabled(true); + } + void appendColoredMessagesBatch(QPlainTextEdit* textEdit, const QQueue& messages) { + if (messages.isEmpty()) return; + + textEdit->setUpdatesEnabled(false); + + QTextCursor cursor(textEdit->document()); + cursor.movePosition(QTextCursor::End); + cursor.beginEditBlock(); + + const QTextCharFormat* currentFmt = &formatFor(messages.first()); + cursor.setCharFormat(*currentFmt); + + QString buffer; + buffer.reserve(256 * messages.size()); // 简单预留,减少 realloc + + auto flush = [&]() { + if (!buffer.isEmpty()) { + cursor.insertText(buffer); + buffer.clear(); + } + }; + + for (const QString& msg : messages) { + const QTextCharFormat* fmt = &formatFor(msg); + if (fmt != currentFmt) { + flush(); + currentFmt = fmt; + cursor.setCharFormat(*currentFmt); + } + buffer += msg; + buffer += QLatin1Char('\n'); + } + flush(); + + cursor.endEditBlock(); + textEdit->setUpdatesEnabled(true); + } }; #pragma once \ No newline at end of file diff --git a/src/launcher/GUI/front/pages/pluginManagerWidget.hpp b/src/launcher/GUI/pages/pluginManagerWidget.hpp similarity index 100% rename from src/launcher/GUI/front/pages/pluginManagerWidget.hpp rename to src/launcher/GUI/pages/pluginManagerWidget.hpp diff --git a/src/launcher/GUI/front/pages/settingWidget.h b/src/launcher/GUI/pages/settingWidget.h similarity index 87% rename from src/launcher/GUI/front/pages/settingWidget.h rename to src/launcher/GUI/pages/settingWidget.h index b87db5b..64d83a8 100644 --- a/src/launcher/GUI/front/pages/settingWidget.h +++ b/src/launcher/GUI/pages/settingWidget.h @@ -19,57 +19,12 @@ #include #include #include -#include #include "git_version.h" #include #include #include #include -#include -class hardwareInfoWidget : public QWidget { - Q_OBJECT -public: - hardwareInfoWidget() { - connect(&systemStateMonitor::getInstance(), &systemStateMonitor::addCpuUsageData, this, &hardwareInfoWidget::addCpuUsageData); - connect(&systemStateMonitor::getInstance(), &systemStateMonitor::addCpuTempData, this, &hardwareInfoWidget::addCpuTempData); - connect(&systemStateMonitor::getInstance(), &systemStateMonitor::addMemUsageData, this, &hardwareInfoWidget::addMemUsageData); - jsonMap["CPUUSAGE"] = genWaveFormWidgetJson("cpu_usage", 80, 0, 240); - waveForms["CPUUSAGE"] = new WaveFormWidget(jsonMap["CPUUSAGE"]); - layout->addWidget(waveForms["CPUUSAGE"]); - - jsonMap["MEMUSAGE"] = genWaveFormWidgetJson("mem_useage", 80, 0, 240); - waveForms["MEMUSAGE"] = new WaveFormWidget(jsonMap["MEMUSAGE"]); - layout->addWidget(waveForms["MEMUSAGE"]); - - jsonMap["CPUTEMP"] = genWaveFormWidgetJson("cpu_temp", 80, 0, 240); - waveForms["CPUTEMP"] = new WaveFormWidget(jsonMap["CPUTEMP"]); - layout->addWidget(waveForms["CPUTEMP"]); - - for (auto& widget : waveForms) { - widget->setMinimumWidth(720); - widget->setMinimumHeight(200); - widget->setFixedYrange(0, 100); - } - } -protected: - void resizeEvnt() { - - } -public slots: - void addCpuUsageData(double input) { - waveForms["CPUUSAGE"]->appendData(input); - } - void addCpuTempData(double input) { - waveForms["CPUTEMP"]->appendData(input); - } - void addMemUsageData(double input) { - waveForms["MEMUSAGE"]->appendData(input); - } -private: - QMapjsonMap; - QMap waveForms; - QGridLayout* layout = new QGridLayout(this); -}; +//#include class settingWidget :public QWidget{ Q_OBJECT @@ -82,6 +37,8 @@ public: std::vectorbtns; QLabel* icon, * Title; int currentPageIndex = 0; + calibration _calibration; + cameraRealTimeCapture _cameraRealTimeCapture; settingWidget(appConfig* _configIn):_config(_configIn){ QPalette palette; palette.setColor(QPalette::WindowText, Qt::white); @@ -348,11 +305,11 @@ public: connect(showConsoleBtn, &QPushButton::clicked, [=]() { ShowWindow(_config->consoleHandle, SW_SHOW); - }); + }); connect(hideConsoleBtn, &QPushButton::clicked, [=]() { ShowWindow(_config->consoleHandle, SW_HIDE); - }); + }); connect(setResolutionBtn, &QPushButton::clicked, [=]() { // 获取当前窗口的顶级窗口 @@ -360,10 +317,10 @@ public: while (topWidget->parentWidget()) { topWidget = topWidget->parentWidget(); } - + // 设置窗口大小为1920x1040 topWidget->resize(1920, 1040); - + // 可选:将窗口居中显示 QScreen* screen = QApplication::primaryScreen(); if (screen) { @@ -372,12 +329,12 @@ public: int y = (screenGeometry.height() - 1080) / 2; topWidget->move(x, y); } - }); + }); m_layout->addWidget(consoleGroupBox); } // 硬件信息区域 - { + /*{ // 创建硬件信息分组容器 QGroupBox* hardwareGroupBox = new QGroupBox(QString::fromStdString(Translation::getInstance().translate("Hardware Information"))); hardwareGroupBox->setObjectName("hardwareGroupBox"); @@ -397,7 +354,7 @@ public: padding: 0 10px 0 10px; } )"); - + QVBoxLayout* hardwareMainLayout = new QVBoxLayout(hardwareGroupBox); hardwareMainLayout->setContentsMargins(15, 15, 15, 15); hardwareMainLayout->setSpacing(10); @@ -417,8 +374,53 @@ public: hardwareMainLayout->addWidget(&_hardwareInfoWidget); m_layout->addWidget(hardwareGroupBox); - } + }*/ + //小工具 + { + // 创建控制台设置分组容器 + QGroupBox* GroupBox = new QGroupBox(QString::fromStdString(Translation::getInstance().translate("小工具"))); + GroupBox->setObjectName("toolsGroupBox"); + GroupBox->setStyleSheet(R"( + QGroupBox#toolsGroupBox { + background: rgb(50, 55, 60); + border-radius: 10px; + font-family: "微软雅黑"; + font-size: 14px; + font-weight: bold; + color: white; + padding-top: 20px; + } + QGroupBox#toolsGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 10px 0 10px; + } + )"); + QVBoxLayout* consoleMainLayout = new QVBoxLayout(GroupBox); + consoleMainLayout->setContentsMargins(15, 15, 15, 15); + consoleMainLayout->setSpacing(10); + { + fancyButtonText* btn = new fancyButtonText(u8"九点标定"); + QObject::connect(btn, &QPushButton::clicked, &_calibration,&QWidget::show); + consoleMainLayout->addWidget(btn); + } + { + fancyButtonText* btn = new fancyButtonText(u8"相机实时取流"); + QObject::connect(btn, &QPushButton::clicked, &_cameraRealTimeCapture, &QWidget::show); + consoleMainLayout->addWidget(btn); + } + { + fancyButtonText* btn = new fancyButtonText(u8"打开配置文件"); + QObject::connect(btn, &QPushButton::clicked, &_cameraRealTimeCapture, &QWidget::show); + consoleMainLayout->addWidget(btn); + connect(btn, &QPushButton::clicked, [=]() { + QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(appConfig::getInstance().missionJsonPath))); + }); + consoleMainLayout->addWidget(btn); + } + m_layout->addWidget(GroupBox); + } // 添加底部伸缩空间 m_layout->addStretch(); @@ -431,7 +433,7 @@ protected: private: appConfig* _config; - hardwareInfoWidget _hardwareInfoWidget; + //hardwareInfoWidget _hardwareInfoWidget; //std::vector> privateJsondatas;//路径与数据 //std::vector> privateWidgets;//路径与数据 //std::vectorjsonLayouts; diff --git a/src/launcher/GUI/front/pages/sqlControlWidget.h b/src/launcher/GUI/pages/sqlControlWidget.h similarity index 98% rename from src/launcher/GUI/front/pages/sqlControlWidget.h rename to src/launcher/GUI/pages/sqlControlWidget.h index f4c0a21..e090532 100644 --- a/src/launcher/GUI/front/pages/sqlControlWidget.h +++ b/src/launcher/GUI/pages/sqlControlWidget.h @@ -113,8 +113,7 @@ public: // 导出数据 bool success = false; if (db) { - std::mutex mutex; - success = db->exportTableToCSV(tableName, filePath, mutex); + success = db->exportTableToCSV(tableName, filePath); } // 提示导出结果 diff --git a/src/launcher/GUI/front/pages/summaryDataPage.h b/src/launcher/GUI/pages/summaryDataPage.h similarity index 100% rename from src/launcher/GUI/front/pages/summaryDataPage.h rename to src/launcher/GUI/pages/summaryDataPage.h diff --git a/src/launcher/GUI/paramEditorDialog.h b/src/launcher/GUI/paramEditorDialog.h index 27edfb4..ad71bb6 100644 --- a/src/launcher/GUI/paramEditorDialog.h +++ b/src/launcher/GUI/paramEditorDialog.h @@ -60,7 +60,7 @@ public: m_tableView->setItemDelegateForColumn(0, new QStyledItemDelegate(m_tableView)); m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows); m_tableView->setSelectionMode(QAbstractItemView::SingleSelection); - m_tableView->setColumnWidth(0, 120); // 可根据实际调整 + m_tableView->setColumnWidth(0, 280); // 禁止第一列选中 m_tableView->setColumnHidden(0, false); // 显示第一列 @@ -225,6 +225,7 @@ private slots: //result.push_back({ key, convertedValue }); emit qtFuncBridge::getInstance()->editParam(key, convertedValue); } + emit qtFuncBridge::getInstance()->saveMissionJson(); this->close(); delete this; //qDebug() << "Result JSON: " << QString::fromStdString(result.dump(4)); @@ -344,6 +345,7 @@ private: errorMsg = QString("获取值错误: %1").arg(e.what()); return false; } + return false; } // 更新模型中的数据项 diff --git a/src/launcher/GUI/pluginManager/pluginManager.h b/src/launcher/GUI/pluginManager/pluginManager.h deleted file mode 100644 index 4799c82..0000000 --- a/src/launcher/GUI/pluginManager/pluginManager.h +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -static std::string config_path = "./config/pluginConfig.json"; -struct PluginData -{ - std::string plugin_name = "ERROR"; - std::string plugin_path; - bool disabled; - bool auto_run; - nlohmann::json plugin_setting; - - IPlugin* plugin_ptr; - HMODULE HMODULE_; -}; -class EventManager { -public: - void subscribe(Event::EventType type, IPlugin* listener) { - listeners[type].push_back(listener); - } - - void unsubscribe(Event::EventType type, IPlugin* listener) { - auto& lst = listeners[type]; - lst.erase(std::remove(lst.begin(), lst.end(), listener), lst.end()); - } - - void publish(const Event& event) { - for (auto listener : listeners[event.type]) { - listener->onEvent(event); - } - } - -private: - std::unordered_map> listeners; -}; -class PluginManager { -public: - PluginManager() - { - init(); - } - void init() { - LoadJson(config_path); - for (auto& plugin_data : plugin_list) - { - LoadPlugin(plugin_data.second.plugin_path); - } - }; - PluginData LoadPlugin(std::string& plugin_path); - void LoadPlugin(PluginData& plugin_data); - void RemovePlugin(PluginData& plugin_data); - - void LoadJson(std::string path = config_path); - void SaveJson(std::string path = config_path); - void LoadAllPlugin(); - - std::vector getList() { - std::vector result; - for (auto& plugin : plugin_list){ - result.push_back(plugin.second); - } - return result; - } -private: - QMutex mutex; - QMutex jsonMutex; - std::unordered_mapplugin_list;//key路径 -}; -#pragma once \ No newline at end of file diff --git a/src/launcher/GUI/pluginManager/pluginManger.cpp b/src/launcher/GUI/pluginManager/pluginManger.cpp deleted file mode 100644 index bc6793a..0000000 --- a/src/launcher/GUI/pluginManager/pluginManger.cpp +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include -#include -#include -#include -#include - -typedef IPlugin* (*CreatePluginFunc)(); -typedef void (*DestroyPluginFunc)(IPlugin*); -PluginData PluginManager::LoadPlugin(std::string& plugin_path) -{ - - PluginData plugin_data; - auto it = plugin_list.find(plugin_path); - if (it != plugin_list.end()) - { - plugin_data.plugin_name = "exist"; - return plugin_data; - } - - CreatePluginFunc createPluginFunc; - DestroyPluginFunc destroyPluginFunc; - HMODULE dllHandle = LoadLibrary(plugin_path.c_str()); - if (dllHandle == nullptr) { - std::cerr << "Failed to load DLL: " << plugin_path << std::endl; - plugin_data.plugin_name = "dll handle error"; - return plugin_data; - } - - // 获取工厂函数 - createPluginFunc = (CreatePluginFunc)GetProcAddress(dllHandle, "createPlugin"); - destroyPluginFunc = (DestroyPluginFunc)GetProcAddress(dllHandle, "destroyPlugin"); - - if (!createPluginFunc || !destroyPluginFunc) { - std::cerr << "Failed to get functions from DLL" << std::endl; - FreeLibrary(dllHandle); - dllHandle = nullptr; - plugin_data.plugin_name = "none func found"; - return plugin_data; - } - auto plugin_ptr = createPluginFunc(); - - //插入插件数据 - plugin_data.plugin_name = plugin_ptr->name; - plugin_data.plugin_path = plugin_path; - plugin_data.disabled = true; - plugin_data.auto_run = false; - plugin_data.plugin_ptr = plugin_ptr; - plugin_data.HMODULE_ = dllHandle; - plugin_list.insert(std::make_pair(plugin_data.plugin_path, plugin_data)); - - SaveJson(); - return plugin_data; - // 创建插件实例 - //plugin_data.plugin_ptr = createPluginFunc(); - //plugin_data.HMODULE_ = dllHandle; - //pluginList.emplace_back(plugin, dllHandle); -} -void PluginManager::LoadPlugin(PluginData& plugin_data) -{ - - CreatePluginFunc createPluginFunc; - DestroyPluginFunc destroyPluginFunc; - HMODULE dllHandle = LoadLibrary(plugin_data.plugin_path.c_str()); - if (dllHandle == nullptr) { - std::cerr << "Failed to load DLL: " << plugin_data.plugin_path << std::endl; - return; - } - - // 获取工厂函数 - createPluginFunc = (CreatePluginFunc)GetProcAddress(dllHandle, "createPlugin"); - destroyPluginFunc = (DestroyPluginFunc)GetProcAddress(dllHandle, "destroyPlugin"); - - if (!createPluginFunc || !destroyPluginFunc) { - std::cerr << "Failed to get functions from DLL" << std::endl; - FreeLibrary(dllHandle); - dllHandle = nullptr; - return; - } - - // 创建插件实例 - plugin_data.plugin_ptr = createPluginFunc(); - plugin_data.HMODULE_ = dllHandle; - //pluginList.emplace_back(plugin, dllHandle); -} -void PluginManager::RemovePlugin(PluginData& plugin_data) { - if (plugin_list.size() == 0) - return; - QMutexLocker locker(&mutex); - IPlugin* plugin = plugin_data.plugin_ptr; - HMODULE hDll = plugin_data.HMODULE_; - - auto destroyPlugin = (void (*)(IPlugin*))GetProcAddress(hDll, "destroyPlugin"); - if (destroyPlugin) { - destroyPlugin(plugin); - } - - FreeLibrary(hDll); - auto it = plugin_list.find(plugin_data.plugin_path); - if (it != plugin_list.end()) - plugin_list.erase(it); - SaveJson(); -} - -void PluginManager::LoadJson(std::string path) -{ - QMutexLocker locker(&jsonMutex); - try{ - nlohmann::json jsonObj = readJsonFromPath(path); - for (auto it = jsonObj.begin(); it != jsonObj.end(); ++it){ - PluginData data; - data.plugin_name = it.key(); - auto value = it.value(); - data.plugin_path = value["path"]; - data.disabled = value["disabled"]; - data.auto_run = value["autoRun"]; - data.plugin_setting = value["pluginSetting"]; - plugin_list.insert(std::make_pair(data.plugin_path, data)); - } - std::vectorvec; - /* for (auto& json : jsonObj) - vec.push_back(json.) ;*/ - } - catch (...){ - - } -} -void PluginManager::SaveJson(std::string path) { - QMutexLocker locker(&jsonMutex); - nlohmann::json jsonObj; - for (auto& it : plugin_list) { - nlohmann::json obj; - obj["path"] = it.second.plugin_path; - obj["disabled"] = it.second.disabled; - obj["autoRun"] = it.second.auto_run; - obj["pluginSetting"] = it.second.plugin_setting; - jsonObj[it.second.plugin_name] = obj; - } - saveJsonFromPath(path, jsonObj); -} -void PluginManager::LoadAllPlugin() { - for (auto& data : plugin_list) - { - LoadPlugin(data.second); - } -} \ No newline at end of file diff --git a/src/launcher/GUI/uiModule/uiModule_cameraRealTimeCapture.h b/src/launcher/GUI/uiModule/uiModule_cameraRealTimeCapture.h index e498be6..7778dc6 100644 --- a/src/launcher/GUI/uiModule/uiModule_cameraRealTimeCapture.h +++ b/src/launcher/GUI/uiModule/uiModule_cameraRealTimeCapture.h @@ -11,12 +11,14 @@ #include #include #include +#include //实时取流线程 class GrabbingThread :public QThread { public: - GrabbingThread(QLabel* showImageLabelIN, QMutex* mutex) { + GrabbingThread(QLabel* showImageLabelIN, QMutex* mutexIn) { showImageLabel = showImageLabelIN; + mutex = mutexIn; } void setCameraName(std::string cameraNameIN) { cameraName = cameraNameIN; diff --git a/src/launcher/GUI/uiModule/uiModule_histogramWidget.h b/src/launcher/GUI/uiModule/uiModule_histogramWidget.h index c895a99..0c66a55 100644 --- a/src/launcher/GUI/uiModule/uiModule_histogramWidget.h +++ b/src/launcher/GUI/uiModule/uiModule_histogramWidget.h @@ -191,164 +191,14 @@ protected: } }; -//class histogramWidget : public QWidget { -// Q_OBJECT -//public: -// histogramWidget(QString title, QWidget* parent = nullptr) -// : QWidget(parent), enableAnimation(true) -// { -// setStyleSheet("background-color: rgb(50, 55, 60); color: white;"); -// initUI(title); -// initChart(); -// } -// -// void setTitle(const QString& text) { -// titleLabel->setText(text); -// } -// -// void setStats(int total, int bad, int good, double goodRate) { -// labelLeft->setText(QString(u8"检测总数: %1\n不良数: %2").arg(total).arg(bad)); -// labelRight->setText(QString(u8"良品数: %1\n良品率: %2%").arg(good).arg(goodRate, 0, 'f', 2)); -// } -// -// void addBarCategory(const QString& category, double value) { -// categories << category; -// *barSet << value; -// updateChart(); -// } -// -// void clearBarData() { -// categories.clear(); -// barSet->remove(0, barSet->count()); -// updateChart(); -// } -// -// void setAnimationEnabled(bool enabled) { -// enableAnimation = enabled; -// chart->setAnimationOptions(enableAnimation ? QChart::SeriesAnimations : QChart::NoAnimation); -// } -// -//private: -// QLabel* titleLabel; -// QLabel* labelLeft; -// QLabel* labelRight; -// QChart* chart; -// QChartView* chartView; -// QBarSet* barSet; -// QStringList categories; -// bool enableAnimation; -// -// void initUI(QString title) { -// QVBoxLayout* mainLayout = new QVBoxLayout(this); -// -// titleLabel = new QLabel(title); -// titleLabel->setStyleSheet("font-size: 16px; font-weight: bold;"); -// mainLayout->addWidget(titleLabel); -// -// QHBoxLayout* dataLayout = new QHBoxLayout(); -// labelLeft = new QLabel(u8"检测总数\n不良数"); -// labelRight = new QLabel(u8"良品数\n良品率"); -// labelLeft->setAlignment(Qt::AlignLeft); -// labelRight->setAlignment(Qt::AlignLeft); -// dataLayout->addWidget(labelLeft); -// dataLayout->addStretch(); -// dataLayout->addWidget(labelRight); -// mainLayout->addLayout(dataLayout); -// -// chartView = new QChartView(); -// chartView->setRenderHint(QPainter::Antialiasing); -// mainLayout->addWidget(chartView); -// -// this->setStyleSheet( -// "QLineEdit { background-color: rgb(50, 55, 60); color: white; border-radius: 4px; padding: 2px; } " -// "QLabel { color: white; } " -// ); -// } -// -// void initChart() { -// barSet = new QBarSet("数量"); -// *barSet << 0; // 初始一个数据 -// -// QBarSeries* series = new QBarSeries(); -// series->append(barSet); -// -// chart = new QChart(); -// chart->addSeries(series); -// chart->setBackgroundVisible(false); -// chart->legend()->hide(); -// chart->setAnimationOptions(enableAnimation ? QChart::SeriesAnimations : QChart::NoAnimation); -// -// QBarCategoryAxis* axisX = new QBarCategoryAxis(); -// axisX->append(categories); -// chart->addAxis(axisX, Qt::AlignBottom); -// series->attachAxis(axisX); -// -// QValueAxis* axisY = new QValueAxis(); -// axisY->setLabelFormat("%.0f"); -// axisY->setLabelsBrush(QBrush(QColor(255, 255, 255))); -// axisY->setRange(0, 100); // 初始范围,后面会动态调整 -// chart->addAxis(axisY, Qt::AlignLeft); -// series->attachAxis(axisY); -// -// chartView->setChart(chart); -// -// chartView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); -// chartView->setContentsMargins(0, 0, 0, 0); -// chartView->setStyleSheet("background-color: rgb(50, 55, 60); border: none;"); -// chart->setMargins(QMargins(0, 0, 0, 0)); // 去掉 QChart 的四周空白 -// chart->setBackgroundBrush(QBrush(QColor(50, 55, 60))); -// } -// -// void updateChart() { -// QMutexLocker locker(&mutex); -// chart->removeAllSeries(); -// -// QBarSeries* series = new QBarSeries(); -// series->append(barSet); -// chart->addSeries(series); -// -// QBarCategoryAxis* axisX = new QBarCategoryAxis(); -// axisX->append(categories); -// chart->addAxis(axisX, Qt::AlignBottom); -// series->attachAxis(axisX); -// -// QValueAxis* axisY = new QValueAxis(); -// axisY->setLabelFormat("%.0f"); -// // 添加每个柱子上方的数值标签 -// for (int i = 0; i < barSet->count(); ++i) { -// QGraphicsSimpleTextItem* label = new QGraphicsSimpleTextItem(QString::number((*barSet)[i])); -// label->setBrush(QBrush(Qt::white)); -// QPointF pos = chart->mapToPosition(QPointF(i, (*barSet)[i]), series); -// label->setPos(pos.x() - 5, pos.y() - 20); -// chart->scene()->addItem(label); -// } -// -// chart->setAnimationOptions(enableAnimation ? QChart::SeriesAnimations : QChart::NoAnimation); -// } -// -//protected: -// void paintEvent(QPaintEvent* event) override { -// QPainter painter(this); -// painter.setRenderHint(QPainter::Antialiasing); -// -// int radius = 10; -// QRect r = rect(); -// -// painter.setBrush(QColor(50, 55, 60)); -// painter.setPen(Qt::NoPen); -// painter.drawRoundedRect(r, radius, radius); -// } -//private: -// QMutex mutex; -//}; - class dayNightShiftHistogramWidget : public QWidget { public: histogramWidget* dayHistogramWidget; histogramWidget* nightHistogramWidget; dayNightShiftHistogramWidget() { - dayHistogramWidget = new histogramWidget("白班(08:30-20:30)"); - nightHistogramWidget = new histogramWidget("夜班(20:30-08:30)"); + QString ymd = QDate::currentDate().toString("yyyy-MM-dd"); + dayHistogramWidget = new histogramWidget(ymd + "白班(08:30-20:30)"); + nightHistogramWidget = new histogramWidget(ymd +"夜班(20:30-08:30)"); QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); @@ -366,15 +216,18 @@ public: //} void addDefect(std::vectordefects) { bool isDay = isDayShiftNow(); - //判断是否切换班次,如切换则清空下个班次的数据 + //判断是否切换班次,如切换则清空当前班次的数据 if (lastIsDayState != isDay) { + QString ymd = QDate::currentDate().toString("yyyy-MM-dd"); if (isDay == true) { - nightHistogramWidget->clearBarData(); - nightDefectMap.clear(); - } - else { dayHistogramWidget->clearBarData(); dayDefectMap.clear(); + dayHistogramWidget->setTitle(ymd + "白班(08:30-20:30)"); + } + else { + nightHistogramWidget->clearBarData(); + nightDefectMap.clear(); + nightHistogramWidget->setTitle(ymd + "夜班(20:30-08:30)"); } okCnt = 0; ngCnt = 0; diff --git a/src/launcher/GUI/uiModule/uiModule_imageView.h b/src/launcher/GUI/uiModule/uiModule_imageView.h index 2db683f..7f11d38 100644 --- a/src/launcher/GUI/uiModule/uiModule_imageView.h +++ b/src/launcher/GUI/uiModule/uiModule_imageView.h @@ -97,6 +97,9 @@ public: setInteractive(false); setEnabled(false); setObjectName("SonGraphicsView"); + // 缩放以鼠标位置为锚点 + setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + setResizeAnchor(QGraphicsView::AnchorViewCenter); //scene->addItem(rectGroup); setScene(scene); @@ -138,12 +141,18 @@ protected: if (scene->items().isEmpty()) return; - QPoint numDegrees = event->angleDelta() / 8; - if (!numDegrees.isNull()) { - zoom(numDegrees / 15); - centerOn(currentPos); + // 支持高分辨率触控板与普通滚轮,按步进平滑缩放 + const QPoint angle = event->angleDelta(); + double steps = 0.0; + if (!angle.isNull()) { + steps = static_cast(angle.y()) / 120.0; // 120 == one step } - event->accept(); + if (steps != 0.0) { + zoom(steps); + event->accept(); + return; + } + QGraphicsView::wheelEvent(event); } void keyPressEvent(QKeyEvent* event) override { @@ -233,6 +242,30 @@ private: QMutex mutex; + // 计算当前视图适配整图时的缩放倍率 + double fitScale() const { + if (!pixmapItem) return 1.0; + QRectF br = pixmapItem->boundingRect(); + if (br.isEmpty()) return 1.0; + QSize vp = viewport()->size(); + if (vp.width() <= 0 || vp.height() <= 0) return 1.0; + double sx = static_cast(vp.width()) / br.width(); + double sy = static_cast(vp.height()) / br.height(); + return std::min(sx, sy); + } + + // 根据当前内容更新缩放上下限 + void updateZoomBounds() { + double f = fitScale(); + minScaleBound = std::max(f * 0.2, 1e-3); // 最小可视缩放(不至于太小) + maxScaleBound = std::max(minScaleBound * 500.0, f * 50.0); // 最大放大倍数 + } + + // 获取当前统一缩放(假设等比缩放) + double currentScale() const { + return transform().m11(); + } + void showImg(const QPixmap& img) { QMutexLocker locker(&mutex); setEnabled(true); @@ -251,19 +284,40 @@ private: scene->addItem(pixmapItem); setSceneRect(img.rect()); + // 重置变换并自适应居中显示 + resetTransform(); fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio); + updateZoomBounds(); } + // 旧接口保留,转调到新的双精度缩放 void zoom(const QPoint& factor) { - QRectF FOV = mapToScene(rect()).boundingRect(); - float scaleX = static_cast(imageWidth) / FOV.width(); - float scaleY = static_cast(imageHeight) / FOV.height(); + zoom(static_cast(factor.y())); + } - double currentScale = transform().m11(); - if ((factor.y() > 0 && currentScale > 10.0) || (factor.y() < 0 && currentScale < 0.1)) - return; + // 新的缩放实现:按步进平滑缩放,并限制上下限 + void zoom(double steps) { + if (steps == 0.0 || !pixmapItem) return; + // 每个滚轮档位使用指数缩放,数值可根据体验调整 + const double perStep = 1.15; // 单步缩放系数 + double desiredFactor = std::pow(perStep, steps); - scale(factor.y() > 0 ? 1.2 : 0.8, factor.y() > 0 ? 1.2 : 0.8); + double cur = currentScale(); + // 目标缩放值(绝对) + double target = cur * desiredFactor; + // 边界更新并裁剪 + updateZoomBounds(); + if (target < minScaleBound) target = minScaleBound; + if (target > maxScaleBound) target = maxScaleBound; + // 需要应用的相对缩放 + double apply = target / cur; + if (std::abs(apply - 1.0) < 1e-6) return; + scale(apply, apply); + } + + void centerOnImageCenter() { + if (!pixmapItem) return; + centerOn(pixmapItem); } void togglePan(bool pan, const QPoint& startPos = QPoint()) { @@ -296,6 +350,10 @@ private: } }*/ } + + // 缩放界限(根据内容动态调整) + double minScaleBound = 1e-3; + double maxScaleBound = 1e6; }; //切换窗口 在切换时用pixmap替换现有的以实现 class ImageWidget : public QWidget { @@ -386,7 +444,8 @@ public: layout->addWidget(viewer); viewer->setDragMode(QGraphicsView::ScrollHandDrag); - viewer->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + // 以鼠标为缩放锚点 + viewer->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); viewer->setRenderHint(QPainter::Antialiasing); viewer->setRenderHint(QPainter::SmoothPixmapTransform); viewer->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -536,23 +595,14 @@ public slots: // 保存原始状态 originalSize = this->size(); - // 在网格布局中重新放置,占据更多空间 + // 在网格布局中重新放置,占据整个布局 parentGridLayout->removeWidget(this); - //计算父布局的总行数和总列数 - int maxRowSpan = parentGridLayout->rowCount();// 父布局总行数 - int maxColSpan = parentGridLayout->columnCount();// 父布局总列数 - //放大后的跨度 - int zoomColSize = maxColSpan - 1; - int zoomRowSize = maxRowSpan - 1; - if (originalRow >= zoomRowSize -1 || originalColumn >= zoomColSize -1) { - int x = qMax(0, originalRow - (zoomRowSize - 1)); - int y = qMax(0, originalColumn - (zoomColSize - 1)); - parentGridLayout->addWidget(this, x, y, zoomRowSize, zoomColSize); - } - else{ - parentGridLayout->addWidget(this, originalRow, originalColumn, zoomRowSize, zoomColSize); - } + int maxRowSpan = std::max(1, parentGridLayout->rowCount()); + int maxColSpan = std::max(1, parentGridLayout->columnCount()); + + // 直接从(0,0)开始,跨越整个网格,避免计算产生的0或负跨度 + parentGridLayout->addWidget(this, 0, 0, maxRowSpan, maxColSpan); this->raise(); // 更新按钮状态 @@ -570,7 +620,11 @@ public slots: // 恢复原始布局位置 parentGridLayout->removeWidget(this); - parentGridLayout->addWidget(this, originalRow, originalColumn, originalRowSpan, originalColumnSpan); + parentGridLayout->addWidget(this, + std::max(0, originalRow), + std::max(0, originalColumn), + std::max(1, originalRowSpan), + std::max(1, originalColumnSpan)); //更新按钮状态 isZoomed = false; diff --git a/src/launcher/GUI/uiModule/uiModule_kakong.h b/src/launcher/GUI/uiModule/uiModule_kakong.h deleted file mode 100644 index 2595a23..0000000 --- a/src/launcher/GUI/uiModule/uiModule_kakong.h +++ /dev/null @@ -1,620 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -static QString convertSecondsToDateTime(unsigned long long seconds) { - // 将秒数转换为时间点 - std::chrono::seconds sec(seconds); - std::chrono::time_point timePoint(sec); - - // 转换为时间戳 - auto time = std::chrono::system_clock::to_time_t(timePoint); - - // 使用 QDateTime 来格式化时间 - QDateTime dateTime = QDateTime::fromTime_t(static_cast(time)); - - // 将时间转换为指定格式的 QString - QString formattedDateTime = dateTime.toString("yyyy-MM-dd hh:mm:ss"); - - return formattedDateTime; -} -struct kaKongData -{ - QString Name; - int type = 0; - unsigned long long startTimeM = 0; - unsigned long long keepTime = 0; - bool banBie = false; - bool baiBan = false; - bool yeBan = false; - - bool louDong = false; - int louDongMin = 0; - int louDongMax = 0; - - bool louCeng = false; - int louCengMin = 0; - int louCengMax = 0; - - bool xianTi = false; - int xianTiMin = 0; - int xianTiMax = 0; - - bool jiTai = false; - int jiTaiHaoMin = 0; - int jiTaiHaoMax = 0; - - bool riQi = false; - int riQiMin = 0; - int riQiMax = 0; -}; -class CustomWidget : public QWidget { -public: - CustomWidget(QWidget* parent = nullptr) : QWidget(parent) {} - -protected: - void paintEvent(QPaintEvent* event) override { - Q_UNUSED(event); - - QPainter painter(this); - painter.setPen(Qt::black); // 设置画笔颜色为黑色 - painter.drawRect(rect().adjusted(0, 0, -1, -1)); // 绘制边框 - } -}; -class kakongSonWidget -{ - -public: - QWidget* widget; - QCheckBox* checkBox; - QCheckBox* baiBan; - QCheckBox* yeBanBan; - kakongSonWidget(QString title) - { - widget = new CustomWidget(); - QVBoxLayout* layout = new QVBoxLayout(); - widget->setLayout(layout); - { - QHBoxLayout* hLayout = new QHBoxLayout(); - QLabel* label = new QLabel(title); - checkBox = new QCheckBox(); - QLabel* label2 = new QLabel(u8"启用"); - hLayout->addWidget(label); - hLayout->addWidget(checkBox); - hLayout->addWidget(label2); - layout->addLayout(hLayout); - } - { - baiBan = new QCheckBox(); - QLabel* label = new QLabel(u8"白班"); - QHBoxLayout* hLayout = new QHBoxLayout(); - hLayout->addWidget(baiBan); - hLayout->addWidget(label); - layout->addLayout(hLayout); - } - { - yeBanBan = new QCheckBox(); - QLabel* label = new QLabel(u8"夜班"); - QHBoxLayout* hLayout = new QHBoxLayout(); - hLayout->addWidget(yeBanBan); - hLayout->addWidget(label); - layout->addLayout(hLayout); - } - QLineEdit* lineEdit = new QLineEdit(); - } -}; -class kakongSonWidget2 -{ - -public: - QWidget* widget; - QCheckBox* checkBox; - QLineEdit* minLineEdit; - QLineEdit* maxLineEdit; - kakongSonWidget2(QString title) - { - widget = new CustomWidget(); - QVBoxLayout* layout = new QVBoxLayout(); - widget->setLayout(layout); - { - QHBoxLayout* hLayout = new QHBoxLayout(); - QLabel* label = new QLabel(title); - checkBox = new QCheckBox(); - QLabel* label2 = new QLabel(u8"启用"); - hLayout->addWidget(label); - hLayout->addWidget(checkBox); - hLayout->addWidget(label2); - layout->addLayout(hLayout); - } - { - QLabel* label = new QLabel(u8"最小"); - minLineEdit = new QLineEdit(); - minLineEdit->setFixedWidth(60); - QHBoxLayout* hLayout = new QHBoxLayout(); - hLayout->addWidget(label); - hLayout->addWidget(minLineEdit); - layout->addLayout(hLayout); - } - { - QLabel* label = new QLabel(u8"最大"); - maxLineEdit =new QLineEdit(); - maxLineEdit->setFixedWidth(60); - QHBoxLayout* hLayout = new QHBoxLayout(); - hLayout->addWidget(label); - hLayout->addWidget(maxLineEdit); - layout->addLayout(hLayout); - } - QLineEdit* lineEdit = new QLineEdit(); - } -}; -class kakong -{ -public: - - QWidget *widget; - QHBoxLayout* layout; - QLineEdit* lineEdit; - QSpinBox* spinBox; - QLabel* icon; - - QLabel* restTimeH; - QLabel* restTimeM; - QLabel* restTimeS; - - QLabel* startTime; - QListWidget* listWidget; - QPushButton* saveBtn; - QPushButton* cancelBtn; - bool tikTok = false; - QList< kaKongData>datas; - kakongSonWidget* banBieWidget; - kakongSonWidget2* louDongWidget; - kakongSonWidget2* louCengWidget; - kakongSonWidget2* xianTiWidget; - kakongSonWidget2* jiTaiWidget; - kakongSonWidget2* riQiWidget; - - unsigned long long nowStartTimeM = 0; - unsigned long long nowKeepTime = 0; - - QPushButton* clearBtn; - QPushButton* delBtn; - QPushButton* cancelBtn2; - int currentIndex = -1; - - QPushButton* cnc3btn; - QPushButton* cnc5btn; - QPushButton* cnc6btn; - void loadDataFromJson() - { - QList dataList; - - // 打开 JSON 文件并读取数据 - QFile file(".\\config\\kakong.json"); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QByteArray jsonData = file.readAll(); - file.close(); - - // 解析 JSON 数据 - QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); - if (jsonDoc.isArray()) { - QJsonArray dataArray = jsonDoc.array(); - - // 逐个读取 JSON 数组中的对象,并添加到 dataList 中 - for (const QJsonValue& value : dataArray) { - if (value.isObject()) { - QJsonObject obj = value.toObject(); - kaKongData data; - data.Name = obj["Name"].toString(); - data.type = obj["type"].toInt(); - data.startTimeM = obj["startTimeM"].toVariant().toULongLong(); - data.keepTime = obj["keepTime"].toVariant().toULongLong(); - data.banBie = obj["banBie"].toBool(); - data.baiBan = obj["baiBan"].toBool(); - data.yeBan = obj["yeBan"].toBool(); - data.louDong = obj["louDong"].toBool(); - data.louDongMin = obj["louDongMin"].toInt(); - data.louDongMax = obj["louDongMax"].toInt(); - data.louCeng = obj["louCeng"].toBool(); - data.louCengMin = obj["louCengMin"].toInt(); - data.louCengMax = obj["louCengMax"].toInt(); - data.xianTi = obj["xianTi"].toBool(); - data.xianTiMin = obj["xianTiMin"].toInt(); - data.xianTiMax = obj["xianTiMax"].toInt(); - data.jiTai = obj["jiTai"].toBool(); - data.jiTaiHaoMin = obj["jiTaiHaoMin"].toInt(); - data.jiTaiHaoMax = obj["jiTaiHaoMax"].toInt(); - data.riQi = obj["riQi"].toBool(); - data.riQiMin = obj["riQiMin"].toInt(); - data.riQiMax = obj["riQiMax"].toInt(); - - dataList.append(data); - } - } - } - else { - qDebug() << "JSON 文件不是一个数组。"; - } - } - else { - qDebug() << "无法打开文件:" ; - } - - datas = dataList; - reFreshList(); - } - - void saveToJson() - { - QJsonArray dataArray; - - // 将数据列表转换为 JSON 数组 - for (const kaKongData& data : datas) { - QJsonObject obj; - obj["Name"] = data.Name; - obj["type"] = data.type; - obj["startTimeM"] = static_cast(data.startTimeM); - obj["keepTime"] = static_cast(data.keepTime); - obj["banBie"] = data.banBie; - obj["baiBan"] = data.baiBan; - obj["yeBan"] = data.yeBan; - obj["louDong"] = data.louDong; - obj["louDongMin"] = data.louDongMin; - obj["louDongMax"] = data.louDongMax; - obj["louCeng"] = data.louCeng; - obj["louCengMin"] = data.louCengMin; - obj["louCengMax"] = data.louCengMax; - obj["xianTi"] = data.xianTi; - obj["xianTiMin"] = data.xianTiMin; - obj["xianTiMax"] = data.xianTiMax; - obj["jiTai"] = data.jiTai; - obj["jiTaiHaoMin"] = data.jiTaiHaoMin; - obj["jiTaiHaoMax"] = data.jiTaiHaoMax; - obj["riQi"] = data.riQi; - obj["riQiMin"] = data.riQiMin; - obj["riQiMax"] = data.riQiMax; - - dataArray.append(obj); - } - - // 创建 JSON 文档 - QJsonDocument doc(dataArray); - - // 将 JSON 数据保存到文件 - QFile file(".\\config\\kakong.json"); - if (file.open(QIODevice::WriteOnly)) { - file.write(doc.toJson()); - file.close(); - qDebug() << "数据已保存到文件:" << ".\\config\\kakong.json"; - } - else { - qDebug() << "无法打开文件进行保存:" << ".\\config\\kakong.json"; - } - } - kakong() - { - - widget = new QWidget(); - QVBoxLayout* Vlayout = new QVBoxLayout(); - layout = new QHBoxLayout(); - widget->setLayout(layout); - layout->addLayout(Vlayout); - /// - QHBoxLayout* hLayout = new QHBoxLayout(); - QLabel* label = new QLabel(u8"配方"); - lineEdit=new QLineEdit(); - QLabel* label2 = new QLabel(u8"卡控时间"); - spinBox = new QSpinBox(); - QLabel* label3 = new QLabel(u8"小时|有效时间"); - restTimeH =new QLabel(u8"0"); - QLabel* label4 = new QLabel(u8"小时"); - restTimeM = new QLabel(u8"0"); - QLabel* label6 = new QLabel(u8"分钟"); - restTimeS = new QLabel(u8"0"); - QLabel* label7 = new QLabel(u8"秒"); - icon= new QLabel(); - icon->setFixedHeight(20); - icon->setFixedWidth(20); - setIconColor(true); - QLabel* label5 = new QLabel(u8"开始时间"); - startTime = new QLabel(u8"0"); - hLayout->addWidget(label); - hLayout->addWidget(lineEdit); - hLayout->addWidget(label2); - hLayout->addWidget(spinBox); - hLayout->addWidget(label3); - hLayout->addWidget(restTimeH); - hLayout->addWidget(label4); - hLayout->addWidget(restTimeM); - hLayout->addWidget(label6); - hLayout->addWidget(restTimeS); - hLayout->addWidget(label7); - hLayout->addWidget(icon); - hLayout->addWidget(label5); - hLayout->addWidget(startTime); - Vlayout->addLayout(hLayout); - { - QHBoxLayout* hLayout2 = new QHBoxLayout(); - cnc3btn = new QPushButton(u8"cnc3"); - cnc3btn->setDisabled(true); - cnc5btn = new QPushButton(u8"cnc5"); - cnc6btn = new QPushButton(u8"cnc6"); - cnc3btn->setFixedWidth(120); - cnc5btn->setFixedWidth(120); - cnc6btn->setFixedWidth(120); - hLayout2->addWidget(cnc3btn); - hLayout2->addWidget(cnc5btn); - hLayout2->addWidget(cnc6btn); - hLayout2->setAlignment(Qt::AlignLeft); - Vlayout->addLayout(hLayout2); - } - { - QHBoxLayout* hLayout2 = new QHBoxLayout(); - banBieWidget = new kakongSonWidget(u8"班别"); - hLayout2->addWidget(banBieWidget->widget); - louDongWidget = new kakongSonWidget2(u8"楼栋"); - hLayout2->addWidget(louDongWidget->widget); - louCengWidget = new kakongSonWidget2(u8"楼层"); - hLayout2->addWidget(louCengWidget->widget); - xianTiWidget = new kakongSonWidget2(u8"线体"); - hLayout2->addWidget(xianTiWidget->widget); - jiTaiWidget = new kakongSonWidget2(u8"机台号"); - hLayout2->addWidget(jiTaiWidget->widget); - riQiWidget = new kakongSonWidget2(u8"日期"); - hLayout2->addWidget(riQiWidget->widget); - Vlayout->addLayout(hLayout2); - } - { - QHBoxLayout* hLayout2 = new QHBoxLayout(); - saveBtn = new QPushButton(u8"保存"); - cancelBtn = new QPushButton(u8"取消"); - saveBtn->setFixedWidth(120); - cancelBtn->setFixedWidth(120); - hLayout2->addWidget(saveBtn); - - hLayout2->addWidget(cancelBtn); - Vlayout->addLayout(hLayout2); - } - //////////// - { - QVBoxLayout*vlayout2 = new QVBoxLayout(); - QLabel* label = new QLabel(u8"配方管理"); - listWidget= new QListWidget(); - clearBtn = new QPushButton(u8"清空"); - delBtn = new QPushButton(u8"删除"); - cancelBtn2 = new QPushButton(u8"取消配方"); - vlayout2->addWidget(label); - vlayout2->addWidget(listWidget); - QHBoxLayout* hLayout2 = new QHBoxLayout(); - hLayout2->addWidget(clearBtn); - hLayout2->addWidget(delBtn); - vlayout2->addLayout(hLayout2); - vlayout2->addWidget(cancelBtn); - layout->addLayout(vlayout2); - } - loadDataFromJson(); - } - ~kakong() - { - saveToJson(); - } - void timerTask() - { - auto currentTime = std::chrono::system_clock::now(); - auto currentTimeStamp = std::chrono::time_point_cast(currentTime).time_since_epoch().count(); - unsigned long long nowTime = static_cast(currentTimeStamp); - int time = (nowKeepTime + nowStartTimeM) - nowTime; - if (time > 0) - { - int resH = time / 3600; - int resM = (time - resH * 3600) / 60; - int resS = (time - resH * 3600 - resM * 60) % 3600; - restTimeH->setText(QString::number(resH)); - restTimeM->setText(QString::number(resM)); - restTimeS->setText(QString::number(resS)); - } - else - { - setIconColor(true); - restTimeH->setText("0"); - restTimeM->setText("0"); - restTimeS->setText("0"); - } - } - void setIconColor(bool setRed) - { - if(setRed ==true) - icon->setStyleSheet("background-color: red;"); - else - icon->setStyleSheet("background-color: green;"); - } - void reFreshList() - { - listWidget->clear(); - for (auto data : datas) - { - listWidget->addItem(data.Name); - } - } - void listSelect(int row) - { - currentIndex = row; - auto currentTime = std::chrono::system_clock::now(); - auto currentTimeStamp = std::chrono::time_point_cast(currentTime).time_since_epoch().count(); - unsigned long long nowTime = static_cast(currentTimeStamp); - { - int time = datas[row].startTimeM; - startTime->setText(convertSecondsToDateTime(time)); - } - nowStartTimeM = datas[row].startTimeM; - nowKeepTime = datas[row].keepTime; - switch (datas[row].type) - { - case 1: - cnc3btn->setDisabled(true); - break; - case 2: - cnc5btn->setDisabled(true); - break; - case 3: - cnc6btn->setDisabled(true); - break; - } - if (datas[row].keepTime + datas[row].startTimeM < nowTime)//超过时间 - setIconColor(true); - else//有效 - { - setIconColor(false); - int time = (datas[row].keepTime + datas[row].startTimeM) - nowTime; - int resH = time / 3600; - int resM = (time- resH*3600) / 60; - int resS = (time - resH * 3600- resM*60) % 3600; - restTimeH->setText(QString::number(resH)); - restTimeM->setText(QString::number(resM)); - restTimeS->setText(QString::number(resS)); - } - lineEdit->setText(datas[row].Name); - - if (datas[row].banBie == true) - { - banBieWidget->checkBox->setChecked(true); - if (datas[row].baiBan == true) - banBieWidget->baiBan->setChecked(true); - if (datas[row].yeBan == true) - banBieWidget->yeBanBan->setChecked(true); - } - if (datas[row].louDong == true) - { - louDongWidget->checkBox->setChecked(true); - louDongWidget->minLineEdit->setText(QString::number(datas[row].louDongMin)); - louDongWidget->maxLineEdit->setText(QString::number(datas[row].louDongMax)); - } - if (datas[row].louCeng == true) - { - louCengWidget->checkBox->setChecked(true); - louCengWidget->minLineEdit->setText(QString::number(datas[row].louCengMin)); - louCengWidget->maxLineEdit->setText(QString::number(datas[row].louCengMax)); - } - if (datas[row].xianTi == true) - { - xianTiWidget->checkBox->setChecked(true); - xianTiWidget->minLineEdit->setText(QString::number(datas[row].xianTiMin)); - xianTiWidget->maxLineEdit->setText(QString::number(datas[row].xianTiMax)); - } - if (datas[row].jiTai == true) - { - jiTaiWidget->checkBox->setChecked(true); - jiTaiWidget->minLineEdit->setText(QString::number(datas[row].jiTaiHaoMin)); - jiTaiWidget->maxLineEdit->setText(QString::number(datas[row].jiTaiHaoMax)); - } - if (datas[row].riQi == true) - { - riQiWidget->checkBox->setChecked(true); - riQiWidget->minLineEdit->setText(QString::number(datas[row].riQiMin)); - riQiWidget->maxLineEdit->setText(QString::number(datas[row].riQiMax)); - } - } - void saveFunc() - { - auto currentTime = std::chrono::system_clock::now(); - auto currentTimeStamp = std::chrono::time_point_cast(currentTime).time_since_epoch().count(); - kaKongData newData; - newData.startTimeM = static_cast(currentTimeStamp); - newData.Name = lineEdit->text(); - newData.keepTime = spinBox->value() * 60 * 60; - if (cnc3btn->isEnabled() == false) - newData.type = 1; - else if (cnc5btn->isEnabled() == false) - newData.type = 2; - else if (cnc6btn->isEnabled() == false) - newData.type = 3; - if (banBieWidget->checkBox->isChecked() == true) - { - newData.banBie = true; - if (banBieWidget->baiBan->isChecked() == true) - newData.baiBan = true; - if (banBieWidget->yeBanBan->isChecked() == true) - newData.yeBan = true; - } - if (louDongWidget->checkBox->isChecked() == true) - { - newData.louDong = true; - newData.louDongMin = louDongWidget->minLineEdit->text().toInt(); - newData.louDongMax = louDongWidget->maxLineEdit->text().toInt(); - } - if (louCengWidget->checkBox->isChecked() == true) - { - newData.louCeng = true; - newData.louCengMin = louCengWidget->minLineEdit->text().toInt(); - newData.louCengMax = louCengWidget->maxLineEdit->text().toInt(); - } - if (xianTiWidget->checkBox->isChecked() == true) - { - newData.xianTi = true; - newData.xianTiMin = xianTiWidget->minLineEdit->text().toInt(); - newData.xianTiMax = xianTiWidget->maxLineEdit->text().toInt(); - } - if (jiTaiWidget->checkBox->isChecked() == true) - { - newData.jiTai = true; - newData.jiTaiHaoMin = jiTaiWidget->minLineEdit->text().toInt(); - newData.jiTaiHaoMax = jiTaiWidget->maxLineEdit->text().toInt(); - } - if (riQiWidget->checkBox->isChecked() == true) - { - newData.riQi = true; - newData.riQiMin = riQiWidget->minLineEdit->text().toInt(); - newData.riQiMax = riQiWidget->maxLineEdit->text().toInt(); - } - setIconColor(false); - datas.push_back(newData); - reFreshList(); - } - void delData() - { - if (currentIndex > 0) - { - nowStartTimeM = 0; - nowKeepTime = 0; - datas.removeAt(currentIndex); - reFreshList(); - } - } - void clearData() - { - listWidget->clear(); - currentIndex = -1; - datas.clear(); - nowStartTimeM = 0; - nowKeepTime = 0; - } - void cancelData() - { - nowStartTimeM = 0; - nowKeepTime = 0; - } - void cncSwitchTo3() - { - cnc3btn->setDisabled(true); - cnc5btn->setEnabled(true); - cnc6btn->setEnabled(true); - } - void cncSwitchTo5() - { - cnc5btn->setDisabled(true); - cnc3btn->setEnabled(true); - cnc6btn->setEnabled(true); - } - void cncSwitchTo6() - { - cnc6btn->setDisabled(true); - cnc5btn->setEnabled(true); - cnc3btn->setEnabled(true); - } -}; diff --git a/src/launcher/GUI/uiModule/uiModule_softwareDataDisplay.h b/src/launcher/GUI/uiModule/uiModule_softwareDataDisplay.h index 38083ef..aff8368 100644 --- a/src/launcher/GUI/uiModule/uiModule_softwareDataDisplay.h +++ b/src/launcher/GUI/uiModule/uiModule_softwareDataDisplay.h @@ -118,7 +118,7 @@ private slots: public slots: void onTriggerSateChanged(int loopCounterPerMin, int maxInterval) { int activeThreadCount = QThreadPool::globalInstance()->activeThreadCount(); - triggerState->setText(QString::number(loopCounterPerMin) + "L " + QString::number(maxInterval) + "ms " + QString::number(activeThreadCount) +"T"); + triggerState->setText(QString::number(loopCounterPerMin) + "L " + QString::number(maxInterval) + "ms " + QString::number(activeThreadCount) +"/" + QString::number(QThreadPool::globalInstance()->maxThreadCount()) + "T"); } private: QTimer* timer; diff --git a/src/launcher/appConfig/appConfig.cpp b/src/launcher/appConfig/appConfig.cpp index 786c9e8..7b14aa6 100644 --- a/src/launcher/appConfig/appConfig.cpp +++ b/src/launcher/appConfig/appConfig.cpp @@ -37,23 +37,4 @@ void appConfig::parsingSettingJson() v.viewers.assign(data.value()["viewer"].begin(), data.value()["viewer"].end()); viewDatas.push_back(v); } - - if (missionJson["backend"]["missionSettings"].contains("存储原图") == false) { - missionJson["backend"]["missionSettings"]["存储原图"] = true; - } - if (missionJson["backend"]["missionSettings"].contains("存储结果图") == false) { - missionJson["backend"]["missionSettings"]["存储结果图"] = true; - } - if (missionJson["backend"]["missionSettings"].contains("存储Seg图") == false) { - missionJson["backend"]["missionSettings"]["存储Seg图"] = true; - } - if (missionJson["backend"]["missionSettings"].contains("存储Cls图") == false) { - missionJson["backend"]["missionSettings"]["存储Cls图"] = true; - } - if (missionJson["backend"]["missionSettings"].contains("原图存图天数") == false) { - missionJson["backend"]["missionSettings"]["原图存图天数"] = true; - } - if (missionJson["backend"]["missionSettings"].contains("结果图存图天数") == false) { - missionJson["backend"]["missionSettings"]["结果图存图天数"] = true; - } } diff --git a/src/launcher/appConfig/appConfig.h b/src/launcher/appConfig/appConfig.h index 0456950..0797e4b 100644 --- a/src/launcher/appConfig/appConfig.h +++ b/src/launcher/appConfig/appConfig.h @@ -13,14 +13,13 @@ private: // 禁用拷贝构造函数和赋值运算符 appConfig(const appConfig&) = delete; appConfig& operator=(const appConfig&) = delete; - public: // 获取单例实例 static appConfig& getInstance() { static appConfig instance; return instance; } - + bool exitWithRestart = false; void parsingSettingJson(); void loadSetting() { parsingSettingJson(); diff --git a/src/launcher/appConfig/appExternalConfig.hpp b/src/launcher/appConfig/appExternalConfig.hpp deleted file mode 100644 index 93f88ac..0000000 --- a/src/launcher/appConfig/appExternalConfig.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -class appExternalConfig { -public: - void parse() - { - - } - -private: - //std::unordered_map dataMap; - //std::string configPath = "./config/externalData.json"; -}; -#pragma once \ No newline at end of file diff --git a/src/launcher/appCore.hpp b/src/launcher/appCore.hpp index 390de44..248ce56 100644 --- a/src/launcher/appCore.hpp +++ b/src/launcher/appCore.hpp @@ -8,7 +8,7 @@ // #include "interface.h" #include -#include +//#include #define HIDE_CONSOLE 1 class backEnd { @@ -60,7 +60,7 @@ class appCore : public QObject{ public: backEnd _backEnd; logService* _logService = logService::getInstance(); - systemStateMonitor* _systemStateMonitor = &systemStateMonitor::getInstance(); + //systemStateMonitor* _systemStateMonitor = &systemStateMonitor::getInstance(); appCore() { initConfig(); diff --git a/src/launcher/logger/qtLogRediretor.cpp b/src/launcher/logger/qtLogRediretor.cpp index 1d9a12a..3bc4122 100644 --- a/src/launcher/logger/qtLogRediretor.cpp +++ b/src/launcher/logger/qtLogRediretor.cpp @@ -9,10 +9,29 @@ static void qtMessageHandler(QtMsgType type, const QMessageLogContext& context, if (!qtRediretor_Ptr) { return; } - + QString typeText = ""; + switch (type) + { + case QtDebugMsg: + typeText = "DEBUG"; + break; + case QtWarningMsg: + typeText = "WARNING"; + break; + case QtCriticalMsg: + typeText = "ERROR"; + break; + case QtFatalMsg: + typeText = "ERROR"; + break; + default: + typeText = "INFO"; + break; + } // 构建格式化的日志消息 // 格式: [文件名:行号] 消息内容 - QString outputMessage = QString("[%1:%2] %3") + QString outputMessage = QString("[%1][%2:%3] %4") + .arg(typeText) .arg(QFileInfo(context.file).fileName()) .arg(context.line) .arg(msg); diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index 15d3d07..3e64d05 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -180,6 +180,17 @@ void connectSignalAndSlot(appCore* _core, MainWindow* _MainWindow, qtFuncBridge* _core->_backEnd.backend, &IBackend::getAllParams, Qt::DirectConnection); QObject::connect(bridge, &qtFuncBridge::editParam, _core->_backEnd.backend, &IBackend::editParam, Qt::DirectConnection); + QObject::connect(bridge, &qtFuncBridge::saveMissionJson, + _core->_backEnd.backend, [=]() { + auto &config = appConfig::getInstance(); + config.missionJson["backend"] = _core->_backEnd.backend->getJson(); + config.saveSettingJson(); + }, Qt::DirectConnection); + + QObject::connect(bridge, &qtFuncBridge::restartInit,[=]() { + appConfig::getInstance().exitWithRestart = true; + QApplication::quit(); + }); } int main(int argc, char* argv[]) @@ -243,5 +254,12 @@ int main(int argc, char* argv[]) if (config.dataBase) delete config.dataBase; config.dataBase = nullptr; }); - return a.exec(); + + int qtRes = a.exec(); + if (config.exitWithRestart) { + ShowWindow(hWnd, SW_SHOW); + std::cout << "程序将在五秒后重启..." << std::endl; + restartProgram(false,true,5000); + } + return qtRes; } \ No newline at end of file diff --git a/src/launcher/systemState/fetchHardwareMonitor.h b/src/launcher/systemState/fetchHardwareMonitor.h deleted file mode 100644 index 90ddc83..0000000 --- a/src/launcher/systemState/fetchHardwareMonitor.h +++ /dev/null @@ -1,181 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -static void findByTypeAndPrefix(const QJsonObject& obj, - const QString& type, - const QString& prefix, - QList& values){ - if (obj.contains("Type") && obj["Type"].toString() == type && - obj.contains("Text") && obj["Text"].toString().startsWith(prefix)) - { - values.append(obj["Value"].toString()); - } - - if (obj.contains("Children") && obj["Children"].isArray()) { - for (const QJsonValue& child : obj["Children"].toArray()) { - if (child.isObject()) - findByTypeAndPrefix(child.toObject(), type, prefix, values); - } - } -} -//CPU 每核心平均占用率 -static std::vector parseCpuPerCoreLoads(const QJsonObject& root){ - QList values; - findByTypeAndPrefix(root, "Load", "CPU Core", values); - std::vector result; - for (auto& val : values) { - result.push_back(val.mid(0, val.size() - 2).toDouble()); - } - return result; -} - -//CPU 每核心平均温度 -static std::vector parseCpuPerCoreTemperatures(const QJsonObject& root){ - QList values; - findByTypeAndPrefix(root, "Temperature", "CPU Core", values); - std::vector result; - result.reserve(values.size()); // 预留空间,避免扩容 - - for (const auto& val : values) { - bool ok; - double num = val.left(val.size() - 2).toDouble(&ok); - if (ok) { - result.push_back(num); - } - } - - return result; -} -// 计算整体 CPU 占用(平均值) -static double calculateOverallCpuLoad(const QJsonObject& root) { - - std::vector coreLoads = parseCpuPerCoreLoads(root); - if (coreLoads.empty()) { - return -1; // 没有数据 - } - double sum = std::accumulate(coreLoads.begin(), coreLoads.end(), 0.0); - return sum / coreLoads.size(); -} - -// 计算整体 CPU 温度(平均值) -static double calculateOverallCpuTemperature(const QJsonObject& root) { - const std::vector coreTemperatures = parseCpuPerCoreTemperatures(root); - if (coreTemperatures.empty()) { - return -1; // 没有数据 - } - double sum = std::accumulate(coreTemperatures.begin(), coreTemperatures.end(), 0.0); - return sum / coreTemperatures.size(); -} -// 计算整体 CPU 温度(最高值) -static double calculateMaxCpuTemperature(const QJsonObject& root) { - const std::vector coreTemperatures = parseCpuPerCoreTemperatures(root); - if (coreTemperatures.empty()) { - return -1; // 没有数据 - } - auto maxIt = std::max_element(coreTemperatures.begin(), coreTemperatures.end()); - double maxVal = (maxIt != coreTemperatures.end()) ? *maxIt : 0.0; - - return maxVal; -} -//内存占用率 -static double parseMemoryUsage(const QJsonObject& root){ - QList values; - findByTypeAndPrefix(root, "Load", "Memory", values); // 匹配 "Memory" - if (!values.isEmpty()) - return values.first().mid(0, values.first().size() - 2).toDouble(); // 取第一个 - return -1; -} - - -class JsonFetcher : public QObject { - Q_OBJECT -public: - - explicit JsonFetcher(QObject* parent = nullptr): - QObject(parent), manager(new QNetworkAccessManager(this)) { - connect(manager, &QNetworkAccessManager::finished, - this, &JsonFetcher::onFinished); - } - - void fetch(const QUrl& url) { - QNetworkRequest request(url); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - manager->get(request); - } - -signals: - void jsonReady(const QJsonObject& obj); - void error(const QString& err); - -private slots: - void onFinished(QNetworkReply* reply) { - if (reply->error() != QNetworkReply::NoError) { - emit error(reply->errorString()); - reply->deleteLater(); - return; - } - - QByteArray data = reply->readAll(); - reply->deleteLater(); - - QJsonParseError parseError; - QJsonDocument doc = QJsonDocument::fromJson(data, &parseError); - if (parseError.error != QJsonParseError::NoError) { - emit error(parseError.errorString()); - return; - } - - if (!doc.isObject()) { - emit error("Invalid JSON format (expected object)."); - return; - } - - QJsonObject root = filterJson(doc.object()); - emit jsonReady(root); - } - -private: - QNetworkAccessManager* manager; - - QJsonObject filterJson(const QJsonObject& obj) const { - QJsonObject filtered; - - // 只保留需要的字段 - static const QStringList allowedKeys = { - "id", "Text", "Min", "Value", "Max", "Type", "Children" - }; - - for (auto it = obj.begin(); it != obj.end(); ++it) { - if (!allowedKeys.contains(it.key())) continue; - - if (it.key() == "Children" && it.value().isArray()) { - filtered.insert("Children", filterArray(it.value().toArray())); - } - else { - filtered.insert(it.key(), it.value()); - } - } - - return filtered; - } - QJsonArray filterArray(const QJsonArray& arr) const { - QJsonArray newArr; - for (const QJsonValue& val : arr) { - if (val.isObject()) { - newArr.append(filterJson(val.toObject())); - } - else { - newArr.append(val); - } - } - return newArr; - } -}; -#pragma once \ No newline at end of file diff --git a/src/launcher/systemState/hardwareInfo.h b/src/launcher/systemState/hardwareInfo.h deleted file mode 100644 index 30afde4..0000000 --- a/src/launcher/systemState/hardwareInfo.h +++ /dev/null @@ -1,246 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -static QProcess* process = nullptr; -static HANDLE jobHandle = nullptr; - -using hwinfo::unit::bytes_to_MiB; -class hardwareInfo :public QObject { - Q_OBJECT -public: - hardwareInfo() { - const auto cpus = hwinfo::getAllCPUs(); - std::vector threads_utility = cpus[0].threadsUtilisation(); - cpuMaxThreadsUtilityRecord = std::vector(threads_utility.size(), 0); - //test(); - } - double getAvgCpuUseage() { - const auto cpus = hwinfo::getAllCPUs(); - for (const auto& cpu : cpus) { - std::vector threads_utility = cpu.threadsUtilisation(); - double result = 0; - for (int i = 0; i < threads_utility.size();i++) { - cpuMaxThreadsUtilityRecord[i] = qMax(threads_utility[i], cpuMaxThreadsUtilityRecord[i]); - result += threads_utility[i] / qMax(cpuMaxThreadsUtilityRecord[i],1.0); - } - return result / threads_utility.size() * 100.0; - } - } - double getAvgMemUseage() { - hwinfo::Memory memory; - double freeByte = memory.free_Bytes(); - double totalByte = memory.total_Bytes(); - return (1.0 - freeByte / totalByte) * 100.0; - } -#pragma region 测试 - void test() { - fmt::print( - "hwinfo is an open source, MIT licensed project that implements a platform independent " - "hardware and system information gathering API for C++.\n\n" - "If you face any issues, find bugs or if your platform is not supported yet, do not hesitate to create " - "a ticket at https://github.com/lfreist/hwinfo/issues.\n\n" - "Thanks for using hwinfo!\n\n"); - cpuCollectTest(); - osCollectTest(); - gpuCollectTest(); - memCollectTest(); - motherBoardCollectTest(); - diskCollectTest(); - netCollectTest(); - return; - } - void cpuCollectTest() { - fmt::print( - "Hardware Report:\n\n" - "----------------------------------- CPU ------------------------------------\n"); - const auto cpus = hwinfo::getAllCPUs(); - for (const auto& cpu : cpus) { - // clang-format off - fmt::print("Socket {}:\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} L1: {}, L2: {}, L3: {}\n", - cpu.id(), - "vendor:", cpu.vendor(), - "model:", cpu.modelName(), - "physical cores:", cpu.numPhysicalCores(), - "logical cores:", cpu.numLogicalCores(), - "max frequency:", cpu.maxClockSpeed_MHz(), - "regular frequency:", cpu.regularClockSpeed_MHz(), - "cache size:", cpu.L1CacheSize_Bytes(), cpu.L2CacheSize_Bytes(), cpu.L3CacheSize_Bytes()); - // clang-format on - - std::vector threads_utility = cpu.threadsUtilisation(); - std::vector threads_speed = cpu.currentClockSpeed_MHz(); - assert((threads_utility.size() == threads_speed.size())); - for (size_t thread_id = 0; thread_id != threads_utility.size(); ++thread_id) { - fmt::print("{:<20} Thread {}: {} MHz ({}%)\n", " ", thread_id, threads_speed[thread_id], - threads_utility[thread_id] * 100); - } - // fmt::print("{}\n", cpu.currentTemperature_Celsius()); - } - } - void osCollectTest() { - hwinfo::OS os; - // clang-format off - fmt::print("----------------------------------- OS ------------------------------------\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n", - "Operating System:", os.name(), - "version:", os.version(), - "kernel:", os.kernel(), - "architecture:", os.is32bit() ? "32 bit" : "64 bit", - "endianess:", os.isLittleEndian() ? "little endian" : "big endian"); - // clang-format on - } - void gpuCollectTest() { - auto gpus = hwinfo::getAllGPUs(); - fmt::print("----------------------------------- GPU -----------------------------------\n"); - for (const auto& gpu : gpus) { - // clang-format off - fmt::print("GPU {}:\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n", - gpu.id(), - "vendor:", gpu.vendor(), - "model:", gpu.name(), - "driverVersion:", gpu.driverVersion(), - "memory [MiB]:", bytes_to_MiB(gpu.memory_Bytes()), - "frequency:", gpu.frequency_MHz(), - "cores:", gpu.num_cores(), - "vendor_id:", gpu.vendor_id(), - "device_id:", gpu.device_id()); - // clang-format on - } - } - void memCollectTest() { - hwinfo::Memory memory; - // clang-format off - fmt::print("----------------------------------- RAM -----------------------------------\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n", - "size [MiB]:", bytes_to_MiB(memory.total_Bytes()), - "free [MiB]:", bytes_to_MiB(memory.free_Bytes()), - "available [MiB]:", bytes_to_MiB(memory.available_Bytes())); - // clang-format on - - for (const auto& module : memory.modules()) { - // clang-format off - fmt::print("RAM {}:\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n", - module.id, - "vendor:", module.vendor, - "model:", module.model, - "name:", module.name, - "serial-number:", module.serial_number, - "Frequency [MHz]:", module.frequency_Hz == -1 ? -1 : static_cast(module.frequency_Hz) / 1e6); - // clang-format on - } - } - void motherBoardCollectTest() { - hwinfo::MainBoard main_board; - // clang-format off - fmt::print("------------------------------- Main Board --------------------------------\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n", - "vendor:", main_board.vendor(), - "name:", main_board.name(), - "version:", main_board.version(), - "serial-number:", main_board.serialNumber()); - // clang-format on - - } - void diskCollectTest() { - std::vector disks = hwinfo::getAllDisks(); - fmt::print("--------------------------------- Disks -----------------------------------\n"); - if (!disks.empty()) { - int disk_counter = 0; - for (const auto& disk : disks) { - // clang-format off - fmt::print("Disk {}:\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n", - disk_counter++, - "vendor:", disk.vendor(), - "model:", disk.model(), - "serial-number:", disk.serialNumber(), - "size:", disk.size_Bytes(), - "free:", disk.free_size_Bytes(), - "volumes:", fmt::join(disk.volumes(), ", ")); - // clang-format on - } - } - else { - fmt::print("No Disks installed or detected\n"); - } - } - void netCollectTest() { - std::vector networks = hwinfo::getAllNetworks(); - fmt::print("--------------------------------- Networks -----------------------------------\n"); - if (!networks.empty()) { - int network_counter = 0; - for (const auto& network : networks) { - // clang-format off - if (network.ip4().size() > 0 || network.ip6().size() > 0) { - fmt::print( - "Network {}:\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n" - "{:<20} {}\n", - network_counter++, - "description:", network.description(), - "interface index:", network.interfaceIndex(), - "mac:", network.mac(), - "ipv4:", network.ip4(), - "ipv6:", network.ip6()); - } - // clang-format on - } - } - else { - fmt::print("No Networks installed or detected\n"); - } - } -#pragma endregion -private: - std::vectorcpuMaxThreadsUtilityRecord; -}; - -#pragma once \ No newline at end of file diff --git a/src/launcher/systemState/systemStateMonitor.h b/src/launcher/systemState/systemStateMonitor.h deleted file mode 100644 index e0ece84..0000000 --- a/src/launcher/systemState/systemStateMonitor.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include -#include - -class systemStateMonitor : public QThread { - Q_OBJECT -private: - // 私有构造函数 - systemStateMonitor() { - this->start(); - } - - // 禁用拷贝构造函数和赋值运算符 - systemStateMonitor(const systemStateMonitor&) = delete; - systemStateMonitor& operator=(const systemStateMonitor&) = delete; - -public: - // 获取单例实例 - static systemStateMonitor& getInstance() { - static systemStateMonitor instance; - return instance; - } - - ~systemStateMonitor() { - runFlag = false; - quit(); - wait(); - } -protected: - void run() override { - while (runFlag) { - emit addCpuUsageData(_hardwareInfo.getAvgCpuUseage()); - emit addMemUsageData(_hardwareInfo.getAvgMemUseage()); - QThread::msleep(2000); - } - - } -signals: - void addCpuUsageData(double input); - void addCpuTempData(double input); - void addMemUsageData(double input); -private: - bool runFlag = true; - hardwareInfo _hardwareInfo; -}; \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam1213/581-BaoMo.cpp b/src/mission/581-BaoMo-Cam1213/581-BaoMo.cpp deleted file mode 100644 index 0ee499e..0000000 --- a/src/mission/581-BaoMo-Cam1213/581-BaoMo.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include <581-BaoMo.h> - -mission* createMission() { - return new _581_BaoMo(); -} -void destroyMission(mission* _mission) { - delete _mission; -} \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam1213/581-BaoMo.h b/src/mission/581-BaoMo-Cam1213/581-BaoMo.h deleted file mode 100644 index d2ee48e..0000000 --- a/src/mission/581-BaoMo-Cam1213/581-BaoMo.h +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#pragma region 算法 -#include -#include -#include -using namespace HDevEngineCpp; - -#pragma endregion - - -class _581_BaoMo : public mission { -public: - using generalTrigger = _581_Union_triggerTemplate; - generalTrigger _station_1; - generalTrigger _station_2; - detParams _params; - void onConfigReloaded() { - HDevEngineCpp::HDevEngine myEngine; - myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl"); - } - bool initCustom() { -#pragma region 注册触发器回调 - //generalTrigger::resultHandleCallback resultCallback_general = - // ([=](yh_581_address address, _581_Result resultData, std::shared_ptr data) { - // _serviceManager->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果 - // }); - _station_1.init("Camera1","包膜后底托位置度检测相机12",20200,2,1, &_params,_serviceManager,bridge, generalAlgoTest); - _station_2.init("Camera2", "包膜后底托位置度检测相机13",20400,2,1,&_params, _serviceManager, bridge, generalAlgoTest); -#pragma endregion - return true; - } - void reloadAlgo(QByteArray& byteArray) { - - } - - //9600 -}; - - - - - -#pragma once \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam1234/581-BaoMo.cpp b/src/mission/581-BaoMo-Cam1234/581-BaoMo.cpp deleted file mode 100644 index a765ef4..0000000 --- a/src/mission/581-BaoMo-Cam1234/581-BaoMo.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include <581-BaoMo.h> -mission* createMission() { - return new _581_BaoMo(); -} -void destroyMission(mission* _mission) { - delete _mission; -} \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam1234/581-BaoMo.h b/src/mission/581-BaoMo-Cam1234/581-BaoMo.h deleted file mode 100644 index 0a9ba18..0000000 --- a/src/mission/581-BaoMo-Cam1234/581-BaoMo.h +++ /dev/null @@ -1,264 +0,0 @@ -#include -struct _581_BaoMoResult -{ - bool result = true; - std::vector < std::string> defects; -}; -class baoMoHouDaMianDetParams { -public: - handleAiModelSeg* seg; - handleAiModelCls* cls; - handleAiModelCls* cls2; -}; -//class _581Baomo_BaoMoHouShangDaMian { -//public: -// baoMoHouDaMianDetParams _detParams; -// detCallbackChain* ganeralDet; -// std::string cameraName; -// QString viewerName; -// void init(std::string cameraNameIn, QString viewerNameIN, -// ServiceManager* _serviceManagerIN, -// nlohmann::ordered_json& _missionJson, -// SQLiteDB* _SQLiteDB, qtFuncBridge* bridgeIn) { -// viewerName = viewerNameIN; -// cameraName = cameraNameIn; -// _serviceManager = _serviceManagerIN; -// _detParams.seg = _serviceManager->_handleAiModelManager->getSegModel("seg"); -// _detParams.cls = _serviceManager->_handleAiModelManager->getClsModel("cls"); -// _detParams.cls2 = _serviceManager->_handleAiModelManager->getClsModel("cls2"); -// ganeralDet = new detCallbackChain(_serviceManagerIN, &_detParams, bridgeIn); -// ganeralDet->registerProcessAlgoCallback(BaoMoHouDaMian); -// ganeralDet->registerResultHandleCallback(std::bind(&_581Baomo_BaoMoHouShangDaMian::resultHandle, this, _1, _2)); -// } -// //9200 1 -// void evaluate(int triggerPos, int triggerValue, int snPos, int dataPos, QByteArray& byteArray) { -// std::string sn = _serviceManager->_triggerManager->readSnFromQByteArray(byteArray, snPos, false, false, -1); -// auto camera = _serviceManager->_cameraManager->getCamera(cameraName); -// for (int i = 0; i < 2; i++) { -// std::shared_ptr data = _serviceManager->_detDataManager->createDetData( -// QString::number(triggerPos), sn, 1, camera->config.oriSaveFormat);//创建数据包 -// camera->captureImage(data);//拍照 -// //data->oriImgs.push_back(cv::imread("D://Image_20250809202445856.bmp", -1)); -// ganeralDet->ansyncProcess(data, "");//处理算法 -// data->resultImgShowSet.push_back(new showImgPack(viewerName, "结果图")); -// data->additional["触发地址"] = triggerPos; -// data->additional["完成信号"] = triggerPos + 98; -// data->additional["结果信号"] = triggerPos + 106; -// data->additional["数据地址"] = dataPos; -// QThread::msleep(3000); -// } -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(triggerPos + 98) + "_1");//完成信号 -// qDebug() << triggerPos << triggerValue << QString::fromUtf8("检测开始 uuid :") << "SN" << QString::fromStdString(sn);; -// } -// void resultHandle(std::shared_ptr data, _581_Result resultData) { -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(data->additional["触发地址"].toInt() + 106) + "_1");//发送结果 -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(data->additional["完成信号"].toInt()) + "_0");//完成信号复位 -// _serviceManager->_missionResultHandle->toBarChart(data->SNcode, resultData.result, resultData.defects); -// -// } -//private: -// -// qtFuncBridge* bridge; -// ServiceManager* _serviceManager = nullptr; -//}; -//class _581Baomo_trigger2ImgTemplate { -//public: -// detParams _detParams; -// detCallbackChain* ganeralDet; -// std::string cameraName; -// QString viewerName; -// void init(std::string cameraNameIn, QString viewerNameIN, -// ServiceManager* _serviceManagerIN, -// nlohmann::ordered_json& _missionJson, -// SQLiteDB* _SQLiteDB, qtFuncBridge* bridgeIn) { -// viewerName = viewerNameIN; -// cameraName = cameraNameIn; -// _serviceManager = _serviceManagerIN; -// ganeralDet = new detCallbackChain(_serviceManagerIN, &_detParams, bridgeIn); -// ganeralDet->registerProcessAlgoCallback(_952_15_H_Algo); -// ganeralDet->registerResultHandleCallback(std::bind(&_581Baomo_trigger2ImgTemplate::resultHandle, this, _1, _2)); -// } -// //9200 1 -// void evaluate(int triggerPos, int triggerValue, int snPos, int dataPos, QByteArray& byteArray) { -// std::string sn = _serviceManager->_triggerManager->readSnFromQByteArray(byteArray, snPos, false, false, -1); -// auto camera = _serviceManager->_cameraManager->getCamera(cameraName); -// for (int i = 0; i < 2; i++) { -// std::shared_ptr data = _serviceManager->_detDataManager->createDetData( -// QString::number(triggerPos), sn, 1, camera->config.oriSaveFormat);//创建数据包 -// camera->captureImage(data);//拍照 -// ganeralDet->ansyncProcess(data, "");//处理算法 -// data->resultImgShowSet.push_back(new showImgPack(viewerName, "结果图")); -// data->additional["触发地址"] = triggerPos; -// data->additional["完成信号"] = triggerPos + 98; -// data->additional["结果信号"] = triggerPos + 106; -// data->additional["数据地址"] = dataPos; -// } -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(triggerPos + 98) + "_1");//完成信号 -// qDebug() << triggerPos << triggerValue << QString::fromUtf8("检测开始 uuid :") << "SN" << QString::fromStdString(sn);; -// } -// void resultHandle(std::shared_ptr data, _581_Result resultData) { -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(data->additional["触发地址"].toInt() + 106) + "_1");//发送结果 -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(data->additional["完成信号"].toInt()) + "_0");//完成信号复位 -// -// } -//private: -// -// qtFuncBridge* bridge; -// ServiceManager* _serviceManager = nullptr; -//}; - -#include -#include -#include -using namespace HDevEngineCpp; - -_581_BaoMoResult SUB_BaoMoHouDaMian(std::shared_ptr data, cv::Mat src, cv::Mat& Paint, - baoMoHouDaMianDetParams* _detParams) { - _581_BaoMoResult aireuslt; - TextRendererZH textPainter(Paint.cols, Paint.rows, 150); - bool huaShangNg = false; - cv::Mat segImg = ~_detParams->seg->segPtr->Evaluate(src); - std::vector> contours; - cv::findContours(segImg, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); - bool isOK = true; - for (int i = 0; i < contours.size(); i++) { - cv::Rect rect = cv::boundingRect(contours[i]); - if (rect.width < 100 && rect.height < 100) continue; // 过滤掉小轮廓 - auto clsImgs = cutImg2ClsVec(rect, src, cv::Size(256, 256)); - bool clsIsNg = false; - for (auto& clsImg : clsImgs) { - if (_detParams->cls->Evaluate(clsImg) == 1) { // 假设1表示NG - int clsResult = _detParams->cls2->Evaluate(clsImg); - if (clsResult == 1) { - clsIsNg = true; - huaShangNg = true; - //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); - isOK = false; - cv::drawContours(Paint, contours, i, color, 2); - textPainter.putText(Paint, "划伤", cv::Point(rect.x + 10, rect.y - 20), cv::Scalar(0, 255, 0)); - } - //else { - // cv::Mat imgTmp; - // 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); - } - if (huaShangNg == true) - aireuslt.defects.push_back("划伤"); - return aireuslt; -} -static bool ALGO_BaoMoHouDaMian(std::shared_ptr data, - baoMoHouDaMianDetParams* _detParams, - yh_581_address address) { - qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start"; - - ///////////////////取图//处理////////////////// - if (data->oriImgs.size() != 1) { - qCritical() << "图片数量不满足要求:" << data->oriImgs.size(); - return false; - } - if (data->oriImgs[0].rows == 100) { - cv::Mat Paint; - data->oriImgs[0].copyTo(Paint); - cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2); - return false; - } - - cv::Mat Paint; - //QMutex paintMutex; - clock_t start, finish; - start = clock(); - - cv::Mat src1 = data->oriImgs[0]; - cv::Mat srcHalf; - cv::resize(src1, srcHalf, cv::Size(0, 0), 0.5, 0.5); - if (srcHalf.channels() != 3) - cv::cvtColor(srcHalf, Paint, cv::COLOR_GRAY2BGR); - else - srcHalf.copyTo(Paint); - //TextRendererZH textPainter(Paint.cols, Paint.rows, 150); - //std::future <_581_Result> handleAiFuture = std::async(std::launch::async, _BaoMoHouDaMian, data, srcHalf, Paint, _detParams); - /*HalconCpp::HObject in_Image = MatToHObject(src1); - HDevEngineCpp::HDevProcedure proc("_4_Cal_Long_Coatingcover_Dist"); - HDevProcedureCall procedureCall(proc); - procedureCall.SetInputIconicParamObject("in_Image", in_Image); - procedureCall.SetInputCtrlParamTuple("in_xResolution", HTuple(0.0308812)); - procedureCall.SetInputCtrlParamTuple("in_yResolution", HTuple(0.029527)); - procedureCall.Execute(); - HTuple out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance"); - HTuple out_Line = procedureCall.GetOutputCtrlParamTuple("out_Line"); - HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag"); - int outFlag = out_Flag.D();*/ - //handleAiFuture.wait(); - //_result = handleAiFuture.get(); - //if (outFlag == 1) { - // for (int i = 0; i < out_Line.Length() / 4; i++) { - // cv::line(Paint, cv::Point(out_Line[i * 4 + 1].D() / 2, out_Line[i * 4].D()) / 2, - // cv::Point(out_Line[i * 4 + 3].D() / 2, out_Line[i * 4 + 2].D() / 2), - // cv::Scalar(0, 255, 0), 5); - // } - // /*out_Distance[0]: 上端盖到膜的距离< / c> - // * out_Distance[1] : 中端盖到膜的距离< / c> - // * out_Distance[2] : 下端盖到膜的距离< / c> - // * out_Distance[3] : 电芯宽度 < / c> - // * out_Distance[4] : 电芯高度< / c>*/ - // textPainter.putText(Paint, "上端盖到膜的距离:" + std::to_string(out_Distance[0].D()), cv::Point(50, 150), cv::Scalar(0, 255, 0)); - // textPainter.putText(Paint, "中端盖到膜的距离:" + std::to_string(out_Distance[1].D()), cv::Point(50, 350), cv::Scalar(0, 255, 0)); - // textPainter.putText(Paint, "下端盖到膜的距离:" + std::to_string(out_Distance[2].D()), cv::Point(50, 550), cv::Scalar(0, 255, 0)); - // textPainter.putText(Paint, "电芯宽度:" + std::to_string(out_Distance[3].D()), cv::Point(50, 750), cv::Scalar(0, 255, 0)); - // textPainter.putText(Paint, "电芯高度:" + std::to_string(out_Distance[4].D()), cv::Point(50, 950), cv::Scalar(0, 255, 0)); - //} - //else { - // textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255)); - //} - data->service->_triggerManager->writeFloat("D" + address.resultAddr + "_1");//发送OK - data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X - data->resultImgs.push_back(Paint); - - return false; -} - -class _581_BaoMo : public mission { -public: - using baoMoHouDaMianTrigger = _581_Union_triggerTemplate; - baoMoHouDaMianTrigger _station_1; - baoMoHouDaMianTrigger _station_2; - baoMoHouDaMianDetParams _baoMoHouDaMianDetParams; - - using generalTrigger = _581_Union_triggerTemplate; - generalTrigger _station_3; - generalTrigger _station_4; - detParams _detParams; - void onConfigReloaded() { - HDevEngineCpp::HDevEngine myEngine; - myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl"); - } - bool initCustom() { -#pragma region 注册触发器回调 - _station_1.init("Camera1","包膜前外观检测大面相机1(上大面)", 18000,2, 1, &_baoMoHouDaMianDetParams,_serviceManager, bridge, ALGO_BaoMoHouDaMian); - _station_2.init("Camera2", "包膜前外观检测大面相机2(下大面)", 18200,2, 1, &_baoMoHouDaMianDetParams, _serviceManager,bridge, ALGO_BaoMoHouDaMian); - - _station_3.init("Camera3", "包膜前产品边缘检测大面相机3(下大面2)", 18400,2, 2, &_detParams,_serviceManager,bridge, generalAlgoTest); - _station_4.init("Camera4", "包膜前前产品边缘检测大面相机4(下大面2)", 18600 ,2, 2, &_detParams, _serviceManager, bridge, generalAlgoTest); -#pragma endregion - return true; - } - void reloadAlgo(QByteArray& byteArray) { - - } - - //9600 -}; - - - -#pragma once \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam5678/581-BaoMo.h b/src/mission/581-BaoMo-Cam5678/581-BaoMo.h deleted file mode 100644 index 7665f0d..0000000 --- a/src/mission/581-BaoMo-Cam5678/581-BaoMo.h +++ /dev/null @@ -1,353 +0,0 @@ -#include -#include - -struct _581_BaoMoResult -{ - bool result = true; - std::vector < std::string> defects; -}; -class baoMoHouDaMianDetParams { -public: - handleAiModelSeg* seg = nullptr; - handleAiModelCls* cls = nullptr; - handleAiModelCls* cls2 = nullptr; -}; -#pragma region 算法 -#include -#include -#include -using namespace HDevEngineCpp; -std::vector BaoMoHou_DaMianAi(std::shared_ptr data, cv::Mat src, cv::Mat& Paint, - baoMoHouDaMianDetParams* _detParams) { - if (_detParams->seg == nullptr || _detParams->cls == nullptr || _detParams->cls2 == nullptr) - return {}; - std::vector defects; - TextRendererZH textPainter(Paint.cols, Paint.rows, 150); - bool huaShangNg = false; - cv::Mat segImg = ~_detParams->seg->segPtr->Evaluate(src); - std::vector> contours; - cv::findContours(segImg, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); - bool isOK = true; - for (int i = 0; i < contours.size(); i++) { - cv::Rect rect = cv::boundingRect(contours[i]); - if (rect.width < 100 || rect.height < 100) continue; // 过滤掉小轮廓 - auto clsImgs = cutImg2ClsVec(rect, src, cv::Size(128, 128)); - bool clsIsNg = false; - for (auto& clsImg : clsImgs) { - if (_detParams->cls->clsPtr->Evaluate(clsImg) == 1) { // 假设1表示NG - int clsResult = _detParams->cls2->Evaluate(clsImg); - if (clsResult == 1) { - clsIsNg = true; - huaShangNg = true; - //data->clsOriginImgs.push_back({ std::to_string(i),clsImg }); - } - } - } - if (clsIsNg == true) { - cv::Scalar color = cv::Scalar(0, 0, 255); - isOK = false; - cv::drawContours(Paint, contours, i, color, 2); - textPainter.putText(Paint, "划伤", cv::Point(rect.x + 10, rect.y - 20), color); - } - //else { - // cv::Mat imgTmp; - // 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); - } - if (huaShangNg == true) - defects.push_back("划伤"); - return defects; -} -#pragma endregion -#pragma region 算法 -static bool BaoMoHou_ShangDaMian(std::shared_ptr data, baoMoHouDaMianDetParams* _detParams, yh_581_address address) -{ - qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start"; - - ///////////////////取图//处理////////////////// - if (data->oriImgs.size() != 1) - { - qCritical() << "图片数量不满足要求:" << data->oriImgs.size(); - return false; - } - if (data->oriImgs[0].rows == 150) { - cv::Mat Paint; - data->oriImgs[0].copyTo(Paint); - cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2); - return false; - } - - cv::Mat Paint; - //QMutex paintMutex; - clock_t start, finish; - start = clock(); - - cv::Mat src1 = data->oriImgs[0]; - cv::Mat srcHalf; - cv::resize(src1, srcHalf, cv::Size(0, 0), 0.5, 0.5); - if (srcHalf.channels() != 3) - cv::cvtColor(srcHalf, Paint, cv::COLOR_GRAY2BGR); - else - srcHalf.copyTo(Paint); - TextRendererZH textPainter(Paint.cols, Paint.rows, 150); - std::future > handleAiFuture = std::async(std::launch::async, BaoMoHou_DaMianAi, data, srcHalf, Paint, _detParams); - HalconCpp::HObject in_Image = MatToHObject(src1); - HDevEngineCpp::HDevProcedure proc("_4_Cal_Long_Coatingcover_Dist"); - HDevProcedureCall procedureCall(proc); - procedureCall.SetInputIconicParamObject("in_Image", in_Image); - procedureCall.SetInputCtrlParamTuple("in_xResolution", HTuple(0.0308812)); - procedureCall.SetInputCtrlParamTuple("in_yResolution", HTuple(0.029527)); - procedureCall.Execute(); - HTuple out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance"); - HTuple out_Line = procedureCall.GetOutputCtrlParamTuple("out_Line"); - HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag"); - int outFlag = out_Flag.D(); - handleAiFuture.wait(); - auto defects = handleAiFuture.get(); - if (outFlag == 1) { - for (int i = 0; i < out_Line.Length() / 4; i++) { - cv::line(Paint, cv::Point(out_Line[i * 4 + 1].D(), out_Line[i * 4].D()) / 2, - cv::Point(out_Line[i * 4 + 3].D(), out_Line[i * 4 + 2].D()) / 2, - cv::Scalar(0, 255, 0), 5); - } - /*out_Distance[0]: 上端盖到膜的距离< / c> - * out_Distance[1] : 中端盖到膜的距离< / c> - * out_Distance[2] : 下端盖到膜的距离< / c> - * out_Distance[3] : 电芯宽度 < / c> - * out_Distance[4] : 电芯高度< / c>*/ - textPainter.putText(Paint, "上端盖到膜的距离:" + std::to_string(out_Distance[0].D()) + "mm", cv::Point(50, 150), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "中端盖到膜的距离:" + std::to_string(out_Distance[1].D()) + "mm", cv::Point(50, 350), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "下端盖到膜的距离:" + std::to_string(out_Distance[2].D()) + "mm", cv::Point(50, 550), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "电芯宽度:" + std::to_string(out_Distance[3].D()) + "mm", cv::Point(50, 750), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "电芯高度:" + std::to_string(out_Distance[4].D()) + "mm", cv::Point(50, 950), cv::Scalar(0, 255, 0)); - } - else { - data->halconOK = false; - textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255)); - } - - data->resultImgs.push_back(Paint); - data->service->_missionResultHandle->toBarChart(data->SNcode, defects.size() == 0, defects); - data->service->_triggerManager->writeFloat("D" + address.resultAddr + "_1");//发送OK - return true; -} -//class _581Baomo_BaoMoHouShangDaMian { -//public: -// baoMoHouDaMianDetParams _detParams; -// detCallbackChain* ganeralDet; -// std::string cameraName; -// QString viewerName; -// void init(std::string cameraNameIn, QString viewerNameIN, -// ServiceManager* _serviceManagerIN, -// nlohmann::ordered_json& _missionJson, -// SQLiteDB* _SQLiteDB, qtFuncBridge* bridgeIn) { -// viewerName = viewerNameIN; -// cameraName = cameraNameIn; -// _serviceManager = _serviceManagerIN; -// _detParams.seg = _serviceManager->_handleAiModelManager->getSegModel("seg_gpu0"); -// _detParams.cls = _serviceManager->_handleAiModelManager->getClsModel("cls_gpu0"); -// _detParams.cls2 = _serviceManager->_handleAiModelManager->getClsModel("cls2_gpu0"); -// ganeralDet = new detCallbackChain(_serviceManagerIN, &_detParams, bridgeIn); -// ganeralDet->registerProcessAlgoCallback(BaoMoHou_ShangDaMian); -// ganeralDet->registerResultHandleCallback(std::bind(&_581Baomo_BaoMoHouShangDaMian::resultHandle, this, _1, _2)); -// } -// //9200 1 -// void evaluate(int triggerPos, int triggerValue, int snPos, int dataPos, QByteArray& byteArray) { -// std::string sn = _serviceManager->_triggerManager->readSnFromQByteArray(byteArray, snPos, false, false, -1); -// auto camera = _serviceManager->_cameraManager->getCamera(cameraName); -// // for (int i = 0; i < 2; i++) { -// std::shared_ptr data = _serviceManager->_detDataManager->createDetData( -// QString::number(triggerPos), sn, 1, camera->config.oriSaveFormat);//创建数据包 -// camera->captureImage(data);//拍照 -// //data->oriImgs.push_back(cv::imread("D://Image_20250809202445856.bmp", -1)); -// ganeralDet->ansyncProcess(data, "");//处理算法 -// data->resultImgShowSet.push_back(new showImgPack(viewerName, "结果图")); -// data->additional["触发地址"] = triggerPos; -// data->additional["完成信号"] = triggerPos + 98; -// data->additional["结果信号"] = triggerPos + 106; -// data->additional["数据地址"] = dataPos; -// //v } -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(triggerPos + 98) + "_1");//完成信号 -// qDebug() << triggerPos << triggerValue << QString::fromUtf8("检测开始 uuid :") << "SN" << QString::fromStdString(sn);; -// } -// void resultHandle(std::shared_ptr data, _581_BaoMoResult resultData) { -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(data->additional["触发地址"].toInt() + 106) + "_1");//发送结果 -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(data->additional["完成信号"].toInt()) + "_0");//完成信号复位 -// _serviceManager->_missionResultHandle->toBarChart(data->SNcode, resultData.result, resultData.defects); -// -// } -//private: -// -// qtFuncBridge* bridge; -// ServiceManager* _serviceManager = nullptr; -//}; -static bool BaoMoHou_XiaDaMian(std::shared_ptr data, baoMoHouDaMianDetParams* _detParams, yh_581_address address) -{ - qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start"; - - ///////////////////取图//处理////////////////// - if (data->oriImgs.size() != 1) - { - qCritical() << "图片数量不满足要求:" << data->oriImgs.size(); - return false; - } - if (data->oriImgs[0].rows == 150) { - cv::Mat Paint; - data->oriImgs[0].copyTo(Paint); - cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2); - return false; - } - - cv::Mat Paint; - //QMutex paintMutex; - clock_t start, finish; - start = clock(); - - cv::Mat src1 = data->oriImgs[0]; - cv::Mat srcHalf; - cv::resize(src1, srcHalf, cv::Size(0, 0), 0.5, 0.5); - if (srcHalf.channels() != 3) - cv::cvtColor(srcHalf, Paint, cv::COLOR_GRAY2BGR); - else - srcHalf.copyTo(Paint); - auto _result = BaoMoHou_DaMianAi(data, srcHalf, Paint, _detParams); - //TextRendererZH textPainter(Paint.cols, Paint.rows, 150); - //std::future <_581_BaoMoResult> handleAiFuture = std::async(std::launch::async, BaoMoHou_XiaMianAi, data, srcHalf, Paint, _detParams); - //HalconCpp::HObject in_Image = MatToHObject(src1); - //HDevEngineCpp::HDevProcedure proc("_4_Cal_Long_Coatingcover_Dist"); - //HDevProcedureCall procedureCall(proc); - //procedureCall.SetInputIconicParamObject("in_Image", in_Image); - //procedureCall.SetInputCtrlParamTuple("in_xResolution", HTuple(0.0308812)); - //procedureCall.SetInputCtrlParamTuple("in_yResolution", HTuple(0.029527)); - //procedureCall.Execute(); - //HTuple out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance"); - //HTuple out_Line = procedureCall.GetOutputCtrlParamTuple("out_Line"); - //HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag"); - //int outFlag = out_Flag.D(); - //handleAiFuture.wait(); - //_result = handleAiFuture.get(); - //if (outFlag == 1) { - // for (int i = 0; i < out_Line.Length() / 4; i++) { - // cv::line(Paint, cv::Point(out_Line[i * 4 + 1].D(), out_Line[i * 4].D()) / 2, - // cv::Point(out_Line[i * 4 + 3].D(), out_Line[i * 4 + 2].D()) / 2, - // cv::Scalar(0, 255, 0), 5); - // } - // /*out_Distance[0]: 上端盖到膜的距离< / c> - // * out_Distance[1] : 中端盖到膜的距离< / c> - // * out_Distance[2] : 下端盖到膜的距离< / c> - // * out_Distance[3] : 电芯宽度 < / c> - // * out_Distance[4] : 电芯高度< / c>*/ - // textPainter.putText(Paint, "上端盖到膜的距离:" + std::to_string(out_Distance[0].D()) + "mm", cv::Point(50, 150), cv::Scalar(0, 255, 0)); - // textPainter.putText(Paint, "中端盖到膜的距离:" + std::to_string(out_Distance[1].D()) + "mm", cv::Point(50, 350), cv::Scalar(0, 255, 0)); - // textPainter.putText(Paint, "下端盖到膜的距离:" + std::to_string(out_Distance[2].D()) + "mm", cv::Point(50, 550), cv::Scalar(0, 255, 0)); - // textPainter.putText(Paint, "电芯宽度:" + std::to_string(out_Distance[3].D()) + "mm", cv::Point(50, 750), cv::Scalar(0, 255, 0)); - // textPainter.putText(Paint, "电芯高度:" + std::to_string(out_Distance[4].D()) + "mm", cv::Point(50, 950), cv::Scalar(0, 255, 0)); - //} - //else { - // textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255)); - //} - - data->resultImgs.push_back(Paint); - data->service->_triggerManager->writeFloat("D" + address.resultAddr + "_1");//发送OK - return true; -} -//class _581Baomo_BaoMoHouXiaDaMian { -//public: -// baoMoHouDaMianDetParams _detParams; -// detCallbackChain* ganeralDet; -// std::string cameraName; -// QString viewerName; -// void init(std::string cameraNameIn, QString viewerNameIN, -// ServiceManager* _serviceManagerIN, -// nlohmann::ordered_json& _missionJson, -// SQLiteDB* _SQLiteDB, qtFuncBridge* bridgeIn) { -// viewerName = viewerNameIN; -// cameraName = cameraNameIn; -// _serviceManager = _serviceManagerIN; -// _detParams.seg = _serviceManager->_handleAiModelManager->getSegModel("seg_gpu1"); -// _detParams.cls = _serviceManager->_handleAiModelManager->getClsModel("cls_gpu1"); -// _detParams.cls2 = _serviceManager->_handleAiModelManager->getClsModel("cls2_gpu1"); -// ganeralDet = new detCallbackChain(_serviceManagerIN, &_detParams, bridgeIn); -// ganeralDet->registerProcessAlgoCallback(BaoMoHou_XiaDaMian); -// ganeralDet->registerResultHandleCallback(std::bind(&_581Baomo_BaoMoHouXiaDaMian::resultHandle, this, _1, _2)); -// } -// //9200 1 -// void evaluate(int triggerPos, int triggerValue, int snPos, int dataPos, QByteArray& byteArray) { -// std::string sn = _serviceManager->_triggerManager->readSnFromQByteArray(byteArray, snPos, false, false, -1); -// auto camera = _serviceManager->_cameraManager->getCamera(cameraName); -// // for (int i = 0; i < 2; i++) { -// std::shared_ptr data = _serviceManager->_detDataManager->createDetData( -// QString::number(triggerPos), sn, 1, camera->config.oriSaveFormat);//创建数据包 -// camera->captureImage(data);//拍照 -// //data->oriImgs.push_back(cv::imread("D://Image_20250809202445856.bmp", -1)); -// ganeralDet->ansyncProcess(data, "");//处理算法 -// data->resultImgShowSet.push_back(new showImgPack(viewerName, "结果图")); -// data->additional["触发地址"] = triggerPos; -// data->additional["完成信号"] = triggerPos + 98; -// data->additional["结果信号"] = triggerPos + 106; -// data->additional["数据地址"] = dataPos; -// //v } -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(triggerPos + 98) + "_1");//完成信号 -// qDebug() << triggerPos << triggerValue << QString::fromUtf8("检测开始 uuid :") << "SN" << QString::fromStdString(sn);; -// } -// void resultHandle(std::shared_ptr data, _581_BaoMoResult resultData) { -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(data->additional["触发地址"].toInt() + 106) + "_1");//发送结果 -// _serviceManager->_triggerManager->writeShort("D" + QByteArray::number(data->additional["完成信号"].toInt()) + "_0");//完成信号复位 -// _serviceManager->_missionResultHandle->toBarChart(data->SNcode, resultData.result, resultData.defects); -// -// } -//private: -// -// qtFuncBridge* bridge; -// ServiceManager* _serviceManager = nullptr; -//}; -#pragma endregion - -class _581_BaoMo : public mission { -public: - using baoMoHouShangDaMianTrigger = _581_Union_triggerTemplate; - baoMoHouShangDaMianTrigger _station_1;//shangdamian - baoMoHouShangDaMianTrigger _station_3;//shangdamian - - using baoMoHouXiaDaMianTrigger = _581_Union_triggerTemplate; - baoMoHouXiaDaMianTrigger _station_2;//xiadamian - baoMoHouXiaDaMianTrigger _station_4;//xiadamian - - baoMoHouDaMianDetParams _baoMoHouDaMianDetParams; - detParams _detParams; - void onConfigReloaded() { - HDevEngineCpp::HDevEngine myEngine; - myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl"); - } - bool initCustom() { - -#pragma region 注册触发器回调 - //baoMoHouShangDaMianTrigger::resultHandleCallback resultCallback_BaoMoHouShangDaMian = - // ([=](yh_581_address address, _581_BaoMoResult resultData, std::shared_ptr data ) { - // _serviceManager->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果 - // _serviceManager->_missionResultHandle->toBarChart(data->SNcode, resultData.result, resultData.defects); - // }); - _station_1.init("Camera1", "包膜后大面外观检测相机5(上大面1)",18800,2,1, &_baoMoHouDaMianDetParams, _serviceManager,bridge, BaoMoHou_ShangDaMian); - _station_3.init("Camera3", "包膜后大面外观检测相机7(上大面2)", 19200, 2, 1, &_baoMoHouDaMianDetParams, _serviceManager, bridge, BaoMoHou_ShangDaMian); - - //baoMoHouXiaDaMianTrigger::resultHandleCallback resultCallback_BaoMoHouXiaDaMian = - // ([=](yh_581_address address, _581_BaoMoResult resultData, std::shared_ptr data) { - // _serviceManager->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果 - // _serviceManager->_missionResultHandle->toBarChart(data->SNcode, resultData.result, resultData.defects); - // }); - _station_2.init("Camera2", "包膜后大面外观检测相机6(下大面四角1)", 19000, 2, 1, &_baoMoHouDaMianDetParams, _serviceManager, bridge, BaoMoHou_XiaDaMian); - _station_4.init("Camera4", "包膜后大面外观检测相机8(下大面四角2)",19400,2,1, &_baoMoHouDaMianDetParams, _serviceManager, bridge, BaoMoHou_XiaDaMian); -#pragma endregion - return true; - } -}; - - - - - -#pragma once \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp b/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp new file mode 100644 index 0000000..43980a2 --- /dev/null +++ b/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp @@ -0,0 +1,201 @@ +#include <581-BaoMo-Cam91011.h> + +mission* createMission() { + return new _581_BaoMo(); +} +void destroyMission(mission* _mission) { + delete _mission; +} + +std::vector < std::string> _BaoMoHouDaMian(std::shared_ptr data, cv::Mat src, cv::Mat& Paint, + baoMoHouDaMianDetParams* _detParams) { + std::vector < std::string> aireuslt; + TextRendererZH textPainter(Paint.cols, Paint.rows, 150); + bool huaShangNg = false; + cv::Mat segImg = ~_detParams->seg->Evaluate(src); + std::vector> contours; + cv::findContours(segImg, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + bool isOK = true; + for (int i = 0; i < contours.size(); i++) { + cv::Rect rect = cv::boundingRect(contours[i]); + if (rect.width < 100 && rect.height < 100) continue; // 过滤掉小轮廓 + auto clsImgs = cutImg2ClsVec(rect, src, cv::Size(256, 256)); + bool clsIsNg = false; + for (auto& clsImg : clsImgs) { + if (_detParams->cls->Evaluate(clsImg) == 1) { // 假设1表示NG + int clsResult = _detParams->cls2->Evaluate(clsImg); + if (clsResult == 1) { + clsIsNg = true; + huaShangNg = true; + //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); + isOK = false; + cv::drawContours(Paint, contours, i, color, 2); + textPainter.putText(Paint, "划伤", cv::Point(rect.x + 10, rect.y - 20), cv::Scalar(0, 255, 0)); + } + //else { + // cv::Mat imgTmp; + // 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); + } + if (huaShangNg == true) + aireuslt.push_back("划伤"); + return aireuslt; +} +void exceptionResume(std::shared_ptr data, baoMoHouDaMianDetParams* _detParams, yh_581_address address, QString why = "") { + qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why; + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + textPainter.putText(Paint, why.toStdString(), cv::Point(500, 50), cv::Scalar(0, 255, 0)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 +} +bool halconAlgo1_BaoMoHouCeMian_HouDu(std::shared_ptr data, yh_581_address address, cv::Mat& src, cv::Mat& Paint, QMutex* mutex, std::vector < std::string> defects) { + bool isOK = false; + double Width = -1; + HalconCpp::HObject in_Image = MatToHObject(src); + HDevEngineCpp::HDevProcedure proc("_4_Cal_Short_Coatingcover_Dist"); + HDevProcedureCall procedureCall(proc); + procedureCall.SetInputIconicParamObject("in_Image", in_Image); + procedureCall.SetInputCtrlParamTuple("in_xResolution", HTuple(0.0308812)); + procedureCall.SetInputCtrlParamTuple("in_yResolution", HTuple(0.029527)); + procedureCall.Execute(); + HTuple out_Width = procedureCall.GetOutputCtrlParamTuple("out_Width"); + HTuple out_Line = procedureCall.GetOutputCtrlParamTuple("out_Line"); + HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag"); + int outFlag = out_Flag.D(); + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + + double limitHigh = data->service->_paramSyncManager->get("最大宽度阈值(MAX)", 200).toFloat(); + double limitLow = data->service->_paramSyncManager->get("最小宽度阈值(MIN)", 0).toFloat(); + + if (outFlag == 1) { + QMutexLocker locker(mutex); + for (int i = 0; i < out_Line.Length() / 4; i++) { + cv::line(Paint, cv::Point(out_Line[i * 4 + 1].D(), out_Line[i * 4].D()) / 2, + cv::Point(out_Line[i * 4 + 3].D(), out_Line[i * 4 + 2].D()) / 2, + cv::Scalar(0, 255, 0), 5); + } + Width = out_Width.D(); + + if (limitHigh > Width && limitLow < Width) { + textPainter.putText(Paint, "电芯厚度:" + std::to_string(Width) + "mm", cv::Point(50, 450), cv::Scalar(0, 255, 0)); + isOK = true; + } + else { + textPainter.putText(Paint, "电芯厚度:" + std::to_string(Width) + "mm", cv::Point(50, 450), cv::Scalar(0, 0, 255)); + textPainter.putText(Paint, "厚度判定不良", cv::Point(50, 350), cv::Scalar(0, 0, 255)); + defects.push_back("厚度判定不良"); + } + } + else { + QMutexLocker locker(mutex); + textPainter.putText(Paint, "电芯厚度检测异常", cv::Point(50, 250), cv::Scalar(0, 0, 255)); + data->halconOK = false; + } + + data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(Width)); + return isOK; +} +bool halconAlgo1_BaoMoHouCeMian_PoSun(std::shared_ptr data, yh_581_address address, cv::Mat& src, cv::Mat& Paint, QMutex* mutex, std::vector < std::string> defects) { + QMutexLocker locker(mutex); + bool isOK = false; + try { + HalconCpp::HObject in_Image = MatToHObject(src); + HalconCpp::HObject test; + cv::Mat img = HObject2Mat(test); + cv::resize(img, img, cv::Size(), 0.5, 0.5); + HTuple in_Parameters; + in_Parameters[0] = data->service->_paramSyncManager->get("灰度管控阈值", 230).toInt(); + in_Parameters[1] = data->service->_paramSyncManager->get("缺陷像素数量管控阈值(pix)", 300000).toInt(); + in_Parameters[2] = data->service->_paramSyncManager->get("缺陷的宽度管控阈值(pix)", 600).toInt(); + in_Parameters[3] = data->service->_paramSyncManager->get("缺陷的高度管控阈值(pix)", 60).toInt(); + + HDevEngineCpp::HDevProcedure proc("_4_TR_TL_BlueCover_Inspection"); + HDevProcedureCall procedureCall(proc); + procedureCall.SetInputIconicParamObject("in_Image", in_Image); + procedureCall.SetInputCtrlParamTuple("in_Parameters", in_Parameters); + procedureCall.Execute(); + HObject out_DisplayImage = procedureCall.GetOutputIconicParamObject("out_DisplayImage"); + HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag"); + HTuple out_NgDetails = procedureCall.GetOutputCtrlParamTuple("out_NgDetails"); + + int outFlag = out_Flag.D(); + Paint = HObject2Mat(out_DisplayImage); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + + if (outFlag == 1) { + textPainter.putText(Paint, "破损检测OK", cv::Point(50, 50), cv::Scalar(0, 255, 0)); + isOK = true; + } + else { + textPainter.putText(Paint, "破损检测NG", cv::Point(50, 50), cv::Scalar(0, 0, 255)); + std::string ngDetailStr = gbkToUtf8(out_NgDetails.ToString().Text()); + textPainter.putText(Paint, ngDetailStr.substr(1, ngDetailStr.length() - 2), cv::Point(50, 150), cv::Scalar(0, 0, 255)); + data->halconOK = false; + } + return isOK; + } + CATCH_EXCEPTIONS + cv::resize(src, Paint, cv::Size(), 0.5, 0.5); + if (src.channels() == 1) + cv::cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + else + src.copyTo(Paint); + return isOK; +} +bool ALGO_BaoMoHouCeMian(std::shared_ptr data, baoMoHouDaMianDetParams* _detParams,yh_581_address address){ + try { + qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start"; + std::vector < std::string> defects; + ///////////////////取图//处理////////////////// + if (data->oriImgs.size() < 1) + { + qCritical() << "图片数量不满足要求:" << data->oriImgs.size(); + return false; + } + cv::Mat Paint; + clock_t start, finish; + start = clock(); + + data->oriImgs[0] = cv::imread("D:/04QCB82602000JFB5000019N_Camera2_0.bmp", -1); + // + + cv::Mat src = data->oriImgs[0]; + QMutex mutex; + + std::future handleAiFuture1 = std::async(std::launch::async, halconAlgo1_BaoMoHouCeMian_PoSun, data, address, std::ref(src), std::ref(Paint), &mutex, std::ref(defects)); + std::future handleAiFuture2 = std::async(std::launch::async, halconAlgo1_BaoMoHouCeMian_HouDu, data, address, std::ref(src), std::ref(Paint), &mutex, std::ref(defects)); + + handleAiFuture1.wait(); + bool res1 = handleAiFuture1.get(); + + handleAiFuture2.wait(); + bool res2 = handleAiFuture2.get(); + //if (res1 == false || res2 == false) { + + //} + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1"); + data->service->_missionResultHandle->toBarChart(data->SNcode, !defects.size() > 0, defects); + data->resultImgs.push_back(Paint); + return true; + } + CATCH_EXCEPTIONS + exceptionResume(data, _detParams, address, "检测异常"); + return true; +} \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam91011/581-BaoMo.h b/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.h similarity index 63% rename from src/mission/581-BaoMo-Cam91011/581-BaoMo.h rename to src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.h index 9ccb4f8..255e2c5 100644 --- a/src/mission/581-BaoMo-Cam91011/581-BaoMo.h +++ b/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.h @@ -1,10 +1,10 @@ -#include +#include #include class baoMoHouDaMianDetParams { public: - handleAiModelSeg* seg; - handleAiModelCls* cls; - handleAiModelCls* cls2; + handdleAI::pSegmentation* seg; + handdleAI::pClassification* cls; + handdleAI::pClassification* cls2; }; #pragma region 算法 #include @@ -25,12 +25,20 @@ public: using generalTrigger = _581_Union_triggerTemplate; generalTrigger _station_3; - baoMoHouDaMianDetParams _baoMoHouDaMianDetParams; + std::vector < baoMoHouDaMianDetParams> _baoMoHouDaMianDetParams = std::vector < baoMoHouDaMianDetParams>(2); detParams _detParams; + bool initOnce = false; void onConfigReloaded() { HDevEngineCpp::HDevEngine myEngine; - myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl"); - + myEngine.SetProcedurePath("./halconAlgo/AlgoLibrary_602.hdpl"); + if (initOnce == false) { + //for (auto& param : _baoMoHouDaMianDetParams) { + // param.seg = handdleAI::CreateSegObjS("./handleaiModels/yiCiZhuYe/pSeg_DingWei.BHD", 16, 0); + // param.cls = handdleAI::CreateClsObjV3("./handleaiModels/yiCiZhuYe/pSeg_CanYe.BHD", 16, 0); + // param.cls2 = handdleAI::CreateClsObjV3("./handleaiModels/yiCiZhuYe/pCls_CanYe.BHD", 0, 1); + //} + initOnce = true; + } } bool initCustom() { @@ -39,8 +47,8 @@ public: // ([=](yh_581_address address, _581_BaoMoResult, std::shared_ptr ) { // _serviceManager->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果 // }); - _station_1.init("Camera1","包膜后侧面贴胶错位检测相机9",19600,2,1,&_baoMoHouDaMianDetParams,_serviceManager, bridge, ALGO_BaoMoHouCeMian); - _station_2.init("Camera2", "包膜后侧面贴胶错位检测相机10",19800,2,1, &_baoMoHouDaMianDetParams, _serviceManager, bridge, ALGO_BaoMoHouCeMian); + _station_1.init("Camera1","包膜后侧面贴胶错位检测-外-相机9",19600,2,1,&_baoMoHouDaMianDetParams[0], _serviceManager, bridge, ALGO_BaoMoHouCeMian); + _station_2.init("Camera2", "包膜后侧面贴胶错位检测-内-相机10",19800,2,1, &_baoMoHouDaMianDetParams[1], _serviceManager, bridge, ALGO_BaoMoHouCeMian); //generalTrigger::resultHandleCallback resultCallback_general = // ([=](yh_581_address address, _581_Result, std::shared_ptr ) { diff --git a/src/mission/581-BaoMo-Cam91011/581-BaoMo.cpp b/src/mission/581-BaoMo-Cam91011/581-BaoMo.cpp deleted file mode 100644 index 6d208e8..0000000 --- a/src/mission/581-BaoMo-Cam91011/581-BaoMo.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include <581-BaoMo.h> - -mission* createMission() { - return new _581_BaoMo(); -} -void destroyMission(mission* _mission) { - delete _mission; -} - -std::vector < std::string> _BaoMoHouDaMian(std::shared_ptr data, cv::Mat src, cv::Mat& Paint, - baoMoHouDaMianDetParams* _detParams) { - std::vector < std::string> aireuslt; - TextRendererZH textPainter(Paint.cols, Paint.rows, 150); - bool huaShangNg = false; - cv::Mat segImg = ~_detParams->seg->segPtr->Evaluate(src); - std::vector> contours; - cv::findContours(segImg, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); - bool isOK = true; - for (int i = 0; i < contours.size(); i++) { - cv::Rect rect = cv::boundingRect(contours[i]); - if (rect.width < 100 && rect.height < 100) continue; // 过滤掉小轮廓 - auto clsImgs = cutImg2ClsVec(rect, src, cv::Size(256, 256)); - bool clsIsNg = false; - for (auto& clsImg : clsImgs) { - if (_detParams->cls->Evaluate(clsImg) == 1) { // 假设1表示NG - int clsResult = _detParams->cls2->Evaluate(clsImg); - if (clsResult == 1) { - clsIsNg = true; - huaShangNg = true; - //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); - isOK = false; - cv::drawContours(Paint, contours, i, color, 2); - textPainter.putText(Paint, "划伤", cv::Point(rect.x + 10, rect.y - 20), cv::Scalar(0, 255, 0)); - } - //else { - // cv::Mat imgTmp; - // 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); - } - if (huaShangNg == true) - aireuslt.push_back("划伤"); - return aireuslt; -} - -bool ALGO_BaoMoHouCeMian(std::shared_ptr data, baoMoHouDaMianDetParams* _detParams,yh_581_address address){ - qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start"; - std::vector < std::string> defects; - ///////////////////取图//处理////////////////// - if (data->oriImgs.size() != 1) - { - qCritical() << "图片数量不满足要求:" << data->oriImgs.size(); - return false; - } - if (data->oriImgs[0].rows == 100) { - cv::Mat Paint; - data->oriImgs[0].copyTo(Paint); - cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2); - return false; - } - - cv::Mat Paint; - //QMutex paintMutex; - clock_t start, finish; - start = clock(); - - cv::Mat src1 = data->oriImgs[0]; - cv::Mat srcHalf; - cv::resize(src1, srcHalf, cv::Size(0, 0), 0.5, 0.5); - if (srcHalf.channels() != 3) - cv::cvtColor(srcHalf, Paint, cv::COLOR_GRAY2BGR); - else - srcHalf.copyTo(Paint); - TextRendererZH textPainter(Paint.cols, Paint.rows, 150); - //std::future <_581_Result> handleAiFuture = std::async(std::launch::async, _BaoMoHouDaMian, data, srcHalf, Paint, _detParams); - HalconCpp::HObject in_Image = MatToHObject(src1); - HDevEngineCpp::HDevProcedure proc("_4_Cal_Short_Coatingcover_Dist"); - HDevProcedureCall procedureCall(proc); - procedureCall.SetInputIconicParamObject("in_Image", in_Image); - procedureCall.SetInputCtrlParamTuple("in_xResolution", HTuple(0.0308812)); - procedureCall.SetInputCtrlParamTuple("in_yResolution", HTuple(0.029527)); - procedureCall.Execute(); - HTuple out_Width = procedureCall.GetOutputCtrlParamTuple("out_Width"); - HTuple out_Line = procedureCall.GetOutputCtrlParamTuple("out_Line"); - HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag"); - int outFlag = out_Flag.D(); - //handleAiFuture.wait(); - //_result = handleAiFuture.get(); - if (outFlag == 1) { - for (int i = 0; i < out_Line.Length() / 4; i++) { - cv::line(Paint, cv::Point(out_Line[i * 4 + 1].D(), out_Line[i * 4].D()) / 2, - cv::Point(out_Line[i * 4 + 3].D(), out_Line[i * 4 + 2].D()) / 2, - cv::Scalar(0, 255, 0), 5); - } - /*out_Distance[0]: 上端盖到膜的距离< / c> - * out_Distance[1] : 中端盖到膜的距离< / c> - * out_Distance[2] : 下端盖到膜的距离< / c> - * out_Distance[3] : 电芯宽度 < / c> - * out_Distance[4] : 电芯高度< / c>*/ - textPainter.putText(Paint, "电芯厚度:" + std::to_string(out_Width.D()) + "mm", cv::Point(50, 150), cv::Scalar(0, 255, 0)); - } - else { - textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255)); - defects.push_back("算法不良"); - } - data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果 - data->service->_missionResultHandle->toBarChart(data->SNcode, !defects.size()>0, defects); - data->resultImgs.push_back(Paint); - - return true; -} \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam91011/CMakeLists.txt b/src/mission/581-BaoMo-Cam91011/CMakeLists.txt index d94ce25..15e8b6c 100644 --- a/src/mission/581-BaoMo-Cam91011/CMakeLists.txt +++ b/src/mission/581-BaoMo-Cam91011/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581-Dgh-CB-1/CMakeLists.txt b/src/mission/581-Dgh-CB-1/CMakeLists.txt index 26de14b..07f8cdb 100644 --- a/src/mission/581-Dgh-CB-1/CMakeLists.txt +++ b/src/mission/581-Dgh-CB-1/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581-Dgh-CB-2/CMakeLists.txt b/src/mission/581-Dgh-CB-2/CMakeLists.txt index 26de14b..07f8cdb 100644 --- a/src/mission/581-Dgh-CB-2/CMakeLists.txt +++ b/src/mission/581-Dgh-CB-2/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581-Dgh-DB-1/CMakeLists.txt b/src/mission/581-Dgh-DB-1/CMakeLists.txt index 26de14b..07f8cdb 100644 --- a/src/mission/581-Dgh-DB-1/CMakeLists.txt +++ b/src/mission/581-Dgh-DB-1/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581-Dgh-DB-2/581-Dgh-DB-2.h b/src/mission/581-Dgh-DB-2/581-Dgh-DB-2.h index a6d7c26..94fa59e 100644 --- a/src/mission/581-Dgh-DB-2/581-Dgh-DB-2.h +++ b/src/mission/581-Dgh-DB-2/581-Dgh-DB-2.h @@ -4,11 +4,229 @@ #include #include #pragma region 算法 - +class GunYaHou2DParam { +public: + handdleAI::pSegmentation* seg = nullptr; + handdleAI::pClassification* cls = nullptr; + handdleAI::pDetection* det = nullptr; +}; using namespace HDevEngineCpp; -#pragma endregion +static bool generalAlgoTestDuanBian(std::shared_ptr data, detParams* _detParams, yh_581_address address) { + try { + qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start"; + data->customPath = "{imgSaveRootDir}/{yyyy-MM-dd}/{saveObjectName}{imageType}/{HH}H/{processResult}/"; + std::vector < std::string> defects = { "测试" }; + ///////////////////取图//处理////////////////// + if (data->oriImgs.size() < 1) + { + qCritical() << "图片数量不满足要求:" << data->oriImgs.size(); + return false; + } + if (data->oriImgs[0].rows == 100) { + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2); + return false; + } + cv::Mat Paint; + QMutex paintMutex; + clock_t start, finish; + start = clock(); + cv::Mat src1 = data->oriImgs[0]; + if (src1.channels() != 3) + cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR); + else + src1.copyTo(Paint); + + TextRendererZH textPainter(Paint.cols, Paint.rows, 15); + textPainter.putText(Paint, "划伤", cv::Point(10, 10), cv::Scalar(0, 255, 0)); + cv::putText(Paint, "pos:" + data->additional["触发地址"].toString().toStdString(), cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2); + data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.123");//发送数据1 + data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.456");//发送数据2 + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果 + data->service->_missionResultHandle->toBarChart(data->SNcode, !defects.size() > 0, defects);//发送图标操作 + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + return true; + } + CATCH_EXCEPTIONS + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送异常结果 + return false; +} + +void exceptionResume(std::shared_ptr data, GunYaHou2DParam* _detParams, yh_581_address address, QString why = "") { + qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why; + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + textPainter.putText(Paint, why.toStdString(), cv::Point(500, 50), cv::Scalar(0, 255, 0)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 +} +cv::Mat LocalCutImg_DET(handdleAI::pDetection* pDet, cv::Mat src, float zoom, int checkNameId, cv::Rect& cutRoi) +{ + cv::Mat dst; + cv::resize(src, dst, cv::Size(src.cols / zoom, src.rows / zoom)); + std::vector resultBox = pDet->Evaluate(dst); //结果为中心点+宽高 + + cv::Mat contourImg; + std::vector> contours; + //cv::threshold(dstImg, contourImg, pSeg->m_classes, 255, cv::THRESH_BINARY_INV); + //cv::findContours(contourImg, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); + + cv::Mat roiImg; + + if (resultBox.size() <= 0) + { + cv::Mat rstMat = cv::Mat(100, 100, CV_8UC1, cv::Scalar(0, 0, 0)); + cutRoi = cv::Rect(0, 0, 100, 100); + return rstMat; + } + + double maxArea = 0; + int index = -1; + for (int j = 0; j < resultBox.size(); j++) + { + double area = resultBox[j].w * resultBox[j].h; + if (area >= maxArea) + { + maxArea = area; + index = j; + } + } + + /*cv::Rect rect = cv::boundingRect(contours[index]); + cv::rectangle(roiImg, cv::Rect(resultBox[j].x - resultBox[j].w / 2, resultBox[j].y - resultBox[j].h / 2, resultBox[j].w, resultBox[j].h), cv::Scalar(0, 0, 255), 5);*/ + int addpixel = 15; + + cutRoi.x = ((resultBox[index].x - resultBox[index].w / 2) * zoom); + cutRoi.y = ((resultBox[index].y - resultBox[index].h / 2) * zoom); + cutRoi.width = (resultBox[index].w * zoom); + cutRoi.height = (resultBox[index].h * zoom); + //cv::rectangle(src, cutRoi, cv::Scalar(0, 0, 255), 2, 8); + /* cutRoi.x = rect.x * zoom; + cutRoi.y = rect.y * zoom; + cutRoi.width = rect.width * zoom; + cutRoi.height = rect.height * zoom;*/ + + src(cutRoi).copyTo(roiImg); + return roiImg; +} +static std::vectordingGaiHanClsCut(cv::Rect boundingBox, cv::Mat imgInput, cv::Size targetSize = cv::Size(128, 128)) +{ + std::vector result; + int splitCount = getMax(boundingBox.width, boundingBox.height) / getMax(boundingBox.width, boundingBox.height); + //std::cout << "splitCount" << splitCount; + if (splitCount > 2) {//大于2分段裁 + if (boundingBox.width > boundingBox.height) {//宽大于高,横着裁 + for (int i = 0; i < splitCount; i++) { + result.push_back(cutImg2Cls(cv::Rect(boundingBox.x + boundingBox.height * i, boundingBox.y, boundingBox.height, boundingBox.height), imgInput)); + } + result.push_back(cutImg2Cls(cv::Rect(boundingBox.x + boundingBox.width - boundingBox.height, boundingBox.y, boundingBox.height, boundingBox.height), imgInput)); + } + else { + for (int i = 0; i < splitCount; i++) { + result.push_back(cutImg2Cls(cv::Rect(boundingBox.x, boundingBox.y + boundingBox.width * i, boundingBox.width, boundingBox.width), imgInput)); + } + result.push_back(cutImg2Cls(cv::Rect(boundingBox.x, boundingBox.y + boundingBox.height - boundingBox.width, boundingBox.width, boundingBox.width), imgInput)); + } + return result; + } + else + return std::vector(1, cutImg2Cls(boundingBox, imgInput, targetSize)); +} +bool handleAiEvaluate(std::shared_ptr data, GunYaHou2DParam* _detParams,cv::Mat& srcImg, cv::Mat& showImg) { + bool handleAiResultIsOK = true; + clock_t start = clock(); + cv::Mat imgForDet; + srcImg.copyTo(imgForDet); + cv::Rect detRect; + cv::Mat det_Image = LocalCutImg_DET(_detParams->det, imgForDet, 1, 0, detRect); + //addImgToSaveStruct(det_Image, "0", savePath_sorce + "/" + SN + "_det_" + sdataTime_name + ".bmp");//保存seg图 + cv::Mat segImg = ~_detParams->seg->Evaluate(det_Image);//一定要取反,因为seg默认抓到的区域为黑色 + data->segOriginImgs.push_back(segImg); + clock_t stop = clock(); + std::vector>contours;//点集 + stop = clock(); + cv::findContours(segImg, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); // 寻找白色区域并储存为点集 + //QMutexLocker lock(showImgLocker);//加锁防止和halcon线程冲突 + int clsResult = 0; + for (int i = 0; i < contours.size(); i++)//遍历点集 + { + cv::Rect rect = cv::boundingRect(contours[i]);//最小外接矩形 + //if( (rect.height > 25 || rect.width > 50) && (rect.height > 10 && rect.width > 10))// 过滤 + if ((rect.height > 40 || rect.width > 100) && (rect.height > 30 && rect.width > 10)) + { + auto clsimgs = dingGaiHanClsCut(rect, det_Image); + bool isNg = false; + int cnt = 0; + for (auto& clsImg : clsimgs) + { + clsResult = _detParams->cls->Evaluate(clsImg);//cls检测 得出的是int型 从0开始 + if (clsResult == 1 || clsResult == 3) { + isNg = true; + } + //addImgToSaveStruct(clsImg, "0", savePath_sorce + "/" + SN + "_cls" + QString::number(clsResult) + "_" + sdataTime_name + ".bmp"); + data->clsOriginImgs.push_back({std::to_string(clsResult),clsImg}); + cnt++; + drawContours(showImg(detRect), contours, i, cv::Scalar(0, 255, 0), 1); + } + if (isNg == true) + { + rectangle(showImg, cv::Rect{ rect.x + detRect.x,rect.y + detRect.y,rect.width ,rect.height }, cv::Scalar(0, 0, 255), 2, 8, 0); + //drawContours(showImg(detRect), contours, i, cv::Scalar(0, 255, 0), 1); + handleAiResultIsOK = false; + } + else + { + if (clsResult == 2) + { + rectangle(showImg, cv::Rect{ rect.x + detRect.x,rect.y + detRect.y,rect.width ,rect.height }, cv::Scalar(0, 255, 255), 2, 8, 0); + //drawContours(showImg(detRect), contours, i, cv::Scalar(0, 255, 0), 1); + } + } + } + else + { + auto clsimgs = dingGaiHanClsCut(rect, det_Image); + int cnt = 0; + for (auto& clsImg : clsimgs) + { + data->clsOriginImgs.push_back({ std::to_string(clsResult),clsImg }); + //addImgToSaveStruct(clsImg, "0", savePath_sorce + "/CSSMALL_" + SN + "_" + sdataTime_name + ".bmp"); + cnt++; + drawContours(showImg(detRect), contours, i, cv::Scalar(0, 255, 0), 1); + } + } + } + return handleAiResultIsOK; +} +static bool GunYaHou2D(std::shared_ptr data, GunYaHou2DParam* _detParams, yh_581_address address) { + try { + cv::Mat sourceImg = data->oriImgs[0]; + cv::Mat Paint; + sourceImg.copyTo(Paint); + + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + handleAiEvaluate(data, _detParams,sourceImg,Paint); + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 + } + CATCH_EXCEPTIONS + exceptionResume(data, _detParams, address,"算法异常"); + return true; +} +#pragma endregion class _581_Dgh : public mission { public: @@ -16,25 +234,30 @@ public: generalTrigger dgh_db_mh_2d_1; generalTrigger dgh_db_mh_2d_2; - generalTrigger dgh_db_gy_2d_1; - generalTrigger dgh_db_gy_2d_2; + _581_Union_triggerTemplate dgh_db_gy_2d_1; + _581_Union_triggerTemplate dgh_db_gy_2d_2; generalTrigger dgh_db_gy_3d_1; generalTrigger dgh_db_gy_3d_2; detParams _params; + std::vector _GunYaHou2DParam = std::vector(2); + bool initOnce = false; void onConfigReloaded() { HDevEngineCpp::HDevEngine myEngine; myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl"); + if (initOnce == false) { + initOnce = true; + } } bool initCustom(){ #pragma region 注册触发器回调 满焊 - dgh_db_mh_2d_1.init("Camera1", "短边满焊前2D-1", 18400,4,1, &_params, _serviceManager, bridge, generalAlgoTest); - dgh_db_mh_2d_2.init("Camera2", "短边满焊前2D-2", 18600,4,1, &_params, _serviceManager, bridge, generalAlgoTest); - dgh_db_gy_2d_1.init("Camera3", "短边滚压后2D-1", 19200,4,1, &_params, _serviceManager, bridge, generalAlgoTest); - dgh_db_gy_2d_2.init("Camera4", "短边滚压后2D-2", 19400,4,1, &_params, _serviceManager, bridge, generalAlgoTest); - dgh_db_gy_3d_1.init("Camera5", "短边滚压后3D-1", 19600,4,1, &_params, _serviceManager, bridge, generalAlgoTest); - dgh_db_gy_3d_2.init("Camera6", "短边滚压后3D-2", 19800,4,1, &_params, _serviceManager, bridge, generalAlgoTest); + dgh_db_mh_2d_1.init("Camera1", "短边满焊前2D-1", 18400,4,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "满焊前2D"); + dgh_db_mh_2d_2.init("Camera2", "短边满焊前2D-2", 18600,4,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "满焊前2D"); + dgh_db_gy_2d_1.init("Camera3", "短边滚压后2D-1-外侧", 19200,4,1, &_GunYaHou2DParam[0], _serviceManager, bridge, GunYaHou2D, "滚压后2D"); + dgh_db_gy_2d_2.init("Camera4", "短边滚压后2D-2-内侧", 19400,4,1, &_GunYaHou2DParam[1], _serviceManager, bridge, GunYaHou2D, "滚压后2D"); + dgh_db_gy_3d_1.init("Camera5", "短边滚压后3D-1", 19600,4,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "滚压后3D"); + dgh_db_gy_3d_2.init("Camera6", "短边滚压后3D-2", 19800,4,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "滚压后3D"); #pragma endregion return true; } diff --git a/src/mission/581-Dgh-DB-2/CMakeLists.txt b/src/mission/581-Dgh-DB-2/CMakeLists.txt index 26de14b..07f8cdb 100644 --- a/src/mission/581-Dgh-DB-2/CMakeLists.txt +++ b/src/mission/581-Dgh-DB-2/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581-Mfd_djy_sd/CMakeLists.txt b/src/mission/581-Mfd_djy_sd/CMakeLists.txt index d94ce25..15e8b6c 100644 --- a/src/mission/581-Mfd_djy_sd/CMakeLists.txt +++ b/src/mission/581-Mfd_djy_sd/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581-Mfd_yh_mh_hh/581-Mfd.h b/src/mission/581-Mfd_yh_mh_hh/581-Mfd.h index 0e38554..86c611e 100644 --- a/src/mission/581-Mfd_yh_mh_hh/581-Mfd.h +++ b/src/mission/581-Mfd_yh_mh_hh/581-Mfd.h @@ -79,7 +79,7 @@ static bool ManHan(std::shared_ptr data, mfd_detParams* _detParams, yh cameraNumberStr = "4"; FixtureNumber = "8"; } - data->customPath = QString::fromStdString("{imgSaveRootDir}/{yyyy-MM-dd}/{HH}H/{imageType}/{processResult}/相机" + cameraNumberStr + "孔" + FixtureNumber + "/"); + data->customPath = QString::fromStdString("{imgSaveRootDir}/{yyyy-MM-dd}/{saveObjectName}{imageType}/{HH}H/{processResult}/相机" + cameraNumberStr + "孔" + FixtureNumber + "/"); HalconCpp::HObject in_Image = MatToHObject(src1); HDevEngineCpp::HDevProcedure proc("_9_manhan"); HDevProcedureCall procedureCall(proc); @@ -166,6 +166,7 @@ static bool ManHan(std::shared_ptr data, mfd_detParams* _detParams, yh } static bool YuHan(std::shared_ptr data, mfd_detParams* _detParams, yh_581_address address){ try { + data->service->_missionResultHandle->toBarChart("", true, {"测试"}); std::map sqlMapData; sqlMapData["项目"] = "预焊"; sqlMapData["相机"] = "相机" + address.triggerAddr; diff --git a/src/mission/581-Mfd_yh_mh_hh/CMakeLists.txt b/src/mission/581-Mfd_yh_mh_hh/CMakeLists.txt index d94ce25..15e8b6c 100644 --- a/src/mission/581-Mfd_yh_mh_hh/CMakeLists.txt +++ b/src/mission/581-Mfd_yh_mh_hh/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581-Ruke/CMakeLists.txt b/src/mission/581-Ruke/CMakeLists.txt index 26347b4..7e8a6b0 100644 --- a/src/mission/581-Ruke/CMakeLists.txt +++ b/src/mission/581-Ruke/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.h b/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.h index 24e91d3..f1b5230 100644 --- a/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.h +++ b/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.h @@ -42,9 +42,9 @@ public: bool initCustom() { #pragma region 注册触发器回调 - cam_1.init("Camera1", "残液检测-相机1", { { 1900, 1,1800,"1910","1920"} }, 1, &canyeDetParams[0], _serviceManager, bridge, yizhuCanYe); - cam_2.init("Camera2", "残液检测-相机2", { { 1901, 1,1830,"1911","1921"} }, 1, &canyeDetParams[1], _serviceManager, bridge, yizhuCanYe); - cam_3.init("Camera3", "残液检测-相机3", { { 1902, 1,1850,"1912","1922"} }, 1, &canyeDetParams[2], _serviceManager, bridge, yizhuCanYe); + cam_1.init("Camera1", "残液检测-相机1", { { 1900, 1,{1800},"1910","1920"} }, 1, &canyeDetParams[0], _serviceManager, bridge, yizhuCanYe); + cam_2.init("Camera2", "残液检测-相机2", { { 1901, 1,{1830},"1911","1921"} }, 1, &canyeDetParams[1], _serviceManager, bridge, yizhuCanYe); + cam_3.init("Camera3", "残液检测-相机3", { { 1902, 1,{1850},"1912","1922"} }, 1, &canyeDetParams[2], _serviceManager, bridge, yizhuCanYe); #pragma endregion return true; diff --git a/src/mission/581_YiCiZhuYe_canye/CMakeLists.txt b/src/mission/581_YiCiZhuYe_canye/CMakeLists.txt index 26347b4..7e8a6b0 100644 --- a/src/mission/581_YiCiZhuYe_canye/CMakeLists.txt +++ b/src/mission/581_YiCiZhuYe_canye/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581_YuHan_hanhou/581_YuHan_hanhou.h b/src/mission/581_YuHan_hanhou/581_YuHan_hanhou.h index 3b54e5d..558aeb1 100644 --- a/src/mission/581_YuHan_hanhou/581_YuHan_hanhou.h +++ b/src/mission/581_YuHan_hanhou/581_YuHan_hanhou.h @@ -67,27 +67,27 @@ public: } bool initCustom() { #pragma region 注册触发器回调 - if (_configMap["hanhou"] == "OUT") { - lv_top90_1.init("Camera1", "极耳尺寸-外-铝-相机1(顶部90°)", { { 522, 1,540,"523","530",820} }, 1, &lvDetParams[0], _serviceManager, bridge, hanHouCeLiang); - lv_down90_2.init("Camera2", "极耳尺寸-外-铝-相机2(底部90°)", { { 524, 1,540,"525","532",-1} }, 1, &lvDetParams[1], _serviceManager, bridge, hanHouDown); - tong_top90_3.init("Camera3", "极耳尺寸-外-铜-相机3(顶部90°)", { { 526,1,540,"527","534",800} }, 1, &tongDetParams[0], _serviceManager, bridge, hanHouCeLiang); - tong_down90_4.init("Camera4", "极耳尺寸-外-铜-相机4(底部90°)", { { 528, 1,540,"529","536",-1} }, 1, &tongDetParams[1], _serviceManager, bridge, hanHouDown); + if (_serviceManager->_paramSyncManager->get("hanhou","OUT") == "OUT") { + lv_top90_1.init("Camera1", "极耳尺寸-外-铝-相机1(顶部90°)", { { 522, 1,{540},"523","530",820} }, 1, &lvDetParams[0], _serviceManager, bridge, hanHouCeLiang); + lv_down90_2.init("Camera2", "极耳尺寸-外-铝-相机2(底部90°)", { { 524, 1,{540},"525","532",-1} }, 1, &lvDetParams[1], _serviceManager, bridge, hanHouDown); + tong_top90_3.init("Camera3", "极耳尺寸-外-铜-相机3(顶部90°)", { { 526,1,{540},"527","534",800} }, 1, &tongDetParams[0], _serviceManager, bridge, hanHouCeLiang); + tong_down90_4.init("Camera4", "极耳尺寸-外-铜-相机4(底部90°)", { { 528, 1,{540},"529","536",-1} }, 1, &tongDetParams[1], _serviceManager, bridge, hanHouDown); - lv_top45_5.init("Camera5", "底部撕裂-外-铝-相机5(顶部45°)", { { 562,1,540,"563","570",-1} }, 1, &lvDetParams[2], _serviceManager, bridge, hanHouDown); - lv_down45_6.init("Camera6", "底部撕裂-外-铝-相机6(底部45°)", { { 564, 1,540,"565","572",-1} }, 1, &lvDetParams[3], _serviceManager, bridge, hanHouDown); - tong_top45_7.init("Camera7", "底部撕裂-外-铜-相机7(顶部45°)", { { 566, 1,540,"567","574",-1} }, 1, &tongDetParams[2], _serviceManager, bridge, hanHouDown); - tong_down45_8.init("Camera8", "底部撕裂-外-铜-相机8(底部45°)", { { 568, 1,540,"569","576",-1} }, 1, &tongDetParams[3], _serviceManager, bridge, hanHouDown); + lv_top45_5.init("Camera5", "底部撕裂-外-铝-相机5(顶部45°)", { { 562,1,{540},"563","570",-1} }, 1, &lvDetParams[2], _serviceManager, bridge, hanHouDown); + lv_down45_6.init("Camera6", "底部撕裂-外-铝-相机6(底部45°)", { { 564, 1,{540},"565","572",-1} }, 1, &lvDetParams[3], _serviceManager, bridge, hanHouDown); + tong_top45_7.init("Camera7", "底部撕裂-外-铜-相机7(顶部45°)", { { 566, 1,{540},"567","574",-1} }, 1, &tongDetParams[2], _serviceManager, bridge, hanHouDown); + tong_down45_8.init("Camera8", "底部撕裂-外-铜-相机8(底部45°)", { { 568, 1,{540},"569","576",-1} }, 1, &tongDetParams[3], _serviceManager, bridge, hanHouDown); } else { - lv_top90_1.init("Camera1", "极耳尺寸-内-铝-相机1(顶部90°)", { { 602, 1,580,"603","610",860} }, 1, &lvDetParams[0], _serviceManager, bridge, hanHouCeLiang); - lv_down90_2.init("Camera2", "极耳尺寸-内-铝-相机2(底部90°)", { { 604, 1,580,"605","612",-1} }, 1, &lvDetParams[1], _serviceManager, bridge, hanHouDown); - tong_top90_3.init("Camera3", "极耳尺寸-内-铜-相机3(顶部90°)", { { 606,1,580,"607","614",840} }, 1, &tongDetParams[0], _serviceManager, bridge, hanHouCeLiang); - tong_down90_4.init("Camera4", "极耳尺寸-内-铜-相机4(底部90°)", { { 608, 1,580,"609","616",-1} }, 1, &tongDetParams[1], _serviceManager, bridge, hanHouDown); + lv_top90_1.init("Camera1", "极耳尺寸-内-铝-相机1(顶部90°)", { { 602, 1,{580},"603","610",860} }, 1, &lvDetParams[0], _serviceManager, bridge, hanHouCeLiang); + lv_down90_2.init("Camera2", "极耳尺寸-内-铝-相机2(底部90°)", { { 604, 1,{580},"605","612",-1} }, 1, &lvDetParams[1], _serviceManager, bridge, hanHouDown); + tong_top90_3.init("Camera3", "极耳尺寸-内-铜-相机3(顶部90°)", { { 606,1,{580},"607","614",840} }, 1, &tongDetParams[0], _serviceManager, bridge, hanHouCeLiang); + tong_down90_4.init("Camera4", "极耳尺寸-内-铜-相机4(底部90°)", { { 608, 1,{580},"609","616",-1} }, 1, &tongDetParams[1], _serviceManager, bridge, hanHouDown); - lv_top45_5.init("Camera5", "底部撕裂-内-铝-相机5(顶部45°)", { { 642,1,580,"643","650",-1} }, 1, &lvDetParams[2], _serviceManager, bridge, hanHouDown); - lv_down45_6.init("Camera6", "底部撕裂-内-铝-相机6(底部45°)", { { 644, 1,580,"645","652",-1} }, 1, &lvDetParams[3], _serviceManager, bridge, hanHouDown); - tong_top45_7.init("Camera7", "底部撕裂-内-铜-相机7(顶部45°)", { { 646, 1,580,"647","654",-1} }, 1, &tongDetParams[2], _serviceManager, bridge, hanHouDown); - tong_down45_8.init("Camera8", "底部撕裂-内-铜-相机8(底部45°)", { { 648, 1,580,"649","656",-1} }, 1, &tongDetParams[3], _serviceManager, bridge, hanHouDown); + lv_top45_5.init("Camera5", "底部撕裂-内-铝-相机5(顶部45°)", { { 642,1,{580},"643","650",-1} }, 1, &lvDetParams[2], _serviceManager, bridge, hanHouDown); + lv_down45_6.init("Camera6", "底部撕裂-内-铝-相机6(底部45°)", { { 644, 1,{580},"645","652",-1} }, 1, &lvDetParams[3], _serviceManager, bridge, hanHouDown); + tong_top45_7.init("Camera7", "底部撕裂-内-铜-相机7(顶部45°)", { { 646, 1,{580},"647","654",-1} }, 1, &tongDetParams[2], _serviceManager, bridge, hanHouDown); + tong_down45_8.init("Camera8", "底部撕裂-内-铜-相机8(底部45°)", { { 648, 1,{580},"649","656",-1} }, 1, &tongDetParams[3], _serviceManager, bridge, hanHouDown); } #pragma endregion return true; diff --git a/src/mission/581_YuHan_hanhou/CMakeLists.txt b/src/mission/581_YuHan_hanhou/CMakeLists.txt index 26347b4..7e8a6b0 100644 --- a/src/mission/581_YuHan_hanhou/CMakeLists.txt +++ b/src/mission/581_YuHan_hanhou/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581_YuHan_hanqian/581_YuHan_hanqian.h b/src/mission/581_YuHan_hanqian/581_YuHan_hanqian.h index 46ae801..d0bf975 100644 --- a/src/mission/581_YuHan_hanqian/581_YuHan_hanqian.h +++ b/src/mission/581_YuHan_hanqian/581_YuHan_hanqian.h @@ -242,15 +242,15 @@ public: } bool initCustom() { #pragma region 注册触发器回调 - in_lv_top_1.init("Camera1", "极耳翻折-铝-内-相机1(顶部)", { { 682, 1,760,"683","670",-1} }, 1, &lvDetParams[0], _serviceManager, bridge, jiErFanZhe); - in_lv_down_2.init("Camera2", "极耳翻折-铝-内-相机2(底部)", { { 684, 1,760,"685","672",-1} }, 1, &lvDetParams[1], _serviceManager, bridge, jiErFanZhe); - in_tong_top_3.init("Camera3", "极耳翻折-铜-内-相机3(顶部)", { { 686,1,760,"687","674",-1} }, 1, &tongDetParams[0], _serviceManager, bridge, jiErFanZhe); - in_tong_down_4.init("Camera4", "极耳翻折-铜-内-相机4(底部)", { { 688, 1,760,"689","676",-1} }, 1, &tongDetParams[1], _serviceManager, bridge, jiErFanZhe); + in_lv_top_1.init("Camera1", "极耳翻折-铝-内-相机1(顶部)", { { 682, 1,{760},"683","670",-1} }, 1, &lvDetParams[0], _serviceManager, bridge, jiErFanZhe); + in_lv_down_2.init("Camera2", "极耳翻折-铝-内-相机2(底部)", { { 684, 1,{760},"685","672",-1} }, 1, &lvDetParams[1], _serviceManager, bridge, jiErFanZhe); + in_tong_top_3.init("Camera3", "极耳翻折-铜-内-相机3(顶部)", { { 686,1,{760},"687","674",-1} }, 1, &tongDetParams[0], _serviceManager, bridge, jiErFanZhe); + in_tong_down_4.init("Camera4", "极耳翻折-铜-内-相机4(底部)", { { 688, 1,{760},"689","676",-1} }, 1, &tongDetParams[1], _serviceManager, bridge, jiErFanZhe); - out_lv_top_5.init("Camera5", "极耳翻折-铝-外-相机5(顶部)", { { 702,1,720,"703","710",-1} }, 1, &lvDetParams[2], _serviceManager, bridge, jiErFanZhe); - out_lv_down_6.init("Camera6", "极耳翻折-铝-外-相机6(底部)", { { 704, 1,720,"705","712",-1} }, 1, &lvDetParams[3], _serviceManager, bridge, jiErFanZhe); - out_tong_top_7.init("Camera7", "极耳翻折-铜-外-相机7(顶部)", { { 706, 1,720,"707","714",-1} }, 1, &tongDetParams[2], _serviceManager, bridge, jiErFanZhe); - out_tong_down_8.init("Camera8", "极耳翻折-铜-外-相机8(底部)", { { 708, 1,720,"709","716",-1} }, 1, &tongDetParams[3], _serviceManager, bridge, jiErFanZhe); + out_lv_top_5.init("Camera5", "极耳翻折-铝-外-相机5(顶部)", { { 702,1,{720},"703","710",-1} }, 1, &lvDetParams[2], _serviceManager, bridge, jiErFanZhe); + out_lv_down_6.init("Camera6", "极耳翻折-铝-外-相机6(底部)", { { 704, 1,{720},"705","712",-1} }, 1, &lvDetParams[3], _serviceManager, bridge, jiErFanZhe); + out_tong_top_7.init("Camera7", "极耳翻折-铜-外-相机7(顶部)", { { 706, 1,{720},"707","714",-1} }, 1, &tongDetParams[2], _serviceManager, bridge, jiErFanZhe); + out_tong_down_8.init("Camera8", "极耳翻折-铜-外-相机8(底部)", { { 708, 1,{720},"709","716",-1} }, 1, &tongDetParams[3], _serviceManager, bridge, jiErFanZhe); #pragma endregion return true; } diff --git a/src/mission/581_YuHan_hanqian/CMakeLists.txt b/src/mission/581_YuHan_hanqian/CMakeLists.txt index 26347b4..7e8a6b0 100644 --- a/src/mission/581_YuHan_hanqian/CMakeLists.txt +++ b/src/mission/581_YuHan_hanqian/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581-BaoMo-Cam5678/581-BaoMo.cpp b/src/mission/581_ZhongHan_dibutiejiao/581_ZhongHan_dibutiejiao.cpp similarity index 55% rename from src/mission/581-BaoMo-Cam5678/581-BaoMo.cpp rename to src/mission/581_ZhongHan_dibutiejiao/581_ZhongHan_dibutiejiao.cpp index 0ee499e..ad9a35b 100644 --- a/src/mission/581-BaoMo-Cam5678/581-BaoMo.cpp +++ b/src/mission/581_ZhongHan_dibutiejiao/581_ZhongHan_dibutiejiao.cpp @@ -1,7 +1,7 @@ -#include <581-BaoMo.h> +#include <581_ZhongHan_dibutiejiao.h> mission* createMission() { - return new _581_BaoMo(); + return new _581_YuHan_hanqian(); } void destroyMission(mission* _mission) { delete _mission; diff --git a/src/mission/581_ZhongHan_dibutiejiao/581_ZhongHan_dibutiejiao.h b/src/mission/581_ZhongHan_dibutiejiao/581_ZhongHan_dibutiejiao.h new file mode 100644 index 0000000..2ad015f --- /dev/null +++ b/src/mission/581_ZhongHan_dibutiejiao/581_ZhongHan_dibutiejiao.h @@ -0,0 +1,410 @@ +#include +#include +#pragma region 算法 +#include +#include +#include +using namespace HDevEngineCpp; +#pragma endregion +class zhongHanFanMianTeJiaoParams { +public: + bool isTong = true; + std::string in_Product_Str = "Cu"; + +}; +void GetStringSize(HDC hdc, const char* str, int* w, int* h) +{ + SIZE size; + GetTextExtentPoint32A(hdc, str, strlen(str), &size); + if (w != 0) *w = size.cx; + if (h != 0) *h = size.cy; +} +void DrawRotatedRect2Mat(cv::Mat& img, cv::RotatedRect rotateRect, cv::Scalar color, int thickness, int linType) +{ + std::vector boxPts(4); + rotateRect.points(boxPts.data()); + for (int mm = 0; mm < 4; mm++) { + cv::line(img, boxPts[mm], boxPts[(mm + 1) % 4], color, thickness, linType); + } +} + +bool halconProcess(cv::Mat& sourceImg, cv::Mat& Paint,std::string produce) { + try { + + HDevEngineCpp::HDevProcedure proc("_3_Neg_CoverGlue_Inspection"); + HDevEngineCpp::HDevProcedureCall procedureCall(proc); + + HalconCpp::HObject in_Image;//原始三通道图像 + HalconCpp::HTuple in_Product = HalconCpp::HTuple((char*)produce.c_str());//产品类别, 'Gu':铜 'Al':铝 + HalconCpp::HTuple in_LineType = "602";//线体类别 + HalconCpp::HTuple in_Resolution(0.0192118);//相机精度(mm/pix) + HalconCpp::HTuple in_FilePath("./halconFiles/ZH_TieJiao_Down/");//模板文件路径 + + in_Image = MatToHObject(sourceImg); + procedureCall.SetInputIconicParamObject("in_Image", in_Image); + procedureCall.SetInputCtrlParamTuple("in_Product", in_Product); + procedureCall.SetInputCtrlParamTuple("in_LineType", in_LineType); + procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution); + procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath); + procedureCall.Execute();//执行halcon程序 + + HalconCpp::HTuple out_Circle;//焊印圆中心坐标(y,x,R) + HalconCpp::HTuple out_LinePoint;//线的坐标(y1,x1,y2,x2) + HalconCpp::HTuple out_Distance;//连接片的中心到上下极耳胶纸的距离 + //out_Distance[0]:连接片的中心到上极耳胶纸的距离< / c> + //out_Distance[1] : 连接片的中心到下极耳胶纸的距离< / c> + HalconCpp::HTuple out_Rectangle;//矩形框,共计两个(y,x,phi,width,height) + HalconCpp::HTuple out_NGTails;//NG的明细 + HalconCpp::HTuple out_Flag;//算法的执行结果, 0: 算法检测NG 1: 算法执行成功 + out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle"); + out_LinePoint = procedureCall.GetOutputCtrlParamTuple("out_LinePoint"); + out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance"); + out_Rectangle = procedureCall.GetOutputCtrlParamTuple("out_Rectangle"); + out_NGTails = procedureCall.GetOutputCtrlParamTuple("out_NGTails"); + out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag"); + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + if (out_Flag.D() == 1) { + int out_Distanc_Size = out_Distance.Length(); + if (out_Distance.Length() > 1) { + double distance1 = out_Distance[0].D(); + if (distance1 <= 12) {//NG + textPainter.putText(Paint, + ("连接片的中心到上极耳胶纸的距离:" + QByteArray::number(distance1) + "mm").toStdString().c_str(), + cv::Point(0, 600), cv::Scalar(0, 255, 0)); + + } + else { + textPainter.putText(Paint, + ("连接片的中心到上极耳胶纸的距离:" + QByteArray::number(distance1) + "mm").toStdString().c_str(), + cv::Point(0, 600), cv::Scalar(0, 255, 0)); + } + double distance2 = out_Distance[1].D(); + if (distance2 <= 12) {//NG + textPainter.putText(Paint, + ("连接片的中心到下极耳胶纸的距离:" + QByteArray::number(distance2) + "mm").toStdString().c_str(), + cv::Point(0, 1050), cv::Scalar(0, 255, 0)); + } + else { + textPainter.putText(Paint, + ("连接片的中心到下极耳胶纸的距离:" + QByteArray::number(distance2) + "mm").toStdString().c_str(), + cv::Point(0, 1050), cv::Scalar(0, 255, 0)); + } + } + + //画圆心十字 + cv::drawMarker(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), cv::Scalar(0, 255, 0), cv::MARKER_CROSS, 200, 5); + + //画圆 + cv::circle(Paint, + cv::Point(out_Circle[1].D(), out_Circle[0].D()), + out_Circle[2].D(), cv::Scalar(0, 255, 0), 5); + + //画线 + if (out_LinePoint.Length() > 3) { + for (int i = 0; i < out_LinePoint.Length() / 4; i++) { + cv::line(Paint, + cv::Point(out_LinePoint[i * 4 + 1].D(), out_LinePoint[i * 4 + 0].D()), + cv::Point(out_LinePoint[i * 4 + 3].D(), out_LinePoint[i * 4 + 2].D()), + cv::Scalar(0, 255, 0), 5); + } + } + + //画矩形 + if (out_Rectangle.Length() > 4) { + for (int j = 0; j < out_Rectangle.Length() / 5; j++) { + cv::RotatedRect rRect; + rRect.center.y = out_Rectangle[j * 5 + 0].D(); + rRect.center.x = out_Rectangle[j * 5 + 1].D(); + rRect.angle = out_Rectangle[j * 5 + 2].D(); + rRect.size.width = out_Rectangle[j * 5 + 3].D(); + rRect.size.height = out_Rectangle[j * 5 + 4].D(); + + DrawRotatedRect2Mat(Paint, rRect, cv::Scalar(0, 255, 0), 3, cv::LINE_4); + } + } + } + else { + std::string NgTails = out_NGTails.S().Text();//NG明细 + textPainter.putText(Paint, NgTails.c_str(), cv::Point(0, 550), cv::Scalar(0, 255, 255)); + } + if (out_Flag.D() == 1) { + textPainter.putText(Paint,"OK", cv::Point(0, 50), cv::Scalar(0, 255, 0)); + return false; + } + else { + textPainter.putText(Paint, "NG", cv::Point(0, 50), cv::Scalar(0, 0, 255)); + return true; + } + + } + catch (HDevEngineCpp::HDevEngineException& ex) { + + std::cout << "HDevEngineException: " << ex.Message() << std::endl; \ + qDebug() << "HDevEngineException: " << ex.Message(); \ + } + catch (HalconCpp::HException& ex) { + + std::cout << "Halcon Exception Caught!" << std::endl; \ + std::cout << "Error Code: " << ex.ErrorCode() << std::endl; \ + std::cout << "Error Message: " << ex.ErrorMessage() << std::endl; \ + qDebug() << "Halcon Exception Caught!"; \ + qDebug() << "Error Code: " << ex.ErrorCode(); \ + qDebug() << "Error Message: " << ex.ErrorMessage(); \ + } +} +bool dibutiejiao_90(std::shared_ptr data, zhongHanFanMianTeJiaoParams* _detParams, sx_581_address address) { + try{ +#if 0 + /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓调试用↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/ + cv::Mat resultImage = img2D.clone(); + if (resultImage.channels() == 1) { + cv::cvtColor(resultImage, resultImage, cv::COLOR_GRAY2BGR); + } + QString okng_tag = "OK"; + cv::Mat seg_detectImage; + cv::resize(img2D, seg_detectImage, cv::Size(), 1, 1); + plcResult = "1"; + bool isNG = false; + if (DOGLIVE) { + std::vector>clsImgs; + bool isNG = handleAiProcess(seg_detectImage, resultImage, seg_jierFanZhe, cls_jierFanZhe, clsImgs); + for (int i = 0; i < clsImgs.size(); i++) { + addImgToSaveStruct(clsImgs[i].second, "0", getClsSaveFormat(SN, okng_tag, i, clsImgs[i].first)); + } + } + if (isNG == false)//OK + { + putTextHusky(resultImage, utf8_to_gbk("OK").c_str(), cv::Point(50, 50), cv::Scalar(0, 255, 0), 200); + okng_tag = "OK"; + } + else + { + putTextHusky(resultImage, utf8_to_gbk("NG").c_str(), cv::Point(50, 50), cv::Scalar(0, 0, 255), 200); + plcResult = "2"; + } + cv::resize(resultImage, resultImage, cv::Size(), 0.5, 0.5); + resMat.push_back(resultImage); + if (resMat.size() > 0) + { + addImgToSaveStruct(seg_detectImage, "0", getSegSaveFormat(SN, okng_tag));//存seg图 + addImgToSaveStruct(resMat[0], "0", getResSaveFormat(SN, okng_tag));//存结果图 + } + addImgToSaveStruct(HikMat[0], "0", getOriSaveFormat(SN, okng_tag));//存原图图 + + return true; + /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑调试用↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/ +#else + //存图数据加保存队列,加锁,避免数据访问冲突 + QByteArray plcResult = "2"; + cv::Mat sourceImg; + data->oriImgs[0].copyTo(sourceImg); + cv::Mat Paint; + if (_detParams->in_Product_Str == "Cu") { + cv::rotate(sourceImg, sourceImg, cv::ROTATE_180);//为保证算法一致, + } + sourceImg.copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + bool isNG = halconProcess(sourceImg, Paint, _detParams->in_Product_Str); + QString okNgSaveText = "NG"; + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + if (isNG == false)//OK + { + okNgSaveText = "OK"; + plcResult = "1"; + } + else + { + data->aiDetOK = false; + plcResult = "2"; + } + plcResult = "1";//强制OK + data->resultImgs.push_back(Paint); + sourceImg.release(); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + return true; +#endif + } + CATCH_EXCEPTIONS + + qDebug() << "[Error] " << QString::fromUtf8("检测失败!"); + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + TextRendererZH textPainter(Paint.cols, Paint.rows, 15); + textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 + return true; +} +//void aiEvaluate(cv::Mat input, cv::Mat& Paint, bool& isNG) +//{ +// cv::Mat forSeg; +// input.copyTo(forSeg); +// cv::resize(forSeg, forSeg, cv::Size(), 0.25, 0.25); +// cv::Mat segRes = ~seg_diBu->Evaluate(forSeg); +// cv::resize(segRes, segRes, cv::Size(), 4, 4); +// std::vector>contours; +// cv::findContours(segRes, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); +// for (auto& contour : contours) { +// cv::Rect rect = cv::boundingRect(contour); +// if (rect.width < 350 || rect.height < 350) +// continue; +// cv::Mat clsImg = cutImg2Cls(rect, input); +// int claResult = cls_diBu->Evaluate(clsImg); +// switch (claResult) +// { +// case 0://OK +// cv::rectangle(Paint, rect, cv::Scalar(0, 255, 0), 3); +// break; +// case 1://NG +// cv::rectangle(Paint, rect, cv::Scalar(0, 0, 255), 3); +// putTextHusky(Paint, +// utf8_to_gbk("NG").c_str(), +// cv::Point(rect.x, rect.y), cv::Scalar(0, 0, 255), 50); +// isNG = true; +// break; +// } +// } +// +//} +bool dibutiejiao_45(std::shared_ptr data, zhongHanFanMianTeJiaoParams* _detParams, sx_581_address address) { + try { +#if 0 + /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓调试用↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/ + cv::Mat resultImage = img2D.clone(); + if (resultImage.channels() == 1) { + cv::cvtColor(resultImage, resultImage, cv::COLOR_GRAY2BGR); + } + QString okng_tag = "OK"; + cv::Mat seg_detectImage; + cv::resize(img2D, seg_detectImage, cv::Size(), 1, 1); + plcResult = "1"; + bool isNG = false; + if (DOGLIVE) { + std::vector>clsImgs; + bool isNG = handleAiProcess(seg_detectImage, resultImage, seg_jierFanZhe, cls_jierFanZhe, clsImgs); + for (int i = 0; i < clsImgs.size(); i++) { + addImgToSaveStruct(clsImgs[i].second, "0", getClsSaveFormat(SN, okng_tag, i, clsImgs[i].first)); + } + } + if (isNG == false)//OK + { + putTextHusky(resultImage, utf8_to_gbk("OK").c_str(), cv::Point(50, 50), cv::Scalar(0, 255, 0), 200); + okng_tag = "OK"; + } + else + { + putTextHusky(resultImage, utf8_to_gbk("NG").c_str(), cv::Point(50, 50), cv::Scalar(0, 0, 255), 200); + plcResult = "2"; + } + cv::resize(resultImage, resultImage, cv::Size(), 0.5, 0.5); + resMat.push_back(resultImage); + if (resMat.size() > 0) + { + addImgToSaveStruct(seg_detectImage, "0", getSegSaveFormat(SN, okng_tag));//存seg图 + addImgToSaveStruct(resMat[0], "0", getResSaveFormat(SN, okng_tag));//存结果图 + } + addImgToSaveStruct(HikMat[0], "0", getOriSaveFormat(SN, okng_tag));//存原图图 + + return true; + /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑调试用↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/ +#else + //存图数据加保存队列,加锁,避免数据访问冲突 + QByteArray plcResult = "2"; + cv::Mat sourceImg; + data->oriImgs[0].copyTo(sourceImg); + cv::Mat Paint; + cv::resize(sourceImg, sourceImg, cv::Size(), 0.5, 0.5); + sourceImg.copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + bool isNG = false; + //aiEvaluate(sourceImg, Paint, isNG); + QString okNgSaveText = "NG"; + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + if (isNG == false)//OK + { + textPainter.putText(Paint, "OK", cv::Point(100, 50), cv::Scalar(0, 255, 0)); + okNgSaveText = "OK"; + } + else + { + textPainter.putText(Paint, "NG", cv::Point(100, 50), cv::Scalar(0, 255, 0)); + data->aiDetOK = false; + plcResult = "2"; + } + plcResult = "1";//强制OK + data->resultImgs.push_back(Paint); + sourceImg.release(); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + return true; +#endif + } + CATCH_EXCEPTIONS + + qDebug() << "[Error] " << QString::fromUtf8("检测失败!"); + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + TextRendererZH textPainter(Paint.cols, Paint.rows, 15); + textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 + return true; +} +class _581_YuHan_hanqian : public mission { +public: + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> chuizhi_1; + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> qingxie_2; + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> qingxie_3; + + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> chuizhi_4; + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> qingxie_5; + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> qingxie_6; + + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> chuizhi_7; + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> qingxie_8; + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> qingxie_9; + + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> chuizhi_10; + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> qingxie_11; + _581_SX_Single_triggerTemplate< zhongHanFanMianTeJiaoParams> qingxie_12; + zhongHanFanMianTeJiaoParams tongDetParams; + zhongHanFanMianTeJiaoParams lvDetParams; + void onConfigReloaded() { + HDevEngineCpp::HDevEngine myEngine; + myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl"); + lvDetParams.isTong = false; + tongDetParams.in_Product_Str = "Cu"; + lvDetParams.in_Product_Str="Lv"; + + } + bool initCustom() { +#pragma region 注册触发器回调 + chuizhi_1.init("Camera1", "底部贴胶检测-左-铜-相机1(90°)", { { 5500, 1,{5530},"5502","5504",-1} }, 1, &tongDetParams, _serviceManager, bridge, dibutiejiao_90,"贴胶90度"); + qingxie_2.init("Camera2", "底部贴胶检测-左-铜-相机2(45°)", { { 5510, 1,{5530},"5512","5514",-1} }, 1, &tongDetParams, _serviceManager, bridge, dibutiejiao_45,"贴胶45度"); + qingxie_3.init("Camera3", "底部贴胶检测-左-铜-相机3(45°)", { { 5520, 1,{5530},"5522","5524",-1} }, 1, &tongDetParams, _serviceManager, bridge, dibutiejiao_45,"贴胶45度"); + chuizhi_4.init("Camera4", "底部贴胶检测-左-铝-相机4(90°)", { { 5550, 1,{5530},"5552","5554",-1} }, 1, &lvDetParams, _serviceManager, bridge, dibutiejiao_90, "贴胶90度"); + qingxie_5.init("Camera5", "底部贴胶检测-左-铝-相机5(45°)", { { 5560, 1,{5530},"5562","5564",-1} }, 1, &lvDetParams, _serviceManager, bridge, dibutiejiao_45, "贴胶45度"); + qingxie_6.init("Camera6", "底部贴胶检测-左-铝-相机6(45°)", { { 5570, 1,{5530},"5572","5574",-1} }, 1, &lvDetParams, _serviceManager, bridge, dibutiejiao_45, "贴胶45度"); + chuizhi_7.init("Camera7", "底部贴胶检测-右-铜-相机1(90°)", { { 5700, 1,{5730},"5702","5704",-1} }, 1, &tongDetParams, _serviceManager, bridge, dibutiejiao_90, "贴胶90度"); + qingxie_8.init("Camera8", "底部贴胶检测-右-铜-相机2(45°)", { { 5710, 1,{5730},"5712","5714",-1} }, 1, &tongDetParams, _serviceManager, bridge, dibutiejiao_45, "贴胶45度"); + qingxie_9.init("Camera9", "底部贴胶检测-右-铜-相机3(45°)", { { 5720, 1,{5730},"5722","5724",-1} }, 1, &tongDetParams, _serviceManager, bridge, dibutiejiao_45, "贴胶45度"); + chuizhi_10.init("Camera10", "底部贴胶检测-右-铝-相机4(90°)", { { 5750, 1,{5730},"5752","5754",-1} }, 1, &lvDetParams, _serviceManager, bridge, dibutiejiao_90, "贴胶90度"); + qingxie_11.init("Camera11", "底部贴胶检测-右-铝-相机5(45°)", { { 5760, 1,{5730},"5762","5764",-1} }, 1, &lvDetParams, _serviceManager, bridge, dibutiejiao_45, "贴胶45度"); + qingxie_12.init("Camera12", "底部贴胶检测-右-铝-相机6(45°)", { { 5770, 1,{5730},"5772","5774",-1} }, 1, &lvDetParams, _serviceManager, bridge, dibutiejiao_45, "贴胶45度"); +#pragma endregion + return true; + } +}; + + + + + +#pragma once \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam1234/CMakeLists.txt b/src/mission/581_ZhongHan_dibutiejiao/CMakeLists.txt similarity index 98% rename from src/mission/581-BaoMo-Cam1234/CMakeLists.txt rename to src/mission/581_ZhongHan_dibutiejiao/CMakeLists.txt index d94ce25..15e8b6c 100644 --- a/src/mission/581-BaoMo-Cam1234/CMakeLists.txt +++ b/src/mission/581_ZhongHan_dibutiejiao/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581_ZhongHan_hanhou/581_ZhongHan_hanhou.cpp b/src/mission/581_ZhongHan_hanhou/581_ZhongHan_hanhou.cpp index 7b47f5a..39cd41c 100644 --- a/src/mission/581_ZhongHan_hanhou/581_ZhongHan_hanhou.cpp +++ b/src/mission/581_ZhongHan_hanhou/581_ZhongHan_hanhou.cpp @@ -1,7 +1,7 @@ #include <581_ZhongHan_hanhou.h> void exceptionResume(std::shared_ptr data, zhongHan3DParams* _detParams, sx_581_address address, QString why = "") { - qDebug() << "[Error] " << QString::fromUtf8("¼ì²âʧ°Ü!") << data->uuid << QString::fromStdString(data->SNcode) << why; + qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why; cv::Mat Paint; data->oriImgs[0].copyTo(Paint); if (Paint.channels() == 1) @@ -11,10 +11,10 @@ void exceptionResume(std::shared_ptr data, zhongHan3DParams* _detParams textPainter.putText(Paint, why.toStdString(), cv::Point(500, 50), cv::Scalar(0, 255, 0)); cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); data->resultImgs.push_back(Paint); - data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//½á¹û·´À¡ + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 } void exceptionResume(std::shared_ptr data, zhongHan2dCeLiangParams* _detParams, sx_581_address address, QString why = "") { - qDebug() << "[Error] " << QString::fromUtf8("¼ì²âʧ°Ü!") << data->uuid << QString::fromStdString(data->SNcode) << why; + qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why; cv::Mat Paint; data->oriImgs[0].copyTo(Paint); if (Paint.channels() == 1) @@ -24,10 +24,10 @@ void exceptionResume(std::shared_ptr data, zhongHan2dCeLiangParams* _de textPainter.putText(Paint, why.toStdString(), cv::Point(500, 50), cv::Scalar(0, 255, 0)); cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); data->resultImgs.push_back(Paint); - data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//½á¹û·´À¡ + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 } void exceptionResume(std::shared_ptr data, zhongHan2dCeMianParams* _detParams, sx_581_address address, QString why = "") { - qDebug() << "[Error] " << QString::fromUtf8("¼ì²âʧ°Ü!") << data->uuid << QString::fromStdString(data->SNcode) << why; + qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why; cv::Mat Paint; data->oriImgs[0].copyTo(Paint); if (Paint.channels() == 1) @@ -37,24 +37,26 @@ void exceptionResume(std::shared_ptr data, zhongHan2dCeMianParams* _det textPainter.putText(Paint, why.toStdString(), cv::Point(500, 50), cv::Scalar(0, 255, 0)); cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); data->resultImgs.push_back(Paint); - data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//½á¹û·´À¡ + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 } bool zhongHan_hanHouCeLiang(std::shared_ptr data, zhongHan2dCeLiangParams* _detParams, sx_581_address address) { try { QByteArray plcResult = "2"; - //img2D = cv::imread("D:\\Öպ¸CCD´æͼ\\º¸ºóÕýÃæ²âÁ¿CCD\\2025-07-28\\ԭͼ\\21H\\errSN\\ORI0_errSN_DA1806128_0_21-34-01-10.bmp", -1); + //img2D = cv::imread("D:\\终焊CCD存图\\焊后正面测量CCD\\2025-07-28\\原图\\21H\\errSN\\ORI0_errSN_DA1806128_0_21-34-01-10.bmp", -1); cv::Mat sourceImg = data->oriImgs[0]; cv::Rect cutRect; if (_detParams->isTong == true) { cutRect = cv::Rect(2000, 0, 3000, 3648); } - if (_detParams->isTong == true) { + if (_detParams->isTong == false) { cutRect = cv::Rect(400, 0, 3000, 3648); } cv::Mat cutImage = sourceImg(cutRect & (cv::Rect(0, 0, sourceImg.cols, sourceImg.rows))); - + //if (_detParams->isTong == false) { + // cv::rotate(cutImage, cutImage, cv::ROTATE_180); + //} cv::Mat Paint; cutImage.copyTo(Paint); if (Paint.channels() == 1) @@ -65,6 +67,7 @@ bool zhongHan_hanHouCeLiang(std::shared_ptr data, zhongHan2dCeLiangPar cv::Mat segResult = _detParams->seg_hanHouDingWei->Evaluate(segProcessMat); data->segOriginImgs.push_back(segProcessMat); data->segOriginImgs.push_back(cutImage); + data->segOriginImgs.push_back(segResult); HDevEngineCpp::HDevProcedure proc("_2_Cal_Welding_Distance"); HDevEngineCpp::HDevProcedureCall procedureCall(proc); @@ -78,24 +81,33 @@ bool zhongHan_hanHouCeLiang(std::shared_ptr data, zhongHan2dCeLiangPar procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution); procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath); procedureCall.Execute(); - HTuple out_BaseLineCor, out_LineCor, - out_Distance1, out_Distance2, out_Distance3, out_Distance4, - out_ColorType, out_Flag; - out_BaseLineCor = procedureCall.GetOutputCtrlParamTuple("out_BaseLineCor"); + HTuple out_BaseLineCor; + HTuple out_LineCor; + HTuple out_Distance1; + HTuple out_Distance2; + HTuple out_HYValues1; + HTuple out_HYValues2; + HTuple out_ColorType; + HTuple out_Flag; + HTuple out_NgTails; + //out_BaseLineCor = procedureCall.GetOutputCtrlParamTuple("out_BaseLineCor"); out_LineCor = procedureCall.GetOutputCtrlParamTuple("out_LineCor"); out_Distance1 = procedureCall.GetOutputCtrlParamTuple("out_Distance1"); out_Distance2 = procedureCall.GetOutputCtrlParamTuple("out_Distance2"); - out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType"); + out_HYValues1 = procedureCall.GetOutputCtrlParamTuple("out_HYValues1"); + out_HYValues2 = procedureCall.GetOutputCtrlParamTuple("out_HYValues2"); out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag"); + out_NgTails = procedureCall.GetOutputCtrlParamTuple("out_NgTails"); + double xingBaoDingBuDaoHanYinJianJu; TextRendererZH textPainter(Paint.cols, Paint.rows, 120); if (out_Flag.D() == 1) { { - int out_BaseLineCor_L = out_BaseLineCor.Length(); + /*int out_BaseLineCor_L = out_BaseLineCor.Length(); for (auto i = 0; i < out_BaseLineCor_L / 4; i++) cv::line(Paint, cv::Point(out_BaseLineCor[i * 4 + 1].D(), out_BaseLineCor[i * 4].D()), cv::Point(out_BaseLineCor[i * 4 + 3].D(), out_BaseLineCor[i * 4 + 2].D()), - cv::Scalar(0, 255, 0), 20); + cv::Scalar(0, 255, 0), 20);*/ int out_LineCor_L = out_LineCor.Length(); for (auto i = 0; i < out_LineCor_L / 4; i++) @@ -105,15 +117,38 @@ bool zhongHan_hanHouCeLiang(std::shared_ptr data, zhongHan2dCeLiangPar } //1 { - textPainter.putText(Paint, "ˮƽ¼ä¾à:" + std::to_string(out_Distance1[0].D()), cv::Point(50, 25), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "Êúֱ¼ä¾à:" + std::to_string(out_Distance1[1].D()), cv::Point(50, 25), cv::Scalar(0, 255, 0)); - data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + QByteArray::number(out_Distance1[1].D())); + textPainter.putText(Paint, "上焊印下边缘到连接片圆心水平间距:" + QString::number(out_Distance1[0].D(),'f', 3).toStdString() + "mm", cv::Point(50, 0), cv::Scalar(0, 255, 0)); + if(data->cameraKeyName == "Camera1") { + textPainter.putText(Paint, "上焊印左边缘圆心竖直间距:" + QString::number(out_Distance1[1].D(), 'f', 3).toStdString() + "mm", cv::Point(50, 120), cv::Scalar(0, 255, 0)); + } + else { + textPainter.putText(Paint, "上焊印右边缘圆心竖直间距:" + QString::number(out_Distance1[1].D(), 'f', 3).toStdString() + "mm", cv::Point(50, 120), cv::Scalar(0, 255, 0)); + } + textPainter.putText(Paint, "上焊印上边缘到芯包间距:" + QString::number(out_Distance1[2].D(), 'f', 3).toStdString() + "mm", cv::Point(50, 240), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "上焊印长:" + QString::number(out_HYValues1[0].D(),'f', 3).toStdString() + "mm", cv::Point(50, 360), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "上焊印宽:" + QString::number(out_HYValues1[1].D(),'f', 3).toStdString() + "mm", cv::Point(50, 480), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "上焊印面积:" + QString::number(out_HYValues1[2].D(), 'f', 3).toStdString() + "mm²", cv::Point(50, 600), cv::Scalar(0, 255, 0)); + data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(out_Distance1[1].D())); } //2 { - textPainter.putText(Paint, "ˮƽ¼ä¾à:" + std::to_string(out_Distance2[0].D()), cv::Point(50, 450), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "Êúֱ¼ä¾à:" + std::to_string(out_Distance2[1].D()), cv::Point(50, 675), cv::Scalar(0, 255, 0)); - data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + QByteArray::number(out_Distance2[1].D())); + textPainter.putText(Paint, "下焊印面积:" + QString::number(out_HYValues2[0].D(), 'f', 3).toStdString() + "mm²", cv::Point(50, cutImage.rows - 770), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "下焊印长:" + QString::number(out_HYValues2[1].D(), 'f', 3).toStdString() + "mm", cv::Point(50, cutImage.rows - 650), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "下焊印宽:" + QString::number(out_HYValues2[2].D(), 'f', 3).toStdString() + "mm", cv::Point(50, cutImage.rows - 530), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "下焊印下边缘到芯包间距:" + QString::number(out_Distance2[2].D(), 'f', 3).toStdString() + "mm", cv::Point(50, cutImage.rows - 410), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "下焊印上边缘到连接片圆心水平间距:" + QString::number(out_Distance2[0].D(), 'f', 3).toStdString() + "mm", cv::Point(50, cutImage.rows - 290), cv::Scalar(0, 255, 0)); + if (data->cameraKeyName == "Camera1") { + textPainter.putText(Paint, "下焊印左边缘到连接片圆心竖直间距:" + QString::number(out_Distance2[1].D(), 'f', 3).toStdString() + "mm", cv::Point(50, cutImage.rows - 170), cv::Scalar(0, 255, 0)); + } + else { + textPainter.putText(Paint, "下焊印右边缘到连接片圆心竖直间距:" + QString::number(out_Distance2[1].D(), 'f', 3).toStdString() + "mm", cv::Point(50, cutImage.rows - 170), cv::Scalar(0, 255, 0)); + } + xingBaoDingBuDaoHanYinJianJu = (out_Distance1[2].D() + out_Distance2[2].D())/2; + + if (data->cameraKeyName == "Camera1") + data->service->_triggerManager->writeFloat("D5820_" + QByteArray::number(xingBaoDingBuDaoHanYinJianJu)); + else + data->service->_triggerManager->writeFloat("D5822_" + QByteArray::number(xingBaoDingBuDaoHanYinJianJu)); } } else @@ -122,10 +157,11 @@ bool zhongHan_hanHouCeLiang(std::shared_ptr data, zhongHan2dCeLiangPar data->halconOK = false; plcResult = "2"; } - plcResult = "1";//ǿÖÆOK + plcResult = "1";//强制OK + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); data->resultImgs.push_back(Paint); sourceImg.release(); - data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//½á¹û·´À¡ + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 return true; } CATCH_EXCEPTIONS @@ -158,15 +194,17 @@ std::vector aiEvaluate(cv::Mat input, cv::Mat& Paint, bool& isNG, zhong break; case 1://NG cv::rectangle(Paint, rect, cv::Scalar(0, 0, 255), 3); + cv::drawContours(Paint, contours, clsIndex - 1, cv::Scalar(0, 0, 255),2); textPainter.putText(Paint, "NG" , cv::Point(rect.x, rect.y), cv::Scalar(0, 0, 255)); isNG = true; break; - case 2://ÆøÅÝ - textPainter.putText(Paint, "˺ÁÑ", cv::Point(rect.x, rect.y), cv::Scalar(0, 0, 255)); + case 2:// + textPainter.putText(Paint, "撕裂", cv::Point(rect.x, rect.y), cv::Scalar(0, 0, 255)); cv::rectangle(Paint, rect, cv::Scalar(0, 0, 255), 3); isNG = true; break; } + } return clsImgs; } @@ -174,24 +212,31 @@ bool zhongHan_hanHouCeMian(std::shared_ptr data, zhongHan2dCeMianParam { try { - cv::Rect cutROI; - if (data->cameraKeyName == "Camera2") { - cutROI = cv::Rect(2000, 1550, 1500, 1300); + + cv::Mat segImage, cutImage, img2D = data->oriImgs[0]; + cv::resize(data->oriImgs[0], segImage, cv::Size(), 0.2, 0.2); + segImage = ~_detParams->seg_JiErDIngWei->Evaluate(segImage); + std::vector> contours; + cv::findContours(segImage, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); + if (contours.size() != 0) { + int maxIndex = 0; + double maxArea = cv::contourArea(contours[0]); + for (int i = 0; i < contours.size(); i++) { + double area = cv::contourArea(contours[i]); + if (area > maxArea) { + maxIndex = i; + maxArea = area; + } + } + cv::Rect ROI = cv::boundingRect(contours[maxIndex]); + ROI.x = ROI.x * 5 - 30; + ROI.y = ROI.y * 5 - 30; + ROI.width = ROI.width * 5 + 60; + ROI.height = ROI.height * 5 + 60; + ROI = ROI & (cv::Rect(0, 0, data->oriImgs[0].cols, data->oriImgs[0].rows)); + data->oriImgs[0](ROI).copyTo(cutImage); } - else if (data->cameraKeyName == "Camera3") { - cutROI = cv::Rect(2000, 1450, 1500, 1300); - } - else if (data->cameraKeyName == "Camera5") { - cutROI = cv::Rect(1900, 1380, 1500, 1300); - } - else if (data->cameraKeyName == "Camera6") { - cutROI = cv::Rect(2070, 1500, 1500, 1300); - } - else { - cutROI = cv::Rect(1900, 1350, 1600, 1500); - } - cv::Mat img2D = data->oriImgs[0]; - cv::Mat cutImage = img2D(cutROI & cv::Rect(0, 0, img2D.cols, img2D.rows)).clone();//²üô³ö¼ì²âÇøÓ򣬼ӿ촦Àí + cv::Mat Paint; cutImage.copyTo(Paint); bool isNG = false; @@ -199,12 +244,12 @@ bool zhongHan_hanHouCeMian(std::shared_ptr data, zhongHan2dCeMianParam std::vector clsImgs; clsImgs.resize(0); - //µ÷»úʱÆÁ±Σ¬ÅÜÁϴò¿ª + //调机时屏蔽,跑料打开 clsImgs = aiEvaluate(cutImage, Paint, isNG,_detParams); TextRendererZH textPainter(Paint.cols, Paint.rows, 120); if (isNG == true) { - textPainter.putText(Paint, "NG", cv::Point(0, 50), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "NG", cv::Point(0, 50), cv::Scalar(0, 0, 255)); } else { textPainter.putText(Paint, "OK", cv::Point(0, 50), cv::Scalar(0, 255, 0)); @@ -215,7 +260,7 @@ bool zhongHan_hanHouCeMian(std::shared_ptr data, zhongHan2dCeMianParam data->resultImgs.push_back(Paint); data->segOriginImgs.push_back(cutImage); - data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//½á¹û·´À¡ + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 } CATCH_EXCEPTIONS exceptionResume(data, _detParams, address, "ERROR"); @@ -249,21 +294,21 @@ halconResult halconProcess(cv::Mat img2d, cv::Mat img3d, int cnt, handdleAI::pSe procedureCall.SetInputCtrlParamTuple("in_xResolution", in_xResolution); procedureCall.SetInputCtrlParamTuple("in_yResolution", in_yResolution); procedureCall.SetInputCtrlParamTuple("in_zResolution", in_zResolution); - procedureCall.Execute();//ִÐÐhalcon³ÌÐò + procedureCall.Execute();//执行halcon程序 - out_HYNumber = procedureCall.GetOutputCtrlParamTuple("out_HYNumber");//»ñȡÊä³ö¿ØÖÆÀà±äÁ¿ - out_HYPointX = procedureCall.GetOutputCtrlParamTuple("out_HYPointX");//»ñȡÊä³ö¿ØÖÆÀà±äÁ¿ - out_HYPointY = procedureCall.GetOutputCtrlParamTuple("out_HYPointY");//»ñȡÊä³ö¿ØÖÆÀà±äÁ¿ - out_HYHeightValue = procedureCall.GetOutputCtrlParamTuple("out_HYHeightValue");//»ñȡÊä³ö¿ØÖÆÀà±äÁ¿ - out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//»ñȡÊä³öͼÏñÀà±äÁ¿ + out_HYNumber = procedureCall.GetOutputCtrlParamTuple("out_HYNumber");//获取输出控制类变量 + out_HYPointX = procedureCall.GetOutputCtrlParamTuple("out_HYPointX");//获取输出控制类变量 + out_HYPointY = procedureCall.GetOutputCtrlParamTuple("out_HYPointY");//获取输出控制类变量 + out_HYHeightValue = procedureCall.GetOutputCtrlParamTuple("out_HYHeightValue");//获取输出控制类变量 + out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出图像类变量 int flag = out_Flag.D(); TextRendererZH textPainter(hResult.Paint.cols, hResult.Paint.rows, 120); if (flag == 1) { hResult.hyCount = (int)out_HYNumber[0].D() + (int)out_HYNumber[1].D(); - textPainter.putText(hResult.Paint, "ÉϺ¸ӡÊýÁ¿:" + std::to_string((int)out_HYNumber[0].D()), cv::Point(0, 50), cv::Scalar(0, 255, 0)); - textPainter.putText(hResult.Paint, "Ϻ¸ӡÊýÁ¿:" + std::to_string((int)out_HYNumber[1].D()), cv::Point(0, 150), cv::Scalar(0, 255, 0)); + textPainter.putText(hResult.Paint, "上焊印数量:" + std::to_string((int)out_HYNumber[0].D()), cv::Point(0, 50), cv::Scalar(0, 255, 0)); + textPainter.putText(hResult.Paint, "下焊印数量:" + std::to_string((int)out_HYNumber[1].D()), cv::Point(0, 150), cv::Scalar(0, 255, 0)); hResult.data.topHanYinCount = (int)out_HYNumber[0].D(); hResult.data.bottomHanYinCount = (int)out_HYNumber[1].D(); @@ -279,7 +324,7 @@ halconResult halconProcess(cv::Mat img2d, cv::Mat img3d, int cnt, handdleAI::pSe data.push_back(out_HYHeightValue[i].D()); } else - textPainter.putText(hResult.Paint, "ÊýÁ¿²»ƥÅä", cv::Point(0, 250), cv::Scalar(0, 255, 0)); + textPainter.putText(hResult.Paint, "数量不匹配", cv::Point(0, 250), cv::Scalar(0, 255, 0)); double sum = 0.0; double min_val = std::numeric_limits::infinity(); @@ -288,18 +333,18 @@ halconResult halconProcess(cv::Mat img2d, cv::Mat img3d, int cnt, handdleAI::pSe for (double value : data) { sum += value; if (value < min_val) { - hResult.data.minHanYinDepth = value; // ¸üÐÂ×îСֵ + hResult.data.minHanYinDepth = value; // 更新最小值 } if (value > max_val) { - hResult.data.maxHanYinDepth = value; // ¸üÐÂ×î´óֵ + hResult.data.maxHanYinDepth = value; // 更新最大值 } } - // ¼ÆËãƽ¾ùֵ + // 计算平均值 hResult.data.avgHanYinDepth = sum / data.size(); } else { - textPainter.putText(hResult.Paint, "Ë㷨´íÎó", cv::Point(0, 250), cv::Scalar(0, 255, 0)); + textPainter.putText(hResult.Paint, "算法错误", cv::Point(0, 250), cv::Scalar(0, 255, 0)); hResult.result = false; } } @@ -312,25 +357,22 @@ bool zhongHan_hanHou3D(std::shared_ptr data, zhongHan3DParams* _detPar { exceptionResume(data, _detParams, address,"OK"); return true; - cv::Mat img2D1 = data->oriImgs[0], img3D1 = data->oriImgs[1], img2D2 = data->oriImgs[2], img3D2 = data->oriImgs[3]; + cv::Mat img2D1 = data->oriImgs[0], img3D1 = data->oriImgs[1]; //ASYNC// auto furture1 = std::async(std::launch::async, &halconProcess, img2D1, img3D1, 0, _detParams->seg_3dHanYinDingWei); - auto furture2 = std::async(std::launch::async, &halconProcess, img2D2, img3D2, 1, _detParams->seg_3dHanYinDingWei); furture1.wait(); halconResult result1 = furture1.get(); - furture2.wait(); - halconResult result2 = furture2.get(); data->segOriginImgs.push_back(result1.segResult); - data->segOriginImgs.push_back(result2.segResult); - data->service->_triggerManager->writeShort("D" + QByteArray::number(address.valueOffsetAddr) + "_1");//½á¹û·´À¡ - data->service->_triggerManager->writeShort("D" + QByteArray::number(address.valueOffsetAddr + 1) + "_1");//½á¹û·´À¡ + data->service->_triggerManager->writeShort("D" + QByteArray::number(address.valueOffsetAddr) + "_1");//结果反馈 + data->service->_triggerManager->writeShort("D" + QByteArray::number(address.valueOffsetAddr + 1) + "_1");//结果反馈 - cv::Mat PaintSum(result1.Paint.rows, result1.Paint.cols + result2.Paint.cols, CV_8UC3); - result1.Paint.copyTo(PaintSum(cv::Rect(0, 0, result1.Paint.cols, result1.Paint.rows))); - result2.Paint.copyTo(PaintSum(cv::Rect(result1.Paint.cols, 0, result1.Paint.cols, result1.Paint.rows))); - data->resultImgs.push_back(PaintSum); - data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//½á¹û·´À¡ + //cv::Mat PaintSum(result1.Paint.rows, result1.Paint.cols + result2.Paint.cols, CV_8UC3); + //result1.Paint.copyTo(PaintSum(cv::Rect(0, 0, result1.Paint.cols, result1.Paint.rows))); + //result2.Paint.copyTo(PaintSum(cv::Rect(result1.Paint.cols, 0, result1.Paint.cols, result1.Paint.rows))); + data->resultImgs.push_back(result1.Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 + return true; } CATCH_EXCEPTIONS exceptionResume(data, _detParams, address,"ERROR"); diff --git a/src/mission/581_ZhongHan_hanhou/581_ZhongHan_hanhou.h b/src/mission/581_ZhongHan_hanhou/581_ZhongHan_hanhou.h index 4004ae5..a4be55d 100644 --- a/src/mission/581_ZhongHan_hanhou/581_ZhongHan_hanhou.h +++ b/src/mission/581_ZhongHan_hanhou/581_ZhongHan_hanhou.h @@ -13,6 +13,7 @@ public: }; class zhongHan2dCeMianParams { public: + handdleAI::pSegmentation* seg_JiErDIngWei = nullptr; handdleAI::pSegmentation* seg_ceMian = nullptr; handdleAI::pClassification* cls_ceMian = nullptr; bool isTong = true; @@ -58,41 +59,54 @@ public: _581_SX_Single_triggerTemplate< zhongHan3DParams> _3D_2; zhongHan2dCeLiangParams tongZhongHan2dCeLiangParams; zhongHan2dCeLiangParams lvZhongHan2dCeLiangParams; - std::vector< zhongHan2dCeMianParams> tongZhongHan2dCeMianParams; - std::vector< zhongHan2dCeMianParams> lvZhongHan2dCeMianParams; + std::vector< zhongHan2dCeMianParams> tongZhongHan2dCeMianParams = std::vector< zhongHan2dCeMianParams>(2); + std::vector< zhongHan2dCeMianParams> lvZhongHan2dCeMianParams = std::vector< zhongHan2dCeMianParams>(2); zhongHan3DParams tongZhongHan3DParams; zhongHan3DParams lvZhongHan3DParams; bool initOnce = false; void onConfigReloaded() { HDevEngineCpp::HDevEngine myEngine; - myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_628_1.hdpl"); + myEngine.SetProcedurePath("./halconAlgo/AlgoLibrary_602.hdpl"); if (initOnce == false) { - //for (auto& params : tongDetParams) { - // params.segDingWei = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanqian/60_2_hanqian_dingwei_seg.BHD", 64, 0); - // params.segJiErFanZhe = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanqian/60_2_hanqian_segT.BHD", 64, 0); - // params.clsJiErFanZhe = handdleAI::CreateClsObjV3("./handleaiModels/yuhan_hanqian/60_2_hanqian_clsT.BHD", 0, 1); - //} - //for (auto& params : lvDetParams) { - // params.segDingWei = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanqian/60_2_hanqian_dingwei_seg.BHD", 64, 1); - // params.segJiErFanZhe = handdleAI::CreateSegObjS("./handleaiModels/yuhan_hanqian/60_2_hanqian_segL.BHD", 64, 1); - // params.clsJiErFanZhe = handdleAI::CreateClsObjV3("./handleaiModels/yuhan_hanqian/60_2_hanqian_clsL.BHD", 1, 1); - // params.isTong = false; - //} + tongZhongHan2dCeLiangParams.seg_hanHouDingWei = handdleAI::CreateSegObjS("./handleAiModels/seg-hanHouDingWei.BHD", 64, 0); + lvZhongHan2dCeLiangParams.seg_hanHouDingWei = handdleAI::CreateSegObjS("./handleAiModels/seg-hanHouDingWei.BHD", 64, 1); + + tongZhongHan2dCeMianParams[0].seg_JiErDIngWei = handdleAI::CreateSegObjS("./handleAiModels/pSeg_JiErDingWei_45_T_GPU0.BHD", 64, 0); + tongZhongHan2dCeMianParams[0].seg_ceMian = handdleAI::CreateSegObjS("./handleAiModels/seg_ZhongHan_HanHou_45_T_GPU0.BHD", 64, 0); + tongZhongHan2dCeMianParams[0].cls_ceMian = handdleAI::CreateClsObjV3("./handleAiModels/cls_ZhongHan_HanHou_45_T_GPU0.BHD", 0, 1); + + tongZhongHan2dCeMianParams[1].seg_JiErDIngWei = handdleAI::CreateSegObjS("./handleAiModels/pSeg_JiErDingWei_45_T_GPU0.BHD", 64, 0); + tongZhongHan2dCeMianParams[1].seg_ceMian = handdleAI::CreateSegObjS("./handleAiModels/seg_ZhongHan_HanHou_45_T_GPU0.BHD", 64, 0); + tongZhongHan2dCeMianParams[1].cls_ceMian = handdleAI::CreateClsObjV3("./handleAiModels/cls_ZhongHan_HanHou_45_T_GPU0.BHD", 0, 1); + + lvZhongHan2dCeMianParams[0].seg_JiErDIngWei = handdleAI::CreateSegObjS("./handleAiModels/pSeg_JiErDingWei_45_L_GPU1.BHD", 64, 1); + lvZhongHan2dCeMianParams[0].seg_ceMian = handdleAI::CreateSegObjS("./handleAiModels/seg_ZhongHan_HanHou_45_L_GPU1.BHD", 64, 1); + lvZhongHan2dCeMianParams[0].cls_ceMian = handdleAI::CreateClsObjV3("./handleAiModels/cls_ZhongHan_HanHou_45_L_GPU1.BHD", 1, 1); + + lvZhongHan2dCeMianParams[1].seg_JiErDIngWei = handdleAI::CreateSegObjS("./handleAiModels/pSeg_JiErDingWei_45_L_GPU1.BHD", 64, 1); + lvZhongHan2dCeMianParams[1].seg_ceMian = handdleAI::CreateSegObjS("./handleAiModels/seg_ZhongHan_HanHou_45_L_GPU1.BHD", 64, 1); + lvZhongHan2dCeMianParams[1].cls_ceMian = handdleAI::CreateClsObjV3("./handleAiModels/cls_ZhongHan_HanHou_45_L_GPU1.BHD", 1, 1); + + lvZhongHan2dCeLiangParams.isTong = false; + + //tongZhongHan3DParams.seg_3dHanYinDingWei = handdleAI::CreateSegObjS("./handleAiModels/seg-Hanhou3DZhuaQu.BHD", 1, 0); + //lvZhongHan3DParams.seg_3dHanYinDingWei = handdleAI::CreateSegObjS("./handleAiModels/seg-Hanhou3DZhuaQu.BHD", 1, 1); + initOnce = true; } } bool initCustom() { #pragma region 注册触发器回调 - lv_top_1.init("Camera1", "焊印检测-内-铜-相机1(90°)", { { 5360, 1,5340,"5362","5364",-1} }, 1, &tongZhongHan2dCeLiangParams, _serviceManager, bridge, zhongHan_hanHouCeLiang); - lv_left45_2.init("Camera2", "翻折撕裂-内-铜-相机2(45°)", { { 5370, 1,5340,"5372","5374",-1} }, 1, &tongZhongHan2dCeMianParams[0], _serviceManager, bridge, zhongHan_hanHouCeMian); - lv_right45_3.init("Camera3", "翻折撕裂-内-铜-相机3(45°)", { { 5380,1,5340,"5382","5384",5406} }, 1, &tongZhongHan2dCeMianParams[1], _serviceManager, bridge, zhongHan_hanHouCeMian); - _3D_1.init("Camera4", "焊后检测-3D相机1" , { { 5400, 1,5340,"5402","5404",-1} }, 1, &tongZhongHan3DParams, _serviceManager, bridge, zhongHan_hanHou3D); + lv_top_1.init("Camera1", "焊印检测-内-铜-相机1(90°)", { { 5360, 1,{5340},"5362","5364",5800} }, 1, &tongZhongHan2dCeLiangParams, _serviceManager, bridge, zhongHan_hanHouCeLiang, "90°存图"); + lv_left45_2.init("Camera2", "翻折撕裂-内-铜-相机2(45°)", { { 5370, 1,{5340},"5372","5374",-1} }, 1, &tongZhongHan2dCeMianParams[0], _serviceManager, bridge, zhongHan_hanHouCeMian,"45°存图"); + lv_right45_3.init("Camera3", "翻折撕裂-内-铜-相机3(45°)", { { 5380,1,{5340},"5382","5384",5406} }, 1, &tongZhongHan2dCeMianParams[1], _serviceManager, bridge, zhongHan_hanHouCeMian, "45°存图"); + _3D_1.init("Camera4", "焊后检测-3D相机2(右)" , { { 5400, 1,{5340},"5402","5404",-1} }, 1, &tongZhongHan3DParams, _serviceManager, bridge, zhongHan_hanHou3D,"3D存图"); - tong_top_5.init("Camera5", "焊印检测-外-铝-相机5(90°)", { { 5440, 1,5420,"5442","5444",-1} }, 1, &lvZhongHan2dCeLiangParams, _serviceManager, bridge, zhongHan_hanHouCeLiang); - tong_left45_6.init("Camere6", "翻折撕裂-外-铝-相机6(45°)", { { 5450,1,5420,"5452","5454",-1} }, 1, &lvZhongHan2dCeMianParams[0], _serviceManager, bridge, zhongHan_hanHouCeMian); - tong_right45_7.init("Camera7", "翻折撕裂-外-铝-相机7(45°)", { { 5460, 1,5420,"5462","5464",5486} }, 1, &lvZhongHan2dCeMianParams[1], _serviceManager, bridge, zhongHan_hanHouCeMian); - _3D_2.init("Camera8", "焊后检测-3D相机2", { { 5480, 1,5420,"5482","5484",-1} }, 1, &lvZhongHan3DParams, _serviceManager, bridge, zhongHan_hanHou3D); + tong_top_5.init("Camera5", "焊印检测-外-铝-相机5(90°)", { { 5440, 1,{5420},"5442","5444",5804} }, 1, &lvZhongHan2dCeLiangParams, _serviceManager, bridge, zhongHan_hanHouCeLiang, "90°存图"); + tong_left45_6.init("Camera6", "翻折撕裂-外-铝-相机6(45°)", { { 5450,1,{5420},"5452","5454",-1} }, 1, &lvZhongHan2dCeMianParams[0], _serviceManager, bridge, zhongHan_hanHouCeMian, "45°存图"); + tong_right45_7.init("Camera7", "翻折撕裂-外-铝-相机7(45°)", { { 5460, 1,{5420},"5462","5464",5486} }, 1, &lvZhongHan2dCeMianParams[1], _serviceManager, bridge, zhongHan_hanHouCeMian, "45°存图"); + _3D_2.init("Camera8", "焊后检测-3D相机1(左)", { { 5480, 1,{5420},"5482","5484",-1} }, 1, &lvZhongHan3DParams, _serviceManager, bridge, zhongHan_hanHou3D, "3D存图"); #pragma endregion return true; } diff --git a/src/mission/581_ZhongHan_hanhou/CMakeLists.txt b/src/mission/581_ZhongHan_hanhou/CMakeLists.txt index d94ce25..15e8b6c 100644 --- a/src/mission/581_ZhongHan_hanhou/CMakeLists.txt +++ b/src/mission/581_ZhongHan_hanhou/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581_ZhongHan_hanqian/581_ZhongHan_hanqian.h b/src/mission/581_ZhongHan_hanqian/581_ZhongHan_hanqian.h index b8bd5e4..7b3ba38 100644 --- a/src/mission/581_ZhongHan_hanqian/581_ZhongHan_hanqian.h +++ b/src/mission/581_ZhongHan_hanqian/581_ZhongHan_hanqian.h @@ -86,6 +86,7 @@ bool hanQianCeLiang_Main(std::shared_ptr data, zhongHanHanQianParams* sourceImg = img2D(cutROI & cv::Rect(0, 0, img2D.cols, img2D.rows)).clone(); #endif cv::Mat sourceImg = data->oriImgs[0]; + sourceImg(cv::Rect(2400, 0, 3000, 3648)).copyTo(sourceImg); cv::Mat Paint; sourceImg.copyTo(Paint); if (Paint.channels() == 1) @@ -129,13 +130,13 @@ bool hanQianCeLiang_Main(std::shared_ptr data, zhongHanHanQianParams* TextRendererZH textPainter(Paint.cols, Paint.rows, 120); if (flag == 1) { - double Out_Vale_T_1 = out_Distance[0].D();//铜(正)极的包膜距离(mm) - double Out_Vale_T_2 = out_Distance[1].D();//铜(正)极连接片中心的和上极耳水平边缘距离(mm) - double Out_Vale_T_3 = out_Distance[2].D();//铜(正)极连接片中心的和下极耳水平边缘距离(mm) + double Out_Vale_T_1 = out_Distance[0].D();//铜(负)极的包膜距离(mm) + double Out_Vale_T_2 = out_Distance[1].D();//铜(负)极连接片中心的和上极耳水平边缘距离(mm) + double Out_Vale_T_3 = out_Distance[2].D();//铜(负)极连接片中心的和下极耳水平边缘距离(mm) - double Out_Vale_L_1 = out_Distance[3].D();//铝(负)极的包膜距离(mm) - double Out_Vale_L_2 = out_Distance[4].D();//铝(负)极连接片中心的和上极耳水平边缘距离(mm) - double Out_Vale_L_3 = out_Distance[5].D();//铝(负)极连接片中心的和下极耳水平边缘距离(mm) + double Out_Vale_L_1 = out_Distance[3].D();//铝(正)极的包膜距离(mm) + double Out_Vale_L_2 = out_Distance[4].D();//铝(正)极连接片中心的和上极耳水平边缘距离(mm) + double Out_Vale_L_3 = out_Distance[5].D();//铝(正)极连接片中心的和下极耳水平边缘距离(mm) double extremum_Value = out_Distance[6].D(); @@ -157,11 +158,11 @@ bool hanQianCeLiang_Main(std::shared_ptr data, zhongHanHanQianParams* } _detParams->insertResult(_calResult); - textPainter.putText(Paint, "铜(正)极的包膜距离:" + std::to_string(Out_Vale_T_1), cv::Point(50, 50), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "铜(负)极的包膜距离:" + std::to_string(Out_Vale_T_1), cv::Point(50, 50), cv::Scalar(0, 255, 0)); data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(Out_Vale_T_1));//数据1 - textPainter.putText(Paint, "铜(正)极连接片中心的和上极耳水平边缘距离:" + std::to_string(Out_Vale_T_2), cv::Point(50, 200), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "铜(正)极连接片中心的和下极耳水平边缘距离:" + std::to_string(Out_Vale_T_3), cv::Point(50, 350), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "铜(正)极和铝(负)极的中心距离:" + std::to_string(extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "铜(负)极连接片中心的和上极耳水平边缘距离:" + std::to_string(Out_Vale_T_2), cv::Point(50, 200), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "铜(负)极连接片中心的和下极耳水平边缘距离:" + std::to_string(Out_Vale_T_3), cv::Point(50, 350), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "铜(负)极和铝(正)极的中心距离:" + std::to_string(extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0)); data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(extremum_Value));//数据2 for (int i = 0; i < 5; i++){ cv::line(Paint, cv::Point(out_LinePoint[i * 4 + 1].D(), out_LinePoint[i * 4].D()), @@ -173,6 +174,11 @@ bool hanQianCeLiang_Main(std::shared_ptr data, zhongHanHanQianParams* cv::drawMarker(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), cv::Scalar(0, 255, 0), cv::MARKER_CROSS, 200, 5); cv::circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 5); } + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + plcResult = "1";//强制OK + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + return true; } else{ std::string errTails = out_NGTails.S().Text(); @@ -215,6 +221,7 @@ bool hanQianCeLiang_Sub(std::shared_ptr data, zhongHanHanQianParams* _ #endif } cv::Mat sourceImg = data->oriImgs[0]; + sourceImg(cv::Rect(0, 0, 3000, 3648)).copyTo(sourceImg); cv::Mat Paint; sourceImg.copyTo(Paint); if (Paint.channels() == 1) @@ -238,11 +245,11 @@ bool hanQianCeLiang_Sub(std::shared_ptr data, zhongHanHanQianParams* _ } if (_calResult.algoFailed == false) { - textPainter.putText(Paint, "铝(负)极的包膜距离:" + std::to_string(_calResult.Out_Vale_L_1), cv::Point(50, 50), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "铝(正)包膜距离:" + std::to_string(_calResult.Out_Vale_L_1), cv::Point(50, 50), cv::Scalar(0, 255, 0)); data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(_calResult.Out_Vale_L_1));//数据1 - textPainter.putText(Paint, "铝(负)极连接片中心的和上极耳水平边缘距离:" + std::to_string(_calResult.Out_Vale_L_2), cv::Point(50, 200), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "铝(负)极连接片中心的和下极耳水平边缘距离:" + std::to_string(_calResult.Out_Vale_L_3), cv::Point(50, 350), cv::Scalar(0, 255, 0)); - textPainter.putText(Paint, "铜(正)极和铝(负)极的中心距离:" + std::to_string(_calResult.extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "铝(正)极连接片中心的和上极耳水平边缘距离:" + std::to_string(_calResult.Out_Vale_L_2), cv::Point(50, 200), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "铝(正)极连接片中心的和下极耳水平边缘距离:" + std::to_string(_calResult.Out_Vale_L_3), cv::Point(50, 350), cv::Scalar(0, 255, 0)); + textPainter.putText(Paint, "铜(负)极和铝(正)极的中心距离:" + std::to_string(_calResult.extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0)); data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(_calResult.extremum_Value));//数据2 for (int i = 0; i < 5; i++) { cv::line(Paint, cv::Point(_calResult.lines[i * 4 + 1], _calResult.lines[i * 4]), @@ -297,7 +304,7 @@ public: bool initCustom() { #pragma region 注册触发器回调 tong_1.init("Camera1", "焊前定位-相机1", { { 5060, 1,{5070},"5062","5064",5066} }, 1, &detParams, _serviceManager, bridge, hanQianCeLiang_Main); - lv_1.init("Camera1", "焊前定位-相机2", { { 5090, 1,{5100},"5092","5094",5096} }, 1, &detParams, _serviceManager, bridge, hanQianCeLiang_Sub); + lv_1.init("Camera2", "焊前定位-相机2", { { 5090, 1,{5100},"5092","5094",5096} }, 1, &detParams, _serviceManager, bridge, hanQianCeLiang_Sub); #pragma endregion return true; } diff --git a/src/mission/581_ZhongHan_hanqian/CMakeLists.txt b/src/mission/581_ZhongHan_hanqian/CMakeLists.txt index d94ce25..15e8b6c 100644 --- a/src/mission/581_ZhongHan_hanqian/CMakeLists.txt +++ b/src/mission/581_ZhongHan_hanqian/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) diff --git a/src/mission/581_ZhongHan_silie_jixing/581_ZhongHan_silie_jixing.cpp b/src/mission/581_ZhongHan_silie_jixing/581_ZhongHan_silie_jixing.cpp new file mode 100644 index 0000000..0bb7a9a --- /dev/null +++ b/src/mission/581_ZhongHan_silie_jixing/581_ZhongHan_silie_jixing.cpp @@ -0,0 +1,247 @@ +#include <581_ZhongHan_silie_jixing.h> + +void aiEvaluate(cv::Mat input, handdleAI::pSegmentation* seg, handdleAI::pClassification* cls,cv::Mat& Paint, bool& isNG){ + cv::Mat forSeg; + input.copyTo(forSeg); + //cv::resize(forSeg, forSeg, cv::Size(), 0.25, 0.25); + cv::Mat segRes; + if (seg != nullptr) + { + segRes = ~seg->Evaluate(forSeg); + cv::resize(segRes, segRes, cv::Size(), 4, 4); + std::vector>contours; + cv::findContours(segRes, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); + int cnt = 0; + for (auto& contour : contours) { + cv::Rect rect = cv::boundingRect(contour); + if (rect.width < 250 || rect.height < 250) + continue; + cv::Mat clsImg = cutImg2Cls(rect, input); + cnt++; + int claResult = cls->Evaluate(clsImg); + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + switch (claResult) + { + case 0://OK + cv::rectangle(Paint, rect, cv::Scalar(0, 255, 0), 3); + break; + case 1://NG + cv::rectangle(Paint, rect, cv::Scalar(0, 0, 255), 3); + textPainter.putText(Paint,"NG",cv::Point(rect.x, rect.y), cv::Scalar(0, 0, 255)); + isNG = true; + break; + } + } + } + else { + isNG = false; + } + +} +bool lieHenJianCe90(std::shared_ptr data, LieHenJianCeParams* _detParams, sx_581_address address){ + try { + { + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + TextRendererZH textPainter(Paint.cols, Paint.rows, 15); + textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 + return true; + } + cv::Mat sourceImage; + data->oriImgs[0].copyTo(sourceImage); + cv::Mat imgPaint; + sourceImage.copyTo(imgPaint); + bool isNG_1 = false; + bool isNG_2 = false; + QByteArray plcResult = "1"; + //检测 + cv::Rect cutROI_1; + cv::Rect cutROI_2; + if (_detParams->isTong == true) {//铜 + cutROI_1 = cv::Rect(2800, 700, 1400, 700) & cv::Rect(0, 0, sourceImage.cols, sourceImage.rows); + cutROI_2 = cv::Rect(2800, 2330, 1400, 700) & cv::Rect(0, 0, sourceImage.cols, sourceImage.rows); + } + else {//铝 + cutROI_1 = cv::Rect(1280, 730, 1400, 700) & cv::Rect(0, 0, sourceImage.cols, sourceImage.rows); + cutROI_2 = cv::Rect(1280, 2240, 1400, 700) & cv::Rect(0, 0, sourceImage.cols, sourceImage.rows); + } + aiEvaluate(data->oriImgs[0](cutROI_1), _detParams->seg_diBu, _detParams->cls_diBu, imgPaint(cutROI_1), isNG_1); + aiEvaluate(data->oriImgs[0](cutROI_2), _detParams->seg_diBu, _detParams->cls_diBu, imgPaint(cutROI_2), isNG_2); + QString okNgSaveText = "OK"; + TextRendererZH textPainter(imgPaint.cols, imgPaint.rows, 300); + if (isNG_1 == true || isNG_2 == true) { + textPainter.putText(imgPaint, "NG", cv::Point(50, 50), cv::Scalar(0, 0, 255)); + okNgSaveText = "NG"; + plcResult = "2"; + } + else { + textPainter.putText(imgPaint, "OK", cv::Point(50, 50), cv::Scalar(0, 255, 0)); + } + data->resultImgs.push_back(imgPaint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 + return true; + } + CATCH_EXCEPTIONS + + qDebug() << "[Error] " << QString::fromUtf8("检测失败!"); + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + TextRendererZH textPainter(Paint.cols, Paint.rows, 15); + textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 + return true; + + +} + +bool lieHenJianCe45(std::shared_ptr data, LieHenJianCeParams* _detParams, sx_581_address address) { + try + { + cv::Mat sourceImg; + cv::Rect cutROI; + cutROI = cv::Rect(1600, 900, 2200, 1400) & cv::Rect(0, 0, data->oriImgs[0].cols, data->oriImgs[0].rows); + data->oriImgs[0](cutROI).copyTo(sourceImg); + cv::Mat Paint; + sourceImg.copyTo(Paint); + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + bool isNG = false; + QByteArray plcResult = "1"; + textPainter.putText(Paint, "OK", cv::Point(0, 50), cv::Scalar(0, 255, 0)); + //cv::rectangle(Paint, cutROI, cv::Scalar(0, 255, 0), 5); + data->resultImgs.push_back(Paint); + + sourceImg.release(); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + return true; + } + CATCH_EXCEPTIONS + + qDebug() << "[Error] " << QString::fromUtf8("检测失败!"); + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + TextRendererZH textPainter(Paint.cols, Paint.rows, 15); + textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 + return true; + +} + + +bool jiXingJianCe(std::shared_ptr data, JiXingJianCeParams* _detParams, sx_581_address address){ + try + { + /*if (indexTest < 17) + img2D = cv::imread("./testImages/" + std::to_string(indexTest++) + ".bmp", -1);*/ + + //存图数据加保存队列,加锁,避免数据访问冲突 + //cv::Rect cutRect(0, 0, img2D.cols, img2D.rows);//裁剪出有效区域 + //cutRect = cutRect & cv::Rect(0, 0, img2D.cols, img2D.rows); + cv::Mat sourceImg; + data->oriImgs[0].copyTo(sourceImg); + + HDevEngineCpp::HDevProcedure proc("_2_JX_Inspection"); + HDevProcedureCall procedureCall(proc); + + cv::Mat Paint; + sourceImg.copyTo(Paint); + //极性检测 + HObject in_Image; + HTuple in_FilePath = "./halconFiles/"; + HTuple in_LineType = "602"; + in_Image = MatToHObject(sourceImg); + procedureCall.SetInputIconicParamObject("in_Image", in_Image);//设置输入图像类变量 + procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath); + procedureCall.SetInputCtrlParamTuple("in_LineType", in_LineType); + procedureCall.Execute();//执行halcon程序 + HTuple out_ColorType; + HTuple out_Flag; + HTuple out_InspectionPosition; + HTuple out_NgTails; + out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出图像类变量 + out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量 + out_InspectionPosition = procedureCall.GetOutputCtrlParamTuple("out_InspectionPosition"); + out_NgTails = procedureCall.GetOutputCtrlParamTuple("out_NgTails"); + //相机2 OK为铜 NG为铝 + QByteArray algoResult = "2"; + QString okNgSaveText = "NG"; + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + if (out_Flag.D() == 1) + { + if (out_InspectionPosition.Length() > 3) { + for (int i = 0; i < out_InspectionPosition.Length() / 4; i++) { + cv::Rect rect = cv::Rect(out_InspectionPosition[i * 4 + 0], \ + out_InspectionPosition[i * 4 + 1], \ + out_InspectionPosition[i * 4 + 2], \ + out_InspectionPosition[i * 4 + 3]); + cv::rectangle(Paint, rect, cv::Scalar(0, 255, 255), 2); + } + } + + std::string jx_Type = out_ColorType.S().Text(); + if (jx_Type == "LV") { + //铝 + cv::putText(Paint, "NG", cv::Point(0, 500), 2, 10, cv::Scalar(0, 0, 255), 5); + } + else if (jx_Type == "CU") { + //铜 + textPainter.putText(Paint, "铜极", cv::Point(0, 0), cv::Scalar(0, 255, 0)); + cv::putText(Paint, "OK", cv::Point(0, 500), 2, 10, cv::Scalar(0, 255, 0), 5); + algoResult = "1"; + okNgSaveText = "OK"; + } + else { + textPainter.putText(Paint, "NG", cv::Point(0, 50), cv::Scalar(0, 0, 255)); + } + } + else { + std::string temp_NGTails = out_NgTails.S().Text(); + textPainter.putText(Paint, "NG", cv::Point(0, 50), cv::Scalar(0, 0, 255)); + textPainter.putText(Paint, temp_NGTails.c_str(), cv::Point(0, 350), cv::Scalar(0, 255, 0)); + + } + + algoResult = "1"; + sourceImg.release(); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + algoResult);//结果反馈 + return true; + } + CATCH_EXCEPTIONS + + qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode); + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + TextRendererZH textPainter(Paint.cols, Paint.rows, 15); + textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈 + return true; + + +} + + +mission* createMission() { + return new _581_ZhongHan_silie_jixing(); +} +void destroyMission(mission* _mission) { + delete _mission; +} \ No newline at end of file diff --git a/src/mission/581_ZhongHan_silie_jixing/581_ZhongHan_silie_jixing.h b/src/mission/581_ZhongHan_silie_jixing/581_ZhongHan_silie_jixing.h new file mode 100644 index 0000000..a438497 --- /dev/null +++ b/src/mission/581_ZhongHan_silie_jixing/581_ZhongHan_silie_jixing.h @@ -0,0 +1,83 @@ +#include +#include +#pragma region 算法 +#include +#include +#include +using namespace HDevEngineCpp; +#pragma endregion +class LieHenJianCeParams { +public: + handdleAI::pSegmentation* seg_diBu = nullptr; + handdleAI::pClassification* cls_diBu = nullptr; + bool isTong = false; +}; + +class JiXingJianCeParams { +public: + +}; + +void aiEvaluate(cv::Mat input, handdleAI::pSegmentation* seg, handdleAI::pClassification* cls, cv::Mat& Paint, bool& isNG); +bool lieHenJianCe90(std::shared_ptr data, LieHenJianCeParams* _detParams, sx_581_address address); + +bool lieHenJianCe45(std::shared_ptr data, LieHenJianCeParams* _detParams, sx_581_address address); + +bool jiXingJianCe(std::shared_ptr data, JiXingJianCeParams* _detParams, sx_581_address address); + + + + +class _581_ZhongHan_silie_jixing : public mission { +public: + _581_SX_Single_triggerTemplate< LieHenJianCeParams> liehen_tong_1; + _581_SX_Single_triggerTemplate< LieHenJianCeParams> liehen_tong_2; + _581_SX_Single_triggerTemplate< LieHenJianCeParams> liehen_tong_3; + + _581_SX_Single_triggerTemplate< LieHenJianCeParams> liehen_lv_4; + _581_SX_Single_triggerTemplate< LieHenJianCeParams> liehen_lv_5; + _581_SX_Single_triggerTemplate< LieHenJianCeParams> liehen_lv_6; + + _581_SX_Single_triggerTemplate< JiXingJianCeParams> jixing_cu; + + JiXingJianCeParams tongJiXingParams; + LieHenJianCeParams tong90Params; + LieHenJianCeParams lv90Params; + + LieHenJianCeParams tong45Params; + LieHenJianCeParams lv45Params; + bool initOnce = false; + void onConfigReloaded() { + HDevEngineCpp::HDevEngine myEngine; + myEngine.SetProcedurePath("./halconAlgo/AlgoLibrary_602.hdpl"); + initOnce = true; + + //tong90Params.seg_diBu = handdleAI::CreateSegObjS("./handleaiModels/seg-zhongHanHanHouDiBu.BHD", 1, 0); + //tong90Params.cls_diBu = handdleAI::CreateClsObjV3("./handleaiModels/cls-zhongHanHanHouDiBu.BHD", 0, 1); + + //lv90Params.seg_diBu = handdleAI::CreateSegObjS("./handleaiModels/seg-zhongHanHanHouDiBu.BHD", 1, 1); + //lv90Params.cls_diBu = handdleAI::CreateClsObjV3("./handleaiModels/cls-zhongHanHanHouDiBu.BHD", 1, 1); + lv90Params.isTong == false; + } + bool initCustom() { +#pragma region 注册触发器回调 + liehen_tong_1.init("Camera1", "裂痕检测-铜-相机1", { { 5280, 1,{5160},"5282","5284",-1} }, 1, &tong90Params, _serviceManager, bridge, lieHenJianCe90, "CCD裂痕检测"); + liehen_tong_2.init("Camera2", "裂痕检测-铜-相机2", { { 5290, 1,{5160},"5292","5294",-1} }, 1, &tong45Params, _serviceManager, bridge, lieHenJianCe45, "CCD裂痕检测"); + liehen_tong_3.init("Camera3", "裂痕检测-铜-相机3", { { 5300, 1,{5160},"5302","5304",-1} }, 1, &tong45Params, _serviceManager, bridge, lieHenJianCe45, "CCD裂痕检测"); + + liehen_lv_4.init("Camera4", "裂痕检测-铝-相机4", { { 5310, 1,{5180},"5312","5314",-1} }, 1, &lv90Params, _serviceManager, bridge, lieHenJianCe90, "CCD裂痕检测"); + liehen_lv_5.init("Camera5", "裂痕检测-铝-相机5", { { 5320, 1,{5180},"5322","5324",-1} }, 1, &lv45Params, _serviceManager, bridge, lieHenJianCe45, "CCD裂痕检测"); + liehen_lv_6.init("Camera6", "裂痕检测-铝-相机6", { { 5330, 1,{5180},"5332","5334",-1} }, 1, &lv45Params, _serviceManager, bridge, lieHenJianCe45, "CCD裂痕检测"); + + jixing_cu.init("Camera7", "极性检测-相机1", { { 5000, 1,{5010},"5002","5004",-1} }, 1, &tongJiXingParams, _serviceManager, bridge, jiXingJianCe, "CCD极性检测"); + +#pragma endregion + return true; + } +}; + + + + + +#pragma once \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam1213/CMakeLists.txt b/src/mission/581_ZhongHan_silie_jixing/CMakeLists.txt similarity index 90% rename from src/mission/581-BaoMo-Cam1213/CMakeLists.txt rename to src/mission/581_ZhongHan_silie_jixing/CMakeLists.txt index 26347b4..15e8b6c 100644 --- a/src/mission/581-BaoMo-Cam1213/CMakeLists.txt +++ b/src/mission/581_ZhongHan_silie_jixing/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) @@ -40,8 +40,8 @@ FILE(GLOB UI_FILES "./*.ui") #find_package(Qt5 COMPONENTS Core REQUIRED) -find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network REQUIRED) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network Sql REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network Sql REQUIRED) add_library(${CURRENT_FOLDER} SHARED ${HEAD_FILES} @@ -64,6 +64,7 @@ target_link_libraries(${CURRENT_FOLDER} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Network + Qt${QT_VERSION_MAJOR}::Sql ) diff --git a/src/mission/581_ZhongHan_tiejiao_dingbu/581_ZhongHan_tiejiao_dingbu.cpp b/src/mission/581_ZhongHan_tiejiao_dingbu/581_ZhongHan_tiejiao_dingbu.cpp new file mode 100644 index 0000000..f5256ce --- /dev/null +++ b/src/mission/581_ZhongHan_tiejiao_dingbu/581_ZhongHan_tiejiao_dingbu.cpp @@ -0,0 +1,217 @@ +#include <581_ZhongHan_tiejiao_dingbu.h> +#include +#include +#include +#include + +bool TieJiaoZhengMian90(std::shared_ptr data, ZhongHanTieJiaoParams* _detParams, sx_581_address address) { + try + { +#if 0 + /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓调机用↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/ + plcResult = "1"; + QString resultTag = "OK"; + cv::Mat resultImage = img2D.clone(); + textPainter.putText(resultImage, byteArrayToUnicode("OK").toStdString().c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + cv::resize(resultImage, resultImage, cv::Size(), 0.5, 0.5); + resMat.push_back(resultImage); + addImgToSaveStruct(resMat[0], "0", getResSaveFormat(SN, resultTag));//保存结果图 + return true; + /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑调机用↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/ +#else + + /*if (in_Product_Str == "Cu") { + img2D = cv::imread("./testImages/Cu.png", -1); + } + else { + img2D = cv::imread("./testImages/Al.png", -1); + }*/ + + //存图数据加保存队列,加锁,避免数据访问冲突 + QByteArray plcResult = "2"; + cv::Mat sourceImg; + data->oriImgs[0].copyTo(sourceImg); + if (_detParams->in_Product_Str == "Cu") { + cv::rotate(sourceImg, sourceImg, cv::ROTATE_180);//为保证算法一致, + } + cv::Mat Paint; + sourceImg.copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + + HDevEngineCpp::HDevProcedure proc("_3_Pos_CoverGlue_Inspection"); + HDevEngineCpp::HDevProcedureCall procedureCall(proc); + + //vs+halcon联调debug + /*myEngine.StartDebugServer(); + procedureCall.SetWaitForDebugConnection(true);*/ + + HalconCpp::HObject in_Image;//原始三通道图像 + HalconCpp::HTuple in_Product = HalconCpp::HTuple((char*)(_detParams->in_Product_Str).c_str());//产品类别, 'Gu':铜 'Al':铝 + HalconCpp::HTuple in_LineType = "602";//线体类别 + HalconCpp::HTuple in_Resolution(0.0208127);//相机精度(mm/pix) + HalconCpp::HTuple in_FilePath("./halconFiles/ZH_TieJiao_Up/");//模板文件路径 + + in_Image = MatToHObject(sourceImg); + procedureCall.SetInputIconicParamObject("in_Image", in_Image); + procedureCall.SetInputCtrlParamTuple("in_Product", in_Product); + procedureCall.SetInputCtrlParamTuple("in_LineType", in_LineType); + procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution); + procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath); + procedureCall.Execute();//执行halcon程序 + + HalconCpp::HTuple out_Circle;//焊印圆中心坐标(y,x,R) + HalconCpp::HTuple out_LinePoint;//线的坐标(y1,x1,y2,x2) + HalconCpp::HTuple out_Rectangle;//矩形框,共计两个(y,x,phi,width,height) + HalconCpp::HTuple out_NGTails;//NG的明细 + HalconCpp::HTuple out_Flag;//算法的执行结果, 0: 算法检测NG 1: 算法执行成功 + out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle"); + out_LinePoint = procedureCall.GetOutputCtrlParamTuple("out_LinePoint"); + out_Rectangle = procedureCall.GetOutputCtrlParamTuple("out_Rectangle"); + out_NGTails = procedureCall.GetOutputCtrlParamTuple("out_NGTails"); + out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag"); + TextRendererZH textPainter(Paint.cols, Paint.rows, 300); + if (out_Flag.D() == 1) { + //画圆心十字 + cv::drawMarker(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), cv::Scalar(0, 255, 0), cv::MARKER_CROSS, 200, 5); + + //画圆 + cv::circle(Paint, + cv::Point(out_Circle[1].D(), out_Circle[0].D()), + out_Circle[2].D(), cv::Scalar(0, 255, 0), 5); + + //画线 + if (out_LinePoint.Length() > 3) { + for (int i = 0; i < out_LinePoint.Length() / 4; i++) { + cv::line(Paint, + cv::Point(out_LinePoint[i * 4 + 1].D(), out_LinePoint[i * 4 + 0].D()), + cv::Point(out_LinePoint[i * 4 + 3].D(), out_LinePoint[i * 4 + 2].D()), + cv::Scalar(0, 255, 0), 5); + } + } + + //画矩形 + if (out_Rectangle.Length() > 4) { + for (int j = 0; j < out_Rectangle.Length() / 5; j++) { + cv::RotatedRect rRect; + rRect.center.y = out_Rectangle[j * 5 + 0].D(); + rRect.center.x = out_Rectangle[j * 5 + 1].D(); + rRect.angle = out_Rectangle[j * 5 + 2].D(); + rRect.size.width = out_Rectangle[j * 5 + 3].D(); + rRect.size.height = out_Rectangle[j * 5 + 4].D(); + + DrawRotatedRect2Mat(Paint, rRect, cv::Scalar(0, 255, 0), 3, cv::LINE_4); + } + } + } + else { + std::string NgTails = out_NGTails.S().Text();//NG明细 + textPainter.putText(Paint, NgTails, cv::Point(0, 600), cv::Scalar(0, 255, 0)); + } + + if (out_Flag.D() == 1) { + textPainter.putText(Paint, "OK", cv::Point(0, 50), cv::Scalar(0, 255, 0)); + plcResult = "1"; + } + else { + textPainter.putText(Paint, "NG", cv::Point(0, 50), cv::Scalar(0, 0, 255)); + plcResult = "2"; + data->halconOK = false; + } + plcResult = "1"; + data->resultImgs.push_back(Paint); + + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + sourceImg.release(); + return true; +#endif + } + CATCH_EXCEPTIONS + qDebug() << "[Error] " << QString::fromUtf8("检测失败!"); + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + TextRendererZH textPainter(Paint.cols, Paint.rows, 15); + QByteArray plcResult = "2"; + textPainter.putText(Paint, "NG", cv::Point(50, 50), cv::Scalar(0, 0, 255)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + + cv::Mat sourceImg; + data->oriImgs[0].copyTo(sourceImg); + if (_detParams->in_Product_Str == "Cu") { + cv::rotate(sourceImg, sourceImg, cv::ROTATE_180);//为保证算法一致, + } + plcResult = "1"; + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + return true; +} + +bool TieJiaoZhengMian45(std::shared_ptr data, ZhongHanTieJiaoParams* _detParams, sx_581_address address) { + try + { + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + bool isNG = false; + QByteArray plcResult = "1"; + TextRendererZH textainter(Paint.cols, Paint.rows, 300); + if (isNG == true) + { + plcResult = "2"; + textainter.putText(Paint, "NG", cv::Point(50, 50), cv::Scalar(0, 0, 255)); + } + else { + textainter.putText(Paint, "OK", cv::Point(50, 50), cv::Scalar(0, 255, 0)); + } + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);//结果图缩放 + data->resultImgs.push_back(Paint); + + plcResult = "1"; + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + return true; + } + CATCH_EXCEPTIONS + + qDebug() << "[Error] " << QString::fromUtf8("检测失败!"); + cv::Mat Paint; + Paint.copyTo(data->oriImgs[0]); + if (Paint.channels() == 1) { + cv::cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR); + } + QByteArray plcResult = "2"; + TextRendererZH textainter(Paint.cols, Paint.rows, 300); + textainter.putText(Paint, "NG", cv::Point(50, 50), cv::Scalar(0, 0, 255)); + cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5); + data->resultImgs.push_back(Paint); + plcResult = "1"; + data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 + return true; +} + + +void DrawRotatedRect2Mat(cv::Mat& img, cv::RotatedRect rotateRect, cv::Scalar color, int thickness, int linType) +{ + std::vector boxPts(4); + rotateRect.points(boxPts.data()); + for (int mm = 0; mm < 4; mm++) { + cv::line(img, boxPts[mm], boxPts[(mm + 1) % 4], color, thickness, linType); + } +} + + + + + + + + + + + +mission* createMission() { + return new _581_ZhongHan_tiejiao_dingbu(); +} +void destroyMission(mission* _mission) { + delete _mission; +} \ No newline at end of file diff --git a/src/mission/581_ZhongHan_tiejiao_dingbu/581_ZhongHan_tiejiao_dingbu.h b/src/mission/581_ZhongHan_tiejiao_dingbu/581_ZhongHan_tiejiao_dingbu.h new file mode 100644 index 0000000..3117c34 --- /dev/null +++ b/src/mission/581_ZhongHan_tiejiao_dingbu/581_ZhongHan_tiejiao_dingbu.h @@ -0,0 +1,60 @@ +#include +#include +#pragma region 算法 +#include +#include +#include +using namespace HDevEngineCpp; +#pragma endregion +class ZhongHanTieJiaoParams { +public: + std::string in_Product_Str = ""; +}; + + + +void DrawRotatedRect2Mat(cv::Mat& img, cv::RotatedRect rotateRect, cv::Scalar color, int thickness, int linType); +bool TieJiaoZhengMian90(std::shared_ptr data, ZhongHanTieJiaoParams* _detParams, sx_581_address address); +bool TieJiaoZhengMian45(std::shared_ptr data, ZhongHanTieJiaoParams* _detParams, sx_581_address address); + +class _581_ZhongHan_tiejiao_dingbu : public mission { +public: + _581_SX_Single_triggerTemplate< ZhongHanTieJiaoParams> in_tong_90_1; + _581_SX_Single_triggerTemplate< ZhongHanTieJiaoParams> in_tong_45_2; + _581_SX_Single_triggerTemplate< ZhongHanTieJiaoParams> in_tong_45_3; + + _581_SX_Single_triggerTemplate< ZhongHanTieJiaoParams> out_tong_90_4; + _581_SX_Single_triggerTemplate< ZhongHanTieJiaoParams> out_tong_45_5; + _581_SX_Single_triggerTemplate< ZhongHanTieJiaoParams> out_tong_45_6; + + ZhongHanTieJiaoParams tongParams; + ZhongHanTieJiaoParams lvParams; + bool initOnce = false; + void onConfigReloaded() { + HDevEngineCpp::HDevEngine myEngine; + myEngine.SetProcedurePath("./halconAlgo/AlgoLibrary_602.hdpl"); + initOnce = true; + + tongParams.in_Product_Str = "Cu"; + lvParams.in_Product_Str = "Al"; + } + bool initCustom() { +#pragma region 注册触发器回调 + in_tong_90_1.init("Camera1", "贴胶检测-内-铜-相机1(90°)", { { 5200, 1,{5120},"5202","5204",-1} }, 1, &tongParams, _serviceManager, bridge, TieJiaoZhengMian90); + in_tong_45_2.init("Camera2", "贴胶检测-内-铜-相机2(45°)", { { 5210, 1,{5120},"5212","5214",-1} }, 1, &tongParams, _serviceManager, bridge, TieJiaoZhengMian45); + in_tong_45_3.init("Camera3", "贴胶检测-内-铜-相机3(45°)", { { 5220, 1,{5120},"5222","5224",-1} }, 1, &tongParams, _serviceManager, bridge, TieJiaoZhengMian45); + + out_tong_90_4.init("Camera4", "贴胶检测-外-铝-相机4(90°)", { { 5230, 1,{5140},"5232","5234",-1} }, 1, &lvParams, _serviceManager, bridge, TieJiaoZhengMian90); + out_tong_45_5.init("Camera5", "贴胶检测-外-铝-相机5(45°)", { { 5240, 1,{5140},"5242","5244",-1} }, 1, &lvParams, _serviceManager, bridge, TieJiaoZhengMian45); + out_tong_45_6.init("Camera6", "贴胶检测-外-铝-相机6(45°)", { { 5250, 1,{5140},"5252","5254",-1} }, 1, &lvParams, _serviceManager, bridge, TieJiaoZhengMian45); + +#pragma endregion + return true; + } +}; + + + + + +#pragma once \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam5678/CMakeLists.txt b/src/mission/581_ZhongHan_tiejiao_dingbu/CMakeLists.txt similarity index 90% rename from src/mission/581-BaoMo-Cam5678/CMakeLists.txt rename to src/mission/581_ZhongHan_tiejiao_dingbu/CMakeLists.txt index 26347b4..15e8b6c 100644 --- a/src/mission/581-BaoMo-Cam5678/CMakeLists.txt +++ b/src/mission/581_ZhongHan_tiejiao_dingbu/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "*.h" ) @@ -40,8 +40,8 @@ FILE(GLOB UI_FILES "./*.ui") #find_package(Qt5 COMPONENTS Core REQUIRED) -find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network REQUIRED) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network Sql REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network Sql REQUIRED) add_library(${CURRENT_FOLDER} SHARED ${HEAD_FILES} @@ -64,6 +64,7 @@ target_link_libraries(${CURRENT_FOLDER} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Network + Qt${QT_VERSION_MAJOR}::Sql ) diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt deleted file mode 100644 index f9a95fd..0000000 --- a/src/plugin/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# CMakeList.txt: 遍历文件夹 添加子项目 - -set(OUR_LIBS "") -SUBDIRENAMES(OUR_LIBS ${CMAKE_CURRENT_SOURCE_DIR} "" OFF) -message("OUR_LIBS :" ${OUR_LIBS}) - - -# 遍历子库 -foreach(dll ${OUR_LIBS}) - add_subdirectory(${dll}) -endforeach(dll ${}) diff --git a/src/plugin/autoDelete/CMakeLists.txt b/src/plugin/autoDelete/CMakeLists.txt deleted file mode 100644 index a4b4bed..0000000 --- a/src/plugin/autoDelete/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -# 获取获取当前目录名 -get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME) -string(TIMESTAMP RUN_TIME) -message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME}) - -set(DLL_NAMES "opencv") -foreach(child ${DLL_NAMES}) - LIST(APPEND ENV_INCLUDE ${${child}_include}) - LIST(APPEND ENV_LIB ${${child}_lib}) - LIST(APPEND ENV_TARGET ${${child}_target_link}) -endforeach() -message(" ENV_INCLUDE : " ${ENV_INCLUDE} ) -message(" ENV_LIB : " ${ENV_LIB} ) -message(" ENV_TARGET : " ${ENV_TARGET} ) -include_directories( - - ${ENV_INCLUDE} - ) - -link_directories ( - ${ENV_LIB} - - ) - - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_CXX_STANDARD 11) -SET(CMAKE_CXX_STANDARD_REQUIRED ON) - -set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -FILE(GLOB HEAD_FILES "*.h" ) -FILE(GLOB SRC_FILES "./*.cpp") -FILE(GLOB UI_FILES "./*.ui") - - -#find_package(Qt5 COMPONENTS Core REQUIRED) -find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) - -add_library(${CURRENT_FOLDER} SHARED - ${HEAD_FILES} - ${SRC_FILES} - ${UI_FILES} - ) - - - -set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} - ) - - -target_link_libraries(${CURRENT_FOLDER} PRIVATE - ${ENV_TARGET} - Qt${QT_VERSION_MAJOR}::Core - ) - - -# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY) - - - - -string(TIMESTAMP RUN_TIME) -message( " modelx end : " ${CURRENT_FOLDER}:${RUN_TIME}) -message( " header files "${HEAD_FILES}) diff --git a/src/plugin/autoDelete/autoDelete.cpp b/src/plugin/autoDelete/autoDelete.cpp deleted file mode 100644 index ee011fd..0000000 --- a/src/plugin/autoDelete/autoDelete.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include -IPlugin* createPlugin() { - return new autoDeletePlugin(); -} -void destroyPlxugin(IPlugin* plugin) { - delete plugin; -} \ No newline at end of file diff --git a/src/plugin/autoDelete/autoDelete.h b/src/plugin/autoDelete/autoDelete.h deleted file mode 100644 index 38b4fbd..0000000 --- a/src/plugin/autoDelete/autoDelete.h +++ /dev/null @@ -1,238 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/// -/// 自动删除文件夹,支持按日期删除,按磁盘剩余容量删除,或者两者都是,请在主线程声明qtimer -/// -class autoDelete : public QThread -{ - Q_OBJECT -public: - enum clearMode - { - dayBefore, - sizeOver, - sizeOverOrDayBefore, - }; - /// - /// 构造函数 - /// - /// 文件夹路径 - /// 删除几天前的,磁盘剩余容量小于多少,两者都是 - /// 检测间隔如果只检测日期建议设大一点,如果只检测磁盘容量建议设小一点,默认十分钟 - autoDelete(std::vector pathVec, clearMode mode, int Interval) - { - for (auto& path : pathVec) - detPathVec.push_back(QString::fromStdString(path)); - detMode = mode; - threadInterval = Interval; - this->start(); - } - ~autoDelete() - { - runFlag = false; - } - void run() override - { - while (runFlag) - { - exacute(); - QThread::sleep(threadInterval); - } - } - void exacute() - { - for (auto& detPath : detPathVec) - { - switch (detMode) - { - case dayBefore://删除几天前的 - deleteDirBeforeDays(detPath, daySet); - break; - case sizeOver://磁盘剩余容量小于多少 - if (getDriveFreeSpaceAsGb(detPath) < sizeSet) - deleteOldestSonDir(detPath);//删除最老的文件夹 - break; - case sizeOverOrDayBefore://两者都是 - if (getDriveFreeSpaceAsGb(detPath) < sizeSet)//磁盘剩余容量小于多少 - deleteOldestDir(detPath);//删除最老的文件夹 - deleteDirBeforeDays(detPath, daySet);//同时删除几天前的 - break; - default: - qDebug() << "none mode det"; - break; - } - } - } - void setDay(int day) - { - daySet = day; - } - void setSize(int size) - { - sizeSet = size; - } -private: - bool deleteOldestSonDir(const QString& folderPath) - { - QString oldestDir = getOldestDir(folderPath); - if (oldestDir.isEmpty()) - return false; - oldestDir = folderPath + "//" + oldestDir; - deleteOldestDir(oldestDir); - if (getAllDirs(oldestDir).size() == 0)//删除后文件夹为空,删除父文件夹 - { - QDir dir(oldestDir); - dir.removeRecursively(); - } - return true; - } - bool deleteDirBeforeDays(const QString& folderPath, int day) - { - std::vector dirs = getAllDirs(folderPath); - for (auto& dir : dirs) - { - QFileInfo fileInfo(QString::fromStdString(dir)); - QDateTime fileTime = fileInfo.created(); - QDateTime nowTime = QDateTime::currentDateTime(); - std::string result = fileTime.toString("yyyy-MM-dd").toStdString(); - int dayBefore = fileTime.daysTo(nowTime); - if (dayBefore > day) - { - QDir dir(QString::fromStdString(dir)); - dir.removeRecursively(); - } - } - return true; - } - /// - /// 检查磁盘剩余空间,以GB为单位返回 - /// - /// example"E://""E://111/222"支持文件夹或者磁盘路径 - /// - int getDriveFreeSpaceAsGb(const QString& folderPath) { - QStorageInfo storageInfo(folderPath); - - if (storageInfo.isValid() && storageInfo.isReady()) { - return storageInfo.bytesAvailable() / 1073741824; - } - - return -1; // Indicate failure to retrieve disk space - } - /// - /// 检查磁盘剩余空间,以Mb为单位返回 - /// - /// example"E://""E://111/222"支持文件夹或者磁盘路径 - /// - int getDriveFreeSpaceAsMb(const QString& folderPath) { - QStorageInfo storageInfo(folderPath); - - if (storageInfo.isValid() && storageInfo.isReady()) { - return storageInfo.bytesAvailable() / 1048576; - } - - return -1; // Indicate failure to retrieve disk space - } - /// - /// 返回最老创建时间文件夹名 - /// - /// - /// - QString getOldestDir(const QString& folderPath) - { - std::string oldestDir; - QDateTime oldestTime; - std::vector files = getAllDirs(folderPath); - for (auto file : files) - { - QFileInfo fileInfo(QString::fromStdString(folderPath.toStdString() + "//" + file)); - QDateTime fileTime = fileInfo.created(); - QString str = fileInfo.created().toString(); - std::cout << "Current date and time: " << str.toStdString() << std::endl; - if (oldestTime.isNull() || fileTime < oldestTime) - { - oldestTime = fileTime; - oldestDir = file; - } - } - return QString::fromStdString(oldestDir); - } - /// - /// 删除最老创建时间文件夹 - /// - /// - /// - bool deleteOldestDir(const QString& folderPath) - { - QString oldestDir = getOldestDir(folderPath); - if (oldestDir.isEmpty()) - return false; - oldestDir = folderPath + "//" + oldestDir; - QDir dir(oldestDir); - dir.removeRecursively(); - return true; - } - std::vector getAllDirs(const QString& folderPath) - { - std::vector foldersVec; - QDir folderDir(folderPath); - if (!folderDir.exists()) { - return foldersVec; - } - - QStringList folders = folderDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - - for (const QString& folder : folders) { - foldersVec.push_back(folderPath.toStdString() + "//" + folder.toStdString()); - } - return foldersVec; - } - std::vector detPathVec; - clearMode detMode; - int daySet = 30;//天 - int sizeSet = 100;//GB - int threadInterval = 0;//sec - bool runFlag = true; -}; - - -class autoDeletePlugin :public IPlugin -{ -public: - autoDelete _autoDelete; - autoDeletePlugin(): - _autoDelete({ "D://CCD" }, autoDelete::dayBefore, 3600) { - name = "hwMonitor"; - } - bool start() - { - _autoDelete.start(); - return true; - } - bool stop() - { - _autoDelete.terminate(); - _autoDelete.quit(); - return true; - } - pluginState getState() - { - return _autoDelete.isRunning() ? pluginState::running : pluginState::stop; - } -}; - -extern "C" -{ - __declspec(dllexport) IPlugin* createPlugin(); - __declspec(dllexport) void destroyPlxugin(IPlugin* plugin); -} - -#pragma once \ No newline at end of file diff --git a/src/plugin/hwMonitor/CMakeLists.txt b/src/plugin/hwMonitor/CMakeLists.txt deleted file mode 100644 index a4b4bed..0000000 --- a/src/plugin/hwMonitor/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -# 获取获取当前目录名 -get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME) -string(TIMESTAMP RUN_TIME) -message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME}) - -set(DLL_NAMES "opencv") -foreach(child ${DLL_NAMES}) - LIST(APPEND ENV_INCLUDE ${${child}_include}) - LIST(APPEND ENV_LIB ${${child}_lib}) - LIST(APPEND ENV_TARGET ${${child}_target_link}) -endforeach() -message(" ENV_INCLUDE : " ${ENV_INCLUDE} ) -message(" ENV_LIB : " ${ENV_LIB} ) -message(" ENV_TARGET : " ${ENV_TARGET} ) -include_directories( - - ${ENV_INCLUDE} - ) - -link_directories ( - ${ENV_LIB} - - ) - - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_CXX_STANDARD 11) -SET(CMAKE_CXX_STANDARD_REQUIRED ON) - -set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -FILE(GLOB HEAD_FILES "*.h" ) -FILE(GLOB SRC_FILES "./*.cpp") -FILE(GLOB UI_FILES "./*.ui") - - -#find_package(Qt5 COMPONENTS Core REQUIRED) -find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) - -add_library(${CURRENT_FOLDER} SHARED - ${HEAD_FILES} - ${SRC_FILES} - ${UI_FILES} - ) - - - -set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} - ) - - -target_link_libraries(${CURRENT_FOLDER} PRIVATE - ${ENV_TARGET} - Qt${QT_VERSION_MAJOR}::Core - ) - - -# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY) - - - - -string(TIMESTAMP RUN_TIME) -message( " modelx end : " ${CURRENT_FOLDER}:${RUN_TIME}) -message( " header files "${HEAD_FILES}) diff --git a/src/plugin/hwMonitor/hardwareMonitor.cpp b/src/plugin/hwMonitor/hardwareMonitor.cpp deleted file mode 100644 index 08b7a82..0000000 --- a/src/plugin/hwMonitor/hardwareMonitor.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include -IPlugin* createPlugin() { - return new hardwareMonitorPlugin(); -} -void destroyPlugin(IPlugin* plugin) { - delete plugin; -} \ No newline at end of file diff --git a/src/plugin/hwMonitor/hardwareMonitor.h b/src/plugin/hwMonitor/hardwareMonitor.h deleted file mode 100644 index b09c937..0000000 --- a/src/plugin/hwMonitor/hardwareMonitor.h +++ /dev/null @@ -1,217 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class hardwareMonitor :public QThread -{ -public: - int outputCnt = 10; - struct CPUUsage { - DWORD_PTR coreId; - double usage; - }; - struct oneTimeData - { - QString time; - std::vectorcpuState; - std::vectormemState; - }; - std::vector getCPUUsagePerCore() { - std::vector coreUsages; - int numCores = sysInfo.dwNumberOfProcessors; - std::vector idleTimes(numCores), kernelTimes(numCores), userTimes(numCores); - std::vector prevIdleTimes(numCores), prevKernelTimes(numCores), prevUserTimes(numCores); - - // 初始获取 - GetSystemTimes(&prevIdleTimes[0], &prevKernelTimes[0], &prevUserTimes[0]); - - Sleep(100); - - // 获取再次的 CPU 时间 - GetSystemTimes(&idleTimes[0], &kernelTimes[0], &userTimes[0]); - - for (int i = 0; i < numCores; ++i) { - ULARGE_INTEGER idleTime, kernelTime, userTime; - ULARGE_INTEGER prevIdleTime, prevKernelTime, prevUserTime; - - idleTime.LowPart = idleTimes[i].dwLowDateTime; - idleTime.HighPart = idleTimes[i].dwHighDateTime; - kernelTime.LowPart = kernelTimes[i].dwLowDateTime; - kernelTime.HighPart = kernelTimes[i].dwHighDateTime; - userTime.LowPart = userTimes[i].dwLowDateTime; - userTime.HighPart = userTimes[i].dwHighDateTime; - - prevIdleTime.LowPart = prevIdleTimes[i].dwLowDateTime; - prevIdleTime.HighPart = prevIdleTimes[i].dwHighDateTime; - prevKernelTime.LowPart = prevKernelTimes[i].dwLowDateTime; - prevKernelTime.HighPart = prevKernelTimes[i].dwHighDateTime; - prevUserTime.LowPart = prevUserTimes[i].dwLowDateTime; - prevUserTime.HighPart = prevUserTimes[i].dwHighDateTime; - - ULONGLONG totalIdle = idleTime.QuadPart - prevIdleTime.QuadPart; - ULONGLONG totalKernel = kernelTime.QuadPart - prevKernelTime.QuadPart; - ULONGLONG totalUser = userTime.QuadPart - prevUserTime.QuadPart; - - ULONGLONG total = totalKernel + totalUser; - - CPUUsage usage; - usage.coreId = i; - usage.usage = (total > 0) ? (static_cast(total - totalIdle) / total) * 100.0 : 0.0; - coreUsages.push_back(usage); - } - - return coreUsages; - } - std::vector getMemState() - { - MEMORYSTATUSEX memInfo; - memInfo.dwLength = sizeof(MEMORYSTATUSEX); - if (GlobalMemoryStatusEx(&memInfo)) { - // 获取总物理内存和已用内存 - DWORDLONG totalPhysical = memInfo.ullTotalPhys; - DWORDLONG usedPhysical = memInfo.ullTotalPhys - memInfo.ullAvailPhys; - - // 获取总虚拟内存和已用虚拟内存 - DWORDLONG totalVirtual = memInfo.ullTotalVirtual; - DWORDLONG usedVirtual = memInfo.ullTotalVirtual - memInfo.ullAvailVirtual; - - // 计算内存占用率 - double physicalMemoryUsage = (static_cast(usedPhysical) / totalPhysical) * 100.0; - double virtualMemoryUsage = (static_cast(usedVirtual) / totalVirtual) * 100.0; - return { physicalMemoryUsage,virtualMemoryUsage }; - } - else - return { 0,0 }; - } - ~hardwareMonitor() - { - runFlag = false; - } - static void createDirectoryIfNotExists(const std::string& path) { - // 检查路径是否存在 - if (!std::filesystem::exists(path)) { - // 创建路径 - - std::filesystem::create_directories(path); - //std::cout << "已创建文件夹: " << path << std::endl; - } - else {/* - std::cout << "文件夹已存在: " << path << std::endl;*/ - } - } - void writeCsv(std::vector& State) { - if (State.size() == 0) - { - //std::cerr << "hw数据为空! " << std::endl; - return; - } - createDirectoryIfNotExists("./Log"); - QString fileName("./Log/" + QDate::currentDate().toString("yyyy-MM-dd") + "hwMonitor.csv"); - QFile file(fileName); - bool isEmpty = !file.exists() || file.size() == 0; - // 打开文件进行写入 - if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) { - //std::cerr << "无法打开文件进行写入: " << file.errorString().toStdString() << std::endl; - return; - } - - QTextStream out(&file); - - // 表头 - if (isEmpty == true) - { - QStringList headers; - headers.append("getTime"); - for (int i = 0; i < State[0].cpuState.size(); i++) - headers.append("CORE" + QString::number(i)); - headers.append("pMem,vMem"); - out << headers.join(",") << "\n"; - } - - // 循环写入数据 - for (auto& data : State) - { - QStringList csvData; - csvData.append(data.time); - for (auto& cpuData : data.cpuState) - csvData.append(QString::number(cpuData.usage)); - for (auto& memuData : data.memState) - csvData.append(QString::number(memuData)); - out << csvData.join(",") << "\n"; - } - - // 关闭文件 - file.close(); - State.clear();//成功写入后清除 - } - void run() - { - //初始化 - runFlag = true; - GetSystemInfo(&sysInfo); - //循环读取 - std::vector< oneTimeData> datas; - while (runFlag) - { - oneTimeData _oneTimeData; - //CPU占用 - _oneTimeData.cpuState = getCPUUsagePerCore(); - //内存占用 - _oneTimeData.memState = getMemState(); - //记录时间 - _oneTimeData.time = QTime::currentTime().toString("HH:mm:ss"); - - QThread::msleep(10); - datas.push_back(_oneTimeData); - if (datas.size() > outputCnt) - { - writeCsv(datas); - } - - } - } - void stop() - { - runFlag = false; - } -private: - SYSTEM_INFO sysInfo; - bool runFlag = true; -}; -class hardwareMonitorPlugin :public IPlugin -{ -public: - hardwareMonitor _hardwareMonitor; - hardwareMonitorPlugin() { - name = "hwMonitor"; - } - bool start() - { - _hardwareMonitor.start(); - return true; - } - bool stop() - { - _hardwareMonitor.stop(); - return true; - } - pluginState getState() - { - return _hardwareMonitor.isRunning() ? pluginState::running : pluginState::stop; - } -}; - -extern "C" -{ - __declspec(dllexport) IPlugin* createPlugin(); - __declspec(dllexport) void destroyPlugin(IPlugin* plugin); -} - - -#pragma once \ No newline at end of file diff --git a/subModule/Hd_CameraModule_3DKeyence/CMakeLists.txt b/subModule/Hd_CameraModule_3DKeyence/CMakeLists.txt index cb49af5..8533141 100644 --- a/subModule/Hd_CameraModule_3DKeyence/CMakeLists.txt +++ b/subModule/Hd_CameraModule_3DKeyence/CMakeLists.txt @@ -29,7 +29,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "./*.h" ) diff --git a/subModule/Hd_CameraModule_3DKeyence/Hd_CameraModule_3DKeyence.cpp b/subModule/Hd_CameraModule_3DKeyence/Hd_CameraModule_3DKeyence.cpp index 526ea93..12900e1 100644 --- a/subModule/Hd_CameraModule_3DKeyence/Hd_CameraModule_3DKeyence.cpp +++ b/subModule/Hd_CameraModule_3DKeyence/Hd_CameraModule_3DKeyence.cpp @@ -528,12 +528,12 @@ bool Hd_CameraModule_3DKeyence::run() while (imgTakeNum != imgTarget) { int timeOutCnt = 0; - while (_imageAvailable[deviceId] != 1 && timeOutCnt < 1200) + while (_imageAvailable[deviceId] != 1 && timeOutCnt < 120) { timeOutCnt++; QThread::msleep(10); } - if (timeOutCnt >= 1200) + if (timeOutCnt >= 120) { heightMatS.push_back(cv::Mat(G_yImageSize, G_xImageSize, CV_8UC1, cv::Scalar(0, 0, 0))); luminanceMatS.push_back(cv::Mat(G_yImageSize, G_xImageSize, CV_8UC1, cv::Scalar(0, 0, 0))); @@ -580,13 +580,21 @@ bool Hd_CameraModule_3DKeyence::run() qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Free memory Finished: "; m_mutex->lock(); - cv::Mat luminanceMat(yImageSize, xImageSize, CV_16UC1, luminanceImage); + cv::Mat luminanceMat; + if(_lastImageSizeHeight[deviceId] != 0) + luminanceMat = cv::Mat(_lastImageSizeHeight[deviceId], xImageSize, CV_16UC1, luminanceImage); + else + luminanceMat = cv::Mat(yImageSize, xImageSize, CV_16UC1, luminanceImage); cv::normalize(luminanceMat, luminanceMat, 0, 255, cv::NORM_MINMAX); cv::convertScaleAbs(luminanceMat, luminanceMat); + luminanceMatS.enqueue(luminanceMat); cv::Mat heightImg; - cv::Mat(yImageSize, xImageSize, CV_16UC1, heightImage).copyTo(heightImg); + if (_lastImageSizeHeight[deviceId] != 0) + cv::Mat(_lastImageSizeHeight[deviceId], xImageSize, CV_16UC1, heightImage).copyTo(heightImg); + else + cv::Mat(yImageSize, xImageSize, CV_16UC1, heightImage).copyTo(heightImg); heightMatS.enqueue(heightImg); m_mutex->unlock(); qDebug() << __FUNCTION__ << " line:" << __LINE__ << " success to acquire 3d image! camera_name: " << camera_name; diff --git a/subModule/Hd_CameraModule_HIK_hard_GIGE/CMakeLists.txt b/subModule/Hd_CameraModule_HIK_hard_GIGE/CMakeLists.txt index e86c65b..8412669 100644 --- a/subModule/Hd_CameraModule_HIK_hard_GIGE/CMakeLists.txt +++ b/subModule/Hd_CameraModule_HIK_hard_GIGE/CMakeLists.txt @@ -28,7 +28,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "./*.h" ) diff --git a/subModule/Hd_CameraModule_HIK_hard_GIGE/Hd_CameraModule_HIK_hard_GIGE.cpp b/subModule/Hd_CameraModule_HIK_hard_GIGE/Hd_CameraModule_HIK_hard_GIGE.cpp index e79ee85..3789fba 100644 --- a/subModule/Hd_CameraModule_HIK_hard_GIGE/Hd_CameraModule_HIK_hard_GIGE.cpp +++ b/subModule/Hd_CameraModule_HIK_hard_GIGE/Hd_CameraModule_HIK_hard_GIGE.cpp @@ -26,6 +26,16 @@ bool ifRunning = false; MV_CC_DEVICE_INFO_LIST m_stDevList; // ch:设备信息列表结构体变量,用来存储设备列表 //MV_GENTL_IF_INFO_LIST m_stIFList; void CloseDevice(); +static MV_CC_DEVICE_INFO_LIST QByteArrayToMV_CC_DeviceInfoList(const QByteArray& byteArray) { + MV_CC_DEVICE_INFO_LIST deviceInfoList; + if (byteArray.size() == sizeof(MV_CC_DEVICE_INFO_LIST)) { + memcpy(&deviceInfoList, byteArray.constData(), sizeof(MV_CC_DEVICE_INFO_LIST)); + } + else { + qDebug() << "Invalid size of QByteArray for MV_CC_DEVICE_INFO_LIST!"; + } + return deviceInfoList; +} QString byteArrayToUnicode(const QByteArray array) { // state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功 @@ -94,9 +104,15 @@ void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFra //搜索所有设备 int SearchDevice() { - memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); - // ch:枚举子网内所有设备 | en:Enumerate all devices within subnet - int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList); + if (m_stDevList.nDeviceNum == 0) { + memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); + // ch:枚举子网内所有设备 | en:Enumerate all devices within subnet + int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList); + if (MV_OK != nRet) + { + return 0; + } + } for (int i = 0; i < m_stDevList.nDeviceNum; i++) { //SN @@ -110,10 +126,6 @@ int SearchDevice() break; } } - if (MV_OK != nRet) - { - return 0; - } return -1; } @@ -387,6 +399,13 @@ bool Hd_CameraModule_HIK_hard_PCIE::readData(std::vector& mat, QByteArr bool Hd_CameraModule_HIK_hard_PCIE::writeData(std::vector& mat, QByteArray& data) { Q_UNUSED(mat); + if (data.contains("deviceList")) { + auto result = QByteArrayToMV_CC_DeviceInfoList(data.mid(10)); + if (result.nDeviceNum != 0) { + m_stDevList = result; + return true; + } + } QStringList dataList = QString::fromUtf8(data).split("_"); //2024.02.18更新,相机对应的读SN信号时,表示新产品进入,设置初始值 if (data == "rest_newProductIn") @@ -538,7 +557,7 @@ bool Hd_CameraModule_HIK_hard_PCIE::run() break; } if (cnt > 120) { - queuepic.push_back(cv::Mat(250, 250, CV_8UC3, cv::Scalar(0, 255, 0))); //返回空图 + queuepic.push_back(cv::Mat(200, 200, CV_8UC1, cv::Scalar(0))); //返回空图 std::cout << "timeout" << std::endl; n_mutex->unlock(); return true; diff --git a/subModule/Hd_CameraModule_HIK_hard_PCIE.cpp b/subModule/Hd_CameraModule_HIK_hard_PCIE.cpp deleted file mode 100644 index 3116cf3..0000000 --- a/subModule/Hd_CameraModule_HIK_hard_PCIE.cpp +++ /dev/null @@ -1,570 +0,0 @@ -#include "Hd_CameraModule_HIK_hard_PCIE.h" -#include -using namespace std; -#include -QByteArray mv_Status = "connected";//0106 新增相机断联报警 -long long index = 0; //相机序号 -void* handle; -string Username = ""; -bool m_flag = false; -//MV_CC_DEVICE_INFO_LIST m_stDevList;//相机设备 -bool moduleStatus = true; -QQueue queuepic; -//data == "rest_newProductIn"时要结束run;机台报警,取图超时,复位后重新拍的情况。 -bool ifBreak = false; -//ifRunning减少ifBreak的判断;"rest_newProductIn"时,Logic_camera_thread框架会结束未处理完的相相机取图 -bool ifRunning = false; - -MV_GENTL_DEV_INFO_LIST m_stDevList; // ch:设备信息列表结构体变量,用来存储设备列表 -MV_GENTL_IF_INFO_LIST m_stIFList; -void CloseDevice(); -QString byteArrayToUnicode(const QByteArray array) { - - // state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功 - // 如果转换成功,则值为0,如果值大于0,则说明转换失败 - QTextCodec::ConverterState state; - // 先尝试使用utf-8的方式把QByteArray转换成QString - QString text = QTextCodec::codecForName("UTF-8")->toUnicode(array.constData(), array.size(), &state); - // 如果转换时无效字符数量大于0,说明编码格式不对 - if (state.invalidChars > 0) - { - // 再尝试使用GBK的方式进行转换,一般就能转换正确(当然也可能是其它格式,但比较少见了) - text = QTextCodec::codecForName("GBK")->toUnicode(array); - } - return text; -} -QMutex* n_mutex = new QMutex(); -//cv::Mat srcImage; -//是否为标准通信流程: -//标准通信流程,run函数设置曝光/增益;非标准通信流程(简单通信流程),回调函数设置曝光/增益 -int imgCnt = 0; -bool ifStandard = false; -//相机取图超时时间 -int getImageTimeOut = 3000; -//总取图数 -int imgIndex = 0; -//曝光值列表 -QQueue expourseTimeList; -//增益列表 -QQueue gainList; - -bool IsColor(MvGvspPixelType enType) -{ - switch (enType) - { - case PixelType_Gvsp_RGB8_Packed: - case PixelType_Gvsp_YUV422_Packed: - case PixelType_Gvsp_YUV422_YUYV_Packed: - case PixelType_Gvsp_BayerGR8: - case PixelType_Gvsp_BayerRG8: - case PixelType_Gvsp_BayerGB8: - case PixelType_Gvsp_BayerBG8: - case PixelType_Gvsp_BayerGB10: - case PixelType_Gvsp_BayerGB10_Packed: - case PixelType_Gvsp_BayerBG10: - case PixelType_Gvsp_BayerBG10_Packed: - case PixelType_Gvsp_BayerRG10: - case PixelType_Gvsp_BayerRG10_Packed: - case PixelType_Gvsp_BayerGR10: - case PixelType_Gvsp_BayerGR10_Packed: - case PixelType_Gvsp_BayerGB12: - case PixelType_Gvsp_BayerGB12_Packed: - case PixelType_Gvsp_BayerBG12: - case PixelType_Gvsp_BayerBG12_Packed: - case PixelType_Gvsp_BayerRG12: - case PixelType_Gvsp_BayerRG12_Packed: - case PixelType_Gvsp_BayerGR12: - case PixelType_Gvsp_BayerGR12_Packed: - return true; - default: - return false; - } -} -//0106 断线重连 -void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser); -void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFrameInfo0, void* pUser0); -//搜索所有设备 -int SearchDevice() -{ - //MV_CC_Initialize(); - /* MV_CC_DEVICE_INFO_LIST stDeviceList; - memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); - unsigned int nnRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE | MV_GENTL_CAMERALINK_DEVICE | MV_GENTL_CXP_DEVICE | MV_GENTL_XOF_DEVICE, &stDeviceList); - return 1;*/ - const char* chCtiPath = "MvFGProducerXoF.cti";//.cti文件路径 - int nRet = 0; - nRet = MV_CC_EnumInterfacesByGenTL(&m_stIFList, chCtiPath); - if (nRet != MV_OK) - { - qDebug() << "EnumInterfacsByGenTL fail"; - return 0; - } - - if (m_stIFList.nInterfaceNum == 0) - { - qDebug() << "No Device"; - return 0; - } - - // ch:枚举子网内所有设备 | en:Enumerate all devices within subnet - for (int p = 0; p < m_stIFList.nInterfaceNum; p++) - { - memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); - nRet = MV_CC_EnumDevicesByGenTL(m_stIFList.pIFInfo[p], &m_stDevList); - bool ifHas = false; - for (int i = 0; i < m_stDevList.nDeviceNum; i++) - { - //SN - unsigned char* name = m_stDevList.pDeviceInfo[i]->chSerialNumber; - string userName = static_cast((LPCSTR)name); - if (Username == userName) - { - index = i; - ifHas = true; - break; - } - } - if (ifHas)break; - } - if (MV_OK != nRet) - { - return 0; - } - return -1; -} - -bool connectDevice() -{ - //MV_CC_Initialize(); - index = -1; - SearchDevice(); - if (index == -1) - { - //未匹配到相机 - //qDebug() << "[Waring] " << "Hd_CameraModule_HIK not match --CameraName:" << QString::fromStdString(Username); - return false; - } - unsigned char* name = m_stDevList.pDeviceInfo[index]->chSerialNumber; - string userName = static_cast((LPCSTR)name); - qDebug() << "[INFO] " << " start" << "--UserName:" << QString::fromStdString(userName); - if (handle != NULL) - { - MV_CC_StopGrabbing(handle); - MV_CC_CloseDevice(handle); - MV_CC_DestroyHandle(handle); - } - - //打开相机 - MV_CC_CreateHandleByGenTL(&handle, m_stDevList.pDeviceInfo[index]); - int nRet = MV_CC_OpenDevice(handle); - ////触发模式 - MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_LINE0); - MV_CC_SetEnumValue(handle, "TriggerMode", MV_TRIGGER_MODE_ON); - // //加载用户集,相机设置应当UserSet1 - nRet = MV_CC_SetEnumValueByString(handle, "UserSetSelector", "UserSet1"); - if (MV_OK != nRet) - { - qDebug() << "Set UserSetSelector fail! nRet " << nRet; - } - // ch:注册抓图回调 | en:Register image callback - MV_CC_SetIntValueEx(handle, "GevHeartbeatTimeout", 3000);//心跳日志 - - nRet = MV_CC_RegisterImageCallBackEx(handle, ImageCallBackEx, handle);//注册回调 - if (MV_OK != nRet) - return false; - nRet = MV_CC_RegisterExceptionCallBack(handle, ReconnectDevice, NULL);//断线重连 - if (MV_OK != nRet) - return false; - MV_CC_StartGrabbing(handle); - return true; -} -void SetExposureTime(float exposureValue) -{ - qDebug() << "[INFO] " << "exposureValue:" << exposureValue; - MV_CC_SetEnumValue(handle, "ExposureAuto", MV_EXPOSURE_AUTO_MODE_OFF); - MV_CC_SetFloatValue(handle, "ExposureTime", exposureValue); -} - -void SetGain(float GainValue) -{ - qDebug() << "[INFO] " << "GainValue:" << GainValue; - MV_CC_SetEnumValue(handle, "GainAuto", 0); - MV_CC_SetFloatValue(handle, "Gain", GainValue); -} - -//0518 断线重连 -void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser) -{ - mv_Status = "disconnect"; - qDebug() << "[Error] " << " MV camera disconnects!"; - moduleStatus = false; - if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT) - { - //断开连接 - CloseDevice(); - handle = nullptr; - BOOL bConnected = FALSE; - while (1) - { - Sleep(100); - if (connectDevice() == true) - { - qWarning() << "[Hd_CameraModule_HIK] " << " Hd_CameraModule_HIK create success again! "; - moduleStatus = true; - break; - } - - } - } -} - -//0106 断连提示 -void _stdcall ExceptionCB(unsigned int nMesgType, void* pUser) { - mv_Status = "disconnect"; - qDebug() << "[Error] " << " MvCameraTL disconnects!"; -} - - -Hd_CameraModule_HIK_hard_PCIE* create() -{ - qDebug() << "[INFO] " << "Hd_CameraModule_HIK create success!"; - return new Hd_CameraModule_HIK_hard_PCIE; -} - -void destory(Hd_CameraModule_HIK_hard_PCIE* ptr) -{ - if (ptr) - { - delete ptr; - ptr = nullptr; - } - qDebug() << "[INFO] " << "Hd_CameraModule_HIK destory success!"; -} - -//回调函数; -//经测试,相机像素格式Mono8、RGB8是可以正常转换的,YUV422还需要优化;RGB8格式比YUV422帧率低;BGR格式会导致异色问题 -void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFrameInfo0, void* pUser0) -{ - Q_UNUSED(pUser0) - int frameNum = 0; - double time_Start = (double)clock(); - n_mutex->lock(); - cv::Mat srcImage = cv::Mat(); - //qDebug() << "[info]" << __FUNCTION__ << " line:" << __LINE__ << "--- start"; - if (pFrameInfo0) - { - //获取的是单通道灰度图 - if (pFrameInfo0->enPixelType == PixelType_Gvsp_Mono8)//获取当前采集到的图像格式 - { - srcImage = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC1, pData0); - } - //获取的是RGB8图 - else if (pFrameInfo0->enPixelType == PixelType_Gvsp_BGR8_Packed) - { - srcImage = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3, pData0); - - //cvtColor(srcImage, srcImage, COLOR_RGB2BGR);//导致异色 - } - else if (IsColor(pFrameInfo0->enPixelType)) //其它格式彩色图 - { - MvGvspPixelType enDstPixelType = PixelType_Gvsp_Undefined; - enDstPixelType = PixelType_Gvsp_BGR8_Packed; - unsigned char* pConvertData = NULL; - pConvertData = (unsigned char*)malloc(pFrameInfo0->nWidth * pFrameInfo0->nHeight * 3); - if (NULL == pConvertData) - { - printf("malloc pConvertData fail!\n"); - } - else - { - unsigned int nConvertDataSize = 0; - nConvertDataSize = pFrameInfo0->nWidth * pFrameInfo0->nHeight * 3; - - // ch:像素格式转换 | en:Convert pixel format - MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 }; - - frameNum = pFrameInfo0->nFrameNum; //ch:帧号 | en:frame number - stConvertParam.nWidth = pFrameInfo0->nWidth; //ch:图像宽 | en:image width - stConvertParam.nHeight = pFrameInfo0->nHeight; //ch:图像高 | en:image height - stConvertParam.pSrcData = pData0; //ch:输入数据缓存 | en:input data buffer - stConvertParam.nSrcDataLen = pFrameInfo0->nFrameLen; //ch:输入数据大小 | en:input data size - stConvertParam.enSrcPixelType = pFrameInfo0->enPixelType; //ch:输入像素格式 | en:input pixel format - stConvertParam.enDstPixelType = enDstPixelType; //ch:输出像素格式 | en:output pixel format - stConvertParam.pDstBuffer = pConvertData; //ch:输出数据缓存 | en:output data buffer - stConvertParam.nDstBufferSize = nConvertDataSize; //ch:输出缓存大小 | en:output buffer size - int nRet = MV_CC_ConvertPixelType(handle, &stConvertParam); - - Mat mysrcImage = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3, stConvertParam.pDstBuffer); - mysrcImage.copyTo(srcImage); - - free(pConvertData); - pConvertData = NULL; - stConvertParam = { 0 }; - } - } - } - if (srcImage.empty()) - { - srcImage = cv::Mat(5, 5, CV_8UC1).setTo(0); - } - if (ifStandard == false) - { - imgIndex++; - if (expourseTimeList.size() > 1 && expourseTimeList[imgIndex % expourseTimeList.size()] != expourseTimeList[(imgIndex - 1) % expourseTimeList.size()]) - SetExposureTime(expourseTimeList[imgIndex % expourseTimeList.size()]); - if (gainList.size() > 1 && gainList[imgIndex % gainList.size()] != gainList[(imgIndex - 1) % gainList.size()]) - SetGain(gainList[imgIndex % gainList.size()]); - } - queuepic.push_back(srcImage); - m_flag = true; - n_mutex->unlock(); - pData0 = { 0 }; - imgCnt++; - double time_End = (double)clock(); - std::cout << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getImg,Time:" << (time_End - time_Start) << "ms" - << "--CameraName:" << Username << " imgIndex:" << imgCnt << "nFrameNum : " << frameNum << std::endl; - qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getImg,Time:" << (time_End - time_Start) << "ms" - << "--CameraName:" << QString::fromStdString(Username) << " imgIndex:" << imgCnt << "nFrameNum : " << frameNum; -} - -Hd_CameraModule_HIK_hard_PCIE::Hd_CameraModule_HIK_hard_PCIE() -{ - //m_thread = new MyThread; - //m_mutex = new QMutex(); -} -//关闭设备 -void CloseDevice() -{ - if (handle == nullptr) - return; - unsigned int nRet = MV_CC_StopGrabbing(handle); - if (nRet == 0) { - MV_CC_CloseDevice(handle); - MV_CC_DestroyHandle(handle); - } - //nRet = MV_CC_CloseDevice(handle); - //nRet = MV_CC_DestroyHandle(handle); -} -Hd_CameraModule_HIK_hard_PCIE::~Hd_CameraModule_HIK_hard_PCIE() -{ - CloseDevice(); - if (n_mutex) - { - delete n_mutex; - n_mutex = nullptr; - } - - qDebug() << "[INFO] " << " delete success!"; -} -//从类中读数据到实例对象 -bool Hd_CameraModule_HIK_hard_PCIE::readData(std::vector& mat, QByteArray& data) -{ - if (queuepic.isEmpty()) - { - //qCritical() << __FUNCTION__ << " line:" <<__LINE__ << " srcImage is null"; - return false; - } - n_mutex->lock(); - cv::Mat img = queuepic.dequeue(); - mat.push_back(img); - queuepic.clear(); - n_mutex->unlock(); - - qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg readData--CameraName:" << QString::fromStdString(Username) << "--imgIndex : " << imgIndex; - return true; -} - -//实例对象把数据写入到类;加载模型后会运行此函数 -bool Hd_CameraModule_HIK_hard_PCIE::writeData(std::vector& mat, QByteArray& data) -{ - Q_UNUSED(mat); - QStringList dataList = QString::fromUtf8(data).split("_"); - //2024.02.18更新,相机对应的读SN信号时,表示新产品进入,设置初始值 - if (data == "rest_newProductIn") - { - //根据实际项目,设置初始值:曝光、增益,ROI区域等 - { - if (expourseTimeList.size() > 0) - SetExposureTime(expourseTimeList[0]); - if (gainList.size() > 0) - SetGain(gainList[0]); - } - if (queuepic.size() > 0) - { - n_mutex->lock(); - queuepic.clear(); - n_mutex->unlock(); - std::cout << "rest_newProductIn , queuePic.size() > 0 ,signal maybe too fast " << Username << std::endl; - qWarning() << __FUNCTION__ << " line: " << __LINE__ << "rest_newProductIn , queuePic.size() > 0 ,signal maybe too fast " << QString::fromStdString(Username); - } - if (ifRunning == true) - { - ifBreak = true; - Sleep(10); - } - imgIndex = 0; - return true; - } - else if (dataList.size() > 1) { - if (dataList[0] == "cameraTriggerSignal") { - imgShouldGetVec.clear(); - imgShouldGetIndex = 0; - for (int i = 1; i < dataList.size(); i++) - imgShouldGetVec.push_back(dataList[i].toInt()); - } - } - else - { - m_flag = false; - expourseTimeList.clear(); - gainList.clear(); - } - //Username= data.toStdString(); - return true; -} -//传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1... -bool Hd_CameraModule_HIK_hard_PCIE::initParas(QByteArray& initData) -{ - QByteArrayList valueList = initData.split('+'); - Username = valueList[0]; - imgIndex = 0; - expourseTimeList.clear(); - gainList.clear(); - if (valueList.size() > 1) - for (int i = 1; i < valueList.size(); i++) - { - QString valuei = byteArrayToUnicode(valueList[i]); - //valuei.prepend(valueList[i]); - if (valuei.contains("expourseTime")) - { - QStringList expourseTimeL = valuei.split('#'); - if (expourseTimeL.size() > 1) - for (int j = 1; j < expourseTimeL.size(); j++) - expourseTimeList.enqueue(expourseTimeL[j].toFloat()); - } - if (valuei.contains("gain")) - { - QStringList gainL = valuei.split('#'); - if (gainL.size() > 1) - for (int j = 1; j < gainL.size(); j++) - gainList.enqueue(gainL[j].toFloat()); - } - - if (valuei.contains("是否为标准通信流程")) - { - if (valuei.contains("true")) - ifStandard = true; - } - if (valuei.contains("取图超时")) - { - QStringList gainL = valuei.split('#'); - if (gainL.size() > 1) - getImageTimeOut = gainL[1].toInt(); - if (getImageTimeOut < 50) - getImageTimeOut = 1000; - } - if (valuei.contains("OffsetX")) - { - QStringList valueL = valuei.split('#'); - if (valueL.size() > 1) - if (valueL[1].toInt() >= 0) - MV_CC_SetIntValue(handle, "OffsetX", valueL[1].toInt()); - } - if (valuei.contains("OffsetY")) - { - QStringList valueL = valuei.split('#'); - if (valueL.size() > 1) - if (valueL[1].toInt() >= 0) - MV_CC_SetIntValue(handle, "OffsetY", valueL[1].toInt()); - } - if (valuei.contains("Width")) - { - QStringList valueL = valuei.split('#'); - if (valueL.size() > 1) - if (valueL[1].toInt() >= 0) - MV_CC_SetIntValue(handle, "Width", valueL[1].toInt()); - } - if (valuei.contains("Height")) - { - QStringList valueL = valuei.split('#'); - if (valueL.size() > 1) - if (valueL[1].toInt() >= 0) - MV_CC_SetIntValue(handle, "Height", valueL[1].toInt()); - } - } - - bool ifOk = connectDevice(); - if (ifOk == true) - { - if (expourseTimeList.size() > 0) - SetExposureTime(expourseTimeList[0]); - if (gainList.size() > 0) - SetGain(gainList[0]); - } - imgIndex = 0; - return ifOk; -} - -bool Hd_CameraModule_HIK_hard_PCIE::run() -{ - - qDebug() << "[INFO] " << " run start" << QString::fromStdString(Username); - bool result = false; - ifRunning = true; - ifBreak = false; - try - { - m_flag = false; - int mytime = 0; - int cnt = 0; - while (true) - { - /* if (moduleStatus == false || mytime++ > getImageTimeOut || ifBreak == true) - { - result = false; - break; - }*/ - - cnt++; - if (queuepic.size() > 0) - { - result = true; - std::cout << "\n gotImg" << std::endl; - break; - } - if (cnt > 2000) { - n_mutex->lock(); - //queuepic.push_back(cv::imread("D://Image_20250809202445856.bmp", -1)); - queuepic.push_back(cv::Mat(200, 200, CV_8UC3, cv::Scalar(0, 255, 0))); //返回空图 - std::cout << "timeout" << std::endl; - n_mutex->unlock(); - return true; - } - QThread::msleep(1); - } - //考虑到误触发、漏触发的图,在这里进行设置。 - //需要设置曝光时 - if (ifStandard == true) - { - imgIndex++; - if (expourseTimeList.size() > 1 && expourseTimeList[imgIndex % expourseTimeList.size()] != expourseTimeList[(imgIndex - 1) % expourseTimeList.size()]) - SetExposureTime(expourseTimeList[imgIndex % expourseTimeList.size()]); - if (gainList.size() > 1 && gainList[imgIndex % gainList.size()] != gainList[(imgIndex - 1) % gainList.size()]) - SetGain(gainList[imgIndex % gainList.size()]); - } - } - catch (QString ev) - { - qDebug() << "[Error] " << " ev:" << ev; - } - qDebug() << "[INFO] " << __LINE__ << " run end"; - return result; -} - -//相机连接状态:正常连接或断开 -bool Hd_CameraModule_HIK_hard_PCIE::checkStatus() -{ - //status = moduleStatus; - return moduleStatus; -} - diff --git a/subModule/Hd_CameraModule_HIK_hard_PCIE.h b/subModule/Hd_CameraModule_HIK_hard_PCIE.h deleted file mode 100644 index 5bf23b2..0000000 --- a/subModule/Hd_CameraModule_HIK_hard_PCIE.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef Hd_CameraModule_HIK_hard_PCIE_H -#define Hd_CameraModule_HIK_hard_PCIE_H -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace cv; -#pragma execution_character_set("utf-8") - -class Hd_CameraModule_HIK_hard_PCIE :public dsModuleBase -{ -public: - Hd_CameraModule_HIK_hard_PCIE(); - virtual ~Hd_CameraModule_HIK_hard_PCIE(); - //从类中读数据到实例对象 - bool readData(std::vector& mat, QByteArray& data); - //实例对象把数据写入到类 - bool writeData(std::vector& mat, QByteArray& data); - bool initParas(QByteArray& initData); - bool run(); - bool checkStatus(); -private: - std::vector imgShouldGetVec; - int imgShouldGetIndex = 0; - //MyThread *m_thread = nullptr; - //QMutex* m_mutex; -}; - -extern "C" -{ -Q_DECL_EXPORT Hd_CameraModule_HIK_hard_PCIE * create(); -Q_DECL_EXPORT void destory(Hd_CameraModule_HIK_hard_PCIE * ptr); -} - -#endif // Hd_CameraModule_HIK_hard_H -//Hd_CameraModule_HIK_hard_PCIE diff --git a/subModule/Hd_CameraModule_HIK_hard_PCIE/CMakeLists.txt b/subModule/Hd_CameraModule_HIK_hard_PCIE/CMakeLists.txt index e86c65b..8412669 100644 --- a/subModule/Hd_CameraModule_HIK_hard_PCIE/CMakeLists.txt +++ b/subModule/Hd_CameraModule_HIK_hard_PCIE/CMakeLists.txt @@ -28,7 +28,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "./*.h" ) diff --git a/subModule/Hd_CameraModule_HIK_hard_PCIE/Hd_CameraModule_HIK_hard_PCIE.cpp b/subModule/Hd_CameraModule_HIK_hard_PCIE/Hd_CameraModule_HIK_hard_PCIE.cpp index 074e3dd..1abe4b2 100644 --- a/subModule/Hd_CameraModule_HIK_hard_PCIE/Hd_CameraModule_HIK_hard_PCIE.cpp +++ b/subModule/Hd_CameraModule_HIK_hard_PCIE/Hd_CameraModule_HIK_hard_PCIE.cpp @@ -158,8 +158,8 @@ bool connectDevice() MV_CC_CreateHandleByGenTL(&handle, m_stDevList.pDeviceInfo[index]); int nRet = MV_CC_OpenDevice(handle); ////触发模式 - MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_LINE0); - MV_CC_SetEnumValue(handle, "TriggerMode", MV_TRIGGER_MODE_ON); + //MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_LINE0); + //MV_CC_SetEnumValue(handle, "TriggerMode", MV_TRIGGER_MODE_ON); // //加载用户集,相机设置应当UserSet1 nRet = MV_CC_SetEnumValueByString(handle, "UserSetSelector", "UserSet1"); if (MV_OK != nRet) @@ -340,8 +340,8 @@ void CloseDevice() return; unsigned int nRet = MV_CC_StopGrabbing(handle); if (nRet == 0) { - MV_CC_CloseDevice(handle); - MV_CC_DestroyHandle(handle); + //MV_CC_CloseDevice(handle); + //MV_CC_DestroyHandle(handle); } //nRet = MV_CC_CloseDevice(handle); //nRet = MV_CC_DestroyHandle(handle); @@ -536,7 +536,7 @@ bool Hd_CameraModule_HIK_hard_PCIE::run() if (cnt > 150) { n_mutex->lock(); //queuepic.push_back(cv::imread("D://Image_20250809202445856.bmp", -1)); - queuepic.push_back(cv::Mat(200, 200, CV_8UC3, cv::Scalar(0, 255, 0))); //返回空图 + queuepic.push_back(cv::Mat(200, 200, CV_8UC1, cv::Scalar(0))); //返回空图 std::cout << "timeout" << std::endl; n_mutex->unlock(); return true; diff --git a/subModule/Hd_CameraModule_HIK_hard_USB/CMakeLists.txt b/subModule/Hd_CameraModule_HIK_hard_USB/CMakeLists.txt index 3f4ea58..a629df5 100644 --- a/subModule/Hd_CameraModule_HIK_hard_USB/CMakeLists.txt +++ b/subModule/Hd_CameraModule_HIK_hard_USB/CMakeLists.txt @@ -28,7 +28,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "./*.h" ) diff --git a/subModule/Hd_CameraModule_HIK_hard_USB/Hd_CameraModule_HIK_hard_USB.cpp b/subModule/Hd_CameraModule_HIK_hard_USB/Hd_CameraModule_HIK_hard_USB.cpp index 8c242aa..1559841 100644 --- a/subModule/Hd_CameraModule_HIK_hard_USB/Hd_CameraModule_HIK_hard_USB.cpp +++ b/subModule/Hd_CameraModule_HIK_hard_USB/Hd_CameraModule_HIK_hard_USB.cpp @@ -36,7 +36,16 @@ QString byteArrayToUnicode(const QByteArray array) { } return text; } - +static MV_CC_DEVICE_INFO_LIST QByteArrayToMV_CC_DeviceInfoList(const QByteArray& byteArray) { + MV_CC_DEVICE_INFO_LIST deviceInfoList; + if (byteArray.size() == sizeof(MV_CC_DEVICE_INFO_LIST)) { + memcpy(&deviceInfoList, byteArray.constData(), sizeof(MV_CC_DEVICE_INFO_LIST)); + } + else { + qDebug() << "Invalid size of QByteArray for MV_CC_DEVICE_INFO_LIST!"; + } + return deviceInfoList; +} #pragma execution_character_set("utf-8") QMutex* n_mutex;// = new QMutex(); @@ -93,9 +102,15 @@ bool IsColor(MvGvspPixelType enType) //搜索所有设备 int SearchDevice() { - memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); - // ch:枚举子网内所有设备 | en:Enumerate all devices within subnet - int nRet = MV_CC_EnumDevices(MV_USB_DEVICE , &m_stDevList); + if (m_stDevList.nDeviceNum == 0) { + memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); + // ch:枚举子网内所有设备 | en:Enumerate all devices within subnet + int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList); + if (MV_OK != nRet) + { + return 0; + } + } for (int i = 0; i < m_stDevList.nDeviceNum; i++) { //SN @@ -109,21 +124,17 @@ int SearchDevice() break; } } - if (MV_OK != nRet) - { - return 0; - } return -1; } -bool connctDevice() +bool connectDevice() { index = -1; SearchDevice(); if (index == -1) { //未匹配到相机 - qDebug() << "[Waring] " << "Hd_CameraModule_HIK_soft not match --CameraName:" << QString::fromStdString(Username); + qDebug() << "[Waring] " << "Hd_CameraModule_HIK_hard_USB not match --CameraName:" << QString::fromStdString(Username); return false; } unsigned char* name = m_stDevList.pDeviceInfo[index]->SpecialInfo.stGigEInfo.chUserDefinedName; @@ -177,9 +188,9 @@ void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser) while (1) { Sleep(100); - if (connctDevice() == true) + if (connectDevice() == true) { - qWarning() << "[Hd_CameraModule_HIK_soft] " << " Hd_CameraModule_HIK_soft create success again! "; + qWarning() << "[Hd_CameraModule_HIK_hard_USB] " << " Hd_CameraModule_HIK_hard_USB create success again! "; moduleStatus = true; break; } @@ -215,20 +226,20 @@ int RGB2BGR(unsigned char* pRgbData, unsigned int nWidth, unsigned int nHeight) } -Hd_CameraModule_HIK_soft* create() +Hd_CameraModule_HIK_hard_USB* create() { - qDebug() << "[INFO] " << "Hd_CameraModule_HIK_soft create success!" ; - return new Hd_CameraModule_HIK_soft; + qDebug() << "[INFO] " << "Hd_CameraModule_HIK_hard_USB create success!" ; + return new Hd_CameraModule_HIK_hard_USB; } -void destory(Hd_CameraModule_HIK_soft * ptr) +void destory(Hd_CameraModule_HIK_hard_USB * ptr) { if(ptr) { delete ptr; ptr = nullptr; } - qDebug() << "[INFO] " << "Hd_CameraModule_HIK_soft destory success!"; + qDebug() << "[INFO] " << "Hd_CameraModule_HIK_hard_USB destory success!"; } //回调函数; //经测试,相机像素格式Mono8、RGB8是可以正常转换的,YUV422还需要优化;RGB8格式比YUV422帧率低;BGR格式会导致异色问题 @@ -339,7 +350,7 @@ void SetGain(float GainValue) MV_CC_SetEnumValue(handle, "GainAuto", 0); MV_CC_SetFloatValue(handle, "Gain", GainValue); } -Hd_CameraModule_HIK_soft::Hd_CameraModule_HIK_soft() +Hd_CameraModule_HIK_hard_USB::Hd_CameraModule_HIK_hard_USB() { n_mutex = new QMutex(); m_thread = new MyThread; @@ -353,7 +364,7 @@ void CloseDevice() handle = nullptr; //此处注释掉的话,软件断开再连接,回调函数不出图 } -Hd_CameraModule_HIK_soft::~Hd_CameraModule_HIK_soft() +Hd_CameraModule_HIK_hard_USB::~Hd_CameraModule_HIK_hard_USB() { m_flag = true; Sleep(10); @@ -374,7 +385,7 @@ Hd_CameraModule_HIK_soft::~Hd_CameraModule_HIK_soft() qDebug() << "[INFO] " << " delete success!"; } //从类中读数据到实例对象 -bool Hd_CameraModule_HIK_soft::readData(std::vector &mat,QByteArray &data) +bool Hd_CameraModule_HIK_hard_USB::readData(std::vector &mat,QByteArray &data) { if (queuepic.isEmpty()) { @@ -392,9 +403,16 @@ bool Hd_CameraModule_HIK_soft::readData(std::vector &mat,QByteArray &da return true; } //实例对象把数据写入到类 -bool Hd_CameraModule_HIK_soft::writeData(std::vector &mat,QByteArray &data) +bool Hd_CameraModule_HIK_hard_USB::writeData(std::vector &mat,QByteArray &data) { //2024.02.18更新,相机对应的读SN信号时,表示新产品进入,设置初始值 + if (data.contains("deviceList")) { + auto result = QByteArrayToMV_CC_DeviceInfoList(data.mid(10)); + if (result.nDeviceNum != 0) { + m_stDevList = result; + return true; + } + } if (data == "rest_newProductIn") { //根据实际项目,设置初始值:曝光、增益,ROI区域等 @@ -476,7 +494,7 @@ bool Hd_CameraModule_HIK_soft::writeData(std::vector &mat,QByteArray &d data.append("TriggerMode_" + ui.comboBox_triggerMode->currentText());*/ - qDebug() << "Hd_CameraModule_HIK_soft::writeData::" << data; + qDebug() << "Hd_CameraModule_HIK_hard_USB::writeData::" << data; m_flag = false; //Username = data.toStdString(); @@ -485,7 +503,7 @@ bool Hd_CameraModule_HIK_soft::writeData(std::vector &mat,QByteArray &d //传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1... -bool Hd_CameraModule_HIK_soft::initParas(QByteArray& initData) +bool Hd_CameraModule_HIK_hard_USB::initParas(QByteArray& initData) { QByteArrayList valueList = initData.split('+'); Username = valueList[0]; @@ -497,7 +515,7 @@ bool Hd_CameraModule_HIK_soft::initParas(QByteArray& initData) bool ifOk = true; if (handle == NULL) - ifOk = connctDevice(); + ifOk = connectDevice(); if (ifOk == false) return false; if (valueList.size() > 1) @@ -618,7 +636,7 @@ bool Hd_CameraModule_HIK_soft::initParas(QByteArray& initData) return ifOk; } -bool Hd_CameraModule_HIK_soft::run() +bool Hd_CameraModule_HIK_hard_USB::run() { if (imgIndex == expourseTimeList.size()) imgIndex = 0; @@ -664,7 +682,7 @@ bool Hd_CameraModule_HIK_soft::run() break; } if (cnt > 150) { - queuepic.push_back(cv::Mat(200, 200, CV_8UC3, cv::Scalar(0, 255, 0))); //返回空图 + queuepic.push_back(cv::Mat(200, 200, CV_8UC1, cv::Scalar(0))); //返回空图 std::cout << "timeout" << std::endl; n_mutex->unlock(); return true; @@ -709,7 +727,7 @@ bool Hd_CameraModule_HIK_soft::run() } //相机连接状态:正常连接或断开 -bool Hd_CameraModule_HIK_soft::checkStatus() +bool Hd_CameraModule_HIK_hard_USB::checkStatus() { //status = moduleStatus; return moduleStatus; diff --git a/subModule/Hd_CameraModule_HIK_hard_USB/Hd_CameraModule_HIK_hard_USB.h b/subModule/Hd_CameraModule_HIK_hard_USB/Hd_CameraModule_HIK_hard_USB.h index 8cec454..cd42309 100644 --- a/subModule/Hd_CameraModule_HIK_hard_USB/Hd_CameraModule_HIK_hard_USB.h +++ b/subModule/Hd_CameraModule_HIK_hard_USB/Hd_CameraModule_HIK_hard_USB.h @@ -1,5 +1,5 @@ -#ifndef Hd_CameraModule_HIK_soft_H -#define Hd_CameraModule_HIK_soft_H +#ifndef Hd_CameraModule_HIK_hard_USB_H +#define Hd_CameraModule_HIK_hard_USB_H #include @@ -22,11 +22,11 @@ using namespace cv; class MyThread; -class Hd_CameraModule_HIK_soft :public dsModuleBase +class Hd_CameraModule_HIK_hard_USB :public dsModuleBase { public: - Hd_CameraModule_HIK_soft(); - virtual ~Hd_CameraModule_HIK_soft(); + Hd_CameraModule_HIK_hard_USB(); + virtual ~Hd_CameraModule_HIK_hard_USB(); //从类中读数据到实例对象 bool readData(std::vector& mat, QByteArray& data); //实例对象把数据写入到类 @@ -52,8 +52,8 @@ signals: extern "C" { -Q_DECL_EXPORT Hd_CameraModule_HIK_soft * create(); -Q_DECL_EXPORT void destory(Hd_CameraModule_HIK_soft * ptr); +Q_DECL_EXPORT Hd_CameraModule_HIK_hard_USB * create(); +Q_DECL_EXPORT void destory(Hd_CameraModule_HIK_hard_USB * ptr); } -#endif // Hd_CameraModule_HIK_soft_H +#endif // Hd_CameraModule_HIK_hard_USB_H diff --git a/subModule/Hd_CameraModule_HIK_soft_GIGE/CMakeLists.txt b/subModule/Hd_CameraModule_HIK_soft_GIGE/CMakeLists.txt index e86c65b..8412669 100644 --- a/subModule/Hd_CameraModule_HIK_soft_GIGE/CMakeLists.txt +++ b/subModule/Hd_CameraModule_HIK_soft_GIGE/CMakeLists.txt @@ -28,7 +28,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "./*.h" ) diff --git a/subModule/Hd_CameraModule_HIK_soft_GIGE/Hd_CameraModule_HIK_soft_GIGE.cpp b/subModule/Hd_CameraModule_HIK_soft_GIGE/Hd_CameraModule_HIK_soft_GIGE.cpp index 32eadfd..9391dbb 100644 --- a/subModule/Hd_CameraModule_HIK_soft_GIGE/Hd_CameraModule_HIK_soft_GIGE.cpp +++ b/subModule/Hd_CameraModule_HIK_soft_GIGE/Hd_CameraModule_HIK_soft_GIGE.cpp @@ -25,6 +25,16 @@ bool ifRunning = false; MV_CC_DEVICE_INFO_LIST m_stDevList; // ch:设备信息列表结构体变量,用来存储设备列表 //MV_GENTL_IF_INFO_LIST m_stIFList; void CloseDevice(); +static MV_CC_DEVICE_INFO_LIST QByteArrayToMV_CC_DeviceInfoList(const QByteArray& byteArray) { + MV_CC_DEVICE_INFO_LIST deviceInfoList; + if (byteArray.size() == sizeof(MV_CC_DEVICE_INFO_LIST)) { + memcpy(&deviceInfoList, byteArray.constData(), sizeof(MV_CC_DEVICE_INFO_LIST)); + } + else { + qDebug() << "Invalid size of QByteArray for MV_CC_DEVICE_INFO_LIST!"; + } + return deviceInfoList; +} QString byteArrayToUnicode(const QByteArray array) { // state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功 @@ -93,9 +103,15 @@ void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFra //搜索所有设备 int SearchDevice() { - memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); - // ch:枚举子网内所有设备 | en:Enumerate all devices within subnet - int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList); + if (m_stDevList.nDeviceNum == 0) { + memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); + // ch:枚举子网内所有设备 | en:Enumerate all devices within subnet + int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList); + if (MV_OK != nRet) + { + return 0; + } + } for (int i = 0; i < m_stDevList.nDeviceNum; i++) { //SN @@ -109,10 +125,6 @@ int SearchDevice() break; } } - if (MV_OK != nRet) - { - return 0; - } return -1; } @@ -246,13 +258,13 @@ void _stdcall ExceptionCB(unsigned int nMesgType, void* pUser) { } -Hd_CameraModule_HIK_hard_PCIE* create() +Hd_CameraModule_HIK_soft_GIGE* create() { qDebug() << "[INFO] " << "Hd_CameraModule_HIK create success!"; - return new Hd_CameraModule_HIK_hard_PCIE; + return new Hd_CameraModule_HIK_soft_GIGE; } -void destory(Hd_CameraModule_HIK_hard_PCIE* ptr) +void destory(Hd_CameraModule_HIK_soft_GIGE* ptr) { if (ptr) { @@ -348,12 +360,12 @@ void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFra << "--CameraName:" << QString::fromStdString(Username) << " imgIndex:" << imgCnt << "nFrameNum : " << frameNum; } -Hd_CameraModule_HIK_hard_PCIE::Hd_CameraModule_HIK_hard_PCIE() +Hd_CameraModule_HIK_soft_GIGE::Hd_CameraModule_HIK_soft_GIGE() { //m_thread = new MyThread; //m_mutex = new QMutex(); } -Hd_CameraModule_HIK_hard_PCIE::~Hd_CameraModule_HIK_hard_PCIE() +Hd_CameraModule_HIK_soft_GIGE::~Hd_CameraModule_HIK_soft_GIGE() { CloseDevice(); if (n_mutex) @@ -365,7 +377,7 @@ Hd_CameraModule_HIK_hard_PCIE::~Hd_CameraModule_HIK_hard_PCIE() qDebug() << "[INFO] " << " delete success!"; } //从类中读数据到实例对象 -bool Hd_CameraModule_HIK_hard_PCIE::readData(std::vector& mat, QByteArray& data) +bool Hd_CameraModule_HIK_soft_GIGE::readData(std::vector& mat, QByteArray& data) { if (queuepic.isEmpty()) { @@ -382,9 +394,16 @@ bool Hd_CameraModule_HIK_hard_PCIE::readData(std::vector& mat, QByteArr } //实例对象把数据写入到类;加载模型后会运行此函数 -bool Hd_CameraModule_HIK_hard_PCIE::writeData(std::vector& mat, QByteArray& data) +bool Hd_CameraModule_HIK_soft_GIGE::writeData(std::vector& mat, QByteArray& data) { Q_UNUSED(mat); + if (data.contains("deviceList")) { + auto result = QByteArrayToMV_CC_DeviceInfoList(data.mid(10)); + if (result.nDeviceNum != 0) { + m_stDevList = result; + return true; + } + } QStringList dataList = QString::fromUtf8(data).split("_"); //2024.02.18更新,相机对应的读SN信号时,表示新产品进入,设置初始值 if (data == "rest_newProductIn") @@ -430,7 +449,7 @@ bool Hd_CameraModule_HIK_hard_PCIE::writeData(std::vector& mat, QByteAr return true; } //传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1... -bool Hd_CameraModule_HIK_hard_PCIE::initParas(QByteArray& initData) +bool Hd_CameraModule_HIK_soft_GIGE::initParas(QByteArray& initData) { QByteArrayList valueList = initData.split('+'); Username = valueList[0]; @@ -512,7 +531,7 @@ bool Hd_CameraModule_HIK_hard_PCIE::initParas(QByteArray& initData) return ifOk; } -bool Hd_CameraModule_HIK_hard_PCIE::run() +bool Hd_CameraModule_HIK_soft_GIGE::run() { //queuepic.clear(); qDebug() << "[INFO] " << " run start" << QString::fromStdString(Username); @@ -543,7 +562,7 @@ bool Hd_CameraModule_HIK_hard_PCIE::run() break; } if (cnt > 120) { - queuepic.push_back(cv::Mat(250, 250, CV_8UC3, cv::Scalar(0, 255, 0))); //返回空图 + queuepic.push_back(cv::Mat(200, 200, CV_8UC1, cv::Scalar(0))); //返回空图 std::cout << "timeout" << std::endl; n_mutex->unlock(); return true; @@ -571,7 +590,7 @@ bool Hd_CameraModule_HIK_hard_PCIE::run() } //相机连接状态:正常连接或断开 -bool Hd_CameraModule_HIK_hard_PCIE::checkStatus() +bool Hd_CameraModule_HIK_soft_GIGE::checkStatus() { //status = moduleStatus; return moduleStatus; diff --git a/subModule/Hd_CameraModule_HIK_soft_GIGE/Hd_CameraModule_HIK_soft_GIGE.h b/subModule/Hd_CameraModule_HIK_soft_GIGE/Hd_CameraModule_HIK_soft_GIGE.h index 5bf23b2..294c838 100644 --- a/subModule/Hd_CameraModule_HIK_soft_GIGE/Hd_CameraModule_HIK_soft_GIGE.h +++ b/subModule/Hd_CameraModule_HIK_soft_GIGE/Hd_CameraModule_HIK_soft_GIGE.h @@ -1,5 +1,5 @@ -#ifndef Hd_CameraModule_HIK_hard_PCIE_H -#define Hd_CameraModule_HIK_hard_PCIE_H +#ifndef Hd_CameraModule_HIK_soft_GIGE_H +#define Hd_CameraModule_HIK_soft_GIGE_H #include #include #include @@ -14,11 +14,11 @@ using namespace cv; #pragma execution_character_set("utf-8") -class Hd_CameraModule_HIK_hard_PCIE :public dsModuleBase +class Hd_CameraModule_HIK_soft_GIGE :public dsModuleBase { public: - Hd_CameraModule_HIK_hard_PCIE(); - virtual ~Hd_CameraModule_HIK_hard_PCIE(); + Hd_CameraModule_HIK_soft_GIGE(); + virtual ~Hd_CameraModule_HIK_soft_GIGE(); //从类中读数据到实例对象 bool readData(std::vector& mat, QByteArray& data); //实例对象把数据写入到类 @@ -35,9 +35,9 @@ private: extern "C" { -Q_DECL_EXPORT Hd_CameraModule_HIK_hard_PCIE * create(); -Q_DECL_EXPORT void destory(Hd_CameraModule_HIK_hard_PCIE * ptr); +Q_DECL_EXPORT Hd_CameraModule_HIK_soft_GIGE * create(); +Q_DECL_EXPORT void destory(Hd_CameraModule_HIK_soft_GIGE * ptr); } #endif // Hd_CameraModule_HIK_hard_H -//Hd_CameraModule_HIK_hard_PCIE +//Hd_CameraModule_HIK_soft_GIGE diff --git a/subModule/Hd_SocketModule_FinsTcp/CMakeLists.txt b/subModule/Hd_SocketModule_FinsTcp/CMakeLists.txt index 13762e7..93c262c 100644 --- a/subModule/Hd_SocketModule_FinsTcp/CMakeLists.txt +++ b/subModule/Hd_SocketModule_FinsTcp/CMakeLists.txt @@ -31,7 +31,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "./*.h" ) diff --git a/subModule/Hd_VirtualCamera/CMakeLists.txt b/subModule/Hd_VirtualCamera/CMakeLists.txt index 0f64ccb..3a82d8e 100644 --- a/subModule/Hd_VirtualCamera/CMakeLists.txt +++ b/subModule/Hd_VirtualCamera/CMakeLists.txt @@ -28,7 +28,7 @@ SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) +SET(CMAKE_AUTOUIC OFF) set(CMAKE_AUTORCC ON) FILE(GLOB HEAD_FILES "./*.h" ) diff --git a/subModule/Hd_VirtualCamera/Hd_VirtualCamera.cpp b/subModule/Hd_VirtualCamera/Hd_VirtualCamera.cpp index e7a4159..2f04a31 100644 --- a/subModule/Hd_VirtualCamera/Hd_VirtualCamera.cpp +++ b/subModule/Hd_VirtualCamera/Hd_VirtualCamera.cpp @@ -77,7 +77,7 @@ bool Hd_VirtualCamera::run()//����� } else { vector mats; - mats.push_back(cv::Mat(20960,3200,CV_8UC3,cv::Scalar(0,255,0))); + mats.push_back(cv::Mat(2096,3200,CV_8UC3,cv::Scalar(0,255,0))); queuePic.enqueue(mats); } n_mutex->unlock();