美文网首页
海康SDK人脸摄像头对接

海康SDK人脸摄像头对接

作者: RunningJiang | 来源:发表于2020-12-10 13:45 被阅读0次

    1、前言

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

    2、开发环境

    • ubuntu18.04系统
    • CH-HCNetSDKV6.1.4.42_build20200527_linux64
    • C++11
      吐槽一下:海康摄像头目前的SDK只提供了linux x86版本的32位和64位的版本,并没有提供linux arm的sdk,这个真是让人摸不着头脑

    3、功能开发

    • 海康提供的example


      example

      参考这个例子基本上就可以把登录问题搞定了

    • 参考开发文档


    #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;
    }
    

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

    • 参考流程写一段上传人脸图片入库的代码,这里默认库已经建好了,且只有唯一一个库的ID=1,现在就是往里面写入发送图片就可以了。
        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;
    

    相关文章

      网友评论

          本文标题:海康SDK人脸摄像头对接

          本文链接:https://www.haomeiwen.com/subject/crilgktx.html