大家好,欢迎来到IT知识分享网。
目录
背景说明:
使用NVR网络录像机接入监控摄像头,NVR内置人脸库、人脸抓拍、比对功能、事件配置。
使用的设备型号:DS-9632NX-I8R/VPro
1、初始化配置
1.1、设置通道默认密码
1.2、添加摄像头
NVR具有自动广播功能,可以在下方的设备列表中显示所有摄像头。
然后选中添加上上方列表,开启监控。

注意勾选默认密码,否则会引起连接失败问题

1.3、设置不采集时间段
下图灰白区域表示摄像头不采集、不启用事件的事件范围,
选择一个摄像头进行配置
批量复制到其他监控
1.4、抓拍延迟设置
此处设置的开头、结尾延迟5秒,为后续的人物目标识别成功后,截取视频时间段前后五秒,共10秒的视频。默认延迟30s
1.5、录像保存时长设置
1.6、人脸库维护
1.7、导入照片
由于nvr限定jpg、jpeg类型,不支持png,所以需要进行转码
具体参见 Java工具-实现无损png转换jpg格式-CSDN博客
1.8、设置事件
1.8.1、引擎配置
必须要设置目标识别,否则人脸库无法建模,后续人脸目标比对无法进行。
1.8.2、事件设置
选择目标事件,确定必须启用
1.8.2.1、目标比对
选择目标比对,开启,
1.8.2.2、设置屏蔽区
点击右键绘图完毕
1.8.2.3、人脸库
关联人脸库和阈值设置
如果需要提高图片质量,可以设置仰俯角,避免低头、偏头图片
1.9、事件检索
在下图,设置检索条件
2、ISAPI透传对接
2.1、下载SDK包
地址:海康开放平台
下载对应操作系统的开发包
2.2、检查是否支持ISAPI
注意检查默认登录端口8000
选择内部的ISAPI透传的demo
2.3、引入依赖
将对应的库文件引入到项目的lib下
2.4、启动demo
启动类 JavaDemoSTDXMLConfigApp
启动后效果,使用这个demo可以进行api调试。
后续可以参照平台的接口出入参进行对接开发
3、java端接入
3.1、项目结构
win下存放dll文件,需要额外引入 sdk中的examples.jar、jna.jar文件
其中 HIKSDKStructure 类用于解决兼容低版本的Structure调用问题
import com.sun.jna.Structure; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; /* * 由于 这个问题是因为海康jna.jar比较老,结构体定义没有getFiledOrder,可创建一个类继承 Structure * 产生错误:Structure.getFieldOrder() on class com.xxx.sdk.HCNetSDK$NET_DVR_DEVICEINFO_V30 does not provide enough names [0] ([]) to match declared fields [31] ([byAlarmInPortNum, * 解决:对 HCNetSDK 接口中的静态类里面,所有继承 Structure 替换为 HIKSDKStructure 即可 * @author xuancg * @date 2024/6/13 */ public class HIKSDKStructure extends Structure { protected List<String> getFieldOrder(){ List<String> fieldOrderList = new ArrayList<String>(); for (Class<?> cls = getClass(); !cls.equals(HIKSDKStructure.class); cls = cls.getSuperclass()) { Field[] fields = cls.getDeclaredFields(); int modifiers; for (Field field : fields) { modifiers = field.getModifiers(); if (Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) { continue; } fieldOrderList.add(field.getName()); } } return fieldOrderList; } }
HCNetSDK 类可以通过sdk中查找引入。但需要将所有的Structure 替换为HIKSDKStructure
public class OsSelect { public static boolean isLinux() { return System.getProperty("os.name").toLowerCase().contains("linux"); } public static boolean isWindows() { return System.getProperty("os.name").toLowerCase().contains("windows"); } }
3.2、类属性定义
static HCNetSDK hCNetSDK = null; static int lUserID;//用户句柄 private static String rootPath; public static final int ISAPI_DATA_LEN = 1024*1024; public static final int ISAPI_STATUS_LEN = 4*4096; public static final int BYTE_ARRAY_LEN = 1024;
3.3、初始化
public static boolean init(){ if(null == rootPath){ rootPath = System.getProperty("user.dir"); //由于我是多模块下的,此处路径存在问题,实际最好通过外部配置定义 rootPath += "/my-project"; } log.info("加载lib路径=" + rootPath); if (hCNetSDK == null) { if (!createSDKInstance()) { System.out.println("Load SDK fail"); return false; } } //linux系统建议调用以下接口加载组件库 if (OsSelect.isLinux()) { HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256); HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256); // TODO 需要下载对应linux版本 并替换 //这里是库的绝对路径,请根据实际情况修改,注意改路径必须有访问权限 String strPath1 = rootPath + "/libs/libcrypto.so.1.1"; String strPath2 = rootPath + "/libs/libssl.so.1.1"; System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length()); ptrByteArray1.write(); hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer()); System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length()); ptrByteArray2.write(); hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer()); String strPathCom = rootPath + "/libs/"; HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH(); System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length()); struComPath.write(); hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer()); } boolean initSuc = hCNetSDK.NET_DVR_Init(); if (initSuc != true) { log.info("初始化失败"); } /加载日志*/ return hCNetSDK.NET_DVR_SetLogToFile(3, "./sdklog", false); } private static boolean createSDKInstance() { if (hCNetSDK == null) { synchronized (HCNetSDK.class) { String strDllPath = ""; try { if (OsSelect.isWindows()) //win系统加载SDK库路径 strDllPath = rootPath + "\\libs\\win\\HCNetSDK.dll"; else if (OsSelect.isLinux()) //Linux系统加载SDK库路径 strDllPath = rootPath + "/libs/linux/libhcnetsdk.so"; hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class); } catch (Exception ex) { System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage()); return false; } } } return true; }
3.4、登录
/ * 登录,端口默认8000,成功后会将其他终端登录下线 * @param sDeviceIP ip地址 * @param sUsername 登录名 * @param sPassword 密码 */ public static boolean loginByV40(String sDeviceIP,String sUsername,String sPassword){ //注册之前先注销已注册的用户,预览情况下不可注销 if (lUserID > -1) { //先注销 hCNetSDK.NET_DVR_Logout(lUserID); lUserID = -1; } //注册 HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息 HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息 m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN]; System.arraycopy(sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, sDeviceIP.length()); m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN]; System.arraycopy(sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, sUsername.length()); m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN]; System.arraycopy(sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, sPassword.length()); m_strLoginInfo.wPort = 8000; // 此处只能设置0,否则errcode=9 m_strLoginInfo.byLoginMode = 0; //登录模式(不同模式具体含义详见“Remarks”说明):0- SDK私有协议,1- ISAPI协议,2- 自适应(设备支持协议类型未知时使用,一般不建议) m_strLoginInfo.byHttps = 0; //ISAPI协议登录时是否启用HTTPS(byLoginMode为1时有效):0- 不启用,1- 启用,2- 自适应(设备支持协议类型未知时使用,一般不建议) m_strLoginInfo.bUseAsynLogin = false; //是否异步登录:0- 否,1- 是 m_strLoginInfo.write(); lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo); if (lUserID == -1) { // 9-从设备接收数据失败。 log.info("注册失败,错误号:" + hCNetSDK.NET_DVR_GetLastError()); } else { log.info("注册成功,lUserID=" + lUserID); } return true; } // 登出 public void logout() { //注销 if (lUserID > -1) { //先注销 hCNetSDK.NET_DVR_Logout(lUserID); lUserID = -1; } hCNetSDK.NET_DVR_Cleanup(); }
3.5、发起ISAPI调用
/ * 事件搜索 * @param req * @return */ public EventRecordSearchResp eventSearchApi(EventRecordSearchReq req) { HCNetSDK.NET_DVR_XML_CONFIG_INPUT struXMLInput = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT(); struXMLInput.read(); struXMLInput.dwSize = struXMLInput.size(); String strURL = "POST /ISAPI/ContentMgmt/eventRecordSearch?format=json"; int iURLlen = strURL.length(); HCNetSDK.BYTE_ARRAY ptrUrl = new HCNetSDK.BYTE_ARRAY(iURLlen+1); System.arraycopy(strURL.getBytes(), 0, ptrUrl.byValue, 0, strURL.length()); ptrUrl.write(); struXMLInput.lpRequestUrl = ptrUrl.getPointer(); struXMLInput.dwRequestUrlLen = iURLlen; String strInbuffer = JSONUtil.toJsonStr(req); int iInBufLen = strInbuffer.length(); if(iInBufLen==0) { struXMLInput.lpInBuffer=null; struXMLInput.dwInBufferSize=0; struXMLInput.write(); } else { HCNetSDK.BYTE_ARRAY ptrInBuffer = new HCNetSDK.BYTE_ARRAY(iInBufLen+1); ptrInBuffer.read(); ptrInBuffer.byValue = strInbuffer.getBytes(); ptrInBuffer.write(); struXMLInput.lpInBuffer = ptrInBuffer.getPointer(); struXMLInput.dwInBufferSize = iInBufLen; struXMLInput.write(); } HCNetSDK.BYTE_ARRAY ptrStatusByte = new HCNetSDK.BYTE_ARRAY(ISAPI_STATUS_LEN); ptrStatusByte.read(); HCNetSDK.BYTE_ARRAY ptrOutByte = new HCNetSDK.BYTE_ARRAY(ISAPI_DATA_LEN); ptrOutByte.read(); HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT struXMLOutput = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT(); struXMLOutput.read(); struXMLOutput.dwSize = struXMLOutput.size(); struXMLOutput.lpOutBuffer = ptrOutByte.getPointer(); struXMLOutput.dwOutBufferSize = ptrOutByte.size(); struXMLOutput.lpStatusBuffer = ptrStatusByte.getPointer(); struXMLOutput.dwStatusSize = ptrStatusByte.size(); struXMLOutput.write(); if(!hCNetSDK.NET_DVR_STDXMLConfig(lUserID, struXMLInput, struXMLOutput)) { int iErr = hCNetSDK.NET_DVR_GetLastError(); log.error( "NET_DVR_STDXMLConfig失败,错误号:" + iErr); return null; } else { struXMLOutput.read(); ptrOutByte.read(); ptrStatusByte.read(); // 输出结果 String strOutXML = new String(ptrOutByte.byValue).trim(); // 输出状态 String strStatus = new String(ptrStatusByte.byValue).trim(); return JSONUtil.toBean(strOutXML, EventRecordSearchResp.class); } }
3.6、入参对象
import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter; import java.util.UUID; /* * 事件搜索入参 * @author xuancg * @date 2024/6/14 */ @Data public class EventRecordSearchReq { private EventSearchDescription EventSearchDescription; public void setChannels(int...channels){ this.EventSearchDescription.setChannels(channels); } public void setEventType(EventType type){ this.EventSearchDescription.setEventType(type.name()); } public void setAlarmResult(AlarmResult type){ this.EventSearchDescription.setAlarmResultAuxEventType(type.name()); } public void setPageNum(int pageNum){ this.EventSearchDescription.setMaxResults(pageNum); } / * 默认从1开始 * @param pageSize */ public void setPageSize(int pageSize){ int offset = (pageSize - 1) * this.EventSearchDescription.getMaxResults(); if(offset < 0){ offset = 0; } this.EventSearchDescription.setSearchResultPosition(offset); } @Data public class EventSearchDescription{ public EventSearchDescription() { this.searchID = UUID.randomUUID().toString(); } // 随机生成 搜索记录唯一标识, range:[,], desc:用来确认上层客户端是否为同一个(倘若是同一个,则设备记录内存,下次搜索加快速度) private String searchID; private String eventType; private String alarmResultAuxEventType; private int[] channels; // 每页个数 private int maxResults = 30; // 起始位置相当于offset ,如果第二页则=30 private int searchResultPosition = 0; private String type = "all"; } @Data public class timeSpanList { // 格式 2024-06-14T23:59:59 08:00 private String endTime; private String startTime; } /* * 检索类型 */ @Getter @AllArgsConstructor public enum EventType{ alarmResult("目标事件"), ; private String desc; } @Getter @AllArgsConstructor public enum AlarmResult{ alarmResultSuccess("目标比对成功"), ; private String desc; } }
3.7、出参对象
import lombok.Data; import java.util.List; /* * 事件搜索出参 * 日期格式均为=2024-06-13T11:39:00+08:00 东八区 * @author xuancg * @date 2024/6/14 */ @Data public class EventRecordSearchResp { private EventSearchResult EventSearchResult; @Data public class EventSearchResult{ /搜索结果数*/ private int numOfMatches; /是否有更多结果 MORE=是*/ private String responseStatusStrg; /总结果数*/ private int totalMatches; private List<Targets> Targets; } @Data public class Targets{ /抓拍时间*/ private String alarmEndTime; private AlarmResult alarmResult; private String alarmResultAuxEventType; /2024-06-13T11:39:00+08:00*/ private String alarmStartTime; private int channel; private String eventType; private int id; private MetadataMatches metadataMatches; /背景图地址http*/ private String pictureUrl; /人脸范围照地址http*/ private String smallPictureUrl; /前置后置延迟时间,单位秒 */ private int postRecordTimeSeconds; private int preRecordTimeSeconds; /视频采集开始时间 用于换取采集视频*/ private String startTime; private String endTime; /等同channel*/ private int triggerChannel; } @Data public class AlarmResult{ private String FDID; /人脸库名称*/ private String FDLibName; /人脸库照片地址,http开头*/ private String FDPicURL; private String ageGroup; private String gender; /人物姓名*/ private String name; /相似度,小于1*/ private float similarity; } @Data public class MetadataMatches{ private List<AssociatedMetadata> associatedMetadataUrlList; private String eventType; } @Data public class AssociatedMetadata { private AssociatedMetadataUrl associatedMetadataUrl; } @Data public class AssociatedMetadataUrl { private int channelID; /video*/ private String metadataType; } }
具体完整的代码见资源绑定
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/109988.html



























