python 调用海康linux下psdatacall_demo,实现获视频取码流并返回到python,以及上传信息到人脸库的方法

首先要注意的是库必须要更新,在开发的时候,发现5.2的库没有上传人脸库的一个结构体,因此有必要更新库到5.3

其他 我这里是由海康原来的demo,生成一个动态库,然后再由python调用这个动态库实现人脸上传和视频码流返回

,码流返回我采用的是在c++里面传入python的函数,然后将函数全局化,然后在回调函数里面调用python的函数将码流信息通过参数形式返回到python

首先要修改的是makefile,修改之后的makefile如下:

CC       = gcc
CXX      = g++
CFLAGS   = -g
CXXFLAGS = $(CFLAGS)


LIBPATH = ./
LIBS = -Wl,-rpath=./:./HCNetSDKCom -lhcnetsdk 
SRC = ./main.cpp
TARGET = ./getpsdata.so


all: 
$(CXX) $(OPTI) $(CXXFLAGS) -shared -fPIC $(SRC) -o $(TARGET) -L$(LIBPATH) $(LIBS)


.PHONY: clean
clean:

rm -f $(TARGET)

makefile 主要修改的是生成的目标,以及编译的时候多带了编译共享库的选项

修改后的main文件如下:

 /*
* Copyright(C) 2011,Hikvision Digital Technology Co., Ltd 

* File   name��main.cpp
* Discription��demo for muti thread get stream
* Version    ��1.0
* Author     ��luoyuhua
* Create Date��2011-12-10
* Modification History��
*/


#include
#include
#include
#include
#include "HCNetSDK.h"
#include "iniFile.h"
// ȡ�������Ϣ�������̴߳���
typedef struct tagREAL_PLAY_INFO
{
char szIP[16];
int iUserID;
int iChannel;
}REAL_PLAY_INFO, *LPREAL_PLAY_INFO;
//导入人脸数据条件
FILE *g_pFile = NULL;
typedef void (*Func)(BYTE*);
Func rePyGetData = NULL;
void g_RealDataCallBack_V30(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize,void* dwUser)
{
//LPREAL_PLAY_INFO pPlayInfo = (LPREAL_PLAY_INFO)dwUser;
    //printf("[g_RealDataCallBack_V30]Get data, ip=%s, channel=%d, handle=%d, data size is %d, thread=%d\n", 
//pPlayInfo->szIP, pPlayInfo->iChannel, lRealHandle, dwBufSize, pthread_self());


//printf("[g_RealDataCallBack_V30]Get data, handle=%d, data size is %d, thread=%d\n", 
//lRealHandle, dwBufSize, pthread_self());
//NET_DVR_SaveRealData(lRealHandle, cFilename);
}




void PsDataCallBack(LONG lRealHandle, DWORD dwDataType,BYTE *pPacketBuffer,DWORD nPacketSize, void* pUser)
{
if (dwDataType  == NET_DVR_SYSHEAD)
{
//д��ͷ����
g_pFile = fopen("./record/ps.dat", "wb");

if (g_pFile == NULL)
{
printf("CreateFileHead fail\n");
return;
}


//д��ͷ����
fwrite(pPacketBuffer, sizeof(unsigned char), nPacketSize, g_pFile);


printf("write head len=%d\n", nPacketSize);
}
else
{
if(g_pFile != NULL)
{


fwrite(pPacketBuffer, sizeof(unsigned char), nPacketSize, g_pFile);
printf("write data len=%d\n", nPacketSize);
rePyGetData(pPacketBuffer);
}
}
}




