From f325db7fe5c4888285295b3fa94b93a68f2d29ee Mon Sep 17 00:00:00 2001 From: "bob.pan" Date: Sat, 18 Sep 2021 16:41:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=BD=AE=E6=AF=82=E6=8A=A0?= =?UTF-8?q?=E5=9B=BE=E7=AE=97=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=83=8C?= =?UTF-8?q?=E6=99=AF=E5=9B=BE=E8=87=AA=E9=80=82=E5=BA=94=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E6=89=BE=E5=9C=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/algorithm/AlgorithmFluorescence.cpp | 13 +- src/algorithm/ImageProcess.cpp | 651 +++--------------------- src/algorithm/ImageProcess.h | 14 +- src/tpMain/DetectState.cpp | 43 +- src/tpMain/DetectState.h | 17 +- tpvs17/tpMain/QAlgParamDlg.cpp | 122 ++++- tpvs17/tpMain/QAlgParamDlg.h | 9 +- tpvs17/tpMain/QAlgParamDlg.ui | 328 ++++++++++-- tpvs17/tpMain/QSystemSettingDlg.cpp | 115 +---- tpvs17/tpMain/lpMainWin.cpp | 46 +- tpvs17/tpMain/lpMainWin.h | 2 + tpvs17/tpMain/lpMainWin.ui | 14 + 12 files changed, 618 insertions(+), 756 deletions(-) diff --git a/src/algorithm/AlgorithmFluorescence.cpp b/src/algorithm/AlgorithmFluorescence.cpp index c9cbce2..d5bd7de 100644 --- a/src/algorithm/AlgorithmFluorescence.cpp +++ b/src/algorithm/AlgorithmFluorescence.cpp @@ -53,7 +53,7 @@ int CAlgorithmFluorescence::IImageAnalysis(class IImageObject* pImgObj, TP_ALGOR { qDebug() << "start alg"; QMutexLocker locker(&mutex); - + CircleParam cParam; double dStart = cv::getTickCount(); Mat matSrc = getImage(pImgObj).clone();//获取相机原始图像 QVariantMap vMap = pImgObj->IVarFromUI().toMap();//获取由UI传递过来的算法参数 @@ -82,6 +82,9 @@ int CAlgorithmFluorescence::IImageAnalysis(class IImageObject* pImgObj, TP_ALGOR double ratioVal = vMap.value("Ratio").toDouble();//偏距系数 bool bEqual = vMap.value("bEqual").toBool();//使用使用图像增强 int filterSize = vMap.value("filterSize").toInt();//过滤圆大小 + cParam.CirclePolarity = vMap.value("Circle_Polarity",0).toInt(); + cParam.CircleACThres = vMap.value("Circle_ACThres",3).toInt(); + cParam.CircleEdgeWidth = vMap.value("Circle_EdgeWidth",3).toInt(); if (nthreshold <= 0) nthreshold = 15; @@ -109,13 +112,17 @@ int CAlgorithmFluorescence::IImageAnalysis(class IImageObject* pImgObj, TP_ALGOR if (bUseBackground == true)//使用背景图 做减法找圆 { - matMatch = ImageProcess::findCircleByBackground(matSrc, matBack, &lCircle); + Point2f centerPoint; + double radius = 0; + matMatch = ImageProcess::findCircleByBackground(matSrc, matBack, centerPoint, radius, bEqual, filterSize, cParam); + lCircle.ptCenter = centerPoint; + lCircle.fRadius = radius; } else { //不需要 背景图找圆算法 Point2f centerPoint; double radius = 0; - matMatch = ImageProcess::findCircle(matSrc, centerPoint, radius, bEqual,filterSize); + matMatch = ImageProcess::findCircle(matSrc, centerPoint, radius, bEqual,filterSize,cParam); lCircle.ptCenter = centerPoint; lCircle.fRadius = radius; } diff --git a/src/algorithm/ImageProcess.cpp b/src/algorithm/ImageProcess.cpp index cb4e241..2df580f 100644 --- a/src/algorithm/ImageProcess.cpp +++ b/src/algorithm/ImageProcess.cpp @@ -44,538 +44,6 @@ Mat findEdge2(const Mat &Src) return ret; } #define REAIZE 2 -//老算法 准确率低 -cv::Mat ImageProcess::findCircleObject(const Mat &src, const Mat& backgroundImg, bool useBackgroundFlag, int nThres /*= 20*/, luffy_base::luffyCircle *pCircle /*= NULL*/) -{ -#ifdef MOTO_DETECT//摩轮型号识别抠图算法 - if (!useBackgroundFlag) - { - Mat detectImg; - cv::resize(src, detectImg, cv::Size(src.cols / REAIZE, src.rows / REAIZE)); - int bBaseX = detectImg.cols; - int bBaseY = detectImg.rows; - equalizeHist(detectImg, detectImg); - detectImg = _EnhanImg_sharpen(detectImg); - - EDCircles edcircles(detectImg); - vector EDCircle = edcircles.getCircles(); - double maxR = 0; - int nIndex = -1; - for (int i = 0; i < EDCircle.size(); i++) - { - int startX = EDCircle[i].center.x - EDCircle[i].r; - int startY = EDCircle[i].center.y - EDCircle[i].r; - if (startX < 0 || startY < 0) - continue; - if (EDCircle[i].center.x + EDCircle[i].r > bBaseX || EDCircle[i].center.y + EDCircle[i].r > bBaseY) - continue; - if (EDCircle[i].r > maxR) - { - maxR = EDCircle[i].r; - nIndex = i; - } - } - if (nIndex != -1) - { - int startX = EDCircle[nIndex].center.x * REAIZE - EDCircle[nIndex].r * REAIZE; - int startY = EDCircle[nIndex].center.y * REAIZE - EDCircle[nIndex].r* REAIZE; - double radius = EDCircle[nIndex].r; - int hight = 2 * radius * REAIZE; - - if (startX > 0 && startY > 0 && hight > 0 \ - && startX < src.cols &&startY < src.rows \ - &&hight < src.cols&&hight < src.rows \ - && startX + hight < src.cols && startY + hight < src.rows) - { - Mat cutMat = src(Rect(startX, startY, hight, hight)); - if (cutMat.data != NULL) - { - //Mat dst; - //double rate = src.cols*1.0 / ALG_RESIZE_IMAGE_WIDTH; - //const cv::Size cSize = cv::Size(cutMat.cols*1.0 / rate, cutMat.rows*1.0 / rate); - //cv::resize(cutMat, dst, cSize); - if (hight < 50) - return Mat(); - cv::Point2d center; - center.x = EDCircle[nIndex].center.x * REAIZE; - center.y = EDCircle[nIndex].center.y * REAIZE; - pCircle->ptCenter = center; - - //float fScale = src.cols / ALG_RESIZE_IMAGE_WIDTH; - //pCircle->fRadius = hight*1.0 / fScale; - pCircle->fRadius = radius * REAIZE; - - //2021-05-10 增加图像大小判断 对超过900像素的图像进行再一次压缩 - if (cutMat.cols >= 900 || cutMat.rows >= 900) - { - Mat newCutImg; - cv::resize(cutMat, newCutImg, cv::Size(cutMat.cols / REAIZE, cutMat.rows / REAIZE)); - pCircle->fRadius = pCircle->fRadius / REAIZE; - return newCutImg; - } - return cutMat; - } - } - } - return Mat(); - } - else - { - if (src.empty() || backgroundImg.empty() || src.rows < 500) { - return Mat(); - } - - assert(backgroundImg.type() == CV_8UC1); - - Mat imgTmp, imgBinary; - const cv::Size cSize = cv::Size(ALG_RESIZE_IMAGE_WIDTH, floorf(ALG_RESIZE_IMAGE_WIDTH / (float)src.cols*(float)src.rows)); - cv::resize(src, imgTmp, cSize); - Mat foregroundImg = getForeImage(imgTmp, backgroundImg);// 0421 - -// cv::resize(foregroundImg, foregroundImg, cv::Size(src.cols / REAIZE, src.rows / REAIZE)); - - using namespace luffy_base; - luffy_threshold::Threshold(foregroundImg, imgBinary, nThres);//0421 - - Mat dilatedImgBin; - dilate(imgBinary, dilatedImgBin, Mat::ones(21, 21, CV_32FC1)); - erode(dilatedImgBin, imgBinary, Mat::ones(21, 21, CV_32FC1)); - openOper(imgBinary, Mat::ones(1, 11, CV_32FC1)); - - vector> conts; - cv::findContours(imgBinary, conts, RETR_EXTERNAL, CHAIN_APPROX_NONE); - imgBinary.setTo(0); - - for (int i = 0; i < conts.size(); i++) { - const vector &pt = conts.at(i); - if (pt.size() < 20) { - continue; - } - Rect rt = boundingRect(pt); - if (rt.width < 5 || rt.height < 5) { - continue; - } - drawContours(imgBinary, conts, i, Scalar::all(255), -1); - } - - Mat hit; vector pts; - luffy_hit::firstHit4Circle(imgBinary, hit, pts, Point(cSize.width / 2, cSize.height / 2), 0, cSize.width / 2, 360, luffy_hit::emHitOut2In); - - int nMinFitNum = 100; - luffy_imageProc::RansacParam rs(0.01, 3, 150, nMinFitNum, 240); - vector pts2 = luffy_imageProc::fitModelbyRansac(pts, luffy_imageProc::emModelCircle, &rs); - - float fRadius; - Point2f ptCenter; - bool bFind = luffy_imageProc::lsCircleFit(pts2, fRadius, ptCenter); - - if (!bFind) { - return Mat(); - } - Mat dst; - const int nOffset = 1; - fRadius += nOffset; - Rect rt(ptCenter.x - fRadius + nOffset, ptCenter.y - fRadius + nOffset, 2 * fRadius, 2 * fRadius); - rt &= Rect(0, 0, imgTmp.cols, imgTmp.rows); - imgTmp(rt).copyTo(dst); - static int nCount = cv::getTickCount(); - if (pCircle) { - /*float fScale = src.cols / ALG_RESIZE_IMAGE_WIDTH; - Mat matBig = src - backgroundImg; - pCircle->fRadius = fRadius * fScale; - pCircle->ptCenter = Point(ptCenter.x * fScale, ptCenter.y * fScale); - Rect rt(pCircle->ptCenter.x - pCircle->fRadius + nOffset, pCircle->ptCenter.y - pCircle->fRadius + nOffset, 2 * pCircle->fRadius, 2 * pCircle->fRadius); - rt &= Rect(0, 0, matBig.cols, matBig.rows); - src(rt).copyTo(dst);*/ - float fScale = src.cols / ALG_RESIZE_IMAGE_WIDTH; - Mat matBig = src - backgroundImg; - pCircle->fRadius = fRadius * fScale; - pCircle->ptCenter = Point(ptCenter.x * fScale, ptCenter.y * fScale); - - Mat matBinary; - luffy_threshold::Threshold(matBig, matBinary, nThres); - // add - openOper(matBinary, Mat::ones(3, 3, CV_32FC1)); - Mat hit; vector pts; - luffy_hit::firstHit4Circle(matBinary, hit, pts, pCircle->ptCenter, 0, pCircle->fRadius + 20, 360, luffy_hit::emHitOut2In);//luffy_hit::emHitOut2In - std::map mp; - std::for_each(pts.begin(), pts.end(), [&](Point p) { - double dis = fabs(luffy_math::disofPoints(pCircle->ptCenter, p)); - mp[dis] = p; - }); - - const int bound = 200; - //int startIndex = mp.size() - bound; - std::map::iterator it = mp.begin(); - //std::advance(it, startIndex); - std::vector ppts; - int i = 0; - for (it; it != mp.end(); ++it, ++i) - { - if (i == bound) break; - ppts.push_back(it->second); - } - luffy_imageProc::RansacParam rs(0.01, 5.0, 300, 70, 120); - vector pts2 = luffy_imageProc::fitModelbyRansac(ppts, luffy_imageProc::emModelCircle, &rs); - float fRadius2; - Point2f ptCenter2; - bool bFind = luffy_imageProc::lsCircleFit(pts2, fRadius2, ptCenter2); - if (bFind) { - pCircle->fRadius = fRadius2; - pCircle->ptCenter = ptCenter2; - Rect rt(ptCenter2.x - fRadius2 + nOffset, ptCenter2.y - fRadius2 + nOffset, 2 * fRadius2, 2 * fRadius2); - - if (rt.x < 0 || rt.y < 0 || rt.x + rt.width > matBinary.cols || rt.y + rt.height > matBinary.rows) { - return Mat(); - } - rt &= Rect(0, 0, matBinary.cols, matBinary.rows); - src(rt).copyTo(dst); - } - else - { - return Mat(); - } - } - return dst; - } - - -#else//汽轮型号识别抠图算法 -/* -2020-06-19 使用三种预防措施找圆 -第一阶梯 使用EDCircle算法,图像经过2.5倍增亮找圆 -如若在第一阶梯没有找到圆(找到的圆不符合条件),进入第二阶梯 -第二阶梯 使用EDCircle算法,图像改为原图 -如若在第二阶梯还没找到圆,进入第三阶梯使用传统找圆算法(结合监测背景图) -第三阶梯不管怎样都会找出一个最佳圆 -*/ - - if (src.empty() || backgroundImg.empty() || src.rows < 500) { - return Mat(); - } - bool findFlag = false; - /*第一阶梯找圆*/ - assert(backgroundImg.type() == CV_8UC1); - Mat detectImg; - cv::resize(src, detectImg, cv::Size(src.cols / REAIZE, src.rows / REAIZE)); - int bBaseX = detectImg.cols; - int bBaseY = detectImg.rows; - Mat upLight_Img = detectImg + 1.5 * detectImg;//20200423 修改 对图像进行叠加,增强目标亮度 - blur(upLight_Img, upLight_Img, Size(3, 3)); - EDCircles edcircles(upLight_Img); - vector EDCircle = edcircles.getCircles(); - double maxR = 0; - int nIndex = -1; - for (int i = 0; i < EDCircle.size(); i++) - { - int startX = EDCircle[i].center.x - EDCircle[i].r; - int startY = EDCircle[i].center.y - EDCircle[i].r; - if (startX < 0 || startY <0) - continue; - if (EDCircle[i].center.x + EDCircle[i].r> bBaseX || EDCircle[i].center.y + EDCircle[i].r>bBaseY) - continue; - if (EDCircle[i].r > maxR) - { - maxR = EDCircle[i].r; - nIndex = i; - } - } - if (nIndex != -1) - { - int startX = EDCircle[nIndex].center.x * REAIZE - EDCircle[nIndex].r * REAIZE; - int startY = EDCircle[nIndex].center.y * REAIZE - EDCircle[nIndex].r* REAIZE; - double centerX = EDCircle[nIndex].center.x * REAIZE; - double centerY = EDCircle[nIndex].center.y * REAIZE; - double radius = EDCircle[nIndex].r; - - - if (radius < 50)//小于阈值 进行二次查找 radius一般大于100,小于50像素的基本是其他小圆 - {/*第二阶梯找圆 2020 - 06 - 19 添加 原图查找圆*/ - blur(detectImg, detectImg, Size(3,3)); - EDCircles edcircles2(detectImg); - vector EDCircle2 = edcircles2.getCircles(); - double maxR = 0; - int mIndex = -1; - for (int i = 0; i < EDCircle2.size(); i++) - { - int startX = EDCircle2[i].center.x - EDCircle2[i].r; - int startY = EDCircle2[i].center.y - EDCircle2[i].r; - if (startX < 0 || startY < 0) - continue; - if (EDCircle2[i].center.x + EDCircle2[i].r > bBaseX || EDCircle2[i].center.y + EDCircle2[i].r > bBaseY) - continue; - if (EDCircle2[i].r > maxR) - { - maxR = EDCircle2[i].r; - mIndex = i; - } - } - if (mIndex == -1) - return Mat(); - startX = EDCircle2[nIndex].center.x * REAIZE - EDCircle2[nIndex].r * REAIZE; - startY = EDCircle2[nIndex].center.y * REAIZE - EDCircle2[nIndex].r* REAIZE; - centerX = EDCircle2[nIndex].center.x * REAIZE; - centerY = EDCircle2[nIndex].center.y * REAIZE; - radius = EDCircle2[nIndex].r; - - if (radius < 50)/*第三阶梯找圆*/ - { - if (src.empty() || backgroundImg.empty() || src.rows < 500) { - return Mat(); - } - assert(backgroundImg.type() == CV_8UC1); - Mat imgTmp, imgBinary; - const cv::Size cSize = cv::Size(ALG_RESIZE_IMAGE_WIDTH, floorf(ALG_RESIZE_IMAGE_WIDTH / (float)src.cols*(float)src.rows)); - cv::resize(src, imgTmp, cSize); - Mat foregroundImg = getForeImage(imgTmp, backgroundImg);// 0421 - using namespace luffy_base; //nThres = 90; - luffy_threshold::Threshold(foregroundImg, imgBinary, nThres);//0421 - - Mat dilatedImgBin; - closeOper(imgBinary, 7); - vector> conts; - cv::findContours(imgBinary, conts, RETR_EXTERNAL, CHAIN_APPROX_NONE); - imgBinary.setTo(0); - //筛选最大轮廓的作为圆拟合区域 - int maxsize = 0; - int nbestIndex = 0; - for (int i = 0; i < conts.size(); i++) - { - if (conts.at(i).size()>maxsize) - { - maxsize = conts.at(i).size(); - nbestIndex = i; - } - } - if (conts.size() > 0) - { - drawContours(imgBinary, vector>(1, conts.at(nbestIndex)), -1, Scalar::all(255), -1); - } - Mat hit; vector pts; - luffy_hit::firstHit4Circle(imgBinary, hit, pts, Point(cSize.width / 2, cSize.height / 2), 0, cSize.width / 2, 360, luffy_hit::emHitOut2In); - int nMinFitNum = 150; - if (pts.size() < nMinFitNum)//解决检测目标在图像边缘导致的抠图识别问题 - { - if (conts.size()>0) - pts = conts.at(nbestIndex); - } - - luffy_imageProc::RansacParam rs(0.01, 2, 150, nMinFitNum, 240); - vector pts2 = luffy_imageProc::fitModelbyRansac(pts, luffy_imageProc::emModelCircle, &rs); - float fRadius; - Point2f ptCenter; - bool bFind = luffy_imageProc::lsCircleFit(pts2, fRadius, ptCenter); - - if (!bFind) { - return Mat(); - } - Mat dst; - const int nOffset = 1; - fRadius += nOffset; - Rect rt(ptCenter.x - fRadius + nOffset, ptCenter.y - fRadius + nOffset, 2 * fRadius, 2 * fRadius); - rt &= Rect(0, 0, imgTmp.cols, imgTmp.rows); - imgTmp(rt).copyTo(dst); - static int nCount = cv::getTickCount(); - if (pCircle) { - float fScale = src.cols / ALG_RESIZE_IMAGE_WIDTH; - Mat matBig = src - backgroundImg; - pCircle->fRadius = fRadius * fScale; - pCircle->ptCenter = Point(ptCenter.x * fScale, ptCenter.y * fScale); - - Mat matBinary; - luffy_threshold::Threshold(matBig, matBinary, nThres); - Mat hit; vector pts; - luffy_hit::firstHit4Circle(matBinary, hit, pts, pCircle->ptCenter, 0, pCircle->fRadius + 10, 360, luffy_hit::emHitOut2In);//luffy_hit::emHitOut2In - luffy_imageProc::RansacParam rs(0.01, 2.5, 200, 150, 220); - vector pts2 = luffy_imageProc::fitModelbyRansac(pts, luffy_imageProc::emModelCircle, &rs); - float fRadius2; - Point2f ptCenter2; - bool bFind = luffy_imageProc::lsCircleFit(pts2, fRadius2, ptCenter2); - if (bFind) { - pCircle->fRadius = fRadius2; - pCircle->ptCenter = ptCenter2; - Rect rt(ptCenter2.x - fRadius2 + nOffset, ptCenter2.y - fRadius2 + nOffset, 2 * fRadius2, 2 * fRadius2); - - if (rt.x < 0 || rt.y < 0 || rt.x + rt.width > matBinary.cols || rt.y + rt.height > matBinary.rows) { - return Mat(); - } - rt &= Rect(0, 0, matBinary.cols, matBinary.rows); - src(rt).copyTo(dst); - int nWidth = ((int)((double)dst.cols / fScale / 4)) * 4; - cv::resize(dst, dst, cv::Size(nWidth, nWidth)); - } - } - - return dst; - } - } - - - int hight = 2 * radius * REAIZE; - - if (startX > 0 && startY > 0 && hight > 0 \ - && startX < src.cols &&startY < src.rows \ - &&hight < src.cols&&hight < src.rows \ - && startX+hightptCenter = center; - pCircle->fRadius = radius * REAIZE / rate; - return dst; - } - } - } - return Mat(); - -// /*以下为旧代码 目前不使用*/ -// if (src.empty() || backgroundImg.empty() || src.rows < 500) { -// return Mat(); -// } -// -// assert(backgroundImg.type() == CV_8UC1); -// -// Mat imgTmp, imgBinary; -// const cv::Size cSize = cv::Size(ALG_RESIZE_IMAGE_WIDTH, floorf(ALG_RESIZE_IMAGE_WIDTH / (float)src.cols*(float)src.rows)); -// cv::resize(src, imgTmp, cSize); -// -// Mat foregroundImg = getForeImage(imgTmp, backgroundImg);// 0421 -// -// using namespace luffy_base; //nThres = 90; -// luffy_threshold::Threshold(foregroundImg, imgBinary, nThres);//0421 -// -// Mat dilatedImgBin; -// closeOper(imgBinary, 7); -// //dilate(imgBinary, dilatedImgBin, Mat::ones(7, 7, CV_32FC1));// -// //erode(dilatedImgBin, imgBinary, Mat::ones(7, 7, CV_32FC1)); -// //openOper(imgBinary, Mat::ones(1, 13, CV_32FC1));//集智抠图问题修改 20190329 -// -// vector> conts; -// cv::findContours(imgBinary, conts, RETR_EXTERNAL, CHAIN_APPROX_NONE); -// imgBinary.setTo(0); -// -// /* -// for (int i = 0; i < conts.size(); i++) { -// const vector &pt = conts.at(i); -// if (pt.size() < 20) { -// continue; -// } -// Rect rt = boundingRect(pt); -// if (rt.width < 5 || rt.height < 5) { -// continue; -// } -// drawContours(imgBinary, conts, i, Scalar::all(255), -1); -// } -// */ -// -////筛选最大轮廓的作为圆拟合区域 -// int maxsize = 0; -// int nbestIndex = 0; -// for (int i = 0; i < conts.size(); i++) -// { -// if (conts.at(i).size()>maxsize) -// { -// maxsize = conts.at(i).size(); -// nbestIndex = i; -// } -// } -// if (conts.size() > 0) -// { -// drawContours(imgBinary, vector>(1,conts.at(nbestIndex)), -1, Scalar::all(255), -1); -// } -// //openOper(imgBinary, 17);//集智抠图问题修改 20190329 -// -// -// Mat hit; vector pts; -// luffy_hit::firstHit4Circle(imgBinary, hit, pts, Point(cSize.width / 2, cSize.height / 2), 0, cSize.width/ 2, 360, luffy_hit::emHitOut2In); -// -// //luffy_imageProc::RansacParam rs(0.02, 2.5, 70, 100, 220); -// //luffy_imageProc::RansacParam rs(0.01, 2, 150, 150, 240);//20190117 -// -// int nMinFitNum = 150; -// -// if (pts.size() < nMinFitNum)//解决检测目标在图像边缘导致的抠图识别问题 -// { -// if (conts.size()>0) -// pts = conts.at(nbestIndex); -// } -// -// luffy_imageProc::RansacParam rs(0.01, 2, 150, nMinFitNum, 240); -// vector pts2 = luffy_imageProc::fitModelbyRansac(pts, luffy_imageProc::emModelCircle, &rs); -//#ifdef _DEBUG -// Mat imgColor; -// cv::cvtColor(imgTmp, imgColor, CV_GRAY2BGR); -// for (int i = 0; i < pts.size(); i++) { -// imgColor.at(pts.at(i))[0] = 255;//B -// imgColor.at< cv::Vec3b >(pts.at(i))[1] = 0;//G -// imgColor.at< cv::Vec3b >(pts.at(i))[2] = 0;//R -// } -// for (int i = 0; i < pts2.size(); i++) { -// imgColor.at(pts2.at(i))[0] = 0;//B -// imgColor.at< cv::Vec3b >(pts2.at(i))[1] = 0;//G -// imgColor.at< cv::Vec3b >(pts2.at(i))[2] = 255;//R -// } -//#endif -// -// float fRadius; -// Point2f ptCenter; -// bool bFind = luffy_imageProc::lsCircleFit(pts2, fRadius, ptCenter); -// -// if (!bFind) { -// return Mat(); -// } -// Mat dst; -// const int nOffset = 1; -// fRadius += nOffset; -// Rect rt(ptCenter.x - fRadius + nOffset, ptCenter.y - fRadius + nOffset, 2 * fRadius, 2 * fRadius); -// rt &= Rect(0, 0, imgTmp.cols, imgTmp.rows); -// imgTmp(rt).copyTo(dst); -// static int nCount = cv::getTickCount(); -// if (pCircle) { -// float fScale = src.cols / ALG_RESIZE_IMAGE_WIDTH; -// Mat matBig = src - backgroundImg; -// pCircle->fRadius = fRadius * fScale; -// pCircle->ptCenter = Point(ptCenter.x * fScale, ptCenter.y * fScale); -// -// Mat matBinary; -// luffy_threshold::Threshold(matBig, matBinary, nThres); -// Mat hit; vector pts; -// luffy_hit::firstHit4Circle(matBinary, hit, pts, pCircle->ptCenter, 0, pCircle->fRadius + 10, 360, luffy_hit::emHitOut2In);//luffy_hit::emHitOut2In -// luffy_imageProc::RansacParam rs(0.01, 2.5, 200, 150, 220); -// vector pts2 = luffy_imageProc::fitModelbyRansac(pts, luffy_imageProc::emModelCircle, &rs); -// float fRadius2; -// Point2f ptCenter2; -// bool bFind = luffy_imageProc::lsCircleFit(pts2, fRadius2, ptCenter2); -// if (bFind) { -// pCircle->fRadius = fRadius2; -// pCircle->ptCenter = ptCenter2; -// Rect rt(ptCenter2.x - fRadius2 + nOffset, ptCenter2.y - fRadius2 + nOffset, 2 * fRadius2, 2 * fRadius2); -// -// if (rt.x < 0 || rt.y < 0 || rt.x + rt.width > matBinary.cols || rt.y + rt.height > matBinary.rows ) { -// return Mat(); -// } -// rt &= Rect(0, 0, matBinary.cols, matBinary.rows); -// src(rt).copyTo(dst); -// int nWidth = ((int)((double)dst.cols / fScale / 4)) * 4; -// cv::resize(dst, dst, cv::Size(nWidth, nWidth)); -// } -// } -// -//return dst; - -#endif -} cv::Mat ImageProcess::getForeImage(const Mat & src, const Mat &backgroundImg) { @@ -587,7 +55,7 @@ cv::Mat ImageProcess::getForeImage(const Mat & src, const Mat &backgroundImg) } //输入一张灰度图,输出抠出的圆小图和半径,圆心坐标 -cv::Mat ImageProcess::findCircle(const Mat &srcImg, Point2f& center, double &radius, bool bEqual, int filterSize) +cv::Mat ImageProcess::findCircle(const Mat &srcImg, Point2f& center, double &radius, bool bEqual, int filterSize, const CircleParam& cParam) { Mat detectImg; Mat src = srcImg; @@ -630,18 +98,26 @@ cv::Mat ImageProcess::findCircle(const Mat &srcImg, Point2f& center, double &rad center.x = (EDCircle[nIndex].center.x * REAIZE); center.y = (EDCircle[nIndex].center.y * REAIZE); radius = radius * REAIZE; - return DetectCircle(srcImg, center, radius, bEqual); + return DetectCircle(srcImg, Mat(), center, radius, bEqual, cParam); } else { center.x = srcImg.cols/2; center.y = srcImg.rows/2; radius = 0; - return DetectCircle(srcImg,center,radius,bEqual); + return DetectCircle(srcImg, Mat(), center,radius,bEqual, cParam); } } -Mat ImageProcess::DetectCircle(Mat img, Point2f& center, double& radius, bool bEqual) +Mat ImageProcess::DetectCircle(Mat srcImg, Mat background, Point2f& center, double& radius, bool bEqual, const CircleParam& cParam) { + Mat img; + if (!background.empty()) + { + img = getForeImage(srcImg, background); + } + else { + img = srcImg; + } Mat detectImg; if (bEqual == true) { @@ -654,19 +130,23 @@ Mat ImageProcess::DetectCircle(Mat img, Point2f& center, double& radius, bool bE CircleDetector cd; cd.setAlgoType(CircleDetector::PeakCircle); - cd.setEdgeWidth(6); - cd.setPolarity(Polarity::White2Black); + cd.setEdgeWidth(cParam.CircleEdgeWidth); + if(cParam.CirclePolarity == 0) + cd.setPolarity(Polarity::Black2White); + else + cd.setPolarity(Polarity::White2Black); + cd.setFindBy(FindBy::Best); double difRadiusMin = radius - 100; - double difRadiusMax = radius + 150; + double difRadiusMax = radius + 100; if (difRadiusMin < 0) { difRadiusMin = 0; - difRadiusMax = abs(center.y - (img.cols / 2)) - 50; + difRadiusMax = abs(abs(center.y - (img.cols / 2)) - 50); } cd.setRadii(difRadiusMin, difRadiusMax); - cd.setACThres(3); + cd.setACThres(cParam.CircleACThres); vector allScores; Vec3f bestCircle; float bestScore = cd.detectBest(detectImg, Point2f(center.x, center.y), bestCircle, &allScores); @@ -688,54 +168,63 @@ Mat ImageProcess::DetectCircle(Mat img, Point2f& center, double& radius, bool bE rect.y = 0; rect.width = 2 * r; rect.height = 2 * r; - Mat s = img(rect); + Mat s = srcImg(rect); center = cen; radius = r; return s; } //使用背景图做减法扣圆 -cv::Mat ImageProcess::findCircleByBackground(const Mat &src, const Mat& backgroundImg, luffy_base::luffyCircle *pCircle /*= NULL*/) +cv::Mat ImageProcess::findCircleByBackground(const Mat &srcImg, const Mat& backgroundImg, Point2f& center, double &radius, bool bEqual, int filterSize, const CircleParam& cParam) { - if (src.empty() || backgroundImg.empty() || src.rows < 500) { - return Mat(); - } - assert(backgroundImg.type() == CV_8UC1); - Mat imgTmp = src; - Mat foregroundImg = getForeImage(imgTmp, backgroundImg); + Mat detectImg; + Mat src = srcImg; - CircleDetector cd; - cd.setAlgoType(CircleDetector::PeakCircle); - cd.setEdgeWidth(6); - cd.setPolarity(Polarity::White2Black); - cd.setFindBy(FindBy::Best); - double difRadiusMin = 0; - double difRadiusMax = (foregroundImg.cols>foregroundImg.rows? foregroundImg.rows/2 : foregroundImg.cols/2)-50; - cd.setRadii(difRadiusMin, difRadiusMax); - cd.setACThres(3); - vector allScores; - Vec3f bestCircle; - float bestScore = cd.detectBest(foregroundImg, Point2f(imgTmp.cols/2, imgTmp.rows/2), bestCircle, &allScores); - if (abs(bestScore) <= FLT_EPSILON || bestCircle == Vec3f::zeros()) { - return Mat(); - } + cv::resize(src, detectImg, cv::Size(src.cols / REAIZE, src.rows / REAIZE)); + int bBaseX = detectImg.cols; + int bBaseY = detectImg.rows; + if (bEqual == true) + equalizeHist(detectImg, detectImg); + detectImg = _EnhanImg_sharpen(detectImg); - Point2f cen(bestCircle[0], bestCircle[1]); - double r = bestCircle[2]; - Rect rect; - rect.x = cen.x - r; - rect.y = cen.y - r; - if (rect.x < 0) - rect.x = 0; - if (rect.y < 0) - rect.y = 0; - rect.width = 2 * r; - rect.height = 2 * r; - Mat rltMat = src(rect); - if (pCircle) + EDCircles edcircles(detectImg); + vector EDCircle = edcircles.getCircles(); + double maxR = 0; + int nIndex = -1; + for (int i = 0; i < EDCircle.size(); i++) + { + int startX = EDCircle[i].center.x - EDCircle[i].r; + int startY = EDCircle[i].center.y - EDCircle[i].r; + if (startX < 0 || startY < 0) + continue; + if (EDCircle[i].center.x + EDCircle[i].r > bBaseX || EDCircle[i].center.y + EDCircle[i].r > bBaseY) + continue; + if ((EDCircle[i].r * REAIZE) < filterSize)//过滤半径小于指定宽度的圆 + continue; + + if (EDCircle[i].r > maxR) + { + maxR = EDCircle[i].r; + nIndex = i; + } + } + if (nIndex != -1) { - pCircle->fRadius = r; - pCircle->ptCenter = cen; + int startX = EDCircle[nIndex].center.x * REAIZE - EDCircle[nIndex].r * REAIZE; + int startY = EDCircle[nIndex].center.y * REAIZE - EDCircle[nIndex].r* REAIZE; + radius = EDCircle[nIndex].r; + int hight = 2 * radius * REAIZE; + + center.x = (EDCircle[nIndex].center.x * REAIZE); + center.y = (EDCircle[nIndex].center.y * REAIZE); + radius = radius * REAIZE; + return DetectCircle(srcImg, backgroundImg, center, radius, bEqual, cParam); } - return rltMat; -} \ No newline at end of file + else { + center.x = srcImg.cols / 2; + center.y = srcImg.rows / 2; + radius = 0; + return DetectCircle(srcImg, backgroundImg, center, radius, bEqual, cParam); + } +} + diff --git a/src/algorithm/ImageProcess.h b/src/algorithm/ImageProcess.h index 101b617..48b5cd3 100644 --- a/src/algorithm/ImageProcess.h +++ b/src/algorithm/ImageProcess.h @@ -14,18 +14,22 @@ using namespace cv; #define ALG_RESIZE_IMAGE_WIDTH 416.0 - +struct CircleParam { + int CirclePolarity{ 0 }; + int CircleACThres{ 3 }; + int CircleEdgeWidth{ 3 }; +}; class ImageProcess { public: ImageProcess(); ~ImageProcess(); - static cv::Mat findCircleObject(const Mat &src, const Mat& backgroundImg, bool useBackgroundFlag, int nThres = 20, luffy_base::luffyCircle *pCircle = NULL); static cv::Mat getForeImage(const Mat & src, const Mat &backgroundImg); - static cv::Mat findCircle(const Mat &srcImg, Point2f& center, double &radius, bool bEqual, int filterSize=50);//找圆 - static cv::Mat DetectCircle(Mat img, Point2f& center, double& radius, bool bEqual);//精细找圆 - static cv::Mat findCircleByBackground(const Mat &src, const Mat& backgroundImg, luffy_base::luffyCircle *pCircle /*= NULL*/); + static cv::Mat findCircle(const Mat &srcImg, Point2f& center, double &radius, bool bEqual, int filterSize, const CircleParam& cParam);//找圆 + //精细找圆 + static cv::Mat DetectCircle(Mat img, Mat background, Point2f& center, double& radius, bool bEqual, const CircleParam& cParam); + static cv::Mat findCircleByBackground(const Mat &srcImg, const Mat& backgroundImg, Point2f& center, double &radius, bool bEqual, int filterSize, const CircleParam& cParam); }; #endif diff --git a/src/tpMain/DetectState.cpp b/src/tpMain/DetectState.cpp index 277acc4..1418fb2 100644 --- a/src/tpMain/DetectState.cpp +++ b/src/tpMain/DetectState.cpp @@ -42,21 +42,23 @@ void DetectState::init(QString strPath) QJsonObject algObj = jsMyself.value(WHEEL_SELFDEFINE_ALGPARA).toObject(); if (!algObj.isEmpty()) { - m_AlgThres = algObj.value("Threshold").toInt(15); - m_RatioDetectType = algObj.value("RatioType").toInt(0); - m_bUseEqual = algObj.value("bEqual").toBool(false);//使用使用图像增强 - m_filterSize = algObj.value("filterSize").toInt(50);//过滤圆大小 - } - else { - m_AlgThres = 15; + m_algParam.m_AlgThres = algObj.value("Threshold").toInt(15); + m_algParam.m_RatioDetectType = algObj.value("RatioType").toInt(0); + m_algParam.m_bUseEqual = algObj.value("bEqual").toBool(false);//使用使用图像增强 + m_algParam.m_filterSize = algObj.value("filterSize").toInt(50);//过滤圆大小 + + m_algParam.m_Circle_Polarity = algObj.value("circle_polarity").toInt(0); + m_algParam.m_Circle_EdgeWidth = algObj.value("circle_edgewidth").toInt(3); + m_algParam.m_Circle_ACThres = algObj.value("circle_acthres").toInt(3); + m_algParam.m_UseBackground = algObj.value("useBackground").toInt(0); } + QJsonObject detectImage = jsMyself.value(WHEEL_SELFDEFINE_DETECTIMAGE).toObject(); if (!detectImage.isEmpty()) { m_Debug = detectImage.value("Debug").toInt(1001); saveGood = detectImage.value("Save_Good").toInt(0); saveBad = detectImage.value("Save_Bad").toInt(0); - m_UseBackground = detectImage.value("UseBackground").toInt(0); saveCutGood = detectImage.value("SaveCut_Good").toInt(0); saveCutBad = detectImage.value("SaveCut_Bad").toInt(0); m_SaveImgDirPath = detectImage.value("SaveImgPath").toString(); @@ -217,7 +219,6 @@ void DetectState::saveDeteImage() DetectImage.insert("Save_Bad", saveBad); DetectImage.insert("Save_Good", saveGood); DetectImage.insert("SaveImgPath",m_SaveImgDirPath); - DetectImage.insert("UseBackground", m_UseBackground); jsMyself.insert("DetectImage", DetectImage); @@ -238,10 +239,14 @@ void DetectState::saveDeteImage() jsMyself.insert(WHEEL_SELFDEFINE_AUTOITEM, autosystemobj); QJsonObject algObj; - algObj.insert("Threshold", m_AlgThres); - algObj.insert("RatioType", m_RatioDetectType); - algObj.insert("bEqual", m_bUseEqual);//使用使用图像增强 - algObj.insert("filterSize", m_filterSize);//过滤圆大小 + algObj.insert("Threshold", m_algParam.m_AlgThres); + algObj.insert("RatioType", m_algParam.m_RatioDetectType); + algObj.insert("bEqual", m_algParam.m_bUseEqual);//使用使用图像增强 + algObj.insert("filterSize", m_algParam.m_filterSize);//过滤圆大小 + algObj.insert("circle_polarity", m_algParam.m_Circle_Polarity); + algObj.insert("circle_edgewidth", m_algParam.m_Circle_EdgeWidth); + algObj.insert("circle_acthres", m_algParam.m_Circle_ACThres); + algObj.insert("useBackground", m_algParam.m_UseBackground); jsMyself.insert(WHEEL_SELFDEFINE_ALGPARA, algObj); QZkJsonParser::WriteJsonObject(fileMyself, jsMyself); } @@ -275,10 +280,14 @@ void DetectState::save() jsMyself.insert("CheckDB", objCheckDb); QJsonObject algObj; - algObj.insert("Threshold", m_AlgThres); - algObj.insert("RatioType", m_RatioDetectType); - algObj.insert("bEqual",m_bUseEqual);//使用使用图像增强 - algObj.insert("filterSize",m_filterSize);//过滤圆大小 + algObj.insert("Threshold", m_algParam.m_AlgThres); + algObj.insert("RatioType", m_algParam.m_RatioDetectType); + algObj.insert("bEqual", m_algParam.m_bUseEqual);//使用使用图像增强 + algObj.insert("filterSize", m_algParam.m_filterSize);//过滤圆大小 + algObj.insert("circle_polarity", m_algParam.m_Circle_Polarity); + algObj.insert("circle_edgewidth", m_algParam.m_Circle_EdgeWidth); + algObj.insert("circle_acthres", m_algParam.m_Circle_ACThres); + algObj.insert("useBackground", m_algParam.m_UseBackground); jsMyself.insert(WHEEL_SELFDEFINE_ALGPARA, algObj); QZkJsonParser::WriteJsonObject(fileMyself, jsMyself); } diff --git a/src/tpMain/DetectState.h b/src/tpMain/DetectState.h index a5d40d1..948534c 100644 --- a/src/tpMain/DetectState.h +++ b/src/tpMain/DetectState.h @@ -5,6 +5,17 @@ #include #include /*系统参数管理类 全局调用*/ +typedef struct tagAlgoParam { + int m_UseBackground{ 0 };//是否使用背景图 + int m_RatioDetectType{ 0 };//偏距检测模式: 0 不启用, 1 检测使用偏距过滤 ,2 结果使用偏距过滤 + bool m_bUseEqual{ false };//是否使用图像增强 + int m_filterSize{ 50 };//过滤圆大小 + int m_AlgThres{15};//阈值 + + int m_Circle_Polarity{ 0 };//边缘转换 + int m_Circle_EdgeWidth{ 3 };//边缘宽度 + int m_Circle_ACThres{ 3 };//边缘对比度 +}AlgoParam; class DetectState :public lpsingleton { public: @@ -72,16 +83,12 @@ public: int m_PLC_SaveMsgInLog;//是否保存数据到系统日志 int m_PLC_ResHoldTime; - int m_AlgThres; int m_showThressValue; int m_showThressList; int m_UseCutImg; - int m_UseBackground{0}; bool bLockDetect{ false }; - int m_RatioDetectType{ 0 };//偏距检测模式: 0 不启用, 1 检测使用偏距过滤 ,2 结果使用偏距过滤 - bool m_bUseEqual{ false };//是否使用图像增强 - int m_filterSize{ 50 };//过滤圆大小 + AlgoParam m_algParam; }; #endif diff --git a/tpvs17/tpMain/QAlgParamDlg.cpp b/tpvs17/tpMain/QAlgParamDlg.cpp index 93ae4cf..d6ce99c 100644 --- a/tpvs17/tpMain/QAlgParamDlg.cpp +++ b/tpvs17/tpMain/QAlgParamDlg.cpp @@ -1,11 +1,131 @@ #include "QAlgParamDlg.h" - +#include "DetectState.h" +#include "qshowimg.h" +#include +#include +#pragma execution_character_set("utf-8") QAlgParamDlg::QAlgParamDlg(QWidget *parent) : QWidget(parent) { ui.setupUi(this); + + connect(ui.m_pbShowBackImage, SIGNAL(clicked()), this, SLOT(onButtonClicked())); + connect(ui.m_pbApply, SIGNAL(clicked()), this, SLOT(onButtonClicked())); + connect(ui.m_pbExit, SIGNAL(clicked()), this, SLOT(onButtonClicked())); + ui.label->setVisible(false); } QAlgParamDlg::~QAlgParamDlg() { } + +Q_SLOT void QAlgParamDlg::onButtonClicked() +{ + QString strObj = sender()->objectName(); + if (strObj == "m_pbShowBackImage") + { + QShowImg m_showImgDlg(this); + m_showImgDlg.setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); + m_showImgDlg.setWindowModality(Qt::ApplicationModal); + m_showImgDlg.setAttribute(Qt::WA_ShowModal, true); + m_showImgDlg.setWindowIcon(QIcon(":/image/leaper")); + QString DstPath = ".\\user\\background.png"; + connect(&m_showImgDlg, SIGNAL(sgChangeImg()), this, SLOT(onChangeBG())); + connect(this, SIGNAL(sgChangeBG(QString)), &m_showImgDlg, SLOT(setPicPath(QString))); + m_showImgDlg.setPicPath(DstPath); + m_showImgDlg.exec(); + } + else if (strObj == "m_pbApply") + { + getParam(); + ui.label->setVisible(true); + m_timeID = startTimer(1000); + } + else if (strObj == "m_pbExit") + { + close(); + } +} + + +void QAlgParamDlg::showEvent(QShowEvent *event) +{ + setParam(); +} + +void QAlgParamDlg::timerEvent(QTimerEvent *event) +{ + if (m_timeID == event->timerId()) + { + killTimer(m_timeID); + m_timeID = 0; + ui.label->setVisible(false); + } +} + +void QAlgParamDlg::setParam() +{ + ui.checkBox->setChecked(DetectState::instance()->m_algParam.m_UseBackground == 0 ? false : true); + ui.checkBox_equal->setChecked(DetectState::instance()->m_algParam.m_bUseEqual); + ui.spinBox_filterSize->setValue(DetectState::instance()->m_algParam.m_filterSize); + + ui.spinBox_circle_ACThres->setValue(DetectState::instance()->m_algParam.m_Circle_ACThres); + ui.spinBox_circle_EdgeWidth->setValue(DetectState::instance()->m_algParam.m_Circle_EdgeWidth); + ui.comboBox_transform->setCurrentIndex(DetectState::instance()->m_algParam.m_Circle_Polarity); + ui.checkBox_ratio->setChecked(DetectState::instance()->m_algParam.m_RatioDetectType==0?false:true); + +} + +void QAlgParamDlg::getParam() +{ + DetectState::instance()->m_algParam.m_UseBackground = ui.checkBox->isChecked(); + DetectState::instance()->m_algParam.m_bUseEqual = ui.checkBox_equal->isChecked(); + DetectState::instance()->m_algParam.m_filterSize = ui.spinBox_filterSize->value(); + + DetectState::instance()->m_algParam.m_Circle_ACThres = ui.spinBox_circle_ACThres->value(); + DetectState::instance()->m_algParam.m_Circle_EdgeWidth = ui.spinBox_circle_EdgeWidth->value(); + DetectState::instance()->m_algParam.m_Circle_Polarity = ui.comboBox_transform->currentIndex(); + DetectState::instance()->m_algParam.m_RatioDetectType = ui.checkBox_ratio->isChecked(); + + DetectState::instance()->save(); +} + +Q_SLOT void QAlgParamDlg::onChangeBG() +{ + QFileDialog fileDialog; + fileDialog.setWindowTitle(tr("ѡıͼ")); + fileDialog.setNameFilter("Picture(*.bmp *.jpg *.png)"); + fileDialog.setFileMode(QFileDialog::ExistingFiles); + if (fileDialog.exec() == QDialog::Accepted) + { + QStringList backgroundFile = fileDialog.selectedFiles(); + if (backgroundFile.size() > 0) + { + QString DstPath = QApplication::applicationDirPath() + "\\user\\background.png"; + QString sourcePath = backgroundFile.at(0); + DstPath.replace("\\", "/"); + if (sourcePath == DstPath) { + // //return; + // //return true; + } + if (!QFile::exists(sourcePath)) { + //return false; + } + QDir *createfile = new QDir; + bool exist = createfile->exists(DstPath); + if (exist) { + //if (converFileIfExist){ + createfile->remove(DstPath); + //} + } + if (!QFile::copy(sourcePath, DstPath)) { + //return false; + } + //emit sgChangeBG(DstPath); + QMessageBox infobox(QMessageBox::Information, tr("ʾ"), tr("ͼɣ."), QMessageBox::Yes, NULL); + infobox.setWindowIcon(QIcon(":/image/leaper")); + infobox.setButtonText(QMessageBox::Yes, tr("ȷ")); + infobox.exec(); + } + } +} \ No newline at end of file diff --git a/tpvs17/tpMain/QAlgParamDlg.h b/tpvs17/tpMain/QAlgParamDlg.h index 8439a67..512f95e 100644 --- a/tpvs17/tpMain/QAlgParamDlg.h +++ b/tpvs17/tpMain/QAlgParamDlg.h @@ -11,9 +11,16 @@ class QAlgParamDlg : public QWidget public: QAlgParamDlg(QWidget *parent = Q_NULLPTR); ~QAlgParamDlg(); - + Q_SLOT void onButtonClicked(); +protected: + virtual void showEvent(QShowEvent *event); + virtual void timerEvent(QTimerEvent *event); + void setParam(); + void getParam(); + Q_SLOT void onChangeBG(); private: Ui::QAlgParamDlg ui; + int m_timeID{ 0 }; }; #endif diff --git a/tpvs17/tpMain/QAlgParamDlg.ui b/tpvs17/tpMain/QAlgParamDlg.ui index baacb38..45f0cdb 100644 --- a/tpvs17/tpMain/QAlgParamDlg.ui +++ b/tpvs17/tpMain/QAlgParamDlg.ui @@ -6,52 +6,298 @@ 0 0 - 624 - 429 + 332 + 342 算法参数设置 - - - - 30 - 40 - 91 - 16 - - - - 是否使用偏距 - - - - - - 30 - 70 - 54 - 12 - - - - TextLabel - - - - - - 30 - 100 - 54 - 12 - - - - TextLabel - - + + + + + + + + 12 + + + + 二级圆定位: + + + + + + + 12 + + + + QAbstractSpinBox::NoButtons + + + + + + + + 12 + + + + 边缘宽度: + + + + + + + + 12 + + + + QAbstractSpinBox::NoButtons + + + + + + + + 12 + + + + + 从深到浅 + + + + + 从浅到深 + + + + + + + + + 12 + + + + 边缘对比度: + + + + + + + + 12 + + + + 边缘转换: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + 12 + + + + 圆半径大小过滤: + + + + + + + + 100 + 0 + + + + + 12 + + + + QAbstractSpinBox::NoButtons + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 12 + + + + 检测背景图更换: + + + + + + + + 12 + + + + 查看检测背景 + + + + + + + + + + 12 + + + + 是否使用图像增强 + + + + + + + + 12 + + + + 是否使用背景图找圆算法 + + + + + + + + 12 + + + + 型号匹配: + + + + + + + 12 + + + + 是否使用偏距过滤模板 + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 12 + + + + 应用 + + + + + + + + 12 + + + + 退出 + + + + + + + + + 参数已生效!!! + + + + diff --git a/tpvs17/tpMain/QSystemSettingDlg.cpp b/tpvs17/tpMain/QSystemSettingDlg.cpp index 960486d..3cf79cb 100644 --- a/tpvs17/tpMain/QSystemSettingDlg.cpp +++ b/tpvs17/tpMain/QSystemSettingDlg.cpp @@ -167,15 +167,6 @@ bool QSystemSettingDlg::InitTreeWidget(QTreeWidget* pTreewidget) void QSystemSettingDlg::addComRoot(class QTreeWidget *pTreewidget, QString strName /*= QString()*/) { -// QTreeWidgetItem *m_ComItems = new QTreeWidgetItem(pTreewidget, QStringList(tr("相关设备配置"))); -// pStationSetButton = new QPushButton(tr("打开配置页面")); -// pTreewidget->setItemWidget(m_ComItems, 1, pStationSetButton); -// m_ComItems->setSizeHint(1, QSize(100, 30)); -// pStationSetButton->setObjectName("pStationSetButton"); -// connect(pStationSetButton, SIGNAL(clicked()), this, SLOT(onTreeWidgetButton())); -// m_listObj.append(pStationSetButton); -// m_TreeItemMap.insert(strName, m_ComItems); - QTreeWidgetItem *pLanguage = new QTreeWidgetItem(pTreewidget, QStringList(tr("语言"))); m_Language = new QComboBox; pTreewidget->setItemWidget(pLanguage, 1, m_Language); @@ -231,16 +222,10 @@ void QSystemSettingDlg::addPicRoot(QTreeWidget *pTreewidget, QString strName) QTreeWidgetItem *m_RootItems = new QTreeWidgetItem(pTreewidget, QStringList(tr("检测图像设置"))); m_TreeItemMap.insert(strName, m_RootItems); m_RootItems->setSizeHint(1, QSize(100, 30)); - picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("检测背景更换")))); picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("抠图后")))); picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("抠图后")))); picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("原图")))); picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("原图")))); - picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("背景图")))); -// picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("阈值参数")))); - picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("图像增强")))); - picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("过滤半径")))); - picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("偏距系数")))); picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("检测结果")))); picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("图像保存路径")))); picitems.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(tr("设置保存路径")))); @@ -271,46 +256,12 @@ void QSystemSettingDlg::addPicRoot(QTreeWidget *pTreewidget, QString strName) connect(m_saveImgSrc_bad, SIGNAL(stateChanged(int)), this, SLOT(onCheckstateChanged(int))); m_saveImgSrc_bad->setChecked(DetectState::instance()->saveBad == (int)true); - QCheckBox *m_useBackground = new QCheckBox; - m_useBackground->setText(tr("使用背景图抠图")); - m_useBackground->setObjectName("m_useBackground"); - connect(m_useBackground, SIGNAL(stateChanged(int)), this, SLOT(onCheckstateChanged(int))); - m_useBackground->setChecked(DetectState::instance()->m_UseBackground == (int)true); -//算法参数 -// m_Algthreshold = new QSpinBox(); -// m_Algthreshold->setMinimum(0); -// m_Algthreshold->setMaximum(255); -// m_Algthreshold->setToolTip(tr("背景图抠图算法阈值参数")); -// m_Algthreshold->setValue(DetectState::instance()->m_AlgThres); - - QCheckBox *m_bEqual = new QCheckBox; - m_bEqual->setText(tr("使用图像增强")); - m_bEqual->setObjectName("m_bEqual"); - connect(m_bEqual, SIGNAL(stateChanged(int)), this, SLOT(onCheckstateChanged(int))); - m_bEqual->setChecked(DetectState::instance()->m_bUseEqual); - - m_AlgFilterSize = new QSpinBox(); - m_AlgFilterSize->setMinimum(1); - m_AlgFilterSize->setMaximum(9999); - m_AlgFilterSize->setToolTip(tr("过滤圆半径Size")); - m_AlgFilterSize->setValue(DetectState::instance()->m_filterSize); - - QCheckBox *m_useRatio = new QCheckBox; - m_useRatio->setText(tr("使用偏距系数过滤模板")); - m_useRatio->setObjectName("m_useRatio"); - connect(m_useRatio, SIGNAL(stateChanged(int)), this, SLOT(onCheckstateChanged(int))); - m_useRatio->setChecked(DetectState::instance()->m_RatioDetectType == 0 ? false : true); - -// QCheckBox *m_ResAll2A = new QCheckBox; m_ResAll2A->setText(tr("轮毂全去A通道")); m_ResAll2A->setObjectName("m_ResAll2A"); connect(m_ResAll2A, SIGNAL(stateChanged(int)), this, SLOT(onCheckstateChanged(int))); m_ResAll2A->setChecked(DetectState::instance()->m_bObjAll2A == (int)true); - QPushButton* pChangeBGbp = new QPushButton(tr("查看检测背景")); - connect(pChangeBGbp, SIGNAL(clicked()), this, SLOT(onChangeBackground())); - m_pLbShowPath = new QLabel; m_pLbShowPath->setText(DetectState::instance()->m_SaveImgDirPath); @@ -326,33 +277,19 @@ void QSystemSettingDlg::addPicRoot(QTreeWidget *pTreewidget, QString strName) pSavePara->setObjectName("pSavePara"); connect(pSavePara, SIGNAL(clicked()), this, SLOT(onTreeWidgetButton())); - pTreewidget->setItemWidget(picitems.at(0), 1, pChangeBGbp); - pTreewidget->setItemWidget(picitems.at(1), 1, m_saveImgRes_good); - pTreewidget->setItemWidget(picitems.at(2), 1, m_saveImgRes_bad); - pTreewidget->setItemWidget(picitems.at(3), 1, m_saveImgSrc_good); - pTreewidget->setItemWidget(picitems.at(4), 1, m_saveImgSrc_bad); - pTreewidget->setItemWidget(picitems.at(5), 1, m_useBackground); -// pTreewidget->setItemWidget(picitems.at(6), 1, m_Algthreshold); - pTreewidget->setItemWidget(picitems.at(6), 1, m_bEqual); - pTreewidget->setItemWidget(picitems.at(7), 1, m_AlgFilterSize); - pTreewidget->setItemWidget(picitems.at(8), 1, m_useRatio); - - pTreewidget->setItemWidget(picitems.at(9), 1, m_ResAll2A); - pTreewidget->setItemWidget(picitems.at(10), 1, m_pLbShowPath); - pTreewidget->setItemWidget(picitems.at(11), 1, pbSetSavePath); - pTreewidget->setItemWidget(picitems.at(12), 1, pbOpenImgPath); - pTreewidget->setItemWidget(picitems.at(13), 1, pSavePara); - - m_listObj.append(pChangeBGbp); + pTreewidget->setItemWidget(picitems.at(0), 1, m_saveImgRes_good); + pTreewidget->setItemWidget(picitems.at(1), 1, m_saveImgRes_bad); + pTreewidget->setItemWidget(picitems.at(2), 1, m_saveImgSrc_good); + pTreewidget->setItemWidget(picitems.at(3), 1, m_saveImgSrc_bad); + pTreewidget->setItemWidget(picitems.at(4), 1, m_ResAll2A); + pTreewidget->setItemWidget(picitems.at(5), 1, m_pLbShowPath); + pTreewidget->setItemWidget(picitems.at(6), 1, pbSetSavePath); + pTreewidget->setItemWidget(picitems.at(7), 1, pbOpenImgPath); + pTreewidget->setItemWidget(picitems.at(8), 1, pSavePara); + m_listObj.append(m_saveImgRes_bad); m_listObj.append(m_saveImgRes_good); m_listObj.append(m_saveImgSrc_bad); - m_listObj.append(m_useBackground); -// m_listObj.append(m_Algthreshold); - m_listObj.append(m_bEqual); - m_listObj.append(m_AlgFilterSize); - m_listObj.append(m_useRatio); - m_listObj.append(m_saveImgSrc_good); m_listObj.append(m_ResAll2A); m_listObj.append(m_pLbShowPath); @@ -369,12 +306,6 @@ void QSystemSettingDlg::addPicRoot(QTreeWidget *pTreewidget, QString strName) picitems.at(6)->setSizeHint(1, QSize(100, 40)); picitems.at(7)->setSizeHint(1, QSize(100, 40)); picitems.at(8)->setSizeHint(1, QSize(100, 40)); - picitems.at(9)->setSizeHint(1, QSize(100, 40)); - picitems.at(10)->setSizeHint(1, QSize(100, 40)); - picitems.at(11)->setSizeHint(1, QSize(100, 40)); - picitems.at(12)->setSizeHint(1, QSize(100, 40)); - picitems.at(13)->setSizeHint(1, QSize(100, 40)); -// picitems.at(14)->setSizeHint(1, QSize(100, 40)); } void QSystemSettingDlg::addPLCRoot(QTreeWidget *pTreewidget, QString strName) @@ -762,15 +693,15 @@ Q_SLOT void QSystemSettingDlg::onCheckstateChanged(int state) else if (strObj == "m_saveImgSrc_bad") { DetectState::instance()->saveBad = int(state == 2); } - else if (strObj == "m_useBackground") { - DetectState::instance()->m_UseBackground = int(state == 2); - } - else if (strObj == "m_bEqual") { - DetectState::instance()->m_bUseEqual = int(state == 2); - } - else if (strObj == "m_useRatio") { - DetectState::instance()->m_RatioDetectType = int(state == 2); - } +// else if (strObj == "m_useBackground") { +// DetectState::instance()->m_UseBackground = int(state == 2); +// } +// else if (strObj == "m_bEqual") { +// DetectState::instance()->m_bUseEqual = int(state == 2); +// } +// else if (strObj == "m_useRatio") { +// DetectState::instance()->m_RatioDetectType = int(state == 2); +// } else if (strObj == "m_ResAll2A") { DetectState::instance()->m_bObjAll2A = (state == 2 ? true : false); } @@ -1018,10 +949,10 @@ Q_SLOT void QSystemSettingDlg::onTreeWidgetButton() else DetectState::instance()->m_CameraTrigeType = 0; } - if (m_AlgFilterSize) - { - DetectState::instance()->m_filterSize = m_AlgFilterSize->value(); - } +// if (m_AlgFilterSize) +// { +// DetectState::instance()->m_filterSize = m_AlgFilterSize->value(); +// } // if (m_Algthreshold) // { // DetectState::instance()->m_AlgThres = m_Algthreshold->value(); diff --git a/tpvs17/tpMain/lpMainWin.cpp b/tpvs17/tpMain/lpMainWin.cpp index 9d4dffa..1081b38 100644 --- a/tpvs17/tpMain/lpMainWin.cpp +++ b/tpvs17/tpMain/lpMainWin.cpp @@ -22,9 +22,9 @@ #include "QZkJsonParser.h" #include -#define VERSION_HUB "3.0.1.0" -#define VERSION_ALG "3.0.1.0" -#define UPDATE_TIME "2021-09-16" +#define VERSION_HUB "3.0.1.2" +#define VERSION_ALG "3.0.1.2" +#define UPDATE_TIME "2021-09-18" #pragma execution_character_set("utf-8") lpMainWin::lpMainWin(QWidget *parent) @@ -61,6 +61,7 @@ lpMainWin::lpMainWin(QWidget *parent) connect(ui.action_connect_mode, SIGNAL(triggered()), this, SLOT(onActionClicked())); connect(ui.action_checkdata, SIGNAL(triggered()), this, SLOT(onActionClicked())); connect(ui.action_modelmgr, SIGNAL(triggered()), this, SLOT(onActionClicked())); + connect(ui.action_algParam, SIGNAL(triggered()), this, SLOT(onActionClicked())); connect(ui.actionSystemSeting, SIGNAL(triggered()), this, SLOT(onActionClicked())); connect(ui.actioncamSetting, SIGNAL(triggered()), this, SLOT(onActionClicked())); @@ -80,6 +81,7 @@ lpMainWin::lpMainWin(QWidget *parent) pToolMenu->addAction(ui.action_debug); pToolMenu->addAction(ui.actionSystemSeting); pToolMenu->addAction(ui.actioncamSetting); + pToolMenu->addAction(ui.action_algParam); QToolButton* pbutton = new QToolButton(this); pbutton->setMenu(pToolMenu); @@ -158,6 +160,7 @@ lpMainWin::lpMainWin(QWidget *parent) ui.tp_main_tabWidget->insertTab(0, m_pixMapList, tr("历史")); ui.tp_main_tabWidget->setCurrentIndex(0); + m_pAlgParamDlg = new QAlgParamDlg(); } { /*发送模板库线程*/ @@ -372,6 +375,11 @@ lpMainWin::~lpMainWin() delete m_CamSettingDlg; m_CamSettingDlg = nullptr; } + if (m_pAlgParamDlg) + { + delete m_pAlgParamDlg; + m_pAlgParamDlg = nullptr; + } if (m_ImgViewer) { delete m_ImgViewer; m_ImgViewer = nullptr; @@ -688,18 +696,23 @@ QVariant lpMainWin::IGetVariantById(int id) vMap.insert("d2h", dDiameter); vMap.insert("useThickness", DetectState::instance()->bUseThickness); vMap.insert("useDiameter", DetectState::instance()->bUseDiameter); - vMap.insert("Threshold", DetectState::instance()->m_AlgThres);//算法图像阈值 vMap.insert("IsCutImg", DetectState::instance()->m_UseCutImg); - vMap.insert("useBackground", DetectState::instance()->m_UseBackground>0?true:false);//使用背景图 vMap.insert("Ratio", m_glbalRatio);//偏距系数 - vMap.insert("RatioType", DetectState::instance()->m_RatioDetectType);//偏距检测模式 启用方式 - vMap.insert("bEqual", DetectState::instance()->m_bUseEqual);//使用使用图像增强 - vMap.insert("filterSize", DetectState::instance()->m_filterSize);//过滤圆大小 + vMap.insert("Threshold", DetectState::instance()->m_algParam.m_AlgThres);//算法图像阈值 + vMap.insert("useBackground", DetectState::instance()->m_algParam.m_UseBackground > 0 ? true:false);//使用背景图 + vMap.insert("RatioType", DetectState::instance()->m_algParam.m_RatioDetectType);//偏距检测模式 启用方式 + vMap.insert("bEqual", DetectState::instance()->m_algParam.m_bUseEqual);//使用使用图像增强 + vMap.insert("filterSize", DetectState::instance()->m_algParam.m_filterSize);//过滤圆大小 + + vMap.insert("Circle_ACThres", DetectState::instance()->m_algParam.m_Circle_ACThres);// + vMap.insert("Circle_EdgeWidth", DetectState::instance()->m_algParam.m_Circle_EdgeWidth);// + vMap.insert("Circle_Polarity", DetectState::instance()->m_algParam.m_Circle_Polarity);// + //传递模板库指针 void* address = (void*)m_pCtrl->getAllModelMapPtr(); long long varadr = (long long)address; vMap.insert("modelMap", varadr); - + //传递检测模板名指针 void* pdefectList = (void*)&forDefectList; long long val = (long long)pdefectList; vMap.insert("defectList", val); @@ -828,6 +841,19 @@ Q_SLOT void lpMainWin::onActionClicked() m_pworkUI->onExec(); } } + else if ("action_algParam" == strObj)//算法参数设置 + { + if (m_pAlgParamDlg) + { + m_pAlgParamDlg->setParent(this); + m_pAlgParamDlg->setWindowTitle(tr("算法参数")); + m_pAlgParamDlg->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); + m_pAlgParamDlg->setWindowIcon(QIcon(":/image/leaper")); + m_pAlgParamDlg->setWindowModality(Qt::ApplicationModal); + m_pAlgParamDlg->setAttribute(Qt::WA_ShowModal, true); + m_pAlgParamDlg->show(); + } + } else if ("action_checkdata" == strObj) {//历史数据查询 QProcess process; process.setWorkingDirectory(QCoreApplication::applicationDirPath()); @@ -1757,7 +1783,7 @@ Q_SLOT void lpMainWin::onUpdateUI() ui.main_lb_res_Channle_Show->setVisible(false); } - if (DetectState::instance()->m_RatioDetectType > 0) + if (DetectState::instance()->m_algParam.m_RatioDetectType > 0) { ui.label_ratioTitle->setVisible(true); ui.label_ratioValue->setVisible(true); diff --git a/tpvs17/tpMain/lpMainWin.h b/tpvs17/tpMain/lpMainWin.h index 587855f..a7c3a78 100644 --- a/tpvs17/tpMain/lpMainWin.h +++ b/tpvs17/tpMain/lpMainWin.h @@ -21,6 +21,7 @@ #include "qpixmapbar.h" #include "QSystemSettingDlg.h" #include "QCamSettingDlg.h" +#include "QAlgParamDlg.h" class lpMainWin : public QMainWindow { @@ -186,6 +187,7 @@ private: QPixmapListBar* m_pixMapList{ nullptr };//展示历史检测结果 QSystemSettingDlg* m_pSystemSettingDlg{ nullptr }; QCamSettingDlg* m_CamSettingDlg{ nullptr }; + QAlgParamDlg* m_pAlgParamDlg{ nullptr };//算法调参页面 private: IUserCtrl *m_pUserCtrl{ nullptr };//用户管理模块 diff --git a/tpvs17/tpMain/lpMainWin.ui b/tpvs17/tpMain/lpMainWin.ui index d4d2a75..40f2c88 100644 --- a/tpvs17/tpMain/lpMainWin.ui +++ b/tpvs17/tpMain/lpMainWin.ui @@ -1123,6 +1123,20 @@ font: 75 24pt "Consolas"; + + + + :/ToolBarPic/ToolBarpic/app8.png:/ToolBarPic/ToolBarpic/app8.png + + + 算法设置 + + + + 12 + + +