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.

1401 lines
41 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 "ValveDetector.h"
#include <algorithm>
#include "patterndetector.h"
using namespace luffy_base;
ValveDetector::ValveDetector()
{
luffy_triangle::createNewTrigValue(3600);
}
ValveDetector::~ValveDetector()
{
}
enum detectMode
{
shootWheelExist = 0,
shootTargetMatch = 1
};
void remove(Mat &img, int fValveWidth) {
int nStep = 20;
int nOffset = 30;
float fThres = 0.8;
Mat imgDst;
cv::threshold(img, imgDst, 1, 255.0, THRESH_OTSU);
Mat imgHalf;
Rect ret = Rect(0, imgDst.rows / 2 + nOffset, imgDst.cols, imgDst.rows / 2 - nOffset);
if (ret.y > imgDst.rows || (imgDst.rows / 2 + nOffset + imgDst.rows / 2 - nOffset) > imgDst.rows)
return;
imgDst(ret).copyTo(imgHalf);
Mat imgProj;
luffy_projection::project2axis(imgHalf, imgProj, luffy_projection::emProjX, cv::NORM_MINMAX);
Mat imgBlob(1, imgProj.cols, CV_8UC1);
imgBlob.setTo(0);
float *pProj = imgProj.ptr<float>(0);
uchar *pBlob = imgBlob.ptr<uchar>(0);
for (int i = 0; i < imgProj.cols; i++) {
if (pProj[i] >= fThres) {
pBlob[i] = 255;
int offset = 120;
int nIndex = 0;
bool bLineMode = false;
for (int j = 0; j < offset; j++) {
int nX = i + offset - j;
nX = nX % imgProj.cols;
if (bLineMode) {
pBlob[nX] = 255;
}
else {
if (pProj[nX] >= fThres) {
bLineMode = true;
nIndex = i + offset - j;
}
}
}
if (bLineMode) {
if (nIndex >= imgProj.cols) {
break;
}
else {
i = nIndex;
}
}
}
}
for (int i = 0; i < imgProj.cols; i++){
if (pBlob[i] != 0) {
img.col(i).setTo(0);
}
}
}
Point getNextMinMax(Mat *img, Point maxLoc, double minVal, InputParam InputParameter)
{
int templateH = InputParameter.barTemplate.rows;
int templateW = InputParameter.barTemplate.cols;
int startX = maxLoc.x - templateW / 2;
int startY = 0;
int endX = maxLoc.x + templateW / 2;
int endY = img->rows - 1;
if (startX < 0 || startY < 0)
{
startX = 0;
startY = 0;
}
if (endX > img->cols - 1 || endY >img->rows - 1)
{
endX = img->cols - 1;
endY = img->rows - 1;
}
for (int y = startY; y < endY + 1; y++)
{
float* fPtr = (float*)img->row(y).data;
for (int x = startX; x <= endX; x++)
{
fPtr[x] = minVal;
}
}
double minValue, maxValue;
Point iminLoc, imaxLoc;
minMaxLoc(*img, &minValue, &maxValue, &iminLoc, &imaxLoc);
return imaxLoc;
}
void findCandidateValsInMat(const Mat &_img, vector<Point> &canPoints, InputParam InputParameter)
{
Mat result = _img.clone();
double minVal, maxVal;
Point minLoc, maxLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
canPoints.push_back(maxLoc);
int barNum = InputParameter.barNum;
if (barNum <=0)
{
qWarning() << "burNum cannot be negatIve or ZERO";
return;
}
int maxLength = InputParameter.nMaxAngle;
int interval = maxLength / barNum;
for (int i = 1; i < barNum; i++)
{
int nextLoc = maxLoc.x + (i*interval);
if (nextLoc >= maxLength)
{
nextLoc = nextLoc % maxLength;
}
canPoints.push_back(Point(nextLoc, 0));
}
/*Point next_maxPoint;
next_maxPoint = getNextMinMax(&result, maxLoc, minVal, InputParameter);
canPoints.push_back(next_maxPoint);
next_maxPoint = getNextMinMax(&result, next_maxPoint, minVal, InputParameter);
canPoints.push_back(next_maxPoint);
next_maxPoint = getNextMinMax(&result, next_maxPoint, minVal, InputParameter);
canPoints.push_back(next_maxPoint);
next_maxPoint = getNextMinMax(&result, next_maxPoint, minVal, InputParameter);
canPoints.push_back(next_maxPoint);*/
/*next_maxPoint = getNextMinMax(&result, next_maxPoint, minVal, InputParameter);
canPoints.push_back(next_maxPoint);*/
}
void findOffsets(InputParam in, const vector<Point> & canVec, vector<double> & detectOffset)
{
int barNum = in.barNum;
if (barNum <=0)
{
qWarning() << "barNum cannot be negative or ZERO";
return;
}
int maxLength = in.nMaxAngle;
int withinOffset = in.withinOffset;
int width = in.barTemplate.cols;
for (int i = 0; i < barNum; i++)
{
float barX = canVec[i].x + width / 2.0;
float holeX = barX + withinOffset;
if (holeX > maxLength)
{
//holeX = holeX % maxLength;
holeX = fmod(holeX, (double)maxLength);
}
detectOffset.push_back(holeX);
}
}
void creatMask(const Mat &img2Rect, const vector<double> &offsetVec, InputParam paramIn, Mat &iMask)
{
int smallMove = 20;
for (int i = 0; i < offsetVec.size(); i++)
{
int holeX = offsetVec[i];
int width = paramIn.imgTemplate.cols + 2*smallMove;
int startX = holeX - paramIn.imgTemplate.cols / 2 - smallMove;
if (startX < 0)
{
int offset = abs(startX);
startX = paramIn.nMaxAngle - offset;
//iMask(Rect(startX, 0, offset, img2Rect.rows)).setTo(255);
}
if (startX + paramIn.imgTemplate.cols + 2*smallMove> paramIn.nMaxAngle)
{
width = paramIn.nMaxAngle - startX;
int offset = startX + paramIn.imgTemplate.cols + 2*smallMove- paramIn.nMaxAngle;
iMask(Rect(0, 0, offset, img2Rect.rows)).setTo(255);
}
Rect candidateRoi(startX, 0, width, img2Rect.rows);
iMask(candidateRoi).setTo(255);
}
}
void genSobelImage1(Mat& img, Mat* pSobelx /*= NULL*/, Mat* pSobely /*= NULL*/)
{
Mat sobelx, sobely;
Sobel(img, sobelx, CV_32FC1, 1, 0);
Sobel(img, sobely, CV_32FC1, 0, 1);
img = sobelx.mul(sobelx) + sobely.mul(sobely);
Mat tempImg;
img.convertTo(tempImg, CV_32FC1);
Mat tempImg0;
sqrt(tempImg, tempImg0);
img = tempImg0;
if (pSobelx)
{
*pSobelx = sobelx;
}
if (pSobely)
{
*pSobely = sobely;
}
}
cv::Mat getSobelDir(const Mat& sobelX, const Mat& sobelY)
{
Mat img(sobelX.rows, sobelX.cols, CV_16UC1);
for (int i = 0; i < img.rows; ++i)
{
Mat row = img.row(i);
float* pDataX = (float*)sobelX.row(i).data;
float* pDataY = (float*)sobelY.row(i).data;
ushort* pData = (ushort*)row.data;
for (int j = 0; j < img.cols; ++j)
{
float dx = pDataX[j];
float dy = pDataY[j];
float angle = 0;
if (dx == 0 && dy == 0)
{
angle = 0;
}
else
{
angle = atan2f(dy, dx);
if (angle < 0)
{
angle += 2.0 * M_PI;
}
}
pData[j] = floorf((angle / M_PI) * 180);
}
}
return img;
}
void genSobelDir1(Mat& img)
{
Mat srcImg = img.clone();
Mat sobelX, sobelY;
genSobelImage1(srcImg, &sobelX, &sobelY);
img = getSobelDir(sobelX, sobelY);
}
void histMeanStddev(const Mat& hist, double* pMean, double* pStddev)
{
float * pData = (float*)hist.data;
double sum = 0;
int count = 0;
for (int i = 0; i < hist.cols; ++i)
{
if (!pData[i])
{
continue;
}
count += pData[i];
sum += pData[i] * i;
}
if (count == 1)
{
if (pMean)
{
*pMean = sum;
}
if (pStddev)
{
*pStddev = 0;
}
return;
}
*pMean = sum / (double)count;
sum = 0;
for (int i = 0; i < hist.cols; ++i)
{
if (!pData[i])
{
continue;
}
double d = i - *pMean;
sum += d*d*pData[i];
}
*pStddev = sqrt(sum / (double)(count - 1));
}
double tempScoreShoot(Mat &_img, Mat &template_img, detectMode mode)
{
qDebug() << "tempScoreShoot";
double dis = 0.0;
Mat templateDir = template_img.clone();
Mat temporaryDir = _img.clone();
//temporaryDir = temporaryDir(Rect(0, 30, temporaryDir.cols, temporaryDir.rows - 30));
Mat normTemplateDir, normTemporaryDir;
Mat blurredTempl, blurredTempo;
cv::GaussianBlur(templateDir, blurredTempl, Size(3, 3), 5.0);
cv::GaussianBlur(temporaryDir, blurredTempo, Size(3, 3), 5.0);
luffy_imageProc::meanvarnorm(blurredTempl, normTemplateDir, 120, 50);
luffy_imageProc::meanvarnorm(blurredTempo, normTemporaryDir, 120, 50);
// normTemplateDir.convertTo(normTemplateDir, CV_16UC1);
// normTemporaryDir.convertTo(normTemporaryDir, CV_16UC1);
normTemplateDir.convertTo(normTemplateDir, CV_32F);
normTemporaryDir.convertTo(normTemporaryDir, CV_32F);
genSobelDir1(normTemplateDir);
genSobelDir1(normTemporaryDir);
Mat templateHist, temporaryHist, magHist;
float range[] = { 0, 360 };
const float * histRange = { range };
int histSize = 36;
calcHist(&normTemplateDir, 1, 0, Mat(), templateHist, 1, &histSize, &histRange, true, false);
calcHist(&normTemporaryDir, 1, 0, Mat(), temporaryHist, 1, &histSize, &histRange, true, false);
#ifdef VEIW_HISTGRAM
Mat dstImage = Mat::zeros(512, 800, CV_8UC3);
//normalize(templateHist, templateHist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
//normalize(temporaryHist, temporaryHist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
double max = 0;
double max1 = 0;
minMaxLoc(templateHist, NULL, &max, 0, 0);
minMaxLoc(temporaryHist, NULL, &max1, 0, 0);
max = MAX(max, max1);
double bin_w = (double)dstImage.cols / histSize; // the interval of every bin
double bin_u = (double)dstImage.rows / max; //// the maximal height
// draw histGram
for (int i = 0; i < histSize; i++)
{
Point p0 = Point(i*bin_w, dstImage.rows);
int val = templateHist.at<float>(i);
int val1 = temporaryHist.at<float>(i);
Point p1 = Point((i + 1)*bin_w, dstImage.rows - val*bin_u);
Point p2 = Point((i + 1)*bin_w, dstImage.rows - val1*bin_u);
rectangle(dstImage, p0, p1, Scalar(0, 255), 1, 8, 0);
rectangle(dstImage, p0, p2, Scalar(0, 0, 255), 1, 8, 0);
//imshow("image", dstImage);
}
char string[12];
int yAxis = 0;
for (int i = 1; yAxis < max; i++)
{
yAxis = i*max / 10;
itoa(yAxis, string, 10);
cv::putText(dstImage, string, Point(0, dstImage.rows - yAxis*bin_u), 1, 1, Scalar(0, 255, 255));
}
int xAxis = 0;
for (int i = 1; xAxis < 360; i++)
{
xAxis = i * 20;
itoa(xAxis, string, 10);
cv::putText(dstImage, string, Point(xAxis*(dstImage.cols / 360), dstImage.rows), 1, 1, Scalar(0, 255, 255));
}
#endif // VEIW_HISTGRAM
switch (mode)
{
case shootWheelExist:
{
/* double templMean, templStddev, tempoMean, tempoStddev;
transpose(templateHist, templateHist);
transpose(temporaryHist, temporaryHist);
histMeanStddev(templateHist, &templMean, &templStddev);
histMeanStddev(temporaryHist, &tempoMean, &tempoStddev);
double meanDiff = abs(templMean - tempoMean);
double stddevDiff = abs(templStddev - tempoStddev);
if (meanDiff > 1.5 || stddevDiff > 1.5)
{
qDebug() << "there is no wheel exist";
return 0;
}
else
{
qDebug() << "wheel exists";
return 1;
}*/
}
case shootTargetMatch:
{
qDebug() << "start get matchScore:" ;
double templCount = cv::sum(templateHist.rowRange(12, 25)).val[0];
double temporCount = cv::sum(temporaryHist.rowRange(12, 25)).val[0];
dis = temporCount / templCount;
if (dis > 0.60)
{
if (dis > 1)
{
dis = 1;
qDebug() << "matchScore:" << dis;
return dis;
}
else
{
qDebug() << "matchScore:" << dis;
return dis;
}
}
qDebug() << "fail to find the targetMatch";
return 0;
}
}
qDebug() << "end tempScoreShoot";
return 0;
}
cv::Mat LoopRoi(Mat &src, int x, int nWidth) {
Mat dst;
if (x + nWidth > src.cols) {
if (src.type() == CV_8UC1)
{
dst.create(Size(nWidth, src.rows), CV_8UC1);
}
else
{
dst.create(Size(nWidth, src.rows), CV_32FC1);
}
src(Rect(x, 0, src.cols - x, src.rows)).copyTo(dst(Rect(0, 0, src.cols - x, src.rows)));
src(Rect(0, 0, nWidth - src.cols + x, src.rows)).copyTo(dst(Rect(src.cols - x, 0, nWidth - src.cols + x, src.rows)));
}
else {
Rect roi(x, 0, nWidth, src.rows);
src(roi).copyTo(dst);
}
return dst;
}
cv::Point2f ValveDetector::getCenterPoints(Mat &_Img, const Mat &centerTempl, InputParam paramIn, Point2f pt, Mat & rstMat)
{//<2F><><EFBFBD>Ķ<EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD> 0<>ر<EFBFBD> 1<><31><EFBFBD><EFBFBD>
if (0 == paramIn.nCenterAlg) {
return pt;
}
if (paramIn.wheelType == 1)
{
if (paramIn.backGround.empty())
{
return pt;
}
else
{
Record_List roiRecord = paramIn.roi.records;
int nRoiCount = roiRecord.size();
if (nRoiCount > 0)
{
Item_List itemRoi = roiRecord.front();
int width = abs(itemRoi.front().second.at(2));
int height = abs(itemRoi.front().second.at(3));
int corr_x = itemRoi.front().second.at(0) - width / 2.0;
int corr_y = itemRoi.front().second.at(1) - height / 2.0;
Rect rect = Rect(corr_x, corr_y, width, height);
Mat roiMat = _Img(rect);
Mat backCandidateMat = paramIn.backGround(rect);
//Mat forMat = abs(roiMat - backCandidateMat);
luffy_base::luffyCircle pCircle;
findCircleObject(roiMat, backCandidateMat, paramIn.backgroundThresh, &pCircle);
rstMat = findCircleObject(_Img, paramIn.backGround, paramIn.backgroundThresh, NULL);
float axis_x = corr_x + pCircle.ptCenter.x;
float axis_y = corr_y + pCircle.ptCenter.y;
return Point2f(axis_x, axis_y);
}
}
luffy_base::luffyCircle pCircle;
rstMat = findCircleObject(_Img, paramIn.backGround, paramIn.backgroundThresh, &pCircle);
qDebug() << "get image";
return pCircle.ptCenter;
}
else
{
Mat centerMatch;
int nOffset = 80; //need
int templW = centerTempl.cols;
int templH = centerTempl.rows;
int nStartX = pt.x - templW / 2 - nOffset;
int nStartY = pt.y - templH / 2 - nOffset;
if (nStartX<0||nStartY<0)
return Point2f(0, 0);
if ((2 * nOffset + templH)>_Img.rows)
return Point2f(0, 0);
if ((2 * nOffset + templW)>_Img.cols)
return Point2f(0, 0);
if ((2 * nOffset + templH+nStartY) > _Img.rows)
return Point2f(0, 0);
if ((2 * nOffset + templW+nStartX) > _Img.cols)
return Point2f(0, 0);
Mat imgRoi;
_Img(Rect(pt.x - templW / 2 - nOffset, pt.y - templH / 2 - nOffset, 2 * nOffset + templW, 2 * nOffset + templH)).copyTo(imgRoi);
matchTemplate(imgRoi, centerTempl, centerMatch, CV_TM_CCOEFF_NORMED);
Point p;
double v = luffy_math::getMinMaxData(centerMatch, luffy_math::emDataMax, &p);
int localCenterX = p.x + templW / 2;
int localCenterY = p.y + templH / 2;
int newCenterX = pt.x - templW / 2 - nOffset + localCenterX;
int newCenterY = pt.y - templH / 2 - nOffset + localCenterY;
/*Mat img1 = _Img.clone();
Mat img2 = _Img.clone();
Mat img3 = _Img.clone();
vector<Mat> imgs;
imgs.push_back(img1);
imgs.push_back(img2);
imgs.push_back(img3);
Mat rst;
merge(imgs, rst);
cv::circle(rst, Point(newCenterX, newCenterY), 3, Scalar(255), -1);*/
return Point2f(newCenterX, newCenterY);
}
}
cv::Mat ValveDetector::getForeImage(const Mat & src, const Mat &backgroundImg)
{
Mat resizedBackgroundImg = backgroundImg;
if (backgroundImg.size() != src.size()) {
resize(backgroundImg, resizedBackgroundImg, src.size());
}
qDebug() << src.cols << "" << src.rows << "" << resizedBackgroundImg.cols << "" << resizedBackgroundImg.rows;
qDebug() << src.channels() << "" << resizedBackgroundImg.channels();
Mat h = src - resizedBackgroundImg;
qDebug() << "h pass";
return (src - resizedBackgroundImg);
}
cv::Mat ValveDetector::findCircleObject(const Mat &src, const Mat& backgroundImg, int nThres, luffy_base::luffyCircle *pCircle)
{
if (src.empty() || backgroundImg.empty() || src.rows < 500) {
return Mat();
}
assert(backgroundImg.type() == CV_8UC1);
Mat imgTmp, imgBinary;
const cv::Size cSize = cv::Size(ALG_RESIZE_IMAGE_WIDTH, floorf(ALG_RESIZE_IMAGE_WIDTH / (float)src.cols*(float)src.rows));
cv::resize(src, imgTmp, cSize);
Mat foregroundImg = getForeImage(imgTmp, backgroundImg);// 0421
using namespace luffy_base;
luffy_threshold::Threshold(foregroundImg, imgBinary, nThres);//0421
//luffy_threshold::Threshold(imgTmp, imgBinary, nThres);
Mat dilatedImgBin;
dilate(imgBinary, dilatedImgBin, Mat::ones(7, 7, CV_32FC1));
erode(dilatedImgBin, imgBinary, Mat::ones(7, 7, CV_32FC1));
erode(imgBinary, imgBinary, Mat::ones(1, 13, CV_32FC1));
dilate(imgBinary, imgBinary, Mat::ones(1, 13, CV_32FC1));
vector<vector<Point>> conts;
cv::findContours(imgBinary, conts, RETR_EXTERNAL, CHAIN_APPROX_NONE);
imgBinary.setTo(0);
for (int i = 0; i < conts.size(); i++) {
const vector<Point> &pt = conts.at(i);
if (pt.size() < 20) {
continue;
}
Rect rt = boundingRect(pt);
if (rt.width < 5 || rt.height < 5) {
continue;
}
drawContours(imgBinary, conts, i, Scalar::all(255), -1);
}
Mat hit; vector<Point> pts;
luffy_hit::firstHit4Circle(imgBinary, hit, pts, Point(cSize.width / 2, cSize.height / 2), 0, cSize.width / 2, 360, luffy_hit::emHitOut2In);
qDebug() << "image8";
//luffy_imageProc::RansacParam rs(0.02, 2.5, 70, 100, 220);
luffy_imageProc::RansacParam rs(0.01, 3, 200, 150, 240);//0421
vector<Point> pts2 = luffy_imageProc::fitModelbyRansac(pts, luffy_imageProc::emModelCircle, &rs);
#ifdef _DEBUG
Mat imgColor;
cv::cvtColor(imgTmp, imgColor, CV_GRAY2BGR);
for (int i = 0; i < pts.size(); i++) {
imgColor.at<cv::Vec3b>(pts.at(i))[0] = 255;//B
imgColor.at< cv::Vec3b >(pts.at(i))[1] = 0;//G
imgColor.at< cv::Vec3b >(pts.at(i))[2] = 0;//R
}
for (int i = 0; i < pts2.size(); i++) {
imgColor.at<cv::Vec3b>(pts2.at(i))[0] = 0;//B
imgColor.at< cv::Vec3b >(pts2.at(i))[1] = 0;//G
imgColor.at< cv::Vec3b >(pts2.at(i))[2] = 255;//R
}
#endif
float fRadius;
Point2f ptCenter;
bool bFind = luffy_imageProc::lsCircleFit(pts2, fRadius, ptCenter);
qDebug() << "image9";
if (!bFind) {
return Mat();
}
Mat dst;
const int nOffset = 1;
fRadius += nOffset;
Rect rt(ptCenter.x - fRadius + nOffset, ptCenter.y - fRadius + nOffset, 2 * fRadius, 2 * fRadius);
rt &= Rect(0, 0, imgTmp.cols, imgTmp.rows);
imgTmp(rt).copyTo(dst);
static int nCount = cv::getTickCount();
if (pCircle) {
float fScale = src.cols / ALG_RESIZE_IMAGE_WIDTH;
Mat matBig = src - backgroundImg;//0421
//Mat matBig = src;
pCircle->fRadius = fRadius * fScale;
pCircle->ptCenter = Point(ptCenter.x * fScale, ptCenter.y * fScale);
Mat matBinary;
luffy_threshold::Threshold(matBig, matBinary, nThres);
Mat hit; vector<Point> pts;
luffy_hit::firstHit4Circle(matBinary, hit, pts, pCircle->ptCenter, 0, pCircle->fRadius + 10, 360, luffy_hit::emHitOut2In);
luffy_imageProc::RansacParam rs(0.01, 2.5, 200, 150, 220);
vector<Point> pts2 = luffy_imageProc::fitModelbyRansac(pts, luffy_imageProc::emModelCircle, &rs);
float fRadius2;
Point2f ptCenter2;
bool bFind = luffy_imageProc::lsCircleFit(pts2, fRadius2, ptCenter2);
if (bFind) {
pCircle->fRadius = fRadius2;
pCircle->ptCenter = ptCenter2;
Rect rt(ptCenter2.x - fRadius2 + nOffset, ptCenter2.y - fRadius2 + nOffset, 2 * fRadius2, 2 * fRadius2);
if (rt.x < 0 || rt.y < 0 || rt.x + rt.width > matBinary.cols || rt.y + rt.height > matBinary.rows) {
return Mat();
}
rt &= Rect(0, 0, matBinary.cols, matBinary.rows);
src(rt).copyTo(dst);
int nWidth = ((int)((double)dst.cols / fScale / 4)) * 4;
cv::resize(dst, dst, cv::Size(nWidth, nWidth));
}
}
return dst;
}
bool isRequiredModel(Mat &_img, InputParam &paramIn)
{
int notSatisified = 0;
Mat imgRect = _img.clone();
Mat rstImage;
luffy_match::LoopMatMatch(imgRect, imgRect, luffy_match::emLoopMatX, rstImage);
int interval = floor(paramIn.nMaxAngle / paramIn.barNum);
double minVal, maxVal;
Point minLoc, maxLoc;
cv::minMaxLoc(rstImage, &minVal, &maxVal, &minLoc, &maxLoc);
vector<int> loc;
loc.push_back(maxLoc.x);
Point getMaxLoc;
for (int i = 1; i < paramIn.barNum + 1; i++)
{
getMaxLoc = getNextMinMax(&rstImage, maxLoc, 0, paramIn);
maxLoc = getMaxLoc;
loc.push_back(getMaxLoc.x);
}
std::sort(loc.begin(), loc.end());
for (int j = 0; j < loc.size(); j++)
{
if (j + 1 >= 7)
{
break;
}
int diff = loc[j + 1] - loc[j];
int interDiff = abs(diff - interval);
if (interDiff > 10)
{
notSatisified++;
}
}
if (notSatisified > 2)
{
return false;
}
else
{
return true;
}
}
void getTargetPosAndVal(const Mat &img, InputParam &in, double &val, int &nPos)
{
vector<int> diffVec;
vector<int> vec;
vec.resize(in.barNum);
diffVec.resize(in.barNum);
Mat result = img.clone();
double minVal, maxVal;
Point minLoc, maxLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
int maxLength = in.nMaxAngle;
int interval = in.nMaxAngle / in.barNum;
int barX = maxLoc.x + in.barTemplate.cols / 2;
barX = barX % maxLength;
int valveOffset = in.nValveOffset;
diffVec[0] = abs(barX - valveOffset);
vec[0] = barX;
for (int i = 1; i < diffVec.size(); i++)
{
int vOffset = barX + interval*i;
if (vOffset >=in.nMaxAngle)
{
vOffset = vOffset % maxLength;
}
diffVec[i] = abs(vOffset - valveOffset);
vec[i] = vOffset;
}
size_t valIndex = std::min_element(diffVec.begin(), diffVec.end()) - diffVec.begin();
nPos = vec[valIndex];
val = maxVal;
//nPos = barX;
}
int roiCandidateMatch(const vector<Mat> &vec, Mat templ)
{
vector<float> candidateVal;
candidateVal.resize(vec.size());
for (int i = 0; i < vec.size(); ++i)
{
Mat roi = vec[i];
Mat roiMatch;
luffy_match::LoopMatMatch(roi, templ, luffy_match::emLoopMatX, roiMatch);
Point pt3;
double v3 = luffy_math::getMinMaxData(roiMatch, luffy_math::emDataMax, &pt3);
candidateVal[i] = v3;
}
auto val = std::max_element(candidateVal.begin(), candidateVal.end());
int index = std::distance(candidateVal.begin(), val);
return index;
}
bool imageRotateMatch(Mat & imgSrc, InputParam &paramIn, OutputParam &paramOut, vector<double> candidatePoints)
{
float templateAngle = paramIn.nValveOffset / paramIn.nMaxAngle * 360;
Mat imgTemplate = paramIn.imgTemplate;
vector<Mat> templates;
templates.resize(360);
int rotateOffset = 15;
int x = imgTemplate.cols / 2 - rotateOffset;
int y = imgTemplate.rows / 2 - rotateOffset;
int width = imgTemplate.cols - 2 * x;
int height = imgTemplate.rows - 2 * y;
Rect rect = Rect(x, y, width, height);
for (int i = templateAngle, j = 0; i < 360 + templateAngle, j < 360; ++i, ++j)
{
i = i % 360;
Mat transMat = getRotationMatrix2D(Point2f(imgTemplate.cols / 2.0, imgTemplate.rows / 2.0), j, 1.0);
Mat dst;
warpAffine(imgTemplate, dst, transMat, imgTemplate.size());
Mat dstRoi = dst(rect);
templates[i] = dstRoi;
}
vector<vector<float>> candiateAngleRange;
candiateAngleRange.resize(candidatePoints.size());
int nOffSet = 0;
for (int x = 0; x < candidatePoints.size(); ++x)
{
float startIndex = candidatePoints[x] - templates[0].cols / 2.0 - nOffSet;
startIndex = luffy_math::mod(startIndex, paramIn.nMaxAngle);
float holeStartAngle = startIndex / paramIn.nMaxAngle * 360;
float endIndex = candidatePoints[x] + templates[0].cols + nOffSet;
float holeEndAngle = 0.0;
if (endIndex > paramIn.nMaxAngle)
{
holeEndAngle = fmod(endIndex, paramIn.nMaxAngle) / paramIn.nMaxAngle * 360;
}
else
{
holeEndAngle = endIndex / paramIn.nMaxAngle * 360;
}
candiateAngleRange[x].push_back(holeStartAngle);
candiateAngleRange[x].push_back(holeEndAngle);
}
float fvalveWidth = paramIn.fValveWidth;
float fvalveDis = paramIn.fValveDis;
Point wheelCenter = paramIn.ptCenter;
int offset = 30;
Mat srcImg = imgSrc.clone();
int outterRadius = fvalveDis + offset;
int innerRadius = fvalveDis - offset;
Mat wheelRoi = srcImg(Rect(wheelCenter.x - outterRadius, wheelCenter.y - outterRadius, outterRadius * 2, outterRadius * 2));
Mat wheelRoiMask(wheelRoi.size(), wheelRoi.type(), Scalar::all(0));
cv::circle(wheelRoiMask, Point2f(wheelRoi.cols / 2.0, wheelRoi.rows / 2.0), outterRadius, Scalar::all(255), -1);
cv::circle(wheelRoiMask, Point2f(wheelRoi.cols / 2.0, wheelRoi.rows / 2.0), innerRadius, Scalar::all(0), -1);
Mat selectRoi = (wheelRoiMask / 255).mul(wheelRoi);
/*vector<Mat> imgs;
Mat img1 = selectRoi.clone();
Mat img2 = selectRoi.clone();
imgs.push_back(selectRoi);
imgs.push_back(img2);
imgs.push_back(img1);
Mat showImage;
showImage.setTo(0);
merge(imgs, showImage);*/
/*std::map<float, Point> valToLoc;*/
////qDebug() << "start";
//float sumVal = 0;
Point p = Point(0, 0);
float maxVal = _I32_MIN;
float m_Index = 0.0;
Mat roi;
roi.setTo(0);
for (int k = 0; k < selectRoi.rows; ++k) {
//uchar *ptr = selectRoi.row(k).data;
for (int m = 0; m < selectRoi.cols; ++m) {
//qDebug() << "k:" << k << "m :" << m ;
float dis = luffy_math::disofPoints(Point2f(m, k), Point2f(wheelRoi.cols / 2.0, wheelRoi.rows / 2.0));
if (dis > outterRadius || dis < innerRadius) {
continue;
}
float nIndex = luffy_math::caculAngle(Point2f(wheelRoi.cols / 2.0, wheelRoi.rows / 2.0), Point2f(m, k));
int flag = false;
for (int y = 0; y < candiateAngleRange.size(); ++y) {
if (candiateAngleRange[y][0] > candiateAngleRange[y][1]) {
if ((nIndex >= candiateAngleRange[y][0] && nIndex < 360) || (nIndex >=0 && nIndex <=candiateAngleRange[y][1])) {
const Mat& templ = templates[nIndex];
int nwidth = templ.cols;
int nheight = templ.rows;
if ((m + nwidth >= outterRadius * 2) || (k + nheight > outterRadius * 2)) {
continue;
}
Mat matchRoi = selectRoi(Rect(m, k, nwidth, nheight));
Mat val;
cv::matchTemplate(matchRoi, templ, val, CV_TM_CCOEFF_NORMED);
//float val = norm(matchRoi, templ, NORM_L2);
if (val.at<float>(0, 0) > maxVal) {
maxVal = val.at<float>(0, 0);
p = Point(m, k);
m_Index = nIndex;
roi = matchRoi;
}
}
}
if (nIndex >= candiateAngleRange[y][0] && nIndex <= candiateAngleRange[y][1]) {
//selectRoi.at<uchar>(k, m) = 0;
const Mat& templ = templates[nIndex];
int nwidth = templ.cols;
int nheight = templ.rows;
if ((m + nwidth >= outterRadius * 2) || (k + nheight > outterRadius * 2)) {
continue;
}
Mat matchRoi = selectRoi(Rect(m, k, nwidth, nheight));
Mat val;
cv::matchTemplate(matchRoi, templ, val, CV_TM_CCOEFF_NORMED);
//float val = norm(matchRoi, templ, NORM_L2);
if (val.at<float>(0, 0) > maxVal) {
maxVal = val.at<float>(0, 0);
p = Point(m, k);
m_Index = nIndex;
roi = matchRoi;
}
}
}
}
}
Point2f pLoc = Point2f(p.x + templates.front().cols / 2.0, p.y + templates.front().rows / 2.0);
paramOut.rstPoint = paramIn.ptCenter + pLoc - Point2f(wheelRoi.cols / 2.0, wheelRoi.rows / 2.0);
paramOut.dAngleRes = m_Index;
paramOut.dScore = maxVal;
paramIn.fValveWidth = templates.front().cols / 2.0;
//cv::rectangle(showImage, p, Point(p.x + templates[0].cols, p.y + templates[0].rows), Scalar(0, 0, 255), 2, 8, 0);
double disVal = tempScoreShoot(roi, templates[55], detectMode::shootTargetMatch);
return true;
}
bool ValveDetector::detect(Mat & imgSrc, InputParam &paramIn, OutputParam &paramOut, Mat &imgDst /*= Mat()*/)
{
int rtWidth = 100;
if (paramIn.ptCenter.x - rtWidth < 0 || paramIn.ptCenter.y - rtWidth < 0)
return false;
if (paramIn.ptCenter.x + 2 * rtWidth > imgSrc.cols)
return false;
if (paramIn.ptCenter.y + 2 * rtWidth>imgSrc.rows)
return false;
if (paramIn.barNum <= 0)
return false;
cv::Mat imgCenter = imgSrc(Rect(paramIn.ptCenter.x - rtWidth, paramIn.ptCenter.y - rtWidth, 2 * rtWidth, 2 * rtWidth));
Scalar scMean = cv::mean(imgCenter);
if (scMean[0] < 20) {
paramOut.dAngle = 3610;
paramOut.dScore = 0;
}
else {
float fValveWidth = paramIn.fValveWidth;
float fValveDis = paramIn.fValveDis;
int offset = 10;
int nImgHeight = fValveWidth * 2 + 2 * offset;
Mat img2Rect;
paramIn.ptCenter = Point(paramIn.ptCenter.x , paramIn.ptCenter.y);
luffy_math::polar2rect(imgSrc, img2Rect, paramIn.ptCenter, fValveDis - nImgHeight / 2, fValveDis + nImgHeight / 2, paramIn.nMaxAngle);
Mat imgMatch, barCompare;
if (paramIn.flagCircle == 1 )
{
luffy_match::LoopMatMatch(img2Rect, paramIn.barTemplate, luffy_match::emLoopMatX, barCompare);
double score = 0;
int tarPos;
getTargetPosAndVal(barCompare, paramIn, score, tarPos);//<2F><><EFBFBD><EFBFBD><EFBFBD>ǶȺͷ<C8BA><CDB7><EFBFBD>
paramOut.dAngle = tarPos;
paramOut.dScore = score;
}
else
{
luffy_match::LoopMatMatch(img2Rect, paramIn.barTemplate, luffy_match::emLoopMatX, barCompare);
vector<Point> candidatePoints;
findCandidateValsInMat(barCompare, candidatePoints, paramIn);
int bIsNotStatisfy = 0;
Mat imgRect = img2Rect.clone();
for (int i = 0; i < candidatePoints.size(); i++)
{
int rectW = paramIn.barTemplate.cols;
int rectH = img2Rect.rows;
if ((candidatePoints[i].x + rectW) > img2Rect.cols)
{
rectW = img2Rect.cols - candidatePoints[i].x;
int leftOffset = candidatePoints[i].x + paramIn.barTemplate.cols - img2Rect.cols;
img2Rect(Rect(0, 0, leftOffset, rectH)).setTo(0);
}
Rect rToBeErease(candidatePoints[i].x, 0, rectW, rectH);
img2Rect(rToBeErease).setTo(0);
Mat barRoi = LoopRoi(barCompare, candidatePoints[i].x, paramIn.barTemplate.cols);
double dx = luffy_math::getMinMaxData(barRoi, luffy_math::emDataMax);
if (dx < paramIn.nBarScore / 100.0) {
bIsNotStatisfy++;
}
}
if (bIsNotStatisfy < 2) {
vector<double> detectedOffset;
findOffsets(paramIn, candidatePoints, detectedOffset);
//Mat iMask(img2Rect.size(), img2Rect.type(), Scalar::all(0));
//creatMask(img2Rect, detectedOffset, paramIn, iMask);
vector<Mat> vecImg;
int nOffset = 10;
for (int i = 0; i < detectedOffset.size(); i++) {
int nStart = detectedOffset.at(i) - paramIn.imgTemplate.cols / 2.0 - nOffset;
nStart = luffy_math::mod(nStart, paramIn.nMaxAngle);
Mat roi = LoopRoi(imgRect, nStart, paramIn.imgTemplate.cols + 2 * nOffset);
Mat roi2 = roi(Rect(0, 0, roi.cols, roi.rows *3.0 / 5));
// Mat roi3;
// float m = 128; float d = 70.0;
// luffy_imageProc::meanvarnorm(roi2, roi3, m, d);
if (paramIn.wheelType == 0)
{
vecImg.push_back(roi2);
}
else
{
vecImg.push_back(roi);
}
}
// FOR MOTORCIRCLE PROGRAM START
Mat ret(vecImg.size(), vecImg.size(), CV_32FC1, Scalar(0));
for (int i = 0; i < vecImg.size(); i++) {
for (int j = 0; j < vecImg.size(); j++) {
Mat imgMatch2;
Point pt;
Mat templ;
luffy_match::LoopMatMatch(vecImg.at(i), vecImg.at(j), luffy_match::emLoopMatY, imgMatch2);
double v = luffy_math::getMinMaxData(imgMatch2, luffy_math::emDataMax, &pt);
ret.at<float>(i, j) = v;
}
}
float fMin = 1000;
int nIndex = 0;
std::map<float, int> scoreMapIndex;
for (int i = 0; i < ret.cols; i++) {
float fSum = sum(ret.col(i))[0];
scoreMapIndex[fSum] = i;
if (fSum < fMin) {
fMin = fSum;
nIndex = i;
}
}
std::map<float, int>::iterator it = scoreMapIndex.begin();
int candidateIndex = 0;
int ni = 0;
for (; it != scoreMapIndex.end(); ++it, ++ni)
{
if (ni == 1)
{
candidateIndex = it->second;
}
}
//FOR MOTORCIRCLE END
double mcutOffset = 1.0;
float ss = 0.0;
if (paramIn.wheelType == 0)
{
mcutOffset = 2.0;
// FOR MOTORCIRCLE PROGRAM START
Mat imgTemplate = paramIn.imgTemplate(Rect(0, 0, paramIn.imgTemplate.cols, paramIn.imgTemplate.rows / mcutOffset));
Mat ret0;
matchTemplate(vecImg[nIndex], imgTemplate, ret0, CV_TM_CCORR_NORMED);
Point p0;
double v0 = luffy_math::getMinMaxData(ret0, luffy_math::emDataMax, &p0);
Mat ret1;
matchTemplate(vecImg[candidateIndex], imgTemplate, ret1, CV_TM_CCORR_NORMED);
Point p1;
double v1 = luffy_math::getMinMaxData(ret1, luffy_math::emDataMax, &p1);
nIndex = v1 > v0 ? candidateIndex : nIndex;
Mat identicalImg = vecImg[nIndex](Rect(10, 0, imgTemplate.cols, imgTemplate.rows));
double disVal = tempScoreShoot(identicalImg, imgTemplate, detectMode::shootTargetMatch);
std::vector<Mat> vecMat;
auto imgCrop = [&](Mat srcMat, std::vector<Mat>& vecMat){
int rightTopX = srcMat.cols - imgTemplate.cols;
int leftDownY = srcMat.rows - imgTemplate.rows;
Mat rightTopMat = srcMat(Rect(rightTopX, 0, imgTemplate.cols, imgTemplate.rows));
Mat leftDownMat = srcMat(Rect(0, leftDownY, imgTemplate.cols, imgTemplate.rows));
Mat rightDownMat = srcMat(Rect(rightTopX, leftDownY, imgTemplate.cols, imgTemplate.rows));
vecMat.push_back(rightTopMat);
vecMat.push_back(leftDownMat);
vecMat.push_back(rightDownMat);
};
imgCrop(vecImg[nIndex], vecMat);
for each (Mat vMat in vecMat)
{
double s = tempScoreShoot(vMat, imgTemplate, detectMode::shootTargetMatch);
if (s > disVal)
{
disVal = s;
}
}
int targetIndex = nIndex;
float maxVal = disVal;
if (disVal < 0.85)
{
float vMax = FLT_MIN;
for (int k = 0; k < vecImg.size(); k++)
{
if (k == nIndex)
{
continue;
}
else
{
Mat imgRet;
matchTemplate(vecImg[k], imgTemplate, imgRet, CV_TM_CCORR_NORMED);
Point pnt;
double v3 = luffy_math::getMinMaxData(imgRet, luffy_math::emDataMax, &pnt);
if (v3 > vMax)
{
targetIndex = k;
vMax = v3;
}
}
}
}
nIndex = targetIndex;
Mat imgMatchRet;
matchTemplate(vecImg[nIndex], imgTemplate, imgMatchRet, CV_TM_CCORR_NORMED);
Point pt3;
double v3 = luffy_math::getMinMaxData(imgMatchRet, luffy_math::emDataMax, &pt3);
float nPos = pt3.x + detectedOffset.at(nIndex) - nOffset;
paramOut.dAngle = fmod(nPos, (double)paramIn.nMaxAngle);
paramOut.dScore = v3;
}
else
{
Rect ret = Rect(0, 0, paramIn.imgTemplate.cols, paramIn.imgTemplate.rows / mcutOffset);
if (paramIn.imgTemplate.cols <= 0 || paramIn.imgTemplate.rows / mcutOffset <= 0 || paramIn.imgTemplate.rows / mcutOffset > paramIn.imgTemplate.rows)
return false;
Mat imgTemplate = paramIn.imgTemplate(ret);
PatternDetector m_detect;
m_detect.train(imgTemplate);
Vec4f t_vec;
int m_posIndex = 0;
float maxVal = 0;
int m_index = 0;
for (int k = 0; k < vecImg.size(); k++)
{
Mat roiMat = vecImg[k];
float score = m_detect.detectBest(roiMat, t_vec);
if (score > maxVal)
{
maxVal = score;
m_posIndex = t_vec[0];
m_index = k;
}
}
float nPos = m_posIndex + detectedOffset.at(m_index) - nOffset - imgTemplate.cols / 2.0;
paramOut.dAngle = fmod(nPos, (double)paramIn.nMaxAngle);
paramOut.dScore = maxVal / 100.0;
}
}
else {
qDebug() << "bar check is failed";
paramOut.dAngle = 3610;
paramOut.dScore = 0;
}
}
}
if (paramOut.dScore < paramIn.dScoreThres / 100.0 )
{
paramOut.nErrorType += 8;
}
paramOut.bIsFind = true;
return true;
}
void ValveDetector::drawResult(Mat &img, InputParam &paramIn, OutputParam &paramOut)
{
if (img.empty()) {
return;
}
QString strObj = paramIn.strObj;
QString str = "type: " + (strObj.isEmpty() ? "no type" : strObj);
putText(img, str.toLatin1().data(), Point(10, 100), 3, 2, LP_COLOR_RED, 3);
QString strAngle;
if (!paramOut.bIsFind) {
strAngle = "result: can not find valve";
}
else {
strAngle = "result: " + QString::number(paramOut.dAngleRes, 'f', 2);
}
putText(img, strAngle.toLatin1().data(), Point(10, 200), 3, 2, LP_COLOR_RED, 3);
QString strScore;
QString strComp = ">";
if ((paramOut.nErrorType & 0x08) || (paramOut.nErrorType & 0x16)) {
strComp = "<";
}
strScore = "score=" + QString::number((paramOut.dScore)*100.0, 'f', 2) + "%" + strComp + QString::number(paramIn.dScoreThres, 'f', 2) + "%";
putText(img, strScore.toLatin1().data(), Point(10, 400), 3, 2, LP_COLOR_RED, 3);
str = "time: " + QString::number((int)paramOut.dTime) + "ms";
putText(img, str.toLatin1().data(), Point(10, 300), 3, 2, LP_COLOR_RED, 3);
str = "errorType: " + QString::number(paramOut.nErrorType);
putText(img, str.toLatin1().data(), Point(10, 500), 3, 2, LP_COLOR_RED, 3);
if (paramOut.flag == 1)
{
str = "Attention: center need to be ccalibrated";
putText(img, str.toLatin1().data(), Point(10, 600), 3, 2, LP_COLOR_RED, 3);
}
if (paramOut.nErrorType & 0x16) {
strComp = ">";
}
else
{
strComp = "<";
}
if (paramOut.showMatchScore >= 0)
{
str = "model judge score = " + QString::number(paramOut.showMatchScore, 'f', 4) + strComp + QString::number(paramIn.cMatchScore, 'f', 4);
putText(img, str.toLatin1().data(), Point(10, 700), 3, 2, LP_COLOR_RED, 3);
}
if (paramOut.bIsFind) {
//<! base line
luffy_base::luffy_triangle::createNewTrigValue(paramIn.nMaxAngle);
/*ͨ<><CDA8><EFBFBD>Ƕȡ<C7B6>Բ<EFBFBD>ĺ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EAB6A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>*/
int tmpX2 = paramIn.ptCenter.x + paramIn.fValveDis * luffy_base::luffy_triangle::getCos(paramIn.nMaxAngle, paramIn.nStartOffset);
int tmpY2 = paramIn.ptCenter.y - paramIn.fValveDis * luffy_base::luffy_triangle::getSin(paramIn.nMaxAngle, paramIn.nStartOffset);
qDebug() << "x, y : " << tmpX2 << tmpY2;
Point ptValveBase(tmpX2, tmpY2);
cv::line(img, paramIn.ptCenter, ptValveBase, LP_COLOR_GREEN, 2);//<2F><><EFBFBD>Ʊ궨<C6B1><EAB6A8><EFBFBD><EFBFBD>Բ<EFBFBD>ĵ<EFBFBD>ֱ<EFBFBD><D6B1>
cv::circle(img, ptValveBase, 3, LP_COLOR_GREEN, 3);//<2F><><EFBFBD>Ʊ궨<C6B1><EAB6A8>Բ<EFBFBD><D4B2> <20>Ŵ<EFBFBD>
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>оλ<D0BE>úͻ<C3BA><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>о*/
int angle = paramOut.dAngle >= paramIn.nMaxAngle ? 0 : paramOut.dAngle;
int tmpX = paramIn.ptCenter.x + paramIn.fValveDis * luffy_base::luffy_triangle::getCos(paramIn.nMaxAngle, angle);
int tmpY = paramIn.ptCenter.y - paramIn.fValveDis * luffy_base::luffy_triangle::getSin(paramIn.nMaxAngle, angle);
Point ptValve(tmpX, tmpY);
cv::line(img, paramIn.ptCenter, ptValve, LP_COLOR_RED, 2);
cv::circle(img, ptValve, paramIn.fValveWidth, LP_COLOR_RED, 2);
cv::circle(img, ptValve, 3, LP_COLOR_BLUE, 3);
double startAlg = paramIn.nStartOffset*1.0 / 10;
double endAlg = angle * 1.0 / 10;
if (startAlg < endAlg)
{
cv::ellipse(img, paramIn.ptCenter, Size(150, 150), 0, 360-startAlg, 360-endAlg,Scalar(255,0,255),2);
}
else {
cv::ellipse(img, paramIn.ptCenter, Size(150, 150), 0, 0, -endAlg, Scalar(255, 0, 255), 2);
cv::ellipse(img, paramIn.ptCenter, Size(150, 150), 0, 0, 360-startAlg, Scalar(255, 0, 255), 2);
}
}
cv::circle(img, paramIn.ptCenter, 3, LP_COLOR_BLUE, 2);
if (paramIn.nCenterAlg == 1)
{
cv::circle(img, paramIn.originalPoint, 3, LP_COLOR_GREEN, 2);
}
}
double ValveDetector::ruleData(double dAngle, int nType)
{
if (0 != nType) {
dAngle = 361;
}
if (dAngle < 0) {
dAngle += 360.0;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int r = rand() % 100;
double dr = r / 4000.0;
dAngle += dr;
if (dAngle >= 359.99 && dAngle < 360.0)
{
dAngle += 0.01;
}
if (dAngle < 361.0 && dAngle >= 360.0)
{
dAngle -= 360;
}
return dAngle;
}
QString ValveDetector::genResultTip(QString str, int nType)
{
if (nType & 0x0001) {
// no image
str += "no image; ";
}
if (nType & 0x0002) {
// no obj
str += "no obj; ";
}
if (nType & 0x0004) {
// lost calibrate info
str += "no cali info; ";
}
if (nType & 0x0008) {
// less than score th
str += "less than scoreTh; ";
}
if (nType &0x0010)
{
str += "model is not matched; ";
}
return str;
}
cv::Point2f ValveDetector::getCenter(Mat & imgSrc, Point2f pt, InputParam &paramIn)
{
if (0 == paramIn.nCenterAlg) {
return pt;
}
Mat imgBinary;
int nOffset = 80; //need
Mat imgRoi;
imgSrc(Rect(pt.x - nOffset, pt.y - nOffset, 2 * nOffset, 2 * nOffset)).copyTo(imgRoi);
cv::threshold(imgRoi, imgBinary, 40, 255.0, THRESH_BINARY_INV);
vector<vector<Point>> con;
Rect rect = Rect(0, 0, imgBinary.cols, imgBinary.rows);
if (rect.width > imgBinary.cols || rect.height > imgBinary.rows)
return pt;
cv::rectangle(imgBinary, rect, Scalar(255), 1);
cv::findContours(imgBinary.clone(), con, RETR_EXTERNAL, CHAIN_APPROX_NONE);
bool bFind = false;
Point2f ptNew;
for (int i = 0; i < con.size(); i++) {
const vector<Point>& c = con.at(i);
if (c.size() < 20) {
continue;
}
Rect rt = boundingRect(c);
if (abs(rt.width - rt.height) > 5) {
continue;
}
int nArea = luffy_blob::getArea(imgBinary.size(), c);
double r = (rt.width + rt.height) / 4.0;
double d = nArea / r /r;
if (d < 2.5) {
continue;
}
bFind = true;
ptNew.x = rt.x + rt.width / 2.0 + pt.x - nOffset;
ptNew.y = rt.y + rt.height / 2.0 + pt.y - nOffset;
}
if (bFind) {
return ptNew;
}
return pt;
}
/*
void ValveDetector::drawToImage(Mat &img, InputParam &paramIn, OutputParam &paramOut)
{
if (img.empty())
{
return;
}
QString strObj = paramIn.strObj;
QString str = "type: " + (strObj.isEmpty() ? "no type" : strObj);
putText(img, str.toLatin1().data(), Point(10, 100), 3, 3, LP_COLOR_RED, 3);
QString strAngle;
if (!paramOut.bIsFind) {
strAngle = "result: can not find valve";
}
else {
strAngle = "result: " + QString::number(paramOut.dAngleRes, 'f', 2);
}
putText(img, strAngle.toLatin1().data(), Point(10, 200), 3, 3, LP_COLOR_RED, 3);
QString strScore;
QString strComp = ">";
if (paramOut.nErrorType & 0x08) {
strComp = "<";
}
strScore = "score=" + QString::number((paramOut.dScore)*100.0, 'f', 2) + "%" + strComp + QString::number(paramIn.dScoreThres, 'f', 2) + "%";
putText(img, strScore.toLatin1().data(), Point(10, 400), 3, 3, LP_COLOR_RED, 3);
str = "time: " + QString::number((int)paramOut.dTime) + "ms";
putText(img, str.toLatin1().data(), Point(10, 300), 3, 3, LP_COLOR_RED, 3);
str = "errorType: " + QString::number(paramOut.nErrorType);
putText(img, str.toLatin1().data(), Point(10, 500), 3, 3, LP_COLOR_RED, 3);
if (paramOut.bIsFind) {
//<! base line
luffy_base::luffy_triangle::createNewTrigValue(paramIn.nMaxAngle);
int tmpX2 = paramIn.ptCenter.x + paramIn.fValveDis * luffy_base::luffy_triangle::getCos(paramIn.nMaxAngle, paramIn.nValveOffset);
int tmpY2 = paramIn.ptCenter.y - paramIn.fValveDis * luffy_base::luffy_triangle::getSin(paramIn.nMaxAngle, paramIn.nValveOffset);
Point ptValveBase(tmpX2, tmpY2);
cv::line(img, paramIn.ptCenter, ptValveBase, LP_COLOR_GREEN, 2);
//cv::circle(img, paramIn.ptCenter, paramIn.fValveDis, LP_COLOR_GREEN, 2);
//cv::circle(img, ptValveBase, paramIn.fValveWidth, LP_COLOR_GREEN, 2);
cv::circle(img, ptValveBase, 3, LP_COLOR_GREEN, 3);
//<! result line
cv::line(img, paramIn.ptCenter, paramOut.rstPoint, LP_COLOR_RED, 2);
cv::circle(img, paramOut.rstPoint, paramIn.fValveWidth, LP_COLOR_RED, 2);
cv::circle(img, paramOut.rstPoint, 3, LP_COLOR_BLUE, 3);
}
cv::circle(img, paramIn.ptCenter, 3, LP_COLOR_BLUE, 2);
}
*/