diff --git a/BaseModules/Hd_AI_algo_fangBaoFa/CMakeLists.txt b/BaseModules/Hd_AI_algo_fangBaoFa/CMakeLists.txt new file mode 100644 index 0000000..be2265d --- /dev/null +++ b/BaseModules/Hd_AI_algo_fangBaoFa/CMakeLists.txt @@ -0,0 +1,71 @@ +# 获取获取当前目录名 +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" "halconAlgo" "myTools" "handdleAI") +foreach(child ${DLL_NAMES}) + LIST(APPEND ENV_INCLUDE ${${child}_include}) + LIST(APPEND ENV_LIB ${${child}_lib}) + LIST(APPEND ENV_TARGET ${${child}_target_link}) +endforeach() +message(" ENV_INCLUDE : " ${ENV_INCLUDE} ) +message(" ENV_LIB : " ${ENV_LIB} ) +message(" ENV_TARGET : " ${ENV_TARGET} ) +include_directories( + + ${ENV_INCLUDE} + ) + +link_directories ( + ${ENV_LIB} + + ) + + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_CXX_STANDARD 11) +SET(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +FILE(GLOB HEAD_FILES "./*.h" ) +FILE(GLOB SRC_FILES "./*.cpp") +FILE(GLOB UI_FILES "./*.ui") + + +#find_package(Qt5 COMPONENTS Core REQUIRED) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED) +add_library(${CURRENT_FOLDER} SHARED + ${HEAD_FILES} + ${SRC_FILES} + ${UI_FILES} + ) + + + +set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + ) + + +target_link_libraries(${CURRENT_FOLDER} PRIVATE + ${ENV_TARGET} + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Network + ) + + +# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY) + + + + +string(TIMESTAMP RUN_TIME) +message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME}) diff --git a/BaseModules/Hd_AI_algo_fangBaoFa/Hd_AI_algo_fangBaoFa.cpp b/BaseModules/Hd_AI_algo_fangBaoFa/Hd_AI_algo_fangBaoFa.cpp new file mode 100644 index 0000000..b3fea4a --- /dev/null +++ b/BaseModules/Hd_AI_algo_fangBaoFa/Hd_AI_algo_fangBaoFa.cpp @@ -0,0 +1,1094 @@ +#include "Hd_AI_algo_fangBaoFa.h" +#include + +#include +#include +#include +#include +#include +#include +using namespace cv; +//原图保存文件夹s + QString oriImgSaveDir = "D:/601线/软连接CCD/防爆阀CCD/相机1/原图/"; +//原图class图保存文件夹 + QString classImgSaveDir = "D:/601线/软连接CCD/防爆阀CCD/相机1/class图/"; +//结果保存文件夹 + QString resImgSaveDir = "D:/601线/软连接CCD/防爆阀CCD/相机1/结果图/"; + int algoResult = 0;//0 OK 1 NG +//切图的class的width,根据项目实际设置! + int sizeW = 150; +//切图的class的height,根据项目实际设置! + int sizeH = 150; +//切图的class的width,根据项目实际设置!0为黑,255为白; + int fillColour = 0; + + +//检测线程锁 + 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"; + } + 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 geteOriSaveFromat() + { + 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 = "";//缺陷名称 + 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_fangBaoFa::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_fangBaoFa* create() +{ + qDebug() << "[INFO] " << " Hd_AI_algo_fangBaoFa create success!" ; + return new Hd_AI_algo_fangBaoFa; +} + +void destory(Hd_AI_algo_fangBaoFa* ptr) +{ + qDebug() << "[INFO] " << "Hd_AI_algo_fangBaoFa destory success!"; + if(ptr) + { + delete ptr; + ptr = nullptr; + } +} + +Hd_AI_algo_fangBaoFa::Hd_AI_algo_fangBaoFa() +{ + 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_fangBaoFa::~Hd_AI_algo_fangBaoFa() +{ + 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_fangBaoFa::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 = "1*" + QByteArray::number(algoResult) + "&+" + 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_fangBaoFa::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_fangBaoFa::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", geteOriSaveFromat());//保存原图 + //if (!source_savePath.isEmpty()) + //{ + // //std::cout << "try savePath::" << savePath.toStdString() << std::endl; + // //测试相机的, + // //while (HikMat[0].cols > 2000)cv::resize(HikMat[0], HikMat[0], cv::Size(), 0.08, 0.08);' + // for (int i = 0; i < initValueList.size(); i++) + // { + // QString minit = byteArrayToUnicode(initValueList[i]); + // if (initValueList[i].contains(data.split(',')[2].split('_')[0])) + // if (initValueList[i].contains(QString("原图_保存").toLocal8Bit())) + // { + // addImgToSaveStruct(HikMat[0], "0", byteArrayToUnicode(source_savePath + ".bmp"));//保存原图 + // if (HikMat.size() == 2)//3D + // addImgToSaveStruct(HikMat[1], "0", byteArrayToUnicode(source_savePath + ".tif")); + // } + // } + //} + + //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_fangBaoFa::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_fangBaoFa::detectThread); + //运行存图线程 + QFuture future2 = QtConcurrent::run(this, &Hd_AI_algo_fangBaoFa::saveImgThread); + //detectThread(); + //seg_hanHouDingWei = handdleAI::CreateSegObjS("./model/seg-hanHouDingWei.BHD",32,0); + //原图总文件夹 + isDirExist(oriImgSaveDir); + //原图class总文件夹 + isDirExist(classImgSaveDir); + //结果图总文件夹 + isDirExist(resImgSaveDir); + + //qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ; + return true; +} +// 解码 +bool Hd_AI_algo_fangBaoFa::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_fangBaoFa::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(); + //} + //sourceImg = cv::imread("D:\\mySN15-46-33-86.bmp",-1); + //sourceImg = cv::imread("D:/CCD/Image_20241017202132775.bmp", -1); + sourceImg = cv::imread("D:/1/ruanLianJie/fbf/Image_20240816162604747.bmp",-1); + cv::Mat Paint; + sourceImg.copyTo(Paint); + if(Paint.channels() == 1) + cvtColor(Paint, Paint, COLOR_GRAY2BGR); + + HObject ho_Image; + HTuple hv_Pix(0.2); + HTuple hv_Distance_Value; + HTuple hv_Out_Point; + HTuple hv_Make; + MatToHObject(sourceImg,&ho_Image); + _628_3_ExplosionProofValves(ho_Image, hv_Pix, + &hv_Distance_Value,&hv_Out_Point, + &hv_Make); + if(hv_Make.D() == 1) + { + int crossLineLength = 50; + cv::line(Paint, cv::Point(hv_Out_Point[1].D(), hv_Out_Point[0].D()), + cv::Point(hv_Out_Point[1].D() - crossLineLength, hv_Out_Point[0].D()), + cv::Scalar(0, 255, 0), 5); + cv::line(Paint, cv::Point(hv_Out_Point[1].D(), hv_Out_Point[0].D()), + cv::Point(hv_Out_Point[1].D() + crossLineLength, hv_Out_Point[0].D()), + cv::Scalar(0, 255, 0), 5); + cv::line(Paint, cv::Point(hv_Out_Point[1].D(), hv_Out_Point[0].D()), + cv::Point(hv_Out_Point[1].D(), hv_Out_Point[0].D() - crossLineLength), + cv::Scalar(0, 255, 0), 5); + cv::line(Paint, cv::Point(hv_Out_Point[1].D(), hv_Out_Point[0].D()), + cv::Point(hv_Out_Point[1].D(), hv_Out_Point[0].D() + crossLineLength), + cv::Scalar(0, 255, 0), 5); + int crossLineLength2 = 150; + cv::line(Paint, cv::Point(hv_Out_Point[3].D(), hv_Out_Point[2].D()), + cv::Point(hv_Out_Point[3].D() - crossLineLength2, hv_Out_Point[2].D()), + cv::Scalar(0, 255, 0), 5); + cv::line(Paint, cv::Point(hv_Out_Point[3].D(), hv_Out_Point[2].D()), + cv::Point(hv_Out_Point[3].D() + crossLineLength2, hv_Out_Point[2].D()), + cv::Scalar(0, 255, 0), 5); + cv::line(Paint, cv::Point(hv_Out_Point[3].D(), hv_Out_Point[2].D()), + cv::Point(hv_Out_Point[3].D(), hv_Out_Point[2].D() - crossLineLength2), + cv::Scalar(0, 255, 0), 5); + cv::line(Paint, cv::Point(hv_Out_Point[3].D(), hv_Out_Point[2].D()), + cv::Point(hv_Out_Point[3].D(), hv_Out_Point[2].D() + crossLineLength2), + cv::Scalar(0, 255, 0), 5); + putTextHusky(Paint, utf8_to_gbk("间距"+std::to_string(hv_Distance_Value.D())).c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + } + else + putTextHusky(Paint, utf8_to_gbk("算法错误").c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + + + QQueue defectInfoList; + + + detect_mutex->lock(); + + + + + + resMat.push_back(Paint); + 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"; + //存图数据入队,按需 + if (resMat.size() > 0 ) + { + createDirectoryIfNotExists(resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); + addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//保存原图 + } + 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_fangBaoFa::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_fangBaoFa::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_fangBaoFa::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_fangBaoFa::run() +{ + clock_t start, stop; + start = clock(); + + //Sleep(1000); + detectThread(); + stop = clock(); + qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"< +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "imgproc/imgproc_c.h" +#include "base.h" +#include "handleAI.h" +#pragma execution_character_set("utf-8") + + + +//保存图片的结构体 +struct saveImgStruct; +//{ +// cv::Mat out_Mat; +// std::string saveKey; //关键字,用于LOG日志 +// std::string savePath; //保存路径 +//}; + +//初始化流程(一次):Hd_AI_algo_fangBaoFa,initParas +//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程 +class Hd_AI_algo_fangBaoFa :public Base +{ + Q_OBJECT +public: + Hd_AI_algo_fangBaoFa(); + virtual ~Hd_AI_algo_fangBaoFa(); + //从类中读数据到实例对象 + 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); + //handdleAI::pSegmentation* seg_hanHouDingWei; +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_fangBaoFa * create(); + Q_DECL_EXPORT void destory(Hd_AI_algo_fangBaoFa * 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_fangBaoFa/base.h b/BaseModules/Hd_AI_algo_fangBaoFa/base.h new file mode 100644 index 0000000..00bd6b2 --- /dev/null +++ b/BaseModules/Hd_AI_algo_fangBaoFa/base.h @@ -0,0 +1,69 @@ +#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_jiZhuCeLiangMain/CMakeLists.txt b/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/CMakeLists.txt new file mode 100644 index 0000000..be2265d --- /dev/null +++ b/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/CMakeLists.txt @@ -0,0 +1,71 @@ +# 获取获取当前目录名 +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" "halconAlgo" "myTools" "handdleAI") +foreach(child ${DLL_NAMES}) + LIST(APPEND ENV_INCLUDE ${${child}_include}) + LIST(APPEND ENV_LIB ${${child}_lib}) + LIST(APPEND ENV_TARGET ${${child}_target_link}) +endforeach() +message(" ENV_INCLUDE : " ${ENV_INCLUDE} ) +message(" ENV_LIB : " ${ENV_LIB} ) +message(" ENV_TARGET : " ${ENV_TARGET} ) +include_directories( + + ${ENV_INCLUDE} + ) + +link_directories ( + ${ENV_LIB} + + ) + + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_CXX_STANDARD 11) +SET(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +FILE(GLOB HEAD_FILES "./*.h" ) +FILE(GLOB SRC_FILES "./*.cpp") +FILE(GLOB UI_FILES "./*.ui") + + +#find_package(Qt5 COMPONENTS Core REQUIRED) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED) +add_library(${CURRENT_FOLDER} SHARED + ${HEAD_FILES} + ${SRC_FILES} + ${UI_FILES} + ) + + + +set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + ) + + +target_link_libraries(${CURRENT_FOLDER} PRIVATE + ${ENV_TARGET} + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Network + ) + + +# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY) + + + + +string(TIMESTAMP RUN_TIME) +message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME}) diff --git a/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/Hd_AI_algo_jiZhuCeLiangMain.cpp b/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/Hd_AI_algo_jiZhuCeLiangMain.cpp new file mode 100644 index 0000000..02340e5 --- /dev/null +++ b/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/Hd_AI_algo_jiZhuCeLiangMain.cpp @@ -0,0 +1,1146 @@ +#include "Hd_AI_algo_jiZhuCeLiangMain.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include "sharedMem_Main.h" +using namespace cv; + +//原图保存文件夹s + QString oriImgSaveDir = "D:/601线/软连接CCD/极柱测量CCD/原图/"; +//原图class图保存文件夹 + QString classImgSaveDir = "D:/601线/软连接CCD/极柱测量CCD/class图/"; +//结果保存文件夹 + QString resImgSaveDir = "D:/601线/软连接CCD/极柱测量CCD/结果图/"; + int algoResult = 0;//0 OK 1 NG +//切图的class的width,根据项目实际设置! + int sizeW = 150; +//切图的class的height,根据项目实际设置! + int sizeH = 150; +//切图的class的width,根据项目实际设置!0为黑,255为白; + int fillColour = 0; + + +//检测线程锁 + 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"; + } + 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 geteOriSaveFromat() + { + 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 = "";//缺陷名称 + 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_jiZhuCeLiangMain::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_jiZhuCeLiangMain* create() +{ + qDebug() << "[INFO] " << " Hd_AI_algo_jiZhuCeLiangMain create success!" ; + return new Hd_AI_algo_jiZhuCeLiangMain; +} + +void destory(Hd_AI_algo_jiZhuCeLiangMain* ptr) +{ + qDebug() << "[INFO] " << "Hd_AI_algo_jiZhuCeLiangMain destory success!"; + if(ptr) + { + delete ptr; + ptr = nullptr; + } +} + +Hd_AI_algo_jiZhuCeLiangMain::Hd_AI_algo_jiZhuCeLiangMain() +{ + 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_jiZhuCeLiangMain::~Hd_AI_algo_jiZhuCeLiangMain() +{ + ifdetectThread = false; + Sleep(10); + if (detect_mutex) + { + delete detect_mutex; + detect_mutex = nullptr; + } + if (saveStruct_mutex) + { + delete saveStruct_mutex; + saveStruct_mutex = nullptr; + } + releaseSharedMemory(); + /*DestroySegObj(pSeg); + DestroyClsObj(pCls);*/ +} +//从类中读数据到实例对象 +bool Hd_AI_algo_jiZhuCeLiangMain::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 = "1&" + QByteArray::number(algoResult) + "+" + 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_jiZhuCeLiangMain::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_jiZhuCeLiangMain::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", geteOriSaveFromat());//保存原图 + //if (!source_savePath.isEmpty()) + //{ + // //std::cout << "try savePath::" << savePath.toStdString() << std::endl; + // //测试相机的, + // //while (HikMat[0].cols > 2000)cv::resize(HikMat[0], HikMat[0], cv::Size(), 0.08, 0.08);' + // for (int i = 0; i < initValueList.size(); i++) + // { + // QString minit = byteArrayToUnicode(initValueList[i]); + // if (initValueList[i].contains(data.split(',')[2].split('_')[0])) + // if (initValueList[i].contains(QString("原图_保存").toLocal8Bit())) + // { + // addImgToSaveStruct(HikMat[0], "0", byteArrayToUnicode(source_savePath + ".bmp"));//保存原图 + // if (HikMat.size() == 2)//3D + // addImgToSaveStruct(HikMat[1], "0", byteArrayToUnicode(source_savePath + ".tif")); + // } + // } + //} + + //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_jiZhuCeLiangMain::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_jiZhuCeLiangMain::detectThread); + //运行存图线程 + QFuture future2 = QtConcurrent::run(this, &Hd_AI_algo_jiZhuCeLiangMain::saveImgThread); + //detectThread(); + initSharedMemory(); + //原图总文件夹 + isDirExist(oriImgSaveDir); + //原图class总文件夹 + isDirExist(classImgSaveDir); + //结果图总文件夹 + isDirExist(resImgSaveDir); + + //qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ; + return true; +} +// 解码 +bool Hd_AI_algo_jiZhuCeLiangMain::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_jiZhuCeLiangMain::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(); + //} + //sourceImg = cv::imread("D:\\mySN15-46-33-86.bmp",-1); + //sourceImg = cv::imread("D:/1/2820698.bmp", -1); + sourceImg = cv::imread("D:/1/ruanLianJie/fj/2.bmp",-1); + cv::Mat Paint; + sourceImg.copyTo(Paint); + if(Paint.channels() == 1) + cvtColor(Paint, Paint, COLOR_GRAY2BGR); + + HObject ho_Image_L; + HObject ho_Image_T; + HTuple hv_Pix_L(0.02); + HTuple hv_Pix_T(0.02); + HTuple hv_Out_Line_T; + HTuple hv_Out_Point_T; + HTuple hv_Out_Chamfering_T; + HTuple hv_Distances_T; + HTuple hv_Out_Line_L; + HTuple hv_Out_Point_L; + HTuple hv_Out_Chamfering_L; + HTuple hv_Distances_L; + HTuple hv_Out_InterpoleValue; + HTuple hv_Makes; + MatToHObject(sourceImg, &ho_Image_L); + while (g_unionCalculate->getData(ho_Image_T) == false) + QThread::msleep(1); + _628_3_PoleDetections(ho_Image_L, ho_Image_T, + hv_Pix_L,hv_Pix_T, + &hv_Out_Line_T, &hv_Out_Point_T, + &hv_Out_Chamfering_T,&hv_Distances_T, + &hv_Out_Line_L,& hv_Out_Point_L, + &hv_Out_Chamfering_L,&hv_Distances_L, + &hv_Out_InterpoleValue,&hv_Makes); + if(hv_Makes.D() == 1) + { + double interpoleValue = hv_Out_InterpoleValue[0].D(); + + int hv_Out_Line_T_Length = hv_Out_Line_T.Length(); + int hv_Out_Point_T_Length = hv_Out_Point_T.Length(); + double edgeValue_T = hv_Out_Chamfering_T[0].D(); + double upDownDistance_T = hv_Distances_T[0].D() + , leftRightDistance_T = hv_Distances_T[1].D(); + + int hv_Out_Line_L_Length = hv_Out_Line_L.Length(); + int hv_Out_Point_L_Length = hv_Out_Point_L.Length(); + double edgeValue_L = hv_Out_Chamfering_L[0].D(); + double upDownDistance_L = hv_Distances_L[0].D() + , leftRightDistance_L = hv_Distances_L[1].D(); + + //发送到另一算法线程 + unionCalculate::calResult _calResult; + _calResult.upDownDistance = upDownDistance_L; + _calResult.leftRightDistance = leftRightDistance_L; + _calResult.interpoleValue = interpoleValue; + for (int i = 0; i < hv_Out_Line_L_Length; i++) + _calResult.lines.push_back(hv_Out_Line_L[i].D()); + for (int i = 0; i < hv_Out_Point_L_Length; i++) + _calResult.points.push_back(hv_Out_Point_L[i].D()); + g_unionCalculate->insertResult(_calResult); + + //Paint + { + std::string text = "垂直间距:" + std::to_string(upDownDistance_T); + text = text.substr(0, text.find(".") + 4) + "mm"; + putTextHusky(Paint, + utf8_to_gbk(text).c_str(), + cv::Point(50, 50), cv::Scalar(0, 0, 255), 280); + } + { + std::string text = "水平间距:" + std::to_string(leftRightDistance_T); + text = text.substr(0, text.find(".") + 4) + "mm"; + putTextHusky(Paint, + utf8_to_gbk(text).c_str(), + cv::Point(50, 300), cv::Scalar(0, 0, 255), 280); + } + { + std::string text = " 极间距:" + std::to_string(interpoleValue); + text = text.substr(0, text.find(".") + 4) + "mm"; + putTextHusky(Paint, + utf8_to_gbk(text).c_str(), + cv::Point(50, 550), cv::Scalar(0, 0, 255), 280); + } + for (int i = 0; i < hv_Out_Line_T_Length / 4; i++) + cv::line(Paint, cv::Point(hv_Out_Line_T[i * 4 + 1].D(), hv_Out_Line_T[i * 4].D()), + cv::Point(hv_Out_Line_T[i * 4 + 3].D(), hv_Out_Line_T[i * 4 + 2].D()), + cv::Scalar(0, 255, 0), 20); + for (int i = 0; i < hv_Out_Point_T_Length / 3; i++) + cv::circle(Paint, cv::Point(hv_Out_Point_T[i * 3 + 1].D(), hv_Out_Point_T[i * 3].D()), + hv_Out_Point_T[i * 3 + 2].D(), + cv::Scalar(0, 255, 0), 20); + + } + else + { + putTextHusky(Paint, byteArrayToUnicode("算法错误").toStdString().c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + unionCalculate::calResult _calResult; + _calResult.algoFailed = true; + g_unionCalculate->insertResult(_calResult); + } + + + + + + detect_mutex->lock(); + + + + + QQueue defectInfoList; + resMat.push_back(Paint); + 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"; + //存图数据入队,按需 + if (resMat.size() > 0 ) + { + createDirectoryIfNotExists(resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); + addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//保存原图 + } + 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_jiZhuCeLiangMain::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_jiZhuCeLiangMain::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_jiZhuCeLiangMain::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_jiZhuCeLiangMain::run() +{ + clock_t start, stop; + start = clock(); + + //Sleep(1000); + detectThread(); + stop = clock(); + qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"< +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "imgproc/imgproc_c.h" +#include "base.h" +#include "handleAI.h" +#include +#pragma execution_character_set("utf-8") + +//保存图片的结构体 +struct saveImgStruct; +//{ +// cv::Mat out_Mat; +// std::string saveKey; //关键字,用于LOG日志 +// std::string savePath; //保存路径 +//}; + +//初始化流程(一次):Hd_AI_algo_jiZhuCeLiangMain,initParas +//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程 +class Hd_AI_algo_jiZhuCeLiangMain :public Base +{ + Q_OBJECT +public: + Hd_AI_algo_jiZhuCeLiangMain(); + virtual ~Hd_AI_algo_jiZhuCeLiangMain(); + //从类中读数据到实例对象 + 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_jiZhuCeLiangMain * create(); + Q_DECL_EXPORT void destory(Hd_AI_algo_jiZhuCeLiangMain * 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_jiZhuCeLiangMain/base.h b/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/base.h new file mode 100644 index 0000000..00bd6b2 --- /dev/null +++ b/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/base.h @@ -0,0 +1,69 @@ +#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_jiZhuCeLiangMain/sharedMem_Main.h b/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/sharedMem_Main.h new file mode 100644 index 0000000..6850c39 --- /dev/null +++ b/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/sharedMem_Main.h @@ -0,0 +1,59 @@ +#include +#include +#include "unionCal.h" +// 全局变量,用于指向 unionCalculate 实例的指针 +unionCalculate* g_unionCalculate = nullptr; +HANDLE hMapFile; +unionCalculate** sharedUnionCalculatePtr = nullptr; + +// 创建或获取共享内存,用于存储指向 unionCalculate 类实例的指针 +extern "C" __declspec(dllexport) void initSharedMemory() { + // 创建共享内存对象,存储 unionCalculate* 指针 + hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(unionCalculate*), "unionCalculatePtr"); + + if (hMapFile == NULL) { + std::cerr << "Could not create file mapping object (" << GetLastError() << ")" << std::endl; + return; + } + + // 将共享内存映射到当前进程的地址空间 + sharedUnionCalculatePtr = (unionCalculate**)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(unionCalculate*)); + + if (sharedUnionCalculatePtr == NULL) { + std::cerr << "Could not map view of file (" << GetLastError() << ")" << std::endl; + CloseHandle(hMapFile); + return; + } + + // 如果指针为空,创建一个新的 unionCalculate 实例并保存 + if (*sharedUnionCalculatePtr == nullptr) { + g_unionCalculate = new unionCalculate(); + *sharedUnionCalculatePtr = g_unionCalculate; // 存储指针到共享内存 + std::cout << "Created new unionCalculate instance." << std::endl; + } + else { + // 如果已经存在,直接使用 + g_unionCalculate = *sharedUnionCalculatePtr; + std::cout << "Using existing unionCalculate instance." << std::endl; + } +} + +// 释放共享内存 +extern "C" __declspec(dllexport) void releaseSharedMemory() { + if (g_unionCalculate) { + delete g_unionCalculate; + } + + if (sharedUnionCalculatePtr) { + UnmapViewOfFile(sharedUnionCalculatePtr); + } + + if (hMapFile) { + CloseHandle(hMapFile); + } +} + +// 获取指向 unionCalculate 实例的指针 +extern "C" __declspec(dllexport) unionCalculate* getUnionCalculateInstance() { + return g_unionCalculate; +} \ No newline at end of file diff --git a/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/铝极_要比铜极先初始化 b/BaseModules/Hd_AI_algo_jiZhuCeLiangMain/铝极_要比铜极先初始化 new file mode 100644 index 0000000..e69de29 diff --git a/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/CMakeLists.txt b/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/CMakeLists.txt new file mode 100644 index 0000000..be2265d --- /dev/null +++ b/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/CMakeLists.txt @@ -0,0 +1,71 @@ +# 获取获取当前目录名 +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" "halconAlgo" "myTools" "handdleAI") +foreach(child ${DLL_NAMES}) + LIST(APPEND ENV_INCLUDE ${${child}_include}) + LIST(APPEND ENV_LIB ${${child}_lib}) + LIST(APPEND ENV_TARGET ${${child}_target_link}) +endforeach() +message(" ENV_INCLUDE : " ${ENV_INCLUDE} ) +message(" ENV_LIB : " ${ENV_LIB} ) +message(" ENV_TARGET : " ${ENV_TARGET} ) +include_directories( + + ${ENV_INCLUDE} + ) + +link_directories ( + ${ENV_LIB} + + ) + + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_CXX_STANDARD 11) +SET(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +FILE(GLOB HEAD_FILES "./*.h" ) +FILE(GLOB SRC_FILES "./*.cpp") +FILE(GLOB UI_FILES "./*.ui") + + +#find_package(Qt5 COMPONENTS Core REQUIRED) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED) +add_library(${CURRENT_FOLDER} SHARED + ${HEAD_FILES} + ${SRC_FILES} + ${UI_FILES} + ) + + + +set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + ) + + +target_link_libraries(${CURRENT_FOLDER} PRIVATE + ${ENV_TARGET} + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Network + ) + + +# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY) + + + + +string(TIMESTAMP RUN_TIME) +message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME}) diff --git a/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/Hd_AI_algo_jiZhuCeLiangSub.cpp b/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/Hd_AI_algo_jiZhuCeLiangSub.cpp new file mode 100644 index 0000000..80d5425 --- /dev/null +++ b/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/Hd_AI_algo_jiZhuCeLiangSub.cpp @@ -0,0 +1,1087 @@ +#include "Hd_AI_algo_jiZhuCeLiangSub.h" +#include + +#include +#include +#include +#include +#include +#include +#include "sharedMen_Sub.h" +using namespace cv; +//原图保存文件夹s + QString oriImgSaveDir = "D:/601线/软连接CCD/极柱测量CCD/原图/"; +//原图class图保存文件夹 + QString classImgSaveDir = "D:/601线/软连接CCD/极柱测量CCD/class图/"; +//结果保存文件夹 + QString resImgSaveDir = "D:/601线/软连接CCD/极柱测量CCD/结果图/"; + int algoResult = 0;//0 OK 1 NG +//切图的class的width,根据项目实际设置! + int sizeW = 150; +//切图的class的height,根据项目实际设置! + int sizeH = 150; +//切图的class的width,根据项目实际设置!0为黑,255为白; + int fillColour = 0; + + +//检测线程锁 + 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"; + } + 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 geteOriSaveFromat() + { + 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 = "";//缺陷名称 + 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_jiZhuCeLiangSub::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_jiZhuCeLiangSub* create() +{ + qDebug() << "[INFO] " << " Hd_AI_algo_jiZhuCeLiangSub create success!" ; + return new Hd_AI_algo_jiZhuCeLiangSub; +} + +void destory(Hd_AI_algo_jiZhuCeLiangSub* ptr) +{ + qDebug() << "[INFO] " << "Hd_AI_algo_jiZhuCeLiangSub destory success!"; + if(ptr) + { + delete ptr; + ptr = nullptr; + } +} + +Hd_AI_algo_jiZhuCeLiangSub::Hd_AI_algo_jiZhuCeLiangSub() +{ + 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_jiZhuCeLiangSub::~Hd_AI_algo_jiZhuCeLiangSub() +{ + ifdetectThread = false; + Sleep(10); + if (detect_mutex) + { + delete detect_mutex; + detect_mutex = nullptr; + } + if (saveStruct_mutex) + { + delete saveStruct_mutex; + saveStruct_mutex = nullptr; + } + ReleaseSharedMemory(); + /*DestroySegObj(pSeg); + DestroyClsObj(pCls);*/ +} +//从类中读数据到实例对象 +bool Hd_AI_algo_jiZhuCeLiangSub::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 = "1&" + QByteArray::number(algoResult) + "+" + 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_jiZhuCeLiangSub::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_jiZhuCeLiangSub::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", geteOriSaveFromat());//保存原图 + //if (!source_savePath.isEmpty()) + //{ + // //std::cout << "try savePath::" << savePath.toStdString() << std::endl; + // //测试相机的, + // //while (HikMat[0].cols > 2000)cv::resize(HikMat[0], HikMat[0], cv::Size(), 0.08, 0.08);' + // for (int i = 0; i < initValueList.size(); i++) + // { + // QString minit = byteArrayToUnicode(initValueList[i]); + // if (initValueList[i].contains(data.split(',')[2].split('_')[0])) + // if (initValueList[i].contains(QString("原图_保存").toLocal8Bit())) + // { + // addImgToSaveStruct(HikMat[0], "0", byteArrayToUnicode(source_savePath + ".bmp"));//保存原图 + // if (HikMat.size() == 2)//3D + // addImgToSaveStruct(HikMat[1], "0", byteArrayToUnicode(source_savePath + ".tif")); + // } + // } + //} + + //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_jiZhuCeLiangSub::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_jiZhuCeLiangSub::detectThread); + //运行存图线程 + QFuture future2 = QtConcurrent::run(this, &Hd_AI_algo_jiZhuCeLiangSub::saveImgThread); + //detectThread(); + initSharedMemory(); + //原图总文件夹 + isDirExist(oriImgSaveDir); + //原图class总文件夹 + isDirExist(classImgSaveDir); + //结果图总文件夹 + isDirExist(resImgSaveDir); + + //qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ; + return true; +} +// 解码 +bool Hd_AI_algo_jiZhuCeLiangSub::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_jiZhuCeLiangSub::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"); + + // sourceImg = cv::imread("D:/1/2813489.bmp", -1); + sourceImg = cv::imread("D:/1/ruanLianJie/zj/1.bmp",-1); + + cv::Mat Paint; + sourceImg.copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, COLOR_GRAY2BGR); + + + HObject image; + MatToHObject(sourceImg, &image); + while(*sharedUnionCalculatePtr==nullptr) + QThread::msleep(1); + (*sharedUnionCalculatePtr)->insertSubData(image);//发送检测数据到主线程 + + unionCalculate::calResult _calResult; + while ((*sharedUnionCalculatePtr)->getResult(_calResult) == false) + QThread::msleep(1); + if(_calResult.algoFailed == false) + { + //Paint + { + std::string text = "垂直间距:" + std::to_string(_calResult.upDownDistance); + text = text.substr(0, text.find(".") + 4) + "mm"; + putTextHusky(Paint, + utf8_to_gbk(text).c_str(), + cv::Point(50, 50), cv::Scalar(0, 0, 255), 280); + } + { + std::string text = "水平间距:" + std::to_string(_calResult.leftRightDistance); + text = text.substr(0, text.find(".") + 4) + "mm"; + putTextHusky(Paint, + utf8_to_gbk(text).c_str(), + cv::Point(50, 300), cv::Scalar(0, 0, 255), 280); + } + { + std::string text = " 极间距:" + std::to_string(_calResult.interpoleValue); + text = text.substr(0, text.find(".") + 4) + "mm"; + putTextHusky(Paint, + utf8_to_gbk(text).c_str(), + cv::Point(50, 550), cv::Scalar(0, 0, 255), 280); + } + for (int i = 0; i < _calResult.lines.size() / 4; i++) + cv::line(Paint, cv::Point(_calResult.lines[i * 4 + 1], _calResult.lines[i * 4]), + cv::Point(_calResult.lines[i * 4 + 3], _calResult.lines[i * 4 + 2]), + cv::Scalar(0, 255, 0), 20); + for (int i = 0; i < _calResult.points.size() / 3; i++) + cv::circle(Paint, cv::Point(_calResult.points[i * 3 + 1], _calResult.points[i * 3]), + _calResult.points[i * 3 + 2], + cv::Scalar(0, 255, 0), 20); + } + else + putTextHusky(Paint, byteArrayToUnicode("算法错误").toStdString().c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + QQueue defectInfoList; + + + detect_mutex->lock(); + + + + + + resMat.push_back(Paint); + 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"; + //存图数据入队,按需 + if (resMat.size() > 0 ) + { + createDirectoryIfNotExists(resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); + addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//保存原图 + } + 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_jiZhuCeLiangSub::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_jiZhuCeLiangSub::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_jiZhuCeLiangSub::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_jiZhuCeLiangSub::run() +{ + clock_t start, stop; + start = clock(); + + //Sleep(1000); + detectThread(); + stop = clock(); + qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"< +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "imgproc/imgproc_c.h" +#include "base.h" +#include "handleAI.h" +#pragma execution_character_set("utf-8") + + + +//保存图片的结构体 +struct saveImgStruct; +//{ +// cv::Mat out_Mat; +// std::string saveKey; //关键字,用于LOG日志 +// std::string savePath; //保存路径 +//}; + +//初始化流程(一次):Hd_AI_algo_jiZhuCeLiangSub,initParas +//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程 +class Hd_AI_algo_jiZhuCeLiangSub :public Base +{ + Q_OBJECT +public: + Hd_AI_algo_jiZhuCeLiangSub(); + virtual ~Hd_AI_algo_jiZhuCeLiangSub(); + //从类中读数据到实例对象 + 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_jiZhuCeLiangSub * create(); + Q_DECL_EXPORT void destory(Hd_AI_algo_jiZhuCeLiangSub * 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_jiZhuCeLiangSub/base.h b/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/base.h new file mode 100644 index 0000000..00bd6b2 --- /dev/null +++ b/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/base.h @@ -0,0 +1,69 @@ +#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_jiZhuCeLiangSub/sharedMen_Sub.h b/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/sharedMen_Sub.h new file mode 100644 index 0000000..20c7bd8 --- /dev/null +++ b/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/sharedMen_Sub.h @@ -0,0 +1,41 @@ +#include +#include +#include +#include // 包含unionCalculate类的定义 + +// 全局变量 +HANDLE hMapFile; +unionCalculate** sharedUnionCalculatePtr = nullptr; + +// 导出函数:获取 unionCalculate 实例并启动线程 +extern "C" __declspec(dllexport) void initSharedMemory() { + // 打开现有的共享内存 + hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "unionCalculatePtr"); + + if (hMapFile == NULL) { + std::cerr << "Could not open file mapping object (" << GetLastError() << ")" << std::endl; + return; + } + + sharedUnionCalculatePtr = (unionCalculate**)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(unionCalculate*)); + + if (sharedUnionCalculatePtr == NULL) { + std::cerr << "Could not map view of file (" << GetLastError() << ")" << std::endl; + CloseHandle(hMapFile); + return; + } + + std::cout << "DLL B: Acquired unionCalculate instance" << std::endl; + +} + +// 导出函数:停止线程并释放共享内存 +extern "C" __declspec(dllexport) void ReleaseSharedMemory() { + + if (sharedUnionCalculatePtr) { + UnmapViewOfFile(sharedUnionCalculatePtr); + } + if (hMapFile) { + CloseHandle(hMapFile); + } +} diff --git a/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/铜极 b/BaseModules/Hd_AI_algo_jiZhuCeLiangSub/铜极 new file mode 100644 index 0000000..e69de29 diff --git a/BaseModules/Hd_AI_algo_maJiaReRong/CMakeLists.txt b/BaseModules/Hd_AI_algo_maJiaReRong/CMakeLists.txt new file mode 100644 index 0000000..be2265d --- /dev/null +++ b/BaseModules/Hd_AI_algo_maJiaReRong/CMakeLists.txt @@ -0,0 +1,71 @@ +# 获取获取当前目录名 +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" "halconAlgo" "myTools" "handdleAI") +foreach(child ${DLL_NAMES}) + LIST(APPEND ENV_INCLUDE ${${child}_include}) + LIST(APPEND ENV_LIB ${${child}_lib}) + LIST(APPEND ENV_TARGET ${${child}_target_link}) +endforeach() +message(" ENV_INCLUDE : " ${ENV_INCLUDE} ) +message(" ENV_LIB : " ${ENV_LIB} ) +message(" ENV_TARGET : " ${ENV_TARGET} ) +include_directories( + + ${ENV_INCLUDE} + ) + +link_directories ( + ${ENV_LIB} + + ) + + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_CXX_STANDARD 11) +SET(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +FILE(GLOB HEAD_FILES "./*.h" ) +FILE(GLOB SRC_FILES "./*.cpp") +FILE(GLOB UI_FILES "./*.ui") + + +#find_package(Qt5 COMPONENTS Core REQUIRED) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED) +add_library(${CURRENT_FOLDER} SHARED + ${HEAD_FILES} + ${SRC_FILES} + ${UI_FILES} + ) + + + +set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + ) + + +target_link_libraries(${CURRENT_FOLDER} PRIVATE + ${ENV_TARGET} + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Network + ) + + +# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY) + + + + +string(TIMESTAMP RUN_TIME) +message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME}) diff --git a/BaseModules/Hd_AI_algo_maJiaReRong/Hd_AI_algo_maJiaReRong.cpp b/BaseModules/Hd_AI_algo_maJiaReRong/Hd_AI_algo_maJiaReRong.cpp new file mode 100644 index 0000000..f8fc0a5 --- /dev/null +++ b/BaseModules/Hd_AI_algo_maJiaReRong/Hd_AI_algo_maJiaReRong.cpp @@ -0,0 +1,1079 @@ +#include "Hd_AI_algo_maJiaReRong.h" +#include + +#include +#include +#include +#include +#include +#include +using namespace cv; +//原图保存文件夹s + QString oriImgSaveDir = "D:/601线/软连接CCD/马甲热熔CCD/相机1/原图/"; +//原图class图保存文件夹 + QString classImgSaveDir = "D:/601线/软连接CCD/马甲热熔CCD/相机1/class图/"; +//结果保存文件夹 + QString resImgSaveDir = "D:/601线/软连接CCD/马甲热熔CCD/相机1/结果图/"; + int algoResult = 0;//0 OK 1 NG +//切图的class的width,根据项目实际设置! + int sizeW = 150; +//切图的class的height,根据项目实际设置! + int sizeH = 150; +//切图的class的width,根据项目实际设置!0为黑,255为白; + int fillColour = 0; + + +//检测线程锁 + 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"; + } + 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 geteOriSaveFromat() + { + 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 = "";//缺陷名称 + 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_maJiaReRong::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_maJiaReRong* create() +{ + qDebug() << "[INFO] " << " Hd_AI_algo_maJiaReRong create success!" ; + return new Hd_AI_algo_maJiaReRong; +} + +void destory(Hd_AI_algo_maJiaReRong* ptr) +{ + qDebug() << "[INFO] " << "Hd_AI_algo_maJiaReRong destory success!"; + if(ptr) + { + delete ptr; + ptr = nullptr; + } +} + +Hd_AI_algo_maJiaReRong::Hd_AI_algo_maJiaReRong() +{ + 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_maJiaReRong::~Hd_AI_algo_maJiaReRong() +{ + 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_maJiaReRong::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 = "1*" + QByteArray::number(algoResult) + "&+" + 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_maJiaReRong::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_maJiaReRong::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", geteOriSaveFromat());//保存原图 + //if (!source_savePath.isEmpty()) + //{ + // //std::cout << "try savePath::" << savePath.toStdString() << std::endl; + // //测试相机的, + // //while (HikMat[0].cols > 2000)cv::resize(HikMat[0], HikMat[0], cv::Size(), 0.08, 0.08);' + // for (int i = 0; i < initValueList.size(); i++) + // { + // QString minit = byteArrayToUnicode(initValueList[i]); + // if (initValueList[i].contains(data.split(',')[2].split('_')[0])) + // if (initValueList[i].contains(QString("原图_保存").toLocal8Bit())) + // { + // addImgToSaveStruct(HikMat[0], "0", byteArrayToUnicode(source_savePath + ".bmp"));//保存原图 + // if (HikMat.size() == 2)//3D + // addImgToSaveStruct(HikMat[1], "0", byteArrayToUnicode(source_savePath + ".tif")); + // } + // } + //} + + //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_maJiaReRong::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_maJiaReRong::detectThread); + //运行存图线程 + QFuture future2 = QtConcurrent::run(this, &Hd_AI_algo_maJiaReRong::saveImgThread); + //detectThread(); + //seg_hanHouDingWei = handdleAI::CreateSegObjS("./model/seg-hanHouDingWei.BHD",32,0); + //原图总文件夹 + isDirExist(oriImgSaveDir); + //原图class总文件夹 + isDirExist(classImgSaveDir); + //结果图总文件夹 + isDirExist(resImgSaveDir); + + //qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ; + return true; +} +// 解码 +bool Hd_AI_algo_maJiaReRong::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_maJiaReRong::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(); + //} + //sourceImg = cv::imread("D:\\mySN15-46-33-86.bmp",-1); + //sourceImg = cv::imread("D:/CCD/Image_20241017202132775.bmp", -1); + sourceImg = cv::imread("D:/1/majia/Image_20241016210237741.bmp",-1); + cv::Mat Paint; + sourceImg.copyTo(Paint); + if(Paint.channels() == 1) + cvtColor(Paint, Paint, COLOR_GRAY2BGR); + + HObject ho_Image; + HTuple hv_Out_Rectangle; + HTuple hv_Make; + HTuple hv_Text; + MatToHObject(sourceImg,&ho_Image); + _628_3_TopCoverMelted(ho_Image + ,&hv_Out_Rectangle,&hv_Make, + &hv_Text); + if(hv_Make.D() == 1) + { + for (int i = 0; i < hv_Out_Rectangle.Length() / 4; i++) + { + double lt_X = hv_Out_Rectangle[i * 4 + 1]; + double lt_Y = hv_Out_Rectangle[i * 4 ]; + double rd_X = hv_Out_Rectangle[i * 4 + 3]; + double rd_Y = hv_Out_Rectangle[i * 4 + 2]; + double width = rd_X - lt_X; + double height = rd_Y - lt_Y; + cv::Rect rect = cv::Rect(lt_X, lt_Y , width, height); + cv::rectangle(Paint, rect, cv::Scalar(0, 255, 0), 2); + } + std::string str = hv_Text.S(); + putTextHusky(Paint, utf8_to_gbk(str).c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + } + else + putTextHusky(Paint, utf8_to_gbk("算法错误").c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + + + QQueue defectInfoList; + + + detect_mutex->lock(); + + + + + + resMat.push_back(Paint); + 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"; + //存图数据入队,按需 + if (resMat.size() > 0 ) + { + createDirectoryIfNotExists(resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); + addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//保存原图 + } + 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_maJiaReRong::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_maJiaReRong::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_maJiaReRong::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_maJiaReRong::run() +{ + clock_t start, stop; + start = clock(); + + //Sleep(1000); + detectThread(); + stop = clock(); + qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"< +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "imgproc/imgproc_c.h" +#include "base.h" +#include "handleAI.h" +#pragma execution_character_set("utf-8") + + + +//保存图片的结构体 +struct saveImgStruct; +//{ +// cv::Mat out_Mat; +// std::string saveKey; //关键字,用于LOG日志 +// std::string savePath; //保存路径 +//}; + +//初始化流程(一次):Hd_AI_algo_maJiaReRong,initParas +//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程 +class Hd_AI_algo_maJiaReRong :public Base +{ + Q_OBJECT +public: + Hd_AI_algo_maJiaReRong(); + virtual ~Hd_AI_algo_maJiaReRong(); + //从类中读数据到实例对象 + 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); + //handdleAI::pSegmentation* seg_hanHouDingWei; +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_maJiaReRong * create(); + Q_DECL_EXPORT void destory(Hd_AI_algo_maJiaReRong * 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_maJiaReRong/base.h b/BaseModules/Hd_AI_algo_maJiaReRong/base.h new file mode 100644 index 0000000..00bd6b2 --- /dev/null +++ b/BaseModules/Hd_AI_algo_maJiaReRong/base.h @@ -0,0 +1,69 @@ +#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_LogicDll_module/Logic_hdataprocess.cpp b/BaseModules/Hd_LogicDll_module/Logic_hdataprocess.cpp index 24a420c..ab2d8ac 100644 --- a/BaseModules/Hd_LogicDll_module/Logic_hdataprocess.cpp +++ b/BaseModules/Hd_LogicDll_module/Logic_hdataprocess.cpp @@ -18,10 +18,10 @@ void HSnData::addSnVector(QVector snVec) QVector vec_str = queue_vector_sn.last(); if (!vec_str.isEmpty()) { - if (!vec_str[0].contains(snVec[0])) //demo流程重入检查也可以 - { - queue_vector_sn.append(snVec); - } + //if (!vec_str[0].contains(snVec[0])) //demo流程重入检查也可以 + //{ + // queue_vector_sn.append(snVec); + //} /*else std::cout << "HSnData::addSnVector err" << std::endl;*/ } diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fdecb9..2b14a71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,8 +127,8 @@ if(ON) else() SET( ${child}_target_link "opencv_world410" ) endif() - elseif(${child} MATCHES "3DAI") - SET( ${child}_target_link "cosmeticAlg" ) + elseif(${child} MATCHES "halconAlgo") + SET( ${child}_target_link "Inspection" ) elseif(${child} MATCHES "basler") SET( ${child}_target_link "GCBase_MD_VC141_v3_1_Basler_pylon" diff --git a/env/halconAlgo/dll/Inspection.dll b/env/halconAlgo/dll/Inspection.dll new file mode 100644 index 0000000..f31b795 Binary files /dev/null and b/env/halconAlgo/dll/Inspection.dll differ diff --git a/env/halconAlgo/include/algo.h b/env/halconAlgo/include/algo.h new file mode 100644 index 0000000..58b7102 --- /dev/null +++ b/env/halconAlgo/include/algo.h @@ -0,0 +1,375 @@ +#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, HTuple* hv_StartRun); + +/* +*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_Pix£ºÏñËؾ«¶È +* hv_out_line:Êä³öֱÏß×ø±ê +* hv_distance£ºÊä³ö²âÁ¿ֵ ->¸ߣ¬¿í¡£Êý×éÐÎʽ +* hv_Make£ºÊä³ö-1ΪË㷨´íÎó£¬Êä³ö1ΪË㷨Õý³£ִÐÐ +* ÂÁ¼«¶ú²üô²âÁ¿º¯Êý +* ÈýЭԤº¸»ų́ +*/ + +extern "C" __declspec(dllexport) void _stdcall cs_628_jier_L(HObject ho_Image, HTuple hv_Pix, HTuple* hv_out_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 £º×óÉÏÊä³öµIJâÁ¿ֵ£¨2¸öֵ£© +* hv_Out_TopRight_Line £ºÓÒÉÏÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_TopRight_Value £ºÓÒÉÏÊä³öµIJâÁ¿ֵ£¨2¸öֵ£© +* hv_Out_BottomLeft_Line £º×óÏÂÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_BottomLeft_Value £º×óÏÂÊä³öµIJâÁ¿ֵ£¨2¸öֵ£© +** hv_Out_BottomRight_Line £ºÓÒÏÂÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_BottomRight_Value £ºÓÒÏÂÊä³öµIJâÁ¿ֵ£¨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 £º×óÉÏÊä³öµIJâÁ¿ֵ£¨2¸öֵ£© +* hv_Out_TopRight_Line £ºÓÒÉÏÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_TopRight_Value £ºÓÒÉÏÊä³öµIJâÁ¿ֵ£¨2¸öֵ£© +* hv_Out_BottomLeft_Line £º×óÏÂÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_BottomLeft_Value £º×óÏÂÊä³öµIJâÁ¿ֵ£¨2¸öֵ£© +** hv_Out_BottomRight_Line £ºÓÒÏÂÊä³öÏߵĶ˵ã×ø±ê +* hv_Out_BottomRight_Value £ºÓÒÏÂÊä³öµIJâÁ¿ֵ£¨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_Out_Rectangle : Êä³ö¾ØÐεÄÁ½¸ö¶¥µã×ø±ê +* hv_Text £ºÊä³ö¼ì²âÐÅϢ×ַû´®¸ñʽ +* hv_Make£ºÊä³ö-1ΪË㷨´íÎó£¬Êä³ö1ΪË㷨Õý³£ִÐÐ +*ÈíÁ¬½ÓÈÈÈ۹¤λº¯Êý +* ÈýЭµĻų́ +*/ +extern "C" __declspec(dllexport) void _stdcall _628_3_TopCoverMelted(HObject ho_Image, HTuple* hv_Out_Rectangle, HTuple* hv_Make, + HTuple* hv_Text); + +/* +* ho_Image_L £ºÊäÈëͼƬ£¨ÂÁ£© +* ho_Image_T £ºÊäÈëͼƬ£¨ͭ£© +* hv_Pix_L £ºÂÁ¼«Ïà»úÏñËؾ«¶È +* hv_Pix_T £ºͭ¼«Ïà»úÏñËؾ«¶È +* hv_Out_Line_T £ºͭ¼«Êä³öÏߵĶ˵ã×ø±꣨ÐèÅжϸöÊý£© +* hv_Out_Point_T £ºͭ¼«Êä³öÖÐÐÄԲµÄÖÐÐÄ×ø±꼰°뾶 +* hv_Out_Chamfering_T £ºͭ¼«Êä³öµ¹½Çֵ +* hv_Distances_T £ºͭ¼«Êä³öÉÏÏ£¬×óÓҾàÀë +* hv_Out_Line_L £ºÂÁ¼«Êä³öÏߵĶ˵ã×ø±꣨ÐèÅжϸöÊý£© +* hv_Out_Point_L £ºÂÁ¼«Êä³öÖÐÐÄԲµÄÖÐÐÄ×ø±꼰°뾶 +* hv_Out_Chamfering_L £ºÂÁ¼«Êä³öµ¹½Çֵ +* hv_Distances_L £ºÂÁ¼«Êä³öÉÏÏ£¬×óÓҾàÀë +* hv_Out_InterpoleValue £ºÊä³öÁ½¼«Öù֮¼ä¾àÀë +* hv_Makes£ºÊä³ö-1ΪË㷨´íÎó£¬Êä³ö1ΪË㷨Õý³£ִÐÐ +*ÈíÁ¬½Ӽ«Öù²âÁ¿¹¤λº¯Êý +* ÈýЭµĻų́ +*/ + +extern "C" __declspec(dllexport) void _stdcall _628_3_PoleDetections(HObject ho_Image_L, HObject ho_Image_T, HTuple hv_Pix_L, + HTuple hv_Pix_T, HTuple* hv_Out_Line_T, HTuple* hv_Out_Point_T, HTuple* hv_Out_Chamfering_T, + HTuple* hv_Distances_T, HTuple* hv_Out_Line_L, HTuple* hv_Out_Point_L, HTuple* hv_Out_Chamfering_L, + HTuple* hv_Distances_L, HTuple* hv_Out_InterpoleValue, HTuple* hv_Makes); + +/* +* ho_Image £ºÊäÈëͼƬ +* hv_Pix £ºÏà»úÏñËؾ«¶È +* hv_Distance_Value £º¼ä¾à²âÁ¿ֵ +* hv_Out_Point £ºÊä³ö·À±¬·§ÖÐÐĵãºͶþάÂëÖÐÐĵã¾àÀë +* hv_Makes£ºÊä³ö-1ΪË㷨´íÎó£¬Êä³ö1ΪË㷨Õý³£ִÐÐ +*ÈíÁ¬½ӷÀ±¬·§Óë¶þάÂë֮¼ä¾àÀë²âÁ¿º¯Êý +* ÈýЭµĻų́ +*/ +extern "C" __declspec(dllexport) void _stdcall _628_3_ExplosionProofValves(HObject ho_Image, HTuple hv_Pix, HTuple* hv_Distance_Value, + HTuple* hv_Out_Point, 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); + +//Function Name: Cal_Defect_Height +//Author: +//Description: 2D»ñȡȱÏݺó, »ùÓÚÌØÕ÷µãµÄλÖùØϵ, ½¨Á¢2DºÍ3DµÄӳÉ乨ϵ. +//Input: in_Image2: ÃܷⶤÇøÓòµÄ2D¶þֵ»¯µÄͼÏñ(bmp),, +// in_Image3: 3DÉî¶ÈͼÏñ(tiff), +// in_xResolution: xÏ򾫶È(mm/pix) +// in_yResolution: yÏ򾫶È(mm/pix), +// in_zResolution: ZÏ򾫶È(mm/pix) +// in_DefectLocation: 2dͼÏñȱÏÝ×ø±êµãλÖÃ, ÿËĸöһ×é, +// in_DefectLocation[0]:ȱÏÝÍâ½ӾØÐεÄXÏò×ø±ê(pix) +// in_DefectLocation[1]:ȱÏÝÍâ½ӾØÐεÄyÏò×ø±ê(pix) +// in_DefectLocation[2]:ȱÏÝÍâ½ӾØÐεĿí¶Èwidth(pix) +// in_DefectLocation[3]:ȱÏÝÍâ½ӾØÐεĸ߶Èheight(pix) +// in_FilePath, ¾ØÕómartixÎļþ·¾¶, +// in_offsetValue, λÖò¹³¥ֵ, +// in_offsetValue[0]: ×ó¹¤λXÏ򲹳¥ֵ(pix) +// in_offsetValue[1]: ×ó¹¤λYÏ򲹳¥ֵ(pix) +// in_offsetValue[2]: Óҹ¤λXÏ򲹳¥ֵ(pix) +// in_offsetValue[3]: Óҹ¤λYÏ򲹳¥ֵ(pix) +// in_HoffsetValue, ȱÏݸ߶Ȳ¹³¥ֵ(Õýֵ,µ¥λ:mm) +//output£º out_Height: ȱÏݵĸ߶È(mm), +// out_Flag: Ë㷨ִÐеıê־λ, 0: Ë㷨ִÐÐÒ쳣 1:Ë㷨ִÐÐok +// Ӯºϻų́ +//verion change log: XXX 2024-10-22 V1.1 Create new function + +extern "C" __declspec(dllexport) void _stdcall Cal_Defect_Height(HObject ho_in_Image2, HObject ho_in_Image3, HTuple hv_in_xResolution, + HTuple hv_in_yResolution, HTuple hv_in_zResolution, HTuple hv_in_DefectLocation, + HTuple hv_in_FilePath, HTuple hv_in_OffsetValue, HTuple hv_in_HoffsetValue, HTuple* hv_out_Height, + HTuple* hv_out_Angle, HTuple* hv_out_Flag); + + + + + +#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); + + +void Cal_PointCould_HeightValue(HObject ho_Tmp_Region, HObject ho_Zero_Region, HObject ho_XImageScaled, + HObject ho_YImageScaled, HObject ho_ZImageScaled, HTuple hv_HeightPointPerenct, + HTuple* hv_Out_Mean, HTuple* hv_Out_Max, HTuple* hv_Out_Min, HTuple* hv_Out_Height, + HTuple* hv_Out_Flag, HTuple* hv_Out_NgTails); + +void cs_628_PoleDetection(HObject ho_Image, HTuple hv_Pix, HTuple* hv_Distances, + HTuple* hv_UP_Down_Point, HTuple* hv_life_Ren_Point, HTuple* hv_Point, HTuple* hv_Chamfering, + HTuple* hv_Make); + + +#endif + + + + + diff --git a/env/halconAlgo/include/unionCal.h b/env/halconAlgo/include/unionCal.h new file mode 100644 index 0000000..911c788 --- /dev/null +++ b/env/halconAlgo/include/unionCal.h @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include "algo.h" +class unionCalculate +{ +public: + //struct dataStruct + //{ + // cv::Mat matImg; + // HObject halconImg; + // dataStruct(cv::Mat img1, HObject img2) + // :matImg(img1), + // halconImg(img2) + // { + + // } + //}; + //方法1 用sn匹配 + //std::unordered_map<,std::string,dataStruct> dataMap; + //void insertSubData(std::string& sign,cv::Mat& img) + //{ + // dataVec.insert(std::make_pair(sign, img)); + //} + //dataStruct getData(std::string& sign) + //{ + //} + + //方法2 获取最新的 + //子算法转完hobject再发送 + + + void insertSubData(HObject img) + { + mutexUnionCaculate.lock(); + dataQueue.enqueue(img); + mutexUnionCaculate.unlock(); + } + bool getData(HObject& res) + { + mutexUnionCaculate.lock(); + if (dataQueue.size() == 0) + { + mutexUnionCaculate.unlock(); + return false; + } + res = dataQueue.dequeue(); + dataQueue.clear(); + mutexUnionCaculate.unlock(); + return true; + } + + struct calResult + { + bool algoFailed = false; + std::vectorlines; + std::vectorpoints; + double upDownDistance, leftRightDistance; + double interpoleValue; + }; + void insertResult(calResult res) + { + mutexUnionCaculate.lock(); + resultQueue.enqueue(res); + mutexUnionCaculate.unlock(); + } + bool getResult(calResult& res) + { + mutexUnionCaculate.lock(); + if (resultQueue.size() == 0) + { + mutexUnionCaculate.unlock(); + return false; + } + res = resultQueue.dequeue(); + resultQueue.clear(); + mutexUnionCaculate.unlock(); + return true; + } +private: + QQueue dataQueue; + QQueueresultQueue; + std::mutex mutexUnionCaculate; +}; + + +#pragma once diff --git a/env/halconAlgo/lib/Inspection.lib b/env/halconAlgo/lib/Inspection.lib new file mode 100644 index 0000000..5a0e12a Binary files /dev/null and b/env/halconAlgo/lib/Inspection.lib differ diff --git a/env/myTools/include/myTools.h b/env/myTools/include/myTools.h index f960081..78b1009 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) @@ -15,8 +15,8 @@ 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);