大华sdk人脸识别获取人脸信息和图片

大华监控官网SDK版本:NetSDK_JAVA_Linux64_V3.055.0000000.0.R.210602/NetSDK_JAVA_Win64_V3.055.0000000.0.R.210602


import com.netsdk.common.Res;
import com.netsdk.lib.NetSDKLib;
import com.netsdk.lib.ToolKits;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import static com.netsdk.demo.module.LoginModule.netsdk;

/**
 */
public class TestHandle{
  private String m_strIp = "XX.X.XXX.XXX";//监控地址
  private int m_nPort = 37777;//端口 默认是使用37777 
  private String m_strUser = "XXXX";//账号
  private String m_strPassword = "XXXXXXXX";//密码

  public static final NetSDKLib netSdk = NetSDKLib.NETSDK_INSTANCE;
  // 登陆句柄
  private NetSDKLib.LLong loginHandle = new NetSDKLib.LLong(0);
  // 设备信息扩展
  private NetSDKLib.NET_DEVICEINFO_Ex deviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();

  // 全景图
  private static BufferedImage globalBufferedImage = null;

  // 人脸图
  private static BufferedImage personBufferedImage = null;

  // 候选人图
  private static BufferedImage candidateBufferedImage = null;

  // 用于人脸检测
  private static int groupId = 0;

  private static int index = -1;

  // 设备断线通知回调
  private static DisConnect disConnect = new DisConnect();

  // 网络连接恢复
  private static HaveReConnect haveReConnect = new HaveReConnect();

  public static void main(String[] args) {
    TestHandle testHandle= new TestHandle ();
    //初始化
    testHandle.InitTest(disConnect, haveReConnect);
    //登录
    testHandle.Login();

    testHandle.Run();

  }

  public void Run() {
    //订阅
    RealLoadPicture(0, 1, AnalyzerDataCB.getInstance());
    //防止程序执行完
    try {
      new BufferedReader(new InputStreamReader(System.in)).readLine();
      System.in.read();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }


  // 设备断线回调: 通过 CLIENT_Init 设置该回调函数,当设备出现断线时,SDK会调用该函数
  private static class DisConnect implements NetSDKLib.fDisConnect {
    public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
      System.out.printf("Device[%s] Port[%d] DisConnect!\n", pchDVRIP, nDVRPort);
    }
  }

