借鉴了曹同学的案例实现了python调用海康SDK实现登入、预览功能 并添加了抓图、光学变倍功能;光学变倍功能通过分装的c++DLL再通过Python调用进行实现;
python实现的功能如下:
import os
import ctypes
#获取所有的库文件到一个列表
path = "HKCam/"
def file_name(file_dir):
pathss=[]
for root, dirs, files in os.walk(file_dir):
for file in files:
pathss.append("HKCam/"+file)
return pathss
dll_list=file_name(path)
lUserID = 0
def callCpp(func_name,*args):
for HK_dll in dll_list:
try:
lib = ctypes.cdll.LoadLibrary(HK_dll)
try:
value = eval("lib.%s"%func_name)(*args)
# print("调用的库:"+HK_dll)
# print("执行成功,返回值:"+str(value))
return value
except:
continue
except:
# print("库文件载入失败:"+HK_dll)
continue
# print("没有找到接口!")
return False
# region 登入
#定义登入结构体
class LPNET_DVR_DEVICEINFO_V30(ctypes.Structure):
_fields_ = [
("sSerialNumber", ctypes.c_byte * 48),
("byAlarmInPortNum", ctypes.c_byte),
("byAlarmOutPortNum", ctypes.c_byte),
("byDiskNum", ctypes.c_byte),
("byDVRType", ctypes.c_byte),
("byChanNum", ctypes.c_byte),
("byStartChan", ctypes.c_byte),
("byAudioChanNum", ctypes.c_byte),
("byIPChanNum", ctypes.c_byte),
("byZeroChanNum", ctypes.c_byte),
("byMainProto", ctypes.c_byte),
("bySubProto", ctypes.c_byte),
("bySupport", ctypes.c_byte),
("bySupport1", ctypes.c_byte),
("bySupport2", ctypes.c_byte),
("wDevType", ctypes.c_uint16),
("bySupport3", ctypes.c_byte),
("byMultiStreamProto", ctypes.c_byte),
("byStartDChan", ctypes.c_byte),
("byStartDTalkChan", ctypes.c_byte),
("byHighDChanNum", ctypes.c_byte),
("bySupport4", ctypes.c_byte),
("byLanguageType", ctypes.c_byte),
("byVoiceInChanNum", ctypes.c_byte),
("byStartVoiceInChanNo", ctypes.c_byte),
("byRes3", ctypes.c_byte * 2),
("byMirrorChanNum", ctypes.c_byte),
("wStartMirrorChanNo", ctypes.c_uint16),
("byRes2", ctypes.c_byte * 2)]
#用户注册设备 并登入,需要修改IP,账号、密码
def NET_DVR_Login_V30(sDVRIP = "192.168.1.65",wDVRPort = 8000,sUserName = "admin",sPassword = "guoji123"):
init_res = callCpp("NET_DVR_Init")#SDK初始化
if init_res:
print("SDK初始化成功")
error_info = callCpp("NET_DVR_GetLastError")
print("SDK初始化错误:" + str(error_info))
else:
error_info = callCpp("NET_DVR_GetLastError")
print("SDK初始化错误:" + str(error_info))
return False
set_overtime = callCpp("NET_DVR_SetConnectTime",5000,4)#设置超时
if set_overtime:
print("设置超时时间成功")
else:
error_info = callCpp("NET_DVR_GetLastError")
print("设置超时错误信息:" + str(error_info))
return False
#用户注册设备
#c++传递进去的是byte型数据,需要转成byte型传进去,否则会乱码
sDVRIP = bytes(sDVRIP,"ascii")
sUserName = bytes(sUserName,"ascii")
sPassword = bytes(sPassword,"ascii")
print( "数据转化成功")
DeviceInfo = LPNET_DVR_DEVICEINFO_V30()
print(DeviceInfo)
lUserID = callCpp("NET_DVR_Login_V30",sDVRIP,wDVRPort,sUserName,sPassword,ctypes.byref(DeviceInfo))
print("登录成功,用户ID:"+str(lUserID))
if lUserID == -1:
error_info = callCpp("NET_DVR_GetLastError")
print("登录错误信息:" + str(error_info))
return error_info
else:
return lUserID
# endregion
# region 预览
#定义预览结构体
class NET_DVR_PREVIEWINFO(ctypes.Structure):
_fields_ = [
("lChannel", ctypes.c_long),
("lLinkMode", ctypes.c_long),
("hPlayWnd", ctypes.c_void_p),
("sMultiCastIP", ctypes.c_char_p),
("byProtoType", ctypes.c_byte),
("byRes", ctypes.c_byte * 3)]
# 预览实现
def Preview():
lpPreviewInfo=NET_DVR_PREVIEWINFO()
# hPlayWnd需要输入创建图形窗口的handle,没有输入无法实现BMP抓图
lpPreviewInfo.hPlayWnd=None
lpPreviewInfo.lChannel=1
lpPreviewInfo.dwLinkMode=0
lpPreviewInfo.sMultiCastIP=None
m_lRealHandle=callCpp("NET_DVR_RealPlay_V30",lUserID,ctypes.byref(lpPreviewInfo),None,None,True)
if(m_lRealHandle<0):
error_info = callCpp("NET_DVR_GetLastError")
print("预览失败:" + str(error_info))
else:
print("预览成功")
return m_lRealHandle
# endregion
# region 抓图
# BMP抓图预览的时候hPlayWnd显示窗口不能为none
def Get_BMPPicture():
sBmpPicFileName = bytes("pytest.bmp", "ascii")
if(callCpp("NET_DVR_CapturePicture",m_lRealHandle,sBmpPicFileName)==False):
error_info = callCpp("NET_DVR_GetLastError")
print("抓图失败:" + str(error_info))
else:
print("抓图成功")
# 抓图数据结构体
class NET_DVR_JPEGPARA(ctypes.Structure):
_fields_ = [
("wPicSize", ctypes.c_ushort),
("wPicQuality", ctypes.c_ushort)]
# jpeg抓图hPlayWnd显示窗口能为none,存在缺点采集图片速度慢
def Get_JPEGpicture():
sJpegPicFileName = bytes("pytest.jpg", "ascii")
lChannel=1
lpJpegPara=NET_DVR_JPEGPARA()
lpJpegPara.wPicSize=0
lpJpegPara.wPicQuality=0
if (callCpp("NET_DVR_CaptureJPEGPicture", lUserID, lChannel, ctypes.byref(lpJpegPara), sJpegPicFileName)== False):
error_info = callCpp("NET_DVR_GetLastError")
print("抓图失败:" + str(error_info))
else:
print("抓图成功")
# endregion
#相机登入
NET_DVR_Login_V30()
# 相机预览
m_lRealHandle=Preview()
# 获取光学变倍的dll动态链接库
CamDLL=ctypes.cdll.LoadLibrary("HKZoomCam.dll")
# 获取当前相机的光学变倍数
f = CamDLL.CapCamZoom(lUserID)
# 输入光学变倍数进行光学变倍,并输出变倍后的光学变倍
f1 = CamDLL.ChangeCamZoom(lUserID, 2)
print(f)
print(f1)
# Get_BMPPicture()
Get_JPEGpicture()
相机光学变倍的功能通过C++实现并封装成Dll文件 进行调用;光学变倍实现功能c++代码如下,需要配置海康的库文件和头文件,
// HKRedCam.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
//#include "afxdialogex.h"
#include "HCNetSDK.h"
#include<iostream>
using namespace std;
int main()
{
LONG m_lServerID;
LONG m_lChannel;
LONG m_iDevIndex;
LONG m_lPUServerID;
LONG m_lPlayHandle;
long m_lUserID;
long m_lPreviewHandle;
if (!NET_DVR_Init())
{
cout << ("初始化:SDK初始化失败!错误信息:%s(%d)", NET_DVR_GetErrorMsg(), NET_DVR_GetLastError()) << endl;
}
else
{
NET_DVR_SetLogToFile(3, "./record/");
cout << ("初始化成功") << endl;
}
NET_DVR_DEVICEINFO_V30 struDeviceInfo;
m_lUserID = NET_DVR_Login_V30("192.168.1.65", 8000, "admin", "guoji123", &struDeviceInfo);
printf("注册返回值:%d!!!\n", m_lUserID);
if (m_lUserID < 0)
{
cout << "登入失败" << endl;
}
else
{
NET_DVR_PREVIEWINFO struPara;
struPara.byPreviewMode = 0;
struPara.byProtoType = 0;
struPara.dwStreamType = 0;
struPara.dwLinkMode = 0;
struPara.lChannel = 1;
m_lPreviewHandle = NET_DVR_RealPlay_V40(m_lUserID, &struPara, NULL, NULL);
if (m_lPreviewHandle < 0)
{
cout << "预览失败:" << NET_DVR_GetErrorMsg() << " " << NET_DVR_GetLastError() << endl;
}
else
{
cout << "预览成功" << endl;
}
}
bool m_bGetFocusmodeCfg = false;
NET_DVR_FOCUSMODE_CFG m_struFocusModeCfg;
DWORD dwReturned = 0;
if (NET_DVR_GetDVRConfig(m_lUserID, NET_DVR_GET_FOCUSMODECFG, 1, &m_struFocusModeCfg, sizeof(m_struFocusModeCfg), &dwReturned))
{
cout<<"聚焦模式:获取参数成功!"<<endl;
m_bGetFocusmodeCfg = true;
cout << "光学变倍值: " << m_struFocusModeCfg.fOpticalZoomLevel << endl;
}
else
{
cout << "聚焦模式:获取参数失败!错误信息: " << NET_DVR_GetLastError() << endl;
}
if (m_lUserID < 0)
{
printf("聚焦模式:未登录设备!");
}
else
{
if (!m_bGetFocusmodeCfg)//只是一个判断,判断是否获取参数成功
{
printf("聚焦模式:还未获取参数!");
}
else
{
m_struFocusModeCfg.fOpticalZoomLevel = 1;
if (NET_DVR_SetDVRConfig(m_lUserID, NET_DVR_SET_FOCUSMODECFG, 1, &(m_struFocusModeCfg), sizeof(m_struFocusModeCfg)))
{
cout << "光学变倍修改成功,修改后的光学变倍为:" << m_struFocusModeCfg.fOpticalZoomLevel << endl;
}
else
{
cout << "聚焦模式:设置失败!错误信息: " << NET_DVR_GetLastError() << endl;
}
}
}
return 0;
}
python功能实现Demo
python功能实现Demo连接:https://download.csdn.net/download/weixin_40851278/10526598
c++光学变倍实现Demo连接:https://download.csdn.net/download/weixin_40851278/10526586
参考文档:https://blog.csdn.net/caobin0825/article/details/79667442