海康工业相机的应用部署不是简简单单!?

作者:SkyXZ

优快云:SkyXZ~-优快云博客

博客园:SkyXZ - 博客园

笔者使用的设备及环境:WSL2-Ubuntu22.04+MV-CS016-10UC

        不会吧?不会吧?不会还有人拿到海康工业相机还是一脸懵叭?不会还有人觉得海康相机的API使用很难叭?不用慌!这篇文章从官方文档涵盖了海康相机官方MVS软件的使用以及Linux海康SDK-API包的理解上手,一篇文章带你走出海康相机使用新手村!!!让你一文读完之后便可自信的对朋友说:“海康相机?简简单单!!!”

参考资料:

一、海康官方MVS客户端使用教程

        我们首先根据自己的系统在官网下载我们的MVS客户端,我的系统为Linux,因此我选择下载第二个Linux版本的客户端

image-20250118041419982

        下载完成后我们会得到一个ZIP压缩包,我们解压后可以看到有很多不同CPU架构的版本,我们选择适合自己系统的版本使用如下命令即可完成安装,安装完成后的客户端将在/opt/MVS目录下

微信截图_20250117134813

sudo dpkg -i MVS-***********.deb #自行替换适合自己的系统版本安装包

        我们使用如下命令即可进入MVS安装环境并且启动我们的客户端

cd /opt/MVS/bin #进入软件目录
./MVS.sh #运行客户端

        运行客户端后我们可以看到我们的客户端主界面如下,左边主要为我们的设备区在这个区域我们可以看到当前连接到我们电脑的所有海康相机设备,最上方为菜单栏提供文件、视图、设置、工具和帮助的功能,下方为控制工具条可以为相机参数保存等操作提供快捷入口

image-20250118042210593

        接着我们选中我们的相机可以看到我们进入了如下界面,在这个界面中左下方为接口和设备信息获取窗口可以显示设备详细信息,中间为图像预览窗口上方左一按钮点击后即可开启相机实时取流查看图像,右边为属性设置窗口,可以对相机的基本参数进行设置,如:触发模式、增益、曝光时间、帧率、像素格式等等

image-20250118042654848

        由于属性设置客户端中有中文介绍,那么我们接着主要开始讲解我们的SDK-API的使用方法叭

二、海康相机开发实战上手

        在我们上一节安装的MVS目录下存在着海康相机驱动所需要的全部头文件以及链接库,我们首先在我们的工作空间下面新建一个文件夹,接着将MVS安装目录下的includelib文件全部复制进来

mkdir -P HK_Camera/src #创建工作目录及源码文件夹
cd HK_Camera/ #进入工作目录
cp -r /opt/MVS/include/ HK_Camera/  #复制头文件
cp -r /opt/MVS/lib/ HK_Camera/ #复制链接库
touch CmakeLists.txt #创建Cmake文件

        我们首先来看一下海康相机组件包的项目结构叭,要驱动海康工业相机需要有两个主要的驱动包includelib,其具体的结构以及对应的作用请看下图:

HK_Camera/
├── CmakeLists.txt
├── include/
│ ├── CameraParams.h
│ ├── MvCameraControl.h
│ ├── MvErrorDefine.h
│ ├── MvISPErrorDefine.h
│ ├── MvObsoleteInterfaces.h
│ ├── ObsoleteCamParams.h
│ └── PixelType.h
├── lib/
│ ├── 32/
│ ├── 64/
│ └── CLProtocol/
└── src/

  • CameraParams.h :定义了相机相关的参数结构体和枚举类型,包含了相机的基本信息结构(如GigE相机信息、USB相机信息等),定义了图像采集相关的参数(如图像大小、像素格式等),定义了相机工作模式(如单帧模式、连续采集模式等),定义了网络传输相关的参数

  • MvCameraControl.h :定义了相机控制的主要API接口,包含相机的初始化、连接、断开等基本操作函数,包含图像采集相关的函数(开始采集、停止采集、获取图像等),包含参数设置和获取的函数,包含文件操作相关的函数,是SDK的主要接口文件

