From da29e77880ad4e85164fe1e09ce8d4ef22237e74 Mon Sep 17 00:00:00 2001 From: rci <15089880081@gmail.com> Date: Sun, 20 Oct 2024 16:49:57 +0800 Subject: [PATCH] tmp backup --- .../CMakeLists.txt | 5 +- .../Hd_AI_algo_hanHou.cpp} | 534 +++++---- .../Hd_AI_algo_hanHou.h} | 25 +- .../base.h | 0 .../CMakeLists.txt | 2 +- .../Hd_AI_algo_jixing1.cpp | 21 +- .../Hd_AI_algo_jixing1.h | 0 .../base.h | 0 .../CMakeLists.txt | 2 +- .../Hd_AI_algo_jixing1.cpp | 21 +- .../Hd_AI_algo_jixing1.h | 0 .../base.h | 0 .../Hd_AI_algo_jixing1.cpp | 1029 ----------------- .../Hd_AI_algo_jixing1.h | 119 -- BaseModules/Hd_AI_algo_jixing_cam4/base.h | 69 -- .../CMakeLists.txt | 2 +- .../Hd_CameraModule_HIK_soft.cpp | 722 ++++++++++++ .../Hd_CameraModule_HIK_soft.h | 59 + .../Hd_CameraModule_HIK_soft_TakeTwo/base.h | 33 + CMakeLists.txt | 2 +- env/Myalgo/dll/Inspection.dll | Bin 106496 -> 0 bytes env/Myalgo/include/Myalgo.h | 110 -- env/Myalgo/lib/Inspection.lib | Bin 2430 -> 0 bytes env/halconAlgo/dll/Inspection.dll | Bin 0 -> 320000 bytes env/halconAlgo/include/algo.h | 272 +++++ env/halconAlgo/lib/Inspection.lib | Bin 0 -> 4302 bytes env/myTools/include/myTools.h | 7 +- 27 files changed, 1471 insertions(+), 1563 deletions(-) rename BaseModules/{Hd_AI_algo_jixing_cam4 => Hd_AI_algo_hanHou_T}/CMakeLists.txt (90%) rename BaseModules/{Hd_AI_algo_jixing_cam4/Hd_AI_algo_jixing1.cpp => Hd_AI_algo_hanHou_T/Hd_AI_algo_hanHou.cpp} (65%) rename BaseModules/{Hd_AI_algo_jixing_cam4/Hd_AI_algo_jixing1.h => Hd_AI_algo_hanHou_T/Hd_AI_algo_hanHou.h} (85%) rename BaseModules/{Hd_AI_algo_jixing_cam1 => Hd_AI_algo_hanHou_T}/base.h (100%) rename BaseModules/{Hd_AI_algo_jixing_cam3 => Hd_AI_algo_jixing_L}/CMakeLists.txt (96%) rename BaseModules/{Hd_AI_algo_jixing_cam1 => Hd_AI_algo_jixing_L}/Hd_AI_algo_jixing1.cpp (98%) rename BaseModules/{Hd_AI_algo_jixing_cam1 => Hd_AI_algo_jixing_L}/Hd_AI_algo_jixing1.h (100%) rename BaseModules/{Hd_AI_algo_jixing_cam2 => Hd_AI_algo_jixing_L}/base.h (100%) rename BaseModules/{Hd_AI_algo_jixing_cam2 => Hd_AI_algo_jixing_T}/CMakeLists.txt (96%) rename BaseModules/{Hd_AI_algo_jixing_cam2 => Hd_AI_algo_jixing_T}/Hd_AI_algo_jixing1.cpp (98%) rename BaseModules/{Hd_AI_algo_jixing_cam2 => Hd_AI_algo_jixing_T}/Hd_AI_algo_jixing1.h (100%) rename BaseModules/{Hd_AI_algo_jixing_cam3 => Hd_AI_algo_jixing_T}/base.h (100%) delete mode 100644 BaseModules/Hd_AI_algo_jixing_cam3/Hd_AI_algo_jixing1.cpp delete mode 100644 BaseModules/Hd_AI_algo_jixing_cam3/Hd_AI_algo_jixing1.h delete mode 100644 BaseModules/Hd_AI_algo_jixing_cam4/base.h rename BaseModules/{Hd_AI_algo_jixing_cam1 => Hd_CameraModule_HIK_soft_TakeTwo}/CMakeLists.txt (96%) create mode 100644 BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/Hd_CameraModule_HIK_soft.cpp create mode 100644 BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/Hd_CameraModule_HIK_soft.h create mode 100644 BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/base.h delete mode 100644 env/Myalgo/dll/Inspection.dll delete mode 100644 env/Myalgo/include/Myalgo.h delete mode 100644 env/Myalgo/lib/Inspection.lib create mode 100644 env/halconAlgo/dll/Inspection.dll create mode 100644 env/halconAlgo/include/algo.h create mode 100644 env/halconAlgo/lib/Inspection.lib diff --git a/BaseModules/Hd_AI_algo_jixing_cam4/CMakeLists.txt b/BaseModules/Hd_AI_algo_hanHou_T/CMakeLists.txt similarity index 90% rename from BaseModules/Hd_AI_algo_jixing_cam4/CMakeLists.txt rename to BaseModules/Hd_AI_algo_hanHou_T/CMakeLists.txt index 70505c8..be2265d 100644 --- a/BaseModules/Hd_AI_algo_jixing_cam4/CMakeLists.txt +++ b/BaseModules/Hd_AI_algo_hanHou_T/CMakeLists.txt @@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME) string(TIMESTAMP RUN_TIME) message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME}) -set(DLL_NAMES "opencv" "halcon" "Myalgo" "myTools" ) +set(DLL_NAMES "opencv" "halcon" "halconAlgo" "myTools" "handdleAI") foreach(child ${DLL_NAMES}) LIST(APPEND ENV_INCLUDE ${${child}_include}) LIST(APPEND ENV_LIB ${${child}_lib}) @@ -39,7 +39,7 @@ 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) - +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED) add_library(${CURRENT_FOLDER} SHARED ${HEAD_FILES} ${SRC_FILES} @@ -58,6 +58,7 @@ set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C target_link_libraries(${CURRENT_FOLDER} PRIVATE ${ENV_TARGET} Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Network ) diff --git a/BaseModules/Hd_AI_algo_jixing_cam4/Hd_AI_algo_jixing1.cpp b/BaseModules/Hd_AI_algo_hanHou_T/Hd_AI_algo_hanHou.cpp similarity index 65% rename from BaseModules/Hd_AI_algo_jixing_cam4/Hd_AI_algo_jixing1.cpp rename to BaseModules/Hd_AI_algo_hanHou_T/Hd_AI_algo_hanHou.cpp index 7f85c24..5564798 100644 --- a/BaseModules/Hd_AI_algo_jixing_cam4/Hd_AI_algo_jixing1.cpp +++ b/BaseModules/Hd_AI_algo_hanHou_T/Hd_AI_algo_hanHou.cpp @@ -1,94 +1,151 @@ -#include "Hd_AI_algo_jixing1.h" +#include "Hd_AI_algo_hanHou.h" #include -#include + #include #include #include -#include "Myalgo.h" -#include -#include +#include +#include +#include using namespace cv; - -//原图ä¿�存文件夹 -QString oriImgSaveDir = "D:/601线/超声波预焊01机/æž�性检测CCD/原图/"; +QByteArray silieResultText = "0"; +QByteArray fanzheResultText = "0"; +QByteArray jiErWidth = "0"; +QByteArray jiErHeight = "0"; +QByteArray hanYin1 = "0"; +QByteArray hanYin2 = "0"; +//原图ä¿�存文件夹s + QString oriImgSaveDir = "D:/601线/预焊CCD/焊å�Žæ£€æµ‹CCD/原图/"; //原图class图ä¿�存文件夹 -QString classImgSaveDir = "D:/601线/超声波预焊01机/æž�性检测CCD/class图/"; + QString classImgSaveDir = "D:/601线/预焊CCD/焊å�Žæ£€æµ‹CCD/class图/"; //结果ä¿�存文件夹 -QString resImgSaveDir = "D:\\601线\\超声波超声波预焊01机\\æž�性检测CCD\\结果图\\"; + QString resImgSaveDir = "D:/601线/预焊CCD/焊å�Žæ£€æµ‹CCD/结果图/"; //切图的classçš„width,根æ�®é¡¹ç›®å®žé™…设置ï¼� -int sizeW = 150; + int sizeW = 150; //切图的classçš„height,根æ�®é¡¹ç›®å®žé™…设置ï¼� -int sizeH = 150; + int sizeH = 150; //切图的classçš„width,根æ�®é¡¹ç›®å®žé™…设置ï¼�0为黑,255为白; -int fillColour = 0; -int algoResult; + int fillColour = 0; + //检测线程é”� -QMutex* detect_mutex; + QMutex* detect_mutex; //ä¿�存线程é”� -QMutex* saveStruct_mutex; + QMutex* saveStruct_mutex; //检测线程è¿�行标志 -bool ifdetectThread = false; + bool ifdetectThread = false; -QString cameraKey_index = ""; + QString cameraKey_index = ""; -//åˆ�始化å�‚数列表 -QByteArrayList initValueList; -static void createDirectoryIfNotExists(const QString& path) { - QDir dir; - dir.mkpath(path); -} -static std::string getCurrentTime() { + //åˆ�始化å�‚数列表 + QByteArrayList initValueList; + static void createDirectoryIfNotExists(const QString& path) { + QDir dir; + dir.mkpath(path); + } + static std::string getCurrentTime() { - // 获å�–当å‰�时间点 - auto now = std::chrono::system_clock::now(); - - // 转æ�¢ä¸ºå­—符串 - auto currentTime = std::chrono::system_clock::to_time_t(now); - auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 100; - std::tm* localTime = std::localtime(¤tTime); - std::stringstream ss; - ss << std::put_time(localTime, "%H-%M-%S") << "-" << std::setfill('0') << std::setw(2) << ms.count(); - return ss.str(); -} -static QString getCurrentDate() -{ - QDateTime currentDateTime = QDateTime::currentDateTime(); - return currentDateTime.toString("yyyy-MM-dd"); -} -static QString getCurrentHour() -{ - QDateTime currentDateTime = QDateTime::currentDateTime(); - return QString::number(currentDateTime.time().hour()) + "H"; -} -inline std::string utf8_to_gbk(const std::string& str) -{ - std::wstring_convert> conv; - std::wstring tmp_wstr = conv.from_bytes(str); - //GBK locale name in windows - const char* GBK_LOCALE_NAME = ".936"; - std::wstring_convert> convert(new std::codecvt_byname(GBK_LOCALE_NAME)); - return convert.to_bytes(tmp_wstr); -} - -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; -} + // 获å�–当å‰�时间点 + auto now = std::chrono::system_clock::now(); + // 转æ�¢ä¸ºå­—符串 + auto currentTime = std::chrono::system_clock::to_time_t(now); + auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 100; + std::tm* localTime = std::localtime(¤tTime); + std::stringstream ss; + ss << std::put_time(localTime, "%H-%M-%S") << "-" << std::setfill('0') << std::setw(2) << ms.count(); + return ss.str(); + } + static QString getCurrentDate() + { + QDateTime currentDateTime = QDateTime::currentDateTime(); + return currentDateTime.toString("yyyy-MM-dd"); + } + static QString getCurrentHour() + { + QDateTime currentDateTime = QDateTime::currentDateTime(); + return QString::number(currentDateTime.time().hour())+"H"; + } + 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; + } + static cv::Rect findMaxAreaContour(cv::Mat src) + { + int maxIndex = 0, maxArea = 0; + std::vector>contours; + cv::findContours(src, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); + if (contours.size() == 0) + return cv::Rect(0, 0, 0, 0); + for (int i = 0; i < contours.size(); i++) + { + int Area = cv::contourArea(contours[i]); + if (Area > maxArea) + { + maxArea = Area; + maxIndex = i; + } + } + if (contours.size() != 0) + return cv::boundingRect(contours[maxIndex]); + return cv::Rect(0, 0, 0, 0); + } + inline std::string utf8_to_gbk(const std::string& str) + { + std::wstring_convert> conv; + std::wstring tmp_wstr = conv.from_bytes(str); + //GBK locale name in windows + const char* GBK_LOCALE_NAME = ".936"; + std::wstring_convert> convert(new std::codecvt_byname(GBK_LOCALE_NAME)); + return convert.to_bytes(tmp_wstr); + } + void getAllFiles(std::string path, std::vector& files, std::string format) + { + intptr_t hFile = 0;//文件å�¥æŸ„ + struct _finddata_t fileinfo;//文件信æ�¯ + std::string p; + if ((hFile = _findfirst(p.assign(path).append("\\*" + format).c_str(), &fileinfo)) != -1) //文件存在 + { + do + { + if ((fileinfo.attrib & _A_SUBDIR))//判断是å�¦ä¸ºæ–‡ä»¶å¤¹ + { + if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)//文件夹å��中ä¸�å�«"."å’Œ".." + { + files.push_back(p.assign(path).append("\\").append(fileinfo.name)); //ä¿�存文件夹å�� + getAllFiles(p.assign(path).append("\\").append(fileinfo.name), files, format); //递归é��历文件夹 + } + } + else + { + files.push_back(p.assign(path).append("\\").append(fileinfo.name));//如果ä¸�是文件夹,储存文件å�� + } + } while (_findnext(hFile, &fileinfo) == 0); + _findclose(hFile); + } + } + QString getOriSaveFromat() + { + return oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + + "ORI_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".bmp"; + } + QString getResSaveFromat() + { + return resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + + "RES_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".png"; + } // 缺陷信æ�¯ç»“构体 typedef struct { QString defectName = "";//缺陷å��ç§° @@ -223,6 +280,8 @@ void GetStringSize(HDC hdc, const char* str, int* w, int* h) if (h != 0) *h = size.cy; } //在图åƒ�写中文,英文也å�¯ä»¥å†™ + + void putTextZH(cv::Mat& dst, const char* str, cv::Point org, cv::Scalar color, int fontsize, const char* fn = "Arial", bool italic = false, bool underline = false) { @@ -388,7 +447,7 @@ void drawDefects(cv::Mat& sourceMat, QQueue defectInfoList) //判断文件夹是å�¦å­˜åœ¨ï¼Œä¸�存在则创建 -void Hd_AI_algo_jixing1::isDirExist(QString fullDirName) +void Hd_AI_algo_hanHou::isDirExist(QString fullDirName) { QDir* photo = new QDir; bool exist = photo->exists(fullDirName); @@ -406,28 +465,27 @@ void Hd_AI_algo_jixing1::isDirExist(QString fullDirName) photo = nullptr; } -Hd_AI_algo_jixing1* create() +Hd_AI_algo_hanHou* create() { - qDebug() << "[INFO] " << " Hd_AI_algo_jixing1 create success!"; - return new Hd_AI_algo_jixing1; + qDebug() << "[INFO] " << " Hd_AI_algo_hanHou create success!" ; + return new Hd_AI_algo_hanHou; } -void destory(Hd_AI_algo_jixing1* ptr) +void destory(Hd_AI_algo_hanHou* ptr) { - qDebug() << "[INFO] " << "Hd_AI_algo_jixing1 destory success!"; - if (ptr) + qDebug() << "[INFO] " << "Hd_AI_algo_hanHou destory success!"; + if(ptr) { delete ptr; ptr = nullptr; } } -Hd_AI_algo_jixing1::Hd_AI_algo_jixing1() +Hd_AI_algo_hanHou::Hd_AI_algo_hanHou() { detect_mutex = new QMutex; saveStruct_mutex = new QMutex; ifdetectThread = false; - for (int i = 0; i < 4; i++) { QString DirPath = "E:/testImg/source" + QString::number(i); @@ -447,7 +505,7 @@ Hd_AI_algo_jixing1::Hd_AI_algo_jixing1() } } -Hd_AI_algo_jixing1::~Hd_AI_algo_jixing1() +Hd_AI_algo_hanHou::~Hd_AI_algo_hanHou() { ifdetectThread = false; Sleep(10); @@ -461,29 +519,35 @@ Hd_AI_algo_jixing1::~Hd_AI_algo_jixing1() delete saveStruct_mutex; saveStruct_mutex = nullptr; } + handdleAI::DestroySegObj(seg_hanHouSiLie); + handdleAI::DestroySegObj(seg_hanHouFanZhe); /*DestroySegObj(pSeg); DestroyClsObj(pCls);*/ } //从类中读数æ�®åˆ°å®žä¾‹å¯¹è±¡ -bool Hd_AI_algo_jixing1::readData(std::vector& vec_mat, QByteArray& data) +bool Hd_AI_algo_hanHou::readData(std::vector&vec_mat,QByteArray &data) { detect_mutex->lock(); //qDebug() << __FUNCTION__ << " line:" <<__LINE__ << " data len:" << data.length(); - if (resMat.size() > 0) + if (resMat.size()>0) { vec_mat.push_back(resMat[0]); resMat.clear(); } else { - if (HikMat.size() > 0) + if(HikMat.size()>0) vec_mat.push_back(HikMat[0]); //qDebug() << __FUNCTION__ << " line:" << __LINE__ << " resMat.data err:"; } //if (allNum++ % 2 == 0) // data = "2*3*2";// resByte.dequeue(); //else - data = QByteArray::number(algoResult) + "&" + QByteArray::number(algoResult - 1) + "+" + QByteArray::number(algoResult); + data = "1*&" + fanzheResultText + "&" + silieResultText + + "+" + fanzheResultText + "+" + silieResultText + + "+" + jiErWidth + "+" + jiErHeight + + "+" + hanYin1 + "+" + hanYin2 + ;//1OK,2NG resByte.clear(); ////之å�Žæ ¹æ�®ç»“果类修改 //if(resIfNg == true) @@ -491,41 +555,40 @@ bool Hd_AI_algo_jixing1::readData(std::vector& vec_mat, QByteArray& dat //else data = "OK"; detect_mutex->unlock(); /*if(cameraKey_index.contains('_')) - qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName:" + qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName:" << cameraKey_index.split("_")[0] << " imgIndex:" << cameraKey_index.split("_")[1]; else qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName imgIndex:" << cameraKey_index;*/ return true; } //从类中读数æ�®åˆ°å®žä¾‹å¯¹è±¡ -bool Hd_AI_algo_jixing1::encodeResultValue(QVector append_value, QByteArray& resultByte) +bool Hd_AI_algo_hanHou::encodeResultValue(QVector append_value,QByteArray &resultByte) { try { std::string sendMsg; - for (int i = 0; i < append_value.size(); i++) + for(int i = 0 ; i < append_value.size();i++) { std::string value = append_value.at(1); //type int type = 3; std::string m_type; - m_type.insert(0, 4, '1'); - memcpy((void*)m_type.c_str(), (void*)&type, 4); + m_type.insert(0,4,'1'); + memcpy ( (void*)m_type.c_str(),(void*)&type,4 ); sendMsg.append(m_type); //len int len = value.length(); std::string m_len; - m_len.insert(0, 4, '1'); - memcpy((void*)m_len.c_str(), (void*)&len, 4); + m_len.insert(0,4,'1'); + memcpy ( (void*)m_len.c_str(),(void*)&len,4 ); sendMsg.append(m_len); //data x sendMsg.append(value); } resultByte = QByteArray::fromStdString(sendMsg); - } - catch (QString ev) + } catch (QString ev) { qCritical() << "[Error] " << " ev:" << ev; return false; @@ -533,13 +596,13 @@ bool Hd_AI_algo_jixing1::encodeResultValue(QVector append_value, QB return true; } -int myallNum[4] = { 0 }; +int myallNum[4] = {0}; QMap lastImgMap; //接收数æ�® -bool Hd_AI_algo_jixing1::writeData(std::vector& vec_mat, QByteArray& data) +bool Hd_AI_algo_hanHou::writeData(std::vector& vec_mat, QByteArray &data) { //qDebug() << __FUNCTION__ << "line:"<< __LINE__ << " data len" << data.length() ; - if (vec_mat.empty()) + if(vec_mat.empty()) { qCritical() << "[Error] " << " vec_mat is null !"; return false; @@ -547,7 +610,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector& vec_mat, QByteArray& da detect_mutex->lock(); HikMat.clear(); for (int i = 0; i < vec_mat.size(); i++) - HikMat.enqueue(vec_mat[i]); + HikMat.enqueue(vec_mat[i]); QByteArray source_savePath; QByteArray sData = data; @@ -558,7 +621,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector& vec_mat, QByteArray& da cameraKey_index = splitDataList[2]; QByteArray saveDir = splitDataList[0] + "/" + splitDataList[1] + "/"; isDirExist(byteArrayToUnicode(saveDir)); //ä¸�存在,创建 - QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz"); + QString sdataTime= QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz"); source_savePath = splitDataList[0] + "/" + splitDataList[1] + "/" + sdataTime.toLocal8Bit() + "-" + splitDataList[2] + "-" + splitDataList[3];// +".bmp"; } //int index = -1; @@ -584,11 +647,8 @@ bool Hd_AI_algo_jixing1::writeData(std::vector& vec_mat, QByteArray& da }*/ - - createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); - addImgToSaveStruct(HikMat[0], "0", oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" - "ORI" + cameraKey_index + QString::fromStdString(getCurrentTime()) + ".bmp");//ä¿�存原图 + addImgToSaveStruct(HikMat[0], "0",getOriSaveFromat());//ä¿�存原图 //if (!source_savePath.isEmpty()) //{ // //std::cout << "try savePath::" << savePath.toStdString() << std::endl; @@ -639,7 +699,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector& vec_mat, QByteArray& da /*saveKey.enqueue("datalist[0]"); Dir2D.enqueue("datalist[1]"); - QStringList SN_dataTime; + QStringList SN_dataTime; SN_dataTime = datalist[3].split('_'); DateTime1 = "SN_dataTime[1]"; SN.enqueue("SN_dataTime[0]");*/ @@ -656,7 +716,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector& vec_mat, QByteArray& da //ä¼ å…¥initParas函数,格å¼�为:相机key+å�‚æ•°å��1#å�‚数值1#å�‚数值2+å�‚æ•°å��2#å�‚数值1... //åˆ�始化 -bool Hd_AI_algo_jixing1::initParas(QByteArray& byte) +bool Hd_AI_algo_hanHou::initParas(QByteArray& byte) { initValueList = byte.split('+'); QStringList valueiList; @@ -681,13 +741,13 @@ bool Hd_AI_algo_jixing1::initParas(QByteArray& byte) valueiList.append(valuei); } - /*pSeg = CreateSegObjS(pSeg_modulePath, 128, gpuId); pCls = CreateClsObjV3(pCls_modulePath, gpuId, 1);*/ //StationNo = vec_ret.at(0).toInt(); - + seg_hanHouSiLie = handdleAI::CreateSegObjS("./model/seg-yuHanhanHouSiLie.BHD"); + seg_hanHouFanZhe = handdleAI::CreateSegObjS("./model/seg-yuHanhanFanZhe.BHD"); //InitThreads(StationNo, img2D); //InitModels(StationNo, img2D); @@ -696,9 +756,9 @@ bool Hd_AI_algo_jixing1::initParas(QByteArray& byte) //线程检测:结果类完æˆ�时,使用 //ifThreadRunDetect = true; - //QFuture future1 = QtConcurrent::run(this, &Hd_AI_algo_jixing1::detectThread); + //QFuture future1 = QtConcurrent::run(this, &Hd_AI_algo_hanHou::detectThread); //è¿�行存图线程 - QFuture future2 = QtConcurrent::run(this, &Hd_AI_algo_jixing1::saveImgThread); + QFuture future2 = QtConcurrent::run(this, &Hd_AI_algo_hanHou::saveImgThread); //detectThread(); //原图总文件夹 @@ -708,48 +768,149 @@ bool Hd_AI_algo_jixing1::initParas(QByteArray& byte) //结果图总文件夹 isDirExist(resImgSaveDir); - //qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ; return true; } // è§£ç � -bool Hd_AI_algo_jixing1::decodeAiValue(QByteArray byte, QVector& vec_ret) +bool Hd_AI_algo_hanHou::decodeAiValue(QByteArray byte,QVector &vec_ret) { - if (byte.isEmpty()) + if(byte.isEmpty()) { qCritical() << "[Error] " << " byte is null!"; return false; } /*******************************************/ - byte.remove(0, 8); - QByteArray mm_data = byte.mid(0, 4); - memcpy((void*)¶mNum, (void*)mm_data.data(), 4); + byte.remove(0,8); + QByteArray mm_data = byte.mid(0,4); + memcpy((void*)¶mNum,(void*)mm_data.data(), 4); qDebug() << "[INFO] " << " paramNum:" << paramNum; - byte.remove(0, 4); + byte.remove(0,4); /*******************************************/ while (!byte.isEmpty()) { int type = 0; - QByteArray m_type = byte.mid(0, 4); - memcpy((void*)&type, (void*)m_type.data(), 4); - byte.remove(0, 4); + QByteArray m_type = byte.mid(0,4); + memcpy((void*)&type,(void*)m_type.data(), 4); + byte.remove(0,4); int len = 0; - QByteArray m_len = byte.mid(0, 4); - memcpy((void*)&len, (void*)m_len.data(), 4); - byte.remove(0, 4); + QByteArray m_len = byte.mid(0,4); + memcpy((void*)&len,(void*)m_len.data(), 4); + byte.remove(0,4); - QByteArray mm_data = byte.mid(0, len); + QByteArray mm_data = byte.mid(0,len); vec_ret.append(mm_data); - byte.remove(0, len); + byte.remove(0,len); } return true; } +void halconAlgoProcess(cv::Mat& img,cv::Mat &Paint)//算法先画 +{ + HObject ho_Image; + HTuple hv_Pix(0.0303); + HTuple hv_out_line; + HTuple hv_out_Soldering_line; + HTuple hv_distance; + HTuple hv_Make; + MatToHObject(img, &ho_Image); + cs_628_jier_T(ho_Image,hv_Pix,&hv_out_line,&hv_out_Soldering_line, + &hv_distance, & hv_Make); + if (hv_Make.D() == 1) + { + cv::line(Paint, + cv::Point(hv_out_line[1].D() / 2, hv_out_line[0].D() / 2), + cv::Point(hv_out_line[3].D() / 2, hv_out_line[2].D() / 2), + cv::Scalar(0, 255, 0), 5); + cv::line(Paint, + cv::Point(hv_out_line[5].D() / 2, hv_out_line[4].D() / 2), + cv::Point(hv_out_line[7].D() / 2, hv_out_line[6].D() / 2), + cv::Scalar(0, 255, 0), 5); + + cv::line(Paint, + cv::Point(hv_out_line[9].D() / 2, hv_out_line[8].D() / 2), + cv::Point(hv_out_line[11].D() / 2, hv_out_line[10].D() / 2), + cv::Scalar(0, 255, 0), 5); + + cv::line(Paint, + cv::Point(hv_out_line[13].D() / 2, hv_out_line[12].D() / 2), + cv::Point(hv_out_line[15].D() / 2, hv_out_line[14].D() / 2), + cv::Scalar(0, 255, 0), 5); + + cv::line(Paint, + cv::Point(hv_out_Soldering_line[1].D() / 2, hv_out_Soldering_line[0].D() / 2), + cv::Point(hv_out_Soldering_line[3].D() / 2, hv_out_Soldering_line[2].D() / 2), + cv::Scalar(0, 255, 0), 5); + + cv::line(Paint, + cv::Point(hv_out_Soldering_line[5].D() / 2, hv_out_Soldering_line[4].D() / 2), + cv::Point(hv_out_Soldering_line[7].D() / 2, hv_out_Soldering_line[6].D() / 2), + cv::Scalar(0, 255, 0), 5); + + double height = hv_distance[0].D(); + double weight = hv_distance[1].D(); + double upEdge = hv_distance[2].D(); + double leftEdge = hv_distance[3].D(); + + jiErWidth = QByteArray::number(weight); + jiErHeight = QByteArray::number(height); + hanYin1 = QByteArray::number(upEdge); + hanYin2 = QByteArray::number(leftEdge); + + putTextHusky(Paint, utf8_to_gbk("æž�耳高" + std::to_string(height)).c_str(), + cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); + putTextHusky(Paint, utf8_to_gbk("æž�耳宽" + std::to_string(weight)).c_str(), + cv::Point(0, 250), cv::Scalar(0, 255, 0), 300); + putTextHusky(Paint, utf8_to_gbk("上间è·�" + std::to_string(upEdge)).c_str(), + cv::Point(0, 500), cv::Scalar(0, 255, 0), 300); + putTextHusky(Paint, utf8_to_gbk("下间è·�" + std::to_string(leftEdge)).c_str(), + cv::Point(0, 750), cv::Scalar(0, 255, 0), 300); + } + else + putTextHusky(Paint, utf8_to_gbk("算法异常1").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); +} +void siLieProcess(cv::Mat& segRes, cv::Mat& Paint,bool& result) +{ + std::vector> contours; + cv::findContours(segRes, contours, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); + int cnt = 0; + for (auto r : contours) + { + cv::Rect originRect = cv::boundingRect(r); + if (originRect.width < 50 || originRect.height < 50) + continue; + cv::Rect rect = originRect; + //cv::Mat clsImg = cutImg2Cls(rect, img); + //int clsRes = clsPtr->Evaluate(clsImg); + cv::Scalar color = cv::Scalar(0, 0, 255, 30); + cv::rectangle(Paint, originRect, color, 4); + putTextHusky(Paint, utf8_to_gbk("撕裂").c_str(), cv::Point(rect.x - rect.width / 2, rect.y - rect.height / 2), cv::Scalar(0, 255, 0), 100); + result = false; + } +} +void fanZheProcess(cv::Mat& segRes, cv::Mat& Paint, bool& result) +{ + std::vector> contours; + cv::findContours(segRes, contours, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); + int cnt = 0; + for (auto r : contours) + { + cv::Rect originRect = cv::boundingRect(r); + if (originRect.width < 100 || originRect.height < 50) + continue; + cv::Rect rect = originRect; + //cv::Mat clsImg = cutImg2Cls(rect, img); + //int clsRes = clsPtr->Evaluate(clsImg); + cv::Scalar color = cv::Scalar(0, 0, 255, 30); + cv::rectangle(Paint, originRect, color, 4); + putTextHusky(Paint, utf8_to_gbk("翻折").c_str(), cv::Point(rect.x- rect.width/2, rect.y-rect.height/2), cv::Scalar(0, 255, 0), 100); + result = false; + } +} //---------检测æµ�程,根æ�®å®žé™…项目修改--------- -bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime) +bool Hd_AI_algo_hanHou::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime) { try { @@ -779,63 +940,40 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi // csvName.write(lines[i].toStdString().c_str()); // csvName.close(); //} - + //sourceImg = cv::imread("D:\\mySN15-46-33-86.bmp",-1); + sourceImg = cv::imread("D:/1/Image_20241017204025590.bmp", -1); + cv::Mat Paint; + sourceImg.copyTo(Paint); + if(Paint.channels() == 1) + cvtColor(Paint, Paint, COLOR_GRAY2BGR); QQueue defectInfoList; - //æž�性检测 - HObject ho_Image; - HTuple hv_out_Value; - HTuple hv_Make; - //cv::imwrite("C://1.bmp", sourceImg); - MatToHObject(sourceImg, &ho_Image); - _628_1_Polarity_detection(ho_Image, &hv_out_Value, &hv_Make); - //相机1 OK为é“� NG为铜s - if (hv_Make.D() != -1) - { - if (hv_out_Value.D() == 1)//é“� - { - putTextHusky(sourceImg, utf8_to_gbk("é“�æž�").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); - //cv::putText(sourceImg, "Aluminium", cv::Point(0, 240), 2, 10, cv::Scalar(0, 255, 0), 10); - cv::putText(sourceImg, "OK", cv::Point(0, 550), 2, 10, cv::Scalar(0, 255, 0), 10); - algoResult = 1; - //Result = 1 ? 2; - //Result = 1; - } - else if (hv_out_Value.D() == 2)//铜 - { - putTextHusky(sourceImg, utf8_to_gbk("铜æž�").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); - //cv::putText(sourceImg, "Copper", cv::Point(0, 240), 2, 10, cv::Scalar(0, 255, 0), 10); - cv::putText(sourceImg, "NG", cv::Point(0, 550), 2, 10, cv::Scalar(0, 0, 255), 10); - algoResult = 1; - } - else - { - putTextHusky(sourceImg, utf8_to_gbk("算法异常1").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); - // cv::putText(sourceImg, "Algo error1", cv::Point(0, 240), 2, 10, cv::Scalar(0, 0, 255), 10); - //Result = 2; - } - } - else - { - putTextHusky(sourceImg, utf8_to_gbk("算法异常1").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); - // cv::putText(sourceImg, "Algo error2", cv::Point(0, 240), 2, 10, cv::Scalar(0, 0, 255), 10); - } - - ho_Image.Clear(); - hv_out_Value.Clear(); - hv_Make.Clear(); - + detect_mutex->lock(); - //resMat = sourceImg.clone(); - //sourceImg.copyTo(resMat); - resMat.push_back(sourceImg); - //结果图画框和缺陷,在resMat上绘制 - if (resMat.size() > 0) - drawDefects(resMat[0], defectInfoList); + + auto futrue = std::async(std::launch::async, halconAlgoProcess, sourceImg, Paint);//异步执行 + cv::Mat segProcess; + cv::resize(sourceImg, segProcess, cv::Size(), 0.5, 0.5); + //撕裂检测 + cv::Mat siLieSegRes = ~seg_hanHouSiLie->Evaluate(segProcess);//撕裂 + cv::Mat fanZheSegRes = ~seg_hanHouFanZhe->Evaluate(segProcess);//翻折 + futrue.wait();//等待halcon算法完æˆ� + bool silieOk = true, fanZheOk = true; + siLieProcess(siLieSegRes, Paint, silieOk); + fanZheProcess(fanZheSegRes, Paint, fanZheOk); - //QByteArray,根æ�®å®žé™…项目进行解æž� - //å�‚æ•°,例:返回结果图;相机关键字(SN或userID)+ä¿�存路径+缺陷信æ�¯åˆ—表(缺陷å��称,缺陷ä½�ç½®int(x,y,w,h),画框颜色Scalar(a,b,c),缺陷é�¢ç§¯double) + if (silieOk == true)//OK + putTextHusky(Paint, utf8_to_gbk("撕裂OK").c_str(), cv::Point(4800, 50), cv::Scalar(0, 255, 0), 500); + else + putTextHusky(Paint, utf8_to_gbk("撕裂NG").c_str(), cv::Point(4800, 50), cv::Scalar(0, 0, 255), 500); + + if (fanZheOk == true)//OK + putTextHusky(Paint, utf8_to_gbk("翻折OK").c_str(), cv::Point(4800, 300), cv::Scalar(0, 255, 0), 500); + else + putTextHusky(Paint, utf8_to_gbk("翻折NG").c_str(), cv::Point(4800, 300), cv::Scalar(0, 0, 255), 500); + + resMat.push_back(Paint); QJsonArray detaillists; //QByteArrayList resQbyte; for (int i = 0; i < defectInfoList.size(); i++) @@ -857,10 +995,10 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi detailObj.insert("defectRect.width", QString::number(mdefect.defectRect.width)); detailObj.insert("defectRect.height", QString::number(mdefect.defectRect.height)); detailObj.insert("defectScalar0", QString::number(mdefect.defectScalar[0])); - detailObj.insert("defectScalar1", QString::number(mdefect.defectScalar[1])); + detailObj.insert("defectScalar1", QString::number(mdefect.defectScalar[1])); detailObj.insert("defectScalar2", QString::number(mdefect.defectScalar[2])); detailObj.insert("defectArea", QString::number(mdefect.defectArea)); - detailObj.insert("defectLength", QString::number(sqrt(mdefect.defectRect.width * mdefect.defectRect.width + mdefect.defectRect.height * mdefect.defectRect.height))); + detailObj.insert("defectLength", QString::number(sqrt(mdefect.defectRect.width* mdefect.defectRect.width+ mdefect.defectRect.height* mdefect.defectRect.height))); detaillists.append(detailObj); } @@ -873,15 +1011,13 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi //emit sendResultData(resMat, resQbyte); //resQbyte.clear(); - isDirExist(resImgSaveDir + mysaveKey1 + "/"); + //isDirExist(resImgSaveDir + mysaveKey1 + "/"); QString qimgsavePath = resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png"; //存图数æ�®å…¥é˜Ÿ,按需 - QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz"); - if (resMat.size() > 0) + if (resMat.size() > 0 ) { - createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); - addImgToSaveStruct(HikMat[0], "0", resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" - + "RES" + cameraKey_index + QString::fromStdString(getCurrentTime()) + ".png");//ä¿�存原图 + createDirectoryIfNotExists(resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); + addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//ä¿�存原图 } detect_mutex->unlock(); @@ -925,7 +1061,7 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi } //存图加入队列 -void Hd_AI_algo_jixing1::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QString savePath) +void Hd_AI_algo_hanHou::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QString savePath) { //存图数æ�®åŠ ä¿�存队列,加é”�,é�¿å…�æ•°æ�®è®¿é—®å†²çª� saveStruct_mutex->lock(); @@ -937,7 +1073,7 @@ void Hd_AI_algo_jixing1::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QS saveStruct.enqueue(mySave); saveStruct_mutex->unlock(); } -void Hd_AI_algo_jixing1::saveImgThread() +void Hd_AI_algo_hanHou::saveImgThread() { while (1) { @@ -953,7 +1089,7 @@ void Hd_AI_algo_jixing1::saveImgThread() saveImgStruct mysaveStruct = saveStruct.dequeue(); saveStruct_mutex->unlock(); stop = clock(); - if (stop - start > 1000) + if(stop-start >1000) std::cout << "lock stop-start >1000::************************" << stop - start << std::endl; start = clock(); if (mysaveStruct.out_Mat.data) @@ -961,17 +1097,17 @@ void Hd_AI_algo_jixing1::saveImgThread() //std::cout << "savePath::" << mysaveStruct.savePath << std::endl; stop = clock(); if (stop - start > 1000) - std::cout << "imwrite stop-start >1000::--------------------------" << stop - start << std::endl; + std::cout << "imwrite stop-start >1000::--------------------------"<< stop - start << std::endl; _sleep(1); } } } //检测线程,应当å�ªè¿�行一次 -void Hd_AI_algo_jixing1::detectThread() +void Hd_AI_algo_hanHou::detectThread() { do { - if (!ifdetectThread)return; + if (!ifdetectThread)return; //此两行代ç �,é�¿å…�程åº�å�¡æ­»ï¼›_sleep的时间根æ�®å®žé™…项目调整 _sleep(2); @@ -1001,9 +1137,9 @@ void Hd_AI_algo_jixing1::detectThread() isDirExist(resImgSaveDir + mysaveKey); } - + //测试相机的, - //while (sourceImg1.cols > 2000)cv::resize(sourceImg1, sourceImg1, cv::Size(), 0.5, 0.5); + // while (sourceImg1.cols > 2000)cv::resize(sourceImg1, sourceImg1, cv::Size(), 0.5, 0.5); //存图数æ�®å…¥é˜Ÿ //addImgToSaveStruct(sourceImg1, mysaveKey, oriImgSaveDir + mysaveKey + "/" + mySN + myDataTime + ".bmp"); @@ -1016,14 +1152,14 @@ void Hd_AI_algo_jixing1::detectThread() myDir2D.clear(); mySN.clear(); myDataTime.clear(); - qApp->processEvents(); + qApp->processEvents(); } while (ifThreadRunDetect); - + } static int runNum = 0; -bool Hd_AI_algo_jixing1::run() +bool Hd_AI_algo_hanHou::run() { clock_t start, stop; start = clock(); @@ -1031,14 +1167,14 @@ bool Hd_AI_algo_jixing1::run() //Sleep(1000); detectThread(); stop = clock(); - qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++ << " cutTime::" << stop - start; - + qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"< #include @@ -15,13 +15,11 @@ #include #include #include - #include #include #include "imgproc/imgproc_c.h" - #include "base.h" - +#include "handleAI.h" #pragma execution_character_set("utf-8") @@ -34,14 +32,14 @@ struct saveImgStruct; // std::string savePath; //ä¿�存路径 //}; -//åˆ�始化æµ�程(一次):Hd_AI_algo_jixing1,initParas +//åˆ�始化æµ�程(一次):Hd_AI_algo_hanHou,initParas //è¿�行æµ�程:writeData主线程把数æ�®ä¼ è¿‡æ�¥ï¼Œrun,readData此线程把数æ�®ä¼ ä¸»çº¿ç¨‹ -class Hd_AI_algo_jixing1 :public Base +class Hd_AI_algo_hanHou :public Base { Q_OBJECT public: - Hd_AI_algo_jixing1(); - virtual ~Hd_AI_algo_jixing1(); + Hd_AI_algo_hanHou(); + virtual ~Hd_AI_algo_hanHou(); //从类中读数æ�®åˆ°å®žä¾‹å¯¹è±¡ bool readData(std::vector&,QByteArray&); //实例对象把数æ�®å†™å…¥åˆ°ç±» @@ -56,11 +54,10 @@ public: bool decodeAiValue(QByteArray byte,QVector &vec_ret); //---------检测æµ�程,根æ�®å®žé™…项目修改--------- bool AIdetect(cv::Mat img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime); - - + handdleAI::pSegmentation* seg_hanHouSiLie; + handdleAI::pSegmentation* seg_hanHouFanZhe; private: - int allNum = 0; int StationNo=0; int img2D = 2; @@ -106,8 +103,8 @@ private: extern "C" { - Q_DECL_EXPORT Hd_AI_algo_jixing1 * create(); - Q_DECL_EXPORT void destory(Hd_AI_algo_jixing1 * ptr); + Q_DECL_EXPORT Hd_AI_algo_hanHou * create(); + Q_DECL_EXPORT void destory(Hd_AI_algo_hanHou * ptr); } //ä¿�存图片的结构体 struct saveImgStruct diff --git a/BaseModules/Hd_AI_algo_jixing_cam1/base.h b/BaseModules/Hd_AI_algo_hanHou_T/base.h similarity index 100% rename from BaseModules/Hd_AI_algo_jixing_cam1/base.h rename to BaseModules/Hd_AI_algo_hanHou_T/base.h diff --git a/BaseModules/Hd_AI_algo_jixing_cam3/CMakeLists.txt b/BaseModules/Hd_AI_algo_jixing_L/CMakeLists.txt similarity index 96% rename from BaseModules/Hd_AI_algo_jixing_cam3/CMakeLists.txt rename to BaseModules/Hd_AI_algo_jixing_L/CMakeLists.txt index 70505c8..dae4491 100644 --- a/BaseModules/Hd_AI_algo_jixing_cam3/CMakeLists.txt +++ b/BaseModules/Hd_AI_algo_jixing_L/CMakeLists.txt @@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME) string(TIMESTAMP RUN_TIME) message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME}) -set(DLL_NAMES "opencv" "halcon" "Myalgo" "myTools" ) +set(DLL_NAMES "opencv" "halcon" "halconAlgo""myTools" ) foreach(child ${DLL_NAMES}) LIST(APPEND ENV_INCLUDE ${${child}_include}) LIST(APPEND ENV_LIB ${${child}_lib}) diff --git a/BaseModules/Hd_AI_algo_jixing_cam1/Hd_AI_algo_jixing1.cpp b/BaseModules/Hd_AI_algo_jixing_L/Hd_AI_algo_jixing1.cpp similarity index 98% rename from BaseModules/Hd_AI_algo_jixing_cam1/Hd_AI_algo_jixing1.cpp rename to BaseModules/Hd_AI_algo_jixing_L/Hd_AI_algo_jixing1.cpp index 05c9777..759437e 100644 --- a/BaseModules/Hd_AI_algo_jixing_cam1/Hd_AI_algo_jixing1.cpp +++ b/BaseModules/Hd_AI_algo_jixing_L/Hd_AI_algo_jixing1.cpp @@ -4,9 +4,9 @@ #include #include #include -#include "Myalgo.h" #include #include +#include using namespace cv; //原图ä¿�存文件夹 @@ -14,7 +14,7 @@ using namespace cv; //原图class图ä¿�存文件夹 QString classImgSaveDir = "D:/601线/超声波预焊01机/æž�性检测CCD/class图/"; //结果ä¿�存文件夹 - QString resImgSaveDir = "D:\\601线\\超声波超声波预焊01机\\æž�性检测CCD\\结果图\\"; + QString resImgSaveDir = "D:/601线/超声波超声波预焊01机/æž�性检测CCD/结果图/"; //切图的classçš„width,根æ�®é¡¹ç›®å®žé™…设置ï¼� int sizeW = 150; @@ -71,7 +71,16 @@ int algoResult; std::wstring_convert> convert(new std::codecvt_byname(GBK_LOCALE_NAME)); return convert.to_bytes(tmp_wstr); } - + QString getOriSaveFromat() + { + return oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + + "ORI_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".bmp"; + } + QString getResSaveFromat() + { + return resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + + "RES_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".png"; + } QString byteArrayToUnicode(const QByteArray array) { // state用于ä¿�存转æ�¢çжæ€�,它的æˆ�员invalidChars,å�¯ç”¨æ�¥åˆ¤æ–­æ˜¯å�¦è½¬æ�¢æˆ�功 @@ -586,8 +595,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector& vec_mat, QByteArray &da createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); - addImgToSaveStruct(HikMat[0], "0", oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" - "ORI" +cameraKey_index +QString::fromStdString(getCurrentTime())+".bmp");//ä¿�存原图 + addImgToSaveStruct(HikMat[0], "0", getOriSaveFromat());//ä¿�存原图 //if (!source_savePath.isEmpty()) //{ // //std::cout << "try savePath::" << savePath.toStdString() << std::endl; @@ -879,8 +887,7 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi if (resMat.size() > 0) { createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); - addImgToSaveStruct(HikMat[0], "0", resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" - + "RES" + cameraKey_index + QString::fromStdString(getCurrentTime()) + ".png");//ä¿�存原图 + addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//ä¿�存原图 } detect_mutex->unlock(); diff --git a/BaseModules/Hd_AI_algo_jixing_cam1/Hd_AI_algo_jixing1.h b/BaseModules/Hd_AI_algo_jixing_L/Hd_AI_algo_jixing1.h similarity index 100% rename from BaseModules/Hd_AI_algo_jixing_cam1/Hd_AI_algo_jixing1.h rename to BaseModules/Hd_AI_algo_jixing_L/Hd_AI_algo_jixing1.h diff --git a/BaseModules/Hd_AI_algo_jixing_cam2/base.h b/BaseModules/Hd_AI_algo_jixing_L/base.h similarity index 100% rename from BaseModules/Hd_AI_algo_jixing_cam2/base.h rename to BaseModules/Hd_AI_algo_jixing_L/base.h diff --git a/BaseModules/Hd_AI_algo_jixing_cam2/CMakeLists.txt b/BaseModules/Hd_AI_algo_jixing_T/CMakeLists.txt similarity index 96% rename from BaseModules/Hd_AI_algo_jixing_cam2/CMakeLists.txt rename to BaseModules/Hd_AI_algo_jixing_T/CMakeLists.txt index 70505c8..be21793 100644 --- a/BaseModules/Hd_AI_algo_jixing_cam2/CMakeLists.txt +++ b/BaseModules/Hd_AI_algo_jixing_T/CMakeLists.txt @@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME) string(TIMESTAMP RUN_TIME) message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME}) -set(DLL_NAMES "opencv" "halcon" "Myalgo" "myTools" ) +set(DLL_NAMES "opencv" "halcon" "halconAlgo" "myTools" ) foreach(child ${DLL_NAMES}) LIST(APPEND ENV_INCLUDE ${${child}_include}) LIST(APPEND ENV_LIB ${${child}_lib}) diff --git a/BaseModules/Hd_AI_algo_jixing_cam2/Hd_AI_algo_jixing1.cpp b/BaseModules/Hd_AI_algo_jixing_T/Hd_AI_algo_jixing1.cpp similarity index 98% rename from BaseModules/Hd_AI_algo_jixing_cam2/Hd_AI_algo_jixing1.cpp rename to BaseModules/Hd_AI_algo_jixing_T/Hd_AI_algo_jixing1.cpp index 9c12093..0f6ba81 100644 --- a/BaseModules/Hd_AI_algo_jixing_cam2/Hd_AI_algo_jixing1.cpp +++ b/BaseModules/Hd_AI_algo_jixing_T/Hd_AI_algo_jixing1.cpp @@ -4,7 +4,7 @@ #include #include #include -#include "Myalgo.h" +#include #include #include #include @@ -15,7 +15,7 @@ using namespace cv; //原图class图ä¿�存文件夹 QString classImgSaveDir = "D:/601线/超声波预焊01机/æž�性检测CCD/class图/"; //结果ä¿�存文件夹 - QString resImgSaveDir = "D:\\601线\\超声波超声波预焊01机\\æž�性检测CCD\\结果图\\"; + QString resImgSaveDir = "D:/601线/超声波超声波预焊01机/æž�性检测CCD/结果图/"; //切图的classçš„width,根æ�®é¡¹ç›®å®žé™…设置ï¼� int sizeW = 150; @@ -87,7 +87,16 @@ int algoResult; } return text; } - + QString getOriSaveFromat() + { + return oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + + "ORI_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".bmp"; + } + QString getResSaveFromat() + { + return resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + + "RES_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".png"; + } // 缺陷信æ�¯ç»“构体 typedef struct { @@ -586,8 +595,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector& vec_mat, QByteArray &da createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); - addImgToSaveStruct(HikMat[0], "0", oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" - "ORI" +cameraKey_index +QString::fromStdString(getCurrentTime())+".bmp");//ä¿�存原图 + addImgToSaveStruct(HikMat[0], "0", getOriSaveFromat());//ä¿�存原图 //if (myallNum[index] == 1) //{ @@ -862,8 +870,7 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi if (resMat.size() > 0) { createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); - addImgToSaveStruct(HikMat[0], "0", resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" - + "RES" + cameraKey_index + QString::fromStdString(getCurrentTime()) + ".png");//ä¿�存原图 + addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//ä¿�存原图 } detect_mutex->unlock(); diff --git a/BaseModules/Hd_AI_algo_jixing_cam2/Hd_AI_algo_jixing1.h b/BaseModules/Hd_AI_algo_jixing_T/Hd_AI_algo_jixing1.h similarity index 100% rename from BaseModules/Hd_AI_algo_jixing_cam2/Hd_AI_algo_jixing1.h rename to BaseModules/Hd_AI_algo_jixing_T/Hd_AI_algo_jixing1.h diff --git a/BaseModules/Hd_AI_algo_jixing_cam3/base.h b/BaseModules/Hd_AI_algo_jixing_T/base.h similarity index 100% rename from BaseModules/Hd_AI_algo_jixing_cam3/base.h rename to BaseModules/Hd_AI_algo_jixing_T/base.h diff --git a/BaseModules/Hd_AI_algo_jixing_cam3/Hd_AI_algo_jixing1.cpp b/BaseModules/Hd_AI_algo_jixing_cam3/Hd_AI_algo_jixing1.cpp deleted file mode 100644 index 3f00e0f..0000000 --- a/BaseModules/Hd_AI_algo_jixing_cam3/Hd_AI_algo_jixing1.cpp +++ /dev/null @@ -1,1029 +0,0 @@ -#include "Hd_AI_algo_jixing1.h" -#include -#include -#include -#include -#include -#include "Myalgo.h" -#include -#include -#include -using namespace cv; - -//原图ä¿�存文件夹 -QString oriImgSaveDir = "D:/601线/超声波预焊01机/æž�性检测CCD/原图/"; -//原图class图ä¿�存文件夹 -QString classImgSaveDir = "D:/601线/超声波预焊01机/æž�性检测CCD/class图/"; -//结果ä¿�存文件夹 -QString resImgSaveDir = "D:\\601线\\超声波超声波预焊01机\\æž�性检测CCD\\结果图\\"; - -//切图的classçš„width,根æ�®é¡¹ç›®å®žé™…设置ï¼� -int sizeW = 150; -//切图的classçš„height,根æ�®é¡¹ç›®å®žé™…设置ï¼� -int sizeH = 150; -//切图的classçš„width,根æ�®é¡¹ç›®å®žé™…设置ï¼�0为黑,255为白; -int fillColour = 0; -int algoResult; - -//检测线程é”� -QMutex* detect_mutex; -//ä¿�存线程é”� -QMutex* saveStruct_mutex; -//检测线程è¿�行标志 -bool ifdetectThread = false; - -QString cameraKey_index = ""; - -//åˆ�始化å�‚数列表 -QByteArrayList initValueList; -static void createDirectoryIfNotExists(const QString& path) { - QDir dir; - dir.mkpath(path); -} -static std::string getCurrentTime() { - - // 获å�–当å‰�时间点 - auto now = std::chrono::system_clock::now(); - - // 转æ�¢ä¸ºå­—符串 - auto currentTime = std::chrono::system_clock::to_time_t(now); - auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 100; - std::tm* localTime = std::localtime(¤tTime); - std::stringstream ss; - ss << std::put_time(localTime, "%H-%M-%S") << "-" << std::setfill('0') << std::setw(2) << ms.count(); - return ss.str(); -} -static QString getCurrentDate() -{ - QDateTime currentDateTime = QDateTime::currentDateTime(); - return currentDateTime.toString("yyyy-MM-dd"); -} -static QString getCurrentHour() -{ - QDateTime currentDateTime = QDateTime::currentDateTime(); - return QString::number(currentDateTime.time().hour()) + "H"; -} -inline std::string utf8_to_gbk(const std::string& str) -{ - std::wstring_convert> conv; - std::wstring tmp_wstr = conv.from_bytes(str); - //GBK locale name in windows - const char* GBK_LOCALE_NAME = ".936"; - std::wstring_convert> convert(new std::codecvt_byname(GBK_LOCALE_NAME)); - return convert.to_bytes(tmp_wstr); -} -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; -} - - -// 缺陷信æ�¯ç»“构体 -typedef struct { - QString defectName = "";//缺陷å��ç§° - cv::Rect defectRect = { 0,0,0,0 };//缺陷ä½�ç½® - cv::Scalar defectScalar = cv::Scalar(0, 0, 0);//画框颜色 - double defectArea = 0;//缺陷真实é�¢ç§¯ - double defectDepth = 0;//缺陷深度/高度,3Dä¿¡æ�¯ -}defectInfo; - -//Mat转Halcon图åƒ� -void MatToHObject(cv::Mat& image, HalconCpp::HObject* Hobj) -{ - int hgt = image.rows; - int wid = image.cols; - int i; - if (image.type() == CV_8UC3) - { - HalconCpp::HImage himage = HalconCpp::HImage(); - - std::vector imgchannel; - split(image, imgchannel); - cv::Mat imgB = imgchannel[0]; - cv::Mat imgG = imgchannel[1]; - cv::Mat imgR = imgchannel[2]; - uchar* dataR = new uchar[hgt * wid]; - uchar* dataG = new uchar[hgt * wid]; - uchar* dataB = new uchar[hgt * wid]; - for (i = 0; i < hgt; i++) - { - memcpy(dataR + wid * i, imgR.data + imgR.step * i, wid); - memcpy(dataG + wid * i, imgG.data + imgG.step * i, wid); - memcpy(dataB + wid * i, imgB.data + imgB.step * i, wid); - } - himage.GenImage3("byte", wid, hgt, dataR, dataG, dataB); - HalconCpp::HString tmpType; - Hlong tmpW, tmpH; - void* hImgPtR, * hImgPtG, * hImgPtB; - himage.GetImagePointer3(&hImgPtR, &hImgPtG, &hImgPtB, &tmpType, &tmpW, &tmpH); - - GenImage3(Hobj, "byte", wid, hgt, (Hlong)hImgPtR, (Hlong)hImgPtG, (Hlong)hImgPtB); - delete[]dataR; - delete[]dataG; - delete[]dataB; - dataR = NULL; - dataG = NULL; - dataB = NULL; - } - else if (image.type() == CV_8UC1) - { - //HalconCpp::HImage himage = HalconCpp::HImage(); - - ////uchar* data = new uchar[hgt * wid]; - ////for (i = 0; i < hgt; i++) - ////{ - //// memcpy(data + wid * i, image.data + image.step * i, wid); - ////} - ////gen_image_const - //himage.GenImage1("byte", wid, hgt, image.data); - - //HalconCpp::HString tmpType; - //Hlong tmpW, tmpH; - //void* hImgPt; - //hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH); - //GenImage1(&Hobj, "byte", wid, hgt, (Hlong)hImgPt); - GenImage1(Hobj, "byte", wid, hgt, (Hlong)image.data); - - /* delete[] data; - data = NULL;*/ - - } - else if (image.type() == CV_16UC1) - { - HalconCpp::HImage himage = HalconCpp::HImage(); - - ushort* data = new ushort[hgt * wid * 2]; - - memcpy(data, image.data, hgt * wid * 2); - - - himage.GenImage1("uint2", wid, hgt, data); - - HalconCpp::HString tmpType; - Hlong tmpW, tmpH; - void* hImgPt; - hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH); - GenImage1(Hobj, "uint2", wid, hgt, (Hlong)hImgPt); - - delete[] data; - data = NULL; - - } - else if (image.type() == CV_16SC1) - { - HalconCpp::HImage himage = HalconCpp::HImage(); - - short* data = new short[hgt * wid * 2]; - - memcpy(data, image.data, hgt * wid * 2); - - - himage.GenImage1("int2", wid, hgt, data); - - HalconCpp::HString tmpType; - Hlong tmpW, tmpH; - void* hImgPt; - hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH); - GenImage1(Hobj, "int2", wid, hgt, (Hlong)hImgPt); - - delete[] data; - data = NULL; - - } - -} - -//判断文件是å�¦å­˜åœ¨ï¼Œä¸�存在则创建 -bool isFileExist(QString fullFileName) -{ - QFileInfo fileInfo(fullFileName); - if (fileInfo.isFile()) - { - return true; - } - return false; -} - -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 putTextZH(cv::Mat& dst, const char* str, cv::Point org, cv::Scalar color, int fontsize, - const char* fn = "Arial", bool italic = false, bool underline = false) -{ - CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3)); - - - int x, y, r, b; - //å��标点大于图åƒ�宽和高直接返回 - if (org.x > dst.cols || org.y > dst.rows) return; - x = org.x < 0 ? -org.x : 0; - y = org.y < 0 ? -org.y : 0; - - - LOGFONTA lf; - lf.lfHeight = -fontsize; //字体高度 - lf.lfWidth = 0; //å¹³å�‡å®½åº¦ - lf.lfEscapement = 0; //字符排列角度 - lf.lfOrientation = 0; //字符本身旋转的角度 - lf.lfWeight = 5; //设置字体线æ�¡çš„宽度 - lf.lfItalic = italic; //斜体 - lf.lfUnderline = underline; //下划线 - lf.lfStrikeOut = 0; //是å�¦å­—符中央加横线 - lf.lfCharSet = DEFAULT_CHARSET; //字符集 - lf.lfOutPrecision = 0; //字体的精确度 - lf.lfQuality = PROOF_QUALITY; //字体质é‡� - lf.lfPitchAndFamily = 0; //选择字体的间è·�和字体家æ—� - strcpy_s(lf.lfFaceName, fn); //字体的å��ç§° - - - HFONT hf = CreateFontIndirectA(&lf); - HDC hdc = CreateCompatibleDC(0); - HFONT holdfont = (HFONT)SelectObject(hdc, hf); - - - int strBaseW = 0, strBaseH = 0; - int singleRow = 0; - char buf[1 << 12]; - strcpy_s(buf, str); - char* bufT[1 << 12]; //这个用于分隔字符串å�Žå‰©ä½™çš„字符,å�¯èƒ½ä¼šè¶…出。 - - - //处ç�†å¤šè¡Œ - { - int nnh = 0; - int cw, ch; - - - const char* ln = strtok_s(buf, "\n", bufT); - while (ln != 0) - { - GetStringSize(hdc, ln, &cw, &ch); - strBaseW = max(strBaseW, cw); - strBaseH = max(strBaseH, ch); - - - ln = strtok_s(0, "\n", bufT); - nnh++; - } - singleRow = strBaseH; - strBaseH *= nnh; - } - - - if (org.x + strBaseW < 0 || org.y + strBaseH < 0) - { - SelectObject(hdc, holdfont); - DeleteObject(hf); - DeleteObject(hdc); - return; - } - - - r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1; - b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1; - org.x = org.x < 0 ? 0 : org.x; - org.y = org.y < 0 ? 0 : org.y; - - - BITMAPINFO bmp = { 0 }; - BITMAPINFOHEADER& bih = bmp.bmiHeader; - int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4)); - - - bih.biSize = sizeof(BITMAPINFOHEADER); - bih.biWidth = strBaseW; - bih.biHeight = strBaseH; - bih.biPlanes = 1; - bih.biBitCount = 24; - bih.biCompression = BI_RGB; - bih.biSizeImage = strBaseH * strDrawLineStep; - bih.biClrUsed = 0; - bih.biClrImportant = 0; - - - void* pDibData = 0; - HBITMAP hBmp = CreateDIBSection(hdc, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0); - - - CV_Assert(pDibData != 0); - HBITMAP hOldBmp = (HBITMAP)SelectObject(hdc, hBmp); - - - //color.val[2], color.val[1], color.val[0] - SetTextColor(hdc, RGB(255, 255, 255)); - SetBkColor(hdc, 0); - //SetStretchBltMode(hDC, COLORONCOLOR); - - - strcpy_s(buf, str); - const char* ln = strtok_s(buf, "\n", bufT); - int outTextY = 0; - while (ln != 0) - { - TextOutA(hdc, 0, outTextY, ln, strlen(ln)); - outTextY += singleRow; - ln = strtok_s(0, "\n", bufT); - } - uchar* dstData = (uchar*)dst.data; - int dstStep = dst.step / sizeof(dstData[0]); - unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep; - unsigned char* pStr = (unsigned char*)pDibData + x * 3; - for (int tty = y; tty <= b; ++tty) - { - unsigned char* subImg = pImg + (tty - y) * dstStep; - unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep; - for (int ttx = x; ttx <= r; ++ttx) - { - for (int n = 0; n < dst.channels(); ++n) { - double vtxt = subStr[n] / 255.0; - int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n]; - subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv); - } - - - subStr += 3; - subImg += dst.channels(); - } - } - - - SelectObject(hdc, hOldBmp); - SelectObject(hdc, holdfont); - DeleteObject(hf); - DeleteObject(hBmp); - DeleteDC(hdc); -} - -void drawDefects(cv::Mat& sourceMat, QQueue defectInfoList) -{ - for (int i = 0; i < defectInfoList.size(); i++) - { - defectInfo mdefect = defectInfoList[i]; - - cv::rectangle(sourceMat, cv::Point(mdefect.defectRect.x, mdefect.defectRect.y), - cv::Point(mdefect.defectRect.x + mdefect.defectRect.width, mdefect.defectRect.y + mdefect.defectRect.height), mdefect.defectScalar, 3, 8); - - QByteArray path_arr = mdefect.defectName.toLocal8Bit(); - const char* path = path_arr.data(); - putTextZH(sourceMat, path, cv::Point(mdefect.defectRect.x, mdefect.defectRect.y - 50), mdefect.defectScalar, 50, "微软雅黑"); - } -} - - - -//判断文件夹是å�¦å­˜åœ¨ï¼Œä¸�存在则创建 -void Hd_AI_algo_jixing1::isDirExist(QString fullDirName) -{ - QDir* photo = new QDir; - bool exist = photo->exists(fullDirName); - if (exist) - { - //qDebug() << fullDirName << "::已存在"; - } - else - { - //创建photo文件夹 - //qDebug() << fullDirName << "::ä¸�存在,创建"; - photo->mkdir(fullDirName); - } - delete photo; - photo = nullptr; -} - -Hd_AI_algo_jixing1* create() -{ - qDebug() << "[INFO] " << " Hd_AI_algo_jixing1 create success!"; - return new Hd_AI_algo_jixing1; -} - -void destory(Hd_AI_algo_jixing1* ptr) -{ - qDebug() << "[INFO] " << "Hd_AI_algo_jixing1 destory success!"; - if (ptr) - { - delete ptr; - ptr = nullptr; - } -} - -Hd_AI_algo_jixing1::Hd_AI_algo_jixing1() -{ - detect_mutex = new QMutex; - saveStruct_mutex = new QMutex; - ifdetectThread = false; - - for (int i = 0; i < 4; i++) - { - QString DirPath = "E:/testImg/source" + QString::number(i); - QStringList imgFilters; - imgFilters << "*.jpg" << "*.png" << "*.PNG" << "*.gif" << "*.tif" << "*.jpeg" << "*.bmp"; - QDir qdir(DirPath); - //返回文件å��列表 - QStringList localSourceImgsName = qdir.entryList(imgFilters, QDir::Files | QDir::Readable, QDir::Name); - for (int j = 0; j < localSourceImgsName.size(); j++) - { - QString imgPath = DirPath + "/" + localSourceImgsName[j]; - QFile myf(imgPath); - if (myf.exists()) - myf.remove(); - //Sleep(1); - } - } -} - -Hd_AI_algo_jixing1::~Hd_AI_algo_jixing1() -{ - ifdetectThread = false; - Sleep(10); - if (detect_mutex) - { - delete detect_mutex; - detect_mutex = nullptr; - } - if (saveStruct_mutex) - { - delete saveStruct_mutex; - saveStruct_mutex = nullptr; - } - /*DestroySegObj(pSeg); - DestroyClsObj(pCls);*/ -} -//从类中读数æ�®åˆ°å®žä¾‹å¯¹è±¡ -bool Hd_AI_algo_jixing1::readData(std::vector& vec_mat, QByteArray& data) -{ - detect_mutex->lock(); - //qDebug() << __FUNCTION__ << " line:" <<__LINE__ << " data len:" << data.length(); - if (resMat.size() > 0) - { - vec_mat.push_back(resMat[0]); - resMat.clear(); - } - else - { - if (HikMat.size() > 0) - vec_mat.push_back(HikMat[0]); - //qDebug() << __FUNCTION__ << " line:" << __LINE__ << " resMat.data err:"; - } - //if (allNum++ % 2 == 0) - // data = "2*3*2";// resByte.dequeue(); - //else - data = QByteArray::number(algoResult) + "&" + QByteArray::number(algoResult - 1) + "+" + QByteArray::number(algoResult);//1OK,2NG - resByte.clear(); - ////之å�Žæ ¹æ�®ç»“果类修改 - //if(resIfNg == true) - // data = "NG"; - //else data = "OK"; - detect_mutex->unlock(); - /*if(cameraKey_index.contains('_')) - qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName:" - << cameraKey_index.split("_")[0] << " imgIndex:" << cameraKey_index.split("_")[1]; - else - qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName imgIndex:" << cameraKey_index;*/ - return true; -} -//从类中读数æ�®åˆ°å®žä¾‹å¯¹è±¡ -bool Hd_AI_algo_jixing1::encodeResultValue(QVector append_value, QByteArray& resultByte) -{ - try - { - std::string sendMsg; - for (int i = 0; i < append_value.size(); i++) - { - std::string value = append_value.at(1); - //type - int type = 3; - std::string m_type; - m_type.insert(0, 4, '1'); - memcpy((void*)m_type.c_str(), (void*)&type, 4); - sendMsg.append(m_type); - - //len - int len = value.length(); - std::string m_len; - m_len.insert(0, 4, '1'); - memcpy((void*)m_len.c_str(), (void*)&len, 4); - sendMsg.append(m_len); - - //data x - sendMsg.append(value); - } - resultByte = QByteArray::fromStdString(sendMsg); - } - catch (QString ev) - { - qCritical() << "[Error] " << " ev:" << ev; - return false; - } - return true; -} - -int myallNum[4] = { 0 }; -QMap lastImgMap; -//接收数æ�® -bool Hd_AI_algo_jixing1::writeData(std::vector& vec_mat, QByteArray& data) -{ - //qDebug() << __FUNCTION__ << "line:"<< __LINE__ << " data len" << data.length() ; - if (vec_mat.empty()) - { - qCritical() << "[Error] " << " vec_mat is null !"; - return false; - } - detect_mutex->lock(); - HikMat.clear(); - for (int i = 0; i < vec_mat.size(); i++) - HikMat.enqueue(vec_mat[i]); - - QByteArray source_savePath; - QByteArray sData = data; - QByteArrayList splitDataList = sData.split(','); - if (splitDataList.size() >= 4) - { - if (splitDataList[2].contains('_')) - cameraKey_index = splitDataList[2]; - QByteArray saveDir = splitDataList[0] + "/" + splitDataList[1] + "/"; - isDirExist(byteArrayToUnicode(saveDir)); //ä¸�存在,创建 - QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz"); - source_savePath = splitDataList[0] + "/" + splitDataList[1] + "/" + sdataTime.toLocal8Bit() + "-" + splitDataList[2] + "-" + splitDataList[3];// +".bmp"; - } - //int index = -1; - /*if (sData.contains("offline-camera0")) - { - index = 0; - savePath = "E:\\testImg\\source0\\"+QString::number(myallNum[0]++) + ".bmp"; - } - else if (sData.contains("offline-camera1")) - { - index = 1; - savePath = "E:\\testImg\\source1\\" + QString::number(myallNum[1]++) + ".bmp"; - } - else if (sData.contains("offline-camera2")) - { - index = 2; - savePath = "E:\\testImg\\source2\\" + QString::number(myallNum[2]++) + ".bmp"; - } - else if (sData.contains("offline-camera3")) - { - index = 3; - savePath = "E:\\testImg\\source3\\" + QString::number(myallNum[3]++) + ".bmp"; - }*/ - - - - - createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); - addImgToSaveStruct(HikMat[0], "0", oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" - "ORI" + cameraKey_index + QString::fromStdString(getCurrentTime()) + ".bmp");//ä¿�存原图 - - //if (myallNum[index] == 1) - //{ - // cv::Mat img; - // lastImgMap.insert(index, img); - //} - //else - //{ - // //判断和上一张图,是å�¦é‡�å¤� - // int dataLength = HikMat[0].total() * HikMat[0].elemSize(); - // bool res = false; - // if (myallNum[index] > 0) - // { - // cv::Mat img = lastImgMap.value(index); - // if (img.total() * img.elemSize() == dataLength) - // { - // res = memcmp(img.data, HikMat[0].data, dataLength) == 0; - // if (res == true) - // std::cout << "res ==true ====!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; - // } - // } - //} - //lastImgMap.insert(index, HikMat[0]); - - //or检测:ä¿�存路径,æ‹�ç…§é�¢æ��述,相机key_第几张图,SN_时间戳 - //and检测:ä¿�存路径,æ‹�ç…§é�¢æ��述,相机key_第几张图,相机key_第几张图,SN_时间戳,SN_时间戳 - //汇总:ä¿�存路径,æ‹�ç…§é�¢æ��述,触å�‘ä¿¡å�·_åº�å�·åˆ—表0,SN_时间戳 - QString qstring_data = data; - QStringList datalist = qstring_data.split(','); - - - /*saveKey.enqueue("datalist[0]"); - Dir2D.enqueue("datalist[1]"); - QStringList SN_dataTime; - SN_dataTime = datalist[3].split('_'); - DateTime1 = "SN_dataTime[1]"; - SN.enqueue("SN_dataTime[0]");*/ - //qCritical() << __FUNCTION__ << " line: " << __LINE__ << " data:" << qstring_data; - detect_mutex->unlock(); - - //qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << " data: " << data << " run end"; - //cv::Mat resultDstImg = vec_mat[0].clone();// = pSeg->Evaluate(sourceImg); //返回å�•通é�“二值图 图片错误输出Image Error!但ä¸�报错。。 - //resultDstImg = pSeg->Evaluate(resultDstImg); - //resultDstImg.release(); - - return true; -} - -//ä¼ å…¥initParas函数,格å¼�为:相机key+å�‚æ•°å��1#å�‚数值1#å�‚数值2+å�‚æ•°å��2#å�‚数值1... -//åˆ�始化 -bool Hd_AI_algo_jixing1::initParas(QByteArray& byte) -{ - initValueList = byte.split('+'); - QStringList valueiList; - - if (byte.contains("onlySetParameter")) - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,valueList[0]:" << initValueList[0]; - if (initValueList.size() > 1) - for (int i = 1; i < initValueList.size(); i++) - { - QString valuei = byteArrayToUnicode(initValueList[i]); - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,lastName:" << initValueList[0] << " ,valuei:" << valuei; - } - return true; - } - - - if (initValueList.size() > 1) - for (int i = 1; i < initValueList.size(); i++) - { - QString valuei = byteArrayToUnicode(initValueList[i]); - valueiList.append(valuei); - } - - - /*pSeg = CreateSegObjS(pSeg_modulePath, 128, gpuId); - pCls = CreateClsObjV3(pCls_modulePath, gpuId, 1);*/ - - - //StationNo = vec_ret.at(0).toInt(); - - //InitThreads(StationNo, img2D); - //InitModels(StationNo, img2D); - - //è¿�行检测线程 - ifdetectThread = true; - - //线程检测:结果类完æˆ�时,使用 - //ifThreadRunDetect = true; - //QFuture future1 = QtConcurrent::run(this, &Hd_AI_algo_jixing1::detectThread); - //è¿�行存图线程 - QFuture future2 = QtConcurrent::run(this, &Hd_AI_algo_jixing1::saveImgThread); - //detectThread(); - - //原图总文件夹 - isDirExist(oriImgSaveDir); - //原图class总文件夹 - isDirExist(classImgSaveDir); - //结果图总文件夹 - isDirExist(resImgSaveDir); - - - //qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ; - return true; -} -// è§£ç � -bool Hd_AI_algo_jixing1::decodeAiValue(QByteArray byte, QVector& vec_ret) -{ - if (byte.isEmpty()) - { - qCritical() << "[Error] " << " byte is null!"; - return false; - } - - /*******************************************/ - byte.remove(0, 8); - QByteArray mm_data = byte.mid(0, 4); - memcpy((void*)¶mNum, (void*)mm_data.data(), 4); - qDebug() << "[INFO] " << " paramNum:" << paramNum; - byte.remove(0, 4); - /*******************************************/ - - while (!byte.isEmpty()) - { - int type = 0; - QByteArray m_type = byte.mid(0, 4); - memcpy((void*)&type, (void*)m_type.data(), 4); - byte.remove(0, 4); - - int len = 0; - QByteArray m_len = byte.mid(0, 4); - memcpy((void*)&len, (void*)m_len.data(), 4); - byte.remove(0, 4); - - QByteArray mm_data = byte.mid(0, len); - vec_ret.append(mm_data); - byte.remove(0, len); - } - return true; -} - -//---------检测æµ�程,根æ�®å®žé™…项目修改--------- -bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime) -{ - try - { - //存图数æ�®åŠ ä¿�存队列,加é”�,é�¿å…�æ•°æ�®è®¿é—®å†²çª� - saveStruct_mutex->lock(); - saveImgStruct mySave; - Mat sourceImg; - sourceImg = img2D.clone(); - //img2D.copyTo(sourceImg); - //img2D.release(); - QString mysaveKey1 = mysaveKey; //"offlineStation1_off_1" - saveStruct_mutex->unlock(); - - QJsonDocument document; - QJsonObject obj; - obj.insert("result_key", "mysaveKey"); - obj.insert("SN", "mySN"); - obj.insert("DataTime", "myDataTime"); - - - //QFile csvName("test.csv"); - //QStringList lines; - //lines << "class,name\n" << "3,4,5,6,7\n" << "a,b,c,d\n"; - //if (csvName.open(QIODevice::WriteOnly)) //若文件ä¸�存在,会自动创建 - //{ - // for (int i = 0; i < lines.size(); i++) - // csvName.write(lines[i].toStdString().c_str()); - // csvName.close(); - //} - - QQueue defectInfoList; - - //æž�性检测 - HObject ho_Image; - HTuple hv_out_Value; - HTuple hv_Make; - //cv::imwrite("C://1.bmp", sourceImg); - MatToHObject(sourceImg, &ho_Image); - _628_1_Polarity_detection(ho_Image, &hv_out_Value, &hv_Make); - //相机2 OK为铜 NG为é“� - if (hv_Make.D() != -1) - { - if (hv_out_Value.D() == 1)//é“� - { - putTextHusky(sourceImg, utf8_to_gbk("é“�æž�").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); - //cv::putText(sourceImg, "Aluminium", cv::Point(0, 240), 2, 10, cv::Scalar(0, 255, 0), 10); - cv::putText(sourceImg, "NG", cv::Point(0, 550), 2, 10, cv::Scalar(0, 0, 255), 10); - algoResult = 1; - //Result = 1 ? 2; - //Result = 1; - } - else if (hv_out_Value.D() == 2)//铜 - { - putTextHusky(sourceImg, utf8_to_gbk("铜æž�").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); - //cv::putText(sourceImg, "Copper", cv::Point(0, 240), 2, 10, cv::Scalar(0, 255, 0), 10); - cv::putText(sourceImg, "OK", cv::Point(0, 550), 2, 10, cv::Scalar(0, 255, 0), 10); - algoResult = 1; - } - else - { - putTextHusky(sourceImg, utf8_to_gbk("算法异常1").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); - // cv::putText(sourceImg, "Algo error1", cv::Point(0, 240), 2, 10, cv::Scalar(0, 0, 255), 10); - //Result = 2; - } - } - else - { - putTextHusky(sourceImg, utf8_to_gbk("算法异常1").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300); - // cv::putText(sourceImg, "Algo error2", cv::Point(0, 240), 2, 10, cv::Scalar(0, 0, 255), 10); - } - - ho_Image.Clear(); - hv_out_Value.Clear(); - hv_Make.Clear(); - - detect_mutex->lock(); - //resMat = sourceImg.clone(); - //sourceImg.copyTo(resMat); - resMat.push_back(sourceImg); - //结果图画框和缺陷,在resMat上绘制 - if (resMat.size() > 0) - drawDefects(resMat[0], defectInfoList); - - //QByteArray,根æ�®å®žé™…项目进行解æž� - //å�‚æ•°,例:返回结果图;相机关键字(SN或userID)+ä¿�存路径+缺陷信æ�¯åˆ—表(缺陷å��称,缺陷ä½�ç½®int(x,y,w,h),画框颜色Scalar(a,b,c),缺陷é�¢ç§¯double) - - QJsonArray detaillists; - //QByteArrayList resQbyte; - for (int i = 0; i < defectInfoList.size(); i++) - { - defectInfo mdefect = defectInfoList[i]; - //resQbyte.push_back(mdefect.defectName.toLocal8Bit()); //中文也å�¯ä»¥QString::number(1.1).toUtf8() - //resQbyte.push_back(QString::number(mdefect.defectRect.x).toUtf8()); - //resQbyte.push_back(QString::number(mdefect.defectRect.y).toUtf8()); - //resQbyte.push_back(QString::number(mdefect.defectRect.width).toUtf8()); - //resQbyte.push_back(QString::number(mdefect.defectRect.height).toUtf8()); - //resQbyte.push_back(QString::number(mdefect.defectScalar[0]).toUtf8()); - //resQbyte.push_back(QString::number(mdefect.defectScalar[1]).toUtf8()); - //resQbyte.push_back(QString::number(mdefect.defectScalar[2]).toUtf8()); - //resQbyte.push_back(QString::number(mdefect.defectArea).toUtf8()); - QJsonObject detailObj; - detailObj.insert("defectName", "mdefect.defectName"); - detailObj.insert("defectRect.x", QString::number(mdefect.defectRect.x)); - detailObj.insert("defectRect.y", QString::number(mdefect.defectRect.y)); - detailObj.insert("defectRect.width", QString::number(mdefect.defectRect.width)); - detailObj.insert("defectRect.height", QString::number(mdefect.defectRect.height)); - detailObj.insert("defectScalar0", QString::number(mdefect.defectScalar[0])); - detailObj.insert("defectScalar1", QString::number(mdefect.defectScalar[1])); - detailObj.insert("defectScalar2", QString::number(mdefect.defectScalar[2])); - detailObj.insert("defectArea", QString::number(mdefect.defectArea)); - detailObj.insert("defectLength", QString::number(sqrt(mdefect.defectRect.width * mdefect.defectRect.width + mdefect.defectRect.height * mdefect.defectRect.height))); - - detaillists.append(detailObj); - } - - - //使用完删除 - defectInfoList.clear(); - - //往主界é�¢å�‘ - //emit sendResultData(resMat, resQbyte); - //resQbyte.clear(); - - isDirExist(resImgSaveDir + mysaveKey1 + "/"); - QString qimgsavePath = resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png"; - //存图数æ�®å…¥é˜Ÿ,按需 - QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz"); - if (resMat.size() > 0) - { - createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); - addImgToSaveStruct(HikMat[0], "0", resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" - + "RES" + cameraKey_index + QString::fromStdString(getCurrentTime()) + ".png");//ä¿�存原图 - } - detect_mutex->unlock(); - - obj.insert("detaillists", detaillists); - obj.insert("qimgsavePath", qimgsavePath); - document.setObject(obj); - //resByte.clear(); - QByteArray qa = document.toJson(); - //resByte .enqueue(qa); - - - //resMat.release(); - sourceImg.release(); - - mySave.out_Mat.resize(0); - mysaveKey1.clear(); - qApp->processEvents(); - - - ////原图和结果都往主界é�¢å�‘? - //std::vector resMat; - //resMat.push_back(img2D); - //resMat.push_back(sourceRectangles); - //QByteArray resByte = mysaveKey.toLocal8Bit(); - //resByte.append(myDir2D.toLocal8Bit()); - //resByte.append(mySN.toLocal8Bit()); - //resByte.append(myDataTime.toLocal8Bit()); - - ////往主界é�¢å�‘é€�图片和数æ�® - ////emit writeData(resMat, resByte); - //resMat.resize(0); - //resByte.resize(0); - } - catch (...) - { - qDebug() << "[Error] " << QString::fromUtf8("检测失败!"); - return false; - } - return true; - -} - -//存图加入队列 -void Hd_AI_algo_jixing1::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QString savePath) -{ - //存图数æ�®åŠ ä¿�存队列,加é”�,é�¿å…�æ•°æ�®è®¿é—®å†²çª� - saveStruct_mutex->lock(); - saveImgStruct mySave; - mySave.out_Mat = img2D.clone(); - //img2D.copyTo(mySave.out_Mat); - mySave.saveKey = mysaveKey.toLocal8Bit().toStdString(); - mySave.savePath = savePath.toLocal8Bit().toStdString(); - saveStruct.enqueue(mySave); - saveStruct_mutex->unlock(); -} -void Hd_AI_algo_jixing1::saveImgThread() -{ - while (1) - { - if (!ifdetectThread)return; - _sleep(5); - qApp->processEvents(); - if (saveStruct.size() < 1)continue; - for (int i = 0; i < saveStruct.size(); i++) - { - clock_t start, stop; - start = clock(); - saveStruct_mutex->lock(); - saveImgStruct mysaveStruct = saveStruct.dequeue(); - saveStruct_mutex->unlock(); - stop = clock(); - if (stop - start > 1000) - std::cout << "lock stop-start >1000::************************" << stop - start << std::endl; - start = clock(); - if (mysaveStruct.out_Mat.data) - imwrite(mysaveStruct.savePath, mysaveStruct.out_Mat); - //std::cout << "savePath::" << mysaveStruct.savePath << std::endl; - stop = clock(); - if (stop - start > 1000) - std::cout << "imwrite stop-start >1000::--------------------------" << stop - start << std::endl; - _sleep(1); - } - } -} -//检测线程,应当å�ªè¿�行一次 -void Hd_AI_algo_jixing1::detectThread() -{ - do - { - if (!ifdetectThread)return; - - //此两行代ç �,é�¿å…�程åº�å�¡æ­»ï¼›_sleep的时间根æ�®å®žé™…项目调整 - _sleep(2); - qApp->processEvents(); - //å�–æ•°æ�®åŠ é”�,é�¿å…�æ•°æ�®è®¿é—®å†²çª� - detect_mutex->lock(); - //if (HikMat.size() < 1 || saveKey.size() < 1 || Dir2D.size() < 1 || SN.size() < 1 )//|| DateTime1.size() < 1) - //{ - // detect_mutex->unlock(); - // continue; - //} - - cv::Mat sourceImg1 = HikMat[0];// .dequeue(); - QString mysaveKey = "saveKey";// .dequeue(); - QString myDir2D = "Dir2D";// .dequeue(); - QString mySN = "SN";// .dequeue(); - QString myDataTime = "DateTime1"; - detect_mutex->unlock(); - - //判断存图文件夹是å�¦å­˜åœ¨,ä¸�存在则创建 - { - //原图总文件夹 - isDirExist(oriImgSaveDir + mysaveKey); - //原图class总文件夹 - isDirExist(classImgSaveDir + mysaveKey); - //结果图总文件夹 - isDirExist(resImgSaveDir + mysaveKey); - - } - - //测试相机的, - //while (sourceImg1.cols > 2000)cv::resize(sourceImg1, sourceImg1, cv::Size(), 0.5, 0.5); - - //存图数æ�®å…¥é˜Ÿ - //addImgToSaveStruct(sourceImg1, mysaveKey, oriImgSaveDir + mysaveKey + "/" + mySN + myDataTime + ".bmp"); - - //-------检测æµ�程,根æ�®å®žé™…项目修改--------- - AIdetect(sourceImg1, mysaveKey, oriImgSaveDir, mySN, myDataTime); - //sourceImg1.release(); - - mysaveKey.clear(); - myDir2D.clear(); - mySN.clear(); - myDataTime.clear(); - qApp->processEvents(); - - } while (ifThreadRunDetect); - -} - -static int runNum = 0; -bool Hd_AI_algo_jixing1::run() -{ - clock_t start, stop; - start = clock(); - - //Sleep(1000); - detectThread(); - stop = clock(); - qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++ << " cutTime::" << stop - start; - - - //qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << "Mat_name: " << Mat_name << " run end"; - return true; -} - -bool Hd_AI_algo_jixing1::checkStatus() -{ - status = moduleStatus; - return status; -} - diff --git a/BaseModules/Hd_AI_algo_jixing_cam3/Hd_AI_algo_jixing1.h b/BaseModules/Hd_AI_algo_jixing_cam3/Hd_AI_algo_jixing1.h deleted file mode 100644 index 889dc14..0000000 --- a/BaseModules/Hd_AI_algo_jixing_cam3/Hd_AI_algo_jixing1.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef Hd_AI_algo_jixing1_H -#define Hd_AI_algo_jixing1_H - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "imgproc/imgproc_c.h" - -#include "base.h" - -#pragma execution_character_set("utf-8") - - - -//ä¿�存图片的结构体 -struct saveImgStruct; -//{ -// cv::Mat out_Mat; -// std::string saveKey; //关键字,用于LOG日志 -// std::string savePath; //ä¿�存路径 -//}; - -//åˆ�始化æµ�程(一次):Hd_AI_algo_jixing1,initParas -//è¿�行æµ�程:writeData主线程把数æ�®ä¼ è¿‡æ�¥ï¼Œrun,readData此线程把数æ�®ä¼ ä¸»çº¿ç¨‹ -class Hd_AI_algo_jixing1 :public Base -{ - Q_OBJECT -public: - Hd_AI_algo_jixing1(); - virtual ~Hd_AI_algo_jixing1(); - //从类中读数æ�®åˆ°å®žä¾‹å¯¹è±¡ - bool readData(std::vector&,QByteArray&); - //实例对象把数æ�®å†™å…¥åˆ°ç±» - bool writeData(std::vector&, QByteArray&); - bool initParas(QByteArray&); - //è¿�行(Logic_taskthread.cpp) - bool run(); - //线程状æ€� - bool checkStatus();// { return true; }; - - bool encodeResultValue(QVector append_value,QByteArray &resultByte); - bool decodeAiValue(QByteArray byte,QVector &vec_ret); - //---------检测æµ�程,根æ�®å®žé™…项目修改--------- - bool AIdetect(cv::Mat img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime); - - - -private: - - int allNum = 0; - int StationNo=0; - int img2D = 2; - - bool moduleStatus = true; - - //输入图片队列 - QQueue HikMat; - //输入关键字队列 - QString saveKey="saveKey"; - //结果路径文件夹队列 - QString Dir2D="Dir2D"; - //产å“�SN队列 - QString SN="SN"; - //产å“�时间戳队列 - QString DateTime1="DateTime1"; - - int paramNum; - - //是å�¦ä½¿ç”¨çº¿ç¨‹æ£€æµ‹æ–¹å¼� - bool ifThreadRunDetect = false; - //检测结果图 - std::vector resMat; - //检测结果 - bool resIfNg = false; - - QQueue resByte; - - //检测线程 - void detectThread(); - //存图线程 - void saveImgThread(); - - //ä¿�存图片队列 - QQueue saveStruct; - - //判断文件夹是å�¦å­˜åœ¨ï¼Œä¸�存在则创建 - void isDirExist(QString fullDirName); - - //存图加入队列 - void addImgToSaveStruct(cv::Mat img2D, QString saveKey, QString savePath); -}; - -extern "C" -{ - Q_DECL_EXPORT Hd_AI_algo_jixing1 * create(); - Q_DECL_EXPORT void destory(Hd_AI_algo_jixing1 * ptr); -} -//ä¿�存图片的结构体 -struct saveImgStruct -{ - cv::Mat out_Mat; - std::string saveKey; //关键字,用于LOG日志 - std::string savePath; //ä¿�存路径 -}; -#endif // Hd_AI_927_2D_module_H diff --git a/BaseModules/Hd_AI_algo_jixing_cam4/base.h b/BaseModules/Hd_AI_algo_jixing_cam4/base.h deleted file mode 100644 index 00bd6b2..0000000 --- a/BaseModules/Hd_AI_algo_jixing_cam4/base.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef __BASECLASS_H__ -#define __BASECLASS_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class Base :public QObject -{ - Q_OBJECT -public: - bool init_flag; //是å�¦åˆ�始化,false,true - bool status = true; //相机状æ€�(判断相机是å�¦æ–­å¼€è¿žæŽ¥ï¼‰ - std::string paras; //传输数æ�® - std::vector m_mat; //传输图片 - std::string moduleName; //模å�—å��ç§° -public: - Base(){} - virtual ~Base(){} - virtual bool readData(std::vector&,QByteArray&){return true;} - virtual bool writeData(std::vector&,QByteArray&){return true;} - virtual bool initParas(QByteArray&){return true;} - virtual bool run() {return true;} - virtual bool checkStatus() { return true; } - -//signals: - //QByteArrayList,根æ�®å®žé™…项目进行解æž�;因ä¸�确定æ¯�个å�‚数的长度,固用队列的方å¼�。æ¯�个QByteArray表示一个值,使用时先转æ�¢ä¸ºQString - //å�‚æ•°,例:返回结果图;相机关键字(SN或userID)+ä¿�存路径+缺陷信æ�¯åˆ—表(缺陷å��称,缺陷ä½�ç½®int(x,y,w,h),画框颜色Scalar(a,b,c),缺陷é�¢ç§¯double) - //void sendResultData(cv::Mat resMat, QJsonObject resQbj); -}; - -/* -//QJsonObject 转QByteArray -{ - QJsonDocument document; - QJsonObject obj; - obj.insert(password, "pwd"); - obj.insert(userName, "usr"); - document.setObject(obj); - QByteArray abyte = document.toJson(QJsonDocument::Compact); -} - -//QByteArray转QJsonObject -{ - QByteArray ba = reply->readAll(); - QJsonDocument doc = QJsonDocument::fromJson(ba); - QJsonObject obj = doc.object(); -} -*/ -/* -//从类中读数æ�®åˆ°å®žä¾‹å¯¹è±¡ -virtual bool readData(std::vector&,QByteArray&){return true;} - - - - - - - - -*/ - -#endif diff --git a/BaseModules/Hd_AI_algo_jixing_cam1/CMakeLists.txt b/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/CMakeLists.txt similarity index 96% rename from BaseModules/Hd_AI_algo_jixing_cam1/CMakeLists.txt rename to BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/CMakeLists.txt index 3f7d257..3f4ea58 100644 --- a/BaseModules/Hd_AI_algo_jixing_cam1/CMakeLists.txt +++ b/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/CMakeLists.txt @@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME) string(TIMESTAMP RUN_TIME) message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME}) -set(DLL_NAMES "opencv" "halcon" "Myalgo""myTools" ) +set(DLL_NAMES "mvs" "opencv") foreach(child ${DLL_NAMES}) LIST(APPEND ENV_INCLUDE ${${child}_include}) LIST(APPEND ENV_LIB ${${child}_lib}) diff --git a/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/Hd_CameraModule_HIK_soft.cpp b/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/Hd_CameraModule_HIK_soft.cpp new file mode 100644 index 0000000..423d8d9 --- /dev/null +++ b/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/Hd_CameraModule_HIK_soft.cpp @@ -0,0 +1,722 @@ +#include "Hd_CameraModule_HIK_soft.h" +using namespace std; +int firstExposureTime = 3000; +int secondExposureTime = 3000; +std::mutex triggerLock; +#include +#include +#include +#include +QByteArray mv_Status = "connected";//0106 新增相机断è�”报警 +//cv::Mat srcImage; +int index = -1; //相机åº�å�· +void* handle; //相机指针 +string Username = ""; +bool m_flag = false; +MV_CC_DEVICE_INFO_LIST m_stDevList;//相机设备 +bool moduleStatus = true; +QQueue queuepic; +cv::Mat matList[1000] = { cv::Mat() }; +//data == "rest_newProductIn"æ—¶è¦�结æ�Ÿrun;机å�°æŠ¥è­¦ï¼Œå�–图超时,å¤�ä½�å�Žé‡�æ–°æ‹�的情况。 +bool ifBreak = false; +//ifRunningå‡�å°‘ifBreak的判断;"rest_newProductIn"时,Logic_camera_thread框架会结æ�Ÿæœªå¤„ç�†å®Œçš„相相机å�–图 +bool ifRunning = false; +bool ifChangeExpourseAndGain = true; +MV_CAM_TRIGGER_SOURCE initTriggerSource = MV_TRIGGER_SOURCE_SOFTWARE; +MV_CAM_TRIGGER_SOURCE currentTriggerSource = MV_TRIGGER_SOURCE_SOFTWARE; + + +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; +} + +#pragma execution_character_set("utf-8") + +QMutex* n_mutex;// = new QMutex(); +//是å�¦ä¸ºæ ‡å‡†é€šä¿¡æµ�程: +//标准通信æµ�程,run函数设置æ›�å…‰/增益;é�žæ ‡å‡†é€šä¿¡æµ�程(简å�•通信æµ�程),回调函数设置æ›�å…‰/增益 +bool ifStandard = false; +//相机å�–图超时时间 +int getImageTimeOut = 1000; +//总å�–图数 +int imgIndex = 0; +//æ›�光值列表 +QQueue expourseTimeList; +//增益列表 +QQueue gainList; + +//0106 断线é‡�连 +void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser); +void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFrameInfo0, void* pUser0); + + +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; + } +} + +//æ�œç´¢æ‰€æœ‰è®¾å¤‡ +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); + for (int i = 0; i < m_stDevList.nDeviceNum; i++) + { + //SN + unsigned char* name = m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chSerialNumber; + //userID + //unsigned char* name=m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chUserDefinedName; + string userName = static_cast((LPCSTR)name); + if (Username == userName) + { + index = i; + break; + } + } + if (MV_OK != nRet) + { + return 0; + } + return -1; +} + +bool connctDevice() +{ + index = -1; + SearchDevice(); + if (index == -1) + { + //未匹é…�到相机 + qDebug() << "[Waring] " << "Hd_CameraModule_HIK_soft not match --CameraName:" << QString::fromStdString(Username); + return false; + } + unsigned char* name = m_stDevList.pDeviceInfo[index]->SpecialInfo.stGigEInfo.chUserDefinedName; + 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_CreateHandle(&handle, m_stDevList.pDeviceInfo[index]); + int nRet = MV_CC_OpenDevice(handle); + ////触å�‘模å¼� + MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE); + 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; +} + +//0106 断线é‡�连 +void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser) +{ + mv_Status = "disconnect"; + qDebug() << "[Error] " << " MV camera disconnects!"; + moduleStatus = false; + if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT) + { + //断开连接 + MV_CC_CloseDevice(handle); + int nRet = MV_CC_DestroyHandle(handle); + handle = nullptr; + BOOL bConnected = FALSE; + while (1) + { + Sleep(100); + if (connctDevice() == true) + { + qWarning() << "[Hd_CameraModule_HIK_soft] " << " Hd_CameraModule_HIK_soft create success again! "; + moduleStatus = true; + break; + } + + } + } +} +void _stdcall ExceptionCB(unsigned int nMesgType, void* pUser) { + mv_Status = "disconnect"; + qDebug() << "[Error] " << " MV camera disconnects!"; + moduleStatus = false; +} + +int RGB2BGR(unsigned char* pRgbData, unsigned int nWidth, unsigned int nHeight) +{ + + if (NULL == pRgbData) + { + return MV_E_PARAMETER; + } + + for (unsigned int j = 0; j < nHeight; j++) + { + for (unsigned int i = 0; i < nWidth; i++) + { + unsigned char red = pRgbData[j * (nWidth * 3) + i * 3]; + pRgbData[j * (nWidth * 3) + i * 3] = pRgbData[j * (nWidth * 3) + i * 3 + 2]; + pRgbData[j * (nWidth * 3) + i * 3 + 2] = red; + } + } + + return MV_OK; + +} + +Hd_CameraModule_HIK_soft* create() +{ + qDebug() << "[INFO] " << "Hd_CameraModule_HIK_soft create success!" ; + return new Hd_CameraModule_HIK_soft; +} + +void destory(Hd_CameraModule_HIK_soft * ptr) +{ + if(ptr) + { + delete ptr; + ptr = nullptr; + } + qDebug() << "[INFO] " << "Hd_CameraModule_HIK_soft destory success!"; +} +//回调函数; +//ç»�测试,相机åƒ�ç´ æ ¼å¼�Mono8ã€�RGB8是å�¯ä»¥æ­£å¸¸è½¬æ�¢çš„,YUV422还需è¦�优化;RGB8æ ¼å¼�比YUV422帧率低;BGRæ ¼å¼�会导致异色问题 +void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFrameInfo0, void* pUser0) +{ + SetExposureTime(secondExposureTime); + triggerLock.unlock(); + n_mutex->lock(); + double time_Start = (double)clock(); + int frameNum = 0; + cv::Mat srcImage = cv::Mat(); + 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); + } + + ////获å�–的是RGB8图 + //else if (pFrameInfo0->enPixelType == PixelType_Gvsp_RGB8_Packed) + //{ + // cv::Mat dst = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3, pData0); + // //cv::cvtColor(matimage, matimage, cv::COLOR_RGB2BGR); + // srcImage = cv::Mat::zeros(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3); + // std::vector channels; + // cv::split(dst, channels);//分割matimage的通é�“ + // std::vector dstchannels; + // for (int i = 2; i >= 0; i--) + // { + // dstchannels.push_back(channels[i]); + // } + // merge(dstchannels, srcImage); + //} + + 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); + } + + m_flag = true; + queuepic.push_back(srcImage.clone()); + n_mutex->unlock(); + pData0 = { 0 }; + double time_End = (double)clock(); + qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getImg,Time:" << (time_End - time_Start) << "ms" + << "--CameraName:" << QString::fromStdString(Username) << " imgIndex:" << imgIndex << "nFrameNum : " << frameNum; + /*QString savePath = "../runtime/Bin_DEVICE/testImg/camera_" + QString::number(imgIndex + 1)+".png"; + cv::Mat resizeS; + cv::resize(srcImage, resizeS, cv::Size(), 0.1, 0.1); + cv::imwrite(savePath.toStdString(), resizeS);*/ +} + +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); +} +Hd_CameraModule_HIK_soft::Hd_CameraModule_HIK_soft() +{ + n_mutex = new QMutex(); + m_thread = new MyThread; +} +//关闭设备 +void CloseDevice() +{ + MV_CC_StopGrabbing(handle); + MV_CC_CloseDevice(handle); + MV_CC_DestroyHandle(handle); + handle = nullptr; //此处注释掉的è¯�,软件断开å†�连接,回调函数ä¸�出图 +} + +Hd_CameraModule_HIK_soft::~Hd_CameraModule_HIK_soft() +{ + m_flag = true; + Sleep(10); + CloseDevice(); + if (n_mutex) + { + delete n_mutex; + n_mutex = nullptr; + } + if(m_thread) + { + m_thread->exit(); + m_thread->wait(1); + delete m_thread; + m_thread = nullptr; + } + + qDebug() << "[INFO] " << " delete success!"; +} +//从类中读数æ�®åˆ°å®žä¾‹å¯¹è±¡ +bool Hd_CameraModule_HIK_soft::readData(std::vector &mat,QByteArray &data) +{ + if (queuepic.isEmpty()) + { + qCritical() << __FUNCTION__ << " line:" <<__LINE__ << " srcImage is null"; + return false; + } + n_mutex->lock(); + cv::Mat img = cv::Mat(); + queuepic.dequeue().copyTo(img); + mat.push_back(img.clone()); + n_mutex->unlock(); + QString qimgIndex = "imgIndex_" + QString::number(imgIndex-1)+"_中文测试"; + data = qimgIndex.toLocal8Bit(); + qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg readData--CameraName:" << QString::fromStdString(Username) << "--imgIndex : " << imgIndex-1; + return true; +} +//实例对象把数æ�®å†™å…¥åˆ°ç±» +bool Hd_CameraModule_HIK_soft::writeData(std::vector &mat,QByteArray &data) +{ + //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 + { + m_flag = false; + //expourseTimeList.clear(); + //gainList.clear(); + } + if (data == "ifChangeExpourseAndGain_false") + ifChangeExpourseAndGain = false; + else + ifChangeExpourseAndGain = true; + if (data.contains("SetExposureTime_")) + { + QByteArrayList dataList = data.split('#'); + for (int i = 0; i < dataList.size(); i++) + { + if (dataList[i].contains("SetExposureTime_")) + { + int value = byteArrayToUnicode(dataList[i]).split("SetExposureTime_")[1].toInt(); + SetExposureTime(value); + } + if (dataList[i].contains("SetGain_")) + { + double value = byteArrayToUnicode(dataList[i]).split("SetGain_")[1].toInt(); + SetGain(value); + } + if (dataList[i].contains("TriggerMode_")) + { + QString value = byteArrayToUnicode(dataList[i]).split("TriggerMode_")[1]; + if (value == "软触å�‘") + ////触å�‘模å¼� + { + MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE); + currentTriggerSource = MV_TRIGGER_SOURCE_SOFTWARE; + } + else + { + MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_LINE0); + currentTriggerSource = MV_TRIGGER_SOURCE_LINE0; + } + } + } + } + //调试模å¼�下,data==ifChangeExpourseAndGain_falseï¼›é�žè°ƒè¯•模å¼�è¿�行时,dataä¸�包å�«SetExposureTime_ + else if (data != "ifChangeExpourseAndGain_false" && initTriggerSource != currentTriggerSource) + { + MV_CC_SetEnumValue(handle, "TriggerSource", initTriggerSource); + currentTriggerSource = initTriggerSource; + } + + + /*data.append("SetExposureTime_" + ui.spinBox->text() + "#"); + data.append("SetGain_" + ui.doubleSpinBox->text() + "#"); + data.append("TriggerMode_" + ui.comboBox_triggerMode->currentText());*/ + + + qDebug() << "Hd_CameraModule_HIK_soft::writeData::" << data; + + m_flag = false; + //Username = data.toStdString(); + return true; +} + + +//ä¼ å…¥initParas函数,格å¼�为:相机key+å�‚æ•°å��1#å�‚数值1#å�‚数值2+å�‚æ•°å��2#å�‚数值1... +bool Hd_CameraModule_HIK_soft::initParas(QByteArray& initData) +{ + QByteArrayList valueList = initData.split('+'); + Username = valueList[0]; + imgIndex = 0; + + expourseTimeList.clear(); + gainList.clear(); + + + bool ifOk = true; + if (handle == NULL) + ifOk = connctDevice(); + if (ifOk == false) + return false; + 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()); + } + + if (valuei.contains("触å�‘æ–¹å¼�")) + { + QStringList valueL = valuei.split('#'); + if (valueL.size() > 1) + if (valueL[1].toInt() >= 0) + if (valueL[1] == "软触å�‘") + { + MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE); + currentTriggerSource = MV_TRIGGER_SOURCE_SOFTWARE; + initTriggerSource = MV_TRIGGER_SOURCE_SOFTWARE; + } + else + { + MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_LINE0); + currentTriggerSource = MV_TRIGGER_SOURCE_LINE0; + initTriggerSource = MV_TRIGGER_SOURCE_LINE0; + } + } + } + + if (ifOk == true) + { + if (expourseTimeList.size() > 0) + SetExposureTime(expourseTimeList[0]); + if (gainList.size() > 0) + SetGain(gainList[0]); + } + imgIndex = 0; + if (ifOk == true) + { + MVCC_FLOATVALUE mf = { 0 }; + MV_CC_GetFloatValue(handle, "ExposureTime", &mf); + std::cout << "ExposureTime::" << mf.fCurValue << std::endl; + mf = { 0 }; + MV_CC_GetFloatValue(handle, "Gain", &mf); + std::cout << "Gain::" << mf.fCurValue << std::endl; + MVCC_INTVALUE mI = { 0 }; + MV_CC_GetIntValue(handle, "OffsetX", &mI); + std::cout << "OffsetX::" << mI.nCurValue << std::endl; + mI = { 0 }; + MV_CC_GetIntValue(handle, "OffsetY", &mI); + std::cout << "OffsetY::" << mI.nCurValue << std::endl; + mI = { 0 }; + MV_CC_GetIntValue(handle, "Width", &mI); + std::cout << "Width::" << mI.nCurValue << std::endl; + mI = { 0 }; + MV_CC_GetIntValue(handle, "Height", &mI); + std::cout << "Height::" << mI.nCurValue << std::endl; + MVCC_ENUMVALUE me = { 0 }; + MV_CC_GetEnumValue(handle,"BalanceWhiteAuto",&me); //自动白平衡 + std::cout << "BalanceWhiteAuto::" << me.nCurValue << std::endl; + + } + + return ifOk; +} +bool Hd_CameraModule_HIK_soft::run() +{ + if (imgIndex == expourseTimeList.size()) + imgIndex = 0; + //Sleep(100); + qDebug() << "[INFO] " << " run start" <lock(); + m_flag = false; + //Sleep(2); + //n_mutex->unlock(); + //m_thread->run(); //start()线程è¿�行,频率高时有低概率无å“�应; + + if (currentTriggerSource == MV_TRIGGER_SOURCE_SOFTWARE) + { + MV_CC_SetCommandValue(handle, "TriggerSoftware"); + qDebug() << "[INFO] " << "TriggerSoftware"; + } + else + qDebug() << "[INFO] " << "TriggerHardware"; + //MV_CC_SetCommandValue(handle, "TriggerSoftware"); + //Sleep(15); + int mytime = 0; + qDebug() << "[INFO] " << " waite Img" << QString::fromStdString(Username); + while (true) + { + if (moduleStatus == false || mytime++ > getImageTimeOut || ifBreak == true )//|| m_flag==true) + { + result = false; + break; + } + n_mutex->lock(); + if (queuepic.size() > 0) + { + n_mutex->unlock(); + result = true; + break; + } + n_mutex->unlock(); + Sleep(1); + } + Sleep(1); + + //qDebug() << "[INFO] " << " expourseTimeList " << QString::fromStdString(Username); + //软触å�‘,ä¸�考虑误触å�‘ã€�æ¼�触å�‘ + if (ifChangeExpourseAndGain == true) + { + imgIndex++; + if (expourseTimeList.size() > 1 && expourseTimeList[imgIndex % expourseTimeList.size()] != expourseTimeList[(imgIndex - 1) % expourseTimeList.size()]) + SetExposureTime(expourseTimeList[imgIndex % expourseTimeList.size()]); + //Sleep(1); + if (gainList.size() > 1 && gainList[imgIndex % gainList.size()] != gainList[(imgIndex - 1) % gainList.size()]) + SetGain(gainList[imgIndex % gainList.size()]); + //Sleep(1); + } + if (result == false) + { + QString currPath = "../runtime/Bin_DEVICE/testImg/testImg_"; + if (ifChangeExpourseAndGain == true) + currPath +=QString::number(imgIndex-1); + else + currPath += QString::number(imgIndex); + currPath += ".jpg"; + cv::Mat readMat = cv::imread(currPath.toStdString()); + queuepic.push_back(readMat); + qDebug() << "å�–图失败,读å�–图片:" << currPath; + result = true; + } + + } + catch (QString ev) + { + qDebug() << "[Error] " << " ev:" << ev ; + } + qDebug() << "[INFO] " << __LINE__ << " run end" ; + return result; +} + +//相机连接状æ€�:正常连接或断开 +bool Hd_CameraModule_HIK_soft::checkStatus() +{ + //status = moduleStatus; + return moduleStatus; +} + +void MyThread::run() +{ + SetExposureTime(firstExposureTime);//第一次æ›�光数值 + MV_CC_SetCommandValue(handle, "TriggerSoftware"); + triggerLock.lock(); + triggerLock.lock(); + MV_CC_SetCommandValue(handle, "TriggerSoftware"); +} diff --git a/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/Hd_CameraModule_HIK_soft.h b/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/Hd_CameraModule_HIK_soft.h new file mode 100644 index 0000000..51b82b9 --- /dev/null +++ b/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/Hd_CameraModule_HIK_soft.h @@ -0,0 +1,59 @@ +#ifndef Hd_CameraModule_HIK_soft_H +#define Hd_CameraModule_HIK_soft_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "base.h" + +using namespace cv; +#pragma execution_character_set("utf-8") + + +class MyThread; +class Hd_CameraModule_HIK_soft :public Base +{ +public: + Hd_CameraModule_HIK_soft(); + virtual ~Hd_CameraModule_HIK_soft(); + //从类中读数æ�®åˆ°å®žä¾‹å¯¹è±¡ + bool readData(std::vector& mat, QByteArray& data); + //实例对象把数æ�®å†™å…¥åˆ°ç±» + bool writeData(std::vector& mat, QByteArray& data); + bool initParas(QByteArray&); + bool run(); + bool checkStatus(); +private: + MyThread *m_thread = nullptr; +}; + +class MyThread : public QThread +{ + Q_OBJECT +public: + explicit MyThread(QObject *parent = nullptr):m_obj(parent){} + void run(); +private: + QObject *m_obj; +signals: + +}; + +extern "C" +{ +Q_DECL_EXPORT Hd_CameraModule_HIK_soft * create(); +Q_DECL_EXPORT void destory(Hd_CameraModule_HIK_soft * ptr); +} + +#endif // Hd_CameraModule_HIK_soft_H diff --git a/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/base.h b/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/base.h new file mode 100644 index 0000000..510c3df --- /dev/null +++ b/BaseModules/Hd_CameraModule_HIK_soft_TakeTwo/base.h @@ -0,0 +1,33 @@ +#ifndef __BASECLASS_H__ +#define __BASECLASS_H__ + +#include +#include +#include +#include +#include +#include + +class Base :public QObject +{ + Q_OBJECT +public: + bool init_flag; //是å�¦åˆ�始化,false,true + bool status = true; //相机状æ€�(判断相机是å�¦æ–­å¼€è¿žæŽ¥ï¼‰ + std::string paras; //传输数æ�® + std::vector m_mat; //传输图片 + std::string moduleName; //模å�—å��ç§° +public: + Base(){} + virtual ~Base(){} + virtual bool readData(std::vector&,QByteArray&){return true;} + virtual bool writeData(std::vector&,QByteArray&){return true;} + virtual bool initParas(QByteArray&){return true;} + virtual bool run() {return true;} + virtual bool checkStatus() { return true; } +signals: + void trigged(bool); +}; + + +#endif diff --git a/CMakeLists.txt b/CMakeLists.txt index 695d985..2b14a71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,7 @@ if(ON) else() SET( ${child}_target_link "opencv_world410" ) endif() - elseif(${child} MATCHES "Myalgo") + elseif(${child} MATCHES "halconAlgo") SET( ${child}_target_link "Inspection" ) elseif(${child} MATCHES "basler") SET( ${child}_target_link diff --git a/env/Myalgo/dll/Inspection.dll b/env/Myalgo/dll/Inspection.dll deleted file mode 100644 index 5c6481fb8e3925719210a53b7202ab2bceb6f98a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106496 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π7APqC};>#-xvWi`ntv4pXWg;Lki=l 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 diff --git a/env/Myalgo/include/Myalgo.h b/env/Myalgo/include/Myalgo.h deleted file mode 100644 index 32028fe..0000000 --- a/env/Myalgo/include/Myalgo.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once -#include -#include -#include - -//#include -//#include - -using namespace HalconCpp; - -#if 1 ºó¶Ëµ÷Óú¯Êý - -/* - ho_Image:ÊäÈëԭͼ - hv_out_Value£ºÊä³ö¼ì²â½á¹û 1ΪÂÁ£¬2Ϊͭ - hv_Make£ºËã·¨Ö´ÐÐ״̬-1ΪËã·¨NG£¬1ΪËã·¨ok - ¼«ÐÔ¼ì²âº¯Êý - ÈýЭ»ų́ -*/ -extern "C" __declspec(dllexport) void _stdcall _628_1_Polarity_detection(HObject ho_Image, HTuple* hv_out_Value, HTuple* hv_Make); - - - - -/* -* ho_Image£ºÊäÈëͼƬ£¨Ô­Í¼£© -* hv_model£º¸³ÖµÎª1ʱÊÇ»ù×¼±ê¶¨Ä£Ê½£¬0ΪÕý³£¼ì²âģʽ -* hv_BenchmarkFile£º»ù×¼±ê¶¨ÎļþµÄ·¾¶ -* hv_NinePointDocument£º¾ÅµãÎļþµÄ·¾¶ -*hv_CameraNumber£ºÉ϶¤Ïà»ú±àºÅ -* hv_out_Cirle£ºÊä³ö·Å¶¤¿×µÄÔ²ÐÄx£¬Ô²ÐÄy£¬°ë¾¶¡£Êý×éÐÎʽ -* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐУ¬Êä³öΪ2Ϊ»ù×¼±ê¶¨³É¹¦ -* hv_offset_x£ºxÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î -* hv_offset_y£ºyÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î -* É϶¤Òýµ¼º¯Êý -*/ - -extern "C" __declspec(dllexport) void _stdcall _628_SealingNails(HObject ho_Image, HTuple hv_model, HTuple hv_BenchmarkFile, - HTuple hv_NinePointDocument, HTuple hv_CameraNumber, HTuple* hv_out_Cirle, HTuple* hv_Make, - HTuple* hv_offset_x, HTuple* hv_offset_y); - -/* -* ho_Image£ºÊäÈëͼƬ£¨Ô­Í¼£© -* hv_model£º¸³ÖµÎª1ʱÊÇ»ù×¼±ê¶¨Ä£Ê½£¬0ΪÕý³£¼ì²âģʽ -* hv_BenchmarkFile£º»ù×¼±ê¶¨ÎļþµÄ·¾¶ -* hv_NinePointDocument£º¾ÅµãÎļþµÄ·¾¶ -*hv_CameraNumber£ºÔ¤º¸Ïà»ú±àºÅ -* hv_out_Cirle£ºÊä³ö·Å¶¤¿×µÄÔ²ÐÄx£¬Ô²ÐÄy£¬°ë¾¶¡£Êý×éÐÎʽ -* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐУ¬Êä³öΪ2Ϊ»ù×¼±ê¶¨³É¹¦ -* hv_offset_x£ºxÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î -* hv_offset_y£ºyÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î -* hv_Text:Êä³ö±¨¾¯ÐÅÏ¢°üÀ¨£¨ok£¬ÎÞ¶¤£¬Ç̶¤£¬·´¶¤£© -* Ô¤º¸º¯Êý -*/ - -extern "C" __declspec(dllexport) void _stdcall _628_yuhan(HObject ho_Image, HTuple hv_Model, HTuple hv_BenchmarkFile, HTuple hv_NinePointDocument, - HTuple hv_CameraNumber, HTuple* hv_out_Cirle, HTuple* hv_Make, HTuple* hv_offset_x, - HTuple* hv_offset_y, HTuple* hv_Text); - - -/* -* ho_Image£ºÊäÈëͼƬ£¨Ô­Í¼£© -* hv_model£º¸³ÖµÎª1ʱÊÇ»ù×¼±ê¶¨Ä£Ê½£¬0ΪÕý³£¼ì²âģʽ -* hv_BenchmarkFile£º»ù×¼±ê¶¨ÎļþµÄ·¾¶ -* hv_NinePointDocument£º¾ÅµãÎļþµÄ·¾¶ -*hv_CameraNumber£ºÔ¤º¸Ïà»ú±àºÅ -* hv_out_Cirle£ºÊä³ö·Å¶¤¿×µÄÔ²ÐÄx£¬Ô²ÐÄy£¬°ë¾¶¡£Êý×éÐÎʽ -* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐУ¬Êä³öΪ2Ϊ»ù×¼±ê¶¨³É¹¦ -* hv_offset_x£ºxÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î -* hv_offset_y£ºyÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î -* ÖÕº¸º¯Êý -*/ -extern "C" __declspec(dllexport) void _stdcall _628_FinalWelding(HObject ho_Image, HTuple hv_model, HTuple hv_BenchmarkFile, - HTuple hv_NinePointDocument, HTuple hv_CameraNumber, HTuple* hv_out_Cirle, HTuple* hv_Make, - HTuple* hv_offset_x, HTuple* hv_offset_y); -#endif - -#if 1 halconµ÷Óú¯Êý -void gen_arrow_contour_xld(HObject* ho_Arrow, HTuple hv_Row1, HTuple hv_Column1, - HTuple hv_Row2, HTuple hv_Column2, HTuple hv_HeadLength, HTuple hv_HeadWidth); -void Get_Rectangle2_Corner_new(HObject ho_Rectangle, HTuple* hv_out_Row, HTuple* hv_out_Col); - -void pts_to_best_line(HObject* ho_Line, HTuple hv_Rows, HTuple hv_Cols, HTuple hv_ActiveNum, - HTuple* hv_Row1, HTuple* hv_Column1, HTuple* hv_Row2, HTuple* hv_Column2); -void rake(HObject ho_Image, HObject* ho_Regions, HTuple hv_Elements, HTuple hv_DetectHeight, - HTuple hv_DetectWidth, HTuple hv_Sigma, HTuple hv_Threshold, HTuple hv_Transition, - HTuple hv_Select, HTuple hv_Row1, HTuple hv_Column1, HTuple hv_Row2, HTuple hv_Column2, - HTuple* hv_ResultRow, HTuple* hv_ResultColumn); - -void pts_to_best_circle(HObject* ho_Circle, HTuple hv_Rows, HTuple hv_Cols, HTuple hv_ArcType, - HTuple hv_ActiveNum, HTuple* hv_RowCenter, HTuple* hv_ColCenter, HTuple* hv_Radius, - HTuple* hv_StartPhi, HTuple* hv_EndPhi, HTuple* hv_PointOrder, HTuple* hv_ArcAngle); - -void region_to_spoke(HObject ho_Region, HTuple hv_Offset, HTuple* hv_SpokeRows, - HTuple* hv_SpokeCols); - -void spoke(HObject ho_Image, HObject* ho_Regions, HTuple hv_Elements, HTuple hv_DetectHeight, - HTuple hv_DetectWidth, HTuple hv_Sigma, HTuple hv_Threshold, HTuple hv_Transition, - HTuple hv_Select, HTuple hv_ROIRows, HTuple hv_ROICols, HTuple hv_Direct, HTuple* hv_ResultRow, - HTuple* hv_ResultColumn, HTuple* hv_ArcType); - -void _628_PreWelded(HObject ho_Image, HTuple hv_model, HTuple hv_BenchmarkFile, - HTuple hv_NinePointDocument, HTuple hv_CameraNumber, HTuple* hv_out_Cirle, HTuple* hv_Make, - HTuple* hv_offset_x, HTuple* hv_offset_y); -#endif - - - - - diff --git a/env/Myalgo/lib/Inspection.lib b/env/Myalgo/lib/Inspection.lib deleted file mode 100644 index d9d48677032e5fcf26ed4ee2a784dda830ab7e57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2430 zcmcIl%}*0S6#sP#Z9zi_;DunaL=xd3^n*5<5K|P54Nyoa=tbAHTVa#!N7{10ix+|y zFCI-e;l;mzlL!6)6FnIdFD4pdqA?~WUh%!|%x>3~FSV1*&b&9jo%fsfF*7`+S8{7t zyC+m{yA<)tQVNSnEF2ZH``rM}0LnhlIRpe&fKb@(T>}93(2m`MyFhSP(^B(`3z@7o zb7SdxCbgJd$Y`lzwVcn@%u*4WmR_ElYsTQQ3$h{ETg&NLZDu+<4J{G9tlcz=x^+8m z8D?>nwlNE3t%aVE8|!O2TXG;m!D~x--J%WBx@lD#AznQrBidrg(ko_dLo@O;p&z(5zUL*p(jQWy|K2LkAX4~jGQ+x}_E=MWDypH}+p z?}FFh>((^fSR58cFC`am6FVw9+{76-ENenNF1zF5gp=LImLHF{hd%WAD2K_v+{TUk zgZ0&sC0hb!X!2AFVoaj<+PG=xHGL#1m#7r*milL*@Y9$?cu(LGLXBRUC}dCKSf7Nt zN1?|#P{676cn@_E{k@zXygj!bjG}+DZ{EyRO4ZWCnmU>pQ|D6YS$o<0Jxd~U;SS0l zo-qeXGn#n~5tCf0P$tU#n?B#cLE~Qp2Xj;)Po4zotk9Gu536-e9se)Loe#?Q+w`;d&hCTZO5Ly{zw+=Xt(y<5%m@qPO8_dEC{JfA}Q-_ zQtG&_-%CM^jBAI7PvTvbIQ-B1EaAN7{91F(8e2cU{ro;wKWoPkuY)&|ICW&5l2BdC zfx&z4hRL#zZkp!TryUl5eJy-qi;A@9c}o7(;-q{m8qWCS#q&3VWYI4z+K<#9rhWrn CQVe|n diff --git a/env/halconAlgo/dll/Inspection.dll b/env/halconAlgo/dll/Inspection.dll new file mode 100644 index 0000000000000000000000000000000000000000..f906aa38b5b252107c4d4e1be7226f4238e78d33 GIT binary patch literal 320000 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

vyP2lNc$;%&HCOqV-{6FXJHoI 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�<6jq;fT};UlPGL;hHhB!6 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 C0-5Rn literal 0 HcmV?d00001 diff --git a/env/halconAlgo/include/algo.h b/env/halconAlgo/include/algo.h new file mode 100644 index 0000000..892636f --- /dev/null +++ b/env/halconAlgo/include/algo.h @@ -0,0 +1,272 @@ +#pragma once +#include +#include +#include + +//#include +//#include + +using namespace HalconCpp; + +#if 1 ºó¶Ëµ÷Óú¯Êý + +/* + ho_Image:ÊäÈëԭͼ + hv_out_Value£ºÊä³ö¼ì²â½á¹û 1ΪÂÁ£¬2Ϊͭ + hv_Make£ºËã·¨Ö´ÐÐ״̬-1ΪËã·¨NG£¬1ΪËã·¨ok + ¼«ÐÔ¼ì²âº¯Êý + Ô¤º¸ÈýЭ»ų́ +*/ +extern "C" __declspec(dllexport) void _stdcall _628_1_Polarity_detection(HObject ho_Image, HTuple* hv_out_Value, HTuple* hv_Make); + +/* +* ho_Image£ºÊäÈëͼƬ£¨Ô­Í¼£© +* hv_NinePointDocument£º¾ÅµãÎļþµÄ·¾¶ +* hv_SetNumber:ÉèÖýº¶¤µÄ×îС¸öÊý +* hv_Circle_Point£ºÊä³ö·Å¶¤¿×µÄÔ²ÐÄx£¬Ô²ÐÄy£¬°ë¾¶¡£Êý×éÐÎʽ +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐÐ +*hv_Out_Roboot1£ºÎü×ì1-> Îü×ì±àºÅ,x¾ø¶Ô×ø±ê£¬y¾ø¶Ô×ø±ê +* hv_Out_Roboot2£ºÎü×ì2->Îü×ì±àºÅ£¬x¾ø¶Ô×ø±ê£¬y¾ø¶Ô×ø±ê +* hv_Out_Roboot3£ºÎü×ì3->Îü×ì±àºÅ£¬x¾ø¶Ô×ø±ê£¬y¾ø¶Ô×ø±ê +* »úÆ÷ÈËÒýµ¼º¯Êý +* ÈýЭ»ų́ +*/ +extern "C" __declspec(dllexport) void _stdcall _628_BootTheMachine(HObject ho_Image, HTuple hv_NinePointDocument, HTuple hv_SetNumber, + HTuple* hv_Circle_Point, HTuple* hv_Make, HTuple* hv_Out_Roboot1, HTuple* hv_Out_Roboot2,HTuple* hv_Out_Roboot3); + +/* +*ho_Image£ºÊäÈëͼƬ£¨Ô­Í¼£© +* hv_Pix£ºÏñËØ¾«¶È +* hv_out_line:Êä³öÖ±Ïß×ø±ê +* hv_distance£ºÊä³ö²âÁ¿Öµ ->¸ß£¬¿í¡£Êý×éÐÎʽ +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐÐ +* Í­¼«¶ú²Ã¼ô²âÁ¿º¯Êý +* ÈýЭԤº¸»ų́ +*/ + +extern "C" __declspec(dllexport) void _stdcall cs_628_jier_T(HObject ho_Image, HTuple hv_Pix, HTuple* hv_out_line, HTuple* hv_out_Soldering_line, + HTuple* hv_distance, HTuple* hv_Make); + + + +/* +* ho_Image£ºÊäÈëͼƬ£¨Ô­Í¼£© +* hv_model£º¸³ÖµÎª1ʱÊÇ»ù×¼±ê¶¨Ä£Ê½£¬0ΪÕý³£¼ì²âģʽ +* hv_BenchmarkFile£º»ù×¼±ê¶¨ÎļþµÄ·¾¶ +* hv_NinePointDocument£º¾ÅµãÎļþµÄ·¾¶ +*hv_CameraNumber£ºÉ϶¤Ïà»ú±àºÅ +* hv_out_Cirle£ºÊä³ö·Å¶¤¿×µÄÔ²ÐÄx£¬Ô²ÐÄy£¬°ë¾¶¡£Êý×éÐÎʽ +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐУ¬Êä³öΪ2Ϊ»ù×¼±ê¶¨³É¹¦ +* hv_offset_x£ºxÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î +* hv_offset_y£ºyÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î +* ´ò¶¤¶¤Òýµ¼º¯Êý +* ÈýЭµÄ»ų́ +*/ + +extern "C" __declspec(dllexport) void _stdcall _628_NailingPosition(HObject ho_Image, HTuple hv_model, HTuple hv_BenchmarkFile, + HTuple hv_NinePointDocument, HTuple hv_CameraNumber, HTuple* hv_out_Cirle, HTuple* hv_Make, + HTuple* hv_offset_x, HTuple* hv_offset_y); + + +/* + ho_Image:ÊäÈëԭͼ + hv_out_Value£ºÊä³ö¼ì²â½á¹û[1,1] .1ΪÂÁ£¬[2,2] 2Ϊͭ + hv_Make£ºËã·¨Ö´ÐÐ״̬-1ΪËã·¨NG£¬1ΪËã·¨ok + ¼«ÐÔ¼ì²âº¯Êý + ÖÕº¸ÈýЭ»ų́ +*/ +extern "C" __declspec(dllexport) void _stdcall _628_2_Polarity_detection(HObject ho_Image, HTuple* hv_out_Value, HTuple* hv_Make); + +/* +* ho_Image_L£ºÊäÈëͼƬÂÁ +* ho_Image_T£ºÊäÈëͼƬͭ +* hv_Pix_T:Í­¼«ÏñËØ¾«¶È +* hv_Pix_L:ÂÁ¼«ÏñËØ¾«¶È +* hv_Out_Vale_L£ºÊä³öÂÁ¼«²âÁ¿Öµ°üÀ¨Á½¸öÖµ +* hv_Out_Line_L£ºÊä³öÂÁ¼«»®Ïß×ø±ê +* hv_Out_Vale_T£ºÊä³öÂÁ¼«²âÁ¿Öµ°üÀ¨Á½¸öÖµ +* hv_Out_Line_T£ºÊä³öÍ­¼«¼«»®Ïß×ø±ê +* hv_Out_extremum_Value£ºÊä³öÁ½¼«Ö®¼äµÄ¾àÀë +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐÐ +* Ô¤º¸º¸Ç°²âÁ¿º¯Êý +* ÈýЭµÄ»ų́ +*/ +extern "C" __declspec(dllexport) void _stdcall _628_2_BeforeWelding_Distnce(HObject ho_Image_L, HObject ho_Image_T, HTuple hv_Pix_T, + HTuple hv_Pix_L, HTuple* hv_Out_Vale_L, HTuple* hv_Out_Line_L, HTuple* hv_Out_Vale_T, + HTuple* hv_Out_Line_T, HTuple* hv_Out_extremum_Value, HTuple* hv_Makes); + +/* +* ho_Image £ºÊäÈëͼƬÂÁ¼« +* ho_ImageSeg £ºÊäÈëͼƬsegͼ£¨¶þֵͼ£© +* hv_Pix : ÂÁ¼«ÏñËØ¾«¶È +* hv_Out_TopLeft_Line : ×óÉÏÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_TopLeft_Value £º×óÉÏÊä³öµÄ²âÁ¿Öµ£¨2¸öÖµ£© +* hv_Out_TopRight_Line £ºÓÒÉÏÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_TopRight_Value £ºÓÒÉÏÊä³öµÄ²âÁ¿Öµ£¨2¸öÖµ£© +* hv_Out_BottomLeft_Line £º×óÏÂÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_BottomLeft_Value £º×óÏÂÊä³öµÄ²âÁ¿Öµ£¨2¸öÖµ£© +** hv_Out_BottomRight_Line £ºÓÒÏÂÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_BottomRight_Value £ºÓÒÏÂÊä³öµÄ²âÁ¿Öµ£¨2¸öÖµ£© +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐÐ +* Ô¤º¸º¸ºó²âÁ¿ÂÁ¼«º¯Êý +* ÈýЭµÄ»ų́ +*/ + +extern "C" __declspec(dllexport) void _stdcall _628_AfterWelding_Distance_L(HObject ho_Image, HObject ho_ImageSeg, HTuple hv_Pix, + HTuple* hv_Out_TopLeft_Line, HTuple* hv_Out_TopLeft_Value, HTuple* hv_Out_TopRight_Line, + HTuple* hv_Out_TopRight_Value, HTuple* hv_Out_BottomLeft_Line, HTuple* hv_Out_BottomLeft_Value, + HTuple* hv_Out_BottomRight_Line, HTuple* hv_Out_BottomRight_Value, HTuple* hv_Make); + +/* +* ho_Image £ºÊäÈëͼƬÂÁ¼« +* ho_ImageSeg £ºÊäÈëͼƬsegͼ£¨¶þֵͼ£© +* hv_Pix : ÂÁ¼«ÏñËØ¾«¶È +* hv_Out_TopLeft_Line : ×óÉÏÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_TopLeft_Value £º×óÉÏÊä³öµÄ²âÁ¿Öµ£¨2¸öÖµ£© +* hv_Out_TopRight_Line £ºÓÒÉÏÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_TopRight_Value £ºÓÒÉÏÊä³öµÄ²âÁ¿Öµ£¨2¸öÖµ£© +* hv_Out_BottomLeft_Line £º×óÏÂÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_BottomLeft_Value £º×óÏÂÊä³öµÄ²âÁ¿Öµ£¨2¸öÖµ£© +** hv_Out_BottomRight_Line £ºÓÒÏÂÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_BottomRight_Value £ºÓÒÏÂÊä³öµÄ²âÁ¿Öµ£¨2¸öÖµ£© +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐÐ +* Ô¤º¸º¸ºó²âÁ¿Í­¼«º¯Êý +* ÈýЭµÄ»ų́ +*/ + +extern "C" __declspec(dllexport) void _stdcall _628_AfterWelding_Distance_T(HObject ho_Image, HObject ho_ImageSeg, HTuple hv_Pix, + HTuple* hv_Out_TopLeft_Line, HTuple* hv_Out_TopLeft_Value, HTuple* hv_Out_TopRight_Line, + HTuple* hv_Out_TopRight_Value, HTuple* hv_Out_BottomLeft_Line, HTuple* hv_Out_BottomLeft_Value, + HTuple* hv_Out_BottomRight_Line, HTuple* hv_Out_BottomRight_Value, HTuple* hv_Make); + + + + + + + + + + + + + + + + + + +/* +* ho_Image£ºÊäÈëͼƬ£¨Ô­Í¼£© +* hv_model£º¸³ÖµÎª1ʱÊÇ»ù×¼±ê¶¨Ä£Ê½£¬0ΪÕý³£¼ì²âģʽ +* hv_BenchmarkFile£º»ù×¼±ê¶¨ÎļþµÄ·¾¶ +* hv_NinePointDocument£º¾ÅµãÎļþµÄ·¾¶ +*hv_CameraNumber£ºÉ϶¤Ïà»ú±àºÅ +* hv_out_Cirle£ºÊä³ö·Å¶¤¿×µÄÔ²ÐÄx£¬Ô²ÐÄy£¬°ë¾¶¡£Êý×éÐÎʽ +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐУ¬Êä³öΪ2Ϊ»ù×¼±ê¶¨³É¹¦ +* hv_offset_x£ºxÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î +* hv_offset_y£ºyÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î +* É϶¤Òýµ¼º¯Êý +* Ó®ºÏµÄ»ų́ +*/ + +extern "C" __declspec(dllexport) void _stdcall _628_SealingNails(HObject ho_Image, HTuple hv_model, HTuple hv_BenchmarkFile, + HTuple hv_NinePointDocument, HTuple hv_CameraNumber, HTuple* hv_out_Cirle, HTuple* hv_Make, + HTuple* hv_offset_x, HTuple* hv_offset_y); + +/* +* ho_Image£ºÊäÈëͼƬ£¨Ô­Í¼£© +* hv_model£º¸³ÖµÎª1ʱÊÇ»ù×¼±ê¶¨Ä£Ê½£¬0ΪÕý³£¼ì²âģʽ +* hv_BenchmarkFile£º»ù×¼±ê¶¨ÎļþµÄ·¾¶ +* hv_NinePointDocument£º¾ÅµãÎļþµÄ·¾¶ +*hv_CameraNumber£ºÔ¤º¸Ïà»ú±àºÅ +* hv_out_Cirle£ºÊä³ö·Å¶¤¿×µÄÔ²ÐÄx£¬Ô²ÐÄy£¬°ë¾¶¡£Êý×éÐÎʽ +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐУ¬Êä³öΪ2Ϊ»ù×¼±ê¶¨³É¹¦ +* hv_offset_x£ºxÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î +* hv_offset_y£ºyÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î +* hv_Text:Êä³ö±¨¾¯ÐÅÏ¢°üÀ¨£¨ok£¬ÎÞ¶¤£¬Ç̶¤£¬·´¶¤£© +* Ó®ºÏ»ų́ +* Ô¤º¸º¯Êý +*/ +extern "C" __declspec(dllexport) void _stdcall _628_yuhan(HObject ho_Image, HTuple hv_Model, HTuple hv_BenchmarkFile, HTuple hv_NinePointDocument, + HTuple hv_CameraNumber, HTuple* hv_out_Cirle, HTuple* hv_Make, HTuple* hv_offset_x, + HTuple* hv_offset_y, HTuple* hv_Text); + +/* +* ho_Image£ºÊäÈëͼƬ£¨Ô­Í¼£© +* hv_model£º¸³ÖµÎª1ʱÊÇ»ù×¼±ê¶¨Ä£Ê½£¬0ΪÕý³£¼ì²âģʽ +* hv_BenchmarkFile£º»ù×¼±ê¶¨ÎļþµÄ·¾¶ +* hv_NinePointDocument£º¾ÅµãÎļþµÄ·¾¶ +*hv_CameraNumber£ºÔ¤º¸Ïà»ú±àºÅ +* hv_out_Cirle£ºÊä³ö·Å¶¤¿×µÄÔ²ÐÄx£¬Ô²ÐÄy£¬°ë¾¶¡£Êý×éÐÎʽ +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐУ¬Êä³öΪ2Ϊ»ù×¼±ê¶¨³É¹¦ +* hv_offset_x£ºxÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î +* hv_offset_y£ºyÖá·½ÏòÉÏÏà¶ÔÓÚ»ù׼λÖÃµÄÆ«²î +* ÖÕº¸º¯Êý +* Ó®ºÏµÄ»ų́ +*/ +extern "C" __declspec(dllexport) void _stdcall _628_FinalWelding(HObject ho_Image, HTuple hv_model, HTuple hv_BenchmarkFile, + HTuple hv_NinePointDocument, HTuple hv_CameraNumber, HTuple* hv_out_Cirle, HTuple* hv_Make, + HTuple* hv_offset_x, HTuple* hv_offset_y); + +/* +* ho_Image1£ºÊäÈëͼƬ£¨Ô­Í¼£© +* ho_Image2£ºÊäÈëͼƬ£¨Ô­Í¼£© +* ho_Image3£ºÊäÈëͼƬ£¨Ô­Í¼£© +* ho_Image4£ºÊäÈëͼƬ£¨Ô­Í¼£© +*ho_Out_Image1£ºÊä³öͼƬ1 +* ho_Out_image2£ºÊä³öͼƬ2 +* hv_Make£ºÊä³ö-1ΪËã·¨´íÎó£¬Êä³ö1ΪËã·¨Õý³£Ö´ÐУ¬Êä³öΪ2Ϊ»ù×¼±ê¶¨³É¹¦ +* hv_sacats£º¹âÔ´Óë¹âÖá¼Ð½Ç +* hv_Tilts£º¹âÔ´°²×°Î»Öà +*/ + +extern "C" __declspec(dllexport) void _stdcall _628_25D(HObject ho_Image1, HObject ho_Image2, HObject ho_Image3, HObject ho_Image4, + HObject* ho_Out_Image1, HObject* ho_Out_image2, HTuple hv_sacats, HTuple hv_Tilts, + HTuple* hv_Make); + + +#endif + +#if 1 halconµ÷Óú¯Êý + +void gen_arrow_contour_xld(HObject* ho_Arrow, HTuple hv_Row1, HTuple hv_Column1, + HTuple hv_Row2, HTuple hv_Column2, HTuple hv_HeadLength, HTuple hv_HeadWidth); +void Get_Rectangle2_Corner_new(HObject ho_Rectangle, HTuple* hv_out_Row, HTuple* hv_out_Col); + +void pts_to_best_line(HObject* ho_Line, HTuple hv_Rows, HTuple hv_Cols, HTuple hv_ActiveNum, + HTuple* hv_Row1, HTuple* hv_Column1, HTuple* hv_Row2, HTuple* hv_Column2); +void rake(HObject ho_Image, HObject* ho_Regions, HTuple hv_Elements, HTuple hv_DetectHeight, + HTuple hv_DetectWidth, HTuple hv_Sigma, HTuple hv_Threshold, HTuple hv_Transition, + HTuple hv_Select, HTuple hv_Row1, HTuple hv_Column1, HTuple hv_Row2, HTuple hv_Column2, + HTuple* hv_ResultRow, HTuple* hv_ResultColumn); + +void pts_to_best_circle(HObject* ho_Circle, HTuple hv_Rows, HTuple hv_Cols, HTuple hv_ArcType, + HTuple hv_ActiveNum, HTuple* hv_RowCenter, HTuple* hv_ColCenter, HTuple* hv_Radius, + HTuple* hv_StartPhi, HTuple* hv_EndPhi, HTuple* hv_PointOrder, HTuple* hv_ArcAngle); + +void region_to_spoke(HObject ho_Region, HTuple hv_Offset, HTuple* hv_SpokeRows, + HTuple* hv_SpokeCols); + +void spoke(HObject ho_Image, HObject* ho_Regions, HTuple hv_Elements, HTuple hv_DetectHeight, + HTuple hv_DetectWidth, HTuple hv_Sigma, HTuple hv_Threshold, HTuple hv_Transition, + HTuple hv_Select, HTuple hv_ROIRows, HTuple hv_ROICols, HTuple hv_Direct, HTuple* hv_ResultRow, + HTuple* hv_ResultColumn, HTuple* hv_ArcType); + +void _628_PreWelded(HObject ho_Image, HTuple hv_model, HTuple hv_BenchmarkFile, + HTuple hv_NinePointDocument, HTuple hv_CameraNumber, HTuple* hv_out_Cirle, HTuple* hv_Make, + HTuple* hv_offset_x, HTuple* hv_offset_y); + +void BeforeWelding_L(HObject ho_Image_L, HTuple hv_Pix_T, HTuple* hv_Make, HTuple* hv_Out_Line, + HTuple* hv_Out_Vale, HTuple* hv_Out_PointRow, HTuple* hv_Out_PointCol); + +void BeforeWelding_T(HObject ho_Image_T, HTuple hv_Pix_T, HTuple* hv_Make, HTuple* hv_Out_Line, + HTuple* hv_Out_Vale, HTuple* hv_Out_PointRow, HTuple* hv_Out_PointCol); + + +#endif + + + + + diff --git a/env/halconAlgo/lib/Inspection.lib b/env/halconAlgo/lib/Inspection.lib new file mode 100644 index 0000000000000000000000000000000000000000..a0ce9b4a4fb5bc5b170b23be91b8c10edbe1b517 GIT binary patch literal 4302 zcmcImO>7fK6n?fte(c1F2uO&wl2Ie^qY{#hZ9t7GCv_2lB&3N^Q6#ik>+IeH=|5V_yql0Qd}`{T4vyDnQpJK+k<93brWS zqf8!PixPQeOK%?lN#BAk(L(?vk$GF9_fSXa{lKJ(ZBx*Vd_f7$4;2mGr#U4Ln7POL4Sy6L(#i7HQ zyrRnbt&xeefI=$Sr!}L1WXzalgK_KpOx~3(TjMSndI^aWHLGXbG%K0BKBZ;zMo|dO z-$VGr(iywUA@8S=Cyb(2U_^RD6Yb==vYgi_Yn;fKf%@ijjpC= zi|1B5z-lMJW*5Ny9smVpv>V_7%CiVo20ATZl^lu!%%gq}+Ye}~qF~`cH*`WfbifX1 zg9!9M7xY3D0uZdz6NWH^?DehBpTbk%6EcpNlh+bUba^Kh8jY0YLG7y5q+jiFk%cer zr|lS?q>wY^CXL0HM{TB*W!32ZLQYZ>yNR%2`Pp>;FLLVIYnXMrgtYgN!&#;h5^G-6 zw%UQ+&3Q0aC>)73I)M^HN#_L0-3-CCyPv<@8Nf3LD}tWEoPJ^X;=r7(0i^NcC$6wI z1%2a#Moz0}19(c=&n|49qP$^x2-_44tuntPGXoYR1QCz>kv#>m)gZRJu?Fdhib3s% z{=N=0)9>kt!U5>7?wm5RC9`ZUR$>Qc55^`Zrcc}5;u|*utXf+DE1kY*4m+$b5eR3J zH7_sWl>4iJz{ii?QRogd#~|>?Q@H(*CC@EZj5ZeYiIWeyxIPKjLiR7|#UA<>?qE!# zCJ5*7y&dPa7$O_WYj@tr^lhp968*;HFC$bN? zWp-szU%&DE5k=j`k?WoHK5$WOB5DcaUn}3Q5jNcxt(BEyXM7a<)W+C}L~U06_)qFD zIw{&Yw(oW##@Bi#JDa;FlS3OHZ`bdsSb-t9%iFh{g6fj%fvZ5&(tcx~3~`eX1F Pon;Y367Q4Z-y!@jvQaCc literal 0 HcmV?d00001 diff --git a/env/myTools/include/myTools.h b/env/myTools/include/myTools.h index f960081..46bb0cc 100644 --- a/env/myTools/include/myTools.h +++ b/env/myTools/include/myTools.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include #define FENGZHUANG_API __declspec(dllexport) @@ -10,13 +10,14 @@ #include #include #include +#include using namespace cv; FENGZHUANG_API void putTextHusky(Mat& dst, const char* str, Point org, Scalar color, int fontSize, const char* fn = "Arial", bool italic = false, bool underline = false); -FENGZHUANG_API int32_t createDirectory(const wstring& directoryPath); -FENGZHUANG_API int32_t createDirectory(const string& directoryPath); +FENGZHUANG_API int32_t createDirectory(const std::wstring& directoryPath); +FENGZHUANG_API int32_t createDirectory(const std::string& directoryPath); FENGZHUANG_API char* UnicodeToAnsi(const wchar_t* szStr); FENGZHUANG_API wchar_t* AnsiToUnicode(const char* szStr); FENGZHUANG_API std::string WString2String(const std::wstring& ws);