Files
ds-628/basemoduleBackup/Hd_AI_3D_module/Hd_AI_3D_module.cpp
T
2025-07-27 16:12:08 +08:00

1500 lines
57 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "Hd_AI_3D_module.h"
#include <QDateTime>
#include <QtConcurrent/QtConcurrent>
#include <qfuture.h>
#include <Halcon.h>
#include <QTextCodec>
using namespace cv;
using namespace std;
using namespace HalconCpp;
//原图保存文件夹
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 qstring_data;
QString cameraKey_index = "";
QString sData;
QStringList splitDataList;
//初始化参数列表
QByteArrayList initValueList;
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, "微软雅黑");
}
}
cv::Mat RotateImage180(const cv::Mat& image)
{
cv::Mat rotatedImage;
cv::flip(image, rotatedImage, -1);
return rotatedImage;
}
HalconCpp::HObject MatToHObject(cv::Mat& image)
{
HalconCpp::HObject Hobj;
int hgt = image.rows;
int wid = image.cols;
int i;
if (image.type() == CV_8UC3)
{
HalconCpp::HImage himage = HalconCpp::HImage();
std::vector<cv::Mat> imgchannel;
split(image, imgchannel);
cv::Mat imgB = imgchannel[0];
cv::Mat imgG = imgchannel[1];
cv::Mat imgR = imgchannel[2];
uchar* dataR = new uchar[hgt * wid];
uchar* dataG = new uchar[hgt * wid];
uchar* dataB = new uchar[hgt * wid];
for (i = 0; i < hgt; i++)
{
memcpy(dataR + wid * i, imgR.data + imgR.step * i, wid);
memcpy(dataG + wid * i, imgG.data + imgG.step * i, wid);
memcpy(dataB + wid * i, imgB.data + imgB.step * i, wid);
}
himage.GenImage3("byte", wid, hgt, dataR, dataG, dataB);
HalconCpp::HString tmpType;
Hlong tmpW, tmpH;
void* hImgPtR, * hImgPtG, * hImgPtB;
himage.GetImagePointer3(&hImgPtR, &hImgPtG, &hImgPtB, &tmpType, &tmpW, &tmpH);
GenImage3(&Hobj, "byte", wid, hgt, (Hlong)hImgPtR, (Hlong)hImgPtG, (Hlong)hImgPtB);
delete[]dataR;
delete[]dataG;
delete[]dataB;
dataR = NULL;
dataG = NULL;
dataB = NULL;
}
else if (image.type() == CV_8UC1)
{
//HalconCpp::HImage himage = HalconCpp::HImage();
////uchar* data = new uchar[hgt * wid];
////for (i = 0; i < hgt; i++)
////{
//// memcpy(data + wid * i, image.data + image.step * i, wid);
////}
////gen_image_const
//himage.GenImage1("byte", wid, hgt, image.data);
//HalconCpp::HString tmpType;
//Hlong tmpW, tmpH;
//void* hImgPt;
//hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH);
//GenImage1(&Hobj, "byte", wid, hgt, (Hlong)hImgPt);
//GenImage1(&Hobj, "byte", wid, hgt, (Hlong)image.data);
/* delete[] data;
data = NULL;*/
uchar* data = new uchar[hgt * wid];
for (i = 0; i < hgt; i++)
memcpy(data + wid * i, image.data + image.step * i, wid);
GenImage1(&Hobj, "byte", wid, hgt, (Hlong)data);
delete[] data;
data = NULL;
}
else if (image.type() == CV_16UC1)
{
HalconCpp::HImage himage = HalconCpp::HImage();
ushort* data = new ushort[hgt * wid * 2];
memcpy(data, image.data, hgt * wid * 2);
himage.GenImage1("uint2", wid, hgt, data);
HalconCpp::HString tmpType;
Hlong tmpW, tmpH;
void* hImgPt;
hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH);
GenImage1(&Hobj, "uint2", wid, hgt, (Hlong)hImgPt);
delete[] data;
data = NULL;
}
else if (image.type() == CV_16SC1)
{
HalconCpp::HImage himage = HalconCpp::HImage();
short* data = new short[hgt * wid * 2];
memcpy(data, image.data, hgt * wid * 2);
himage.GenImage1("int2", wid, hgt, data);
HalconCpp::HString tmpType;
Hlong tmpW, tmpH;
void* hImgPt;
hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH);
GenImage1(&Hobj, "int2", wid, hgt, (Hlong)hImgPt);
delete[] data;
data = NULL;
}
return Hobj;
}
cv::Mat HObject2Mat(HalconCpp::HObject& Hobj) //HObject类型转Mat类型
{
HalconCpp::HTuple htCh;
HalconCpp::HString cType;
cv::Mat Image;
ConvertImageType(Hobj, &Hobj, "byte");
CountChannels(Hobj, &htCh);
Hlong wid = 0;
Hlong hgt = 0;
if (htCh[0].I() == 1)
{
HImage hImg(Hobj);
void* ptr = hImg.GetImagePointer1(&cType, &wid, &hgt);//GetImagePointer1(Hobj, &ptr, &cType, &wid, &hgt);
int W = wid;
int H = hgt;
Image.create(H, W, CV_8UC1);
unsigned char* pdata = static_cast<unsigned char*>(ptr);
memcpy(Image.data, pdata, W * H);
}
else if (htCh[0].I() == 3)
{
void* Rptr;
void* Gptr;
void* Bptr;
HImage hImg(Hobj);
hImg.GetImagePointer3(&Rptr, &Gptr, &Bptr, &cType, &wid, &hgt);
int W = wid;
int H = hgt;
Image.create(H, W, CV_8UC3);
std::vector<cv::Mat> VecM(3);
VecM[0].create(H, W, CV_8UC1);
VecM[1].create(H, W, CV_8UC1);
VecM[2].create(H, W, CV_8UC1);
unsigned char* R2 = (unsigned char*)Rptr;
unsigned char* G = (unsigned char*)Gptr;
unsigned char* B = (unsigned char*)Bptr;
memcpy(VecM[2].data, R2, W * H);
memcpy(VecM[1].data, G, W * H);
memcpy(VecM[0].data, B, W * H);
cv::merge(VecM, Image);
}
return Image;
}
//判断文件夹是否存在,不存在则创建
void Hd_AI_3D_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_3D_module* create()
{
qDebug() << "[INFO] " << " Hd_AI_3D_module create success!" ;
return new Hd_AI_3D_module;
}
void destory(Hd_AI_3D_module* ptr)
{
qDebug() << "[INFO] " << "Hd_AI_3D_module destory success!";
if(ptr)
{
delete ptr;
ptr = nullptr;
}
}
Hd_AI_3D_module::Hd_AI_3D_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_3D_module::~Hd_AI_3D_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_3D_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() > 0)
vec_mat.push_back(HikMat[1]);
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " resMat.data err:";
}
//if (allNum++ % 2 == 0)
// data = "2";// resByte.dequeue();
//else
//data = "1*1.1,2.2";//1OK,2NG
////之后根据结果类修改
//if(resIfNg == true)
// data = "NG";
//else data = "OK";
if (!savePath_result.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);'
for (int i = 0; i < initValueList.size(); i++)
{
QString minit = byteArrayToUnicode(initValueList[i]);
if (initValueList[i].contains(moduleData.split(',')[2].split('_')[0]))
{
if (resultOKNG == 1)
{
isDirExist(savePath_result + "/OK");
addImgToSaveStruct(vec_mat[0], "0", savePath_result + "/OK/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".jpg");//保存结果图
}
else
{
isDirExist(savePath_result + "/NG");
addImgToSaveStruct(vec_mat[0], "0", savePath_result + "/NG/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".jpg");//保存结果图
}
}
}
}
QString plcOkNgtext = "";
if (resultOKNG == 1)
plcOkNgtext = "OK";
else
plcOkNgtext = "NG";
QString sdataTime_msz = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
QString outResultText = sdataTime_msz + "," + SN + "," + splitDataList[1] + "," + plcOkNgtext + "," + QByteArray::number(resultData[0]) + "," + QByteArray::number(resultData[1])
+ "," + QByteArray::number(resultData[2]) + "," + QByteArray::number(resultData[3]) + "," + QByteArray::number(resultData[4]) + "," + QByteArray::number(resultData[5]);
//判断 文件夹/文件 是否存在
QFileInfo csv_fileInfo(savePath_csv + ".csv");
if (!csv_fileInfo.exists())
{
//创建文件1
QFile file(savePath_csv + ".csv");
if (file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream out(&file);
out.setCodec(QTextCodec::codecForName("utf-8"));
out << QString::fromStdString("日期,产品条码,相机工位,相机结果,清洗后长边铝壳间隙实际值,清洗后长边盖板台阶实际值,清洗后长边铝壳间隙实际值长边R角1,清洗后长边铝壳间隙实际值长边R角1,清洗后长边盖板台阶实际值长边R角1,清洗后长边盖板台阶实际值长边R角2 \n");
//out << QString::fromStdString("时间码,二维码,存盘路径,总结果,工位1_2D_TF,工位1_2D_TR,工位1_3D_TF,工位1_3D_TR,工位1_DE2,工位1_DE3 \n");
out << outResultText << "\n";
file.close();
}
else
{
qDebug() << "____________________________" << __LINE__ << " csv !open ";
}
}
else
{
//创建文件1
QFile file(savePath_csv + ".csv");
if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
{
QTextStream out(&file);
out.setCodec(QTextCodec::codecForName("utf-8"));
out << outResultText << "\n";
file.close();
}
else
{
qDebug() << "____________________________" << __LINE__ << " csv !open ";
}
}
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;*/
//resultOKNG = 1;
data = QByteArray::number(resultOKNG) + "*" + QByteArray::number(resultData[0]) + "," + QByteArray::number(resultData[1]) + "," + QByteArray::number(resultData[2]) + "," + QByteArray::number(resultData[3])
+ "," + QByteArray::number(resultData[4]) + "," + QByteArray::number(resultData[5]);
//data = "1*1.1,2.2";
resByte.clear();
return true;
}
//从类中读数据到实例对象
bool Hd_AI_3D_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_3D_module::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &data)
{
QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd");
//图片保存文件夹
QByteArray allDir = initValueList.last().split('#')[1];
isDirExist(allDir + "/" + sdataTime);
QString name = "原图";
saveDir_sorce = allDir + "/" + sdataTime + "/" + name;
isDirExist(saveDir_sorce); //不存在,创建
//name = "seg图";
//saveDir_seg = allDir + "/" + sdataTime + "/" + name;
//isDirExist(saveDir_seg); //不存在,创建
//name = "cls图";
//saveDir_cls = allDir + "/" + sdataTime + "/" + name;
//isDirExist(saveDir_cls); //不存在,创建
name = "结果图";
saveDir_result = allDir + "/" + sdataTime + "/" + name;
isDirExist(saveDir_result); //不存在,创建
name = "csv数据表";
saveDir_csv = allDir + "/" + sdataTime + "/" + name;
isDirExist(saveDir_csv); //不存在,创建
savePath_csv = saveDir_csv + "/" + sdataTime;
qDebug() << __FUNCTION__ << "line:" << __LINE__ << " data:" << data;
if (vec_mat.empty())
{
qCritical() << "[Error] " << " vec_mat is null !";
return false;
}
detect_mutex->lock();
HikMat.clear();
for (int i = 0; i < vec_mat.size(); i++)
HikMat.enqueue(vec_mat[i]);
//QByteArray source_savePath;
sData = byteArrayToUnicode(data);
splitDataList = sData.split(',');
SN = splitDataList[3];
qDebug() << __FUNCTION__ << "line:" << __LINE__ << "QingXH3D1 SN:" << SN;
if (splitDataList.size() >= 4)
{
//if (splitDataList[2].contains('_'))
// cameraKey_index = splitDataList[2];
//QByteArray saveDir = splitDataList[0] + "/" + splitDataList[1] + "/";
//isDirExist(byteArrayToUnicode(saveDir)); //不存在,创建
QString sdataTime_msz = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
sdataTime_name = sdataTime_msz;
//QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd");
QString sdataTime_h = QDateTime::currentDateTime().toString("hh");
savePath_sorce = saveDir_sorce + "/" + splitDataList[1];
//savePath_seg = saveDir_seg + "/" + splitDataList[1];
//savePath_cls = saveDir_cls + "/" + splitDataList[1];
savePath_result = saveDir_result + "/" + splitDataList[1];
//if (!checkedNameList.contains(splitDataList[1]))
//{
// isDirExist(saveDir_sorce + "/" + splitDataList[1]);
// isDirExist(saveDir_seg + "/" + splitDataList[1]);
// isDirExist(saveDir_cls + "/" + splitDataList[1]);
// isDirExist(saveDir_result + "/" + splitDataList[1]);
// checkedNameList.append(splitDataList[1]);
//}
isDirExist(savePath_sorce);
//isDirExist(savePath_seg);
//isDirExist(savePath_cls);
isDirExist(savePath_result);
savePath_sorce = saveDir_sorce + "/" + splitDataList[1] + "/" + sdataTime_h + "H";
//savePath_seg = saveDir_seg + "/" + splitDataList[1] + "/" + sdataTime + "/" + sdataTime_h + "H";
//savePath_cls = saveDir_cls + "/" + splitDataList[1] + "/" + sdataTime + "/" + sdataTime_h + "H";
savePath_result = saveDir_result + "/" + splitDataList[1] + "/" + sdataTime_h + "H";
isDirExist(savePath_sorce);
//isDirExist(savePath_seg);
//isDirExist(savePath_cls);
isDirExist(savePath_result);
//savePath_sorce = saveDir_sorce + "/" + splitDataList[1] + "/" + sdataTime + "/" + sdataTime_h + "H" + "/" + SN;
//isDirExist(savePath_sorce);
}
resultOKNG = 1;
resultData[0] = 0;
resultData[1] = 0;
if (!savePath_sorce.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);'
for (int i = 0; i < initValueList.size(); i++)
{
QString minit = byteArrayToUnicode(initValueList[i]);
if (initValueList[i].contains(data.split(',')[2].split('_')[0]))
if (HikMat.size() == 2)//3D
{
addImgToSaveStruct(HikMat[0], "0", savePath_sorce + "/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".tiff");
addImgToSaveStruct(HikMat[1], "0", savePath_sorce + "/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".bmp");
}
else
addImgToSaveStruct(HikMat[0], "0", savePath_sorce + "/" + SN + "_" + splitDataList[2] + "_" + sdataTime_name + ".bmp");//保存原图
}
}
moduleData = data;
qstring_data = byteArrayToUnicode(data);
detect_mutex->unlock();
//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_3D_module::initParas(QByteArray& byte)
{
myEngine.SetProcedurePath("./halconFilesAlgo/AlgoLibrary_628_1.hdpl"); //设置hdvp路径
initValueList = byte.split('+');
QStringList valueiList;
if (byte.contains("onlySetParameter"))
{
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,valueList[0]:" << initValueList[0];
if (initValueList.size() > 1)
for (int i = 1; i < initValueList.size(); i++)
{
QString valuei = byteArrayToUnicode(initValueList[i]);
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "onlySetParameter,lastName:" << initValueList[0] << " ,valuei:" << valuei;
}
return true;
}
/*if (initValueList.size() > 1)
for (int i = 1; i < initValueList.size(); i++)
{
QString valuei = byteArrayToUnicode(initValueList[i]);
valueiList.append(valuei);
}*/
QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd");
//图片保存文件夹
QByteArray allDir = initValueList.last().split('#')[1];
isDirExist(allDir + "/" + sdataTime);
QString name = "原图";
saveDir_sorce = allDir + "/" + sdataTime + "/" + name;
isDirExist(saveDir_sorce); //不存在,创建
//name = "seg图";
//saveDir_seg = allDir + "/" + sdataTime + "/" + name;
//isDirExist(saveDir_seg); //不存在,创建
//name = "cls图";
//saveDir_cls = allDir + "/" + sdataTime + "/" + name;
//isDirExist(saveDir_cls); //不存在,创建
name = "结果图";
saveDir_result = allDir + "/" + sdataTime + "/" + name;
isDirExist(saveDir_result); //不存在,创建
name = "csv数据表";
saveDir_csv = allDir + "/" + sdataTime + "/" + name;
isDirExist(saveDir_csv); //不存在,创建
savePath_csv = saveDir_csv + "/" + sdataTime;
//StationNo = vec_ret.at(0).toInt();
//InitModels();
//InitThreads(StationNo, img2D);
//InitModels(StationNo, img2D);
//运行检测线程
ifdetectThread = true;
//线程检测:结果类完成时,使用
//ifThreadRunDetect = true;
//QFuture<void> future1 = QtConcurrent::run(this, &Hd_AI_3D_module::detectThread);
//运行存图线程
QFuture<void> future2 = QtConcurrent::run(this, &Hd_AI_3D_module::saveImgThread);
//detectThread();
//原图总文件夹
isDirExist(oriImgSaveDir);
//原图class总文件夹
isDirExist(classImgSaveDir);
//结果图总文件夹
isDirExist(resImgSaveDir);
//qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ;
return true;
}
bool Hd_AI_3D_module::InitModels() {
int flag = 0;
//seg_aokeng = CreateSegObjS((char*)modelPath_seg_aokeng.c_str(), 1, 0); if (seg_aokeng->getStatus() != SegStatus::Seg_Success)flag++;
//seg_zhenyan = CreateSegObjS((char*)modelPath_seg_zhenyan.c_str(), 1, 0); if (seg_zhenyan->getStatus() != SegStatus::Seg_Success)flag++;
//seg_pianhan = CreateSegObjS((char*)modelPath_seg_pianhan.c_str(), 1, 0); if (seg_pianhan->getStatus() != SegStatus::Seg_Success)flag++;
//seg_rongding = CreateSegObjS((char*)modelPath_seg_rongding.c_str(), 1, 0); if (seg_rongding->getStatus() != SegStatus::Seg_Success)flag++;
//det_hanhou = CreateDetObjS((char*)modelPath_det_hanhou.c_str(), 1, 0); if (det_hanhou->getStatus() != DetStatus::Det_Success)flag++;
// det_neiquan = CreateDetObjS((char*)modelPath_det_neiquan.c_str(), 1, 0); if (det_neiquan->getStatus() != DetStatus::Det_Success)flag++;
//cls_hanhou = CreateClsObjV3((char*)modelPath_cls_hanhou.c_str(), 0, 1); if (cls_hanhou->getStatus() != ClsStatus::Cls_Success)flag++;
return (flag == 0);
}
// 解码
bool Hd_AI_3D_module::decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret)
{
if(byte.isEmpty())
{
qCritical() << "[Error] " << " byte is null!";
return false;
}
/*******************************************/
byte.remove(0,8);
QByteArray mm_data = byte.mid(0,4);
memcpy((void*)&paramNum,(void*)mm_data.data(), 4);
qDebug() << "[INFO] " << " paramNum:" << paramNum;
byte.remove(0,4);
/*******************************************/
while (!byte.isEmpty())
{
int type = 0;
QByteArray m_type = byte.mid(0,4);
memcpy((void*)&type,(void*)m_type.data(), 4);
byte.remove(0,4);
int len = 0;
QByteArray m_len = byte.mid(0,4);
memcpy((void*)&len,(void*)m_len.data(), 4);
byte.remove(0,4);
QByteArray mm_data = byte.mid(0,len);
vec_ret.append(mm_data);
byte.remove(0,len);
}
return true;
}
//---------检测流程,根据实际项目修改---------
bool Hd_AI_3D_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_3D_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.toLocal8Bit().toStdString();
mySave.savePath = savePath.toLocal8Bit().toStdString();
saveStruct.enqueue(mySave);
saveStruct_mutex->unlock();
}
void Hd_AI_3D_module::saveImgThread()
{
while (1)
{
if (!ifdetectThread)return;
_sleep(5);
qApp->processEvents();
if (saveStruct.size() < 1)continue;
for (int i = 0; i < saveStruct.size(); i++)
{
clock_t start, stop;
start = clock();
saveStruct_mutex->lock();
saveImgStruct mysaveStruct = saveStruct.dequeue();
saveStruct_mutex->unlock();
stop = clock();
if(stop-start >1000)
std::cout << "lock stop-start >1000::************************" << stop - start << std::endl;
start = clock();
if (mysaveStruct.out_Mat.data)
imwrite(mysaveStruct.savePath, mysaveStruct.out_Mat);
//std::cout << "savePath::" << mysaveStruct.savePath << std::endl;
stop = clock();
if (stop - start > 1000)
std::cout << "imwrite stop-start >1000::--------------------------"<< stop - start << std::endl;
_sleep(1);
}
}
}
//检测线程,应当只运行一次
void Hd_AI_3D_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_3D_module::run()
{
try
{
qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << SN << "_run start";
clock_t start, stop, start1, stop1, start2, stop2;
start = clock();
//if (HikMat.isEmpty())
//{
// cv::Mat null_mat = cv::Mat::zeros(cv::Size(100, 100), CV_8UC3);
// resMat.push_back(null_mat);
// qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << SN << "_HikMat.isEmpty";
// return true;
//}
//
//if (HikMat[0].rows == 100 || HikMat[0].cols == 100 || HikMat[1].rows == 100 || HikMat[1].cols == 100)
//{
// cv::Mat null_mat = cv::Mat::zeros(cv::Size(100, 100), CV_8UC3);
// resMat.push_back(null_mat);
// resultData[0] = 1.1;
// resultData[1] = 2.2;
// resultData[2] = 3.3;
// resultData[3] = 4.4;
// resultData[4] = 5.5;
// resultData[5] = 6.6;
// qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << SN << "_HikMat is 100 * 100";
// return true;
//}
cv::Mat HeightImage;
cv::Mat LightImage;
cv::Mat resultImg;
cv::Mat img_dst;
cv::Mat srcImg;
cv::Mat tmpMatL = cv::imread("D://04QCB30601000JF4K0000041_camera3D4_0_2025-04-19-15-30-07-703.bmp", -1), tmpMatH=cv::imread("D://04QCB30601000JF4K0000041_camera3D4_0_2025-04-19-15-30-07-703.tiff",-1);
if (tmpMatL.channels() == 3)
cv::cvtColor(tmpMatL, srcImg, COLOR_BGR2GRAY);
else
srcImg = tmpMatL.clone();
if (tmpMatH.channels() == 3)
cv::cvtColor(tmpMatH, HeightImage, COLOR_BGR2GRAY);
else
HeightImage = tmpMatH.clone();
srcImg.copyTo(LightImage);
srcImg.copyTo(img_dst);
cv::cvtColor(img_dst, img_dst, COLOR_GRAY2BGR);
//#if 0
HalconCpp::HObject in_imageH = MatToHObject(HeightImage);
HalconCpp::HObject in_imageLum = MatToHObject(LightImage);
HalconCpp::HTuple out_Flag;//, 算法的执行结果, 0: 算法执行异常 1 : 算法执行成功
HTuple in_xResolution = 0.0025;
HTuple in_yResolution = 0.05;
HTuple in_zResolution = 0.0004;
HTuple out_MaxHeight; //最大高度
HTuple out_MaxWidth; //最大缝隙
HTuple out_ResultColumn; //X坐标
HTuple out_ResultRow; //Y坐标
HObject out_DisplayImage;
HTuple in_Location;
if (splitDataList[1].contains("清洗3D1") || splitDataList[1].contains("清洗3D2"))
in_Location = "Left";
else
in_Location = "Right";
HDevEngineCpp::HDevProcedure proc("detect_gap_width_height_6_1");
HDevProcedureCall procedureCall(proc);
procedureCall.SetInputIconicParamObject("in_imageH", in_imageH);//传给算法图片
procedureCall.SetInputIconicParamObject("in_imageLum", in_imageLum);//传给算法图片
procedureCall.SetInputCtrlParamTuple("in_xResolution", in_xResolution);//传给算法参数
procedureCall.SetInputCtrlParamTuple("in_yResolution", in_yResolution);//传给算法参数
procedureCall.SetInputCtrlParamTuple("in_zResolution", in_zResolution);//传给算法参数
procedureCall.SetInputCtrlParamTuple("in_Location", in_Location);//传给算法参数
procedureCall.Execute();//执行halcon程序
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量
//高度+-0.3 宽度0.06
if (out_Flag.Length() > 0)
{
qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "_out_Flag" << out_Flag.I();
if (out_Flag.I() == 1) //算法检测成功
{
out_MaxHeight = procedureCall.GetOutputCtrlParamTuple("out_MaxHeight");//获取输出控制类变量
out_MaxWidth = procedureCall.GetOutputCtrlParamTuple("out_MaxWidth");//获取输出控制类变量
out_ResultRow = procedureCall.GetOutputCtrlParamTuple("out_ResultRow");//获取输出控制类变量
out_ResultColumn = procedureCall.GetOutputCtrlParamTuple("out_ResultColumn");//获取输出控制类变量
out_DisplayImage = procedureCall.GetOutputIconicParamObject("out_DisplayImage");//获取输出控制类变量
cv::Mat outputImage = HObject2Mat(out_DisplayImage);
if (outputImage.channels() != 3)
cv::cvtColor(outputImage, outputImage, COLOR_GRAY2BGR);
outputImage.copyTo(resultImg);
qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "_YuHanQian3D_out_MaxHeight" << out_MaxHeight.D() << "_YuHanQian3D_out_MaxWidth" << out_MaxWidth.D();
if (out_MaxHeight.Length() > 0 && out_MaxWidth.Length() > 0)
{
resultData[0] = out_MaxWidth[0].D();
resultData[1] = out_MaxHeight.D();
resultData[2] = out_MaxWidth[1].D();
resultData[3] = out_MaxWidth[1].D();
resultData[4] = out_MaxHeight.D();
resultData[5] = out_MaxHeight.D();
resultOKNG = 1;//初始化为OK
if (out_MaxHeight.D() >= 0.8 || out_MaxHeight.D() <= -0.8){//NG
//resultOKNG = 2;
QString text = "最大高度:" + QString::number(out_MaxHeight.D());
QByteArray path_arr = text.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(resultImg, path, cv::Point(50, 550), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false);
}
else{
QString UP_Down = "最大高度:" + QString::number(out_MaxHeight.D());
QByteArray path_arr = UP_Down.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(resultImg, path, cv::Point(50, 550), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false);
}
if (out_MaxWidth.D() > 0.3) {//NG
QString text = "最大宽度:" + QString::number(out_MaxWidth.D());
QByteArray path_arr = text.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(resultImg, path, cv::Point(50, 950), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false);
}
else
{//OK
QString text = "最大宽度:" + QString::number(out_MaxWidth.D());
QByteArray path_arr = text.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(resultImg, path, cv::Point(50, 950), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false);
}
if (out_MaxWidth[1].D() > 0.3) {//NG
resultOKNG = 2;
QString text = "两端最大宽度:" + QString::number(out_MaxWidth[1].D());
QByteArray path_arr = text.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(resultImg, path, cv::Point(50, 1350), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false);
}
else
{//OK
QString text = "两端最大宽度:" + QString::number(out_MaxWidth[1].D());
QByteArray path_arr = text.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(resultImg, path, cv::Point(50, 1350), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false);
}
/*double extraWidthData = out_MaxWidth[1].D();
{
QString text = "两端最大宽度:" + QString::number(extraWidthData);
QByteArray path_arr = text.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(resultImg, path, cv::Point(50, 1350), cv::Scalar(0, 255, 0), 250, "微软雅黑", false, false);
}*/
}
}
else
{
resultData[0] = 1.1;
resultData[1] = 2.2;
resultData[2] = 3.3;
resultData[3] = 4.4;
resultData[4] = 5.5;
resultData[5] = 6.6;
QString UP_Down = "压装异常或间隙不良";
QByteArray path_arr = UP_Down.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(img_dst, path, cv::Point(50, 200), cv::Scalar(0, 255, 0), 150, "微软雅黑", false, false);
qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "YuHanQian3D Algo Error NG" << out_Flag.I();
resultOKNG = 2;
}
}
//#endif
if (resultImg.cols > 0 && resultImg.rows > 0)
{
if (resultOKNG == 1)
{
putTextZH(resultImg, "OK", cv::Point(50, 0), cv::Scalar(0, 255, 0), 150, "微软雅黑", false, false);
}
else
{
putTextZH(resultImg, "NG", cv::Point(50, 0), cv::Scalar(0, 0, 255), 150, "微软雅黑", false, false);
}
resMat.push_back(resultImg);
}
else
{
if (resultOKNG == 1)
{
putTextZH(img_dst, "OK", cv::Point(50, 0), cv::Scalar(0, 255, 0), 200, "微软雅黑", false, false);
}
else
{
putTextZH(img_dst, "NG", cv::Point(50, 0), cv::Scalar(0, 0, 255), 200, "微软雅黑", false, false);
}
resMat.push_back(img_dst);
}
stop = clock();
qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "RunTime::" << stop - start;
}
catch (HDevEngineCpp::HDevEngineException& ex) {
std::cerr << "HDevEngineException: " << ex.Message() << std::endl;
}
catch (HException& ex) {
// 捕获Halcon异常
std::cerr << "Halcon Exception Caught!" << std::endl;
std::cerr << "Error Code: " << ex.ErrorCode() << std::endl;
std::cerr << "Error Message: " << ex.ErrorMessage() << std::endl;
}
catch (std::exception& ex) {
// 捕获其他标准异常
std::cerr << "Standard Exception Caught: " << ex.what() << std::endl;
}
catch (...)
{
qDebug() << __FUNCTION__ << "line:" << __LINE__ << SN << "_YuHanQian3D _error";
return true;
}
return true;
}
bool Hd_AI_3D_module::checkStatus()
{
status = moduleStatus;
return status;
}