#include "QAlgDetect.h" #include "ED.h" #include "EDLines.h" #include "EDCircles.h" #include #include #include "CircleDetector.h" using namespace std; static QImage cvMat2QImage(const cv::Mat& mat) { if (mat.type() == CV_8UC1) { QImage image(mat.cols, mat.rows, QImage::Format_Indexed8); image.setColorCount(256); for (int i = 0; i < 256; i++) { image.setColor(i, qRgb(i, i, i)); } uchar *pSrc = mat.data; for (int row = 0; row < mat.rows; row++) { uchar *pDest = image.scanLine(row); memcpy(pDest, pSrc, mat.cols); pSrc += mat.step; } return image; } else if (mat.type() == CV_8UC3) { const uchar *pSrc = (const uchar*)mat.data; QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888); if (image.isNull()) return QImage(); return image.rgbSwapped(); } else if (mat.type() == CV_8UC4) { const uchar *pSrc = (const uchar*)mat.data; QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32); return image.copy(); } else { qDebug() << "ERROR: Mat could not be converted to QImage."; return QImage(); } } static cv::Mat QImageToMat(QImage image) { cv::Mat mat; QImage::Format f = image.format(); switch (image.format()) { case QImage::Format_ARGB32: case QImage::Format_RGB32: case QImage::Format_ARGB32_Premultiplied: mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); break; case QImage::Format_RGB888: mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); cv::cvtColor(mat, mat, CV_BGR2RGB); break; case QImage::Format_Indexed8: case QImage::Format_Grayscale8: mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); break; } return mat; } 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; } QAlgDetect::QAlgDetect(QObject *parent) : QObject(parent) { } QAlgDetect::~QAlgDetect() { } #define REAIZE 4 void QAlgDetect::detect(QImage img, QVariantMap param, AlgCallBack func) { bool bEqual = param.value("equal").toBool(); Mat srcImg = QImageToMat(img); if(srcImg.channels()!=1) cv::cvtColor(srcImg, srcImg, CV_RGB2GRAY); 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< 50 ) 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; double radius = EDCircle[nIndex].r; int hight = 2 * radius * REAIZE; QPointF centerP; centerP.setX(EDCircle[nIndex].center.x * REAIZE); centerP.setY(EDCircle[nIndex].center.y * REAIZE); double r = radius * REAIZE; Mat aa = DetectCircle(srcImg, centerP, r, bEqual); QImage rltImg = cvMat2QImage(aa); if (func) { func(rltImg); return; } } else { QPointF centerP; centerP.setX(srcImg.cols/2); centerP.setY(srcImg.rows/2); double r = 0; Mat aa = DetectCircle(srcImg, centerP, r, bEqual); QImage rltImg = cvMat2QImage(aa); if (func) { func(rltImg); return; } } if (func) { func(img); } } Mat QAlgDetect::DetectCircle(Mat img, QPointF 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; difRadiusMax = abs(center.y()-(img.cols / 2))-50; } cd.setRadii(difRadiusMin, difRadiusMax); cd.setACThres(3); vector allScores; Vec3f bestCircle; float bestScore = cd.detectBest(detectImg, Point2f(center.x(), center.y()), bestCircle, &allScores); if (abs(bestScore) <= FLT_EPSILON || bestCircle == Vec3f::zeros()) { return Mat(); } QPointF 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); return s; }