如何降低海康、大华等网络摄像头调用的高延迟问题(一):海康威视网络摄像头的python sdk使用(opencv读取sdk流)

目录

1.python sdk使用

1.海康SDK下载

 2.opencv读取sdk流


 先说效果,我是用的AI推理的实时流,延迟从高达7秒降到小于1秒

如果觉得这个延迟还不能接受,下一章,给大家介绍点上不得台面的小方法

SDK(Software Development Kit)是软件开发工具包的缩写,它是一组用于开发特定软件或应用程序的工具、库和文档的集合。SDK提供了开发所需的资源和接口,帮助开发者更高效地构建应用程序。

SDK通常包含以下内容:

  1. 工具:SDK提供了一系列开发工具,如编译器、调试器、IDE(集成开发环境)等,用于编写、调试和测试代码。
  2. 库:SDK中的库是预先编译好的可重用代码模块,包含常见的功能和算法,开发者可以直接调用这些库来简化开发过程。
  3. 示例代码:SDK通常附带一些示例代码,展示如何使用SDK提供的功能和接口,帮助开发者快速上手并理解开发流程。
  4. 文档:SDK提供详细的文档,包括API参考、开发指南、示例代码解释等,帮助开发者了解SDK的功能和使用方法。
  5. 依赖项:SDK可能需要依赖其他软件或库,例如操作系统、第三方库等,开发者需要满足这些依赖关系才能使用SDK。

SDK的作用是简化开发过程,提供开发所需的资源和接口,节省开发者的时间和精力。通过使用SDK,开发者可以快速构建功能丰富、高效的应用程序,而无需从头开始编写所有的代码和功能。

1.python sdk使用

之前常常采用python来读取usb摄像头,因为其语言风格易读且上手快。起先,使用rtsp流来读海康的网络相机,视频画面出现延迟卡顿的现象,如果对于实时性要求较高(起码得和网页预览效果相当的帧率)的话,用rtsp流读取的方式显得不可取,本文采用在python中调用HikVision的SDK读取IP相机的方式实现,帧率的话和网络预览效果相当

1.海康SDK下载

 

下载好解压后

进入以下路径

海康威视-HCNetSDKV6.1.9.48_build20230410_win64---Demo示例---5- Python开发示例---1-预览取流解码Demo

1.找到这个lib路径,里面应该是空的

看需要选择win或者linux

2.返回主目录,选择库文件,复制全部文件(实际按官方文档只需要部分库文件,不过可以傻瓜式全部打包),粘贴到上面的lib文件夹的win文件中

下面是官方文档的操作说明

1. 更新设备网络SDK时,SDK开发包【库文件】里的HCNetSDK.dll、HCCore.dll、HCNetSDKCom文件夹、libssl-1_1.dll、libcrypto-1_1.dll、hlog.dll、hpr.dll、zlib1.dll、PlayCtrl.dll、SuperRender.dll、AudioRender.dll等文件均要加载到程序里面,【HCNetSDKCom文件夹】(包含里面的功能组件dll库文件)需要和HCNetSDK.dll、HCCore.dll一起加载,放在同一个目录下,且HCNetSDKCom文件夹名不能修改。

2. 如果自行开发软件不能正常实现相应功能,而且程序没有指定加载的dll库路径,请在程序运行的情况下尝试删除HCNetSDK.dll。如果可以删除,说明程序可能调用到系统盘Windows->System32目录下的dll文件,建议删除或者更新该目录下的相关dll文件;如果不能删除,dll文件右键选择属性确认SDK库版本。

3. 如按上述步骤操作后还是不能实现相应功能,请根据NET_DVR_GetLastError返回的错误号判断原因。

3.运行test_main.py

获取实时画面

 2.opencv读取sdk流

将下面代码贴到test_main.py的同级目录下

运行即可

有问题的朋友欢迎评论区留言

