上传人脸图片到人脸库

controller:

@RestController
@RequestMapping("/facePicture")
public class FacePictureHandleController {

    @Autowired
    private FacePictureHandleService facePictureHandleService;

    @RequestMapping(value = "/handle/uploadFile")
    public String padUploadFile(@RequestParam("file") MultipartFile file,HttpServletRequest request) {
        try {
            FacePicture facePicture=new FacePicture();
            HttpSession session = request.getSession(true);
            Map<String, String> userInfo = (Map<String, String>) session
                    .getAttribute(SessionConstants.SESSION_KEY_USER_INFO);
            facePicture.setCardId(userInfo.get("loginUser"));

            File f=null;
            String fileName = file.getOriginalFilename();
            try {
                //获取文件字节数组
                byte [] bytes = file.getBytes();
                File pfile = new File("/fileupload/");
                //判断文件夹是否存在
                if(!pfile.exists()){
                    //不存在时,创建文件夹
                    pfile.mkdirs();
                }
                //创建文件
                f = new File(pfile, fileName);
                //写入指定文件夹
                OutputStream out = new FileOutputStream(f);
                out.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
                return "上传失败";
            }


            Integer facePictureRes = facePictureHandleService.saveFacePictureHandle(facePicture,f.getPath());
            if(facePictureRes==0){
                return "上传失败";
            }
            return "上传成功";
        } catch (Exception e) {
            log.error("上传文件异常", e);
        }
        return "上传失败";
    }
}

service:

@Service
public class FacePictureHandleService {

  
    /**
    *配置文件
    */
    @Value("${groupId}")
    private String groupId;
    @Value("${uploadWaitTime}")
    private int uploadWaitTime;
    @Value("${groupName}")
    private String groupName;


    @Autowired
    private FacePictureHandleDao facePictureHandleDao;

    @Autowired
    private FaceDetectService faceDetectService;

