关于linux下使用python调用海康威视SDK包

关于linux下使用python调用海康威视SDK包

   由于公司的项目需要在了Linux环境下使用python语言调用海康威视的SDK包对海康威视摄像头进行解码显示。因此本菜鸟开始了艰辛的SDK调用之旅。
   首先,要说明使用python直接调用SDK包是不成功的,因此我决定曲线救国,先将 C++程序通过swig进行封装,再使用CodeBlocks生成动态链接(so文件)再对海康威视SDK包进行调用,后续会将资源进行一个整理并发送上去,大家可以参考一下。

C++程序与转化

HKIPcamera.cpp


#include <opencv2/opencv.hpp>
#include <iostream>
#include <time.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <list>
#include "HCNetSDK.h"
#include "LinuxPlayM4.h"
#include <unistd.h>
#include <pthread.h>
 
 
#define USECOLOR 1
#define WINAPI
 
 
using namespace cv;
using namespace std;
 
 
//--------------------------------------------
int iPicNum = 0;//Set channel NO.
LONG nPort = -1;
HWND hWnd = NULL;
pthread_mutex_t g_cs_frameList;
list<Mat> g_frameList;
LONG lUserID;
NET_DVR_DEVICEINFO_V30 struDeviceInfo;
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;
 
 
//printf("widthStep=%d.\n",widthStep);
 
 
for (row = 0; row<height; row++)
{
idx = row * widthStep;
int rowptr = row*width;
 
 
for (col = 0; col<width; col++)
{
//int colhalf=col>>1;
tmp = (row / 2)*(width / 2) + (col / 2);
//         if((row==1)&&( col>=1400 &&col<=1600))
//         {
//          printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);
//          printf("row*width+col=%d,width*height+width*height/4+tmp=%d,width*height+tmp=%d.\n",row*width+col,width*height+width*height/4+tmp,width*height+tmp);
//         }
Y = (unsigned int)inYv12[row*width + col];
U = (unsigned int)inYv12[width*height + width*height / 4 + tmp];
V = (unsigned int)inYv12[width*height + tmp];
//         if ((col==200))
//         {
//         printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);
//         printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp);
//         return ;
//         }
if ((idx + col * 3 + 2)> (1200 * widthStep))
{
//printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2);
}
outYuv[idx + col * 3] = Y;
outYuv[idx + col * 3 + 1] = U;
outYuv[idx + col * 3 + 2] = V;
}
}
//printf("col=%d,row=%d.\n",col,row);
}
 
 
 
 
//解码回调 视频为YUV数据(YV12),音频为PCM数据
void CALLBACK DecCBFun(int nPort, char * pBuf, int nSize, FRAME_INFO * pFrameInfo, void * nReserved1, int 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
//printf("%d\n",end-start);
 
 
//Mat frametemp(pImg), frame;
 
 
//frametemp.copyTo(frame);
//      cvShowImage("IPCamera",pImg);
//      cvWaitKey(1);
pthread_mutex_lock(&g_cs_frameList);
Mat mat=cvarrToMat(pImg);
g_frameList.push_back(mat);
pthread_mutex_unlock(&g_cs_frameList);
 
 
#if USECOLOR
//      cvReleaseImage(&pImgYCrCb);
//      cvReleaseImage(&pImg);
#else
/*cvReleaseImage(&pImg);*/
#endif
//此时是YV12格式的视频数据,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile);
//fwrite(pBuf,nSize,1,fp);
}
/***************
else if (lFrameType ==T_AUDIO16)
{
//此时是音频数据,数据保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile);
}
else
{
}
*******************/
 
}
 
 
///实时流回调
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_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL))
//{
//  dRet=PlayM4_GetLastError(nPort);
//  break;
//}
 
 
//打开视频解码
if (!PlayM4_Play(nPort, hWnd))
{
dRet = PlayM4_GetLastError(nPort);
break;
}
 
 
//打开音频解码, 需要码流是复合流
//          if (!PlayM4_PlaySound(nPort))
//          {
//              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);
cout << (L"PlayM4_InputData failed \n") << endl;
}
}
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;
}
}
void * ReadCamera(void* 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 << "Code stream callback success!" << endl;
sleep(-1);
//fclose(fp);
//---------------------------------------
//关闭预览
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){
pthread_t hThread;
cout << "IP:" << ip << "    UserName:" << usr << "    PassWord:" << password << endl;
NET_DVR_Init();
NET_DVR_SetConnectTime(2000, 1);
NET_DVR_SetReconnect(10000, true);
OpenCamera(ip, usr, password);
pthread_mutex_init(&g_cs_frameList, NULL);
//hThread = ::CreateThread(NULL, 0, ReadCamera, NULL, 0, 0);
pthread_create(&hThread, NULL, ReadCamera, NULL);
}
 
 
Mat getframe(){
Mat frame1;
pthread_mutex_lock(&g_cs_frameList);
while (!g_frameList.size()){
pthread_mutex_unlock(&g_cs_frameList);
pthread_mutex_lock(&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();
pthread_mutex_unlock(&g_cs_frameList);
return(frame1);
}
 
 
void release(){
//close(hThread);
NET_DVR_StopRealPlay(lRealPlayHandle);
//注销用户
NET_DVR_Logout(lUserID);
NET_DVR_Cleanup();
}

HKIPcamera.h


#include <opencv2/opencv.hpp>
using namespace cv;
 
void init(char* ip, char* usr, char* password);
Mat getframe();
void release();
// An highlighted block
var foo = 'bar';

// 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"

将这三个文件放进你新建的文件夹 如图
在这里插入图片描述
其中HKIPcamera .cxx与HKIPcamera.py文件是通过swig转换的,注意图片中已经放进了opencv.i与opencv文件夹,是在这里下载,将下载的文件和上面三个文件放在同一个文件夹,在这个文件夹内打开终端,输入

swig -I/home/xxx/opencv/modules/core/include/ -python -c++ HKIPcamera.i 

/home/xxx/opencv-3.4.6/modules/core/include/这个需换成自己的opencv的路径,经转换后,会出现.cxx与.py文件,接下来就是使用codeblock进行生成.os文件

os文件生成

打开codeblock,点击file新建项目选择生成动态链接库项目标题随意,我的是HIKPcamera,如图:
在这里插入图片描述
新建的工程,Add file,将HKIPcameracpp,HKIPcamera.h,HKIPcamera_wrap.cxx加入到工程。
在这里插入图片描述

在工程下右键,Build options——linker settings——linker libraries,添加opencv的所有so文件(opencv/debug/lib、opencv/debug/lib/python3
添加海康sdk中的所有so文件HKCream/lib/linux、HKCream/lib/linux/lib/HCNetSDKCom/
在这里插入图片描述

在工程下右键,build options——search directories——complier 中添加/home/user/anaconda/envs/xxx/include/python3.6m、/usr/include/boost、/usr/local/include/
、/usr/local/include/opencv、/usr/local/include/opencv2以及海康sdk头文件路径HKCream/incCn
在这里插入图片描述

project——build options——search directories——linker中添加 /usr/local/lib

project—— build option —— Compiler settings —— Other compiler options 添加 -fPIC

主界面——Settings——compiler——linker settings——linker libraries添加 /usr/lib/x86_64-linux-gnu/libpthread.a 右边other linker options 添加 -lpthread
在这里插入图片描述
将os动态链接库地址添加进系统路径
在/etc/ld.so.conf文件结尾添加网络sdk库的路径


sudo vim /etc/ld.so.conf
# 末尾添加
/home/HCIPcream/HCIPcream/lib/linux/HCNetSDKCom
/home/HCIPcream/HCIPcream/lib/linux/HCNetSDKCom/lib
# 保存退出
sudo ldconfig

右键工程build,在HIKPcamera会生成 liblibhksdk.so文件

说一下这里的坑

1.在工程下右键,build options——search directories——complier 中添加/home/user/anaconda/envs/xxx/include/python3.6m,这个是你现在环境正在使用的或者说你要编译python程序使用的python语言的地址,如果你放错了python语言的位置,会报关于python中字符未定义等错误
2.关于海康威视SDK包如果你使用的是最新版本的python那么你一定要用最新版本的sdk包,而且不能在同一目录下放入多个版本的SDK包,要不然会报错,如果版本不对会报openssl未加载的错误,会提示openssl的版本不对
3.关于LinxPLayM4.h,以及libPlayCtrl.os文件都是从海康威视的播放库SDK包里找到

测试

将liblibhksdk.so改名为_HKIPcamera.so,与之前生成的HKIPcamera.py文件一同放到HKCream文件夹,新建test.py文件,输入:


import HKIPcamera
import time
import numpy as np
import cv2
 
#ip地址、用户名和密码请自己修改
ip = str('0.0.0.0')
name = str('admin')     
pw = str('admin')        #password
HKIPcamera.init(ip, name, pw)
 
while True:
    fram = HKIPcamera.getframe()
    cv2.imshow('1',np.array(fram))
    if cv2.waitKey(24) & 0xFF == 27:
        break 
HKIPcamera.release()

参考
[1]: https://blog.csdn.net/ustczhang/article/details/79030715
[2]: http://t.csdn.cn/iDvek

### 回答1: Windows下Python调用海康威视SDK,可以通过以下步骤实现。 1. 下载SDK及相关文档:前往海康威视官方网站下载对应的SDK及其相关文档,确保下载的SDK版本与Python环境兼容。 2. 安装SDK:运行SDK安装程序,按照提示进行安装。安装完成后,可能需要将SDK中的相关环境变量添加到系统的PATH变量中。 3. 安装Python相关库:使用pip等工具安装与SDK调用相关的Python库。常用的库括pyhkws、pyhkwsnet等。 4. 编写调用代码:在Python代码中,引入SDK所需的相关模块,例如pyhkws,使用相应的接口进行操作。根据需求,可以调用海康威视SDK提供的各种功能,例如视频流播放、设备管理、人脸识别等。 5. 执行代码:运行Python代码,测试SDK调用是否成功。根据具体需求,可能需要提供设备地址、账号密码等参数进行连接和认证,以便进行相应的操作。 需要注意的是,在调用海康威视SDK之前,要确保配置正确并且与SDK版本匹配。另外,海康威视SDK的具体使用方法及接口文档可以参考官方提供的文档和示例代码,更好地了解和使用SDK的功能。 ### 回答2: 海康威视是一家领先的安防产品和解决方案提供商,其提供了SDK(软件开发工具),使得开发人员可以通过Python语言调用海康威视的功能和服务。 在Window操作系统下,要使用Python调用海康威视SDK,需要进行以下步骤: 1. 下载并安装Python编程环境:在Python官方网站上可以下载适用于Windows系统的Python安装程序。安装完成后,配置Python环境变量。 2. 下载并安装海康威视SDK:在海康威视官方网站上,搜索并下载适用于PythonSDK。解压缩下载的文件到指定的目录。 3. 调用海康威视SDK:在Python程序中引入SDK提供的模块,并使用相应的函数来实现所需的功能。具体的调用方式可以在SDK提供的开发文档中找到,开发文档通常含了接口说明、示例代码和使用说明等。 4. 安装依赖库:根据SDK的要求,可能需要在Python环境中安装一些额外的依赖库。可以使用pip命令来安装这些库。 5. 配置SDK参数:根据实际情况,可能需要在代码中配置一些参数,如设备地址、用户名、密码等。 6. 开发和测试:编写Python代码来调用海康威视SDK提供的功能,并进行测试。可以根据具体需求来调用不同的接口,如视频监控、设备管理等。 需要注意的是,Python调用海康威视SDK需要按照其提供的接口规范进行开发,确保传入正确的参数和按照正确的顺序调用函数。另外,使用海康威视SDK之前,可能需要申请相应的许可证或者API密钥,并按照其规定的使用方式进行调用。 总之,通过以上步骤,可以在Window系统上使用Python语言调用海康威视SDK,实现相应的安防功能。 ### 回答3: 海康威视SDK是一款用于实现视频监控设备操作和管理的开发工具,可以用于构建Windows环境下的视频监控应用程序。以下是在Python环境下调用海康威视SDK的一些步骤: 首先,确保已经安装了Python开发环境以及海康威视SDK的驱动。然后,通过pip命令安装PythonSDK,可以使用以下命令: ``` pip install hkws-sdk ``` 在程序中引入SDK的库文件,例如: ``` from hikvision.hikvision import Hikvision ``` 创建一个Hikvision对象,并进行初始化配置,例如设置SDK相关的参数: ``` hik = Hikvision() hik.set_ip("192.168.1.100") # 设置设备IP地址 hik.set_port(8000) # 设置设备端口号 hik.set_username("admin") # 设置登录用户名 hik.set_password("password") # 设置登录密码 hik.init() # 初始化SDK ``` 通过Hikvision对象的方法进行相关操作,例如获取设备信息: ``` device_info = hik.get_device_info() print(device_info) ``` 进行视频预览,例如设置预览窗口和开始预览: ``` hik.set_preview_window(hwnd) # 设置预览窗口句柄 hik.start_preview() # 开始预览 ``` 以上是一个简单的示例,具体的调用方式和方法可以根据海康威视SDK的文档和编程需求进行调整。在使用过程中,要注意配置正确的设备参数以及处理异常情况,确保与设备成功建立连接并获取需要的数据。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小秀峰哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值