|
|
|
|
|
#include "ImageProcess.h"
|
|
|
|
|
|
#include "qstring.h"
|
|
|
|
|
|
#include "CVUtils.h"
|
|
|
|
|
|
#include "ED.h"
|
|
|
|
|
|
#include "EDLines.h"
|
|
|
|
|
|
#include "EDCircles.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "CircleDetector.h"
|
|
|
|
|
|
|
|
|
|
|
|
//摩轮宏定义 表示该算法用于摩轮型号识别检测
|
|
|
|
|
|
#define MOTO_DETECT
|
|
|
|
|
|
|
|
|
|
|
|
ImageProcess::ImageProcess()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ImageProcess::~ImageProcess()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
Mat _EnhanImg_sharpen(const Mat &img) {
|
|
|
|
|
|
int mGainValue = 3;
|
|
|
|
|
|
float amount = mGainValue * 0.5f;
|
|
|
|
|
|
Mat blurred;
|
|
|
|
|
|
|
|
|
|
|
|
int mSmoothValue = 3;
|
|
|
|
|
|
GaussianBlur(img, blurred, Size(), mSmoothValue);
|
|
|
|
|
|
Mat lowContrastMask = abs(img - blurred) < 5;
|
|
|
|
|
|
Mat orResult = img * (1 + amount) + blurred * (-amount);
|
|
|
|
|
|
img.copyTo(orResult, lowContrastMask);
|
|
|
|
|
|
Mat openMat = orResult.clone();
|
|
|
|
|
|
return openMat;
|
|
|
|
|
|
}
|
|
|
|
|
|
Mat findEdge2(const Mat &Src)
|
|
|
|
|
|
{
|
|
|
|
|
|
Mat ret = Src.clone();
|
|
|
|
|
|
Mat kernel = (Mat_<float>(5, 5) <<
|
|
|
|
|
|
-1, -1, -1, -1, -1,
|
|
|
|
|
|
-1, -1, -1, -1, -1,
|
|
|
|
|
|
-1, -1, 24, -1, -1,
|
|
|
|
|
|
-1, -1, -1, -1, -1,
|
|
|
|
|
|
-1, -1, -1, -1, -1);
|
|
|
|
|
|
filter2D(Src, ret, CV_8UC1, kernel);
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
#define REAIZE 2
|
|
|
|
|
|
|
|
|
|
|
|
cv::Mat ImageProcess::getForeImage(const Mat & src, const Mat &backgroundImg)
|
|
|
|
|
|
{
|
|
|
|
|
|
Mat resizedBackgroundImg = backgroundImg;
|
|
|
|
|
|
if (backgroundImg.size() != src.size()) {
|
|
|
|
|
|
resize(backgroundImg, resizedBackgroundImg, src.size());
|
|
|
|
|
|
}
|
|
|
|
|
|
return (src - resizedBackgroundImg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//输入一张灰度图,输出抠出的圆小图和半径,圆心坐标
|
|
|
|
|
|
cv::Mat ImageProcess::findCircle(const Mat &srcImg, Point2f& center, double &radius, bool bEqual, int filterSize, const CircleParam& cParam)
|
|
|
|
|
|
{
|
|
|
|
|
|
Mat detectImg;
|
|
|
|
|
|
Mat src = srcImg;
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
{
|
|
|
|
|
|
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, Mat(), center, radius, bEqual, cParam);
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
center.x = srcImg.cols/2;
|
|
|
|
|
|
center.y = srcImg.rows/2;
|
|
|
|
|
|
radius = 0;
|
|
|
|
|
|
return DetectCircle(srcImg, Mat(), center,radius,bEqual, cParam);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
{
|
|
|
|
|
|
equalizeHist(img, detectImg);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
detectImg = img;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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 = radius - 100;
|
|
|
|
|
|
double difRadiusMax = radius + 100;
|
|
|
|
|
|
if (difRadiusMin < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
difRadiusMin = 0;
|
|
|
|
|
|
difRadiusMax = abs(abs(center.y - (img.cols / 2)) - 50);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cd.setRadii(difRadiusMin, difRadiusMax);
|
|
|
|
|
|
cd.setACThres(cParam.CircleACThres);
|
|
|
|
|
|
vector<float> allScores;
|
|
|
|
|
|
Vec3f bestCircle;
|
|
|
|
|
|
float bestScore = cd.detectBest(detectImg, Point2f(center.x, center.y), bestCircle, &allScores);
|
|
|
|
|
|
if (abs(bestScore) <= FLT_EPSILON || bestCircle == Vec3f::zeros()) {
|
|
|
|
|
|
center.x = 0;
|
|
|
|
|
|
center.y = 0;
|
|
|
|
|
|
radius = 0;
|
|
|
|
|
|
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 s = srcImg(rect);
|
|
|
|
|
|
center = cen;
|
|
|
|
|
|
radius = r;
|
|
|
|
|
|
return s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//使用背景图做减法扣圆
|
|
|
|
|
|
cv::Mat ImageProcess::findCircleByBackground(const Mat &srcImg, const Mat& backgroundImg, Point2f& center, double &radius, bool bEqual, int filterSize, const CircleParam& cParam)
|
|
|
|
|
|
{
|
|
|
|
|
|
Mat detectImg;
|
|
|
|
|
|
Mat src = srcImg;
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
{
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|