# coding=utf-8
import os
import platform
from HCNetSDK import *
from PlayCtrl import *
import numpy as np
import time
import cv2class HKCam(object):def __init__(self,camIP,username,password,devport=8000):# 登录的设备信息self.DEV_IP = create_string_buffer(camIP.encode())self.DEV_PORT =devportself.DEV_USER_NAME = create_string_buffer(username.encode())self.DEV_PASSWORD = create_string_buffer(password.encode())self.WINDOWS_FLAG = False if platform.system() != "Windows" else Trueself.funcRealDataCallBack_V30 = Noneself.recent_img = None #最新帧self.n_stamp = None #帧时间戳self.last_stamp = None #上次时间戳# 加载库,先加载依赖库                                                                   # 1 根据操作系统,加载对应的dll文件if self.WINDOWS_FLAG:            os.chdir(r'./lib/win')self.Objdll = ctypes.CDLL(r'./HCNetSDK.dll')  # 加载网络库self.Playctrldll = ctypes.CDLL(r'./PlayCtrl.dll')  # 加载播放库else:os.chdir(r'./lib/linux')self.Objdll = cdll.LoadLibrary(r'./libhcnetsdk.so')self.Playctrldll = cdll.LoadLibrary(r'./libPlayCtrl.so')# 设置组件库和SSL库加载路径                                                              # 2 设置组件库和SSL库加载路径self.SetSDKInitCfg()# 初始化DLLself.Objdll.NET_DVR_Init()                                                               # 3 相机初始化# 启用SDK写日志self.Objdll.NET_DVR_SetLogToFile(3, bytes('./SdkLog_Python/', encoding="utf-8"), False)os.chdir(r'../../') # 切换工作路径到../../# 登录(self.lUserId, self.device_info) = self.LoginDev()                                       # 4 登录相机self.Playctrldll.PlayM4_ResetBuffer(self.lUserId,1)#清空指定缓冲区的剩余数据。这个地方传进来的是self.lUserId,为什么呢?print(self.lUserId)if self.lUserId < 0:#登录失败err = self.Objdll.NET_DVR_GetLastError()print('Login device fail, error code is: %d' % self.Objdll.NET_DVR_GetLastError())# 释放资源self.Objdll.NET_DVR_Cleanup()exit()else:print(f'摄像头[{camIP}]登录成功!!')self.start_play()                                                                         # 5 开始播放time.sleep(1)def start_play(self,):#global funcRealDataCallBack_V30                                                                        self.PlayCtrl_Port = c_long(-1)  # 播放句柄# 获取一个播放句柄 #wuzh获取未使用的通道号if not self.Playctrldll.PlayM4_GetPort(byref(self.PlayCtrl_Port)):print(u'获取播放库句柄失败')# 定义码流回调函数       self.funcRealDataCallBack_V30 = REALDATACALLBACK(self.RealDataCallBack_V30)# 开启预览self.preview_info = NET_DVR_PREVIEWINFO()self.preview_info.hPlayWnd = 0self.preview_info.lChannel = 1  # 通道号self.preview_info.dwStreamType = 0  # 主码流self.preview_info.dwLinkMode = 0  # TCPself.preview_info.bBlocked = 1  # 阻塞取流# 开始预览并且设置回调函数回调获取实时流数据self.lRealPlayHandle = self.Objdll.NET_DVR_RealPlay_V40(self.lUserId, byref(self.preview_info), self.funcRealDataCallBack_V30, None)if self.lRealPlayHandle < 0:print ('Open preview fail, error code is: %d' %self. Objdll.NET_DVR_GetLastError())# 登出设备self.Objdll.NET_DVR_Logout(self.lUserId)# 释放资源self.Objdll.NET_DVR_Cleanup()exit()def SetSDKInitCfg(self,):# 设置SDK初始化依赖库路径# 设置HCNetSDKCom组件库和SSL库加载路径# print(os.getcwd())if self.WINDOWS_FLAG:strPath = os.getcwd().encode('gbk')sdk_ComPath = NET_DVR_LOCAL_SDK_PATH()sdk_ComPath.sPath = strPathself.Objdll.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))self.Objdll.NET_DVR_SetSDKInitCfg(3, create_string_buffer(strPath + b'\libcrypto-1_1-x64.dll'))self.Objdll.NET_DVR_SetSDKInitCfg(4, create_string_buffer(strPath + b'\libssl-1_1-x64.dll'))else:strPath = os.getcwd().encode('utf-8')sdk_ComPath = NET_DVR_LOCAL_SDK_PATH()sdk_ComPath.sPath = strPathself.Objdll.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))self.Objdll.NET_DVR_SetSDKInitCfg(3, create_string_buffer(strPath + b'/libcrypto.so.1.1'))self.Objdll.NET_DVR_SetSDKInitCfg(4, create_string_buffer(strPath + b'/libssl.so.1.1'))def LoginDev(self,):# 登录注册设备device_info = NET_DVR_DEVICEINFO_V30()lUserId = self.Objdll.NET_DVR_Login_V30(self.DEV_IP, self.DEV_PORT, self.DEV_USER_NAME, self.DEV_PASSWORD, byref(device_info))return (lUserId, device_info)def read(self,):while self.n_stamp==self.last_stamp:continueself.last_stamp=self.n_stampreturn self.n_stamp,self.recent_imgdef DecCBFun(self,nPort, pBuf, nSize, pFrameInfo, nUser, nReserved2):if pFrameInfo.contents.nType == 3:t0 = time.time()# 解码返回视频YUV数据,将YUV数据转成jpg图片保存到本地# 如果有耗时处理,需要将解码数据拷贝到回调函数外面的其他线程里面处理,避免阻塞回调导致解码丢帧nWidth = pFrameInfo.contents.nWidthnHeight = pFrameInfo.contents.nHeight#nType = pFrameInfo.contents.nTypedwFrameNum = pFrameInfo.contents.dwFrameNumnStamp = pFrameInfo.contents.nStamp#print(nWidth, nHeight, nType, dwFrameNum, nStamp, sFileName)YUV = np.frombuffer(pBuf[:nSize],dtype=np.uint8)YUV = np.reshape(YUV,[nHeight+nHeight//2,nWidth])img_rgb = cv2.cvtColor(YUV,cv2.COLOR_YUV2BGR_YV12)self.recent_img,self.n_stamp = img_rgb,nStampdef RealDataCallBack_V30(self,lPlayHandle, dwDataType, pBuffer, dwBufSize, pUser):# 码流回调函数if dwDataType == NET_DVR_SYSHEAD:# 设置流播放模式self.Playctrldll.PlayM4_SetStreamOpenMode(self.PlayCtrl_Port, 0)# 打开码流,送入40字节系统头数据if self.Playctrldll.PlayM4_OpenStream(self.PlayCtrl_Port, pBuffer, dwBufSize, 1024*1024):# 设置解码回调,可以返回解码后YUV视频数据#global FuncDecCBself.FuncDecCB = DECCBFUNWIN(self.DecCBFun)self.Playctrldll.PlayM4_SetDecCallBackExMend(self.PlayCtrl_Port, self.FuncDecCB, None, 0, None)# 开始解码播放if self.Playctrldll.PlayM4_Play(self.PlayCtrl_Port, None):print(u'播放库播放成功')else:print(u'播放库播放失败')else:print(u'播放库打开流失败')elif dwDataType == NET_DVR_STREAMDATA:self.Playctrldll.PlayM4_InputData(self.PlayCtrl_Port, pBuffer, dwBufSize)else:print (u'其他数据,长度:', dwBufSize)def release(self):self.Objdll.NET_DVR_StopRealPlay(self.lRealPlayHandle)if self.PlayCtrl_Port.value > -1:self.Playctrldll.PlayM4_Stop(self.PlayCtrl_Port)self.Playctrldll.PlayM4_CloseStream( self.PlayCtrl_Port)self.Playctrldll.PlayM4_FreePort( self.PlayCtrl_Port)PlayCtrl_Port = c_long(-1)self.Objdll.NET_DVR_Logout(self.lUserId)self.Objdll.NET_DVR_Cleanup()print('释放资源结束')def __enter__(self):return selfdef __exit__(self, exc_type, exc_val, exc_tb):self.release()if __name__=="__main__":camIP ='192.168.1.122'#camIP ='192.168.3.157'DEV_PORT = 8000username ='admin'password = 'admin'HIK= HKCam(camIP,username,password)last_stamp = 0while True:t0 =time.time()n_stamp,img = HIK.read()last_stamp=n_stamp'''TODO'''kkk = cv2.waitKey(1)if kkk ==ord('q'):breakHIK.release()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/140371.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React组件渲染和更新的过程

