目錄
1.python sdk使用
1.??礢DK下載
?2.opencv讀取sdk流
?先說效果,我是用的AI推理的實時流,延遲從高達7秒降到小于1秒
如果覺得這個延遲還不能接受,下一章,給大家介紹點上不得臺面的小方法
SDK(Software Development Kit)是軟件開發(fā)工具包的縮寫,它是一組用于開發(fā)特定軟件或應用程序的工具、庫和文檔的集合。SDK提供了開發(fā)所需的資源和接口,幫助開發(fā)者更高效地構建應用程序。
SDK通常包含以下內容:
- 工具:SDK提供了一系列開發(fā)工具,如編譯器、調試器、IDE(集成開發(fā)環(huán)境)等,用于編寫、調試和測試代碼。
- 庫:SDK中的庫是預先編譯好的可重用代碼模塊,包含常見的功能和算法,開發(fā)者可以直接調用這些庫來簡化開發(fā)過程。
- 示例代碼:SDK通常附帶一些示例代碼,展示如何使用SDK提供的功能和接口,幫助開發(fā)者快速上手并理解開發(fā)流程。
- 文檔:SDK提供詳細的文檔,包括API參考、開發(fā)指南、示例代碼解釋等,幫助開發(fā)者了解SDK的功能和使用方法。
- 依賴項:SDK可能需要依賴其他軟件或庫,例如操作系統(tǒng)、第三方庫等,開發(fā)者需要滿足這些依賴關系才能使用SDK。
SDK的作用是簡化開發(fā)過程,提供開發(fā)所需的資源和接口,節(jié)省開發(fā)者的時間和精力。通過使用SDK,開發(fā)者可以快速構建功能豐富、高效的應用程序,而無需從頭開始編寫所有的代碼和功能。
1.python sdk使用
之前常常采用python來讀取usb攝像頭,因為其語言風格易讀且上手快。起先,使用rtsp流來讀海康的網(wǎng)絡相機,視頻畫面出現(xiàn)延遲卡頓的現(xiàn)象,如果對于實時性要求較高(起碼得和網(wǎng)頁預覽效果相當?shù)膸剩┑脑?,用rtsp流讀取的方式顯得不可取,本文采用在python中調用HikVision的SDK讀取IP相機的方式實現(xiàn),幀率的話和網(wǎng)絡預覽效果相當
1.??礢DK下載
?
下載好解壓后
進入以下路徑
??低?HCNetSDKV6.1.9.48_build20230410_win64---Demo示例---5- Python開發(fā)示例---1-預覽取流解碼Demo
1.找到這個lib路徑,里面應該是空的
看需要選擇win或者linux
2.返回主目錄,選擇庫文件,復制全部文件(實際按官方文檔只需要部分庫文件,不過可以傻瓜式全部打包),粘貼到上面的lib文件夾的win文件中
下面是官方文檔的操作說明
1. 更新設備網(wǎng)絡SDK時,SDK開發(fā)包【庫文件】里的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. 如果自行開發(fā)軟件不能正常實現(xiàn)相應功能,而且程序沒有指定加載的dll庫路徑,請在程序運行的情況下嘗試刪除HCNetSDK.dll。如果可以刪除,說明程序可能調用到系統(tǒng)盤Windows->System32目錄下的dll文件,建議刪除或者更新該目錄下的相關dll文件;如果不能刪除,dll文件右鍵選擇屬性確認SDK庫版本。
3. 如按上述步驟操作后還是不能實現(xiàn)相應功能,請根據(jù)NET_DVR_GetLastError返回的錯誤號判斷原因。
3.運行test_main.py
獲取實時畫面
?2.opencv讀取sdk流
將下面代碼貼到test_main.py的同級目錄下
運行即可文章來源:http://www.zghlxwxcb.cn/news/detail-725353.html
有問題的朋友歡迎評論區(qū)留言文章來源地址http://www.zghlxwxcb.cn/news/detail-725353.html
# coding=utf-8
import os
import platform
from HCNetSDK import *
from PlayCtrl import *
import numpy as np
import time
import cv2
class HKCam(object):
def __init__(self,camIP,username,password,devport=8000):
# 登錄的設備信息
self.DEV_IP = create_string_buffer(camIP.encode())
self.DEV_PORT =devport
self.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 True
self.funcRealDataCallBack_V30 = None
self.recent_img = None #最新幀
self.n_stamp = None #幀時間戳
self.last_stamp = None #上次時間戳
# 加載庫,先加載依賴庫 # 1 根據(jù)操作系統(tǒng),加載對應的dll文件
if self.WINDOWS_FLAG:
os.chdir(r'./lib/win')
self.Objdll = ctypes.CDLL(r'./HCNetSDK.dll') # 加載網(wǎng)絡庫
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()
# 初始化DLL
self.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)#清空指定緩沖區(qū)的剩余數(shù)據(jù)。這個地方傳進來的是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'獲取播放庫句柄失敗')
# 定義碼流回調函數(shù)
self.funcRealDataCallBack_V30 = REALDATACALLBACK(self.RealDataCallBack_V30)
# 開啟預覽
self.preview_info = NET_DVR_PREVIEWINFO()
self.preview_info.hPlayWnd = 0
self.preview_info.lChannel = 1 # 通道號
self.preview_info.dwStreamType = 0 # 主碼流
self.preview_info.dwLinkMode = 0 # TCP
self.preview_info.bBlocked = 1 # 阻塞取流
# 開始預覽并且設置回調函數(shù)回調獲取實時流數(shù)據(jù)
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 = strPath
self.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 = strPath
self.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:
continue
self.last_stamp=self.n_stamp
return self.n_stamp,self.recent_img
def DecCBFun(self,nPort, pBuf, nSize, pFrameInfo, nUser, nReserved2):
if pFrameInfo.contents.nType == 3:
t0 = time.time()
# 解碼返回視頻YUV數(shù)據(jù),將YUV數(shù)據(jù)轉成jpg圖片保存到本地
# 如果有耗時處理,需要將解碼數(shù)據(jù)拷貝到回調函數(shù)外面的其他線程里面處理,避免阻塞回調導致解碼丟幀
nWidth = pFrameInfo.contents.nWidth
nHeight = pFrameInfo.contents.nHeight
#nType = pFrameInfo.contents.nType
dwFrameNum = pFrameInfo.contents.dwFrameNum
nStamp = 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,nStamp
def RealDataCallBack_V30(self,lPlayHandle, dwDataType, pBuffer, dwBufSize, pUser):
# 碼流回調函數(shù)
if dwDataType == NET_DVR_SYSHEAD:
# 設置流播放模式
self.Playctrldll.PlayM4_SetStreamOpenMode(self.PlayCtrl_Port, 0)
# 打開碼流,送入40字節(jié)系統(tǒng)頭數(shù)據(jù)
if self.Playctrldll.PlayM4_OpenStream(self.PlayCtrl_Port, pBuffer, dwBufSize, 1024*1024):
# 設置解碼回調,可以返回解碼后YUV視頻數(shù)據(jù)
#global FuncDecCB
self.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'其他數(shù)據(jù),長度:', 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 self
def __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 = 8000
username ='admin'
password = 'admin'
HIK= HKCam(camIP,username,password)
last_stamp = 0
while True:
t0 =time.time()
n_stamp,img = HIK.read()
last_stamp=n_stamp
'''
TODO
'''
kkk = cv2.waitKey(1)
if kkk ==ord('q'):
break
HIK.release()
到了這里,關于如何降低???、大華等網(wǎng)絡攝像頭調用的高延遲問題(一):海康威視網(wǎng)絡攝像頭的python sdk使用(opencv讀取sdk流)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!