image-20250117141841904

  • MvErrorDefine.h :定义了SDK所有的错误码,包含通用错误码(0x80000000-0x800000FF)、GenICam错误码(0x80000100-0x800001FF)、GigE相关错误码(0x80000200-0x800002FF)、USB相关错误码(0x80000300-0x800003FF)、固件升级相关错误码(0x80000400-0x800004FF)
  • MvISPErrorDefine.h :定义了图像处理(ISP)相关的错误码,包含通用错误码、内存相关错误码、图像格式相关错误码、降噪处理相关错误码、去污点相关错误码
  • PixelType.h :定义了相机支持的所有像素格式类型(enum MvGvspPixelType),主要包含以下几类像素格式:Mono(单色): Mono8/10/12/16等、Bayer: BayerGR8/10/12, BayerRG8/10/12等、RGB: RGB8_Packed, BGR8_Packed等、YUV: YUV411/422/444等、3D点云相关格式
  • ObsoleteCamParams.h :定义了一些已过时但仍支持的相机参数结构体
  • MvObsoleteInterfaces.h :定义了一些已过时但仍支持的接口函数

        由于海康的这些头文件里的API有着非常非常详细的双语介绍(如下图),因此我们将以海康工业相机MV-CS016-10UC来主要介绍使用海康相机的API使用及相机的使用流程,类似于OpenCV调用免驱摄像头一般,海康摄像头的使用也主要分为四步,分别是初始化相机——>设置相机参数——>开始取图——>停止采集和清理资源,接下来我们将一边介绍主要使用的API一边手把手带着大家使能我们的海康相机,首先我们创建我们的main.cc

touch src/main.cc #创建文件

        接着我们开始编写我们的Cmake文件,由于Cmake比较简单,我们便不详细的展开说明了:

#step 1 设置我们的项目以及版本最小需求
cmake_minimum_required(VERSION 3.10)
project(HK_Camera)
#step 2 设置C++标准
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#step 3 设置编译类型
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release)
endif()
#step 4 添加海康相机SDK路径
set(MVCAM_SDK_PATH "${PROJECT_SOURCE_DIR}/lib/64")  # SDK库文件路径
set(MVCAM_INCLUDE_PATH "${PROJECT_SOURCE_DIR}/include")  # SDK头文件路径
#step 5 添加头文件路径
include_directories(
    ${PROJECT_SOURCE_DIR}/include
    ${MVCAM_INCLUDE_PATH}
)
#step 6 添加库文件路径
link_directories(
    ${MVCAM_SDK_PATH}
)
#step 7 添加源文件
add_executable(${PROJECT_NAME} 
    src/main.cc
) 
#step 8 链接海康相机库
target_link_libraries(${PROJECT_NAME}
    MvCameraControl  # 海康相机主库
    pthread         # 线程库
)
#step 9 设置编译选项
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -O2)
#step 10 安装目标
install(TARGETS ${PROJECT_NAME}
    RUNTIME DESTINATION bin
) 

