海康SDK人脸摄像头对接

2020-12-10  本文已影响0人  RunningJiang

1、前言

最近有个项目要用到人脸识别,由于很多原因最后决定采购海康的人脸识别摄像头(支持人脸抓拍+人脸比对等功能),项目中要集成的功能包括:人脸识别结果的返回和人员信息的下发配置。

2、开发环境

3、功能开发

#include <stdio.h>
#include <iostream>
#include "Windows.h"
#include "HCNetSDK.h"
using namespace std;

//时间解析宏定义
#define GET_YEAR(_time_)      (((_time_)>>26) + 2000) 
#define GET_MONTH(_time_)     (((_time_)>>22) & 15)
#define GET_DAY(_time_)       (((_time_)>>17) & 31)
#define GET_HOUR(_time_)      (((_time_)>>12) & 31) 
#define GET_MINUTE(_time_)    (((_time_)>>6)  & 63)
#define GET_SECOND(_time_)    (((_time_)>>0)  & 63)

BOOL CALLBACK MessageCallback(LONG lCommand, NET_DVR_ALARMER *pAlarmer, char *pAlarmInfo, DWORD dwBufLen, void* pUser)
{
    switch(lCommand) 
    {       
        case COMM_SNAP_MATCH_ALARM: //人脸比对结果信息
        {
            NET_VCA_FACESNAP_MATCH_ALARM struFaceMatchAlarm = {0};
            memcpy(&struFaceMatchAlarm, pAlarmInfo, sizeof(NET_VCA_FACESNAP_MATCH_ALARM));
            
            NET_DVR_TIME struAbsTime = {0};
            struAbsTime.dwYear = GET_YEAR(struFaceMatchAlarm.struSnapInfo.dwAbsTime);
            struAbsTime.dwMonth = GET_MONTH(struFaceMatchAlarm.struSnapInfo.dwAbsTime);
            struAbsTime.dwDay = GET_DAY(struFaceMatchAlarm.struSnapInfo.dwAbsTime);
            struAbsTime.dwHour = GET_HOUR(struFaceMatchAlarm.struSnapInfo.dwAbsTime);
            struAbsTime.dwMinute = GET_MINUTE(struFaceMatchAlarm.struSnapInfo.dwAbsTime);
            struAbsTime.dwSecond = GET_SECOND(struFaceMatchAlarm.struSnapInfo.dwAbsTime);

            printf("人脸比对结果上传[0x%x]:[%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d]fSimilarity[%f]FaceID[%d]BlackListID[%d]"
            "Sex[%d]Glasses[%d]Age[%d]MatchPicNum[%d]PicTransType[%d]\n", lCommand, 
            struAbsTime.dwYear, struAbsTime.dwMonth, struAbsTime.dwDay, struAbsTime.dwHour, struAbsTime.dwMinute, 
            struAbsTime.dwSecond, struFaceMatchAlarm.fSimilarity, struFaceMatchAlarm.struSnapInfo.dwSnapFacePicID,
            struFaceMatchAlarm.struBlackListInfo.struBlackListInfo.dwRegisterID, struFaceMatchAlarm.struSnapInfo.bySex,
            struFaceMatchAlarm.struSnapInfo.byGlasses, struFaceMatchAlarm.struSnapInfo.byAge, 
            struFaceMatchAlarm.byMatchPicNum, struFaceMatchAlarm.byPicTransType);
    

            //保存抓拍图片
            if (struFaceMatchAlarm.dwSnapPicLen > 0 && struFaceMatchAlarm.pSnapPicBuffer  != NULL && struFaceMatchAlarm.byPicTransType == 0)
            {      
                char cFilename[256] = {0};
                HANDLE hFile;
                DWORD dwReturn;

                char chTime[128];
                sprintf(chTime,"%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d",struAbsTime.dwYear,struAbsTime.dwMonth,struAbsTime.dwDay,struAbsTime.dwHour,struAbsTime.dwMinute,struAbsTime.dwSecond);

                sprintf(cFilename, "FaceSnapPic[%s][%s].jpg",struFaceMatchAlarm.struSnapInfo.struDevInfo.struDevIP.sIpV4, chTime);
              
                hFile = CreateFile(cFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
                if (hFile == INVALID_HANDLE_VALUE)
                {
                    break;
                }
                WriteFile(hFile, struFaceMatchAlarm.pSnapPicBuffer, struFaceMatchAlarm.dwSnapPicLen, &dwReturn, NULL);
                CloseHandle(hFile);
                hFile = INVALID_HANDLE_VALUE;
            }

            
            //保存黑名单人脸图片
            if (struFaceMatchAlarm.struBlackListInfo.dwBlackListPicLen > 0 && struFaceMatchAlarm.struBlackListInfo.pBuffer1 != NULL)
            {      
                char cFilename[256] = {0};
                HANDLE hFile;
                DWORD dwReturn;

                char chTime[128];
                sprintf(chTime,"%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d",struAbsTime.dwYear,struAbsTime.dwMonth,struAbsTime.dwDay,struAbsTime.dwHour,struAbsTime.dwMinute,struAbsTime.dwSecond);

                sprintf(cFilename, "FaceBlackListPic[%s].jpg", chTime);
              
                hFile = CreateFile(cFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
                if (hFile == INVALID_HANDLE_VALUE)
                {
                    break;
                }
                WriteFile(hFile, struFaceMatchAlarm.struBlackListInfo.pBuffer1, struFaceMatchAlarm.struBlackListInfo.dwBlackListPicLen, &dwReturn, NULL);
                CloseHandle(hFile);
                hFile = INVALID_HANDLE_VALUE;
            }           
        }
        break;
        default:
        printf("其他报警,报警信息类型: 0x%x\n", lCommand);
        break;
    }

    return TRUE;
}

void main() {
    //---------------------------------------
    // 初始化
    NET_DVR_Init();
    //设置连接时间与重连时间
    NET_DVR_SetConnectTime(2000, 1);
    NET_DVR_SetReconnect(10000, true);

    //---------------------------------------
    // 注册设备
    LONG lUserID;

    //登录参数,包括设备地址、登录用户、密码等
    NET_DVR_USER_LOGIN_INFO struLoginInfo = {0};
    struLoginInfo.bUseAsynLogin = 0; //同步登录方式
    strcpy(struLoginInfo.sDeviceAddress, "192.0.0.64"); //设备IP地址
    struLoginInfo.wPort = 8000; //设备服务端口
    strcpy(struLoginInfo.sUserName, "admin"); //设备登录用户名
    strcpy(struLoginInfo.sPassword, "abcd1234"); //设备登录密码
  
    //设备信息, 输出参数
    NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = {0};

    lUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);
    if (lUserID < 0)
    {
        printf("Login failed, error code: %d\n", NET_DVR_GetLastError());
        NET_DVR_Cleanup();
        return;
    }
  
    //设置报警回调函数
    NET_DVR_SetDVRMessageCallBack_V31(MessageCallback, NULL);
  
    //启用布防
    LONG lHandle;
    NET_DVR_SETUPALARM_PARAM  struAlarmParam={0};
    struAlarmParam.dwSize=sizeof(struAlarmParam);
    //其他报警布防参数不需要设置

    lHandle = NET_DVR_SetupAlarmChan_V41(lUserID, & struAlarmParam);
    if (lHandle < 0)
    {
        printf("NET_DVR_SetupAlarmChan_V41 error, %d\n", NET_DVR_GetLastError());
        NET_DVR_Logout(lUserID);
        NET_DVR_Cleanup(); 
        return;
    }
  
    Sleep(50000); //等待过程中,如果设备上传报警信息,在报警回调函数里面接收和处理报警信息

    //撤销布防上传通道
    if (!NET_DVR_CloseAlarmChan_V30(lHandle))
    {
        printf("NET_DVR_CloseAlarmChan_V30 error, %d\n", NET_DVR_GetLastError());
        NET_DVR_Logout(lUserID);
        NET_DVR_Cleanup(); 
        return;
    }
  
    //注销用户
    NET_DVR_Logout(lUserID);
    //释放SDK资源
    NET_DVR_Cleanup();
    return;
}

参考这段代码就可以把获取人脸对比信息的搞定了。

    NET_DVR_Init();
    NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, (void *)this);

    NET_DVR_SetConnectTime(3000, 2);
    NET_DVR_SetReconnect(60000, false);
    hikSnapInfo *data_info = new hikSnapInfo;

    NET_DVR_DEVICEINFO_V40 strutDeviceInfo{0};
    NET_DVR_USER_LOGIN_INFO structLoginInfo{0};

    structLoginInfo.bUseAsynLogin = false;
    structLoginInfo.wPort = port;
    memcpy(structLoginInfo.sDeviceAddress, camera_ip.c_str(), NET_DVR_DEV_ADDRESS_MAX_LEN);
    memcpy(structLoginInfo.sUserName, camera_username.c_str(), NAME_LEN);
    memcpy(structLoginInfo.sPassword, camera_password.c_str(), NAME_LEN);
    data_info->iUserID = NET_DVR_Login_V40(&structLoginInfo, &strutDeviceInfo);

    string set_res = "";

    if (data_info->iUserID < 0)
    {
        LOG(ERROR) << "Login failed, error code:" << NET_DVR_GetLastError() << ";ip:" << camera_ip << ";user_name:" << camera_username << ";password:" << camera_password;
        NET_DVR_Cleanup();
        delete data_info;
        data_info = nullptr;
        return JsonReturn(1001, "Login failed");
    }
    else
    {
        LOG(INFO) << "Login " << camera_ip << ":" << port << " success";
    }

    NET_DVR_XML_CONFIG_INPUT input_param;
    string search_library_cmd = "GET /ISAPI/Intelligent/FDLib/1";
    input_param.lpRequestUrl = const_cast<char *>(search_library_cmd.c_str());
    input_param.dwSize = sizeof(input_param);
    input_param.dwRequestUrlLen = search_library_cmd.size();
    input_param.lpInBuffer = NULL;
    input_param.dwInBufferSize = 0;

    NET_DVR_XML_CONFIG_OUTPUT output_param;
    int out_size = 512;
    char *save_output = new char[out_size];
    output_param.dwSize = sizeof(output_param);

    output_param.lpOutBuffer = save_output;
    output_param.dwOutBufferSize = sizeof(char) * out_size;
    output_param.lpStatusBuffer = NULL;
    output_param.dwStatusSize = 0;

    //first search default face library
    bool find_re = NET_DVR_STDXMLConfig(data_info->iUserID, &input_param, &output_param);
    if (find_re)
    {
        printf("%s\n", save_output);
        LOG(INFO) << "search face library success then do upload face";

        NET_DVR_FACELIB_COND facelib_cond;
        facelib_cond.dwSize = sizeof(facelib_cond);
        string face_id = "1";
        memcpy(facelib_cond.szFDID, face_id.c_str(), face_id.size());
        facelib_cond.byConcurrent = 0;
        facelib_cond.byCover = 0;
        facelib_cond.byCustomFaceLibID = 0;

        //init upload face
        int upload_handle = NET_DVR_UploadFile_V40(data_info->iUserID, IMPORT_DATA_TO_FACELIB, &facelib_cond, sizeof(facelib_cond), NULL, NULL, 0);
        if (upload_handle == -1)
        {
            LOG(ERROR) << "init upload failed code:" << NET_DVR_GetLastError();
            return JsonReturn(1001, "init upload failed");
        }
        else
        {
            LOG(INFO) << "upload file beign ....";
            vector<PersonInfo> persons_upload_info;
            cJSON *root = cJSON_Parse(person_info.c_str());
            cJSON *json_person_info = cJSON_GetObjectItem(root, "persons");
            if (json_person_info == nullptr)
            {
                LOG(ERROR) << "person info has problem";
                return JsonReturn(1001, "person info has problem");
            }
            else
            {
                cJSON *child_person = json_person_info->child;
                while (child_person != nullptr)
                {
                    PersonInfo person_obj;
                    cJSON *json_id = cJSON_GetObjectItem(child_person, "id");
                    if (json_id == nullptr)
                    {
                        LOG(ERROR) << "ID json not exists please check config json file";
                        return JsonReturn(1001, "person info has problem");
                    }
                    person_obj.id = json_id->valuestring;

                    cJSON *json_image = cJSON_GetObjectItem(child_person, "image");
                    if (json_image == nullptr)
                    {
                        LOG(ERROR) << "image json not exists please check config json file";
                        return JsonReturn(1001, "person info has problem");
                    }
                    string image_path = json_image->valuestring;

                    cJSON *json_name = cJSON_GetObjectItem(child_person, "name");
                    if (json_name == nullptr)
                    {
                        LOG(ERROR) << "name json not exists please check config json file";
                        return JsonReturn(1001, "person info has problem");
                    }
                    string person_name = json_name->valuestring;
                    LOG(INFO) << "person id is : " << person_obj.id << " :" << image_path << " : " << person_name;

                    child_person = child_person->next;
                    stringstream buffer;
                    ifstream in(image_path);
                    buffer.clear();
                    buffer.str("");
                    buffer << in.rdbuf();
                    string contents(buffer.str());
                    string image_name = BaseName(image_path);
                    if (contents.size() > 1000)
                    {
                        //todo this only consider the jpg format
                        NET_DVR_SEND_PARAM_IN param_in;
                        param_in.pSendData = reinterpret_cast<unsigned char *>(const_cast<char *>(contents.c_str()));
                        param_in.dwSendDataLen = contents.size();
                        LOG(INFO) << "image size is :" << param_in.dwSendDataLen;
                        param_in.byPicType = 1;
                        param_in.byPicURL = 0;
                        param_in.byUploadModeling = 0;
                        param_in.dwPicMangeNo = 0;
                        param_in.dwPicDisplayTime = 0;
                        memcpy(param_in.sPicName, image_name.c_str(), NAME_LEN);
                        string xml_header = "<FaceAppendData>";
                        string name_data = "<name>" + person_name + "</name>";
                        string certificate_number = "<certificateNumber>" + person_obj.id + "</certificateNumber>";
                        //todo may be need to save
                        //string person_info_extend = "<PersonInfoExtendList><PersonInfoExtend><id>" + person_obj.id + "</id></PersonInfoExtend></PersonInfoExtendList>";
                        string xml_end = "</FaceAppendData>";
                        string append_data = xml_header + name_data + certificate_number + xml_end;
                        param_in.pSendAppendData = reinterpret_cast<unsigned char *>(const_cast<char *>(append_data.c_str()));
                        param_in.dwSendAppendDataLen = append_data.size();

                        NET_DVR_TIME_V30 net_time;
                        struct tm *t;
                        time_t tt;
                        time(&tt);
                        t = localtime(&tt);
                        net_time.wYear = t->tm_year + 1900;
                        net_time.byMonth = t->tm_mon;
                        net_time.byDay = t->tm_mday;
                        net_time.byHour = t->tm_hour;
                        net_time.byMinute = t->tm_min;
                        net_time.bySecond = t->tm_sec;
                        param_in.struTime = net_time;
                        int re = NET_DVR_UploadSend(upload_handle, &param_in, NULL);
                        if (re == -1)
                        {
                            LOG(ERROR) << "send data occurs problem " << NET_DVR_GetLastError();
                        }
                        else
                        {
                            LOG(INFO) << " do face uplaod .... ";
                            unsigned int progress = 0;
                            while (true)
                            {
                                int state = NET_DVR_GetUploadState(upload_handle, &progress);
                                if (state == -1)
                                {
                                    LOG(ERROR) << "get upload state occurs problem " << NET_DVR_GetLastError();
                                    break;
                                }
                                if (state != 2)
                                {
                                    if (state == 1)
                                    {
                                        person_obj.status = 1;
                                        NET_DVR_UPLOAD_FILE_RET upload_ret;
                                        NET_DVR_GetUploadResult(upload_handle, &upload_ret, sizeof(upload_ret));
                                        person_obj.pic_id = reinterpret_cast<char *>(upload_ret.sUrl);
                                        LOG(INFO) << "upload one face image success " << person_obj.id << "and pic id is :" << person_obj.pic_id;
                                    }
                                    else
                                    {
                                        person_obj.status = 0;
                                        if (state == 39 || state == 40 || state == 41)
                                        {
                                            LOG(ERROR) << "extract face feature occurs problem";
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        LOG(INFO) << "imagae size is too small" << contents.size();
                        person_obj.status = 0;
                    }
                    persons_upload_info.push_back(person_obj);
                }
            }
            set_res = GenerateResult(1000, persons_upload_info);
        }
        NET_DVR_UploadClose(upload_handle);
    }
    else
    {
        LOG(ERROR) << "search error code:" << NET_DVR_GetLastError();
        return JsonReturn(1001, "Please first create library");
    }
    delete[] save_output;
    return set_res;
上一篇下一篇

猜你喜欢

热点阅读