600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > windows下python调用海康威视网络摄像头sdk

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

时间:2021-02-14 20:24:46

相关推荐

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

本文参考以下博文加自己的实践,发现有些步骤是不必要的,例如不需要为opencv等第三方库指定路径

运行环境:

准备工作

1、海康SDK下载

2、下载安装vcpkg

3、安装Swig

4、下载OpenCV-swig接口文件

实现方案

1. 使用swig编译生成python和c++数据交换需要的.py和.cxx文件

HKIPcamera.i

HKIPcamera.h

HKIPcamera.cpp

2. 修改海康SDK下的plaympeg4.h文件

3、用VS编译生成动态链接库文件

将该库给别人使用

本文参考以下博文加自己的实践,发现有些步骤是不必要的,例如不需要为opencv等第三方库指定路径

/c1052/article/details/95082377

/archives/hikvision/comment-page-2#comments

/GottaYiWanLiu/article/details/106187962

运行环境:

Win10系统,64位,Anaconda3

python 3.7.9(基于anaconda环境)

vcpkg(boost,opencv3)

Visual Studio

硬件:DS-2CD3T56DWD-I5

相机SDK: 设备网络SDK_V6.1.4.42(for Windows x64)

准备工作

1、海康SDK下载

下载地址:/cn/download_61.html

选择自己对应的系统平台版本,我这边选的是设备网络SDK_Win64 :CH-HCNetSDKV6.1.4.42_build2027_win64

该文件夹下主要是头文件和库文件。

2、下载安装vcpkg

vcpkg如何安装请参考别的博客。安装完以后,命令行cd至vcpkg根目录,然后命令行输入

./vcpkg install boost:x64-windows

./vcpkg install opencv3:x64-windows

1

2

即可安装boost和opencv3。

3、安装Swig

Swig是用来封装库的,下载链接:/download.html

我安装的版本是swigwin-4.0.2:/swig/swigwin-4.0.2.zip

然后将安装目录添加至环境变量path

4、下载OpenCV-swig接口文件

下载地址:/renatoGarcia/opencv-swig

我们主要会用到其目录下lib文件夹中的文件opencv文件夹和opencv.i接口文件

实现方案

1. 使用swig编译生成python和c++数据交换需要的.py和.cxx文件

新建一个文件夹,例如HicVision_python_SDK文件夹。将下载的opencv-swig\lib下的opencv.i和opencv文件夹放入新建的HicVision_python_SDK文件夹中。

复制以下三个文件,到新建的HicVision_python_SDK文件夹中。注意代码中的字符串不要出现中文即可避免编码问题。

HKIPcamera.i

/* Example of wrapping a C function that takes a C double array as input using

* numpy typemaps for SWIG. */

%module HKIPcamera

%include <opencv/mat.i>

%cv_mat__instantiate_defaults

%header %{

/* Includes the header in the wrapper code */

#include "HKIPcamera.h"

%}

%include "HKIPcamera.h"

1

2

3

4

5

6

7

8

9

10

11

HKIPcamera.h

#include <opencv2/opencv.hpp>

using namespace cv;

void init(char* ip, char* usr, char* password);

Mat getframe();

void release();

1

2

3

4

5

6

HKIPcamera.cpp

#include <opencv\cv.h>

#include <opencv\highgui.h>

#include <opencv2\opencv.hpp>

#include <iostream>

#include <time.h>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <windows.h>

#include "HCNetSDK.h"

#include "plaympeg4.h"

#define USECOLOR 1

using namespace cv;

using namespace std;

//--------------------------------------------

int iPicNum = 0;//Set channel NO.

LONG nPort = -1;

HWND hWnd = NULL;

CRITICAL_SECTION g_cs_frameList;

list<Mat> g_frameList;

LONG lUserID;

NET_DVR_DEVICEINFO_V30 struDeviceInfo;

HANDLE hThread;

LONG lRealPlayHandle = -1;

void yv12toYUV(char *outYuv, char *inYv12, int width, int height, int widthStep)

{

int col, row;

unsigned int Y, U, V;

int tmp;

int idx;

for (row = 0; row < height; row++)

{

idx = row * widthStep;

int rowptr = row * width;

for (col = 0; col < width; col++)

{

tmp = (row / 2)*(width / 2) + (col / 2);

Y = (unsigned int)inYv12[row*width + col];

U = (unsigned int)inYv12[width*height + width * height / 4 + tmp];

V = (unsigned int)inYv12[width*height + tmp];

outYuv[idx + col * 3] = Y;

outYuv[idx + col * 3 + 1] = U;

outYuv[idx + col * 3 + 2] = V;

}

}

}

