资讯专栏INFORMATION COLUMN

Python调用海康威视网络相机C++的SDK

csRyan / 2538人阅读

摘要:调用海康威视网络相机的本文参考笔者将此文章中遗漏或未遇见的问题归纳总结,并分享自己在运行过程中遇到的问题,与君共勉。其次,将海康威视文件夹中文件夹下所有文件复制到文件夹下。

Python调用海康威视网络相机C++的SDK

本文参考:https://blog.csdn.net/c20081052/article/details/95082377 笔者将此文章中遗漏或未遇见的问题归纳总结,并分享自己在运行过程中遇到的问题,与君共勉。


一、运行环境

Win10系统 (64位)

Python3.7 (若是有用Python2.x版本的童鞋,尽量升级Python版本。在实验过程中,有其他童鞋由于Python版本问题,无法读取Python库)

Opencv3_4_2 、Visual Studio 2015(尽量使用同一版本)

海康硬件IDS-2DC7S420MW-A

海康SDK:CH-HCNetSDKV6.1.6.45_build20210302_win64


二、相关下载

建议在D盘或者E盘新建文件夹 ,名字为:App_install 。

1、海康SDK下载(文末有百度网盘,可自提)

下载地址:https://open.hikvision.com/download/5cda567cf47ae80dd41a54b3?type=10

选择自己对应的系统版本,笔者选的是设备网络SDK_Win64。

将其解压,主要会用到里面的头文件与库文件。将其汉语名称头文件改为include、库文件改为lib。

2、安装Opencv(文末有百度网盘,可自提)

笔者安装的是Opencv3_4_2。

在官网上下载3.4.2版本,双击即可解压。建议放到App_install文件夹,解压后将其bin路径添加到系统环境变量path下。

3、安装Swigwin(文末有百度网盘,可自提)

Swigwin是用来封装库的。

下载链接:http://www.swig.org/index.php

笔者选择的是3.0.12这个版本(本人之前选择的是最新版本,但是由于不明确的错误问题,还是按引用文章的版本安装),将其安装并解压到App_install目录下。

将此文件名路径添加到系统环境变量path中。

4、下载boost库(文末有百度网盘,可自提)

下载地址:https://www.boost.org/users/history/

笔者选择的是 boost_1_70_0.zip (因为本文主要是将win10环境下的), 将其解压到待会工程需要用的路径下即可;此处还是先解压到App_install文件夹下,待会会将解压后的文件夹拷贝到后面要用的路径下。

5、下载OpenCV-swig接口文件(文末有百度网盘,可自提)

下载地址:https://github.com/renatoGarcia/opencv-swig 将其下载并解压到App_install文件夹下。

需要用到其目录下lib文件夹中的文件opencv和opencv.i接口文件。

至此,前期准备工作搞定。App_install文件夹下的文件如下图:


三、实现步骤

1、使用swigwin编译生成Python和C++数据交换 的 .py和.cxx文件

复制以下三个文件(注意不要更改文件名),保存到同一文件夹下。笔者均将文件都放在新建文件夹 HicVision_python_SDK (建议名字一样)

HKIPcamera.h

#include using namespace cv;void init(char* ip, char* usr, char* password);Mat getframe();void release();

HKIPcamera.cpp

#include #include #include #include #include #include #include #include #include #include "HCNetSDK.h"#include "plaympeg4.h"#define USECOLOR 1using 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 << "码流回调成功!" << 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();}