(1)海康相机使用基本部署流程

        Cmake编写完成后我们开始编写我们的代码,首先导入一些我们需要的头文件

        接着为了便于我们的使用,我们首先创建一个HKCamera类,其中包含有五个主要的函数分别是InitCamera()SetParameters()StartGrabbing()GetOneFrame()StopGrabbing()分别用来初始化我们的相机、设置相机参数、开始取流、获取一帧图像以及停止采集释放资源

        我们开始首先完成初始化相机的函数,要使用我们的海康相机那么首先肯定就需要先知道当前设备链接了哪些相机,因此我们便需要先使用MV_CC_EnumDevices函数来枚举当前链接上主机的网口orUSB海康相机,海康官方的API以及MV_CC_DEVICE_INFO_LIST结构体解析如下:

        因此根据API的描述,我们首先需要创建一个MV_CC_DEVICE_INFO_LIST类型的结构体,同时我们还需要定义一个nRet变量来获取调用API后返回的值来判断我们是否成功使用了API,因此我们的代码应该为下述形式:

        在枚举了相机之后如果相机数量不为零我们便可以选择开启我们的海康相机啦,我们首先查看一下打开相机的API介绍

        根据这个API的说明我们可以知道我们在使用这个函数前还需要利用MV_CC_CreateHandle这个API创建一个句柄同时一个设备同时只能被一个进程以独占方式打开,并且关闭设备时需要调用MV_CC_CloseDevice函数,同时我们了解到这个API还有一个可选参数nAccessMode,可以用来设置访问权限,分别有MV_ACCESS_Exclusive独占权限、MV_ACCESS_Control控制权限、MV_ACCESS_Monitor监控权限、为了打开我们的摄像头我们还需再次查看MV_CC_CreateHandleAPI介绍

        根据这个API的说明,我们需要使用之前创建的MV_CC_DEVICE_INFO_LIST类型结构体stDeviceList中的成员变量pDeviceInfo,于是我们的代码便应该如下:

        至此我们的InitCamera()函数便搭建完成啦,完整代码如下:

        完成了初始化相机的函数接下来我们便来完成我们SetParameters()设置相机基本参数的函数,首先我们根据海康的用户手册可以知道我们有几个基本的参数可以进行设置,分别是相机的触发模式像素格式曝光时间增益Buff相机帧率等,我们在这里只对这四个常见参数进行设定,通过查阅API手册我们可以知道这四个参数设置分别对应以下两个APIMV_CC_SetEnumValueMV_CC_SetFloatValue同时我们可以通过MV_CC_GetFloatValueAPI来获取每一个属性键值的可调节参数范围,这些函数的API以及参数列表中涉及到的结构体介绍如下:

        我们通过查阅用户手册可以知道海康工业相机的属性键值遵循GenICam标准,因此我们能调整和获取的常用属性键值有如下几个:

        因此,根据上述的分析,我们首先设置我们相机的触发模式围为OFF内触发模式,同时设置我们的像素格式为BayerRG8

        接着为了避免我们的参数设置有问题以及为了便于自检,我们首先利用MV_CC_GetFloatValue来获取当前我们使用的相机的每一个属性参数的可调节范围,再根据获取到的可调节范围来检查我们设置参数的可用性并进一步修改我们的参数,因此我们以曝光时间的设置为例子代码应该为如下形式:我们首先创建一个MVCC_FLOATVALUE形式的结构体stExposureTime用来获取曝光时间的可调节信息,接着判定我们设置的exposureTime是否超过了stExposureTime.fMinstExposureTime.fMax的范围,如果没有那么我们便将exposureTime使用MV_CC_SetFloatValueAPI进行设置

        至此我们的InitCamera()函数便搭建完成啦,完整代码如下:

        完成了相机基本参数的设置我们便可以开始取流啦!!!这部分有同学就会问了,欸?我们前面就已经打开摄像头了,为什么这里还会有取流和取帧两个函数呢?这就是海康摄像头和OpenCV使用免驱摄像头逻辑上的区别了,我们可以把这个过程类比于我们电动抽水机,前面打开摄像头的函数可以理解为给抽水机上电,而我们这里的开始取流StartGrabbing()便是让图像暂存在相机内部的缓存中,可以理解为让抽水机开始工作一直出水,而我们的取帧函数GetOneFrame()便是从相机的缓存中读取一帧图像并将图像数据复制到我们准备好的内存中,可以理解为拿一个水桶来接水,这样我们便可以随接随用

        理解了为什么我们便开始讲解取流函数StartGrabbing(),在海康的API里面有一个专门的函数便是用来取流的,他的API介绍如下:

        可以看到使用这个函数非常的简单,和我们上面的操作非常类似,只要将我们创建的句柄传入其中即可,按照如下代码调用了之后我们的相机便会开始取流并将图像存储在相机内部的缓存里面临时存储

        接着我们便可以获取当前属性参数下的图像数据包的大小,由于这个属性参数不变那么每帧的图像数据大小的范围便也不会变,因此我们只需要获取一次数据包的大小便可以,所以我们将数据包大小获取放在开始取流的函数里面,我们看到他的API介绍如下:

        其中还涉及到了一个数据包结构体MVCC_INTVALUE,求定义如下:

        了解了其定义后我们便可以使用这个API来获取数据包的大小并用malloc函数来分配我们主机的内存

        至此我们的StartGrabbing()函数便搭建完成啦,完整代码如下:

        接着我们再来编写我们的取帧函数GetOneFrame(),海康给了我们一个专门的获取一帧图像的API,具体其介绍如下,我们可以看到这个API采用的是超时机制,因此SDK内部会一直等待直到有数据时才会返回一帧图像

        因此我们便可以用如下的方式来使用这个API,同时我们在这里再加上一次错误判定,以防止句柄或者分配的内存地址指针为空:

        至此我们的StartGrabbing()函数便搭建完成啦,完整代码如下:

        最后我们只需要编写释放资源的函数StopGrabbing()便大功告成啦!释放资源比较简单,我们只需要按照我们开始的顺序倒叙关闭即可,即:停止取流、关闭相机、摧毁句柄,最后释放我们主机的内存即可,他们对应的API介绍如下:

        因此我们最后的函数的代码长这样:

        最后我们只需要在主函数依次进行调用即可,这部分代码比较简单,我相信来了解海康工业相机的同学这部分不需要再展开细讲啦:

        最后我们完整的代码及运行效果如下:(但是又有同学要问了,我们该如何显示图像呢?请继续翻到下面,我将在下面进行介绍)

