add callback imaging
This commit is contained in:
parent
e89cf3b359
commit
ed0895405a
27
CMakeSettings.json
Normal file
27
CMakeSettings.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
{
|
||||
"name": "x64-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Release",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"variables": []
|
||||
}
|
||||
]
|
||||
}
|
||||
108
LLM.md
108
LLM.md
@ -1,88 +1,30 @@
|
||||
请帮助我生成一个C++编写的Qt UI代码,使用`initUI()`函数实现UI的创建,具体要求如下:
|
||||
这个类的签名为`class HikWidget`继承自QWidget
|
||||
整个UI分为左右两部分,水平分布比例为3:1,开始时设置窗口大小为1280x720
|
||||
左侧为一个QGraphicsView控件,为类成员变量`QGraphicsView *m_gv`,后面如无特殊说明类内成员变量都应当以`m_`开头
|
||||
右侧为三个groupbox,这三个groupbox垂直分布,这里可以使用局部变量,从上到下分别显示文字为“相机操作”、“图像保存”、“相机参数”
|
||||
“相机操作”groupbox中为一个2x2表格布局,里面有四个pushButton控件,从左到右从上倒下分别显示“打开相机”、“关闭相机”、“开始取流”、“结束取流”
|
||||
这几个pushButton声明为成员变量,并根据控件属性和提示文字含义帮我取变量名,例如“打开相机”对应`QPushBotton *m_btn_opencamera`
|
||||
“图像保存”groupbox中为一个水平布局,包括一个只读的lineEditor、一个comboBox、两个pushBotton,这四个控件都应该是成员变量
|
||||
lineEditor中显示保存文件路径,comboBox选择保存图像格式,至少有`.jpg`, `.png`, `.tif`, `.bmp`几个选项
|
||||
两个pushButton显示文字为“打开...”和“保存”,一个负责选择保存路径,一个实际执行保存行为(initUI时不考虑信号与槽)
|
||||
最后“相机参数”groupbox中为一个2x2的表格布局,每一行都是一个label和一个doubelSpinBox,其中两个spin应当为成员变量
|
||||
第一行的label显示文字“曝光时间:”,对应第一行的spin设置的是曝光时间
|
||||
第二行的label显示文字“增益设置:”,对应第二行的spin设置的是增益
|
||||
|
||||
---
|
||||
|
||||
我希望将图像保存GroupBox修改一下设计,将这个GroupBox修改为2x3表格布局
|
||||
第一行3列合并显示m_edit_savePath,第二行分别显示m_cmb_imgFormat、m_btn_openDir、m_btn_saveImage
|
||||
请结合手册提供的回调函数注册代码,使用 lambda 函数的方式,实现类 `` 中的注册回调函数功能
|
||||
|
||||
```cpp
|
||||
// 图像保存GroupBox
|
||||
QGroupBox *saveGroup = new QGroupBox("图像保存", rightPanel);
|
||||
QHBoxLayout *saveLayout = new QHBoxLayout(saveGroup);
|
||||
|
||||
m_edit_savePath = new QLineEdit(saveGroup);
|
||||
m_edit_savePath->setReadOnly(true);
|
||||
m_edit_savePath->setPlaceholderText("保存路径...");
|
||||
m_edit_savePath->setClearButtonEnabled(true);
|
||||
|
||||
m_cmb_imgFormat = new QComboBox(saveGroup);
|
||||
QStringList formats = { ".jpg", ".png", ".tif", ".bmp" };
|
||||
m_cmb_imgFormat->addItems(formats);
|
||||
|
||||
m_btn_openDir = new QPushButton("打开...", saveGroup);
|
||||
m_btn_openDir->setFixedWidth(80);
|
||||
|
||||
m_btn_saveImage = new QPushButton("保存", saveGroup);
|
||||
m_btn_saveImage->setFixedWidth(80);
|
||||
|
||||
saveLayout->addWidget(m_edit_savePath);
|
||||
saveLayout->addWidget(m_cmb_imgFormat);
|
||||
saveLayout->addWidget(m_btn_openDir);
|
||||
saveLayout->addWidget(m_btn_saveImage);
|
||||
saveGroup->setLayout(saveLayout);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
请使用单例模式帮助我设计一个海康相机的类,类签名为`class HikCamera`
|
||||
根据手册,类成员应当有一个句柄指针`void *handler`
|
||||
并参考一下我对FLIR相机的时间仿照着设计海康相机类,先仅需要生成头文件`HikCamera.hpp`相关代码即可
|
||||
|
||||
```cpp
|
||||
// FLIRCamera.hpp
|
||||
// 初始化/去初始化相机
|
||||
void init();
|
||||
void deinit();
|
||||
|
||||
// 开始/停止图像采集
|
||||
void startGrabing();
|
||||
void stopGrabing();
|
||||
|
||||
// 设置参数
|
||||
void setExposure(double exposure);
|
||||
void setGain(double gain);
|
||||
|
||||
// 注册图像回调
|
||||
void registerImageCallback();
|
||||
|
||||
// 线程安全的单例示意代码
|
||||
class YourSingleton {
|
||||
public:
|
||||
static YourSingleton& getInstance() {
|
||||
static YourSingleton instance;
|
||||
return instance;
|
||||
/* 相机 SDK 示例代码 */
|
||||
void __stdcall ImageCallBackEx(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser)
|
||||
{
|
||||
if (pFrameInfo)
|
||||
{
|
||||
printf("Get One Frame: Width[%d], Height[%d], FrameLen[%I64d] nFrameNum[%d]\n",
|
||||
pFrameInfo->nExtendWidth, pFrameInfo->nExtendHeight, pFrameInfo->nFrameLenEx,pFrameInfo->nFrameNum);
|
||||
// pData 是图像指针,pFrameInfo->nFrameLenEx 是图像长度, 可以进行图像处理
|
||||
}
|
||||
|
||||
// 禁用拷贝和移动
|
||||
YourSingleton(const YourSingleton&) = delete;
|
||||
YourSingleton(YourSingleton&&) = delete;
|
||||
YourSingleton& operator=(const YourSingleton&) = delete;
|
||||
YourSingleton& operator=(YourSingleton&&) = delete;
|
||||
}
|
||||
|
||||
private:
|
||||
YourSingleton() = default; // 或提供参数化构造
|
||||
~YourSingleton() = default; // 或自定义析构
|
||||
};
|
||||
// 注册抓图回调
|
||||
nRet = MV_CC_RegisterImageCallBackEx(handle, ImageCallBackEx, handle);
|
||||
Check(nRet);
|
||||
|
||||
// 设置缓存节点个数
|
||||
nRet = MV_CC_SetImageNodeNum(handle, 5);
|
||||
Check(nRet);
|
||||
|
||||
// 开始取流
|
||||
nRet = MV_CC_StartGrabbing(handle);
|
||||
Check(nRet);
|
||||
|
||||
/* 类中代码 */
|
||||
// 注册图像回调函数
|
||||
void registerImageCallback();
|
||||
```
|
||||
@ -1,6 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class HikCamera {
|
||||
#include <CameraParams.h>
|
||||
#include <MvCameraControl.h>
|
||||
#include <MvErrorDefine.h>
|
||||
#include <PixelType.h>
|
||||
|
||||
class HikCamera{
|
||||
public:
|
||||
// 获取单例实例
|
||||
static HikCamera &getInstance() {
|
||||
|
||||
@ -9,8 +9,11 @@ public:
|
||||
|
||||
private:
|
||||
void initUI();
|
||||
void connectAllSignalsAndSlots();
|
||||
|
||||
// 左侧视图
|
||||
QGraphicsScene *m_scene;
|
||||
QGraphicsPixmapItem *m_pixmapItem;
|
||||
QGraphicsView *m_gv;
|
||||
|
||||
// 相机操作按钮
|
||||
|
||||
@ -1,10 +1,16 @@
|
||||
#include "HikCamera.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <CameraParams.h>
|
||||
#include <MvCameraControl.h>
|
||||
#include <MvErrorDefine.h>
|
||||
#include <PixelType.h>
|
||||
#include <iostream>
|
||||
|
||||
// 静态成员函数作为SDK回调函数
|
||||
static void __stdcall ImageCallback(unsigned char *pData, MV_FRAME_OUT_INFO_EX *pFrameInfo, void *pUser) {
|
||||
// 将用户数据转换为HikCamera实例
|
||||
/*HikCamera *instance = static_cast<HikCamera *>(pUser);
|
||||
if (instance) {
|
||||
instance->handleFrameData(pData, pFrameInfo);
|
||||
}*/
|
||||
}
|
||||
|
||||
void HikCamera::init() {
|
||||
// 初始化 SDK
|
||||
@ -24,17 +30,32 @@ void HikCamera::init() {
|
||||
}
|
||||
|
||||
void HikCamera::deinit() {
|
||||
|
||||
// 关闭相机
|
||||
int nRet = MV_OK;
|
||||
nRet = MV_CC_CloseDevice(m_handler);
|
||||
|
||||
// 销毁相机实例
|
||||
nRet = MV_CC_DestroyHandle(m_handler);
|
||||
|
||||
// 去初始化 SDK
|
||||
MV_CC_Finalize();
|
||||
}
|
||||
|
||||
void HikCamera::startGrabbing() {}
|
||||
void HikCamera::startGrabbing() {
|
||||
int nRet = MV_OK;
|
||||
nRet = MV_CC_StartGrabbing(m_handler);
|
||||
}
|
||||
|
||||
void HikCamera::stopGrabbing() {}
|
||||
void HikCamera::stopGrabbing() {
|
||||
int nRet = MV_OK;
|
||||
nRet = MV_CC_StopGrabbing(m_handler);
|
||||
}
|
||||
|
||||
void HikCamera::setExposure(double exposure) {}
|
||||
|
||||
void HikCamera::setGain(double gain) {}
|
||||
|
||||
void HikCamera::registerImageCallback() {}
|
||||
void HikCamera::registerImageCallback() {
|
||||
int nRet = MV_OK;
|
||||
nRet = MV_CC_RegisterImageCallBackEx(m_handler, ImageCallback, nullptr);
|
||||
}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
#include "HikWidget.hpp"
|
||||
#include "HikCamera.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
HikWidget::HikWidget(QWidget *parent) : QWidget(parent) {
|
||||
setWindowTitle("HikVision Camera Control");
|
||||
resize(1280, 720); // 设置初始窗口大小
|
||||
initUI();
|
||||
connectAllSignalsAndSlots();
|
||||
}
|
||||
|
||||
void HikWidget::initUI() {
|
||||
@ -13,7 +17,10 @@ void HikWidget::initUI() {
|
||||
mainLayout->setSpacing(15);
|
||||
|
||||
// 左侧 - QGraphicsView
|
||||
m_gv = new QGraphicsView(this);
|
||||
m_pixmapItem = new QGraphicsPixmapItem();
|
||||
m_scene = new QGraphicsScene(this);
|
||||
m_scene->addItem(m_pixmapItem);
|
||||
m_gv = new QGraphicsView(m_scene, this);
|
||||
m_gv->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
m_gv->setRenderHint(QPainter::Antialiasing);
|
||||
m_gv->setBackgroundBrush(Qt::darkGray);
|
||||
@ -104,6 +111,89 @@ void HikWidget::initUI() {
|
||||
mainLayout->addWidget(rightPanel, 1); // 3:1比例中的1份
|
||||
|
||||
// 设置按钮初始状态
|
||||
m_btn_openCamera->setEnabled(true);
|
||||
m_btn_closeCamera->setEnabled(false);
|
||||
m_btn_startGrabbing->setEnabled(false);
|
||||
m_btn_stopGrabbing->setEnabled(false);
|
||||
}
|
||||
|
||||
void HikWidget::connectAllSignalsAndSlots() {
|
||||
// 相机操作按钮连接
|
||||
connect(m_btn_openCamera, &QPushButton::clicked, this, [this]() {
|
||||
HikCamera::getInstance().init();
|
||||
HikCamera::getInstance().registerImageCallback();
|
||||
m_btn_openCamera->setEnabled(false);
|
||||
m_btn_closeCamera->setEnabled(true);
|
||||
m_btn_startGrabbing->setEnabled(true);
|
||||
m_btn_stopGrabbing->setEnabled(false);
|
||||
});
|
||||
|
||||
connect(m_btn_closeCamera, &QPushButton::clicked, this, [this]() {
|
||||
HikCamera::getInstance().deinit();
|
||||
m_btn_openCamera->setEnabled(true);
|
||||
m_btn_closeCamera->setEnabled(false);
|
||||
m_btn_startGrabbing->setEnabled(false);
|
||||
m_btn_stopGrabbing->setEnabled(false);
|
||||
});
|
||||
|
||||
connect(m_btn_startGrabbing, &QPushButton::clicked, this, [this]() {
|
||||
HikCamera::getInstance().startGrabbing();
|
||||
m_btn_startGrabbing->setEnabled(false);
|
||||
m_btn_stopGrabbing->setEnabled(true);
|
||||
});
|
||||
|
||||
connect(m_btn_stopGrabbing, &QPushButton::clicked, this, [this]() {
|
||||
HikCamera::getInstance().stopGrabbing();
|
||||
m_btn_stopGrabbing->setEnabled(false);
|
||||
m_btn_startGrabbing->setEnabled(true);
|
||||
});
|
||||
|
||||
// 图像保存按钮连接
|
||||
connect(m_btn_openDir, &QPushButton::clicked, this, [this]() {
|
||||
QString dir = QFileDialog::getExistingDirectory(
|
||||
this, "选择保存目录", QDir::homePath(),
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
|
||||
if (!dir.isEmpty()) {
|
||||
m_edit_savePath->setText(QDir::toNativeSeparators(dir));
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_btn_saveImage, &QPushButton::clicked, this, [this]() {
|
||||
QString path = m_edit_savePath->text();
|
||||
if (path.isEmpty()) {
|
||||
QMessageBox::warning(this, "警告", "请先选择保存路径");
|
||||
return;
|
||||
}
|
||||
|
||||
QDir dir(path);
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkpath(".")) {
|
||||
QMessageBox::critical(this, "错误", "无法创建保存目录");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 生成时间戳文件名 yyyy-MM-dd-HH-mm-ss-zzz
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
QString timestamp = now.toString("yyyy-MM-dd-HH-mm-ss-zzz");
|
||||
QString format = m_cmb_imgFormat->currentText();
|
||||
|
||||
QString filePath = QDir::toNativeSeparators(
|
||||
dir.filePath(timestamp + format));
|
||||
|
||||
qDebug() << "图片保存路径:" << filePath;
|
||||
});
|
||||
|
||||
// 相机参数连接
|
||||
connect(m_spin_exposureTime, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
|
||||
[](double value) {
|
||||
HikCamera::getInstance().setExposure(value);
|
||||
});
|
||||
|
||||
connect(m_spin_gain, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
|
||||
[](double value) {
|
||||
HikCamera::getInstance().setGain(value);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user