HKIPcamera.i(若此文件不明白如何写的,可以多复制一份下文的opencv.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"

将第二步相关下载中的opencv-swig-master/lib下的opencv文件夹和opencv.i 这两个文件复制到 HicVision_python_SDK文件夹下。

将解压的boost_1_70_0文件夹也一并拷贝到这个目录下。

将App_install/opencv3_4_2/build/include中opencv2文件夹复制到HicVision_python_SDK文件夹下。(注:此处与之前博主不同,是因为笔者在生成.py与.cxx文件时报错,将此文件复制后,运行成功)

然后打开cmd,切到HicVision_python_SDK 这个文件夹下。

举例:本人HicVision_python_SDK 文件夹在D盘下。win+r,输入cmd,回车;输入d:,转到D盘,输入cd+空格+文件名 转到文件夹下。

然后输入指令

E:/Win32-MFC-Projects/HicVision_python_SDK>swig -IE:/App_install/opencv3_4_2/opencv/build/include -python -c++ HKIPcamera.i

指定你opencv安装的头文件路径,会生成上图所示的HKIPcamera_wrap.cxxHKIPcamera.py 两个文件(蓝色方框文件)。

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

该文件在App_install / CH-HCNetSDKV6.0.2.35_build20190411_Win64 / include 目录下:

第五行,extern “C” __declspec(dllexport)的"C"和____之间需要增加空格,否则会导致编译报错。如下:

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

新建win32控制台应用 工程,选择"DLL",“空项目”;取消选择"安全开发生命周期(SDL)检测"。若为Visual Studio2019版,请自行在属性页中更改。

应用程序设置页参考如下:

在资源方案管理器页将如下图所示的文件导入,即将上文提到的生成的文件拷贝到项目中(笔者起名为HKIPcamera项目名,建议一致)

编译平台是release x64下的,因此将配置该平台环境的属性页,点击 视图->属性页


其中 VC++目录->包含目录中添加如下头文件路径:(请根据实际安装位置补全其全路径名称,笔者省去了有些安装路径名)

C:/Python3.7/includeC:/Python3.7/Lib/site-packages/numpy/core/include(以下类似)HicVision_python_SDK/boost_1_70_0CH-HCNetSDKV6.0.2.35_build20190411_Win64/includeopencv3_4_2/opencv/build/include/opencv2opencv3_4_2/opencv/build/include/opencvopencv3_4_2/opencv/build/include

VC++目录->库目录中添加如下库的路径:(自行补全实际安装路径名)

C:/Python3.7/libsHicVision_python_SDK/boost_1_70_0/libsCH-HCNetSDKV6.0.2.35_build20190411_Win64/libCH-HCNetSDKV6.0.2.35_build20190411_Win64/lib/HCNetSDKComopencv3_4_2/opencv/build/x64/vc14/lib

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

WIN32NDEBUG_CONSULE_CRT_SECURE_NO_WARNINGS

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

opencv_world342.lib  (release下是这个,debug下需要改为opencv_world342d.lib)HCNetSDK.libGdiPlus.libHCAlarm.libHCCore.libHCGeneralCfgMgr.libHCPreview.libPlayCtrl.lib

在通用属性->常规->字符集中选择使用多字节字符集

在C/C+±>代码生成->运行库选的是多线程DLL(/MD)

Python3.7中 include文件夹下:object.h 注释掉第56行

​ pyconfig.h 注释掉第330~332行


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

若生成成功 将注释掉的行数 恢复原样(不恢复貌似也没问题)。

在生成 HKIPcamera.dll文件与HKIPcamera.lib文件之后,复制两份 HKIPcamera.dll 文件,

其中一份重命名为 _HKIPcamera.pyd (注意文件名前面 _ ) 到 HicVision_python_SDK目录下,并将海康SDK中的 HCNetSDKCom 文件夹拷贝过来

以及将上文中用swig生成的HKIPcamera.py 也复制到HicVision_python_SDK文件夹下。

将 _HKIPcamera.pyd文件,包含目录路径,添加到系统环境变量Path中,并将 _HKIPcamera.pyd所在文件夹目录,也添加到系统环境变量目录中。如下:

4、遇到问题

生成时遇到未定义问题,可以先查看本文引用文章,后面关于此问题解法。若仍无法解决,可能是C++版本问题,下载DirectX修复工具,修复Visual Studio后,再进行生成操作。

DirectX下载地址:https://blog.csdn.net/vbcom/article/details/6962388

下载后解压,点击

允许其更改电脑;出来界面后,点击工具-> 选项->扩展->开始扩展

扩展完成后,进入首页,点击检测并修复,若无问题,退出。

若有其他问题,请查看DirectX官网解决方法。


四、测试

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

import HKIPcameraimport timeimport numpy as npimport matplotlib.pyplot as pltimport cv2ip = 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)

笔者未一次成功,报错DLL找不到指定模块。

究其原因,是找不到.dll文件,故将所有链接的.dll文件移到.pyd同文件夹下。

首先,将此文件夹下文件全部复制到.pyd文件夹下,其中.dll文件会重复,跳过或者覆盖均可。

