This commit is contained in:
Main
2025-02-15 09:49:12 +08:00
parent 7adf21c978
commit 26f7b7bb47
30 changed files with 29418 additions and 2825 deletions
@@ -1,921 +0,0 @@
#include "Hd_AI_2D3Ddata_module.h"
#include <QDateTime>
#include <QtConcurrent/QtConcurrent>
#include <qfuture.h>
#pragma execution_character_set("utf-8")
using namespace cv;
using namespace std;
//原图保存文件夹
static QString oriImgSaveDir = "F:/ORI/";
//原图class图保存文件夹
static QString classImgSaveDir = "F:/ORIclass/";
//结果保存文件夹
static QString resImgSaveDir = "F:/res/";
//切图的class的width,根据项目实际设置!
static int sizeW = 150;
//切图的class的height,根据项目实际设置!
static int sizeH = 150;
//切图的class的width,根据项目实际设置!0为黑,255为白;
static int fillColour = 0;
//检测线程锁
static QMutex* detect_mutex;
//保存线程锁
static QMutex* saveStruct_mutex;
//检测线程运行标志
static bool ifdetectThread = false;
// 缺陷信息结构体
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_2D3Ddata_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_2D3Ddata_module* create()
{
qDebug() << "[INFO] " << " Hd_AI_2D3Ddata_module create success!" ;
return new Hd_AI_2D3Ddata_module;
}
void destory(Hd_AI_2D3Ddata_module* ptr)
{
qDebug() << "[INFO] " << "Hd_AI_2D3Ddata_module destory success!";
if(ptr)
{
delete ptr;
ptr = nullptr;
}
}
Hd_AI_2D3Ddata_module::Hd_AI_2D3Ddata_module()
{
detect_mutex = new QMutex;
saveStruct_mutex = new QMutex;
ifdetectThread = false;
}
Hd_AI_2D3Ddata_module::~Hd_AI_2D3Ddata_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);*/
}
QByteArray m_writeData;
static int defectNums = 0;
//static cv::Mat resMat;
//从类中读数据到实例对象
bool Hd_AI_2D3Ddata_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
{
if(HikMat.size())
vec_mat.push_back(HikMat[0]);
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " resMat.data err:";
}
//if (allNum++ % 21 == 20)
// data = "2";// resByte.dequeue();
//else
//if (allNum++ % 2 == 0)
// data = "0*2*3*2";// resByte.dequeue();
//else
data = "1";// "0*1*2*3";//1OK,2NG
resByte.clear();
////之后根据结果类修改
//if(resIfNg == true)
// data = "NG";
//else data = "OK";
detect_mutex->unlock();
return true;
}
//从类中读数据到实例对象
bool Hd_AI_2D3Ddata_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;
}
//接收数据
bool Hd_AI_2D3Ddata_module::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &data)
{
m_writeData = 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]);
//测试相机的,
//while (HikMat[0].cols > 2000)cv::resize(HikMat[0], HikMat[0], cv::Size(), 0.1, 0.1);
//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();
//cv::Mat resultDstImg = vec_mat[0].clone();// = pSeg->Evaluate(sourceImg); //返回单通道二值图 图片错误输出Image Error!但不报错。。
//resultDstImg = pSeg->Evaluate(resultDstImg);
//resultDstImg.release();
return true;
}
//初始化
bool Hd_AI_2D3Ddata_module::initParas(QByteArray& byte)
{
//if(byte.isEmpty())
//{
// qCritical() << "[Error] " << " byte is null!";
// return false;
//}
//QVector<QByteArray> vec_ret;
//decodeAiValue(byte,vec_ret);
//if(vec_ret.isEmpty())
//{
// qCritical() << "[Error] " << " vec_ret is null!";
// return false;
//}
///*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_2D3Ddata_module::detectThread);
////运行存图线程
//QFuture<void> future2 = QtConcurrent::run(this, &Hd_AI_2D3Ddata_module::saveImgThread);
////detectThread();
////原图总文件夹
//isDirExist(oriImgSaveDir);
////原图class总文件夹
//isDirExist(classImgSaveDir);
////结果图总文件夹
//isDirExist(resImgSaveDir);
wstring taskPath = L"task\\haiwai_demo_model1\\haiwai_demo_model1.task";
wcout.imbue(locale("zh_CN"));
//bool ret = instance(taskPath, 0);
//if (!ret)
//{
// //销毁实例
// destroyInstance();
// cout << "run task false\n";
// return false;
//}
//vector<Mat> srcMats;
//vector<RESULTDATA1> results;
////传入图片vector 和 接收结果的容器
//ret = PBTASK_EXPORT::run(srcMats, results);//初始化一下AI模型
//qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ;
return true;
}
// 解码
bool Hd_AI_2D3Ddata_module::decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret)
{
if(byte.isEmpty())
{
qCritical() << "[Error] " << " byte is null!";
return false;
}
/*******************************************/
byte.remove(0,8);
QByteArray mm_data = byte.mid(0,4);
memcpy((void*)&paramNum,(void*)mm_data.data(), 4);
qDebug() << "[INFO] " << " paramNum:" << paramNum;
byte.remove(0,4);
/*******************************************/
while (!byte.isEmpty())
{
int type = 0;
QByteArray m_type = byte.mid(0,4);
memcpy((void*)&type,(void*)m_type.data(), 4);
byte.remove(0,4);
int len = 0;
QByteArray m_len = byte.mid(0,4);
memcpy((void*)&len,(void*)m_len.data(), 4);
byte.remove(0,4);
QByteArray mm_data = byte.mid(0,len);
vec_ret.append(mm_data);
byte.remove(0,len);
}
return true;
}
//---------检测流程,根据实际项目修改---------
bool Hd_AI_2D3Ddata_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_2D3Ddata_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_2D3Ddata_module::saveImgThread()
{
while (1)
{
if (!ifdetectThread)return;
_sleep(1);
qApp->processEvents();
if (saveStruct.size() < 1)continue;
for (int i = 0; i < saveStruct.size(); i++)
{
saveStruct_mutex->lock();
saveImgStruct mysaveStruct = saveStruct.dequeue();
saveStruct_mutex->unlock();
//if (mysaveStruct.out_Mat.data)imwrite(mysaveStruct.savePath, mysaveStruct.out_Mat);
//std::cout << "savePath::" << mysaveStruct.savePath << std::endl;
_sleep(1);
}
}
}
//检测线程,应当只运行一次
void Hd_AI_2D3Ddata_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);
}
bool myMath(double a, double b)
{
return a > b;
}
static int runNum = 0;
QQueue<double> timeAll_A;
QQueue<double> timeAll_B;
bool Hd_AI_2D3Ddata_module::run()
{
defectNums = 0;
vector<Mat> srcMats;
clock_t start = 0;
clock_t stop = 0;
double time = 0;
//cv::Mat mat;
float prob = 0;
if (HikMat.isEmpty())
return true;
srcMats.push_back(HikMat[0]);
start = clock();
stop = clock();
time = stop - start;
timeAll_B.enqueue(time);
start = clock();
qSort(timeAll_A.begin(), timeAll_A.end(), myMath);
qSort(timeAll_B.begin(), timeAll_B.end(), myMath);
timeAll_A.rend();
timeAll_B.rend();
//Sleep(50);
//detectThread();
//stop = clock();
qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum<<" cutTime::"<<stop-start;
runNum++;
//qDebug() << "[INFO] " << "Mat_name: " << Mat_name << " run end";
return true;
}
bool Hd_AI_2D3Ddata_module::checkStatus()
{
status = moduleStatus;
return status;
}
@@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(TIMESTAMP RUN_TIME)
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
set(DLL_NAMES "opencv" "handdleAI3.0")
set(DLL_NAMES "opencv" "halcon" "halconAlgo" "myTools" "handdleAI")
foreach(child ${DLL_NAMES})
LIST(APPEND ENV_INCLUDE ${${child}_include})
LIST(APPEND ENV_LIB ${${child}_lib})
@@ -39,7 +39,7 @@ FILE(GLOB UI_FILES "./*.ui")
#find_package(Qt5 COMPONENTS Core REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED)
add_library(${CURRENT_FOLDER} SHARED
${HEAD_FILES}
${SRC_FILES}
@@ -58,6 +58,7 @@ set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C
target_link_libraries(${CURRENT_FOLDER} PRIVATE
${ENV_TARGET}
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
)
@@ -1,5 +1,5 @@
#ifndef Hd_AI_empty_module_H
#define Hd_AI_empty_module_H
#ifndef Hd_AI_algo_jierFanZhe_UP_H
#define Hd_AI_algo_jierFanZhe_UP_H
#include <assert.h>
#include <atlstr.h>
@@ -15,13 +15,12 @@
#include <fstream>
#include <string>
#include <ctime>
#include <halconcpp/HalconCpp.h>
#include <opencv2/opencv.hpp>
#include "imgproc/imgproc_c.h"
#include "base.h"
#include "handleAI.h"
#include <HDevEngineCpp.h>
#pragma execution_character_set("utf-8")
@@ -34,16 +33,16 @@ struct saveImgStruct;
// std::string savePath; //保存路径
//};
//初始化流程(一次):Hd_AI_empty_module,initParas
//初始化流程(一次):Hd_AI_algo_jierFanZhe_UP,initParas
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
class Hd_AI_empty_module :public Base
class Hd_AI_algo_jierFanZhe_UP :public Base
{
Q_OBJECT
public:
Hd_AI_empty_module();
virtual ~Hd_AI_empty_module();
Hd_AI_algo_jierFanZhe_UP();
virtual ~Hd_AI_algo_jierFanZhe_UP();
//从类中读数据到实例对象
bool readData(std::vector<cv::Mat>&,QByteArray&);
bool readData(std::vector<cv::Mat>&, QByteArray&);
//实例对象把数据写入到类
bool writeData(std::vector<cv::Mat>&, QByteArray&);
bool initParas(QByteArray&);
@@ -52,17 +51,17 @@ public:
//线程状态
bool checkStatus();// { return true; };
bool encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte);
bool decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret);
bool encodeResultValue(QVector<std::string> append_value, QByteArray& resultByte);
bool decodeAiValue(QByteArray byte, QVector<QByteArray>& vec_ret);
//---------检测流程,根据实际项目修改---------
bool AIdetect(cv::Mat img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime);
handdleAI::pSegmentation* seg_jierFanZhe;
handdleAI::pClassification* cls_jierFanZhe;
private:
clock_t ctStart, ctStop;
HDevEngineCpp::HDevEngine myEngine;
int allNum = 0;
int StationNo=0;
int StationNo = 0;
int img2D = 2;
bool moduleStatus = true;
@@ -70,13 +69,13 @@ private:
//输入图片队列
QQueue<cv::Mat> HikMat;
//输入关键字队列
QString saveKey="saveKey";
QString saveKey = "saveKey";
//结果路径文件夹队列
QString Dir2D="Dir2D";
QString Dir2D = "Dir2D";
//产品SN队列
QString SN="SN";
QString SN = "SN";
//产品时间戳队列
QString DateTime1="DateTime1";
QString DateTime1 = "DateTime1";
int paramNum;
@@ -93,7 +92,7 @@ private:
void detectThread();
//存图线程
void saveImgThread();
//保存图片队列
QQueue<saveImgStruct> saveStruct;
@@ -106,8 +105,8 @@ private:
extern "C"
{
Q_DECL_EXPORT Hd_AI_empty_module * create();
Q_DECL_EXPORT void destory(Hd_AI_empty_module * ptr);
Q_DECL_EXPORT Hd_AI_algo_jierFanZhe_UP* create();
Q_DECL_EXPORT void destory(Hd_AI_algo_jierFanZhe_UP* ptr);
}
//保存图片的结构体
struct saveImgStruct
@@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(TIMESTAMP RUN_TIME)
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
set(DLL_NAMES "opencv" "halcon")
set(DLL_NAMES "opencv" "halcon" "halconAlgo" "myTools" "handdleAI")
foreach(child ${DLL_NAMES})
LIST(APPEND ENV_INCLUDE ${${child}_include})
LIST(APPEND ENV_LIB ${${child}_lib})
@@ -39,7 +39,7 @@ FILE(GLOB UI_FILES "./*.ui")
#find_package(Qt5 COMPONENTS Core REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED)
add_library(${CURRENT_FOLDER} SHARED
${HEAD_FILES}
${SRC_FILES}
@@ -58,6 +58,7 @@ set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C
target_link_libraries(${CURRENT_FOLDER} PRIVATE
${ENV_TARGET}
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
)
@@ -1,5 +1,5 @@
#ifndef Hd_AI_tmp_module_savImg_H
#define Hd_AI_tmp_module_savImg_H
#ifndef Hd_AI_algo_jierFanZhe_UP_H
#define Hd_AI_algo_jierFanZhe_UP_H
#include <assert.h>
#include <atlstr.h>
@@ -15,13 +15,12 @@
#include <fstream>
#include <string>
#include <ctime>
#include <halconcpp/HalconCpp.h>
#include <opencv2/opencv.hpp>
#include "imgproc/imgproc_c.h"
#include "base.h"
#include "handleAI.h"
#include <HDevEngineCpp.h>
#pragma execution_character_set("utf-8")
@@ -34,16 +33,16 @@ struct saveImgStruct;
// std::string savePath; //保存路径
//};
//初始化流程(一次):Hd_AI_tmp_module_savImg,initParas
//初始化流程(一次):Hd_AI_algo_jierFanZhe_UP,initParas
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
class Hd_AI_tmp_module_savImg :public Base
class Hd_AI_algo_jierFanZhe_UP :public Base
{
Q_OBJECT
public:
Hd_AI_tmp_module_savImg();
virtual ~Hd_AI_tmp_module_savImg();
Hd_AI_algo_jierFanZhe_UP();
virtual ~Hd_AI_algo_jierFanZhe_UP();
//从类中读数据到实例对象
bool readData(std::vector<cv::Mat>&,QByteArray&);
bool readData(std::vector<cv::Mat>&, QByteArray&);
//实例对象把数据写入到类
bool writeData(std::vector<cv::Mat>&, QByteArray&);
bool initParas(QByteArray&);
@@ -52,17 +51,17 @@ public:
//线程状态
bool checkStatus();// { return true; };
bool encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte);
bool decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret);
bool encodeResultValue(QVector<std::string> append_value, QByteArray& resultByte);
bool decodeAiValue(QByteArray byte, QVector<QByteArray>& vec_ret);
//---------检测流程,根据实际项目修改---------
bool AIdetect(cv::Mat img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime);
handdleAI::pSegmentation* seg_jierFanZhe;
handdleAI::pClassification* cls_jierFanZhe;
private:
clock_t ctStart, ctStop;
HDevEngineCpp::HDevEngine myEngine;
int allNum = 0;
int StationNo=0;
int StationNo = 0;
int img2D = 2;
bool moduleStatus = true;
@@ -70,13 +69,13 @@ private:
//输入图片队列
QQueue<cv::Mat> HikMat;
//输入关键字队列
QString saveKey="saveKey";
QString saveKey = "saveKey";
//结果路径文件夹队列
QString Dir2D="Dir2D";
QString Dir2D = "Dir2D";
//产品SN队列
QString SN="SN";
QString SN = "SN";
//产品时间戳队列
QString DateTime1="DateTime1";
QString DateTime1 = "DateTime1";
int paramNum;
@@ -93,7 +92,7 @@ private:
void detectThread();
//存图线程
void saveImgThread();
//保存图片队列
QQueue<saveImgStruct> saveStruct;
@@ -106,8 +105,8 @@ private:
extern "C"
{
Q_DECL_EXPORT Hd_AI_tmp_module_savImg * create();
Q_DECL_EXPORT void destory(Hd_AI_tmp_module_savImg * ptr);
Q_DECL_EXPORT Hd_AI_algo_jierFanZhe_UP* create();
Q_DECL_EXPORT void destory(Hd_AI_algo_jierFanZhe_UP* ptr);
}
//保存图片的结构体
struct saveImgStruct
@@ -1,4 +1,4 @@
#ifndef __BASECLASS_H__
#ifndef __BASECLASS_H__
#define __BASECLASS_H__
#include <iostream>
@@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(TIMESTAMP RUN_TIME)
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
set(DLL_NAMES "opencv" "halcon")
set(DLL_NAMES "opencv" "halcon" "halconAlgo" "myTools" "handdleAI")
foreach(child ${DLL_NAMES})
LIST(APPEND ENV_INCLUDE ${${child}_include})
LIST(APPEND ENV_LIB ${${child}_lib})
@@ -39,7 +39,7 @@ FILE(GLOB UI_FILES "./*.ui")
#find_package(Qt5 COMPONENTS Core REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED)
add_library(${CURRENT_FOLDER} SHARED
${HEAD_FILES}
${SRC_FILES}
@@ -58,6 +58,7 @@ set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C
target_link_libraries(${CURRENT_FOLDER} PRIVATE
${ENV_TARGET}
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
)
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
#ifndef Hd_AI_seg_module_H
#define Hd_AI_seg_module_H
#ifndef Hd_AI_algo_jierFanZhe_UP_H
#define Hd_AI_algo_jierFanZhe_UP_H
#include <assert.h>
#include <atlstr.h>
@@ -15,13 +15,12 @@
#include <fstream>
#include <string>
#include <ctime>
#include <halconcpp/HalconCpp.h>
#include <opencv2/opencv.hpp>
#include "imgproc/imgproc_c.h"
#include "base.h"
#include "handleAI.h"
#include <HDevEngineCpp.h>
#pragma execution_character_set("utf-8")
@@ -34,16 +33,16 @@ struct saveImgStruct;
// std::string savePath; //保存路径
//};
//初始化流程(一次):Hd_AI_seg_module,initParas
//初始化流程(一次):Hd_AI_algo_jierFanZhe_UP,initParas
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
class Hd_AI_seg_module :public Base
class Hd_AI_algo_jierFanZhe_UP :public Base
{
Q_OBJECT
public:
Hd_AI_seg_module();
virtual ~Hd_AI_seg_module();
Hd_AI_algo_jierFanZhe_UP();
virtual ~Hd_AI_algo_jierFanZhe_UP();
//从类中读数据到实例对象
bool readData(std::vector<cv::Mat>&,QByteArray&);
bool readData(std::vector<cv::Mat>&, QByteArray&);
//实例对象把数据写入到类
bool writeData(std::vector<cv::Mat>&, QByteArray&);
bool initParas(QByteArray&);
@@ -52,17 +51,17 @@ public:
//线程状态
bool checkStatus();// { return true; };
bool encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte);
bool decodeAiValue(QByteArray byteArray,QVector<QByteArray> &vec_ret);
bool encodeResultValue(QVector<std::string> append_value, QByteArray& resultByte);
bool decodeAiValue(QByteArray byte, QVector<QByteArray>& vec_ret);
//---------检测流程,根据实际项目修改---------
bool AIdetect(cv::Mat img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime);
handdleAI::pSegmentation* seg_jierFanZhe;
handdleAI::pClassification* cls_jierFanZhe;
private:
clock_t ctStart, ctStop;
HDevEngineCpp::HDevEngine myEngine;
int allNum = 0;
int StationNo;
int StationNo = 0;
int img2D = 2;
bool moduleStatus = true;
@@ -70,13 +69,13 @@ private:
//输入图片队列
QQueue<cv::Mat> HikMat;
//输入关键字队列
QString saveKey="saveKey";
QString saveKey = "saveKey";
//结果路径文件夹队列
QString Dir2D="Dir2D";
QString Dir2D = "Dir2D";
//产品SN队列
QString SN="SN";
QString SN = "SN";
//产品时间戳队列
QString DateTime1="DateTime1";
QString DateTime1 = "DateTime1";
int paramNum;
@@ -93,7 +92,7 @@ private:
void detectThread();
//存图线程
void saveImgThread();
//保存图片队列
QQueue<saveImgStruct> saveStruct;
@@ -106,8 +105,8 @@ private:
extern "C"
{
Q_DECL_EXPORT Hd_AI_seg_module * create();
Q_DECL_EXPORT void destory(Hd_AI_seg_module * ptr);
Q_DECL_EXPORT Hd_AI_algo_jierFanZhe_UP* create();
Q_DECL_EXPORT void destory(Hd_AI_algo_jierFanZhe_UP* ptr);
}
//保存图片的结构体
struct saveImgStruct
@@ -1,4 +1,4 @@
#ifndef __BASECLASS_H__
#ifndef __BASECLASS_H__
#define __BASECLASS_H__
#include <iostream>
@@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(TIMESTAMP RUN_TIME)
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
set(DLL_NAMES "opencv" "handdleAI3.0")
set(DLL_NAMES "opencv" "halcon" "halconAlgo" "myTools" "handdleAI")
foreach(child ${DLL_NAMES})
LIST(APPEND ENV_INCLUDE ${${child}_include})
LIST(APPEND ENV_LIB ${${child}_lib})
@@ -39,7 +39,7 @@ FILE(GLOB UI_FILES "./*.ui")
#find_package(Qt5 COMPONENTS Core REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED)
add_library(${CURRENT_FOLDER} SHARED
${HEAD_FILES}
${SRC_FILES}
@@ -58,6 +58,7 @@ set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C
target_link_libraries(${CURRENT_FOLDER} PRIVATE
${ENV_TARGET}
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
)
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
#ifndef Hd_AI_2D3Ddata_module_H
#define Hd_AI_2D3Ddata_module_H
#ifndef Hd_AI_algo_jierFanZhe_UP_H
#define Hd_AI_algo_jierFanZhe_UP_H
#include <assert.h>
#include <atlstr.h>
@@ -15,13 +15,12 @@
#include <fstream>
#include <string>
#include <ctime>
#include <halconcpp/HalconCpp.h>
#include <opencv2/opencv.hpp>
#include "imgproc/imgproc_c.h"
#include "base.h"
#include "handleAI.h"
#include <HDevEngineCpp.h>
#pragma execution_character_set("utf-8")
@@ -34,16 +33,16 @@ struct saveImgStruct;
// std::string savePath; //保存路径
//};
//初始化流程(一次):Hd_AI_2D3Ddata_module,initParas
//初始化流程(一次):Hd_AI_algo_jierFanZhe_UP,initParas
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
class Hd_AI_2D3Ddata_module :public Base
class Hd_AI_algo_jierFanZhe_UP :public Base
{
Q_OBJECT
public:
Hd_AI_2D3Ddata_module();
virtual ~Hd_AI_2D3Ddata_module();
Hd_AI_algo_jierFanZhe_UP();
virtual ~Hd_AI_algo_jierFanZhe_UP();
//从类中读数据到实例对象
bool readData(std::vector<cv::Mat>&,QByteArray&);
bool readData(std::vector<cv::Mat>&, QByteArray&);
//实例对象把数据写入到类
bool writeData(std::vector<cv::Mat>&, QByteArray&);
bool initParas(QByteArray&);
@@ -52,17 +51,17 @@ public:
//线程状态
bool checkStatus();// { return true; };
bool encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte);
bool decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret);
bool encodeResultValue(QVector<std::string> append_value, QByteArray& resultByte);
bool decodeAiValue(QByteArray byte, QVector<QByteArray>& vec_ret);
//---------检测流程,根据实际项目修改---------
bool AIdetect(cv::Mat img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime);
handdleAI::pSegmentation* seg_jierFanZhe;
handdleAI::pClassification* cls_jierFanZhe;
private:
clock_t ctStart, ctStop;
HDevEngineCpp::HDevEngine myEngine;
int allNum = 0;
int StationNo;
int StationNo = 0;
int img2D = 2;
bool moduleStatus = true;
@@ -70,13 +69,13 @@ private:
//输入图片队列
QQueue<cv::Mat> HikMat;
//输入关键字队列
QString saveKey="saveKey";
QString saveKey = "saveKey";
//结果路径文件夹队列
QString Dir2D="Dir2D";
QString Dir2D = "Dir2D";
//产品SN队列
QString SN="SN";
QString SN = "SN";
//产品时间戳队列
QString DateTime1="DateTime1";
QString DateTime1 = "DateTime1";
int paramNum;
@@ -93,7 +92,7 @@ private:
void detectThread();
//存图线程
void saveImgThread();
//保存图片队列
QQueue<saveImgStruct> saveStruct;
@@ -106,8 +105,8 @@ private:
extern "C"
{
Q_DECL_EXPORT Hd_AI_2D3Ddata_module * create();
Q_DECL_EXPORT void destory(Hd_AI_2D3Ddata_module * ptr);
Q_DECL_EXPORT Hd_AI_algo_jierFanZhe_UP* create();
Q_DECL_EXPORT void destory(Hd_AI_algo_jierFanZhe_UP* ptr);
}
//保存图片的结构体
struct saveImgStruct
@@ -1,4 +1,4 @@
#ifndef __BASECLASS_H__
#ifndef __BASECLASS_H__
#define __BASECLASS_H__
#include <iostream>
@@ -1,918 +0,0 @@
#include "Hd_AI_seg_module.h"
#include <QDateTime>
#include <QtConcurrent/QtConcurrent>
#include <qfuture.h>
#pragma execution_character_set("utf-8")
using namespace cv;
using namespace std;
//原图保存文件夹
static QString oriImgSaveDir = "F:/ORI/";
//原图class图保存文件夹
static QString classImgSaveDir = "F:/ORIclass/";
//结果保存文件夹
static QString resImgSaveDir = "F:/res/";
//切图的class的width,根据项目实际设置!
static int sizeW = 150;
//切图的class的height,根据项目实际设置!
static int sizeH = 150;
//切图的class的width,根据项目实际设置!0为黑,255为白;
static int fillColour = 0;
//检测线程锁
static QMutex* detect_mutex;
//保存线程锁
static QMutex* saveStruct_mutex;
//检测线程运行标志
static bool ifdetectThread = false;
// 缺陷信息结构体
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_seg_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_seg_module* create()
{
qDebug() << "[INFO] " << " Hd_AI_seg_module create success!" ;
return new Hd_AI_seg_module;
}
void destory(Hd_AI_seg_module* ptr)
{
qDebug() << "[INFO] " << "Hd_AI_seg_module destory success!";
if(ptr)
{
delete ptr;
ptr = nullptr;
}
}
Hd_AI_seg_module::Hd_AI_seg_module()
{
detect_mutex = new QMutex;
saveStruct_mutex = new QMutex;
ifdetectThread = false;
}
Hd_AI_seg_module::~Hd_AI_seg_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);*/
}
static int defectNums = 0;
//static cv::Mat resMat;
//从类中读数据到实例对象
bool Hd_AI_seg_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";// resByte.dequeue();
//else
if (defectNums == 0)
data = "1";//1OK,2NG
else
data = "2";
resByte.clear();
////之后根据结果类修改
//if(resIfNg == true)
// data = "NG";
//else data = "OK";
detect_mutex->unlock();
return true;
}
//从类中读数据到实例对象
bool Hd_AI_seg_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;
}
//接收数据
bool Hd_AI_seg_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]);
//测试相机的,
//while (HikMat[0].cols > 2000)cv::resize(HikMat[0], HikMat[0], cv::Size(), 0.1, 0.1);
//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();
//cv::Mat resultDstImg = vec_mat[0].clone();// = pSeg->Evaluate(sourceImg); //返回单通道二值图 图片错误输出Image Error!但不报错。。
//resultDstImg = pSeg->Evaluate(resultDstImg);
//resultDstImg.release();
return true;
}
//初始化
bool Hd_AI_seg_module::initParas(QByteArray& byteArray)
{
//if(byteArray.isEmpty())
//{
// qCritical() << "[Error] " << " byteArray is null!";
// return false;
//}
//QVector<QByteArray> vec_ret;
//decodeAiValue(byteArray,vec_ret);
//if(vec_ret.isEmpty())
//{
// qCritical() << "[Error] " << " vec_ret is null!";
// return false;
//}
///*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_seg_module::detectThread);
////运行存图线程
//QFuture<void> future2 = QtConcurrent::run(this, &Hd_AI_seg_module::saveImgThread);
////detectThread();
////原图总文件夹
//isDirExist(oriImgSaveDir);
////原图class总文件夹
//isDirExist(classImgSaveDir);
////结果图总文件夹
//isDirExist(resImgSaveDir);
wstring taskPath = L"task\\haiwai_demo_model1\\haiwai_demo_model1.task";
wcout.imbue(locale("zh_CN"));
//bool ret = instance(taskPath, 0);
//if (!ret)
//{
// //销毁实例
// destroyInstance();
// cout << "run task false\n";
// return false;
//}
//vector<Mat> srcMats;
//vector<RESULTDATA1> results;
////传入图片vector 和 接收结果的容器
//ret = PBTASK_EXPORT::run(srcMats, results);//初始化一下AI模型
//qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ;
return true;
}
// 解码
bool Hd_AI_seg_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_seg_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_seg_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_seg_module::saveImgThread()
{
while (1)
{
if (!ifdetectThread)return;
_sleep(1);
qApp->processEvents();
if (saveStruct.size() < 1)continue;
for (int i = 0; i < saveStruct.size(); i++)
{
saveStruct_mutex->lock();
saveImgStruct mysaveStruct = saveStruct.dequeue();
saveStruct_mutex->unlock();
//if (mysaveStruct.out_Mat.data)imwrite(mysaveStruct.savePath, mysaveStruct.out_Mat);
//std::cout << "savePath::" << mysaveStruct.savePath << std::endl;
_sleep(1);
}
}
}
//检测线程,应当只运行一次
void Hd_AI_seg_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);
}
bool myMath(double a, double b)
{
return a > b;
}
static int runNum = 0;
QQueue<double> timeAll_A;
QQueue<double> timeAll_B;
bool Hd_AI_seg_module::run()
{
defectNums = 0;
vector<Mat> srcMats;
clock_t start = 0;
clock_t stop = 0;
double time = 0;
//cv::Mat mat;
float prob = 0;
if (HikMat.isEmpty())
return false;
srcMats.push_back(HikMat[0]);
start = clock();
stop = clock();
time = stop - start;
timeAll_B.enqueue(time);
start = clock();
qSort(timeAll_A.begin(), timeAll_A.end(), myMath);
qSort(timeAll_B.begin(), timeAll_B.end(), myMath);
timeAll_A.rend();
timeAll_B.rend();
//Sleep(50);
//detectThread();
//stop = clock();
//qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"<<stop-start;
runNum++;
//qDebug() << "[INFO] " << "Mat_name: " << Mat_name << " run end";
return true;
}
bool Hd_AI_seg_module::checkStatus()
{
status = moduleStatus;
return status;
}
@@ -374,8 +374,8 @@ bool Logic_camera_thread::saveImage(std::vector<cv::Mat> camera_mat)
//拍照面描述
QString Surface;
if(cameraProductSurface.size()>0)
Surface = cameraProductSurface[camera_index% cameraProductSurface.size()];
if (cameraProductSurface.size() > 0)
Surface = SN_signal;
//camera_index,0,1,2;cameraProductSurface,tp1,tp2;对应,tp1,tp2,tp1;
//qDebug() << "m_Module.module_key::" << m_Module.module_key << " saveImage getCameraData Time ::" << stop - start;
//添加到容器SnCameraData
@@ -811,10 +811,6 @@ bool Logic_taskthread::deleteSnData ( QByteArray byteArray, QVector<QString>& sn
bool Logic_taskthread::writeAiCommond ( QString cameraName,QString camera_name_index,QByteArray byteArray )
{
QByteArrayList PLCvec_ret= logicUiTransport::decodePlcResult(byteArray); // 存储结果的
std::map<QString, QVariant> CsvAndChartData =
logicUiTransport::decodeCsvAndChartData(byteArray);//发送导表格或者数据库的
_CsvWriter.addtData(CsvAndChartData["条码"].toString(), CsvAndChartData);//写入csv文件
if (PLCvec_ret.isEmpty() )
{
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " vec_ret is null!";
@@ -10,7 +10,7 @@
#include <Windows.h>
#include "struct.h"
#include <rlib/rlib_writeCsv.h>
#pragma execution_character_set("utf-8") //能够正常显示中文字符串
class Logic_taskthread : public QThread
{
@@ -81,7 +81,6 @@ public:
QString CmdHeadShort = "write_short_";
QString CmdHeadString = "write_string_";
private:
CsvWriter _CsvWriter;
QQueue<dataPack> taskImageDataPack;
QMutex* task_image_lock = nullptr;
int mysaveimagethreadindex = -1;