Qt 与 Halcon 联合开发六:基于海康SDK设计完整的相机类【附源码】
在现代工业自动化、机器人视觉、等领域,相机模块的作用至关重要。通过相机模块采集到的图像数据,我们能够进行一系列的图像处理和分析。为了高效地控制相机和处理图像,本篇文章将介绍如何使用Qt和Halcon联合开发一个相机模块,帮助开发者掌握如何在视觉上位机中应用相机模块。
项目下载
通过网盘分享的文件:Qt-Halcon联合开发六:基于海康SDK封装相机模块
链接: https://pan.baidu.com/s/14qEf-5HOHe1W8Yqv_hTX_Q?pwd=jkcf 提取码: jkcf
1. 相机模块的开发与重要性
相机模块通常作为视觉上位机的关键组件之一,负责采集图像数据并进行传输。这一模块是整个视觉系统的核心,不仅直接影响到图像数据的质量,还决定了后续图像处理、分析和识别的效果。在开发复杂的视觉系统时,相机模块需要具备以下功能:
- 设备控制:控制相机的开关、参数设置、图像采集等。
- 数据采集:实时采集图像数据并进行回调处理。
- 数据传输:将采集到的图像数据传输给图像处理平台(如Halcon)。
- 错误反馈:处理相机的连接、采集过程中的错误,确保系统稳定运行。
开发一个高效的相机模块对于实现精准的图像分析至关重要,尤其是在复杂的自动化检测、机器人视觉等场景中。通过与Halcon集成,我们可以借助Halcon强大的图像处理能力,进行更加高效的图像分析和数据处理。
2. 项目背景与开发工具
本项目结合了Qt和Halcon两个强大的开发工具:
- Qt:Qt是一款跨平台的开发框架,适用于开发桌面应用程序和GUI应用。它可以非常方便地与硬件设备进行交互,特别适合用于相机控制和用户界面开发。
- Halcon:Halcon是一款强大的工业级图像处理库,提供了丰富的图像处理算法,支持多种图像格式与设备接口,能够快速处理和分析图像数据。
在这篇文章中,我们将使用这两个工具联合开发一个相机模块,利用Qt控制相机的操作,利用Halcon进行图像处理。
3. 相机模块的设计
我们将开发一个名为HikCamera
的相机类,来实现与相机的交互和图像数据的处理。该类主要负责以下任务:
- 打开相机设备
- 设置相机参数
- 开始和停止图像采集
- 执行软触发操作
- 处理采集到的图像数据
3.1 完整的HikCamera
类定义
#ifndef HIKCAMERA_H
#define HIKCAMERA_H#include <QString>
#include <QDebug>
#include <QDateTime>
#include <QSettings>
#include "MvCameraControl.h"// 将字符数组转换为QString
#define tc(a) QString::fromLocal8Bit(a)
// 图像回调函数
void __stdcall ImageCallBack(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser);
// 异常回调函数
void __stdcall ExceptionCallBack(unsigned int nMsgType, void* pUser);
class HikCamera
{// 定义相机连接模式enum OpenCameraWay{OpenContinue, ///< 连续采集OpenSoftWare, ///< 软触发采集OpenHardWare, ///< 硬触发采集};/*** @enum ImageFormat* @brief 枚举相机的图像数据格式*/enum class ImageFormat{Mono8, ///< 黑白图像RGB8, ///< RGB8图像格式BayerRG8, ///< BayerRG8图像格式};// 定义相机类型enum class CameraType{GIGE, ///< 网口相机USB3, ///< USB3相机CL, ///< CameraLink相机};public:/*** @brief 构造函数,初始化相机对象* @param[in] index 相机索引* @param[in] ip 相机IP地址*/HikCamera(const int index, const QString& ip);/*** @brief 析构函数,销毁相机对象*/~HikCamera();/*** @brief 打开相机* @return 是否成功打开相机*/bool openCamera();/*** @brief 设置相机参数* @param[in] ExposureTime 曝光时间* @param[in] Gain 增益* @param[in] TriggerDelay 触发延时* @param[in] Width 图像宽度* @param[in] Height 图像高度* @param[in] offSetX 偏移量X* @param[in] offSetY 偏移量Y* @return 是否成功设置相机参数*/bool setCameraParameters(float ExposureTime, float Gain, float TriggerDelay, int Width, int Height, int offSetX, int offSetY);/*** @brief 开始图像采集* @return 是否成功开始采集*/bool startGrabbing();/*** @brief 停止图像采集* @return 是否成功停止采集*/bool stopGrabbing();/*** @brief 关闭相机* @return 是否成功关闭相机*/bool closeCamera();/*** @brief 判断相机是否已打开* @return 相机是否打开*/bool isOpen() const;/*** @brief 判断是否正在采集图像* @return 是否正在采集*/bool isGrabbing() const;/*** @brief 执行软触发* @return 是否成功执行软触发*/bool executeSoftTrigger();/*** @brief 更新相机内部的最新错误信息* @param[in] msg 错误信息*/void setLastErrorMsg(const QString& msg) { m_lastErrorMsg = msg; }/*** @brief 将IP地址转换为整数* @param[in] ip IP地址* @return 转换后的整数*/unsigned int ipAddressToInt(const QString& ip);/*** @brief 设置相机类型* @param[in] type 相机类型,默认为GIGE*/void setCameraType(const CameraType type = CameraType::GIGE) { m_type = type; }/*** @brief 获取相机类型* @return 相机类型*/CameraType getCameraType() const { return m_type; }/*** @brief 设置相机图像格式* @param[in] format 图像格式,默认为Mono8*/void setCameraImageFormat(const ImageFormat format = ImageFormat::Mono8) { m_imageFormat = format; }/*** @brief 获取相机图像格式* @return 图像格式*/ImageFormat getCameraImageFormat() const { return m_imageFormat; }public:/*** @brief 设置触发模式* @param[in] way 触发方式* @return 是否成功设置触发模式*/bool setTriggerMode(OpenCameraWay way);/*** @brief 发送错误信息* @param[in] msg 错误信息*/void sendErrorsMsgs(const QString& msg);/*** @brief 发送信息消息* @param[in] msg 信息消息*/void sendInforMsgs(const QString& msg);public:// 定义相机句柄类型typedef void* HikCameraHandle;HikCameraHandle m_handle; ///< 相机句柄bool m_isOpen; ///< 相机是否已打开bool m_isGrabbing; ///< 是否正在采集图像int m_num; ///< 相机编号int m_i; ///< 相机编号索引QString m_ip; ///< 相机IP地址int m_cameraIndex; ///< 相机索引QString m_lastErrorMsg; ///< 最新的错误信息ImageFormat m_imageFormat; ///< 图像格式CameraType m_type; ///< 相机类型
};#endif // HIKCAMERA_H
3.2 核心功能接口总结
-
构造函数与析构函数
HikCamera::HikCamera(const int index, const QString& ip)
:用于初始化相机对象,接收相机的索引和IP地址作为参数。HikCamera::~HikCamera()
:析构函数,在对象销毁时关闭相机并销毁相机句柄。
-
相机控制接口
openCamera()
:打开相机,查找连接的设备,并初始化设备句柄。closeCamera()
:关闭相机,停止图像采集并关闭设备连接。startGrabbing()
:开始图像采集。stopGrabbing()
:停止图像采集。executeSoftTrigger()
:执行软触发操作。
-
相机参数设置
setCameraParameters()
:设置相机的参数,如曝光时间、增益、图像分辨率等。
-
状态与错误反馈
isOpen()
:检查相机是否已打开。isGrabbing()
:检查是否正在采集图像。setLastErrorMsg()
:设置最新的错误信息。sendErrorsMsgs()
:输出错误信息,帮助开发人员排查问题。
3.3 示例代码分析
打开相机 (openCamera
)
bool HikCamera::openCamera()
{int nRet = MV_OK;m_isOpen = false;// 枚举设备MV_CC_DEVICE_INFO_LIST cameraList;unsigned int i = 0;if (MV_OK != (nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE, &cameraList))){sendErrorsMsgs(tc("无法找到可用的网口相机, 错误码: %1").arg(nRet));return false;}// 选择设备并创建句柄MV_CC_DEVICE_INFO cameraInfo;memcpy(&cameraInfo, cameraList.pDeviceInfo[i], sizeof(MV_CC_DEVICE_INFO));if (MV_OK != (nRet = MV_CC_CreateHandle(&m_handle, &cameraInfo))){sendErrorsMsgs(tc("相机初始化失败, 错误码: %1").arg(nRet));return false;}if (MV_OK != (nRet = MV_CC_OpenDevice(m_handle, MV_ACCESS_Exclusive))){sendErrorsMsgs(tc("无法打开相机, 错误码: %1").arg(nRet));return false;}return (m_isOpen = (MV_OK == nRet));
}
功能说明:
openCamera()
函数首先枚举所有连接到PC的相机设备,然后根据指定的设备类型(如GIGE设备),创建相机句柄并尝试打开相机设备。- 若设备打开失败,函数会输出错误信息并返回
false
。
设置相机参数 (setCameraParameters
)
bool HikCamera::setCameraParameters(float ExposureTime, float Gain, float TriggerDelay, int Width, int Height, int offSetX, int offSetY)
{// 设置曝光时间if (ExposureTime >= 0)if (MV_OK != MV_CC_SetExposureTime(m_handle, ExposureTime))return false;// 设置增益if (Gain >= 0)if (MV_OK != MV_CC_SetGain(m_handle, Gain))return false;// 设置图像分辨率与偏移量if (Width >= 0 && MV_OK != MV_CC_SetWidth(m_handle, static_cast<unsigned int>(Width)))return false;if (Height >= 0 && MV_OK != MV_CC_SetHeight(m_handle, static_cast<unsigned int>(Height)))return false;return true;
}
功能说明:
setCameraParameters()
函数用于设置相机的曝光时间、增益、图像分辨率和ROI区域的偏移量。- 每个参数的设置都会通过SDK的API进行调用,若设置失败,返回
false
。
4. 集成Halcon进行图像处理
相机模块采集到图像后,我们将图像数据传递给Halcon进行后续处理。Halcon能够进行复杂的图像分析、模式识别和检测任务,是工业视觉中广泛使用的工具。
4.1 图像数据回调
void ImageCallBack(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser)
{HikCamera* camera = static_cast<HikCamera*>(pUser);HalconCpp::HObject ho_Image;int imageWidth = pFrameInfo->nWidth;int imageHeight = pFrameInfo->nHeight;switch (pFrameInfo->enPixelType){case PixelType_Gvsp_Mono8:HalconCpp::GenImage1(&ho_Image, "byte", imageWidth, imageHeight, reinterpret_cast<Hlong>(pData));break;case PixelType_Gvsp_RGB8_Packed:HalconCpp::GenImageInterleaved(&ho_Image, reinterpret_cast<Hlong>(pData), "rgb", imageWidth, imageHeight, -1, "byte", 0, 0, 0, 0, -1, 0);break;// 其他图像格式转换...}
}
功能说明:
- 图像数据通过回调函数
ImageCallBack
传递给Halcon进行处理。根据图像的像素类型,选择合适的图像生成方法。 HalconCpp::GenImage1
与HalconCpp::GenImageInterleaved
函数将原始图像数据转化为Halcon可处理的图像对象。