其次,将海康威视文件夹中lib文件夹下所有文件复制到.pyd文件夹下。

进行完上述操作后,多数人运行test均成功,但笔者依旧报错dll找不到指定模板。

不能放弃呀。

笔者又编写测试test1代码,目的是查看_HKIPcamera.pyd是否正常

import _HKIPcameraprint(dir(_HKIPcamera))print(help(_HKIPcamera))

不失所望,它依旧运行不出来。

下载depends(后文有网盘链接可自行下载),运行其应用程序,将_HKIPcamera.pyd拖到其界面,系统自动分析,分析过后出现找不到文件的情况。

寻找其主要原因。笔者这边主要是找不到三个.dll文件:分别是python37.dll,opencv_WORLD342.dll,VCRUNTIME140_1.dll。在我的电脑中,搜索这三个文件,将其复制到.pyd同目录文件中。

若是你缺少与笔者不同的.dll文件,按照与笔者相同的方法即可。

然后重启电脑,打开test1。它就成功了~~


本文中用到的文件:

Swigwin-3.0.12:链接:https://pan.baidu.com/s/1VK_Pb7VcbwVxwwJzKDWuhA 提取码:g3mo

Opencv-swig-master:链接:https://pan.baidu.com/s/1qAa2P4040AROx_a16XZ63Q 提取码:vnw0

boost_1_70_0:链接:https://pan.baidu.com/s/17i4cutVICiiFRy-UEqiCyw 提取码:jgb2

海康威视SDK软件包:链接:https://pan.baidu.com/s/1vMV1bk4EfDrEzJLTweCRzg 提取码:xhwc

Visual Studio2015(64):链接:https://pan.baidu.com/s/1FvxGZWW19I7rIgBuo1itSQ 提取码:noby

DirectX_Repair:链接:https://pan.baidu.com/s/1iNnb6YzJGqCUKxOTCJP_-g 提取码:qruk

depends(汉化版):链接:https://pan.baidu.com/s/1xOAfAQIj-QrR5bYD9bYGhw 提取码:s0r0

Python-3.7.0:链接:https://pan.baidu.com/s/13QdAw4zeV4D4WJfKAOJFUQ 提取码:iyfl


再次声明:本文参考此文https://blog.csdn.net/c20081052/article/details/95082377,并在此基础上查漏补缺。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/119789.html

相关文章

  • 秋招复盘——回顾2022秋招经历

    摘要:接下来,我主要从三个阶段回顾我的秋招,分别是前期中期尾声。到了这里,我的秋招算是正式的尘埃落定了,签完三方后,我的秋招结束了。四复盘总结这次的复盘主要是我自己整个秋招的历程缩影,很多细节无法在一篇文章就说清楚。 ...

    longshengwang 评论0 收藏0
  • 视频编解码行业及发展方向简述

    摘要:了解华为海思的方案海思的前身是华为的半导体部门,主要产品线包括智能手机处理器麒麟系列,视频采集和编解码处理器系列,无线通信方向芯片等。 目录 一、视频行业1、视频...

    dance 评论0 收藏0
  • 全面认识海思SDK及嵌入式层开发(1)

    摘要:注本资料大部分由朱老师物联网大讲堂课程笔记整理而来并且引用了部分他人博客的内容,如有侵权,联系删除水平有限,如有错误,欢迎各位在评论区交流。 目录 一、全面认识和...

    周国辉 评论0 收藏0
  • Qt音视频开发系列文章导航

    摘要:文章链接解码播放回调处理录像存储读取和控制事件订阅解码处理音频播放保存裸流录像存储控制播放常用命令解码播放录像存储读取和控制事件订阅通用接口海康解码海康回调海康录像存储海康本地播 ...

    AlphaGooo 评论0 收藏0
  • 机器视觉、模式识别库汇总

    摘要:十开放模式识别项目开放模式识别项目,致力于开发出一套包含图像处理计算机视觉自然语言处理模式识别机器学习和相关领域算法的函数库。 一、开源生物特征识别库 OpenBROpenBR 是一个用来从照片中识别人脸的工具。还支持推算性别与年龄。使用方法:$ br -algorithm FaceRecognition -compare me.jpg you.jpg二、计算机视觉库 OpenCVOpenC...

    habren 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<