一、回顾Vue组件渲染和更新的过程 二、回顾JSX本质和vdom 三、组件渲染和更新 1、组件渲染过程 props state (组件有了props state)render()生成vnodepatch(elem, vnode) 2、组件更新过程 setState(newState) --> dirtyComponents (可能有子组件)render()生成newVnodepa…

温湿度监测技术又进化了,这个操作太牛了!

无论是在家庭、医疗、农业、制造业&#xff0c;还是在物流和食品行业&#xff0c;精确的温湿度监控对于确保安全、质量和效率都至关重要。 客户案例 医疗行业 在医疗行业&#xff0c;温湿度监控对于存储药品、生物样本和医疗设备至关重要。山东某医院引入了泛地缘科技推出的温湿…

LeetCode【17】电话号码的字母组合

题目&#xff1a; 思路&#xff1a; 参考&#xff1a;https://blog.csdn.net/weixin_46429290/article/details/121888154 和上一个题《子集》的思路一样&#xff0c;先画出树结构&#xff0c;看树的深度&#xff08;遍历层级&#xff09;&#xff0c;树的宽度&#xff08;横向…

智慧门牌管理系统:省市区县区划数据与国家级开发区共融

文章目录 前言一、行政区划数据的重要性二、支持国家级开发区的发展三、数据基础的重要性 前言 随着科技的飞速发展&#xff0c;我们的生活正在发生日新月异的变化。其中&#xff0c;智慧城市的概念正逐渐成为我们生活中的一部分。智慧城市&#xff0c;顾名思义&#xff0c;运…

