海康网络摄像机 python实现OSD获取以及修改

1、下载SDK

海康开放平台SDK下载,下载自己对应系统的SDK,根据里面说明进行配置SDK

2、选好HCNetSDK.py文件

最好直接使用 Demo示例\5- Python开发示例\6-参数配置Demo 路径下的HCNetSDK.py,确保文件里有NET_DVR_SHOWSTRINGINFO以及NET_DVR_SHOWSTRING_V30两个结构体,还有两个字符结构参数,见下面代码。

# 叠加字符结构参数 (NET_DVR_SHOWSTRING_V30结构)
NET_DVR_GET_SHOWSTRING_V30 = 1030
NET_DVR_SET_SHOWSTRING_V30 = 1031


# 叠加字符
class NET_DVR_SHOWSTRINGINFO(Structure):
    pass


LPNET_DVR_SHOWSTRINGINFO = POINTER(NET_DVR_SHOWSTRINGINFO)
NET_DVR_SHOWSTRINGINFO._fields_ = [
    ('wShowString', c_ushort),
    ('wStringSize', c_ushort),
    ('wShowStringTopLeftX', c_ushort),
    ('wShowStringTopLeftY', c_ushort),
    ('sString', c_ubyte * 44),
]


# 叠加字符
class NET_DVR_SHOWSTRING_V30(Structure):
    pass


LPNET_DVR_SHOWSTRING_V30 = POINTER(NET_DVR_SHOWSTRING_V30)
NET_DVR_SHOWSTRING_V30._fields_ = [
    ('dwSize', c_uint32),
    ('struStringInfo', NET_DVR_SHOWSTRINGINFO * 8),
]

3、获取OSD参数

对照SDK手册查看各个参数

def GetOSDString(UserID):

    str_osd_cfg = NET_DVR_SHOWSTRING_V30()
    str_osd_cfg.dwSize = sizeof(str_osd_cfg)

    p_str_osd_cfg = byref(str_osd_cfg)
    l_channel = c_int(1)
    p_int = c_int(0)

    b_get_osd_cfg = sdk.NET_DVR_GetDVRConfig(UserID, NET_DVR_GET_SHOWSTRING_V30, l_channel.value, p_str_osd_cfg, sizeof(str_osd_cfg), byref(p_int))

    if not b_get_osd_cfg:
        print("获取图像参数失败,错误码:", sdk.NET_DVR_GetLastError())
        return

    LenOSDString = len(str_osd_cfg.struStringInfo)
    # print(str_osd_cfg.struStringInfo[0].wShowString)
    OSDStrings = []
    for i in range(LenOSDString):
        if str_osd_cfg.struStringInfo[i].wShowString == 1:
            print('第几个osd:',i)
            # OSDStrings.append(cfg.struStringInfo[i].sString)
            OSDStrings.append(bytes(str_osd_cfg.struStringInfo[i].sString).rstrip(b'\x00').decode('gbk'))
    return OSDStrings

4、设置OSD参数

def SetOSDString(UserID):

    str_osd_cfg = NET_DVR_SHOWSTRING_V30()
    str_osd_cfg.dwSize = sizeof(str_osd_cfg)

    p_str_osd_cfg = byref(str_osd_cfg)
    l_channel = c_int(1)
    p_int = c_int(0)

    i = 1
    str = r'测试5' # 显示文本
    byte_str = str.encode('gbk') # 编码方式,和上面解码方式保持一致
    c_ubyte_array = (c_ubyte * 44).from_buffer_copy(byte_str.ljust(44, b'\x00'))
    str_osd_cfg.struStringInfo[i].wShowString = 1
    str_osd_cfg.struStringInfo[i].sString = c_ubyte_array
    str_osd_cfg.struStringInfo[i].wStringSize = len(c_ubyte_array)
    str_osd_cfg.struStringInfo[i].wShowStringTopLeftX = 80
    str_osd_cfg.struStringInfo[i].wShowStringTopLeftY = 20

    b_set_osd_cfg = sdk.NET_DVR_SetDVRConfig(UserID, NET_DVR_SET_SHOWSTRING_V30, l_channel.value, p_str_osd_cfg, sizeof(str_osd_cfg), byref(p_int))

    if not b_set_osd_cfg:
        print("设置图像参数失败,错误码:", sdk.NET_DVR_GetLastError())
        return

5、整体代码

所有代码以及上传我的资源,可以查看

# --*-- conding:utf-8 --*--
# @Time : 2024/5/11 15:06
# @Author : wangchao124
# @Email : wangchao124@hikvision.com
# @File : ParameterConfigurator.py
# @Software : PyCharm
import os
import platform
import time
from HCNetSDK import *
import re

