海康威视(HikVision)在视频解决方案的地位毋庸置疑,起码属于国内业界顶尖水平。选择他家设备主要有两个原因:首要是因为他家产品贵,这确实是选择的首要原因(毕竟经费是……咳,打住);另一个重要原因是他的技术方案十分全面,包括技术支持、开发文档等。

在项目开发初期,一直使用 Python 开发、USB 摄像头调试,毕竟 Python 在机器学习有「先天」优势。然而把项目转移到 HikVision 的 IP 摄像头时,摄像头提供的 SDK 没有 Python 支持。虽然这不足为怪,但解决起来却比想象中要费劲。因此,记录下近期一些核心的学习资料,为后续回顾使用。

这份日记解决的问题,是把 SDK 从 C++ 迁移至 Python,并结合 OpenCV 进行二次开发。

准备环境

开始之前,先了解我使用的开发环境,部分型号或版本可能不是必要条件。名称版本 / 型号系统Windows10

硬件HikVision IP 摄像头DS-2DC4420IW-D

软件Python3.6+

OpenCV3.4+

设备网络 SDK_Win645.3+

Visual Studio2015

后续所有内容默认必要的开发环境已经完备,包括安装、配置、简单调试等。其中在 Visual Studio 上配置 OpenCV 的方法网上有很多参考文章,请自行检索。

解决方案

把 SDK 从 C++ 搬到 Python 需要解决两个主要问题,一个是从 IP 摄像头中获取图像(码流),另一个是对云台进行控制(角度、倍率等)。为了解决以上两个问题,一共尝试了三个方案,实现过程从简单到复杂,在此总结一下其中各自的利弊。

1. RTSP 协议获取图像

在选择 HikVision 之前也关注了这方面的支持。RTSP 是流媒体协议,可以很方便地通过 URL 获取码流。它的协议如下

// 说明:

// username:用户名,例如admin

// passwd:密码,例如12345

// ip:设备的ip地址,例如192.0.0.64

// port:端口号默认554,若为默认可以不写

// codec:有h264、MPEG-4、mpeg4这几种

// channel:通道号,起始为1

// subtype:码流类型,主码流为main,子码流为sub

rtsp://[username]:[passwd]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream

在 OpenCV 中,很简单就能读取 IP 摄像头。

import cv2

cam = cv2.VideoCapture("rtsp://[username]:[passwd]@[ip]:554/h264/ch1/sub/av_stream")

while True:

ret, frame = cam.read()

cv2.imshow("test", frame)

key = cv2.waitKey(100) & 0xff

if key == 27: # ESC

break

cam.release()

cv2.destroyAllWindows()

然而这么做存在一个很大的缺陷,即通过流媒体协议获得的码流没有办法满足实时要求,返回图像存在 3-5 秒延时,在实际项目中并不可行。另一方面,仅仅取得码流对于实际项目也并不足够,还需要想方设法对云台进行控制。于是,找到了下一种解决方案。

2. ctypes 调用 C 方法

Python 3 已经内置了ctypes模块,SDK 也提供了所有功能的 Demo,所以使用ctypes库进行 Python、C 混合开发应该最简单、直接不过了。

使用ctypes库,目的是直接调用 SDK 提供的若干动态链接库.dll的方法,也就省去了大量的编译操作。在这里,比较直接相关的文章很少,特别感谢两位博客作者的文章ctypes实现了摄像头登入、抓图、光学变倍等功能,也就意味着可以实现云台控制。

整个调用过程与 C++ 实现方式雷同,建议对照「设备网络SDK使用手册」使用。以「云台控制」为例,调用过程如下:

import os, ctypes

import cv2

# 遍历动态链接库目录

def add_dll(path, dll_list):

files = os.listdir(path)

for file in files:

if not os.path.isdir(path + file):

if file.endswith(".dll"):

dll_list.append(path + file)

else:

add_dll(path + file + "/", dll_list)

# 载入动态链接库

def callCpp(func_name, *args):

for so_lib in so_list:

try:

lib = ctypes.cdll.LoadLibrary(so_lib)

try:

