海康威视SDK通过NVR获取视频设备的状态

海康威视SDK通过NVR获取视频设备的状态

前言

项目现场是通过NVR对多路摄像头设备进行集中管理,包括实时画面的预览和视频信号的存储、回放。
现在要实现这样一个功能:定期查询摄像头的状态,以确保摄像头都处于在线状态。

1 问题分析

功能的需求是获取摄像头的状态,那么通过注册(login)设备的方式肯定可行,login成功即表示设备在线,否则即为离线。
但是由于整个园区的视频设备多大几百个,这样的势必会造成批量的注册和登出操作,挺麻烦的,而且遇到多个设备无法注册的情况下会造成整个查询的过程时间很长,效率很慢。
因此,既然NVR是视频设备的集成管理设备,那么我们还是从NVR入手,相比NVR的接口中一定有相关的说明。

2 解决过程

2.1 找到接口

从官网下载的SDK中的《设备网络SDK使用手册.chm》中搜索关键字【通道】,找到了接口【NET_DVR_GetDVRConfig】,通过查阅,判断该接口即为所求。命令:NET_DVR_GET_IPPARACFG_V40;结果结构体:NET_DVR_IPPARACFG_V40;子结构体;NET_DVR_IPDEVINFO_V31,NVR中的视频信号的状态便包含于这个结构体中。

【NET_DVR_GetDVRConfig】的参数和参数说明

2.2 配置参数

根据参数说明,声明一下参数:

        CHCNetSDK.NET_DVR_IPPARACFG_V40 IPParacfg = new CHCNetSDK.NET_DVR_IPPARACFG_V40();//结果
        uint dwOutBufferSize = (uint)Marshal.SizeOf(IPParacfg);//输出大小
        IntPtr pOutBuf = Marshal.AllocHGlobal((int)dwOutBufferSize);//输出结果的指针
        uint lpBytesReturned = 0;
		int lChannel = 0;
        if (!CHCNetSDK.NET_DVR_GetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40,lChannel, pOutBuf, dwOutBufferSize,ref lpBytesReturned))
        {
            IPParacfg = (CHCNetSDK.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(pOutBuf, typeof(CHCNetSDK.NET_DVR_IPPARACFG_V40));
        }

这里面第三个参数lChannel我存有疑问。因为《设备网络SDK编程指南(DVR&NVR).pdf》中说的是【无效】参数,即填写“-1”,而《设备网络SDK使用手册.chm》中说的是说从0开始。而下面的解释也没看明白什么意思,到底是填组号还是通道号 搞不清楚,注册返回的消息里也没有组号啊,难不成要是根据通道号一个一个查的?!。

通道号是指设备视频通道号,通过注册设备(NET_DVR_Login_V30)返回的设备信息(NET_DVR_DEVICEINFO_V30)获取模拟通道个数(byChanNum)、模拟通道起始通道号(byStartChan)和设备支持的最大IP通道数(byIPChanNum+ byHighDChanNum*256)、数字通道起始通道号(byStartDChan)。

我心想,那就先测试一下 看看什么结果吧。
直接上结果:

  1. lChannel=0,返回false,结果失败;
  2. lChannel=1,返回true,结果有误,显示通道数、组数上万;
  3. lChannel=2/3/4/5/…,结果同lChannel=1;
  4. lChannel=-1,结果同lChannel=1。

其实我最开始觉得是将输出结果转换为目标格式的时候出现了问题。我开始尝试用其他版本的SDk去测试,但是并没有结果。
我又回归到最初的版本。当我调整参数测试的时候偶然发现这样一个问题:
当我先用lChannel=0测试的时候确实会出现 返回结果确实是false,但是我在设置lChannel=1,就可以获得正确的结果。

即时窗口中显示的正确结果
事实上我并不知道原因(手动狗头)。
最后代码如下:

	public struct ChannelInfo
    {
        /// <summary>
        /// 设备是否启用
        /// </summary>
        public int IsEnable { get; set; }
        /// <summary>
        /// 通道是否启用
        /// </summary>
        public bool  IsChannleEnable { get; set; }
        /// <summary>
        /// IP地址
        /// </summary>
        public string IPAddress { get; set; }
        public int CameraID { get; set; }
    }
    public List<ChannelInfo> NET_DVR_GetDVRConfig()
    {
        List<ChannelInfo> results =new  List<ChannelInfo>();

        CHCNetSDK.NET_DVR_IPPARACFG_V40 IPParacfg = new CHCNetSDK.NET_DVR_IPPARACFG_V40();
        uint dwOutBufferSize = (uint)Marshal.SizeOf(IPParacfg);
        IntPtr pOutBuf = Marshal.AllocHGlobal((int)dwOutBufferSize);
        uint lpBytesReturned = 0;
        int lChannel =0;
        CHCNetSDK.NET_DVR_GetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40, lChannel, pOutBuf, dwOutBufferSize, ref lpBytesReturned);
        lChannel = 1;
        if (!CHCNetSDK.NET_DVR_GetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40, lChannel, pOutBuf, dwOutBufferSize,ref lpBytesReturned))
        {
            IPParacfg = (CHCNetSDK.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(pOutBuf, typeof(CHCNetSDK.NET_DVR_IPPARACFG_V40));
            if (IPParacfg.dwGroupNum==1&&IPParacfg.dwDChanNum<=64&&IPParacfg.dwDChanNum>0)
            {
                NET_DVR_IPDEVINFO_V31[] IPDeviceInfos = IPParacfg.struIPDevInfo;
                for(int i=0;i< IPDeviceInfos.Length; i++)
                {
                    if (IPDeviceInfos[i].byEnable == 1)
                    {
                        ChannelInfo channelInfo = new ChannelInfo();
                        channelInfo.IPAddress = IPDeviceInfos[i].struIP.sIpV4;
                        channelInfo.IsEnable = IPDeviceInfos[i].byEnable;
                        results.Add(channelInfo);
                    }
                }
            }
        }
        return results;
    }
