Files
ds-628/BaseModules/algoModules/Hd_ShangDing_module/Hd_ShangDing_module.cpp
T
2025-07-29 11:59:42 +08:00

1216 lines
45 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_ShangDing_module.h"
#include <QDateTime>
#include <global.h>
#include <QtConcurrent/QtConcurrent>
#include <qfuture.h>
#include "nlohmannJson.hpp"
#include "generalJsonParsing.hpp"
#include <filesystem>
////逻辑UI头文件
//
//#include "CPPTaskLoader/pbloadtask.h"
//
//#include "io.h"
//#include <direct.h>
//#include <stdio.h>
//#include <iterator>
//#include <regex>
//628算法
#include <handleAI.h>
#pragma execution_character_set("utf-8")
using namespace cv;
using namespace std;
using namespace handdleAI;
//using namespace HalconCpp;
//总保存文件夹
QString AllImgSaveDir = "D:/CCD/";
//切图的class的width,根据项目实际设置!
static int sizeW = 150;
//切图的class的height,根据项目实际设置!
static int sizeH = 150;
//切图的class的width,根据项目实际设置!0为黑,255为白;
static int fillColour = 0;
pDetection* det_DJY;
pClassification* cls_DJY;
std::string modelPath_det_DJY = "../bin/model/det_DJY.BHD";
std::string modelPath_cls_DJY = "../bin/model/cls_DJY.BHD";
//检测线程锁
QMutex* detect_mutex;
//保存线程锁
QMutex* saveStruct_mutex;
//检测线程运行标志
bool ifdetectThread = false;
//检测标志
QString qstring_data;
QString cameraKey_index = "";
QString sData;
QStringList splitDataList;
//初始化参数列表
QByteArrayList initValueList;
QString sdataTime; //产品名里的时间戳
QString okngText = "OK";
QString shortData_result = "1";
QString floatData_offsetX = "-1.1", floatData_offsetY = "-1.1";
// 缺陷信息结构体
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;
static void createDirectoryIfNotExists(const QString& path) {
QDir dir;
dir.mkpath(path);
}
static std::string getCurrentTime() {
// 获取当前时间点
auto now = std::chrono::system_clock::now();
// 转换为字符串
auto currentTime = std::chrono::system_clock::to_time_t(now);
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 100;
std::tm* localTime = std::localtime(&currentTime);
std::stringstream ss;
ss << std::put_time(localTime, "%H-%M-%S") << "-" << std::setfill('0') << std::setw(2) << ms.count();
return ss.str();
}
static QString getCurrentDate()
{
QDateTime currentDateTime = QDateTime::currentDateTime();
return currentDateTime.toString("yyyy-MM-dd");
}
static QString getCurrentHour()
{
QDateTime currentDateTime = QDateTime::currentDateTime();
return QString::number(currentDateTime.time().hour()) + "H";
}
std::pair<QString, QString> getResSaveFormat(QString SN, QString okNgText = "", int count = 0)
{
QString path = AllImgSaveDir + "//" + getCurrentDate() + "//结果图//" + splitDataList[1].split("_")[0] + "//" + getCurrentHour() + "//" + okNgText + "//";
return { path,path + SN + "_" + cameraKey_index + "_" + sdataTime + ".jpg" };
//QString path = resImgSaveDir + getCurrentDate() + "//结果图//" + getCurrentHour() + "//" + okNgText + "//" + SN + "//";
//return { path,path + SN + "_" + cameraKey_index + "_" + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz") + "_" + okNgText + ".jpg" };
}
std::pair<QString, QString> getOriSaveFormat(QString SN, QString okNgText = "", int count = 0)
{
QString path = AllImgSaveDir + "//" + getCurrentDate() + "//原图//" + splitDataList[1].split("_")[0] + "//" + getCurrentHour() + "//";
return{ path, path + SN + "_" + cameraKey_index + "_" + okNgText + "_" + sdataTime + ".bmp" };
//QString path = oriImgSaveDir + getCurrentDate() + "//原图//" + getCurrentHour() + "//" + okNgText + "//" + SN + "//";
//return{ path, path + SN + "_" + cameraKey_index + "_" + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz") + ".bmp" };
}
std::pair<QString, QString> getSegSaveFormat(QString SN, QString okNgText = "", int count = 0)
{
QString path = AllImgSaveDir + "//" + getCurrentDate() + "//seg图//" + splitDataList[1].split("_")[0] + "//" + getCurrentHour() + "//";
return { path,path + SN + "_" + cameraKey_index + "_" + okNgText + "_" + sdataTime + ".bmp" };
//QString path = oriImgSaveDir + getCurrentDate() + "//Seg图//" + getCurrentHour() + "//" + okNgText + "//" + SN + "//";
//return { path,path + SN + "_" + cameraKey_index + "_" + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz") + ".bmp" };
}
std::pair<QString, QString> getClsSaveFormat(QString SN, QString okNgText = "", int count = 0, int clsResult = 99)
{
QString path = AllImgSaveDir + "//" + getCurrentDate() + "//cls图//" + splitDataList[1].split("_")[0] + "//" + getCurrentHour() + "//";
return{ path, path + SN + "_" + cameraKey_index + "_" + okNgText + "_" + QString::number(clsResult) + "_" + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz") + ".bmp" };
//QString path = oriImgSaveDir + getCurrentDate() + "//Cls图//" + getCurrentHour() + "//" + okNgText + "//" + SN + "//";
//return{ path, path + SN + "_" + cameraKey_index + "_" + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz") + ".bmp" };
}
std::pair<QString, QString> getTiffSaveFormat(QString SN, QString okNgText = "", int count = 0)
{
QString path = AllImgSaveDir + "//" + getCurrentDate() + "//原图//" + splitDataList[1].split("_")[0] + "//" + getCurrentHour() + "//" + okNgText + "//";
return { path,path + SN + "_" + cameraKey_index + "_" + sdataTime + ".tiff" };
//QString path = oriImgSaveDir + getCurrentDate() + "//原图//" + getCurrentHour() + "//" + okNgText + "//" + SN + "//";
//return { path,path + SN + "_" + cameraKey_index + "_" + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz") + ".tiff" };
}
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;
}
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 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));
if (std::string(str).length() == 0)return;
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, "微软雅黑");
}
}
Hd_ShangDing_module* create()
{
qDebug() << "[INFO] " << " Hd_ShangDing_module create success!" ;
return new Hd_ShangDing_module;
}
void destory(Hd_ShangDing_module* ptr)
{
qDebug() << "[INFO] " << "Hd_ShangDing_module destory success!";
if(ptr)
{
delete ptr;
ptr = nullptr;
}
}
Hd_ShangDing_module::Hd_ShangDing_module()
{
detect_mutex = new QMutex;
saveStruct_mutex = new QMutex;
ifdetectThread = false;
}
Hd_ShangDing_module::~Hd_ShangDing_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_ShangDing_module::readData(std::vector<cv::Mat>&vec_mat,QByteArray &data)
{
if (HikMat[0].cols == 200)
return true;
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:";
}
data = logicUiTransport::encodeAllData(SN, {floatData_offsetX,floatData_offsetY,shortData_result }, {});
resByte.clear();
addImgToSaveStruct(HikMat[0], "0", getOriSaveFormat(SN, okngText));//保存原图
//{
// okngText = shortData_result == "1" ? "OK":"NG";
// for (int i = 0; i < initValueList.size(); i++)
// {
// QString minit = byteArrayToUnicode(initValueList[i]);
// if (initValueList[i].contains(moduleData.split(',')[2].split('_')[0]))
// if (initValueList[i].contains(QString("原图_保存").toLocal8Bit()))
// {
// addImgToSaveStruct(HikMat[0], "0", getOriSaveFormat(SN, okngText));//保存原图
// }
// }
// resize(vec_mat[0], vec_mat[0], cv::Size(), 0.5, 0.5);
// for (int i = 0; i < initValueList.size(); i++)
// {
// QString minit = byteArrayToUnicode(initValueList[i]);
// if (initValueList[i].contains(moduleData.split(',')[2].split('_')[0]))
// if (initValueList[i].contains(QString("结果图_保存").toLocal8Bit()))
// {
// addImgToSaveStruct(vec_mat[0], "0", getResSaveFormat(SN, okngText));//保存结果图
// }
// }
//}
detect_mutex->unlock();
return true;
}
//从类中读数据到实例对象
bool Hd_ShangDing_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_ShangDing_module::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &data)
{
qDebug() << __FUNCTION__ << "line:" << __LINE__ << " data:" << data;
if (vec_mat.empty())
{
qCritical() << "[Error] " << " vec_mat is null !";
return false;
}
detect_mutex->lock();
HikMat.clear();
qstring_data = byteArrayToUnicode(data);
for (int i = 0; i < vec_mat.size(); i++)
{
if (vec_mat[i].channels() == 3&& qstring_data.contains("放钉"))
cv::cvtColor(vec_mat[i], vec_mat[i], COLOR_BGR2GRAY);
HikMat.enqueue(vec_mat[i]);
}
//hv_Image.push_back(MatToHObject(HikMat[0]));
//std::cout << "vec_mat.size()" << vec_mat.size() << std::endl;
//QByteArray source_savePath;
sData = byteArrayToUnicode(data);
splitDataList = sData.split(',');
singal_sign = splitDataList[1];
SN = splitDataList[3];
cameraKey_index = splitDataList[2];
sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
moduleData = data;
detect_mutex->unlock();
return true;
}
//初始化
bool Hd_ShangDing_module::initParas(QByteArray& byte)
{
initValueList = byte.split('+');
QStringList valueiList;
for (int i = 0; i < initValueList.size(); i++)
{
QString valuei = byteArrayToUnicode(initValueList[i]);
if (valuei.contains("hv_model") && valuei.contains("#"))
{
m_hv_model = valuei.split("#")[1].toInt();
{
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "m_hv_model::" << m_hv_model;
}
}
}
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;
}
////运行检测线程
ifdetectThread = true;
////线程检测:结果类完成时,使用
////ifThreadRunDetect = true;
////QFuture<void> future1 = QtConcurrent::run(this, &Hd_ShangDing_module::detectThread);
//运行存图线程
QFuture<void> future2 = QtConcurrent::run(this, &Hd_ShangDing_module::saveImgThread);
//cv::Mat initimg = cv::imread("../bin/initimg.bmp");
//if (initimg.channels() == 3)
// cv::cvtColor(initimg, initimg, COLOR_BGR2GRAY);
myEngine.SetProcedurePath("./halconFilesAlgo/AlgoLibrary_602.hdpl"); //设置hdvp路径
//MatToHObject(initimg);
//InitModels();
//qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ;
return true;
}
bool Hd_ShangDing_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_DJY = CreateDetObjS((char*)modelPath_det_DJY.c_str(), 1, 0); if (det_DJY->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_DJY = CreateClsObjV3((char*)modelPath_cls_DJY.c_str(), 0, 1); if (cls_DJY->getStatus() != ClsStatus::Cls_Success)flag++;
return (flag == 0);
}
// 解码
bool Hd_ShangDing_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_ShangDing_module::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime)
{
/*try
{*/
//存图数据加保存队列,加锁,避免数据访问冲突
saveStruct_mutex->lock();
saveImgStruct mySave;
Mat sourceImg, sourceImg1, sourceImg2;
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;
detect_mutex->lock();
//结果图画框和缺陷,在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();
/* isDirExist(resImgSaveDir + mysaveKey1 + "/");
QString qimgsavePath = resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".jpg";*/
//存图数据入队,按需
/*if (resMat.size() > 0 )
addImgToSaveStruct(resMat[0], mysaveKey1, resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".jpg");*/
detect_mutex->unlock();
obj.insert("detaillists", detaillists);
//obj.insert("qimgsavePath", qimgsavePath);
document.setObject(obj);
QByteArray qa = document.toJson();
mySave.out_Mat.resize(0);
mysaveKey1.clear();
qApp->processEvents();
/* }
catch (...)
{
qDebug() << "[Error] " << QString::fromUtf8("检测失败!");
hv_Image.clear();
number = 0;
return false;
}*/
return true;
}
//存图加入队列
void Hd_ShangDing_module::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, std::pair<QString, 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.second.toLocal8Bit().toStdString();
mySave.createDirPath = savePath.first;
saveStruct.enqueue(mySave);
saveStruct_mutex->unlock();
}
void Hd_ShangDing_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();
createDirectoryIfNotExists(mysaveStruct.createDirPath);
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_ShangDing_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_ShangDing_module::run()
{
try
{
shortData_result = "0";
floatData_offsetX = "0";
floatData_offsetY = "0";
if (HikMat[0].cols == 200) {
std::cout << "skip";
return true;
}
defectNums = 0;
cv::Mat resImg1, resImg2;
//cv::Mat mat;
float prob = 0;
if (HikMat.isEmpty())
{
shortData_result = "2";
cv::Mat null_mat = cv::Mat::zeros(cv::Size(100, 100), CV_8UC3);
resMat.push_back(null_mat);
return true;
}
if (HikMat.isEmpty() || HikMat[0].rows < 200 || HikMat[0].cols < 200)
{
shortData_result = "2";
cv::Mat null_mat = cv::Mat::zeros(cv::Size(100, 100), CV_8UC3);
resMat.push_back(null_mat);
return true;
}
//if (splitDataList[1].contains("20400_2") || splitDataList[1].contains("20600_2") ||
// splitDataList[1].contains("20800_2") || splitDataList[1].contains("21000_2"))
//{
// cv::Mat srcImg;
// if (HikMat[0].channels() == 3)// && (qstring_data.contains("jizu") || qstring_data.contains("fangbaofa")))
// cv::cvtColor(HikMat[0], srcImg, COLOR_BGR2GRAY);
// else
// srcImg = HikMat[0];
// cv::Mat img_dst;
// cvtColor(HikMat[0], img_dst, cv::COLOR_GRAY2BGR);
// resMat.push_back(img_dst);
// //qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera::放钉" << "_SN::" << SN << splitDataList[1].split("_")[0] << "_" << stop - start << "ms";
// //return true;
//}
//if (splitDataList[1].contains("放钉"))
{
cv::Mat srcImg;
if (HikMat[0].channels() == 3)// && (qstring_data.contains("jizu") || qstring_data.contains("fangbaofa")))
cv::cvtColor(HikMat[0], srcImg, COLOR_BGR2GRAY);
else
srcImg = HikMat[0];
cv::Mat img_dst;
cvtColor(HikMat[0], img_dst, cv::COLOR_GRAY2BGR);
/* HalconCpp::HTuple hv_BenchmarkFile;
hv_BenchmarkFile.Append("C:\\Hd_Mifengding-1\\env\\628\\FD\\");
HalconCpp::HTuple hv_NinePointDocument;
if (qstring_data.contains("放钉1"))
hv_NinePointDocument.Append("C:\\Hd_Mifengding-1\\env\\628\\FD\\jiudian1.tup");
if (qstring_data.contains("放钉2"))
hv_NinePointDocument.Append("C:\\Hd_Mifengding-1\\env\\628\\FD\\jiudian2.tup");
if (qstring_data.contains("放钉3"))
hv_NinePointDocument.Append("C:\\Hd_Mifengding-1\\env\\628\\FD\\jiudian3.tup");
if (qstring_data.contains("放钉4"))
hv_NinePointDocument.Append("C:\\Hd_Mifengding-1\\env\\628\\FD\\jiudian4.tup");
HalconCpp::HTuple hv_CameraNumber;
if (qstring_data.contains("放钉1"))
hv_CameraNumber.Append(1);
if (qstring_data.contains("放钉2"))
hv_CameraNumber.Append(2);
if (qstring_data.contains("放钉3"))
hv_CameraNumber.Append(3);
if (qstring_data.contains("放钉4"))
hv_CameraNumber.Append(4);*/
//HalconCpp::HTuple hv_model = 1;
//int BiaoDingFlag = 2;
//int YiWuFlag = 2;
//hv_model.Append(m_hv_model); //后续开放参数窗口
//try {
// auto jsonConfig = readJsonFromPath("./config/editableConfig.json");
// BiaoDingFlag = jsonConfig["上钉标定"];
// YiWuFlag = jsonConfig["上钉异物检测"];
// if (BiaoDingFlag != 1)
// {
// hv_model = 0;
// }
// else
// {
// hv_model = 1;
// }
//}
//catch (...) {
// qDebug() << __FUNCTION__ << " line:" << __LINE__ << "getJsonError";
//}
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "放钉标定::" << BiaoDingFlag;
////hv_model = 1;
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "放钉标定::" << hv_model.I();
HalconCpp::HObject in_Image = MatToHObject(HikMat[0]);
//<c>* Function Name : _9_shangding < / c>
// <c>* Author : < / c>
// <c>*Description : < / c>
// <c>< / c>
// <c>*Input(HObject) : in_Image, 图像(bmp), < / c>
// <c> < / c>
// <c>*output(HObject) : < / c>
// <c>*Input(HTuple) : in_ProductionType, 生产
// 类别 : 0, 生产模式: 1, 标定模式 < / c>
// <c>* in_CameraNumber, 相机序列号 < / c>
// <c>* in_FilePath1, 模板文件路径; 示例:'./模板文件/' < / c >
// <c>*in_FilePath2, 基准文件路径; < / c>
std::string cameraNumberStr = "1";
if (singal_sign.contains("D19000"))
cameraNumberStr = "2";
else if(singal_sign.contains("D19200"))
cameraNumberStr = "3";
else if (singal_sign.contains("D19400"))
cameraNumberStr = "4";
HDevEngineCpp::HDevProcedure proc("_9_shangding");
HDevProcedureCall procedureCall(proc);
procedureCall.SetInputIconicParamObject("in_Image", in_Image);
procedureCall.SetInputCtrlParamTuple("in_ProductionType", 0);
procedureCall.SetInputCtrlParamTuple("in_CameraNumber", HTuple(cameraNumberStr.c_str()));
procedureCall.SetInputCtrlParamTuple("in_FilePath1", HTuple("./halconFiles/template/"));
procedureCall.SetInputCtrlParamTuple("in_FilePath2", HTuple("./halconFiles/base/"));
procedureCall.Execute();
// <c>*output(HTuple) : < / c>
// <c>*out_Circle, 圆心坐标(y, x, radius) < / c >
// <c>* out_Flag, 算法执行成功标志位, 0 : 算法执行失败 1 : 算法执行成功< / c>
// <c>*out_OffsetX : 模组X轴的补偿量(mm) < / c >
// <c>*out_OffsetY : 模组Y轴的补偿量(mm) < / c >
HTuple out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");
HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");
HTuple out_OffsetX = procedureCall.GetOutputCtrlParamTuple("out_OffsetX");
HTuple out_OffsetY = procedureCall.GetOutputCtrlParamTuple("out_OffsetY");
int outFlag = out_Flag.D();
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera::放钉" << "_SN::" << SN << ",放钉算法结果;" << out_Flag[0].D();
if (outFlag == 1){ //-1为失败,无结果
//圆及十字
cv::circle(img_dst, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 20);
cv::line(img_dst, cv::Point(out_Circle[1].D() - 300, out_Circle[0].D()), cv::Point(out_Circle[1].D() + 300, out_Circle[0].D()), cv::Scalar(0, 255, 0), 15);
cv::line(img_dst, cv::Point(out_Circle[1].D(), out_Circle[0].D() - 300), cv::Point(out_Circle[1].D(), out_Circle[0].D() + 300), cv::Scalar(0, 255, 0), 15);
double offsetX;
double offsetY;
//if (cameraKey_index.contains("DA4940802") || cameraKey_index.contains("DA4940782")) {//B Part Camera
// offsetX = out_OffsetX.D();
// offsetY = out_OffsetY.D();
//}
//else {
// offsetX = 0 - out_OffsetX.D();
// offsetY = 0 - out_OffsetY.D();
//}
offsetX = 0 - out_OffsetX.D();
offsetY = 0 - out_OffsetY.D();
QString UP_Down = "X偏移:" + QString::number(offsetX);
QByteArray path_arr = UP_Down.toLocal8Bit();
const char* path = path_arr.data();
putTextZH(img_dst, path, cv::Point(50, 150), cv::Scalar(0, 255, 0), 150, "微软雅黑");
UP_Down = "Y偏移:" + QString::number(offsetY);
path_arr = UP_Down.toLocal8Bit();
path = path_arr.data();
putTextZH(img_dst, path, cv::Point(50, 350), cv::Scalar(0, 255, 0), 150, "微软雅黑");
UP_Down = "相机:" + QString::fromStdString(cameraNumberStr);
path_arr = UP_Down.toLocal8Bit();
path = path_arr.data();
putTextZH(img_dst, path, cv::Point(50, 0), cv::Scalar(0, 255, 0), 150, "微软雅黑");
if (abs(offsetX) >= 6000 || abs(offsetY) >= 6000)
{
shortData_result = "2";
floatData_offsetX = "-1.1";
floatData_offsetY = "-1.1";
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " 放钉X偏移abs(resultData[0]) >= 6000,may err,set 0";
}
else {
shortData_result = "1";
floatData_offsetX = QString::number(offsetX);
floatData_offsetY = QString::number(offsetY);
}
addImgToSaveStruct(img_dst, "0", getResSaveFormat(SN, okngText));//保存结果图
}
else
{
//resultOKNG = 2;
//resultData[0] = 0;
//resultData[1] = 0;
//QString s;
//if (hv_Make[0].D() == -1)
//{
// s = "算法异常";
//}
//else if (hv_model == 1)
//{
// s = "基准标定";
// cv::circle(img_dst, cv::Point(hv_out_circle[1].D(), hv_out_circle[0].D()), hv_out_circle[2].D(), cv::Scalar(0, 0, 255), 20);
// cv::line(img_dst, cv::Point(hv_out_circle[1].D() - 300, hv_out_circle[0].D()), cv::Point(hv_out_circle[1].D() + 300, hv_out_circle[0].D()), cv::Scalar(0, 0, 255), 15);
// cv::line(img_dst, cv::Point(hv_out_circle[1].D(), hv_out_circle[0].D() - 300), cv::Point(hv_out_circle[1].D(), hv_out_circle[0].D() + 300), cv::Scalar(0, 0, 255), 15);
//}
shortData_result = "2";
floatData_offsetX = "-1.1";
floatData_offsetY = "-1.1";
putTextZH(img_dst, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255), 150, "微软雅黑");
}
if (shortData_result == "1")
{
putTextZH(img_dst, "OK", cv::Point(50, 550), cv::Scalar(0, 255, 0), 150, "微软雅黑");
}
else
{
putTextZH(img_dst, "NG", cv::Point(50, 500), cv::Scalar(0, 0, 255), 150, "微软雅黑");
}
resMat.push_back(img_dst);
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera::放钉:" << hv_CameraNumber.D() << "_SN::" << SN << ",放钉算法结果;" << out_Flag.D();
}
runNum++;
//HikMat.clear();
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "Mat_name: run end" << "model uesd time::" << stop - start << "ms";
return true;
}
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__ << cameraKey_index <<"Mat_error: run end";
}
shortData_result = "2";
cv::Mat null_mat = cv::Mat::zeros(cv::Size(100, 100), CV_8UC3);
resMat.push_back(null_mat);
return true;
}
bool Hd_ShangDing_module::checkStatus()
{
status = moduleStatus;
return status;
}