当前位置: 首页 > article >正文

尝试将相机采集图像流程封装成相机采图类

封装相机采集模块,GrabOnce.cpp下面是一个完整的相机采集图像的流程(控制台模式),要求把这个流程封装成一个相机采图类,类接口要求:
1. 三个对外接口,相机初始化,开始采图,停止采图
2. 类的构造,析构函数要完整,成员变量(私有,公有)定义完善,私有函数和接口函数区分开
3. 界面需要有三个按钮,初始化相机按钮,开始采图按钮,停止采图按钮
4. 语言C++, 界面Qt

一、1. 相机采集类封装(C++/Qt)

//--------------------------- CameraCapture.h ---------------------------
#pragma once
#include <QObject>
#include <QImage>
#include <atomic>
#include "IKapBoard.h"
#include "IKapC.h"

class CameraCapture : public QObject {
    Q_OBJECT
public:
    explicit CameraCapture(QObject *parent = nullptr);
    ~CameraCapture();

    // 对外接口
    bool initCamera();
    void startGrabbing();
    void stopGrabbing();

signals:
    void imageGrabbed(const QImage &image);  // 图像采集信号
    void errorOccurred(const QString &msg);  // 错误信号

private:
    // IKapC 和 IKapBoard 资源
    ITKDEVICE m_cameraHandle = nullptr;
    HANDLE m_boardHandle = INVALID_HANDLE_VALUE;
    std::atomic_bool m_isGrabbing{false};
    bool m_isInitialized = false;

    // 私有方法
    bool configureCamera();
    bool configureFrameGrabber();
    void registerCallbacks();
    void releaseResources();

    // 回调函数包装器
    static void CALLBACK OnFrameReadyWrapper(void *context);
    void handleFrameReady();
};
//--------------------------- CameraCapture.cpp ---------------------------
#include "CameraCapture.h"
#include <QDebug>

CameraCapture::CameraCapture(QObject *parent) : QObject(parent) {}

CameraCapture::~CameraCapture() {
    stopGrabbing();
    releaseResources();
}

bool CameraCapture::initCamera() {
    if (m_isInitialized) return true;

    // 初始化 IKapC
    ITKSTATUS res = ItkManInitialize();
    if (res != ITKSTATUS_OK) {
        emit errorOccurred("IKapC initialization failed");
        return false;
    }

    // 配置相机和采集卡
    if (!configureCamera() || !configureFrameGrabber()) {
        releaseResources();
        return false;
    }

    m_isInitialized = true;
    return true;
}

void CameraCapture::startGrabbing() {
    if (!m_isInitialized || m_isGrabbing) return;

    ITKSTATUS res = ItkDevExecuteCommand(m_cameraHandle, "AcquisitionStart");
    if (res != ITKSTATUS_OK) {
        emit errorOccurred("Failed to start acquisition");
        return;
    }

    int ret = IKapStartGrab(m_boardHandle, 1);
    if (ret != 1) {
        emit errorOccurred("Failed to start grabbing");
        return;
    }

    m_isGrabbing = true;
}

void CameraCapture::stopGrabbing() {
    if (!m_isGrabbing) return;

    int ret = IKapStopGrab(m_boardHandle);
    if (ret != 1) {
        emit errorOccurred("Failed to stop grabbing");
    }

    m_isGrabbing = false;
}

//--------------------------- 私有方法实现 ---------------------------
bool CameraCapture::configureCamera() {
    // ... (参考 GrabOnce.cpp 中的 ConfigureCamera 实现)
    // 枚举设备、打开相机和采集卡
    return true;
}

bool CameraCapture::configureFrameGrabber() {
    // ... (参考 GrabOnce.cpp 中的 ConfigureFrameGrabber 实现)
    // 配置缓冲区、超时、注册回调
    registerCallbacks();
    return true;
}

void CameraCapture::registerCallbacks() {
    // 注册回调函数,传递 this 指针作为上下文
    IKapRegisterCallback(m_boardHandle, IKEvent_FrameReady, &CameraCapture::OnFrameReadyWrapper, this);
}

void CameraCapture::releaseResources() {
    if (m_boardHandle != INVALID_HANDLE_VALUE) {
        IKapClose(m_boardHandle);
        m_boardHandle = INVALID_HANDLE_VALUE;
    }

    if (m_cameraHandle != nullptr) {
        ItkDevClose(m_cameraHandle);
        m_cameraHandle = nullptr;
    }

    ItkManTerminate();
    m_isInitialized = false;
}

//--------------------------- 回调函数包装器 ---------------------------
void CALLBACK CameraCapture::OnFrameReadyWrapper(void *context) {
    CameraCapture *self = static_cast<CameraCapture*>(context);
    self->handleFrameReady();
}

