【HIKROBOT】海康机器人:工业相机SDK二次开发

引言

海康机器人官网链接:https://www.hikrobotics.com/cn
根据购买设备的型号下载用户说明书

笔者实验室购买了两款,一款GigE网口接口的,一款USB接口
在这里插入图片描述
在这里插入图片描述

1 软件安装步骤

1.1 SDK安装

服务支持”>“下载中心”>“机器视觉”中下载MVS客户端安装包及SDK开发包。
在这里插入图片描述
下载安装压缩包,并解压
在这里插入图片描述
查看README如下:

安装包对应的操作系统
 arm架构64位系统:
    MVS-2.1.2_aarch64_20221024.deb
    MVS-2.1.2_aarch64_20221024.tar.gz
arm架构32位系统:
    MVS-2.1.2_armhf_20221024.deb
    MVS-2.1.2_armhf_20221024.tar.gz
    MVS-2.1.2_arm-none_20221024.tar.gz
x86架构64位系统:
    MVS-2.1.2_i386_20221024.deb
    MVS-2.1.2_i386_20221024.tar.gz
x86架构32位系统:
    MVS-2.1.2_x86_64_20221024.deb
    MVS-2.1.2_x86_64_20221024.tar.gz
1. 根据系统名称选择相对应的安装包:在终端中输入“uname -a”命令,根据输出的信息选择安装包,例如:输出的信息包含aarch64就选择aarch64的安装包;
2. .deb安装包通过dpkg命令安装,主要应用于ubuntu等系统;
3. .tar.gz安装包是一个压缩包,通tar命令解压后,再执行setup.sh脚本进行安装。

在这里插入图片描述
实际安装:
根据自己的系统选择解压相应的压缩包,打开INSTALL查看安装步骤

To install the MVS Camera Software  Suite in /opt/MVS   # 软件安装目录
follow these steps:

  1. Gaining root privileges and input password:
       sudo su or su root  # 进入root权限进行安装

  2. Change to the directory which contains this INSTALL file, e.g.: 
       cd ~/MVS-1.0.0_x86_64  # 进入文件夹

  3. Running the configuration scripts source
  	 ./setup.sh  # 执行安装

或者使用deb的方式安装,方便卸载。tar和deb安装都可以

sudo dpkg -i MVS-2.1.2_x86_64_20221208.deb
# 删除用以下命令
sudo dpkg -r mvs

如下图所示:
在这里插入图片描述

1.2 运行实例

source ~/.bashrc
cd /opt/MVS/Samples/64/GrabImage
make
./GrabImage

在这里插入图片描述
开启网络巨帧

# 查看网卡名
ifconfig

在这里插入图片描述

# 开启网络巨帧
sudo ifconfig enp0s31f6 mtu 9000
# 再次使用ifconfig查看,mtu等于9000,即设置成功
ifconfig
# 永久设置网卡开启巨帧
sudo vim /etc/network/interfaces
# 将sudo ifconfig enp0s31f6 mtu 9000写入文件

在这里插入图片描述
在这里插入图片描述

1.3 打开软件

  4. Execute /opt/MVS/bin/MVSPlayer to test your cameras.
  sudo su  # 须进入root权限才能打开软件
  cd /opt/MVS/bin  # 进入软件安装目录
  ./MVS  # 执行软件

在这里插入图片描述
在这里插入图片描述

1.3 软件功能说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2 python+opencv:二次开发SDK

项目目录结构
在这里插入图片描述
其中MVImport从安装目录中拷贝,如下图所示,GrabImage_opencv.py:自定义代码(基于python+OpenCV实现取流,显示、保存视频等),util用于放入自定义的其他功能性脚本
在这里插入图片描述

2.1 相机控制步骤

相机控制分成枚举、打开、参数设置、关闭,销毁句柄五个步骤
在这里插入图片描述

2.1 主代码GrabImage_opencv.py

# -- coding: utf-8 --
"""
2023.03.14
author:alian
function  海康威视摄像头取流
总结海康相机的取流步骤如下:
1 枚举
2 打开
3 参数设置
4 取流
5 关闭
6 销毁句柄
"""
import sys
import threading
import os
import termios
import time
import cv2
import numpy as np
from ctypes import *

sys.path.append("/opt/MVS/Samples/64/Python/MvImport")  # 导入相应SDK的库,实际安装位置绝对路径
from MvImport.MvCameraControl_class import *


def creat_video():  # 创建视频
    time_stamp = time.time()
    video_name = time.strftime("%Y%m%d%H%M%S", time.localtime(time_stamp))
    writer = cv2.VideoWriter("%s.mp4" % video_name, cv2.VideoWriter_fourcc(*"mp4v"), 30, (img_w, img_h))
    return writer,time_stamp


