使用 Qt 实现基于海康相机的图像采集和显示系统(不使用外部视觉库,如Halcon\OpenCv)[工程源码联系博主索要]

本文将梳理一个不借助外部视觉库(如 OpenCV/Halcon)的海康相机图像采集和显示 Demo。该程序直接使用 Qt GUI 来显示图像。通过海康 MVS SDK 实现相机的连接、参数设置、图像采集和异常处理等功能,并通过 Qt 界面展示操作结果。


1. 功能概述

该程序通过 Qt 的 GUI 作为界面,通过海康 MVS SDK 控制相机并显示实时图像。主要功能包括:

  • 相机连接和设置
  • 参数调整(如曝光时间和触发模式)
  • 图像采集与显示
  • 异常处理(如设备断开)

2. 初始化与 GUI 设置

MainWindow 的构造函数中进行界面初始化,包括设置按钮的可见性、启用状态等。 initStyle() 函数用于加载并应用界面的样式表。

cpp 复制代码
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);
    initStyle();

    // 设置初始 UI 状态
    ui->btn_Start->setEnabled(false);
    ui->btn_Stop->setEnabled(false);
    ui->btn_close->setEnabled(false);
    ui->btn_Grab->setVisible(false);
    ui->groupBox->setEnabled(false);
}

3. 相机连接与操作

3.1 枚举和连接相机

通过点击"搜索相机"按钮,程序调用 MV_CC_EnumDevices 枚举连接的相机设备,将可用的相机序列号显示在列表中供用户选择。

cpp 复制代码
void MainWindow::on_btnSeachCamera_clicked() {
    ui->listWidget->clear();
    int nRet = MV_OK;
    bool isGige = ui->radioGIGE->isChecked();

    // 枚举连接的相机
    if (isGige) {
        nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE, &cameraList);
    } else {
        nRet = MV_CC_EnumDevices(MV_USB_DEVICE, &cameraList);
    }

    if (nRet != MV_OK || cameraList.nDeviceNum == 0) {
        setLastErrorMsg(tc("未找到任何可用相机, 错误码: %1").arg(nRet));
        return;
    }

    // 添加相机序列号到列表中
    for (int i = 0; i < cameraList.nDeviceNum; i++) {
        const char *serial = isGige
                             ? reinterpret_cast<char *>(cameraList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chSerialNumber)
                             : reinterpret_cast<char *>(cameraList.pDeviceInfo[i]->SpecialInfo.stUsb3VInfo.chSerialNumber);
        ui->listWidget->addItem(serial);
    }
}
3.2 相机连接及初始化

点击"连接相机"按钮后,程序通过创建相机句柄并打开设备。设置默认曝光时间和注册图像采集、异常处理回调函数。

cpp 复制代码
void MainWindow::on_btnconnect_clicked() {
    MV_CC_DEVICE_INFO cameraInfo;
    int nRet = MV_OK;

    // 创建句柄并打开相机
    memcpy(&cameraInfo, cameraList.pDeviceInfo[0], sizeof(MV_CC_DEVICE_INFO));
    if ((nRet = MV_CC_CreateHandle(&m_handle, &cameraInfo)) != MV_OK) {
        setLastErrorMsg(tc("相机初始化失败, 错误码: %1").arg(nRet));
        return;
    }

    if ((nRet = MV_CC_OpenDevice(m_handle, MV_ACCESS_Exclusive)) != MV_OK) {
        setLastErrorMsg(tc("相机打开失败, 错误码: %1").arg(nRet));
        return;
    }

    // 设置曝光时间并注册回调函数
    MV_CC_SetExposureTime(m_handle, ui->spinBox->value());
    MV_CC_RegisterImageCallBackEx(m_handle, ImageCallBack, this);
    MV_CC_RegisterExceptionCallBack(m_handle, ExceptionCallBack, this);

    // 更新 UI 状态
    ui->btn_Start->setEnabled(true);
    ui->btn_Stop->setEnabled(true);
    ui->btn_close->setEnabled(true);
    ui->btnconnect->setEnabled(false);
    ui->groupBox->setEnabled(true);
}

4. 图像采集与显示

4.1 图像采集回调

通过注册图像回调函数 ImageCallBack,将采集到的图像数据转换为 QImage 格式,以便在 Qt 的 QLabel 中显示。

