备份x
This commit is contained in:
@@ -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*)¶mNum,(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
-2
@@ -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
|
||||
)
|
||||
|
||||
|
||||
+433
-307
File diff suppressed because it is too large
Load Diff
+23
-24
@@ -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
-2
@@ -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
|
||||
)
|
||||
|
||||
|
||||
+467
-304
File diff suppressed because it is too large
Load Diff
+23
-24
@@ -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
-1
@@ -1,4 +1,4 @@
|
||||
#ifndef __BASECLASS_H__
|
||||
#ifndef __BASECLASS_H__
|
||||
#define __BASECLASS_H__
|
||||
|
||||
#include <iostream>
|
||||
+3
-2
@@ -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
+24
-25
@@ -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
-1
@@ -1,4 +1,4 @@
|
||||
#ifndef __BASECLASS_H__
|
||||
#ifndef __BASECLASS_H__
|
||||
#define __BASECLASS_H__
|
||||
|
||||
#include <iostream>
|
||||
+3
-2
@@ -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
+24
-25
@@ -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
-1
@@ -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*)¶mNum,(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;
|
||||
|
||||
+1
-1
@@ -213,7 +213,7 @@ if(ON)
|
||||
|
||||
set(Qt5_DIR ${PROJECT_ROOT_PATH}/env/qt5/lib/cmake/Qt5)
|
||||
set(QT_DIR ${Qt5_DIR})
|
||||
set(qtlist "Core" "Widgets" "Network" "Gui" "PrintSupport" "Concurrent" "Charts" "Sql")
|
||||
set(qtlist "Core" "Widgets" "Network" "Gui" "PrintSupport" "Concurrent" "Charts""Sql")
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||
message("QT_Version :" Qt${QT_VERSION_MAJOR})
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ foreach(dll ${OUR_LIBS})
|
||||
endforeach(dll ${})
|
||||
|
||||
|
||||
set(DLL_NAMES "halcon" "opencv" "json" "handdleAI" "myTools")
|
||||
set(DLL_NAMES "halcon" "opencv" "json" "handdleAI""myTools")
|
||||
foreach(child ${DLL_NAMES})
|
||||
LIST(APPEND ENV_INCLUDE ${${child}_include})
|
||||
LIST(APPEND ENV_LIB ${${child}_lib})
|
||||
|
||||
+227
-239
@@ -38,27 +38,27 @@ Qt_epWindow::Qt_epWindow(QWidget *parent)
|
||||
ui.pushButton_min->setStyleSheet("background-color:transparent;image: url(./Icon/min_n.png);");
|
||||
ui.pushButton_close->setStyleSheet("background-color:transparent;image: url(./Icon/close_n.png);");
|
||||
ui.pushButton_max->setStyleSheet("background-color:transparent;image: url(./Icon/Max_n.png);");
|
||||
|
||||
|
||||
connect(ui.pushButton_min, &QPushButton::pressed, [=]() {
|
||||
this->showMinimized();
|
||||
qApp->processEvents();
|
||||
});
|
||||
connect(ui.pushButton_close, &QPushButton::clicked, [=]() {
|
||||
|
||||
static int sec15 = 15;
|
||||
static QTimer* aotuCloseTimer = new QTimer;
|
||||
connect(aotuCloseTimer, &QTimer::timeout, [=]() {
|
||||
sec15--;
|
||||
waiteBox.setText("确认退出程序?" + QString::number(sec15) + "秒后自动取消此操作。");
|
||||
if (sec15 == 0)
|
||||
{
|
||||
//waiteBox_result = QMessageBox::No;
|
||||
waiteBox.close();
|
||||
aotuCloseTimer->stop();
|
||||
sec15 = 5;
|
||||
}
|
||||
});
|
||||
aotuCloseTimer->start(1000);
|
||||
connect(autouCloseTimer, &QTimer::timeout, [=]() {
|
||||
autoCloseCounter--;
|
||||
waiteBox.setText("确认退出程序?" + QString::number(autoCloseCounter) + "秒后自动取消此操作。");
|
||||
if (autoCloseCounter == 0)
|
||||
{
|
||||
//waiteBox_result = QMessageBox::No;
|
||||
waiteBox.close();
|
||||
autouCloseTimer->stop();
|
||||
autoCloseCounter = 15;
|
||||
delete autouCloseTimer;
|
||||
}
|
||||
});
|
||||
connect(ui.pushButton_close, &QPushButton::clicked, [=]() {
|
||||
autouCloseTimer->stop();
|
||||
autouCloseTimer->start(1000);
|
||||
qApp->processEvents();
|
||||
waiteBox.setWindowTitle("确认退出程序?");
|
||||
waiteBox.setText("确认退出程序?15秒后自动取消此操作。");
|
||||
@@ -76,8 +76,10 @@ Qt_epWindow::Qt_epWindow(QWidget *parent)
|
||||
}
|
||||
else {
|
||||
// 用户点击了“取消”按钮或其他地方,可以选择不执行任何操作或执行其他操作
|
||||
autoCloseCounter = 15;
|
||||
autouCloseTimer->stop();
|
||||
qDebug() << "用户点击了取消或未选择任何操作";
|
||||
|
||||
|
||||
}
|
||||
|
||||
//this->close();
|
||||
@@ -1601,7 +1603,8 @@ void Qt_epWindow::showTransferImage(QString cameraKey_index, QImage* image)
|
||||
//ui.graphicsView->scene()->clear();
|
||||
QPixmap ConvertPixmap;// = QPixmap::fromImage(image);//The QPixmap class is an off-screen image representation that can be used as a paint device
|
||||
//ConvertPixmap.load(imgPath);
|
||||
ConvertPixmap.convertFromImage(*image);
|
||||
if (image != nullptr)
|
||||
ConvertPixmap.convertFromImage(*image);
|
||||
|
||||
if (m_pImageList[index])
|
||||
m_pImageList[index] = nullptr;
|
||||
@@ -1803,24 +1806,6 @@ void Qt_epWindow::getTransferData(QString key, QString cameraName, QString snInf
|
||||
int mm = nowTime.split(" ")[1].split(":")[1].toInt();
|
||||
if ((hh > 8 && hh < 20) || (hh == 8 && mm >= 30) || (hh == 20 && mm < 30))
|
||||
ifNight = false;
|
||||
|
||||
std::string str = byteArray.toStdString();
|
||||
std::string chartData, csvData, defectData;
|
||||
//CHART表格数据
|
||||
int startChart = str.find(chartSplitStart) + std::size(chartSplitStart) - 1;
|
||||
int endChart = str.find(chartSplitEnd) - startChart;
|
||||
if (startChart > 0 && endChart > 0)
|
||||
chartData = str.substr(startChart, endChart);
|
||||
//CSV表格数据
|
||||
int startCSV = str.find(csvSplitStart) + std::size(csvSplitStart) - 1;
|
||||
int endCSV = str.find(csvSplitEnd) - startCSV;
|
||||
if (startCSV > 0 && endCSV > 0)
|
||||
csvData = str.substr(startCSV, endCSV);
|
||||
//缺陷直方图
|
||||
int startDefect = str.find(csvSplitStart) + std::size(csvSplitStart) - 1;
|
||||
int endDefect = str.find(csvSplitEnd) - startDefect;
|
||||
if (startDefect > 0 && endDefect > 0)
|
||||
defectData = str.substr(startDefect, endDefect);
|
||||
if (key.contains("程序号"))
|
||||
{
|
||||
cName_surface_defectNums.clear();
|
||||
@@ -1861,114 +1846,11 @@ void Qt_epWindow::getTransferData(QString key, QString cameraName, QString snInf
|
||||
set_tabQPushButton(0);
|
||||
//waiteBox-> close();
|
||||
}
|
||||
if (chartData.size() > 0)//|| CommunicationProcessLevel==1) //简单流程每张图就是结果
|
||||
else if (myByte.contains("*") )//|| CommunicationProcessLevel==1) //简单流程每张图就是结果
|
||||
{
|
||||
int result = stoi(chartData);
|
||||
|
||||
QPieSeriesData_ALL.allNum++;
|
||||
if (result == 1)
|
||||
{
|
||||
myByte = "OK";
|
||||
setInsertTextColor(ui.plainTextEdit_history, QColor("green"));
|
||||
setInsertTextColor(ui.plainTextEdit_run, QColor("green"));
|
||||
ui.label_result->setStyleSheet("background-color: green;");
|
||||
QPieSeriesData_ALL.okNum++;
|
||||
}
|
||||
else
|
||||
{
|
||||
myByte= "NG";
|
||||
setInsertTextColor(ui.plainTextEdit_history, QColor("red"));
|
||||
setInsertTextColor(ui.plainTextEdit_run, QColor("red"));
|
||||
ui.label_result->setStyleSheet("background-color: red;");
|
||||
QPieSeriesData_ALL.ngNum++;
|
||||
}
|
||||
//list << "序号" << "日期" << "电池芯码" << "结果";
|
||||
QString myS = "序号:" + QString::number(historyLogListNum++) + " 日期:" + nowTime + " SN时间戳:" + snInfo + " 结果:" + myByte;
|
||||
historyLogList.append(myS);
|
||||
//不需要查看历史统计时;
|
||||
if (historyLogList.size() > 100000)
|
||||
historyLogList.dequeue();
|
||||
ui.plainTextEdit_history->appendPlainText(historyLogList.last());
|
||||
//实时信息
|
||||
{
|
||||
ui.label_result->setText(myByte);
|
||||
ui.label_SN->setText(snInfo);
|
||||
ui.label_allNum->setText(QString::number(QPieSeriesData_ALL.allNum));
|
||||
ui.label_OKPercent->setText(QString::number(int(QPieSeriesData_ALL.okNum * 1.0000 / QPieSeriesData_ALL.allNum * 10000) / 100.00) + "%");
|
||||
ui.label_OKNum->setText(QString::number(QPieSeriesData_ALL.okNum));
|
||||
ui.label_NGnum->setText(QString::number(QPieSeriesData_ALL.ngNum));; //百万级变负数??
|
||||
if (QPieSeriesData_ALL.allNum > 1)
|
||||
{
|
||||
stop = clock();
|
||||
if (stop - start > 1000)
|
||||
ui.label_CT->setText(QString::number(int(int(stop - start) * 100 / 1000) * 0.01) + "秒");
|
||||
else
|
||||
ui.label_CT->setText(QString::number(stop - start) + "毫秒");
|
||||
}
|
||||
start = clock();
|
||||
}
|
||||
//饼图更新
|
||||
{
|
||||
//ALL饼图;slices()[0] ok;slices()[1] ng;
|
||||
QPieSeriesData_ALL.series->slices()[0]->setValue(int(QPieSeriesData_ALL.okNum * 1.0000 / QPieSeriesData_ALL.allNum * 10000) / 100.00);
|
||||
QPieSeriesData_ALL.series->slices()[1]->setValue(100.00 - int(QPieSeriesData_ALL.okNum * 1.0000 / QPieSeriesData_ALL.allNum * 10000) / 100.00);
|
||||
|
||||
//换班判断
|
||||
if (ifLastNight != ifNight)
|
||||
{
|
||||
if (ifNight) //白班换夜班,夜班数据清0
|
||||
{
|
||||
QPieSeriesData_night.allNum = 0;
|
||||
QPieSeriesData_night.okNum = 0;
|
||||
QPieSeriesData_night.ngNum = 0;
|
||||
for (int j = 0; j < DefectDataQQueue.size(); j++)
|
||||
{
|
||||
DefectDataQQueue[j].Num_night = 0;
|
||||
ui.tableWidget_night->item(j, 2)->setText(QString::number(DefectDataQQueue[j].Num_night));
|
||||
}
|
||||
}
|
||||
else//夜班换白班,白班数据清0
|
||||
{
|
||||
QPieSeriesData_day.allNum = 0;
|
||||
QPieSeriesData_day.okNum = 0;
|
||||
QPieSeriesData_day.ngNum = 0;
|
||||
for (int j = 0; j < DefectDataQQueue.size(); j++)
|
||||
{
|
||||
DefectDataQQueue[j].Num_day = 0;
|
||||
ui.tableWidget_day->item(j, 2)->setText(QString::number(DefectDataQQueue[j].Num_day));
|
||||
}
|
||||
}
|
||||
ifLastNight = ifNight;
|
||||
}
|
||||
if (ifNight)
|
||||
{
|
||||
QPieSeriesData_night.allNum++;
|
||||
if (myByte == "OK")
|
||||
QPieSeriesData_night.okNum++;
|
||||
else if (myByte == "NG")
|
||||
QPieSeriesData_night.ngNum++;
|
||||
ui.label_allNum_night->setText(QString::number(QPieSeriesData_night.allNum));
|
||||
ui.label_OKPercent_night->setText(QString::number(int(QPieSeriesData_night.okNum * 1.0000 / QPieSeriesData_night.allNum * 10000) / 100.00) + "%");
|
||||
ui.label_OKNum_night->setText(QString::number(QPieSeriesData_night.okNum));
|
||||
ui.label_NGnum_night->setText(QString::number(QPieSeriesData_night.ngNum));; //百万级变负数??
|
||||
QPieSeriesData_night.series->slices()[0]->setValue((QPieSeriesData_night.okNum * 1.0000 / QPieSeriesData_night.allNum * 10000) / 100.00);
|
||||
QPieSeriesData_night.series->slices()[1]->setValue(100.00 - (QPieSeriesData_night.okNum * 1.0000 / QPieSeriesData_night.allNum * 10000) / 100.00);
|
||||
}
|
||||
else
|
||||
{
|
||||
QPieSeriesData_day.allNum++;
|
||||
if (myByte == "OK")
|
||||
QPieSeriesData_day.okNum++;
|
||||
else if (myByte == "NG")
|
||||
QPieSeriesData_day.ngNum++;
|
||||
ui.label_allNum_day->setText(QString::number(QPieSeriesData_day.allNum));
|
||||
ui.label_OKPercent_day->setText(QString::number(int(QPieSeriesData_day.okNum * 1.0000 / QPieSeriesData_day.allNum * 10000) / 100.00) + "%");
|
||||
ui.label_OKNum_day->setText(QString::number(QPieSeriesData_day.okNum));
|
||||
ui.label_NGnum_day->setText(QString::number(QPieSeriesData_day.ngNum));; //百万级变负数??
|
||||
QPieSeriesData_day.series->slices()[0]->setValue(int(QPieSeriesData_day.okNum * 1.0000 / QPieSeriesData_day.allNum * 10000) / 100.00);
|
||||
QPieSeriesData_day.series->slices()[1]->setValue(100.00 - int(QPieSeriesData_day.okNum * 1.0000 / QPieSeriesData_day.allNum * 10000) / 100.00);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1993,92 +1875,8 @@ void Qt_epWindow::getTransferData(QString key, QString cameraName, QString snInf
|
||||
rowNumn++;
|
||||
}
|
||||
}
|
||||
//更新缺陷统计表图
|
||||
if(defectData.size() > 0)
|
||||
{
|
||||
QStringList myByteList = myByteCpy.split(*generalSplit);
|
||||
if (myByteList.size() > 1)
|
||||
for (int i = 1; i < myByteList.size(); i++)
|
||||
{
|
||||
if (myByteList[i] != "1")//1 ok ,其它NG;
|
||||
{
|
||||
for (int j = 0; j < DefectDataQQueue.size(); j++)
|
||||
if (DefectDataQQueue[j].Order == i)
|
||||
{
|
||||
DefectDataQQueue[j].Num_all++;
|
||||
if (ifNight == true)
|
||||
{
|
||||
DefectDataQQueue[j].Num_night++;
|
||||
ui.tableWidget_night->item(j, 2)->setText(QString::number(DefectDataQQueue[j].Num_night));
|
||||
|
||||
if (DefectDataQQueue[j].Num_night > QBarSeriesData_night.lastMax * 0.8)
|
||||
{
|
||||
//重新设置
|
||||
ui.groupBox_4->layout()->removeWidget(QBarSeriesData_night.chartView);
|
||||
restQBarSeries(QBarSeriesData_night, DefectDataQQueue[j].Num_night * 1.25);
|
||||
ui.groupBox_4->layout()->addWidget(QBarSeriesData_night.chartView);
|
||||
//柱状图清空
|
||||
for (int b = QBarSeriesData_night.BarNum - 1; b >= 0; b--)
|
||||
QBarSeriesData_night.m_QBarSet->remove(b);
|
||||
QBarSeriesData_night.axis->clear();
|
||||
QBarSeriesData_night.BarNum = 0;
|
||||
for (int b = 0; b < DefectDataQQueue.size(); b++)
|
||||
{
|
||||
ui.tableWidget_night->setItem(b, 0, new QTableWidgetItem(QString::number(DefectDataQQueue[b].Order)));//缺陷类别
|
||||
ui.tableWidget_night->setItem(b, 1, new QTableWidgetItem(DefectDataQQueue[b].Name));//缺陷名称//居中
|
||||
ui.tableWidget_night->setItem(b, 2, new QTableWidgetItem(QString::number(DefectDataQQueue[b].Num_night)));//缺陷数
|
||||
ui.tableWidget_night->item(b, 0)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
ui.tableWidget_night->item(b, 1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
ui.tableWidget_night->item(b, 2)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
//更新柱状图
|
||||
QBarSeriesData_night.m_QBarSet->append(DefectDataQQueue[b].Num_night); //值
|
||||
QBarSeriesData_night.axis->append(DefectDataQQueue[b].Name);//缺陷名称
|
||||
QBarSeriesData_night.BarNum++;
|
||||
}
|
||||
}
|
||||
else
|
||||
QBarSeriesData_night.m_QBarSet->replace(j, DefectDataQQueue[j].Num_night);
|
||||
}
|
||||
else
|
||||
{
|
||||
DefectDataQQueue[j].Num_day++;
|
||||
ui.tableWidget_day->item(j, 2)->setText(QString::number(DefectDataQQueue[j].Num_day));
|
||||
|
||||
if (DefectDataQQueue[j].Num_day > QBarSeriesData_day.lastMax * 0.8)
|
||||
{
|
||||
//重新设置
|
||||
ui.groupBox_3->layout()->removeWidget(QBarSeriesData_day.chartView);
|
||||
restQBarSeries(QBarSeriesData_day, DefectDataQQueue[j].Num_day * 1.25);
|
||||
ui.groupBox_3->layout()->addWidget(QBarSeriesData_day.chartView);
|
||||
//柱状图清空
|
||||
for (int b = QBarSeriesData_day.BarNum - 1; b >= 0; b--)
|
||||
QBarSeriesData_day.m_QBarSet->remove(b);
|
||||
QBarSeriesData_day.axis->clear();
|
||||
QBarSeriesData_day.BarNum = 0;
|
||||
for (int b = 0; b < DefectDataQQueue.size(); b++)
|
||||
{
|
||||
ui.tableWidget_day->setItem(b, 0, new QTableWidgetItem(QString::number(DefectDataQQueue[b].Order)));//缺陷类别
|
||||
ui.tableWidget_day->setItem(b, 1, new QTableWidgetItem(DefectDataQQueue[b].Name));//缺陷名称//居中
|
||||
ui.tableWidget_day->setItem(b, 2, new QTableWidgetItem(QString::number(DefectDataQQueue[b].Num_day)));//缺陷数
|
||||
ui.tableWidget_day->item(b, 0)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
ui.tableWidget_day->item(b, 1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
ui.tableWidget_day->item(b, 2)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
//更新柱状图
|
||||
QBarSeriesData_day.m_QBarSet->append(DefectDataQQueue[b].Num_day); //值
|
||||
QBarSeriesData_day.axis->append(DefectDataQQueue[b].Name);//缺陷名称
|
||||
QBarSeriesData_day.BarNum++;
|
||||
}
|
||||
}
|
||||
else
|
||||
QBarSeriesData_day.m_QBarSet->replace(j, DefectDataQQueue[j].Num_day);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (CommunicationProcessLevel == 1) //简单流程每张图就是结果
|
||||
{
|
||||
@@ -2104,21 +1902,211 @@ void Qt_epWindow::getTransferData(QString key, QString cameraName, QString snInf
|
||||
rowNumn++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//写表格CSV
|
||||
if (csvData.size()>0)
|
||||
{
|
||||
QString ymd = QDateTime::currentDateTime().toString("yyyy-MM-dd");
|
||||
QString hms = QDateTime::currentDateTime().toString("hh:mm:ss");
|
||||
QStringList outDataList = myByteCpy.split(*generalSplit);
|
||||
std::vector<std::string> strList;
|
||||
strList.push_back(hms.toStdString());// 时间
|
||||
strList.push_back(snInfo.toStdString());//SN
|
||||
strList.push_back(cameraName.toStdString());//相机名
|
||||
for (int cnt = 1; cnt < outDataList.size(); cnt++)
|
||||
strList.push_back(outDataList[cnt].toStdString());
|
||||
//WriteToCsv("./csv/" + ymd.toStdString()+".csv", strList);
|
||||
std::map<QString, QVariant> csvDataResult = logicUiTransport::decodeCsvData(byteArray);
|
||||
bool isNewData = _CsvWriter.isNewData(csvDataResult["条码"].toString());//是否为新数据
|
||||
_CsvWriter.addtData(csvDataResult["条码"].toString(), csvDataResult);
|
||||
bool isNgData = _CsvWriter.isNgData(csvDataResult["条码"].toString());//是否为NG数据
|
||||
|
||||
//写图表,会用到”链接到UI表格数据列表“
|
||||
for (int i = 0; i < DefectDataQQueue.size(); i++) {
|
||||
if (csvDataResult[_CsvWriter.csvAndChartLink[DefectDataQQueue[i].Name]] == "NG") {
|
||||
DefectDataQQueue[i].Num_all++;//某缺陷总数
|
||||
if (ifNight == true)
|
||||
{
|
||||
DefectDataQQueue[i].Num_night++;
|
||||
ui.tableWidget_night->item(i, 2)->setText(QString::number(DefectDataQQueue[i].Num_night));
|
||||
|
||||
if (DefectDataQQueue[i].Num_night > QBarSeriesData_night.lastMax * 0.8)
|
||||
{
|
||||
//重新设置
|
||||
ui.groupBox_4->layout()->removeWidget(QBarSeriesData_night.chartView);
|
||||
restQBarSeries(QBarSeriesData_night, DefectDataQQueue[i].Num_night * 1.25);
|
||||
ui.groupBox_4->layout()->addWidget(QBarSeriesData_night.chartView);
|
||||
//柱状图清空
|
||||
for (int b = QBarSeriesData_night.BarNum - 1; b >= 0; b--)
|
||||
QBarSeriesData_night.m_QBarSet->remove(b);
|
||||
QBarSeriesData_night.axis->clear();
|
||||
QBarSeriesData_night.BarNum = 0;
|
||||
for (int b = 0; b < DefectDataQQueue.size(); b++)
|
||||
{
|
||||
ui.tableWidget_night->setItem(b, 0, new QTableWidgetItem(QString::number(DefectDataQQueue[b].Order)));//缺陷类别
|
||||
ui.tableWidget_night->setItem(b, 1, new QTableWidgetItem(DefectDataQQueue[b].Name));//缺陷名称//居中
|
||||
ui.tableWidget_night->setItem(b, 2, new QTableWidgetItem(QString::number(DefectDataQQueue[b].Num_night)));//缺陷数
|
||||
ui.tableWidget_night->item(b, 0)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
ui.tableWidget_night->item(b, 1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
ui.tableWidget_night->item(b, 2)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
//更新柱状图
|
||||
QBarSeriesData_night.m_QBarSet->append(DefectDataQQueue[b].Num_night); //值
|
||||
QBarSeriesData_night.axis->append(DefectDataQQueue[b].Name);//缺陷名称
|
||||
QBarSeriesData_night.BarNum++;
|
||||
}
|
||||
}
|
||||
else
|
||||
QBarSeriesData_night.m_QBarSet->replace(i, DefectDataQQueue[i].Num_night);
|
||||
}
|
||||
else
|
||||
{
|
||||
DefectDataQQueue[i].Num_day++;
|
||||
ui.tableWidget_day->item(i, 2)->setText(QString::number(DefectDataQQueue[i].Num_day));
|
||||
|
||||
if (DefectDataQQueue[i].Num_day > QBarSeriesData_day.lastMax * 0.8)
|
||||
{
|
||||
//重新设置
|
||||
ui.groupBox_3->layout()->removeWidget(QBarSeriesData_day.chartView);
|
||||
restQBarSeries(QBarSeriesData_day, DefectDataQQueue[i].Num_day * 1.25);
|
||||
ui.groupBox_3->layout()->addWidget(QBarSeriesData_day.chartView);
|
||||
//柱状图清空
|
||||
for (int b = QBarSeriesData_day.BarNum - 1; b >= 0; b--)
|
||||
QBarSeriesData_day.m_QBarSet->remove(b);
|
||||
QBarSeriesData_day.axis->clear();
|
||||
QBarSeriesData_day.BarNum = 0;
|
||||
for (int b = 0; b < DefectDataQQueue.size(); b++)
|
||||
{
|
||||
ui.tableWidget_day->setItem(b, 0, new QTableWidgetItem(QString::number(DefectDataQQueue[b].Order)));//缺陷类别
|
||||
ui.tableWidget_day->setItem(b, 1, new QTableWidgetItem(DefectDataQQueue[b].Name));//缺陷名称//居中
|
||||
ui.tableWidget_day->setItem(b, 2, new QTableWidgetItem(QString::number(DefectDataQQueue[b].Num_day)));//缺陷数
|
||||
ui.tableWidget_day->item(b, 0)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
ui.tableWidget_day->item(b, 1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
ui.tableWidget_day->item(b, 2)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
//更新柱状图
|
||||
QBarSeriesData_day.m_QBarSet->append(DefectDataQQueue[b].Num_day); //值
|
||||
QBarSeriesData_day.axis->append(DefectDataQQueue[b].Name);//缺陷名称
|
||||
QBarSeriesData_day.BarNum++;
|
||||
}
|
||||
}
|
||||
else
|
||||
QBarSeriesData_day.m_QBarSet->replace(i, DefectDataQQueue[i].Num_day);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (totalDataRecord.find(csvDataResult["条码"].toString()) == totalDataRecord.end()) {//新数据
|
||||
QPieSeriesData_ALL.allNum++;
|
||||
if (isNgData != true)
|
||||
QPieSeriesData_ALL.okNum++;
|
||||
else
|
||||
QPieSeriesData_ALL.ngNum++;
|
||||
}
|
||||
else {//老数据 判断上一次的结果是否一致 不一致则需要修改
|
||||
if (totalDataRecord[csvDataResult["条码"].toString()] != isNgData){
|
||||
if (isNgData){
|
||||
QPieSeriesData_ALL.okNum--;
|
||||
QPieSeriesData_ALL.ngNum++;
|
||||
}
|
||||
else{
|
||||
QPieSeriesData_ALL.okNum++;
|
||||
QPieSeriesData_ALL.ngNum--;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
totalDataRecord[csvDataResult["条码"].toString()] = isNgData;//存储当前数据
|
||||
|
||||
if (isNgData != true){//修改显示当前结果的颜色
|
||||
setInsertTextColor(ui.plainTextEdit_history, QColor("green"));
|
||||
setInsertTextColor(ui.plainTextEdit_run, QColor("green"));
|
||||
ui.label_result->setStyleSheet("background-color: green;");
|
||||
}
|
||||
else{
|
||||
setInsertTextColor(ui.plainTextEdit_history, QColor("red"));
|
||||
setInsertTextColor(ui.plainTextEdit_run, QColor("red"));
|
||||
ui.label_result->setStyleSheet("background-color: red;");
|
||||
}
|
||||
//list << "序号" << "日期" << "电池芯码" << "结果";
|
||||
QString myS = "SN->" + snInfo + "\r日期:" + nowTime + "\r结果:";
|
||||
for (auto & data:csvDataResult) {
|
||||
if (data.first != "条码" && data.first != "") {
|
||||
myS.append("\r[" + data.first + "]->" + data.second.toString());
|
||||
}
|
||||
}
|
||||
historyLogList.append(myS);
|
||||
//不需要查看历史统计时;
|
||||
if (historyLogList.size() > 100000)
|
||||
historyLogList.dequeue();
|
||||
ui.plainTextEdit_history->appendPlainText(historyLogList.last());
|
||||
//饼图更新
|
||||
{
|
||||
//ALL饼图;slices()[0] ok;slices()[1] ng;
|
||||
QPieSeriesData_ALL.series->slices()[0]->setValue(int(QPieSeriesData_ALL.okNum * 1.0000 / QPieSeriesData_ALL.allNum * 10000) / 100.00);
|
||||
QPieSeriesData_ALL.series->slices()[1]->setValue(100.00 - int(QPieSeriesData_ALL.okNum * 1.0000 / QPieSeriesData_ALL.allNum * 10000) / 100.00);
|
||||
|
||||
//换班判断
|
||||
if (ifLastNight != ifNight)
|
||||
{
|
||||
if (ifNight) //白班换夜班,夜班数据清0
|
||||
{
|
||||
QPieSeriesData_night.allNum = 0;
|
||||
QPieSeriesData_night.okNum = 0;
|
||||
QPieSeriesData_night.ngNum = 0;
|
||||
for (int j = 0; j < DefectDataQQueue.size(); j++)
|
||||
{
|
||||
DefectDataQQueue[j].Num_night = 0;
|
||||
ui.tableWidget_night->item(j, 2)->setText(QString::number(DefectDataQQueue[j].Num_night));
|
||||
}
|
||||
}
|
||||
else//夜班换白班,白班数据清0
|
||||
{
|
||||
QPieSeriesData_day.allNum = 0;
|
||||
QPieSeriesData_day.okNum = 0;
|
||||
QPieSeriesData_day.ngNum = 0;
|
||||
for (int j = 0; j < DefectDataQQueue.size(); j++)
|
||||
{
|
||||
DefectDataQQueue[j].Num_day = 0;
|
||||
ui.tableWidget_day->item(j, 2)->setText(QString::number(DefectDataQQueue[j].Num_day));
|
||||
}
|
||||
}
|
||||
ifLastNight = ifNight;
|
||||
}
|
||||
if (ifNight)
|
||||
{
|
||||
QPieSeriesData_night.allNum++;
|
||||
if (myByte == "OK")
|
||||
QPieSeriesData_night.okNum++;
|
||||
else if (myByte == "NG")
|
||||
QPieSeriesData_night.ngNum++;
|
||||
ui.label_allNum_night->setText(QString::number(QPieSeriesData_night.allNum));
|
||||
ui.label_OKPercent_night->setText(QString::number(int(QPieSeriesData_night.okNum * 1.0000 / QPieSeriesData_night.allNum * 10000) / 100.00) + "%");
|
||||
ui.label_OKNum_night->setText(QString::number(QPieSeriesData_night.okNum));
|
||||
ui.label_NGnum_night->setText(QString::number(QPieSeriesData_night.ngNum));; //百万级变负数??
|
||||
QPieSeriesData_night.series->slices()[0]->setValue((QPieSeriesData_night.okNum * 1.0000 / QPieSeriesData_night.allNum * 10000) / 100.00);
|
||||
QPieSeriesData_night.series->slices()[1]->setValue(100.00 - (QPieSeriesData_night.okNum * 1.0000 / QPieSeriesData_night.allNum * 10000) / 100.00);
|
||||
}
|
||||
else
|
||||
{
|
||||
QPieSeriesData_day.allNum++;
|
||||
if (myByte == "OK")
|
||||
QPieSeriesData_day.okNum++;
|
||||
else if (myByte == "NG")
|
||||
QPieSeriesData_day.ngNum++;
|
||||
ui.label_allNum_day->setText(QString::number(QPieSeriesData_day.allNum));
|
||||
ui.label_OKPercent_day->setText(QString::number(int(QPieSeriesData_day.okNum * 1.0000 / QPieSeriesData_day.allNum * 10000) / 100.00) + "%");
|
||||
ui.label_OKNum_day->setText(QString::number(QPieSeriesData_day.okNum));
|
||||
ui.label_NGnum_day->setText(QString::number(QPieSeriesData_day.ngNum));; //百万级变负数??
|
||||
QPieSeriesData_day.series->slices()[0]->setValue(int(QPieSeriesData_day.okNum * 1.0000 / QPieSeriesData_day.allNum * 10000) / 100.00);
|
||||
QPieSeriesData_day.series->slices()[1]->setValue(100.00 - int(QPieSeriesData_day.okNum * 1.0000 / QPieSeriesData_day.allNum * 10000) / 100.00);
|
||||
}
|
||||
}
|
||||
//实时信息
|
||||
{
|
||||
ui.label_result->setText(isNgData == true ? "NG" : "OK");
|
||||
ui.label_SN->setText(csvDataResult["条码"].toString());
|
||||
for (auto& data : csvDataResult)
|
||||
if (data.first.contains("CT"))
|
||||
ui.label_CT->setText(data.second.toString());
|
||||
ui.label_allNum->setText(QString::number(QPieSeriesData_ALL.allNum));
|
||||
ui.label_OKPercent->setText(QString::number(int(QPieSeriesData_ALL.okNum * 1.0000 / QPieSeriesData_ALL.allNum * 10000) / 100.00) + "%");
|
||||
ui.label_OKNum->setText(QString::number(QPieSeriesData_ALL.okNum));
|
||||
ui.label_NGnum->setText(QString::number(QPieSeriesData_ALL.ngNum));; //百万级变负数??
|
||||
|
||||
}
|
||||
|
||||
ui.plainTextEdit_run->appendPlainText(runLogList.last());
|
||||
//qApp->processEvents();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <QtCharts>
|
||||
#include "QtCharts/qpieseries.h"
|
||||
#include "QtCharts/qbarseries.h"
|
||||
|
||||
#include <rlib/rlib_writeCsv.h>
|
||||
//通用逻辑接口
|
||||
#include "Logic_transfer.h"
|
||||
#include "QtParameterSettings.h"
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "QtSaveImgSet.h"
|
||||
//缺陷名称设置
|
||||
#include "QtDefectSet.h"
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
//struct LogListStruct
|
||||
@@ -126,6 +127,9 @@ public slots:
|
||||
void getTransfer_cameraDisconnect(QString msg, bool status);*/
|
||||
|
||||
private:
|
||||
CsvWriter _CsvWriter;
|
||||
std::map<QString, bool> totalDataRecord;
|
||||
|
||||
bool ifFisrtRun = true;
|
||||
bool initLogic_transfer_OK = false;
|
||||
bool ifStopLogic_transfer = false;
|
||||
@@ -143,8 +147,7 @@ private:
|
||||
bool WifRun = true;
|
||||
QQueue<QString> runLogList;
|
||||
QQueue<QString> historyLogList;
|
||||
clock_t start, stop;
|
||||
|
||||
|
||||
//显示图片
|
||||
QList < QImageWidget* > m_pImageList;
|
||||
QList < QGraphicsScene*> qgraphicsSceneList;
|
||||
@@ -236,6 +239,8 @@ private:
|
||||
public:
|
||||
enum MousePoss { LeftUp = 0, Up, RightUp, Right, RightDown, Down, LeftDown, Left, Middle };
|
||||
private:
|
||||
QTimer* autouCloseTimer = new QTimer;
|
||||
int autoCloseCounter = 15;
|
||||
MousePoss mp_curPos; //记录鼠标当前所在区域的变量
|
||||
//改变窗口的大小
|
||||
void changeWindowSize(MousePoss type, QRect& wid, QPoint ptemp, int minWidth, int minHeight);
|
||||
|
||||
@@ -0,0 +1,388 @@
|
||||
//#include<qstring.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <qdir.h>
|
||||
#include <io.h>
|
||||
#include <qtimer.h>
|
||||
#include <qthread.h>
|
||||
#include <qdatetime.h>
|
||||
#include <qstorageinfo.h>
|
||||
#include <qdebug.h>
|
||||
#include <iostream>
|
||||
#include <qfiledialog.h>
|
||||
#include <filesystem>
|
||||
|
||||
class fileManager
|
||||
{
|
||||
public:
|
||||
static QString openFolderDialog()
|
||||
{
|
||||
QString folderPath = QFileDialog::getExistingDirectory(
|
||||
nullptr,
|
||||
"Select Folder",
|
||||
QDir::homePath(), // 默认路径,可以根据需要更改
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
|
||||
if (!folderPath.isEmpty()) {
|
||||
// 用户选择了文件夹
|
||||
qDebug() << "Selected Folder: " << folderPath;
|
||||
}
|
||||
else {
|
||||
// 用户取消了选择
|
||||
qDebug() << "Folder selection canceled.";
|
||||
}
|
||||
|
||||
return folderPath;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取所有文件夹
|
||||
/// </summary>
|
||||
/// <param name="folderPath"></param>
|
||||
/// <param name="folderNames"></param>
|
||||
static std::vector<std::string> getAllDirs(const QString& folderPath)
|
||||
{
|
||||
std::vector<std::string> foldersVec;
|
||||
QDir folderDir(folderPath);
|
||||
if (!folderDir.exists()) {
|
||||
return foldersVec;
|
||||
}
|
||||
|
||||
QStringList folders = folderDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
|
||||
for (const QString& folder : folders) {
|
||||
foldersVec.push_back(folder.toStdString());
|
||||
}
|
||||
return foldersVec;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取文件夹下格式的文件,以vector<string>返回
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="files"></param>
|
||||
/// <param name="format"></param>
|
||||
static void getAllFiles(std::string path, std::vector<std::string>& files, std::string format, int targetDepth = INT_MAX, int depth = 0)
|
||||
{
|
||||
if (depth >= targetDepth)
|
||||
return;
|
||||
intptr_t hFile = 0;
|
||||
struct _finddata_t fileinfo;
|
||||
std::string p;
|
||||
if ((hFile = _findfirst(p.assign(path).append("\\*" + format).c_str(), &fileinfo)) != -1)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((fileinfo.attrib & _A_SUBDIR))
|
||||
{
|
||||
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
|
||||
{
|
||||
files.push_back(p.assign(path).append("\\").append(fileinfo.name));
|
||||
depth++;
|
||||
getAllFiles(p.assign(path).append("\\").append(fileinfo.name), files, format, targetDepth ,depth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
files.push_back(p.assign(path).append("\\").append(fileinfo.name));
|
||||
}
|
||||
} while (_findnext(hFile, &fileinfo) == 0);
|
||||
_findclose(hFile);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取文件夹下的图片,以vector<string>返回
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="files"></param>
|
||||
/// <param name="format"></param>
|
||||
static void getAllImages(std::string path, std::vector<std::string>& files, std::string format, int targetDepth = INT_MAX, int depth = 0)
|
||||
{
|
||||
if (depth >= targetDepth)
|
||||
return;
|
||||
intptr_t hFile = 0;
|
||||
struct _finddata_t fileinfo;
|
||||
std::string p;
|
||||
if ((hFile = _findfirst(p.assign(path).append("\\*" + format).c_str(), &fileinfo)) != -1)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((fileinfo.attrib & _A_SUBDIR))
|
||||
{
|
||||
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
|
||||
{
|
||||
std::string filePath = p.assign(path).append("\\").append(fileinfo.name);
|
||||
if (fileManager::isImageFile(filePath) == true)
|
||||
files.push_back(filePath);
|
||||
depth++;
|
||||
getAllImages(filePath, files, format, targetDepth, depth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string filePath = p.assign(path).append("\\").append(fileinfo.name);
|
||||
if (fileManager::isImageFile(filePath) == true)
|
||||
files.push_back(filePath);
|
||||
}
|
||||
} while (_findnext(hFile, &fileinfo) == 0);
|
||||
_findclose(hFile);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 检查磁盘剩余空间,以GB为单位返回
|
||||
/// </summary>
|
||||
/// <param name="folderPath">example"E://""E://111/222"支持文件夹或者磁盘路径</param>
|
||||
/// <returns></returns>
|
||||
static int getDriveFreeSpaceAsGb(const QString& folderPath) {
|
||||
QStorageInfo storageInfo(folderPath);
|
||||
|
||||
if (storageInfo.isValid() && storageInfo.isReady()) {
|
||||
return storageInfo.bytesAvailable() / 1073741824;
|
||||
}
|
||||
|
||||
return -1; // Indicate failure to retrieve disk space
|
||||
}
|
||||
/// <summary>
|
||||
/// 检查磁盘剩余空间,以Mb为单位返回
|
||||
/// </summary>
|
||||
/// <param name="folderPath">example"E://""E://111/222"支持文件夹或者磁盘路径</param>
|
||||
/// <returns></returns>
|
||||
static int getDriveFreeSpaceAsMb(const QString& folderPath) {
|
||||
QStorageInfo storageInfo(folderPath);
|
||||
|
||||
if (storageInfo.isValid() && storageInfo.isReady()) {
|
||||
return storageInfo.bytesAvailable() / 1048576;
|
||||
}
|
||||
|
||||
return -1; // Indicate failure to retrieve disk space
|
||||
}
|
||||
/// <summary>
|
||||
/// 返回最老创建时间文件夹名
|
||||
/// </summary>
|
||||
/// <param name="folderPath"></param>
|
||||
/// <returns></returns>
|
||||
static QString getOldestDir(const QString& folderPath)
|
||||
{
|
||||
std::string oldestDir;
|
||||
QDateTime oldestTime;
|
||||
std::vector<std::string> files= getAllDirs(folderPath);
|
||||
for (auto file : files)
|
||||
{
|
||||
QFileInfo fileInfo(QString::fromStdString(folderPath.toStdString() + "//" + file));
|
||||
QDateTime fileTime = fileInfo.created();
|
||||
QString str = fileInfo.created().toString();
|
||||
std::cout << "Current date and time: " << str.toStdString() << std::endl;
|
||||
if (oldestTime.isNull() || fileTime < oldestTime)
|
||||
{
|
||||
oldestTime = fileTime;
|
||||
oldestDir = file;
|
||||
}
|
||||
}
|
||||
return QString::fromStdString(oldestDir);
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除最老创建时间文件夹
|
||||
/// </summary>
|
||||
/// <param name="folderPath"></param>
|
||||
/// <returns></returns>
|
||||
static bool deleteOldestDir(const QString& folderPath)
|
||||
{
|
||||
QString oldestDir =getOldestDir(folderPath);
|
||||
if (oldestDir.isEmpty())
|
||||
return false;
|
||||
oldestDir= folderPath+ "//" + oldestDir;
|
||||
QDir dir(oldestDir);
|
||||
dir.removeRecursively();
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除最老子文件夹
|
||||
/// </summary>
|
||||
/// <param name="folderPath"></param>
|
||||
/// <returns></returns>
|
||||
static bool deleteOldestSonDir(const QString& folderPath)
|
||||
{
|
||||
QString oldestDir = getOldestDir(folderPath);
|
||||
if (oldestDir.isEmpty())
|
||||
return false;
|
||||
oldestDir = folderPath + "//" + oldestDir;
|
||||
deleteOldestDir(oldestDir);
|
||||
if (getAllDirs(oldestDir).size() == 0)//删除后文件夹为空,删除父文件夹
|
||||
{
|
||||
QDir dir(oldestDir);
|
||||
dir.removeRecursively();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除几天前的所有文件夹
|
||||
/// </summary>
|
||||
/// <param name="folderPath"></param>
|
||||
/// <param name="day"></param>
|
||||
/// <returns></returns>
|
||||
static bool deleteDirBeforeDays(const QString& folderPath, int day)
|
||||
{
|
||||
std::vector<std::string> files=getAllDirs(folderPath);
|
||||
for (auto file : files)
|
||||
{
|
||||
QFileInfo fileInfo(QString::fromStdString(file));
|
||||
QDateTime fileTime = fileInfo.created();
|
||||
QDateTime nowTime = QDateTime::currentDateTime();
|
||||
if (fileTime.daysTo(nowTime) > day)
|
||||
{
|
||||
QDir dir(QString::fromStdString(file));
|
||||
dir.removeRecursively();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//去除重复分割符
|
||||
static QString normalizePathSeparators(const QString& path) {
|
||||
QString normalizedPath = path;
|
||||
|
||||
// Replace backslashes with forward slashes
|
||||
normalizedPath.replace('\\', '/');
|
||||
|
||||
// Remove consecutive forward slashes
|
||||
QString doubleSlash = "//";
|
||||
while (normalizedPath.contains(doubleSlash)) {
|
||||
normalizedPath.replace(doubleSlash, "/");
|
||||
}
|
||||
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
static bool isImageFile(const std::string& filename) {
|
||||
const std::string imageExtensions[] = { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp" };
|
||||
|
||||
std::string lowerFilename = filename;
|
||||
std::transform(lowerFilename.begin(), lowerFilename.end(), lowerFilename.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
for (const std::string& ext : imageExtensions) {
|
||||
if (lowerFilename.size() >= ext.size() &&
|
||||
lowerFilename.compare(lowerFilename.size() - ext.size(), ext.size(), ext) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static std::string getFileName(std::string path)
|
||||
{
|
||||
if (path.find("\\") != std::string::npos)
|
||||
return path.substr(path.find_last_of("\\") + 1, path.find_last_of(".") - path.find_last_of("\\") - 1);
|
||||
return path.substr(path.find_last_of("/") + 1, path.find_last_of(".") - path.find_last_of("/") - 1);
|
||||
}
|
||||
static QString getFileName(const QString& path) {
|
||||
int lastSlashIndex = path.lastIndexOf('/');
|
||||
if (lastSlashIndex == -1) {
|
||||
lastSlashIndex = path.lastIndexOf('\\');
|
||||
}
|
||||
|
||||
int lastDotIndex = path.lastIndexOf('.');
|
||||
|
||||
if (lastDotIndex == -1 || lastDotIndex < lastSlashIndex) {
|
||||
return path.mid(lastSlashIndex + 1);
|
||||
}
|
||||
else {
|
||||
return path.mid(lastSlashIndex + 1, lastDotIndex - lastSlashIndex - 1);
|
||||
}
|
||||
}
|
||||
//统一地址分隔符
|
||||
static QString normalizePathStr(const QString& address, QChar targetSeparator = '/') {
|
||||
QString normalizedAddress = address;
|
||||
for (int i = 0; i < normalizedAddress.size(); ++i) {
|
||||
if (normalizedAddress[i] == '\\' || normalizedAddress[i] == '/') {
|
||||
normalizedAddress[i] = targetSeparator;
|
||||
}
|
||||
}
|
||||
return normalizedAddress;
|
||||
}
|
||||
//统一地址分隔符
|
||||
static std::string normalizePathStr(const std::string& address, char targetSeparator = '/') {
|
||||
std::string normalizedAddress = address;
|
||||
for (char& ch : normalizedAddress) {
|
||||
if (ch == '\\' || ch == '/') {
|
||||
ch = targetSeparator;
|
||||
}
|
||||
}
|
||||
return normalizedAddress;
|
||||
}
|
||||
static void createDirectoryIfNotExists(const QString& path) {
|
||||
QDir dir(path);
|
||||
if (dir.exists() == false)
|
||||
{
|
||||
dir.mkpath(path);
|
||||
}
|
||||
}
|
||||
static bool setFileReadOnly(const std::string& filePath, bool readOnly);
|
||||
};
|
||||
/// <summary>
|
||||
/// 自动删除文件夹,支持按日期删除,按磁盘剩余容量删除,或者两者都是,请在主线程声明qtimer
|
||||
/// </summary>
|
||||
class autoDelete : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum clearMode
|
||||
{
|
||||
dayBefore,
|
||||
sizeOver,
|
||||
sizeOverOrDayBefore,
|
||||
};
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="path">文件夹路径</param>
|
||||
/// <param name="mode">删除几天前的,磁盘剩余容量小于多少,两者都是</param>
|
||||
/// <param name="interval">检测间隔如果只检测日期建议设大一点,如果只检测磁盘容量建议设小一点,默认十分钟</param>
|
||||
autoDelete(QString path,clearMode mode,QTimer *timer)
|
||||
{
|
||||
detPath = path;
|
||||
detMode = mode;
|
||||
connect(timer, &QTimer::timeout, this, [=]() {this->run(); });
|
||||
}
|
||||
~autoDelete()
|
||||
{
|
||||
|
||||
}
|
||||
void run() override
|
||||
{
|
||||
exacute();
|
||||
}
|
||||
void exacute()
|
||||
{
|
||||
switch (detMode)
|
||||
{
|
||||
case dayBefore://删除几天前的
|
||||
fileManager::deleteDirBeforeDays(detPath, daySet);
|
||||
break;
|
||||
case sizeOver://磁盘剩余容量小于多少
|
||||
if (fileManager::getDriveFreeSpaceAsGb(detPath) < sizeSet)
|
||||
fileManager::deleteOldestSonDir(detPath);//删除最老的文件夹
|
||||
break;
|
||||
case sizeOverOrDayBefore://两者都是
|
||||
if (fileManager::getDriveFreeSpaceAsGb(detPath) < sizeSet)//磁盘剩余容量小于多少
|
||||
fileManager::deleteOldestDir(detPath);//删除最老的文件夹
|
||||
fileManager::deleteDirBeforeDays(detPath, daySet);//同时删除几天前的
|
||||
break;
|
||||
default:
|
||||
qDebug() << "none mode det";
|
||||
break;
|
||||
}
|
||||
}
|
||||
void setDay(int day)
|
||||
{
|
||||
daySet = day;
|
||||
}
|
||||
void setSize(int size)
|
||||
{
|
||||
sizeSet = size;
|
||||
}
|
||||
private:
|
||||
QString detPath;
|
||||
clearMode detMode;
|
||||
int daySet = 15;//天
|
||||
int sizeSet = 30;//GB
|
||||
int threadInterval = 0;//ms
|
||||
};
|
||||
|
||||
#pragma once
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,668 @@
|
||||
#include <qfile.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
#include <qdatetime.h>
|
||||
#include <memory>
|
||||
#include <qtextstream.h>
|
||||
#include <QtSql/QSqlDatabase>
|
||||
#include <QtSql/QSqlQuery>
|
||||
#include <QtSql/QSqlError>
|
||||
#include <QtSql/QSqlRecord>
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <qcoreapplication.h>
|
||||
#include <qdir.h>
|
||||
#include <qtimer.h>
|
||||
#include <chrono>
|
||||
#include <qobject.h>
|
||||
#include "nlohmannJson.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <qtimer.h>
|
||||
static nlohmann::json readJsonFromPath(std::string path)
|
||||
{
|
||||
nlohmann::json jsonObj;
|
||||
std::ifstream inputFile(path);
|
||||
if (!inputFile.is_open()) {
|
||||
std::cerr << "Could not open the file - " << path << std::endl;
|
||||
return jsonObj;
|
||||
}
|
||||
try {
|
||||
inputFile >> jsonObj;
|
||||
}
|
||||
catch (nlohmann::json::parse_error& e) {
|
||||
std::cerr << "JSON parse error: " << e.what() << std::endl;
|
||||
return jsonObj;
|
||||
}
|
||||
|
||||
// 关闭文件
|
||||
inputFile.close();
|
||||
return jsonObj;
|
||||
}
|
||||
static bool saveJsonFromPath(std::string path, nlohmann::json& json)
|
||||
{
|
||||
std::ofstream saveFile(path);
|
||||
if (!saveFile.is_open()) {
|
||||
std::cerr << "Could not open the file - " << path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
saveFile << json.dump(4);
|
||||
}
|
||||
catch (nlohmann::json::parse_error& e) {
|
||||
std::cerr << "JSON parse error: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 关闭文件
|
||||
saveFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
class SQLiteDB {
|
||||
public:
|
||||
SQLiteDB(const QString& dbPath, const QString& dbName)
|
||||
: m_dbName(dbName), m_dbPath(dbPath) {
|
||||
}
|
||||
~SQLiteDB() {};
|
||||
bool connect() {
|
||||
// 检查数据库文件是否存在
|
||||
if (!QFile::exists(m_dbPath + m_dbName + ".db")) {
|
||||
QDir().mkpath(m_dbPath);
|
||||
qDebug() << "Database file does not exist. Creating a new database:" << m_dbName;
|
||||
}
|
||||
QCoreApplication::addLibraryPath("./");
|
||||
// 添加 SQLite 数据库驱动
|
||||
m_db = QSqlDatabase::addDatabase("QSQLITE");
|
||||
m_db.setDatabaseName(m_dbPath + m_dbName + ".db");
|
||||
|
||||
// 打开数据库
|
||||
if (!m_db.open()) {
|
||||
qCritical() << "Failed to open or create database:" << m_db.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "Connected to SQLite database:" << m_dbPath + m_dbName;
|
||||
createTable("setting",
|
||||
{
|
||||
{"id","INTEGER PRIMARY KEY AUTOINCREMENT"} ,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
// 关闭数据库连接
|
||||
void disconnect() {
|
||||
if (m_db.isOpen()) {
|
||||
m_db.close();
|
||||
qDebug() << "Database closed.";
|
||||
}
|
||||
}
|
||||
// 执行无返回值的SQL语句(如插入、删除、更新)
|
||||
bool execute(const QString& queryStr, const QVariantList& args = {}) {
|
||||
QSqlQuery query;
|
||||
query.prepare(queryStr);
|
||||
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
query.bindValue(i, args[i]);
|
||||
}
|
||||
|
||||
if (!query.exec()) {
|
||||
qCritical() << "SQL error:" << query.lastError().text();
|
||||
qCritical() << "Query:" << queryStr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 查询数据,返回结果集
|
||||
QList<QMap<QString, QVariant>> query(const QString& queryStr, const QVariantList& args = {}) {
|
||||
QList<QMap<QString, QVariant>> results;
|
||||
QSqlQuery query;
|
||||
query.prepare(queryStr);
|
||||
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
query.bindValue(i, args[i]);
|
||||
}
|
||||
|
||||
if (!query.exec()) {
|
||||
qCritical() << "SQL error:" << query.lastError().text();
|
||||
qCritical() << "Query:" << queryStr;
|
||||
return results;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
QMap<QString, QVariant> row;
|
||||
for (int i = 0; i < query.record().count(); ++i) {
|
||||
row.insert(query.record().fieldName(i), query.value(i));
|
||||
}
|
||||
results.append(row);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
// 检查数据库是否已连接
|
||||
bool isConnected() const {
|
||||
return m_db.isOpen();
|
||||
}
|
||||
////////////////BASE//////////////////////
|
||||
bool createTable(const QString& tableName, const QList<std::pair<QString, QString>>& columns) {
|
||||
if (columns.empty()) {
|
||||
qDebug() << "Create table failed: columns are empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList columnDefinitions;
|
||||
for (const auto& pair : columns) {
|
||||
columnDefinitions << QString("%1 %2").arg(pair.first).arg(pair.second);
|
||||
}
|
||||
|
||||
// 确保表名被双引号包围,处理特殊字符的表名
|
||||
QString sql = QString("CREATE TABLE IF NOT EXISTS \"%1\" (%2)")
|
||||
.arg(tableName)
|
||||
.arg(columnDefinitions.join(", "));
|
||||
QSqlQuery query(m_db);
|
||||
bool res = query.exec(sql);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool dropTable(const QString& tableName) {
|
||||
QString sql = QString("DROP TABLE IF EXISTS %1").arg(tableName);
|
||||
return execute(sql);
|
||||
}
|
||||
|
||||
bool addColumn(const QString& tableName, const QString& columnName, const QString& columnType) {
|
||||
// 检查列名和类型是否有效
|
||||
if (columnName.isEmpty() || columnType.isEmpty()) {
|
||||
qDebug() << "Add column failed: column name or type is empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 构造 SQL 语句
|
||||
QString sql = QString("ALTER TABLE \"%1\" ADD COLUMN \"%2\" %3").arg(tableName, columnName, columnType);
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
query.prepare(sql);
|
||||
|
||||
// 执行 SQL 语句
|
||||
if (!query.exec()) {
|
||||
qDebug() << "Add column failed:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "Column" << columnName << "added to table" << tableName;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool tableExists(const QString& tableName) {
|
||||
// 使用 sqlite_master 查询表是否存在
|
||||
QString sql = QString("SELECT name FROM sqlite_master WHERE type='table' AND name='%1';").arg(tableName);
|
||||
|
||||
QList<QMap<QString, QVariant>> result = query(sql);
|
||||
return !result.isEmpty(); // 如果结果不为空,则表示表存在
|
||||
}
|
||||
|
||||
bool _insert(const QString& tableName,
|
||||
const std::map<QString, QVariant>& data) {
|
||||
// 如果数据为空,返回 false
|
||||
if (data.empty()) {
|
||||
qDebug() << "Insert failed: data is empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果表名为空,返回 false
|
||||
if (tableName.isEmpty()) {
|
||||
qDebug() << "Insert failed: tableName is empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList columns, values;
|
||||
for (const auto& pair : data) {
|
||||
columns << pair.first;
|
||||
// 直接插入数据(明文传输),需要确保数据已经适当转义
|
||||
values << "'" + pair.second.toString().replace("'", "''") + "'"; // 处理引号
|
||||
}
|
||||
|
||||
// 构造 SQL 查询语句(不使用绑定参数)
|
||||
QString sql = QString("INSERT INTO \"%1\" (%2) VALUES (%3)")
|
||||
.arg(tableName) // 使用双引号包围表名,确保兼容特殊字符
|
||||
.arg(columns.join(", "))
|
||||
.arg(values.join(", "));
|
||||
|
||||
qDebug() << "Generated SQL: " << sql;
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
|
||||
// 检查数据库连接
|
||||
if (!m_db.isOpen()) {
|
||||
qDebug() << "Database is not open!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并检查错误
|
||||
if (!query.exec(sql)) {
|
||||
qDebug() << "Insert failed:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _update(const QString& tableName,
|
||||
const std::map<QString, QVariant>& data,
|
||||
const std::map<QString, QVariant>& conditions) {
|
||||
if (data.empty() || conditions.empty()) {
|
||||
qDebug() << "Update failed: data or conditions are empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList setClauses;
|
||||
for (const auto& pair : data) {
|
||||
QString value = pair.second.toString().replace("'", "''"); // 防止单引号注入
|
||||
setClauses << QString("%1 = '%2'").arg(pair.first).arg(value);
|
||||
}
|
||||
|
||||
QStringList whereClauses;
|
||||
for (const auto& pair : conditions) {
|
||||
QString conditionValue = pair.second.toString().replace("'", "''");
|
||||
whereClauses << QString("%1 = '%2'").arg(pair.first).arg(conditionValue);
|
||||
}
|
||||
|
||||
// 构造 SQL 查询语句(不使用绑定参数)
|
||||
QString sql = QString("UPDATE \"%1\" SET %2 WHERE %3")
|
||||
.arg(tableName)
|
||||
.arg(setClauses.join(", "))
|
||||
.arg(whereClauses.join(" AND "));
|
||||
|
||||
qDebug() << "Generated SQL: " << sql;
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
|
||||
// 检查数据库连接
|
||||
if (!m_db.isOpen()) {
|
||||
qDebug() << "Database is not open!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并检查错误
|
||||
if (!query.exec(sql)) {
|
||||
qDebug() << "Update failed:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool _delete(const QString& tableName,
|
||||
const std::map<QString, QVariant>& conditions) {
|
||||
if (conditions.empty()) {
|
||||
qDebug() << "Delete failed: conditions are empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList whereClauses;
|
||||
for (const auto& pair : conditions) {
|
||||
whereClauses << QString("%1 = :%2").arg(pair.first).arg(pair.first + "_condition");
|
||||
}
|
||||
|
||||
QString sql = QString("DELETE FROM \"%1\" WHERE %2")
|
||||
.arg(tableName)
|
||||
.arg(whereClauses.join(" AND "));
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
query.prepare(sql);
|
||||
|
||||
// 绑定条件参数
|
||||
for (const auto& pair : conditions) {
|
||||
query.bindValue(":" + pair.first + "_condition", QVariant::fromValue(pair.second));
|
||||
}
|
||||
|
||||
if (!query.exec()) {
|
||||
qDebug() << "Delete failed:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::map<QString, QVariant>> _search(const QString& tableName,
|
||||
const QStringList& columns,
|
||||
const std::map<QString, QVariant>& conditions = {}) {
|
||||
// 如果没有指定列名,则选择所有列
|
||||
QStringList selectColumns = columns.isEmpty() ? QStringList("*") : columns;
|
||||
|
||||
// 构建基本的 SQL 查询
|
||||
QString sql = QString("SELECT %1 FROM \"%2\"").arg(selectColumns.join(", "), tableName);
|
||||
|
||||
if (!conditions.empty()) {
|
||||
QStringList whereClauses;
|
||||
for (const auto& pair : conditions) {
|
||||
// 直接拼接条件,确保值已经处理好以防 SQL 注入
|
||||
QString value = pair.second.toString().replace("'", "''"); // 防止单引号注入
|
||||
whereClauses << QString("%1 = '%2'").arg(pair.first).arg(value);
|
||||
}
|
||||
sql += " WHERE " + whereClauses.join(" AND ");
|
||||
}
|
||||
|
||||
qDebug() << "Generated SQL: " << sql;
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
|
||||
// 检查数据库连接
|
||||
if (!m_db.isOpen()) {
|
||||
qDebug() << "Database is not open!";
|
||||
return {};
|
||||
}
|
||||
|
||||
// 执行查询并检查错误
|
||||
if (!query.exec(sql)) {
|
||||
qDebug() << "Search failed:" << query.lastError().text();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::map<QString, QVariant>> results;
|
||||
while (query.next()) {
|
||||
std::map<QString, QVariant> row;
|
||||
for (int i = 0; i < query.record().count(); ++i) {
|
||||
row[query.record().fieldName(i)] = query.value(i);
|
||||
}
|
||||
results.push_back(row);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
///////////////////EX//FUNC/////////////////
|
||||
bool exportTableToCSV(const QString& tableName, const QString& filePath, std::mutex& _mutex) {
|
||||
using namespace std::chrono; // 便于使用 chrono 相关功能
|
||||
// 记录开始时间
|
||||
auto start = high_resolution_clock::now();
|
||||
// 查询表中的所有数据
|
||||
QString csvFileName = filePath + "/" + tableName + ".csv";
|
||||
QString sql = QString("SELECT * FROM \"%1\"").arg(tableName);
|
||||
QSqlQuery query(m_db);
|
||||
|
||||
if (!query.exec(sql)) {
|
||||
qCritical() << "Query execution failed: " << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果查询没有返回数据,返回 false
|
||||
if (!query.next()) {
|
||||
qDebug() << "No data found in table" << tableName;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 打开文件进行写入
|
||||
QFile file(csvFileName);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qCritical() << "Failed to open file" << csvFileName;
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream out(&file);
|
||||
|
||||
// 获取列名顺序
|
||||
QSqlRecord record = query.record();
|
||||
QStringList columns;
|
||||
for (int i = 0; i < record.count(); ++i) {
|
||||
columns << record.fieldName(i); // 保证列名按查询结果顺序提取
|
||||
}
|
||||
|
||||
// 写入表头(列名)
|
||||
out << columns.join(",") << "\n"; // 表头以逗号分隔
|
||||
|
||||
// 写入数据行
|
||||
do {
|
||||
QStringList values;
|
||||
for (const auto& column : columns) {
|
||||
values << query.value(column).toString(); // 获取每列的值,保持列名顺序
|
||||
}
|
||||
out << values.join(",") << "\n"; // 每行数据以逗号分隔
|
||||
} while (query.next()); // 循环处理所有数据行
|
||||
|
||||
file.close(); // 关闭文件
|
||||
// 记录结束时间
|
||||
auto end = high_resolution_clock::now();
|
||||
|
||||
// 计算耗时
|
||||
auto duration = duration_cast<milliseconds>(end - start);
|
||||
qDebug() << csvFileName << "EXPORT CSV COST: " << duration.count() << "ms";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QString m_dbName;
|
||||
QString m_dbPath;
|
||||
QSqlDatabase m_db;
|
||||
};
|
||||
|
||||
class CsvWriter
|
||||
{
|
||||
public:
|
||||
CsvWriter()
|
||||
{
|
||||
try
|
||||
{
|
||||
m_json = readJsonFromPath("./sqldrivers/sqliteCfg.json");
|
||||
for (auto& data : m_json["数据列表"]){
|
||||
db_InitColumns.append({ QString::fromStdString(data),"TEXT" });
|
||||
db_newCol.append({ QString::fromStdString(data),"TEXT" });
|
||||
}
|
||||
for (auto& data : m_json["链接到UI表格数据列表"].items()){
|
||||
csvAndChartLink[QString::fromStdString(data.key())] = QString::fromStdString(data.value());
|
||||
}
|
||||
if(m_json["新增数据列表"].size()>0){
|
||||
//for (auto& data : m_json["新增数据列表"]){
|
||||
// db_newCol.append({ QString::fromStdString(data),"TEXT" });
|
||||
//}
|
||||
m_json["新增数据列表"].clear();
|
||||
saveJsonFromPath("./sqldrivers/sqliteCfg.json", m_json);
|
||||
}
|
||||
for (auto& data : m_json["判断NG依据数据列表"]) {
|
||||
isNgDepends.push_back(QString::fromStdString(data));
|
||||
}
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
std::cerr << "readJsonFromPath error" << std::endl;
|
||||
}
|
||||
init();
|
||||
}
|
||||
~CsvWriter()
|
||||
{
|
||||
//stopAutoExport();
|
||||
}
|
||||
std::map<QString, QString>csvAndChartLink;
|
||||
void addtData(const QString& snCode, const std::map<QString, QVariant>& data) {
|
||||
std::lock_guard<std::mutex> locker(_mutex);
|
||||
QString currentProcessCsvName = getCurrentProcessCsvName();
|
||||
if (currentProcessCsvName != currentProcessCsvNameCache)
|
||||
if (_db->createTable(currentProcessCsvName, db_InitColumns))
|
||||
currentProcessCsvNameCache = currentProcessCsvName;
|
||||
auto res = _db->_search(currentProcessCsvName, {}, { {"条码",snCode} });
|
||||
if (res.empty() == true)//当前数据为空时查询过去的数据是否为空
|
||||
{
|
||||
auto lastRes = _db->_search(getLastProcessCsvName(), {}, { {"条码",snCode} });
|
||||
if (lastRes.empty() == true)//过去的数据也为空 则视作现在要插入的数据为全新的数据
|
||||
{
|
||||
std::map<QString, QVariant> insertData = data;
|
||||
insertData["条码"] = snCode;
|
||||
insertData["创建时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
|
||||
insertData["修改时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
|
||||
_db->_insert(currentProcessCsvName, insertData);
|
||||
}
|
||||
else//过去的数据不为空 更新到过去的数据上
|
||||
{
|
||||
std::map<QString, QVariant> updateData = data;
|
||||
updateData["修改时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
|
||||
_db->_update(getLastProcessCsvName(), updateData, { {"条码",snCode} });
|
||||
}
|
||||
|
||||
}
|
||||
else//当前数据不为空 更新到当前数据上
|
||||
{
|
||||
std::map<QString, QVariant> updateData = data;
|
||||
updateData["修改时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
|
||||
_db->_update(getCurrentProcessCsvName(), updateData, { {"条码",snCode} });
|
||||
}
|
||||
if (timer.elapsed() > m_intervalMs)
|
||||
{
|
||||
exportCsv();
|
||||
timer.start();
|
||||
}
|
||||
}
|
||||
bool isNewData(const QString& snCode) {
|
||||
std::lock_guard<std::mutex> locker(_mutex);
|
||||
auto res = _db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} });
|
||||
return res.empty();
|
||||
}
|
||||
bool isNgData(const QString& snCode) {
|
||||
std::lock_guard<std::mutex> locker(_mutex);
|
||||
auto res = _db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} });
|
||||
if (res.empty() == true)
|
||||
return false;
|
||||
for (auto& data : isNgDepends) {
|
||||
if (res[0][data].toString() == "NG")
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
std::vector<QString> isNgDepends;
|
||||
QQueue<std::pair< QString, std::map<QString, QVariant>> > addDataCacheQueue;
|
||||
std::mutex _mutex;
|
||||
SQLiteDB* _db;
|
||||
int m_intervalMs = 10000;
|
||||
QElapsedTimer timer;
|
||||
QString currentProcessCsvNameCache;
|
||||
nlohmann::json m_json;
|
||||
QList<std::pair<QString, QString>> db_newCol = {};
|
||||
QList<std::pair<QString, QString>> db_InitColumns = {
|
||||
{"条码", "TEXT NOT NULL PRIMARY KEY"},
|
||||
{"创建时间", "TEXT"},
|
||||
{"修改时间", "TEXT"}
|
||||
};
|
||||
//void run()
|
||||
//{
|
||||
// init();
|
||||
// while (m_running == true) {
|
||||
// QThread::msleep(m_intervalMs);
|
||||
// while (addDataCacheQueue.empty() == false)
|
||||
// {
|
||||
// auto data = addDataCacheQueue.dequeue();
|
||||
// addtData(data.first, data.second);
|
||||
// }
|
||||
// exportCsv();
|
||||
// }
|
||||
// delete _db;
|
||||
//}
|
||||
void init()
|
||||
{
|
||||
std::lock_guard<std::mutex> locker(_mutex);
|
||||
_db = new SQLiteDB("./sqlDatabse/", "database");
|
||||
_db->connect();
|
||||
if (!_db->createTable(getLastProcessCsvName(), db_InitColumns)) {
|
||||
qDebug() << "Failed to create table " << getLastProcessCsvName();
|
||||
}
|
||||
currentProcessCsvNameCache = getCurrentProcessCsvName();
|
||||
if (!_db->createTable(currentProcessCsvNameCache, db_InitColumns)) {
|
||||
qDebug() << "Failed to create table " << currentProcessCsvNameCache;
|
||||
}
|
||||
for (auto& data : db_newCol) {
|
||||
_db->addColumn(getLastProcessCsvName(), data.first, data.second);
|
||||
_db->addColumn(getCurrentProcessCsvName(), data.first, data.second);
|
||||
}
|
||||
timer.start();
|
||||
}
|
||||
QString getCurrentProcessCsvName() {
|
||||
// 获取当前时间
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
|
||||
// 获取当前小时和分钟
|
||||
int hour = currentDateTime.time().hour();
|
||||
int minute = currentDateTime.time().minute();
|
||||
|
||||
// 判断是否在白班时间范围(8:30到20:30)
|
||||
bool isDayShift = (hour > 8 || (hour == 8 && minute >= 30)) && (hour < 20 || (hour == 20 && minute <= 30));
|
||||
|
||||
// 判断是否是前一天的夜班
|
||||
bool isDayBefore = hour <= 8 || (hour == 8 && minute <= 29);
|
||||
|
||||
// 获取当前日期(yyyy-MM-dd格式)
|
||||
QString dateStr;
|
||||
if (isDayBefore == true)
|
||||
dateStr = currentDateTime.addDays(-1).toString("yyyy-MM-dd");
|
||||
else
|
||||
dateStr = currentDateTime.toString("yyyy-MM-dd");
|
||||
|
||||
// 根据时间段返回班次信息
|
||||
if (isDayShift) {
|
||||
return (dateStr + "白班");
|
||||
}
|
||||
else {
|
||||
return (dateStr + "夜班");
|
||||
}
|
||||
}
|
||||
QString getLastProcessCsvName() {
|
||||
// 获取当前时间
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
|
||||
// 获取当前小时和分钟
|
||||
int hour = currentDateTime.time().hour();
|
||||
int minute = currentDateTime.time().minute();
|
||||
|
||||
// 判断是否在白班时间范围(8:30到20:30)
|
||||
bool isDayShift = (hour == 8 && minute >= 30) && (hour == 20 && minute <= 30);
|
||||
// 判断是否为上一天
|
||||
bool isDayBefore = hour == 20 && minute <= 30;
|
||||
// 获取上一班的日期
|
||||
QDateTime lastShiftDateTime;
|
||||
if (isDayBefore) {
|
||||
// 当前是白班,上一班是前一天的夜班
|
||||
lastShiftDateTime = currentDateTime.addDays(-1);
|
||||
}
|
||||
else
|
||||
lastShiftDateTime = currentDateTime;
|
||||
|
||||
// 获取上一班的日期(yyyy-MM-dd格式)
|
||||
QString dateStr = lastShiftDateTime.toString("yyyy-MM-dd");
|
||||
|
||||
// 根据时间段返回班次信息
|
||||
if (isDayShift) {
|
||||
return (dateStr + "夜班"); // 上一班是夜班
|
||||
}
|
||||
else {
|
||||
return (dateStr + "白班"); // 上一班是白班
|
||||
}
|
||||
}
|
||||
//void startAutoExport(int intervalMs = 10000) {
|
||||
// m_intervalMs = intervalMs;
|
||||
// m_running = true;
|
||||
// this->start();
|
||||
//}
|
||||
//void stopAutoExport() {
|
||||
// m_running = false;
|
||||
// this->wait();
|
||||
//}
|
||||
void exportCsv()
|
||||
{
|
||||
//std::lock_guard<std::mutex> locker(_mutex);
|
||||
_db->exportTableToCSV(getLastProcessCsvName(), "./csv/", _mutex);
|
||||
_db->exportTableToCSV(getCurrentProcessCsvName(), "./csv/", _mutex);
|
||||
QString currentProcessCsvName = getCurrentProcessCsvName();
|
||||
if (currentProcessCsvName != currentProcessCsvNameCache)
|
||||
if (!_db->createTable(currentProcessCsvName, db_InitColumns)) {
|
||||
return;
|
||||
}
|
||||
else
|
||||
currentProcessCsvNameCache = currentProcessCsvName;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma once
|
||||
Vendored
+52
-13
@@ -21,11 +21,16 @@
|
||||
const char* packSplit = "|"; // Separator between fields
|
||||
const char* resultSplitStart = "[resultCmdSplitStart]"; // PLC result start delimiter
|
||||
const char* resultSplitEnd = "[resultCmdSplitEnd]"; // PLC result end delimiter
|
||||
const char* csvChartSplitStart = "[csvChartCmdSplitStart]"; // CSV and chart data start delimiter
|
||||
const char* csvChartSplitEnd = "[csvChartCmdSplitEnd]"; // CSV and chart data end delimiter
|
||||
const char* csvStart = "[csvCmdSplitStart]"; // CSV and chart data start delimiter
|
||||
const char* csvEnd = "[csvCmdSplitEnd]"; // CSV and chart data end delimiter
|
||||
const char* chartStart = "[chartCmdSplitStart]"; // CSV and chart data start delimiter
|
||||
const char* chartEnd = "[chartCmdSplitEnd]"; // CSV and chart data end delimiter
|
||||
namespace logicUiTransport
|
||||
{
|
||||
QByteArray encodeAllData(QString SN,QList<QString> plcResult, std::map<QString, QVariant> csvAndChartData)
|
||||
//打包图表只能输入 "OK" "NG"
|
||||
QByteArray encodeAllData(QString SN,QList<QString> plcResult,
|
||||
std::map<QString, QVariant> csvData)
|
||||
//std::map<QString, QVariant> ChartData)
|
||||
{
|
||||
QByteArray encodedData;
|
||||
|
||||
@@ -37,16 +42,27 @@ namespace logicUiTransport
|
||||
}
|
||||
encodedData.append(resultSplitEnd);
|
||||
|
||||
// Encode csvAndChartData map
|
||||
encodedData.append(csvChartSplitStart);
|
||||
// Encode csvData map
|
||||
encodedData.append(csvStart);
|
||||
encodedData.append(QString("条码") + packSplit);
|
||||
encodedData.append(SN + packSplit);
|
||||
for (const auto& pair : csvAndChartData)
|
||||
for (const auto& pair : csvData)
|
||||
{
|
||||
encodedData.append(pair.first.toUtf8() + packSplit);
|
||||
encodedData.append(pair.second.toString().toUtf8() + packSplit);
|
||||
}
|
||||
encodedData.append(csvChartSplitEnd);
|
||||
encodedData.append(csvEnd);
|
||||
|
||||
// Encode csvData map
|
||||
//encodedData.append(chartStart);
|
||||
//encodedData.append(QString("条码") + packSplit);
|
||||
//encodedData.append(SN + packSplit);
|
||||
//for (const auto& pair : ChartData)
|
||||
//{
|
||||
// encodedData.append(pair.first.toUtf8() + packSplit);
|
||||
// encodedData.append(pair.second.toString().toUtf8() + packSplit);
|
||||
//}
|
||||
//encodedData.append(chartEnd);
|
||||
|
||||
return encodedData;
|
||||
}
|
||||
@@ -74,13 +90,13 @@ namespace logicUiTransport
|
||||
return plcResultList;
|
||||
}
|
||||
|
||||
std::map<QString, QVariant> decodeCsvAndChartData(QByteArray& input)
|
||||
std::map<QString, QVariant> decodeCsvData(QByteArray& input)
|
||||
{
|
||||
std::map<QString, QVariant> csvAndChartData;
|
||||
std::map<QString, QVariant> csvResultData;
|
||||
|
||||
// Find the data between csvChartSplitStart and csvChartSplitEnd
|
||||
int startIndex = input.indexOf(csvChartSplitStart) + strlen(csvChartSplitStart);
|
||||
int endIndex = input.indexOf(csvChartSplitEnd);
|
||||
int startIndex = input.indexOf(csvStart) + strlen(csvStart);
|
||||
int endIndex = input.indexOf(csvEnd);
|
||||
|
||||
if (startIndex >= 0 && endIndex >= 0 && endIndex > startIndex)
|
||||
{
|
||||
@@ -92,15 +108,38 @@ namespace logicUiTransport
|
||||
{
|
||||
if (i + 1 < csvList.size())
|
||||
{
|
||||
csvAndChartData[csvList[i]] = QVariant(csvList[i + 1]);
|
||||
csvResultData[csvList[i]] = QVariant(csvList[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return csvAndChartData;
|
||||
return csvResultData;
|
||||
}
|
||||
|
||||
//std::map<QString, QVariant> decodeChartData(QByteArray& input)
|
||||
//{
|
||||
// std::map<QString, QVariant> chartResultData;
|
||||
|
||||
// int startIndex = input.indexOf(chartStart) + strlen(chartStart);
|
||||
// int endIndex = input.indexOf(chartEnd);
|
||||
|
||||
// if (startIndex >= 0 && endIndex >= 0 && endIndex > startIndex)
|
||||
// {
|
||||
// QByteArray chartData = input.mid(startIndex, endIndex - startIndex);
|
||||
// QStringList chartList = QString(chartData).split(packSplit, Qt::SkipEmptyParts);
|
||||
|
||||
// // Decode key-value pairs
|
||||
// for (int i = 0; i < chartList.size(); i += 2)
|
||||
// {
|
||||
// if (i + 1 < chartList.size())
|
||||
// {
|
||||
// chartResultData[chartList[i]] = QVariant(chartList[i + 1]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return chartResultData;
|
||||
//}
|
||||
};
|
||||
|
||||
#pragma once
|
||||
|
||||
Vendored
-1
@@ -10,7 +10,6 @@
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <corecrt_wstring.h>
|
||||
using namespace cv;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user