This commit is contained in:
2025-10-20 09:33:57 +08:00
parent 75136618f7
commit 1708f0b55e
5 changed files with 322 additions and 319 deletions
+4 -2
View File
@@ -12,6 +12,7 @@
#include <qpixmap.h>
#include <opencv.hpp>
#include <qvariant.h>
enum initStatus{
NotInit,
InitFailure,
@@ -28,7 +29,7 @@ struct showImgPack{
};
enum valueType {
finsInt,
finsShort,
finsFloat
};
@@ -37,6 +38,7 @@ struct PlcValueViewerStruct {
QString valueName;
int valueAddr;
valueType type;
QVariant value = -999;
};
class qtFuncBridge : public QObject {
@@ -90,7 +92,7 @@ signals:
//排障
void runCommand_addBtn(const QString& btnName, const QString& tip, const QString& uuid);
void runCommand_addPlcValueViewer(QString groupName, std::vector<std::pair<QString, int>> viewerNameAndAddress);
void runCommand_refeshPlcValueViewer(int address,int value);
void runCommand_refeshPlcValueViewer(int address,QString value);
//性能监测
void sendTriggerManagerLoopData(int loopCounterPerMin,int maxInterval);
+5 -3
View File
@@ -85,6 +85,8 @@ static bool generalAlgoTest(std::shared_ptr <detData> data, detParams* _detParam
TextRendererZH textPainter(Paint.cols, Paint.rows, 15);
textPainter.putText(Paint, "划伤", cv::Point(10,10), cv::Scalar(0, 255, 0));
cv::putText(Paint, "pos:" + data->additional["触发地址"].toString().toStdString(), cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2);
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.123");//发送数据1
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2)+ "_0.456");//发送数据2
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
data->service->_missionResultHandle->handleAllResult(data->SNcode, !defects.size() > 0, defects);//发送图标操作
data->resultImgs.push_back(Paint);
@@ -156,9 +158,9 @@ public:
{ {"触发",address[i].triggerAddr },
{"反馈",address[i].completeAddr.toInt()},
{"结果",address[i].resultAddr.toInt()},
{"数值1",address[i].valueOffsetAddr},
{"数值2",address[i].valueOffsetAddr + 2},
{"数值3",address[i].valueOffsetAddr + 4} });
{"数值1",address[i].valueOffsetAddr,finsFloat},
{"数值2",address[i].valueOffsetAddr + 2,finsFloat},
{"数值3",address[i].valueOffsetAddr + 4,finsFloat} });
}
}
//获取图片并进行检测
+43 -7
View File
@@ -19,6 +19,34 @@ class detThreadManager;
class detDataManager;
class lightSourceManager;
class detProcess;
// 将此静态函数加入到类 triggerManager 的合适位置(如 private 部分)
static float readFinsFloatFromQByteArray(const QByteArray& buf, int startByteIndex, bool highLowConversion) {
if (startByteIndex < 0 || startByteIndex + 3 >= buf.size()) {
return std::numeric_limits<float>::quiet_NaN();
}
auto u8 = [&buf](int i)->uint8_t { return static_cast<uint8_t>(buf.at(i)); };
uint8_t b0 = u8(startByteIndex + 0);
uint8_t b1 = u8(startByteIndex + 1);
uint8_t b2 = u8(startByteIndex + 2);
uint8_t b3 = u8(startByteIndex + 3);
// highLowConversion == true -> 不交换,顺序 b0 b1 b2 b3
// highLowConversion == false -> 每个 16-bit word 内高低位需要互换,得到 b1 b0 b3 b2
if (!highLowConversion) {
std::swap(b0, b1);
std::swap(b2, b3);
}
uint32_t u = (static_cast<uint32_t>(b0) << 24) |
(static_cast<uint32_t>(b1) << 16) |
(static_cast<uint32_t>(b2) << 8) |
(static_cast<uint32_t>(b3));
float f;
std::memcpy(&f, &u, sizeof(f));
return f;
}
//防止重复触发
class triggerLockerT {
public:
@@ -396,7 +424,7 @@ public:
void registerPlcValueViewer(const QString& groupName, const std::vector<PlcValueViewerStruct>& viewerDatas) {
for (auto& data : viewerDatas) {
if (data.valueAddr < 0)continue;
plcValueViewerDatas.push_back({ data.valueAddr, -999 });
plcValueViewerDatas.push_back(data);
}
std::vector<std::pair<QString, int>> forShow;
for (auto& data : viewerDatas) {
@@ -404,19 +432,27 @@ public:
}
emit bridge->runCommand_addPlcValueViewer(groupName, forShow);
}
void checkPlcValueViewer(readAllStruct& _struct, QByteArray& byteArray) {
QMutexLocker locer(&mutex);
for (auto& data : plcValueViewerDatas) {
int checkPos = (data.first - _struct.startPos) * 2 + 1;
if(checkPos< byteArray.size() && checkPos >= 0)
if (byteArray.at(checkPos) != data.second) {
data.second = byteArray.at(checkPos);
emit bridge->runCommand_refeshPlcValueViewer(data.first, data.second);
int checkPos = (data.valueAddr - _struct.startPos) * 2 + 1;
if (checkPos < byteArray.size() && checkPos >= 0) {
QVariant newValue;
if (data.type == finsFloat) {
newValue = readFinsFloatFromQByteArray(byteArray, checkPos, false);
}
else
newValue = byteArray.at(checkPos);
if (newValue != data.value) {
data.value = newValue;
emit bridge->runCommand_refeshPlcValueViewer(data.valueAddr, data.value.toString());
}
}
}
}
std::vector<std::pair<int, int>>plcValueViewerDatas;
std::vector<PlcValueViewerStruct>plcValueViewerDatas;
private:
QElapsedTimer lostConnectionCountTimer,lostConnectionRePrintTimer;
qtFuncBridge* bridge;
@@ -97,9 +97,9 @@ public slots:
auto widget = new plcValueViewer(groupName, viewerNameAndAddress, plcViwerLineedits);
plcValueViewerLayout->addWidget(widget->widget,Qt::AlignTop);
}
void refreshPlcValueViewer(int address, QVariant value) {
void refreshPlcValueViewer(int address, QString value) {
for (auto& lineedit : plcViwerLineedits[address]) {
lineedit->setText(value.toString());
lineedit->setText(value);
}
}
private:
+268 -305
View File
@@ -1,334 +1,297 @@
#include <missionBase.hpp>
#include <yhGlobal.h>
#include "cal_disJiao.h"
class mfd_detParams {
public:
int biaoding = 0;
};
#pragma region 算法
#include <simpleAlgo.h>
#include <hdevengine/HDevEngineCpp.h>
#include <opencvPaintAlgo.hpp>
# include "HalconCpp.h"
using namespace HDevEngineCpp;
using namespace HalconCpp;
static bool ManHan(std::shared_ptr <detData> data, mfd_detParams* _detParams, yh_581_address address){
HObject ho_in_image;
HTuple hv_out_standardPar;
HTuple hv_out_flat;
HTuple in_ProductType;
HTuple hv_out_disLeftVertical;
HTuple hv_out_LeftVerticalLinePar;
HTuple hv_out_disLeftLevel;
HTuple hv_out_LeftLevelLinePar;
HTuple hv_out_disRightVertical;
HTuple hv_out_RightVerticalLinePar;
HTuple hv_out_disRightLevel;
HTuple hv_out_RightLevelLinePar;
cv::Mat img = cv::imread("D:/CCD/2025-10-04-19-57-14-928_04QCB6CJ27501JFA40006167_camera4_3.bmp", -1);
cv::cvtColor(img, img, cv::COLOR_BGR2GRAY);
cv::threshold(img, img, 60, 255, cv::THRESH_BINARY);
std::vector<std::vector<cv::Point>> contours;
cv::findContours(img, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
if (contours.size() != 0)
{
for (int j = 0; j < contours.size(); j++)
{
cv::Rect rect = cv::boundingRect(contours[j]);
if (rect.width > 1000 && rect.height > 900 )
{
return true;
}
}
}
//cv::cvtColor(img, img, cv::COLOR_GRAY2BGR);
ho_in_image = MatToHObject(img);
in_ProductType = "181-2";
cal_distanceJiao_4(ho_in_image, in_ProductType, &hv_out_standardPar, &hv_out_flat,
&hv_out_disLeftVertical, &hv_out_LeftVerticalLinePar, &hv_out_disLeftLevel,
&hv_out_LeftLevelLinePar, &hv_out_disRightVertical, &hv_out_RightVerticalLinePar,
&hv_out_disRightLevel, &hv_out_RightLevelLinePar);
int falg = hv_out_flat.I();
return true;
std::map<QString, QVariant> sqlMapData;
sqlMapData["项目"] = "上钉";
sqlMapData["相机"] = "相机" + address.triggerAddr;
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
///////////////////取图//处理//////////////////
if (data->oriImgs.size() != 1)
{
qCritical() << "图片数量不满足要求:" << data->oriImgs.size();
return false;
}
if (data->oriImgs[0].rows == 100) {
cv::Mat Paint;
data->oriImgs[0].copyTo(Paint);
cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2);
return false;
}
void exceptionResume(std::shared_ptr<detData> data, mfd_detParams* _detParams, yh_581_address address, QString why = "") {
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why;
cv::Mat Paint;
cv::Mat src1 = data->oriImgs[0];
if (src1.channels() != 3)
cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR);
else
src1.copyTo(Paint);
//处理算法
#pragma region halcon处理
QString singal_sign = data->additional["触发地址"].toString();
std::string cameraNumberStr = "1", FixtureNumber = "1";
data->oriImgs[0].copyTo(Paint);
if (Paint.channels() == 1)
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
TextRendererZH textPainter(Paint.cols, Paint.rows, 100);
textPainter.putText(Paint, "NG", cv::Point(100, 50), cv::Scalar(0, 255, 0));
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
data->resultImgs.push_back(Paint);
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//结果反馈
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.01");//结果反馈
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.01");//结果反馈
}
using namespace HDevEngineCpp;
static bool ManHan(std::shared_ptr <detData> data, mfd_detParams* _detParams, yh_581_address address){
try {
data->_saveMode = saveMode::oneFile;
std::map<QString, QVariant> sqlMapData;
sqlMapData["项目"] = "满焊";
sqlMapData["相机"] = "相机" + address.triggerAddr;
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
if (singal_sign.contains("20000")) {
cameraNumberStr = "1";
FixtureNumber = "1";
}
else if (singal_sign.contains("20002")) {
cameraNumberStr = "1";
FixtureNumber = "2";
}
else if (singal_sign.contains("20200")) {
cameraNumberStr = "2";
FixtureNumber = "3";
}
else if (singal_sign.contains("20202")) {
cameraNumberStr = "2";
FixtureNumber = "4";
}
else if (singal_sign.contains("20400")) {
cameraNumberStr = "3";
FixtureNumber = "5";
}
else if (singal_sign.contains("20402")) {
cameraNumberStr = "3";
FixtureNumber = "6";
}
else if (singal_sign.contains("20600")) {
cameraNumberStr = "4";
FixtureNumber = "7";
}
else if (singal_sign.contains("20602")) {
cameraNumberStr = "4";
FixtureNumber = "8";
}
HalconCpp::HObject in_Image = MatToHObject(src1);
HDevEngineCpp::HDevProcedure proc("_9_manhan");
HDevProcedureCall procedureCall(proc);
procedureCall.SetInputIconicParamObject("in_Image", in_Image);
procedureCall.SetInputCtrlParamTuple("in_ProductionType", _detParams->biaoding);
procedureCall.SetInputCtrlParamTuple("in_CameraNumber", HTuple(cameraNumberStr.c_str()));
procedureCall.SetInputCtrlParamTuple("in_FixtureNumber", HTuple(FixtureNumber.c_str()));
procedureCall.SetInputCtrlParamTuple("in_FilePath1", HTuple("./halconFiles/template_manHan/"));
procedureCall.SetInputCtrlParamTuple("in_FilePath2", HTuple("./halconFiles/base_manHan/"));
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");
#pragma endregion
int outFlag = out_Flag.D();
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera::放钉" << "_SN::" << SN << ",放钉算法结果;" << out_Flag[0].D();
TextRendererZH textPainter(Paint.cols, Paint.rows, 150);
if (outFlag == 1) { //-1为失败,无结果
//先处理数据
double offsetX;
double offsetY;
offsetX = 0 - out_OffsetX.D();
offsetY = 0 - out_OffsetY.D();
//if (singal_sign.contains("D18800"))
// offsetX -= 0.2;
//else if (singal_sign.contains("D19000")) {
// offsetX -= 0.15;
// offsetY += 0.1;
//}
//else if (singal_sign.contains("D19400")) {
// offsetY -= 0.2;
//}
if (abs(offsetX) >= 6000 || abs(offsetY) >= 6000)
///////////////////取图//处理//////////////////
if (data->oriImgs.size() != 1)
{
qCritical() << "图片数量不满足要求:" << data->oriImgs.size();
return false;
}
cv::Mat Paint;
cv::Mat src1 = data->oriImgs[0];
if (src1.channels() != 3)
cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR);
else
src1.copyTo(Paint);
//处理算法
#pragma region halcon处理
std::string cameraNumberStr = "1", FixtureNumber = "1";
if (address.triggerAddr == 20000) {
cameraNumberStr = "1";
FixtureNumber = "1";
}
else if (address.triggerAddr == 20002) {
cameraNumberStr = "1";
FixtureNumber = "2";
}
else if (address.triggerAddr == 20200) {
cameraNumberStr = "2";
FixtureNumber = "3";
}
else if (address.triggerAddr == 20202) {
cameraNumberStr = "2";
FixtureNumber = "4";
}
else if (address.triggerAddr == 20400) {
cameraNumberStr = "3";
FixtureNumber = "5";
}
else if (address.triggerAddr == 20402) {
cameraNumberStr = "3";
FixtureNumber = "6";
}
else if (address.triggerAddr == 20600) {
cameraNumberStr = "4";
FixtureNumber = "7";
}
else if (address.triggerAddr == 20602) {
cameraNumberStr = "4";
FixtureNumber = "8";
}
data->SNcode = "相机" + cameraNumberStr + "孔" + FixtureNumber + "_" + data->SNcode;
HalconCpp::HObject in_Image = MatToHObject(src1);
HDevEngineCpp::HDevProcedure proc("_9_manhan");
HDevProcedureCall procedureCall(proc);
procedureCall.SetInputIconicParamObject("in_Image", in_Image);
procedureCall.SetInputCtrlParamTuple("in_ProductionType", _detParams->biaoding);
procedureCall.SetInputCtrlParamTuple("in_CameraNumber", HTuple(cameraNumberStr.c_str()));
procedureCall.SetInputCtrlParamTuple("in_FixtureNumber", HTuple(FixtureNumber.c_str()));
procedureCall.SetInputCtrlParamTuple("in_FilePath1", HTuple("./halconFiles/template_manHan/"));
procedureCall.SetInputCtrlParamTuple("in_FilePath2", HTuple("./halconFiles/base_manHan/"));
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");
#pragma endregion
int outFlag = out_Flag.D();
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera::放钉" << "_SN::" << SN << ",放钉算法结果;" << out_Flag[0].D();
TextRendererZH textPainter(Paint.cols, Paint.rows, 150);
textPainter.putText(Paint, "相机:" + cameraNumberStr + " 孔" + FixtureNumber, cv::Point(50, 0), cv::Scalar(0, 255, 0));
if (outFlag == 1) { //-1为失败,无结果
//先处理数据
double offsetX = 0 - out_OffsetX.D() * 1000;//和激光交流后要求我们*1000
double offsetY = 0 - out_OffsetY.D() * 1000;
double X_Circle = out_Circle[1].D();
double Y_Circle = out_Circle[0].D();
if (abs(offsetX) >= 6000 || abs(offsetY) >= 6000)
{
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送结果
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " 满焊X偏移abs(resultData[0]) >= 6000,may err,set 0";
data->halconOK = false;
}
else {
sqlMapData["偏移X"] = offsetX;
sqlMapData["偏移Y"] = offsetY;
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(offsetX));//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(offsetY));//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
data->halconOK = true;
}
//圆及十字
cv::circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 20);
cv::line(Paint, 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(Paint, 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);
textPainter.putText(Paint, "X偏移:" + std::to_string(offsetX), cv::Point(50, 150), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "Y偏移:" + std::to_string(offsetY), cv::Point(50, 350), cv::Scalar(0, 255, 0));
//textPainter.putText(Paint, "圆心X坐标:" + std::to_string(X_Circle), cv::Point(50, 150), cv::Scalar(0, 255, 0));
//textPainter.putText(Paint, "圆心Y坐标:" + std::to_string(offsetY), cv::Point(50, 350), cv::Scalar(0, 255, 0));
}
else {
data->halconOK = false;
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送结果
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " 满焊X偏移abs(resultData[0]) >= 6000,may err,set 0";
data->halconOK = false;
textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255));
}
if (data->halconOK == true) {
textPainter.putText(Paint, "OK", cv::Point(50, 550), cv::Scalar(0, 255, 0));
sqlMapData["结果"] = "OK";
}
else {
sqlMapData["偏移X"] = offsetX;
sqlMapData["偏移Y"] = offsetY;
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(offsetX));//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(offsetY));//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
data->halconOK = true;
textPainter.putText(Paint, "NG", cv::Point(50, 500), cv::Scalar(0, 0, 255));
sqlMapData["结果"] = "NG";
}
//圆及十字
cv::circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 20);
cv::line(Paint, 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(Paint, 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);
textPainter.putText(Paint, "X偏移:" + std::to_string(offsetX), cv::Point(50, 150), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "Y偏移:" + std::to_string(offsetY), cv::Point(50, 350), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "相机:" + cameraNumberStr, cv::Point(50, 0), cv::Scalar(0, 255, 0));
data->service->_csvWriter->addData(QString::fromStdString(data->SNcode), sqlMapData);
data->resultImgs.push_back(Paint);
return true;
}
else{
data->halconOK = false;
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送结果
textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255));
}
if (data->halconOK == true) {
textPainter.putText(Paint, "OK", cv::Point(50, 550), cv::Scalar(0, 255, 0));
sqlMapData["结果"] = "OK";
}
else {
textPainter.putText(Paint, "NG", cv::Point(50, 500), cv::Scalar(0, 0, 255));
sqlMapData["结果"] = "NG";
}
data->service->_csvWriter->addData(QString::fromStdString(data->SNcode), sqlMapData);
data->resultImgs.push_back(Paint);
return true;
CATCH_EXCEPTIONS
exceptionResume(data, _detParams, address, "异常");
}
static bool YuHan(std::shared_ptr <detData> data, mfd_detParams* _detParams, yh_581_address address){
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
std::map<QString, QVariant> sqlMapData;
sqlMapData["项目"] = "预焊";
sqlMapData["相机"] = "相机" + address.triggerAddr;
///////////////////取图//处理//////////////////
if (data->oriImgs.size() != 1){
qCritical() << "图片数量不满足要求:" << data->oriImgs.size();
return false;
}
if (data->oriImgs[0].rows == 100) {
cv::Mat Paint;
data->oriImgs[0].copyTo(Paint);
cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2);
return false;
}
try {
data->_saveMode = saveMode::oneFile;
std::map<QString, QVariant> sqlMapData;
sqlMapData["项目"] = "预焊";
sqlMapData["相机"] = "相机" + address.triggerAddr;
///////////////////取图//处理//////////////////
if (data->oriImgs.size() != 1) {
qCritical() << "图片数量不满足要求:" << data->oriImgs.size();
return false;
}
cv::Mat Paint;
cv::Mat src1 = data->oriImgs[0];
if (src1.channels() != 3)
cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR);
else
src1.copyTo(Paint);
//处理算法
cv::Mat Paint;
cv::Mat src1 = data->oriImgs[0];
//src1 = cv::imread("D://ceshi/15H/1/333.bmp",-1);
if (src1.channels() != 3)
cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR);
else
src1.copyTo(Paint);
//处理算法
#pragma region halcon处理
QString singal_sign = address.triggerAddr;
std::string cameraNumberStr = "1", FixtureNumber = "1";
if (singal_sign.contains("19600")) {
cameraNumberStr = "1";
FixtureNumber = "1";
}
else if (singal_sign.contains("19602")) {
cameraNumberStr = "1";
FixtureNumber = "3";
}
else if (singal_sign.contains("19800")) {
cameraNumberStr = "2";
FixtureNumber = "2";
}
else if (singal_sign.contains("19802")) {
cameraNumberStr = "2";
FixtureNumber = "4";
}
HDevEngineCpp::HDevProcedure proc("_9_yuhan");
HalconCpp::HObject in_Image = MatToHObject(src1);
HDevProcedureCall procedureCall(proc);
procedureCall.SetInputIconicParamObject("in_Image", in_Image);
procedureCall.SetInputCtrlParamTuple("in_ProductionType", 0);
procedureCall.SetInputCtrlParamTuple("in_Resolution", HTuple(0.00749026));
procedureCall.SetInputCtrlParamTuple("in_CameraNumber", HTuple(cameraNumberStr.c_str()));
procedureCall.SetInputCtrlParamTuple("in_FixtureNumber", HTuple(FixtureNumber.c_str()));
procedureCall.SetInputCtrlParamTuple("in_FilePath1", HTuple("./halconFiles/yuhan_template/"));
procedureCall.SetInputCtrlParamTuple("in_FilePath2", HTuple("./halconFiles/yuhan_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");
std::string cameraNumberStr = "1", FixtureNumber = "1";
if (address.triggerAddr == 19600) {
cameraNumberStr = "1";
FixtureNumber = "1";
}
else if (address.triggerAddr == 19602) {
cameraNumberStr = "1";
FixtureNumber = "3";
}
else if (address.triggerAddr == 19800) {
cameraNumberStr = "2";
FixtureNumber = "2";
}
else if (address.triggerAddr == 19802) {
cameraNumberStr = "2";
FixtureNumber = "4";
}
data->SNcode = "相机" + cameraNumberStr + "孔" + FixtureNumber + "_" + data->SNcode;
HDevEngineCpp::HDevProcedure proc("_9_yuhan");
HalconCpp::HObject in_Image = MatToHObject(src1);
HDevProcedureCall procedureCall(proc);
procedureCall.SetInputIconicParamObject("in_Image", in_Image);
procedureCall.SetInputCtrlParamTuple("in_ProductionType", 0);
procedureCall.SetInputCtrlParamTuple("in_Resolution", HTuple(0.0069699));
procedureCall.SetInputCtrlParamTuple("in_CameraNumber", HTuple(cameraNumberStr.c_str()));
procedureCall.SetInputCtrlParamTuple("in_FixtureNumber", HTuple(FixtureNumber.c_str()));
procedureCall.SetInputCtrlParamTuple("in_FilePath1", HTuple("./halconFiles/template_yuhan/"));
procedureCall.SetInputCtrlParamTuple("in_FilePath2", HTuple("./halconFiles/base_yuhan/"));
procedureCall.SetInputCtrlParamTuple("in_NailType", 1);//1:平钉 2:凹钉;
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");
#pragma endregion
int outFlag = out_Flag.D();
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera::放钉" << "_SN::" << SN << ",放钉算法结果;" << out_Flag[0].D();
TextRendererZH textPainter(Paint.cols, Paint.rows, 150);
if (outFlag == 1) { //-1为失败,无结果
double offsetX;
double offsetY;
offsetX = 0 - out_OffsetX.D();
offsetY = 0 - out_OffsetY.D();
//if (singal_sign.contains("D18800"))
// offsetX -= 0.2;
//else if (singal_sign.contains("D19000")) {
// offsetX -= 0.15;
// offsetY += 0.1;
//}
//else if (singal_sign.contains("D19400")) {
// offsetY -= 0.2;
//}
if (abs(offsetX) >= 6000 || abs(offsetY) >= 6000){
int outFlag = out_Flag.D();
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera::放钉" << "_SN::" << SN << ",放钉算法结果;" << out_Flag[0].D();
TextRendererZH textPainter(Paint.cols, Paint.rows, 150);
textPainter.putText(Paint, "相机:" + cameraNumberStr + " 孔位" + FixtureNumber, cv::Point(50, 0), cv::Scalar(0, 255, 0));
if (outFlag == 1) { //-1为失败,无结果
double offsetX = out_OffsetX.D();
double offsetY = out_OffsetY.D();
//if (address.triggerAddr == 19600)
// offsetX -= 0.2;
//else if (address.triggerAddr == 19602) {
// offsetX -= 0.15;
// offsetY += 0.1;
//}
//else (address.triggerAddr == 19800) {
// offsetY -= 0.2;
//}
if (abs(offsetX) >= 6000 || abs(offsetY) >= 6000) {
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送结果
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " 预焊X偏移abs(resultData[0]) >= 6000,may err,set 0";
data->halconOK = false;
}
else {
sqlMapData["偏移X"] = offsetX;
sqlMapData["偏移Y"] = offsetY;
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(offsetX));//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(offsetY));//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
data->halconOK = true;
}
//圆及十字
cv::circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 20);
cv::line(Paint, 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(Paint, 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);
textPainter.putText(Paint, "X偏移:" + std::to_string(offsetX), cv::Point(50, 150), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "Y偏移:" + std::to_string(offsetY), cv::Point(50, 350), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "圆心坐标X:" + std::to_string(out_Circle[1].D()), cv::Point(50, 750), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "圆心坐标Y:" + std::to_string(out_Circle[0].D()), cv::Point(50, 950), cv::Scalar(0, 255, 0));
}
else {
data->halconOK = false;
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送结果
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " 预焊X偏移abs(resultData[0]) >= 6000,may err,set 0";
data->halconOK = false;
textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255));
}
if (data->halconOK == true) {
textPainter.putText(Paint, "OK", cv::Point(50, 550), cv::Scalar(0, 255, 0));
sqlMapData["结果"] = "OK";
}
else {
sqlMapData["偏移X"] = offsetX;
sqlMapData["偏移Y"] = offsetY;
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(offsetX));//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(offsetY));//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
data->halconOK = true;
textPainter.putText(Paint, "NG", cv::Point(50, 500), cv::Scalar(0, 0, 255));
sqlMapData["结果"] = "NG";
}
//圆及十字
cv::circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 20);
cv::line(Paint, 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(Paint, 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);
data->service->_csvWriter->addData(QString::fromStdString(data->SNcode), sqlMapData);
data->resultImgs.push_back(Paint);
textPainter.putText(Paint, "X偏移:" + std::to_string(offsetX), cv::Point(50, 150), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "Y偏移:" + std::to_string(offsetY), cv::Point(50, 350), cv::Scalar(0, 255, 0));
textPainter.putText(Paint, "相机:" + cameraNumberStr + " 孔位" + FixtureNumber, cv::Point(50, 0), cv::Scalar(0, 255, 0));
return true;
}
else{
data->halconOK = false;
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");//发送偏移Y
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送结果
textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255));
}
if (data->halconOK == true){
textPainter.putText(Paint, "OK", cv::Point(50, 550), cv::Scalar(0, 255, 0));
sqlMapData["结果"] = "OK";
}
else{
textPainter.putText(Paint, "NG", cv::Point(50, 500), cv::Scalar(0, 0, 255));
sqlMapData["结果"] = "NG";
}
data->service->_csvWriter->addData(QString::fromStdString(data->SNcode), sqlMapData);
data->resultImgs.push_back(Paint);
return true;
CATCH_EXCEPTIONS
exceptionResume(data, _detParams, address, "异常");
}
#pragma endregion
class _581_Mfd : public mission {
public:
@@ -348,20 +311,20 @@ public:
detParams _detParams;
void onConfigReloaded() {
HDevEngineCpp::HDevEngine myEngine;
myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl");
myEngine.SetProcedurePath("./halconAlgo/AlgoLibrary_602.hdpl");
}
bool initCustom() {
#pragma region 注册触发器回调
yh_1.init("Camera1", "预焊1", 19600, 2, 1, &_params, _serviceManager, bridge, YuHan);
yh_2.init("Camera2", "预焊2", 19800, 2, 1, &_params, _serviceManager, bridge, YuHan);
yh_1.init("Camera1", "预焊1", 19600, 2, 1, &_params, _serviceManager, bridge, YuHan, "预焊CCD");
yh_2.init("Camera2", "预焊2", 19800, 2, 1, &_params, _serviceManager, bridge, YuHan, "预焊CCD");
mh_1.init("Camera3", "满焊1", 20000, 2, 1, &_params, _serviceManager, bridge, ManHan);
mh_2.init("Camera4", "满焊2", 20200, 2, 1, &_params, _serviceManager, bridge, ManHan);
mh_3.init("Camera5", "满焊3", 20400, 2, 1, &_params, _serviceManager, bridge, ManHan);
mh_4.init("Camera6", "满焊4", 20600, 2, 1, &_params, _serviceManager, bridge, ManHan);
mh_1.init("Camera3", "满焊1", 20000, 2, 1, &_params, _serviceManager, bridge, ManHan, "满焊CCD");
mh_2.init("Camera4", "满焊2", 20200, 2, 1, &_params, _serviceManager, bridge, ManHan, "满焊CCD");
mh_3.init("Camera5", "满焊3", 20400, 2, 1, &_params, _serviceManager, bridge, ManHan, "满焊CCD");
mh_4.init("Camera6", "满焊4", 20600, 2, 1, &_params, _serviceManager, bridge, ManHan, "满焊CCD");
hh_2D.init("Camera7", "焊后2d", 20800, 2, 1, &_detParams, _serviceManager, bridge, generalAlgoTest);
hh_3D.init("Camera8", "焊后3d", 21000, 2, 1, &_detParams, _serviceManager, bridge, generalAlgoTest);
hh_2D.init("Camera7", "焊后2d", 20800, 2, 1, &_detParams, _serviceManager, bridge, generalAlgoTest, "焊后CCD");
hh_3D.init("Camera8", "焊后3d", 21000, 2, 1, &_detParams, _serviceManager, bridge, generalAlgoTest, "焊后CCD");
#pragma endregion
return true;
}