package com.netsdk.demo.customize.faceReconEx; import com.netsdk.demo.util.CaseMenu; import com.netsdk.demo.util.PaintJPanel; import com.netsdk.lib.NetSDKLib; import com.netsdk.lib.ToolKits; import com.netsdk.lib.Utils; import com.netsdk.lib.enumeration.EM_PERSON_FEATURE_ERRCODE; import com.netsdk.lib.enumeration.ENUMERROR; import com.sun.jna.Memory; import com.sun.jna.ptr.IntByReference; import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Scanner; import static com.netsdk.lib.NetSDKLib.EM_CERTIFICATE_TYPE.CERTIFICATE_TYPE_IC; import static com.netsdk.lib.Utils.getOsPrefix; /** * @author : 47040 * @since : Created in 2020/7/20 16:28 */ public class FaceReconExDemo { // The constant net sdk public static final NetSDKLib netsdk = NetSDKLib.NETSDK_INSTANCE; // The constant config sdk. public static NetSDKLib configsdk = NetSDKLib.CONFIG_INSTANCE; public static String encode; static { String osPrefix = getOsPrefix(); if (osPrefix.toLowerCase().startsWith("win32-amd64")) { encode = "GBK"; } else if (osPrefix.toLowerCase().startsWith("linux-amd64")) { encode = "UTF-8"; } } ////////////////////////////////////// 登录相关 /////////////////////////////// ////////////////////////////////////////////////////////////////////////////// private NetSDKLib.NET_DEVICEINFO_Ex deviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex(); // 设备信息 private NetSDKLib.LLong m_hLoginHandle = new NetSDKLib.LLong(0); // 登录句柄 /** login with high level 高安全级别登陆 */ public void loginWithHighLevel() { NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY pstlnParam = new NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY() { { szIP = m_strIpAddr.getBytes(); nPort = m_nPort; szUserName = m_strUser.getBytes(); szPassword = m_strPassword.getBytes(); } }; // 输入结构体参数 NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY pstOutParam = new NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY(); // 输结构体参数 // 写入sdk m_hLoginHandle = netsdk.CLIENT_LoginWithHighLevelSecurity(pstlnParam, pstOutParam); if (m_hLoginHandle.longValue() == 0) { System.err.printf( "Login Device[%s] Port[%d]Failed. %s\n", m_strIpAddr, m_nPort, netsdk.CLIENT_GetLastError()); } else { deviceInfo = pstOutParam.stuDeviceInfo; // 获取设备信息 System.out.println("Login Success"); System.out.println("Device Address:" + m_strIpAddr); System.out.println("设备包含:" + deviceInfo.byChanNum + "个通道"); } } /** logout 退出 */ public void logOut() { if (m_hLoginHandle.longValue() != 0) { netsdk.CLIENT_Logout(m_hLoginHandle); System.out.println("LogOut Success"); } } //////////////////////////////////////// 订阅事件/退订 /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// private NetSDKLib.LLong m_hAttachHandle = new NetSDKLib.LLong(0); // 订阅相关 private final NetSDKLib.fAnalyzerDataCallBack analyzerDataCB = FaceReconAnalyzerDataCallBack.getSingleInstance(); private int channel = 0; public void setChannelID() { System.out.println("请输入通道,从0开始计数,-1表示全部"); Scanner sc = new Scanner(System.in); this.channel = sc.nextInt(); } public void AttachEventRealLoadPic() { this.DetachEventRealLoadPic(); // 先退订,设备不会对重复订阅作校验,重复订阅后会有重复的事件返回 int bNeedPicture = 1; // 需要图片 m_hAttachHandle = netsdk.CLIENT_RealLoadPictureEx( m_hLoginHandle, channel, NetSDKLib.EVENT_IVS_ALL, bNeedPicture, analyzerDataCB, null, null); if (m_hAttachHandle.longValue() != 0) { System.out.printf("Chn[%d] CLIENT_RealLoadPictureEx Success\n", channel); } else { System.out.printf( "Ch[%d] CLIENT_RealLoadPictureEx Failed!LastError = %s\n", channel, ToolKits.getErrorCode()); } } /** 停止侦听智能事件 */ public void DetachEventRealLoadPic() { if (m_hAttachHandle.longValue() != 0) { netsdk.CLIENT_StopLoadPic(m_hAttachHandle); } } private String faceUid; public void addPerson() throws IOException { // 人脸图片 BufferedImage jpg = ImageIO.read(new File("D:/新建文件夹/psc2-large.jpg")); ByteArrayOutputStream byteArrOutput = new ByteArrayOutputStream(); ImageIO.write(jpg, "jpg", byteArrOutput); ////////////////// 获取背景图的缓存、宽高 ///////////// byte[] buffer = byteArrOutput.toByteArray(); // jpg格式的Buf Memory memory = new Memory(buffer.length); memory.write(0, buffer, 0, buffer.length); faceUid = addTargetRecognitionDB( "1", buffer.length, jpg.getWidth(), jpg.getHeight(), memory, "person1", (byte) 1, Arrays.asList("2021", "04", "28").toArray(new String[] {}), "浙江", "杭州", "1", (byte) 1); } /** * 添加人员信息(即注册人脸) * * @param groupId 组ID(人脸库ID) * @param nPicBufLen 图片大小 * @param width 图片宽 * @param height 图片高 * @param memory 保存图片的缓存 * @param personName 人员名称 * @param bySex 性别 * @param birthday 生日(年月日数组) * @param province 省份 * @param id 证件编号 * @param byIdType 证件类型 * @return 新增人脸的uid(uid由设备生成,具备唯一性) */ public String addTargetRecognitionDB( String groupId, int nPicBufLen, int width, int height, Memory memory, String personName, byte bySex, String[] birthday, String province, String city, String id, byte byIdType) { // 入参 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); // 生日设置 stuIn.stPersonInfoEx.wYear = (short) Integer.parseInt(birthday[0]); stuIn.stPersonInfoEx.byMonth = (byte) Integer.parseInt(birthday[1]); stuIn.stPersonInfoEx.byDay = (byte) Integer.parseInt(birthday[2]); // 性别,1-男,2-女,作为查询条件时,此参数填0,则表示此参数无效 stuIn.stPersonInfoEx.bySex = bySex; // 人员名字 try { System.arraycopy( personName.getBytes(encode), 0, stuIn.stPersonInfoEx.szPersonName, 0, personName.getBytes(encode).length); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 证件类型 stuIn.stPersonInfoEx.byIDType = byIdType; // 人员唯一标识(证件号码,工号,或其他编号) System.arraycopy(id.getBytes(), 0, stuIn.stPersonInfoEx.szID, 0, id.getBytes().length); // 国际,符合ISO3166规范 System.arraycopy("CN".getBytes(), 0, stuIn.stPersonInfoEx.szCountry, 0, "CN".getBytes().length); // 省份 try { System.arraycopy( province.getBytes(encode), 0, stuIn.stPersonInfoEx.szProvince, 0, province.getBytes(encode).length); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 城市 try { System.arraycopy( city.getBytes(encode), 0, stuIn.stPersonInfoEx.szCity, 0, city.getBytes(encode).length); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 图片张数、大小、宽、高、缓存设置 if (memory != null) { stuIn.stPersonInfoEx.wFacePicNum = 1; // 图片张数 stuIn.stPersonInfoEx.szFacePicInfo[0].dwFileLenth = nPicBufLen; stuIn.stPersonInfoEx.szFacePicInfo[0].dwOffSet = 0; stuIn.stPersonInfoEx.szFacePicInfo[0].wWidth = (short) width; stuIn.stPersonInfoEx.szFacePicInfo[0].wHeight = (short) height; stuIn.nBufferLen = nPicBufLen; stuIn.pBuffer = memory; } // 出参 NetSDKLib.NET_OUT_OPERATE_FACERECONGNITIONDB stuOut = new NetSDKLib.NET_OUT_OPERATE_FACERECONGNITIONDB(); stuIn.write(); if (netsdk.CLIENT_OperateFaceRecognitionDB(m_hLoginHandle, stuIn, stuOut, 3000)) { stuOut.read(); System.out.println( "添加人员成功!,szUID: " + new String(stuOut.szUID, Charset.forName(Utils.getPlatformEncode())).trim()); } else { System.out.println("添加人员信息失败,失败原因: " + ENUMERROR.getErrorMessage()); return "-1"; } stuIn.read(); return new String(stuOut.szUID, Charset.forName(Utils.getPlatformEncode())).trim(); } public void queryStatus() { if (Integer.parseInt(faceUid) > 0) { searchByPicture(faceUid, "1", 0); } else { System.out.println("uid 无效,请重试"); } } /** * 查询状态 * * @param uid 人员uid * @param channel 通道号(查询注册库与通道无关,0,-1均可) * @param groudId 人脸库的id */ public void searchByPicture(String uid, String groudId, int channel) { // IVSS设备,查询条件只有 stInStartFind.stPerson 里的参数有效 NetSDKLib.NET_IN_STARTFIND_FACERECONGNITION stInStartFind = new NetSDKLib.NET_IN_STARTFIND_FACERECONGNITION(); NetSDKLib.LLong findHandle; int nToken; // 通道号 stInStartFind.nChannelID = channel; stInStartFind.bPersonExEnable = 1; // 人员信息查询条件是否有效, 并使用扩展结构体 stInStartFind.stFilterInfo.nUIDNum = 1; // uid 64*32,每个uid占32字节,最多64个uid byte[] szUid = uid.getBytes(Charset.forName(Utils.getPlatformEncode())); System.arraycopy(szUid, 0, stInStartFind.stFilterInfo.szUIDs, 0 * 32, szUid.length); // System.arraycopy(szUid, 0, stInStartFind.stPersonInfoEx.szUID, 0, szUid.length); // System.arraycopy(szGroudId, 0, stInStartFind.stPersonInfoEx.szGroupID, 0, szGroudId.length); stInStartFind.stFilterInfo.nGroupIdNum = 1; byte[] szGroupId = groudId.getBytes(Charset.forName(Utils.getPlatformEncode())); System.arraycopy( szGroupId, 0, stInStartFind.stFilterInfo.szGroupIdArr[0].szGroupId, 0, szGroupId.length); // 查询注册库 stInStartFind.stFilterInfo.szRange[0] = NetSDKLib.EM_FACE_DB_TYPE.NET_FACE_DB_TYPE_BLACKLIST; stInStartFind.stFilterInfo.emFaceType = NetSDKLib.EM_FACERECOGNITION_FACE_TYPE.EM_FACERECOGNITION_FACE_TYPE_ALL; // 让设备根据查询条件整理结果集 NetSDKLib.NET_OUT_STARTFIND_FACERECONGNITION stOutParam = new NetSDKLib.NET_OUT_STARTFIND_FACERECONGNITION(); stInStartFind.write(); stOutParam.write(); if (netsdk.CLIENT_StartFindFaceRecognition(m_hLoginHandle, stInStartFind, stOutParam, 2000)) { findHandle = stOutParam.lFindHandle; if (stOutParam.nTotalCount == 0) { System.out.println("查询结果为空,请检查查询条件"); return; } if (stOutParam.nTotalCount == -1) { // -1表示总条数未生成,要推迟获取, 使用CLIENT_AttachFaceFindState接口状态 nToken = stOutParam.nToken; // 入参 NetSDKLib.NET_IN_FACE_FIND_STATE pstInParam = new NetSDKLib.NET_IN_FACE_FIND_STATE(); pstInParam.nTokenNum = 1; pstInParam.nTokens = new IntByReference(nToken); // 查询令牌 pstInParam.cbFaceFindState = DefaultFaceFindStateCallback.getInstance(); // 出参 NetSDKLib.NET_OUT_FACE_FIND_STATE pstOutParam = new NetSDKLib.NET_OUT_FACE_FIND_STATE(); pstInParam.write(); NetSDKLib.LLong attachFaceHandle = netsdk.CLIENT_AttachFaceFindState(m_hLoginHandle, pstInParam, pstOutParam, 4000); pstInParam.read(); if (attachFaceHandle.longValue() != 0) { System.out.println("AttachFaceFindState Succeed!"); } // 等待进度完成 try { while (DefaultFaceFindStateCallback.getInstance() .getProgress(m_hLoginHandle.longValue(), attachFaceHandle.longValue(), nToken) < 100) {} // 进度到100 doFindSearchByPicture(findHandle, 10); } catch (InterruptedException e) { e.printStackTrace(); } } else { doFindSearchByPicture(findHandle, 10); } } else { System.out.println( "CLIENT_StartFindFaceRecognition Failed, Error:" + ToolKits.getErrorCode()); } } /** * 以图搜图 * * @param longHandle CLIENT_StartFindFaceRecognition 接口返回的查询句柄 * @param count 查询的个数 */ public void doFindSearchByPicture(NetSDKLib.LLong longHandle, int count) { int doNextCount = 0; // 分页查找数据 NetSDKLib.NET_IN_DOFIND_FACERECONGNITION stFindIn = new NetSDKLib.NET_IN_DOFIND_FACERECONGNITION(); stFindIn.lFindHandle = longHandle; stFindIn.nCount = 10; // 当前想查询的记录条数 stFindIn.nBeginNum = 0; // 每次递增 NetSDKLib.NET_OUT_DOFIND_FACERECONGNITION stFindOut = new NetSDKLib.NET_OUT_DOFIND_FACERECONGNITION(); stFindOut.bUseCandidatesEx = 1; // 是否使用候选对象扩展结构体 for (int i = 0; i < count; i++) { stFindOut.stuCandidatesEx[i].stPersonInfo.szFacePicInfo[0].nFilePathLen = 256; stFindOut.stuCandidatesEx[i].stPersonInfo.szFacePicInfo[0].pszFilePath = new Memory(256); } do { stFindIn.write(); stFindOut.write(); if (netsdk.CLIENT_DoFindFaceRecognition(stFindIn, stFindOut, 1000)) { System.out.printf("Record Number [%d]\n", stFindOut.nCadidateExNum); if (stFindOut.nCadidateExNum == 0) { System.out.println("没有查询到相关数据"); break; } for (int i = 0; i < stFindOut.nCadidateExNum; i++) { int index = i + doNextCount * count; // 查询的总个数 - 1, 从0开始 // 建模状态 /** 0:未知 1:建模失败,可能是图片不符合要求,需要换图片 2:有可用的特征值 3:正在计算特征值 4:已建模,但算法升级导致数据不可用,需要重新建模 */ int status = stFindOut.stuCandidatesEx[i].stPersonInfo.emFeatureState; System.out.println("建模状态: " + status); // 如果建模失败,打印建模失败原因 if (status == 1) { System.out.println( "失败原因: " + EM_PERSON_FEATURE_ERRCODE.getErrorMessage( stFindOut.stuCandidatesEx[i].stPersonInfo.emFeatureErrCode)); } } } else { System.out.println( "CLIENT_DoFindFaceRecognition Failed, Error:" + ENUMERROR.getErrorMessage()); break; } if (stFindOut.nCadidateNum < stFindIn.nCount) { System.out.println("没有更多数据,结束查询"); break; } else { stFindIn.nBeginNum += count; doNextCount++; } } while (true); netsdk.CLIENT_StopFindFaceRecognition(longHandle); } /////////////////////////////////////// 简易控制台 /////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // 初始化测试 public void InitTest() { FaceReconExUtils.Init(); // 初始化SDK库 this.loginWithHighLevel(); // 高安全登录 } // 加载测试内容 public void RunTest() { CaseMenu menu = new CaseMenu(); menu.addItem(new CaseMenu.Item(this, "选择通道", "setChannelID")); menu.addItem(new CaseMenu.Item(this, "订阅任务", "AttachEventRealLoadPic")); menu.addItem(new CaseMenu.Item(this, "退订任务", "DetachEventRealLoadPic")); menu.addItem(new CaseMenu.Item(this, "添加人脸", "addPerson")); menu.addItem(new CaseMenu.Item(this, "查询人员建模状态", "queryStatus")); menu.run(); } // 结束测试 public void EndTest() { System.out.println("End Test"); this.logOut(); // 退出 System.out.println("See You..."); FaceReconExUtils.cleanAndExit(); // 清理资源并退出 } /////////////// 配置登陆地址,端口,用户名,密码 //////////////////////// // private String m_strIpAddr = "172.23.12.29"; // 模拟器 private String m_strIpAddr = "172.12.245.68"; // 模拟器 private int m_nPort = 37777; private String m_strUser = "admin"; private String m_strPassword = "admin123"; ////////////////////////////////////////////////////////////////////// public static void main(String[] args) { FaceReconExDemo demo = new FaceReconExDemo(); if (args.length == 4) { demo.m_strIpAddr = args[0]; demo.m_nPort = Integer.parseInt(args[1]); demo.m_strUser = args[2]; demo.m_strPassword = args[3]; } demo.InitTest(); if (demo.m_hLoginHandle.longValue() != 0) { demo.RunTest(); } demo.EndTest(); } }