海康网站下载的相机调试工具,可以预览相机和设置相机的一些参数。

网站: https://www.hikrobotics.com/cn

下载你相机型号相关的安装包,这个要是有困难可以找海康售后帮忙,你提供的相机型号,工作人员会知道你下载和操作,海康售后挺好的,当初笔者不熟悉的时候也是很耐心的指导我操作。

主机通过网线连接相机,主机的IP地址选择自动分配,这样就会和相机在一个网段内。打开MVS工具,会识别主机中的网卡,如果该网卡中有相机连接,会显示出来。

笔者记得第一次连接的时候,好像预览画面中什么都没有是黑色的,如果你也是这样不必着急,因为相机需要设置。首先相机上面有1个调亮度和1个调焦距的物理旋钮。你需要将物理按钮的属性调整到合适位置,确保那个环节没有问题。再一个这个工具中可以设置相机的属性,笔者这里在相机的默认属性基础上调节了4个属性:

* 自动曝光:连续 * 自动增益:连续 * 亮度:100 * 像素格式:UV 422 Packed

完成上述操作,应该能正常预览相机的画面。

Python

在Python中连接工业相机获取帧图像处理,我们首先需要连接相机,然后获取到每一帧图像,将图像送给业务层。

在Python中需要连接相机,需要借助海康提供的.dll文件和其API文件

这些API文件和.dll文件,在安装完MVS软件后会获得。

将5个API文件和.dll文件夹里面的所有文件都拷贝到你的工程中,存放路径你可以自己定义。但是在MvCameraControl_class.py文件中,会有一行代码是输入MvCameraControl.dll文件路径的:

from ctypes import *
from org.venus.std.src.pro.input.hk2000w.api.CameraParams_const import MV_ACCESS_Exclusive
MvCamCtrldll = WinDLL("./api/dll/MvCameraControl.dll")

这里请根据你自己的存放目录填写。补充一下,在Python中填写相对路径时在路径前面加./,就是你项目运行的根目录。这个连接代码是参考示例程序的,示例程序里面填写的路径就是一个MvCameraControl.dll文件,但是笔者在使用过程中只导入这一个文件程序运行有错误,肯定的是这个文件找到了,但是这个文件中也引用到了其他的.dll文件,有人说通过什么工具之类的可以查看这个.dll文件引用到了其他的具体哪一个.dll文件,笔者对那个操作不熟悉,就没有那样做,而是把那个.dll文件夹中所有的文件都拷贝过来,约60M,省事。

将这些文件拷贝到项目中就可以开始写代码了:

import msvcrt
import sys
import threading
import time
from ctypes import POINTER, sizeof, byref, memset, c_ubyte, cdll, cast, c_bool
import cv2 as cv
import numpy as np
from org.venus.std.src.config import constants
from org.venus.std.src.pro.input.hk2000w import watch
from org.venus.std.src.pro.input.hk2000w.api.CameraParams_const import MV_GIGE_DEVICE, MV_USB_DEVICE, MV_ACCESS_Exclusive
from org.venus.std.src.pro.input.hk2000w.api.CameraParams_header import MV_CC_DEVICE_INFO_LIST, MV_CC_DEVICE_INFO, \
    MV_TRIGGER_MODE_OFF, MV_FRAME_OUT, MV_EXPOSURE_AUTO_MODE_CONTINUOUS, MV_GAIN_MODE_CONTINUOUS
