优化轮毂抠图算法,增加背景图自适应位置找圆

jizhi
bob.pan 5 years ago
parent a494893c78
commit f325db7fe5

@ -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;
}

@ -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<mCircle> 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<vector<Point>> conts;
cv::findContours(imgBinary, conts, RETR_EXTERNAL, CHAIN_APPROX_NONE);
imgBinary.setTo(0);
for (int i = 0; i < conts.size(); i++) {
const vector<Point> &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<Point> 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<Point> 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<Point> pts;
luffy_hit::firstHit4Circle(matBinary, hit, pts, pCircle->ptCenter, 0, pCircle->fRadius + 20, 360, luffy_hit::emHitOut2In);//luffy_hit::emHitOut2In
std::map<double, cv::Point> 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<double, cv::Point>::iterator it = mp.begin();
//std::advance(it, startIndex);
std::vector<cv::Point> 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<Point> 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 使
使EDCircle2.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<mCircle> 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<mCircle> 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<vector<Point>> 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<vector<Point>>(1, conts.at(nbestIndex)), -1, Scalar::all(255), -1);
}
Mat hit; vector<Point> 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<Point> 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<Point> 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<Point> 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+hight<src.cols && startY+hight<src.rows)
{
Mat cutMat = src(Rect(startX, startY, hight, hight));
if (cutMat.data != NULL)
{
if (hight < 50)
return Mat();
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);
cv::Point2d center;
center.x = centerX;// EDCircle[nIndex].center.x * REAIZE;
center.y = centerY;// EDCircle[nIndex].center.y * REAIZE;
pCircle->ptCenter = 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<vector<Point>> conts;
// cv::findContours(imgBinary, conts, RETR_EXTERNAL, CHAIN_APPROX_NONE);
// imgBinary.setTo(0);
//
// /*
// for (int i = 0; i < conts.size(); i++) {
// const vector<Point> &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<vector<Point>>(1,conts.at(nbestIndex)), -1, Scalar::all(255), -1);
// }
// //openOper(imgBinary, 17);//集智抠图问题修改 20190329
//
//
// Mat hit; vector<Point> 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<Point> 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<cv::Vec3b>(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<cv::Vec3b>(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<Point> 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<Point> 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<float> 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<float> 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<mCircle> 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);
}
else {
center.x = srcImg.cols / 2;
center.y = srcImg.rows / 2;
radius = 0;
return DetectCircle(srcImg, backgroundImg, center, radius, bEqual, cParam);
}
return rltMat;
}

@ -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

@ -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);
}

@ -5,6 +5,17 @@
#include <QObject>
#include <QString>
/*系统参数管理类 全局调用*/
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<DetectState>
{
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

@ -1,11 +1,131 @@
#include "QAlgParamDlg.h"
#include "DetectState.h"
#include "qshowimg.h"
#include <QFileDialog>
#include <QMessageBox>
#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();
}
}
}

@ -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

@ -6,52 +6,298 @@
<rect>
<x>0</x>
<y>0</y>
<width>624</width>
<height>429</height>
<width>332</width>
<height>342</height>
</rect>
</property>
<property name="windowTitle">
<string>算法参数设置</string>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>30</x>
<y>40</y>
<width>91</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>是否使用偏距</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>30</x>
<y>70</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>30</x>
<y>100</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="title">
<string>二级圆定位:</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QSpinBox" name="spinBox_circle_ACThres">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>边缘宽度:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_circle_EdgeWidth">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBox_transform">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<item>
<property name="text">
<string>从深到浅</string>
</property>
</item>
<item>
<property name="text">
<string>从浅到深</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>边缘对比度:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>边缘转换:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>圆半径大小过滤:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_filterSize">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>检测背景图更换:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_pbShowBackImage">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>查看检测背景</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkBox_equal">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>是否使用图像增强</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>是否使用背景图找圆算法</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="title">
<string>型号匹配:</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_ratio">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>是否使用偏距过滤模板</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_pbApply">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>应用</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_pbExit">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>退出</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>参数已生效!!!</string>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>

@ -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();

@ -22,9 +22,9 @@
#include "QZkJsonParser.h"
#include <QProcess>
#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);

@ -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 };//用户管理模块

@ -1123,6 +1123,20 @@ font: 75 24pt &quot;Consolas&quot;;</string>
</font>
</property>
</action>
<action name="action_algParam">
<property name="icon">
<iconset resource="../../src/tpMain/hubDetect.qrc">
<normaloff>:/ToolBarPic/ToolBarpic/app8.png</normaloff>:/ToolBarPic/ToolBarpic/app8.png</iconset>
</property>
<property name="text">
<string>算法设置</string>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>

Loading…
Cancel
Save