You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
whellvalue/src/algorithm/ImageProcess.cpp

220 lines
5.5 KiB
C++

5 years ago
#include "ImageProcess.h"
#include "qstring.h"
#include "CVUtils.h"
#include "ED.h"
#include "EDLines.h"
#include "EDCircles.h"
#include "CircleDetector.h"
5 years ago
//摩轮宏定义 表示该算法用于摩轮型号识别检测
#define MOTO_DETECT
ImageProcess::ImageProcess()
{
}
ImageProcess::~ImageProcess()
{
5 years ago
}
5 years ago
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;
}
5 years ago
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;
}
5 years ago
#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)
{
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, center, radius, bEqual);
}
else {//EDCirle 没找到圆 直径调用精细找圆算法
center.x = srcImg.cols / 2;
center.y = srcImg.rows / 2;
radius = 0;
return DetectCircle(srcImg, center, radius, bEqual);
}
}
Mat ImageProcess::DetectCircle(Mat img, Point2f& center, double& radius, bool bEqual)
{
Mat detectImg;
if (bEqual == true)
{
equalizeHist(img, detectImg);
}
else {
detectImg = img;
}
CircleDetector cd;
cd.setAlgoType(CircleDetector::PeakCircle);
cd.setEdgeWidth(3);
cd.setPolarity(Polarity::White2Black);
cd.setFindBy(FindBy::Best);
double difRadiusMin = radius - 100;
double difRadiusMax = radius + 150;
if (difRadiusMin < 0)
{
difRadiusMin = 0;
if(radius>0)
difRadiusMax = abs(center.y - (img.cols / 2)) - 50;
else {
int minV = (img.rows / 2) > (img.cols / 2) ? (img.cols / 2) : (img.rows / 2);
difRadiusMax = minV - 50;
center.x = img.cols / 2;
center.y = img.rows / 2;
}
}
cd.setRadii(difRadiusMin, difRadiusMax);
cd.setACThres(3);
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();
}
5 years ago
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 = img(rect);
center = cen;
radius = r;
return s;
}
//使用背景图做减法扣圆
cv::Mat ImageProcess::findCircleByBackground(const Mat &src, const Mat& backgroundImg, luffy_base::luffyCircle *pCircle /*= NULL*/)
{
if (src.empty() || backgroundImg.empty() || src.rows < 500) {
return Mat();
}
assert(backgroundImg.type() == CV_8UC1);
Mat imgTmp = src;
Mat foregroundImg = getForeImage(imgTmp, backgroundImg);
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();
}
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;
}