void CameraCapture::handleFrameReady() {
    unsigned char *buffer = nullptr;
    int frameSize = 0;
    IKAPBUFFERSTATUS status;

    // 获取图像数据
    IKapGetBufferStatus(m_boardHandle, 0, &status);
    if (status.uFull == 1) {
        IKapGetInfo(m_boardHandle, IKP_FRAME_SIZE, &frameSize);
        IKapGetBufferAddress(m_boardHandle, 0, (void**)&buffer);

        // 转换为 QImage(假设图像格式为 RGB888)
        QImage img(buffer, status.uWidth, status.uHeight, QImage::Format_RGB888);
        emit imageGrabbed(img);  // 发送图像信号
    }
}

 二、QT界面实现

//--------------------------- MainWindow.h ---------------------------
#include <QMainWindow>
#include "CameraCapture.h"

namespace Ui { class MainWindow; }

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void onInitClicked();
    void onStartClicked();
    void onStopClicked();
    void updateImage(const QImage &img);
    void handleError(const QString &msg);

private:
    Ui::MainWindow *ui;
    CameraCapture *m_camera;
};
//--------------------------- MainWindow.cpp ---------------------------
#include "MainWindow.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow), m_camera(new CameraCapture(this)) {
    ui->setupUi(this);
    
    // 初始化按钮状态
    ui->startButton->setEnabled(false);
    ui->stopButton->setEnabled(false);

    // 连接信号槽
    connect(ui->initButton, &QPushButton::clicked, this, &MainWindow::onInitClicked);
    connect(ui->startButton, &QPushButton::clicked, this, &MainWindow::onStartClicked);
    connect(ui->stopButton, &QPushButton::clicked, this, &MainWindow::onStopClicked);
    connect(m_camera, &CameraCapture::imageGrabbed, this, &MainWindow::updateImage);
    connect(m_camera, &CameraCapture::errorOccurred, this, &MainWindow::handleError);
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::onInitClicked() {
    if (m_camera->initCamera()) {
        ui->startButton->setEnabled(true);
        ui->initButton->setEnabled(false);
    }
}

void MainWindow::onStartClicked() {
    m_camera->startGrabbing();
    ui->startButton->setEnabled(false);
    ui->stopButton->setEnabled(true);
}

void MainWindow::onStopClicked() {
    m_camera->stopGrabbing();
    ui->startButton->setEnabled(true);
    ui->stopButton->setEnabled(false);
}

void MainWindow::updateImage(const QImage &img) {
    ui->imageLabel->setPixmap(QPixmap::fromImage(img).scaled(
        ui->imageLabel->size(), Qt::KeepAspectRatio));
}

void MainWindow::handleError(const QString &msg) {
    QMessageBox::critical(this, "Error", msg);
}

 三、Qt 界面文件(MainWindow.ui)

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
    <class>MainWindow</class>
    <widget class="QMainWindow" name="MainWindow">
        <widget class="QWidget" name="centralWidget">
            <layout class="QVBoxLayout">
                <item>
                    <widget class="QLabel" name="imageLabel">
                        <property name="minimumSize">
                            <size>
                                <width>640</width>
                                <height>480</height>
                            </size>
                        </property>
                    </widget>
                </item>
                <item>
                    <layout class="QHBoxLayout">
                        <item>
                            <widget class="QPushButton" name="initButton">
                                <property name="text">
                                    <string>Initialize</string>
                                </property>
                            </widget>
                        </item>
                        <item>
                            <widget class="QPushButton" name="startButton">
                                <property name="text">
                                    <string>Start</string>
                                </property>
                            </widget>
                        </item>
                        <item>
                            <widget class="QPushButton" name="stopButton">
                                <property name="text">
                                    <string>Stop</string>
                                </property>
                            </widget>
                        </item>
                    </layout>
                </item>
            </layout>
        </widget>
    </widget>
</ui>


http://www.kler.cn/a/596369.html

相关文章:

  • 微信小游戏:跳一跳,自动化操作
  • BlockChain.java
  • 西门子200smart之modbus_TCP(做从站与第三方设备)通讯
  • 【机器学习】手撕封装PCA——将高维数据映射到低维数据的过程
  • TPCTF 2025 web 复现
  • 【unordered_set和unordered_map】—— 我与C++的不解之缘(二十七)
  • wyq01
  • geant4的主要模块及其作用:
  • 【大模型算法工程】大模型应用工具化、忠诚度以及知识库场景下PDF双栏解析问题的讨论
  • Apache Flink技术原理深入解析:任务执行流程全景图
  • spring boot 拦截器
  • 【Attention】SKAttention
  • MySQL密码修改的全部方式一篇详解
  • vue学习九
  • 红宝书第十一讲:超易懂版「ES6类与继承」零基础教程:用现实例子+图解实现
  • 生物信息复习笔记(3)——GEO数据库
  • CPU架构和微架构
  • Redis 知识点梳理
  • 如何快速定位高 CPU 使用率的进程
  • git_version_control_proper_practice