from org.venus.std.src.pro.input.hk2000w.api.MvCameraControl_class import MvCamera
from org.venus.std.src.pro.input.hk2000w.api.PixelType_header import PixelType_Gvsp_YUV422_Packed
# 为线程定义一个函数
def work_thread(cam=0, pData=0, nDataSize=0):
    stOutFrame = MV_FRAME_OUT()
    memset(byref(stOutFrame), 0, sizeof(stOutFrame))
    while True:
        startFrame = time.perf_counter()
        ret = cam.MV_CC_GetImageBuffer(stOutFrame, 1000)
        # print("相机像素格式(PixelType_header.py文件中根据编码找到对应的格式)",stOutFrame.stFrameInfo.enPixelType)
        if None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 17301505:
            print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (
                stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))
            pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)()
            cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,
                               stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)
            data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight),
                                 dtype=np.uint8)
            image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)
        elif None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 17301514:
            print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (
                stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))
            pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)()
            cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,
                               stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)
            data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight),
                                 dtype=np.uint8)
            image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)
        elif None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 35127316:
            print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (
                stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))
            pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 3)()
            cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,
                               stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 3)
            data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 3),
                                 dtype=np.uint8)
            image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)
        elif None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 34603039:
            print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (
                stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))
            pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 2)()
            cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,
                               stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 2)
            data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 2),
                                 dtype=np.uint8)
            image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)
        else:
            print("no data[0x%x]" % ret)
        nRet = cam.MV_CC_FreeImageBuffer(stOutFrame)
        endFrame = time.perf_counter()
        print("相机一帧时间",str(endFrame-startFrame))
# 需要显示的图像数据转换
def image_control(data, stFrameInfo):
    if stFrameInfo.enPixelType == 17301505:
        image = data.reshape((stFrameInfo.nHeight, stFrameInfo.nWidth))
        image_show(image=image, name=stFrameInfo.nHeight)
    elif stFrameInfo.enPixelType == 17301514:
        data = data.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)
        image = cv.cvtColor(data, cv.COLOR_BAYER_GB2RGB)
        image_show(image=image, name=stFrameInfo.nHeight)
    elif stFrameInfo.enPixelType == 35127316:
        data = data.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)
        image = cv.cvtColor(data, cv.COLOR_RGB2BGR)
        image_show(image=image, name=stFrameInfo.nHeight)
    elif stFrameInfo.enPixelType == 34603039:
        data = data.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)
        image = cv.cvtColor(data, cv.COLOR_YUV2BGR_Y422)
        image_show(image=image, name=stFrameInfo.nHeight)
# 显示图像
def image_show(image, name):
    startTime = time.perf_counter()
    infos = watch.run(image)
    if infos is None:
        print("没有识别到FJ信息")
    else:
        print("FJ信息数量",len(infos))
        for info in infos:
            print("FJ信息", info)
    endTime = time.perf_counter()
    #我们可以使用time.perf_counter()方法来查找程序的执行时间。
    #方法time.perf_counter()返回以秒为单位的时间浮点值
    print("拿到图像时间", str(startTime),"图像处理完毕时间", str(startTime),"耗时", str(endTime-startTime))
    if constants.WaitNextFrame:
        cv.waitKey()
