From 40a40b4a211fd45debe3ba4b7f113cca951cd0cd Mon Sep 17 00:00:00 2001 From: kooki3 <1498306179@qq.com> Date: Thu, 11 Dec 2025 14:38:59 +0800 Subject: [PATCH] =?UTF-8?q?VisualRobot=5Fwzh=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=9F=BA=E4=BA=8E=E9=97=B4=E6=AD=87=E6=80=A7=E8=BD=AF=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E7=9A=84=E4=BC=AA=E5=AE=9E=E6=97=B6=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VisualRobot/mainwindow.cpp | 71 ++++++++++++++++++++++++++++++++++++++ VisualRobot/mainwindow.h | 13 +++++++ 2 files changed, 84 insertions(+) diff --git a/VisualRobot/mainwindow.cpp b/VisualRobot/mainwindow.cpp index ac91902..a0a397d 100644 --- a/VisualRobot/mainwindow.cpp +++ b/VisualRobot/mainwindow.cpp @@ -75,6 +75,7 @@ MainWindow::MainWindow(QWidget *parent) : m_pcMyCamera = NULL; m_bGrabbing = false; m_hWnd = (void*)ui->widgetDisplay->winId(); + m_isTriggerMode = false; // 初始化触发模式标志 // 初始化设备热拔插自动枚举相关变量 m_deviceEnumTimer = new QTimer(this); @@ -120,6 +121,14 @@ MainWindow::MainWindow(QWidget *parent) : m_yoloStatsTimer = new QTimer(this); connect(m_yoloStatsTimer, &QTimer::timeout, this, &MainWindow::UpdateYoloStats); + // 初始化间歇软触发定时器 + m_softTriggerTimer = new QTimer(this); + m_softTriggerEnabled = false; + connect(m_softTriggerTimer, &QTimer::timeout, this, &MainWindow::onSoftTriggerTimeout); + + // 初始化新帧等待相关 + m_newFrameAvailable = false; + // 加载缺陷分类模板库 if (m_defectDetection->LoadTemplateLibrary("../Img/Templates")) { @@ -173,6 +182,9 @@ MainWindow::MainWindow(QWidget *parent) : on_bnEnum_clicked(); } + + + MainWindow::~MainWindow() { if (m_sysMonitor) @@ -323,6 +335,13 @@ void __stdcall MainWindow::ImageCallBack(unsigned char * pData, MV_FRAME_OUT_INF // 拷贝一份到临时变量, 用于清晰度计算 tempFrame = pMainWindow->m_lastFrame; + + // 如果是触发模式,通知新帧可用 + if (pMainWindow->m_isTriggerMode) { + QMutexLocker locker(&pMainWindow->m_newFrameMutex); + pMainWindow->m_newFrameAvailable = true; + pMainWindow->m_newFrameCondition.wakeAll(); + } } // 3) 计算清晰度并发射信号 @@ -358,6 +377,7 @@ void __stdcall MainWindow::ImageCallBack(unsigned char * pData, MV_FRAME_OUT_INF } } + void MainWindow::ImageCallBackInner(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo) { // 变量定义 @@ -623,10 +643,12 @@ void MainWindow::on_bnContinuesMode_clicked() m_pcMyCamera->SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF); ui->cbSoftTrigger->setEnabled(false); ui->bnTriggerExec->setEnabled(false); + m_isTriggerMode = false; // 切换到连续模式 } AppendLog("连续模式已开启", INFO); } + void MainWindow::on_bnTriggerMode_clicked() { if (true == ui->bnTriggerMode->isChecked()) @@ -645,10 +667,12 @@ void MainWindow::on_bnTriggerMode_clicked() m_pcMyCamera->SetEnumValue("TriggerSource", MV_TRIGGER_SOURCE_LINE0); } ui->cbSoftTrigger->setEnabled(true); + m_isTriggerMode = true; // 设置触发模式标志 } AppendLog("触发模式已开启", INFO); } + void MainWindow::on_bnStart_clicked() { // 变量定义 @@ -708,12 +732,44 @@ void MainWindow::on_cbSoftTrigger_clicked() ui->bnTriggerExec->setEnabled(true); AppendLog("软件触发已开启", INFO); } + + // 启用间歇软触发,每0.5秒触发一次 + m_softTriggerEnabled = true; + m_softTriggerTimer->start(500); // 500ms间隔 + AppendLog("间歇软触发已启用,每0.5秒自动触发", INFO); } else { m_pcMyCamera->SetEnumValue("TriggerSource", MV_TRIGGER_SOURCE_LINE0); AppendLog("软件触发已关闭", INFO); ui->bnTriggerExec->setEnabled(false); + + // 禁用间歇软触发 + m_softTriggerEnabled = false; + m_softTriggerTimer->stop(); + AppendLog("间歇软触发已禁用", INFO); + } +} + + +void MainWindow::onSoftTriggerTimeout() +{ + if (!m_softTriggerEnabled || !m_bGrabbing || !m_pcMyCamera) { + return; + } + + // 执行软件触发 + int nRet = m_pcMyCamera->CommandExecute("TriggerSoftware"); + if (MV_OK != nRet) { + AppendLog("间歇软触发执行失败", ERROR); + } else { + // 只在第一次或每10次触发时记录日志,避免日志过多 + static int triggerCount = 0; + if (triggerCount % 10 == 0 || triggerCount == 0) { + AppendLog(QString("间歇软触发执行成功 (第%1次)").arg(++triggerCount), INFO); + } else { + ++triggerCount; + } } } @@ -734,6 +790,7 @@ void MainWindow::on_bnTriggerExec_clicked() } } + void MainWindow::on_bnGetParam_clicked() { // 变量定义 @@ -3224,6 +3281,19 @@ void MainWindow::YoloRealTimeDetectionThread() break; } + // 如果是触发模式,等待新帧可用 + if (m_isTriggerMode) { + QMutexLocker locker(&m_newFrameMutex); + while (!m_newFrameAvailable && m_yoloDetectionRunning) { + m_newFrameCondition.wait(&m_newFrameMutex); + } + if (m_yoloDetectionRunning) { + m_newFrameAvailable = false; + } else { + break; + } + } + // 获取最新帧 if (!GrabLastFrameBGR(currentFrame)) { @@ -3299,6 +3369,7 @@ void MainWindow::YoloRealTimeDetectionThread() QThread::msleep(10); } + // 停止统计信息定时器 m_yoloStatsTimer->stop(); diff --git a/VisualRobot/mainwindow.h b/VisualRobot/mainwindow.h index ad142c1..5ad1297 100644 --- a/VisualRobot/mainwindow.h +++ b/VisualRobot/mainwindow.h @@ -67,6 +67,7 @@ private slots: void on_CallDLwindow_clicked(); // 新增的槽函数 void on_bnCapture_clicked(); // 拍照按钮点击事件 + void onSoftTriggerTimeout(); // 软件触发定时器超时槽函数 private: Ui::MainWindow *ui; @@ -159,6 +160,18 @@ private: double m_biasLength = 0.0; // 长度变换系数 double m_biasWidth = 0.0; // 宽度变换系数 + // 间歇软触发相关 + QTimer* m_softTriggerTimer; // 软件触发定时器 + bool m_softTriggerEnabled; // 软件触发使能标志 + bool m_isTriggerMode; // 当前是否为触发模式 + + // 新帧等待相关(用于YOLO在触发模式下等待) + QMutex m_newFrameMutex; + QWaitCondition m_newFrameCondition; + bool m_newFrameAvailable; + + + // 将缓存的最新一帧转为BGR Mat(经SDK内存编码为JPEG后imdecode,稳妥) bool GrabLastFrameBGR(Mat& outBGR); // Mat 转 QPixmap(显示用) -- Gitee