  // 网络连接恢复,设备重连成功回调
  // 通过 CLIENT_SetAutoReconnect 设置该回调函数,当已断线的设备重连成功时,SDK会调用该函数
  private static class HaveReConnect implements NetSDKLib.fHaveReConnect {
    public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
      System.out.printf("ReConnect Device[%s] Port[%d]\n", pchDVRIP, nDVRPort);
    }
  }

  /**
   * 写成静态主要是防止被回收
   */
  private static class AnalyzerDataCB implements NetSDKLib.fAnalyzerDataCallBack {
    private AnalyzerDataCB() {
    }

    private static class AnalyzerDataCBHolder {
      private static final PictureHandle.AnalyzerDataCB instance = new PictureHandle.AnalyzerDataCB();
    }

    public static PictureHandle.AnalyzerDataCB getInstance() {
      return PictureHandle.AnalyzerDataCB.AnalyzerDataCBHolder.instance;
    }

    public int invoke(
            NetSDKLib.LLong lAnalyzerHandle,
            int dwAlarmType,
            Pointer pAlarmInfo,
            Pointer pBuffer,
            int dwBufSize,
            Pointer dwUser,
            int nSequence,
            Pointer reserved) {
      if (lAnalyzerHandle.longValue() == 0 || pAlarmInfo == null) {
        return -1;
      }

      switch (dwAlarmType) {
        case NetSDKLib.EVENT_IVS_FACERECOGNITION: // /< 人脸识别事件
        {
          // DEV_EVENT_FACERECOGNITION_INFO 结构体比较大,new对象会比较耗时, ToolKits.GetPointerData内容拷贝是不耗时的。
          // 如果多台设备或者事件处理比较频繁,可以考虑将 static DEV_EVENT_FACERECOGNITION_INFO msg = new
          // DEV_EVENT_FACERECOGNITION_INFO(); 改为全局。
          // 写成全局,是因为每次new花费时间较多, 如果改为全局,此case下的处理需要加锁
          // 加锁,是因为共用一个对象,防止数据出错

          // 耗时800ms左右
          NetSDKLib.DEV_EVENT_FACERECOGNITION_INFO msg = new NetSDKLib.DEV_EVENT_FACERECOGNITION_INFO();

          // 耗时20ms左右
          ToolKits.GetPointerData(pAlarmInfo, msg);

          //保存人脸对比信息
          try {
            saveFaceDetectInfo(msg);
          } catch (IOException e) {
            e.printStackTrace();
          }

          // 保存图片,获取图片缓存
          // 耗时20ms左右
          try {
            saveFaceRecognitionPic(pBuffer, dwBufSize, msg);
          } catch (FileNotFoundException e) {
            e.printStackTrace();
          }

          // 释放内存
          msg = null;
          System.gc();

          break;
        }
             /*   case NetSDKLib.EVENT_IVS_FACEDETECT: // /< 人脸检测
                {
                    NetSDKLib.DEV_EVENT_FACEDETECT_INFO msg = new NetSDKLib.DEV_EVENT_FACEDETECT_INFO();

                    ToolKits.GetPointerData(pAlarmInfo, msg);

                    // 保存图片,获取图片缓存
                    try {
                        saveFaceDetectPic(pBuffer, dwBufSize, msg);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }

                    // 释放内存
                    msg = null;
                    System.gc();

                    break;
                }*/
        default:
          break;
      }

      return 0;
    }


    /**
     * 保存人脸识别事件图片
     *
     * @param pBuffer             抓拍图片信息
     * @param dwBufSize           抓拍图片大小
     * @param faceRecognitionInfo 人脸识别事件信息
     */
    public void saveFaceRecognitionPic(
            Pointer pBuffer, int dwBufSize, NetSDKLib.DEV_EVENT_FACERECOGNITION_INFO faceRecognitionInfo)
            throws FileNotFoundException {

      DateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
      Date currentDate = new Date();
      File path = new File("D:\\test\\" + df.format(currentDate).toString());
      if (!path.exists()) {
        path.mkdir();
      }

      if (pBuffer == null || dwBufSize <= 0) {
        return;
      }

      /// 保存全景图 ///
      if (faceRecognitionInfo.bGlobalScenePic == 1) {

        String strGlobalPicPathName =
                path + "\\" + faceRecognitionInfo.UTC.toStringTitle() + "_FaceRecognition_Global.jpg";
        byte[] bufferGlobal =
                pBuffer.getByteArray(
                        faceRecognitionInfo.stuGlobalScenePicInfo.dwOffSet,
                        faceRecognitionInfo.stuGlobalScenePicInfo.dwFileLenth);
        ByteArrayInputStream byteArrInputGlobal = new ByteArrayInputStream(bufferGlobal);

        try {
          globalBufferedImage = ImageIO.read(byteArrInputGlobal);
          if (globalBufferedImage != null) {
            File globalFile = new File(strGlobalPicPathName);
            if (globalFile != null) {
              ImageIO.write(globalBufferedImage, "jpg", globalFile);
            }
          }
        } catch (IOException e2) {
          e2.printStackTrace();
        }
      }

      /// 保存人脸图 /
      if (faceRecognitionInfo.stuObject.stPicInfo != null) {
        String strPersonPicPathName =
                path + "\\" + faceRecognitionInfo.UTC.toStringTitle() + "_FaceRecognition_Person.jpg";
        byte[] bufferPerson =
                pBuffer.getByteArray(
                        faceRecognitionInfo.stuObject.stPicInfo.dwOffSet,
                        faceRecognitionInfo.stuObject.stPicInfo.dwFileLenth);
        ByteArrayInputStream byteArrInputPerson = new ByteArrayInputStream(bufferPerson);

        try {
          personBufferedImage = ImageIO.read(byteArrInputPerson);
          if (personBufferedImage != null) {
            File personFile = new File(strPersonPicPathName);
            if (personFile != null) {
              ImageIO.write(personBufferedImage, "jpg", personFile);
            }
          }
        } catch (IOException e2) {
          e2.printStackTrace();
        }
      }

      / 保存对比图 //
      if (faceRecognitionInfo.nRetCandidatesExNum > 0
              && faceRecognitionInfo.stuCandidatesEx != null) {
        int maxValue = -1;

        // 设备可能返回多张图片,这里只显示相似度最高的
        int[] nSimilary = new int[faceRecognitionInfo.nRetCandidatesExNum];
        for (int i = 0; i < faceRecognitionInfo.nRetCandidatesExNum; i++) {
          nSimilary[i] = faceRecognitionInfo.stuCandidatesEx[i].bySimilarity & 0xff;
        }

        for (int i = 0; i < nSimilary.length; i++) {
          if (maxValue < nSimilary[i]) {
            maxValue = nSimilary[i];
            index = i;
          }
        }

        String strCandidatePicPathName =
                path
                        + "\\"
                        + faceRecognitionInfo.UTC.toStringTitle()
                        + "_FaceRecognition_Candidate.jpg";

        // 每个候选人的图片个数:faceRecognitionInfo.stuCandidatesEx[index].stPersonInfo.wFacePicNum,
        // 正常情况下只有1张。如果有多张,只获取第一张
        byte[] bufferCandidate =
                pBuffer.getByteArray(
                        faceRecognitionInfo.stuCandidatesEx[index].stPersonInfo.szFacePicInfo[0].dwOffSet,
                        faceRecognitionInfo
                                .stuCandidatesEx[index]
                                .stPersonInfo
                                .szFacePicInfo[0]
                                .dwFileLenth);
        ByteArrayInputStream byteArrInputCandidate = new ByteArrayInputStream(bufferCandidate);

        try {
          candidateBufferedImage = ImageIO.read(byteArrInputCandidate);
          if (candidateBufferedImage != null) {
            File candidateFile = new File(strCandidatePicPathName);
            if (candidateFile != null) {
              ImageIO.write(candidateBufferedImage, "jpg", candidateFile);
            }
          }
        } catch (IOException e2) {
          e2.printStackTrace();
        }
      }
    }

    /**
     * 保存人脸对比信息
     */
    public void saveFaceDetectInfo(NetSDKLib.DEV_EVENT_FACERECOGNITION_INFO faceMsg) throws IOException {
      //人脸信息
      if (faceMsg.stuFaceData != null) {
        DateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
        Date currentDate = new Date();
        File path = new File("D:\\test\\" + df.format(currentDate).toString());
        if (!path.exists()) {
          path.mkdir();
        }
        String strCandidateInfoPathName =path+ "\\"+ "faceDetectInfo.txt";
        File faceDetectInfoFile = new File(strCandidateInfoPathName);
        if (faceDetectInfoFile != null) {
          FileWriter fileWriter=null;
          StringBuilder faceDetectInfoStr=new StringBuilder();

          String nAge="";
          if(nAge=="-1"){
            nAge="未知";
          }

          faceDetectInfoStr.append("对比信息\r\n")
                  .append("人脸信息:\r\n")
                  .append("时间:").append(faceMsg.UTC).append("\r\n")
                  .append("性别:").append(Res.string().getSex(faceMsg.stuFaceData.emSex)).append("\r\n")
                  .append("年龄:").append(nAge).append("\r\n")
                  .append("肤色:").append(Res.string().getColor(faceMsg.stuFaceData.emRace)).append("\r\n")
                  .append("眼睛:").append(Res.string().getEyeState(faceMsg.stuFaceData.emEye)).append("\r\n")
                  .append("嘴巴:").append(Res.string().getMouthState(faceMsg.stuFaceData.emMouth)).append("\r\n")
                  .append("口罩:").append(Res.string().getMaskState(faceMsg.stuFaceData.emMask)).append("\r\n")
                  .append("胡子:").append(Res.string().getBeardState(faceMsg.stuFaceData.emBeard)).append("\r\n");


          if (faceMsg.nRetCandidatesExNum > 0){
            for(int i=0;i<faceMsg.nRetCandidatesExNum;i++){
              StringBuilder birthday=new StringBuilder();
              if(faceMsg.stuCandidatesEx[i].stPersonInfo.wYear!=0){
                birthday.append(faceMsg.stuCandidatesEx[i].stPersonInfo.wYear);
              }else if(faceMsg.stuCandidatesEx[i].stPersonInfo.byMonth!=0){
                birthday.append("-").append(faceMsg.stuCandidatesEx[i].stPersonInfo.byMonth);
              }else if(faceMsg.stuCandidatesEx[i].stPersonInfo.byDay!=0){
                birthday.append("-").append(faceMsg.stuCandidatesEx[i].stPersonInfo.byDay);
              }

              faceDetectInfoStr.append("人脸库候选人信息:\r\n")
                      .append("姓名:").append(new String(faceMsg.stuCandidatesEx[i].stPersonInfo.szPersonName, "GBK")
                      .trim()).append("\r\n")
                      .append("性别:").append(Res.string()
                      .getSex(faceMsg.stuCandidatesEx[i].stPersonInfo.bySex)).append("\r\n")
                      .append("生日:").append(birthday).append("\r\n")
                      .append("证件号:").append(new String(faceMsg.stuCandidatesEx[i].stPersonInfo.szID, "GBK")
                      .trim()).append("\r\n")
                      .append("人脸库ID:").append(new String(faceMsg.stuCandidatesEx[i].stPersonInfo.szGroupID, "GBK")
                      .trim()).append("\r\n")
                      .append("人脸库名称:").append(new String(faceMsg.stuCandidatesEx[i].stPersonInfo.szGroupName, "GBK")
                      .trim()).append("\r\n")
                      .append("相似度:").append(faceMsg.stuCandidatesEx[i].bySimilarity).append("\r\n");
            }
          }

          try {
            fileWriter=new FileWriter(faceDetectInfoFile,true);
            fileWriter.write(faceDetectInfoStr+"\r\n");
          } catch (IOException e) {
            e.printStackTrace();
          }finally {
            if(fileWriter!=null){
              fileWriter.close();
            }
          }
        }

      }
      //候选人信息

    }

    ;

    /**
     * 保存人脸检测事件图片
     *
     * @param pBuffer        抓拍图片信息
     * @param dwBufSize      抓拍图片大小
     * @param faceDetectInfo 人脸检测事件信息
     */
    public void saveFaceDetectPic(
            Pointer pBuffer, int dwBufSize, NetSDKLib.DEV_EVENT_FACEDETECT_INFO faceDetectInfo)
            throws FileNotFoundException {
      DateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
      Date currentDate = new Date();
      File path = new File("D:\\" + currentDate);
      if (!path.exists()) {
        path.mkdir();
      }

      if (pBuffer == null || dwBufSize <= 0) {
        return;
      }

      // 小图的 stuObject.nRelativeID 来匹配大图的 stuObject.nObjectID,来判断是不是 一起的图片
      if (groupId != faceDetectInfo.stuObject.nRelativeID) { // /->保存全景图
        personBufferedImage = null;
        groupId = faceDetectInfo.stuObject.nObjectID;

        String strGlobalPicPathName =
                path + "\\" + faceDetectInfo.UTC.toStringTitle() + "_FaceDetection_Global.jpg";
        byte[] bufferGlobal = pBuffer.getByteArray(0, dwBufSize);
        ByteArrayInputStream byteArrInputGlobal = new ByteArrayInputStream(bufferGlobal);

        try {
          globalBufferedImage = ImageIO.read(byteArrInputGlobal);
          if (globalBufferedImage != null) {
            File globalFile = new File(strGlobalPicPathName);
            if (globalFile != null) {
              ImageIO.write(globalBufferedImage, "jpg", globalFile);
            }
          }
        } catch (IOException e2) {
          e2.printStackTrace();
        }
      } else if (groupId == faceDetectInfo.stuObject.nRelativeID) { // /->保存人脸图
        if (faceDetectInfo.stuObject.stPicInfo != null) {
          String strPersonPicPathName =
                  path + "\\" + faceDetectInfo.UTC.toStringTitle() + "_FaceDetection_Person.jpg";
          byte[] bufferPerson = pBuffer.getByteArray(0, dwBufSize);
          ByteArrayInputStream byteArrInputPerson = new ByteArrayInputStream(bufferPerson);

          try {
            personBufferedImage = ImageIO.read(byteArrInputPerson);
            if (personBufferedImage != null) {
              File personFile = new File(strPersonPicPathName);
              if (personFile != null) {
                ImageIO.write(personBufferedImage, "jpg", personFile);
              }
            }
          } catch (IOException e2) {
            e2.printStackTrace();
          }
        }
      }
    }
  }

  // 订阅
  public void RealLoadPicture(int channel, int bNeedPicture, NetSDKLib.fAnalyzerDataCallBack callback) {
    loginHandle = netsdk.CLIENT_RealLoadPictureEx(loginHandle, channel,
            NetSDKLib.EVENT_IVS_ALL, bNeedPicture, callback, null, null);
    if (loginHandle.longValue() == 0) {
      System.err.println("CLIENT_RealLoadPictureEx Failed, Error:" + ToolKits.getErrorCodePrint());
    } else {
      System.out.println("通道[" + channel + "]订阅成功!");
    }

  }

  private static boolean bInit = false;
  private static boolean bLogopen = false;

  //初始化
  public static boolean InitTest(NetSDKLib.fDisConnect disConnect, NetSDKLib.fHaveReConnect haveReConnect) {
    bInit = netsdk.CLIENT_Init(disConnect, null);
    if (!bInit) {
      System.out.println("Initialize SDK failed");
      return false;
    }

    //打开日志,可选
    NetSDKLib.LOG_SET_PRINT_INFO setLog = new NetSDKLib.LOG_SET_PRINT_INFO();
    File path = new File("./sdklog/");
    if (!path.exists()) {
      path.mkdir();
    }
    String logPath = path.getAbsoluteFile().getParent() + "\\sdklog\\" + ToolKits.getDate() + ".log";
    setLog.nPrintStrategy = 0;
    setLog.bSetFilePath = 1;
    System.arraycopy(logPath.getBytes(), 0, setLog.szLogFilePath, 0, logPath.getBytes().length);
    System.out.println(logPath);
    setLog.bSetPrintStrategy = 1;
    bLogopen = netsdk.CLIENT_LogOpen(setLog);
    if (!bLogopen) {
      System.err.println("Failed to open NetSDK log");
    }

    // 设置断线重连回调接口,设置过断线重连成功回调函数后,当设备出现断线情况,SDK内部会自动进行重连操作
    // 此操作为可选操作,但建议用户进行设置
    netsdk.CLIENT_SetAutoReconnect(haveReConnect, null);

    //设置登录超时时间和尝试次数,可选
    int waitTime = 5000; //登录请求响应超时时间设置为5S
    int tryTimes = 1;    //登录时尝试建立链接1次
    netsdk.CLIENT_SetConnectTime(waitTime, tryTimes);


    // 设置更多网络参数,NET_PARAM的nWaittime,nConnectTryNum成员与CLIENT_SetConnectTime
    // 接口设置的登录设备超时时间和尝试次数意义相同,可选
    NetSDKLib.NET_PARAM netParam = new NetSDKLib.NET_PARAM();
    netParam.nConnectTime = 10000;      // 登录时尝试建立链接的超时时间
    netParam.nGetConnInfoTime = 3000;   // 设置子连接的超时时间
    netParam.nGetDevInfoTime = 3000;//获取设备信息超时时间,为0默认1000ms
    netsdk.CLIENT_SetNetworkParam(netParam);

    return true;
  }

  //登陆
  public void Login() {
    // 登陆设备
    int nSpecCap = NetSDKLib.EM_LOGIN_SPAC_CAP_TYPE.EM_LOGIN_SPEC_CAP_TCP;    // TCP登入
    IntByReference nError = new IntByReference(0);
    loginHandle = netSdk.CLIENT_LoginEx2(m_strIp, m_nPort, m_strUser,
            m_strPassword, nSpecCap, null, deviceInfo, nError);
    if (loginHandle.longValue() != 0) {
      System.out.printf("Login Device[%s] Success!\n", m_strIp);
    } else {
      System.err.printf("Login Device[%s] Fail.Error[0x%x]\n", m_strIp, netSdk.CLIENT_GetLastError());
      LoginOut();
    }
  }


  //登出
  public void LoginOut() {
    if (loginHandle.longValue() != 0) {
      netSdk.CLIENT_Logout(loginHandle);
    }
    System.out.println("END...");
    netSdk.CLIENT_Cleanup();
  }

  /**
   * 设备断线回调
   */
  private static class DisConnectCallBack implements NetSDKLib.fDisConnect {

    private DisConnectCallBack() {
    }

    private static class CallBackHolder {
      private static PictureHandle.DisConnectCallBack instance = new PictureHandle.DisConnectCallBack();
    }

    public static PictureHandle.DisConnectCallBack getInstance() {
      return PictureHandle.DisConnectCallBack.CallBackHolder.instance;
    }

    public void invoke(NetSDKLib.LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser) {
      System.out.printf("Device[%s] Port[%d] DisConnect!\n", pchDVRIP, nDVRPort);
    }
  }

  /**
   * 设备重连回调
   */
  private static class HaveReConnectCallBack implements NetSDKLib.fHaveReConnect {
    private HaveReConnectCallBack() {
    }

    private static class CallBackHolder {
      private static PictureHandle.HaveReConnectCallBack instance = new PictureHandle.HaveReConnectCallBack();
    }

    public static PictureHandle.HaveReConnectCallBack getInstance() {
      return PictureHandle.HaveReConnectCallBack.CallBackHolder.instance;
    }

    public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
      System.out.printf("ReConnect Device[%s] Port[%d]\n", pchDVRIP, nDVRPort);

    }
  }
}


开发流程:
1、根据sdk 运行人脸识别demo

2、查找对应订阅的代码转成对于的web代码

3、由于是使用 main方法,需加上阻止程序执行完的代码

4、在对于存放地址D盘下能看到 人类对比信息的txt文件和图片
注意:
1、需自己开发调用NetSDKLib里的方法,不能直接调用提供的demo、model里的方法,只能参考,官网的代码是java swing 图形界面开发方式,web方式的需自行参考demo转换。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值