#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_(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 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 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 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); } }