性能测试-JMeter分布式测试及其详细步骤

性能测试概要 性能测试是软件测试中的一种&#xff0c;它可以衡量系统的稳定性、扩展性、可靠性、速度和资源使用。它可以发现性能瓶颈&#xff0c;确保能满足业务需求。很多系统都需要做性能测试&#xff0c;如Web应用、数据库和操作系统等。 性能测试种类非常多&#xff0c…

wps/word 之 word中的两个表格 如何合并成为一个表格(已解决)

第一步&#xff1a;新建两个表格&#xff1a; 如何实现上面的两个表格合并呢&#xff1f; 分别选定每个表格&#xff0c;然后鼠标右键---》表格属性 在表格属性中的 表格---》选择 无文字环绕。 第二个表格按照同样的方法 设置 无文字环绕。 然后将中的文本行删去即可以了。选…

去中心遇见混币器

区块链的去中心化交易所在保护隐私和安全性上有着无可比拟的优势&#xff0c;用户甚至不需要提供注册资料&#xff0c;只要有web3钱包即可跟智能合约交易。在uniswap上可兑换绝大多数加密币&#xff0c;新推出的衍生品交易所ununx已经可以交易美股&#xff0c;期货和外汇,一个全…

运行 XXXApplication 时出错,命令行过长

运行 XXXApplication 时出错&#xff0c;命令行过长 问题原因&#xff1a;当在运行 XXXApplication 时遇到命令行过长的错误&#xff0c;通常是由于操作系统的限制导致的。在某些操作系统中&#xff0c;命令行的长度是有限制的&#xff0c;超过该限制会导致出错。 问题解决&am…

vue2打包优化-小白也可快速上手的一套

需求&#xff1a;项目过大可以使用打包优化&#xff0c;减少项目体积&#xff0c;加速页面加载&#xff0c;增强用户体验&#xff0c;跟着步骤来即可实现&#xff0c;主要是vue2的打包优化&#xff0c;不是vue3&#xff0c;文章可能有点长&#xff0c;但是很实用哈哈&#xff0…

Java实现业务异步的几种方案

背景&#xff1a; 在java中异步线程很重要&#xff0c;比如在业务流处理时&#xff0c;需要通知硬件设备&#xff0c;发短信通知用户&#xff0c;或者需要上传一些图片资源到其他服务器这种耗时的操作&#xff0c;在主线程里处理会阻塞整理流程&#xff0c;而且我们也不需要等…

修改ruoyi框架前端刷新页面时紫色的背景颜色

问题描述 最近在使用ruoyi的前后端分离框架&#xff0c;发现前端VUE页面刷新的时候&#xff0c;会出现加载的紫色页面&#xff0c;想要修改这个颜色&#xff0c;请看下面的教程。 修改教程 找到public/index.html&#xff0c;然后找到background为#7171C6这个颜色的代码&…

DDoS攻击与CC攻击:网络安全的两大挑战

在今天的数字时代&#xff0c;网络安全问题越来越突出&#xff0c;其中分布式拒绝服务攻击&#xff08;DDoS攻击&#xff09;和HTTP洪泛攻击&#xff08;CC攻击&#xff09;是两种常见的网络威胁。本文将探讨这两种攻击的概念、原理以及如何有效地应对它们。 1. DDoS攻击&…