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

255 lines
6.6 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
//摩轮宏定义 表示该算法用于摩轮型号识别检测
ImageProcess::ImageProcess()
{
}
5 years ago
ImageProcess::~ImageProcess()
{
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;
}
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;
float centerX = 0;
float centerY = 0;
double tmpmaxR = 0;
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 (EDCircle[i].r > tmpmaxR)
{
centerX = EDCircle[i].center.x * REAIZE;
centerY = EDCircle[i].center.y * REAIZE;
tmpmaxR = 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;
centerX = EDCircle[i].center.x * REAIZE;
centerY = EDCircle[i].center.y * REAIZE;
}
}
if (nIndex != -1)//找到合适的圆 只需要圆心
{
radius = EDCircle[nIndex].r * REAIZE;
center.x = (EDCircle[nIndex].center.x * REAIZE);
center.y = (EDCircle[nIndex].center.y * REAIZE);
return DetectCircle(srcImg, Mat(), center, radius, bEqual, cParam);
}
else {
center.x = centerX;
center.y = centerY;
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);
if (center.x == 0 || center.y == 0)
{
center.x = img.cols / 2;
center.y = img.rows / 2;
}
int rY = img.rows - center.y;
int rX = img.cols - center.x;
int min_dify = center.y > rY ? rY : center.y;
int min_difx = center.x > rX ? rX : center.x;
int maxRadius = abs(abs(min_difx > min_dify ? min_dify : min_difx) - 50);
double difRadiusMin = radius - 150;
double difRadiusMax = radius + 250;
if (difRadiusMin <= 0)
{
difRadiusMin = cParam.filterSize;
difRadiusMax = maxRadius;
}
//控制范围,不让检测越界
//if (difRadiusMin < cParam.filterSize)
difRadiusMin = cParam.filterSize;
//if (difRadiusMax > maxRadius)
difRadiusMax = maxRadius;
if (difRadiusMin > difRadiusMax)
difRadiusMin = 0;
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();
}
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 = 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;
float centerX = 0;
float centerY = 0;
double tmpmaxR = 0;
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 (EDCircle[i].r > tmpmaxR)
{
centerX = EDCircle[i].center.x * REAIZE;
centerY = EDCircle[i].center.y * REAIZE;
tmpmaxR = 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;
centerX = EDCircle[i].center.x * REAIZE;
centerY = EDCircle[i].center.y * REAIZE;
}
}
if (nIndex != -1)
{
center.x = (EDCircle[nIndex].center.x * REAIZE);
center.y = (EDCircle[nIndex].center.y * REAIZE);
return DetectCircle(srcImg, backgroundImg, center, radius, bEqual, cParam);
}
else {
center.x = centerX;
center.y = centerY;
radius = 0;
return DetectCircle(srcImg, backgroundImg, center, radius, bEqual, cParam);
}
}