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.
wheeldetect/src/algorithm/AlgorithmFluorescence.cpp

354 lines
9.9 KiB
C++

#include "AlgorithmFluorescence.h"
#include "ImageCompareModel.h"
#include "ImageProcess.h"
#include "..\tpMain\IWheelModel.h"
#include "ImageCompareModel.h"
#include "QVariant"
#include "QImage"
#include "QDebug"
#include "QPixmap"
#include "CVUtils.h"
#include "qtcvutils.h"
#include "qfile.h"
#include "qtextstream.h"
#include "qiodevice.h"
#include "..\tpMain\Result2Ui.h"
#pragma execution_character_set("utf-8")
using namespace cv;
using namespace lp;
class CLocalWheel{
public:
CLocalWheel() {
useHeight = true;
useDiameter = true;
}
cv::Mat img;
int height;
int diameter;
bool useHeight;
bool useDiameter;
QStringList defectList;
};
CAlgorithmFluorescence::CAlgorithmFluorescence(void)
{
}
CAlgorithmFluorescence::~CAlgorithmFluorescence(void)
{
}
//cv::BackgroundSubtractorMOG CAlgorithmFluorescence::bgSubtractor(30, 5, 0.95, false);
QString CAlgorithmFluorescence::bestMatch(const QMap<QString, IWheelModel*>* modelMap, CLocalWheel*pLocal, double* pMinDis /*= NULL*/, int minDisNum /*= -1*/) const
{
double minDis = DBL_MAX;
QString bestName;
vector<double> disVec(modelMap->size());
int nIndex = 0;
if (!modelMap)
return bestName;
QStringList strDetectModels = pLocal->defectList;
while (strDetectModels.size())
{
QString strModelName = strDetectModels.takeFirst();
if (!modelMap->contains(strModelName))
continue;
QMap<QString,IWheelModel*>::const_iterator itsModel = modelMap->find(strModelName);
disVec[nIndex] = DBL_MAX;
IWheelModel *pWheel = itsModel.value();
if (!pWheel)
break;
if (pLocal->useDiameter) {
if (abs(pLocal->diameter-pWheel->getDiameter()) >= 15) {
nIndex++;
continue;
}
}
if (pLocal->useHeight) {
if (abs(pLocal->height - pWheel->getThickness()) >= 15) {
nIndex++;
continue;
}
}
QString name = strModelName;// i.key();
ImageCompareModel* pModel = pWheel->getImageComModel();
if (pModel->getBaseImg().data == NULL)
{
nIndex++;
continue;
}
pModel->setIsEnableCache(false);
double dis = pModel->compare(pLocal->img, NULL, true, 1);
disVec[nIndex] = dis;
if (dis < minDis && dis != -1)
{
minDis = dis;
bestName = name;
}
nIndex++;
}
if (pMinDis)
{
*pMinDis = minDis;
}
if (minDisNum > 1)
{
sort(disVec.begin(), disVec.end());
std::copy_n(disVec.begin(), minDisNum, pMinDis);
}
return bestName;
}
int CAlgorithmFluorescence::IImageAnalysis(class IImageObject* pImgObj, TP_ALGORITHM_OPTION* pOpt, class IDetectorEngine* pDE)
{
QMutexLocker locker(&mutex);
qDebug() << "start alg";
double dStart = cv::getTickCount();
Mat matSrc = getImage(pImgObj).clone();
QVariantMap vMap = pImgObj->IVarFromUI().toMap();
long long modelMapPtr = vMap.value("modelMap").toLongLong();
QMap<QString, IWheelModel*> *ptr = (QMap<QString, IWheelModel*>*)modelMapPtr;
long long defectListPtr = vMap.value("defectList").toLongLong();
QStringList* strModelListptr = (QStringList*)defectListPtr;
QStringList strModelList;
if(strModelListptr)
strModelList = *(strModelListptr);
int th = vMap.value("thickness", -1).toInt();
bool useThickness = vMap.value("useThickness", 0).toBool();
bool useDiameter = vMap.value("useDiameter", 0).toBool();
double dD2H = vMap.value("d2h", -1).toDouble();
int nthreshold = vMap.value("Threshold", 15).toInt();
if (nthreshold <= 0)
nthreshold = 15;
int IsCutedImg = vMap.value("IsCutImg", 0).toInt();//裁剪后的轮毂图
QVariantMap rltMap;
luffy_base::luffyCircle lCircle;
static bool bReload = false;
Mat matBack = getBackGroundImage(pImgObj, bReload);//获取背景图
Mat matMatch;//装载抠图后的图像
if (IsCutedImg == 0){
if (matSrc.size().height != matBack.size().height || matSrc.size().width != matBack.size().width)
{
rltMap.insert("error", 0);
pImgObj->IVariantMapToUI(rltMap);
bReload = true;
return 0;
}
else{
bReload = false;
}
//imageSegementation(matSrc);
matMatch = ImageProcess::findCircleObject(matSrc, matBack, nthreshold/*15*/, &lCircle/* NULL*/);
}
else{
matMatch = matSrc;
}
//Mat matMatch = ImageProcess::findCircleObject(matSrc, matBack, 15, NULL/* &lCircle*/);
//double dDiameter = dD2H * matMatch.rows;
double dDiameter = dD2H * lCircle.fRadius * 2;
Result2Ui *pResult = new Result2Ui;
CLocalWheel wheelLocal;
wheelLocal.defectList = strModelList;// *getDefectListPtr(pImgObj);
wheelLocal.img = matMatch.clone();
wheelLocal.height = th;
wheelLocal.diameter = dDiameter;
wheelLocal.useHeight = useThickness;
wheelLocal.useDiameter = useDiameter;
if (!matMatch.empty() && ptr && ptr->size() > 0) {
vector<double> minDisVec(ptr->size());
qDebug() << "start bestMatch";
QString str = bestMatch(ptr, &wheelLocal, &(minDisVec[0]), minDisVec.size());
qDebug() << "end bestMatch";
pResult->m_strModel = str;
pResult->m_dMinDis = minDisVec[0];
if (ptr->contains(str) && ptr->value(str)->getImageComModel()) {
ImageCompareModel *pModel = ptr->value(str)->getImageComModel();
double d = pModel->getDisThre();
double dValue = (d - minDisVec[0]) / d * 0.4 + 0.6;
pResult->m_dScore = dValue;
}
}
else {
}
qDebug() << "pull result";
pResult->m_pixSrc = QtCVUtils::cvMatToQPixmap(matSrc);//!>原图像发送值UI 用于保存备份和调试
QImage img = QtCVUtils::cvMatToQImage(matMatch);
pResult->m_pixResult = QtCVUtils::cvMatToQPixmap(matMatch);// .scaled(125, 125);
pResult->m_dDiameter = dDiameter;
pResult->m_dThickness = th;
//!>传递检测结果到UI
//pImgObj->IDrawImage(img.scaled(300, 300));//!>显示结果图片到UI的第二个窗口上
double dTime = (cv::getTickCount() - dStart) / cv::getTickFrequency();
pResult->m_dRunTime = dTime;
long long varRlt = (long long)pResult;
rltMap.insert("result", varRlt);
pImgObj->IVariantMapToUI(rltMap);
qDebug() << "finish alg";
return 1;
}
QStringList *CAlgorithmFluorescence::getDefectListPtr(class IImageObject *pImgObj)
{
return nullptr;
// IAlgorithmShared *pShare = pImgObj->IGetShared();
// int nMap = pShare->IGetInt("defectList");
// return (QStringList*)nMap;
}
QMap<QString, IWheelModel*> *CAlgorithmFluorescence::getWheelMapPtr(class IImageObject *pImgObj)
{
// IAlgorithmShared *pShare = pImgObj->IGetShared();
// if (!pShare)
// return nullptr;
// int nMap = pShare->IGetInt("modelMap");
// return (QMap<QString, IWheelModel*>*)nMap;
return nullptr;
}
cv::Mat CAlgorithmFluorescence::getImage(class IImageObject *pImgObj)
{
emTpColorFormat colorFormat = pImgObj->IColorFormat();
int nImageW;
int nImageH;
int nBitsPerPixel;
int nBytesPerLine;
BYTE* pImageData = pImgObj->IImageData(nImageW, nImageH, nBitsPerPixel, nBytesPerLine);
Mat matSrc;
if (TP_COLOR_Y800 != colorFormat)
{
Mat colorMat = Mat(nImageH, nImageW, CV_8UC4, pImageData, nBytesPerLine);
matSrc = getFirstChannel(colorMat);
}
else
{
matSrc = Mat(nImageH, nImageW, CV_8UC1, pImageData, nBytesPerLine);
}
return matSrc;
}
cv::Mat CAlgorithmFluorescence::getBackGroundImage(class IImageObject *pObj, bool bReLoad)
{
static Mat matback;
if (matback.empty()) {
QString filepath = /*getPath(pObj) +*/ ".\\user\\background.png";
matback = cv::imread(string((const char *)filepath.toLocal8Bit()), 0);
//matback = cv::imread(filepath.toLatin1().data(), 0);
if (matback.empty()) {
QString filepath = getPath(pObj) + "\\user\\background_r.png";
matback = cv::imread(string((const char *)filepath.toLocal8Bit()), 0);
//matback = cv::imread(filepath.toLatin1().data(), 0);
cv::flip(matback, matback, 1);
}
}
else {
if (bReLoad) {
QString filepath = getPath(pObj) + "\\user\\background.png";
matback = cv::imread(string((const char *)filepath.toLocal8Bit()), 0);
if (matback.empty()) {
QString filepath = getPath(pObj) + "\\user\\background_r.png";
matback = cv::imread(string((const char *)filepath.toLocal8Bit()), 0);
//matback = cv::imread(filepath.toLatin1().data(), 0);
cv::flip(matback, matback, 1);
}
}
}
return matback;
}
QString CAlgorithmFluorescence::getPath(class IImageObject *pObj)
{
IAlgorithmShared* pShare = pObj->IGetShared();
if (!pShare)
return QString();
QStringList mlist = pObj->IGetShared()->IGetStringList("filepath");
if (mlist.empty()) {
return QString();
}
return mlist.first();
}
//void CAlgorithmFluorescence::imageSegementation(const cv::Mat &srcImage)
//{
// Mat mask;
// //Mat sobelImg = srcImage.clone();
// //genSobelImage(sobelImg);
// //sobelImg.convertTo(sobelImg, CV_8UC1);
//
//
// Mat sobelX, sobelY;
// Sobel(srcImage, sobelX, CV_32FC1, 1, 0, 3, BORDER_REPLICATE);
// Sobel(srcImage, sobelY, CV_32FC1, 0, 1, 3, BORDER_REPLICATE);
// Mat img = sobelX.mul(sobelX) + sobelY.mul(sobelY);
// Mat tempImg;
// img.convertTo(tempImg, CV_32FC1);
// Mat tempImg0;
// sqrt(tempImg, tempImg0);
// img = tempImg0;
// img.convertTo(img, CV_8UC1);
// Mat blurImg;
// cv::medianBlur(img, blurImg, 11);
// bgSubtractor(img, mask, 0.001);
//
// /*cv::Mat element5(5, 5, CV_8U, cv::Scalar(1));
// cv::Mat closedMat;
// cv::morphologyEx(mask, closedMat, cv::MORPH_CLOSE, element5);*/
//
// //cv::floodFill();
// luffy_base::luffyCircle pCircle;
//
// vector<cv::Mat> mats= ImageProcess::findCircleObject(mask, srcImage, 15, &pCircle);
// if (mats.size() == 0)
// {
// return;
// }
// if (mats[0].size() != mats[1].size())
// {
// return;
// }
// Mat dilatedImgBin;
// Mat imgBinary = mats[0] > 0;
// dilate(imgBinary, dilatedImgBin, Mat::ones(5, 5, CV_32FC1));
// erode(dilatedImgBin, imgBinary, Mat::ones(5, 5, CV_32FC1));
// imgBinary = ~imgBinary;
// //Mat canvas(imgBinary.size(), imgBinary.type(), Scalar::all(0));
// vector<vector<Point>> cons;
// cv::findContours(imgBinary, cons, RETR_EXTERNAL, CHAIN_APPROX_NONE);
// for (const vector<Point> & pContour : cons)
// {
// const int& size = pContour.size();
// if (size < 200)
// {
// Mat(pContour).setTo(255);
// //continue;
// }
// //cv::fillPoly(canvas, vector<vector<Point>>(1, pContour), Scalar(255));
// }
// //Mat tarMat = (~canvas).mul(mats[1]) / 255;
// //openOper(imgBinary, Mat::ones(1, 13, CV_32FC1));
//
//
//
//
// return;
//
//}