//解码回调 视频为YUV数据(YV12),音频为PCM数据

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 USECOLOR

//int start = clock();

static IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 3);//得到图像的Y分量

yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth, pFrameInfo->nHeight, pImgYCrCb->widthStep);//得到全部RGB图像

static IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 3);

cvCvtColor(pImgYCrCb, pImg, CV_YCrCb2RGB);

//int end = clock();

#else

static IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 1);

memcpy(pImg->imageData, pBuf, pFrameInfo->nWidth*pFrameInfo->nHeight);

#endif

EnterCriticalSection(&g_cs_frameList);

//g_frameList.push_back(pImg);

g_frameList.push_back(cv::cvarrToMat(pImg));

LeaveCriticalSection(&g_cs_frameList);

}

///实时流回调

void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser)

{

DWORD dRet;

switch (dwDataType)

{

case NET_DVR_SYSHEAD: //系统头

if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号

{

break;

}

if (dwBufSize > 0)

{

if (!PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 1024 * 1024))

{

dRet = PlayM4_GetLastError(nPort);

break;

}

//设置解码回调函数 只解码不显示

if (!PlayM4_SetDecCallBack(nPort, DecCBFun))

{

dRet = PlayM4_GetLastError(nPort);

break;

}

//打开视频解码

if (!PlayM4_Play(nPort, hWnd))

{

dRet = PlayM4_GetLastError(nPort);

break;

}

}

break;

case NET_DVR_STREAMDATA: //码流数据

if (dwBufSize > 0 && nPort != -1)

{

BOOL inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);

while (!inData)

{

Sleep(10);

inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);

OutputDebugString(L"PlayM4_InputData failed \n");

}

}

break;

}

}

void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)

{

char tempbuf[256] = { 0 };

switch (dwType)

{

case EXCEPTION_RECONNECT: //预览时重连

printf("----------reconnect--------%d\n", time(NULL));

break;

default:

break;

}

}

bool OpenCamera(char* ip, char* usr, char* password)

{

lUserID = NET_DVR_Login_V30(ip, 8000, usr, password, &struDeviceInfo);

if (lUserID == 0)

{

cout << "Log in success!" << endl;

return TRUE;

}

else

{

printf("Login error, %d\n", NET_DVR_GetLastError());

NET_DVR_Cleanup();

return FALSE;

}

}

DWORD WINAPI ReadCamera(LPVOID IpParameter)

{

//---------------------------------------

//设置异常消息回调函数

NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL);

//cvNamedWindow("Mywindow", 0);

//cvNamedWindow("IPCamera", 0);

//HWND h = (HWND)cvGetWindowHandle("Mywindow");

//h = cvNamedWindow("IPCamera");

//---------------------------------------

//启动预览并设置回调数据流

NET_DVR_CLIENTINFO ClientInfo;

ClientInfo.lChannel = 1; //Channel number 设备通道号

ClientInfo.hPlayWnd = NULL; //窗口为空,设备SDK不解码只取流

ClientInfo.lLinkMode = 1; //Main Stream

ClientInfo.sMultiCastIP = NULL;

LONG lRealPlayHandle;

lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, fRealDataCallBack, NULL, TRUE);

if (lRealPlayHandle < 0)

{

printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n", NET_DVR_GetLastError());

return -1;

}

else

cout << "Call NET_DVR_RealPlay_V30 successful!" << endl;

Sleep(-1);

if (!NET_DVR_StopRealPlay(lRealPlayHandle))

{

printf("NET_DVR_StopRealPlay error! Error number: %d\n", NET_DVR_GetLastError());

return 0;

}

NET_DVR_Logout(lUserID);

NET_DVR_Cleanup();

return 0;

}

void init(char* ip, char* usr, char* password) {

//HANDLE hThread;

//LPDWORD threadID;

//---------------------------------------

// 初始化

NET_DVR_Init();

//设置连接时间与重连时间

NET_DVR_SetConnectTime(2000, 1);

NET_DVR_SetReconnect(10000, true);

OpenCamera(ip, usr, password);

InitializeCriticalSection(&g_cs_frameList);

hThread = ::CreateThread(NULL, 0, ReadCamera, NULL, 0, 0);

}

Mat getframe() {

Mat frame1;

EnterCriticalSection(&g_cs_frameList);

while (!g_frameList.size()) {

LeaveCriticalSection(&g_cs_frameList);

EnterCriticalSection(&g_cs_frameList);

}

list<Mat>::iterator it;

it = g_frameList.end();

it--;

Mat dbgframe = (*(it));

(*g_frameList.begin()).copyTo(frame1);

frame1 = dbgframe;

g_frameList.pop_front();

//imshow("camera", frame1);

//waitKey(1);

g_frameList.clear(); // 丢掉旧的帧

LeaveCriticalSection(&g_cs_frameList);

return(frame1);

}

