修改BUG:保存图像数据,分相机保存
This commit is contained in:
parent
c96fc7fb63
commit
92fe7b1345
180
camhandler.cpp
180
camhandler.cpp
@ -4,11 +4,15 @@
|
||||
// 构造/析构
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
CamHandler::CamHandler(QObject *parent)
|
||||
: QObject(parent), mDevice(nullptr), mStream(nullptr), mDeviceInfo(nullptr)
|
||||
CamHandler::CamHandler(const QString &name,QObject *parent)
|
||||
: QObject(parent)
|
||||
, mDevice(nullptr)
|
||||
, mStream(nullptr)
|
||||
, mDeviceInfo(nullptr)
|
||||
{
|
||||
camName = name; // <<< 增加 camName 的初始化
|
||||
state = false;
|
||||
saveFlag =false;
|
||||
saveFlag = false;
|
||||
// 连接定时器的超时信号到采集槽
|
||||
connect(&mAcquireTimer, &QTimer::timeout, this, &CamHandler::onAcquireTimerTimeout);
|
||||
|
||||
@ -19,16 +23,14 @@ CamHandler::CamHandler(QObject *parent)
|
||||
CamHandler::~CamHandler()
|
||||
{
|
||||
// 确保在销毁对象时清理资源
|
||||
if (mStream)
|
||||
{
|
||||
if (mStream) {
|
||||
stopAcquisition(); // 确保流和缓冲区已清理
|
||||
mStream->Close();
|
||||
PvStream::Free(mStream);
|
||||
mStream = nullptr;
|
||||
}
|
||||
|
||||
if (mDevice)
|
||||
{
|
||||
if (mDevice) {
|
||||
mDevice->Disconnect();
|
||||
PvDevice::Free(mDevice);
|
||||
mDevice = nullptr;
|
||||
@ -53,13 +55,13 @@ QList<QString> CamHandler::listAvailableDevices()
|
||||
mSystem.Find();
|
||||
|
||||
// 遍历发现的设备
|
||||
for (uint32_t i = 0; i < mSystem.GetDeviceCount(); i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < mSystem.GetDeviceCount(); i++) {
|
||||
const PvDeviceInfo *lInfo = mSystem.GetDeviceInfo(i);
|
||||
// 获取设备的显示ID (例如:型号/序列号)
|
||||
QString lDisplayID = QString::fromLocal8Bit(lInfo->GetDisplayID().GetAscii());
|
||||
|
||||
deviceList.append(lDisplayID + " (ID: " + QString::fromLocal8Bit(lInfo->GetConnectionID().GetAscii()) + ")");
|
||||
deviceList.append(lDisplayID + " (ID: "
|
||||
+ QString::fromLocal8Bit(lInfo->GetConnectionID().GetAscii()) + ")");
|
||||
}
|
||||
|
||||
return deviceList;
|
||||
@ -68,9 +70,8 @@ QList<QString> CamHandler::listAvailableDevices()
|
||||
bool CamHandler::connectToDevice(const QString &aConnectionID)
|
||||
{
|
||||
QString errMsg;
|
||||
if (mDevice)
|
||||
{
|
||||
emit logMsg( "Already connected. Please disconnect first.");
|
||||
if (mDevice) {
|
||||
emit logMsg("Already connected. Please disconnect first.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -78,9 +79,8 @@ bool CamHandler::connectToDevice(const QString &aConnectionID)
|
||||
// 确保在 selectDevice 前调用 Find() (虽然 listAvailableDevices 可能已经调用,但再次调用更安全)
|
||||
mDeviceInfo = selectDevice(aConnectionID);
|
||||
|
||||
if (!mDeviceInfo)
|
||||
{
|
||||
errMsg = "Error: Device not found for ID:" + aConnectionID;
|
||||
if (!mDeviceInfo) {
|
||||
errMsg = "Error: Device not found for ID:" + aConnectionID;
|
||||
emit logMsg(errMsg);
|
||||
return false;
|
||||
}
|
||||
@ -90,15 +90,14 @@ bool CamHandler::connectToDevice(const QString &aConnectionID)
|
||||
PvResult lResult;
|
||||
mDevice = PvDevice::CreateAndConnect(mDeviceInfo, &lResult);
|
||||
|
||||
if (mDevice == nullptr)
|
||||
{
|
||||
emit logMsg( "Error: Unable to connect to device. Result:" + QString(lResult.GetCodeString()));
|
||||
if (mDevice == nullptr) {
|
||||
emit logMsg("Error: Unable to connect to device. Result:"
|
||||
+ QString(lResult.GetCodeString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 打开流
|
||||
if (!openStream())
|
||||
{
|
||||
if (!openStream()) {
|
||||
disconnectDevice();
|
||||
return false;
|
||||
}
|
||||
@ -109,7 +108,7 @@ bool CamHandler::connectToDevice(const QString &aConnectionID)
|
||||
// 5. 创建和队列缓冲区
|
||||
// createStreamBuffers();
|
||||
|
||||
emit logMsg( "Successfully connected and configured stream.");
|
||||
emit logMsg("Successfully connected and configured stream.");
|
||||
state = true;
|
||||
return true;
|
||||
}
|
||||
@ -118,9 +117,8 @@ void CamHandler::startAcquisition()
|
||||
{
|
||||
// 5. 创建和队列缓冲区
|
||||
createStreamBuffers();
|
||||
if (!mDevice || !mStream)
|
||||
{
|
||||
emit logMsg( "Not connected. Cannot start acquisition.");
|
||||
if (!mDevice || !mStream) {
|
||||
emit logMsg("Not connected. Cannot start acquisition.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -128,18 +126,15 @@ void CamHandler::startAcquisition()
|
||||
PvGenParameterArray *lDeviceParams = mDevice->GetParameters();
|
||||
PvGenCommand *lStart = dynamic_cast<PvGenCommand *>(lDeviceParams->Get("AcquisitionStart"));
|
||||
|
||||
if (lStart != nullptr)
|
||||
{
|
||||
emit logMsg( "Enabling streaming and sending AcquisitionStart command.");
|
||||
if (lStart != nullptr) {
|
||||
emit logMsg("Enabling streaming and sending AcquisitionStart command.");
|
||||
mDevice->StreamEnable(); // 启用流
|
||||
lStart->Execute(); // 发送命令
|
||||
lStart->Execute(); // 发送命令
|
||||
|
||||
// 3. 启动定时器,驱动采集循环
|
||||
mAcquireTimer.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
emit logMsg( "Error: AcquisitionStart command not found on device.");
|
||||
} else {
|
||||
emit logMsg("Error: AcquisitionStart command not found on device.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,10 +144,9 @@ void CamHandler::stopAcquisition()
|
||||
return;
|
||||
|
||||
// 1. 停止计时器
|
||||
if (mAcquireTimer.isActive())
|
||||
{
|
||||
if (mAcquireTimer.isActive()) {
|
||||
mAcquireTimer.stop();
|
||||
emit logMsg( "Acquisition timer stopped.");
|
||||
emit logMsg("Acquisition timer stopped.");
|
||||
}
|
||||
|
||||
// 2. 获取 AcquisitionStop 命令
|
||||
@ -160,47 +154,43 @@ void CamHandler::stopAcquisition()
|
||||
PvGenCommand *lStop = dynamic_cast<PvGenCommand *>(lDeviceParams->Get("AcquisitionStop"));
|
||||
|
||||
// 3. 停止采集和禁用流
|
||||
if (lStop != nullptr)
|
||||
{
|
||||
emit logMsg( "Sending AcquisitionStop command to the device");
|
||||
if (lStop != nullptr) {
|
||||
emit logMsg("Sending AcquisitionStop command to the device");
|
||||
lStop->Execute();
|
||||
}
|
||||
emit logMsg( "Disable streaming on the controller.");
|
||||
emit logMsg("Disable streaming on the controller.");
|
||||
mDevice->StreamDisable();
|
||||
|
||||
// 4. 清理缓冲区:终止队列中的所有缓冲区并将它们移到输出队列
|
||||
emit logMsg( "Aborting buffers still in stream");
|
||||
emit logMsg("Aborting buffers still in stream");
|
||||
mStream->AbortQueuedBuffers();
|
||||
|
||||
// 5. 从输出队列中检索剩余的缓冲区,丢弃它们
|
||||
PvBuffer *lBuffer = NULL;
|
||||
PvResult lOperationResult;
|
||||
// 必须清空队列,防止下次采集时使用错误的旧缓冲区
|
||||
while (mStream->GetQueuedBufferCount() > 0)
|
||||
{
|
||||
while (mStream->GetQueuedBufferCount() > 0) {
|
||||
mStream->RetrieveBuffer(&lBuffer, &lOperationResult);
|
||||
// 注意:这里没有释放 lBuffer,因为缓冲区资源将在析构或断开时处理
|
||||
}
|
||||
|
||||
emit logMsg( "Acquisition stopped and buffers cleaned up.");
|
||||
emit logMsg("Acquisition stopped and buffers cleaned up.");
|
||||
}
|
||||
|
||||
void CamHandler::disconnectDevice()
|
||||
{
|
||||
// 停止采集,清理流资源
|
||||
if (mStream)
|
||||
{
|
||||
if (mStream) {
|
||||
stopAcquisition(); // 确保流和缓冲区已清理
|
||||
emit logMsg( "Closing stream");
|
||||
emit logMsg("Closing stream");
|
||||
mStream->Close();
|
||||
PvStream::Free(mStream);
|
||||
mStream = nullptr;
|
||||
}
|
||||
|
||||
// 断开设备连接,释放设备资源
|
||||
if (mDevice)
|
||||
{
|
||||
emit logMsg( "Disconnecting device");
|
||||
if (mDevice) {
|
||||
emit logMsg("Disconnecting device");
|
||||
mDevice->Disconnect();
|
||||
PvDevice::Free(mDevice);
|
||||
mDevice = nullptr;
|
||||
@ -209,8 +199,8 @@ void CamHandler::disconnectDevice()
|
||||
// mDeviceInfo 由 mSystem 管理,置空指针
|
||||
mDeviceInfo = nullptr;
|
||||
|
||||
emit logMsg( "Disconnected and resources freed.");
|
||||
state =false;
|
||||
emit logMsg("Disconnected and resources freed.");
|
||||
state = false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
@ -231,38 +221,29 @@ void CamHandler::onAcquireTimerTimeout()
|
||||
// 尝试检索下一个缓冲区,使用较短的超时时间 (10ms)
|
||||
PvResult lResult = mStream->RetrieveBuffer(&lBuffer, &lOperationResult, 10);
|
||||
|
||||
if (lResult.IsOK())
|
||||
{
|
||||
if (lOperationResult.IsOK())
|
||||
{
|
||||
if (lResult.IsOK()) {
|
||||
if (lOperationResult.IsOK()) {
|
||||
// 成功采集到有效图像
|
||||
PvPayloadType lType = lBuffer->GetPayloadType();
|
||||
|
||||
if (lType == PvPayloadTypeImage)
|
||||
{
|
||||
if (lType == PvPayloadTypeImage) {
|
||||
// 转换为 QImage 并发送信号
|
||||
QImage image = convertPvBufferToQImage(lBuffer);
|
||||
if (!image.isNull())
|
||||
{
|
||||
if (!image.isNull()) {
|
||||
emit imageReady(image);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
emit logMsg("Image conversion failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
emit logMsg( "Buffer retrieved, but does not contain an image payload. Requeuing.");
|
||||
} else {
|
||||
emit logMsg("Buffer retrieved, but does not contain an image payload. Requeuing.");
|
||||
}
|
||||
|
||||
// 重新排队缓冲区
|
||||
mStream->QueueBuffer(lBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// 检索到缓冲区但操作结果不成功(例如:超时、重发过多)
|
||||
emit logMsg( "RetrieveBuffer operation result is not OK:" + QString(lOperationResult.GetCodeString()) + ". Requeuing.");
|
||||
emit logMsg("RetrieveBuffer operation result is not OK:"
|
||||
+ QString(lOperationResult.GetCodeString()) + ". Requeuing.");
|
||||
mStream->QueueBuffer(lBuffer); // 必须重新排队
|
||||
}
|
||||
}
|
||||
@ -278,13 +259,11 @@ const PvDeviceInfo *CamHandler::selectDevice(const QString &aConnectionID)
|
||||
{
|
||||
mSystem.Find();
|
||||
// mSystem.Find() 已经在 connectToDevice 中调用
|
||||
for (uint32_t i = 0; i < mSystem.GetDeviceCount(); i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < mSystem.GetDeviceCount(); i++) {
|
||||
const PvDeviceInfo *lInfo = mSystem.GetDeviceInfo(i); // 从成员变量 mSystem 获取
|
||||
QString tmp = QString::fromLocal8Bit(lInfo->GetConnectionID().GetAscii());
|
||||
|
||||
if (aConnectionID == tmp)
|
||||
{
|
||||
if (aConnectionID == tmp) {
|
||||
// 找到匹配的设备,返回的指针由 mSystem 管理,在 CamHandler 生命周期内有效
|
||||
return lInfo;
|
||||
}
|
||||
@ -294,30 +273,32 @@ const PvDeviceInfo *CamHandler::selectDevice(const QString &aConnectionID)
|
||||
|
||||
bool CamHandler::openStream()
|
||||
{
|
||||
emit logMsg( "Opening stream to device.");
|
||||
emit logMsg("Opening stream to device.");
|
||||
PvResult lResult;
|
||||
|
||||
// 使用静态工厂方法 PvStream::CreateAndOpen
|
||||
mStream = PvStream::CreateAndOpen(mDeviceInfo->GetConnectionID(), &lResult);
|
||||
|
||||
if (mStream == nullptr)
|
||||
{
|
||||
emit logMsg( "Error: Unable to stream from device. Result:" + QString(lResult.GetCodeString()));
|
||||
if (mStream == nullptr) {
|
||||
emit logMsg("Error: Unable to stream from device. Result:"
|
||||
+ QString(lResult.GetCodeString()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CamHandler::createStreamBuffers()
|
||||
{
|
||||
// 从设备获取 payload size (图像/数据的字节大小)
|
||||
uint32_t lSize = mDevice->GetPayloadSize();
|
||||
|
||||
// 确定要创建的缓冲区数量
|
||||
uint32_t lBufferCount = (mStream->GetQueuedBufferMaximum() < BUFFER_COUNT) ? mStream->GetQueuedBufferMaximum() : BUFFER_COUNT;
|
||||
uint32_t lBufferCount = (mStream->GetQueuedBufferMaximum() < BUFFER_COUNT)
|
||||
? mStream->GetQueuedBufferMaximum()
|
||||
: BUFFER_COUNT;
|
||||
|
||||
emit logMsg( "Allocating" + QString::number(lBufferCount) + " buffers of size " + QString::number(lSize) + " bytes.");
|
||||
emit logMsg("Allocating" + QString::number(lBufferCount) + " buffers of size "
|
||||
+ QString::number(lSize) + " bytes.");
|
||||
|
||||
// 分配 PvBuffer 数组
|
||||
// 注意:在析构函数或 disconnectDevice 中需要释放这个内存!
|
||||
@ -326,8 +307,7 @@ void CamHandler::createStreamBuffers()
|
||||
// **重要提示:您的原始代码没有在析构函数中释放 lBuffers 指针!** // 这是一个内存泄漏风险。要解决这个问题,您需要将 lBuffers 存储为一个成员变量 (例如 QList<PvBuffer*>)
|
||||
// 或者只在析构函数/disconnectDevice 中确保释放它们。
|
||||
|
||||
for (uint32_t i = 0; i < lBufferCount; i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < lBufferCount; i++) {
|
||||
// 为每个缓冲区分配内存
|
||||
(lBuffers + i)->Alloc(static_cast<uint32_t>(lSize));
|
||||
|
||||
@ -343,40 +323,30 @@ QImage CamHandler::convertPvBufferToQImage(PvBuffer *aBuffer)
|
||||
uint32_t lWidth = lImage->GetWidth();
|
||||
uint32_t lHeight = lImage->GetHeight();
|
||||
|
||||
|
||||
|
||||
|
||||
// 使用全局线程池启动任务 (异步执行)
|
||||
// 简化实现:仅支持 Mono8 (8位灰度) 格式
|
||||
if (lImage->GetPixelType() == PvPixelMono8)
|
||||
{
|
||||
if(saveFlag){
|
||||
if (lImage->GetPixelType() == PvPixelMono8) {
|
||||
if (saveFlag) {
|
||||
const void *lDataPointer = lImage->GetDataPointer();
|
||||
quint32 lDataSize = lImage->GetImageSize();
|
||||
// 3. 复制原始数据到 QByteArray(线程安全的关键)
|
||||
QByteArray rawDataCopy(
|
||||
reinterpret_cast<const char*>(lDataPointer),
|
||||
lDataSize
|
||||
);
|
||||
QByteArray rawDataCopy(reinterpret_cast<const char *>(lDataPointer), lDataSize);
|
||||
|
||||
// 4. 创建 SaveTask 并提交给全局线程池
|
||||
SaveTask *task = new SaveTask(
|
||||
rawDataCopy
|
||||
);
|
||||
SaveTask *task = new SaveTask(rawDataCopy,camName);
|
||||
|
||||
QThreadPool::globalInstance()->start(task);
|
||||
}
|
||||
|
||||
// 直接使用图像数据创建 QImage
|
||||
return QImage(
|
||||
(uchar *)lImage->GetDataPointer(),
|
||||
lWidth,
|
||||
lHeight,
|
||||
lWidth, // 步长/字节数
|
||||
QImage::Format_Grayscale8
|
||||
).copy(); // .copy() 确保 QImage 拥有数据,安全地在 Qt 环境中使用
|
||||
return QImage((uchar *) lImage->GetDataPointer(),
|
||||
lWidth,
|
||||
lHeight,
|
||||
lWidth, // 步长/字节数
|
||||
QImage::Format_Grayscale8)
|
||||
.copy(); // .copy() 确保 QImage 拥有数据,安全地在 Qt 环境中使用
|
||||
}
|
||||
|
||||
emit logMsg( "Unsupported pixel format" );
|
||||
emit logMsg("Unsupported pixel format");
|
||||
return QImage();
|
||||
}
|
||||
|
||||
28
camhandler.h
28
camhandler.h
@ -1,25 +1,25 @@
|
||||
#ifndef CAMHANDLER_H
|
||||
#define CAMHANDLER_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QImage> // 用于在信号中传输图像数据
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QImage> // 用于在信号中传输图像数据
|
||||
#include <QTimer> // 用于驱动采集循环
|
||||
#include <QTimer> // 用于驱动采集循环
|
||||
|
||||
// eBUS SDK 核心头文件
|
||||
#include <PvSystem.h>
|
||||
#include <QThreadPool> // 需要包含 QThreadPool
|
||||
#include "savetask.h"
|
||||
#include <PvBuffer.h>
|
||||
#include <PvDevice.h>
|
||||
#include <PvDeviceU3V.h>
|
||||
#include <PvGenCommand.h>
|
||||
#include <PvGenParameter.h>
|
||||
#include <PvGenParameterArray.h>
|
||||
#include <PvImage.h>
|
||||
#include <PvStream.h>
|
||||
#include <PvStreamU3V.h>
|
||||
#include <PvBuffer.h>
|
||||
#include <PvImage.h>
|
||||
#include <PvGenParameter.h>
|
||||
#include <PvGenCommand.h>
|
||||
#include <PvGenParameterArray.h>
|
||||
#include "savetask.h"
|
||||
#include <QThreadPool> // 需要包含 QThreadPool
|
||||
#include <PvSystem.h>
|
||||
|
||||
// 用于流缓冲区数量的定义 (参考例程)
|
||||
#define BUFFER_COUNT 16
|
||||
@ -29,7 +29,7 @@ class CamHandler : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CamHandler(QObject *parent = nullptr);
|
||||
explicit CamHandler(const QString &name,QObject *parent = nullptr);
|
||||
~CamHandler();
|
||||
|
||||
// 公有接口:连接/断开/发现
|
||||
@ -43,11 +43,11 @@ public:
|
||||
void stopAcquisition();
|
||||
bool state;
|
||||
bool saveFlag;
|
||||
|
||||
QString camName;
|
||||
|
||||
// ------------------- 信号 (Signals) -------------------
|
||||
signals:
|
||||
void imageReady(const QImage &image); // 发送采集到的图像数据
|
||||
void imageReady(const QImage &image); // 发送采集到的图像数据
|
||||
void logMsg(const QString &msg);
|
||||
|
||||
// ------------------- 槽 (Slots) -------------------
|
||||
|
||||
@ -18,11 +18,9 @@ DialogCamSet::~DialogCamSet()
|
||||
void DialogCamSet::on_pushButton_2_clicked()
|
||||
{
|
||||
QString portName = ui->comboBox->currentText();
|
||||
if(!ph->openPort(portName)){
|
||||
QMessageBox::critical(this,"Error","Connect "+portName +" Failed");
|
||||
}else{
|
||||
QMessageBox::information(this,"Success","Connect "+portName +" Successfully");
|
||||
if (!ph->openPort(portName)) {
|
||||
QMessageBox::critical(this, "Error", "Connect " + portName + " Failed");
|
||||
} else {
|
||||
QMessageBox::information(this, "Success", "Connect " + portName + " Successfully");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
#define DIALOGCAMSET_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "parameterhandler.h"
|
||||
#include "QMessageBox"
|
||||
#include "parameterhandler.h"
|
||||
|
||||
namespace Ui {
|
||||
class DialogCamSet;
|
||||
|
||||
@ -6,18 +6,16 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
cam1 = new CamHandler();
|
||||
cam2 = new CamHandler();
|
||||
connect(cam1,&CamHandler::logMsg,this,&MainWindow::onLogPrint1);
|
||||
connect(cam1,&CamHandler::imageReady,this,&MainWindow::picUpdate1);
|
||||
cam1 = new CamHandler("cam1",this);
|
||||
cam2 = new CamHandler("cam2",this);
|
||||
connect(cam1, &CamHandler::logMsg, this, &MainWindow::onLogPrint1);
|
||||
connect(cam1, &CamHandler::imageReady, this, &MainWindow::picUpdate1);
|
||||
|
||||
|
||||
connect(cam2,&CamHandler::logMsg,this,&MainWindow::onLogPrint2);
|
||||
connect(cam2, &CamHandler::logMsg, this, &MainWindow::onLogPrint2);
|
||||
|
||||
m_scene1 = new QGraphicsScene(this);
|
||||
ui->graphicsView->setScene(m_scene1);
|
||||
m_imageItem1 = nullptr; // 初始化图像项指针
|
||||
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@ -29,23 +27,20 @@ void MainWindow::onLogPrint1(const QString &msg)
|
||||
{
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
QString dateTimeString = currentDateTime.toString("yyyy--MM--dd HH-mm-ss");
|
||||
ui->textBrowser->append(dateTimeString+" [cam1] --> " +msg);
|
||||
|
||||
ui->textBrowser->append(dateTimeString + " [cam1] --> " + msg);
|
||||
}
|
||||
|
||||
void MainWindow::onLogPrint2(const QString &msg)
|
||||
{
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
QString dateTimeString = currentDateTime.toString("yyyy--MM--dd HH-mm-ss");
|
||||
ui->textBrowser->append(dateTimeString+" [cam2] --> " +msg);
|
||||
|
||||
ui->textBrowser->append(dateTimeString + " [cam2] --> " + msg);
|
||||
}
|
||||
|
||||
void MainWindow::picUpdate1(const QImage &image)
|
||||
{
|
||||
// onLogPrint1("here rev");
|
||||
if (image.isNull())
|
||||
{
|
||||
if (image.isNull()) {
|
||||
qWarning() << "Received null image.";
|
||||
return;
|
||||
}
|
||||
@ -57,8 +52,7 @@ void MainWindow::picUpdate1(const QImage &image)
|
||||
QPixmap pixmap = QPixmap::fromImage(image);
|
||||
|
||||
// 2. 将 QPixmap 放入 QGraphicsPixmapItem 中
|
||||
if (m_imageItem1 == nullptr)
|
||||
{
|
||||
if (m_imageItem1 == nullptr) {
|
||||
// 第一次显示图像:创建 QGraphicsPixmapItem 并添加到 Scene
|
||||
m_imageItem1 = m_scene1->addPixmap(pixmap);
|
||||
|
||||
@ -68,9 +62,7 @@ void MainWindow::picUpdate1(const QImage &image)
|
||||
// 可选:调整 QGraphicsView 视口以适应图像
|
||||
// 如果您希望图像完整显示在 View 中,可以调用 fitInView
|
||||
ui->graphicsView->fitInView(m_scene1->sceneRect(), Qt::KeepAspectRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// 更新现有图像(更高效):直接更新 QGraphicsPixmapItem 的 QPixmap
|
||||
m_imageItem1->setPixmap(pixmap);
|
||||
}
|
||||
@ -83,10 +75,8 @@ void MainWindow::on_pushButton_2_clicked()
|
||||
{
|
||||
dc = new DialogCamSet(this);
|
||||
dc->show();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_pushButton_3_clicked()
|
||||
|
||||
{
|
||||
@ -97,7 +87,7 @@ void MainWindow::on_pushButton_3_clicked()
|
||||
// }
|
||||
// cam1->connectToDevice("28B702523408");
|
||||
|
||||
if(!cam1->connectToDevice("28B702523408")){
|
||||
if (!cam1->connectToDevice("28B702523408")) {
|
||||
onLogPrint1("open failed");
|
||||
return;
|
||||
}
|
||||
@ -107,53 +97,41 @@ void MainWindow::on_pushButton_3_clicked()
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
// cam2->startAcquisition();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_pushButton_4_clicked()
|
||||
{
|
||||
if(cam1->state){
|
||||
if (cam1->state) {
|
||||
cam1->stopAcquisition();
|
||||
}else{
|
||||
} else {
|
||||
onLogPrint1("Please connect firstly");
|
||||
}
|
||||
// cam2->stopAcquisition();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_pushButton_5_clicked()
|
||||
{
|
||||
ui->textBrowser->clear();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_pushButton_6_clicked()
|
||||
{
|
||||
if(cam1->state){
|
||||
if (cam1->state) {
|
||||
cam1->startAcquisition();
|
||||
}else{
|
||||
} else {
|
||||
onLogPrint1("Please connect firstly");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_pushButton_clicked()
|
||||
{
|
||||
cam1->saveFlag=true;
|
||||
cam1->saveFlag = true;
|
||||
onLogPrint1("start saving ...");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_pushButton_7_clicked()
|
||||
{
|
||||
|
||||
cam1->saveFlag=false;
|
||||
cam1->saveFlag = false;
|
||||
onLogPrint1("stop saving ...");
|
||||
|
||||
}
|
||||
|
||||
|
||||
13
mainwindow.h
13
mainwindow.h
@ -1,13 +1,12 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include "dialogcamset.h"
|
||||
#include "camhandler.h"
|
||||
#include "QDateTime"
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsPixmapItem>
|
||||
|
||||
#include <QGraphicsScene>
|
||||
#include <QMainWindow>
|
||||
#include "QDateTime"
|
||||
#include "camhandler.h"
|
||||
#include "dialogcamset.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
@ -28,7 +27,6 @@ public slots:
|
||||
void onLogPrint2(const QString &msg);
|
||||
void picUpdate1(const QImage &image);
|
||||
|
||||
|
||||
private slots:
|
||||
void on_pushButton_2_clicked();
|
||||
|
||||
@ -52,6 +50,5 @@ private:
|
||||
|
||||
QGraphicsScene *m_scene1;
|
||||
QGraphicsPixmapItem *m_imageItem1; // 用于保存图像项的指针
|
||||
|
||||
};
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
@ -1,22 +1,23 @@
|
||||
#include "ParameterHandler.h"
|
||||
#include <QDebug>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
|
||||
ParameterHandler::ParameterHandler(QObject *parent)
|
||||
: QObject(parent), m_serialPort(new QSerialPort(this))
|
||||
: QObject(parent)
|
||||
, m_serialPort(new QSerialPort(this))
|
||||
{
|
||||
// 将 QSerialPort 的 readyRead 信号连接到槽函数,用于数据接收
|
||||
connect(m_serialPort, &QSerialPort::readyRead,
|
||||
this, &ParameterHandler::handleReadyRead);
|
||||
connect(m_serialPort, &QSerialPort::readyRead, this, &ParameterHandler::handleReadyRead);
|
||||
|
||||
// 将 QSerialPort 的 errorOccurred 信号连接到槽函数,用于错误处理
|
||||
// 使用 QOverload 确保连接到正确的重载函数
|
||||
connect(m_serialPort, QOverload<QSerialPort::SerialPortError>::of(&QSerialPort::errorOccurred),
|
||||
this, &ParameterHandler::handleError);
|
||||
connect(m_serialPort,
|
||||
QOverload<QSerialPort::SerialPortError>::of(&QSerialPort::errorOccurred),
|
||||
this,
|
||||
&ParameterHandler::handleError);
|
||||
}
|
||||
|
||||
|
||||
ParameterHandler::~ParameterHandler()
|
||||
{
|
||||
// 析构时确保串口关闭
|
||||
@ -51,7 +52,8 @@ bool ParameterHandler::openPort(const QString &portName)
|
||||
|
||||
// 1. 尝试打开串口,以读写模式
|
||||
if (!m_serialPort->open(QIODevice::ReadWrite)) {
|
||||
QString errorMsg = QString("无法打开串口 %1: %2").arg(portName).arg(m_serialPort->errorString());
|
||||
QString errorMsg
|
||||
= QString("无法打开串口 %1: %2").arg(portName).arg(m_serialPort->errorString());
|
||||
qWarning() << errorMsg;
|
||||
emit errorOccurred(errorMsg);
|
||||
return false;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
#ifndef PARAMETERHANDLER_H
|
||||
#define PARAMETERHANDLER_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QObject>
|
||||
#include <QSerialPort>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QSerialPortInfo> // <-- 增加此头文件
|
||||
#include <QString>
|
||||
|
||||
class ParameterHandler : public QObject
|
||||
{
|
||||
|
||||
31
savetask.cpp
31
savetask.cpp
@ -1,30 +1,35 @@
|
||||
// SaveTask.cpp 文件中
|
||||
|
||||
#include "SaveTask.h"
|
||||
|
||||
// 实际的 run() 方法在 SaveTask.cpp 中实现
|
||||
void SaveTask::run()
|
||||
{
|
||||
if (m_rawData.isEmpty())
|
||||
{
|
||||
qWarning("SaveTask received empty raw data. Aborting save.");
|
||||
qWarning("SaveTask for camera %s received empty raw data. Aborting save.", qPrintable(m_camName));
|
||||
return;
|
||||
}
|
||||
|
||||
// --- 耗时的文件 I/O 操作在此处执行,不阻塞主线程 ---
|
||||
// --- 耗时的文件 I/O 操作在此处执行,在线程池中 ---
|
||||
|
||||
QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmsszzz");
|
||||
|
||||
// 构造文件名:时间戳_宽度x高度_像素类型.raw
|
||||
QString filename = QString("%1.raw")
|
||||
// 构造文件名:相机名称_时间戳.raw
|
||||
QString filename = QString("%1_%2.raw")
|
||||
.arg(m_camName)
|
||||
.arg(timestamp);
|
||||
|
||||
|
||||
// 设置保存路径
|
||||
QString savePath = QDir::currentPath() + "/RawSavedImages/";
|
||||
// 使用相机名称创建保存路径的子目录
|
||||
QString savePath = QDir::currentPath() + "/RawSavedImages/" + m_camName + "/"; // <<< 增加目录
|
||||
|
||||
QDir dir(savePath);
|
||||
if (!dir.exists())
|
||||
{
|
||||
dir.mkpath(".");
|
||||
if (!dir.mkpath("."))
|
||||
{
|
||||
qWarning("Error: Failed to create save directory: %s", qPrintable(savePath));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QString fullPath = savePath + filename;
|
||||
@ -36,16 +41,12 @@ void SaveTask::run()
|
||||
qint64 bytesWritten = file.write(m_rawData);
|
||||
file.close();
|
||||
|
||||
if (bytesWritten == m_rawData.size())
|
||||
{
|
||||
// 保存成功,可以发送日志或简单地使用 qInfo()
|
||||
// qInfo() << "Raw data saved successfully to:" << fullPath;
|
||||
}
|
||||
else
|
||||
if (bytesWritten != m_rawData.size())
|
||||
{
|
||||
qWarning() << QString("Error: Only %1 of %2 bytes written to %3")
|
||||
.arg(bytesWritten).arg(m_rawData.size()).arg(fullPath);
|
||||
}
|
||||
// else { qInfo() << "Raw data saved successfully to:" << fullPath; }
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
10
savetask.h
10
savetask.h
@ -1,12 +1,12 @@
|
||||
#ifndef SAVETASK_H
|
||||
#define SAVETASK_H
|
||||
|
||||
#include <QRunnable>
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QRunnable>
|
||||
|
||||
/**
|
||||
* @brief SaveTask 封装了将原始图像字节数据异步保存到文件的任务。
|
||||
@ -22,8 +22,8 @@ public:
|
||||
* @param height 图像高度。
|
||||
* @param pixelType 图像的原始像素格式(例如 PvPixelMono8 的整数值)。
|
||||
*/
|
||||
SaveTask(const QByteArray &data)
|
||||
: m_rawData(data)
|
||||
SaveTask(const QByteArray &data, const QString &camName)
|
||||
: m_rawData(data), m_camName(camName) // <<< 增加 camName 的初始化
|
||||
{
|
||||
// 设置为 true,以便任务执行完成后,QThreadPool 自动清理内存
|
||||
setAutoDelete(true);
|
||||
@ -36,7 +36,7 @@ public:
|
||||
|
||||
private:
|
||||
QByteArray m_rawData;
|
||||
|
||||
QString m_camName; // <<< 增加成员变量来存储相机名称
|
||||
};
|
||||
|
||||
#endif // SAVETASK_H
|
||||
|
||||
Loading…
Reference in New Issue
Block a user