题外话:博主写这篇文章的背景也很简单, 公司需要对接商汤的DVR摄像头,捕捉其人脸识别的数据。坑爹的是商汤没有出Java的Demo, 对方负责对接的人员又不懂技术,只能自己硬啃. 写这篇博客的目的很简单,就是为各位有需要对接商汤摄像头的道友提供一些小小的帮助.
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.1.0</version>
</dependency>
public class STNetSDK {
private static final Logger log = Logger.getLogger("STNetSDK");
private static DvrService dvrService = SpringContextHolder.getBean(DvrService.class);
public static final int ST_MAX_POLYGON_NUM = 16;// 多边形最大顶点个数
public static final int ST_MAX_CANDIDATE_NUM = 50;// 多边形最大顶点个数
public static final int MAX_PATH = 260;// 多边形最大顶点个数
public static final int ST_MAX_PERSON_NAME_LEN = 64;// 人员名字最大长度
public static final int ST_MAX_PERSON_ID_LEN = 32;// 人员id最大长度
public static final int ST_MAX_PERSON_IMAGE_NUM = 48;// 每个人员对应的最大人脸图片数
public static final int ST_MAX_PROVINCE_NAME_LEN = 64;// 省份名称最大长度
public static final int ST_MAX_CITY_NAME_LEN = 64;// 城市名称最大长度
public static final int NET_COUNTRY_LENGTH = 3;// 国家缩写长度
public static final int ST_COMMON_STRING_16 = 16;// // 通用字符串长度16
public static final int NET_COMMENT_LENGTH = 100;// 备注信息长度
public static final int NET_GROUPID_LENGTH = 64;// group id 信息长度
public static final int NET_GROUPNAME_LENGTH = 128;// group name 信息长度
public static final int ST_COMMON_STRING_128 = 128;// 通用字符串长度128
public static final int ST_MAX_NAME_LEN = 16;// 通用名字字符串长度
public static final int ST_SERIALNO_LEN = 48; // 设备序列号字符长度
public static class NET_DEVICEINFO_Ex extends Structure {
public byte[] sSerialNumber = new byte[ST_SERIALNO_LEN];// 序列号
public int nAlarmInPortNum;// DVR报警输入个数
public int nAlarmOutPortNum;// DVR报警输出个数
public int nDiskNum;// DVR硬盘个数
public int nDVRType;// DVR类型,见枚举 NET_DEVICE_TYPE
public int nChanNum;// DVR通道个数
public byte byLimitLoginTime;// 在线超时时间,为0表示不限制登陆,非0表示限制的分钟数
public byte byLeftLogTimes;// 当登陆失败原因为密码错误时,通过此参数通知用户,剩余登陆次数,为0时表示此参数无效
public byte[] bReserved = new byte[2]; // 保留字节,字节对齐
public int nLockLeftTime;// 当登陆失败,用户解锁剩余时间(秒数), -1表示设备未设置该参数
public byte[] Reserved = new byte[24];// 保留
public static class ByReference extends NET_DEVICEINFO_Ex implements Structure.ByReference {
}
public static class ByValue extends NET_DEVICEINFO_Ex implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("sSerialNumber");
a.add("nAlarmInPortNum");
a.add("nAlarmOutPortNum");
a.add("nDiskNum");
a.add("nDVRType");
a.add("nChanNum");
a.add("byLimitLoginTime");
a.add("byLeftLogTimes");
a.add("bReserved");
a.add("nLockLeftTime");
a.add("Reserved");
return a;
}
}
public static class ST_MSG_OBJECT extends Structure {
public int nObjectID; // 物体ID,每个ID表示一个唯一的物体
public byte[] szObjectType = new byte[128]; // 物体类型
public int nConfidence; // 置信度(0~255),值越大表示置信度越高
public int nAction; // 物体动作:1:Appear 2:Move 3:Stay 4:Remove 5:Disappear 6:Split 7:Merge 8:Rename
public ST_RECT BoundingBox; // 包围盒
public ST_POINT Center; // 物体型心
public int nPolygonNum; // 多边形顶点个数
public ST_POINT[] Contour = new ST_POINT[ST_MAX_POLYGON_NUM]; // 较精确的轮廓多边形
public int rgbaMainColor; // 表示车牌、车身等物体主要颜色;按字节表示,分别为红、绿、蓝和透明度,例如:RGB值为(0,255,0),透明度为0时, 其值为0x00ff0000.
public byte[] szText = new byte[124]; // 物体上相关的带0结束符文本,比如车牌,集装箱号等等
public byte[] szObjectSubType = new byte[62]; // 物体子类别,根据不同的物体类型,可以取以下子类型:
// Vehicle Category:"Unknown" 未知,"Motor" 机动车,"Non-Motor":非机动车,"Bus": 公交车,"Bicycle" 自行车,"Motorcycle":摩托车,"PassengerCar":客车,
// "LargeTruck":大货车, "MidTruck":中货车,"SaloonCar":轿车,"Microbus":面包车,"MicroTruck":小货车,"Tricycle":三轮车, "Passerby":行人
// Plate Category:"Unknown" 未知,"Normal" 蓝牌黑牌,"Yellow" 黄牌,"DoubleYellow" 双层黄尾牌,"Police" 警牌"Armed" 武警牌,
// "Military" 部队号牌,"DoubleMilitary" 部队双层,"SAR" 港澳特区号牌,"Trainning" 教练车号牌
// "Personal" 个性号牌,"Agri" 农用牌,"Embassy" 使馆号牌,"Moto" 摩托车号牌,"Tractor" 拖拉机号牌,"Other" 其他号牌
// "Civilaviation"民航号牌,"Black"黑牌
// "PureNewEnergyMicroCar"纯电动新能源小车,"MixedNewEnergyMicroCar,"混合新能源小车,"PureNewEnergyLargeCar",纯电动新能源大车
// "MixedNewEnergyLargeCar"混合新能源大车
// HumanFace Category:"Normal" 普通人脸,"HideEye" 眼部遮挡,"HideNose" 鼻子遮挡,"HideMouth" 嘴部遮挡,"TankCar"槽罐车(装化学药品、危险品)
public short wColorLogoIndex; // 车标索引
public short wSubBrand; // 车辆子品牌 需要通过映射表得到真正的子品牌 映射表详见开发手册
public byte byReserved1;
public /*boolean*/ boolean bPicEnble; // 是否有物体对应图片文件信息 TODO
public ST_PIC_INFO stPicInfo; // 物体对应图片信息
public /*boolean*/ boolean bShotFrame; // 是否是抓拍张的识别结果
public /*boolean*/ boolean bColor; // 物体颜色(rgbaMainColor)是否可用
public byte byReserved2;
public byte byTimeType; // 时间表示类型,详见EM_TIME_TYPE说明
public NET_TIME_EX stuCurrentTime; // 针对视频浓缩,当前时间戳(物体抓拍或识别时,会将此识别智能帧附在一个视频帧或jpeg图片中,此帧所在原始视频中的出现时间)
public NET_TIME_EX stuStartTime; // 开始时间戳(物体开始出现时)
public NET_TIME_EX stuEndTime; // 结束时间戳(物体最后出现时)
public ST_RECT stuOriginalBoundingBox; // 包围盒(绝对坐标)
public ST_RECT stuSignBoundingBox; // 车标坐标包围盒
/* public int dwCurrentSequence; // 当前帧序号(抓下这个物体时的帧)
public int dwBeginSequence; // 开始帧序号(物体开始出现时的帧序号)
public int dwEndSequence; // 结束帧序号(物体消逝时的帧序号)
public int nBeginFileOffset; // 开始时文件偏移, 单位: 字节(物体开始出现时,视频帧在原始视频文件中相对于文件起始处的偏移)TODO
public long nEndFileOffset; // 结束时文件偏移, 单位: 字节(物体消逝时,视频帧在原始视频文件中相对于文件起始处的偏移)TODO
public byte[] byColorSimilar = new byte[8]; // 物体颜色相似度,取值范围:0-100,数组下标值代表某种颜色,详见EM_COLOR_TYPE
public byte[] byUpperBodyColorSimilar = new byte[8]; // 上半身物体颜色相似度(物体类型为人时有效)
public byte[] byLowerBodyColorSimilar = new byte[8]; // 下半身物体颜色相似度(物体类型为人时有效)
public int nRelativeID; // 相关物体ID
public byte[] szSubText = new byte[20]; // "ObjectType"为"Vehicle"或者"Logo"时,表示车标下的某一车系,比如奥迪A6L,由于车系较多,SDK实现时透传此字段,设备如实填写。
public short wBrandYear; // 车辆品牌年款 需要通过映射表得到真正的年款 映射表详见开发手册
*/
public static class ByReference extends ST_MSG_OBJECT implements Structure.ByReference {
}
public static class ByValue extends ST_MSG_OBJECT implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
//a.add("dwSize");
a.add("nObjectID");
a.add("szObjectType");
a.add("nConfidence");
a.add("nAction");
a.add("BoundingBox");
a.add("Center");
a.add("nPolygonNum");
a.add("Contour");
a.add("rgbaMainColor");
a.add("szText");
a.add("szObjectSubType");
a.add("wColorLogoIndex");
a.add("wSubBrand");
a.add("byReserved1");
a.add("bPicEnble");
a.add("stPicInfo");
a.add("bShotFrame");
a.add("bColor");
a.add("byReserved2");
a.add("byTimeType");
a.add("stuCurrentTime");
a.add("stuStartTime");
a.add("stuEndTime");
a.add("stuOriginalBoundingBox");
a.add("stuSignBoundingBox");
/*a.add("dwCurrentSequence");
a.add("dwBeginSequence");
a.add("dwEndSequence");
a.add("nBeginFileOffset");
a.add("nEndFileOffset");
a.add("byColorSimilar");
a.add("byUpperBodyColorSimilar");
a.add("byLowerBodyColorSimilar");
a.add("nRelativeID");
a.add("szSubText");
a.add("wBrandYear");*/
return a;
}
}
public static class NET_TIME_EX extends Structure {
public int dwYear; // 年
public int dwMonth; // 月
public int dwDay; // 日
public int dwHour; // 时
public int dwMinute; // 分
public int dwSecond; // 秒
public int dwMillisecond; // 毫秒
public int[] dwReserved = new int[2]; // 保留字段
public static class ByReference extends NET_TIME_EX implements Structure.ByReference {
}
public static class ByValue extends NET_TIME_EX implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("dwYear");
a.add("dwMonth");
a.add("dwDay");
a.add("dwHour");
a.add("dwMinute");
a.add("dwSecond");
a.add("dwMillisecond");
a.add("dwReserved");
return a;
}
}
public static class NET_TIME extends Structure {
public int dwYear; // 年
public int dwMonth; // 月
public int dwDay; // 日
public int dwHour; // 时
public int dwMinute; // 分
public int dwSecond; // 秒
public static class ByReference extends NET_TIME_EX implements Structure.ByReference {
}
public static class ByValue extends NET_TIME_EX implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("dwYear");
a.add("dwMonth");
a.add("dwDay");
a.add("dwHour");
a.add("dwMinute");
a.add("dwSecond");
return a;
}
}
public static class ST_RECT extends Structure {
public NativeLong left;
public NativeLong top;
public NativeLong right;
public NativeLong bottom;
public static class ByReference extends ST_RECT implements Structure.ByReference {
}
public static class ByValue extends ST_RECT implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("left");
a.add("top");
a.add("right");
a.add("bottom");
return a;
}
}
public static class FACERECOGNITION_PERSON_INFOEX extends Structure {
public byte[] szPersonName = new byte[ST_MAX_PERSON_NAME_LEN]; // 姓名
public short wYear; // 出生年,作为查询条件时,此参数填0,则表示此参数无效
public byte byMonth; // 出生月,作为查询条件时,此参数填0,则表示此参数无效
public byte byDay; // 出生日,作为查询条件时,此参数填0,则表示此参数无效
public byte bImportantRank; // 人员重要等级,1~10,数值越高越重要,作为查询条件时,此参数填0,则表示此参数无效
public byte bySex; // 性别,1-男,2-女,作为查询条件时,此参数填0,则表示此参数无效
public byte[] szID = new byte[ST_MAX_PERSON_ID_LEN]; // 人员唯一标示(身份证号码,工号,或其他编号)
public short wFacePicNum; // 图片张数
public ST_PIC_INFO[] szFacePicInfo = new ST_PIC_INFO[ST_MAX_PERSON_IMAGE_NUM]; // 当前人员对应的图片信息
public byte byType; // 人员类型,详见 EM_PERSON_TYPE
public byte byIDType; // 证件类型,详见 EM_CERTIFICATE_TYPE
public byte byGlasses; // 是否戴眼镜,0-未知 1-不戴 2-戴
public byte byAge; // 年龄,0表示未知
public byte[] szProvince = new byte[ST_MAX_PROVINCE_NAME_LEN]; // 省份
public byte[] szCity = new byte[ST_MAX_CITY_NAME_LEN]; // 城市
public byte[] szUID = new byte[ST_MAX_PERSON_ID_LEN]; // 人员唯一标识符,首次由服务端生成,区别于ID字段
// 修改,删除操作时必填
public byte[] szCountry = new byte[NET_COUNTRY_LENGTH]; // 国籍,符合ISO3166规范
public byte byIsCustomType; // 人员类型是否为自定义: 0 使用Type规定的类型 1 自定义,使用szCustomType字段
public byte[] szCustomType = new byte[ST_COMMON_STRING_16]; // 人员自定义类型
public byte[] szComment = new byte[NET_COMMENT_LENGTH]; // 备注信息
public byte[] szGroupID = new byte[NET_GROUPID_LENGTH]; // 人员所属组ID
public byte[] szGroupName = new byte[NET_GROUPNAME_LENGTH]; // 人员所属组名, 用户自己申请内存的情况时,
public byte emEmotion; // 表情
public byte[] szHomeAddress = new byte[ST_COMMON_STRING_128]; // 注册人员家庭地址
public byte emGlassesType; // 眼镜类型
public byte emRace; // 种族
public byte emEye; // 眼睛状态
public byte emMouth; // 嘴巴状态
public byte emMask; // 口罩状态
public byte emBeard; // 胡子状态
public int nAttractive; // 魅力值, -1表示无效, 0未识别,识别时范围1-100,得分高魅力高
public byte emFeatureState; // 人员建模状态
public byte[] byReserved = new byte[2044]; // 保留字节
public static class ByReference extends FACERECOGNITION_PERSON_INFOEX implements Structure.ByReference {
}
public static class ByValue extends FACERECOGNITION_PERSON_INFOEX implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("szPersonName");
a.add("wYear");
a.add("byMonth");
a.add("byDay");
a.add("bImportantRank");
a.add("bySex");
a.add("szID");
a.add("wFacePicNum");
a.add("szFacePicInfo");
a.add("byType");
a.add("byIDType");
a.add("byGlasses");
a.add("byAge");
a.add("szProvince");
a.add("szCity");
a.add("szUID");
a.add("szCountry");
a.add("byIsCustomType");
a.add("szCustomType");
a.add("szComment");
a.add("szGroupID");
a.add("szGroupName");
a.add("emEmotion");
a.add("szHomeAddress");
a.add("emGlassesType");
a.add("emRace");
a.add("emEye");
a.add("emMouth");
a.add("emMask");
a.add("emBeard");
a.add("nAttractive");
a.add("emFeatureState");
a.add("byReserved");
return a;
}
}
public static class EVENT_INTELLI_COMM_INFO extends Structure {
public byte emClassType; // 智能事件所属大类
public int nPresetID; // 该事件触发的预置点,对应该设置规则的预置点
public byte[] bReserved = new byte[124]; // 保留字节,留待扩展.
public static class ByReference extends EVENT_INTELLI_COMM_INFO implements Structure.ByReference {
}
public static class ByValue extends EVENT_INTELLI_COMM_INFO implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("emClassType");
a.add("nPresetID");
a.add("bReserved");
return a;
}
}
public static class ST_PIC_INFO_EX3 extends Structure {
public int dwOffSet; // 文件在二进制数据块中的偏移位置, 单位:字节
public int dwFileLenth; // 文件大小, 单位:字节
public short wWidth; // 图片宽度, 单位:像素
public short wHeight; // 图片高度, 单位:像素
public byte[] szFilePath = new byte[64]; // 文件路径
public byte bIsDetected; // 图片是否算法检测出来的检测过的提交识别服务器时,
// 则不需要再时检测定位抠图,1:检测过的,0:没有检测过
public byte[] bReserved = new byte[11]; // 保留
public static class ByReference extends ST_PIC_INFO_EX3 implements Structure.ByReference {
}
public static class ByValue extends ST_PIC_INFO_EX3 implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("dwOffSet");
a.add("dwFileLenth");
a.add("wWidth");
a.add("wHeight");
a.add("szFilePath");
a.add("bIsDetected");
a.add("bReserved");
return a;
}
}
public static class ST_POINT extends Structure {
public short nx;
public short ny;
public static class ByReference extends ST_POINT implements Structure.ByReference {
}
public static class ByValue extends ST_POINT implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("nx");
a.add("ny");
return a;
}
}
public static class ST_PIC_INFO extends Structure {
public int dwOffSet; // 文件在二进制数据块中的偏移位置, 单位:字节
public int dwFileLenth; // 文件大小, 单位:字节
public short wWidth; // 图片宽度, 单位:像素
public short wHeight; // 图片高度, 单位:像素
public Pointer pszFilePath; // 鉴于历史原因,该成员只在事件上报时有效
// 文件路径
// 用户使用该字段时需要自行申请空间进行拷贝保存
public byte bIsDetected; //图片是否算法检测出来的检测过的提交识别服务器时,
//则不需要再时检测定位抠图,1:检测过的,0:没有检测过
public byte[] bReserved = new byte[7]; // 12<--16
public ST_POINT stuPoint; // 小图左上角在大图的位置,使用绝对坐标系
public static class ByReference extends ST_PIC_INFO implements Structure.ByReference {
}
public static class ByValue extends ST_PIC_INFO implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("dwOffSet");
a.add("dwFileLenth");
a.add("wWidth");
a.add("wHeight");
a.add("pszFilePath");
a.add("bIsDetected");
a.add("bReserved");
a.add("stuPoint");
return a;
}
}
public static class FACERECOGNITION_PERSON_INFO extends Structure {
public byte[] szPersonName = new byte[ST_MAX_NAME_LEN]; // 姓名,此参数作废
public int wYear; // 出生年,作为查询条件时,此参数填0,则表示此参数无效
public byte byMonth; // 出生月,作为查询条件时,此参数填0,则表示此参数无效
public byte byDay; // 出生日,作为查询条件时,此参数填0,则表示此参数无效
public byte[] szID = new byte[ST_MAX_PERSON_ID_LEN]; // 人员唯一标示(身份证号码,工号,或其他编号)
public byte bImportantRank; // 人员重要等级,1~10,数值越高越重要,作为查询条件时,此参数填0,则表示此参数无效
public byte bySex; // 性别,1-男,2-女,作为查询条件时,此参数填0,则表示此参数无效
public short wFacePicNum; // 图片张数
public ST_PIC_INFO[] szFacePicInfo = new ST_PIC_INFO[ST_MAX_PERSON_IMAGE_NUM]; // 当前人员对应的图片信息
public byte byType; // 人员类型,详见 EM_PERSON_TYPE
public byte byIDType; // 证件类型,详见 EM_CERTIFICATE_TYPE
public byte byGlasses; // 是否戴眼镜,0-未知 1-不戴 2-戴
public byte byAge; // 年龄,0表示未知
public byte[] szProvince = new byte[ST_MAX_PROVINCE_NAME_LEN]; // 省份
public byte[] szCity = new byte[ST_MAX_CITY_NAME_LEN]; // 城市
public byte[] szPersonNameEx = new byte[ST_MAX_PERSON_NAME_LEN]; // 姓名,因存在姓名过长,16字节无法存放问题,故增加此参数,
public byte[] szUID = new byte[ST_MAX_PERSON_ID_LEN]; // 人员唯一标识符,首次由服务端生成,区别于ID字段
// 修改,删除操作时必填
public byte[] szCountry = new byte[NET_COUNTRY_LENGTH]; // 国籍,符合ISO3166规范
public byte byIsCustomType; // 人员类型是否为自定义: 0 使用Type规定的类型 1 自定义,使用szPersonName字段
public Pointer pszComment; // 备注信息, 用户自己申请内存的情况时,
// 下方bCommentLen需填写对应的具体长度值,推荐长度 NET_COMMENT_LENGTH
public Pointer pszGroupID; // 人员所属组ID, 用户自己申请内存的情况时,
// 下方bGroupIdLen需填写对应的具体长度值,推荐长度 NET_GROUPID_LENGTH
public Pointer pszGroupName; // 人员所属组名, 用户自己申请内存的情况时,
// 下方bGroupNameLen需填写对应的具体长度值,推荐长度 NET_GROUPNAME_LENGTH
public Pointer pszFeatureValue; // 人脸特征, 用户自己申请内存的情况时,
// 下方bFeatureValueLen需填写对应的具体长度值,推荐长度 NET_FEATUREVALUE_LENGTH
public byte bGroupIdLen; // pszGroupID的长度
public byte bGroupNameLen; // pszGroupName的长度
public byte bFeatureValueLen; // pszFeatureValue的长度
public byte bCommentLen; // pszComment的长度
public byte emEmotion; // 表情
public static class ByReference extends FACERECOGNITION_PERSON_INFO implements Structure.ByReference {
}
public static class ByValue extends FACERECOGNITION_PERSON_INFO implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("szPersonName");
a.add("wYear");
a.add("byMonth");
a.add("byDay");
a.add("szID");
a.add("bImportantRank");
a.add("bySex");
a.add("wFacePicNum");
a.add("szFacePicInfo");
a.add("byType");
a.add("byIDType");
a.add("byGlasses");
a.add("byAge");
a.add("szProvince");
a.add("szCity");
a.add("szPersonNameEx");
a.add("szUID");
a.add("szCountry");
a.add("byIsCustomType");
a.add("pszComment");
a.add("pszGroupID");
a.add("pszGroupName");
a.add("pszFeatureValue");
a.add("bGroupIdLen");
a.add("bGroupNameLen");
a.add("bFeatureValueLen");
a.add("bCommentLen");
a.add("emEmotion");
return a;
}
}
public static class CANDIDATE_INFO extends Structure {
public FACERECOGNITION_PERSON_INFO stPersonInfo; // 人员信息
// 布控(黑名单)库,指布控库中人员信息;
// 历史库,指历史库中人员信息
// 报警库,指布控库的人员信息
public byte bySimilarity; // 和查询图片的相似度,百分比表示,1~100
public byte byRange; // 人员所属数据库范围,详见EM_FACE_DB_TYPE
public byte byReserved1;
public NET_TIME stTime; // 当byRange为历史数据库时有效,表示查询人员出现的时间
public byte[] szAddress = new byte[MAX_PATH]; // 当byRange为历史数据库时有效,表示查询人员出现的地点
public boolean bIsHit; // 是否有识别结果,指这个检测出的人脸在库中有没有比对结果
public ST_PIC_INFO_EX3 stuSceneImage; // 人脸全景图
public int nChannelID; // 通道号
public byte[] byReserved = new byte[32]; // 保留字节
public static class ByReference extends CANDIDATE_INFO implements Structure.ByReference {
}
public static class ByValue extends CANDIDATE_INFO implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("stPersonInfo");
a.add("bySimilarity");
a.add("byRange");
a.add("byReserved1");
a.add("stTime");
a.add("szAddress");
a.add("bIsHit");
a.add("stuSceneImage");
a.add("nChannelID");
a.add("byReserved");
return a;
}
}
public static class DEV_EVENT_FACERECOGNITION_INFO extends Structure {
public int nChannelID; // 通道号
public byte[] szName = new byte[128]; // 事件名称
public int nEventID; // 事件ID
public NET_TIME_EX UTC; // 事件发生的时间
public ST_MSG_OBJECT stuObject; // 检测到的物体
public int nCandidateNum; // 当前人脸匹配到的候选对象数量
public CANDIDATE_INFO[] stuCandidates = new CANDIDATE_INFO[ST_MAX_CANDIDATE_NUM]; // 当前人脸匹配到的候选对象信息
public byte bEventAction; // 事件动作,0表示脉冲事件,1表示持续性事件开始,2表示持续性事件结束;
public byte byImageIndex; // 图片的序号, 同一时间内(精确到秒)可能有多张图片, 从0开始
public byte[] byReserved1 = new byte[51]; // 对齐
public /*boolean*/ boolean bGlobalScenePic; // 全景图是否存在
public ST_PIC_INFO stuGlobalScenePicInfo; // 全景图片信息
//public byte[] szSnapDevAddress = new byte[MAX_PATH]; // 抓拍当前人脸的设备地址,如:滨康路37号
public int nOccurrenceCount; // 事件触发累计次数 TODO
//public EVENT_INTELLI_COMM_INFO stuIntelliCommInfo; // 智能事件公共信息
public NET_FACE_DATA stuFaceData; // 人脸数据
/*public char szUID; // 抓拍人员写入数据库的唯一标识符
public int bReserved; // 保留字节,留待扩展.
public int nRetCandidatesExNum; // 当前人脸匹配到的候选对象数量实际返回值
public CANDIDATE_INFOEX stuCandidatesEx; // 当前人脸匹配到的候选对象信息扩展*/
public static class ByReference extends DEV_EVENT_FACERECOGNITION_INFO implements Structure.ByReference {
}
public static class ByValue extends DEV_EVENT_FACERECOGNITION_INFO implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("nChannelID");
a.add("szName");
a.add("nEventID");
a.add("UTC");
a.add("stuObject");
a.add("nCandidateNum");
a.add("stuCandidates");
a.add("bEventAction");
a.add("byImageIndex");
a.add("byReserved1");
a.add("bGlobalScenePic");
a.add("stuGlobalScenePicInfo");
//a.add("szSnapDevAddress");
a.add("nOccurrenceCount");
//a.add("stuIntelliCommInfo");
a.add("stuFaceData");
/*a.add("szUID");
a.add("bReserved");
a.add("nRetCandidatesExNum");
a.add("stuCandidatesEx");*/
return a;
}
}
public static class NET_FACE_DATA extends Structure {
public byte emSex; // 性别
public int nAge; // 年龄,-1表示该字段数据无效
public int nFeatureValidNum; // 人脸特征数组有效个数,与 emFeature 结合使用
public byte emFeature; // 人脸特征数组,与 nFeatureValidNum 结合使用
public byte emRace; // 种族
public byte emEye; // 眼睛状态
public byte emMouth; // 嘴巴状态
public byte emMask; // 口罩状态
public byte emBeard; // 胡子状态
public int nAttractive; // 魅力值, -1表示无效, 0未识别,识别时范围1-100,得分高魅力高
public byte[] bReserved = new byte[128]; // 保留字节,留待扩展.
public static class ByReference extends NET_FACE_DATA implements Structure.ByReference {
}
public static class ByValue extends NET_FACE_DATA implements Structure.ByValue {
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected List getFieldOrder() {
List a = new ArrayList();
a.add("emSex");
a.add("nAge");
a.add("nFeatureValidNum");
a.add("emFeature");
a.add("emRace");
a.add("emEye");
a.add("emMouth");
a.add("emMask");
a.add("emBeard");
a.add("nAttractive");
a.add("bReserved");
return a;
}
}
public static final int EVENT_IVS_ALL = 0x00000001;//订阅所有事件
public static final int EVENT_IVS_FACEDETECT = 0x0000001A;//人脸检测事件 (对应 DEV_EVENT_FACEDETECT_INFO)
public static final int EVENT_IVS_FACERECOGNITION = 0x00000117;//人脸识别事件(对应 DEV_EVENT_FACERECOGNITION_INFO)
public interface Dll extends Library {
Dll instance = (Dll) Native.loadLibrary("stnetsdk", Dll.class);
/**
* 初始化方法
*/
void CLIENT_Init();
/**
* 清除资源
*/
void CLIENT_Cleanup();
/**
* 获取版本
*
* @return
*/
int CLIENT_GetSDKVersion();
/**
* 设置断线重连成功回调函数接口,设置后 SDK 内部检测到设备断线则进行自动重连。
*
* @param cbAutoConnect
* @param dwUser
*/
void CLIENT_SetAutoReconnect(HaveReConnectCallBack cbAutoConnect, int dwUser);
/**
* 设置连接设备超时时间和尝试次数接口。
*
* @param nWaitTime 每次登录时,等待设备响应超时时间
* @param nTryTimes 每次登录时,连接尝试登录设备次数。
*/
void CLIENT_SetConnectTime(int nWaitTime, int nTryTimes);
Long CLIENT_LoginEx2(final String pchDVRIP, int wDVRPort, final String pchUserName, final String pchPassword, int EM_LOGIN_SPEC_CAP_TCP, String pCapParam, NET_DEVICEINFO_Ex lpDeviceInfo, int error);
/**
* 错误代码回调
*
* @return
*/
Long CLIENT_GetLastError();
/**
* 智能图片报警订阅接口
*
* @param lLoginID 登陆设备id
* @param nChannelID 智能图片报警订阅通道号,通道号从 0 开始
* @param dwAlarmType 期望订阅的报警类型 如:EVENT_IVS_ALL //所有报警信息都会上传
* @param bNeedPicFile 是否订阅图片文件 TRUE:表示订阅图片文件,在回调函数中会返回智能图片信息 FALSE:表示不订阅图片文件,在回调函数中不会返回智能图片信息(在不
* 需要图片信息时,可减少网络流量)
* @param //cbAnalyzerData 智能图片报警回调函数
* @param dwUser 用户数据,SDK 通过智能图片报警回调函数 fAnalyzerDataCallBack将该数据返回给用户,以便用户后续操作
* @param pointer 保留参数 该字段建议填 NULL
* @return
*/
Long CLIENT_RealLoadPictureEx(Long lLoginID, int nChannelID, int dwAlarmType, boolean bNeedPicFile, fAnalyzerDataCallBack analyzerDataCallBack, int dwUser, Pointer pointer);
/**
* 主动注册功能-开启服务监听
*
* @param ip 服务器ip
* @param port 端口
* @param nTimeout
* @param cbListen 回调函数
* @param dwUserData
* @return
*/
Long CLIENT_ListenServer(String ip, int port, int nTimeout, ServiceCallBackCallBack cbListen, Long dwUserData);
}
/**
* 获取人脸识别的回调函数接口
*/
public interface fAnalyzerDataCallBack extends Callback {
int fAnalyzerDataCallBack(Long lAnalyzerHandle, int dwAlarmType,
Pointer pAlarmInfo, String pBuffer, int dwBufSize, Long dwUser, int nSequence,
Pointer reserved);
}
/**
* 断线重连回调函数
*/
public interface HaveReConnectCallBack extends Callback {
int HaveReConnect(long lLoginID, String pchDVRIP, long nDVRPort, long dwUser);
}
/**
* 主动注册回调函数
*/
public interface ServiceCallBackCallBack extends Callback {
int ServiceCallBack(long lHandle, String pIp, short wPort, long lCommand, String pParam, int dwParamLen, Long dwUserData);
}
/**
* 获取人脸识别的回调函数接口实现类
*/
static class fAnalyzerDataCallBackImpl implements fAnalyzerDataCallBack {
@Override
public int fAnalyzerDataCallBack(Long lAnalyzerHandle, int dwAlarmType, Pointer pAlarmInfo, String pBuffer, int dwBufSize, Long dwUser
, int nSequence, Pointer reserved) {
//实时人脸抓拍上传
DEV_EVENT_FACERECOGNITION_INFO strFaceSnapInfo = new DEV_EVENT_FACERECOGNITION_INFO();
strFaceSnapInfo.write();
Pointer pFaceSnapInfo = strFaceSnapInfo.getPointer();
pFaceSnapInfo.write(0, pAlarmInfo.getByteArray(0, strFaceSnapInfo.size()), 0, strFaceSnapInfo.size());
strFaceSnapInfo.read();
log.info("strFaceSnapInfo = " + strFaceSnapInfo);
String sex = "";
if (1 == strFaceSnapInfo.stuFaceData.emSex) {
sex = "男";
} else if (2 == strFaceSnapInfo.stuFaceData.emSex) {
sex = "女";
} else {
sex = "未知";
}
String sAlarmType = "事件名称:" + new String(strFaceSnapInfo.szName) +
" 年龄:" + strFaceSnapInfo.stuFaceData.nAge + ",性别:" + sex;
log.info("sAlarmType = " + sAlarmType);
HumanFactory.createHuman(strFaceSnapInfo.stuFaceData.emSex, strFaceSnapInfo.stuFaceData.nAge, dvrCode);
return 1;
}
}
static class HaveReConnectCallBackImpl implements HaveReConnectCallBack {
@Override
public int HaveReConnect(long lLoginID, String pchDVRIP, long nDVRPort, long dwUser) {
log.info("断线(断网)重连回调函数:lLoginID = [" + lLoginID + "], pchDVRIP = [" + pchDVRIP + "], nDVRPort = [" + nDVRPort + "], dwUser = [" + dwUser + "]");
return 0;
}
}
static class ServiceCallBackCallBackImpl implements ServiceCallBackCallBack {
@Override
public int ServiceCallBack(long lHandle, String pIp, short wPort, long lCommand, String pParam, int dwParamLen, Long dwUserData) {
System.err.println("断电回调函数:lHandle = [" + lHandle + "], pIp = [" + pIp + "], wPort = [" + wPort + "], lCommand = [" + lCommand + "], pParam = [" + pParam + "], dwParamLen = [" + dwParamLen + "], dwUserData = [" + dwUserData + "]");
if (1 == lCommand) {
int nError = 0;
NET_DEVICEINFO_Ex stDevInfo = new NET_DEVICEINFO_Ex();
long loginId = Dll.instance.CLIENT_LoginEx2(pIp, wPort, "admin", "admin", 2, pParam, stDevInfo, nError);
}
return 0;
}
}
/**
* 初始化
*/
private static STNetSDK.HaveReConnectCallBack haveReConnectCallBack = new STNetSDK.HaveReConnectCallBackImpl();
public static void init() {
//初始化
Dll.instance.CLIENT_Init();
//获取版本
int s = Dll.instance.CLIENT_GetSDKVersion();
log.info("NetSDK version is " + s);
//设置断线重连回调接口,设置过断线重连成功回调函数后,当设备出现断线情况,SDK内部会自动进行重连操作。
Dll.instance.CLIENT_SetAutoReconnect(haveReConnectCallBack, 0);
//设置连接设备超时时间和尝试次数
Dll.instance.CLIENT_SetConnectTime(500, 3);
//释放资源
//Dll.instance.CLIENT_Cleanup();
}
/**
* 登陆功能--------------Begin------------------------
*/
private static STNetSDK.fAnalyzerDataCallBack fanalyzerDataCallBack = new STNetSDK.fAnalyzerDataCallBackImpl();
private static STNetSDK.ServiceCallBackCallBack serviceCallBackCallBack = new STNetSDK.ServiceCallBackCallBackImpl();
/**
* 登陆
*
* @param dvrIp
* @param dvrPort
* @param dvr_loginName
* @param dvr_loginPassword
*/
public static Long login(String dvrIp, int dvrPort, String dvr_loginName, String dvr_loginPassword) {
//初始化
init();
NET_DEVICEINFO_Ex net_deviceinfo_ex = new NET_DEVICEINFO_Ex();
Long loginId = Dll.instance.CLIENT_LoginEx2(dvrIp, dvrPort, dvr_loginName, dvr_loginPassword, 0, null, net_deviceinfo_ex, 0);
log.info("loginId = " + loginId);
log.info("net_deviceinfo_ex = " + net_deviceinfo_ex);
dvrCode = new String(net_deviceinfo_ex.sSerialNumber);
dvrService.insertDvr(String.valueOf(loginId), dvrIp, dvrCode);
if (0 == loginId) {
Long error = Dll.instance.CLIENT_GetLastError();
System.err.println("loginIdError = " + error);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Long aLong = Dll.instance.CLIENT_ListenServer("192.168.1.183", 6060, 0, serviceCallBackCallBack, null);
System.out.println("aLong = " + aLong);
return loginId;
}
/**
* 抓取回调函数里面的数据
*
* @throws InterruptedException
*/
private static String dvrCode;
public static void FetchingData(String dvrIp, int dvrPort, String dvr_loginName, String dvr_loginPassword) throws InterruptedException {
//登陆
Long loginId = login(dvrIp, dvrPort, dvr_loginName, dvr_loginPassword);
//抓取数据
Long dataId = Dll.instance.CLIENT_RealLoadPictureEx(loginId, 0, EVENT_IVS_FACERECOGNITION, true, fanalyzerDataCallBack, 0, null);
if (0 == dataId) {
Long dataIdError = Dll.instance.CLIENT_GetLastError();
System.err.println("dataIdError = " + dataIdError);
}
//释放资源
// Dll.instance.CLIENT_Cleanup();
}
}