【海康威视】-NVR使用及ISAPI协议透传接入

【海康威视】-NVR使用及ISAPI协议透传接入背景说明 使用 NVR 网络录像机接入监控摄像头 NVR 内置人脸库 人脸抓拍 比对功能 事件配置

大家好,欢迎来到IT知识分享网。

目录

1、初始化配置

1.1、设置通道默认密码

1.2、添加摄像头

1.3、设置不采集时间段

1.4、抓拍延迟设置

1.5、录像保存时长设置

1.6、人脸库维护

1.7、导入照片

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

2.3、引入依赖

2.4、启动demo

3、java端接入

3.1、项目结构

3.2、类属性定义

3.3、初始化 

3.4、登录

3.5、发起ISAPI调用

3.6、入参对象

3.7、出参对象


背景说明:

使用NVR网络录像机接入监控摄像头,NVR内置人脸库、人脸抓拍、比对功能、事件配置。

使用的设备型号:DS-9632NX-I8R/VPro

1、初始化配置

【海康威视】-NVR使用及ISAPI协议透传接入

1.1、设置通道默认密码

【海康威视】-NVR使用及ISAPI协议透传接入

1.2、添加摄像头

NVR具有自动广播功能,可以在下方的设备列表中显示所有摄像头。

然后选中添加上上方列表,开启监控。

【海康威视】-NVR使用及ISAPI协议透传接入wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==编辑

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

【海康威视】-NVR使用及ISAPI协议透传接入
【海康威视】-NVR使用及ISAPI协议透传接入wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==编辑

1.3、设置不采集时间段

下图灰白区域表示摄像头不采集、不启用事件的事件范围,

选择一个摄像头进行配置

【海康威视】-NVR使用及ISAPI协议透传接入

批量复制到其他监控

【海康威视】-NVR使用及ISAPI协议透传接入

1.4、抓拍延迟设置

此处设置的开头、结尾延迟5秒,为后续的人物目标识别成功后,截取视频时间段前后五秒,共10秒的视频。默认延迟30s

【海康威视】-NVR使用及ISAPI协议透传接入

1.5、录像保存时长设置

【海康威视】-NVR使用及ISAPI协议透传接入

1.6、人脸库维护

【海康威视】-NVR使用及ISAPI协议透传接入

1.7、导入照片

由于nvr限定jpg、jpeg类型,不支持png,所以需要进行转码

具体参见 Java工具-实现无损png转换jpg格式-CSDN博客

【海康威视】-NVR使用及ISAPI协议透传接入

1.8、设置事件

1.8.1、引擎配置

必须要设置目标识别,否则人脸库无法建模,后续人脸目标比对无法进行。

【海康威视】-NVR使用及ISAPI协议透传接入

1.8.2、事件设置

选择目标事件,确定必须启用

【海康威视】-NVR使用及ISAPI协议透传接入

1.8.2.1、目标比对

选择目标比对,开启,

【海康威视】-NVR使用及ISAPI协议透传接入

1.8.2.2、设置屏蔽区

点击右键绘图完毕

1.8.2.3、人脸库

关联人脸库和阈值设置

【海康威视】-NVR使用及ISAPI协议透传接入

如果需要提高图片质量,可以设置仰俯角,避免低头、偏头图片

【海康威视】-NVR使用及ISAPI协议透传接入

1.9、事件检索

在下图,设置检索条件

【海康威视】-NVR使用及ISAPI协议透传接入

【海康威视】-NVR使用及ISAPI协议透传接入

2、ISAPI透传对接

2.1、下载SDK包

地址:海康开放平台

下载对应操作系统的开发包

【海康威视】-NVR使用及ISAPI协议透传接入

2.2、检查是否支持ISAPI

【海康威视】-NVR使用及ISAPI协议透传接入

注意检查默认登录端口8000

【海康威视】-NVR使用及ISAPI协议透传接入

选择内部的ISAPI透传的demo

【海康威视】-NVR使用及ISAPI协议透传接入

2.3、引入依赖

将对应的库文件引入到项目的lib下

【海康威视】-NVR使用及ISAPI协议透传接入

【海康威视】-NVR使用及ISAPI协议透传接入

2.4、启动demo

启动类 JavaDemoSTDXMLConfigApp

【海康威视】-NVR使用及ISAPI协议透传接入

启动后效果,使用这个demo可以进行api调试。

【海康威视】-NVR使用及ISAPI协议透传接入

后续可以参照平台的接口出入参进行对接开发

【海康威视】-NVR使用及ISAPI协议透传接入

3、java端接入

3.1、项目结构

win下存放dll文件,需要额外引入 sdk中的examples.jar、jna.jar文件

【海康威视】-NVR使用及ISAPI协议透传接入

其中 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

(0)
上一篇 2026-02-03 15:10
下一篇 2026-02-03 15:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信