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.

235 lines
5.7 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "QAlgDetect.h"
#include "ED.h"
#include "EDLines.h"
#include "EDCircles.h"
#include <QDebug>
#include <vector>
#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_<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;
}
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);//<2F><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> ͼ<><CDBC><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><E3B2BB>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ
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< 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;
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.setX(img.cols / 2);
center.setY(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()) {
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;
}