void release() {

::CloseHandle(hThread);

NET_DVR_StopRealPlay(lRealPlayHandle);

//关闭预览

NET_DVR_Logout(lUserID);

//注销用户

NET_DVR_Cleanup();

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

这样HicVision_python_SDK文件夹下就拥有上图红框的所有文件了。然后使用cmd或者powershell,cd到这个路径,执行

swig -ID:\vcpkg\installed\x64-windows\include -python -c++ HKIPcamera.i

1

注意将其中的D:\vcpkg修改为自己的vcpkg安装目录。

执行之后将在该目录生成HKIPcamera.py和HKIPcamera_wrap.cxx。

2. 修改海康SDK下的plaympeg4.h文件

这里直接参考/c1052/article/details/95082377所描述即可:

3、用VS编译生成动态链接库文件

首先创建空C++项目,并且项目命名为HKIPcamera

然后将之前文件夹下的三个文件放入项目中:

修改上面的编译选项为Release和x64

右键项目属性,切换选项卡为Release和x64,修改配置类型为动态库(.dll)

项目下添加3rdparty文件夹,在里面添加海康威视sdk的头文件和库文件:

取消安全周期检查:

VC++目录->包含目录中添加如下头文件路径(修改python目录到你自己的):

注意使用了vcpkg之后,就不需要添加使用vcpkg安装的opencv等库的头文件和.lib了。

3rdparty\include

D:\ProgramData\Anaconda3\envs\dust37\Lib\site-packages\numpy\core\include

D:\ProgramData\Anaconda3\envs\dust37\include

1

2

3

VC++目录->库目录中添加如下库的路径:(修改python目录到你自己的)

D:\ProgramData\Anaconda3\envs\dust37\libs

3rdparty\lib

3rdparty\lib\HCNetSDKCom

1

2

3

预处理器->预处理器定义中内容如下:

WIN32

NDEBUG

_CONSULE

_CRT_SECURE_NO_WARNINGS

1

2

3

4

链接器->输入->附加依赖项中添加:

HCNetSDK.lib

GdiPlus.lib

HCAlarm.lib

HCCore.lib

HCGeneralCfgMgr.lib

HCPreview.lib

PlayCtrl.lib

注意使用了vcpkg之后,就不需要添加使用vcpkg安装的opencv等库的头文件和.lib了。

完成以上步骤后,右键工程项目名选择生成,之后会在工程x64文件夹下的Release文件夹下生成.dll和.lib文件如下(红色)

复制一份 HKIPcamera.dll 文件并重命名为 _HKIPcamera.pyd到该目录下,并将海康SDK中的3rdparty\lib下的库文件都复制到该目录),以及将上文中用swig生成的HKIPcamera.py 也复制过来(如上图蓝色)

最后编写了个test.py也放在上图目录下,其内容如下(主要用来检测是否编译成功了):

import HKIPcamera

import time

import numpy as np

import matplotlib.pyplot as plt

import cv2

ip = str('10.167.93.111') # 摄像头IP地址,要和本机IP在同一局域网

name = str('admin') # 管理员用户名

pw = str('abcd1234') # 管理员密码

HKIPcamera.init(ip, name, pw)

# HKIPcamera.getfram()

#for i in range(100):

while(True):

t = time.time()

fram = HKIPcamera.getframe()

t2 = time.time()

cv2.imshow('123', np.array(fram))

cv2.waitKey(1)

print(t2-t)

time.sleep(0.1)

HKIPcamera.release()

time.sleep(5)

HKIPcamera.init(ip, name, pw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

在anaconda的prompt控制台下运行该test.py,会看到python调用SDK的实时画面,其延迟性同网页预览版差不多。但比rtsp流读取的效果好很多~

至此成功!

将该库给别人使用

经过测试,该库给别人使用的唯一条件是目标计算机使用的python版本需要与编译时的python版本完全一致,而不需要在指定目录下安装opencv等库。

因此放上我个人编译的版本。注意需要使用Python 3.7.9运行。运行时修改test.py中的8-10行为你自己的ip,name和pd

ip = str('10.167.93.111') # 摄像头IP地址,要和本机IP在同一局域网

name = str('admin') # 管理员用户名

pw = str('abcd1234') # 管理员密码

1

2

3

然后使用

python test.py

1

即可运行。

————————————————

版权声明:本文为CSDN博主「张小小恩」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:/ylzf/article/details/109247587

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。