Windows下通过python调用海康SDK实现登入、预览、抓图、光学变倍功能

    借鉴了曹同学的案例实现了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

猜你喜欢

转载自blog.csdn.net/weixin_40851278/article/details/80949594