V20251125-2.2.6
修改了CLS切图函数的逻辑,现在会按最初图像的中心点开始切图。 修改算法NG(halconNg)时存图的文件夹名字为algoNG。 修复基恩士相机可能出现丢亮度图的问题。
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@
|
||||
#include <QDir>
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
const std::string softwareVersion = "20251119-2.2.5";
|
||||
const std::string softwareVersion = "20251125-2.2.6";
|
||||
const std::string euiJsonVersion = "1.0.6";
|
||||
#define globalDatabasePth "./sqlDatabase/eui_db.db" //全局数据库路径
|
||||
#define saveImgEnable 1
|
||||
|
||||
@@ -124,6 +124,8 @@ static std::vector<cv::Mat> cutImg2ClsVec(cv::Rect boundingBox, cv::Mat imgInput
|
||||
std::cerr << "Invalid bounding box or empty input image." << std::endl;
|
||||
return result;
|
||||
}
|
||||
if (boundingBox.width < targetSize.width && boundingBox.height < targetSize.height)
|
||||
return { cutImg2Cls(boundingBox, imgInput, targetSize) };
|
||||
|
||||
const int w = boundingBox.width;
|
||||
const int h = boundingBox.height;
|
||||
@@ -139,8 +141,8 @@ static std::vector<cv::Mat> cutImg2ClsVec(cv::Rect boundingBox, cv::Mat imgInput
|
||||
const bool splitHoriz = (w > h); // 横向长 -> 沿X方向切
|
||||
const int longSide = splitHoriz ? w : h;
|
||||
const int step = minSide;
|
||||
const int beginCoord = splitHoriz ? boundingBox.x : boundingBox.y;
|
||||
const int endCoord = beginCoord + longSide;
|
||||
const int beginCoord = splitHoriz ? boundingBox.x - targetSize.height / 2 + boundingBox.height / 2 : boundingBox.y - targetSize.width / 2 + boundingBox.width / 2;
|
||||
const int endCoord = beginCoord + longSide + (splitHoriz ? targetSize.width / 2 : targetSize.height / 2);
|
||||
|
||||
// 计算切块起点列表
|
||||
std::vector<int> starts;
|
||||
@@ -156,12 +158,14 @@ static std::vector<cv::Mat> cutImg2ClsVec(cv::Rect boundingBox, cv::Mat imgInput
|
||||
|
||||
result.reserve(starts.size());
|
||||
if (splitHoriz) {
|
||||
int y = boundingBox.y - targetSize.width / 2 + boundingBox.height / 2;
|
||||
for (int x : starts) {
|
||||
result.emplace_back(cutImg2Cls(cv::Rect(x, boundingBox.y, minSide, minSide), imgInput, targetSize));
|
||||
result.emplace_back(cutImg2Cls(cv::Rect(x, y, minSide, minSide), imgInput, targetSize));
|
||||
}
|
||||
} else {
|
||||
int x = boundingBox.x - targetSize.width / 2 + boundingBox.width / 2;
|
||||
for (int y : starts) {
|
||||
result.emplace_back(cutImg2Cls(cv::Rect(boundingBox.x, y, minSide, minSide), imgInput, targetSize));
|
||||
result.emplace_back(cutImg2Cls(cv::Rect(x, y, minSide, minSide), imgInput, targetSize));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,7 +399,7 @@ static void MatToHObjectV(cv::Mat& image, HalconCpp::HObject* Hobj)
|
||||
}
|
||||
|
||||
}
|
||||
static HalconCpp::HObject MatToHObject(cv::Mat& image)
|
||||
static HalconCpp::HObject MatToHObject(const cv::Mat& image)
|
||||
{
|
||||
HalconCpp::HObject Hobj;
|
||||
int hgt = image.rows;
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
QString processResult;
|
||||
if (!data->aiDetOK && !data->halconOK) processResult = "NG";
|
||||
else if (!data->aiDetOK) processResult = "aiNG";
|
||||
else if (!data->halconOK) processResult = "halconNG";
|
||||
else if (!data->halconOK) processResult = "algoNG";
|
||||
else processResult = "OK";
|
||||
result.replace("{processResult}", processResult);
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#include <iostream>
|
||||
#include <opencv.hpp>
|
||||
#include <handleAI.h>
|
||||
#include <simpleAlgo.h>
|
||||
#include <global.h>
|
||||
#include <basic.hpp>
|
||||
#include <simpleAlgo.h>
|
||||
using namespace std;
|
||||
|
||||
void rlj_hanyin(const std::string path, const std::string format, const std::string outputPath, cv::Size fillter) {
|
||||
//int
|
||||
handdleAI::pSegmentation* seg = handdleAI::CreateSegObjS("./cutImgFiles/RLJ_HANYINZHUAQU_SEG.BHD", 1, 0);
|
||||
//handdleAI::pSegmentation* seg = handdleAI::CreateSegObjS("./cutImgFiles/YUHAN_LV_SEG.BHD", 1, 0);
|
||||
//handdleAI::pClassification* cls = handdleAI::CreateClsObjV3("./cutImgFiles/YUHAN_LV_CLS.BHD", 0, 1);
|
||||
|
||||
std::vector<std::string> images;
|
||||
cv::glob(path + "/*." + format, images, false);
|
||||
std::cout << "files count" << images.size() << std::endl;
|
||||
QString timeStamp = getDateTimeStamp();
|
||||
for (size_t i = 0; i < images.size(); i++) {
|
||||
std::string filePath = outputPath + "/" + timeStamp.toStdString() + "/" + std::to_string(i) + "/";
|
||||
createDirectoryIfNotExists(QString::fromStdString(filePath));
|
||||
cv::Mat srcImage = cv::imread(images[i], -1);
|
||||
cv::Mat Paint;
|
||||
if (srcImage.cols == 1)
|
||||
cv::cvtColor(srcImage, Paint, cv::COLOR_GRAY2BGR);
|
||||
else
|
||||
srcImage.copyTo(Paint);
|
||||
|
||||
if (srcImage.empty()) {
|
||||
std::cout << "ͼƬΪ¿Õ£¡" << std::endl;
|
||||
continue;
|
||||
}
|
||||
bool isNg = false;
|
||||
auto SegResult = ~seg->Evaluate(srcImage);
|
||||
auto rect = findMaxAreaContour(SegResult);
|
||||
auto clsImg = cutImg2Cls(rect, srcImage, cv::Size(256, 256));
|
||||
std::string text = isNg == true ? "NG" : "OK";
|
||||
cv::imwrite(filePath + "/ " + getCurrentDateTime() + "RES.bmp", clsImg);
|
||||
cv::imwrite(filePath + "/ " + text + "Paint.bmp", Paint);
|
||||
std::cout << i << "/" << images.size() << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <qstring.h>
|
||||
#include <qtimer.h>
|
||||
#include <qdatetime.h>
|
||||
QString getDateTimeStamp()
|
||||
{
|
||||
return QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss");
|
||||
}
|
||||
static const std::vector<std::string> saveR = { "OK","NG" };
|
||||
@@ -1,7 +1,13 @@
|
||||
#include <baoMo.hpp>
|
||||
|
||||
#include <yuhan.hpp>
|
||||
#include <RLJ.hpp>
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
baomoXiaDMianSiJiaoCut("E:\\imgs", "bmp", "./outputs/" , cv::Size(50, 50));
|
||||
//rlj_hanyin("D:\\º¸Ó¡Image\\11.20\\T\\NG", "bmp", "./outputs/", cv::Size(300, 300));
|
||||
//yuhan_hanqian("D:\\testImage\\OK", "bmp", "./outputs/" , cv::Size(300, 300));
|
||||
// yuhan_hanqian("D:\\testImg\\L", "bmp", "./outputs/", cv::Size(50, 50));
|
||||
cv::Mat img = cv::imread("D:\\testImage\\04QCB82602000JFBN00206BN_Camera3_ORI_0_09-42-34-710.bmp", -1);
|
||||
//755 4300 60 300
|
||||
auto imgs = cutImg2ClsVec(cv::Rect(8120, 4850, 1007, 129), img);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include <iostream>
|
||||
#include <opencv.hpp>
|
||||
#include <handleAI.h>
|
||||
#include <simpleAlgo.h>
|
||||
#include <global.h>
|
||||
#include <basic.hpp>
|
||||
using namespace std;
|
||||
|
||||
void yuhan_hanqian(const std::string path, const std::string format, const std::string outputPath, cv::Size fillter) {
|
||||
//int
|
||||
handdleAI::pSegmentation* seg = handdleAI::CreateSegObjS("./cutImgFiles/YUHAN_TONG_SEG.BHD", 1, 0);
|
||||
handdleAI::pClassification* cls = handdleAI::CreateClsObjV3("./cutImgFiles/YUHAN_TONG_CLS.BHD", 0, 1);
|
||||
//handdleAI::pSegmentation* seg = handdleAI::CreateSegObjS("./cutImgFiles/YUHAN_LV_SEG.BHD", 1, 0);
|
||||
//handdleAI::pClassification* cls = handdleAI::CreateClsObjV3("./cutImgFiles/YUHAN_LV_CLS.BHD", 0, 1);
|
||||
|
||||
std::vector<std::string> images;
|
||||
cv::glob(path + "/*." + format, images, false);
|
||||
std::cout << "files count" << images.size() << std::endl;
|
||||
QString timeStamp = getDateTimeStamp();
|
||||
for (size_t i = 0; i < images.size(); i++) {
|
||||
std::string filePath = outputPath + "/" + timeStamp.toStdString() + "/" + std::to_string(i) + "/";
|
||||
createDirectoryIfNotExists(QString::fromStdString(filePath));
|
||||
cv::Mat srcImage = cv::imread(images[i], -1);
|
||||
cv::resize(srcImage, srcImage, cv::Size(), 0.5, 0.5);
|
||||
cv::Mat Paint;
|
||||
if (srcImage.cols == 1)
|
||||
cv::cvtColor(srcImage, Paint, cv::COLOR_GRAY2BGR);
|
||||
else
|
||||
srcImage.copyTo(Paint);
|
||||
|
||||
if (srcImage.empty()) {
|
||||
std::cout << "ͼƬΪ¿Õ£¡" << std::endl;
|
||||
continue;
|
||||
}
|
||||
bool isNg = false;
|
||||
cv::Mat SegResult = ~seg->Evaluate(srcImage);
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
cv::findContours(SegResult, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
|
||||
for (int ii = 0; ii < contours.size(); ii++) {
|
||||
cv::Rect rect = cv::boundingRect(contours[ii]);
|
||||
if (rect.width > fillter.width && rect.height > fillter.height) {
|
||||
//cv::putText(Paint, std::to_string(ii), cv::Point(rect.x + rect.width / 2, rect.y + rect.height / 2), 1, 2, cv::Scalar(255, 255, 255), 5);
|
||||
auto imgs = cutImg2ClsVec(rect, srcImage);
|
||||
for (int o = 0; o < imgs.size(); o++) {
|
||||
int r = cls->Evaluate(imgs[o]);
|
||||
qDebug() << r;
|
||||
if (r== 1)
|
||||
isNg = true;
|
||||
cv::imwrite(filePath + "/" + timeStamp.toStdString() + "_" + std::to_string(i) + "_" + std::to_string(ii) + "_" + std::to_string(o) + saveR[r] + "CLS.bmp", imgs[o]);
|
||||
}
|
||||
if(isNg)
|
||||
cv::rectangle(Paint, rect, cv::Scalar(0, 0, 255), 3);
|
||||
else
|
||||
cv::rectangle(Paint, rect, cv::Scalar(0, 255, 0), 3);
|
||||
}
|
||||
}
|
||||
std::string text = isNg == true ? "NG" : "OK";
|
||||
cv::imwrite(filePath + "/ " + text + "Paint.bmp", Paint);
|
||||
std::cout << i << "/" << images.size() << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
#include <581_Ruanlianjie_hanqian_hanhou.h>
|
||||
void exceptionResume(std::shared_ptr<detData> data, hanHouJianCe* _detParams, sx_581_address address, QString why = "") {
|
||||
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why;
|
||||
cv::Mat Paint;
|
||||
data->oriImgs[0].copyTo(Paint);
|
||||
if (Paint.channels() == 1)
|
||||
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
|
||||
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 300);
|
||||
textPainter.putText(Paint, why.toStdString(), cv::Point(500, 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 + "_1");//结果反馈
|
||||
|
||||
}
|
||||
void exceptionResume(std::shared_ptr<detData> data, hanQianDingWeiParams* _detParams, sx_581_address address, QString why = "") {
|
||||
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why;
|
||||
cv::Mat Paint;
|
||||
data->oriImgs[0].copyTo(Paint);
|
||||
if (Paint.channels() == 1)
|
||||
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
|
||||
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 300);
|
||||
textPainter.putText(Paint, why.toStdString(), cv::Point(500, 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 + "_1");//结果反馈
|
||||
|
||||
}
|
||||
bool HanQianDingWei(std::shared_ptr <detData> data, hanQianDingWeiParams* _detParams, sx_581_address address){
|
||||
try
|
||||
{
|
||||
bool zuoLJPtoGaiBanEnable = data->service->_paramSyncManager->get("焊前定位", "左侧连接片和盖板距离判定启用", false).toBool();
|
||||
double zuoLJPtoGaiBanMaxThreshold = data->service->_paramSyncManager->get("焊前定位", "左侧连接片和盖板距离(MAX)", 1.8).toDouble();
|
||||
double zuoLJPtoGaiBanMinThreshold = data->service->_paramSyncManager->get("焊前定位", "左侧连接片和盖板距离(MIN)", 0.0).toDouble();
|
||||
|
||||
bool youLJPtoGaiBanEnable = data->service->_paramSyncManager->get("焊前定位", "右侧连接片和盖板距离判定启用", false).toBool();
|
||||
double youLJPtoGaiBanMaxThreshold = data->service->_paramSyncManager->get("焊前定位", "右侧连接片和盖板距离(MAX)", 1.8).toDouble();
|
||||
double youLJPtoGaiBanMinThreshold = data->service->_paramSyncManager->get("焊前定位", "右侧连接片和盖板距离(MIN)", 0.0).toDouble();
|
||||
|
||||
QByteArray plcResult = "1";
|
||||
//data->oriImgs[0] = cv::imread("D://60A01MB5601FB2P246404_Camera1_0_00-43-53.bmp",-1);
|
||||
cv::Mat sourceImg = data->oriImgs[0];
|
||||
cv::Mat Paint;
|
||||
sourceImg.copyTo(Paint);
|
||||
if (Paint.channels() == 1)
|
||||
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
|
||||
HDevEngineCpp::HDevProcedure proc("_3_HQDW_Inspection");
|
||||
HDevEngineCpp::HDevProcedureCall procedureCall(proc);
|
||||
|
||||
HTuple in_Resolution(0.0349425), in_FilePath("./halconFiles/");
|
||||
HObject inputImage = MatToHObject(sourceImg);
|
||||
|
||||
procedureCall.SetInputIconicParamObject("in_Image", inputImage);
|
||||
procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution);
|
||||
procedureCall.SetInputCtrlParamTuple("in_FilePath", in_FilePath);
|
||||
procedureCall.Execute();//执行halcon程序
|
||||
HTuple out_ColorType;
|
||||
HTuple out_Distance;
|
||||
HTuple out_CCDistance;
|
||||
HTuple make;
|
||||
HObject out_DisplayImage;
|
||||
//out_LinePoint = procedureCall.GetOutputCtrlParamTuple("out_LinePoint");//获取输出控制类变量
|
||||
out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出控制类变量
|
||||
//out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");//获取输出控制类变量
|
||||
out_Distance = procedureCall.GetOutputCtrlParamTuple("out_Distance");//获取输出控制类变量
|
||||
out_CCDistance = procedureCall.GetOutputCtrlParamTuple("out_CCDistance");//获取输出控制类变量
|
||||
make = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量
|
||||
out_DisplayImage = procedureCall.GetOutputIconicParamObject("out_DisplayImage");//获取输出控制类变量
|
||||
int flag = make.D();
|
||||
|
||||
// Output(HTuple): out_ColorType, 1, 铜; 2,铝</c>
|
||||
|
||||
//正确的应该左边铝 右边铜
|
||||
double value1_1 = 0, value1_2 = 0, value2_1 = 0, value2_2 = 0;
|
||||
bool jiXingEnable = data->service->_paramSyncManager->get("焊前定位", "焊前极性判定启用", false).toBool();
|
||||
if (flag == 1)
|
||||
{
|
||||
//circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 5);
|
||||
//for (int i = 0; i < 2 ; i++)
|
||||
//{
|
||||
// cv::line(Paint, cv::Point(out_LinePoint[i * 4 + 1].D(), out_LinePoint[i * 4].D()),
|
||||
// cv::Point(out_LinePoint[i * 4 + 3].D(), out_LinePoint[i * 4 + 2].D()),
|
||||
// cv::Scalar(0, 255, 0), 10);
|
||||
//}
|
||||
bool isNg = false;
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 200);
|
||||
Paint = HObject2Mat(out_DisplayImage);
|
||||
if (out_Distance.Length() == 3) {
|
||||
value1_1 = out_Distance[1].D();
|
||||
value1_2 = out_Distance[2].D();
|
||||
|
||||
textPainter.putText(Paint, "铜极+铝极连接片中心距离:" + std::to_string(out_Distance[0].D()) + "mm", cv::Point(0, sourceImg.rows - 950), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "电芯上水平边缘和注液孔的中心圆的距离:" + std::to_string(out_Distance[1].D()) + "mm", cv::Point(0, sourceImg.rows - 750), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "电芯下水平边缘和注液孔的中心圆的距离:" + std::to_string(out_Distance[2].D()) + "mm", cv::Point(0, sourceImg.rows - 550), cv::Scalar(0, 255, 0));
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(out_Distance[0].D()));
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr+2) + "_" + QByteArray::number(out_Distance[1].D()));
|
||||
|
||||
data->sqlVec.insert({ "电芯上水平边缘和注液孔的中心圆的距离", out_Distance[1].D() });
|
||||
data->sqlVec.insert({ "电芯下水平边缘和注液孔的中心圆的距离", out_Distance[2].D() });
|
||||
}
|
||||
if (out_CCDistance.Length() == 2) {
|
||||
value2_1 = out_CCDistance[0].D();
|
||||
if (zuoLJPtoGaiBanMaxThreshold < value2_1 || zuoLJPtoGaiBanMinThreshold > value2_1) {//NG
|
||||
textPainter.putText(Paint, "左侧连接片圆心和盖板圆心的距离:" + std::to_string(value2_1) + "mm", cv::Point(0, sourceImg.rows - 350), cv::Scalar(0, 0, 255));
|
||||
if (zuoLJPtoGaiBanEnable == true)
|
||||
isNg = true;
|
||||
}
|
||||
else//OK
|
||||
textPainter.putText(Paint, "左侧连接片圆心和盖板圆心的距离:" + std::to_string(value2_1) + "mm", cv::Point(0, sourceImg.rows - 350), cv::Scalar(0, 255, 0));
|
||||
|
||||
value2_2 = out_CCDistance[1].D();
|
||||
if (youLJPtoGaiBanMaxThreshold < value2_2 || youLJPtoGaiBanMinThreshold > value2_2) {//NG
|
||||
textPainter.putText(Paint, "右侧连接片圆心和盖板圆心的距离:" + std::to_string(value2_2) + "mm", cv::Point(0, sourceImg.rows - 150), cv::Scalar(0, 0, 255));
|
||||
if(youLJPtoGaiBanEnable == true)
|
||||
isNg = true;
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "右侧连接片圆心和盖板圆心的距离:" + std::to_string(value2_2) + "mm", cv::Point(0, sourceImg.rows - 150), cv::Scalar(0, 255, 0));
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 4) + "_" + QByteArray::number(out_CCDistance[0].D()));
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 6) + "_" + QByteArray::number(out_Distance[1].D()));
|
||||
|
||||
data->sqlVec.insert({ "左侧连接片圆心和盖板圆心的距离", out_CCDistance[0].D() });
|
||||
data->sqlVec.insert({ "右侧连接片圆心和盖板圆心的距离", out_CCDistance[1].D() });
|
||||
}
|
||||
|
||||
TextRendererZH textPainter2(Paint.cols, Paint.rows, 600);
|
||||
int left = out_ColorType[0].D();
|
||||
//结果判定,铜在左边,铝在右边
|
||||
if (left == 2)
|
||||
textPainter2.putText(Paint,"铜",cv::Point(0, 1500), cv::Scalar(0, 255, 0));
|
||||
else if (left == 1)
|
||||
textPainter2.putText(Paint,"铝",cv::Point(0, 1500), cv::Scalar(0, 0, 255));
|
||||
else
|
||||
textPainter2.putText(Paint,"异常",cv::Point(0, 1500), cv::Scalar(0, 0, 255));
|
||||
|
||||
int right = out_ColorType[1].D();
|
||||
if (right == 2)
|
||||
textPainter2.putText(Paint,"铜",cv::Point(Paint.cols - 600, 1500), cv::Scalar(0, 0, 255));
|
||||
else if (right == 1)
|
||||
textPainter2.putText(Paint,"铝",cv::Point(Paint.cols - 600, 1500), cv::Scalar(0, 255, 0));
|
||||
else
|
||||
textPainter2.putText(Paint,"异常",cv::Point(Paint.cols - 600, 1500), cv::Scalar(0, 0, 255));
|
||||
|
||||
if ((left == 1 || right == 2) && jiXingEnable)
|
||||
isNg = true;
|
||||
|
||||
TextRendererZH textPainter3(Paint.cols, Paint.rows, 800);
|
||||
if(isNg == true){
|
||||
textPainter3.putText(Paint, "NG", cv::Point(0, 50), cv::Scalar(0, 0, 255));
|
||||
plcResult = "2";
|
||||
data->halconOK = false;
|
||||
}
|
||||
else {
|
||||
textPainter3.putText(Paint, "OK", cv::Point(0, 50), cv::Scalar(0, 255, 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TextRendererZH textPainter4(Paint.cols, Paint.rows, 500);
|
||||
textPainter4.putText(Paint, "NG", cv::Point(0, 50), cv::Scalar(0, 0, 255));//调机
|
||||
plcResult = "2";
|
||||
data->halconOK = false;
|
||||
}
|
||||
if (data->service->_paramSyncManager->get("通用设置","强制OK", false).toBool())
|
||||
plcResult = "1";
|
||||
data->resultImgs.push_back(Paint);
|
||||
sourceImg.release();
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
|
||||
return true;
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
exceptionResume(data, _detParams, address, "检测失败");
|
||||
qDebug() << "[Error] " << QString::fromUtf8("检测失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HanHou2D_halconEvaluate(std::shared_ptr <detData> data, const cv::Mat& sourceImg,const cv::Mat& segImg, cv::Mat& Paint, double& hanHouTongXingDu, int times,QMutex* mutex) {
|
||||
double tongXingDuLimitHigh = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(上限)", 1.8).toDouble();
|
||||
double tongXingDuLimitLow = data->service->_paramSyncManager->get("焊后", "焊后同心度mm(下限)", 0).toDouble();
|
||||
bool tongXingDuLimitEnable = data->service->_paramSyncManager->get("焊后", "焊后同心度判定启用", true).toBool();
|
||||
HDevEngineCpp::HDevProcedure proc("_3_Cal_HY_CC_Distance");
|
||||
HDevEngineCpp::HDevProcedureCall procedureCall(proc);
|
||||
|
||||
HObject in_Image = MatToHObject(sourceImg);
|
||||
HObject in_ImageSeg = MatToHObject(segImg);
|
||||
HalconCpp::HTuple in_FliePath("./halconFiles/"), in_Resolution(0.013736);
|
||||
procedureCall.SetInputIconicParamObject("in_Image", in_Image);
|
||||
procedureCall.SetInputIconicParamObject("in_ImageSeg", in_ImageSeg);
|
||||
procedureCall.SetInputCtrlParamTuple("in_FliePath", in_FliePath);
|
||||
procedureCall.SetInputCtrlParamTuple("in_Resolution", in_Resolution);
|
||||
procedureCall.Execute();//执行halcon程序
|
||||
HalconCpp::HTuple out_CCDistance, out_Circle, out_Flag, out_NgTails;
|
||||
out_CCDistance = procedureCall.GetOutputCtrlParamTuple("out_CCDistance");//获取输出控制类变量
|
||||
out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");//获取输出控制类变量
|
||||
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量
|
||||
out_NgTails = procedureCall.GetOutputCtrlParamTuple("out_NgTails");//获取输出控制类变量
|
||||
int flag = out_Flag.D();
|
||||
bool isNg = false;
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 300);
|
||||
QMutexLocker locker(mutex);
|
||||
if (flag == 1){
|
||||
|
||||
|
||||
double CCDistance = out_CCDistance.D();
|
||||
textPainter.putText(Paint, "焊印同心度:" + std::to_string(CCDistance), cv::Point(0, 50), cv::Scalar(0, 255, 0));
|
||||
|
||||
cv::circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 15);
|
||||
cv::circle(Paint, cv::Point(out_Circle[4].D(), out_Circle[3].D()), out_Circle[5].D(), cv::Scalar(0, 255, 0), 15);
|
||||
if (CCDistance > tongXingDuLimitHigh || CCDistance < tongXingDuLimitLow){
|
||||
textPainter.putText(Paint, "同心度NG", cv::Point(10, 450), cv::Scalar(0, 0, 255));
|
||||
data->halconOK = false;
|
||||
if(tongXingDuLimitEnable == true)
|
||||
isNg = true;
|
||||
}
|
||||
}
|
||||
else{
|
||||
textPainter.putText(Paint, "焊印抓取NG", cv::Point(10, 150), cv::Scalar(0, 0, 255));
|
||||
textPainter.putText(Paint, gbkToUtf8(out_NgTails.ToString().Text()), cv::Point(10, 450), cv::Scalar(0, 0, 255));
|
||||
if (tongXingDuLimitEnable == true)
|
||||
isNg = true;
|
||||
data->halconOK = false;
|
||||
}
|
||||
return isNg;
|
||||
}
|
||||
bool HanHou2D_handleAiEvaluate(std::shared_ptr <detData> data, hanHouJianCe* _detParams,const cv::Mat& sourceImg, cv::Mat& Paint,QMutex* mutex,cv::Point paintOffset) {
|
||||
double hanZhaFillterWidth = data->service->_paramSyncManager->get("焊后", "焊渣过滤值宽mm(上限)", 0.1).toDouble()/ 0.013736;
|
||||
double hanZhaFillterHeight = data->service->_paramSyncManager->get("焊后", "焊渣过滤值高mm(上限)", 0.1).toDouble()/ 0.013736;
|
||||
bool hanZhaEnable = data->service->_paramSyncManager->get("焊后", "焊渣判定启用", false).toBool();
|
||||
|
||||
cv::Mat forSeg;
|
||||
cv::resize(sourceImg, forSeg, cv::Size(), 0.5, 0.5);
|
||||
|
||||
cv::Mat SegResult = ~_detParams->seg_rljHanZha->Evaluate(forSeg);
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
cv::findContours(SegResult, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
|
||||
std::vector<cv::Rect> PaintRects;
|
||||
bool isNg = false;;
|
||||
for (int i = 0; i < contours.size(); i++) {
|
||||
cv::Rect rect = cv::boundingRect(contours[i]);
|
||||
if (rect.width > hanZhaFillterWidth || rect.height > hanZhaFillterHeight) {
|
||||
cv::Mat img = cutImg2Cls(rect, forSeg);
|
||||
bool clsIsNg = false;
|
||||
int clsRes = _detParams->cls_rljHanZha->Evaluate(img);
|
||||
if (clsRes == 1)
|
||||
clsIsNg = true;
|
||||
if (clsIsNg == true) {
|
||||
rect.x *= 2; rect.y *= 2; rect.width *= 2; rect.height *= 2;
|
||||
PaintRects.push_back(rect);
|
||||
isNg = true;
|
||||
}
|
||||
data->clsOriginImgs.push_back({ clsIsNg == true ? "NG" : "OK",img });
|
||||
}
|
||||
}
|
||||
QMutexLocker locker(mutex);
|
||||
for (auto& rect : PaintRects) {
|
||||
cv::rectangle(Paint, rect, cv::Scalar(0, 0, 255), 3);
|
||||
}
|
||||
return isNg;
|
||||
}
|
||||
bool HanHouJianCe2D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx_581_address address){
|
||||
try
|
||||
{
|
||||
|
||||
QString sqlText1 = "焊后同心度结果";
|
||||
QString sqlText2 = "焊后铜极同心度";
|
||||
QString sqlText3 = "焊后铝极同心度";
|
||||
QString sqlText4 = "焊后2dCT";
|
||||
data->oriImgs.clear();
|
||||
data->oriImgs.push_back(cv::imread("D:\\testImage\\rlj_hh_t.bmp",-1));
|
||||
data->oriImgs.push_back(cv::imread("D:\\testImage\\rlj_hh_t.bmp", -1));
|
||||
if (data->oriImgs.size() <= 1) {
|
||||
exceptionResume(data, _detParams, address, "图片数量不满足");
|
||||
return true;
|
||||
}
|
||||
cv::Mat Paint1, Paint2;
|
||||
data->oriImgs[0].copyTo(Paint1);
|
||||
data->oriImgs[1].copyTo(Paint2);
|
||||
if (Paint1.channels() == 1) {
|
||||
cvtColor(Paint1, Paint1, cv::COLOR_GRAY2BGR);
|
||||
}
|
||||
if (Paint2.channels() == 1) {
|
||||
cvtColor(Paint2, Paint2, cv::COLOR_GRAY2BGR);
|
||||
}
|
||||
QMutex mutex1, mutex2;
|
||||
HanHou2D_handleAiEvaluate(data, _detParams, data->oriImgs[0], Paint1, &mutex1, cv::Point(0,0));
|
||||
QByteArray plcResult = "1";
|
||||
double hanHouTongXingDu1 = -1;
|
||||
double hanHouTongXingDu2 = -1;
|
||||
cv::Mat forSeg1, forSeg2;
|
||||
double resizeRate = 0.25;
|
||||
cv::resize(data->oriImgs[0], forSeg1, cv::Size(), resizeRate, resizeRate);
|
||||
cv::Mat seg1 = _detParams->seg_rljHanYinZhuaQu->Evaluate(forSeg1);
|
||||
data->segOriginImgs.push_back(seg1);
|
||||
cv::Rect tongRect = findMaxAreaContour(~seg1);
|
||||
//cv::Point tongCenter(tongRect.x + tongRect.width / 2, tongRect.y + tongRect.height / 2);
|
||||
|
||||
cv::resize(data->oriImgs[1], forSeg2, cv::Size(), resizeRate, resizeRate);
|
||||
cv::Mat seg2 = _detParams->seg_rljHanYinZhuaQu->Evaluate(forSeg2);
|
||||
data->segOriginImgs.push_back(seg2);
|
||||
cv::Rect lvRect = findMaxAreaContour(~seg2);
|
||||
//cv::Point lvCenter(lvRect.x + lvRect.width / 2, lvRect.y + lvRect.height / 2);
|
||||
|
||||
|
||||
auto futrue1 = std::async(std::launch::async, &HanHou2D_halconEvaluate, data, data->oriImgs[0], seg1, std::ref(Paint1), std::ref(hanHouTongXingDu1), 0, &mutex1);
|
||||
auto futrue2 = std::async(std::launch::async, &HanHou2D_halconEvaluate, data, data->oriImgs[1], seg2, std::ref(Paint2), std::ref(hanHouTongXingDu2), 2, &mutex2);
|
||||
|
||||
|
||||
//auto futrue3 = std::async(std::launch::async, &HanHou2D_handleAiEvaluate, data, _detParams, data->oriImgs[0], std::ref(Paint1), &mutex1);
|
||||
//auto futrue4 = std::async(std::launch::async, &HanHou2D_handleAiEvaluate, data, _detParams, data->oriImgs[1], std::ref(Paint2), &mutex2);
|
||||
|
||||
auto tongClsImg = cutImg2Cls(tongRect, forSeg1, cv::Size(256, 256));
|
||||
data->clsOriginImgs.push_back({ "HY",tongClsImg });
|
||||
|
||||
auto lvClsImg = cutImg2Cls(lvRect, forSeg2, cv::Size(256, 256));
|
||||
int lvClsRes = _detParams->cls_hanYinLv->Evaluate(lvClsImg);
|
||||
data->clsOriginImgs.push_back({ "HY",lvClsImg });
|
||||
|
||||
futrue1.wait();
|
||||
futrue2.wait();
|
||||
bool isNg1 = futrue1.get(), isNg2 = futrue2.get();
|
||||
|
||||
//futrue3.wait();
|
||||
//futrue4.wait();
|
||||
|
||||
//futrue3.get();
|
||||
//futrue4.get();
|
||||
|
||||
TextRendererZH textPainter(Paint2.cols, Paint2.rows, 100);
|
||||
if (lvClsRes == 1) {
|
||||
textPainter.putText(Paint2, "CLS-NG", cv::Point(0, 350), cv::Scalar(0, 0, 255));
|
||||
if (data->service->_paramSyncManager->get("焊后", "焊印CLS判定启用", true).toBool()) {
|
||||
isNg2 = true;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint2, "CLS-OK", cv::Point(0, 350), cv::Scalar(0, 255, 0));
|
||||
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(hanHouTongXingDu1));
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(hanHouTongXingDu2));
|
||||
|
||||
|
||||
|
||||
if (isNg1 == true || isNg2 == true) {//判断存图
|
||||
data->halconOK = false;
|
||||
}
|
||||
|
||||
if (isNg1 == false && isNg2 == false) {//都OK发1
|
||||
plcResult = "1";
|
||||
}
|
||||
else if (isNg1 == true && isNg2 == false)//第一次NG发2
|
||||
plcResult = "2";
|
||||
else if (isNg1 == false && isNg2 == true)//第二次NG发3
|
||||
plcResult = "3";
|
||||
else if (isNg1 == true && isNg2 == true)//两次都NG发4
|
||||
plcResult = "4";
|
||||
else//为了DEBUG
|
||||
plcResult = "5";
|
||||
//plcResult = "1";
|
||||
cv::Mat PaintSum;
|
||||
cv::vconcat(Paint1, Paint2, PaintSum);
|
||||
data->resultImgs.push_back(PaintSum);
|
||||
if (data->service->_paramSyncManager->get("通用设置","强制OK", false).toBool())
|
||||
plcResult = "1";
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);
|
||||
return true;
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
exceptionResume(data, _detParams, address, "检测失败");
|
||||
qDebug() << "[Error] " << QString::fromUtf8("检测失败!");
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
bool HanHouJianCe3D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx_581_address address) {
|
||||
try {
|
||||
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
|
||||
std::vector < std::string> defects = { };
|
||||
///////////////////取图//处理//////////////////
|
||||
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;
|
||||
}
|
||||
|
||||
cv::Mat Paint;
|
||||
QMutex paintMutex;
|
||||
clock_t start, finish;
|
||||
start = clock();
|
||||
cv::Mat src1 = data->oriImgs[0];
|
||||
if (src1.channels() != 3)
|
||||
cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR);
|
||||
else
|
||||
src1.copyTo(Paint);
|
||||
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 300);
|
||||
textPainter.putText(Paint, "OK", 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->writeShort("D" + address.resultAddr + "_1");//发送结果
|
||||
//data->service->_missionResultHandle->toBarChart(data->SNcode, !defects.size() > 0, defects);//发送图标操作
|
||||
data->resultImgs.push_back(Paint);
|
||||
return true;
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
exceptionResume(data, _detParams, address, "检测失败");
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
mission* createMission() {
|
||||
return new _581_Ruanlianjie_hanqian_hanhou();
|
||||
}
|
||||
void destroyMission(mission* _mission) {
|
||||
delete _mission;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <missionBase.hpp>
|
||||
#include <sxGlobal.h>
|
||||
#include <simpleAlgo.h>
|
||||
#include <hdevengine/HDevEngineCpp.h>
|
||||
#include <Halcon.h>
|
||||
#include <HalconCpp.h>
|
||||
#include <qmutex.h>
|
||||
#include <qqueue.h>
|
||||
#include <opencvPaintAlgo.hpp>
|
||||
using namespace HDevEngineCpp;
|
||||
using namespace HalconCpp;
|
||||
class hanQianDingWeiParams {
|
||||
|
||||
};
|
||||
class hanHouJianCe {
|
||||
public:
|
||||
handdleAI::pSegmentation* seg_rljHanYinZhuaQu = nullptr;
|
||||
handdleAI::pSegmentation* seg_rljHanZha = nullptr;
|
||||
handdleAI::pClassification* cls_rljHanZha = nullptr;
|
||||
handdleAI::pClassification* cls_hanYinLv = nullptr;
|
||||
};
|
||||
|
||||
bool HanQianDingWei(std::shared_ptr <detData> data, hanQianDingWeiParams* _detParams, sx_581_address address);
|
||||
bool HanHouJianCe2D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx_581_address address);
|
||||
bool HanHouJianCe3D(std::shared_ptr <detData> data, hanHouJianCe* _detParams, sx_581_address address);
|
||||
|
||||
class _581_Ruanlianjie_hanqian_hanhou : public mission {
|
||||
public:
|
||||
|
||||
_581_SX_Single_triggerTemplate<hanQianDingWeiParams> dingwei_1;
|
||||
_581_SX_Single_triggerTemplate<hanQianDingWeiParams> dingwei_2;
|
||||
|
||||
_581_SX_Single_triggerTemplate<hanHouJianCe> jiance_2d_1;
|
||||
_581_SX_Single_triggerTemplate<hanHouJianCe> jiance_2d_2;
|
||||
_581_SX_Single_triggerTemplate<hanHouJianCe> jiance_3d_1;
|
||||
_581_SX_Single_triggerTemplate<hanHouJianCe> jiance_3d_2;
|
||||
|
||||
hanQianDingWeiParams hanqiandingweiparams;
|
||||
std::vector<hanHouJianCe>hanhoujiance2dparams = std::vector<hanHouJianCe>(2);
|
||||
hanHouJianCe hanhoujiance3dparams;
|
||||
|
||||
bool initOnce = false;
|
||||
void onConfigReloaded() {
|
||||
HDevEngineCpp::HDevEngine myEngine;
|
||||
myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl");
|
||||
|
||||
if (initOnce == false) {
|
||||
|
||||
/*hanhoujiance2dparams[0].seg_rljHanYinZhuaQu = handdleAI::CreateSegObjS("./handleAiModels/seg_rljHanYinZhuaQu.BHD", 64, 0);
|
||||
hanhoujiance2dparams[1].seg_rljHanYinZhuaQu = handdleAI::CreateSegObjS("./handleAiModels/seg_rljHanYinZhuaQu.BHD", 64, 1);*/
|
||||
|
||||
hanhoujiance2dparams[0].seg_rljHanZha = handdleAI::CreateSegObjS("./handleAiModels/rlj/seg_rljHanZha.BHD", 64, 0);
|
||||
//hanhoujiance2dparams[1].seg_rljHanZha = handdleAI::CreateSegObjS("./handleAiModels/seg_rljHanZha.BHD", 64, 1);
|
||||
|
||||
hanhoujiance2dparams[0].cls_rljHanZha = handdleAI::CreateClsObjV3("./handleAiModels/rlj/cls_rljHanZha.BHD", 0, 1);
|
||||
//hanhoujiance2dparams[1].cls_rljHanZha = handdleAI::CreateClsObjV3("./handleAiModels/cls_rljHanZha.BHD", 1, 1);
|
||||
|
||||
//hanhoujiance2dparams[0].cls_hanYinLv = handdleAI::CreateClsObjV3("./handleAiModels/cls_hanYinLv.BHD", 0, 1);
|
||||
//hanhoujiance2dparams[1].cls_hanYinLv = handdleAI::CreateClsObjV3("./handleAiModels/cls_hanYinLv.BHD", 1, 1);
|
||||
initOnce = true;
|
||||
}
|
||||
}
|
||||
bool initCustom() {
|
||||
#pragma region 注册触发器回调
|
||||
dingwei_1.init("Camera1", "焊前定位-相机1(前)", { { 4900, 1,{4910},"4902","4904",4930} }, 1, &hanqiandingweiparams, _serviceManager, bridge, HanQianDingWei,"焊前定位CCD");
|
||||
dingwei_2.init("Camera2", "焊前定位-相机2(后)", { { 5800, 1,{5810},"5802","5804",5830} }, 1, &hanqiandingweiparams, _serviceManager, bridge, HanQianDingWei,"焊前定位CCD");
|
||||
|
||||
jiance_2d_1.init("Camera3", "焊后检测2D-相机1(前)", { { 5400, 1,{5410},"5402","5404",5430} }, 2, &hanhoujiance2dparams[0], _serviceManager, bridge, HanHouJianCe2D, "焊后检测CCD");
|
||||
jiance_3d_1.init("Camera4", "焊后检测3D-相机1(前)", { { 5500, 1,{5510},"5502","5504",5530} }, 1, &hanhoujiance3dparams, _serviceManager, bridge, HanHouJianCe3D,"焊后检测CCD");
|
||||
jiance_2d_2.init("Camera5", "焊后检测2D-相机2(后)", { { 5600, 1,{5610},"5602","5604",5630} }, 2, &hanhoujiance2dparams[1], _serviceManager, bridge, HanHouJianCe2D, "焊后检测CCD");
|
||||
jiance_3d_2.init("Camera6", "焊后检测3D-相机2(后)", { { 5700, 1,{5710},"5702","5704",5730} }, 1, &hanhoujiance3dparams, _serviceManager, bridge, HanHouJianCe3D,"焊后检测CCD");
|
||||
#pragma endregion
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
@@ -0,0 +1,77 @@
|
||||
# 获取获取当前目录名
|
||||
get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
|
||||
set(DLL_NAMES "opencv" "halcon" "handdleAI")
|
||||
foreach(child ${DLL_NAMES})
|
||||
LIST(APPEND ENV_INCLUDE ${${child}_include})
|
||||
LIST(APPEND ENV_LIB ${${child}_lib})
|
||||
LIST(APPEND ENV_TARGET ${${child}_target_link})
|
||||
endforeach()
|
||||
message(" ENV_INCLUDE : " ${ENV_INCLUDE} )
|
||||
message(" ENV_LIB : " ${ENV_LIB} )
|
||||
message(" ENV_TARGET : " ${ENV_TARGET} )
|
||||
include_directories(
|
||||
${PROJECT_ROOT_PATH}/src/core
|
||||
${PROJECT_ROOT_PATH}/src/core/handleAi
|
||||
${PROJECT_ROOT_PATH}/src/core/service
|
||||
${PROJECT_ROOT_PATH}/src/core/sql
|
||||
${ENV_INCLUDE}
|
||||
)
|
||||
|
||||
link_directories (
|
||||
${ENV_LIB}
|
||||
|
||||
)
|
||||
add_compile_options(/utf-8)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
SET(CMAKE_AUTOUIC OFF)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
FILE(GLOB HEAD_FILES "*.h" )
|
||||
FILE(GLOB SRC_FILES "./*.cpp")
|
||||
FILE(GLOB UI_FILES "./*.ui")
|
||||
|
||||
|
||||
#find_package(Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network REQUIRED)
|
||||
|
||||
add_library(${CURRENT_FOLDER} SHARED
|
||||
${HEAD_FILES}
|
||||
${SRC_FILES}
|
||||
${UI_FILES}
|
||||
${PROJECT_ROOT_PATH}/include/interface.h
|
||||
)
|
||||
|
||||
|
||||
|
||||
set_target_properties(${CURRENT_FOLDER} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
|
||||
target_link_libraries(${CURRENT_FOLDER} PRIVATE
|
||||
${ENV_TARGET}
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Gui
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
)
|
||||
|
||||
|
||||
# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY)
|
||||
|
||||
|
||||
|
||||
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " modelx end : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
message( " header files "${HEAD_FILES})
|
||||
@@ -99,24 +99,25 @@ static bool BaoMoHou_ShangDaMian(std::shared_ptr <detData> data, baoMoHouDaMianD
|
||||
HTuple out_Line = procedureCall.GetOutputCtrlParamTuple("out_Line");
|
||||
HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");
|
||||
int outFlag = out_Flag.D();
|
||||
double batteryWidth = -99, batteryHeight = -99, moDaoDingGai = -99;
|
||||
// handleAiFuture.wait();
|
||||
//auto defects = handleAiFuture.get();
|
||||
if (outFlag == 1) {
|
||||
for (int i = 0; i < out_Line.Length() / 4; i++) {
|
||||
cv::line(Paint, cv::Point(out_Line[i * 4 + 1].D(), out_Line[i * 4].D()) / 2,
|
||||
cv::Point(out_Line[i * 4 + 3].D(), out_Line[i * 4 + 2].D()) / 2,
|
||||
//out_Distance[0]: 电芯宽度 < / c>
|
||||
// <c>* out_Distance[1] : 电芯高度< / c>
|
||||
// <c>* out_Distance[2] : 上端盖到膜的距离< / c>
|
||||
// <c>* out_Distance[3] : 中端盖到膜的距离< / c>
|
||||
// <c>* out_Distance[4] : 下端盖到膜的距离 < / c>
|
||||
textPainter.putText(Paint, "电芯宽度:" + std::to_string(out_Distance[0].D()) + "mm", cv::Point(50, 150), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "电芯高度:" + std::to_string(out_Distance[1].D()) + "mm", cv::Point(50, 350), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "上端盖到膜的距离:" + std::to_string(out_Distance[2].D()) + "mm", cv::Point(50, 550), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "中端盖到膜的距离:" + std::to_string(out_Distance[3].D()) + "mm", cv::Point(50, 750), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "下端盖到膜的距离:" + std::to_string(out_Distance[4].D()) + "mm", cv::Point(50, 950), cv::Scalar(0, 255, 0));
|
||||
for (int i = 0; i < out_Line.Length() / 4 - 1; i++) {
|
||||
cv::line(Paint, cv::Point(out_Line[i * 4 + 1].D(), out_Line[i * 4].D()),
|
||||
cv::Point(out_Line[i * 4 + 3].D(), out_Line[i * 4 + 2].D()),
|
||||
cv::Scalar(0, 255, 0), 5);
|
||||
}
|
||||
/*out_Distance[0]: 上端盖到膜的距离< / c>
|
||||
<c>* out_Distance[1] : 中端盖到膜的距离< / c>
|
||||
<c>* out_Distance[2] : 下端盖到膜的距离< / c>
|
||||
<c>* out_Distance[3] : 电芯宽度 < / c>
|
||||
<c>* out_Distance[4] : 电芯高度< / c>*/
|
||||
textPainter.putText(Paint, "上端盖到膜的距离:" + std::to_string(out_Distance[0].D()) + "mm", cv::Point(50, 150), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "中端盖到膜的距离:" + std::to_string(out_Distance[1].D()) + "mm", cv::Point(50, 350), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "下端盖到膜的距离:" + std::to_string(out_Distance[2].D()) + "mm", cv::Point(50, 550), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "电芯宽度:" + std::to_string(out_Distance[3].D()) + "mm", cv::Point(50, 750), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "电芯高度:" + std::to_string(out_Distance[4].D()) + "mm", cv::Point(50, 950), cv::Scalar(0, 255, 0));
|
||||
}
|
||||
else {
|
||||
data->halconOK = false;
|
||||
@@ -125,8 +126,10 @@ static bool BaoMoHou_ShangDaMian(std::shared_ptr <detData> data, baoMoHouDaMianD
|
||||
|
||||
data->resultImgs.push_back(Paint);
|
||||
//data->service->_missionResultHandle->toBarChart(data->SNcode, !defects.size() > 0, defects);
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr)
|
||||
+ "_" + QByteArray::number(batteryWidth)
|
||||
+ "_" + QByteArray::number(batteryHeight)
|
||||
+ "_" + QByteArray::number(moDaoDingGai));
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,20 +3,135 @@
|
||||
#include <hdevengine/HDevEngineCpp.h>
|
||||
#include <opencvPaintAlgo.hpp>
|
||||
#include <yhGlobal.h>
|
||||
struct jiuPiamResult{
|
||||
QByteArray result = "2";
|
||||
QByteArray x = "1.1";
|
||||
QByteArray y = "1.1";
|
||||
};
|
||||
|
||||
|
||||
#pragma region 算法
|
||||
|
||||
using namespace HDevEngineCpp;
|
||||
|
||||
#pragma endregion
|
||||
void exceptionResume(std::shared_ptr<detData> data, detParams* _detParams, yh_581_address address, QString why = "") {
|
||||
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why;
|
||||
cv::Mat Paint;
|
||||
data->oriImgs[0].copyTo(Paint);
|
||||
if (Paint.channels() == 1)
|
||||
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
|
||||
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 300);
|
||||
textPainter.putText(Paint, why.toStdString(), cv::Point(500, 50), cv::Scalar(0, 255, 0));
|
||||
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
|
||||
data->resultImgs.push_back(Paint);
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_1,1,1,1,1,1,1,1,1,1,1,1,1,1");
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
|
||||
}
|
||||
static bool yuHanQian3D(std::shared_ptr <detData> data, detParams* _detParams, yh_581_address address) {
|
||||
try {
|
||||
double heightThreshold = data->service->_paramSyncManager->get("预焊前", "高度/台阶差最大阈值",0.3).toDouble();
|
||||
double widthThreshold = data->service->_paramSyncManager->get("预焊前", "缝隙值最大阈值", 0.1).toDouble();
|
||||
//data->oriImgs.clear();
|
||||
//data->oriImgs.push_back(cv::imread("D://readSnEmpty16-02-21-96_Camera4_0.tiff", -1));
|
||||
//data->oriImgs.push_back(cv::imread("D://readSnEmpty16-02-21-96_Camera4_1.tiff", -1));
|
||||
if (data->oriImgs.size() < 2) {
|
||||
exceptionResume(data, _detParams, address, "NG");
|
||||
return true;
|
||||
}
|
||||
cv::Mat heightImg = data->oriImgs[1];
|
||||
cv::Mat lumImg = data->oriImgs[0];
|
||||
cv::Mat Paint;
|
||||
|
||||
HalconCpp::HObject in_imageH = MatToHObject(heightImg);
|
||||
HalconCpp::HObject in_imageLum = MatToHObject(lumImg);
|
||||
HDevEngineCpp::HDevProcedure proc("_6_detect_gap_width_height");
|
||||
HDevProcedureCall procedureCall(proc);
|
||||
procedureCall.SetInputIconicParamObject("in_imageH", in_imageH);
|
||||
procedureCall.SetInputIconicParamObject("in_imageLum", in_imageLum);
|
||||
|
||||
procedureCall.SetInputCtrlParamTuple("in_xResolution", 0.005);
|
||||
procedureCall.SetInputCtrlParamTuple("in_yResolution", data->service->_paramSyncManager->get("3D设置", "3D相机Y方向精度",0.177).toFloat());
|
||||
procedureCall.SetInputCtrlParamTuple("in_zResolution", 0.0008);
|
||||
if(address.triggerAddr == 18000 || address.triggerAddr == 18002 || address.triggerAddr == 18400 || address.triggerAddr == 18402)
|
||||
procedureCall.SetInputCtrlParamTuple("in_Location", "Right");
|
||||
else
|
||||
procedureCall.SetInputCtrlParamTuple("in_Location", "Left");
|
||||
procedureCall.Execute();
|
||||
HObject out_DisplayImage = procedureCall.GetOutputIconicParamObject("out_DisplayImage");
|
||||
|
||||
HTuple out_MaxHeight = procedureCall.GetOutputCtrlParamTuple("out_MaxHeight");
|
||||
HTuple out_MaxWidth = procedureCall.GetOutputCtrlParamTuple("out_MaxWidth");
|
||||
HTuple out_ResultRow = procedureCall.GetOutputCtrlParamTuple("out_ResultRow");
|
||||
HTuple out_ResultColumn = procedureCall.GetOutputCtrlParamTuple("out_ResultColumn");
|
||||
HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");
|
||||
HTuple out_NgTails = procedureCall.GetOutputCtrlParamTuple("out_NgTails");
|
||||
HTuple out_DisplayRows = procedureCall.GetOutputCtrlParamTuple("out_DisplayRows");
|
||||
HTuple out_DisplayCols = procedureCall.GetOutputCtrlParamTuple("out_DisplayCols");
|
||||
int flag = out_Flag.D();
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 75);
|
||||
Paint = HObject2Mat(out_DisplayImage);
|
||||
textPainter.putText(Paint, data->SNcode, cv::Point(1600,50), cv::Scalar(0, 255, 0));
|
||||
bool isOK = true;
|
||||
QByteArray gaoDuChaSendText, fengXiSendText;
|
||||
if (flag == 1) {
|
||||
int yStart = -25;
|
||||
for (int i = 0; i < 4 && i < out_DisplayRows.Length(); i++) {
|
||||
double MaxHeight = std::abs(out_MaxHeight[i].D());
|
||||
double MaxWidth = std::abs(out_MaxWidth[i].D());
|
||||
|
||||
cv::Point displayPos( 1000, out_DisplayRows[i].D() - 50);
|
||||
textPainter.putText(Paint, "检测区域" + std::to_string(i + 1) + ":", displayPos, cv::Scalar(0, 255, 0));
|
||||
|
||||
displayPos.x += 280;
|
||||
if (std::abs(MaxHeight) > std::abs(heightThreshold)) {
|
||||
textPainter.putText(Paint, "高度/台阶差" + QString::number(MaxHeight, 'f', 3).toStdString() +"mm", displayPos, cv::Scalar(0, 0, 255));
|
||||
isOK = false;
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "高度/台阶差" + QString::number(MaxHeight, 'f', 3).toStdString() + "mm", displayPos, cv::Scalar(0, 255, 0));
|
||||
|
||||
displayPos.x += 600;
|
||||
if (std::abs(MaxWidth) > std::abs(widthThreshold)) {
|
||||
textPainter.putText(Paint, "缝隙值" + QString::number(MaxWidth, 'f', 3).toStdString() + "mm", displayPos, cv::Scalar(0, 0, 255));
|
||||
isOK = false;
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "缝隙值" + QString::number(MaxWidth, 'f', 3).toStdString() + "mm", displayPos, cv::Scalar(0, 255, 0));
|
||||
if (i != 2) {
|
||||
gaoDuChaSendText += QByteArray::number(MaxHeight) + ",";
|
||||
fengXiSendText += QByteArray::number(MaxWidth) + ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
gaoDuChaSendText = "-1,-1,-1,";
|
||||
fengXiSendText = "-1,-1,-1,";
|
||||
std::string ngDetailStr = gbkToUtf8(out_NgTails.ToString().Text());
|
||||
textPainter.putText(Paint, ngDetailStr.substr(1, ngDetailStr.length() - 2), cv::Point(50, 450), cv::Scalar(0, 0, 255));
|
||||
for (int i = 0; i < out_ResultRow.Length(); i++) {
|
||||
cv::circle(Paint, cv::Point(out_ResultRow[i].D(), out_ResultColumn[i].D()),1, cv::Scalar(0, 0, 255), 1);
|
||||
}
|
||||
data->halconOK = false;
|
||||
isOK = false;
|
||||
}
|
||||
QByteArray plcResult = "1";
|
||||
if (isOK == false) {
|
||||
textPainter.putText(Paint, "NG", cv::Point(50, 50), cv::Scalar(0, 0, 255));
|
||||
plcResult = "2";
|
||||
data->halconOK = false;
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "OK", cv::Point(50, 50), cv::Scalar(0, 255, 0));
|
||||
if (data->service->_paramSyncManager->get("通用设置", "强制OK", false).toBool())
|
||||
plcResult = "1";
|
||||
data->resultImgs.push_back(Paint);
|
||||
data->service->_triggerManager->writeFloat("D"
|
||||
+ QByteArray::number(address.valueOffsetAddr) + "_"
|
||||
+ fengXiSendText + "1,1,"
|
||||
+ gaoDuChaSendText + plcResult + "," + plcResult + "," + plcResult + "," + plcResult +"," + plcResult + "," + plcResult);//数值1
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
|
||||
return true;
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
exceptionResume(data, _detParams, address, "NG");
|
||||
return true;
|
||||
}
|
||||
class _581_Dgh : public mission {
|
||||
public:
|
||||
using generalTrigger = _581_Union_triggerTemplate<detParams>;
|
||||
@@ -33,19 +148,27 @@ public:
|
||||
|
||||
void onConfigReloaded() {
|
||||
HDevEngineCpp::HDevEngine myEngine;
|
||||
myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl");
|
||||
myEngine.SetProcedurePath("./halconAlgo/AlgoLibrary_602.hdpl");
|
||||
}
|
||||
bool initCustom() {
|
||||
#pragma region 注册触发器回调
|
||||
dgh_cb_yh_3d_1.init("Camera1", "长边预焊前3D-1", 18000,2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_yh_3d_2.init("Camera2", "长边预焊前3D-2", 18200,2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_yh_3d_3.init("Camera3", "长边预焊前3D-3", 18400,2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_yh_3d_4.init("Camera4", "长边预焊前3D-4", 18600,2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
|
||||
dgh_cb_yh_3d_1.init("Camera1", "长边预焊前3D-1", 18000,2,1, &_params, _serviceManager, bridge, yuHanQian3D);
|
||||
dgh_cb_yh_3d_1.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_yh_3d_2.init("Camera2", "长边预焊前3D-2", 18200,2,1, &_params, _serviceManager, bridge, yuHanQian3D);
|
||||
dgh_cb_yh_3d_2.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_yh_3d_3.init("Camera3", "长边预焊前3D-3", 18400,2,1, &_params, _serviceManager, bridge, yuHanQian3D);
|
||||
dgh_cb_yh_3d_3.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_yh_3d_4.init("Camera4", "长边预焊前3D-4", 18600,2,1, &_params, _serviceManager, bridge, yuHanQian3D);
|
||||
dgh_cb_yh_3d_4.address[1].valueOffsetAddr += 20;
|
||||
|
||||
dgh_cb_mh_3d_1.init("Camera5", "长边满焊前3D-1", 19600,2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_mh_3d_1.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_mh_3d_2.init("Camera6", "长边满焊前3D-2", 19800,2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_mh_3d_2.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_mh_3d_3.init("Camera7", "长边满焊前3D-3", 20000,2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_mh_3d_3.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_mh_3d_4.init("Camera8", "长边满焊前3D-4", 20200,2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_mh_3d_4.address[1].valueOffsetAddr += 20;
|
||||
#pragma endregion
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,13 +3,382 @@
|
||||
#include <hdevengine/HDevEngineCpp.h>
|
||||
#include <opencvPaintAlgo.hpp>
|
||||
#include <yhGlobal.h>
|
||||
|
||||
#pragma region 算法
|
||||
|
||||
using namespace HDevEngineCpp;
|
||||
#pragma region 辊压后2D算法
|
||||
|
||||
class GunYaHou2DParam {
|
||||
public:
|
||||
handdleAI::pSegmentation* seg = nullptr;
|
||||
handdleAI::pClassification* cls = nullptr;
|
||||
handdleAI::pDetection* det = nullptr;
|
||||
};
|
||||
void exceptionResume(std::shared_ptr<detData> data, GunYaHou2DParam* _detParams, yh_581_address address, QString why = "") {
|
||||
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why;
|
||||
cv::Mat Paint;
|
||||
data->oriImgs[0].copyTo(Paint);
|
||||
if (Paint.channels() == 1)
|
||||
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
|
||||
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 300);
|
||||
textPainter.putText(Paint, why.toStdString(), cv::Point(500, 50), cv::Scalar(0, 255, 0));
|
||||
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
|
||||
data->resultImgs.push_back(Paint);
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_1");//数值1
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_1");//数值2
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 4) + "_1");//数值3
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 6) + "_1");//数值4
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 8) + "_1");//数值5
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 10) + "_1");//数值6
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 12) + "_1");//数值7
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 14) + "_1");//数值8
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 16) + "_1");//数值9
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
|
||||
}
|
||||
cv::Mat LocalCutImg_DET(handdleAI::pDetection* pDet, cv::Mat src, float zoom, int checkNameId, cv::Rect& cutRoi)
|
||||
{
|
||||
cv::Mat dst;
|
||||
cv::resize(src, dst, cv::Size(src.cols / zoom, src.rows / zoom));
|
||||
std::vector<handdleAI::Bbox> resultBox = pDet->Evaluate(dst); //结果为中心点+宽高
|
||||
|
||||
cv::Mat contourImg;
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
//cv::threshold(dstImg, contourImg, pSeg->m_classes, 255, cv::THRESH_BINARY_INV);
|
||||
//cv::findContours(contourImg, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
|
||||
|
||||
cv::Mat roiImg;
|
||||
|
||||
if (resultBox.size() <= 0)
|
||||
{
|
||||
cv::Mat rstMat = cv::Mat(100, 100, CV_8UC1, cv::Scalar(0, 0, 0));
|
||||
cutRoi = cv::Rect(0, 0, 100, 100);
|
||||
return rstMat;
|
||||
}
|
||||
|
||||
double maxArea = 0;
|
||||
int index = -1;
|
||||
for (int j = 0; j < resultBox.size(); j++)
|
||||
{
|
||||
double area = resultBox[j].w * resultBox[j].h;
|
||||
if (area >= maxArea)
|
||||
{
|
||||
maxArea = area;
|
||||
index = j;
|
||||
}
|
||||
}
|
||||
|
||||
/*cv::Rect rect = cv::boundingRect(contours[index]);
|
||||
cv::rectangle(roiImg, cv::Rect(resultBox[j].x - resultBox[j].w / 2, resultBox[j].y - resultBox[j].h / 2, resultBox[j].w, resultBox[j].h), cv::Scalar(0, 0, 255), 5);*/
|
||||
int addpixel = 15;
|
||||
|
||||
cutRoi.x = ((resultBox[index].x - resultBox[index].w / 2) * zoom);
|
||||
cutRoi.y = ((resultBox[index].y - resultBox[index].h / 2) * zoom);
|
||||
cutRoi.width = (resultBox[index].w * zoom);
|
||||
cutRoi.height = (resultBox[index].h * zoom);
|
||||
//cv::rectangle(src, cutRoi, cv::Scalar(0, 0, 255), 2, 8);
|
||||
/* cutRoi.x = rect.x * zoom;
|
||||
cutRoi.y = rect.y * zoom;
|
||||
cutRoi.width = rect.width * zoom;
|
||||
cutRoi.height = rect.height * zoom;*/
|
||||
|
||||
src(cutRoi).copyTo(roiImg);
|
||||
return roiImg;
|
||||
}
|
||||
static std::vector<cv::Mat>dingGaiHanClsCut(cv::Rect boundingBox, cv::Mat imgInput, cv::Size targetSize = cv::Size(128, 128))
|
||||
{
|
||||
std::vector<cv::Mat> result;
|
||||
int splitCount = std::max(boundingBox.width, boundingBox.height) / std::max(boundingBox.width, boundingBox.height);
|
||||
//std::cout << "splitCount" << splitCount;
|
||||
if (splitCount > 2) {//大于2分段裁
|
||||
if (boundingBox.width > boundingBox.height) {//宽大于高,横着裁
|
||||
for (int i = 0; i < splitCount; i++) {
|
||||
result.push_back(cutImg2Cls(cv::Rect(boundingBox.x + boundingBox.height * i, boundingBox.y, boundingBox.height, boundingBox.height), imgInput));
|
||||
}
|
||||
result.push_back(cutImg2Cls(cv::Rect(boundingBox.x + boundingBox.width - boundingBox.height, boundingBox.y, boundingBox.height, boundingBox.height), imgInput));
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < splitCount; i++) {
|
||||
result.push_back(cutImg2Cls(cv::Rect(boundingBox.x, boundingBox.y + boundingBox.width * i, boundingBox.width, boundingBox.width), imgInput));
|
||||
}
|
||||
result.push_back(cutImg2Cls(cv::Rect(boundingBox.x, boundingBox.y + boundingBox.height - boundingBox.width, boundingBox.width, boundingBox.width), imgInput));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return std::vector<cv::Mat>(1, cutImg2Cls(boundingBox, imgInput, targetSize));
|
||||
}
|
||||
bool handleAiEvaluate(std::shared_ptr <detData> data, GunYaHou2DParam* _detParams, cv::Mat& srcImg, cv::Mat& showImg) {
|
||||
bool handleAiResultIsOK = true;
|
||||
clock_t start = clock();
|
||||
|
||||
|
||||
//DET方案
|
||||
// cv::Mat imgForDet;
|
||||
//srcImg.copyTo(imgForDet);
|
||||
//cv::Rect detRect;
|
||||
//cv::Mat det_Image = LocalCutImg_DET(_detParams->det, imgForDet, 1, 0, detRect);
|
||||
|
||||
//固定坐标方案
|
||||
//cv::Rect detRect(150, 1400, 3800, 300);
|
||||
//cv::Mat det_Image;
|
||||
//srcImg(detRect).copyTo(det_Image);
|
||||
|
||||
//cv::rectangle(showImg, detRect, cv::Scalar(0, 255, 255), 2);
|
||||
//cv::Mat segImg = ~_detParams->seg->Evaluate(det_Image);//一定要取反,因为seg默认抓到的区域为黑色
|
||||
//data->segOriginImgs.push_back(det_Image);
|
||||
cv::Mat det_Image = srcImg;
|
||||
cv::Mat segImg = ~_detParams->seg->Evaluate(det_Image);//一定要取反,因为seg默认抓到的区域为黑色
|
||||
clock_t stop = clock();
|
||||
std::vector<std::vector<cv::Point>>contours;//点集
|
||||
stop = clock();
|
||||
cv::findContours(segImg, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); // 寻找白色区域并储存为点集
|
||||
//QMutexLocker lock(showImgLocker);//加锁防止和halcon线程冲突
|
||||
int clsResult = 0;
|
||||
for (int i = 0; i < contours.size(); i++)//遍历点集
|
||||
{
|
||||
cv::Rect rect = cv::boundingRect(contours[i]);//最小外接矩形
|
||||
//if( (rect.height > 25 || rect.width > 50) && (rect.height > 10 && rect.width > 10))// 过滤
|
||||
if ((rect.height > 40 || rect.width > 100) && (rect.height > 30 && rect.width > 10))
|
||||
{
|
||||
auto clsimgs = dingGaiHanClsCut(rect, det_Image);
|
||||
bool isNg = false;
|
||||
int cnt = 0;
|
||||
for (auto& clsImg : clsimgs)
|
||||
{
|
||||
clsResult = _detParams->cls->Evaluate(clsImg);//cls检测 得出的是int型 从0开始
|
||||
if (clsResult == 1 || clsResult == 3) {
|
||||
isNg = true;
|
||||
}
|
||||
//addImgToSaveStruct(clsImg, "0", savePath_sorce + "/" + SN + "_cls" + QString::number(clsResult) + "_" + sdataTime_name + ".bmp");
|
||||
data->clsOriginImgs.push_back({ std::to_string(clsResult),clsImg });
|
||||
cnt++;
|
||||
drawContours(showImg, contours, i, cv::Scalar(0, 255, 0), 1);
|
||||
}
|
||||
if (isNg == true)
|
||||
{
|
||||
rectangle(showImg, cv::Rect{ rect.x,rect.y,rect.width ,rect.height }, cv::Scalar(0, 0, 255), 2, 8, 0);
|
||||
//drawContours(showImg(detRect), contours, i, cv::Scalar(0, 255, 0), 1);
|
||||
handleAiResultIsOK = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clsResult == 2)
|
||||
{
|
||||
rectangle(showImg, cv::Rect{ rect.x,rect.y,rect.width ,rect.height }, cv::Scalar(0, 255, 255), 2, 8, 0);
|
||||
//drawContours(showImg(detRect), contours, i, cv::Scalar(0, 255, 0), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto clsimgs = dingGaiHanClsCut(rect, det_Image);
|
||||
int cnt = 0;
|
||||
for (auto& clsImg : clsimgs)
|
||||
{
|
||||
data->clsOriginImgs.push_back({ std::to_string(clsResult),clsImg });
|
||||
//addImgToSaveStruct(clsImg, "0", savePath_sorce + "/CSSMALL_" + SN + "_" + sdataTime_name + ".bmp");
|
||||
cnt++;
|
||||
drawContours(showImg, contours, i, cv::Scalar(0, 255, 0), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return handleAiResultIsOK;
|
||||
}
|
||||
|
||||
static bool GunYaHou2D(std::shared_ptr <detData> data, GunYaHou2DParam* _detParams, yh_581_address address) {
|
||||
try {
|
||||
//data->oriImgs.clear();
|
||||
//data->oriImgs.push_back(cv::imread("D://04QCB82601000JFB50000011_Camera7_0.bmp", -1));
|
||||
//data->oriImgs.push_back(cv::imread("D://04QCB82601000JFB50000011_Camera8_0.bmp", -1));
|
||||
cv::Mat sourceImg1 = data->oriImgs[0], sourceImg2 = data->oriImgs[1];
|
||||
cv::Mat Paint1,Paint2;
|
||||
sourceImg1.copyTo(Paint1);
|
||||
sourceImg2.copyTo(Paint2);
|
||||
if (Paint1.channels() == 1)
|
||||
cvtColor(Paint1, Paint1, cv::COLOR_GRAY2BGR);
|
||||
if (Paint2.channels() == 1)
|
||||
cvtColor(Paint2, Paint2, cv::COLOR_GRAY2BGR);
|
||||
bool isOK = handleAiEvaluate(data, _detParams, sourceImg1, Paint1);
|
||||
isOK = handleAiEvaluate(data, _detParams, sourceImg2, Paint2);
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_1");//数值1
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_1");//数值2
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 4) + "_1");//数值3
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 6) + "_1");//数值4
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 8) + "_1");//数值5
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 10) + "_1");//数值6
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 12) + "_1");//数值7
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 14) + "_1");//数值8
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 16) + "_1");//数值9
|
||||
if (isOK == true)
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
|
||||
else
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
|
||||
|
||||
{
|
||||
TextRendererZH textPainter(Paint1.cols, Paint1.rows, 300);
|
||||
if (isOK == true) {
|
||||
textPainter.putText(Paint1, "OK", cv::Point(0, 200), cv::Scalar(0, 255, 0));
|
||||
}
|
||||
else {
|
||||
textPainter.putText(Paint1, "NG", cv::Point(0, 200), cv::Scalar(0, 0, 255));
|
||||
data->aiDetOK = false;
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, true, { "焊后NG" });
|
||||
qDebug() << QString::fromStdString(data->SNcode) << "is NG";
|
||||
}
|
||||
|
||||
cv::resize(Paint1, Paint1, cv::Size(), 0.5, 0.5);
|
||||
data->resultImgs.push_back(Paint1);
|
||||
}
|
||||
{
|
||||
TextRendererZH textPainter(Paint2.cols, Paint2.rows, 300);
|
||||
if (isOK == true) {
|
||||
textPainter.putText(Paint2, "OK", cv::Point(0, 200), cv::Scalar(0, 255, 0));
|
||||
}
|
||||
else {
|
||||
textPainter.putText(Paint2, "NG", cv::Point(0, 200), cv::Scalar(0, 0, 255));
|
||||
data->aiDetOK = false;
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, true, { "焊后NG" });
|
||||
qDebug() << QString::fromStdString(data->SNcode) << "is NG";
|
||||
}
|
||||
|
||||
cv::resize(Paint2, Paint2, cv::Size(), 0.5, 0.5);
|
||||
data->resultImgs.push_back(Paint2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
exceptionResume(data, _detParams, address, "算法异常");
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
#pragma region 辊压后3D算法
|
||||
static bool gunYaHou3D(std::shared_ptr <detData> data, detParams* _detParams, yh_581_address address) {
|
||||
try {
|
||||
/* double heightThreshold = data->service->_paramSyncManager->get("预焊前", "高度/台阶差最大阈值", 0.3).toDouble();
|
||||
double widthThreshold = data->service->_paramSyncManager->get("预焊前", "缝隙值最大阈值", 0.1).toDouble();*/
|
||||
//data->oriImgs.clear();
|
||||
//data->oriImgs.push_back(cv::imread("D://readSnEmpty16-02-21-96_Camera4_0.tiff", -1));
|
||||
//data->oriImgs.push_back(cv::imread("D://readSnEmpty16-02-21-96_Camera4_1.tiff", -1));
|
||||
if (data->oriImgs.size() < 2) {
|
||||
generalExceptionResume(data, address, "NG");
|
||||
return true;
|
||||
}
|
||||
cv::Mat heightImg = data->oriImgs[1];
|
||||
cv::Mat lumImg = data->oriImgs[0];
|
||||
cv::Mat Paint;
|
||||
|
||||
HalconCpp::HObject in_imageH = MatToHObject(heightImg);
|
||||
HalconCpp::HObject in_imageLum = MatToHObject(lumImg);
|
||||
HDevEngineCpp::HDevProcedure proc("_6_Inspection_Defect_3D");
|
||||
HDevProcedureCall procedureCall(proc);
|
||||
procedureCall.SetInputIconicParamObject("in_imageH", in_imageH);
|
||||
|
||||
procedureCall.SetInputCtrlParamTuple("in_xResolution", 0.005);
|
||||
procedureCall.SetInputCtrlParamTuple("in_yResolution", data->service->_paramSyncManager->get("3D设置", "3D相机Y方向精度", 0.177).toFloat());
|
||||
procedureCall.SetInputCtrlParamTuple("in_zResolution", 0.0008);
|
||||
procedureCall.Execute();
|
||||
|
||||
HTuple out_DefectHeight = procedureCall.GetOutputCtrlParamTuple("out_DefectHeight");
|
||||
HTuple out_DefectRec = procedureCall.GetOutputCtrlParamTuple("out_DefectRec");
|
||||
HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");
|
||||
|
||||
int flag = out_Flag.D();
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 75);
|
||||
textPainter.putText(Paint, data->SNcode, cv::Point(1600, 50), cv::Scalar(0, 255, 0));
|
||||
bool isOK = true;
|
||||
QByteArray textSend;
|
||||
if (flag == 1) {
|
||||
int yStart = -25;
|
||||
for (int i = 0; i < out_DefectHeight .Length(); i++) {
|
||||
double value = out_DefectHeight[i].D();
|
||||
cv::Rect rect(out_DefectRec[i * 4], out_DefectRec[i * 4] + 1, out_DefectRec[i * 4 + 2], out_DefectRec[i * 4 + 3]);
|
||||
textSend += QByteArray::number(value) + ",";
|
||||
data->halconOK = false;
|
||||
isOK = false;
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray plcResult = "1";
|
||||
if (isOK == false) {
|
||||
textPainter.putText(Paint, "NG", cv::Point(50, 50), cv::Scalar(0, 0, 255));
|
||||
plcResult = "2";
|
||||
data->halconOK = false;
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "OK", cv::Point(50, 50), cv::Scalar(0, 255, 0));
|
||||
|
||||
data->resultImgs.push_back(Paint);
|
||||
data->service->_triggerManager->writeFloat("D"
|
||||
+ QByteArray::number(address.valueOffsetAddr) + "_"
|
||||
+ textSend + "1");//数值1
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
|
||||
return true;
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
generalExceptionResume(data, address, "NG");
|
||||
return true;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
static bool generalAlgoTestDuanBian(std::shared_ptr <detData> data, detParams* _detParams, yh_581_address address) {
|
||||
try {
|
||||
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
|
||||
data->customPath = "{imgSaveRootDir}/{yyyy-MM-dd}/{saveObjectName}{imageType}/{HH}H/{processResult}/";
|
||||
std::vector < std::string> defects = { "测试" };
|
||||
///////////////////取图//处理//////////////////
|
||||
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;
|
||||
}
|
||||
|
||||
cv::Mat Paint;
|
||||
QMutex paintMutex;
|
||||
clock_t start, finish;
|
||||
start = clock();
|
||||
cv::Mat src1 = data->oriImgs[0];
|
||||
if (src1.channels() != 3)
|
||||
cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR);
|
||||
else
|
||||
src1.copyTo(Paint);
|
||||
|
||||
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) + "_1");//数值1
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_1");//数值2
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 4) + "_1");//数值3
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 6) + "_1");//数值4
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 8) + "_1");//数值5
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 10) + "_1");//数值6
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 12) + "_1");//数值7
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 14) + "_1");//数值8
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 16) + "_1");//数值9
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
|
||||
data->service->_missionResultHandle->toBarChart(data->SNcode, !defects.size() > 0, defects);//发送图标操作
|
||||
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
|
||||
data->resultImgs.push_back(Paint);
|
||||
return true;
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_1");//数值1
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_1");//数值2
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 4) + "_1");//数值3
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 6) + "_1");//数值4
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 8) + "_1");//数值5
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 10) + "_1");//数值6
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 12) + "_1");//数值7
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 14) + "_1");//数值8
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 16) + "_1");//数值9
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送异常结果
|
||||
return false;
|
||||
}
|
||||
class _581_Dgh : public mission {
|
||||
public:
|
||||
using generalTrigger = _581_Union_triggerTemplate<detParams>;
|
||||
@@ -18,41 +387,58 @@ public:
|
||||
generalTrigger dgh_cb_mh_2d_3;
|
||||
generalTrigger dgh_cb_mh_2d_4;
|
||||
|
||||
generalTrigger dgh_cb_gy_2d_1;
|
||||
generalTrigger dgh_cb_gy_2d_2;
|
||||
generalTrigger dgh_cb_gy_2d_3;
|
||||
generalTrigger dgh_cb_gy_2d_4;
|
||||
_581_Union_triggerTemplate<GunYaHou2DParam> dgh_cb_gy_2d_1;
|
||||
_581_Union_triggerTemplate<GunYaHou2DParam> dgh_cb_gy_2d_2;
|
||||
_581_Union_triggerTemplate<GunYaHou2DParam> dgh_cb_gy_2d_3;
|
||||
_581_Union_triggerTemplate<GunYaHou2DParam> dgh_cb_gy_2d_4;
|
||||
std::vector<GunYaHou2DParam> _GunYaHou2DParam = std::vector<GunYaHou2DParam>(4);
|
||||
|
||||
generalTrigger dgh_cb_gy_3d_1;
|
||||
generalTrigger dgh_cb_gy_3d_2;
|
||||
generalTrigger dgh_cb_gy_3d_3;
|
||||
generalTrigger dgh_cb_gy_3d_4;
|
||||
detParams _params;
|
||||
|
||||
bool initOnce = false;
|
||||
void onConfigReloaded() {
|
||||
HDevEngineCpp::HDevEngine myEngine;
|
||||
myEngine.SetProcedurePath("./halconAlgoFiles/AlgoLibrary_602.hdpl");
|
||||
if (initOnce == false) {
|
||||
for (auto& param : _GunYaHou2DParam) {
|
||||
param.seg = handdleAI::CreateSegObjS("./handleaiModels/seg_hanhou.BHD", 1, 0);
|
||||
param.cls = handdleAI::CreateClsObjV3("./handleaiModels/cls_hanhou.BHD", 0, 1);
|
||||
//param.det = handdleAI::CreateDetObjS("./handleaiModels/det_hanhou.BHD", 1, 0);
|
||||
}
|
||||
initOnce = true;
|
||||
}
|
||||
}
|
||||
bool initCustom() {
|
||||
#pragma region 注册触发器回调 满焊前2D
|
||||
//generalTrigger::resultHandleCallback resultCallback_general =
|
||||
// ([=](yh_581_address address, _581_Result, std::shared_ptr <detData>) {
|
||||
// _serviceManager->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
|
||||
// });
|
||||
dgh_cb_mh_2d_1.init("Camera1", "长边满焊前2D-1",18800, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_mh_2d_2.init("Camera2", "长边满焊前2D-2", 19000, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_mh_2d_3.init("Camera3", "长边满焊前2D-3", 19200, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_mh_2d_4.init("Camera4", "长边满焊前2D-4", 19400, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_mh_2d_1.init("Camera1", "长边满焊前2D-1",18800, 2,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "满焊前2D");
|
||||
dgh_cb_mh_2d_1.address[1].valueOffsetAddr += 20;dgh_cb_mh_2d_1.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_mh_2d_2.init("Camera2", "长边满焊前2D-2", 19000, 2,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "满焊前2D");
|
||||
dgh_cb_mh_2d_2.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_mh_2d_3.init("Camera3", "长边满焊前2D-3", 19200, 2,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "满焊前2D");
|
||||
dgh_cb_mh_2d_3.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_mh_2d_4.init("Camera4", "长边满焊前2D-4", 19400, 2,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "满焊前2D");
|
||||
dgh_cb_mh_2d_4.address[1].valueOffsetAddr += 20;
|
||||
|
||||
dgh_cb_gy_2d_1.init("Camera5", "长边滚压后2D-1", 20400, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_gy_2d_2.init("Camera6", "长边滚压后2D-2", 20600, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_gy_2d_3.init("Camera7", "长边滚压后2D-3", 20800, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_gy_2d_4.init("Camera8", "长边滚压后2D-4", 21000, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_gy_2d_1.init("Camera5", "长边辊压后2D-1", 20400, 2,2, &_GunYaHou2DParam[0], _serviceManager, bridge, GunYaHou2D, "辊压后2D");
|
||||
dgh_cb_mh_2d_1.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_gy_2d_2.init("Camera6", "长边辊压后2D-2", 20600, 2,2, &_GunYaHou2DParam[1], _serviceManager, bridge, GunYaHou2D, "辊压后2D");
|
||||
dgh_cb_gy_2d_2.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_gy_2d_3.init("Camera7", "长边辊压后2D-3", 20800, 2,2, &_GunYaHou2DParam[2], _serviceManager, bridge, GunYaHou2D, "辊压后2D");
|
||||
dgh_cb_gy_2d_3.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_gy_2d_4.init("Camera8", "长边辊压后2D-4", 21000, 2,2, &_GunYaHou2DParam[3], _serviceManager, bridge, GunYaHou2D, "辊压后2D");
|
||||
dgh_cb_gy_2d_4.address[1].valueOffsetAddr += 20;
|
||||
|
||||
dgh_cb_gy_3d_1.init("Camera9", "长边滚压后3D-1", 21200, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_gy_3d_2.init("Camera10", "长边滚压后3D-2", 21400, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_gy_3d_3.init("Camera11", "长边滚压后3D-3", 21600, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_gy_3d_4.init("Camera12", "长边滚压后3D-4", 21800, 2,1, &_params, _serviceManager, bridge, generalAlgoTest);
|
||||
dgh_cb_gy_3d_1.init("Camera9", "长边辊压后3D-1", 21200, 2,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "辊压后3D");
|
||||
dgh_cb_gy_3d_1.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_gy_3d_2.init("Camera10", "长边辊压后3D-2", 21400, 2,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "辊压后3D");
|
||||
dgh_cb_gy_3d_2.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_gy_3d_3.init("Camera11", "长边辊压后3D-3", 21600, 2,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "辊压后3D");
|
||||
dgh_cb_gy_3d_3.address[1].valueOffsetAddr += 20;
|
||||
dgh_cb_gy_3d_4.init("Camera12", "长边辊压后3D-4", 21800, 2,1, &_params, _serviceManager, bridge, generalAlgoTestDuanBian, "辊压后3D");
|
||||
dgh_cb_gy_3d_4.address[1].valueOffsetAddr += 20;
|
||||
#pragma endregion
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -78,15 +78,25 @@ public:
|
||||
|
||||
bool hanQianCeLiang_Main(std::shared_ptr <detData> data, zhongHanHanQianParams* _detParams, sx_581_address address) {
|
||||
try{
|
||||
QByteArray plcResult = "2";
|
||||
QByteArray plcResult = "1";
|
||||
#if 0
|
||||
/*img2D = cv::imread("./testImages/CU_1.png", -1);
|
||||
sourceImg = img2D.clone();*/
|
||||
img2D = cv::imread("./testImages/CU.bmp", -1);
|
||||
sourceImg = img2D(cutROI & cv::Rect(0, 0, img2D.cols, img2D.rows)).clone();
|
||||
data->oriImgs[0] = cv::imread("D:\\testImage\\T.bmp", -1);
|
||||
#endif
|
||||
double xinBaoJianJuLimitHigh = data->service->_paramSyncManager->get("焊前检测","芯包间距(上限)", 72.00).toDouble();
|
||||
double xinBaoJianJuLimitLow = data->service->_paramSyncManager->get("焊前检测", "芯包间距(下限)", 68.00).toDouble();
|
||||
bool xinBaoJianJuLimitEnable = data->service->_paramSyncManager->get("焊前检测", "芯包间距判定启用", true).toBool();
|
||||
|
||||
double xinBaoDingBuDaoYuanXinLimitHigh = data->service->_paramSyncManager->get("焊前检测", "芯包顶部到圆心距离(上限)", 35.00).toDouble();
|
||||
double xinBaoDingBuDaoYuanXinLimitLow = data->service->_paramSyncManager->get("焊前检测", "芯包顶部到圆心距离(下限)", 33.00).toDouble();
|
||||
bool xinBaoDingBuDaoYuanXinLimitEnable = data->service->_paramSyncManager->get("焊前检测", "芯包顶部到圆心距离判定启用", true).toBool();
|
||||
|
||||
double lianJiePianJianJuLimitHigh = data->service->_paramSyncManager->get("焊前检测", "连接片间距(上限)", 124.00).toDouble();
|
||||
double lianJiePianJianJuLimitLow = data->service->_paramSyncManager->get("焊前检测", "连接片间距(下限)", 122.00).toDouble();
|
||||
bool lianJiePianJianJuLimitEnable = data->service->_paramSyncManager->get("焊前检测", "连接片间距判定启用", true).toBool();
|
||||
|
||||
cv::Mat sourceImg = data->oriImgs[0];
|
||||
sourceImg(cv::Rect(2400, 0, 3000, 3648)).copyTo(sourceImg);
|
||||
data->segOriginImgs.push_back(sourceImg);
|
||||
cv::Mat Paint;
|
||||
sourceImg.copyTo(Paint);
|
||||
if (Paint.channels() == 1)
|
||||
@@ -101,7 +111,7 @@ bool hanQianCeLiang_Main(std::shared_ptr <detData> data, zhongHanHanQianParams*
|
||||
|
||||
HalconCpp::HObject ho_Image_T;
|
||||
HalconCpp::HObject ho_Image_L;
|
||||
HalconCpp::HTuple in_Resolution = 0.0337797;
|
||||
HalconCpp::HTuple in_Resolution = 0.032594099;
|
||||
HalconCpp::HTuple in_FilePath = "./halconFiles/ZH_HanYin/";
|
||||
HalconCpp::HTuple in_LineType = "602";
|
||||
ho_Image_T = MatToHObject(sourceImg);
|
||||
@@ -158,11 +168,27 @@ bool hanQianCeLiang_Main(std::shared_ptr <detData> data, zhongHanHanQianParams*
|
||||
}
|
||||
|
||||
_detParams->insertResult(_calResult);
|
||||
textPainter.putText(Paint, "铜(负)极的包膜距离:" + std::to_string(Out_Vale_T_1), cv::Point(50, 50), cv::Scalar(0, 255, 0));
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(Out_Vale_T_1));//数据1
|
||||
if (Out_Vale_T_1 > xinBaoJianJuLimitHigh || Out_Vale_T_1 < xinBaoJianJuLimitLow) {
|
||||
|
||||
textPainter.putText(Paint, "铜(负)极的包膜距离:" + std::to_string(Out_Vale_T_1), cv::Point(50, 50), cv::Scalar(0, 0, 255));
|
||||
if (xinBaoJianJuLimitEnable == true)
|
||||
plcResult = "2";
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "铜(负)极的包膜距离:" + std::to_string(Out_Vale_T_1), cv::Point(50, 50), cv::Scalar(0, 255, 0));
|
||||
|
||||
textPainter.putText(Paint, "铜(负)极连接片中心的和上极耳水平边缘距离:" + std::to_string(Out_Vale_T_2), cv::Point(50, 200), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "铜(负)极连接片中心的和下极耳水平边缘距离:" + std::to_string(Out_Vale_T_3), cv::Point(50, 350), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "铜(负)极和铝(正)极的中心距离:" + std::to_string(extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0));
|
||||
|
||||
if (extremum_Value > lianJiePianJianJuLimitHigh || extremum_Value < lianJiePianJianJuLimitLow) {
|
||||
textPainter.putText(Paint, "铜(负)极和铝(正)极的中心距离:" + std::to_string(extremum_Value), cv::Point(50, 600), cv::Scalar(0, 0, 255));
|
||||
if (lianJiePianJianJuLimitEnable == true)
|
||||
plcResult = "2";
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "铜(负)极和铝(正)极的中心距离:" + std::to_string(extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0));
|
||||
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(Out_Vale_T_1));//数据1
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(extremum_Value));//数据2
|
||||
for (int i = 0; i < 5; i++){
|
||||
cv::line(Paint, cv::Point(out_LinePoint[i * 4 + 1].D(), out_LinePoint[i * 4].D()),
|
||||
@@ -183,11 +209,12 @@ bool hanQianCeLiang_Main(std::shared_ptr <detData> data, zhongHanHanQianParams*
|
||||
textPainter.putText(Paint, "NG" + errTails, cv::Point(0, 50), cv::Scalar(0, 255, 0));
|
||||
data->halconOK = false;
|
||||
}
|
||||
if (data->service->_paramSyncManager->get("通用设置", "强制OK", false).toBool())
|
||||
plcResult = "1";//强制OK
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
|
||||
|
||||
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
|
||||
plcResult = "1";//强制OK
|
||||
data->resultImgs.push_back(Paint);
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
|
||||
return true;
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
@@ -201,23 +228,36 @@ bool hanQianCeLiang_Main(std::shared_ptr <detData> data, zhongHanHanQianParams*
|
||||
textPainter.putText(Paint, "NG", cv::Point(1000, 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 + "_1");//结果反馈
|
||||
if (data->service->_paramSyncManager->get("通用设置", "强制OK", false).toBool())
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
|
||||
else
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//结果反馈
|
||||
return true;
|
||||
}
|
||||
bool hanQianCeLiang_Sub(std::shared_ptr <detData> data, zhongHanHanQianParams* _detParams, sx_581_address address) {
|
||||
try {
|
||||
//测试算法用
|
||||
QByteArray plcResult = "2";
|
||||
QByteArray plcResult = "1";
|
||||
{
|
||||
#if 0
|
||||
//img2D = cv::imread("./testImages/AL_1.png", -1);
|
||||
//sourceImg = img2D.clone();
|
||||
img2D = cv::imread("./testImages/AL.bmp", -1);
|
||||
sourceImg = img2D(cutROI & cv::Rect(0, 0, img2D.cols, img2D.rows)).clone();
|
||||
data->oriImgs[0] = cv::imread("D:\\testImage\\L.bmp", -1);
|
||||
#endif
|
||||
}
|
||||
double xinBaoJianJuLimitHigh = data->service->_paramSyncManager->get("焊前检测", "芯包间距(上限)", 72.00).toDouble();
|
||||
double xinBaoJianJuLimitLow = data->service->_paramSyncManager->get("焊前检测", "芯包间距(下限)", 68.00).toDouble();
|
||||
bool xinBaoJianJuLimitEnable = data->service->_paramSyncManager->get("焊前检测", "芯包间距判定启用", true).toBool();
|
||||
|
||||
double xinBaoDingBuDaoYuanXinLimitHigh = data->service->_paramSyncManager->get("焊前检测", "芯包顶部到圆心距离(上限)", 35.00).toDouble();
|
||||
double xinBaoDingBuDaoYuanXinLimitLow = data->service->_paramSyncManager->get("焊前检测", "芯包顶部到圆心距离(下限)", 33.00).toDouble();
|
||||
bool xinBaoDingBuDaoYuanXinLimitEnable = data->service->_paramSyncManager->get("焊前检测", "芯包顶部到圆心距离判定启用", true).toBool();
|
||||
|
||||
double lianJiePianJianJuLimitHigh = data->service->_paramSyncManager->get("焊前检测", "连接片间距(上限)", 124.00).toDouble();
|
||||
double lianJiePianJianJuLimitLow = data->service->_paramSyncManager->get("焊前检测", "连接片间距(下限)", 122.00).toDouble();
|
||||
bool lianJiePianJianJuLimitEnable = data->service->_paramSyncManager->get("焊前检测", "连接片间距判定启用", true).toBool();
|
||||
|
||||
cv::Mat sourceImg = data->oriImgs[0];
|
||||
sourceImg(cv::Rect(0, 0, 3000, 3648)).copyTo(sourceImg);
|
||||
data->segOriginImgs.push_back(sourceImg);
|
||||
cv::Mat Paint;
|
||||
sourceImg.copyTo(Paint);
|
||||
if (Paint.channels() == 1)
|
||||
@@ -241,11 +281,28 @@ bool hanQianCeLiang_Sub(std::shared_ptr <detData> data, zhongHanHanQianParams* _
|
||||
}
|
||||
|
||||
if (_calResult.algoFailed == false) {
|
||||
textPainter.putText(Paint, "铝(正)包膜距离:" + std::to_string(_calResult.Out_Vale_L_1), cv::Point(50, 50), cv::Scalar(0, 255, 0));
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(_calResult.Out_Vale_L_1));//数据1
|
||||
if (_calResult.Out_Vale_L_1 > xinBaoJianJuLimitHigh || _calResult.Out_Vale_L_1 < xinBaoJianJuLimitLow) {
|
||||
|
||||
textPainter.putText(Paint, "铝(正)包膜距离:" + std::to_string(_calResult.Out_Vale_L_1), cv::Point(50, 50), cv::Scalar(0, 0, 255));
|
||||
if (xinBaoJianJuLimitEnable == true)
|
||||
plcResult = "2";
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "铝(正)包膜距离:" + std::to_string(_calResult.Out_Vale_L_1), cv::Point(50, 50), cv::Scalar(0, 255, 0));
|
||||
|
||||
textPainter.putText(Paint, "铝(正)极连接片中心的和上极耳水平边缘距离:" + std::to_string(_calResult.Out_Vale_L_2), cv::Point(50, 200), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "铝(正)极连接片中心的和下极耳水平边缘距离:" + std::to_string(_calResult.Out_Vale_L_3), cv::Point(50, 350), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "铜(负)极和铝(正)极的中心距离:" + std::to_string(_calResult.extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0));
|
||||
|
||||
if (_calResult.extremum_Value > lianJiePianJianJuLimitHigh || _calResult.extremum_Value < lianJiePianJianJuLimitLow) {
|
||||
textPainter.putText(Paint, "铜(负)极和铝(正)极的中心距离:" + std::to_string(_calResult.extremum_Value), cv::Point(50, 600), cv::Scalar(0, 0, 255));
|
||||
if (lianJiePianJianJuLimitEnable == true)
|
||||
plcResult = "2";
|
||||
}
|
||||
else
|
||||
textPainter.putText(Paint, "铜(负)极和铝(正)极的中心距离:" + std::to_string(_calResult.extremum_Value), cv::Point(50, 600), cv::Scalar(0, 255, 0));
|
||||
|
||||
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(_calResult.Out_Vale_L_1));//数据1
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(_calResult.extremum_Value));//数据2
|
||||
for (int i = 0; i < 5; i++) {
|
||||
cv::line(Paint, cv::Point(_calResult.lines[i * 4 + 1], _calResult.lines[i * 4]),
|
||||
@@ -260,10 +317,13 @@ bool hanQianCeLiang_Sub(std::shared_ptr <detData> data, zhongHanHanQianParams* _
|
||||
textPainter.putText(Paint, "NG:algoError", cv::Point(0, 50), cv::Scalar(0, 255, 0));
|
||||
plcResult = "2";
|
||||
}
|
||||
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
|
||||
plcResult = "1";//强制OK
|
||||
data->resultImgs.push_back(Paint);
|
||||
|
||||
if (data->service->_paramSyncManager->get("通用设置", "强制OK", false).toBool())
|
||||
plcResult = "1";//强制OK
|
||||
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
|
||||
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
|
||||
data->resultImgs.push_back(Paint);
|
||||
return true;
|
||||
}
|
||||
CATCH_EXCEPTIONS
|
||||
@@ -277,7 +337,10 @@ bool hanQianCeLiang_Sub(std::shared_ptr <detData> data, zhongHanHanQianParams* _
|
||||
textPainter.putText(Paint, "NG", cv::Point(1000, 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 + "_1");//结果反馈
|
||||
if (data->service->_paramSyncManager->get("通用设置", "强制OK", false).toBool())
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
|
||||
else
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//结果反馈
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -299,8 +362,8 @@ public:
|
||||
}
|
||||
bool initCustom() {
|
||||
#pragma region 注册触发器回调
|
||||
tong_1.init("Camera1", "焊前定位-相机1", { { 5060, 1,{5070},"5062","5064",5066} }, 1, &detParams, _serviceManager, bridge, hanQianCeLiang_Main);
|
||||
lv_1.init("Camera2", "焊前定位-相机2", { { 5090, 1,{5100},"5092","5094",5096} }, 1, &detParams, _serviceManager, bridge, hanQianCeLiang_Sub);
|
||||
tong_1.init("Camera1", "焊前定位-相机1", { { 5060, 1,{5100,5070},"5062","5064",5066} }, 1, &detParams, _serviceManager, bridge, hanQianCeLiang_Main);
|
||||
lv_1.init("Camera2", "焊前定位-相机2", { { 5090, 1,{5100,5070},"5092","5094",5096} }, 1, &detParams, _serviceManager, bridge, hanQianCeLiang_Sub);
|
||||
#pragma endregion
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -124,8 +124,15 @@ void myCallbackFunc(LJX8IF_PROFILE_HEADER* pProfileHeaderArray, WORD* pHeightPro
|
||||
}
|
||||
if (_luminanceBuf[dwUser] <= pLuminanceProfileArray || (unsigned short*)_luminanceBuf[dwUser] >= (WORD*)pLuminanceProfileArray + dwProfileDataCount * dwCount * 2)
|
||||
memcpy(&_luminanceBuf[dwUser][0], pLuminanceProfileArray, dwProfileDataCount * dwCount * 2);
|
||||
else
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "memcpy _luminanceBuf error";
|
||||
else {
|
||||
try {
|
||||
memcpy(&_luminanceBuf[dwUser][0], pLuminanceProfileArray, dwProfileDataCount * dwCount * 2);
|
||||
}
|
||||
catch (...) {
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << "Get luminanceBuf failed!";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
_imageAvailable[dwUser] = 1; // 图像获取成功 dwUser 和 deviceId 一致
|
||||
_lastImageSizeHeight[dwUser] = dwCount; // 扫描的行数, dwCount 和 yImageSize 一致
|
||||
@@ -414,9 +421,10 @@ bool Hd_CameraModule_3DKeyence::initParas(QByteArray& initData)
|
||||
}
|
||||
|
||||
// Initialize
|
||||
if (!InitHighSpeed())
|
||||
{
|
||||
if (!InitHighSpeed()){
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " InitHighSpeed error! " ;
|
||||
lastError = "初始化高速通讯失败!";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -476,6 +484,7 @@ bool Hd_CameraModule_3DKeyence::run()
|
||||
|
||||
try
|
||||
{
|
||||
_imageAvailable[deviceId] = 0;
|
||||
while (imgTakeNum != imgTarget)
|
||||
{
|
||||
int sleepMs = 10;
|
||||
@@ -486,8 +495,8 @@ bool Hd_CameraModule_3DKeyence::run()
|
||||
QThread::msleep(10);
|
||||
if (cnt++ >= timeoutCnt)
|
||||
{
|
||||
heightMatS.push_back(cv::Mat(G_yImageSize, G_xImageSize, CV_8UC1, cv::Scalar(0, 0, 0)));
|
||||
luminanceMatS.push_back(cv::Mat(G_yImageSize, G_xImageSize, CV_8UC1, cv::Scalar(0, 0, 0)));
|
||||
heightMatS.push_back(cv::Mat(1000, 1000, CV_8UC1, cv::Scalar(0)));
|
||||
luminanceMatS.push_back(cv::Mat(1000, 1000, CV_8UC1, cv::Scalar(0)));
|
||||
imgTakeNum++;
|
||||
qDebug() << "imgGetERROR insert blank img cameraID:" << camera_name;
|
||||
continue;
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# 获取获取当前目录名
|
||||
get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
|
||||
set(DLL_NAMES "keyence3D" "opencv")
|
||||
foreach(child ${DLL_NAMES})
|
||||
|
||||
LIST(APPEND ENV_INCLUDE ${${child}_include})
|
||||
LIST(APPEND ENV_LIB ${${child}_lib})
|
||||
LIST(APPEND ENV_TARGET ${${child}_target_link})
|
||||
endforeach()
|
||||
message(" ENV_INCLUDE : " ${ENV_INCLUDE} )
|
||||
message(" ENV_LIB : " ${ENV_LIB} )
|
||||
message(" ENV_TARGET : " ${ENV_TARGET} )
|
||||
include_directories(
|
||||
|
||||
${ENV_INCLUDE}
|
||||
)
|
||||
|
||||
link_directories (
|
||||
${ENV_LIB}
|
||||
|
||||
)
|
||||
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
SET(CMAKE_AUTOUIC OFF)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
FILE(GLOB HEAD_FILES "./*.h" )
|
||||
FILE(GLOB SRC_FILES "./*.cpp")
|
||||
FILE(GLOB UI_FILES "./*.ui")
|
||||
|
||||
|
||||
#find_package(Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
|
||||
|
||||
add_library(${CURRENT_FOLDER} SHARED
|
||||
${HEAD_FILES}
|
||||
${SRC_FILES}
|
||||
${UI_FILES}
|
||||
)
|
||||
|
||||
|
||||
|
||||
set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
|
||||
target_link_libraries(${CURRENT_FOLDER} PRIVATE
|
||||
${ENV_TARGET}
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
)
|
||||
|
||||
|
||||
# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY)
|
||||
|
||||
|
||||
|
||||
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
@@ -0,0 +1,567 @@
|
||||
#include "Hd_CameraModule_3DKeyence.h"
|
||||
#include <exception>
|
||||
#include <qthread.h>
|
||||
#include <QTextCodec>
|
||||
#include <qqueue.h>
|
||||
#include <qmutex.h>
|
||||
|
||||
int G_xImageSize = 0; // Number of X points.
|
||||
int G_yImageSize = 0; // Number of Y lines.
|
||||
//const int MAX_LJXA_XDATANUM = 3200;
|
||||
//const unsigned int BUFFER_FULL_COUNT = 30000;
|
||||
//
|
||||
//int _imageAvailable[MAX_LJXA_DEVICENUM] = { 0 };
|
||||
//unsigned short* _luminanceBuf[MAX_LJXA_DEVICENUM] = { 0 };
|
||||
//unsigned short* _heightBuf[MAX_LJXA_DEVICENUM] = { 0 };
|
||||
//int _lastImageSizeHeight[MAX_LJXA_DEVICENUM];
|
||||
int imgTakeNum = 0, imgTarget = 1;
|
||||
int imgIndex = 0;
|
||||
int getImageTimeOut = 3000;
|
||||
QString lastError;
|
||||
QMutex* m_mutex = nullptr;
|
||||
std::mutex bufferMutex;
|
||||
QQueue< cv::Mat> heightMatS;//高度图
|
||||
QQueue<cv::Mat> luminanceMatS;//灰度图
|
||||
//data == "rest_newProductIn"时要结束run;机台报警,取图超时,复位后重新拍的情况。
|
||||
bool ifBreak = false;
|
||||
//ifRunning减少ifBreak的判断;"rest_newProductIn"时,Logic_camera_thread框架会结束未处理完的相相机取图
|
||||
bool ifRunning = false;
|
||||
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;
|
||||
}
|
||||
|
||||
bool JumpFlag = false;
|
||||
int yCounts;
|
||||
void myCallbackFunc(LJX8IF_PROFILE_HEADER* pProfileHeaderArray, WORD* pHeightProfileArray, WORD* pLuminanceProfileArray, DWORD dwLuminanceEnable, DWORD dwProfileDataCount, DWORD dwCount, DWORD dwNotify, DWORD dwUser)
|
||||
{
|
||||
try
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " --> Enter callback function";
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "dwProfileDataCount = " << dwProfileDataCount;
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "dwCount = " << dwCount;
|
||||
std::cout << "dwCount->" << dwCount <<" dwProfileDataCount"<< dwProfileDataCount << "dwNotify = " << dwNotify<< std::endl;
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "dwNotify = " << dwNotify;
|
||||
//if (dwCount < 1000)return;
|
||||
/* if ((dwNotify != 0) || (dwNotify & 0x10000) != 0)
|
||||
{
|
||||
return;
|
||||
}*/
|
||||
std::lock_guard<std::mutex> lock(bufferMutex);
|
||||
if (dwCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_imageAvailable[dwUser] == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// _heightBuf 代表的含义:程序里的高度缓存区,pHeightProfileArray 回调函数里的数据
|
||||
// 此处崩溃的可能性:xImageSize 配置文件中设置的值和3D相机调试软件设置的值不一致,会崩溃。
|
||||
if (JumpFlag)
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "JumpFlag";
|
||||
return;
|
||||
}
|
||||
if (_heightBuf[dwUser] == NULL)
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "_heightBuf[dwUser] == NULL";
|
||||
_heightBuf[dwUser] = (unsigned short*)malloc(G_yImageSize * MAX_LJXA_XDATANUM * 2);
|
||||
//return;
|
||||
}
|
||||
if (pHeightProfileArray == NULL)
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "pHeightProfileArray== NULL";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "_heightBuf[dwUser]: " << _heightBuf[dwUser];
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "pHeightProfileArray: " << pHeightProfileArray;
|
||||
|
||||
//判断内存是否重叠
|
||||
if (_heightBuf[dwUser] <= pHeightProfileArray || (unsigned short*)_heightBuf[dwUser] >= (WORD*)pHeightProfileArray + dwProfileDataCount * dwCount * 2)
|
||||
{
|
||||
memcpy(&_heightBuf[dwUser][0], pHeightProfileArray, dwProfileDataCount * dwCount * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "first memcpy _heightBuf error";
|
||||
if (_heightBuf[dwUser] != NULL)
|
||||
{
|
||||
free(_heightBuf[dwUser]);
|
||||
_heightBuf[dwUser] = NULL;
|
||||
}
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " memcpy _heightBuf again ";
|
||||
_heightBuf[dwUser] = (unsigned short*)malloc(yCounts * MAX_LJXA_XDATANUM * 2);
|
||||
memcpy(&_heightBuf[dwUser][0], pHeightProfileArray, dwProfileDataCount * dwCount * 2);
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Second memcpy _heightBuf success ";
|
||||
|
||||
}
|
||||
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "_luminanceBuf[dwUser]: " << _luminanceBuf[dwUser];
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "pLuminanceProfileArray: " << pLuminanceProfileArray;
|
||||
if (dwLuminanceEnable == 1)
|
||||
{
|
||||
if (_luminanceBuf[dwUser] == NULL)
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "_luminanceBuf[dwUser]== NULL";
|
||||
//return;
|
||||
_luminanceBuf[dwUser] = (unsigned short*)malloc(G_yImageSize * MAX_LJXA_XDATANUM * 2);
|
||||
}
|
||||
if (_luminanceBuf[dwUser] <= pLuminanceProfileArray || (unsigned short*)_luminanceBuf[dwUser] >= (WORD*)pLuminanceProfileArray + dwProfileDataCount * dwCount * 2)
|
||||
memcpy(&_luminanceBuf[dwUser][0], pLuminanceProfileArray, dwProfileDataCount * dwCount * 2);
|
||||
else
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "memcpy _luminanceBuf error";
|
||||
}
|
||||
_imageAvailable[dwUser] = 1; // 图像获取成功 dwUser 和 deviceId 一致
|
||||
_lastImageSizeHeight[dwUser] = dwCount; // 扫描的行数, dwCount 和 yImageSize 一致
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " --> execute callback function error";
|
||||
}
|
||||
}
|
||||
|
||||
int Hd_CameraModule_3DKeyence::LJXA_ACQ_OpenDevice(int lDeviceId, LJX8IF_ETHERNET_CONFIG* EthernetConfig, int HighSpeedPortNo)
|
||||
{
|
||||
int errCode = LJX8IF_EthernetOpen(lDeviceId, EthernetConfig);
|
||||
|
||||
_ethernetConfig[lDeviceId] = *EthernetConfig;
|
||||
_highSpeedPortNo[lDeviceId] = HighSpeedPortNo;
|
||||
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Open device ! errCode:" << errCode;
|
||||
return errCode;
|
||||
}
|
||||
|
||||
void Hd_CameraModule_3DKeyence::LJXA_ACQ_CloseDevice(int lDeviceId)
|
||||
{
|
||||
LJX8IF_FinalizeHighSpeedDataCommunication(lDeviceId);
|
||||
LJX8IF_CommunicationClose(lDeviceId);
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Close device!";
|
||||
}
|
||||
|
||||
|
||||
bool Hd_CameraModule_3DKeyence::decodeInitData(QByteArray byteArray,QVector<QByteArray> &vector_data)
|
||||
{
|
||||
while (!byteArray.isEmpty())
|
||||
{
|
||||
int type = 0;
|
||||
QByteArray m_type = byteArray.mid(0,4);
|
||||
memcpy((void*)&type,(void*)m_type.data(), 4);
|
||||
byteArray.remove(0,4);
|
||||
|
||||
int len = 0;
|
||||
QByteArray m_len = byteArray.mid(0,4);
|
||||
memcpy((void*)&len,(void*)m_len.data(), 4);
|
||||
byteArray.remove(0,4);
|
||||
|
||||
QByteArray mm_data = byteArray.mid(0,len);
|
||||
vector_data.append(mm_data);
|
||||
byteArray.remove(0,len);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Hd_CameraModule_3DKeyence* create()
|
||||
{
|
||||
qDebug() << __FUNCTION__ << "line:" << __LINE__ << " Hd_CameraModule_3DKeyence create success!" ;
|
||||
return new Hd_CameraModule_3DKeyence;
|
||||
}
|
||||
|
||||
void destory(Hd_CameraModule_3DKeyence * ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
}
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Hd_CameraModule_3DKeyence destory success!";
|
||||
}
|
||||
|
||||
Hd_CameraModule_3DKeyence::Hd_CameraModule_3DKeyence()
|
||||
{
|
||||
m_mutex = new QMutex;
|
||||
}
|
||||
|
||||
|
||||
Hd_CameraModule_3DKeyence::~Hd_CameraModule_3DKeyence()
|
||||
{
|
||||
if (isopen)
|
||||
{
|
||||
isopen = false;
|
||||
|
||||
// Stop HighSpeed
|
||||
errCode = LJX8IF_StopHighSpeedDataCommunication(deviceId);
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Stop HighSpeed errCode:" << errCode;
|
||||
|
||||
LJXA_ACQ_CloseDevice(deviceId);
|
||||
qDebug() << __FUNCTION__ << "line:" << __LINE__ << " CloseDevice success!";
|
||||
if (heightImage)
|
||||
{
|
||||
free(heightImage);
|
||||
|
||||
}
|
||||
if (luminanceImage)
|
||||
{
|
||||
free(luminanceImage);
|
||||
}
|
||||
}
|
||||
|
||||
// Free memory
|
||||
if (_heightBuf[deviceId] != NULL)
|
||||
{
|
||||
free(_heightBuf[deviceId]);
|
||||
}
|
||||
|
||||
if (_luminanceBuf[deviceId] != NULL)
|
||||
{
|
||||
free(_luminanceBuf[deviceId]);
|
||||
}
|
||||
|
||||
if (startReq_ptr)
|
||||
{
|
||||
delete startReq_ptr;
|
||||
startReq_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (profileInfo_ptr)
|
||||
{
|
||||
delete profileInfo_ptr;
|
||||
profileInfo_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (setParam_Ptr)
|
||||
{
|
||||
delete setParam_Ptr;
|
||||
setParam_Ptr = nullptr;
|
||||
}
|
||||
|
||||
if (getParam_Ptr)
|
||||
{
|
||||
delete getParam_Ptr;
|
||||
getParam_Ptr = nullptr;
|
||||
}
|
||||
if (m_mutex)
|
||||
{
|
||||
delete m_mutex;
|
||||
m_mutex = nullptr;
|
||||
}
|
||||
qDebug() << __FUNCTION__ << "line:" << __LINE__ << " delete success!";
|
||||
}
|
||||
|
||||
bool Hd_CameraModule_3DKeyence::readData(std::vector<cv::Mat> &mats,QByteArray &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
|
||||
QMutexLocker locker(m_mutex);
|
||||
if (luminanceMatS.empty() || heightMatS.empty())
|
||||
{
|
||||
qDebug() << " [Error] " << " srcImage is null";
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < imgTarget; i++) {
|
||||
if (heightMatS.size() >= 1 && luminanceMatS.size() >= 1) {
|
||||
mats.push_back(luminanceMatS.dequeue());
|
||||
mats.push_back(heightMatS.dequeue());
|
||||
}
|
||||
else {
|
||||
mats.push_back(cv::Mat(G_xImageSize, G_yImageSize, CV_8UC1, cv::Scalar(0, 0, 0)));
|
||||
mats.push_back(cv::Mat(G_xImageSize, G_yImageSize, CV_8UC1, cv::Scalar(0, 0, 0)));
|
||||
}
|
||||
}
|
||||
imgTakeNum = 0;
|
||||
qCritical() << " [info] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg readData,deviceId" << deviceId << " imgIndex" << imgIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Hd_CameraModule_3DKeyence::writeData(std::vector<cv::Mat> &mat,QByteArray &data)
|
||||
{
|
||||
if (data == "clearCahce") {
|
||||
QMutexLocker locker(m_mutex);
|
||||
heightMatS.clear();
|
||||
luminanceMatS.clear();
|
||||
}
|
||||
//2024.02.18更新,相机对应的读SN信号时,表示新产品进入,设置初始值
|
||||
//if (data == "rest_newProductIn")
|
||||
//{
|
||||
// //根据实际项目,设置初始值:曝光、增益,ROI区域等
|
||||
// /*{
|
||||
// if (expourseTimeList.size() > 0)
|
||||
// SetExposureTime(expourseTimeList[0]);
|
||||
// if (gainList.size() > 0)
|
||||
// SetGain(gainList[0]);
|
||||
// }
|
||||
// getImageNum = 0;*/
|
||||
// if (luminanceMatS.size() > 0 || heightMatS.size() > 0)
|
||||
// {
|
||||
// m_mutex->lock();
|
||||
// luminanceMatS.clear();
|
||||
// heightMatS.clear();
|
||||
// m_mutex->unlock();
|
||||
// std::cout << "rest_newProductIn , queuePic.size() > 0 ,signal maybe too fast " << camera_name.toStdString() << std::endl;
|
||||
// qWarning() << __FUNCTION__ << " line: " << __LINE__ << "rest_newProductIn , queuePic.size() > 0 ,signal maybe too fast " << camera_name;
|
||||
// }
|
||||
// if (ifRunning == true)
|
||||
// {
|
||||
// ifBreak = true;
|
||||
// Sleep(10);
|
||||
// }
|
||||
// imgIndex = 0;
|
||||
// //getImageNum = 0;
|
||||
// return true;
|
||||
//}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1...
|
||||
bool Hd_CameraModule_3DKeyence::initParas(QByteArray& initData)
|
||||
{
|
||||
QByteArrayList valueList = initData.split('#');
|
||||
if (valueList.size() < 6) {
|
||||
qDebug() << "[Error] " << " Hd_CameraModule_HIK initParas fail--params error!参数数量不满足";
|
||||
lastError = "参数数量不满足";
|
||||
return false;
|
||||
}
|
||||
EthernetConfig.wPortNo = 24691;
|
||||
|
||||
camera_name = valueList[0];
|
||||
auto valueL1 = valueList[0].split('.');
|
||||
if (valueL1.size() == 4)
|
||||
{
|
||||
EthernetConfig.abyIpAddress[0] = valueL1.at(0).toInt();
|
||||
EthernetConfig.abyIpAddress[1] = valueL1.at(1).toInt();
|
||||
EthernetConfig.abyIpAddress[2] = valueL1.at(2).toInt();
|
||||
EthernetConfig.abyIpAddress[3] = valueL1.at(3).toInt();
|
||||
}
|
||||
|
||||
deviceId = valueList[1].toInt();
|
||||
|
||||
xImageSize = valueList[2].toInt();
|
||||
G_xImageSize = valueList[2].toInt();
|
||||
|
||||
yImageSize = valueList[3].toInt();
|
||||
G_yImageSize = valueList[3].toInt();
|
||||
|
||||
imgTarget = valueList[4].toInt();
|
||||
|
||||
getImageTimeOut = valueList[5].toInt();
|
||||
yCounts = yImageSize;
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " camera_name:" << camera_name << " paras init is success!";
|
||||
|
||||
// 初始化申请空间 20230214
|
||||
startReq_ptr = new LJX8IF_HIGH_SPEED_PRE_START_REQ;
|
||||
profileInfo_ptr = new LJX8IF_PROFILE_INFO;
|
||||
startReq_ptr->bySendPosition = 2;
|
||||
|
||||
setParam_Ptr = new LJXA_ACQ_SETPARAM;
|
||||
getParam_Ptr = new LJXA_ACQ_GETPARAM;
|
||||
|
||||
setParam_Ptr->y_linenum = yImageSize;
|
||||
setParam_Ptr->y_pitch_um = y_pitch_um;
|
||||
setParam_Ptr->timeout_ms = timeout_ms;
|
||||
setParam_Ptr->use_external_batchStart = use_external_batchStart;
|
||||
|
||||
// Allocate user memory
|
||||
heightImage = (unsigned short*)malloc(sizeof(unsigned short) * xImageSize * yImageSize);
|
||||
luminanceImage = (unsigned short*)malloc(sizeof(unsigned short) * xImageSize * yImageSize);
|
||||
|
||||
errCode = LJXA_ACQ_OpenDevice(deviceId, &EthernetConfig, HighSpeedPortNo);
|
||||
if ( errCode != LJX8IF_RC_OK )
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Failed to open device ";
|
||||
//Free user memory
|
||||
if ( heightImage )
|
||||
{
|
||||
free(heightImage);
|
||||
}
|
||||
|
||||
if ( luminanceImage )
|
||||
{
|
||||
free(luminanceImage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
isopen = true;
|
||||
|
||||
// Allocate memory
|
||||
_heightBuf[deviceId] = (unsigned short*)malloc(yImageSize * MAX_LJXA_XDATANUM * 2);
|
||||
if (_heightBuf[deviceId] == NULL)
|
||||
{
|
||||
return LJX8IF_RC_ERR_NOMEMORY;
|
||||
}
|
||||
|
||||
_luminanceBuf[deviceId] = (unsigned short*)malloc(yImageSize * MAX_LJXA_XDATANUM * 2);
|
||||
if (_luminanceBuf[deviceId] == NULL)
|
||||
{
|
||||
return LJX8IF_RC_ERR_NOMEMORY;
|
||||
}
|
||||
|
||||
// Initialize
|
||||
if (!InitHighSpeed())
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " InitHighSpeed error! " ;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Hd_CameraModule_3DKeyence::InitHighSpeed()
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( startReq_ptr == nullptr )
|
||||
{
|
||||
startReq_ptr = new LJX8IF_HIGH_SPEED_PRE_START_REQ;
|
||||
startReq_ptr->bySendPosition = 2;
|
||||
qWarning() << __FUNCTION__ << " line: " << __LINE__ << " startReq_ptr is null! ";
|
||||
}
|
||||
if ( profileInfo_ptr == nullptr )
|
||||
{
|
||||
profileInfo_ptr = new LJX8IF_PROFILE_INFO;
|
||||
qWarning() << __FUNCTION__ << " line: " << __LINE__ << " profileInfo_ptr is null! ";
|
||||
}
|
||||
errCode = LJX8IF_InitializeHighSpeedDataCommunicationSimpleArray(deviceId, &_ethernetConfig[deviceId], _highSpeedPortNo[deviceId], &myCallbackFunc, yImageSize, deviceId); // 初始化高速通讯
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " errCode:" << errCode;
|
||||
errCode = LJX8IF_PreStartHighSpeedDataCommunication(deviceId, startReq_ptr, profileInfo_ptr); // 预开始启动高速通信,作用 做预连接
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " errCode:" << errCode;
|
||||
|
||||
// zUnit
|
||||
errCode = LJX8IF_GetZUnitSimpleArray(deviceId, &zUnit);
|
||||
if (errCode != 0 || zUnit == 0)
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " Failed to acquire zunit! ";
|
||||
return false;
|
||||
}
|
||||
errCode = LJX8IF_StartHighSpeedDataCommunication(deviceId); // 正式开始高速通讯
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " errCode: " << errCode;
|
||||
|
||||
//Start HighSpeed
|
||||
_imageAvailable[deviceId] = 0;
|
||||
_lastImageSizeHeight[deviceId] = 0;
|
||||
}
|
||||
catch (const QString ev)
|
||||
{
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " ev: " << ev;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool Hd_CameraModule_3DKeyence::run()
|
||||
{
|
||||
|
||||
ifRunning = true;
|
||||
ifBreak = false;
|
||||
if ( !isopen )
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " device is not opened! ";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
while (imgTakeNum != imgTarget)
|
||||
{
|
||||
int sleepMs = 10;
|
||||
int cnt = 0;
|
||||
int timeoutCnt = getImageTimeOut / sleepMs;
|
||||
while (_imageAvailable[deviceId] != 1 )
|
||||
{
|
||||
QThread::msleep(10);
|
||||
if (cnt++ >= timeoutCnt)
|
||||
{
|
||||
heightMatS.push_back(cv::Mat(G_yImageSize, G_xImageSize, CV_8UC1, cv::Scalar(0, 0, 0)));
|
||||
luminanceMatS.push_back(cv::Mat(G_yImageSize, G_xImageSize, CV_8UC1, cv::Scalar(0, 0, 0)));
|
||||
imgTakeNum++;
|
||||
qDebug() << "imgGetERROR insert blank img cameraID:" << camera_name;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::lock_guard<std::mutex> lock(bufferMutex);
|
||||
_getParam[deviceId].luminance_enabled = profileInfo_ptr->byLuminanceOutput;
|
||||
_getParam[deviceId].x_pointnum = profileInfo_ptr->wProfileDataCount;
|
||||
_getParam[deviceId].y_linenum_acquired = _lastImageSizeHeight[deviceId];
|
||||
_getParam[deviceId].x_pitch_um = profileInfo_ptr->lXPitch / 100.0f;
|
||||
_getParam[deviceId].y_pitch_um = y_pitch_um;
|
||||
_getParam[deviceId].z_pitch_um = zUnit / 100.0f;
|
||||
|
||||
*getParam_Ptr = _getParam[deviceId];
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " getPara Finished: ";
|
||||
int xDataNum = _getParam[deviceId].x_pointnum;
|
||||
|
||||
unsigned short* dwHeightBuf = (unsigned short*)&_heightBuf[deviceId][0];
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " dwHeightBuf Init Finished: ";
|
||||
memcpy(heightImage, dwHeightBuf, xDataNum * yImageSize * 2);
|
||||
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Height Img memcpy Finished: ";
|
||||
std::vector<unsigned short>poits(xDataNum * yImageSize * 2, 0);
|
||||
if (_getParam[deviceId].luminance_enabled > 0)
|
||||
{
|
||||
unsigned short* dwLuminanceBuf = (unsigned short*)&_luminanceBuf[deviceId][0];
|
||||
memcpy(luminanceImage, dwLuminanceBuf, xDataNum * yImageSize * 2);
|
||||
}
|
||||
// Free memory
|
||||
if (_heightBuf[deviceId] != NULL)
|
||||
{
|
||||
free(_heightBuf[deviceId]);
|
||||
_heightBuf[deviceId] = NULL;
|
||||
}
|
||||
|
||||
if (_luminanceBuf[deviceId] != NULL)
|
||||
{
|
||||
free(_luminanceBuf[deviceId]);
|
||||
_luminanceBuf[deviceId] = NULL;
|
||||
}
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Free memory Finished: ";
|
||||
|
||||
m_mutex->lock();
|
||||
cv::Mat luminanceMat;
|
||||
if(_lastImageSizeHeight[deviceId] != 0)
|
||||
luminanceMat = cv::Mat(_lastImageSizeHeight[deviceId], xImageSize, CV_16UC1, luminanceImage);
|
||||
else
|
||||
luminanceMat = cv::Mat(yImageSize, xImageSize, CV_16UC1, luminanceImage);
|
||||
cv::normalize(luminanceMat, luminanceMat, 0, 255, cv::NORM_MINMAX);
|
||||
cv::convertScaleAbs(luminanceMat, luminanceMat);
|
||||
|
||||
luminanceMatS.enqueue(luminanceMat);
|
||||
|
||||
cv::Mat heightImg;
|
||||
if (_lastImageSizeHeight[deviceId] != 0)
|
||||
cv::Mat(_lastImageSizeHeight[deviceId], xImageSize, CV_16UC1, heightImage).copyTo(heightImg);
|
||||
else
|
||||
cv::Mat(yImageSize, xImageSize, CV_16UC1, heightImage).copyTo(heightImg);
|
||||
heightMatS.enqueue(heightImg);
|
||||
m_mutex->unlock();
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " success to acquire 3d image! camera_name: " << camera_name;
|
||||
//Start HighSpeed
|
||||
_imageAvailable[deviceId] = 0;
|
||||
_lastImageSizeHeight[deviceId] = 0;
|
||||
imgTakeNum++;
|
||||
}
|
||||
qDebug() << camera_name <<"Finish";
|
||||
return true;
|
||||
}
|
||||
catch (QString ev)
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line: " << __LINE__ << " ev: " << ev;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
#ifndef Hd_CameraModule_3DKeyence_H
|
||||
#define Hd_CameraModule_3DKeyence_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
#include<iostream>
|
||||
#include <Windows.h>
|
||||
|
||||
#include "LJX8_IF.h"
|
||||
#include "LJX8_ErrorCode.h"
|
||||
|
||||
#include <subModuleBase.h>
|
||||
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
typedef struct {
|
||||
int y_linenum;
|
||||
float y_pitch_um;
|
||||
int timeout_ms;
|
||||
int use_external_batchStart;
|
||||
} LJXA_ACQ_SETPARAM;
|
||||
|
||||
typedef struct {
|
||||
int luminance_enabled;
|
||||
int x_pointnum;
|
||||
int y_linenum_acquired;
|
||||
float x_pitch_um;
|
||||
float y_pitch_um;
|
||||
float z_pitch_um;
|
||||
} LJXA_ACQ_GETPARAM;
|
||||
|
||||
|
||||
const int MAX_LJXA_DEVICENUM = 6;
|
||||
const int MAX_LJXA_XDATANUM = 3200;
|
||||
const unsigned int BUFFER_FULL_COUNT = 30000;
|
||||
|
||||
static int _imageAvailable[MAX_LJXA_DEVICENUM] = { 0 };
|
||||
static unsigned short* _luminanceBuf[MAX_LJXA_DEVICENUM] = { 0 };
|
||||
static unsigned short* _heightBuf[MAX_LJXA_DEVICENUM] = { 0 };
|
||||
static int _lastImageSizeHeight[MAX_LJXA_DEVICENUM];
|
||||
|
||||
class Hd_CameraModule_3DKeyence :public dsModuleBase
|
||||
{
|
||||
public:
|
||||
Hd_CameraModule_3DKeyence();
|
||||
virtual ~Hd_CameraModule_3DKeyence();
|
||||
//从类中读数据到实例对象
|
||||
bool readData(std::vector<cv::Mat>& mats, QByteArray& data);
|
||||
//实例对象把数据写入到类
|
||||
bool writeData(std::vector<cv::Mat>& mat, QByteArray& data);
|
||||
bool initParas(QByteArray& initData);
|
||||
bool run();
|
||||
|
||||
int LJXA_ACQ_OpenDevice(int lDeviceId, LJX8IF_ETHERNET_CONFIG* EthernetConfig, int HighSpeedPortNo);
|
||||
//int LJXA_ACQ_StartAsync(int lDeviceId, LJXA_ACQ_SETPARAM* setParam);
|
||||
//int LJXA_ACQ_AcquireAsync(int lDeviceId, unsigned short* heightImage, unsigned short* luminanceImage, LJXA_ACQ_SETPARAM* setParam, LJXA_ACQ_GETPARAM* getParam);
|
||||
void LJXA_ACQ_CloseDevice(int lDeviceId);
|
||||
|
||||
bool decodeInitData(QByteArray byteArray, QVector<QByteArray>& vector_data);
|
||||
bool InitHighSpeed();
|
||||
private:
|
||||
//int LJXA_ACQ_Acquire(int lDeviceId, unsigned short* heightImage, unsigned short* luminanceImage, LJXA_ACQ_SETPARAM* setParam, LJXA_ACQ_GETPARAM* getParam);
|
||||
LJX8IF_HIGH_SPEED_PRE_START_REQ* startReq_ptr = nullptr;
|
||||
LJX8IF_PROFILE_INFO* profileInfo_ptr = nullptr;
|
||||
|
||||
// Static variable
|
||||
LJX8IF_ETHERNET_CONFIG _ethernetConfig[MAX_LJXA_DEVICENUM];
|
||||
int _highSpeedPortNo[MAX_LJXA_DEVICENUM];
|
||||
|
||||
LJXA_ACQ_GETPARAM _getParam[MAX_LJXA_DEVICENUM];
|
||||
|
||||
int deviceId = 0; // Set "0" if you use only 1 head.
|
||||
int xImageSize = 0; // Number of X points.
|
||||
int yImageSize = 0; // Number of Y lines.
|
||||
float y_pitch_um = 0; // Data pitch of Y data. (e.g. your encoder setting)
|
||||
int timeout_ms = 0; // Timeout value for the acquiring image (in milisecond).
|
||||
int use_external_batchStart = 1; // Set "1" if you controll the batch start timing externally. (e.g. terminal input) 0内部触发,1外部触发
|
||||
std::string outputFilePath1 = "sample_height.csv";
|
||||
std::string outputFilePath2 = "sample_height.tif";
|
||||
std::string outputFilePath3 = "sample_luminance.tif";
|
||||
|
||||
//std::vector< cv::Mat> vector_mat;
|
||||
unsigned short zUnit = 0;
|
||||
|
||||
unsigned short* heightImage = nullptr; // Height image
|
||||
unsigned short* luminanceImage = nullptr; // Luminance image
|
||||
|
||||
LJXA_ACQ_SETPARAM* setParam_Ptr = nullptr;
|
||||
LJXA_ACQ_GETPARAM* getParam_Ptr = nullptr;
|
||||
int HighSpeedPortNo = 24692; // Port number for high-speed communication
|
||||
bool isopen = false;
|
||||
int errCode;
|
||||
|
||||
LJX8IF_ETHERNET_CONFIG EthernetConfig;
|
||||
|
||||
QString camera_name; // 相机名称
|
||||
int recontimeout_ms = 3000;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
Q_DECL_EXPORT Hd_CameraModule_3DKeyence* create();
|
||||
Q_DECL_EXPORT void destory(Hd_CameraModule_3DKeyence* ptr);
|
||||
}
|
||||
|
||||
#endif // HD_MVCAMERA_MODULE_H
|
||||
@@ -0,0 +1,3 @@
|
||||
基恩士3D相机
|
||||
初始化格式 IP#DEVICE-ID(手动按照初始化的顺序从0开始递增)#图像宽(X)#图像高(Y)#取图次数#超时时间
|
||||
192.168.31.1#0#3200#850#1#1000
|
||||
Reference in New Issue
Block a user