image-20250117235331337

(2)海康相机+OpenCV实时取流部署教程

        如果我们要显示采集的图像的话我们有两个方法,首先便是我们的OpenCV,再然后便是海康提供给我们的图像显示API,我们首先介绍大家都会的OpenCV的方案,我们先新引入OpenCV的头文件:

        接着我们在构造函数部分新增CV图像显示的Frame以及我们在构造函数中初始化我们的输出帧和数据包大小结构体:

        然后我们把GetOneFrame()函数变为GetOneFrameAndShow()然后在函数里面新增OpenCV获取帧的代码,将海康与OpenCV进行桥接,由于我们前面设置的采集格式为BGR因此我们可以直接使用BGR数据创建Mat:

        然后我们在主函数里把原先的获取10帧图像修改为while循环持续获得图像,这样便可以实时显示我们摄像头获取的图像:

        最后我们在CmakeLists.txt中添加OpenCV的依赖即可:

# 查找OpenCV包
find_package(OpenCV REQUIRED)
include_directories(
    ${PROJECT_SOURCE_DIR}/include
    ${MVCAM_INCLUDE_PATH}
    ${OpenCV_INCLUDE_DIRS}
)
# 链接海康相机库和OpenCV库
target_link_libraries(${PROJECT_NAME}
    MvCameraControl  # 海康相机主库
    pthread         # 线程库
    ${OpenCV_LIBS}  # OpenCV库
)

        最后我们OpenCV显示图像的完整的代码及显示效果如下:

image-20250118034644685

image-20250118034858385

(3)海康相机官方简易API+X11窗口实时取流部署教程

        但是我们会发现,如果我们摄像头采集的是BGR格式那么用OpenCV会比较方便,但是如果我们采集的不是BGR格式呢?那用OpenCV来显示图像便还需要进行图像的转换,非常的复杂!!!但是如果我们用海康官方的API再加Linux的OpenGL来显示图像那么我们便无需关心图像格式的转换问题啦!接下来我们便开始用海康官方显示API+Linux-OpenGL-X11来实时显示我们的图像,海康API中有关显示的函数有三个(其中一个即将被废除),具体介绍如下:

        MV_CC_DisplayOneFrame()函数为基础函数他的功能最简单但分辨率限制较大并且即将被废除、MV_CC_DisplayOneFrameEx()函数为扩展函数,他支持更大分辨率也支持Windows上的D3D渲染但是不支持超大图像而MV_CC_DisplayOneFrameEx2()函数支持选择渲染模式支持超大图像也支持更多像素格式且性能最好

        接下来我们将以最简单的MV_CC_DisplayOneFrame()函数来完成示例,我们使用X11窗口来显示图像,首先我们导入X11包,接着我们在类中新增创建窗口句柄函数和显示函数并且修改我们的取帧函数:

        接着我们需要利用我们的SetDisplayWindow(void* windowHandle)函数来创建一个X11窗口的句柄:

        然后我们来创建我们的DisplayOneFrame()函数,根据我们上面的函数介绍,我们需要在使用MV_CC_DisplayOneFrame()函数前先定义一个MV_DISPLAY_FRAME_INFO类型的结构体

        根据上述结构体的定义,我们先行配置我们的stDisplayInfo参数

        在定义完这个结构体之后我们便可以使用显示函数API啦,具体的使用代码如下:

        接着我们将原来的GetOneFrame()函数中间添加图像显示函数DisplayOneFrame()即可

        之后便开始修改我们的主函数啦首先在主函数中创建X11窗口并且捕获屏幕信息:

        接着我们设置窗口的基本参数,并设置窗口标题和窗口关闭事件

最后我们显示窗口并持续捕获图像并使用X11事件显示即可

        接着我们修改一下我们的Cmake即可:

        最后我们X11串口+海康的显示API的完整的代码及效果如下:

image-20250118034359365

image-20250118034341634


__EOF__

  • 本文作者: SkyXZ
  • 本文链接: https://www.cnblogs.com/SkyXZ/p/18677928
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
原创作者: SkyXZ 转载于: https://www.cnblogs.com/SkyXZ/p/18677928
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值