1、优化旧lpengine模块中的解决方案管理流程
parent
5922b42a1e
commit
9acbdfb7e8
Binary file not shown.
@ -0,0 +1,79 @@
|
||||
#include "algEg.h"
|
||||
#include "caliCenter.h"
|
||||
#include "qtcvutils.h"
|
||||
|
||||
using namespace luffy_base;
|
||||
algEg::algEg()
|
||||
{
|
||||
}
|
||||
|
||||
algEg::~algEg()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool algEg::Exec(IDetectorTask *lpTask, IDetectorAlgorithm* lpAlgorithm)
|
||||
{
|
||||
qDebug() << "start cali center";
|
||||
//<! detect
|
||||
CaliCenter m_objDetect;
|
||||
InputParam paramInput;
|
||||
OutputParam paramOutput;
|
||||
paramInput.roi = lpAlgorithm->GetParamValue("ROI", LP_ROI).value<LP_DETECTOR_ROI_DATA>();
|
||||
int nID = lpTask->GetTaskInfo()->nCameraID;
|
||||
|
||||
Mat gray;
|
||||
if (!lpTask->GetTaskInfo()->detectImg.empty()) {
|
||||
luffy_imageProc::createImage(lpTask->GetTaskInfo()->detectImg, gray, luffy_imageProc::emCreateGray);
|
||||
}
|
||||
|
||||
if (gray.empty()) {
|
||||
qWarning() << "cali center, gray is empty";
|
||||
return false;
|
||||
}
|
||||
if (gray.size() != paramInput.roi.img.size())
|
||||
{
|
||||
qWarning() << "img size not compare";
|
||||
return false;
|
||||
}
|
||||
Mat mask;
|
||||
luffy_imageProc::createImage(gray, mask, luffy_imageProc::emCreateColor);
|
||||
m_objDetect.detect(gray, paramInput, paramOutput, mask);
|
||||
QPointF pt(paramOutput.ptCenter.x, paramOutput.ptCenter.y);
|
||||
lpAlgorithm->SetOutParamValue("center", pt);
|
||||
lpAlgorithm->SetOutParamValue("image", EngineBase::convMat2QImage(mask));
|
||||
QVariant getCenterRoi;
|
||||
getCenterRoi.setValue(paramOutput.centerRoi);
|
||||
lpAlgorithm->SetOutParamValue("centerRoi", getCenterRoi);
|
||||
qDebug() << "finish cali center";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool algEg::Init(IDetectorTask *lpTask, IDetectorAlgorithm* lpAlgorithm)
|
||||
{
|
||||
LP_ALGORITHM_PARAM param1("ROI", LP_ROI, QVariant(), QObject::tr("圆心模板"));
|
||||
lpAlgorithm->AddParam(¶m1, 1);
|
||||
|
||||
LP_ALGORITHM_PARAM param2("center", LP_POINTF);
|
||||
lpAlgorithm->AddOutParam(¶m2, 1);
|
||||
|
||||
LP_ALGORITHM_PARAM param3("image", LP_IMAGE);
|
||||
lpAlgorithm->AddOutParam(¶m3, 1);
|
||||
|
||||
LP_ALGORITHM_PARAM param4("centerRoi", LP_MAT);
|
||||
lpAlgorithm->AddOutParam(¶m4, 1);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LpAlgoNewInstance(IAlgo** lppAlgo)
|
||||
{
|
||||
*lppAlgo = (IAlgo*)new algEg();
|
||||
}
|
||||
|
||||
bool LpAlgoDeleteInstance()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
#ifndef _ALG_EG_H_
|
||||
#define _ALG_EG_H_
|
||||
|
||||
#include ".\lpbengine.h"
|
||||
#include ".\lpalgorithm.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class algEg : IAlgo
|
||||
{
|
||||
public:
|
||||
algEg();
|
||||
~algEg();
|
||||
virtual bool Exec(IDetectorTask *lpTask, IDetectorAlgorithm* lpAlgorithm);
|
||||
virtual bool Init(IDetectorTask *lpTask, IDetectorAlgorithm* lpAlgorithm);
|
||||
private:
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // _ALG_EG_H_
|
||||
@ -0,0 +1,12 @@
|
||||
#ifndef _ALG_EG_GLOBAL_H_
|
||||
#define _ALG_EG_GLOBAL_H_
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifdef ALG_EG_LIB
|
||||
# define ALG_EG_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define ALG_EG_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // _ALG_EG_GLOBAL_H_
|
||||
@ -0,0 +1,29 @@
|
||||
#ifndef LP_VALVE_DETECTOR_H
|
||||
#define LP_VALVE_DETECTOR_H
|
||||
|
||||
|
||||
#include "Luffy.h"
|
||||
#include "lpbengine.h"
|
||||
using namespace luffy_base;
|
||||
|
||||
struct InputParam
|
||||
{
|
||||
LP_DETECTOR_ROI_DATA roi;
|
||||
};
|
||||
|
||||
struct OutputParam
|
||||
{
|
||||
Point2f ptCenter;
|
||||
Mat centerRoi;
|
||||
};
|
||||
|
||||
class CaliCenter
|
||||
{
|
||||
public:
|
||||
CaliCenter();
|
||||
~CaliCenter();
|
||||
|
||||
bool detect(Mat & imgSrc, InputParam ¶mIn, OutputParam ¶mOut, Mat &imgDst = Mat());
|
||||
};
|
||||
|
||||
#endif //LP_VALVE_DETECTOR_H
|
||||
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;cxx;c;def</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Form Files">
|
||||
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
|
||||
<Extensions>ui</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||
<Extensions>qrc;*</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
|
||||
<Extensions>moc;h;cpp</Extensions>
|
||||
<SourceControlFiles>False</SourceControlFiles>
|
||||
</Filter>
|
||||
<Filter Include="Translation Files">
|
||||
<UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier>
|
||||
<Extensions>ts</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="algEg.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="caliCenter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="algEg.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="algEg_global.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="caliCenter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="calicenter_en.ts">
|
||||
<Filter>Translation Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -0,0 +1,23 @@
|
||||
#ifndef _ALG_EG_H_
|
||||
#define _ALG_EG_H_
|
||||
|
||||
#include ".\lpbengine.h"
|
||||
#include ".\lpalgorithm.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class algEg : IAlgo
|
||||
{
|
||||
public:
|
||||
algEg();
|
||||
virtual ~algEg();
|
||||
virtual bool Exec(IDetectorTask *lpTask, IDetectorAlgorithm* lpAlgorithm);
|
||||
virtual bool Init(IDetectorTask *lpTask, IDetectorAlgorithm* lpAlgorithm);
|
||||
private:
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // _ALG_EG_H_
|
||||
@ -0,0 +1,12 @@
|
||||
#ifndef _ALG_EG_GLOBAL_H_
|
||||
#define _ALG_EG_GLOBAL_H_
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifdef ALG_EG_LIB
|
||||
# define ALG_EG_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define ALG_EG_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // _ALG_EG_GLOBAL_H_
|
||||
@ -0,0 +1,502 @@
|
||||
#include "CaliValve.h"
|
||||
#define VIEW_INTERNAL_MAT
|
||||
using namespace luffy_base;
|
||||
CaliValve::CaliValve()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CaliValve::~CaliValve()
|
||||
{
|
||||
}
|
||||
double disOfPoint(const Point2f& p1, const Point2f& p2)
|
||||
{
|
||||
return norm(p1 - p2);
|
||||
}
|
||||
void CaliValve::preProcessImage(Mat& img, const Mat& mask, double dstMean, double dstStddev, int highlightsThreshold)
|
||||
{
|
||||
|
||||
if (img.type() != CV_32FC1)
|
||||
{
|
||||
img.convertTo(img, CV_32FC1);
|
||||
}
|
||||
|
||||
Mat gaussImg;
|
||||
GaussianBlur(img, gaussImg, Size(3, 3), 5.0);
|
||||
img = gaussImg;
|
||||
|
||||
Mat dilatedMask;
|
||||
dilate(mask, dilatedMask, Mat::ones(Size(3, 3), CV_32FC1));
|
||||
Mat hightlightsMask = img < highlightsThreshold;
|
||||
Mat imgMask = hightlightsMask & (mask > 0);
|
||||
|
||||
Scalar meanScalar, stddevScalar;
|
||||
meanStdDev(img, meanScalar, stddevScalar, imgMask);
|
||||
img = (img - meanScalar.val[0]) * dstStddev / stddevScalar.val[0] + dstMean;
|
||||
imgMask.convertTo(imgMask, CV_32FC1);
|
||||
imgMask /= 255.0;
|
||||
Mat imgNorm = cocentricNorm(img, Point2f(img.cols / 2.0, img.rows / 2.0),
|
||||
imgMask, 125);
|
||||
#ifdef DEBUG_VIEW_INTERNAL_MAT
|
||||
Mat vImgNorm = imgNorm / 255.0;
|
||||
#endif
|
||||
img = imgNorm;
|
||||
}
|
||||
|
||||
cv::Mat CaliValve::genMask(const Mat& img, Point2f center, float innerR /*= -1*/, float outterR /*= -1*/, int type /*= CV_32FC1*/)
|
||||
{
|
||||
Mat mask(img.size(), CV_8UC1);
|
||||
mask.setTo(0);
|
||||
if (innerR == -1)
|
||||
{
|
||||
// default is 30
|
||||
innerR = img.rows*0.178;
|
||||
}
|
||||
if (outterR == -1)
|
||||
{
|
||||
// default is max radius - 10
|
||||
outterR = img.rows*0.425;
|
||||
}
|
||||
circle(mask, center, outterR, Scalar(255), -1);
|
||||
circle(mask, center, innerR, Scalar(0), -1);
|
||||
if (type != CV_8UC1)
|
||||
{
|
||||
mask.convertTo(mask, type);
|
||||
mask /= 255;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
cv::Mat CaliValve::cocentricNorm(Mat& img, Point2f center, const Mat& weightMat, float dstMeanVal)
|
||||
{
|
||||
assert(weightMat.empty() || weightMat.type() == CV_32FC1);
|
||||
|
||||
int w = img.cols;
|
||||
int h = img.rows;
|
||||
vector<Point2f> corners;
|
||||
corners.push_back(Point2f(0, 0));
|
||||
corners.push_back(Point2f(0, h));
|
||||
corners.push_back(Point2f(w, h));
|
||||
corners.push_back(Point2f(w, 0));
|
||||
vector<double> cornerDisVec;
|
||||
for_each(corners.begin(), corners.end(), [&](const Point2f& pt)
|
||||
{
|
||||
double dis = disOfPoint(center, pt);
|
||||
cornerDisVec.push_back(dis);
|
||||
});
|
||||
|
||||
auto farthestCornerDis = max_element(cornerDisVec.begin(), cornerDisVec.end());
|
||||
float maxRadius = *farthestCornerDis;
|
||||
|
||||
int radiusNum = floorf(maxRadius);
|
||||
//radiusNum = 20;
|
||||
float radiusStep = (maxRadius / radiusNum);
|
||||
Mat cocentricSumMat = Mat::zeros(1, radiusNum, CV_32FC1);
|
||||
float* pSumData = (float*)cocentricSumMat.data;
|
||||
Mat cocentricWeightSumMat = Mat::zeros(1, radiusNum, CV_32FC1);
|
||||
float* pWeightSumData = (float*)cocentricWeightSumMat.data;
|
||||
Mat radiusMat(img.rows, img.cols, CV_32FC1);
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
const Mat& imgRow = img.row(y);
|
||||
float* pImgRowData = (float*)imgRow.data;
|
||||
float* pRadiusRowData = (float*)radiusMat.row(y).data;
|
||||
|
||||
float* pWeightRowData = NULL;
|
||||
if (!weightMat.empty())
|
||||
{
|
||||
pWeightRowData = (float*)weightMat.row(y).data;
|
||||
}
|
||||
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
//std::cout << x << " " << y << std::endl;
|
||||
float weight;
|
||||
if (pWeightRowData)
|
||||
{
|
||||
weight = pWeightRowData[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
weight = 1.0;
|
||||
}
|
||||
float val = pImgRowData[x] * weight;
|
||||
float radius = disOfPoint(Point2f(x, y), center);
|
||||
pRadiusRowData[x] = radius;
|
||||
int radiusIdx0 = (int)(radius / radiusStep);
|
||||
assert(radiusIdx0 >= 0);
|
||||
int radiusIdx1 = radiusIdx0 + 1;
|
||||
if (radiusIdx0 >= radiusNum - 1)
|
||||
{
|
||||
pSumData[radiusNum - 1] += val;
|
||||
pWeightSumData[radiusNum - 1] += weight;
|
||||
}
|
||||
else
|
||||
{
|
||||
float s = (radius - radiusStep*radiusIdx0) / radiusStep;
|
||||
pSumData[radiusIdx0] += val*s;
|
||||
pSumData[radiusIdx1] += val*(1 - s);
|
||||
pWeightSumData[radiusIdx0] += s*weight;
|
||||
pWeightSumData[radiusIdx1] += (1 - s)*weight;
|
||||
}
|
||||
}
|
||||
// CvPlot::plot<float>("sum", pSumData, radiusNum);
|
||||
// CvPlot::plot<float>("count", pCountData, radiusNum);
|
||||
// waitKey();
|
||||
}
|
||||
|
||||
for (int i = 0; i < radiusNum; ++i)
|
||||
{
|
||||
//float radius = (i*radiusStep + radiusStep) / 2;
|
||||
if (pWeightSumData[i] == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
pSumData[i] /= pWeightSumData[i];
|
||||
}
|
||||
}
|
||||
|
||||
Mat retMat = Mat::zeros(img.rows, img.cols, img.type());
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
float* pImgRowData = (float*)img.row(y).data;
|
||||
float* pRetRowData = (float*)retMat.row(y).data;
|
||||
float* pRadiusData = (float*)radiusMat.row(y).data;
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
float val = pImgRowData[x];
|
||||
float radius = pRadiusData[x];
|
||||
float mean = interpolate(pSumData, radiusNum, radiusStep, radius);
|
||||
if (mean == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
float newVal = (float)val * dstMeanVal / mean;
|
||||
pRetRowData[x] = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
return retMat;
|
||||
}
|
||||
|
||||
float CaliValve::interpolate(float* pY, int n, float stepX, float x)
|
||||
{
|
||||
int lIdx = (int)(x / stepX);
|
||||
int rIdx = lIdx + 1;
|
||||
if (rIdx > n - 1)
|
||||
{
|
||||
return pY[n - 1];
|
||||
}
|
||||
assert(lIdx >= 0 && lIdx < n && rIdx >= 0 && rIdx < n);
|
||||
float s = (x - lIdx*stepX) / stepX;
|
||||
float ly = pY[lIdx];
|
||||
float ry = pY[rIdx];
|
||||
return ly + (ry - ly)*s;
|
||||
}
|
||||
|
||||
|
||||
Mat CaliValve::extractForegroundWheel(const Mat &background, const Mat &src)
|
||||
{
|
||||
Mat resizedGroundImage = background.clone();
|
||||
if (resizedGroundImage.size() != src.size())
|
||||
{
|
||||
resize(background, resizedGroundImage, src.size());
|
||||
}
|
||||
|
||||
return (src - resizedGroundImage);
|
||||
}
|
||||
|
||||
Mat CaliValve::findWheelObject(Mat src, Mat backGroundImg, int thresh)
|
||||
{
|
||||
|
||||
|
||||
if (src.empty() || backGroundImg.empty() || src.cols < 500)
|
||||
{
|
||||
return Mat();
|
||||
}
|
||||
assert(backGroundImg.type() == CV_8UC1);
|
||||
const cv::Size size = cv::Size(416, floor(416.0 / src.cols * src.rows));
|
||||
Mat resizedImage;
|
||||
resizedImage.setTo(0);
|
||||
resize(src, resizedImage, size);
|
||||
Mat foregroundImg = extractForegroundWheel(backGroundImg, resizedImage);
|
||||
using namespace luffy_base;
|
||||
Mat imgBinary;
|
||||
imgBinary.setTo(0);
|
||||
luffy_threshold::Threshold(foregroundImg, imgBinary, thresh);//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));
|
||||
//openOper(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(size.width / 2, size.height / 2), 0, size.width / 2, 360, luffy_hit::emHitOut2In);
|
||||
|
||||
//luffy_imageProc::RansacParam rs(0.02, 2.5, 70, 100, 220);
|
||||
luffy_imageProc::RansacParam rs(0.01, 3, 150, 100, 240);//0421
|
||||
vector<Point> pts2 = luffy_imageProc::fitModelbyRansac(pts, luffy_imageProc::emModelCircle, &rs);
|
||||
#ifdef _DEBUG
|
||||
Mat imgColor;
|
||||
cv::cvtColor(resizedImage, 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);
|
||||
|
||||
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, resizedImage.cols, resizedImage.rows);
|
||||
resizedImage(rt).copyTo(dst);
|
||||
Mat finalDst(dst.size(), dst.type(), Scalar::all(0));
|
||||
cv::circle(finalDst, Point(finalDst.cols / 2, finalDst.rows / 2), fRadius, Scalar::all(1), -1);
|
||||
dst = dst.mul(finalDst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool CaliValve::cutValve(Mat & img2Rect, Mat &imgTemplate, Rect rtCut, int nAngleMax)
|
||||
{
|
||||
if (rtCut.x < 0) {
|
||||
imgTemplate.create(Size(rtCut.width, rtCut.height), img2Rect.type());
|
||||
Rect rtLeft(nAngleMax + rtCut.x, rtCut.y, -rtCut.x, rtCut.height);
|
||||
Rect rtRight(0, rtCut.y, rtCut.width - rtLeft.width, rtCut.height);
|
||||
|
||||
img2Rect(rtLeft).copyTo(imgTemplate(Rect(0, 0, rtLeft.width, rtLeft.height)));
|
||||
img2Rect(rtRight).copyTo(imgTemplate(Rect(rtLeft.width, 0, rtRight.width, rtLeft.height)));
|
||||
return true;
|
||||
}
|
||||
else if (rtCut.x + rtCut.width >= nAngleMax) {
|
||||
imgTemplate.create(Size(rtCut.width, rtCut.height), img2Rect.type());
|
||||
|
||||
Rect rtLeft(rtCut.x, rtCut.y, nAngleMax-rtCut.x, rtCut.height);
|
||||
Rect rtRight(0, rtCut.y, rtCut.width - rtLeft.width, rtCut.height);
|
||||
|
||||
img2Rect(rtLeft).copyTo(imgTemplate(Rect(0, 0, rtLeft.width, rtLeft.height)));
|
||||
img2Rect(rtRight).copyTo(imgTemplate(Rect(rtLeft.width, 0, rtRight.width, rtLeft.height)));
|
||||
return true;
|
||||
}
|
||||
|
||||
luffy_math::checkRoiRect(Size(img2Rect.cols, img2Rect.rows), rtCut);
|
||||
img2Rect(rtCut).copyTo(imgTemplate);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool CaliValve::detect(Mat & imgSrc, InputParam ¶mIn, OutputParam ¶mOut, Mat &imgDst /*= Mat()*/)
|
||||
{
|
||||
Record_List records = paramIn.roi.records;
|
||||
Record_List barRecords = paramIn.barROI.records;
|
||||
int nCircleCount = records.size();
|
||||
int barCircleCount = barRecords.size();
|
||||
if (nCircleCount == 0 && barCircleCount ==0) {
|
||||
return false;
|
||||
}
|
||||
luffy_base::luffyCircle realCircle;
|
||||
realCircle.ptCenter = Point2f(0, 0);
|
||||
realCircle.fRadius = 10000000000000.0;
|
||||
for (int i = 0; i < nCircleCount; i++) {
|
||||
Item_List item = records.at(i);
|
||||
Feature_List feature = item.at(0);
|
||||
|
||||
if (1 == feature.first) {
|
||||
int size = feature.second.size();
|
||||
if (size < 3)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Point2f p = Point2f(feature.second.at(0), feature.second.at(1));
|
||||
float r = abs(feature.second.at(2));
|
||||
if (r < realCircle.fRadius)
|
||||
{
|
||||
realCircle.fRadius = r;
|
||||
realCircle.ptCenter = p;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
luffy_base::luffyCircle barCircle;
|
||||
for (int i = 0; i < barCircleCount; i++) {
|
||||
Item_List circleItem = barRecords.at(i);
|
||||
Feature_List circleFeature = circleItem.at(0);
|
||||
|
||||
if (1 == circleFeature.first) {
|
||||
int size = circleFeature.second.size();
|
||||
if (size < 3)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
barCircle.ptCenter = Point2f(circleFeature.second.at(0), circleFeature.second.at(1));
|
||||
barCircle.fRadius = abs(circleFeature.second.at(2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cv::circle(imgDst, realCircle.ptCenter, realCircle.fRadius, LP_COLOR_RED, 2);
|
||||
cv::circle(imgDst, realCircle.ptCenter, 2, LP_COLOR_BLUE, 2);
|
||||
cv::circle(imgDst, barCircle.ptCenter, barCircle.fRadius, LP_COLOR_RED, 2);
|
||||
cv::circle(imgDst, barCircle.ptCenter, 2, LP_COLOR_BLUE, 2);
|
||||
cv::circle(imgDst, paramIn.ptCenter, 2, LP_COLOR_RED, 2);
|
||||
|
||||
float fRadius = luffy_math::disofPoints(realCircle.ptCenter, paramIn.ptCenter);
|
||||
int offset = 30;
|
||||
int nImgHeight = realCircle.fRadius * 2 + 2 * offset;
|
||||
Mat img2Rect;
|
||||
luffy_math::polar2rect(imgSrc, img2Rect, paramIn.ptCenter,
|
||||
fRadius - nImgHeight / 2, fRadius + nImgHeight / 2, paramIn.nAngleMax);
|
||||
|
||||
|
||||
if (paramIn.flagCircle > 0)
|
||||
{
|
||||
qWarning() << "outPut param flagCircle :" << paramIn.flagCircle;
|
||||
paramOut.nValveOffset = luffy_math::caculAngle(paramIn.ptCenter, barCircle.ptCenter) / 360.0 * paramIn.nAngleMax;
|
||||
Rect rTargetRoi(paramOut.nValveOffset - barCircle.fRadius, offset, 2 * barCircle.fRadius, 2 * realCircle.fRadius);
|
||||
cutValve(img2Rect, paramOut.barTemplate, rTargetRoi, paramIn.nAngleMax);
|
||||
paramOut.fValveWidth = realCircle.fRadius;
|
||||
paramOut.fValveDis = fRadius;
|
||||
paramOut.withinOffset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//<! cut valve
|
||||
qWarning() << "outPut param flagCircle :" << paramIn.flagCircle;
|
||||
paramOut.nValveOffset = luffy_math::caculAngle(paramIn.ptCenter, realCircle.ptCenter) / 360.0 * paramIn.nAngleMax;
|
||||
float barCircleOffset = luffy_math::caculAngle(paramIn.ptCenter, barCircle.ptCenter) / 360 * paramIn.nAngleMax;
|
||||
|
||||
Rect rbarRoi(barCircleOffset - barCircle.fRadius, offset, 2 * barCircle.fRadius, 2 * realCircle.fRadius);
|
||||
Rect rtRoi(paramOut.nValveOffset - realCircle.fRadius, offset, 2 * realCircle.fRadius, 2 * realCircle.fRadius);
|
||||
cutValve(img2Rect, paramOut.imgTemplate, rtRoi, paramIn.nAngleMax);
|
||||
cutValve(img2Rect, paramOut.barTemplate, rbarRoi, paramIn.nAngleMax);
|
||||
|
||||
if (paramIn.barNum <= 0)
|
||||
{
|
||||
qWarning() << "barNum cannot be negative or ZERO";
|
||||
return false;
|
||||
}
|
||||
|
||||
int T = paramIn.nAngleMax / paramIn.barNum;
|
||||
if ((paramOut.nValveOffset - barCircleOffset > -T && paramOut.nValveOffset - barCircleOffset < 0) ||
|
||||
(paramOut.nValveOffset - barCircleOffset >(paramIn.barNum - 1) * T)
|
||||
)
|
||||
{
|
||||
barCircleOffset = barCircleOffset - T;
|
||||
}
|
||||
|
||||
int interval = luffy_math::mod(paramOut.nValveOffset - barCircleOffset, paramIn.nAngleMax);
|
||||
paramOut.withinOffset = interval;
|
||||
paramOut.fValveWidth = realCircle.fRadius;
|
||||
paramOut.fValveDis = fRadius;
|
||||
}
|
||||
|
||||
///////for test
|
||||
//
|
||||
//Mat circleRoi;
|
||||
//float startx = realCircle.ptCenter.x - realCircle.fRadius;
|
||||
//float starty = realCircle.ptCenter.y - realCircle.fRadius;
|
||||
//imgSrc(Rect(startx, starty, realCircle.fRadius * 2, realCircle.fRadius * 2)).copyTo(circleRoi);
|
||||
//paramOut.imgTemplate = circleRoi;
|
||||
if (paramIn.ifClasify)
|
||||
{
|
||||
Mat grayImage;
|
||||
grayImage.setTo(0);
|
||||
colorConvert(paramOut.background, grayImage);
|
||||
Mat gray = imgSrc.clone();
|
||||
Mat foreGround = findWheelObject(gray, grayImage, paramIn.backgroundThresh);
|
||||
if (foreGround.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int repeatNum = paramIn.barNum;
|
||||
Mat weightMat(foreGround.size(), foreGround.type());
|
||||
selfRotateMin(foreGround, weightMat, repeatNum);
|
||||
Mat mask = genMask(foreGround, Point(foreGround.cols / 2, foreGround.rows / 2), -1, -1, CV_32FC1);
|
||||
weightMat.convertTo(weightMat, CV_32FC1);
|
||||
weightMat = weightMat.mul(mask);
|
||||
weightMat.setTo(0, weightMat < 20);
|
||||
preProcessImage(foreGround, mask, 127.0, 20.0, 256);
|
||||
#ifdef VIEW_INTERNAL_MAT
|
||||
Mat m_weightMat = weightMat / 255.0;
|
||||
Mat baseImage = foreGround / 255.0;
|
||||
#endif
|
||||
paramOut.baseImage = foreGround;
|
||||
paramOut.weightMat = weightMat;
|
||||
paramOut.background = grayImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
paramOut.baseImage = Mat();
|
||||
paramOut.weightMat = Mat();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CaliValve::selfRotateMin(const Mat& src, Mat &dst, int repeatNum)
|
||||
{
|
||||
Point2f center(src.cols / 2.0, src.rows / 2.0);
|
||||
float angleStep = 360.0 / repeatNum;
|
||||
Mat dstMat = Mat::ones(src.size(), src.type())*255;
|
||||
for (int i = 0; i < repeatNum; ++i)
|
||||
{
|
||||
Mat rotateParamMat = getRotationMatrix2D(center, angleStep*i, 1.0);
|
||||
Mat rImg;
|
||||
warpAffine(src, rImg, rotateParamMat, src.size(), INTER_CUBIC, BORDER_CONSTANT);
|
||||
Mat dialitedMat;
|
||||
dilate(rImg, dialitedMat, Mat::ones(3, 3, CV_32FC1));
|
||||
dstMat = min(dstMat, dialitedMat);
|
||||
}
|
||||
dst = dstMat;
|
||||
}
|
||||
|
||||
|
||||
void CaliValve::colorConvert(const Mat& src, Mat & dst)
|
||||
{
|
||||
if (src.channels() == 1)
|
||||
{
|
||||
dst = src.clone();
|
||||
}
|
||||
else if (src.channels() == 3)
|
||||
{
|
||||
cvtColor(src, dst, CV_RGB2GRAY);
|
||||
}
|
||||
else if (src.channels() == 4)
|
||||
{
|
||||
cvtColor(src, dst, CV_RGBA2GRAY);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
#ifndef LP_VALVE_DETECTOR_H
|
||||
#define LP_VALVE_DETECTOR_H
|
||||
#include "Luffy.h"
|
||||
#include "lpbengine.h"
|
||||
|
||||
using namespace luffy_base;
|
||||
|
||||
struct InputParam
|
||||
{
|
||||
LP_DETECTOR_ROI_DATA roi;
|
||||
LP_DETECTOR_ROI_DATA barROI;
|
||||
int flagCircle;
|
||||
|
||||
Point2f ptCenter;
|
||||
int barNum;
|
||||
const int nAngleMax = 3600;
|
||||
int backgroundThresh;
|
||||
int ifClasify;
|
||||
int ibackground;
|
||||
};
|
||||
|
||||
struct OutputParam
|
||||
{
|
||||
float fValveDis;
|
||||
float fValveWidth;
|
||||
Mat imgTemplate;
|
||||
int nValveOffset;
|
||||
Mat barTemplate;
|
||||
int withinOffset;
|
||||
int barNum;
|
||||
int flagCircle;
|
||||
Mat baseImage;
|
||||
Mat background;
|
||||
Mat weightMat;
|
||||
};
|
||||
|
||||
class CaliValve
|
||||
{
|
||||
public:
|
||||
CaliValve();
|
||||
~CaliValve();
|
||||
|
||||
bool detect(Mat & imgSrc, InputParam ¶mIn, OutputParam ¶mOut, Mat &imgDst = Mat());
|
||||
bool cutValve(Mat & img2Rect, Mat &imgTemplate, Rect rtCut, int nAngleMax);
|
||||
void preProcessImage(Mat& img, const Mat& mask, double dstMean, double dstStddev, int highlightsThreshold);
|
||||
Mat genMask(const Mat& img, Point2f center, float innerR = -1,
|
||||
float outterR = -1,
|
||||
int type = CV_32FC1);
|
||||
cv::Mat cocentricNorm(Mat& img, Point2f center, const Mat& weightMat, float dstMeanVal);
|
||||
float interpolate(float* pY, int n, float stepX, float x);
|
||||
Mat extractForegroundWheel(const Mat& background, const Mat& src);
|
||||
Mat findWheelObject(Mat src, Mat backGroundImg, int thresh);
|
||||
void selfRotateMin(const Mat& src, Mat &dst, int repeatNum);
|
||||
Mat rotateImage(const Mat& img, Point2f center, float degree);
|
||||
void colorConvert(const Mat& src, Mat & dst);
|
||||
};
|
||||
|
||||
#endif //LP_VALVE_DETECTOR_H
|
||||
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;cxx;c;def</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Form Files">
|
||||
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
|
||||
<Extensions>ui</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||
<Extensions>qrc;*</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
|
||||
<Extensions>moc;h;cpp</Extensions>
|
||||
<SourceControlFiles>False</SourceControlFiles>
|
||||
</Filter>
|
||||
<Filter Include="Translation Files">
|
||||
<UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier>
|
||||
<Extensions>ts</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="algEg.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="caliValve.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="algEg.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="algEg_global.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="caliValve.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="calivalve_en.ts">
|
||||
<Filter>Translation Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -0,0 +1,104 @@
|
||||
#include "BatchTest4Alg.h"
|
||||
#include "cv.h"
|
||||
#include "highgui.h"
|
||||
#include "Luffy.h"
|
||||
#include "qstringlist.h"
|
||||
#include "qfile.h"
|
||||
#include "qdatetime.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
struct Region {
|
||||
cv::Scalar color;
|
||||
int id;
|
||||
std::vector<cv::Point2i> points;
|
||||
void write(cv::FileStorage& fs) const {
|
||||
fs << "{" << "id" << id << "points" << points << "}";
|
||||
}
|
||||
void read(const cv::FileNode& node) {
|
||||
//node["color"] >> color;
|
||||
node["id"] >> id;
|
||||
node["points"] >> points;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::vector<std::vector<cv::Point>> read_points_info(std::string path) {
|
||||
cv::FileStorage fs;
|
||||
fs.open(path, cv::FileStorage::READ);
|
||||
int count{ -1 };
|
||||
int id{ -1 };
|
||||
std::vector<std::vector<std::vector<cv::Point>>> regions{};
|
||||
std::vector<std::vector<cv::Point>> defect_regions{ std::vector < cv::Point > {} };
|
||||
cv::FileNode node = fs.getFirstTopLevelNode();
|
||||
std::vector<std::vector<cv::Point2i>> dst;
|
||||
while (1) {
|
||||
Region re_load;
|
||||
re_load.read(fs["region" + std::to_string(++count)]);
|
||||
//fs["region" + std::to_string(++count)] >> re_load;
|
||||
auto region = re_load.points;
|
||||
if (region.empty()) {
|
||||
if (!defect_regions.empty())regions.push_back(defect_regions);
|
||||
fs.release();
|
||||
break;
|
||||
}
|
||||
if (id != re_load.id) {
|
||||
if (id != -1)regions.push_back(defect_regions);
|
||||
while (re_load.id > int(regions.size())) {
|
||||
regions.push_back(std::vector < std::vector<cv::Point> > {std::vector < cv::Point > {}});
|
||||
}
|
||||
id = re_load.id;
|
||||
|
||||
defect_regions.clear();
|
||||
}
|
||||
dst.push_back(re_load.points);
|
||||
//defect_regions.push_back(region);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
BatchTest4Alg::BatchTest4Alg()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BatchTest4Alg::~BatchTest4Alg()
|
||||
{
|
||||
}
|
||||
|
||||
bool BatchTest4Alg::batchTest(QString strModel, Point pt, int nError, QString strBase, QString strFile)
|
||||
{
|
||||
QString m = strModel.split("##").last();
|
||||
QString str = strFile.replace(m, m + "-out");
|
||||
str = str.left(str.length() - 3) + "xml";
|
||||
Point ptCali = getCaliPosition(str);
|
||||
double dis = luffy_base::luffy_math::disofPoints(ptCali, pt);
|
||||
dis = sqrt(dis);
|
||||
return dis < 10;
|
||||
}
|
||||
|
||||
cv::Point BatchTest4Alg::getCaliPosition(QString strFile)
|
||||
{
|
||||
std::string str = strFile.toLocal8Bit().data();
|
||||
FileStorage fs(strFile.toLocal8Bit().data(), FileStorage::READ);
|
||||
if (!fs.isOpened()) {
|
||||
return Point();
|
||||
}
|
||||
vector<vector<Point>> pts = read_points_info(strFile.toLocal8Bit().data());
|
||||
if (pts.size() == 0) {
|
||||
return Point();
|
||||
}
|
||||
Rect rt = cv::boundingRect(pts[0]);
|
||||
return Point(rt.x + rt.width / 2, rt.y + rt.height / 2);
|
||||
}
|
||||
|
||||
bool BatchTest4Alg::saveResult(QString strModel, int nError, QString modelFile, QString saveFile)
|
||||
{
|
||||
QFile qFile(saveFile);
|
||||
qFile.open(QIODevice::Append | QIODevice::WriteOnly);
|
||||
QString str = "time:%1, model:%2, result:%3, file:%4\r\n";
|
||||
str = str.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh-mm-ss zzz")).arg(strModel).arg(nError).arg(modelFile);
|
||||
qFile.write(str.toLocal8Bit().data());
|
||||
qFile.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "qstring.h"
|
||||
#include "core\core.hpp"
|
||||
class BatchTest4Alg
|
||||
{
|
||||
public:
|
||||
BatchTest4Alg();
|
||||
~BatchTest4Alg();
|
||||
|
||||
static bool batchTest(QString strModel, cv::Point pt, int nError, QString strBase, QString strFile);
|
||||
static cv::Point getCaliPosition(QString strFile);
|
||||
static bool saveResult(QString strModel, int nError, QString modelFile, QString saveFile);
|
||||
};
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
#ifndef _ALG_EG_H_
|
||||
#define _ALG_EG_H_
|
||||
|
||||
#include ".\lpbengine.h"
|
||||
#include ".\lpalgorithm.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class algEg : IAlgo
|
||||
{
|
||||
public:
|
||||
algEg();
|
||||
~algEg();
|
||||
virtual bool Exec(IDetectorTask *lpTask, IDetectorAlgorithm* lpAlgorithm);
|
||||
virtual bool Init(IDetectorTask *lpTask, IDetectorAlgorithm* lpAlgorithm);
|
||||
cv::Mat background;
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // _ALG_EG_H_
|
||||
@ -0,0 +1,12 @@
|
||||
#ifndef _ALG_EG_GLOBAL_H_
|
||||
#define _ALG_EG_GLOBAL_H_
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifdef ALG_EG_LIB
|
||||
# define ALG_EG_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define ALG_EG_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // _ALG_EG_GLOBAL_H_
|
||||
@ -0,0 +1,407 @@
|
||||
#include "modelVerfication.h"
|
||||
|
||||
//#define VIEW_DEBUG_IMG
|
||||
modelVerfication::modelVerfication(double tarStddevVal, double tarMeanVal) :
|
||||
tarStddev(tarStddevVal)
|
||||
, tarMean(tarMeanVal)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
modelVerfication::~modelVerfication()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
double disOfPoint(const Point2f& p1, const Point2f& p2)
|
||||
{
|
||||
return norm(p1 - p2);
|
||||
}
|
||||
|
||||
float modelVerfication::interpolate(float* pY, int n, float stepX, float x)
|
||||
{
|
||||
int lIdx = (int)(x / stepX);
|
||||
int rIdx = lIdx + 1;
|
||||
if (rIdx > n - 1)
|
||||
{
|
||||
return pY[n - 1];
|
||||
}
|
||||
assert(lIdx >= 0 && lIdx < n && rIdx >= 0 && rIdx < n);
|
||||
float s = (x - lIdx*stepX) / stepX;
|
||||
float ly = pY[lIdx];
|
||||
float ry = pY[rIdx];
|
||||
return ly + (ry - ly)*s;
|
||||
}
|
||||
bool modelVerfication::objectVerification(const Mat &img, Mat& baseImage, double modelValidThresh, int endAngle, double & s)
|
||||
{
|
||||
int diff = abs(img.cols - baseImage.cols);
|
||||
if (diff >=5)
|
||||
{
|
||||
qDebug() << "model verification : model possibly is not match";
|
||||
s = 365;
|
||||
return false;
|
||||
}
|
||||
if (baseImage.type()!=CV_32FC1)
|
||||
{
|
||||
baseImage.convertTo(baseImage, CV_32FC1);
|
||||
}
|
||||
Mat resizedImage(baseImage.size(), baseImage.type(), Scalar::all(0));
|
||||
if (img.size()!= baseImage.size())
|
||||
{
|
||||
resize(img, resizedImage, baseImage.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
resizedImage = img;
|
||||
}
|
||||
|
||||
Mat mask = genMask(resizedImage, Point(resizedImage.cols / 2, resizedImage.rows / 2), -1, -1, CV_8UC1);
|
||||
m32fMaskImg = genMask(resizedImage, Point2f(resizedImage.cols / 2, resizedImage.rows / 2));
|
||||
preProcessImage(resizedImage, mask, tarMean, tarStddev, 256);
|
||||
RData* pData = new RData();
|
||||
rotateMatchData(resizedImage, baseImage, pData, 1, 0, endAngle);
|
||||
|
||||
double result = 0;
|
||||
Mat rstImg, showImage, Ibase;
|
||||
|
||||
if (pData->mDisValVec.empty())
|
||||
{
|
||||
delete pData;
|
||||
qDebug() << "model verification : the distance of model is empty";
|
||||
result = FLT_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bestIndex = min_element(pData->mDisValVec.begin(), pData->mDisValVec.end()) - pData->mDisValVec.begin();
|
||||
|
||||
result = pData->mDisValVec[bestIndex];
|
||||
rstImg = pData->mRImgVec[bestIndex];
|
||||
#ifdef VIEW_DEBUG_IMG
|
||||
showImage = rstImg / 255;
|
||||
Ibase = baseImage / 255;
|
||||
#endif // VIEW_DEBUG_IMG
|
||||
qDebug() << "model verification : found the minimal value model:" << result;
|
||||
delete pData;
|
||||
}
|
||||
|
||||
if (result < modelValidThresh)
|
||||
{
|
||||
qDebug() << "model verification : image is valid";
|
||||
s = result;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "model verification : image is not valid";
|
||||
s = result;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//Mat image = croppedImage / 255.0;
|
||||
}
|
||||
Mat modelVerfication::extractForegroundWheel(const Mat &background, const Mat &src)
|
||||
{
|
||||
Mat resizedGroundImage = background.clone();
|
||||
if (resizedGroundImage.size() != src.size())
|
||||
{
|
||||
resize(background, resizedGroundImage, src.size());
|
||||
}
|
||||
|
||||
return (src - resizedGroundImage);
|
||||
}
|
||||
|
||||
Mat modelVerfication::findWheelObject(Mat src, Mat backGroundImg, int thresh)
|
||||
{
|
||||
|
||||
|
||||
if (src.empty() || backGroundImg.empty() || src.cols < 500)
|
||||
{
|
||||
return Mat();
|
||||
}
|
||||
assert(backGroundImg.type() == CV_8UC1);
|
||||
const cv::Size size = cv::Size(416, floor(416.0 / src.cols * src.rows));
|
||||
Mat resizedImage;
|
||||
resizedImage.setTo(0);
|
||||
resize(src, resizedImage, size);
|
||||
Mat foregroundImg = extractForegroundWheel(backGroundImg, resizedImage);
|
||||
using namespace luffy_base;
|
||||
Mat imgBinary;
|
||||
imgBinary.setTo(0);
|
||||
luffy_threshold::Threshold(foregroundImg, imgBinary, thresh);//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));
|
||||
//openOper(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(size.width / 2, size.height / 2), 0, size.width / 2, 360, luffy_hit::emHitOut2In);
|
||||
|
||||
//luffy_imageProc::RansacParam rs(0.02, 2.5, 70, 100, 220);
|
||||
luffy_imageProc::RansacParam rs(0.01, 3, 150, 100, 240);//0421
|
||||
vector<Point> pts2 = luffy_imageProc::fitModelbyRansac(pts, luffy_imageProc::emModelCircle, &rs);
|
||||
#ifdef _DEBUG
|
||||
Mat imgColor;
|
||||
cv::cvtColor(resizedImage, 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);
|
||||
|
||||
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, resizedImage.cols, resizedImage.rows);
|
||||
resizedImage(rt).copyTo(dst);
|
||||
Mat finalDst(dst.size(), dst.type(), Scalar::all(0));
|
||||
cv::circle(finalDst, Point(finalDst.cols / 2, finalDst.rows / 2), fRadius, Scalar::all(1), -1);
|
||||
dst = dst.mul(finalDst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void ImageCompareModel2::operator()(const cv::Range& range) const
|
||||
{
|
||||
int i0 = range.start;
|
||||
int i1 = range.end;
|
||||
assert(abs(i1 - i0) == 1);
|
||||
model->parallelDetect(i0, m_pData, templ);
|
||||
}
|
||||
|
||||
void modelVerfication::parallelDetect(int index, void *p, Mat templ)
|
||||
{
|
||||
RData *pData = (RData *)p;
|
||||
Mat t = getRotationMatrix2D(pData->mCenter, pData->angle(index), 1.0);
|
||||
Mat rImg;
|
||||
warpAffine(pData->mImgSrc, rImg, t, pData->mImgSrc.size());
|
||||
if (rImg.size() != templ.size())
|
||||
{
|
||||
resize(rImg, rImg, templ.size());
|
||||
}
|
||||
Mat imgRes = abs(templ - rImg);
|
||||
imgRes = imgRes.mul(m32fMaskImg).mul(weightMat);
|
||||
float s = sum(weightMat).val[0];
|
||||
double val = norm(imgRes) / s;
|
||||
pData->mDisValVec[index] = val;
|
||||
pData->mRImgVec[index] = rImg;
|
||||
}
|
||||
|
||||
void modelVerfication::rotateMatchData(const Mat& _img, const Mat &baseImage, RData* pData, float angleStep, float startAngle, float endAngle)
|
||||
{
|
||||
Mat img = _img.clone();
|
||||
Point2f center(img.cols / 2.0, img.rows / 2.0);
|
||||
int nNum = (endAngle - startAngle) / angleStep;
|
||||
RData& data = *pData;
|
||||
data.init(_img, center, angleStep, nNum);
|
||||
data.mStartAngle = startAngle;
|
||||
data.mEndAngle = endAngle;
|
||||
qDebug() << "start parallel test";
|
||||
parallel_for_(Range(0, nNum), ImageCompareModel2(this, pData, baseImage));
|
||||
}
|
||||
|
||||
void modelVerfication::preProcessImage(Mat& img, const Mat& mask, double dstMean, double dstStddev, int highlightsThreshold)
|
||||
{
|
||||
|
||||
if (img.type() != CV_32FC1)
|
||||
{
|
||||
img.convertTo(img, CV_32FC1);
|
||||
}
|
||||
|
||||
Mat gaussImg;
|
||||
GaussianBlur(img, gaussImg, Size(3, 3), 5.0);
|
||||
img = gaussImg;
|
||||
|
||||
Mat dilatedMask;
|
||||
dilate(mask, dilatedMask, Mat::ones(Size(3, 3), CV_32FC1));
|
||||
|
||||
Mat hightlightsMask = img < highlightsThreshold;
|
||||
Mat imgMask = hightlightsMask & dilatedMask;
|
||||
//imgMask.convertTo(imgMask, CV_32FC1);
|
||||
Scalar meanScalar, stddevScalar;
|
||||
meanStdDev(img, meanScalar, stddevScalar, imgMask);
|
||||
img = (img - meanScalar.val[0]) * dstStddev / stddevScalar.val[0] + dstMean;
|
||||
|
||||
imgMask.convertTo(imgMask, CV_32FC1);
|
||||
imgMask /= 255.0;
|
||||
Mat imgNorm = cocentricNorm(img, Point2f(img.cols / 2.0, img.rows / 2.0),
|
||||
imgMask, 125);
|
||||
#ifdef DEBUG_VIEW_INTERNAL_MAT
|
||||
Mat vImgNorm = imgNorm / 255.0;
|
||||
#endif
|
||||
img = imgNorm;
|
||||
}
|
||||
|
||||
cv::Mat modelVerfication::genMask(const Mat& img, Point2f center, float innerR /*= -1*/, float outterR /*= -1*/, int type /*= CV_32FC1*/)
|
||||
{
|
||||
Mat mask(img.size(), CV_8UC1);
|
||||
mask.setTo(0);
|
||||
if (innerR == -1)
|
||||
{
|
||||
// default is 30
|
||||
innerR = img.rows*0.178;
|
||||
}
|
||||
if (outterR == -1)
|
||||
{
|
||||
// default is max radius - 10
|
||||
outterR = img.rows * 0.425;
|
||||
}
|
||||
circle(mask, center, outterR, Scalar(255), -1);
|
||||
circle(mask, center, innerR, Scalar(0), -1);
|
||||
if (type != CV_8UC1)
|
||||
{
|
||||
mask.convertTo(mask, type);
|
||||
mask /= 255;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
cv::Mat modelVerfication::cocentricNorm(Mat& img, Point2f center, const Mat& weightMat, float dstMeanVal)
|
||||
{
|
||||
assert(weightMat.empty() || weightMat.type() == CV_32FC1);
|
||||
|
||||
int w = img.cols;
|
||||
int h = img.rows;
|
||||
vector<Point2f> corners;
|
||||
corners.push_back(Point2f(0, 0));
|
||||
corners.push_back(Point2f(0, h));
|
||||
corners.push_back(Point2f(w, h));
|
||||
corners.push_back(Point2f(w, 0));
|
||||
vector<double> cornerDisVec;
|
||||
for_each(corners.begin(), corners.end(), [&](const Point2f& pt)
|
||||
{
|
||||
double dis = disOfPoint(center, pt);
|
||||
cornerDisVec.push_back(dis);
|
||||
});
|
||||
|
||||
auto farthestCornerDis = max_element(cornerDisVec.begin(), cornerDisVec.end());
|
||||
float maxRadius = *farthestCornerDis;
|
||||
|
||||
int radiusNum = floorf(maxRadius);
|
||||
//radiusNum = 20;
|
||||
float radiusStep = (maxRadius / radiusNum);
|
||||
Mat cocentricSumMat = Mat::zeros(1, radiusNum, CV_32FC1);
|
||||
float* pSumData = (float*)cocentricSumMat.data;
|
||||
Mat cocentricWeightSumMat = Mat::zeros(1, radiusNum, CV_32FC1);
|
||||
float* pWeightSumData = (float*)cocentricWeightSumMat.data;
|
||||
Mat radiusMat(img.rows, img.cols, CV_32FC1);
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
const Mat& imgRow = img.row(y);
|
||||
float* pImgRowData = (float*)imgRow.data;
|
||||
float* pRadiusRowData = (float*)radiusMat.row(y).data;
|
||||
|
||||
float* pWeightRowData = NULL;
|
||||
if (!weightMat.empty())
|
||||
{
|
||||
pWeightRowData = (float*)weightMat.row(y).data;
|
||||
}
|
||||
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
//std::cout << x << " " << y << std::endl;
|
||||
float weight;
|
||||
if (pWeightRowData)
|
||||
{
|
||||
weight = pWeightRowData[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
weight = 1.0;
|
||||
}
|
||||
float val = pImgRowData[x] * weight;
|
||||
float radius = disOfPoint(Point2f(x, y), center);
|
||||
pRadiusRowData[x] = radius;
|
||||
int radiusIdx0 = (int)(radius / radiusStep);
|
||||
assert(radiusIdx0 >= 0);
|
||||
int radiusIdx1 = radiusIdx0 + 1;
|
||||
if (radiusIdx0 >= radiusNum - 1)
|
||||
{
|
||||
pSumData[radiusNum - 1] += val;
|
||||
pWeightSumData[radiusNum - 1] += weight;
|
||||
}
|
||||
else
|
||||
{
|
||||
float s = (radius - radiusStep*radiusIdx0) / radiusStep;
|
||||
pSumData[radiusIdx0] += val*s;
|
||||
pSumData[radiusIdx1] += val*(1 - s);
|
||||
pWeightSumData[radiusIdx0] += s*weight;
|
||||
pWeightSumData[radiusIdx1] += (1 - s)*weight;
|
||||
}
|
||||
}
|
||||
// CvPlot::plot<float>("sum", pSumData, radiusNum);
|
||||
// CvPlot::plot<float>("count", pCountData, radiusNum);
|
||||
// waitKey();
|
||||
}
|
||||
|
||||
for (int i = 0; i < radiusNum; ++i)
|
||||
{
|
||||
//float radius = (i*radiusStep + radiusStep) / 2;
|
||||
if (pWeightSumData[i] == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
pSumData[i] /= pWeightSumData[i];
|
||||
}
|
||||
}
|
||||
|
||||
Mat retMat = Mat::zeros(img.rows, img.cols, img.type());
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
float* pImgRowData = (float*)img.row(y).data;
|
||||
float* pRetRowData = (float*)retMat.row(y).data;
|
||||
float* pRadiusData = (float*)radiusMat.row(y).data;
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
float val = pImgRowData[x];
|
||||
float radius = pRadiusData[x];
|
||||
float mean = interpolate(pSumData, radiusNum, radiusStep, radius);
|
||||
if (mean == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
float newVal = (float)val * dstMeanVal / mean;
|
||||
pRetRowData[x] = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIEW_INTERNAL_MAT
|
||||
Mat viewRetMat = retMat / 255.0;
|
||||
#endif
|
||||
|
||||
return retMat;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
#include "Luffy.h"
|
||||
#include "lpbengine.h"
|
||||
using namespace cv;
|
||||
class RData
|
||||
{
|
||||
public:
|
||||
RData() {};
|
||||
RData(const Mat &img, Point pt, double dAngleStep, int size)
|
||||
: mImgSrc(img)
|
||||
, mStartAngle(0)
|
||||
, mEndAngle(360)
|
||||
{
|
||||
init(img, pt, dAngleStep, size);
|
||||
};
|
||||
void init(const Mat& img, Point pt, double dAngleStep, int size)
|
||||
{
|
||||
mImgSrc = img;
|
||||
mStartAngle = 0;
|
||||
mEndAngle = 360.0;
|
||||
mRImgVec.clear();
|
||||
mRImgVec.resize(size);
|
||||
mDisValVec.clear();
|
||||
mDisValVec.resize(size, FLT_MAX);
|
||||
mCenter = pt;
|
||||
mAngleStep = dAngleStep;
|
||||
}
|
||||
double angle(int index)
|
||||
{
|
||||
return index*mAngleStep + mStartAngle;
|
||||
}
|
||||
double bestAngle()
|
||||
{
|
||||
if (mDisValVec.empty())
|
||||
{
|
||||
return -DBL_MAX;
|
||||
}
|
||||
size_t bestIndex = min_element(mDisValVec.begin(),
|
||||
mDisValVec.end()) - mDisValVec.begin();
|
||||
double bestAngle = angle(bestIndex);
|
||||
return bestAngle;
|
||||
}
|
||||
Mat bestRImg()
|
||||
{
|
||||
if (mRImgVec.empty())
|
||||
{
|
||||
return Mat();
|
||||
}
|
||||
size_t bestIndex = min_element(mDisValVec.begin(),
|
||||
mDisValVec.end()) - mDisValVec.begin();
|
||||
return mRImgVec[bestIndex];
|
||||
}
|
||||
double mAngleStep;
|
||||
Mat mImgSrc;
|
||||
Point mCenter;
|
||||
vector<Mat> mRImgVec;
|
||||
vector<float> mDisValVec;
|
||||
|
||||
float mStartAngle, mEndAngle;
|
||||
};
|
||||
|
||||
class modelVerfication
|
||||
{
|
||||
|
||||
public:
|
||||
modelVerfication(double tarStddevVal, double tarMeanVal);
|
||||
~modelVerfication();
|
||||
|
||||
Mat extractForegroundWheel(const Mat& background, const Mat& src);
|
||||
Mat findWheelObject(Mat src, Mat backGroundImg, int thresh);
|
||||
void rotateMatchData(const Mat& _img, const Mat &baseImage, RData* pData, float angleStep, float startAngle, float endAngle);
|
||||
void parallelDetect(int index, void *p, Mat templ);
|
||||
void preProcessImage(Mat& img, const Mat& mask, double dstMean, double dstStddev, int highlightsThreshold);
|
||||
Mat genMask(const Mat& img, Point2f center, float innerR = -1,
|
||||
float outterR = -1,
|
||||
int type = CV_32FC1);
|
||||
cv::Mat cocentricNorm(Mat& img, Point2f center, const Mat& weightMat, float dstMeanVal);
|
||||
float interpolate(float* pY, int n, float stepX, float x);
|
||||
bool objectVerification(const Mat &img, Mat& baseImage, double modelValidThresh, int endAngle, double & s);
|
||||
void setWeightMat(const Mat& img)
|
||||
{
|
||||
weightMat = img;
|
||||
weightMat.convertTo(weightMat, CV_32FC1);
|
||||
}
|
||||
|
||||
static int h;
|
||||
private:
|
||||
Mat weightMat;
|
||||
Mat m32fMaskImg;
|
||||
double tarStddev;
|
||||
double tarMean;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ImageCompareModel2 : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
ImageCompareModel2(modelVerfication *m, void* pData, Mat T)
|
||||
: m_pData(pData), model(m), templ(T)
|
||||
{}
|
||||
private:
|
||||
void *m_pData;
|
||||
modelVerfication* model;
|
||||
Mat templ;
|
||||
virtual void operator() (const cv::Range& range) const;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,146 @@
|
||||
#ifndef LP_VALVE_DETECTOR_H
|
||||
#define LP_VALVE_DETECTOR_H
|
||||
|
||||
#include "Luffy.h"
|
||||
#include "lpbengine.h"
|
||||
|
||||
#define ALG_RESIZE_IMAGE_WIDTH 416.0
|
||||
//#define VEIW_HISTGRAM
|
||||
using namespace luffy_base;
|
||||
|
||||
struct InputParam
|
||||
{
|
||||
QString strObj;
|
||||
Mat imgTemplate; //气门芯模板
|
||||
int nValveOffset;
|
||||
float fValveWidth;
|
||||
float fValveDis;
|
||||
Point2f ptCenter;
|
||||
double dScoreThres;
|
||||
int nMaxAngle;
|
||||
int nCenterAlg; // 中心校准算法
|
||||
int nBarScore;
|
||||
Mat barTemplate; //辐条参数
|
||||
//int bgThresh;
|
||||
int withinOffset;
|
||||
int barNum; //辐条数量
|
||||
Mat centerRoi;
|
||||
int flagCircle;
|
||||
Mat baseImage; //气门芯型号确认模板图
|
||||
int backgroundThresh; // 抠图阈值
|
||||
int modelMatchScore; //模型匹配值
|
||||
LP_DETECTOR_ROI_DATA roi;
|
||||
cv::Mat backGround;
|
||||
Point2f originalPoint;
|
||||
Mat weightMat;
|
||||
double cMatchScore;
|
||||
int wheelType;
|
||||
|
||||
};
|
||||
|
||||
struct OutputParam
|
||||
{
|
||||
double dTime;
|
||||
double dAngle;
|
||||
double dAngleRes;
|
||||
double dScore;
|
||||
|
||||
int nErrorType;
|
||||
bool bIsFind;
|
||||
QString strResultTip;
|
||||
Point2f rstPoint;
|
||||
int flag;
|
||||
double showMatchScore;
|
||||
};
|
||||
|
||||
class ValveDetector
|
||||
{
|
||||
public:
|
||||
ValveDetector();
|
||||
~ValveDetector();
|
||||
|
||||
bool detect(Mat & imgSrc, InputParam ¶mIn, OutputParam ¶mOut, Mat &imgDst = Mat());
|
||||
void drawResult(Mat &img, InputParam ¶mIn, OutputParam ¶mOut);
|
||||
Point2f getCenter(Mat & imgSrc, Point2f pt, InputParam ¶mIn);
|
||||
double ruleData(double, int);
|
||||
QString genResultTip(QString str, int nType);
|
||||
Point2f getCenterPoints(Mat &_img, const Mat ¢erTempl, InputParam paramIn, Point2f pt, Mat& rstMat);
|
||||
bool saveResult(Mat &img, InputParam ¶mIn, OutputParam ¶mOut, QString modelStr);
|
||||
bool isValid(Mat target, Mat templ, Point2f pt, int validThresh);
|
||||
void drawToImage(Mat &img, InputParam ¶mIn, OutputParam ¶mOut);
|
||||
cv::Mat findCircleObject(const Mat &src, const Mat& backgroundImg, int nThres = 20, luffy_base::luffyCircle *pCircle = NULL);
|
||||
cv::Mat getForeImage(const Mat & src, const Mat &backgroundImg);
|
||||
};
|
||||
/*class RotateData
|
||||
{
|
||||
public:
|
||||
RotateData() {};
|
||||
RotateData(const Mat &img, Point pt, double dAngleStep, int size)
|
||||
: mImgSrc(img)
|
||||
, mStartAngle(0)
|
||||
, mEndAngle(360)
|
||||
{
|
||||
init(img, pt, dAngleStep, size);
|
||||
};
|
||||
void init(const Mat& img, Point pt, double dAngleStep, int size)
|
||||
{
|
||||
mImgSrc = img;
|
||||
mStartAngle = 0;
|
||||
mEndAngle = 360.0;
|
||||
mRImgVec.clear();
|
||||
mRImgVec.resize(size);
|
||||
mDisValVec.clear();
|
||||
mDisValVec.resize(size, FLT_MAX);
|
||||
mCenter = pt;
|
||||
mAngleStep = dAngleStep;
|
||||
}
|
||||
double angle(int index)
|
||||
{
|
||||
return index*mAngleStep + mStartAngle;
|
||||
}
|
||||
double bestAngle()
|
||||
{
|
||||
if (mDisValVec.empty())
|
||||
{
|
||||
return -DBL_MAX;
|
||||
}
|
||||
size_t bestIndex = min_element(mDisValVec.begin(),
|
||||
mDisValVec.end()) - mDisValVec.begin();
|
||||
double bestAngle = angle(bestIndex);
|
||||
return bestAngle;
|
||||
}
|
||||
Mat bestRImg()
|
||||
{
|
||||
if (mRImgVec.empty())
|
||||
{
|
||||
return Mat();
|
||||
}
|
||||
size_t bestIndex = min_element(mDisValVec.begin(),
|
||||
mDisValVec.end()) - mDisValVec.begin();
|
||||
return mRImgVec[bestIndex];
|
||||
}
|
||||
double mAngleStep;
|
||||
Mat mImgSrc;
|
||||
Point mCenter;
|
||||
vector<Mat> mRImgVec;
|
||||
vector<float> mDisValVec;
|
||||
|
||||
float mStartAngle, mEndAngle;
|
||||
};
|
||||
|
||||
class ImageCompareModelInvoker : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
ImageCompareModelInvoker(Mat &templ, void* pData)
|
||||
: m_pData(pData), temp(templ)
|
||||
{}
|
||||
private:
|
||||
void *m_pData;
|
||||
Mat temp;
|
||||
virtual void operator() (const cv::Range& range) const;
|
||||
};*/
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //LP_VALVE_DETECTOR_H
|
||||
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;cxx;c;def</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Form Files">
|
||||
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
|
||||
<Extensions>ui</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||
<Extensions>qrc;*</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
|
||||
<Extensions>moc;h;cpp</Extensions>
|
||||
<SourceControlFiles>False</SourceControlFiles>
|
||||
</Filter>
|
||||
<Filter Include="Translation Files">
|
||||
<UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier>
|
||||
<Extensions>ts</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="algEg.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="valveDetector.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BatchTest4Alg.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="modelVerfication.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="algEg.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="algEg_global.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="valveDetector.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BatchTest4Alg.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="modelVerfication.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="valvedetector_en.ts">
|
||||
<Filter>Translation Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Loading…
Reference in New Issue