update
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# 获取获取当前目录名
|
||||
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")
|
||||
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)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY)
|
||||
|
||||
|
||||
|
||||
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
@@ -0,0 +1,921 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#ifndef Hd_AI_2D3Ddata_module_H
|
||||
#define Hd_AI_2D3Ddata_module_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <atlstr.h>
|
||||
#include <chrono>
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <iostream>
|
||||
#include <QDebug>
|
||||
#include <qqueue.h>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "imgproc/imgproc_c.h"
|
||||
|
||||
#include "base.h"
|
||||
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
|
||||
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct;
|
||||
//{
|
||||
// cv::Mat out_Mat;
|
||||
// std::string saveKey; //关键字,用于LOG日志
|
||||
// std::string savePath; //保存路径
|
||||
//};
|
||||
|
||||
//初始化流程(一次):Hd_AI_2D3Ddata_module,initParas
|
||||
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
|
||||
class Hd_AI_2D3Ddata_module :public Base
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Hd_AI_2D3Ddata_module();
|
||||
virtual ~Hd_AI_2D3Ddata_module();
|
||||
//从类中读数据到实例对象
|
||||
bool readData(std::vector<cv::Mat>&,QByteArray&);
|
||||
//实例对象把数据写入到类
|
||||
bool writeData(std::vector<cv::Mat>&, QByteArray&);
|
||||
bool initParas(QByteArray&);
|
||||
//运行(Logic_taskthread.cpp)
|
||||
bool run();
|
||||
//线程状态
|
||||
bool checkStatus();// { return true; };
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int allNum = 0;
|
||||
int StationNo;
|
||||
int img2D = 2;
|
||||
|
||||
bool moduleStatus = true;
|
||||
|
||||
//输入图片队列
|
||||
QQueue<cv::Mat> HikMat;
|
||||
//输入关键字队列
|
||||
QString saveKey="saveKey";
|
||||
//结果路径文件夹队列
|
||||
QString Dir2D="Dir2D";
|
||||
//产品SN队列
|
||||
QString SN="SN";
|
||||
//产品时间戳队列
|
||||
QString DateTime1="DateTime1";
|
||||
|
||||
int paramNum;
|
||||
|
||||
//是否使用线程检测方式
|
||||
bool ifThreadRunDetect = false;
|
||||
//检测结果图
|
||||
std::vector<cv::Mat> resMat;
|
||||
//检测结果
|
||||
bool resIfNg = false;
|
||||
|
||||
QQueue<QByteArray> resByte;
|
||||
|
||||
//检测线程
|
||||
void detectThread();
|
||||
//存图线程
|
||||
void saveImgThread();
|
||||
|
||||
//保存图片队列
|
||||
QQueue<saveImgStruct> saveStruct;
|
||||
|
||||
//判断文件夹是否存在,不存在则创建
|
||||
void isDirExist(QString fullDirName);
|
||||
|
||||
//存图加入队列
|
||||
void addImgToSaveStruct(cv::Mat img2D, QString saveKey, QString savePath);
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
Q_DECL_EXPORT Hd_AI_2D3Ddata_module * create();
|
||||
Q_DECL_EXPORT void destory(Hd_AI_2D3Ddata_module * ptr);
|
||||
}
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct
|
||||
{
|
||||
cv::Mat out_Mat;
|
||||
std::string saveKey; //关键字,用于LOG日志
|
||||
std::string savePath; //保存路径
|
||||
};
|
||||
#endif // Hd_AI_927_2D_module_H
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef __BASECLASS_H__
|
||||
#define __BASECLASS_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include<QJsonDocument>
|
||||
#include<QJsonObject>
|
||||
#include<QJsonArray>
|
||||
|
||||
class Base :public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
bool init_flag; //是否初始化,false,true
|
||||
bool status = true; //相机状态(判断相机是否断开连接)
|
||||
std::string paras; //传输数据
|
||||
std::vector<cv::Mat> m_mat; //传输图片
|
||||
std::string moduleName; //模块名称
|
||||
public:
|
||||
Base(){}
|
||||
virtual ~Base(){}
|
||||
virtual bool readData(std::vector<cv::Mat>&,QByteArray&){return true;}
|
||||
virtual bool writeData(std::vector<cv::Mat>&,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<cv::Mat>&,QByteArray&){return true;}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
# 获取获取当前目录名
|
||||
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")
|
||||
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)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY)
|
||||
|
||||
|
||||
|
||||
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
@@ -0,0 +1,985 @@
|
||||
#include "Hd_AI_empty_module.h"
|
||||
#include <QDateTime>
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <qfuture.h>
|
||||
|
||||
#include <QTextCodec>
|
||||
using namespace cv;
|
||||
|
||||
//原图保存文件夹
|
||||
QString oriImgSaveDir = "F:/ORI/";
|
||||
//原图class图保存文件夹
|
||||
QString classImgSaveDir = "F:/ORIclass/";
|
||||
//结果保存文件夹
|
||||
QString resImgSaveDir = "F:/res/";
|
||||
|
||||
//切图的class的width,根据项目实际设置!
|
||||
int sizeW = 150;
|
||||
//切图的class的height,根据项目实际设置!
|
||||
int sizeH = 150;
|
||||
//切图的class的width,根据项目实际设置!0为黑,255为白;
|
||||
int fillColour = 0;
|
||||
|
||||
|
||||
//检测线程锁
|
||||
QMutex* detect_mutex;
|
||||
//保存线程锁
|
||||
QMutex* saveStruct_mutex;
|
||||
//检测线程运行标志
|
||||
bool ifdetectThread = false;
|
||||
|
||||
QString cameraKey_index = "";
|
||||
|
||||
QString byteArrayToUnicode(const QByteArray array) {
|
||||
|
||||
// state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功
|
||||
// 如果转换成功,则值为0,如果值大于0,则说明转换失败
|
||||
QTextCodec::ConverterState state;
|
||||
// 先尝试使用utf-8的方式把QByteArray转换成QString
|
||||
QString text = QTextCodec::codecForName("UTF-8")->toUnicode(array.constData(), array.size(), &state);
|
||||
// 如果转换时无效字符数量大于0,说明编码格式不对
|
||||
if (state.invalidChars > 0)
|
||||
{
|
||||
// 再尝试使用GBK的方式进行转换,一般就能转换正确(当然也可能是其它格式,但比较少见了)
|
||||
text = QTextCodec::codecForName("GBK")->toUnicode(array);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
// 缺陷信息结构体
|
||||
typedef struct {
|
||||
QString defectName = "";//缺陷名称
|
||||
cv::Rect defectRect = { 0,0,0,0 };//缺陷位置
|
||||
cv::Scalar defectScalar = cv::Scalar(0, 0, 0);//画框颜色
|
||||
double defectArea = 0;//缺陷真实面积
|
||||
double defectDepth = 0;//缺陷深度/高度,3D信息
|
||||
}defectInfo;
|
||||
|
||||
|
||||
|
||||
//判断文件是否存在,不存在则创建
|
||||
bool isFileExist(QString fullFileName)
|
||||
{
|
||||
QFileInfo fileInfo(fullFileName);
|
||||
if (fileInfo.isFile())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GetStringSize(HDC hdc, const char* str, int* w, int* h)
|
||||
{
|
||||
SIZE size;
|
||||
GetTextExtentPoint32A(hdc, str, strlen(str), &size);
|
||||
if (w != 0) *w = size.cx;
|
||||
if (h != 0) *h = size.cy;
|
||||
}
|
||||
//在图像写中文,英文也可以写
|
||||
void putTextZH(cv::Mat& dst, const char* str, cv::Point org, cv::Scalar color, int fontsize,
|
||||
const char* fn = "Arial", bool italic = false, bool underline = false)
|
||||
{
|
||||
CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3));
|
||||
|
||||
|
||||
int x, y, r, b;
|
||||
//坐标点大于图像宽和高直接返回
|
||||
if (org.x > dst.cols || org.y > dst.rows) return;
|
||||
x = org.x < 0 ? -org.x : 0;
|
||||
y = org.y < 0 ? -org.y : 0;
|
||||
|
||||
|
||||
LOGFONTA lf;
|
||||
lf.lfHeight = -fontsize; //字体高度
|
||||
lf.lfWidth = 0; //平均宽度
|
||||
lf.lfEscapement = 0; //字符排列角度
|
||||
lf.lfOrientation = 0; //字符本身旋转的角度
|
||||
lf.lfWeight = 5; //设置字体线条的宽度
|
||||
lf.lfItalic = italic; //斜体
|
||||
lf.lfUnderline = underline; //下划线
|
||||
lf.lfStrikeOut = 0; //是否字符中央加横线
|
||||
lf.lfCharSet = DEFAULT_CHARSET; //字符集
|
||||
lf.lfOutPrecision = 0; //字体的精确度
|
||||
lf.lfQuality = PROOF_QUALITY; //字体质量
|
||||
lf.lfPitchAndFamily = 0; //选择字体的间距和字体家族
|
||||
strcpy_s(lf.lfFaceName, fn); //字体的名称
|
||||
|
||||
|
||||
HFONT hf = CreateFontIndirectA(&lf);
|
||||
HDC hdc = CreateCompatibleDC(0);
|
||||
HFONT holdfont = (HFONT)SelectObject(hdc, hf);
|
||||
|
||||
|
||||
int strBaseW = 0, strBaseH = 0;
|
||||
int singleRow = 0;
|
||||
char buf[1 << 12];
|
||||
strcpy_s(buf, str);
|
||||
char* bufT[1 << 12]; //这个用于分隔字符串后剩余的字符,可能会超出。
|
||||
|
||||
|
||||
//处理多行
|
||||
{
|
||||
int nnh = 0;
|
||||
int cw, ch;
|
||||
|
||||
|
||||
const char* ln = strtok_s(buf, "\n", bufT);
|
||||
while (ln != 0)
|
||||
{
|
||||
GetStringSize(hdc, ln, &cw, &ch);
|
||||
strBaseW = max(strBaseW, cw);
|
||||
strBaseH = max(strBaseH, ch);
|
||||
|
||||
|
||||
ln = strtok_s(0, "\n", bufT);
|
||||
nnh++;
|
||||
}
|
||||
singleRow = strBaseH;
|
||||
strBaseH *= nnh;
|
||||
}
|
||||
|
||||
|
||||
if (org.x + strBaseW < 0 || org.y + strBaseH < 0)
|
||||
{
|
||||
SelectObject(hdc, holdfont);
|
||||
DeleteObject(hf);
|
||||
DeleteObject(hdc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1;
|
||||
b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1;
|
||||
org.x = org.x < 0 ? 0 : org.x;
|
||||
org.y = org.y < 0 ? 0 : org.y;
|
||||
|
||||
|
||||
BITMAPINFO bmp = { 0 };
|
||||
BITMAPINFOHEADER& bih = bmp.bmiHeader;
|
||||
int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4));
|
||||
|
||||
|
||||
bih.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bih.biWidth = strBaseW;
|
||||
bih.biHeight = strBaseH;
|
||||
bih.biPlanes = 1;
|
||||
bih.biBitCount = 24;
|
||||
bih.biCompression = BI_RGB;
|
||||
bih.biSizeImage = strBaseH * strDrawLineStep;
|
||||
bih.biClrUsed = 0;
|
||||
bih.biClrImportant = 0;
|
||||
|
||||
|
||||
void* pDibData = 0;
|
||||
HBITMAP hBmp = CreateDIBSection(hdc, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0);
|
||||
|
||||
|
||||
CV_Assert(pDibData != 0);
|
||||
HBITMAP hOldBmp = (HBITMAP)SelectObject(hdc, hBmp);
|
||||
|
||||
|
||||
//color.val[2], color.val[1], color.val[0]
|
||||
SetTextColor(hdc, RGB(255, 255, 255));
|
||||
SetBkColor(hdc, 0);
|
||||
//SetStretchBltMode(hDC, COLORONCOLOR);
|
||||
|
||||
|
||||
strcpy_s(buf, str);
|
||||
const char* ln = strtok_s(buf, "\n", bufT);
|
||||
int outTextY = 0;
|
||||
while (ln != 0)
|
||||
{
|
||||
TextOutA(hdc, 0, outTextY, ln, strlen(ln));
|
||||
outTextY += singleRow;
|
||||
ln = strtok_s(0, "\n", bufT);
|
||||
}
|
||||
uchar* dstData = (uchar*)dst.data;
|
||||
int dstStep = dst.step / sizeof(dstData[0]);
|
||||
unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep;
|
||||
unsigned char* pStr = (unsigned char*)pDibData + x * 3;
|
||||
for (int tty = y; tty <= b; ++tty)
|
||||
{
|
||||
unsigned char* subImg = pImg + (tty - y) * dstStep;
|
||||
unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep;
|
||||
for (int ttx = x; ttx <= r; ++ttx)
|
||||
{
|
||||
for (int n = 0; n < dst.channels(); ++n) {
|
||||
double vtxt = subStr[n] / 255.0;
|
||||
int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n];
|
||||
subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv);
|
||||
}
|
||||
|
||||
|
||||
subStr += 3;
|
||||
subImg += dst.channels();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SelectObject(hdc, hOldBmp);
|
||||
SelectObject(hdc, holdfont);
|
||||
DeleteObject(hf);
|
||||
DeleteObject(hBmp);
|
||||
DeleteDC(hdc);
|
||||
}
|
||||
|
||||
void drawDefects(cv::Mat& sourceMat, QQueue<defectInfo> defectInfoList)
|
||||
{
|
||||
for (int i = 0; i < defectInfoList.size(); i++)
|
||||
{
|
||||
defectInfo mdefect = defectInfoList[i];
|
||||
|
||||
cv::rectangle(sourceMat, cv::Point(mdefect.defectRect.x, mdefect.defectRect.y),
|
||||
cv::Point(mdefect.defectRect.x + mdefect.defectRect.width, mdefect.defectRect.y + mdefect.defectRect.height), mdefect.defectScalar, 3, 8);
|
||||
|
||||
QByteArray path_arr = mdefect.defectName.toLocal8Bit();
|
||||
const char* path = path_arr.data();
|
||||
putTextZH(sourceMat, path, cv::Point(mdefect.defectRect.x, mdefect.defectRect.y - 50), mdefect.defectScalar, 50, "微软雅黑");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//判断文件夹是否存在,不存在则创建
|
||||
void Hd_AI_empty_module::isDirExist(QString fullDirName)
|
||||
{
|
||||
QDir* photo = new QDir;
|
||||
bool exist = photo->exists(fullDirName);
|
||||
if (exist)
|
||||
{
|
||||
//qDebug() << fullDirName << "::已存在";
|
||||
}
|
||||
else
|
||||
{
|
||||
//创建photo文件夹
|
||||
//qDebug() << fullDirName << "::不存在,创建";
|
||||
photo->mkdir(fullDirName);
|
||||
}
|
||||
delete photo;
|
||||
photo = nullptr;
|
||||
}
|
||||
|
||||
Hd_AI_empty_module* create()
|
||||
{
|
||||
qDebug() << "[INFO] " << " Hd_AI_empty_module create success!" ;
|
||||
return new Hd_AI_empty_module;
|
||||
}
|
||||
|
||||
void destory(Hd_AI_empty_module* ptr)
|
||||
{
|
||||
qDebug() << "[INFO] " << "Hd_AI_empty_module destory success!";
|
||||
if(ptr)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Hd_AI_empty_module::Hd_AI_empty_module()
|
||||
{
|
||||
detect_mutex = new QMutex;
|
||||
saveStruct_mutex = new QMutex;
|
||||
ifdetectThread = false;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
QString DirPath = "E:/testImg/source" + QString::number(i);
|
||||
QStringList imgFilters;
|
||||
imgFilters << "*.jpg" << "*.png" << "*.PNG" << "*.gif" << "*.tif" << "*.jpeg" << "*.bmp";
|
||||
QDir qdir(DirPath);
|
||||
//返回文件名列表
|
||||
QStringList localSourceImgsName = qdir.entryList(imgFilters, QDir::Files | QDir::Readable, QDir::Name);
|
||||
for (int j = 0; j < localSourceImgsName.size(); j++)
|
||||
{
|
||||
QString imgPath = DirPath + "/" + localSourceImgsName[j];
|
||||
QFile myf(imgPath);
|
||||
if (myf.exists())
|
||||
myf.remove();
|
||||
//Sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Hd_AI_empty_module::~Hd_AI_empty_module()
|
||||
{
|
||||
ifdetectThread = false;
|
||||
Sleep(10);
|
||||
if (detect_mutex)
|
||||
{
|
||||
delete detect_mutex;
|
||||
detect_mutex = nullptr;
|
||||
}
|
||||
if (saveStruct_mutex)
|
||||
{
|
||||
delete saveStruct_mutex;
|
||||
saveStruct_mutex = nullptr;
|
||||
}
|
||||
/*DestroySegObj(pSeg);
|
||||
DestroyClsObj(pCls);*/
|
||||
}
|
||||
//从类中读数据到实例对象
|
||||
bool Hd_AI_empty_module::readData(std::vector<cv::Mat>&vec_mat,QByteArray &data)
|
||||
{
|
||||
detect_mutex->lock();
|
||||
//qDebug() << __FUNCTION__ << " line:" <<__LINE__ << " data len:" << data.length();
|
||||
if (resMat.size()>0)
|
||||
{
|
||||
vec_mat.push_back(resMat[0]);
|
||||
resMat.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
vec_mat.push_back(HikMat[0]);
|
||||
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " resMat.data err:";
|
||||
}
|
||||
if (allNum++ % 21 == 20)
|
||||
data = "2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2";// resByte.dequeue();
|
||||
else
|
||||
data = "1";//1OK,2NG
|
||||
resByte.clear();
|
||||
////之后根据结果类修改
|
||||
//if(resIfNg == true)
|
||||
// data = "NG";
|
||||
//else data = "OK";
|
||||
detect_mutex->unlock();
|
||||
/*if(cameraKey_index.contains('_'))
|
||||
qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName:"
|
||||
<< cameraKey_index.split("_")[0] << " imgIndex:" << cameraKey_index.split("_")[1];
|
||||
else
|
||||
qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName imgIndex:" << cameraKey_index;*/
|
||||
return true;
|
||||
}
|
||||
//从类中读数据到实例对象
|
||||
bool Hd_AI_empty_module::encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string sendMsg;
|
||||
for(int i = 0 ; i < append_value.size();i++)
|
||||
{
|
||||
std::string value = append_value.at(1);
|
||||
//type
|
||||
int type = 3;
|
||||
std::string m_type;
|
||||
m_type.insert(0,4,'1');
|
||||
memcpy ( (void*)m_type.c_str(),(void*)&type,4 );
|
||||
sendMsg.append(m_type);
|
||||
|
||||
//len
|
||||
int len = value.length();
|
||||
std::string m_len;
|
||||
m_len.insert(0,4,'1');
|
||||
memcpy ( (void*)m_len.c_str(),(void*)&len,4 );
|
||||
sendMsg.append(m_len);
|
||||
|
||||
//data x
|
||||
sendMsg.append(value);
|
||||
}
|
||||
resultByte = QByteArray::fromStdString(sendMsg);
|
||||
} catch (QString ev)
|
||||
{
|
||||
qCritical() << "[Error] " << " ev:" << ev;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int myallNum[4] = {0};
|
||||
QMap<int, cv::Mat> lastImgMap;
|
||||
//接收数据
|
||||
bool Hd_AI_empty_module::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &data)
|
||||
{
|
||||
//qDebug() << __FUNCTION__ << "line:"<< __LINE__ << " data len" << data.length() ;
|
||||
if(vec_mat.empty())
|
||||
{
|
||||
qCritical() << "[Error] " << " vec_mat is null !";
|
||||
return false;
|
||||
}
|
||||
detect_mutex->lock();
|
||||
HikMat.clear();
|
||||
HikMat.enqueue(vec_mat[0]);
|
||||
|
||||
QString savePath;
|
||||
QString sData = data;
|
||||
QStringList splitDataList = sData.split(",");
|
||||
if(splitDataList.size()>=4)
|
||||
if(splitDataList[2].contains('_'))
|
||||
cameraKey_index = splitDataList[2];
|
||||
int index = -1;
|
||||
if (sData.contains("offline-camera0"))
|
||||
{
|
||||
index = 0;
|
||||
savePath = "E:\\testImg\\source0\\"+QString::number(myallNum[0]++) + ".bmp";
|
||||
}
|
||||
else if (sData.contains("offline-camera1"))
|
||||
{
|
||||
index = 1;
|
||||
savePath = "E:\\testImg\\source1\\" + QString::number(myallNum[1]++) + ".bmp";
|
||||
}
|
||||
else if (sData.contains("offline-camera2"))
|
||||
{
|
||||
index = 2;
|
||||
savePath = "E:\\testImg\\source2\\" + QString::number(myallNum[2]++) + ".bmp";
|
||||
}
|
||||
else if (sData.contains("offline-camera3"))
|
||||
{
|
||||
index = 3;
|
||||
savePath = "E:\\testImg\\source3\\" + QString::number(myallNum[3]++) + ".bmp";
|
||||
}
|
||||
|
||||
if (!savePath.isEmpty())
|
||||
{
|
||||
//std::cout << "try savePath::" << savePath.toStdString() << std::endl;
|
||||
//测试相机的,
|
||||
while (HikMat[0].cols > 2000)cv::resize(HikMat[0], HikMat[0], cv::Size(), 0.08, 0.08);
|
||||
addImgToSaveStruct(HikMat[0], "0", savePath);//
|
||||
}
|
||||
|
||||
//if (myallNum[index] == 1)
|
||||
//{
|
||||
// cv::Mat img;
|
||||
// lastImgMap.insert(index, img);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// //判断和上一张图,是否重复
|
||||
// int dataLength = HikMat[0].total() * HikMat[0].elemSize();
|
||||
// bool res = false;
|
||||
// if (myallNum[index] > 0)
|
||||
// {
|
||||
// cv::Mat img = lastImgMap.value(index);
|
||||
// if (img.total() * img.elemSize() == dataLength)
|
||||
// {
|
||||
// res = memcmp(img.data, HikMat[0].data, dataLength) == 0;
|
||||
// if (res == true)
|
||||
// std::cout << "res ==true ====!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//lastImgMap.insert(index, HikMat[0]);
|
||||
|
||||
//or检测:保存路径,拍照面描述,相机key_第几张图,SN_时间戳
|
||||
//and检测:保存路径,拍照面描述,相机key_第几张图,相机key_第几张图,SN_时间戳,SN_时间戳
|
||||
//汇总:保存路径,拍照面描述,触发信号_序号列表0,SN_时间戳
|
||||
QString qstring_data = data;
|
||||
QStringList datalist = qstring_data.split(',');
|
||||
|
||||
|
||||
/*saveKey.enqueue("datalist[0]");
|
||||
Dir2D.enqueue("datalist[1]");
|
||||
QStringList SN_dataTime;
|
||||
SN_dataTime = datalist[3].split('_');
|
||||
DateTime1 = "SN_dataTime[1]";
|
||||
SN.enqueue("SN_dataTime[0]");*/
|
||||
//qCritical() << __FUNCTION__ << " line: " << __LINE__ << " data:" << qstring_data;
|
||||
detect_mutex->unlock();
|
||||
|
||||
//qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << " data: " << data << " run end";
|
||||
//cv::Mat resultDstImg = vec_mat[0].clone();// = pSeg->Evaluate(sourceImg); //返回单通道二值图 图片错误输出Image Error!但不报错。。
|
||||
//resultDstImg = pSeg->Evaluate(resultDstImg);
|
||||
//resultDstImg.release();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1...
|
||||
//初始化
|
||||
bool Hd_AI_empty_module::initParas(QByteArray& byteArray)
|
||||
{
|
||||
QByteArrayList valueList = byteArray.split('+');
|
||||
QStringList valueiList;
|
||||
|
||||
if (byteArray.contains("onlySetParameter"))
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,valueList[0]:" << valueList[0];
|
||||
if (valueList.size() > 1)
|
||||
for (int i = 1; i < valueList.size(); i++)
|
||||
{
|
||||
QString valuei = byteArrayToUnicode(valueList[i]);
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,lastName:" << valueList[0] << " ,valuei:" << valuei;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (valueList.size() > 1)
|
||||
for (int i = 1; i < valueList.size(); i++)
|
||||
{
|
||||
QString valuei = byteArrayToUnicode(valueList[i]);
|
||||
valueiList.append(valuei);
|
||||
}
|
||||
|
||||
|
||||
/*pSeg = CreateSegObjS(pSeg_modulePath, 128, gpuId);
|
||||
pCls = CreateClsObjV3(pCls_modulePath, gpuId, 1);*/
|
||||
|
||||
|
||||
//StationNo = vec_ret.at(0).toInt();
|
||||
|
||||
//InitThreads(StationNo, img2D);
|
||||
//InitModels(StationNo, img2D);
|
||||
|
||||
//运行检测线程
|
||||
ifdetectThread = true;
|
||||
|
||||
//线程检测:结果类完成时,使用
|
||||
//ifThreadRunDetect = true;
|
||||
//QFuture<void> future1 = QtConcurrent::run(this, &Hd_AI_empty_module::detectThread);
|
||||
//运行存图线程
|
||||
QFuture<void> future2 = QtConcurrent::run(this, &Hd_AI_empty_module::saveImgThread);
|
||||
//detectThread();
|
||||
|
||||
//原图总文件夹
|
||||
isDirExist(oriImgSaveDir);
|
||||
//原图class总文件夹
|
||||
isDirExist(classImgSaveDir);
|
||||
//结果图总文件夹
|
||||
isDirExist(resImgSaveDir);
|
||||
|
||||
|
||||
//qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ;
|
||||
return true;
|
||||
}
|
||||
// 解码
|
||||
bool Hd_AI_empty_module::decodeAiValue(QByteArray byteArray,QVector<QByteArray> &vec_ret)
|
||||
{
|
||||
if(byteArray.isEmpty())
|
||||
{
|
||||
qCritical() << "[Error] " << " byteArray is null!";
|
||||
return false;
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
byteArray.remove(0,8);
|
||||
QByteArray mm_data = byteArray.mid(0,4);
|
||||
memcpy((void*)¶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_empty_module::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
//存图数据加保存队列,加锁,避免数据访问冲突
|
||||
saveStruct_mutex->lock();
|
||||
saveImgStruct mySave;
|
||||
Mat sourceImg;
|
||||
sourceImg = img2D.clone();
|
||||
//img2D.copyTo(sourceImg);
|
||||
//img2D.release();
|
||||
QString mysaveKey1 = mysaveKey; //"offlineStation1_off_1"
|
||||
saveStruct_mutex->unlock();
|
||||
|
||||
QJsonDocument document;
|
||||
QJsonObject obj;
|
||||
obj.insert("result_key", "mysaveKey");
|
||||
obj.insert("SN", "mySN");
|
||||
obj.insert("DataTime", "myDataTime");
|
||||
|
||||
|
||||
//QFile csvName("test.csv");
|
||||
//QStringList lines;
|
||||
//lines << "class,name\n" << "3,4,5,6,7\n" << "a,b,c,d\n";
|
||||
//if (csvName.open(QIODevice::WriteOnly)) //若文件不存在,会自动创建
|
||||
//{
|
||||
// for (int i = 0; i < lines.size(); i++)
|
||||
// csvName.write(lines[i].toStdString().c_str());
|
||||
// csvName.close();
|
||||
//}
|
||||
|
||||
QQueue<defectInfo> defectInfoList;
|
||||
|
||||
//seg后class检测逻辑
|
||||
/*if (0) {
|
||||
Mat sourceRectangles;// 在原图缺陷位置,边界矩形框出
|
||||
sourceRectangles = sourceImg.clone();
|
||||
//sourceImg.copyTo(sourceRectangles);
|
||||
vector<vector<Point>> contours;
|
||||
|
||||
//seg检测
|
||||
Mat resultDstImg;// = sourceImg.clone();// = pSeg->Evaluate(sourceImg); //返回单通道二值图 图片错误输出Image Error!但不报错。。
|
||||
resultDstImg = pSeg->Evaluate(sourceImg);
|
||||
//int resultClass = pCls->Evaluate(sourceImg); //类别id
|
||||
|
||||
//opencv对二值图进行处理
|
||||
//GaussianBlur(resultDstImg, resultDstImg, Size(3, 3), 1); //缺陷过滤值较大时,可以减少检出数;缺陷较小时,漏检较多
|
||||
threshold(resultDstImg, resultDstImg, pSeg->m_classes, 255, THRESH_BINARY_INV);//大于部分设为0,小于部分设为255
|
||||
//findContours(resultDstImg, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); //不识别内部轮廓,有些情况抓到的图像外框?
|
||||
findContours(resultDstImg, contours, cv::noArray(), cv::RETR_TREE, cv::CHAIN_APPROX_NONE); //需要内部轮廓的写法
|
||||
|
||||
if (contours.size() == 0)
|
||||
{
|
||||
//printf("Notlabeled\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < contours.size(); j++)
|
||||
{
|
||||
Rect rect1 = boundingRect(Mat(contours[j]));
|
||||
|
||||
//最小缺陷过滤参数,根据项目实际设置!
|
||||
int filterNum = 10;
|
||||
float w = rect1.width * 1.0;
|
||||
float h = rect1.height * 1.0;
|
||||
if ((w / sourceImg.cols > 0.98) || (h / sourceImg.rows > 0.98))
|
||||
{
|
||||
//抓到图像外框了
|
||||
//qDebug() << "NG is too big...";
|
||||
continue;
|
||||
}
|
||||
//且逻辑,有的项目需要或逻辑!!
|
||||
if ((w > filterNum && h > filterNum))//||rect1.area> filterNum*filterNum*1.5)
|
||||
{
|
||||
//class检测mat
|
||||
Mat imgCls;
|
||||
|
||||
//此段为切图逻辑为:
|
||||
//缺陷外扩5像素;
|
||||
//判断最大边,大于class建网大小的,按照最大边尺寸比例切大图,然后resize为建网大小;最大边小于等于建网大小的,按照建网大小切图;
|
||||
//越界填充
|
||||
{
|
||||
int startX = rect1.x - 5;
|
||||
int startY = rect1.y - 5;
|
||||
int endX = rect1.x + rect1.width + 5;
|
||||
int endY = rect1.y + rect1.height + 5;
|
||||
|
||||
//尺寸比例
|
||||
double maxscaler, scalerX, scalerY;
|
||||
maxscaler = 1.0;
|
||||
scalerX = (endX - startX) * 1.0 / sizeW;//*1.0转为float,避免被取整了
|
||||
scalerY = (endY - startY) * 1.0 / sizeH;
|
||||
|
||||
maxscaler = max(maxscaler, max(scalerX, scalerY));
|
||||
|
||||
int avgX = (rect1.x + rect1.x + rect1.width) / 2; //中点X位置
|
||||
int avgY = (rect1.y + rect1.y + rect1.height) / 2;//中点Y位置
|
||||
|
||||
startX = avgX - int(maxscaler * sizeW / 2);//强转为int
|
||||
endX = startX + int(maxscaler * sizeW);
|
||||
startY = avgY - int(maxscaler * sizeH / 2);
|
||||
endY = startY + int(maxscaler * sizeH);
|
||||
|
||||
//判断是否越界,越界要填充的像素个数
|
||||
int copyTop = max(0, 0 - startY);
|
||||
int copyButton = max(0, endY - sourceImg.rows);
|
||||
int copyLeft = max(0, 0 - startX);
|
||||
int copyRight = max(0, endX - sourceImg.cols);
|
||||
|
||||
//切图不要越界,会崩溃
|
||||
Mat imgCut = sourceImg(Range(max(0, startY - copyTop), min(sourceImg.rows, endY - copyButton)),
|
||||
Range(max(0, startX - copyLeft), min(sourceImg.cols, endX - copyRight))); //起始行,终止行;起始列,终止列
|
||||
|
||||
//图像扩充
|
||||
if (sourceImg.channels() == 1)
|
||||
{
|
||||
copyMakeBorder(imgCut, imgCut, copyTop, copyButton, copyLeft, copyRight, BORDER_CONSTANT, fillColour);
|
||||
}
|
||||
else
|
||||
{
|
||||
copyMakeBorder(imgCut, imgCut, copyTop, copyButton, copyLeft, copyRight, BORDER_CONSTANT, Scalar(fillColour, fillColour, fillColour));
|
||||
}
|
||||
//resize为建网大小
|
||||
cv::resize(imgCut, imgCls, cv::Size(sizeW, sizeH));
|
||||
imgCut.release();
|
||||
}
|
||||
|
||||
|
||||
int resultClass = 0;
|
||||
float prob = 1.0;
|
||||
|
||||
resultClass = pCls->Evaluate(imgCls); //类别id
|
||||
prob = pCls->getProbability(); //可能性
|
||||
|
||||
//切图保存,按需
|
||||
{
|
||||
isDirExist(classImgSaveDir + mysaveKey1 + "/class_" + QString::number(resultClass));
|
||||
//存图数据入队,按需
|
||||
addImgToSaveStruct(imgCls, mysaveKey1, classImgSaveDir + mysaveKey1 + "/class_" + QString::number(resultClass) + "/" + mySN + myDataTime + QString::number(j) + ".bmp");
|
||||
}
|
||||
|
||||
//此处应添加缺陷计数逻辑
|
||||
|
||||
if (resultClass == 0)//OK
|
||||
{
|
||||
;
|
||||
}
|
||||
else if (resultClass == 1)//划伤Scratch
|
||||
{
|
||||
resIfNg = true;
|
||||
//rectangle(sourceRectangles, rect1.tl(), rect1.br(), Scalar(0, 0, 255), 3, 8);
|
||||
////可行,必须转一下格式
|
||||
//{
|
||||
// QString pathQstr = "划伤";
|
||||
// QByteArray path_arr = pathQstr.toLocal8Bit();
|
||||
// const char* path = path_arr.data();
|
||||
// putTextZH(sourceRectangles, path, cv::Point(rect1.tl().x, rect1.tl().y - 5), Scalar(255, 0, 0), 50, "微软雅黑");
|
||||
//}
|
||||
|
||||
defectInfo mdefectInfo;
|
||||
mdefectInfo.defectName = "划伤";
|
||||
mdefectInfo.defectRect = rect1;
|
||||
mdefectInfo.defectArea = contourArea(contours[j]);
|
||||
mdefectInfo.defectScalar = cv::Scalar(0, 0, 255);
|
||||
defectInfoList.enqueue(mdefectInfo);
|
||||
}
|
||||
else if (resultClass == 2)//碰伤
|
||||
{
|
||||
resIfNg = true;
|
||||
defectInfo mdefectInfo;
|
||||
mdefectInfo.defectName = "碰伤";
|
||||
mdefectInfo.defectRect = rect1;
|
||||
mdefectInfo.defectArea = contourArea(contours[j]);
|
||||
mdefectInfo.defectScalar = cv::Scalar(0, 255, 255);
|
||||
defectInfoList.enqueue(mdefectInfo);
|
||||
}
|
||||
imgCls.release();
|
||||
}
|
||||
else {
|
||||
//cout << "ng is too small<" << filterNum << endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
//cv::Mat resMat = img2D.clone();
|
||||
sourceRectangles.release();
|
||||
contours.resize(0);
|
||||
resultDstImg.release();
|
||||
}
|
||||
*/
|
||||
|
||||
detect_mutex->lock();
|
||||
//resMat = sourceImg.clone();
|
||||
//sourceImg.copyTo(resMat);
|
||||
resMat.push_back(sourceImg);
|
||||
//结果图画框和缺陷,在resMat上绘制
|
||||
if (resMat.size() > 0)
|
||||
drawDefects(resMat[0], defectInfoList);
|
||||
|
||||
//QByteArray,根据实际项目进行解析
|
||||
//参数,例:返回结果图;相机关键字(SN或userID)+保存路径+缺陷信息列表(缺陷名称,缺陷位置int(x,y,w,h),画框颜色Scalar(a,b,c),缺陷面积double)
|
||||
|
||||
QJsonArray detaillists;
|
||||
//QByteArrayList resQbyte;
|
||||
for (int i = 0; i < defectInfoList.size(); i++)
|
||||
{
|
||||
defectInfo mdefect = defectInfoList[i];
|
||||
//resQbyte.push_back(mdefect.defectName.toLocal8Bit()); //中文也可以QString::number(1.1).toUtf8()
|
||||
//resQbyte.push_back(QString::number(mdefect.defectRect.x).toUtf8());
|
||||
//resQbyte.push_back(QString::number(mdefect.defectRect.y).toUtf8());
|
||||
//resQbyte.push_back(QString::number(mdefect.defectRect.width).toUtf8());
|
||||
//resQbyte.push_back(QString::number(mdefect.defectRect.height).toUtf8());
|
||||
//resQbyte.push_back(QString::number(mdefect.defectScalar[0]).toUtf8());
|
||||
//resQbyte.push_back(QString::number(mdefect.defectScalar[1]).toUtf8());
|
||||
//resQbyte.push_back(QString::number(mdefect.defectScalar[2]).toUtf8());
|
||||
//resQbyte.push_back(QString::number(mdefect.defectArea).toUtf8());
|
||||
QJsonObject detailObj;
|
||||
detailObj.insert("defectName", "mdefect.defectName");
|
||||
detailObj.insert("defectRect.x", QString::number(mdefect.defectRect.x));
|
||||
detailObj.insert("defectRect.y", QString::number(mdefect.defectRect.y));
|
||||
detailObj.insert("defectRect.width", QString::number(mdefect.defectRect.width));
|
||||
detailObj.insert("defectRect.height", QString::number(mdefect.defectRect.height));
|
||||
detailObj.insert("defectScalar0", QString::number(mdefect.defectScalar[0]));
|
||||
detailObj.insert("defectScalar1", QString::number(mdefect.defectScalar[1]));
|
||||
detailObj.insert("defectScalar2", QString::number(mdefect.defectScalar[2]));
|
||||
detailObj.insert("defectArea", QString::number(mdefect.defectArea));
|
||||
detailObj.insert("defectLength", QString::number(sqrt(mdefect.defectRect.width* mdefect.defectRect.width+ mdefect.defectRect.height* mdefect.defectRect.height)));
|
||||
|
||||
detaillists.append(detailObj);
|
||||
}
|
||||
|
||||
|
||||
//使用完删除
|
||||
defectInfoList.clear();
|
||||
|
||||
//往主界面发
|
||||
//emit sendResultData(resMat, resQbyte);
|
||||
//resQbyte.clear();
|
||||
|
||||
isDirExist(resImgSaveDir + mysaveKey1 + "/");
|
||||
QString qimgsavePath = resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png";
|
||||
//存图数据入队,按需
|
||||
if (resMat.size() > 0 )
|
||||
addImgToSaveStruct(resMat[0], mysaveKey1, resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png");
|
||||
detect_mutex->unlock();
|
||||
|
||||
obj.insert("detaillists", detaillists);
|
||||
obj.insert("qimgsavePath", qimgsavePath);
|
||||
document.setObject(obj);
|
||||
//resByte.clear();
|
||||
QByteArray qa = document.toJson();
|
||||
//resByte .enqueue(qa);
|
||||
|
||||
|
||||
//resMat.release();
|
||||
sourceImg.release();
|
||||
|
||||
mySave.out_Mat.resize(0);
|
||||
mysaveKey1.clear();
|
||||
qApp->processEvents();
|
||||
|
||||
|
||||
////原图和结果都往主界面发?
|
||||
//std::vector<cv::Mat> resMat;
|
||||
//resMat.push_back(img2D);
|
||||
//resMat.push_back(sourceRectangles);
|
||||
//QByteArray resByte = mysaveKey.toLocal8Bit();
|
||||
//resByte.append(myDir2D.toLocal8Bit());
|
||||
//resByte.append(mySN.toLocal8Bit());
|
||||
//resByte.append(myDataTime.toLocal8Bit());
|
||||
|
||||
////往主界面发送图片和数据
|
||||
////emit writeData(resMat, resByte);
|
||||
//resMat.resize(0);
|
||||
//resByte.resize(0);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
qDebug() << "[Error] " << QString::fromUtf8("检测失败!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
//存图加入队列
|
||||
void Hd_AI_empty_module::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QString savePath)
|
||||
{
|
||||
//存图数据加保存队列,加锁,避免数据访问冲突
|
||||
saveStruct_mutex->lock();
|
||||
saveImgStruct mySave;
|
||||
mySave.out_Mat = img2D.clone();
|
||||
//img2D.copyTo(mySave.out_Mat);
|
||||
mySave.saveKey = (mysaveKey).toStdString();
|
||||
mySave.savePath = (savePath).toStdString();
|
||||
saveStruct.enqueue(mySave);
|
||||
saveStruct_mutex->unlock();
|
||||
}
|
||||
void Hd_AI_empty_module::saveImgThread()
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (!ifdetectThread)return;
|
||||
_sleep(1);
|
||||
qApp->processEvents();
|
||||
if (saveStruct.size() < 1)continue;
|
||||
for (int i = 0; i < saveStruct.size(); i++)
|
||||
{
|
||||
clock_t start, stop;
|
||||
start = clock();
|
||||
saveStruct_mutex->lock();
|
||||
saveImgStruct mysaveStruct = saveStruct.dequeue();
|
||||
saveStruct_mutex->unlock();
|
||||
stop = clock();
|
||||
if(stop-start >1000)
|
||||
std::cout << "lock stop-start >1000::************************" << stop - start << std::endl;
|
||||
start = clock();
|
||||
//if (mysaveStruct.out_Mat.data)imwrite(mysaveStruct.savePath, mysaveStruct.out_Mat);
|
||||
//std::cout << "savePath::" << mysaveStruct.savePath << std::endl;
|
||||
stop = clock();
|
||||
if (stop - start > 1000)
|
||||
std::cout << "imwrite stop-start >1000::--------------------------"<< stop - start << std::endl;
|
||||
_sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//检测线程,应当只运行一次
|
||||
void Hd_AI_empty_module::detectThread()
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!ifdetectThread)return;
|
||||
|
||||
//此两行代码,避免程序卡死;_sleep的时间根据实际项目调整
|
||||
_sleep(2);
|
||||
qApp->processEvents();
|
||||
//取数据加锁,避免数据访问冲突
|
||||
detect_mutex->lock();
|
||||
//if (HikMat.size() < 1 || saveKey.size() < 1 || Dir2D.size() < 1 || SN.size() < 1 )//|| DateTime1.size() < 1)
|
||||
//{
|
||||
// detect_mutex->unlock();
|
||||
// continue;
|
||||
//}
|
||||
|
||||
cv::Mat sourceImg1 = HikMat[0];// .dequeue();
|
||||
QString mysaveKey = "saveKey";// .dequeue();
|
||||
QString myDir2D = "Dir2D";// .dequeue();
|
||||
QString mySN = "SN";// .dequeue();
|
||||
QString myDataTime = "DateTime1";
|
||||
detect_mutex->unlock();
|
||||
|
||||
//判断存图文件夹是否存在,不存在则创建
|
||||
{
|
||||
//原图总文件夹
|
||||
isDirExist(oriImgSaveDir + mysaveKey);
|
||||
//原图class总文件夹
|
||||
isDirExist(classImgSaveDir + mysaveKey);
|
||||
//结果图总文件夹
|
||||
isDirExist(resImgSaveDir + mysaveKey);
|
||||
|
||||
}
|
||||
|
||||
//测试相机的,
|
||||
while (sourceImg1.cols > 2000)cv::resize(sourceImg1, sourceImg1, cv::Size(), 0.5, 0.5);
|
||||
|
||||
//存图数据入队
|
||||
//addImgToSaveStruct(sourceImg1, mysaveKey, oriImgSaveDir + mysaveKey + "/" + mySN + myDataTime + ".bmp");
|
||||
|
||||
//-------检测流程,根据实际项目修改---------
|
||||
AIdetect(sourceImg1, mysaveKey, oriImgSaveDir, mySN, myDataTime);
|
||||
//sourceImg1.release();
|
||||
|
||||
mysaveKey.clear();
|
||||
myDir2D.clear();
|
||||
mySN.clear();
|
||||
myDataTime.clear();
|
||||
qApp->processEvents();
|
||||
|
||||
} while (ifThreadRunDetect);
|
||||
|
||||
}
|
||||
|
||||
static int runNum = 0;
|
||||
bool Hd_AI_empty_module::run()
|
||||
{
|
||||
clock_t start, stop;
|
||||
start = clock();
|
||||
|
||||
//Sleep(1000);
|
||||
//detectThread();
|
||||
//stop = clock();
|
||||
//qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"<<stop-start;
|
||||
|
||||
|
||||
//qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << "Mat_name: " << Mat_name << " run end";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Hd_AI_empty_module::checkStatus()
|
||||
{
|
||||
status = moduleStatus;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#ifndef Hd_AI_empty_module_H
|
||||
#define Hd_AI_empty_module_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <atlstr.h>
|
||||
#include <chrono>
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <iostream>
|
||||
#include <QDebug>
|
||||
#include <qqueue.h>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <halconcpp/HalconCpp.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "imgproc/imgproc_c.h"
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
|
||||
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct;
|
||||
//{
|
||||
// cv::Mat out_Mat;
|
||||
// std::string saveKey; //关键字,用于LOG日志
|
||||
// std::string savePath; //保存路径
|
||||
//};
|
||||
|
||||
//初始化流程(一次):Hd_AI_empty_module,initParas
|
||||
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
|
||||
class Hd_AI_empty_module :public Base
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Hd_AI_empty_module();
|
||||
virtual ~Hd_AI_empty_module();
|
||||
//从类中读数据到实例对象
|
||||
bool readData(std::vector<cv::Mat>&,QByteArray&);
|
||||
//实例对象把数据写入到类
|
||||
bool writeData(std::vector<cv::Mat>&, QByteArray&);
|
||||
bool initParas(QByteArray&);
|
||||
//运行(Logic_taskthread.cpp)
|
||||
bool run();
|
||||
//线程状态
|
||||
bool checkStatus();// { return true; };
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int allNum = 0;
|
||||
int StationNo=0;
|
||||
int img2D = 2;
|
||||
|
||||
bool moduleStatus = true;
|
||||
|
||||
//输入图片队列
|
||||
QQueue<cv::Mat> HikMat;
|
||||
//输入关键字队列
|
||||
QString saveKey="saveKey";
|
||||
//结果路径文件夹队列
|
||||
QString Dir2D="Dir2D";
|
||||
//产品SN队列
|
||||
QString SN="SN";
|
||||
//产品时间戳队列
|
||||
QString DateTime1="DateTime1";
|
||||
|
||||
int paramNum;
|
||||
|
||||
//是否使用线程检测方式
|
||||
bool ifThreadRunDetect = false;
|
||||
//检测结果图
|
||||
std::vector<cv::Mat> resMat;
|
||||
//检测结果
|
||||
bool resIfNg = false;
|
||||
|
||||
QQueue<QByteArray> resByte;
|
||||
|
||||
//检测线程
|
||||
void detectThread();
|
||||
//存图线程
|
||||
void saveImgThread();
|
||||
|
||||
//保存图片队列
|
||||
QQueue<saveImgStruct> saveStruct;
|
||||
|
||||
//判断文件夹是否存在,不存在则创建
|
||||
void isDirExist(QString fullDirName);
|
||||
|
||||
//存图加入队列
|
||||
void addImgToSaveStruct(cv::Mat img2D, QString saveKey, QString savePath);
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
Q_DECL_EXPORT Hd_AI_empty_module * create();
|
||||
Q_DECL_EXPORT void destory(Hd_AI_empty_module * ptr);
|
||||
}
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct
|
||||
{
|
||||
cv::Mat out_Mat;
|
||||
std::string saveKey; //关键字,用于LOG日志
|
||||
std::string savePath; //保存路径
|
||||
};
|
||||
#endif // Hd_AI_927_2D_module_H
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef __BASECLASS_H__
|
||||
#define __BASECLASS_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include<QJsonDocument>
|
||||
#include<QJsonObject>
|
||||
#include<QJsonArray>
|
||||
|
||||
class Base :public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
bool init_flag; //是否初始化,false,true
|
||||
bool status = true; //相机状态(判断相机是否断开连接)
|
||||
std::string paras; //传输数据
|
||||
std::vector<cv::Mat> m_mat; //传输图片
|
||||
std::string moduleName; //模块名称
|
||||
public:
|
||||
Base(){}
|
||||
virtual ~Base(){}
|
||||
virtual bool readData(std::vector<cv::Mat>&,QByteArray&){return true;}
|
||||
virtual bool writeData(std::vector<cv::Mat>&,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<cv::Mat>&,QByteArray&){return true;}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
# 获取获取当前目录名
|
||||
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")
|
||||
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)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY)
|
||||
|
||||
|
||||
|
||||
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
@@ -0,0 +1,918 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#ifndef Hd_AI_seg_module_H
|
||||
#define Hd_AI_seg_module_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <atlstr.h>
|
||||
#include <chrono>
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <iostream>
|
||||
#include <QDebug>
|
||||
#include <qqueue.h>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "imgproc/imgproc_c.h"
|
||||
|
||||
#include "base.h"
|
||||
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
|
||||
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct;
|
||||
//{
|
||||
// cv::Mat out_Mat;
|
||||
// std::string saveKey; //关键字,用于LOG日志
|
||||
// std::string savePath; //保存路径
|
||||
//};
|
||||
|
||||
//初始化流程(一次):Hd_AI_seg_module,initParas
|
||||
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
|
||||
class Hd_AI_seg_module :public Base
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Hd_AI_seg_module();
|
||||
virtual ~Hd_AI_seg_module();
|
||||
//从类中读数据到实例对象
|
||||
bool readData(std::vector<cv::Mat>&,QByteArray&);
|
||||
//实例对象把数据写入到类
|
||||
bool writeData(std::vector<cv::Mat>&, QByteArray&);
|
||||
bool initParas(QByteArray&);
|
||||
//运行(Logic_taskthread.cpp)
|
||||
bool run();
|
||||
//线程状态
|
||||
bool checkStatus();// { return true; };
|
||||
|
||||
bool encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte);
|
||||
bool decodeAiValue(QByteArray byteArray,QVector<QByteArray> &vec_ret);
|
||||
//---------检测流程,根据实际项目修改---------
|
||||
bool AIdetect(cv::Mat img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int allNum = 0;
|
||||
int StationNo;
|
||||
int img2D = 2;
|
||||
|
||||
bool moduleStatus = true;
|
||||
|
||||
//输入图片队列
|
||||
QQueue<cv::Mat> HikMat;
|
||||
//输入关键字队列
|
||||
QString saveKey="saveKey";
|
||||
//结果路径文件夹队列
|
||||
QString Dir2D="Dir2D";
|
||||
//产品SN队列
|
||||
QString SN="SN";
|
||||
//产品时间戳队列
|
||||
QString DateTime1="DateTime1";
|
||||
|
||||
int paramNum;
|
||||
|
||||
//是否使用线程检测方式
|
||||
bool ifThreadRunDetect = false;
|
||||
//检测结果图
|
||||
std::vector<cv::Mat> resMat;
|
||||
//检测结果
|
||||
bool resIfNg = false;
|
||||
|
||||
QQueue<QByteArray> resByte;
|
||||
|
||||
//检测线程
|
||||
void detectThread();
|
||||
//存图线程
|
||||
void saveImgThread();
|
||||
|
||||
//保存图片队列
|
||||
QQueue<saveImgStruct> saveStruct;
|
||||
|
||||
//判断文件夹是否存在,不存在则创建
|
||||
void isDirExist(QString fullDirName);
|
||||
|
||||
//存图加入队列
|
||||
void addImgToSaveStruct(cv::Mat img2D, QString saveKey, QString savePath);
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
Q_DECL_EXPORT Hd_AI_seg_module * create();
|
||||
Q_DECL_EXPORT void destory(Hd_AI_seg_module * ptr);
|
||||
}
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct
|
||||
{
|
||||
cv::Mat out_Mat;
|
||||
std::string saveKey; //关键字,用于LOG日志
|
||||
std::string savePath; //保存路径
|
||||
};
|
||||
#endif // Hd_AI_927_2D_module_H
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef __BASECLASS_H__
|
||||
#define __BASECLASS_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include<QJsonDocument>
|
||||
#include<QJsonObject>
|
||||
#include<QJsonArray>
|
||||
|
||||
class Base :public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
bool init_flag; //是否初始化,false,true
|
||||
bool status = true; //相机状态(判断相机是否断开连接)
|
||||
std::string paras; //传输数据
|
||||
std::vector<cv::Mat> m_mat; //传输图片
|
||||
std::string moduleName; //模块名称
|
||||
public:
|
||||
Base(){}
|
||||
virtual ~Base(){}
|
||||
virtual bool readData(std::vector<cv::Mat>&,QByteArray&){return true;}
|
||||
virtual bool writeData(std::vector<cv::Mat>&,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<cv::Mat>&,QByteArray&){return true;}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
# 获取获取当前目录名
|
||||
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")
|
||||
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)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY)
|
||||
|
||||
|
||||
|
||||
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,119 @@
|
||||
#ifndef Hd_AI_tmp_module_savImg_H
|
||||
#define Hd_AI_tmp_module_savImg_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <atlstr.h>
|
||||
#include <chrono>
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <iostream>
|
||||
#include <QDebug>
|
||||
#include <qqueue.h>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <halconcpp/HalconCpp.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "imgproc/imgproc_c.h"
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
|
||||
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct;
|
||||
//{
|
||||
// cv::Mat out_Mat;
|
||||
// std::string saveKey; //关键字,用于LOG日志
|
||||
// std::string savePath; //保存路径
|
||||
//};
|
||||
|
||||
//初始化流程(一次):Hd_AI_tmp_module_savImg,initParas
|
||||
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
|
||||
class Hd_AI_tmp_module_savImg :public Base
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Hd_AI_tmp_module_savImg();
|
||||
virtual ~Hd_AI_tmp_module_savImg();
|
||||
//从类中读数据到实例对象
|
||||
bool readData(std::vector<cv::Mat>&,QByteArray&);
|
||||
//实例对象把数据写入到类
|
||||
bool writeData(std::vector<cv::Mat>&, QByteArray&);
|
||||
bool initParas(QByteArray&);
|
||||
//运行(Logic_taskthread.cpp)
|
||||
bool run();
|
||||
//线程状态
|
||||
bool checkStatus();// { return true; };
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int allNum = 0;
|
||||
int StationNo=0;
|
||||
int img2D = 2;
|
||||
|
||||
bool moduleStatus = true;
|
||||
|
||||
//输入图片队列
|
||||
QQueue<cv::Mat> HikMat;
|
||||
//输入关键字队列
|
||||
QString saveKey="saveKey";
|
||||
//结果路径文件夹队列
|
||||
QString Dir2D="Dir2D";
|
||||
//产品SN队列
|
||||
QString SN="SN";
|
||||
//产品时间戳队列
|
||||
QString DateTime1="DateTime1";
|
||||
|
||||
int paramNum;
|
||||
|
||||
//是否使用线程检测方式
|
||||
bool ifThreadRunDetect = false;
|
||||
//检测结果图
|
||||
std::vector<cv::Mat> resMat;
|
||||
//检测结果
|
||||
bool resIfNg = false;
|
||||
|
||||
QQueue<QByteArray> resByte;
|
||||
|
||||
//检测线程
|
||||
void detectThread();
|
||||
//存图线程
|
||||
void saveImgThread();
|
||||
|
||||
//保存图片队列
|
||||
QQueue<saveImgStruct> saveStruct;
|
||||
|
||||
//判断文件夹是否存在,不存在则创建
|
||||
void isDirExist(QString fullDirName);
|
||||
|
||||
//存图加入队列
|
||||
void addImgToSaveStruct(cv::Mat img2D, QString saveKey, QString savePath);
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
Q_DECL_EXPORT Hd_AI_tmp_module_savImg * create();
|
||||
Q_DECL_EXPORT void destory(Hd_AI_tmp_module_savImg * ptr);
|
||||
}
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct
|
||||
{
|
||||
cv::Mat out_Mat;
|
||||
std::string saveKey; //关键字,用于LOG日志
|
||||
std::string savePath; //保存路径
|
||||
};
|
||||
#endif // Hd_AI_927_2D_module_H
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef __BASECLASS_H__
|
||||
#define __BASECLASS_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include<QJsonDocument>
|
||||
#include<QJsonObject>
|
||||
#include<QJsonArray>
|
||||
|
||||
class Base :public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
bool init_flag; //是否初始化,false,true
|
||||
bool status = true; //相机状态(判断相机是否断开连接)
|
||||
std::string paras; //传输数据
|
||||
std::vector<cv::Mat> m_mat; //传输图片
|
||||
std::string moduleName; //模块名称
|
||||
public:
|
||||
Base(){}
|
||||
virtual ~Base(){}
|
||||
virtual bool readData(std::vector<cv::Mat>&,QByteArray&){return true;}
|
||||
virtual bool writeData(std::vector<cv::Mat>&,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<cv::Mat>&,QByteArray&){return true;}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -21,6 +21,7 @@ bool Logic_camera_thread::setModule( QString station_name,MyModule module,QJsonO
|
||||
m_name = obj.value("相机key").toString();
|
||||
m_type = "camera";// camera_obj.value("camera_type").toString();
|
||||
getImgTimeout = obj.value("取图超时").toString().toInt();
|
||||
maxCheckTime = obj.value("拍照信号-检查完成的时间").toString().toDouble();
|
||||
if (m_name.isEmpty() || m_type.isEmpty())
|
||||
{
|
||||
qCritical() << "[Error] " << " camera_key or camera_type is null";
|
||||
@@ -76,6 +77,7 @@ void Logic_camera_thread::set_m_stoprun(bool val)
|
||||
QMutexLocker locker(ifMissImage_mutex); // 加锁
|
||||
m_stoprun = val;
|
||||
}
|
||||
clock_t maxTime_start, maxTime_stop;
|
||||
void Logic_camera_thread::run()
|
||||
{
|
||||
while (ifRun)
|
||||
@@ -86,7 +88,7 @@ void Logic_camera_thread::run()
|
||||
m_stoprun = false;
|
||||
getImg_faileNums = 0;
|
||||
ifsaveImage = false;
|
||||
//set_ifMissImage(false);
|
||||
set_ifMissImage(false);
|
||||
cu_runNum = 0;
|
||||
int last_addImageNums = addImageNums;
|
||||
maxTime_start = clock();
|
||||
@@ -288,14 +290,9 @@ bool Logic_camera_thread::runCameraModule()
|
||||
//QMutexLocker locker(ifMissImage_mutex); // 加锁
|
||||
QByteArray task_name;
|
||||
std::vector<cv::Mat> camera_mat;
|
||||
if (CommunicationProcessLevel == 2 && waitenum++%100==0)
|
||||
{
|
||||
//missImgae_addImage(camera_mat);
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " waite trigger!"<< waitenum;
|
||||
}
|
||||
if (CommunicationProcessLevel == 2 && maxTime_stop - maxTime_start > maxCheckTime)
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "maxCheckTime! add img, hardware" << m_Module.module_key;
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " maxTime_stop - maxTime_start > maxCheckTime,missImgae_addImage!";
|
||||
missImgae_addImage(camera_mat);
|
||||
}
|
||||
else
|
||||
@@ -306,16 +303,8 @@ bool Logic_camera_thread::runCameraModule()
|
||||
{
|
||||
Sleep(10);
|
||||
qApp->processEvents();
|
||||
myTime += 10;
|
||||
if (myTime % 1000 == 0)
|
||||
{
|
||||
if (CommunicationProcessLevel == 2)
|
||||
{
|
||||
//missImgae_addImage(camera_mat);
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " waite trigger!";
|
||||
}
|
||||
}
|
||||
if (myTime > maxCheckTime)
|
||||
maxTime_stop = clock();
|
||||
if (maxTime_stop - maxTime_start > getImgTimeout)
|
||||
{
|
||||
if (CommunicationProcessLevel == 2)
|
||||
{
|
||||
@@ -488,12 +477,12 @@ void Logic_camera_thread::setMutex(QMutex *mutex)
|
||||
m_mutex = new QMutex;// mutex;
|
||||
}
|
||||
|
||||
bool Logic_camera_thread::sendDataCommond( QString m_type,cv::Mat mat,QByteArray byteArray )
|
||||
bool Logic_camera_thread::sendDataCommond( QString m_type,cv::Mat mat,QByteArray byteArray)
|
||||
{
|
||||
QMutexLocker locker(m_mutex);
|
||||
dataPack m_pack;
|
||||
m_pack.mat = mat;
|
||||
m_pack.byteArray = byteArray;
|
||||
m_pack.byteArray = byteArray;
|
||||
m_pack.retFlag = m_type;
|
||||
m_pack.cameraName = m_name;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef Logic_camera_thread_H
|
||||
#ifndef Logic_camera_thread_H
|
||||
#define Logic_camera_thread_H
|
||||
|
||||
#include <QObject>
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <QQueue>
|
||||
#include <QMap>
|
||||
#include <QDir>
|
||||
#include <Windows.h>
|
||||
|
||||
#include "struct.h"
|
||||
#include "Logic_hdataintegration.h"
|
||||
@@ -32,7 +33,7 @@ public:
|
||||
void setRunFlag(bool flag){ m_stoprun = flag; }
|
||||
void setMutex( QMutex *mutex);
|
||||
void setSaveImage( QString save){ m_saveImage = save;}
|
||||
bool sendDataCommond(QString m_type,cv::Mat mat,QByteArray byteArray);
|
||||
bool sendDataCommond(QString m_type,cv::Mat mat,QByteArray byte);
|
||||
bool runCameraModule();
|
||||
bool saveImage(std::vector<cv::Mat> mat);
|
||||
//设置相机key、取图超时、模块、拍照面描述、触发方式
|
||||
@@ -82,8 +83,8 @@ public:
|
||||
QMutex* m_iomutex = nullptr;
|
||||
Base* finstcp_ptr = nullptr;
|
||||
QByteArray send_byte;
|
||||
int maxCheckTime = 3000;
|
||||
int waitenum = 0;
|
||||
double maxCheckTime = 3000;
|
||||
|
||||
private:
|
||||
QQueue<Logic_hdataintegration*> mydataIntegrationThread ;
|
||||
QObject *m_obj;
|
||||
@@ -106,8 +107,6 @@ private:
|
||||
QMutex* ifMissImage_mutex = nullptr;
|
||||
//相机数据包
|
||||
QQueue<dataPack> camera_ImageDataPack;
|
||||
int hardNum = 0;
|
||||
clock_t maxTime_start, maxTime_stop;
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
@@ -485,7 +485,7 @@ QByteArray HAlgorithmData::getAlgorithmData(QString SNdataTime,QString cameraNam
|
||||
|
||||
QByteArray HAlgorithmData::getIndexData(Algorithm_Result_Data result_data, int result_index, QString algorithm_result_index)
|
||||
{
|
||||
//qDebug() << __FUNCTION__ << " line: " << __LINE__ << " algorithmKey:" << algorithmKey << " cameraName_and_index: " << cameraName_and_index << " result_data.byteArray len:" << result_data.byteArray.length();
|
||||
//qDebug() << __FUNCTION__ << " line: " << __LINE__ << " algorithmKey:" << algorithmKey << " cameraName_and_index: " << cameraName_and_index << " result_data.byte len:" << result_data.byte.length();
|
||||
|
||||
Algorithm_Result_Data_index index_pack;
|
||||
if (map_delete_Result_index.keys().contains(result_data.key_index))
|
||||
@@ -503,10 +503,10 @@ QByteArray HAlgorithmData::getIndexData(Algorithm_Result_Data result_data, int r
|
||||
QString cameraName = list.at(0);
|
||||
QString task_index = list.at(1);
|
||||
//Logic_taskthread运行算法/汇总模块后,返回的数据
|
||||
QByteArray byteArray = result_data.byteArray;
|
||||
QByteArray byte = result_data.byteArray;
|
||||
//result_data.byte转
|
||||
QByteArrayList vec_Data;
|
||||
vec_Data = byteArray.split('#');
|
||||
vec_Data = byte.split('#');
|
||||
|
||||
if (vec_Data.isEmpty())
|
||||
{
|
||||
@@ -520,7 +520,7 @@ QByteArray HAlgorithmData::getIndexData(Algorithm_Result_Data result_data, int r
|
||||
return index_byte;
|
||||
}
|
||||
|
||||
index_byte = vec_Data[algorithm_result_index.toInt()];// byteArray;// QByteArray::fromStdString(sendMsg);
|
||||
index_byte = vec_Data[algorithm_result_index.toInt()];// byte;// QByteArray::fromStdString(sendMsg);
|
||||
|
||||
// 删除map中的数据
|
||||
if (vec_Data.size() == 1)
|
||||
|
||||
@@ -22,7 +22,7 @@ typedef struct
|
||||
//or检测:保存路径,拍照面描述,相机key_第几张图,SN_时间戳
|
||||
//and检测:保存路径,拍照面描述,相机key_第几张图,相机key_第几张图,SN_时间戳,SN_时间戳
|
||||
//汇总:保存路径,触发信号_序号列表0,,SN_时间戳
|
||||
QByteArray byteArray;
|
||||
QByteArray byteArray;
|
||||
std::vector<cv::Mat> dstImageMat;
|
||||
//拍照面描述
|
||||
QString Surface;
|
||||
@@ -104,8 +104,8 @@ public:
|
||||
|
||||
int m_index = 0;
|
||||
int image_queue_num = 0; //划分相机任务的数量
|
||||
QString cameraKey;
|
||||
private:
|
||||
QString cameraKey;
|
||||
QJsonArray readSnFormatArray; // 存储sn码的格式
|
||||
QVector<QVector<QQueue<SnCameraData>*>> vector_vector_queue_mat_ptr; // 存储相机图片任务的容器;QVector<QQueue<SnCameraData>*>为通道的
|
||||
QMutex* m_mutex;
|
||||
|
||||
@@ -187,6 +187,7 @@ void Logic_myiothread::run()
|
||||
// 一个信号取多张的情况,取图时间长,和通信线程分开。
|
||||
m_runAndCheck_cameraThread->start();
|
||||
int times = 0;
|
||||
heart_start = clock();
|
||||
while ( io_runflag )
|
||||
{
|
||||
//心跳(定时向PLC的指定寄存器写入值)代码。
|
||||
@@ -194,92 +195,65 @@ void Logic_myiothread::run()
|
||||
{
|
||||
//break;
|
||||
//times++;
|
||||
Sleep(10);
|
||||
qApp->processEvents();
|
||||
if ((m_heartTime / 10) <= times++)
|
||||
|
||||
QStringList m_heartCmdList = m_heartCmd.split("#");
|
||||
for (int m = 0; m < m_heartCmdList.size(); m++)
|
||||
{
|
||||
if (!m_heartCmd.isEmpty())
|
||||
{// 发送心跳
|
||||
////QMutexLocker locker(m_iomutex);;
|
||||
QByteArray byteArray = m_heartCmd.toUtf8(); // 设置 从起始位开始读取的指令
|
||||
if (!finstcp_ptr->writeData(vec_mat, byteArray))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr reciveData error!";
|
||||
}
|
||||
times = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rest_signal.isEmpty())
|
||||
Sleep(10);
|
||||
qApp->processEvents();
|
||||
heart_stop = clock();
|
||||
//if ((m_heartTime / 10) <= times++)
|
||||
if (heart_stop - heart_start >= m_heartTime)
|
||||
{
|
||||
if (times % int(m_heartTime / 50 + 1) == 0)
|
||||
{
|
||||
// 修改读取多个命令
|
||||
//QMutexLocker locker(m_iomutex);;
|
||||
QByteArray byteArray = readAll_cmd.toUtf8(); // 设置 从起始位开始读取的指令
|
||||
if (!finstcp_ptr->writeData(vec_mat, byteArray))
|
||||
heart_start = clock();
|
||||
if (!m_heartCmdList[m].isEmpty())
|
||||
{// 发送心跳
|
||||
////QMutexLocker locker(m_iomutex);;
|
||||
QByteArray byte = m_heartCmdList[m].toUtf8(); // 设置 从起始位开始读取的指令
|
||||
if (!finstcp_ptr->writeData(vec_mat, byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr reciveData error!";
|
||||
}
|
||||
|
||||
// 读取到的信息解析
|
||||
QByteArray readByte;
|
||||
if (!finstcp_ptr->readData(vec_mat, readByte))
|
||||
times = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rest_signal.isEmpty())
|
||||
{
|
||||
if (times % int(m_heartTime / 50 + 1) == 0)
|
||||
{
|
||||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr sendData error!";
|
||||
}
|
||||
|
||||
if (readByte.isEmpty())
|
||||
return;
|
||||
QByteArray readsnByte = readByte;
|
||||
QVector<int> vec_value;
|
||||
while (!readByte.isEmpty())
|
||||
{
|
||||
QByteArray retByte = readByte.mid(0, 2);
|
||||
readByte.remove(0, 2);
|
||||
|
||||
QString msg = retByte.toHex();
|
||||
int number_tmp = msg.toInt(NULL, 16);
|
||||
vec_value.push_back(number_tmp);
|
||||
}
|
||||
|
||||
QString m_startpos = rest_signal.split("_")[0];
|
||||
QString m_value = rest_signal.split("_")[1];
|
||||
int trigger_index = m_startpos.mid(1, m_startpos.length() - 1).toInt();
|
||||
trigger_index -= trigger_startpos;
|
||||
if (trigger_index < 0)
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " vec_value is error! read_sn_startpos:" << m_startpos;
|
||||
}
|
||||
else if (vec_value.size() > trigger_index)
|
||||
{
|
||||
//读复位标志满足
|
||||
if (vec_value.at(trigger_index) == m_value.toInt())
|
||||
// 修改读取多个命令
|
||||
//QMutexLocker locker(m_iomutex);;
|
||||
QByteArray byte = readAll_cmd.toUtf8(); // 设置 从起始位开始读取的指令
|
||||
if (!finstcp_ptr->writeData(vec_mat, byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " 复位信号:" << rest_signal;
|
||||
foreach(QString m_station_name, station_list.keys())
|
||||
for (int i = 0; i < station_list.value(m_station_name)->sndata_list.size(); i++)
|
||||
{
|
||||
QStringList cameraList;
|
||||
cameraList.append("all");
|
||||
for (int i = 0; i < 10; i++)
|
||||
station_list.value(m_station_name)->clearData("all", cameraList);
|
||||
}
|
||||
//完成清标志
|
||||
QByteArray send_byte = rest_signal_back.toUtf8();
|
||||
if (!finstcp_ptr->writeData(vec_mat, send_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
}
|
||||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr reciveData error!";
|
||||
}
|
||||
}
|
||||
//程序号;传到到主界面类,再进行切换
|
||||
if (!program_Num.isEmpty())
|
||||
{
|
||||
QString m_startpos = program_Num;// .split("_")[0];
|
||||
//QString m_value = program_Num.split("_")[1];
|
||||
|
||||
// 读取到的信息解析
|
||||
QByteArray readByte;
|
||||
if (!finstcp_ptr->readData(vec_mat, readByte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr sendData error!";
|
||||
}
|
||||
|
||||
if (readByte.isEmpty())
|
||||
return;
|
||||
QByteArray readsnByte = readByte;
|
||||
QVector<int> vec_value;
|
||||
while (!readByte.isEmpty())
|
||||
{
|
||||
QByteArray retByte = readByte.mid(0, 2);
|
||||
readByte.remove(0, 2);
|
||||
|
||||
QString msg = retByte.toHex();
|
||||
int number_tmp = msg.toInt(NULL, 16);
|
||||
vec_value.push_back(number_tmp);
|
||||
}
|
||||
|
||||
QString m_startpos = rest_signal.split("_")[0];
|
||||
QString m_value = rest_signal.split("_")[1];
|
||||
int trigger_index = m_startpos.mid(1, m_startpos.length() - 1).toInt();
|
||||
trigger_index -= trigger_startpos;
|
||||
if (trigger_index < 0)
|
||||
@@ -289,20 +263,19 @@ void Logic_myiothread::run()
|
||||
else if (vec_value.size() > trigger_index)
|
||||
{
|
||||
//读复位标志满足
|
||||
if (vec_value.at(trigger_index) !=0)
|
||||
if (vec_value.at(trigger_index) == m_value.toInt())
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " 程序号:" << vec_value.at(trigger_index);
|
||||
|
||||
dataPack m_data;
|
||||
m_data.algorithmName = "程序号";
|
||||
m_data.cameraName = m_startpos;
|
||||
m_data.byteArray = QByteArray::number(vec_value.at(trigger_index));
|
||||
m_data.retFlag = "algorithm";
|
||||
|
||||
QMutexLocker locker(sendProcess_mutex);
|
||||
sendProcessTask.enqueue(m_data);
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " 复位信号:" << rest_signal;
|
||||
foreach(QString m_station_name, station_list.keys())
|
||||
for (int i = 0; i < station_list.value(m_station_name)->sndata_list.size(); i++)
|
||||
{
|
||||
QStringList cameraList;
|
||||
cameraList.append("all");
|
||||
for (int i = 0; i < 10; i++)
|
||||
station_list.value(m_station_name)->clearData("all", cameraList);
|
||||
}
|
||||
//完成清标志
|
||||
QByteArray send_byte = program_Num_back.toUtf8();
|
||||
QByteArray send_byte = rest_signal_back.toUtf8();
|
||||
if (!finstcp_ptr->writeData(vec_mat, send_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
@@ -310,10 +283,47 @@ void Logic_myiothread::run()
|
||||
}
|
||||
}
|
||||
}
|
||||
//程序号;传到到主界面类,再进行切换
|
||||
if (!program_Num.isEmpty())
|
||||
{
|
||||
QString m_startpos = program_Num;// .split("_")[0];
|
||||
//QString m_value = program_Num.split("_")[1];
|
||||
int trigger_index = m_startpos.mid(1, m_startpos.length() - 1).toInt();
|
||||
trigger_index -= trigger_startpos;
|
||||
if (trigger_index < 0)
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " vec_value is error! read_sn_startpos:" << m_startpos;
|
||||
}
|
||||
else if (vec_value.size() > trigger_index)
|
||||
{
|
||||
//读复位标志满足
|
||||
if (vec_value.at(trigger_index) != 0)
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " 程序号:" << vec_value.at(trigger_index);
|
||||
|
||||
dataPack m_data;
|
||||
m_data.algorithmName = "程序号";
|
||||
m_data.cameraName = m_startpos;
|
||||
m_data.byteArray = QByteArray::number(vec_value.at(trigger_index));
|
||||
m_data.retFlag = "algorithm";
|
||||
|
||||
QMutexLocker locker(sendProcess_mutex);
|
||||
sendProcessTask.enqueue(m_data);
|
||||
//完成清标志
|
||||
QByteArray send_byte = program_Num_back.toUtf8();
|
||||
if (!finstcp_ptr->writeData(vec_mat, send_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 写入
|
||||
writeCommond();
|
||||
@@ -362,8 +372,8 @@ void Logic_myiothread::reciveCommond()
|
||||
// 修改读取多个命令
|
||||
//QMutexLocker locker ( m_iomutex );
|
||||
m_iomutex->lock();
|
||||
QByteArray byteArray = readAll_cmd.toUtf8(); // 设置 从起始位开始读取的指令
|
||||
if ( !finstcp_ptr->writeData(vec_mat,byteArray) )
|
||||
QByteArray byte = readAll_cmd.toUtf8(); // 设置 从起始位开始读取的指令
|
||||
if ( !finstcp_ptr->writeData(vec_mat,byte) )
|
||||
{
|
||||
qCritical() << __FUNCTION__ << "line:"<< __LINE__ << " finstcp_ptr reciveData error!";
|
||||
}
|
||||
@@ -378,7 +388,7 @@ void Logic_myiothread::reciveCommond()
|
||||
stop = clock();
|
||||
double ctime = stop - start;
|
||||
//if (ctime > 500)
|
||||
// qCritical() << __FUNCTION__ << __LINE__ << "readAll_cmd ctime :" << ctime;//;127ms
|
||||
//qCritical() << __FUNCTION__ << __LINE__ << "readAll_cmd ctime :" << ctime<<" m_stationName:"<<m_stationName;//;127ms
|
||||
|
||||
// tmpDate = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||||
//qDebug() << __FUNCTION__ << " line: " << __LINE__ << " readAll_cmd done: " << readAll_cmd << " " << tmpDate;
|
||||
@@ -387,17 +397,17 @@ void Logic_myiothread::reciveCommond()
|
||||
}
|
||||
|
||||
// 读取多个命令信息的解析
|
||||
void Logic_myiothread::decodeCameraCMD(QByteArray byteArray)
|
||||
void Logic_myiothread::decodeCameraCMD(QByteArray byte)
|
||||
{
|
||||
if (byteArray.isEmpty())
|
||||
if (byte.isEmpty())
|
||||
return;
|
||||
|
||||
readsnByte = byteArray;
|
||||
readsnByte = byte;
|
||||
vec_value.clear();
|
||||
while ( !byteArray.isEmpty() )
|
||||
while ( !byte.isEmpty() )
|
||||
{
|
||||
QByteArray retByte = byteArray.mid(0,2);
|
||||
byteArray.remove(0,2);
|
||||
QByteArray retByte = byte.mid(0,2);
|
||||
byte.remove(0,2);
|
||||
|
||||
QString msg = retByte.toHex();
|
||||
int number_tmp = msg.toInt(NULL,16);
|
||||
@@ -426,7 +436,7 @@ void Logic_myiothread::decodeCameraCMD(QByteArray byteArray)
|
||||
//SN逻辑
|
||||
// "读SN信号"满足时,代表新料来了,安装"清理容器数据"-"相机列表"及"通道序号"清理对应的容器;
|
||||
//SN保存到容器HSnData;下料的SN,根据"汇总-触发信号"、"汇总-读哪个SN"匹配Logic_hdataintegration,并保存SN到变量;
|
||||
void Logic_myiothread::readSnInfo(QVector<int> vec_value, QByteArray byteArray)
|
||||
void Logic_myiothread::readSnInfo(QVector<int> vec_value, QByteArray byte)
|
||||
{
|
||||
QStringList keys = map_sn_area_array.keys();
|
||||
//重新加载用
|
||||
@@ -497,19 +507,19 @@ void Logic_myiothread::readSnInfo(QVector<int> vec_value, QByteArray byteArray)
|
||||
// sn码防重入检查
|
||||
QVector<bool> m_vec_sn_flag = map_read_sn_reentry_vector_flag.value(station_name);
|
||||
|
||||
if (m_vec_sn_flag.at(channel_index)) // false 添加sn码 true 已经添加过sn,不再重复添加
|
||||
{
|
||||
// 清理当前sn码的触发信号
|
||||
QString m_signal = "write_short_" + m_startpos + "_0";
|
||||
QByteArray m_byte = m_signal.toUtf8();
|
||||
QMutexLocker locker(m_iomutex);
|
||||
if (!finstcp_ptr->writeData(vec_mat, m_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//if (m_vec_sn_flag.at(channel_index)) // false 添加sn码 true 已经添加过sn,不再重复添加
|
||||
//{
|
||||
// // 清理当前sn码的触发信号
|
||||
// QString m_signal = "write_short_" + m_startpos + "_0";
|
||||
// QByteArray m_byte = m_signal.toUtf8();
|
||||
// //QMutexLocker locker(m_iomutex);;
|
||||
// if (!finstcp_ptr->writeData(vec_mat, m_byte))
|
||||
// {
|
||||
// qCritical() << __FUNCTION__ << " line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
// return;
|
||||
// }
|
||||
// continue;
|
||||
//}
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " m_vec_sn_flag:" << m_vec_sn_flag.at(channel_index);
|
||||
|
||||
|
||||
@@ -566,7 +576,7 @@ void Logic_myiothread::readSnInfo(QVector<int> vec_value, QByteArray byteArray)
|
||||
for (int aaa = 0; aaa < read_datatime_list.size(); aaa++)
|
||||
{
|
||||
//SN为""时,返回配置文件的read_sn_error_send_format值
|
||||
QString datatime = getSn(read_sn_error_send_format, read_datatime_list[aaa].toString(), byteArray);
|
||||
QString datatime = getSn(read_sn_error_send_format, read_datatime_list[aaa].toString(), byte);
|
||||
qDebug() << __FUNCTION__ << " line: " << __LINE__ << " channel_index: " << channel_index << " read_datatime_list: " << datatime;
|
||||
//sn_value = snHex(sn_value); // sn方向相反,重新做转换
|
||||
|
||||
@@ -638,7 +648,7 @@ void Logic_myiothread::readSnInfo(QVector<int> vec_value, QByteArray byteArray)
|
||||
for (int aaa = 0; aaa < read_sn_list.size(); aaa++)
|
||||
{
|
||||
//SN为""时,返回配置文件的read_sn_error_send_format值
|
||||
QString sn_value = getSn(read_sn_error_send_format, read_sn_list[aaa].toString(), byteArray);
|
||||
QString sn_value = getSn(read_sn_error_send_format, read_sn_list[aaa].toString(), byte);
|
||||
qDebug() << __FUNCTION__ << " line: " << __LINE__ << " channel_index: " << channel_index << " sn_value: " << sn_value;
|
||||
//sn_value = snHex(sn_value); // sn方向相反,重新做转换
|
||||
//异常
|
||||
@@ -668,35 +678,72 @@ void Logic_myiothread::readSnInfo(QVector<int> vec_value, QByteArray byteArray)
|
||||
|
||||
|
||||
|
||||
// 清理当前区域数据
|
||||
QString clear_SN = obj.value("读SN后-清0").toString();
|
||||
if (!clear_SN.isEmpty())
|
||||
//// 清理当前区域数据
|
||||
//QString clear_SN = obj.value("读SN后-清0").toString();
|
||||
//if (!clear_SN.isEmpty())
|
||||
//{
|
||||
// QStringList mycmdHead = clear_SN.split("_");
|
||||
// for (int aaa = 0; aaa < read_sn_list.size(); aaa++)
|
||||
// {
|
||||
// QString sn_area = read_sn_list.at(aaa).toString();
|
||||
// QString start_pos = sn_area.split("_")[0];
|
||||
// int lenght = sn_area.split("_")[1].toInt();
|
||||
// QString m_signal = nullptr;
|
||||
// //SN清空
|
||||
// for (auto yyy = 0; yyy < (lenght+1)/2; yyy++)
|
||||
// {
|
||||
// m_signal += mycmdHead[2];
|
||||
// if (yyy != ((lenght + 1) / 2 - 1))
|
||||
// m_signal += ",";
|
||||
// }
|
||||
// m_signal = mycmdHead[0] + "_" + mycmdHead[1] + "_" + start_pos + "_" + m_signal;// QString("write_short_%1_%2").arg(start_pos).arg(m_signal);
|
||||
// QByteArray m_byte = m_signal.toUtf8();
|
||||
// //QMutexLocker locker(m_iomutex);;
|
||||
// if (!finstcp_ptr->writeData(vec_mat, m_byte))
|
||||
// {
|
||||
// qCritical() << __FUNCTION__ << " line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
if (ifReadSnErr == true)
|
||||
{
|
||||
QStringList mycmdHead = clear_SN.split("_");
|
||||
for (int aaa = 0; aaa < read_sn_list.size(); aaa++)
|
||||
QStringList snOKCmdList = obj.value("读SN异常-回复指令").toString().split("#");
|
||||
if (!snOKCmdList.isEmpty())
|
||||
{
|
||||
QString sn_area = read_sn_list.at(aaa).toString();
|
||||
QString start_pos = sn_area.split("_")[0];
|
||||
int lenght = sn_area.split("_")[1].toInt();
|
||||
QString m_signal = nullptr;
|
||||
//SN清空
|
||||
for (auto yyy = 0; yyy < (lenght+1)/2; yyy++)
|
||||
for (int s = 0; s < snOKCmdList.size(); s++)
|
||||
{
|
||||
m_signal += mycmdHead[2];
|
||||
if (yyy != ((lenght + 1) / 2 - 1))
|
||||
m_signal += ",";
|
||||
}
|
||||
m_signal = mycmdHead[0] + "_" + mycmdHead[1] + "_" + start_pos + "_" + m_signal;// QString("write_short_%1_%2").arg(start_pos).arg(m_signal);
|
||||
QByteArray m_byte = m_signal.toUtf8();
|
||||
QMutexLocker locker(m_iomutex);
|
||||
if (!finstcp_ptr->writeData(vec_mat, m_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
//snOKCmd = CmdHeadShort + snOKCmd;
|
||||
QByteArray ok_byte = snOKCmdList[s].toUtf8();
|
||||
if (!finstcp_ptr->writeData(vec_mat, ok_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
QStringList snOKCmdList = obj.value("读SN正常-回复指令").toString().split("#");
|
||||
if (!snOKCmdList.isEmpty())
|
||||
{
|
||||
for (int s = 0; s < snOKCmdList.size(); s++)
|
||||
{
|
||||
//snOKCmd = CmdHeadShort + snOKCmd;
|
||||
QByteArray ok_byte = snOKCmdList[s].toUtf8();
|
||||
if (!finstcp_ptr->writeData(vec_mat, ok_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清理当前sn码的触发信号
|
||||
QString m_signal = "write_short_" + m_startpos + "_0";
|
||||
QByteArray m_byte = m_signal.toUtf8();
|
||||
@@ -706,38 +753,6 @@ void Logic_myiothread::readSnInfo(QVector<int> vec_value, QByteArray byteArray)
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (ifReadSnErr == true)
|
||||
{
|
||||
QString snErrCmd = obj.value("读SN异常-回复指令").toString();
|
||||
if (!snErrCmd.isEmpty())
|
||||
{
|
||||
//snErrCmd = CmdHeadShort + snErrCmd;
|
||||
QByteArray ok_byte = snErrCmd.toUtf8();
|
||||
if (!finstcp_ptr->writeData(vec_mat, ok_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// snOKCmd
|
||||
QString snOKCmd = obj.value("读SN正常-回复指令").toString();
|
||||
if (!snOKCmd.isEmpty())
|
||||
{
|
||||
//snOKCmd = CmdHeadShort + snOKCmd;
|
||||
QByteArray ok_byte = snOKCmd.toUtf8();
|
||||
if (!finstcp_ptr->writeData(vec_mat, ok_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( vec_value.at(trigger_index) == 0 ){ //读到PLC标志为0时
|
||||
// 更改防重入标识符
|
||||
@@ -873,7 +888,7 @@ QString Logic_myiothread::snHex(QString sn)
|
||||
return resultStr;
|
||||
}
|
||||
//SN为""时,返回配置文件的"读SN异常-插值"
|
||||
QString Logic_myiothread::getSn(QString errorinfo,QString area,QByteArray byteArray)
|
||||
QString Logic_myiothread::getSn(QString errorinfo,QString area,QByteArray byte)
|
||||
{
|
||||
QString m_startpos = area.split("_")[0];
|
||||
QString lenght = area.split("_")[1];
|
||||
@@ -881,7 +896,7 @@ QString Logic_myiothread::getSn(QString errorinfo,QString area,QByteArray byteAr
|
||||
int start_index = m_startpos.mid(1,m_startpos.length()-1).toInt();
|
||||
start_index -= trigger_startpos;
|
||||
|
||||
QByteArray snByte = byteArray.mid(start_index*2,lenght.toInt());
|
||||
QByteArray snByte = byte.mid(start_index*2,lenght.toInt());
|
||||
QString sn = snByte;
|
||||
|
||||
if ( sn.contains("\n\r") )
|
||||
@@ -1082,14 +1097,14 @@ void Logic_myiothread::checkTriggerCamera(QVector<int> vec_value)
|
||||
QStringList myCmdHead = m_pack.clear_camera_startpos_flag.split("_");
|
||||
clear_signal = myCmdHead[0]+"_"+ myCmdHead[1] +"_" + clear_signal + +"_" + myCmdHead[2];
|
||||
QByteArray m_byte = clear_signal.toUtf8();
|
||||
QMutexLocker locker(m_iomutex);
|
||||
if ( !finstcp_ptr->writeData(vec_mat,m_byte) )
|
||||
////QMutexLocker locker(m_iomutex);;
|
||||
/*if ( !finstcp_ptr->writeData(vec_mat,m_byte) )
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:"<< __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
if ( vec_value.at(trigger_index) == m_value.toInt() && m_pack.trigger_reentry_signal == 0 )
|
||||
if ( vec_value.at(trigger_index) == m_value.toInt() )//&& m_pack.trigger_reentry_signal == 0 )
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "trigger_signal: " << trigger_signal;
|
||||
|
||||
@@ -1189,7 +1204,7 @@ void Logic_myiothread::checkTriggerAlgorithm(QVector<int> vec_value)
|
||||
}
|
||||
}
|
||||
if (vec_value.at(trigger_index) == m_value.toInt() )
|
||||
if(m_pack.trigger_reentry_signal == 0)
|
||||
//if(m_pack.trigger_reentry_signal == 0)
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "trigger_signal: " << trigger_signal;
|
||||
|
||||
@@ -1258,8 +1273,8 @@ void Logic_myiothread::checkTriggerAlgorithm(QVector<int> vec_value)
|
||||
//}
|
||||
|
||||
}
|
||||
else
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "trigger_signal: " << trigger_signal << " m_pack.trigger_reentry_signal != 0";
|
||||
//else
|
||||
// qDebug() << __FUNCTION__ << " line:" << __LINE__ << "trigger_signal: " << trigger_signal << " m_pack.trigger_reentry_signal != 0";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1741,7 +1756,7 @@ QByteArray runAndCheck_cameraThread::checkCamerasFinish_feedbackSignal(trigger_s
|
||||
QByteArray send_byte = send_msg.toUtf8();
|
||||
return send_byte;
|
||||
|
||||
/*QMutexLocker locker(m_iomutex);
|
||||
/*//QMutexLocker locker(m_iomutex);;
|
||||
if (!finstcp_ptr->writeData(vec_mat, send_byte))
|
||||
{
|
||||
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " finstcp_ptr reciveData error! ";
|
||||
|
||||
@@ -181,6 +181,7 @@ private:
|
||||
QQueue< dataPack> sendProcessTask;
|
||||
QByteArray readsnByte ;
|
||||
QVector<int> vec_value;
|
||||
clock_t heart_start,heart_stop;
|
||||
signals:
|
||||
};
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user