# 系统环境标识
WINDOWS_FLAG = True


def GetPlatform():
    """
    获取当前系统环境
    @return:
    """
    sysstr = platform.system()
    print('' + sysstr)
    if sysstr != "Windows":
        global WINDOWS_FLAG
        WINDOWS_FLAG = False


def SetSDKInitCfg():
    """
    设置SDK初始化依赖库路径
    @return:
    """
    # print(os.getcwd())
    if WINDOWS_FLAG:
        strPath = os.getcwd().encode('gbk')
        sdk_ComPath = NET_DVR_LOCAL_SDK_PATH()
        sdk_ComPath.sPath = strPath
        sdk.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))
        sdk.NET_DVR_SetSDKInitCfg(3, create_string_buffer(strPath + b'\\libcrypto-1_1-x64.dll'))
        sdk.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
        sdk.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))
        sdk.NET_DVR_SetSDKInitCfg(3, create_string_buffer(strPath + b'/libcrypto.so.1.1'))
        sdk.NET_DVR_SetSDKInitCfg(4, create_string_buffer(strPath + b'/libssl.so.1.1'))


def login_v40(ip, port, username, password):
    """
    设备登录V40 与V30功能一致
    @param ip:
    @param port:
    @param username:
    @param password:
    @return:
    """
    # 用户注册设备
    # c++传递进去的是byte型数据,需要转成byte型传进去,否则会乱码
    # 登录参数,包括设备地址、登录用户、密码等
    struLoginInfo = NET_DVR_USER_LOGIN_INFO()
    struLoginInfo.bUseAsynLogin = 0  # 同步登录方式 0- 否,1- 是
    struLoginInfo.sDeviceAddress = bytes(ip, "ascii")  # 设备IP地址
    struLoginInfo.wPort = port  # 设备服务端口
    struLoginInfo.sUserName = bytes(username, "ascii")  # 设备登录用户名
    struLoginInfo.sPassword = bytes(password, "ascii")  # 设备登录密码
    struLoginInfo.byLoginMode = 0

    # 设备信息, 输出参数
    struDeviceInfoV40 = NET_DVR_DEVICEINFO_V40()

    UserID = sdk.NET_DVR_Login_V40(byref(struLoginInfo), byref(struDeviceInfoV40))
    if UserID < 0:
        print("Login failed, error code: %d" % sdk.NET_DVR_GetLastError())
        sdk.NET_DVR_Cleanup()
    else:
        print(ip + '登录成功,设备序列号:%s' % str(struDeviceInfoV40.struDeviceV30.sSerialNumber, encoding="utf8"))
    return UserID


def get_device_status(UserId):
    """
    获取设备在线状态
    @param UserId:
    @return:
    """
    devStatus = sdk.NET_DVR_RemoteControl(UserId, NET_DVR_CHECK_USER_STATUS, None, 0)
    if devStatus:
        print("设备在线")
    else:
        print("设备不在线")



def GetOSDString(UserID):

    str_osd_cfg = NET_DVR_SHOWSTRING_V30()
    str_osd_cfg.dwSize = sizeof(str_osd_cfg)

    p_str_osd_cfg = byref(str_osd_cfg)
    l_channel = c_int(1)
    p_int = c_int(0)

    b_get_osd_cfg = sdk.NET_DVR_GetDVRConfig(UserID, NET_DVR_GET_SHOWSTRING_V30, l_channel.value,
                                             p_str_osd_cfg, sizeof(str_osd_cfg), byref(p_int))


    if not b_get_osd_cfg:
        print("获取图像参数失败,错误码:", sdk.NET_DVR_GetLastError())
        return

    LenOSDString = len(str_osd_cfg.struStringInfo)
    # print(str_osd_cfg.struStringInfo[0].wShowString)
    OSDStrings = []
    for i in range(LenOSDString):
        if str_osd_cfg.struStringInfo[i].wShowString == 1:
            print('第几个osd:',i)
            # OSDStrings.append(cfg.struStringInfo[i].sString)
            OSDStrings.append(bytes(str_osd_cfg.struStringInfo[i].sString).rstrip(b'\x00').decode('gbk'))
    return OSDStrings


