Files
2024-10-11 10:07:08 +08:00

986 lines
34 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "Hd_AI_empty_module.h"
#include <QDateTime>
#include <QtConcurrent/QtConcurrent>
#include <qfuture.h>
#include <QTextCodec>
using namespace cv;
//原图保存文件夹
QString oriImgSaveDir = "F:/ORI/";
//原图class图保存文件夹
QString classImgSaveDir = "F:/ORIclass/";
//结果保存文件夹
QString resImgSaveDir = "F:/res/";
//切图的class的width,根据项目实际设置!
int sizeW = 150;
//切图的class的height,根据项目实际设置!
int sizeH = 150;
//切图的class的width,根据项目实际设置!0为黑,255为白;
int fillColour = 0;
//检测线程锁
QMutex* detect_mutex;
//保存线程锁
QMutex* saveStruct_mutex;
//检测线程运行标志
bool ifdetectThread = false;
QString cameraKey_index = "";
QString byteArrayToUnicode(const QByteArray array) {
// state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功
// 如果转换成功,则值为0,如果值大于0,则说明转换失败
QTextCodec::ConverterState state;
// 先尝试使用utf-8的方式把QByteArray转换成QString
QString text = QTextCodec::codecForName("UTF-8")->toUnicode(array.constData(), array.size(), &state);
// 如果转换时无效字符数量大于0,说明编码格式不对
if (state.invalidChars > 0)
{
// 再尝试使用GBK的方式进行转换,一般就能转换正确(当然也可能是其它格式,但比较少见了)
text = QTextCodec::codecForName("GBK")->toUnicode(array);
}
return text;
}
// 缺陷信息结构体
typedef struct {
QString defectName = "";//缺陷名称
cv::Rect defectRect = { 0,0,0,0 };//缺陷位置
cv::Scalar defectScalar = cv::Scalar(0, 0, 0);//画框颜色
double defectArea = 0;//缺陷真实面积
double defectDepth = 0;//缺陷深度/高度,3D信息
}defectInfo;
//判断文件是否存在,不存在则创建
bool isFileExist(QString fullFileName)
{
QFileInfo fileInfo(fullFileName);
if (fileInfo.isFile())
{
return true;
}
return false;
}
void GetStringSize(HDC hdc, const char* str, int* w, int* h)
{
SIZE size;
GetTextExtentPoint32A(hdc, str, strlen(str), &size);
if (w != 0) *w = size.cx;
if (h != 0) *h = size.cy;
}
//在图像写中文,英文也可以写
void putTextZH(cv::Mat& dst, const char* str, cv::Point org, cv::Scalar color, int fontsize,
const char* fn = "Arial", bool italic = false, bool underline = false)
{
CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3));
int x, y, r, b;
//坐标点大于图像宽和高直接返回
if (org.x > dst.cols || org.y > dst.rows) return;
x = org.x < 0 ? -org.x : 0;
y = org.y < 0 ? -org.y : 0;
LOGFONTA lf;
lf.lfHeight = -fontsize; //字体高度
lf.lfWidth = 0; //平均宽度
lf.lfEscapement = 0; //字符排列角度
lf.lfOrientation = 0; //字符本身旋转的角度
lf.lfWeight = 5; //设置字体线条的宽度
lf.lfItalic = italic; //斜体
lf.lfUnderline = underline; //下划线
lf.lfStrikeOut = 0; //是否字符中央加横线
lf.lfCharSet = DEFAULT_CHARSET; //字符集
lf.lfOutPrecision = 0; //字体的精确度
lf.lfQuality = PROOF_QUALITY; //字体质量
lf.lfPitchAndFamily = 0; //选择字体的间距和字体家族
strcpy_s(lf.lfFaceName, fn); //字体的名称
HFONT hf = CreateFontIndirectA(&lf);
HDC hdc = CreateCompatibleDC(0);
HFONT holdfont = (HFONT)SelectObject(hdc, hf);
int strBaseW = 0, strBaseH = 0;
int singleRow = 0;
char buf[1 << 12];
strcpy_s(buf, str);
char* bufT[1 << 12]; //这个用于分隔字符串后剩余的字符,可能会超出。
//处理多行
{
int nnh = 0;
int cw, ch;
const char* ln = strtok_s(buf, "\n", bufT);
while (ln != 0)
{
GetStringSize(hdc, ln, &cw, &ch);
strBaseW = max(strBaseW, cw);
strBaseH = max(strBaseH, ch);
ln = strtok_s(0, "\n", bufT);
nnh++;
}
singleRow = strBaseH;
strBaseH *= nnh;
}
if (org.x + strBaseW < 0 || org.y + strBaseH < 0)
{
SelectObject(hdc, holdfont);
DeleteObject(hf);
DeleteObject(hdc);
return;
}
r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1;
b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1;
org.x = org.x < 0 ? 0 : org.x;
org.y = org.y < 0 ? 0 : org.y;
BITMAPINFO bmp = { 0 };
BITMAPINFOHEADER& bih = bmp.bmiHeader;
int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4));
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = strBaseW;
bih.biHeight = strBaseH;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = BI_RGB;
bih.biSizeImage = strBaseH * strDrawLineStep;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
void* pDibData = 0;
HBITMAP hBmp = CreateDIBSection(hdc, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0);
CV_Assert(pDibData != 0);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hdc, hBmp);
//color.val[2], color.val[1], color.val[0]
SetTextColor(hdc, RGB(255, 255, 255));
SetBkColor(hdc, 0);
//SetStretchBltMode(hDC, COLORONCOLOR);
strcpy_s(buf, str);
const char* ln = strtok_s(buf, "\n", bufT);
int outTextY = 0;
while (ln != 0)
{
TextOutA(hdc, 0, outTextY, ln, strlen(ln));
outTextY += singleRow;
ln = strtok_s(0, "\n", bufT);
}
uchar* dstData = (uchar*)dst.data;
int dstStep = dst.step / sizeof(dstData[0]);
unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep;
unsigned char* pStr = (unsigned char*)pDibData + x * 3;
for (int tty = y; tty <= b; ++tty)
{
unsigned char* subImg = pImg + (tty - y) * dstStep;
unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep;
for (int ttx = x; ttx <= r; ++ttx)
{
for (int n = 0; n < dst.channels(); ++n) {
double vtxt = subStr[n] / 255.0;
int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n];
subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv);
}
subStr += 3;
subImg += dst.channels();
}
}
SelectObject(hdc, hOldBmp);
SelectObject(hdc, holdfont);
DeleteObject(hf);
DeleteObject(hBmp);
DeleteDC(hdc);
}
void drawDefects(cv::Mat& sourceMat, QQueue<defectInfo> defectInfoList)
{
for (int i = 0; i < defectInfoList.size(); i++)
{
defectInfo mdefect = defectInfoList[i];
cv::rectangle(sourceMat, cv::Point(mdefect.defectRect.x, mdefect.defectRect.y),
cv::Point(mdefect.defectRect.x + mdefect.defectRect.width, mdefect.defectRect.y + mdefect.defectRect.height), mdefect.defectScalar, 3, 8);
QByteArray path_arr = mdefect.defectName.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(sourceMat, path, cv::Point(mdefect.defectRect.x, mdefect.defectRect.y - 50), mdefect.defectScalar, 50, "微软雅黑");
}
}
//判断文件夹是否存在,不存在则创建
void Hd_AI_empty_module::isDirExist(QString fullDirName)
{
QDir* photo = new QDir;
bool exist = photo->exists(fullDirName);
if (exist)
{
//qDebug() << fullDirName << "::已存在";
}
else
{
//创建photo文件夹
//qDebug() << fullDirName << "::不存在,创建";
photo->mkdir(fullDirName);
}
delete photo;
photo = nullptr;
}
Hd_AI_empty_module* create()
{
qDebug() << "[INFO] " << " Hd_AI_empty_module create success!" ;
return new Hd_AI_empty_module;
}
void destory(Hd_AI_empty_module* ptr)
{
qDebug() << "[INFO] " << "Hd_AI_empty_module destory success!";
if(ptr)
{
delete ptr;
ptr = nullptr;
}
}
Hd_AI_empty_module::Hd_AI_empty_module()
{
detect_mutex = new QMutex;
saveStruct_mutex = new QMutex;
ifdetectThread = false;
for (int i = 0; i < 4; i++)
{
QString DirPath = "E:/testImg/source" + QString::number(i);
QStringList imgFilters;
imgFilters << "*.jpg" << "*.png" << "*.PNG" << "*.gif" << "*.tif" << "*.jpeg" << "*.bmp";
QDir qdir(DirPath);
//返回文件名列表
QStringList localSourceImgsName = qdir.entryList(imgFilters, QDir::Files | QDir::Readable, QDir::Name);
for (int j = 0; j < localSourceImgsName.size(); j++)
{
QString imgPath = DirPath + "/" + localSourceImgsName[j];
QFile myf(imgPath);
if (myf.exists())
myf.remove();
//Sleep(1);
}
}
}
Hd_AI_empty_module::~Hd_AI_empty_module()
{
ifdetectThread = false;
Sleep(10);
if (detect_mutex)
{
delete detect_mutex;
detect_mutex = nullptr;
}
if (saveStruct_mutex)
{
delete saveStruct_mutex;
saveStruct_mutex = nullptr;
}
/*DestroySegObj(pSeg);
DestroyClsObj(pCls);*/
}
//从类中读数据到实例对象
bool Hd_AI_empty_module::readData(std::vector<cv::Mat>&vec_mat,QByteArray &data)
{
detect_mutex->lock();
//qDebug() << __FUNCTION__ << " line:" <<__LINE__ << " data len:" << data.length();
if (resMat.size()>0)
{
vec_mat.push_back(resMat[0]);
resMat.clear();
}
else
{
vec_mat.push_back(HikMat[0]);
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " resMat.data err:";
}
if (allNum++ % 21 == 20)
data = "2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2";// resByte.dequeue();
else
data = "1";//1OK,2NG
resByte.clear();
////之后根据结果类修改
//if(resIfNg == true)
// data = "NG";
//else data = "OK";
detect_mutex->unlock();
/*if(cameraKey_index.contains('_'))
qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName:"
<< cameraKey_index.split("_")[0] << " imgIndex:" << cameraKey_index.split("_")[1];
else
qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName imgIndex:" << cameraKey_index;*/
return true;
}
//从类中读数据到实例对象
bool Hd_AI_empty_module::encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte)
{
try
{
std::string sendMsg;
for(int i = 0 ; i < append_value.size();i++)
{
std::string value = append_value.at(1);
//type
int type = 3;
std::string m_type;
m_type.insert(0,4,'1');
memcpy ( (void*)m_type.c_str(),(void*)&type,4 );
sendMsg.append(m_type);
//len
int len = value.length();
std::string m_len;
m_len.insert(0,4,'1');
memcpy ( (void*)m_len.c_str(),(void*)&len,4 );
sendMsg.append(m_len);
//data x
sendMsg.append(value);
}
resultByte = QByteArray::fromStdString(sendMsg);
} catch (QString ev)
{
qCritical() << "[Error] " << " ev:" << ev;
return false;
}
return true;
}
int myallNum[4] = {0};
QMap<int, cv::Mat> lastImgMap;
//接收数据
bool Hd_AI_empty_module::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &data)
{
//qDebug() << __FUNCTION__ << "line:"<< __LINE__ << " data len" << data.length() ;
if(vec_mat.empty())
{
qCritical() << "[Error] " << " vec_mat is null !";
return false;
}
detect_mutex->lock();
HikMat.clear();
HikMat.enqueue(vec_mat[0]);
QString savePath;
QString sData = data;
QStringList splitDataList = sData.split(",");
if(splitDataList.size()>=4)
if(splitDataList[2].contains('_'))
cameraKey_index = splitDataList[2];
int index = -1;
if (sData.contains("offline-camera0"))
{
index = 0;
savePath = "E:\\testImg\\source0\\"+QString::number(myallNum[0]++) + ".bmp";
}
else if (sData.contains("offline-camera1"))
{
index = 1;
savePath = "E:\\testImg\\source1\\" + QString::number(myallNum[1]++) + ".bmp";
}
else if (sData.contains("offline-camera2"))
{
index = 2;
savePath = "E:\\testImg\\source2\\" + QString::number(myallNum[2]++) + ".bmp";
}
else if (sData.contains("offline-camera3"))
{
index = 3;
savePath = "E:\\testImg\\source3\\" + QString::number(myallNum[3]++) + ".bmp";
}
if (!savePath.isEmpty())
{
//std::cout << "try savePath::" << savePath.toStdString() << std::endl;
//测试相机的,
while (HikMat[0].cols > 2000)cv::resize(HikMat[0], HikMat[0], cv::Size(), 0.08, 0.08);
addImgToSaveStruct(HikMat[0], "0", savePath);//
}
//if (myallNum[index] == 1)
//{
// cv::Mat img;
// lastImgMap.insert(index, img);
//}
//else
//{
// //判断和上一张图,是否重复
// int dataLength = HikMat[0].total() * HikMat[0].elemSize();
// bool res = false;
// if (myallNum[index] > 0)
// {
// cv::Mat img = lastImgMap.value(index);
// if (img.total() * img.elemSize() == dataLength)
// {
// res = memcmp(img.data, HikMat[0].data, dataLength) == 0;
// if (res == true)
// std::cout << "res ==true ====!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
// }
// }
//}
//lastImgMap.insert(index, HikMat[0]);
//or检测:保存路径,拍照面描述,相机key_第几张图,SN_时间戳
//and检测:保存路径,拍照面描述,相机key_第几张图,相机key_第几张图,SN_时间戳,SN_时间戳
//汇总:保存路径,拍照面描述,触发信号_序号列表0,SN_时间戳
QString qstring_data = data;
QStringList datalist = qstring_data.split(',');
/*saveKey.enqueue("datalist[0]");
Dir2D.enqueue("datalist[1]");
QStringList SN_dataTime;
SN_dataTime = datalist[3].split('_');
DateTime1 = "SN_dataTime[1]";
SN.enqueue("SN_dataTime[0]");*/
//qCritical() << __FUNCTION__ << " line: " << __LINE__ << " data:" << qstring_data;
detect_mutex->unlock();
//qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << " data: " << data << " run end";
//cv::Mat resultDstImg = vec_mat[0].clone();// = pSeg->Evaluate(sourceImg); //返回单通道二值图 图片错误输出Image Error!但不报错。。
//resultDstImg = pSeg->Evaluate(resultDstImg);
//resultDstImg.release();
return true;
}
//传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1...
//初始化
bool Hd_AI_empty_module::initParas(QByteArray& byteArray)
{
QByteArrayList valueList = byteArray.split('+');
QStringList valueiList;
if (byteArray.contains("onlySetParameter"))
{
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,valueList[0]:" << valueList[0];
if (valueList.size() > 1)
for (int i = 1; i < valueList.size(); i++)
{
QString valuei = byteArrayToUnicode(valueList[i]);
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,lastName:" << valueList[0] << " ,valuei:" << valuei;
}
return true;
}
if (valueList.size() > 1)
for (int i = 1; i < valueList.size(); i++)
{
QString valuei = byteArrayToUnicode(valueList[i]);
valueiList.append(valuei);
}
/*pSeg = CreateSegObjS(pSeg_modulePath, 128, gpuId);
pCls = CreateClsObjV3(pCls_modulePath, gpuId, 1);*/
//StationNo = vec_ret.at(0).toInt();
//InitThreads(StationNo, img2D);
//InitModels(StationNo, img2D);
//运行检测线程
ifdetectThread = true;
//线程检测:结果类完成时,使用
//ifThreadRunDetect = true;
//QFuture<void> future1 = QtConcurrent::run(this, &Hd_AI_empty_module::detectThread);
//运行存图线程
QFuture<void> future2 = QtConcurrent::run(this, &Hd_AI_empty_module::saveImgThread);
//detectThread();
//原图总文件夹
isDirExist(oriImgSaveDir);
//原图class总文件夹
isDirExist(classImgSaveDir);
//结果图总文件夹
isDirExist(resImgSaveDir);
//qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ;
return true;
}
// 解码
bool Hd_AI_empty_module::decodeAiValue(QByteArray byteArray,QVector<QByteArray> &vec_ret)
{
if(byteArray.isEmpty())
{
qCritical() << "[Error] " << " byteArray is null!";
return false;
}
/*******************************************/
byteArray.remove(0,8);
QByteArray mm_data = byteArray.mid(0,4);
memcpy((void*)&paramNum,(void*)mm_data.data(), 4);
qDebug() << "[INFO] " << " paramNum:" << paramNum;
byteArray.remove(0,4);
/*******************************************/
while (!byteArray.isEmpty())
{
int type = 0;
QByteArray m_type = byteArray.mid(0,4);
memcpy((void*)&type,(void*)m_type.data(), 4);
byteArray.remove(0,4);
int len = 0;
QByteArray m_len = byteArray.mid(0,4);
memcpy((void*)&len,(void*)m_len.data(), 4);
byteArray.remove(0,4);
QByteArray mm_data = byteArray.mid(0,len);
vec_ret.append(mm_data);
byteArray.remove(0,len);
}
return true;
}
//---------检测流程,根据实际项目修改---------
bool Hd_AI_empty_module::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime)
{
try
{
//存图数据加保存队列,加锁,避免数据访问冲突
saveStruct_mutex->lock();
saveImgStruct mySave;
Mat sourceImg;
sourceImg = img2D.clone();
//img2D.copyTo(sourceImg);
//img2D.release();
QString mysaveKey1 = mysaveKey; //"offlineStation1_off_1"
saveStruct_mutex->unlock();
QJsonDocument document;
QJsonObject obj;
obj.insert("result_key", "mysaveKey");
obj.insert("SN", "mySN");
obj.insert("DataTime", "myDataTime");
//QFile csvName("test.csv");
//QStringList lines;
//lines << "class,name\n" << "3,4,5,6,7\n" << "a,b,c,d\n";
//if (csvName.open(QIODevice::WriteOnly)) //若文件不存在,会自动创建
//{
// for (int i = 0; i < lines.size(); i++)
// csvName.write(lines[i].toStdString().c_str());
// csvName.close();
//}
QQueue<defectInfo> defectInfoList;
//seg后class检测逻辑
/*if (0) {
Mat sourceRectangles;// 在原图缺陷位置,边界矩形框出
sourceRectangles = sourceImg.clone();
//sourceImg.copyTo(sourceRectangles);
vector<vector<Point>> contours;
//seg检测
Mat resultDstImg;// = sourceImg.clone();// = pSeg->Evaluate(sourceImg); //返回单通道二值图 图片错误输出Image Error!但不报错。。
resultDstImg = pSeg->Evaluate(sourceImg);
//int resultClass = pCls->Evaluate(sourceImg); //类别id
//opencv对二值图进行处理
//GaussianBlur(resultDstImg, resultDstImg, Size(3, 3), 1); //缺陷过滤值较大时,可以减少检出数;缺陷较小时,漏检较多
threshold(resultDstImg, resultDstImg, pSeg->m_classes, 255, THRESH_BINARY_INV);//大于部分设为0,小于部分设为255
//findContours(resultDstImg, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); //不识别内部轮廓,有些情况抓到的图像外框?
findContours(resultDstImg, contours, cv::noArray(), cv::RETR_TREE, cv::CHAIN_APPROX_NONE); //需要内部轮廓的写法
if (contours.size() == 0)
{
//printf("Notlabeled\n");
}
else
{
for (int j = 0; j < contours.size(); j++)
{
Rect rect1 = boundingRect(Mat(contours[j]));
//最小缺陷过滤参数,根据项目实际设置!
int filterNum = 10;
float w = rect1.width * 1.0;
float h = rect1.height * 1.0;
if ((w / sourceImg.cols > 0.98) || (h / sourceImg.rows > 0.98))
{
//抓到图像外框了
//qDebug() << "NG is too big...";
continue;
}
//且逻辑,有的项目需要或逻辑!!
if ((w > filterNum && h > filterNum))//||rect1.area> filterNum*filterNum*1.5)
{
//class检测mat
Mat imgCls;
//此段为切图逻辑为:
//缺陷外扩5像素;
//判断最大边,大于class建网大小的,按照最大边尺寸比例切大图,然后resize为建网大小;最大边小于等于建网大小的,按照建网大小切图;
//越界填充
{
int startX = rect1.x - 5;
int startY = rect1.y - 5;
int endX = rect1.x + rect1.width + 5;
int endY = rect1.y + rect1.height + 5;
//尺寸比例
double maxscaler, scalerX, scalerY;
maxscaler = 1.0;
scalerX = (endX - startX) * 1.0 / sizeW;//*1.0转为float,避免被取整了
scalerY = (endY - startY) * 1.0 / sizeH;
maxscaler = max(maxscaler, max(scalerX, scalerY));
int avgX = (rect1.x + rect1.x + rect1.width) / 2; //中点X位置
int avgY = (rect1.y + rect1.y + rect1.height) / 2;//中点Y位置
startX = avgX - int(maxscaler * sizeW / 2);//强转为int
endX = startX + int(maxscaler * sizeW);
startY = avgY - int(maxscaler * sizeH / 2);
endY = startY + int(maxscaler * sizeH);
//判断是否越界,越界要填充的像素个数
int copyTop = max(0, 0 - startY);
int copyButton = max(0, endY - sourceImg.rows);
int copyLeft = max(0, 0 - startX);
int copyRight = max(0, endX - sourceImg.cols);
//切图不要越界,会崩溃
Mat imgCut = sourceImg(Range(max(0, startY - copyTop), min(sourceImg.rows, endY - copyButton)),
Range(max(0, startX - copyLeft), min(sourceImg.cols, endX - copyRight))); //起始行,终止行;起始列,终止列
//图像扩充
if (sourceImg.channels() == 1)
{
copyMakeBorder(imgCut, imgCut, copyTop, copyButton, copyLeft, copyRight, BORDER_CONSTANT, fillColour);
}
else
{
copyMakeBorder(imgCut, imgCut, copyTop, copyButton, copyLeft, copyRight, BORDER_CONSTANT, Scalar(fillColour, fillColour, fillColour));
}
//resize为建网大小
cv::resize(imgCut, imgCls, cv::Size(sizeW, sizeH));
imgCut.release();
}
int resultClass = 0;
float prob = 1.0;
resultClass = pCls->Evaluate(imgCls); //类别id
prob = pCls->getProbability(); //可能性
//切图保存,按需
{
isDirExist(classImgSaveDir + mysaveKey1 + "/class_" + QString::number(resultClass));
//存图数据入队,按需
addImgToSaveStruct(imgCls, mysaveKey1, classImgSaveDir + mysaveKey1 + "/class_" + QString::number(resultClass) + "/" + mySN + myDataTime + QString::number(j) + ".bmp");
}
//此处应添加缺陷计数逻辑
if (resultClass == 0)//OK
{
;
}
else if (resultClass == 1)//划伤Scratch
{
resIfNg = true;
//rectangle(sourceRectangles, rect1.tl(), rect1.br(), Scalar(0, 0, 255), 3, 8);
////可行,必须转一下格式
//{
// QString pathQstr = "划伤";
// QByteArray path_arr = pathQstr.toLocal8Bit();
// const char* path = path_arr.data();
// putTextZH(sourceRectangles, path, cv::Point(rect1.tl().x, rect1.tl().y - 5), Scalar(255, 0, 0), 50, "微软雅黑");
//}
defectInfo mdefectInfo;
mdefectInfo.defectName = "划伤";
mdefectInfo.defectRect = rect1;
mdefectInfo.defectArea = contourArea(contours[j]);
mdefectInfo.defectScalar = cv::Scalar(0, 0, 255);
defectInfoList.enqueue(mdefectInfo);
}
else if (resultClass == 2)//碰伤
{
resIfNg = true;
defectInfo mdefectInfo;
mdefectInfo.defectName = "碰伤";
mdefectInfo.defectRect = rect1;
mdefectInfo.defectArea = contourArea(contours[j]);
mdefectInfo.defectScalar = cv::Scalar(0, 255, 255);
defectInfoList.enqueue(mdefectInfo);
}
imgCls.release();
}
else {
//cout << "ng is too small<" << filterNum << endl;
continue;
}
}
}
//cv::Mat resMat = img2D.clone();
sourceRectangles.release();
contours.resize(0);
resultDstImg.release();
}
*/
detect_mutex->lock();
//resMat = sourceImg.clone();
//sourceImg.copyTo(resMat);
resMat.push_back(sourceImg);
//结果图画框和缺陷,在resMat上绘制
if (resMat.size() > 0)
drawDefects(resMat[0], defectInfoList);
//QByteArray,根据实际项目进行解析
//参数,例:返回结果图;相机关键字(SN或userID)+保存路径+缺陷信息列表(缺陷名称,缺陷位置int(x,y,w,h),画框颜色Scalar(a,b,c),缺陷面积double)
QJsonArray detaillists;
//QByteArrayList resQbyte;
for (int i = 0; i < defectInfoList.size(); i++)
{
defectInfo mdefect = defectInfoList[i];
//resQbyte.push_back(mdefect.defectName.toLocal8Bit()); //中文也可以QString::number(1.1).toUtf8()
//resQbyte.push_back(QString::number(mdefect.defectRect.x).toUtf8());
//resQbyte.push_back(QString::number(mdefect.defectRect.y).toUtf8());
//resQbyte.push_back(QString::number(mdefect.defectRect.width).toUtf8());
//resQbyte.push_back(QString::number(mdefect.defectRect.height).toUtf8());
//resQbyte.push_back(QString::number(mdefect.defectScalar[0]).toUtf8());
//resQbyte.push_back(QString::number(mdefect.defectScalar[1]).toUtf8());
//resQbyte.push_back(QString::number(mdefect.defectScalar[2]).toUtf8());
//resQbyte.push_back(QString::number(mdefect.defectArea).toUtf8());
QJsonObject detailObj;
detailObj.insert("defectName", "mdefect.defectName");
detailObj.insert("defectRect.x", QString::number(mdefect.defectRect.x));
detailObj.insert("defectRect.y", QString::number(mdefect.defectRect.y));
detailObj.insert("defectRect.width", QString::number(mdefect.defectRect.width));
detailObj.insert("defectRect.height", QString::number(mdefect.defectRect.height));
detailObj.insert("defectScalar0", QString::number(mdefect.defectScalar[0]));
detailObj.insert("defectScalar1", QString::number(mdefect.defectScalar[1]));
detailObj.insert("defectScalar2", QString::number(mdefect.defectScalar[2]));
detailObj.insert("defectArea", QString::number(mdefect.defectArea));
detailObj.insert("defectLength", QString::number(sqrt(mdefect.defectRect.width* mdefect.defectRect.width+ mdefect.defectRect.height* mdefect.defectRect.height)));
detaillists.append(detailObj);
}
//使用完删除
defectInfoList.clear();
//往主界面发
//emit sendResultData(resMat, resQbyte);
//resQbyte.clear();
isDirExist(resImgSaveDir + mysaveKey1 + "/");
QString qimgsavePath = resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png";
//存图数据入队,按需
if (resMat.size() > 0 )
addImgToSaveStruct(resMat[0], mysaveKey1, resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png");
detect_mutex->unlock();
obj.insert("detaillists", detaillists);
obj.insert("qimgsavePath", qimgsavePath);
document.setObject(obj);
//resByte.clear();
QByteArray qa = document.toJson();
//resByte .enqueue(qa);
//resMat.release();
sourceImg.release();
mySave.out_Mat.resize(0);
mysaveKey1.clear();
qApp->processEvents();
////原图和结果都往主界面发?
//std::vector<cv::Mat> resMat;
//resMat.push_back(img2D);
//resMat.push_back(sourceRectangles);
//QByteArray resByte = mysaveKey.toLocal8Bit();
//resByte.append(myDir2D.toLocal8Bit());
//resByte.append(mySN.toLocal8Bit());
//resByte.append(myDataTime.toLocal8Bit());
////往主界面发送图片和数据
////emit writeData(resMat, resByte);
//resMat.resize(0);
//resByte.resize(0);
}
catch (...)
{
qDebug() << "[Error] " << QString::fromUtf8("检测失败!");
return false;
}
return true;
}
//存图加入队列
void Hd_AI_empty_module::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QString savePath)
{
//存图数据加保存队列,加锁,避免数据访问冲突
saveStruct_mutex->lock();
saveImgStruct mySave;
mySave.out_Mat = img2D.clone();
//img2D.copyTo(mySave.out_Mat);
mySave.saveKey = (mysaveKey).toStdString();
mySave.savePath = (savePath).toStdString();
saveStruct.enqueue(mySave);
saveStruct_mutex->unlock();
}
void Hd_AI_empty_module::saveImgThread()
{
while (1)
{
if (!ifdetectThread)return;
_sleep(1);
qApp->processEvents();
if (saveStruct.size() < 1)continue;
for (int i = 0; i < saveStruct.size(); i++)
{
clock_t start, stop;
start = clock();
saveStruct_mutex->lock();
saveImgStruct mysaveStruct = saveStruct.dequeue();
saveStruct_mutex->unlock();
stop = clock();
if(stop-start >1000)
std::cout << "lock stop-start >1000::************************" << stop - start << std::endl;
start = clock();
//if (mysaveStruct.out_Mat.data)imwrite(mysaveStruct.savePath, mysaveStruct.out_Mat);
//std::cout << "savePath::" << mysaveStruct.savePath << std::endl;
stop = clock();
if (stop - start > 1000)
std::cout << "imwrite stop-start >1000::--------------------------"<< stop - start << std::endl;
_sleep(1);
}
}
}
//检测线程,应当只运行一次
void Hd_AI_empty_module::detectThread()
{
do
{
if (!ifdetectThread)return;
//此两行代码,避免程序卡死;_sleep的时间根据实际项目调整
_sleep(2);
qApp->processEvents();
//取数据加锁,避免数据访问冲突
detect_mutex->lock();
//if (HikMat.size() < 1 || saveKey.size() < 1 || Dir2D.size() < 1 || SN.size() < 1 )//|| DateTime1.size() < 1)
//{
// detect_mutex->unlock();
// continue;
//}
cv::Mat sourceImg1 = HikMat[0];// .dequeue();
QString mysaveKey = "saveKey";// .dequeue();
QString myDir2D = "Dir2D";// .dequeue();
QString mySN = "SN";// .dequeue();
QString myDataTime = "DateTime1";
detect_mutex->unlock();
//判断存图文件夹是否存在,不存在则创建
{
//原图总文件夹
isDirExist(oriImgSaveDir + mysaveKey);
//原图class总文件夹
isDirExist(classImgSaveDir + mysaveKey);
//结果图总文件夹
isDirExist(resImgSaveDir + mysaveKey);
}
//测试相机的,
while (sourceImg1.cols > 2000)cv::resize(sourceImg1, sourceImg1, cv::Size(), 0.5, 0.5);
//存图数据入队
//addImgToSaveStruct(sourceImg1, mysaveKey, oriImgSaveDir + mysaveKey + "/" + mySN + myDataTime + ".bmp");
//-------检测流程,根据实际项目修改---------
AIdetect(sourceImg1, mysaveKey, oriImgSaveDir, mySN, myDataTime);
//sourceImg1.release();
mysaveKey.clear();
myDir2D.clear();
mySN.clear();
myDataTime.clear();
qApp->processEvents();
} while (ifThreadRunDetect);
}
static int runNum = 0;
bool Hd_AI_empty_module::run()
{
clock_t start, stop;
start = clock();
//Sleep(1000);
//detectThread();
//stop = clock();
//qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"<<stop-start;
//qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << "Mat_name: " << Mat_name << " run end";
return true;
}
bool Hd_AI_empty_module::checkStatus()
{
status = moduleStatus;
return status;
}