From e89cf3b359201fd747fb465825940271fca51987 Mon Sep 17 00:00:00 2001 From: kaiza_hikaru Date: Sat, 7 Jun 2025 14:19:46 +0800 Subject: [PATCH] first commit --- .gitignore | 3 ++ CMakeLists.txt | 55 +++++++++++++++++++++ LLM.md | 88 ++++++++++++++++++++++++++++++++++ include/HikCamera.hpp | 43 +++++++++++++++++ include/HikWidget.hpp | 31 ++++++++++++ src/HikCamera.cpp | 40 ++++++++++++++++ src/HikWidget.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 10 ++++ 8 files changed, 379 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 LLM.md create mode 100644 include/HikCamera.hpp create mode 100644 include/HikWidget.hpp create mode 100644 src/HikCamera.cpp create mode 100644 src/HikWidget.cpp create mode 100644 src/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a266a99 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs/ +out/ +CMakePresets.json \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f0c061c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.20) +project(HikCameraController LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(SRC_FILES + src/main.cpp + src/HikWidget.cpp + src/HikCamera.cpp +) + +set(HEADER_FILES + include/HikWidget.hpp + include/HikCamera.hpp +) + +add_executable(${PROJECT_NAME} ${SRC_FILES} ${HEADER_FILES}) + +# ====== inner headers ====== +target_include_directories(${PROJECT_NAME} PRIVATE + ${PROJECT_SOURCE_DIR}/include +) +# ====== inner headers ====== + +# ====== Qt6 & OpenCV ====== +set(Qt6_DIR "D:/Environments/Qt/Qt6.9/6.9.0/msvc2022_64/lib/cmake/Qt6" CACHE PATH "Path to Qt6 SDK") +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) +target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets) + +set(OpenCV_DIR "D:/Environments/opencv/build" CACHE PATH "Path to OpenCV SDK") +find_package(OpenCV REQUIRED) +target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS}) +# ====== Qt6 & OpenCV ====== + + +# ====== MVS ====== +set(MVS_DIR "D:/Environments/MVS/Development" CACHE PATH "Path to MVS SDK") + +target_include_directories(${PROJECT_NAME} PRIVATE + ${MVS_DIR}/Includes +) + +target_link_directories(${PROJECT_NAME} PRIVATE + ${MVS_DIR}/Libraries/win64 +) + +target_link_libraries(${PROJECT_NAME} PRIVATE + MvCameraControl.lib +) +# ====== MVS ====== diff --git a/LLM.md b/LLM.md new file mode 100644 index 0000000..02929c6 --- /dev/null +++ b/LLM.md @@ -0,0 +1,88 @@ +请帮助我生成一个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 + +```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; + } + + // 禁用拷贝和移动 + YourSingleton(const YourSingleton&) = delete; + YourSingleton(YourSingleton&&) = delete; + YourSingleton& operator=(const YourSingleton&) = delete; + YourSingleton& operator=(YourSingleton&&) = delete; + +private: + YourSingleton() = default; // 或提供参数化构造 + ~YourSingleton() = default; // 或自定义析构 +}; +``` \ No newline at end of file diff --git a/include/HikCamera.hpp b/include/HikCamera.hpp new file mode 100644 index 0000000..c55aa9d --- /dev/null +++ b/include/HikCamera.hpp @@ -0,0 +1,43 @@ +#pragma once + +class HikCamera { +public: + // 获取单例实例 + static HikCamera &getInstance() { + static HikCamera instance; + return instance; + } + + // 初始化相机 + void init(); + // 去初始化相机 + void deinit(); + + // 开始图像采集 + void startGrabbing(); + // 停止图像采集 + void stopGrabbing(); + + // 设置曝光时间 + void setExposure(double exposure); + // 设置增益 + void setGain(double gain); + + // 注册图像回调函数 + void registerImageCallback(); + + // 禁用拷贝和移动 + HikCamera(const HikCamera &) = delete; + HikCamera(HikCamera &&) = delete; + HikCamera &operator=(const HikCamera &) = delete; + HikCamera &operator=(HikCamera &&) = delete; + +private: + // 私有构造函数 + HikCamera() = default; + // 私有析构函数 + ~HikCamera() = default; + + // 相机句柄 + void *m_handler = nullptr; +}; \ No newline at end of file diff --git a/include/HikWidget.hpp b/include/HikWidget.hpp new file mode 100644 index 0000000..d6a3dd0 --- /dev/null +++ b/include/HikWidget.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include + +class HikWidget : public QWidget { + Q_OBJECT +public: + explicit HikWidget(QWidget *parent = nullptr); + +private: + void initUI(); + + // 左侧视图 + QGraphicsView *m_gv; + + // 相机操作按钮 + QPushButton *m_btn_openCamera; + QPushButton *m_btn_closeCamera; + QPushButton *m_btn_startGrabbing; + QPushButton *m_btn_stopGrabbing; + + // 图像保存控件 + QLineEdit *m_edit_savePath; + QComboBox *m_cmb_imgFormat; + QPushButton *m_btn_openDir; + QPushButton *m_btn_saveImage; + + // 相机参数控件 + QDoubleSpinBox *m_spin_exposureTime; + QDoubleSpinBox *m_spin_gain; +}; \ No newline at end of file diff --git a/src/HikCamera.cpp b/src/HikCamera.cpp new file mode 100644 index 0000000..2ef766a --- /dev/null +++ b/src/HikCamera.cpp @@ -0,0 +1,40 @@ +#include "HikCamera.hpp" + +#include +#include +#include +#include +#include + +void HikCamera::init() { + // 初始化 SDK + int nRet = MV_OK; + MV_CC_Initialize(); + + // 枚举相机 + MV_CC_DEVICE_INFO_LIST stDeviceList; + memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); + nRet = MV_CC_EnumDevices(MV_USB_DEVICE, &stDeviceList); + + // 创建相机实例,也即绑定句柄 + nRet = MV_CC_CreateHandle(&m_handler, stDeviceList.pDeviceInfo[0]); + + // 打开相机 + nRet = MV_CC_OpenDevice(m_handler); +} + +void HikCamera::deinit() { + + // 去初始化 SDK + MV_CC_Finalize(); +} + +void HikCamera::startGrabbing() {} + +void HikCamera::stopGrabbing() {} + +void HikCamera::setExposure(double exposure) {} + +void HikCamera::setGain(double gain) {} + +void HikCamera::registerImageCallback() {} diff --git a/src/HikWidget.cpp b/src/HikWidget.cpp new file mode 100644 index 0000000..2a8dd16 --- /dev/null +++ b/src/HikWidget.cpp @@ -0,0 +1,109 @@ +#include "HikWidget.hpp" + +HikWidget::HikWidget(QWidget *parent) : QWidget(parent) { + setWindowTitle("HikVision Camera Control"); + resize(1280, 720); // 设置初始窗口大小 + initUI(); +} + +void HikWidget::initUI() { + // 主布局 - 水平分割 3:1 + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(10, 10, 10, 10); + mainLayout->setSpacing(15); + + // 左侧 - QGraphicsView + m_gv = new QGraphicsView(this); + m_gv->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_gv->setRenderHint(QPainter::Antialiasing); + m_gv->setBackgroundBrush(Qt::darkGray); + m_gv->setMinimumSize(640, 480); + mainLayout->addWidget(m_gv, 1); // 3:1比例中的3份 + + // 右侧 - 垂直布局容器 + QWidget *rightPanel = new QWidget(this); + rightPanel->setFixedWidth(320); // 限制右侧宽度 + QVBoxLayout *rightLayout = new QVBoxLayout(rightPanel); + rightLayout->setSpacing(15); + rightLayout->setContentsMargins(5, 5, 5, 5); + + // 相机操作GroupBox + QGroupBox *cameraGroup = new QGroupBox("相机操作", rightPanel); + QGridLayout *cameraLayout = new QGridLayout(cameraGroup); + cameraLayout->setSpacing(8); + + m_btn_openCamera = new QPushButton("打开相机", cameraGroup); + m_btn_closeCamera = new QPushButton("关闭相机", cameraGroup); + m_btn_startGrabbing = new QPushButton("开始取流", cameraGroup); + m_btn_stopGrabbing = new QPushButton("结束取流", cameraGroup); + + cameraLayout->addWidget(m_btn_openCamera, 0, 0); + cameraLayout->addWidget(m_btn_closeCamera, 0, 1); + cameraLayout->addWidget(m_btn_startGrabbing, 1, 0); + cameraLayout->addWidget(m_btn_stopGrabbing, 1, 1); + cameraGroup->setLayout(cameraLayout); + + // 图像保存GroupBox - 使用2x3表格布局 + QGroupBox *saveGroup = new QGroupBox("图像保存", rightPanel); + QGridLayout *saveLayout = new QGridLayout(saveGroup); + saveLayout->setVerticalSpacing(8); // 设置行间距 + saveLayout->setHorizontalSpacing(8); // 设置列间距 + saveLayout->setContentsMargins(8, 8, 8, 8); // 设置内边距 + + 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_saveImage = new QPushButton("保存", saveGroup); + + saveLayout->addWidget(m_edit_savePath, 0, 0, 1, 3); // 行0,列0,跨越1行3列 + saveLayout->addWidget(m_cmb_imgFormat, 1, 0); + saveLayout->addWidget(m_btn_openDir, 1, 1); + saveLayout->addWidget(m_btn_saveImage, 1, 2); + saveGroup->setLayout(saveLayout); + + // 相机参数GroupBox + QGroupBox *paramGroup = new QGroupBox("相机参数", rightPanel); + QGridLayout *paramLayout = new QGridLayout(paramGroup); + paramLayout->setVerticalSpacing(10); + + QLabel *lblExposure = new QLabel("曝光时间:", paramGroup); + m_spin_exposureTime = new QDoubleSpinBox(paramGroup); + m_spin_exposureTime->setRange(15.0, 9999806.0); + m_spin_exposureTime->setValue(10000.0); + m_spin_exposureTime->setSingleStep(1.0); + m_spin_exposureTime->setSuffix(" us"); + m_spin_exposureTime->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + QLabel *lblGain = new QLabel("增益设置:", paramGroup); + m_spin_gain = new QDoubleSpinBox(paramGroup); + m_spin_gain->setRange(0.0, 23.981199); + m_spin_gain->setValue(0.0); + m_spin_gain->setSingleStep(0.01); + m_spin_gain->setSuffix(" dB"); + m_spin_gain->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + paramLayout->addWidget(lblExposure, 0, 0); + paramLayout->addWidget(m_spin_exposureTime, 0, 1); + paramLayout->addWidget(lblGain, 1, 0); + paramLayout->addWidget(m_spin_gain, 1, 1); + paramGroup->setLayout(paramLayout); + + // 添加GroupBox到右侧布局 + rightLayout->addWidget(cameraGroup); + rightLayout->addWidget(saveGroup); + rightLayout->addWidget(paramGroup); + rightLayout->addStretch(); // 添加弹性空间 + + // 添加右侧面板到主布局 + mainLayout->addWidget(rightPanel, 1); // 3:1比例中的1份 + + // 设置按钮初始状态 + m_btn_closeCamera->setEnabled(false); + m_btn_stopGrabbing->setEnabled(false); +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..565837b --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,10 @@ +#include +#include "HikWidget.hpp" + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + app.setStyle(QStyleFactory::create("Fusion")); + HikWidget w; + w.show(); + return app.exec(); +} \ No newline at end of file