def SetOSDString(UserID):

    str_osd_cfg = NET_DVR_SHOWSTRING_V30()
    str_osd_cfg.dwSize = sizeof(str_osd_cfg)

    p_str_osd_cfg = byref(str_osd_cfg)
    l_channel = c_int(1)
    p_int = c_int(0)

    i = 1
    str = r'测试5'
    byte_str = str.encode('gbk')
    c_ubyte_array = (c_ubyte * 44).from_buffer_copy(byte_str.ljust(44, b'\x00'))
    str_osd_cfg.struStringInfo[i].wShowString = 1
    str_osd_cfg.struStringInfo[i].sString = c_ubyte_array
    str_osd_cfg.struStringInfo[i].wStringSize = len(c_ubyte_array)
    str_osd_cfg.struStringInfo[i].wShowStringTopLeftX = 80
    str_osd_cfg.struStringInfo[i].wShowStringTopLeftY = 20

    b_set_osd_cfg = sdk.NET_DVR_SetDVRConfig(UserID, NET_DVR_SET_SHOWSTRING_V30, l_channel.value,
                                             p_str_osd_cfg, sizeof(str_osd_cfg), byref(p_int))

    if not b_set_osd_cfg:
        print("设置图像参数失败,错误码:", sdk.NET_DVR_GetLastError())
        return

if __name__ == '__main__':

    # 获取系统平台
    GetPlatform()

    # 加载库,先加载依赖库
    if WINDOWS_FLAG:
        os.chdir(r'./lib/win')
        sdk = ctypes.CDLL(r'./HCNetSDK.dll')
    else:
        os.chdir(r'./lib/linux')
        sdk = cdll.LoadLibrary(r'./libhcnetsdk.so')

    SetSDKInitCfg()  # 设置组件库和SSL库加载路径

    # 初始化
    sdk.NET_DVR_Init()
    # 启用SDK写日志
    sdk.NET_DVR_SetLogToFile(3, bytes('./SdkLog_Python/', encoding="utf-8"), False)

    # 通用参数配置
    sdkCfg = NET_DVR_LOCAL_GENERAL_CFG()
    sdkCfg.byAlarmJsonPictureSeparate = 1
    sdk.NET_DVR_SetSDKLocalCfg(17, byref(sdkCfg))

    # 登录设备
    UserID = login_v40("127.254.11.1", 8000, "admin", "Hik12345")
    get_device_status(UserID)   # 获取设备在线状态

    # 设置字符串
    SetOSDString(UserID)
    print('字符串', GetOSDString(UserID)) # 获取OSD字符串

    # 注销用户,退出程序时调用
    if sdk.NET_DVR_Logout(UserID):
        print("注销成功")

    # 释放SDK资源,退出程序时调用
    sdk.NET_DVR_Cleanup()