value = eval("lib.%s" % func_name)(*args)

# print("调用的库:" + so_lib)

# print("执行成功,返回值:" + str(value))

return value

except:

continue

except:

print("库文件载入失败:" + so_lib)

continue

print("没有找到接口!")

return False

# 云台控制操作

def NET_DVR_PTZControl_Other(lUserID, lChannel, dwPTZCommand, dwStop):

res = callCpp("NET_DVR_PTZControl_Other", lUserID, lChannel, dwPTZCommand, dwStop)

if res:

print("控制成功")

else:

print("控制失败: " + str(callCpp("NET_DVR_GetLastError")))

与使用手册对比,调用的过程还是很直接明了的:填入库方法名,通过callCpp函数实现调用。

如果涉及结构体,只需定义继承自ctypes.Structure的类即可。以「设备抓图」为例:

# 抓图数据结构体

class NET_DVR_JPEGPARA(ctypes.Structure):

_fields_ = [

("wPicSize", ctypes.c_ushort), # WORD

("wPicQuality", ctypes.c_ushort)] # WORD

# jpeg 抓图

# hPlayWnd 显示窗口可以为 none;存在缺点采集图片速度慢

def NET_DVR_CaptureJPEGPicture():

sJpegPicFileName = bytes("pytest.jpg", "ascii")

lpJpegPara = NET_DVR_JPEGPARA()

lpJpegPara.wPicSize = 2

lpJpegPara.wPicQuality = 1

res = callCpp("NET_DVR_CaptureJPEGPicture", lUserID, lChannel, ctypes.byref(lpJpegPara), sJpegPicFileName)

if res == False:

error_info = callCpp("NET_DVR_GetLastError")

print("抓图失败:" + str(error_info))

else:

print("抓图成功")

「云台控制」实现算是满足了,然而「实时预览」却不那么容易解决。如参考文章提到,使用「设备抓图」来获取图像实现的速度稍慢,效果不理想;而要实现「实时预览」功能,则需要使用ctypes处理函数回调。虽然理论上可行,但在直接调用 SDK 的「实时预览」相关方法时却始终无法实现,可能是传递的数据原因,也可能不是,反正最终依然无法解决。因此,又再考虑了另外一种备选方案。

3. swig 封装库

既然已经到走投无路的阶段,只能考虑利用 C++ 实现功能,再自行封装 Python 库了。这种实现方案确实很费劲,操作十分繁琐,但毕竟 SDK 有给出 C++ 的实现,算是最靠谱的方案,所以万不得已的我尝试了这种解决方案。要在 Windows 操作系统下完成封装,能够找到最相关的参考文章似乎只有一篇安装 Swig。Swig 用于封装库,在 Windows 系统下,点击下载对应的「swigwin」版本,解压后将目录添加到系统「环境变量」。

下载 OpenCV-swig 接口文件。该文件用于预编译 OpenCV 相关函数,是一系列.i后缀的文件。点击下载并解压。

将上述接口文件中 lib 文件夹的所有文件拷贝到项目所在目录,并与三个源文件放置在一起。(注:源文件包括HKIPcamera.cpp、HKIPcamera.h和HKIPcamera.i,请回顾出处原文。代码基本与原文一致,需要新增功能也在HKIPcamera.cpp中实现,所以不在此展示。)

通过命令行使用 swig 生成HKIPcamera_wrap.cxx文件。cd到HKIPcamera.i源文件文件夹下,并修改 OpenCV 路径。如:

E:

cd OpenCV Project\HKIPCamera\HKIPCamera

swig -I"D:\Open CV\opencv\build\include" -python -c++ HKIPCamera.i

修改plaympeg4.h文件。这一问题在原文章中有所提及:在extern "C" __declspec(dllexport)的"C"和__之间需要增加空格,否则会导致编译报错。

下载 boost 库。boost 库提供了一系列扩展的 C++ 方法,文件稍大。点击下载(Windows 平台),并将其头文件和库文件添加到项目中。如:

// 头文件目录

D:\Boost\boost_1_68_0

// 库文件目录

D:\Boost\boost_1_68_0\libs

