#include #include #include "camera_thread.h" #include "myiothread.h" #include "FrontendBackendBridge.h" #include #include "csvControler.h" bool showOk = true;//显示ok缺陷的框 std::string fileSavePath("D://CCD//"); ////////////////////// 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) { bridge.front.showImg("Algorithm", data->resultImgs[0], data->resShowIndex);//显示原图 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) { int amount = 0, limit = 1; cv::Mat duanMianSegMat; resize(SprfShapeImage1, duanMianSegMat, cv::Size(SprfShapeImage1.cols / 2, SprfShapeImage1.rows / 2)); cv::Mat resMat = ~modelPtr->DuanMian1Seg->Evaluate(duanMianSegMat); //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, SprfShapeImage1); int res = modelPtr->DuanMian1Cls->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.defectWidth, data.defectHeight); writeSpecificStatement(Paint, L"划痕", data, amount, limit, color); color = Scalar(0, 0, 255); // forHuaHeng++; break; } } cv::rectangle(Paint, data.rect, color, 2); } if (amount >= limit) { putTextHusky(Paint, (WString2String(L"凹坑NG").c_str()), { 6800,3800 }, Scalar(0, 0, 255), 300); CCD1OK = 1; } } #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->sqlVec.push_back({ "_25D_WeiBaoMoQuYuKeTiHuaHeng", CCD1OK }); data->sqlVec.push_back({ "_25D_KeTiFuShi", CCD1OK }); data->sqlVec.push_back({ "_25D_KeTiZangWu", CCD1OK }); data->sqlVec.push_back({ "_25D_GangKeMaMoHu", CCD1OK }); ////////////////////结果保存////////////////// data->resultImgs.push_back(Paint); //////////////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; csvController::writeToData_xxxCSVNew(data, OKNG, &Note,fileSavePath); } 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("camera1X"); double pixAccY = bridge.back.json.PixelAccuracy.getData("camera1Y"); cv::Point qrPos; Rect qrRect; ////////////////算法/////////////////////////////// if (data->skip[0] != 1) { int amount = 0, limit = 1; cv::Mat resMat = ~modelPtr->DuanMian2Seg->Evaluate(SprfShapeImage1); //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, SprfShapeImage1); int res = modelPtr->DuanMian2Cls->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.defectWidth, data.defectHeight); writeSpecificStatement(Paint, L"划痕", data, amount, limit, color); color = Scalar(0, 0, 255); // forHuaHeng++; break; } } cv::rectangle(Paint, data.rect, color, 2); } if (amount >= limit) { putTextHusky(Paint, (WString2String(L"凹坑NG").c_str()), { 6800,3800 }, Scalar(0, 0, 255), 300); CCD1OK = 1; } } #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->sqlVec.push_back({ "_25D_WeiBaoMoQuYuKeTiHuaHeng", CCD1OK }); data->sqlVec.push_back({ "_25D_KeTiFuShi", CCD1OK }); data->sqlVec.push_back({ "_25D_KeTiZangWu", CCD1OK }); data->sqlVec.push_back({ "_25D_GangKeMaMoHu", 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; csvController::writeToData_xxxCSVNew(data, OKNG, &Note, fileSavePath); }