diff --git a/BaseModules/Hd_AI_algo_yiCiZhuYe_CanYe/CMakeLists.txt b/BaseModules/Hd_AI_algo_yiCiZhuYe_CanYe/CMakeLists.txt new file mode 100644 index 0000000..be2265d --- /dev/null +++ b/BaseModules/Hd_AI_algo_yiCiZhuYe_CanYe/CMakeLists.txt @@ -0,0 +1,71 @@ +# 获取获取当前目录名 +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" "halconAlgo" "myTools" "handdleAI") +foreach(child ${DLL_NAMES}) + LIST(APPEND ENV_INCLUDE ${${child}_include}) + LIST(APPEND ENV_LIB ${${child}_lib}) + LIST(APPEND ENV_TARGET ${${child}_target_link}) +endforeach() +message(" ENV_INCLUDE : " ${ENV_INCLUDE} ) +message(" ENV_LIB : " ${ENV_LIB} ) +message(" ENV_TARGET : " ${ENV_TARGET} ) +include_directories( + + ${ENV_INCLUDE} + ) + +link_directories ( + ${ENV_LIB} + + ) + + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_CXX_STANDARD 11) +SET(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +FILE(GLOB HEAD_FILES "./*.h" ) +FILE(GLOB SRC_FILES "./*.cpp") +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} + ${UI_FILES} + ) + + + +set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + ) + + +target_link_libraries(${CURRENT_FOLDER} PRIVATE + ${ENV_TARGET} + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Network + ) + + +# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY) + + + + +string(TIMESTAMP RUN_TIME) +message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME}) diff --git a/BaseModules/Hd_AI_algo_yiCiZhuYe_CanYe/Hd_AI_algo_yiCiZhuYe_CanYe.cpp b/BaseModules/Hd_AI_algo_yiCiZhuYe_CanYe/Hd_AI_algo_yiCiZhuYe_CanYe.cpp new file mode 100644 index 0000000..747fd72 --- /dev/null +++ b/BaseModules/Hd_AI_algo_yiCiZhuYe_CanYe/Hd_AI_algo_yiCiZhuYe_CanYe.cpp @@ -0,0 +1,1081 @@ +#include "Hd_AI_algo_yiCiZhuYe_CanYe.h" +#include + +#include +#include +#include +#include +using namespace cv; + +//原图保存文件夹s + QString oriImgSaveDir = "E:/601线/一次注液CCD/原图/"; +//原图class图保存文件夹 + QString classImgSaveDir = "E:/601线/一次注液CCD/class图/"; +//结果保存文件夹 + QString resImgSaveDir = "E:/601线/一次注液CCD/结果图/"; + +//切图的class的width,根据项目实际设置! + int sizeW = 150; +//切图的class的height,根据项目实际设置! + int sizeH = 150; +//切图的class的width,根据项目实际设置!0为黑,255为白; + int fillColour = 0; + + +//检测线程锁 + QMutex* detect_mutex; +//保存线程锁 + QMutex* saveStruct_mutex; +//检测线程运行标志 + bool ifdetectThread = false; + + QString cameraKey_index = ""; + + //初始化参数列表 + QByteArrayList initValueList; + static void createDirectoryIfNotExists(const QString& path) { + QDir dir; + dir.mkpath(path); + } + static std::string getCurrentTime() { + + // 获取当前时间点 + auto now = std::chrono::system_clock::now(); + + // 转换为字符串 + auto currentTime = std::chrono::system_clock::to_time_t(now); + auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 100; + std::tm* localTime = std::localtime(¤tTime); + std::stringstream ss; + ss << std::put_time(localTime, "%H-%M-%S") << "-" << std::setfill('0') << std::setw(2) << ms.count(); + return ss.str(); + } + static QString getCurrentDate() + { + QDateTime currentDateTime = QDateTime::currentDateTime(); + return currentDateTime.toString("yyyy-MM-dd"); + } + static QString getCurrentHour() + { + QDateTime currentDateTime = QDateTime::currentDateTime(); + return QString::number(currentDateTime.time().hour())+"H"; + } + QString byteArrayToUnicode(const QByteArray array) { + + // state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功 + // 如果转换成功,则值为0,如果值大于0,则说明转换失败 + QTextCodec::ConverterState state; + // 先尝试使用utf-8的方式把QByteArray转换成QString + QString text = QTextCodec::codecForName("UTF-8")->toUnicode(array.constData(), array.size(), &state); + // 如果转换时无效字符数量大于0,说明编码格式不对 + if (state.invalidChars > 0) + { + // 再尝试使用GBK的方式进行转换,一般就能转换正确(当然也可能是其它格式,但比较少见了) + text = QTextCodec::codecForName("GBK")->toUnicode(array); + } + return text; + } + static cv::Rect findMaxAreaContour(cv::Mat src) + { + int maxIndex = 0, maxArea = 0; + std::vector>contours; + cv::findContours(src, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); + if (contours.size() == 0) + return cv::Rect(0, 0, 0, 0); + for (int i = 0; i < contours.size(); i++) + { + int Area = cv::contourArea(contours[i]); + if (Area > maxArea) + { + maxArea = Area; + maxIndex = i; + } + } + if (contours.size() != 0) + return cv::boundingRect(contours[maxIndex]); + return cv::Rect(0, 0, 0, 0); + } + inline std::string utf8_to_gbk(const std::string& str) + { + std::wstring_convert> conv; + std::wstring tmp_wstr = conv.from_bytes(str); + //GBK locale name in windows + const char* GBK_LOCALE_NAME = ".936"; + std::wstring_convert> convert(new std::codecvt_byname(GBK_LOCALE_NAME)); + return convert.to_bytes(tmp_wstr); + } + void getAllFiles(std::string path, std::vector& files, std::string format) + { + 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)); //保存文件夹名 + getAllFiles(p.assign(path).append("\\").append(fileinfo.name), files, format); //递归遍历文件夹 + } + } + else + { + files.push_back(p.assign(path).append("\\").append(fileinfo.name));//如果不是文件夹,储存文件名 + } + } while (_findnext(hFile, &fileinfo) == 0); + _findclose(hFile); + } + } + QString geteOriSaveFromat(int i,QString time) + { + return oriImgSaveDir + time + + "ORI_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + "_" + QString::number(i) + ".bmp"; + } + QString getResSaveFromat() + { + return resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + + "RES_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".png"; + } +// 缺陷信息结构体 +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; + +//Mat转Halcon图像 +void MatToHObject(cv::Mat& image, HalconCpp::HObject* Hobj) +{ + int hgt = image.rows; + int wid = image.cols; + int i; + if (image.type() == CV_8UC3) + { + HalconCpp::HImage himage = HalconCpp::HImage(); + + std::vector imgchannel; + split(image, imgchannel); + cv::Mat imgB = imgchannel[0]; + cv::Mat imgG = imgchannel[1]; + cv::Mat imgR = imgchannel[2]; + uchar* dataR = new uchar[hgt * wid]; + uchar* dataG = new uchar[hgt * wid]; + uchar* dataB = new uchar[hgt * wid]; + for (i = 0; i < hgt; i++) + { + memcpy(dataR + wid * i, imgR.data + imgR.step * i, wid); + memcpy(dataG + wid * i, imgG.data + imgG.step * i, wid); + memcpy(dataB + wid * i, imgB.data + imgB.step * i, wid); + } + himage.GenImage3("byte", wid, hgt, dataR, dataG, dataB); + HalconCpp::HString tmpType; + Hlong tmpW, tmpH; + void* hImgPtR, * hImgPtG, * hImgPtB; + himage.GetImagePointer3(&hImgPtR, &hImgPtG, &hImgPtB, &tmpType, &tmpW, &tmpH); + + GenImage3(Hobj, "byte", wid, hgt, (Hlong)hImgPtR, (Hlong)hImgPtG, (Hlong)hImgPtB); + delete[]dataR; + delete[]dataG; + delete[]dataB; + dataR = NULL; + dataG = NULL; + dataB = NULL; + } + else if (image.type() == CV_8UC1) + { + //HalconCpp::HImage himage = HalconCpp::HImage(); + + ////uchar* data = new uchar[hgt * wid]; + ////for (i = 0; i < hgt; i++) + ////{ + //// memcpy(data + wid * i, image.data + image.step * i, wid); + ////} + ////gen_image_const + //himage.GenImage1("byte", wid, hgt, image.data); + + //HalconCpp::HString tmpType; + //Hlong tmpW, tmpH; + //void* hImgPt; + //hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH); + //GenImage1(&Hobj, "byte", wid, hgt, (Hlong)hImgPt); + GenImage1(Hobj, "byte", wid, hgt, (Hlong)image.data); + + /* delete[] data; + data = NULL;*/ + + } + else if (image.type() == CV_16UC1) + { + HalconCpp::HImage himage = HalconCpp::HImage(); + + ushort* data = new ushort[hgt * wid * 2]; + + memcpy(data, image.data, hgt * wid * 2); + + + himage.GenImage1("uint2", wid, hgt, data); + + HalconCpp::HString tmpType; + Hlong tmpW, tmpH; + void* hImgPt; + hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH); + GenImage1(Hobj, "uint2", wid, hgt, (Hlong)hImgPt); + + delete[] data; + data = NULL; + + } + else if (image.type() == CV_16SC1) + { + HalconCpp::HImage himage = HalconCpp::HImage(); + + short* data = new short[hgt * wid * 2]; + + memcpy(data, image.data, hgt * wid * 2); + + + himage.GenImage1("int2", wid, hgt, data); + + HalconCpp::HString tmpType; + Hlong tmpW, tmpH; + void* hImgPt; + hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH); + GenImage1(Hobj, "int2", wid, hgt, (Hlong)hImgPt); + + delete[] data; + data = NULL; + + } + +} + +//判断文件是否存在,不存在则创建 +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 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_algo_fanMianTieJiao::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_algo_fanMianTieJiao* create() +{ + qDebug() << "[INFO] " << " Hd_AI_algo_fanMianTieJiao create success!" ; + return new Hd_AI_algo_fanMianTieJiao; +} + +void destory(Hd_AI_algo_fanMianTieJiao* ptr) +{ + qDebug() << "[INFO] " << "Hd_AI_algo_fanMianTieJiao destory success!"; + if(ptr) + { + delete ptr; + ptr = nullptr; + } +} + +Hd_AI_algo_fanMianTieJiao::Hd_AI_algo_fanMianTieJiao() +{ + detect_mutex = new QMutex; + saveStruct_mutex = new QMutex; + ifdetectThread = false; + for (int i = 0; i < 4; i++) + { + QString DirPath = "E:/testImg/source" + QString::number(i); + QStringList imgFilters; + imgFilters << "*.jpg" << "*.png" << "*.PNG" << "*.gif" << "*.tif" << "*.jpeg" << "*.bmp"; + QDir qdir(DirPath); + //返回文件名列表 + QStringList localSourceImgsName = qdir.entryList(imgFilters, QDir::Files | QDir::Readable, QDir::Name); + for (int j = 0; j < localSourceImgsName.size(); j++) + { + QString imgPath = DirPath + "/" + localSourceImgsName[j]; + QFile myf(imgPath); + if (myf.exists()) + myf.remove(); + //Sleep(1); + } + } +} + +Hd_AI_algo_fanMianTieJiao::~Hd_AI_algo_fanMianTieJiao() +{ + ifdetectThread = false; + Sleep(10); + if (detect_mutex) + { + delete detect_mutex; + detect_mutex = nullptr; + } + if (saveStruct_mutex) + { + delete saveStruct_mutex; + saveStruct_mutex = nullptr; + } + /*DestroySegObj(pSeg); + DestroyClsObj(pCls);*/ +} +//从类中读数据到实例对象 +bool Hd_AI_algo_fanMianTieJiao::readData(std::vector&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()>0) + vec_mat.push_back(HikMat[0]); + //qDebug() << __FUNCTION__ << " line:" << __LINE__ << " resMat.data err:"; + } + //if (allNum++ % 2 == 0) + // data = "2*3*2";// resByte.dequeue(); + //else + data = "1*0*0";//1OK,2NG + resByte.clear(); + ////之后根据结果类修改 + //if(resIfNg == true) + // data = "NG"; + //else data = "OK"; + detect_mutex->unlock(); + /*if(cameraKey_index.contains('_')) + qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName:" + << cameraKey_index.split("_")[0] << " imgIndex:" << cameraKey_index.split("_")[1]; + else + qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName imgIndex:" << cameraKey_index;*/ + return true; +} +//从类中读数据到实例对象 +bool Hd_AI_algo_fanMianTieJiao::encodeResultValue(QVector append_value,QByteArray &resultByte) +{ + try + { + std::string sendMsg; + for(int i = 0 ; i < append_value.size();i++) + { + std::string value = append_value.at(1); + //type + int type = 3; + std::string m_type; + m_type.insert(0,4,'1'); + memcpy ( (void*)m_type.c_str(),(void*)&type,4 ); + sendMsg.append(m_type); + + //len + int len = value.length(); + std::string m_len; + m_len.insert(0,4,'1'); + memcpy ( (void*)m_len.c_str(),(void*)&len,4 ); + sendMsg.append(m_len); + + //data x + sendMsg.append(value); + } + resultByte = QByteArray::fromStdString(sendMsg); + } catch (QString ev) + { + qCritical() << "[Error] " << " ev:" << ev; + return false; + } + return true; +} + +int myallNum[4] = {0}; +QMap lastImgMap; +//接收数据 +bool Hd_AI_algo_fanMianTieJiao::writeData(std::vector& 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(); + for (int i = 0; i < vec_mat.size(); i++) + HikMat.enqueue(vec_mat[i]); + std::cout<< "[Error] " << " vec_mat is null !"; + QByteArray source_savePath; + QByteArray sData = data; + QByteArrayList splitDataList = sData.split(','); + if (splitDataList.size() >= 4) + { + if (splitDataList[2].contains('_')) + cameraKey_index = splitDataList[2]; + QByteArray saveDir = splitDataList[0] + "/" + splitDataList[1] + "/"; + isDirExist(byteArrayToUnicode(saveDir)); //不存在,创建 + QString sdataTime= QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz"); + source_savePath = splitDataList[0] + "/" + splitDataList[1] + "/" + sdataTime.toLocal8Bit() + "-" + splitDataList[2] + "-" + splitDataList[3];// +".bmp"; + } + //int index = -1; + /*if (sData.contains("offline-camera0")) + { + index = 0; + savePath = "E:\\testImg\\source0\\"+QString::number(myallNum[0]++) + ".bmp"; + } + else if (sData.contains("offline-camera1")) + { + index = 1; + savePath = "E:\\testImg\\source1\\" + QString::number(myallNum[1]++) + ".bmp"; + } + else if (sData.contains("offline-camera2")) + { + index = 2; + savePath = "E:\\testImg\\source2\\" + QString::number(myallNum[2]++) + ".bmp"; + } + else if (sData.contains("offline-camera3")) + { + index = 3; + savePath = "E:\\testImg\\source3\\" + QString::number(myallNum[3]++) + ".bmp"; + }*/ + + QString timestr = getCurrentDate() + "//" + getCurrentHour() + "//"; + createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); + for (int i = 0; i < HikMat.size(); i++) + addImgToSaveStruct(HikMat[i], "0", geteOriSaveFromat(i, timestr));//保存原图 + + //if (myallNum[index] == 1) + //{ + // cv::Mat img; + // lastImgMap.insert(index, img); + //} + //else + //{ + // //判断和上一张图,是否重复 + // int dataLength = HikMat[0].total() * HikMat[0].elemSize(); + // bool res = false; + // if (myallNum[index] > 0) + // { + // cv::Mat img = lastImgMap.value(index); + // if (img.total() * img.elemSize() == dataLength) + // { + // res = memcmp(img.data, HikMat[0].data, dataLength) == 0; + // if (res == true) + // std::cout << "res ==true ====!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; + // } + // } + //} + //lastImgMap.insert(index, HikMat[0]); + + //or检测:保存路径,拍照面描述,相机key_第几张图,SN_时间戳 + //and检测:保存路径,拍照面描述,相机key_第几张图,相机key_第几张图,SN_时间戳,SN_时间戳 + //汇总:保存路径,拍照面描述,触发信号_序号列表0,SN_时间戳 + QString qstring_data = data; + QStringList datalist = qstring_data.split(','); + + + /*saveKey.enqueue("datalist[0]"); + Dir2D.enqueue("datalist[1]"); + QStringList SN_dataTime; + SN_dataTime = datalist[3].split('_'); + DateTime1 = "SN_dataTime[1]"; + SN.enqueue("SN_dataTime[0]");*/ + //qCritical() << __FUNCTION__ << " line: " << __LINE__ << " data:" << qstring_data; + detect_mutex->unlock(); + + //qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << " data: " << data << " run end"; + //cv::Mat resultDstImg = vec_mat[0].clone();// = pSeg->Evaluate(sourceImg); //返回单通道二值图 图片错误输出Image Error!但不报错。。 + //resultDstImg = pSeg->Evaluate(resultDstImg); + //resultDstImg.release(); + run(); + return true; +} + +//传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1... +//初始化 +bool Hd_AI_algo_fanMianTieJiao::initParas(QByteArray& byte) +{ + initValueList = byte.split('+'); + QStringList valueiList; + + if (byte.contains("onlySetParameter")) + { + qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,valueList[0]:" << initValueList[0]; + if (initValueList.size() > 1) + for (int i = 1; i < initValueList.size(); i++) + { + QString valuei = byteArrayToUnicode(initValueList[i]); + qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,lastName:" << initValueList[0] << " ,valuei:" << valuei; + } + return true; + } + + if (initValueList.size() > 1) + for (int i = 1; i < initValueList.size(); i++) + { + QString valuei = byteArrayToUnicode(initValueList[i]); + valueiList.append(valuei); + } + + /*pSeg = CreateSegObjS(pSeg_modulePath, 128, gpuId); + pCls = CreateClsObjV3(pCls_modulePath, gpuId, 1);*/ + + + //StationNo = vec_ret.at(0).toInt(); + + //InitThreads(StationNo, img2D); + //InitModels(StationNo, img2D); + seg_yicizhuyeCanye = CreateSegObjS("./model/seg-yicizhuyeCanye.BHD", 1, 0); + cls_yicizhuyeCanye = CreateClsObjV3("./model/cls-yicizhuyeCanye.BHD", 0, 1); + //运行检测线程 + ifdetectThread = true; + + //线程检测:结果类完成时,使用 + //ifThreadRunDetect = true; + //QFuture future1 = QtConcurrent::run(this, &Hd_AI_algo_fanMianTieJiao::detectThread); + //运行存图线程 + QFuture future2 = QtConcurrent::run(this, &Hd_AI_algo_fanMianTieJiao::saveImgThread); + //detectThread(); + + //原图总文件夹 + isDirExist(oriImgSaveDir); + //原图class总文件夹 + isDirExist(classImgSaveDir); + //结果图总文件夹 + isDirExist(resImgSaveDir); + + //qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ; + return true; +} +// 解码 +bool Hd_AI_algo_fanMianTieJiao::decodeAiValue(QByteArray byte,QVector &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_algo_fanMianTieJiao::AIdetect(std::vector& imgs, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime) +{ + try + { + //存图数据加保存队列,加锁,避免数据访问冲突 + saveStruct_mutex->lock(); + saveImgStruct mySave; + + //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(); + //} + //sourceImg = cv::imread("D:\\mySN15-46-33-86.bmp",-1); + //sourceImg = cv::imread("D:/1/Image_20241017204025590.bmp", -1); + cv::Mat Paint; + imgs[0].copyTo(Paint); + if (Paint.channels() == 1) + cvtColor(Paint, Paint, COLOR_GRAY2BGR); + QQueue defectInfoList; + + detect_mutex->lock(); + bool NG = false; + { + cv::Mat segResult = ~seg_yicizhuyeCanye->Evaluate(imgs[0]); + std::vector>contours; + cv::findContours(segResult, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); + for (int i = 0; i < contours.size(); i++) + { + cv::Rect rect = cv::boundingRect(contours[i]); + if (rect.width < 10 || rect.y < 10) + continue; + cv::Mat clsImg; + segResult(rect).copyTo(clsImg); + cv::resize(clsImg, clsImg, cv::Size(128, 128)); + int clsResult = cls_yicizhuyeCanye->Evaluate(clsImg); + if (clsResult == 1) + { + cv::rectangle(Paint, rect, cv::Scalar(0, 255, 0), 3); + } + else + { + cv::rectangle(Paint, rect, cv::Scalar(0, 0, 255), 3); + NG = true; + } + } + } + if (NG == true) + { + putTextHusky(Paint, utf8_to_gbk("NG").c_str(), cv::Point(0, 50), cv::Scalar(0, 0, 255), 500); + } + else + putTextHusky(Paint, utf8_to_gbk("OK").c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + + resMat.push_back(Paint); + + //定位 + /* cv::Mat segRes = ~seg_jiPianDingWei->Evaluate(sourceImg); + std::vector>contours; + cv::findContours(segRes, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); + bool finalOk = true; + for(auto &contour:contours) + { + cv::Rect rect = cv::boundingRect(contour); + if (rect.width < 50 || rect.height < 50) + continue; + finalOk = false; + cv::rectangle(Paint, rect, cv::Scalar(0, 0, 255), 5); + } + if(finalOk == true) + putTextHusky(Paint, byteArrayToUnicode("OK").toStdString().c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + else + putTextHusky(Paint, byteArrayToUnicode("NG").toStdString().c_str(), cv::Point(0, 50), cv::Scalar(0, 255, 0), 500); + resMat.push_back(img2D);*/ + 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 ) + { + createDirectoryIfNotExists(resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"); + addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//保存原图 + } + 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 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_algo_fanMianTieJiao::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.toLocal8Bit().toStdString(); + mySave.savePath = savePath.toLocal8Bit().toStdString(); + saveStruct.enqueue(mySave); + saveStruct_mutex->unlock(); +} +void Hd_AI_algo_fanMianTieJiao::saveImgThread() +{ + while (1) + { + if (!ifdetectThread)return; + _sleep(5); + qApp->processEvents(); + if (saveStruct.size() < 1)continue; + for (int i = 0; i < saveStruct.size(); i++) + { + clock_t start, stop; + start = clock(); + saveStruct_mutex->lock(); + saveImgStruct mysaveStruct = saveStruct.dequeue(); + saveStruct_mutex->unlock(); + stop = clock(); + if(stop-start >1000) + std::cout << "lock stop-start >1000::************************" << stop - start << std::endl; + start = clock(); + if (mysaveStruct.out_Mat.data) + imwrite(mysaveStruct.savePath, mysaveStruct.out_Mat); + //std::cout << "savePath::" << mysaveStruct.savePath << std::endl; + stop = clock(); + if (stop - start > 1000) + std::cout << "imwrite stop-start >1000::--------------------------"<< stop - start << std::endl; + _sleep(1); + } + } +} +//检测线程,应当只运行一次 +void Hd_AI_algo_fanMianTieJiao::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"); + + //-------检测流程,根据实际项目修改--------- + std::vectormats; + for (auto& img : HikMat) + mats.push_back(img); + AIdetect(mats, mysaveKey, oriImgSaveDir, mySN, myDataTime); + //sourceImg1.release(); + for (auto& img : mats) + img.release(); + //sourceImg1.release(); + + mysaveKey.clear(); + myDir2D.clear(); + mySN.clear(); + myDataTime.clear(); + qApp->processEvents(); + + } while (ifThreadRunDetect); + +} + +static int runNum = 0; +bool Hd_AI_algo_fanMianTieJiao::run() +{ + clock_t start, stop; + start = clock(); + + //Sleep(1000); + detectThread(); + stop = clock(); + qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"< +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "imgproc/imgproc_c.h" +#include "base.h" +#include "handleAI.h" +#pragma execution_character_set("utf-8") +using namespace handdleAI; + + +//保存图片的结构体 +struct saveImgStruct; +//{ +// cv::Mat out_Mat; +// std::string saveKey; //关键字,用于LOG日志 +// std::string savePath; //保存路径 +//}; + +//初始化流程(一次):Hd_AI_algo_fanMianTieJiao,initParas +//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程 +class Hd_AI_algo_fanMianTieJiao :public Base +{ + Q_OBJECT +public: + Hd_AI_algo_fanMianTieJiao(); + virtual ~Hd_AI_algo_fanMianTieJiao(); + //从类中读数据到实例对象 + bool readData(std::vector&,QByteArray&); + //实例对象把数据写入到类 + bool writeData(std::vector&, QByteArray&); + bool initParas(QByteArray&); + //运行(Logic_taskthread.cpp) + bool run(); + //线程状态 + bool checkStatus();// { return true; }; + + bool encodeResultValue(QVector append_value,QByteArray &resultByte); + bool decodeAiValue(QByteArray byte,QVector &vec_ret); + //---------检测流程,根据实际项目修改--------- + bool AIdetect(std::vector& img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime); + + +private: + pSegmentation* seg_yicizhuyeCanye; + pClassification* cls_yicizhuyeCanye; + int allNum = 0; + int StationNo=0; + int img2D = 2; + + bool moduleStatus = true; + + //输入图片队列 + QQueue HikMat; + //输入关键字队列 + QString saveKey="saveKey"; + //结果路径文件夹队列 + QString Dir2D="Dir2D"; + //产品SN队列 + QString SN="SN"; + //产品时间戳队列 + QString DateTime1="DateTime1"; + + int paramNum; + + //是否使用线程检测方式 + bool ifThreadRunDetect = false; + //检测结果图 + std::vector resMat; + //检测结果 + bool resIfNg = false; + + QQueue resByte; + + //检测线程 + void detectThread(); + //存图线程 + void saveImgThread(); + + //保存图片队列 + QQueue saveStruct; + + //判断文件夹是否存在,不存在则创建 + void isDirExist(QString fullDirName); + + //存图加入队列 + void addImgToSaveStruct(cv::Mat img2D, QString saveKey, QString savePath); +}; + +extern "C" +{ + Q_DECL_EXPORT Hd_AI_algo_fanMianTieJiao * create(); + Q_DECL_EXPORT void destory(Hd_AI_algo_fanMianTieJiao * ptr); +} +//保存图片的结构体 +struct saveImgStruct +{ + cv::Mat out_Mat; + std::string saveKey; //关键字,用于LOG日志 + std::string savePath; //保存路径 +}; +static cv::Mat LocalCutImg_DET(pDetection* pDet, cv::Mat src, float zoom, int checkNameId, cv::Rect& cutRoi) +{ + cv::Mat dst; + cv::resize(src, dst, cv::Size(src.cols / zoom, src.rows / zoom)); + vector resultBox = pDet->Evaluate(dst); //结果为中心点+宽高 + + cv::Mat contourImg; + std::vector> contours; + //cv::threshold(dstImg, contourImg, pSeg->m_classes, 255, cv::THRESH_BINARY_INV); + //cv::findContours(contourImg, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); + + cv::Mat roiImg; + + if (resultBox.size() <= 0) + { + cv::Mat rstMat = cv::Mat(100, 100, CV_8UC1, cv::Scalar(0, 0, 0)); + cutRoi = cv::Rect(0, 0, 100, 100); + return rstMat; + } + + double maxArea = 0; + int index = -1; + for (int j = 0; j < resultBox.size(); j++) + { + double area = resultBox[j].w * resultBox[j].h; + if (area >= maxArea) + { + maxArea = area; + index = j; + } + } + + //cv::Rect rect = cv::boundingRect(contours[index]); + + int addpixel = 15; + + cutRoi.x = ((resultBox[index].x - resultBox[index].w / 2) * zoom); + cutRoi.y = ((resultBox[index].y - resultBox[index].h / 2) * zoom); + cutRoi.width = (resultBox[index].w * zoom); + cutRoi.height = (resultBox[index].h * zoom); + //cv::rectangle(src, cutRoi, cv::Scalar(0, 0, 255), 2, 8); + //cutRoi.x = rect.x * zoom; + //cutRoi.y = rect.y * zoom; + //cutRoi.width = rect.width * zoom; + //cutRoi.height = rect.height * zoom; + + src(cutRoi).copyTo(roiImg); + return roiImg; +} +#endif // Hd_AI_927_2D_module_H diff --git a/BaseModules/Hd_AI_algo_yiCiZhuYe_CanYe/base.h b/BaseModules/Hd_AI_algo_yiCiZhuYe_CanYe/base.h new file mode 100644 index 0000000..00bd6b2 --- /dev/null +++ b/BaseModules/Hd_AI_algo_yiCiZhuYe_CanYe/base.h @@ -0,0 +1,69 @@ +#ifndef __BASECLASS_H__ +#define __BASECLASS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Base :public QObject +{ + Q_OBJECT +public: + bool init_flag; //是否初始化,false,true + bool status = true; //相机状态(判断相机是否断开连接) + std::string paras; //传输数据 + std::vector m_mat; //传输图片 + std::string moduleName; //模块名称 +public: + Base(){} + virtual ~Base(){} + virtual bool readData(std::vector&,QByteArray&){return true;} + virtual bool writeData(std::vector&,QByteArray&){return true;} + virtual bool initParas(QByteArray&){return true;} + virtual bool run() {return true;} + virtual bool checkStatus() { return true; } + +//signals: + //QByteArrayList,根据实际项目进行解析;因不确定每个参数的长度,固用队列的方式。每个QByteArray表示一个值,使用时先转换为QString + //参数,例:返回结果图;相机关键字(SN或userID)+保存路径+缺陷信息列表(缺陷名称,缺陷位置int(x,y,w,h),画框颜色Scalar(a,b,c),缺陷面积double) + //void sendResultData(cv::Mat resMat, QJsonObject resQbj); +}; + +/* +//QJsonObject 转QByteArray +{ + QJsonDocument document; + QJsonObject obj; + obj.insert(password, "pwd"); + obj.insert(userName, "usr"); + document.setObject(obj); + QByteArray abyte = document.toJson(QJsonDocument::Compact); +} + +//QByteArray转QJsonObject +{ + QByteArray ba = reply->readAll(); + QJsonDocument doc = QJsonDocument::fromJson(ba); + QJsonObject obj = doc.object(); +} +*/ +/* +//从类中读数据到实例对象 +virtual bool readData(std::vector&,QByteArray&){return true;} + + + + + + + + +*/ + +#endif