设备注册后,必须要调用 NET_DVR_RealPlay_V40() 函数进行预览摄像头画面,后面的抓图、读帧以及云台控制均要求先执行这一步。
C++ SDK中该函数定义如下:
LONG NET_DVR_RealPlay_V40(
LONG lUserID,
LPNET_DVR_PREVIEWINFO lpPreviewInfo,
REALDATACALLBACK fRealDataCallBack_V30,
void *pUser);
可以有1个回调函数 REALDATACALLBACK
typedef void(CALLBACK *REALDATACALLBACK)(
LONG lRealHandle,
DWORD dwDataType,
BYTE *pBuffer,
DWORD dwBufSize,
void *pUser);
注意要计划好显示视频的窗口控件,获取该窗口的句柄,传给NET_DVR_RealPlay_V40
,或回调函数。
捕获视频码流以及解码显示均由该回调函数完成,捕获原始的YUV视频帧也在此进行。
如果要对视频进行分析,有两种方法
1)通过sdk的抓图接口函数抓图进行分析,如 NET_DVR_CapturePicture
2) 实时性要求高,可将预览码流中的原始YUV帧l转换为RGB后,再进行
处理。
import os
import platform
import tkinter
from tkinter import *
from tkinter import ttk
from HCNetSDK import *
from PlayCtrl import *
from time import sleep
import ctypes
WINDOWS_FLAG = True
win = None
funcRealDataCallBack_V30 = None
PlayCtrl_Port = c_long(-1)
Playctrldll = None
FuncDecCB = None
def GetPlatform():
sysstr = platform.system()
print('' + sysstr)
if sysstr != "Windows":
global WINDOWS_FLAG
WINDOWS_FLAG = False
def SetSDKInitCfg():
if WINDOWS_FLAG:
strPath = os.getcwd().encode('gbk')
sdk_ComPath = NET_DVR_LOCAL_SDK_PATH()
sdk_ComPath.sPath = strPath
Objdll.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))
Objdll.NET_DVR_SetSDKInitCfg(3, create_string_buffer(
strPath + b'\libcrypto-1_1-x64.dll'))
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
Objdll.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))
Objdll.NET_DVR_SetSDKInitCfg(
3, create_string_buffer(strPath + b'/libcrypto.so.1.1'))
Objdll.NET_DVR_SetSDKInitCfg(
4, create_string_buffer(strPath + b'/libssl.so.1.1'))
def LoginDev(sdk):
device_info = NET_DVR_DEVICEINFO_V30()
lUserId = Objdll.NET_DVR_Login_V30(
DEV_IP, DEV_PORT, DEV_USER_NAME, DEV_PASSWORD, byref(device_info))
struLoginInfo = NET_DVR_USER_LOGIN_INFO()
struLoginInfo.bUseAsynLogin = 0
struLoginInfo.sDeviceAddress = bytes("192.168..200", "ascii")
struLoginInfo.wPort = 8000
struLoginInfo.sUserName = bytes("admin", "ascii")
struLoginInfo.sPassword = bytes("123456", "ascii")
struLoginInfo.byLoginMode = 0
struDeviceInfoV40 = NET_DVR_DEVICEINFO_V40()
UserID = sdk.NET_DVR_Login_V40(
byref(struLoginInfo), byref(struDeviceInfoV40))
return (UserID, struDeviceInfoV40)
def DecCBFun(nPort, pBuf, nSize, pFrameInfo, nUser, nReserved2):
if pFrameInfo.contents.nType == 3:
sFileName = ('pic/test_stamp[%d].jpg' %
pFrameInfo.contents.nStamp)
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)
lRet = Playctrldll.PlayM4_ConvertToJpegFile(
pBuf, nSize, nWidth, nHeight, nType, c_char_p(sFileName.encode()))
if lRet == 0:
print('PlayM4_ConvertToJpegFile fail, error code is:',
Playctrldll.PlayM4_GetLastError(nPort))
else:
print('PlayM4_ConvertToJpegFile success')
def RealDataCallBack_V30(lPlayHandle, dwDataType, pBuffer, dwBufSize, pUser):
if dwDataType == NET_DVR_SYSHEAD:
Playctrldll.PlayM4_SetStreamOpenMode(PlayCtrl_Port, 0)
if Playctrldll.PlayM4_OpenStream(PlayCtrl_Port, pBuffer, dwBufSize, 1024*1024):
global FuncDecCB
FuncDecCB = DECCBFUNWIN(DecCBFun)
Playctrldll.PlayM4_SetDecCallBackExMend(
PlayCtrl_Port, FuncDecCB, None, 0, None)
if Playctrldll.PlayM4_Play(PlayCtrl_Port, cv.winfo_id()):
print(u'播放库播放成功')
else:
print(u'播放库播放失败')
else:
print(u'播放库打开流失败')
elif dwDataType == NET_DVR_STREAMDATA:
Playctrldll.PlayM4_InputData(PlayCtrl_Port, pBuffer, dwBufSize)
else:
print(u'其他数据,长度:', dwBufSize)
def OpenPreview(Objdll, lUserId, callbackFun):
preview_info = NET_DVR_PREVIEWINFO()
preview_info.hPlayWnd = 0
preview_info.lChannel = 1
preview_info.dwStreamType = 0
preview_info.dwLinkMode = 0
preview_info.bBlocked = 1
preview_info.dwDisplayBufNum = 15
lRealPlayHandle = Objdll.NET_DVR_RealPlay_V40(
lUserId, byref(preview_info), callbackFun, None)
return lRealPlayHandle
def InputData(fileMp4, Playctrldll):
while True:
pFileData = fileMp4.read(4096)
if pFileData is None:
break
if not Playctrldll.PlayM4_InputData(PlayCtrl_Port, pFileData, len(pFileData)):
break
def click_capture():
print("clicked capture button")
pFileName = ctypes.c_char_p()
pFileName.value = bytes("pic/image.jpg", "utf-8")
res = Objdll.NET_DVR_CapturePicture(lRealPlayHandle, pFileName)
if res:
print("Successfullly capture picture, ", pFileName.value)
def click_left():
print("clicked button up")
def click_right():
print("clicked button")
def click_up():
print("clicked button")
def click_down():
print("clicked button")
if __name__ == '__main__':
win = tkinter.Tk()
win.resizable(0, 0)
win.overrideredirect(True)
sw = win.winfo_screenwidth()
sh = win.winfo_screenheight()
ww = 800
wh = 650
x = (sw - ww) / 2
y = (sh - wh) / 2
win.geometry("%dx%d+%d+%d" % (ww, wh, x, y))
cv = Canvas(
win,
width=760,
height=460,
bg="white",
cv.place(x=20, y=10)
btn_left = Button(win, text=" 左 ",
command=click_left).place(x=100, y=530)
btn_right = Button(win, text=" 右 ",
command=click_right).place(x=180, y=530)
btn_top = Button(win, text=" 上 ", command=click_up).place(x=145, y=495)
btn_down = Button(win, text=" 下 ",
command=click_down).place(x=145, y=565)
btn_capture = Button(win, text=" 放大 ",
command=click_capture).place(x=280, y=500)
btn_capture = Button(win, text=" 缩小 ",
command=click_capture).place(x=280, y=530)
btn_capture = Button(win, text=" 截图 ",
command=click_capture).place(x=280, y=560)
lbl_ip = Label(win, text="IP地址", fg="#111").place(x=480, y=490)
ent_ip = Entry(win).place(x=550, y=490)
lbl_port = Label(win, text="端口", fg="#111").place(x=480, y=515)
ent_port = Entry(win).place(x=550, y=515)
lbl_name = Label(win, text="登录名", fg="#111").place(x=480, y=540)
ent_name = Entry(win).place(x=550, y=540)
lbl_password = Label(win, text="密码", fg="#111").place(x=480, y=565)
password = StringVar()
password_entry = ttk.Entry(
win,
textvariable=password,
show='*'
password_entry.place(x=550, y=565)
separator = ttk.Separator(win, orient='horizontal')
separator.place(x=10, y=600, width=790)
btn_q = Button(win, text=' 退出 ', command=win.quit)
btn_q.place(x=660, y=610)
dname = 'D:\workplace\dependency\hik_lib\HCNetSDK.dll'
Objdll = ctypes.cdll.LoadLibrary(dname)
dname = 'D:\workplace\dependency\hik_lib\PlayCtrl.dll'
Playctrldll = ctypes.cdll.LoadLibrary(dname)
print("load dll successfully")
Objdll.NET_DVR_Init()
print("init device successfully ")
Objdll.NET_DVR_SetLogToFile(
3, bytes('./SdkLog_Python/', encoding="utf-8"), False)
print("config log to SdkLog_Python ")
if not Playctrldll.PlayM4_GetPort(byref(PlayCtrl_Port)):
print(u'获取播放库句柄失败')
(lUserId, device_info) = LoginDev(Objdll)
if lUserId < 0:
err = Objdll.NET_DVR_GetLastError()
print('Login device fail, error code is: %d' %
Objdll.NET_DVR_GetLastError())
Objdll.NET_DVR_Cleanup()
exit()
print("login device ")
funcRealDataCallBack_V30 = REALDATACALLBACK(RealDataCallBack_V30)
lRealPlayHandle = OpenPreview(Objdll, lUserId, funcRealDataCallBack_V30)
if lRealPlayHandle < 0:
print('Open preview fail, error code is: %d' %
Objdll.NET_DVR_GetLastError())
Objdll.NET_DVR_Logout(lUserId)
Objdll.NET_DVR_Cleanup()
exit()
win.mainloop()
Objdll.NET_DVR_StopRealPlay(lRealPlayHandle)
if PlayCtrl_Port.value > -1:
Playctrldll.PlayM4_Stop(PlayCtrl_Port)
Playctrldll.PlayM4_CloseStream(PlayCtrl_Port)
Playctrldll.PlayM4_FreePort(PlayCtrl_Port)
PlayCtrl_Port = c_long(-1)
Objdll.NET_DVR_Logout(lUserId)
Objdll.NET_DVR_Cleanup()
其它SDK功能函数, 可以参照上述思路,用ctype重新定义形参、返回值类型,然后重新申明 C++函数。需要注意 C++中的数组、指针、引用类型与ctypes 的转换。
要调用海康摄像机视频,需要使用海康SDK提供的API。需要注意的是,上述代码中的`HCNetSDK`是海康SDK的Python封装,需要先安装。此外,还需要在海康摄像机的管理页面中开启SDK接入功能,并配置好IP地址、端口号、用户名和密码等信息。print('SDK初始化成功')print('SDK初始化失败')print('登录失败')print('登录成功')
python调用海康sdk操作热成像设备获取对应点温度
Python调用海康sdk操作热成像设备获取对应点温度, 海康官方提供有Java版的sdk,遗憾的是里面提供的api比较旧了新版的api需要根据c++版的开发文档自己写对应的Python接口和类。这对于不熟悉c++的开发人员比较吃力。下面的代码示例了通过海康的SDK获取热成像画面上某一点的具体温度。hCNetSDK = CDLL(’./libhcnetsdk.so’)是海康sdk的目录,可以是相对路径也可以是绝对路径。
1.dll动态库python函
这里写自定义目录标题本文参考以下博文加自己的实践,发现有些步骤是不必要的,例如不需要为opencv等第三方库指定路径运行环境:准备工作1、海康SDK下载2、下载安装vcpkg3、安装Swig4、下载OpenCV-swig接口文件
本文参考以下博文加自己的实践,发现有些步骤是不必要的,例如不需要为opencv等第三方库指定路径
https://blog.csdn.net/c20081052/article/details/95082377
https://www.ryannn.com/archives/hi
然后把依赖的dll都放在HKIPcamera.dll的同级目录下就成功了,我是由于缺少opencv的dll(已经添加到环境变量,并且已经在vs里添加到目录里了,居然还是不行)于是就直接把opencv_world3410.dll拷到HKIPcamera.dll目录下了。按照第一个参考链接,海康sdk的dll(下图海康sdk的库文件目录整个都拷)都拷到项目里HKIPcamera.dll同级目录下还是不行。生成解决方案的时候,显示LNK2001:无法解析的外部符号。
搜罗了网上一些关于如何在python中实现海康威视相机的连接与画面播放的资料,最直接的方式是通过rtsp流来实现。
海康的rtsp协议格式如下(参考:海康相机使用RTSP):
rtsp://[username]:[passwd]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream
rtsp://admin:12345@192.168....