|
|
老算法 准确率低
|
|
|
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 使用三种预防措施找圆
|
|
|
第一阶梯 使用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<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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CircleDetector cd;
|
|
|
// cd.setAlgoType(CircleDetector::PeakCircle);
|
|
|
// cd.setEdgeWidth(cParam.CircleEdgeWidth);
|
|
|
//
|
|
|
// if (cParam.CirclePolarity == 0)
|
|
|
// cd.setPolarity(Polarity::Black2White);
|
|
|
// else
|
|
|
// 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(cParam.CircleACThres);
|
|
|
// 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();
|
|
|
// }
|
|
|
//
|
|
|
// 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)
|
|
|
// {
|
|
|
// pCircle->fRadius = r;
|
|
|
// pCircle->ptCenter = cen;
|
|
|
// }
|
|
|
// return rltMat;
|