cpp 复制代码
void ImageCallBack(unsigned char *pData, MV_FRAME_OUT_INFO_EX *pFrameInfo, void *pUser) {
    MainWindow *camera = static_cast<MainWindow *>(pUser);
    QImage img;

    switch (pFrameInfo->enPixelType) {
        case PixelType_Gvsp_Mono8:
            // 单通道灰度图像转换
            img = QImage(pData, pFrameInfo->nWidth, pFrameInfo->nHeight, pFrameInfo->nWidth, QImage::Format_Grayscale8);
            break;

        case PixelType_Gvsp_RGB8_Packed:
            // RGB8 数据转换
            img = QImage(pData, pFrameInfo->nWidth, pFrameInfo->nHeight, QImage::Format_RGB888);
            break;

        case PixelType_Gvsp_BayerRG8:
        case PixelType_Gvsp_BayerBG8:
            // Bayer 格式转换
            img = QImage(pFrameInfo->nWidth, pFrameInfo->nHeight, QImage::Format_RGB888);
            for (int y = 0; y < pFrameInfo->nHeight - 1; y++) {
                for (int x = 0; x < pFrameInfo->nWidth - 1; x++) {
                    int index = y * pFrameInfo->nWidth + x;
                    uchar r, g, b;
                    if (pFrameInfo->enPixelType == PixelType_Gvsp_BayerRG8) {
                        r = pData[index];
                        g = (pData[index + 1] + pData[index + pFrameInfo->nWidth]) / 2;
                        b = pData[index + pFrameInfo->nWidth + 1];
                    } else {
                        b = pData[index];
                        g = (pData[index + 1] + pData[index + pFrameInfo->nWidth]) / 2;
                        r = pData[index + pFrameInfo->nWidth + 1];
                    }
                    img.setPixel(x, y, qRgb(r, g, b));
                }
            }
            break;

        default:
            qWarning("Unsupported pixel type");
            return;
    }

    // 显示图像
    camera->detect(img);
}

void MainWindow::detect(const QImage &image) {
    ui->lab_image->setPixmap(QPixmap::fromImage(image).scaled(ui->lab_image->size()));
}
4.2 触发模式和曝光时间调整

根据用户选择的触发模式和曝光时间设置相机参数。Qt 的信号和槽机制使得切换触发模式和调整曝光时间变得直观。

cpp 复制代码
void MainWindow::on_comboBox_activated(int index) {
    int nRet = MV_OK;
    switch (index) {
        case OpenContinue:
            nRet = MV_CC_SetEnumValue(m_handle, "TriggerMode", 0);
            break;
        case OpenSoftWare:
            nRet = MV_CC_SetEnumValue(m_handle, "TriggerMode", 1);
            nRet = MV_CC_SetEnumValue(m_handle, "TriggerSource", 7);
            break;
        case OpenHardWare:
            nRet = MV_CC_SetEnumValue(m_handle, "TriggerMode", 1);
            nRet = MV_CC_SetEnumValue(m_handle, "TriggerSource", 0);
            break;
    }
    if (nRet != MV_OK) setLastErrorMsg(tc("设置触发模式失败, 错误码: %1").arg(nRet));
}

5. 异常处理与资源释放

5.1 异常处理

程序注册了异常回调函数 ExceptionCallBack,用于处理如设备断开连接等异常情况,并将错误信息显示在界面上。

cpp 复制代码
void ExceptionCallBack(unsigned int nMsgType, void *pUser) {
    if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT) {
        MainWindow *camera = static_cast<MainWindow *>(pUser);
        camera->setLastErrorMsg(tc("相机连接断开"));
    }
}
5.2 资源释放

程序退出时,调用相机停止、关闭函数,释放资源以避免内存泄漏。

cpp 复制代码
void MainWindow::on_btn_close_clicked() {
    on_btn_Stop_clicked();
    int nRet = MV_CC_CloseDevice(m_handle);
    if (nRet != MV_OK) {
        setLastErrorMsg(tc("关闭相机失败, 错误码: %1").arg(nRet));
    }
}

6. 总结

本代码实现了

基于 Qt 的海康相机图像采集和显示系统,直接通过 MVS SDK 进行图像数据处理和显示。Qt 的信号槽机制、MVS SDK 的相机控制 API,以及图像格式转换,使得整个系统操作简单高效。

相关推荐
7yewh18 分钟前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
mahuifa12 小时前
混合开发环境---使用编程AI辅助开发Qt
人工智能·vscode·qt·qtcreator·编程ai
冷眼看人间恩怨12 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
云空17 小时前
《QT 5.14.1 搭建 opencv 环境全攻略》
开发语言·qt·opencv
小老鼠不吃猫18 小时前
力学笃行(二)Qt 示例程序运行
开发语言·qt
晓纪同学19 小时前
QT创建一个模板槽和信号刷新UI
开发语言·qt·ui
爱码小白21 小时前
PyQt5 学习方法之悟道
开发语言·qt·学习方法
只待花开21 小时前
ROS2 python编写 intel realsense D405相机节点通过launch.py启动多个相机并发送图像话题,基于pyrealsense2库
数码相机
KeyPan1 天前
【ORB-SLAM3:相机针孔模型和相机K8模型】
数码相机
千穹凌帝1 天前
基于深度学习多图像融合的屏幕缺陷检测方案
人工智能·深度学习·数码相机