相关文章推荐
谦逊的毛豆  ·  Elasticsearch ...·  1 年前    · 
活泼的蚂蚁  ·  React Native ...·  1 年前    · 

最近用到海康的工业相机,需要读取它的视频流,听说RTSP协议延迟较高,并且没有尝试成功,用了CSDN中一篇文章分享的方法 (59条消息) 利用python加opencv与海康工业相机交互。(得到供opencv处理的数据)_叔均的博客-CSDN博客_getoneframetimeout ,实现了视频流的读取,做一个简单的学习记录。

main.py

import sys
import threading
import msvcrt
import numpy as np
import cv2
from ctypes import *
sys.path.append(r"C:\Program Files (x86)\MVS\Development\Samples\Python\MvImport")  # 换成自己的MVS中的路径
from MvCameraControl_class import *
g_bExit = False
# 这是官方给的线程,只能捕获帧的信息,类似于get one frame: Width[3072], Height[2048], nFrameNum[711]
# 不能得到帧的数据
def work_thread(cam=0, pData=0, nDataSize=0):
    stFrameInfo = MV_FRAME_OUT_INFO_EX()
    memset(byref(stFrameInfo), 0, sizeof(stFrameInfo))
    while True:
        ret = cam.MV_CC_GetOneFrameTimeout(pData, nDataSize, stFrameInfo, 1000)
        if ret == 0:
            print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (
            stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nFrameNum))
        else:
            print("no data[0x%x]" % ret)
        if g_bExit == True:
            break
# 自己在这个线程中修改,可以将相机获得的数据转换成opencv支持的格式,然后再用opencv操作
def work_thread2(cam=0, pData=0, nDataSize=0):
    # 输出帧的信息
    stFrameInfo = MV_FRAME_OUT_INFO_EX()
    # void *memset(void *s, int ch, size_t n);
    # 函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s
    # memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
    # byref(n)返回的相当于C的指针右值&n,本身没有被分配空间
    # 此处相当于将帧信息全部清空了
    memset(byref(stFrameInfo), 0, sizeof(stFrameInfo))
    while True:
        temp = np.asarray(pData)  # 将c_ubyte_Array转化成ndarray得到(3686400,)
        # print(temp)
        # print(temp.shape)
        temp = temp.reshape((1024, 1280, 3))  # 根据自己分辨率进行转化  这里出现报错的时候注意看SDK中的配置,我选用的 RGB8
        temp = cv2.cvtColor(temp, cv2.COLOR_BGR2RGB)  # 这一步获取到的颜色不对,因为默认是BRG,要转化成RGB,颜色才正常
        # gray = cv2.cvtColor(temp, cv2.COLOR_BGR2GRAY)
        # ret, binary = cv2.threshold(gray, 130, 255, cv2.THRESH_BINARY)
        # cv2.namedWindow("binary", cv2.WINDOW_NORMAL)
        cv2.namedWindow("ori", cv2.WINDOW_NORMAL)
        # cv2.imshow('binary', binary) # 黑白二值图
        cv2.imshow("ori", temp)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
        # 采用超时机制获取一帧图片,SDK内部等待直到有数据时返回,成功返回0
        ret = cam.MV_CC_GetOneFrameTimeout(pData, nDataSize, stFrameInfo, 1000)
        if ret == 0:
            print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (
                stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nFrameNum))
        else:
            print("no data[0x%x]" % ret)
        if g_bExit == True:
            break
    cv2.waitKey()
if __name__ == "__main__":
    # 获得设备信息
    deviceList = MV_CC_DEVICE_INFO_LIST()
    tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
    # ch:枚举设备 | en:Enum device
    # nTLayerType [IN] 枚举传输层 ,pstDevList [OUT] 设备列表
    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)
            # 输出设备ID
            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))
        # 输出USB接口的信息
        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(nConnectionNum) >= deviceList.nDeviceNum:
        print("intput error!")
        sys.exit()
    # ch:创建相机实例 | en:Creat Camera Object
    cam = MvCamera()
    # ch:选择设备并创建句柄 | en:Select device and create handle
    # cast(typ, val),这个函数是为了检查val变量是typ类型的,但是这个cast函数不做检查,直接返回val
    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()
    # 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)
    # 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()
    # 从这开始,获取图片数据
    # ch:获取数据包大小 | en:Get payload size
    stParam = MVCC_INTVALUE()
    # csharp中没有memset函数,用什么代替?
    memset(byref(stParam), 0, sizeof(MVCC_INTVALUE))
    # MV_CC_GetIntValue,获取Integer属性值,handle [IN] 设备句柄
    # strKey [IN] 属性键值,如获取宽度信息则为"Width"
    # pIntValue [IN][OUT] 返回给调用者有关相机属性结构体指针
    # 得到图片尺寸,这一句很关键
    # payloadsize,为流通道上的每个图像传输的最大字节数,相机的PayloadSize的典型值是(宽x高x像素大小),此时图像没有附加任何额外信息
    ret = cam.MV_CC_GetIntValue("PayloadSize", stParam)
    if ret != 0:
        print("get payload size fail! ret[0x%x]" % ret)
        sys.exit()
    # 关键句,官方没有这个句子,抓取的图片数据是空的,nCurValue是int64
    nPayloadSize = stParam.nCurValue
    # ch:开始取流 | en:Start grab image
    ret = cam.MV_CC_StartGrabbing()
    if ret != 0:
        print("start grabbing fail! ret[0x%x]" % ret)
        sys.exit()
    #  关键句,官方没有这个句子,抓取的图片数据是空的,CSharp中怎么实现这句话。
    data_buf = (c_ubyte * nPayloadSize)()
    #  date_buf前面的转化不用,不然报错,因为转了是浮点型
        hThreadHandle = threading.Thread(target=work_thread2, args=(cam, data_buf, nPayloadSize))
        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)
        del data_buf
        sys.exit()
    # ch:关闭设备 | Close device
    ret = cam.MV_CC_CloseDevice()
    if ret != 0:
        print("close deivce fail! ret[0x%x]" % ret)
        del data_buf
        sys.exit()
    # ch:销毁句柄 | 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