<think>好的,我现在需要解决用户在使用海康威视SDK时遇到的`AttributeError: 'NoneType' object has no attribute 'NET_DVR_SetSDKInitCfg'`错误。首先,我需要回忆一下这类错误的常见原因以及针对海康威视SDK的具体解决方法。 用户提到在调用`NET_DVR_SetSDKInitCfg`时出现错误,提示NoneType没有这个属性。通常,`NoneType`属性错误意味着某个对象没有被正确初始化,变成了`None`,而用户试图访问这个`None`对象的方法或属性。在这里,可能的场景是SDK的某个模块没有正确加载,或者函数调用前缺少必要的初始化步骤。 首先,我应该检查SDK的初始化流程。海康威视的SDK通常需要先调用`NET_DVR_Init`来进行初始化,之后才能使用其他函数。如果用户没有正确执行初始化步骤,可能会导致后续函数无法找到正确的引用,从而引发属性错误。例如,在调用`NET_DVR_SetSDKInitCfg`之前是否遗漏了`NET_DVR_Init`? 另外,SDK的DLL或so文件是否正确加载也是一个关键点。Python中使用ctypes库加载动态链接库时,如果路径错误或者文件缺失,会导致加载失败,返回None。这时,任何尝试调用该库中的函数都会触发`AttributeError`,因为对象是None。用户需要确认库文件的路径是否正确,文件名是否拼写正确,以及是否拥有访问权限。 接下来,函数的参数和调用方式是否正确?`NET_DVR_SetSDKInitCfg`可能需要特定的参数类型,比如结构体指针或者特定的整数值。如果参数传递错误,比如没有使用正确的ctypes类型(如c_void_p或POINTER结构),可能会导致函数调用失败,进而引发错误。用户需要检查参数是否符合SDK文档的要求,确保数据类型和指针的正确使用。 还有可能的问题包括SDK版本不兼容。海康威视的SDK可能有多个版本,不同版本的函数名称或参数可能有所变化。如果用户使用的SDK版本与代码不兼容,或者没有正确更新SDK文件,也可能导致找不到函数的情况。建议用户核对SDK文档,确认所使用的函数在当前版本中是否存在,或者是否有替代函数。 此外,Python环境的问题也不容忽视。例如,32位和64位的Python解释器与对应的SDK库是否匹配?如果用户使用的是64位Python,但SDK的DLL是32位的,或者反之,就会导致加载失败。需要确认两者的架构一致。 还有可能是在调用函数之前,某些必要的配置没有完成。例如,海康威视的SDK可能需要设置日志路径、网络参数等,这些配置如果缺失,可能导致初始化失败。用户应该参考官方文档,确保所有必要的配置步骤都已正确执行。 另外,用户提到的引用中的其他AttributeError问题,比如Pydantic相关的错误,虽然不完全相关,但也提示了可能的环境或依赖问题。需要检查是否有其他库冲突或环境配置错误,影响了SDK的正常加载。 最后,如果以上步骤都检查无误,问题仍然存在,可能需要查看更详细的错误日志,或者联系海康威视的技术支持,获取更专业的帮助。同时,提供一段示例代码,帮助用户对比自己的代码,找出可能的差异点。 现在,我需要将这些思考整理成一个结构化的回答,逐步引导用户排查问题,同时确保引用相关的资料,比如用户提供的三个引用链接,虽然它们不完全相关,但可以部分支持初始化或环境配置的问题。</think>### 解决海康威视SDK的`NoneType AttributeError`问题 在使用海康威视SDK(如`hikvision`)时,调用`NET_DVR_SetSDKInitCfg`等接口出现`AttributeError: 'NoneType' object has no attribute`错误,通常与**SDK未正确初始化**或**库加载失败**有关。以下是逐步排查和解决方案: --- #### 1. 确认SDK初始化顺序 海康威视SDK要求严格按顺序执行初始化: 1. **先调用`NET_DVR_Init()`**:初始化SDK全局配置。 2. **再调用`NET_DVR_SetSDKInitCfg()`**:设置初始化参数(如日志路径)。 3. 最后调用其他设备连接/控制接口。 ```python from ctypes import * # 加载SDK库(路径需根据实际情况修改) hikvision = cdll.LoadLibrary("./libhcnetsdk.so") # Linux示例 # hikvision = WinDLL("HCNetSDK.dll") # Windows示例 # 步骤1:必须优先初始化 hikvision.NET_DVR_Init() # 步骤2:再设置参数(示例为设置日志路径) hikvision.NET_DVR_SetSDKInitCfg(2, create_string_buffer(b"/tmp/sdk_logs")) ``` 若未执行`NET_DVR_Init`直接调用其他函数,会因SDK未加载而触发`NoneType`错误[^1][^2]。 --- #### 2. 检查SDK库加载状态 当`cdll.LoadLibrary`或`WinDLL`加载失败时,返回`None`对象,导致后续调用报错。 **解决方法:** - **确认库文件路径正确**:检查文件名拼写、路径权限。 - **验证架构匹配**:32位Python需加载32位SDK库,64位同理。 - **依赖项完整**:某些SDK依赖其他动态库(如`libssl.so`),需确保系统已安装。 ```python try: hikvision = cdll.LoadLibrary("HCNetSDK.dll") except Exception as e: print(f"加载失败: {e}") # 根据错误提示排查 ``` --- #### 3. 检查函数参数类型 使用`ctypes`传递参数时,需严格匹配C语言数据类型。例如: - **字符串参数**需转为`c_char_p`或`create_string_buffer`。 - **结构体参数**需用`POINTER()`定义指针。 **错误示例**(直接传递Python字符串): ```python # 错误:未将字符串转为C格式 hikvision.NET_DVR_SetSDKInitCfg(2, "/tmp/logs") ``` **正确示例**: ```python from ctypes import create_string_buffer log_path = create_string_buffer(b"/tmp/sdk_logs") hikvision.NET_DVR_SetSDKInitCfg(2, log_path) ``` --- #### 4. 更新SDK版本并验证兼容性 部分旧版SDK接口可能已弃用。从海康威视官网下载**最新SDK**,并检查: - 函数名称是否变更(如新增版本后缀)。 - 参数类型是否调整(如新增枚举值)。 --- #### 5. 检查Python对象生命周期 若SDK对象被提前释放(如被垃圾回收),可能导致后续调用时对象为`None`。可通过**显式保留引用**避免: ```python class HikSDK: def __init__(self): self._dll = cdll.LoadLibrary("HCNetSDK.dll") self._dll.NET_DVR_Init() def set_config(self, log_path): buf = create_string_buffer(log_path.encode()) self._dll.NET_DVR_SetSDKInitCfg(2, buf) # 使用类实例保持SDK对象引用 sdk = HikSDK() sdk.set_config("/tmp/logs") ``` --- #### 6. 联系技术支持 若上述步骤无效,建议: - 提供完整的错误堆栈和代码片段。 - 联系海康威视技术支持,确认SDK版本与环境的兼容性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值