def run():
    deviceList = MV_CC_DEVICE_INFO_LIST()
    tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
    # ch:枚举设备 | 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)
    for i in range(0, deviceList.nDeviceNum):
        mvcc_dev_info = cast(deviceList.pDeviceInfo[i], POINTER(MV_CC_DEVICE_INFO)).contents
        if mvcc_dev_info.nTLayerType == MV_GIGE_DEVICE:
            print("\ngige device: [%d]" % i)
            strModeName = ""
            for per in mvcc_dev_info.SpecialInfo.stGigEInfo.chModelName:
                strModeName = strModeName + chr(per)
            print("device model name: %s" % strModeName)
            nip1 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24)
            nip2 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16)
            nip3 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8)
            nip4 = (mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff)
            print("current ip: %d.%d.%d.%d\n" % (nip1, nip2, nip3, nip4))
        elif mvcc_dev_info.nTLayerType == MV_USB_DEVICE:
            print("\nu3v device: [%d]" % i)
            strModeName = ""
            for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chModelName:
                if per == 0:
                    break
                strModeName = strModeName + chr(per)
            print("device model name: %s" % strModeName)
            strSerialNumber = ""
            for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chSerialNumber:
                if per == 0:
                    break
                strSerialNumber = strSerialNumber + chr(per)
            print("user serial number: %s" % strSerialNumber)
    # nConnectionNum = input("please input the number of the device to connect:") #输入一个相机编号进行连接
    if int(constants.ConnectionCameraNum) >= deviceList.nDeviceNum:
        print("intput error!")
        sys.exit()
    # ch:创建相机实例 | en:Creat Camera Object
    cam = MvCamera()
    # ch:选择设备并创建句柄 | en:Select device and create handle
    stDeviceList = cast(deviceList.pDeviceInfo[int(constants.ConnectionCameraNum)], 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()
    # ch:打开设备 | 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()
    # ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
    if stDeviceList.nTLayerType == MV_GIGE_DEVICE:
        nPacketSize = cam.MV_CC_GetOptimalPacketSize()
        if int(nPacketSize) > 0:
            ret = cam.MV_CC_SetIntValue("GevSCPSPacketSize", nPacketSize)
            if ret != 0:
                print("Warning: Set Packet Size fail! ret[0x%x]" % ret)
        else:
            print("Warning: Get Packet Size fail! ret[0x%x]" % nPacketSize)
    stBool = c_bool(False)
    ret = cam.MV_CC_GetBoolValue("AcquisitionFrameRateEnable", stBool)
    if ret != 0:
        print("get AcquisitionFrameRateEnable fail! ret[0x%x]" % ret)
        sys.exit()
    # ch:设置触发模式为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()
    设置一些属性:
    自动曝光:连续
    亮度:100
    自动增益:连续
    像素格式:YUV 422 Packed
    # ch:设置自动曝光为连续
    ret = cam.MV_CC_SetEnumValue("ExposureAuto", MV_EXPOSURE_AUTO_MODE_CONTINUOUS)
    if ret != 0:
        print("设置自动曝光为连续 失败! ret[0x%x]" % ret)
        sys.exit()
    # ch:设置自动增益为连续
    ret = cam.MV_CC_SetEnumValue("GainAuto", MV_GAIN_MODE_CONTINUOUS)
    if ret != 0:
        print("设置自动增益为连续 失败! ret[0x%x]" % ret)
        sys.exit()
    # ch:设置亮度为100
    ret = cam.MV_CC_SetIntValue("Brightness", constants.Brightness)
    if ret != 0:
        print("设置亮度为100 失败! ret[0x%x]" % ret)
        sys.exit()
    # ch:设置像素格式为PixelType_Gvsp_YUV422_Packed
    ret = cam.MV_CC_SetEnumValue("PixelFormat", PixelType_Gvsp_YUV422_Packed)
    if ret != 0:
        print("设置像素格式为PixelType_Gvsp_YUV422_Packed 失败! ret[0x%x]" % ret)
        sys.exit()
    # ch:开始取流 | en:Start grab image
    ret = cam.MV_CC_StartGrabbing()
    if ret != 0:
        print("start grabbing fail! ret[0x%x]" % ret)
        sys.exit()
        hThreadHandle = threading.Thread(target=work_thread, args=(cam, None, None))
        hThreadHandle.start()
    except:
        print("error: unable to start thread")
    print("press a key to stop grabbing.")
    msvcrt.getch()
    g_bExit = True
    hThreadHandle.join()
    # ch:停止取流 | en:Stop grab image
    ret = cam.MV_CC_StopGrabbing()
    if ret != 0:
        print("stop grabbing fail! ret[0x%x]" % ret)
        sys.exit()
    # ch:关闭设备 | Close device
    ret = cam.MV_CC_CloseDevice()
    if ret != 0:
        print("close deivce fail! ret[0x%x]" % ret)
        sys.exit()
    # ch:销毁句柄 | Destroy handle
    ret = cam.MV_CC_DestroyHandle()
    if ret != 0:
        print("destroy handle fail! ret[0x%x]" % ret)
        sys.exit()
if __name__ =="__main__":
    print("连接hk工业相机图像")
    run()

上述代码是工程结构中/org/venus/std/src/pro/input/hk2000w/main.py文件的内容。代码不多,可以简单解读一下。

程序入口main函数中执行run函数,在run函数中查找所有的相机设备,虽然我平常只是连接着一个相机,但是的你主机中可以连接多个相机,在找到所有的相机后,相机列表中每个相机会有个编号标识符。通过相机编号连接相机创建句柄并打开相机,然后为相机设置一些属性,就可以开始获取相机的视频流了,run函数中通过如下2行代码将取流操作执行到work_thread线程中,主线程就等待取流线程的工作,结束后就关闭设备,销毁句柄等释放资源操作。

hThreadHandle = threading.Thread(target=work_thread, args=(cam, None, None))
hThreadHandle.start()

work_thread取流线程是一个while True操作,在获取视频流时后根据上文中设置相机的一个属性(像素格式),来执行不同的操作,因为不同的像素格式,视频流转换为图像的操作是不一样的,所以上文中设置像素格式的操作也不是任意设置的,笔者设置的值YUV 422 Packed是因为在示例程序中列出了4种像素格式的转换代码,YUV 422 Packed是其中的一个,所以笔者使用了这一个,代码中使用的匹配方式是如(34603039)类型的数据,这个数据对应的像素格式可以在API文件PixelType_header.py中进行匹配,看看你使用的究竟是哪种像素格式。在对像素格式匹配后,程序执行到image_control函数,将视频流数据传送到image_control函数,继续对像素格式进行匹配,并将视频流转换成图像对象,程序继续执行到image_show函数,这个函数中传递过来的就是图像对象了,可以将图像对象传递到业务层进行处理。

补充一下:在代码中连接相机后可以设置一些属性,是示例代码中只有一个设置触发模式的示例,比如笔者还需要设置一些属性:自动曝光:连续/亮度:100/自动增益:连续/像素格式:YUV 422 Packed,设置属性是调用MvCameraControl_class.py文件中提供的接口函数,接口中并没有直接设置某一个属性的函数,接口是设置某一类型的调用方式。大致有MV_CC_SetIntValue设置整形数据,MV_CC_SetEnumValue设置枚举数据,MV_CC_SetFloatValue设置小数数据,MV_CC_SetBoolValue设置开关数据,MV_CC_SetStringValue设置字符串数据等。这里不过多阐述,当你有这个业务时可以自行研究。

根据笔者想要设置的属性来看,要用到设置枚举和整形的接口。调用设置枚举的接口,需要传入一个key和一个枚举,枚举就是具体的值,这个可以在CameraParams_header.py文件中找到你所要设置的参数的枚举值。那么这个key哪里来呢?key是个字符串,笔者尝试像实例中设置触发模式一样TriggerMode表示触发模式,那么我想设置自动曝光模式应该就是ExposureAutoMode,但是执行时这里却有错误,很显然没有这个key。那么就要再次用到MVS工具了,在工具中连接相机后找到属性树菜单,列表里面都是英文名称对应着相机的属性,找到你要设置相机参数的英文名称,比如截图中的自动曝光就是Exposure Auto属性,点击属性在列表下方会出现该属性的信息,其中有个Node Name属性是ExposureAuto,这个属性就是我们在代码中使用API设置相机属性的key,其他属性同理都可以在这里找到。

背景Python OpenCV连接海康工业相机做图像处理环境Python:3.9.9OpenCV:4.5.5numpy:1.19.32022-05-16_112138.png相机海康:MV-CE200-10GC协议:GigE2022-05-16_112542.pngMVS海康网站下载的相机调试工具,可以预览相机和设置相机的一些参数。网站:https:/...... 因为项目的原因,笔者需要利用程序来实时 调用 海康 工业相机 ,而不是简单的利用 海康 的驱动来 调用 相机。 在经历了反复的踩坑填坑之后,笔者总结了利用c#和 python 调用 海康 相机的两种方法 一、准备工作 无论是用c#还是 python ,都是要通过 海康 的SDK来进行二次 开发 的。 海康 的SDK相当于一个库,里面有各种用于 海康 相机的函数,这些函数被封装成供各大编程 语言 使用。所以,要想利用 python 或者c#与 海康 进行实时交互,就
文章转载: python 语言 下使用 opencv 接口cv2.VideoCapture()接口 调用 海康 机器人 工业相机 一、 Opencv 接口 使用 opencv 的官方接口 VideoCapture() 接口直接 调用 海康 工业相机 , 接下来简单介绍下 VideoCapture() 这个接口 接口:cv2.VideoCapture() 作用:获取本地目录下的视频文件或者使用本电脑的摄像头获取实时数据; 本文需要使用该接口 调用 海康 工业相机 ; 参数写入 “0” , 调用 的是本地电脑摄像头 参数写入 “1” , 调用
``` python import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout import cv2 from HCNetSDK import * 4.创建一个Qt窗口并在其中添加一个标签。 ``` python class Video(QWidget): def __init__(self): super().__init__() self.label = QLabel(self) self.layout = QVBoxLayout() self.layout.addWidget(self.label) self.setLayout(self.layout) 5.初始化 海康 SDK并登录相机。 ``` python def init_camera(): # 初始化SDK if not NET_DVR_Init(): print("SDK初始化失败") sys.exit() # 登录相机 device_info = NET_DVR_DEVICEINFO_V30() device_ip = "192. 16 8.1.64" device_port = 8000 device_username = "admin" device_password = "12345" device_id = NET_DVR_Login_V30(device_ip, device_port, device_username, device_password, device_info) if device_id < 0: print("登录相机失败") sys.exit() return device_id 6.获取相机数据并将其转换为 OpenCV 支持的格式。 ``` python def get_frame(device_id): # 获取相机数据 frame = NET_DVR_GetRealPlayImage(device_id) # 将相机数据转换为 OpenCV 支持的格式 frame_data = frame.contents.pBuffer frame_size = frame.contents.dwSize frame_image = np.frombuffer(frame_data, dtype=np.uint8) frame_image = frame_image.reshape((frame_size[1], frame_size[0], 4)) frame_image = cv2.cvtColor(frame_image, cv2.COLOR_BGRA2BGR) return frame_image 7.在Qt窗口中显示相机数据。 ``` python def show_camera(): app = QApplication(sys.argv) video = Video() video.show() device_id = init_camera() while True: frame_image = get_frame(device_id) frame_image = cv2.resize(frame_image, (640, 480)) frame_image = cv2.cvtColor(frame_image, cv2.COLOR_BGR2RGB) video.label.setPixmap(QPixmap.fromImage(QImage(frame_image.data, frame_image.shape[1], frame_image.shape[0], QImage.Format_RGB888))) if cv2.waitKey(1) & 0xFF == ord('q'): break NET_DVR_Logout(device_id) NET_DVR_Cleanup() sys.exit(app.exec_()) 8.运行程序并显示相机数据。 ``` python if __name__ == '__main__': show_camera() 哈哈,大佬细节啊,在创建master的时候已经连接了 public ModbusMasterTCP(TcpParameters parameters) { super(ModbusConnectionFactory.getTcpMaster(parameters)); this.keepAlive = parameters.isKeepAlive(); try { if (this.isKeepAlive()) { this.connect(); } catch (ModbusIOException var3) { Modbus.log().warning("keepAlive is set, connection failed at creation time."); 应该改成这样,但是也没有必要 if (!modbusMaster.isConnected()) { System.out.println("Modbus主机没有连接,现在建立连接"); modbusMaster.connect(); } else { System.out.println("Modbus主机已经连接");