#include #include #include "camera_thread.h" #include "myiothread.h" #include "FrontendBackendBridge.h" #include #include bool showOk = true;//显示ok缺陷的框 std::string fileSavePath("D://CCD//"); ////////////////////// void writeToData_xxxCsvOkNgNew(detData* rdata, QString OKNG, ngNoteCls* note) { QDateTime currentDateTime = QDateTime::currentDateTime(); std::string ymd = currentDateTime.toString("yyyy-MM-dd").toStdString(); QString filePath = QString::fromStdString(fileSavePath + "//result//" + ymd + "//Data_" + ymd + ".csv"); /* QString searchString = QString::fromStdString(rdata->getSN() + "_" + to_string(rdata->snCountIndex));*/ QString searchString = QString::fromStdString(rdata->SNcode); QFile file(filePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Error opening file."; } QStringList headers; QList data; QTextStream in(&file); while (!in.atEnd()) { QString line = in.readLine(); QStringList fields = line.split(','); if (headers.isEmpty()) { // 如果headers为空,则当前行为标题行 headers = fields; } else { data.append(fields); } } file.close(); // 在data中进行字符串检索并修改匹配的行 int modifiedRowCount = 0; for (int i = data.size() - 1; i > 0; --i) { QStringList& row = data[i]; //if (row.size()<3||row.isEmpty()) //{ // break; //} // 在当前行中检索字符串 try { if (row.size() >= 6) if (row[1].contains(searchString, Qt::CaseInsensitive)) { // 匹配到字符串,进行修改 row[3] = OKNG; row[4] += note->getNgSummaryStr(); row[5] += note->getOkSummaryStr(); modifiedRowCount++; } } catch (...) { break; } } // 将修改后的数据写回文件 QFile writeFile(filePath); if (!writeFile.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug() << "Error opening file for writing."; } QTextStream out(&writeFile); // 写入标题行 out << headers.join(",") << "\n"; // 写入修改后的数据行 for (const auto& row : data) { out << row.join(",") << "\n"; } writeFile.close(); qDebug() << "Modified rows:" << modifiedRowCount; qDebug() << "Data modified and saved to data_modified.csv"; //return 0; } void writeToData_xxxCSVNew(detData* resData, string OKNG, ngNoteCls* note) { QDateTime currentDateTime = QDateTime::currentDateTime(); std::string ymd = currentDateTime.toString("yyyy-MM-dd").toStdString(); int hour = currentDateTime.time().hour(); QString filePath = QString::fromStdString(fileSavePath + "//result//" + ymd + "//Data_" + ymd + ".csv"); //string sn(resData->SNcode + "-" + to_string(resData->snCountIndex)); string sn(resData->SNcode); /*std::string str(to_string(hour) + "H//" + sn + "-" + to_string(resData->snCountIndex) + "//" + ymd + "-" + to_string(hour) + "_" + resData->getSN() + "-" + to_string(resData->snCountIndex));*/ std::string str(to_string(hour) + "H//" + sn + "//" + ymd + "-" + to_string(hour) + "_" + sn); bool fileExist = false; QStringList dataList; if (hour < 10) dataList.append("0" + QString::number(hour) + "H"); else dataList.append(QString::number(hour) + "H"); dataList.append(QString::fromStdString(sn)); dataList.append(QString::fromStdString(str)); dataList.append(QString::fromStdString(OKNG)); dataList.append(note->getNgSummaryStr()); dataList.append(note->getOkSummaryStr()); // 创建CSV文件 QFile file(filePath); if (!file.exists()) { // 创建目录(如果不存在) QDir dir; if (!dir.mkpath(QFileInfo(filePath).absolutePath())) { //qWarning() << "无法创建目录:" << QFileInfo(filePath).absolutePath(); return; } fileExist = true; } // 打开CSV文件并写入数据 if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { QTextStream stream(&file); if (fileExist == true) { stream << "Time,"; stream << "SN,"; stream << "Path,"; stream << "Result,"; stream << "summuryResult,"; stream << "\n"; } // 将数据写入CSV文件 for (const QString& data : dataList) { stream << data << ","; } stream << "\n"; file.close(); qDebug() << "CSV文件写入成功"; } //else // qWarning() << "无法打开CSV文件:" << filePath; } void algoThread::getAllFiles(string path, vector& files, string format) { intptr_t hFile = 0;//恅璃曆梟 struct _finddata_t fileinfo;//恅璃陓洘 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); } } inline string getFileName(string path) { return path.substr(path.find_last_of("\\") + 1, path.find_last_of(".") - path.find_last_of("\\") - 1); } void drawContoursOverlap(cv::Mat& image, const std::vector>& contours) { cv::Mat mask = cv::Mat::zeros(image.size(), CV_8U); // 绘制轮廓在掩码上 cv::drawContours(mask, contours, -1, cv::Scalar(255), cv::FILLED); // 将图像中与掩码不重叠的区域涂黑 cv::Mat result; image.copyTo(result, mask); image.setTo(cv::Scalar(0, 0, 0), ~mask); } void drawContourOnImage(Mat seg, cv::Mat& imgInput, Size offset = Size(0, 0)) { if (seg.empty() || imgInput.empty()) { std::cerr << "Empty contour or input image." << std::endl; return; } cv::Mat imgWithAlpha; cv::cvtColor(imgInput, imgWithAlpha, cv::COLOR_BGR2BGRA); std::vector>contours; if (offset.width != 0 && offset.height != 0) { Mat offsetImg(offset.width + seg.rows, offset.height + seg.cols, CV_8UC1, Scalar(0)); seg.copyTo(offsetImg(Rect(offset.width, offset.height, seg.rows, seg.cols))); offsetImg.copyTo(seg); } cv::findContours(seg, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); for (auto& contour : contours) { cv::Scalar color(0, 255, 0, 128); cv::polylines(imgWithAlpha, contour, true, color); cv::cvtColor(imgWithAlpha, imgInput, cv::COLOR_BGRA2BGR); } } /////Specified function//////////////// void writeSpecificStatement(Mat& Paint, const wchar_t* Text, rectAndData& data, int amount, int limit, Scalar& color) { wstring MM(to_wstring(max(data.defectHeight, data.defectWidth))); MM = MM.substr(0, MM.find_first_of(L".") + 2); putTextHusky(Paint, (WString2String(Text + to_wstring(amount) + L"/" + to_wstring(limit) + L"|" + MM + L"mm")).c_str(), cv::Point(data.rect.x, data.rect.y - 20), color, 20); } /////////////////////ALGOTHREAD///////////////////////// bool algoThread::addDetTask(detData* data) { detQueueMutex.lock(); detQueue.append(data); detQueueMutex.unlock(); this->start(); return false; } bool algoThread::waitForImg(detData* data,int timeOutSet=10000) { int timeOut = 0; int sleepMs = 100; while (1) { int imgSize = data->imgs.size(); int imgAmountMin = data->imgAmountMin; if (imgSize >= imgAmountMin) return true; timeOut+= sleepMs; if (timeOut > timeOutSet) return false; QThread::msleep(sleepMs); } } void algoThread::run() { while (m_runFlag == true) { while (detQueue.size() > 0) { detQueueMutex.lock(); detData* data = detQueue.dequeue();//取出数据 detQueueMutex.unlock(); if (waitForImg(data) == false) { qDebug() << "取图失败"; cout << "get img err" << endl; break; } oriSaveThread->saveOriImg(data);//保存原图 bridge.front.showImg("Camera", data->imgs[0], data->oriShowIndex);//显示原图 int threadId = data->algoThreadIndex;//获取线程id switch (threadId) { case 0: _25D_1_Algo(data); break; case 1: _25D_2_Algo(data); break; } if (data->resultImgs.size() > 0) { for (int cnt = 0; cnt < data->resultImgs.size(); cnt++) { bridge.front.showImg("Algorithm", data->resultImgs[cnt], data->oriShowIndex + cnt);//显示原图 } resSaveThread->saveResImg(data);//保存结果图 } if (!data->SNcode.compare(snDatas->snErrorsnError))//无sn阻塞 data->SNcode = snDatas->waitForSn(data->timeCode); //cout << "algoEnd" << data->algoThreadIndex; sqlDataStruct sqlDataStruct;//定义sql数据 sqlDataStruct.SN = data->SNcode;// for (auto sqlData : data->sqlVec)//将算法中的数据导入到数据结构中 sqlDataStruct.dataVec.push_back(sql->sqlDatasInit(sqlData.first, sqlData.second)); sql->addData(sqlDataStruct);//将数据插入数据库 //delete data; detDataController* dController = data->dController; data->dController->deleteDetData(data->timeCode); } QThread::msleep(10); } } void algoThread::_25D_1_Algo(detData* data) { if (data->imgs.size() < 6) { qDebug() << __FUNCDNAME__ << __LINE__ << "camera Mat size is Error!"; return; } ///////////////////取图///声明///////////////////// ngNoteCls Note; cv::Mat SprfSpecularReflectionImage = data->imgs[0]; cv::Mat SprfDiffuseReflectionImage = data->imgs[1]; cv::Mat SprfShapeImage1 = data->imgs[2]; cv::Mat SprfShapeImage2 = data->imgs[3]; cv::Mat SprfGlossRatioImage = data->imgs[4]; cv::Mat SprfNormalImage = data->imgs[5]; cv::Mat Paint; if (SprfGlossRatioImage.channels() == 1) { cv::cvtColor(SprfGlossRatioImage, Paint, cv::COLOR_GRAY2BGR); } int CCD1OK = 1; double CCD1height = -1; double dmCodeWidth = 0, dmCodeHeight = 0; double pixAccX = bridge.back.json.PixelAccuracy.getData("_25D_1_X"); double pixAccY = bridge.back.json.PixelAccuracy.getData("_25D_1_Y"); cv::Point qrPos; Rect qrRect; ////////////////算法/////////////////////////////// if (data->skip[0] != 1) { HObject ho_Image=simpleAlgo::MatToHObject(SprfShapeImage1); HTuple hv_Out_Mean; HTuple hv_Out_Max; HTuple hv_Out_Min; HTuple hv_Out_Line1; HTuple hv_Out_Line2; HTuple hv_Make; _952_15_Distance(ho_Image, &hv_Out_Mean, &hv_Out_Max, &hv_Out_Min, &hv_Out_Line1, &hv_Out_Line2, &hv_Make); if (hv_Make.D() != -1) { line(Paint, cv::Point(hv_Out_Line1[1].D(), hv_Out_Line1[0].D()), cv::Point(hv_Out_Line1[3].D(), hv_Out_Line1[2].D()), Scalar(0, 255, 0), 1); line(Paint, cv::Point(hv_Out_Line2[1].D(), hv_Out_Line2[0].D()), cv::Point(hv_Out_Line2[3].D(), hv_Out_Line2[2].D()), Scalar(0, 255, 0), 1); cv::putText(Paint, "hv_Out_Max:" + to_string(hv_Out_Max.D()*0.03), cv::Point(100, 100), 1, 10, Scalar(0, 255, 0), 5); } } #if 0 /////////二维码位置屏蔽 avoidArea avoidA; avoidA.addArea(SprfShapeImage1Resize, modelPtr->camera1Seg_erWeiMa); ///////////脏污/////////////////////// if (data->skip[2] != 1) { #if 1 int amount = 0, limit = 1; cv::Mat resMat = ~modelPtr->camera1Seg_ZangWu->Evaluate(SprfSpecularReflectionImageResize); std::vector>contours; cv::findContours(resMat, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vectorpaintVec;//flase NG true OK for (auto contour : contours) { cv::Rect rect = cv::boundingRect(contour); int rectCenterX = 0, rectCenterY = 0; rectCenterX = rect.x + rect.width / 2; rectCenterY = rect.y + rect.height / 2; if (avoidA.checkOverLap(Point(rectCenterX, rectCenterY)) == true)//有与二维码重叠 continue; double defectHeight = rect.height * pixAccY * 2; double defectWidth = rect.width * pixAccX * 2; if (rect.height > 10 && rect.width > 10) { //amount++; rect.x *= 2; rect.y *= 2; rect.width *= 2; rect.height *= 2; if (defectHeight > 2 || defectWidth > 2)//2mm { amount++; paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,false) }); } else //if (showOk == true) paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,true) }); } } for (auto& data : paintVec) { Scalar color; if (amount >= limit || data.result == false)//NG { Note.insertNgData(u8"脏污", data.defectWidth, data.defectHeight); color = Scalar(0, 0, 255); } else//OK color = Scalar(0, 255, 0); cv::rectangle(Paint, data.rect, color, 2); writeSpecificStatement(Paint, L"脏污", data, amount, limit, color); } if (amount >= limit) { putTextHusky(Paint, (WString2String(L"脏污NG").c_str()), { 6800,3600 }, Scalar(0, 0, 255), 300); CCD1OK = 1; } #endif } ///////////////凹坑/////////////// if (data->skip[3] != 1) { int amount = 0, limit = 1; cv::Mat resMat = ~modelPtr->camera1Seg_aoKeng->Evaluate(SprfShapeImage1Resize); drawContourOnImage(resMat, SprfShapeImage1Paint); std::vector>contours; cv::findContours(resMat, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector>contourForGrayShow;//给灰度值计算 std::vectorpaintVec;//flase NG true OK for (auto contour : contours) { cv::Rect rect = cv::boundingRect(contour); int rectCenterX = 0, rectCenterY = 0; rectCenterX = rect.x + rect.width / 2; rectCenterY = rect.y + rect.height / 2; if (avoidA.checkOverLap(Point(rectCenterX, rectCenterY)) == true)//有与二维码重叠 continue; double defectHeight = rect.height * pixAccY * 2; double defectWidth = rect.width * pixAccX * 2; if (rect.height > 10 && rect.width > 10) { rect.x *= 2; rect.y *= 2; rect.width *= 2; rect.height *= 2; Mat img_cls = simpleAlgo::cutImg2Cls(contour, SprfShapeImage1Resize); int res = modelPtr->camera1Cls_aoKeng->Evaluate(img_cls); if (defectHeight > 0 || defectWidth > 0)//有就算 { paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,res,false) }); } else //if (showOk == true) paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,res,true) }); } } //Paint for (auto& data : paintVec) { Scalar color(0, 255, 0); if (data.result == false)//NG { //0--OK 1--凹坑 2--划痕 switch (data.badType) { case 1://凹坑 Note.insertNgData(u8"壳体凹坑", data.defectWidth, data.defectHeight); amount++; color = Scalar(0, 0, 255); writeSpecificStatement(Paint, L"凹坑", data, amount, limit, color); break; case 2://划痕 // Note.insertNgData(u8"壳体划痕", data.first.defectWidth, data.first.defectHeight); // writeSpecificStatement(Paint, L"划痕", data, amount, limit, color); // color = Scalar(0, 0, 255); // forHuaHeng++; break; } } cv::rectangle(Paint, data.rect, color, 2); } #if GRAY_DISPLAY drawContoursOverlap(resMat, contourForGrayShow);//除了容器内的缺陷全部画黑(0 vector> res = grayScaleCalculation(~resMat, SprfShapeImage1Resize); for (auto& data : res) { putTextHusky(Paint, (WString2String(L"G:" + to_wstring(data.second))).c_str(), cv::Point(data.first.x * 2, data.first.y * 2 - 40), Scalar(0, 0, 255), 15); } #endif if (amount >= limit) { putTextHusky(Paint, (WString2String(L"凹坑NG").c_str()), { 6800,3800 }, Scalar(0, 0, 255), 300); CCD1OK = 1; } } ///////////////划伤/////////////// if (data->skip[4] != 1) { int amount = 0, limit = 5; cv::Mat resMat = ~modelPtr->camera1Seg_huaShang->Evaluate(SprfNormalImageResize); cv::Mat resMat2 = ~modelPtr->camera1Seg_huaShang->Evaluate(SprfGlossRatioImageResize); drawContourOnImage(resMat, SprfNormalImagePaint); drawContourOnImage(resMat2, SprfGlossRatioImagePaint); //cv::Mat resM = mergeBinaryMats(resMat, resMat2);//融合两张图片中白色的区域 std::vector>contourForGrayShow;//给灰度值计算 std::vectorpaintVec;//flase NG true OK std::vectorpaintVec2;//flase NG true OK //将resMat中的缺陷切出给cls检测后放入paintvec中 camera1HuaHeng(resMat, SprfNormalImage, modelPtr->camera1Cls_huaHeng, pixAccX, pixAccY, avoidA, paintVec, contourForGrayShow); camera1HuaHeng(resMat2, SprfGlossRatioImage, modelPtr->camera1Cls_huaHeng, pixAccX, pixAccY, avoidA, paintVec2, contourForGrayShow); #if 1 //将paintVec2中的缺陷放入paintVec中,有是否重叠的判读 for (auto& data : paintVec2) { bool overLap = false; for (auto& data2 : paintVec) if (simpleAlgo::isRectOverlap(data.rect, data2.rect) == true)//重合 { data2.contour = simpleAlgo::contourPlusContour(data.contour, data2.contour); overLap = true; if (data.badType > 0)//如果另一张图检测出ng 如果两个都是不同的ng可能有点问题 data2.badType = data.badType; break; } //不重合 if (overLap == false) paintVec.push_back(data); } paintVec2.clear(); #endif #if 0 //将paintVec2中的缺陷放入paintVec中 for (auto& data : paintVec2) { paintVec.push_back(data); } paintVec2.clear(); #endif #if 0 std::vector>contours1; cv::findContours(resMat, contours1, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector>contours2; cv::findContours(resMat, contours2, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); //0 OK 1凹坑 2脏污 3划痕 for (auto contour : contours1)//遍历第一张图 { cv::Rect rect = cv::boundingRect(contour); double defectHeight = rect.height * pixAccY * 2; double defectWidth = rect.width * pixAccX * 2; int rectCenterX = 0, rectCenterY = 0; rectCenterX = rect.x + rect.width / 2; rectCenterY = rect.y + rect.height / 2; if (avoidA.checkOverLap(Point(rectCenterX, rectCenterY)) == true)//有与二维码重叠 continue; if (rect.height > 10 && rect.width > 10) { amount++; rect.x *= 2; rect.y *= 2; rect.width *= 2; rect.height *= 2; Mat forCls = simpleAlgo::cutImg2Cls(contour, SprfNormalImageResize); int res = modelPtr->camera1Cls_huaHeng->Evaluate(forCls); if (res == 0) paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,0,true) }); else paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,res,false) }); if (defectHeight > 10 || defectWidth > 10)//10mm { amount = 10; paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,false) }); } else //if (showOk == true) contourForGrayShow.push_back(contour); } } for (auto contour : contours2)//遍历第二张图 { cv::Rect rect = cv::boundingRect(contour); double defectHeight = rect.height * pixAccY * 2; double defectWidth = rect.width * pixAccX * 2; int rectCenterX = 0, rectCenterY = 0; rectCenterX = rect.x + rect.width / 2; rectCenterY = rect.y + rect.height / 2; if (avoidA.checkOverLap(Point(rectCenterX, rectCenterY)) == true)//有与二维码重叠 continue; if (rect.height > 10 && rect.width > 10) { amount++; rect.x *= 2; rect.y *= 2; rect.width *= 2; rect.height *= 2; if (defectHeight > 10 || defectWidth > 10)//10mm { amount = 10; paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,false) }); } else //if (showOk == true) paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,true) }); contourForGrayShow.push_back(contour); } } #endif //Paint for (auto& data : paintVec) { switch (data.badType) { case 0://OK writeSpecificStatement(Paint, L"clsOk", data, amount, limit, Scalar(0, 255, 0)); cv::rectangle(Paint, data.rect, Scalar(0, 255, 0), 2); break; case 1: //color = Scalar(0, 0, 255); //Note.insertNgData(u8"壳体凹坑", data.defectWidth, data.defectHeight); //writeSpecificStatement(Paint, L"凹坑", data, amount, limit, color); break; case 2: //if (max(data.defectHeight, data.defectWidth) > 2)//>2mm //{ // color = Scalar(0, 0, 255); // Note.insertNgData(u8"壳体脏污", data.defectWidth, data.defectHeight); // writeSpecificStatement(Paint, L"脏污", data, amount, limit, color); //} //else // writeSpecificStatement(Paint, L"脏污OK", data, amount, limit, color); break; case 3: if (max(data.defectHeight, data.defectWidth) > 10)//>10mm { Note.insertNgData(u8"壳体划痕", data.defectWidth, data.defectHeight); writeSpecificStatement(Paint, L"划痕", data, amount, limit, Scalar(0, 0, 255)); cv::rectangle(Paint, data.rect, Scalar(0, 0, 255), 2); } else { writeSpecificStatement(Paint, L"划痕OK", data, amount, limit, Scalar(0, 255, 0)); cv::rectangle(Paint, data.rect, Scalar(0, 255, 0), 2); } amount++; break; default: break; } CCD1OK = 1; } if (amount >= limit) { putTextHusky(Paint, (WString2String(L"划痕NG").c_str()), { 6800,4000 }, Scalar(0, 0, 255), 300); CCD1OK = 1; } #if GRAY_DISPLAY drawContoursOverlap(resMat, contourForGrayShow);//除了容器内的缺陷全部画黑(0 vector> res = grayScaleCalculation(~resMat, SprfNormalImageResize); for (auto& data : res) { putTextHusky(Paint, (WString2String(L"G:" + to_wstring(data.second))).c_str(), cv::Point(data.first.x * 2, data.first.y * 2 - 40), Scalar(0, 0, 255), 15); } #endif } #endif if (CCD1OK == 2) cv::putText(Paint, "NG", cv::Point(150, 600), 1, 10, cv::Scalar(0, 0, 255), 30); else cv::putText(Paint, "OK", cv::Point(150, 600), 1, 10, cv::Scalar(0, 255, 0), 30); ///////////////////无SN阻塞/////////////////////// if (!data->SNcode.compare(snDatas->snErrorsnError)) data->SNcode = snDatas->waitForSn(data->timeCode); cv::putText(Paint, data->SNcode, cv::Point(150, 800), 1, 10, cv::Scalar(0, 255, 0), 10); /////////////////////SQL//////////////////////// data->sqlVec.push_back({ "_25D1Result", CCD1OK }); ////////////////////结果保存////////////////// data->resultImgs.push_back(Paint); //data->resultImgs.push_back(SprfSpecularReflectionImagePaint); //data->resultImgs.push_back(SprfDiffuseReflectionImagePaint); //data->resultImgs.push_back(SprfShapeImage1Paint); //data->resultImgs.push_back(SprfShapeImage2Paint); //data->resultImgs.push_back(SprfGlossRatioImagePaint); //data->resultImgs.push_back(SprfNormalImagePaint); //////////////CSV///////////////////////////// string OKNG("OK"); if (CCD1OK == 2)OKNG = "NG"; qDebug() << "[Debug]algo1 end:" << QString::fromStdString(data->SNcode); std::cout << "algo1 end:" << QString::fromStdString(data->SNcode).toStdString() << endl; writeToData_xxxCSVNew(data, OKNG, &Note); } void algoThread::_25D_2_Algo(detData* data) { if (data->imgs.size() < 6) { qDebug() << __FUNCDNAME__ << __LINE__ << "camera Mat size is Error!"; return; } ///////////////////取图///声明///////////////////// ngNoteCls Note; cv::Mat SprfSpecularReflectionImage = data->imgs[0]; cv::Mat SprfDiffuseReflectionImage = data->imgs[1]; cv::Mat SprfShapeImage1 = data->imgs[2]; cv::Mat SprfShapeImage2 = data->imgs[3]; cv::Mat SprfGlossRatioImage = data->imgs[4]; cv::Mat SprfNormalImage = data->imgs[5]; cv::Mat Paint; if (SprfGlossRatioImage.channels() == 1) { cv::cvtColor(SprfGlossRatioImage, Paint, cv::COLOR_GRAY2BGR); } int CCD1OK = 1; double CCD1height = -1; double dmCodeWidth = 0, dmCodeHeight = 0; double pixAccX = bridge.back.json.PixelAccuracy.getData("_25D_1_X"); double pixAccY = bridge.back.json.PixelAccuracy.getData("_25D_1_Y"); cv::Point qrPos; Rect qrRect; ////////////////算法/////////////////////////////// if (data->skip[0] != 1) { HObject ho_Image = simpleAlgo::MatToHObject(SprfShapeImage1); HTuple hv_Out_Mean; HTuple hv_Out_Max; HTuple hv_Out_Min; HTuple hv_Out_Line1; HTuple hv_Out_Line2; HTuple hv_Make; _952_15_Distance(ho_Image, &hv_Out_Mean, &hv_Out_Max, &hv_Out_Min, &hv_Out_Line1, &hv_Out_Line2, &hv_Make); if (hv_Make.D() != -1) { line(Paint, cv::Point(hv_Out_Line1[1].D(), hv_Out_Line1[0].D()), cv::Point(hv_Out_Line1[3].D(), hv_Out_Line1[2].D()), Scalar(0, 255, 0), 1); line(Paint, cv::Point(hv_Out_Line2[1].D(), hv_Out_Line2[0].D()), cv::Point(hv_Out_Line2[3].D(), hv_Out_Line2[2].D()), Scalar(0, 255, 0), 1); cv::putText(Paint, "hv_Out_Max:" + to_string(hv_Out_Max.D()), cv::Point(100, 100), 1, 10, Scalar(0, 255, 0), 5); } } #if 0 /////////二维码位置屏蔽 avoidArea avoidA; avoidA.addArea(SprfShapeImage1Resize, modelPtr->camera1Seg_erWeiMa); ///////////脏污/////////////////////// if (data->skip[2] != 1) { #if 1 int amount = 0, limit = 1; cv::Mat resMat = ~modelPtr->camera1Seg_ZangWu->Evaluate(SprfSpecularReflectionImageResize); std::vector>contours; cv::findContours(resMat, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vectorpaintVec;//flase NG true OK for (auto contour : contours) { cv::Rect rect = cv::boundingRect(contour); int rectCenterX = 0, rectCenterY = 0; rectCenterX = rect.x + rect.width / 2; rectCenterY = rect.y + rect.height / 2; if (avoidA.checkOverLap(Point(rectCenterX, rectCenterY)) == true)//有与二维码重叠 continue; double defectHeight = rect.height * pixAccY * 2; double defectWidth = rect.width * pixAccX * 2; if (rect.height > 10 && rect.width > 10) { //amount++; rect.x *= 2; rect.y *= 2; rect.width *= 2; rect.height *= 2; if (defectHeight > 2 || defectWidth > 2)//2mm { amount++; paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,false) }); } else //if (showOk == true) paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,true) }); } } for (auto& data : paintVec) { Scalar color; if (amount >= limit || data.result == false)//NG { Note.insertNgData(u8"脏污", data.defectWidth, data.defectHeight); color = Scalar(0, 0, 255); } else//OK color = Scalar(0, 255, 0); cv::rectangle(Paint, data.rect, color, 2); writeSpecificStatement(Paint, L"脏污", data, amount, limit, color); } if (amount >= limit) { putTextHusky(Paint, (WString2String(L"脏污NG").c_str()), { 6800,3600 }, Scalar(0, 0, 255), 300); CCD1OK = 1; } #endif } ///////////////凹坑/////////////// if (data->skip[3] != 1) { int amount = 0, limit = 1; cv::Mat resMat = ~modelPtr->camera1Seg_aoKeng->Evaluate(SprfShapeImage1Resize); drawContourOnImage(resMat, SprfShapeImage1Paint); std::vector>contours; cv::findContours(resMat, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector>contourForGrayShow;//给灰度值计算 std::vectorpaintVec;//flase NG true OK for (auto contour : contours) { cv::Rect rect = cv::boundingRect(contour); int rectCenterX = 0, rectCenterY = 0; rectCenterX = rect.x + rect.width / 2; rectCenterY = rect.y + rect.height / 2; if (avoidA.checkOverLap(Point(rectCenterX, rectCenterY)) == true)//有与二维码重叠 continue; double defectHeight = rect.height * pixAccY * 2; double defectWidth = rect.width * pixAccX * 2; if (rect.height > 10 && rect.width > 10) { rect.x *= 2; rect.y *= 2; rect.width *= 2; rect.height *= 2; Mat img_cls = simpleAlgo::cutImg2Cls(contour, SprfShapeImage1Resize); int res = modelPtr->camera1Cls_aoKeng->Evaluate(img_cls); if (defectHeight > 0 || defectWidth > 0)//有就算 { paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,res,false) }); } else //if (showOk == true) paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,res,true) }); } } //Paint for (auto& data : paintVec) { Scalar color(0, 255, 0); if (data.result == false)//NG { //0--OK 1--凹坑 2--划痕 switch (data.badType) { case 1://凹坑 Note.insertNgData(u8"壳体凹坑", data.defectWidth, data.defectHeight); amount++; color = Scalar(0, 0, 255); writeSpecificStatement(Paint, L"凹坑", data, amount, limit, color); break; case 2://划痕 // Note.insertNgData(u8"壳体划痕", data.first.defectWidth, data.first.defectHeight); // writeSpecificStatement(Paint, L"划痕", data, amount, limit, color); // color = Scalar(0, 0, 255); // forHuaHeng++; break; } } cv::rectangle(Paint, data.rect, color, 2); } #if GRAY_DISPLAY drawContoursOverlap(resMat, contourForGrayShow);//除了容器内的缺陷全部画黑(0 vector> res = grayScaleCalculation(~resMat, SprfShapeImage1Resize); for (auto& data : res) { putTextHusky(Paint, (WString2String(L"G:" + to_wstring(data.second))).c_str(), cv::Point(data.first.x * 2, data.first.y * 2 - 40), Scalar(0, 0, 255), 15); } #endif if (amount >= limit) { putTextHusky(Paint, (WString2String(L"凹坑NG").c_str()), { 6800,3800 }, Scalar(0, 0, 255), 300); CCD1OK = 1; } } ///////////////划伤/////////////// if (data->skip[4] != 1) { int amount = 0, limit = 5; cv::Mat resMat = ~modelPtr->camera1Seg_huaShang->Evaluate(SprfNormalImageResize); cv::Mat resMat2 = ~modelPtr->camera1Seg_huaShang->Evaluate(SprfGlossRatioImageResize); drawContourOnImage(resMat, SprfNormalImagePaint); drawContourOnImage(resMat2, SprfGlossRatioImagePaint); //cv::Mat resM = mergeBinaryMats(resMat, resMat2);//融合两张图片中白色的区域 std::vector>contourForGrayShow;//给灰度值计算 std::vectorpaintVec;//flase NG true OK std::vectorpaintVec2;//flase NG true OK //将resMat中的缺陷切出给cls检测后放入paintvec中 camera1HuaHeng(resMat, SprfNormalImage, modelPtr->camera1Cls_huaHeng, pixAccX, pixAccY, avoidA, paintVec, contourForGrayShow); camera1HuaHeng(resMat2, SprfGlossRatioImage, modelPtr->camera1Cls_huaHeng, pixAccX, pixAccY, avoidA, paintVec2, contourForGrayShow); #if 1 //将paintVec2中的缺陷放入paintVec中,有是否重叠的判读 for (auto& data : paintVec2) { bool overLap = false; for (auto& data2 : paintVec) if (simpleAlgo::isRectOverlap(data.rect, data2.rect) == true)//重合 { data2.contour = simpleAlgo::contourPlusContour(data.contour, data2.contour); overLap = true; if (data.badType > 0)//如果另一张图检测出ng 如果两个都是不同的ng可能有点问题 data2.badType = data.badType; break; } //不重合 if (overLap == false) paintVec.push_back(data); } paintVec2.clear(); #endif #if 0 //将paintVec2中的缺陷放入paintVec中 for (auto& data : paintVec2) { paintVec.push_back(data); } paintVec2.clear(); #endif #if 0 std::vector>contours1; cv::findContours(resMat, contours1, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector>contours2; cv::findContours(resMat, contours2, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); //0 OK 1凹坑 2脏污 3划痕 for (auto contour : contours1)//遍历第一张图 { cv::Rect rect = cv::boundingRect(contour); double defectHeight = rect.height * pixAccY * 2; double defectWidth = rect.width * pixAccX * 2; int rectCenterX = 0, rectCenterY = 0; rectCenterX = rect.x + rect.width / 2; rectCenterY = rect.y + rect.height / 2; if (avoidA.checkOverLap(Point(rectCenterX, rectCenterY)) == true)//有与二维码重叠 continue; if (rect.height > 10 && rect.width > 10) { amount++; rect.x *= 2; rect.y *= 2; rect.width *= 2; rect.height *= 2; Mat forCls = simpleAlgo::cutImg2Cls(contour, SprfNormalImageResize); int res = modelPtr->camera1Cls_huaHeng->Evaluate(forCls); if (res == 0) paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,0,true) }); else paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,res,false) }); if (defectHeight > 10 || defectWidth > 10)//10mm { amount = 10; paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,false) }); } else //if (showOk == true) contourForGrayShow.push_back(contour); } } for (auto contour : contours2)//遍历第二张图 { cv::Rect rect = cv::boundingRect(contour); double defectHeight = rect.height * pixAccY * 2; double defectWidth = rect.width * pixAccX * 2; int rectCenterX = 0, rectCenterY = 0; rectCenterX = rect.x + rect.width / 2; rectCenterY = rect.y + rect.height / 2; if (avoidA.checkOverLap(Point(rectCenterX, rectCenterY)) == true)//有与二维码重叠 continue; if (rect.height > 10 && rect.width > 10) { amount++; rect.x *= 2; rect.y *= 2; rect.width *= 2; rect.height *= 2; if (defectHeight > 10 || defectWidth > 10)//10mm { amount = 10; paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,false) }); } else //if (showOk == true) paintVec.push_back({ rectAndData(rect,defectHeight,defectWidth,true) }); contourForGrayShow.push_back(contour); } } #endif //Paint for (auto& data : paintVec) { switch (data.badType) { case 0://OK writeSpecificStatement(Paint, L"clsOk", data, amount, limit, Scalar(0, 255, 0)); cv::rectangle(Paint, data.rect, Scalar(0, 255, 0), 2); break; case 1: //color = Scalar(0, 0, 255); //Note.insertNgData(u8"壳体凹坑", data.defectWidth, data.defectHeight); //writeSpecificStatement(Paint, L"凹坑", data, amount, limit, color); break; case 2: //if (max(data.defectHeight, data.defectWidth) > 2)//>2mm //{ // color = Scalar(0, 0, 255); // Note.insertNgData(u8"壳体脏污", data.defectWidth, data.defectHeight); // writeSpecificStatement(Paint, L"脏污", data, amount, limit, color); //} //else // writeSpecificStatement(Paint, L"脏污OK", data, amount, limit, color); break; case 3: if (max(data.defectHeight, data.defectWidth) > 10)//>10mm { Note.insertNgData(u8"壳体划痕", data.defectWidth, data.defectHeight); writeSpecificStatement(Paint, L"划痕", data, amount, limit, Scalar(0, 0, 255)); cv::rectangle(Paint, data.rect, Scalar(0, 0, 255), 2); } else { writeSpecificStatement(Paint, L"划痕OK", data, amount, limit, Scalar(0, 255, 0)); cv::rectangle(Paint, data.rect, Scalar(0, 255, 0), 2); } amount++; break; default: break; } CCD1OK = 1; } if (amount >= limit) { putTextHusky(Paint, (WString2String(L"划痕NG").c_str()), { 6800,4000 }, Scalar(0, 0, 255), 300); CCD1OK = 1; } #if GRAY_DISPLAY drawContoursOverlap(resMat, contourForGrayShow);//除了容器内的缺陷全部画黑(0 vector> res = grayScaleCalculation(~resMat, SprfNormalImageResize); for (auto& data : res) { putTextHusky(Paint, (WString2String(L"G:" + to_wstring(data.second))).c_str(), cv::Point(data.first.x * 2, data.first.y * 2 - 40), Scalar(0, 0, 255), 15); } #endif } #endif if (CCD1OK == 2) cv::putText(Paint, "NG", cv::Point(150, 600), 1, 10, cv::Scalar(0, 0, 255), 30); else cv::putText(Paint, "OK", cv::Point(150, 600), 1, 10, cv::Scalar(0, 255, 0), 30); ///////////////////无SN阻塞/////////////////////// if (!data->SNcode.compare(snDatas->snErrorsnError)) data->SNcode = snDatas->waitForSn(data->timeCode); cv::putText(Paint, data->SNcode, cv::Point(150, 800), 1, 10, cv::Scalar(0, 255, 0), 10); /////////////////////SQL//////////////////////// data->sqlVec.push_back({ "Camera1Result", CCD1OK }); data->sqlVec.push_back({ "batteryHeight", (int)(CCD1height * 1000) }); ////////////////////结果保存////////////////// data->resultImgs.push_back(Paint); //data->resultImgs.push_back(SprfSpecularReflectionImagePaint); //data->resultImgs.push_back(SprfDiffuseReflectionImagePaint); //data->resultImgs.push_back(SprfShapeImage1Paint); //data->resultImgs.push_back(SprfShapeImage2Paint); //data->resultImgs.push_back(SprfGlossRatioImagePaint); //data->resultImgs.push_back(SprfNormalImagePaint); //////////////CSV///////////////////////////// string OKNG("OK"); if (CCD1OK == 2)OKNG = "NG"; qDebug() << "[Debug]algo1 end:" << QString::fromStdString(data->SNcode); std::cout << "algo1 end:" << QString::fromStdString(data->SNcode).toStdString() << endl; writeToData_xxxCSVNew(data, OKNG, &Note); }