编译动态链接库。参考 Windows 下使用 Swig 的一篇文章这里生成动态链接库.dll需要另外创建一个新的「Win32 Console Application」工程,且反选「生命周期(SDL)检查」,否则会导致编译失败。

在「属性管理器」添加 Python 头文件目录和库目录。再将HKIPcamera.h文件添加到头文件、HKIPcamera_wrap.cxx和HKIPcamera.cpp添加到源文件 、HKIPcamera.i 添加到工程目录下,进行编译。

将生成的.dll文件改名为_HKIPcamera.pyd,并与HKIPcamera.py放置在同一文件目录下,即可在 Python 中引用。

这里复杂的地方在于,需要配置的环境很多,而且步骤 1-4 属于封装过程,获得.py和.cxx文件;步骤 5-7 属于编译过程,获得.dll文件。目前两个过程需要分别在两个工程项目中完成。

理论上,这一解决方案能够同时解决以上两个主要问题,所以该问题的学习过程算是到此结束了。

总结

RTSP 方案基本满足不了项目要求,因此不作考虑。如果项目中不需要「实时预览」图像回调,使用ctypes就能够满足需求;但如果需要结合图像作二次开发,最终还是需要自行封装库文件来实现 Python 内引用。自行封装的过程略微繁杂,但理清思路以后就只需要在 C++ 实现功能,尚属「一劳永逸」。当然,图像回调功能自行封装实现、云台控制使用ctypes实现也完全可行,不存在明显的局限。

至此,「把 SDK 从 C++ 迁移至 Python,并结合 OpenCV 进行二次开发」算是顺利得到解答,这篇日记的目的也达到了。

说明

本日记中省略了许多配置上的细节,其中有几点容易忽视,在此稍作说明。调试 SDK 时,原有的动态链接库文件需要全部拷贝到系统环境中,与 SDK「说明事项」一致,「HCNetSDKCom 文件夹名不能修改」。

工程项目中新建「属性表」并使用相对路径把 SDK 头文件和库文件引入,可以省去每次重复配置的麻烦。

由于 wrapper 文件使用了Python.h,因此同样需要把 Python 头文件目录和库目录添加到工程项目中,与步骤 7 描述一致。

封装和编译两个过程目前需要分别在两个工程项目中完成。

由于 Python 只能接收Mat类型,原文DecCBFun部分可以改写为:

void CALLBACK DecCBFun(long nPort, char * pBuf, long nSize, FRAME_INFO * pFrameInfo, long nReserved1, long nReserved2)

{

long lFrameType = pFrameInfo->nType;

if (lFrameType == T_YV12)

{

if (g_BGRImage.empty())

{

g_BGRImage.create(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3);

}

Mat YUVImage(pFrameInfo->nHeight + pFrameInfo->nHeight / 2, pFrameInfo->nWidth, CV_8UC1, (unsigned char*)pBuf);

cvtColor(YUVImage, g_BGRImage, COLOR_YUV2BGR_YV12);

EnterCriticalSection(&g_cs_frameList);

g_frameList.push_back(g_BGRImage);

LeaveCriticalSection(&g_cs_frameList);

}

}

如有问题,欢迎留言或邮件咨询修改于 June 23, 2019 21:36:45 (1 年前)

已有 26 条评论zzt

楼主你好,我在修改解码回调部分代码的时候显示“g_BGRImage是未定义的标识符”,请问这个问题要怎么解决?感激不尽!!!

皮几万

已经到 第七步了,python的头文件和库文件 指的是什么文件呢

添加新评论 ▼称呼

邮箱

网站

提交评论© 2016 - 2020 RYAN.