除了main.py,还需要五个py文件,在海康的SDK中可以找到,把他们拿出来和main.py放一起就可以开run。

五个文件的路径

自己的一些探索发现:直接连摄像头的时候会报错,主要是分辨率不匹配的问题,原因是相机在刚上电以后会保存初始配置,他的分别率设置和代码中不一样,需要打开SDK连接相机,基本属性->像素格式->下拉设置为RGB8,在SDK中断开相机连接,再run代码就可以辣。最近用到海康的工业相机,需要读取它的视频流,听说RTSP协议延迟较高,并且没有尝试成功,用了CSDN中一篇文章分享的方法。除了main.py,还需要五个py文件,在海康的SDK中可以找到,把他们拿出来和main.py放一起就可以开run。 图片信息的表示不止只有我们熟知的RGB,还有HLS、HSV、YUV、bayer,由于 opencv 等视觉处理库的广泛运用,RGB空间色彩模型运用最为广泛(实际上是BGR)。 摄像头传感器的感光原理是通过一个个的感光点对光进行采样和量化。但是每一个感光点只能感光RGB中的一种颜色。所以通常所说的50万像素或5000万像素等,指的是有50万或5000万个感光点。每一个感光点只能感光一种颜色,但一个真正图像需要每一个像素点都有RGB三种颜色分量。 在传感器模组的内部有ISP模块,主要用来对前
程序说明: 程序将 海康 摄像头开发需要进行的操作封面到类HK_camera中,使用只需要在mian()函数中实例化HK_camera,将摄像头的IP,用户名,密码给对象即可使用。 程序调用接口的流程都是参考SDK开发文档,并做了简单的修改,有不明白或者觉得不对的地方希望可以给我留言,谢谢。环境: 摄像机型号:CS-C1-11WPFR 电脑环境:32位 opencv 版本: opencv 2.4.
搜罗了网上一些关于如何在 python 中实现 海康 威视 相机 的连接与画面播放的资料,最直接的方式是通过rtsp流来实现。 海康 的rtsp协议格式如下(参考: 海康 相机 使用RTSP): rtsp://[username]:[passwd]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream rtsp://admin:12345@192.168....
海康 工业相机 的底层SDK中提供了两种不同方式的图像数据获 方式,一种是回调方式,一种是主动 流方式。但是官方示例中,只提供了相关数据获 到之后的打印信息,对于图像数据的解析并没有给出,基于以上情况,本文对于这两种 流方式获 到的图像数据进行解析。 一、使用前提.. # 绘制矩形框 x, y, w, h = 100, 100, 200, 200 cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) # 提 ROI roi = img[y:y+h, x:x+w] # 显示结果 cv2.imshow('image', img) cv2.imshow('roi', roi) cv2.waitKey(0) cv2.destroyAllWindows() hhaaiius: @绝迹632 多谢博文!文章一开始提到“RTSP协议没有尝试成功”,请问你用的是哪一款相机?我参考下面的推荐尝试RTSP连mv-ce200-10gc相机目前也没有成功。 https://www.use-ip.co.uk/forum/threads/hikvision-rtsp-stream-urls.890/ Live View URL rtsp://<address>:<port>/Streaming/Channels/<id>/ rtsp://<username>:<password>@<address>:<port>/Streaming/Channels/<id>/ Where <address> is the IP address of your camera, <port> is the RTSP port of the camera, and <username> and <password> refer to the login credentials of your camera. Using the first format, you will be asked to login and verify your credentials before being allowed to view the stream. Using the second format, you will automatically login when requesting the stream <id> refers to the channel number and stream type of the camera. For example, an <id> of 101 refers to channel #1 (first digit, 1xx) using the main stream (second and third digits, x01). Typically, you'll use a program such as VLC Media Player to decode the RTSP stream. 海康工业相机 python opencv取视频流 学习记录 杨杨杨s: 您好博主 按q之后opencv界面没了但是程序还在运行 请问怎么办呀 海康工业相机 python opencv取视频流 学习记录 绝迹632: 属性导入问题已解决,https://blog.csdn.net/weixin_60862392/article/details/129239951?spm=1001.2014.3001.5502