    @Autowired
    private UserInfoDAO userInfoDao;
    /**
     * 保存人脸图片到人脸库
     * @return
     */
    public Integer saveFacePictureHandle(FacePicture facePicture, String filePath) throws UnsupportedEncodingException {
        Memory fileMemory=new Memory(2000000);
        try {
            ToolKits.ReadAllFileToMemory(filePath,fileMemory);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<UserInfo> byUserNameIn = userInfoDao.findByUserNameIn(Collections.singletonList(facePicture.getCardId()));
        facePicture.setName(byUserNameIn.get(0).getName());

        facePicture.setFaceDatabaseName(groupName);
        String gender = byUserNameIn.get(0).getGender();
        int sex=0;
        if("F".equals(gender)){
            sex=2;
        }else if("M".equals(gender)){
            sex=1;
        }


        Long  fId= facePictureHandleDao.queryFaceDatabaseId(facePicture.getCardId());

        if(fId==null){ //未上传图片
            //上传图片到人脸库
            boolean updalodRes = addPerson(groupId, fileMemory, facePicture.getName(), sex, false, "", 0, "",facePicture);
            if(updalodRes){
                facePictureHandleDao.save(facePicture);
                return 1;
            }
        }else{ //已上传过图片
            String uId = facePictureHandleDao.queryFaceDatabaseUid(fId);
            //修改人脸库图片
            boolean updalodRes = modifyPerson(groupId, uId,fileMemory, facePicture.getName(), sex, false, "", 0, "");
            if(updalodRes){
                facePicture.setId(fId);
                int i = facePictureHandleDao.updatePictureData(fId);
                return i;
            }
        }

        File file=new File(filePath);
        if(file!=null){
            file.deleteOnExit();
        }
        return 0;
    }

    public File transferToFile(MultipartFile multipartFile) {
        File file = null;
        try {
            String originalFilename = multipartFile.getOriginalFilename();
            String[] filename = originalFilename.split("\\.");

            file=File.createTempFile(filename[0]+"temp", filename[1]);

            multipartFile.transferTo(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }


    /**
     * 添加人员
     * @param groupId  人脸库ID
     * @param memory  图片数据
     * @param personName 姓名
     * @param sex  性别
     * @param isBirthday 是否下发生日
     * @param birthday  生日
     * @param byIdType  证件类型
     * @param idNo  证件号
     * @return
     */
    public  boolean addPerson(String groupId,
                                    Memory memory,
                                    String personName,
                                    int sex,
                                    boolean isBirthday,
                                    String birthday,
                                    int byIdType,
                                    String idNo,
                                    FacePicture facePicture) throws UnsupportedEncodingException {
        /*
         *  入参
         */
        NetSDKLib.NET_IN_OPERATE_FACERECONGNITIONDB stuIn  = new NetSDKLib.NET_IN_OPERATE_FACERECONGNITIONDB();
        stuIn.emOperateType = NetSDKLib.EM_OPERATE_FACERECONGNITIONDB_TYPE.NET_FACERECONGNITIONDB_ADD;

        / 使用人员扩展信息 //
        stuIn.bUsePersonInfoEx = 1;

        // 人脸库ID
        System.arraycopy(groupId.getBytes(), 0, stuIn.stPersonInfoEx.szGroupID, 0, groupId.getBytes().length);

        // 生日设置
        if(isBirthday) {
            String[] birthdays = birthday.split("-");

            stuIn.stPersonInfoEx.wYear = (short)Integer.parseInt(birthdays[0]);
            stuIn.stPersonInfoEx.byMonth = (byte)Integer.parseInt(birthdays[1]);
            stuIn.stPersonInfoEx.byDay = (byte)Integer.parseInt(birthdays[2]);
        }

        // 性别,1-男,2-女,作为查询条件时,此参数填0,则表示此参数无效
        stuIn.stPersonInfoEx.bySex = (byte)sex;

        // 人员名字
        try {
            System.arraycopy(personName.getBytes("GBK"), 0, stuIn.stPersonInfoEx.szPersonName, 0, personName.getBytes("GBK").length);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        // 证件类型
        stuIn.stPersonInfoEx.byIDType = (byte)byIdType;

        // 证件号
        System.arraycopy(idNo.getBytes(), 0, stuIn.stPersonInfoEx.szID, 0, idNo.getBytes().length);

        // 图片张数、大小、缓存设置
        if(memory != null) {
            stuIn.stPersonInfoEx.wFacePicNum = 1; // 图片张数
            stuIn.stPersonInfoEx.szFacePicInfo[0].dwFileLenth = (int)memory.size();  // 图片大小
            stuIn.stPersonInfoEx.szFacePicInfo[0].dwOffSet = 0;

            stuIn.nBufferLen = (int)memory.size();
            stuIn.pBuffer = memory;
        }

        /*
         * 出参
         */
        NetSDKLib.NET_OUT_OPERATE_FACERECONGNITIONDB stuOut = new NetSDKLib.NET_OUT_OPERATE_FACERECONGNITIONDB() ;

        stuIn.write();
        boolean bRet = faceDetectService.getNetsdk().CLIENT_OperateFaceRecognitionDB(faceDetectService.getLoginHandle(), stuIn, stuOut, uploadWaitTime);
        stuIn.read();

        if(bRet) {
            System.out.println("szUID : " + new String(stuOut.szUID).trim());
        } else {
            System.err.println(faceDetectService.netsdk.CLIENT_GetLastError());
        }

        facePicture.setFaceDatabaseUid(new String(stuOut.szUID, "GBK").trim());

        return bRet;
    }

    /**
     * 修改人员信息
     * @param groupId 人脸库ID
     * @param uid  人员唯一标识符
     * @param memory  图片数据
     * @param personName  姓名
     * @param sex  性别
     * @param isBirthday  是否下发生日
     * @param birthday  生日
     * @param byIdType  证件类型
     * @param idNo  证件号
     * @return true:成功 ,  false:失败
     */
    public  boolean modifyPerson(String groupId,
                                       String uid,
                                       Memory memory,
                                       String personName,
                                       int sex,
                                       boolean isBirthday,
                                       String birthday,
                                       int byIdType,
                                       String idNo) {
        // 入参
        NetSDKLib.NET_IN_OPERATE_FACERECONGNITIONDB stuIn  = new NetSDKLib.NET_IN_OPERATE_FACERECONGNITIONDB();
        stuIn.emOperateType = NetSDKLib.EM_OPERATE_FACERECONGNITIONDB_TYPE.NET_FACERECONGNITIONDB_MODIFY;

        / 使用人员扩展信息  
        stuIn.bUsePersonInfoEx = 1;

        // 人脸库ID
        System.arraycopy(groupId.getBytes(), 0, stuIn.stPersonInfoEx.szGroupID, 0, groupId.getBytes().length);

        // 人员唯一标识符
        System.arraycopy(uid.getBytes(), 0, stuIn.stPersonInfoEx.szUID, 0, uid.getBytes().length);

        // 生日设置
        if(isBirthday) {
            String[] birthdays = birthday.split("-");

            stuIn.stPersonInfoEx.wYear = (short)Integer.parseInt(birthdays[0]);
            stuIn.stPersonInfoEx.byMonth = (byte)Integer.parseInt(birthdays[1]);
            stuIn.stPersonInfoEx.byDay = (byte)Integer.parseInt(birthdays[2]);
        }

        // 性别,1-男,2-女,作为查询条件时,此参数填0,则表示此参数无效
        stuIn.stPersonInfoEx.bySex = (byte)sex;

        // 人员名字
        try {
            System.arraycopy(personName.getBytes("GBK"), 0, stuIn.stPersonInfoEx.szPersonName, 0, personName.getBytes("GBK").length);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        // 证件类型
        stuIn.stPersonInfoEx.byIDType = (byte)byIdType;

        // 证件号
        System.arraycopy(idNo.getBytes(), 0, stuIn.stPersonInfoEx.szID, 0, idNo.getBytes().length);

        // 图片张数、大小、缓存设置
        if(memory != null) {
            stuIn.stPersonInfoEx.wFacePicNum = 1; // 图片张数
            stuIn.stPersonInfoEx.szFacePicInfo[0].dwFileLenth = (int)memory.size();  // 图片大小
            stuIn.stPersonInfoEx.szFacePicInfo[0].dwOffSet = 0;

            stuIn.nBufferLen = (int)memory.size();
            stuIn.pBuffer = memory;
        }

        // 出参
        NetSDKLib.NET_OUT_OPERATE_FACERECONGNITIONDB stuOut = new NetSDKLib.NET_OUT_OPERATE_FACERECONGNITIONDB() ;

        stuIn.write();
        boolean b = faceDetectService.getNetsdk().CLIENT_OperateFaceRecognitionDB(faceDetectService.getLoginHandle(), stuIn, stuOut, uploadWaitTime);

        if(!b) {
            System.err.println("修改人员失败" + ToolKits.getErrorCodePrint());
            return false;
        }
        stuIn.read();

        return true;
    }


    /**
     * 查询人脸库
     * @param groupId 需要查找的人脸库ID; 为空表示查找所有的人脸库
     */
    public  NetSDKLib.NET_FACERECONGNITION_GROUP_INFO[] findGroupInfo(String groupId) {
        NetSDKLib.NET_FACERECONGNITION_GROUP_INFO[] groupInfoRet = null;

        /*
         * 入参
         */
        NetSDKLib.NET_IN_FIND_GROUP_INFO stuIn = new NetSDKLib.NET_IN_FIND_GROUP_INFO();
        System.arraycopy(groupId.getBytes(), 0, stuIn.szGroupId, 0, groupId.getBytes().length);

        /*
         * 出参
         */
        int max = 20;
        NetSDKLib.NET_FACERECONGNITION_GROUP_INFO[] groupInfo  = new NetSDKLib.NET_FACERECONGNITION_GROUP_INFO[max];
        for(int i = 0; i < max; i++) {
            groupInfo[i] = new NetSDKLib.NET_FACERECONGNITION_GROUP_INFO();
        }

        NetSDKLib.NET_OUT_FIND_GROUP_INFO stuOut = new NetSDKLib.NET_OUT_FIND_GROUP_INFO();
        stuOut.pGroupInfos = new Memory(groupInfo[0].size() * groupInfo.length);     // Pointer初始化
        stuOut.pGroupInfos.clear(groupInfo[0].size() * groupInfo.length);
        stuOut.nMaxGroupNum = groupInfo.length;

        ToolKits.SetStructArrToPointerData(groupInfo, stuOut.pGroupInfos);  // 将数组内存拷贝给Pointer

        if(faceDetectService.netsdk.CLIENT_FindGroupInfo(faceDetectService.getLoginHandle(), stuIn, stuOut, 4000)) {

            // 将Pointer的值输出到 数组 NET_FACERECONGNITION_GROUP_INFO
            ToolKits.GetPointerDataToStructArr(stuOut.pGroupInfos, groupInfo);

            if(stuOut.nRetGroupNum > 0) {
                // 根据设备返回的,将有效的人脸库信息返回
                groupInfoRet = new NetSDKLib.NET_FACERECONGNITION_GROUP_INFO[stuOut.nRetGroupNum];
                for(int i = 0; i < stuOut.nRetGroupNum; i++) {
                    groupInfoRet[i] = groupInfo[i];
                }
            }
        } else {
            System.err.println("查询人员信息失败" + ToolKits.getErrorCodePrint());
            return null;
        }

        return groupInfoRet;
    }
}

Dao(JPA):

@Repository
public interface FaceDatabasePictureDao  extends CrudRepository<FacePicture, String> {
    //查询是否已上传过图片
    @Query("select id from FacePicture where  cardId=?")
    public Long queryFaceDatabaseId(String cardId);

    //查询是否已上传过图片
    @Query("select faceDatabaseUid from FacePicture where  id=?")
    public String queryFaceDatabaseUid(Long id);



    @Modifying
    @Query(value="update FacePicture set updatedDate=sysdate()  where id=?")
    @Transactional
    public  int updatePictureData(Long id);
}

人脸识别对比

由于项目启动时就要启动,使用@PostConstruct注解。

service:

@Service
public class FaceDetectService{
    @Value("${mstrIp}")
    private String m_strIp;
    @Value("${mnPort}")
    private int m_nPort;
    @Value("${mstrUser}")
    private String m_strUser;
    @Value("${mstrPassword}")
    private String m_strPassword;

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

    @Autowired
    private FaceDetectDao faceDetectDaoA;
    private static FaceDetectDao faceDetectDao;


    @PostConstruct
    public void init() {
        faceDetectDao=this.faceDetectDaoA;
        //初始化
        InitTest(disConnect, haveReConnect);
        //登录
        Login();
        Run();
    }
    public NetSDKLib getNetsdk(){
        return netsdk;
    }
    public NetSDKLib.LLong getLoginHandle(){
        return loginHandle;
    }

    public static final NetSDKLib netsdk = NetSDKLib.NETSDK_INSTANCE;
    // 登陆句柄
    public static  NetSDKLib.LLong loginHandle = new NetSDKLib.LLong(0);
    // 订阅句柄
    private static NetSDKLib.LLong r_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;

    // 用于人脸检测
    @Value("${face.groupId}")
    private  int groupId;
    @Value("${face.channel}")
    private  int channel;
    @Value("${face.bNeedPicture}")
    private  int bNeedPicture;

    private static int index = -1;

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

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

    public void Run() {
        //订阅
        RealLoadPicture(channel, bNeedPicture, AnalyzerDataCB.getInstance());
    }




    // 设备断线回调: 通过 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 FaceDetectService.AnalyzerDataCB instance = new FaceDetectService.AnalyzerDataCB();
        }

        public static FaceDetectService.AnalyzerDataCB getInstance() {
            return FaceDetectService.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();
                    }

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

                    break;
                }
                default:
                    break;
            }

            return 0;
        }

        /**
         * 保存人脸对比信息
         */
        public void saveFaceDetectInfo(NetSDKLib.DEV_EVENT_FACERECOGNITION_INFO faceMsg) throws IOException {

            //人脸信息
            if (faceMsg.stuFaceData != null) {
                    Res res=new Res();
                    FaceDetect faceDetect =new FaceDetect();

                    faceDetect.setName(new String(faceMsg.stuCandidatesEx[0].stPersonInfo.szPersonName, "GBK")
                            .trim());
                    faceDetect.setSex(res.getSex(faceMsg.stuFaceData.emSex));
                    faceDetect.setDetectTime(Timestamp.valueOf(faceMsg.UTC.toString()));
                    faceDetect.setFaceDatabaseName(new String(faceMsg.stuCandidatesEx[0].stPersonInfo.szGroupName, "GBK")
                            .trim());
                    faceDetect.setSimilarity(String.valueOf(faceMsg.stuCandidatesEx[0].bySimilarity));
                    faceDetect.setFaceDatabaseUid(new String(faceMsg.stuCandidatesEx[0].stPersonInfo.szUID).trim());

                    faceDetectDao.save(faceDetect);

                }

        };

    }



    // 订阅
    public void RealLoadPicture(int channel, int bNeedPicture, NetSDKLib.fAnalyzerDataCallBack callback) {
        r_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 + "]订阅成功!");
        }

    }




    //初始化
    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 FaceDetectService.DisConnectCallBack instance = new FaceDetectService.DisConnectCallBack();
        }

        public static FaceDetectService.DisConnectCallBack getInstance() {
            return FaceDetectService.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 FaceDetectService.HaveReConnectCallBack instance = new FaceDetectService.HaveReConnectCallBack();
        }

        public static FaceDetectService.HaveReConnectCallBack getInstance() {
            return FaceDetectService.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);

        }
    }
}

Dao(JPA):

@Repository
public interface FaceDetectDao extends CrudRepository<FaceDetect, String> {

}

注意:

1、上传图片到人脸库时有一个问题,修改人员信息时,修改的图片与上一个图片是同一张时时会导致图片是空的(不知道什么原因)。

2、new Memory设置太大会导致超时。