python调用海康威视sdk库_HikVision SDK: C++ 至 Python相关推荐

  1. python调用c++动态库 linux_linux中使用boost.python调用c++动态库的方法

    前言 最近开始使用 robot framework 测试c++的动态库,robot framework 是跑在 windows 上面,c++动态库是跑在远程linux主机上面.测试办法是让 robot ...

  2. python调用.net动态库

    # python调用.net动态库 ### pythonnet简介 ----------------------------- - pythonnet是cpython的扩展 - pythonnet提供 ...

  3. python调用C函数库

    python调用C函数库 (2012-10-31 13:47:50) 转载▼ 标签: 动态链接库 c语言 so ctypes python 分类:Python 背景:工作中,有很多公共类库是使用C语言 ...

  4. 通过python调用海康威视工业摄像头并进行图像存储,同时使用opencv实时图像显示(数据流问题已解决)

    通过python调用海康威视工业摄像头并进行图像存储,同时使用opencv实时图像显示. 1:图像存储方式 先说情况,本人是做视觉检测的需要高倍率摄像头进行实时检测,也就是需要深度学习进行图片数据处理 ...

  5. python调用c++动态库

    python调用C++动态库 生成C++动态库 1.编译成64位的dll库 2. C++ 模板 3. 示例 Python调用带参数的动态库 python与c数据类型 int.long.float.do ...

  6. Python调用C++ DLL库 ------OSError: [WinError 126] 找不到指定的模块。

    Python调用C++ DLL库 解决Python中 OSError: [WinError 126] 找不到指定的模块 的问题. 一.问题:   在进行Python开发的过程中,很可能遇到调用C++ ...

  7. windows下python调用海康威视网络摄像头sdk

    本文参考以下博文加自己的实践,发现有些步骤是不必要的,例如不需要为opencv等第三方库指定路径 运行环境: 准备工作 1.海康SDK下载 2.下载安装vcpkg 3.安装Swig 4.下载OpenC ...

  8. Python调用海康威视网络相机之——python调用海康威视C++的SDK

    运行环境: Win10系统,64位,Anaconda3 python 3.5.5(基于anaconda环境) opencv 3.4.2 (早前就已经安装了,本文不会讲如何安装) Visual Stud ...

  9. python调用c#dll_详解Python 调用C# dll库最简方法

    1.为什么要跨平台编程?双平台编程或多平台编程,只是为提供更好开发更兼容的解决方案的一种手段,编程时服务于产品和客户的,也是因地制宜. 先安装python所需的库clr ,我这里已经安装了,可以去对应 ...

最新文章

  1. Apache 访问权限修改
  2. 【密码学02】密码系统原理及数学背景
  3. GAN处理手写图片数据集
  4. pfSense book之静态路由
  5. Android之AsyncTask两种线程池分析和总结
  6. java sort排序
  7. 各种一维卷积(Full卷积、Same卷积、Valid卷积、带深度的一维卷积)
  8. RN-android 打包后,部分图片不显示
  9. Struts2的输入验证(三)-短路验证与非字段验证
  10. python学习------面向对象进阶
  11. 第三季-第6课-静态函数库设计
  12. java array to list iterator_Iterator to list的三种方法
  13. NOD32企业内部更新服务器搭建
  14. Kali Linux 暴力破解 Excel密码
  15. 日语入门难?学日语最好用的工具——早道五十音图
  16. 第一篇:初识信息系统监理工程师
  17. ios11对比android8.0,谁的设计更好?iOS11正式版多图详尽对比安卓8.0
  18. EMC电磁兼容1:EMC、EMI、EMS是什么?它们之间有什么关系?
  19. 计算机报名怎么老是密码错误,中考报名显示密码错误 中考网上报名说我密码错误怎么办...
  20. 安装win7和Ubuntu双系统后,win7耳机没声音,外放有声音

热门文章

  1. WebGL学习笔记(基础知识篇)
  2. 哪种耳机不损伤听力、佩戴不入耳的骨传导蓝牙耳机
  3. python可以写dnf外挂么_只想写游戏辅助 比如绝地求生 Dnf的 需要学会什么语言呢 C C++可以嚒?...
  4. common-lang的StringUtils工具类说明
  5. WebView 截长图
  6. 【PCB专题】如何在嘉立创8月1日起的新规则下免费打样
  7. mysql 删除数据库的所有表_科学网—mysql删除数据库中的所有表 - 高雪峰的博文...
  8. 点评三星Smart TV智能电视
  9. 【福利】哈佛大学公开课:构建动态网站
  10. 英特尔终于将迈进10nm大门