extern "C"{
void GetStream(Func getData)
{
rePyGetData = getData;
printf("GetSteam+++++++++++++++++++++++++++++++++++++++++++\n");
    NET_DVR_Init();
NET_DVR_SetLogToFile(3, "./record/");


// �������ļ���ȡ�豸��Ϣ 
/*
IniFile ini("Device.ini");
unsigned int dwSize = 0;
char sSection[16] = "DEVICE";



char *sIP = ini.readstring(sSection, "ip", "error", dwSize);
int iPort = ini.readinteger(sSection, "port", 0);
char *sUserName = ini.readstring(sSection, "username", "error", dwSize); 
char *sPassword = ini.readstring(sSection, "password", "error", dwSize);
int iChannel = ini.readinteger(sSection, "channel", 0);
*/
NET_DVR_DEVICEINFO_V30 struDeviceInfo;
// printf("登录信息,sIP:%s,iPort:%d,sUserName:%s,sPassword:%s",sIP, iPort, sUserName, sPassword);
int iUserID = NET_DVR_Login_V30("192.168.1.63", 8000, "admin", "guoji123", &struDeviceInfo);
printf("注册返回值:%d!!!\n",iUserID);


if(iUserID >= 0)
{


    //NET_DVR_CLIENTINFO ClientInfo = {0};
    //ClientInfo.lChannel     = iChannel;  //channel NO.
    //ClientInfo.lLinkMode    = 0;
    //ClientInfo.sMultiCastIP = NULL;
    //int iRealPlayHandle = NET_DVR_RealPlay_V30(iUserID, &ClientInfo, PsDataCallBack, NULL, 0);
NET_DVR_PREVIEWINFO struPreviewInfo = {0};
struPreviewInfo.lChannel =1;
struPreviewInfo.dwStreamType = 0;
struPreviewInfo.dwLinkMode = 0;
struPreviewInfo.bBlocked = 1;
struPreviewInfo.bPassbackRecord  = 1;
int iRealPlayHandle = NET_DVR_RealPlay_V40(iUserID, &struPreviewInfo, PsDataCallBack, NULL);
if(iRealPlayHandle >= 0)
{
printf("[GetStream]---RealPlay %s:%d success, \n", "192.168.1.63", 1, NET_DVR_GetLastError());
//int iRet = NET_DVR_SaveRealData(iRealPlayHandle, "./record/realplay.dat");
//NET_DVR_SetStandardDataCallBack(iRealPlayHandle, StandardDataCallBack, 0);


}
else
{
printf("[GetStream]---RealPlay %s:%d failed, error = %d\n", "192.168.1.63", 1, NET_DVR_GetLastError());
}
}
else
{
printf("[GetStream]---Login %s failed, error = %d\n", "192.168.1.63", NET_DVR_GetLastError());
}
while (1){
}
    NET_DVR_Cleanup();
}
int UploadFile(char* DeviceIP,int port,char* userName,char* password,char* picPath){
    NET_DVR_Init();
    NET_DVR_LOCAL_SDK_PATH struLocalPath;
    strcpy(struLocalPath.sPath,"/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/psdatacall_demo/HCNetSDKCom");
    bool set_path = NET_DVR_SetSDKInitCfg(NET_SDK_INIT_CFG_SDK_PATH,&struLocalPath);
    printf("设置组件路径结果:%d\n",set_path);
    NET_DVR_SetLogToFile(3, "/home/caobin/chike/chike/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/psdatacall_demo/record/");
    NET_DVR_DEVICEINFO_V30 struDeviceInfo;
    printf("传进来的参数,IP:%s,端口:%d,用户名:%s,密码:%s,图片路径:%s\n",DeviceIP,port,userName,password,picPath);
    int iUserID = NET_DVR_Login_V30(DeviceIP, port, userName, password, &struDeviceInfo);
    if (iUserID >=0){
    NET_DVR_FACELIB_COND FaceInBuffer = {0};
    FaceInBuffer.dwSize = sizeof(FaceInBuffer);
    printf("结构体大小:%d\n",FaceInBuffer.dwSize);
    strcpy(FaceInBuffer.szFDID,"1");
    FaceInBuffer.byCover = 1;
    FaceInBuffer.byConcurrent = 0;
    int m_lUploadHandle = NET_DVR_UploadFile_V40(iUserID,IMPORT_DATA_TO_FACELIB,&FaceInBuffer,FaceInBuffer.dwSize,NULL,NULL,0);
    printf("上传文件:%d\n",m_lUploadHandle);
    printf("错误类型:%d\n",NET_DVR_GetLastError());


    //读取文件数据
    BYTE* pSendAppendData;
    BYTE* pSendPicData;
    printf("BYTE*定义完成!!\n");
    NET_DVR_SEND_PARAM_IN m_struSendParam;
    /*
    if(NULL!= pSendAppendData){
    delete[] pSendAppendData;
    pSendAppendData = NULL;
    }
    if(NULL!= pSendPicData){
    delete[] pSendPicData;
    pSendPicData = NULL;
    }*/
    printf("数据类型定义完成!\n");
    memset(&m_struSendParam,0,sizeof(m_struSendParam));
    printf("内存清零操作完成!!\n");
    char szLan[1280]={0};
    char szFileName[255];//注,MFC综合实例中给出的长度是MAX_PATH,未找到定义
    DWORD dwFileSize = 0;
    //读取XML文件
    printf("开始读取xml文件!!\n");
    strcpy(szFileName,"/home/caobin/chike/chike/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/psdatacall_demo/tmp.xml");
    FILE *fp;
    if ((fp = fopen(szFileName,"r"))==NULL){
    printf("文件打开不成功!\n");
    }
    fseek(fp,0L,SEEK_END);
    dwFileSize = ftell(fp);
    printf("XML文件大小:%d\n",dwFileSize);
    if (dwFileSize == 0){
    printf("XML文件为空!!\n");
    }
    fseek(fp,0L,SEEK_SET);
    pSendAppendData = new BYTE[dwFileSize];
    fread(pSendAppendData,sizeof(BYTE),dwFileSize,fp);
    m_struSendParam.pSendAppendData = pSendAppendData;
    m_struSendParam.dwSendAppendDataLen = dwFileSize;
    fclose(fp);
    printf("xml文件读取完成,开始读取图片文件!!\n");
    //读取图片文件
    strcpy(szFileName,picPath);
    FILE *picFP;
    if ((picFP = fopen(szFileName,"r"))==NULL){
    printf("图片打开失败!!\n");
    }
    fseek(picFP,0L,SEEK_END);
    dwFileSize = ftell(picFP);
    fseek(picFP,0L,SEEK_SET);
    printf("图片文件大小:%d\n",dwFileSize);
    if(dwFileSize == 0){
    printf("图片文件为空!!\n");
    }
    pSendPicData = new BYTE[dwFileSize];
    fread(pSendPicData,sizeof(BYTE),dwFileSize,picFP);
    m_struSendParam.pSendData = pSendPicData;
    m_struSendParam.dwSendDataLen = dwFileSize;
    m_struSendParam.byPicType = 1;
    m_struSendParam.byPicURL = 0;
    fclose(picFP);


    printf("开始上传图片数据!!!\n");


    if(NET_DVR_UploadSend(m_lUploadHandle,&m_struSendParam,NULL)<0){
    printf("\n上传失败,错误代号:%d\n",NET_DVR_GetLastError());
    return 0;
    }
    else{
    uint pProgress = 0;
    while(pProgress < 100){
    int iStatus = NET_DVR_GetUploadState(m_lUploadHandle,&pProgress);
    if(iStatus == -1){
    printf("上传失败,错误号:%d\n",NET_DVR_GetLastError());
    usleep(100000);
    break;
    }
    else if(iStatus == 2){
    printf("文件正在上传,进度:%d\n",pProgress);
    usleep(100000);
    }
    else if(iStatus == 1){
    printf("上传成功!!!!!\n");
    usleep(100000);
    break;
    }
    else{
    printf("上传失败,状态标志位:%d,错误标志号:%d\n",iStatus,NET_DVR_GetLastError());
    break;
    }
    }
    }
    NET_DVR_UPLOAD_FILE_RET struFaceData;
    BOOL res;
    res = NET_DVR_GetUploadResult(m_lUploadHandle,&struFaceData,sizeof(struFaceData));
    if(res == true){
    printf("上传成功!!!!!!!\n");
    NET_DVR_UploadClose(m_lUploadHandle);
    }else{
    printf("错误!!!\n");
    NET_DVR_UploadClose(m_lUploadHandle);
    }
    }
    return 0;
}
}
/*
int main()
{
    NET_DVR_Init();
NET_DVR_SetLogToFile(3, "./record/");


GetStream();




char c = 0;
while('q' != c)
{
printf("input 'q' to quit\n");
printf("input: ");
scanf("%c", &c);
}




    NET_DVR_Cleanup();
    return 0;
}*/