# opencv转换显示
def work_thread_opencv(cam=0, pData=0, nDataSize=0,video_length=None):
    img_w = 1920
    img_h = 1080
    stFrameInfo = MV_FRAME_OUT_INFO_EX()
    memset(byref(stFrameInfo), 0, sizeof(stFrameInfo))
    # 定义视频对象输出,自定义一段时间后新建视频文件,时间间隔设置为video_length
    writer, time_stamp = creat_video()
    while True:
        ret = cam.MV_CC_GetOneFrameTimeout(pData, nDataSize, stFrameInfo, 1000)
        if ret == 0:
            print("get one frame: Width[%d], Height[%d], PixelType[0x%x], nFrameNum[%d]" % (
            stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.enPixelType, stFrameInfo.nFrameNum))
            print(time.time()-time_stamp)
            # 设置视频采集时长不大于video_length(以小时为单位)
            if video_length!=None and time.time()-time_stamp > video_length*3600:
                writer.release()
                writer, time_stamp = creat_video()
            # 设置相机输出像素格式,用OpenCV显示和保存视频数据
            img = np.asarray(pData)  # 读取帧
            img = img.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)
            img = cv2.resize(img,(img_w,img_h))
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            import tkinter as tk  # 获取屏幕尺寸,用于随屏幕分辨率自适应显示
            root = tk.Tk()
            width = root.winfo_screenwidth()
            height = root.winfo_screenheight()
            root.destroy()
            cv2.imshow('View', cv2.resize(img, (width, height)))
            writer.write(img)  # 写入视频数据
            # 按Q退出
            if cv2.waitKey(24) & 0xFF == ord('q'):
                break
        else:
            print("no data[0x%x]" % ret)
    cv2.destroyAllWindows()  # 释放所有显示图像窗口
    sys.exit()

def press_any_key_exit():  # 任意按键退出程序
    fd = sys.stdin.fileno()
    old_ttyinfo = termios.tcgetattr(fd)
    new_ttyinfo = old_ttyinfo[:]
    new_ttyinfo[3] &= ~termios.ICANON
    new_ttyinfo[3] &= ~termios.ECHO
    termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo)
    try:
        os.read(fd, 7)
    except:
        pass
    finally:
        termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo)

if __name__ == "__main__":
    deviceList = MV_CC_DEVICE_INFO_LIST()
    tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
    # 1 枚举设备 | en:Enum device
    ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
    if ret != 0:
        print("enum devices fail! ret[0x%x]" % ret)
        sys.exit()
    if deviceList.nDeviceNum == 0:
        print("find no device!")
        sys.exit()
    print("Find %d devices!" % deviceList.nDeviceNum)

    nConnectionNum = 0
    # 2 打开
    # 2.1 创建相机实例 | en:Creat Camera Object
    cam = MvCamera()
    # ch:选择设备并创建句柄| en:Select device and create handle
    stDeviceList = cast(deviceList.pDeviceInfo[int(nConnectionNum)], POINTER(MV_CC_DEVICE_INFO)).contents
    ret = cam.MV_CC_CreateHandle(stDeviceList)
    if ret != 0:
        print("create handle fail! ret[0x%x]" % ret)
        sys.exit()
    # 2.2 打开设备 | en:Open device
    ret = cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
    if ret != 0:
        print("open device fail! ret[0x%x]" % ret)
        sys.exit()
    # 3 参数设置
    # 3.1 设置触发模式为off | en:Set trigger mode as off
    ret = cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF)
    if ret != 0:
        print("set trigger mode fail! ret[0x%x]" % ret)
        sys.exit()
    
    # 3.2 获取数据包大小 | en:Get payload size
    stParam = MVCC_INTVALUE()
    memset(byref(stParam), 0, sizeof(MVCC_INTVALUE))
    ret = cam.MV_CC_GetIntValue("PayloadSize", stParam)
    if ret != 0:
        print("get payload size fail! ret[0x%x]" % ret)
        sys.exit()
    nPayloadSize = stParam.nCurValue
    # 4 开始取流 | en:Start grab image
    ret = cam.MV_CC_StartGrabbing()
    if ret != 0:
        print("start grabbing fail! ret[0x%x]" % ret)
        sys.exit()
    # 将PayloadSize的uint数据转为可供numpy处理的数据,后面就可以用numpy将其转化为numpy数组格式。
    data_buf = (c_ubyte * nPayloadSize)()

    try:
        hThreadHandle = threading.Thread(target=work_thread_opencv, args=(cam, data_buf, nPayloadSize))
        hThreadHandle.start()
        hThreadHandle.join()
    except:
        print("error: unable to start thread")
    # 5 关闭
    # 5.1 停止取流 | en:Stop grab image
    ret = cam.MV_CC_StopGrabbing()
    if ret != 0:
        print("stop grabbing fail! ret[0x%x]" % ret)
        del data_buf
        sys.exit()

    # 5.2 关闭设备 | Close device
    ret = cam.MV_CC_CloseDevice()
    if ret != 0:
        print("close deivce fail! ret[0x%x]" % ret)
        del data_buf
        sys.exit()

    # 6 销毁句柄 | Destroy handle
    ret = cam.MV_CC_DestroyHandle()
    if ret != 0:
        print("destroy handle fail! ret[0x%x]" % ret)
        del data_buf
        sys.exit()
    del data_buf

猜你喜欢

转载自blog.csdn.net/qq_44703886/article/details/129500055