#include "Hd_AI_3D_module.h" #include #include #include #include #include using namespace cv; using namespace std; using namespace HalconCpp; //原图保存文件夹 QString oriImgSaveDir = "F:/ORI/"; //原图class图保存文件夹 QString classImgSaveDir = "F:/ORIclass/"; //结果保存文件夹 QString resImgSaveDir = "F:/res/"; //切图的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 qstring_data; QString cameraKey_index = ""; QString sData; QStringList splitDataList; //初始化参数列表 QByteArrayList initValueList; QString byteArrayToUnicode(const QByteArray array) { // state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功 // 如果转换成功,则值为0,如果值大于0,则说明转换失败 QTextCodec::ConverterState state; // 先尝试使用utf-8的方式把QByteArray转换成QString QString text = QTextCodec::codecForName("UTF-8")->toUnicode(array.constData(), array.size(), &state); // 如果转换时无效字符数量大于0,说明编码格式不对 if (state.invalidChars > 0) { // 再尝试使用GBK的方式进行转换,一般就能转换正确(当然也可能是其它格式,但比较少见了) text = QTextCodec::codecForName("GBK")->toUnicode(array); } return text; } // 缺陷信息结构体 typedef struct { QString defectName = "";//缺陷名称 cv::Rect defectRect = { 0,0,0,0 };//缺陷位置 cv::Scalar defectScalar = cv::Scalar(0, 0, 0);//画框颜色 double defectArea = 0;//缺陷真实面积 double defectDepth = 0;//缺陷深度/高度,3D信息 }defectInfo; //判断文件是否存在,不存在则创建 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, "微软雅黑"); } } cv::Mat RotateImage180(const cv::Mat& image) { cv::Mat rotatedImage; cv::flip(image, rotatedImage, -1); return rotatedImage; } HalconCpp::HObject 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;*/ uchar* data = new uchar[hgt * wid]; for (i = 0; i < hgt; i++) memcpy(data + wid * i, image.data + image.step * i, wid); GenImage1(&Hobj, "byte", wid, hgt, (Hlong)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; } return Hobj; } cv::Mat HObject2Mat(HalconCpp::HObject& Hobj) //HObject类型转Mat类型 { HalconCpp::HTuple htCh; HalconCpp::HString cType; cv::Mat Image; ConvertImageType(Hobj, &Hobj, "byte"); CountChannels(Hobj, &htCh); Hlong wid = 0; Hlong hgt = 0; if (htCh[0].I() == 1) { HImage hImg(Hobj); void* ptr = hImg.GetImagePointer1(&cType, &wid, &hgt);//GetImagePointer1(Hobj, &ptr, &cType, &wid, &hgt); int W = wid; int H = hgt; Image.create(H, W, CV_8UC1); unsigned char* pdata = static_cast(ptr); memcpy(Image.data, pdata, W * H); } else if (htCh[0].I() == 3) { void* Rptr; void* Gptr; void* Bptr; HImage hImg(Hobj); hImg.GetImagePointer3(&Rptr, &Gptr, &Bptr, &cType, &wid, &hgt); int W = wid; int H = hgt; Image.create(H, W, CV_8UC3); std::vector VecM(3); VecM[0].create(H, W, CV_8UC1); VecM[1].create(H, W, CV_8UC1); VecM[2].create(H, W, CV_8UC1); unsigned char* R2 = (unsigned char*)Rptr; unsigned char* G = (unsigned char*)Gptr; unsigned char* B = (unsigned char*)Bptr; memcpy(VecM[2].data, R2, W * H); memcpy(VecM[1].data, G, W * H); memcpy(VecM[0].data, B, W * H); cv::merge(VecM, Image); } return Image; } //判断文件夹是否存在,不存在则创建 void Hd_AI_3D_module::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_3D_module* create() { qDebug() << "[INFO] " << " Hd_AI_3D_module create success!" ; return new Hd_AI_3D_module; } void destory(Hd_AI_3D_module* ptr) { qDebug() << "[INFO] " << "Hd_AI_3D_module destory success!"; if(ptr) { delete ptr; ptr = nullptr; } } Hd_AI_3D_module::Hd_AI_3D_module() { 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_3D_module::~Hd_AI_3D_module() { 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_3D_module::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[1]); //qDebug() << __FUNCTION__ << " line:" << __LINE__ << " resMat.data err:"; } //if (allNum++ % 2 == 0) // data = "2";// resByte.dequeue(); //else //data = "1*1.1,2.2";//1OK,2NG ////之后根据结果类修改 //if(resIfNg == true) // data = "NG"; //else data = "OK"; if (!savePath_result.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(moduleData.split(',')[2].split('_')[0])) { if (resultOKNG == 1) { isDirExist(savePath_result + "/OK"); addImgToSaveStruct(vec_mat[0], "0", savePath_result + "/OK/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".jpg");//保存结果图 } else { isDirExist(savePath_result + "/NG"); addImgToSaveStruct(vec_mat[0], "0", savePath_result + "/NG/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".jpg");//保存结果图 } } } } QString plcOkNgtext = ""; if (resultOKNG == 1) plcOkNgtext = "OK"; else plcOkNgtext = "NG"; QString sdataTime_msz = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz"); QString outResultText = sdataTime_msz + "," + SN + "," + splitDataList[1] + "," + plcOkNgtext + "," + QByteArray::number(resultData[0]) + "," + QByteArray::number(resultData[1]) + "," + QByteArray::number(resultData[2]) + "," + QByteArray::number(resultData[3]) + "," + QByteArray::number(resultData[4]) + "," + QByteArray::number(resultData[5]); //判断 文件夹/文件 是否存在 QFileInfo csv_fileInfo(savePath_csv + ".csv"); if (!csv_fileInfo.exists()) { //创建文件1 QFile file(savePath_csv + ".csv"); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out.setCodec(QTextCodec::codecForName("utf-8")); out << QString::fromStdString("日期,产品条码,相机工位,相机结果,清洗后长边铝壳间隙实际值,清洗后长边盖板台阶实际值,清洗后长边铝壳间隙实际值长边R角1,清洗后长边铝壳间隙实际值长边R角1,清洗后长边盖板台阶实际值长边R角1,清洗后长边盖板台阶实际值长边R角2 \n"); //out << QString::fromStdString("时间码,二维码,存盘路径,总结果,工位1_2D_TF,工位1_2D_TR,工位1_3D_TF,工位1_3D_TR,工位1_DE2,工位1_DE3 \n"); out << outResultText << "\n"; file.close(); } else { qDebug() << "____________________________" << __LINE__ << " csv !open "; } } else { //创建文件1 QFile file(savePath_csv + ".csv"); if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) { QTextStream out(&file); out.setCodec(QTextCodec::codecForName("utf-8")); out << outResultText << "\n"; file.close(); } else { qDebug() << "____________________________" << __LINE__ << " csv !open "; } } 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;*/ //resultOKNG = 1; data = QByteArray::number(resultOKNG) + "*" + QByteArray::number(resultData[0]) + "," + QByteArray::number(resultData[1]) + "," + QByteArray::number(resultData[2]) + "," + QByteArray::number(resultData[3]) + "," + QByteArray::number(resultData[4]) + "," + QByteArray::number(resultData[5]); //data = "1*1.1,2.2"; resByte.clear(); return true; } //从类中读数据到实例对象 bool Hd_AI_3D_module::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_3D_module::writeData(std::vector& vec_mat, QByteArray &data) { QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd"); //图片保存文件夹 QByteArray allDir = initValueList.last().split('#')[1]; isDirExist(allDir + "/" + sdataTime); QString name = "原图"; saveDir_sorce = allDir + "/" + sdataTime + "/" + name; isDirExist(saveDir_sorce); //不存在,创建 //name = "seg图"; //saveDir_seg = allDir + "/" + sdataTime + "/" + name; //isDirExist(saveDir_seg); //不存在,创建 //name = "cls图"; //saveDir_cls = allDir + "/" + sdataTime + "/" + name; //isDirExist(saveDir_cls); //不存在,创建 name = "结果图"; saveDir_result = allDir + "/" + sdataTime + "/" + name; isDirExist(saveDir_result); //不存在,创建 name = "csv数据表"; saveDir_csv = allDir + "/" + sdataTime + "/" + name; isDirExist(saveDir_csv); //不存在,创建 savePath_csv = saveDir_csv + "/" + sdataTime; qDebug() << __FUNCTION__ << "line:" << __LINE__ << " data:" << data; 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; sData = byteArrayToUnicode(data); splitDataList = sData.split(','); SN = splitDataList[3]; qDebug() << __FUNCTION__ << "line:" << __LINE__ << "QingXH3D1 SN:" << SN; if (splitDataList.size() >= 4) { //if (splitDataList[2].contains('_')) // cameraKey_index = splitDataList[2]; //QByteArray saveDir = splitDataList[0] + "/" + splitDataList[1] + "/"; //isDirExist(byteArrayToUnicode(saveDir)); //不存在,创建 QString sdataTime_msz = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz"); sdataTime_name = sdataTime_msz; //QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd"); QString sdataTime_h = QDateTime::currentDateTime().toString("hh"); savePath_sorce = saveDir_sorce + "/" + splitDataList[1]; //savePath_seg = saveDir_seg + "/" + splitDataList[1]; //savePath_cls = saveDir_cls + "/" + splitDataList[1]; savePath_result = saveDir_result + "/" + splitDataList[1]; //if (!checkedNameList.contains(splitDataList[1])) //{ // isDirExist(saveDir_sorce + "/" + splitDataList[1]); // isDirExist(saveDir_seg + "/" + splitDataList[1]); // isDirExist(saveDir_cls + "/" + splitDataList[1]); // isDirExist(saveDir_result + "/" + splitDataList[1]); // checkedNameList.append(splitDataList[1]); //} isDirExist(savePath_sorce); //isDirExist(savePath_seg); //isDirExist(savePath_cls); isDirExist(savePath_result); savePath_sorce = saveDir_sorce + "/" + splitDataList[1] + "/" + sdataTime_h + "H"; //savePath_seg = saveDir_seg + "/" + splitDataList[1] + "/" + sdataTime + "/" + sdataTime_h + "H"; //savePath_cls = saveDir_cls + "/" + splitDataList[1] + "/" + sdataTime + "/" + sdataTime_h + "H"; savePath_result = saveDir_result + "/" + splitDataList[1] + "/" + sdataTime_h + "H"; isDirExist(savePath_sorce); //isDirExist(savePath_seg); //isDirExist(savePath_cls); isDirExist(savePath_result); //savePath_sorce = saveDir_sorce + "/" + splitDataList[1] + "/" + sdataTime + "/" + sdataTime_h + "H" + "/" + SN; //isDirExist(savePath_sorce); } resultOKNG = 1; resultData[0] = 0; resultData[1] = 0; if (!savePath_sorce.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 (HikMat.size() == 2)//3D { addImgToSaveStruct(HikMat[0], "0", savePath_sorce + "/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".tiff"); addImgToSaveStruct(HikMat[1], "0", savePath_sorce + "/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".bmp"); } else addImgToSaveStruct(HikMat[0], "0", savePath_sorce + "/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".bmp");//保存原图 } } moduleData = data; qstring_data = byteArrayToUnicode(data); detect_mutex->unlock(); //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_3D_module::initParas(QByteArray& byte) { myEngine.SetProcedurePath("./halconFilesAlgo/AlgoLibrary_628_1.hdpl"); //设置hdvp路径 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); }*/ QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd"); //图片保存文件夹 QByteArray allDir = initValueList.last().split('#')[1]; isDirExist(allDir + "/" + sdataTime); QString name = "原图"; saveDir_sorce = allDir + "/" + sdataTime + "/" + name; isDirExist(saveDir_sorce); //不存在,创建 //name = "seg图"; //saveDir_seg = allDir + "/" + sdataTime + "/" + name; //isDirExist(saveDir_seg); //不存在,创建 //name = "cls图"; //saveDir_cls = allDir + "/" + sdataTime + "/" + name; //isDirExist(saveDir_cls); //不存在,创建 name = "结果图"; saveDir_result = allDir + "/" + sdataTime + "/" + name; isDirExist(saveDir_result); //不存在,创建 name = "csv数据表"; saveDir_csv = allDir + "/" + sdataTime + "/" + name; isDirExist(saveDir_csv); //不存在,创建 savePath_csv = saveDir_csv + "/" + sdataTime; //StationNo = vec_ret.at(0).toInt(); //InitModels(); //InitThreads(StationNo, img2D); //InitModels(StationNo, img2D); //运行检测线程 ifdetectThread = true; //线程检测:结果类完成时,使用 //ifThreadRunDetect = true; //QFuture future1 = QtConcurrent::run(this, &Hd_AI_3D_module::detectThread); //运行存图线程 QFuture future2 = QtConcurrent::run(this, &Hd_AI_3D_module::saveImgThread); //detectThread(); //原图总文件夹 isDirExist(oriImgSaveDir); //原图class总文件夹 isDirExist(classImgSaveDir); //结果图总文件夹 isDirExist(resImgSaveDir); //qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ; return true; } bool Hd_AI_3D_module::InitModels() { int flag = 0; //seg_aokeng = CreateSegObjS((char*)modelPath_seg_aokeng.c_str(), 1, 0); if (seg_aokeng->getStatus() != SegStatus::Seg_Success)flag++; //seg_zhenyan = CreateSegObjS((char*)modelPath_seg_zhenyan.c_str(), 1, 0); if (seg_zhenyan->getStatus() != SegStatus::Seg_Success)flag++; //seg_pianhan = CreateSegObjS((char*)modelPath_seg_pianhan.c_str(), 1, 0); if (seg_pianhan->getStatus() != SegStatus::Seg_Success)flag++; //seg_rongding = CreateSegObjS((char*)modelPath_seg_rongding.c_str(), 1, 0); if (seg_rongding->getStatus() != SegStatus::Seg_Success)flag++; //det_hanhou = CreateDetObjS((char*)modelPath_det_hanhou.c_str(), 1, 0); if (det_hanhou->getStatus() != DetStatus::Det_Success)flag++; // det_neiquan = CreateDetObjS((char*)modelPath_det_neiquan.c_str(), 1, 0); if (det_neiquan->getStatus() != DetStatus::Det_Success)flag++; //cls_hanhou = CreateClsObjV3((char*)modelPath_cls_hanhou.c_str(), 0, 1); if (cls_hanhou->getStatus() != ClsStatus::Cls_Success)flag++; return (flag == 0); } // 解码 bool Hd_AI_3D_module::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_3D_module::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime) { try { //存图数据加保存队列,加锁,避免数据访问冲突 saveStruct_mutex->lock(); saveImgStruct mySave; Mat sourceImg; sourceImg = img2D.clone(); //img2D.copyTo(sourceImg); //img2D.release(); QString mysaveKey1 = mysaveKey; //"offlineStation1_off_1" saveStruct_mutex->unlock(); QJsonDocument document; QJsonObject obj; obj.insert("result_key", "mysaveKey"); obj.insert("SN", "mySN"); obj.insert("DataTime", "myDataTime"); //QFile csvName("test.csv"); //QStringList lines; //lines << "class,name\n" << "3,4,5,6,7\n" << "a,b,c,d\n"; //if (csvName.open(QIODevice::WriteOnly)) //若文件不存在,会自动创建 //{ // for (int i = 0; i < lines.size(); i++) // csvName.write(lines[i].toStdString().c_str()); // csvName.close(); //} QQueue defectInfoList; //seg后class检测逻辑 /*if (0) { Mat sourceRectangles;// 在原图缺陷位置,边界矩形框出 sourceRectangles = sourceImg.clone(); //sourceImg.copyTo(sourceRectangles); vector> contours; //seg检测 Mat resultDstImg;// = sourceImg.clone();// = pSeg->Evaluate(sourceImg); //返回单通道二值图 图片错误输出Image Error!但不报错。。 resultDstImg = pSeg->Evaluate(sourceImg); //int resultClass = pCls->Evaluate(sourceImg); //类别id //opencv对二值图进行处理 //GaussianBlur(resultDstImg, resultDstImg, Size(3, 3), 1); //缺陷过滤值较大时,可以减少检出数;缺陷较小时,漏检较多 threshold(resultDstImg, resultDstImg, pSeg->m_classes, 255, THRESH_BINARY_INV);//大于部分设为0,小于部分设为255 //findContours(resultDstImg, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); //不识别内部轮廓,有些情况抓到的图像外框? findContours(resultDstImg, contours, cv::noArray(), cv::RETR_TREE, cv::CHAIN_APPROX_NONE); //需要内部轮廓的写法 if (contours.size() == 0) { //printf("Notlabeled\n"); } else { for (int j = 0; j < contours.size(); j++) { Rect rect1 = boundingRect(Mat(contours[j])); //最小缺陷过滤参数,根据项目实际设置! int filterNum = 10; float w = rect1.width * 1.0; float h = rect1.height * 1.0; if ((w / sourceImg.cols > 0.98) || (h / sourceImg.rows > 0.98)) { //抓到图像外框了 //qDebug() << "NG is too big..."; continue; } //且逻辑,有的项目需要或逻辑!! if ((w > filterNum && h > filterNum))//||rect1.area> filterNum*filterNum*1.5) { //class检测mat Mat imgCls; //此段为切图逻辑为: //缺陷外扩5像素; //判断最大边,大于class建网大小的,按照最大边尺寸比例切大图,然后resize为建网大小;最大边小于等于建网大小的,按照建网大小切图; //越界填充 { int startX = rect1.x - 5; int startY = rect1.y - 5; int endX = rect1.x + rect1.width + 5; int endY = rect1.y + rect1.height + 5; //尺寸比例 double maxscaler, scalerX, scalerY; maxscaler = 1.0; scalerX = (endX - startX) * 1.0 / sizeW;//*1.0转为float,避免被取整了 scalerY = (endY - startY) * 1.0 / sizeH; maxscaler = max(maxscaler, max(scalerX, scalerY)); int avgX = (rect1.x + rect1.x + rect1.width) / 2; //中点X位置 int avgY = (rect1.y + rect1.y + rect1.height) / 2;//中点Y位置 startX = avgX - int(maxscaler * sizeW / 2);//强转为int endX = startX + int(maxscaler * sizeW); startY = avgY - int(maxscaler * sizeH / 2); endY = startY + int(maxscaler * sizeH); //判断是否越界,越界要填充的像素个数 int copyTop = max(0, 0 - startY); int copyButton = max(0, endY - sourceImg.rows); int copyLeft = max(0, 0 - startX); int copyRight = max(0, endX - sourceImg.cols); //切图不要越界,会崩溃 Mat imgCut = sourceImg(Range(max(0, startY - copyTop), min(sourceImg.rows, endY - copyButton)), Range(max(0, startX - copyLeft), min(sourceImg.cols, endX - copyRight))); //起始行,终止行;起始列,终止列 //图像扩充 if (sourceImg.channels() == 1) { copyMakeBorder(imgCut, imgCut, copyTop, copyButton, copyLeft, copyRight, BORDER_CONSTANT, fillColour); } else { copyMakeBorder(imgCut, imgCut, copyTop, copyButton, copyLeft, copyRight, BORDER_CONSTANT, Scalar(fillColour, fillColour, fillColour)); } //resize为建网大小 cv::resize(imgCut, imgCls, cv::Size(sizeW, sizeH)); imgCut.release(); } int resultClass = 0; float prob = 1.0; resultClass = pCls->Evaluate(imgCls); //类别id prob = pCls->getProbability(); //可能性 //切图保存,按需 { isDirExist(classImgSaveDir + mysaveKey1 + "/class_" + QString::number(resultClass)); //存图数据入队,按需 addImgToSaveStruct(imgCls, mysaveKey1, classImgSaveDir + mysaveKey1 + "/class_" + QString::number(resultClass) + "/" + mySN + myDataTime + QString::number(j) + ".bmp"); } //此处应添加缺陷计数逻辑 if (resultClass == 0)//OK { ; } else if (resultClass == 1)//划伤Scratch { resIfNg = true; //rectangle(sourceRectangles, rect1.tl(), rect1.br(), Scalar(0, 0, 255), 3, 8); ////可行,必须转一下格式 //{ // QString pathQstr = "划伤"; // QByteArray path_arr = pathQstr.toLocal8Bit(); // const char* path = path_arr.data(); // putTextZH(sourceRectangles, path, cv::Point(rect1.tl().x, rect1.tl().y - 5), Scalar(255, 0, 0), 50, "微软雅黑"); //} defectInfo mdefectInfo; mdefectInfo.defectName = "划伤"; mdefectInfo.defectRect = rect1; mdefectInfo.defectArea = contourArea(contours[j]); mdefectInfo.defectScalar = cv::Scalar(0, 0, 255); defectInfoList.enqueue(mdefectInfo); } else if (resultClass == 2)//碰伤 { resIfNg = true; defectInfo mdefectInfo; mdefectInfo.defectName = "碰伤"; mdefectInfo.defectRect = rect1; mdefectInfo.defectArea = contourArea(contours[j]); mdefectInfo.defectScalar = cv::Scalar(0, 255, 255); defectInfoList.enqueue(mdefectInfo); } imgCls.release(); } else { //cout << "ng is too small<" << filterNum << endl; continue; } } } //cv::Mat resMat = img2D.clone(); sourceRectangles.release(); contours.resize(0); resultDstImg.release(); } */ detect_mutex->lock(); //resMat = sourceImg.clone(); //sourceImg.copyTo(resMat); resMat.push_back(sourceImg); //结果图画框和缺陷,在resMat上绘制 if (resMat.size() > 0) drawDefects(resMat[0], defectInfoList); //QByteArray,根据实际项目进行解析 //参数,例:返回结果图;相机关键字(SN或userID)+保存路径+缺陷信息列表(缺陷名称,缺陷位置int(x,y,w,h),画框颜色Scalar(a,b,c),缺陷面积double) QJsonArray detaillists; //QByteArrayList resQbyte; for (int i = 0; i < defectInfoList.size(); i++) { defectInfo mdefect = defectInfoList[i]; //resQbyte.push_back(mdefect.defectName.toLocal8Bit()); //中文也可以QString::number(1.1).toUtf8() //resQbyte.push_back(QString::number(mdefect.defectRect.x).toUtf8()); //resQbyte.push_back(QString::number(mdefect.defectRect.y).toUtf8()); //resQbyte.push_back(QString::number(mdefect.defectRect.width).toUtf8()); //resQbyte.push_back(QString::number(mdefect.defectRect.height).toUtf8()); //resQbyte.push_back(QString::number(mdefect.defectScalar[0]).toUtf8()); //resQbyte.push_back(QString::number(mdefect.defectScalar[1]).toUtf8()); //resQbyte.push_back(QString::number(mdefect.defectScalar[2]).toUtf8()); //resQbyte.push_back(QString::number(mdefect.defectArea).toUtf8()); QJsonObject detailObj; detailObj.insert("defectName", "mdefect.defectName"); detailObj.insert("defectRect.x", QString::number(mdefect.defectRect.x)); detailObj.insert("defectRect.y", QString::number(mdefect.defectRect.y)); detailObj.insert("defectRect.width", QString::number(mdefect.defectRect.width)); detailObj.insert("defectRect.height", QString::number(mdefect.defectRect.height)); detailObj.insert("defectScalar0", QString::number(mdefect.defectScalar[0])); detailObj.insert("defectScalar1", QString::number(mdefect.defectScalar[1])); detailObj.insert("defectScalar2", QString::number(mdefect.defectScalar[2])); detailObj.insert("defectArea", QString::number(mdefect.defectArea)); detailObj.insert("defectLength", QString::number(sqrt(mdefect.defectRect.width* mdefect.defectRect.width+ mdefect.defectRect.height* mdefect.defectRect.height))); detaillists.append(detailObj); } //使用完删除 defectInfoList.clear(); //往主界面发 //emit sendResultData(resMat, resQbyte); //resQbyte.clear(); isDirExist(resImgSaveDir + mysaveKey1 + "/"); QString qimgsavePath = resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png"; //存图数据入队,按需 if (resMat.size() > 0 ) addImgToSaveStruct(resMat[0], mysaveKey1, resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png"); detect_mutex->unlock(); obj.insert("detaillists", detaillists); obj.insert("qimgsavePath", qimgsavePath); document.setObject(obj); //resByte.clear(); QByteArray qa = document.toJson(); //resByte .enqueue(qa); //resMat.release(); sourceImg.release(); mySave.out_Mat.resize(0); mysaveKey1.clear(); qApp->processEvents(); ////原图和结果都往主界面发? //std::vector resMat; //resMat.push_back(img2D); //resMat.push_back(sourceRectangles); //QByteArray resByte = mysaveKey.toLocal8Bit(); //resByte.append(myDir2D.toLocal8Bit()); //resByte.append(mySN.toLocal8Bit()); //resByte.append(myDataTime.toLocal8Bit()); ////往主界面发送图片和数据 ////emit writeData(resMat, resByte); //resMat.resize(0); //resByte.resize(0); } catch (...) { qDebug() << "[Error] " << QString::fromUtf8("检测失败!"); return false; } return true; } //存图加入队列 void Hd_AI_3D_module::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_3D_module::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_3D_module::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_3D_module::run() { try { qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << SN << "_run start"; clock_t start, stop, start1, stop1, start2, stop2; start = clock(); //if (HikMat.isEmpty()) //{ // cv::Mat null_mat = cv::Mat::zeros(cv::Size(100, 100), CV_8UC3); // resMat.push_back(null_mat); // qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << SN << "_HikMat.isEmpty"; // return true; //} // //if (HikMat[0].rows == 100 || HikMat[0].cols == 100 || HikMat[1].rows == 100 || HikMat[1].cols == 100) //{ // cv::Mat null_mat = cv::Mat::zeros(cv::Size(100, 100), CV_8UC3); // resMat.push_back(null_mat); // resultData[0] = 1.1; // resultData[1] = 2.2; // resultData[2] = 3.3; // resultData[3] = 4.4; // resultData[4] = 5.5; // resultData[5] = 6.6; // qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << SN << "_HikMat is 100 * 100"; // return true; //} cv::Mat HeightImage; cv::Mat LightImage; cv::Mat resultImg; cv::Mat img_dst; cv::Mat srcImg; cv::Mat tmpMatL = cv::imread("D://04QCB30601000JF4K0000041_camera3D4_0_2025-04-19-15-30-07-703.bmp", -1), tmpMatH=cv::imread("D://04QCB30601000JF4K0000041_camera3D4_0_2025-04-19-15-30-07-703.tiff",-1); if (tmpMatL.channels() == 3) cv::cvtColor(tmpMatL, srcImg, COLOR_BGR2GRAY); else srcImg = tmpMatL.clone(); if (tmpMatH.channels() == 3) cv::cvtColor(tmpMatH, HeightImage, COLOR_BGR2GRAY); else HeightImage = tmpMatH.clone(); srcImg.copyTo(LightImage); srcImg.copyTo(img_dst); cv::cvtColor(img_dst, img_dst, COLOR_GRAY2BGR); //#if 0 HalconCpp::HObject in_imageH = MatToHObject(HeightImage); HalconCpp::HObject in_imageLum = MatToHObject(LightImage); HalconCpp::HTuple out_Flag;//, 算法的执行结果, 0: 算法执行异常 1 : 算法执行成功 HTuple in_xResolution = 0.0025; HTuple in_yResolution = 0.05; HTuple in_zResolution = 0.0004; HTuple out_MaxHeight; //最大高度 HTuple out_MaxWidth; //最大缝隙 HTuple out_ResultColumn; //X坐标 HTuple out_ResultRow; //Y坐标 HObject out_DisplayImage; HTuple in_Location; if (splitDataList[1].contains("清洗3D1") || splitDataList[1].contains("清洗3D2")) in_Location = "Left"; else in_Location = "Right"; HDevEngineCpp::HDevProcedure proc("detect_gap_width_height_6_1"); HDevProcedureCall procedureCall(proc); procedureCall.SetInputIconicParamObject("in_imageH", in_imageH);//传给算法图片 procedureCall.SetInputIconicParamObject("in_imageLum", in_imageLum);//传给算法图片 procedureCall.SetInputCtrlParamTuple("in_xResolution", in_xResolution);//传给算法参数 procedureCall.SetInputCtrlParamTuple("in_yResolution", in_yResolution);//传给算法参数 procedureCall.SetInputCtrlParamTuple("in_zResolution", in_zResolution);//传给算法参数 procedureCall.SetInputCtrlParamTuple("in_Location", in_Location);//传给算法参数 procedureCall.Execute();//执行halcon程序 out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量 //高度+-0.3 宽度0.06 if (out_Flag.Length() > 0) { qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "_out_Flag" << out_Flag.I(); if (out_Flag.I() == 1) //算法检测成功 { out_MaxHeight = procedureCall.GetOutputCtrlParamTuple("out_MaxHeight");//获取输出控制类变量 out_MaxWidth = procedureCall.GetOutputCtrlParamTuple("out_MaxWidth");//获取输出控制类变量 out_ResultRow = procedureCall.GetOutputCtrlParamTuple("out_ResultRow");//获取输出控制类变量 out_ResultColumn = procedureCall.GetOutputCtrlParamTuple("out_ResultColumn");//获取输出控制类变量 out_DisplayImage = procedureCall.GetOutputIconicParamObject("out_DisplayImage");//获取输出控制类变量 cv::Mat outputImage = HObject2Mat(out_DisplayImage); if (outputImage.channels() != 3) cv::cvtColor(outputImage, outputImage, COLOR_GRAY2BGR); outputImage.copyTo(resultImg); qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "_YuHanQian3D_out_MaxHeight" << out_MaxHeight.D() << "_YuHanQian3D_out_MaxWidth" << out_MaxWidth.D(); if (out_MaxHeight.Length() > 0 && out_MaxWidth.Length() > 0) { resultData[0] = out_MaxWidth[0].D(); resultData[1] = out_MaxHeight.D(); resultData[2] = out_MaxWidth[1].D(); resultData[3] = out_MaxWidth[1].D(); resultData[4] = out_MaxHeight.D(); resultData[5] = out_MaxHeight.D(); resultOKNG = 1;//初始化为OK if (out_MaxHeight.D() >= 0.8 || out_MaxHeight.D() <= -0.8){//NG //resultOKNG = 2; QString text = "最大高度:" + QString::number(out_MaxHeight.D()); QByteArray path_arr = text.toLocal8Bit(); const char* path = path_arr.data(); putTextZH(resultImg, path, cv::Point(50, 550), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false); } else{ QString UP_Down = "最大高度:" + QString::number(out_MaxHeight.D()); QByteArray path_arr = UP_Down.toLocal8Bit(); const char* path = path_arr.data(); putTextZH(resultImg, path, cv::Point(50, 550), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false); } if (out_MaxWidth.D() > 0.3) {//NG QString text = "最大宽度:" + QString::number(out_MaxWidth.D()); QByteArray path_arr = text.toLocal8Bit(); const char* path = path_arr.data(); putTextZH(resultImg, path, cv::Point(50, 950), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false); } else {//OK QString text = "最大宽度:" + QString::number(out_MaxWidth.D()); QByteArray path_arr = text.toLocal8Bit(); const char* path = path_arr.data(); putTextZH(resultImg, path, cv::Point(50, 950), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false); } if (out_MaxWidth[1].D() > 0.3) {//NG resultOKNG = 2; QString text = "两端最大宽度:" + QString::number(out_MaxWidth[1].D()); QByteArray path_arr = text.toLocal8Bit(); const char* path = path_arr.data(); putTextZH(resultImg, path, cv::Point(50, 1350), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false); } else {//OK QString text = "两端最大宽度:" + QString::number(out_MaxWidth[1].D()); QByteArray path_arr = text.toLocal8Bit(); const char* path = path_arr.data(); putTextZH(resultImg, path, cv::Point(50, 1350), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false); } /*double extraWidthData = out_MaxWidth[1].D(); { QString text = "两端最大宽度:" + QString::number(extraWidthData); QByteArray path_arr = text.toLocal8Bit(); const char* path = path_arr.data(); putTextZH(resultImg, path, cv::Point(50, 1350), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false); }*/ } } else { resultData[0] = 1.1; resultData[1] = 2.2; resultData[2] = 3.3; resultData[3] = 4.4; resultData[4] = 5.5; resultData[5] = 6.6; QString UP_Down = "压装异常或间隙不良"; QByteArray path_arr = UP_Down.toLocal8Bit(); const char* path = path_arr.data(); putTextZH(img_dst, path, cv::Point(50, 200), cv::Scalar(0, 255, 0), 150, "微软雅黑", false, false); qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "YuHanQian3D Algo Error NG" << out_Flag.I(); resultOKNG = 2; } } //#endif if (resultImg.cols > 0 && resultImg.rows > 0) { if (resultOKNG == 1) { putTextZH(resultImg, "OK", cv::Point(50, 0), cv::Scalar(0, 255, 0), 150, "微软雅黑", false, false); } else { putTextZH(resultImg, "NG", cv::Point(50, 0), cv::Scalar(0, 0, 255), 150, "微软雅黑", false, false); } resMat.push_back(resultImg); } else { if (resultOKNG == 1) { putTextZH(img_dst, "OK", cv::Point(50, 0), cv::Scalar(0, 255, 0), 200, "微软雅黑", false, false); } else { putTextZH(img_dst, "NG", cv::Point(50, 0), cv::Scalar(0, 0, 255), 200, "微软雅黑", false, false); } resMat.push_back(img_dst); } stop = clock(); qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "RunTime::" << stop - start; } catch (HDevEngineCpp::HDevEngineException& ex) { std::cerr << "HDevEngineException: " << ex.Message() << std::endl; } catch (HException& ex) { // 捕获Halcon异常 std::cerr << "Halcon Exception Caught!" << std::endl; std::cerr << "Error Code: " << ex.ErrorCode() << std::endl; std::cerr << "Error Message: " << ex.ErrorMessage() << std::endl; } catch (std::exception& ex) { // 捕获其他标准异常 std::cerr << "Standard Exception Caught: " << ex.what() << std::endl; } catch (...) { qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "_YuHanQian3D _error"; return true; } return true; } bool Hd_AI_3D_module::checkStatus() { status = moduleStatus; return status; }