//两个函数都是直接在main.cpp中实现了,但是去掉了原来的main函数

在python中调用的时候,上传人脸库需要先将xml文件写好,xml中的男女信息必须是 male和female,否则

人脸图片将上传不上去

以下是python调用生成的库,实现人脸上传的代码:

####上传人脸信息库
def uploadFace(name = "小红",sex = "female",IDNum = "12345678",DeviceIP = "192.168.1.64",userName = "admin",password = "guoji123",
               picpath = "/home/caobin/chike/chike/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/psdatacall_demo/tmp.jpg"):
    f = open("/home/caobin/chike/chike/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/psdatacall_demo/tmp.xml",'w')
    f.writelines("\'1.0\' encoding=\'UTF-8\'?>\n")
    f.writelines("\n")
    f.writelines(""+name+"\n")
    f.writelines(""+sex+"\n")
    f.writelines("ID"+IDNum +"\n")
    f.writelines("\n")
    f.close()
    sDVRIP = bytes(DeviceIP, "ascii")
    sUserName = bytes(userName, "ascii")
    sPassword = bytes(password, "ascii")
    picPath = bytes(picpath,"ascii")
    h_dll_ = ctypes.cdll.LoadLibrary(
        "/home/caobin/chike/chike/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/psdatacall_demo/getpsdata.so")
    h_dll_.UploadFile(sDVRIP,8000,sUserName,sPassword,picPath)
以下是python调用生成的库,获取码流的代码:

h_dll_ = ctypes.cdll.LoadLibrary("/home/caobin/chike/chike/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/psdatacall_demo/getpsdata.so")
list_data = []
def func_called(mydata):
    # print("print by python,called by cpp!")
    print("print by python:"+str(len(mydata)))
    list_data.append(mydata)


# def WriteFaceRes():
#     os.system(
#             r'"/home/caobin/chike/chike/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/consoleDemo/linux64/lib/sdkTest" "192.168.1.64" 8000 "admin" "guoji123" 3')
# #
FUNCCALLED = ctypes.CFUNCTYPE(ctypes.c_void_p,ctypes.c_char_p)
#
h_dll_.GetStream(FUNCCALLED(func_called))






你可能感兴趣的:(海康相机)