<think>我们面对的问题是如何从海康威视NVR获取视频流,并在获取的视频流上应用YOLO模型进行目标检测。整个过程可以分为两个主要步骤:1. 从海康威视NVR获取视频流;2. 将视频流送入YOLO模型进行目标检测。 ### 步骤一:从海康威视NVR获取视频流 海康威视设备通常支持多种方式获取视频流,包括RTSP、SDK等。这里我们介绍两种常用方法: #### 方法1:使用RTSP协议获取视频流 海康威视NVR的RTSP地址格式通常为: `rtsp://username:password@ip:port/Streaming/Channels/channel_id` 其中: - `username`: NVR登录用户名 - `password`: 密码 - `ip`: NVR的IP地址 - `port`: RTSP端口,默认为554 - `channel_id`: 通道号,例如`101`表示通道1的主码流,`102`表示通道1的子码流 示例RTSP地址:`rtsp://admin:[email protected]:554/Streaming/Channels/101` 在Python中,我们可以使用OpenCV来读取RTSP流: ```python import cv2 rtsp_url = "rtsp://admin:[email protected]:554/Streaming/Channels/101" cap = cv2.VideoCapture(rtsp_url) while True: ret, frame = cap.read() if not ret: break # 在这里可以对每一帧进行处理,例如显示 cv2.imshow('Video', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() ``` #### 方法2:使用海康威视SDK(更稳定,功能更全) 海康威视提供了SDK(软件开发工具包),可以通过其官方SDK获取视频流。这需要下载海康威视SDK并安装。 步骤: 1. 从海康威视官网下载SDK(例如,Windows版本为`HCNetSDK`)。 2. 将SDK中的库文件和头文件配置到开发环境中。 3. 使用SDK提供的函数进行设备登录、实时预览等操作。 以下是一个简化的示例(基于海康威视SDK的Python封装,通常使用ctypes调用): ```python import ctypes from ctypes import * # 加载SDK库 dll = cdll.LoadLibrary('./libhcnetsdk.so') # Linux下,Windows为hcnetsdk.dll # 初始化 dll.NET_DVR_Init() # 设置连超时等参数 dll.NET_DVR_SetConnectTime(2000, 1) dll.NET_DVR_SetReconnect(10000, True) # 设备登录信息 device_info = NET_DVR_DEVICEINFO_V30() ip = "192.168.1.100".encode('utf-8') username = "admin".encode('utf-8') password = "123456".encode('utf-8') # 登录设备 lUserID = dll.NET_DVR_Login_V30(ip, 8000, username, password, byref(device_info)) if lUserID < 0: print("Login failed, error code: ", dll.NET_DVR_GetLastError()) exit() # 开始实时预览 preview_info = NET_DVR_PREVIEWINFO() preview_info.hPlayWnd = 0 # 窗口句柄,如果没有窗口可设为0 preview_info.lChannel = 1 # 通道号 preview_info.dwStreamType = 0 # 主码流 preview_info.dwLinkMode = 0 # TCP模式 # 定义实时预览回调函数 RealDataCallBack_V30 = CFUNCTYPE(None, c_long, c_uint, POINTER(c_byte), c_uint, c_void_p) def fRealDataCallBack(lRealHandle, dwDataType, pBuffer, dwBufSize, pUser): # 在这里处理视频流数据(YUV或RGB) pass real_data_callback = RealDataCallBack_V30(fRealDataCallBack) # 开始预览 lRealPlayHandle = dll.NET_DVR_RealPlay_V30(lUserID, byref(preview_info), real_data_callback, None) if lRealPlayHandle < 0: print("Preview failed, error code: ", dll.NET_DVR_GetLastError()) dll.NET_DVR_Logout(lUserID) dll.NET_DVR_Cleanup() exit() # 保持程序运行,直到用户退出 input("Press Enter to stop...") # 停止预览,注销用户,清理资源 dll.NET_DVR_StopRealPlay(lRealPlayHandle) dll.NET_DVR_Logout(lUserID) dll.NET_DVR_Cleanup() ``` 注意:使用SDK方式需要处理视频流数据(通常是YUV数据),并将其转换为RGB格式以便后续使用OpenCV等库处理。 ### 步骤二:使用YOLO进行目标检测 在获取视频帧(RGB格式)后,我们可以使用YOLO模型进行目标检测。这里以YOLOv5为例。 1. 安装YOLOv5: ```bash pip install torch torchvision git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt ``` 2. 在代码中加载YOLOv5模型并进行检测: ```python import torch from yolov5.models.experimental import attempt_load from yolov5.utils.general import non_max_suppression # 加载模型 model = attempt_load('yolov5s.pt', map_location='cpu') # 使用CPU,如果有GPU可改为'cuda:0' # 获取视频流(以OpenCV为例) cap = cv2.VideoCapture(rtsp_url) # 或者使用SDK获取的帧 while cap.isOpened(): ret, frame = cap.read() if not ret: break # 将帧转换为YOLO输入格式 img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img = torch.from_numpy(img).permute(2,0,1).float().div(255.0).unsqueeze(0) # 推理 pred = model(img)[0] # 应用非极大值抑制 pred = non_max_suppression(pred, 0.25, 0.45) # 绘制检测结果 for det in pred[0]: if det is not None and len(det): # det: [x1, y1, x2, y2, conf, cls] x1, y1, x2, y2, conf, cls = det # 绘制矩形框和标签 cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0,255,0), 2) cv2.putText(frame, f'{model.names[int(cls)]} {conf:.2f}', (int(x1), int(y1)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,255,0), 2) cv2.imshow('YOLO Detection', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() ``` ### 整合两个步骤 将上述两个步骤整合起来,即从NVR获取视频流(使用RTSP或SDK),然后对每一帧应用YOLO检测。 注意: 1. 使用RTSP方式可能遇到延迟或断流问题,建议使用SDK方式更稳定。 2. 使用SDK获取的视频流数据需要转换为RGB格式(海SDK通常返回YUV数据,需要转换)。 3. YOLO模型的推理速度需要与视频帧率匹配,如果速度不够,可以考虑使用更小的模型(如YOLOv5s)或硬件加速。 ### 性能优化建议 - 使用多线程:一个线程负责获取视频流,另一个线程负责推理和显示,避免阻塞。 - 使用GPU加速YOLO推理。 - 调整视频流的分辨率和码率,降低解码压力。 ### 引用说明 本文参考了海康威视SDK开发文档和YOLOv5官方文档[^1][^2]。 §§相关问题§§ 1. 如何解决海康威视视频流获取中的延迟问题? 2. YOLO模型如何训练自定义数据集? 3. 除了YOLO,还有哪些目标检测模型适合实时视频分析? 4. 如何将目标检测结果实时推送到Web页面?</think>### 从海康威视NVR获取视频流并使用YOLO进行目标检测的完整方案 #### 一、技术流程概述 ```mermaid graph LR A[海康威视NVR] -->|RTSP/SDK| B[获取视频流] B --> C[视频帧解码] C --> D[YOLO目标检测] D --> E[结果可视化/存储] ``` #### 二、获取视频流的两种核心方法 1. **RTSP协议方式(推荐)** - 海康威视RTSP地址通用格式: $$rtsp://[username]:[password]@[ip]:[port]/Streaming/Channels/[channel_id]$$ - 通道号规则:`101`=通道1主码流,`102`=通道1子码流 - Python实现示例: ```python import cv2 # 配置RTSP地址(替换实际参数) rtsp_url = "rtsp://admin:[email protected]:554/Streaming/Channels/101" # 创建视频捕获对象 cap = cv2.VideoCapture(rtsp_url) while True: ret, frame = cap.read() if not ret: print("视频流中断") break # 此处插入YOLO处理代码 # processed_frame = yolo_detect(frame) cv2.imshow('NVR Stream', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() ``` 2. **海SDK方式(需官方库)** ```python from ctypes import * from hikvision.sdk import * # 需安装官方SDK # 初始化SDK NET_DVR_Init() device_info = NET_DVR_DEVICEINFO_V30() # 登录设备 user_id = NET_DVR_Login_V30("192.168.1.100", 8000, "admin", "password", byref(device_info)) # 设置回调函数收视频帧 @CFUNCTYPE(None, c_long, c_uint, POINTER(c_byte), c_uint, c_void_p) def real_data_callback(lRealHandle, dwDataType, pBuffer, dwBufSize, pUser): if dwDataType == NET_DVR_STREAMDATA: # 将pBuffer转换为numpy数组 frame = np.frombuffer(pBuffer[:dwBufSize], dtype=np.uint8) # 此处可送入YOLO处理 # 开始实时预览 preview_info = NET_DVR_PREVIEWINFO() preview_info.lChannel = 1 # 通道号 handle = NET_DVR_RealPlay_V30(user_id, byref(preview_info), real_data_callback, None) ``` #### 三、集成YOLO目标检测 1. **环境准备** ```bash pip install torch torchvision opencv-python git clone https://github.com/ultralytics/yolov5 # 官方YOLOv5 ``` 2. **检测代码集成** ```python import torch # 加载YOLO模型(选择预训练模型) model = torch.hub.load('ultralytics/yolov5', 'yolov5s') # yolov5n/s/m/l/x def yolo_detect(frame): # 执行推理 results = model(frame) # 解析结果 detections = results.pandas().xyxy[0] for _, row in detections.iterrows(): if row['confidence'] > 0.5: # 置信度阈值 x1, y1, x2, y2 = int(row['xmin']), int(row['ymin']), int(row['xmax']), int(row['ymax']) cv2.rectangle(frame, (x1,y1), (x2,y2), (0,255,0), 2) cv2.putText(frame, f"{row['name']} {row['confidence']:.2f}", (x1,y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,255,0), 2) return frame ``` #### 四、关键优化策略 1. **视频流优化** - 使用子码流(`102`通道)降低分辨率 - 设置OpenCV缓冲大小:`cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)` - 硬件加速解码:`cap.set(cv2.CAP_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY)` 2. **YOLO性能优化** ```python # 模型推理配置优化 model.conf = 0.5 # 置信度阈值 model.iou = 0.45 # IOU阈值 model.max_det = 50 # 最大检测数 # 使用半精度推理(GPU) model = model.half().to('cuda') ``` #### 五、完整工作流示例 ```python rtsp_url = "rtsp://admin:[email protected]:554/Streaming/Channels/102" cap = cv2.VideoCapture(rtsp_url) # 设置低延迟参数 cap.set(cv2.CAP_PROP_FPS, 15) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while cap.isOpened(): ret, frame = cap.read() if not ret: break # YOLO目标检测 results = model(frame) processed_frame = results.render()[0] # 自动渲染结果 cv2.imshow('AI Surveillance', processed_frame) if cv2.waitKey(1) == 27: break # ESC退出 cap.release() ``` > **注意事项** > 1. 需开启NVR的RTSP服务:NVR配置界面 → 网络 → 高级配置 → 集成协议 > 2. 首次使用SDK需注册海开发者账号获取SDK包 > 3. 工业场景建议使用YOLOv5s或YOLOv8n等轻量模型保证实时性 #### 六、故障排查指南 | 问题现象 | 解决方案 | |---------|---------| | 连超时 | 检查防火墙设置,开放554(RTSP)/8000(SDK)端口 | | 黑屏/花屏 | 降低分辨率,切换主/子码流,检查H.265支持 | | 高延迟 | 减少OpenCV的imshow调用频率,使用`cv2.IMREAD_UNCHANGED` | | 内存泄漏 | SDK方式需在循环中手动释放内存:`del frame` | ### 引用说明 本文实现方案参考海康威视SDK开发文档和YOLOv5官方文档[^1][^2]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值