#include "ImageProcess.h" #include "qstring.h" #include "CVUtils.h" #include "ED.h" #include "EDLines.h" #include "EDCircles.h" #include "CircleDetector.h" //摩轮宏定义 表示该算法用于摩轮型号识别检测 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); float centerX = 0; float centerY = 0; /* EDCircles edcircles(detectImg); vector EDCircle = edcircles.getCircles(); double maxR = 0; int nIndex = -1; 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); if (cParam.CircleEdgeWidth <= 0) cd.setEdgeWidth(1); else 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 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; float centerX = 0; float centerY = 0; /* 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; 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); } }