大华监控官网SDK版本:NetSDK_JAVA_Linux64_V3.055.0000000.0.R.210602/NetSDK_JAVA_Win64_V3.055.0000000.0.R.210602
import com.netsdk.common.Res;
import com.netsdk.lib.NetSDKLib;
import com.netsdk.lib.ToolKits;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import static com.netsdk.demo.module.LoginModule.netsdk;
/**
*/
public class TestHandle{
private String m_strIp = "XX.X.XXX.XXX";//监控地址
private int m_nPort = 37777;//端口 默认是使用37777
private String m_strUser = "XXXX";//账号
private String m_strPassword = "XXXXXXXX";//密码
public static final NetSDKLib netSdk = NetSDKLib.NETSDK_INSTANCE;
// 登陆句柄
private NetSDKLib.LLong 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;
// 用于人脸检测
private static int groupId = 0;
private static int index = -1;
// 设备断线通知回调
private static DisConnect disConnect = new DisConnect();
// 网络连接恢复
private static HaveReConnect haveReConnect = new HaveReConnect();
public static void main(String[] args) {
TestHandle testHandle= new TestHandle ();
//初始化
testHandle.InitTest(disConnect, haveReConnect);
//登录
testHandle.Login();
testHandle.Run();
}
public void Run() {
//订阅
RealLoadPicture(0, 1, AnalyzerDataCB.getInstance());
//防止程序执行完
try {
new BufferedReader(new InputStreamReader(System.in)).readLine();
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
// 设备断线回调: 通过 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 PictureHandle.AnalyzerDataCB instance = new PictureHandle.AnalyzerDataCB();
}
public static PictureHandle.AnalyzerDataCB getInstance() {
return PictureHandle.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();
}
// 保存图片,获取图片缓存
// 耗时20ms左右
try {
saveFaceRecognitionPic(pBuffer, dwBufSize, msg);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 释放内存
msg = null;
System.gc();
break;
}
/* case NetSDKLib.EVENT_IVS_FACEDETECT: // /< 人脸检测
{
NetSDKLib.DEV_EVENT_FACEDETECT_INFO msg = new NetSDKLib.DEV_EVENT_FACEDETECT_INFO();
ToolKits.GetPointerData(pAlarmInfo, msg);
// 保存图片,获取图片缓存
try {
saveFaceDetectPic(pBuffer, dwBufSize, msg);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 释放内存
msg = null;
System.gc();
break;
}*/
default:
break;
}
return 0;
}
/**
* 保存人脸识别事件图片
*
* @param pBuffer 抓拍图片信息
* @param dwBufSize 抓拍图片大小
* @param faceRecognitionInfo 人脸识别事件信息
*/
public void saveFaceRecognitionPic(
Pointer pBuffer, int dwBufSize, NetSDKLib.DEV_EVENT_FACERECOGNITION_INFO faceRecognitionInfo)
throws FileNotFoundException {
DateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
Date currentDate = new Date();
File path = new File("D:\\test\\" + df.format(currentDate).toString());
if (!path.exists()) {
path.mkdir();
}
if (pBuffer == null || dwBufSize <= 0) {
return;
}
/// 保存全景图 ///
if (faceRecognitionInfo.bGlobalScenePic == 1) {
String strGlobalPicPathName =
path + "\\" + faceRecognitionInfo.UTC.toStringTitle() + "_FaceRecognition_Global.jpg";
byte[] bufferGlobal =
pBuffer.getByteArray(
faceRecognitionInfo.stuGlobalScenePicInfo.dwOffSet,
faceRecognitionInfo.stuGlobalScenePicInfo.dwFileLenth);
ByteArrayInputStream byteArrInputGlobal = new ByteArrayInputStream(bufferGlobal);
try {
globalBufferedImage = ImageIO.read(byteArrInputGlobal);
if (globalBufferedImage != null) {
File globalFile = new File(strGlobalPicPathName);
if (globalFile != null) {
ImageIO.write(globalBufferedImage, "jpg", globalFile);
}
}
} catch (IOException e2) {
e2.printStackTrace();
}
}
/// 保存人脸图 /
if (faceRecognitionInfo.stuObject.stPicInfo != null) {
String strPersonPicPathName =
path + "\\" + faceRecognitionInfo.UTC.toStringTitle() + "_FaceRecognition_Person.jpg";
byte[] bufferPerson =
pBuffer.getByteArray(
faceRecognitionInfo.stuObject.stPicInfo.dwOffSet,
faceRecognitionInfo.stuObject.stPicInfo.dwFileLenth);
ByteArrayInputStream byteArrInputPerson = new ByteArrayInputStream(bufferPerson);
try {
personBufferedImage = ImageIO.read(byteArrInputPerson);
if (personBufferedImage != null) {
File personFile = new File(strPersonPicPathName);
if (personFile != null) {
ImageIO.write(personBufferedImage, "jpg", personFile);
}
}
} catch (IOException e2) {
e2.printStackTrace();
}
}
/ 保存对比图 //
if (faceRecognitionInfo.nRetCandidatesExNum > 0
&& faceRecognitionInfo.stuCandidatesEx != null) {
int maxValue = -1;
// 设备可能返回多张图片,这里只显示相似度最高的
int[] nSimilary = new int[faceRecognitionInfo.nRetCandidatesExNum];
for (int i = 0; i < faceRecognitionInfo.nRetCandidatesExNum; i++) {
nSimilary[i] = faceRecognitionInfo.stuCandidatesEx[i].bySimilarity & 0xff;
}
for (int i = 0; i < nSimilary.length; i++) {
if (maxValue < nSimilary[i]) {
maxValue = nSimilary[i];
index = i;
}
}
String strCandidatePicPathName =
path
+ "\\"
+ faceRecognitionInfo.UTC.toStringTitle()
+ "_FaceRecognition_Candidate.jpg";
// 每个候选人的图片个数:faceRecognitionInfo.stuCandidatesEx[index].stPersonInfo.wFacePicNum,
// 正常情况下只有1张。如果有多张,只获取第一张
byte[] bufferCandidate =
pBuffer.getByteArray(
faceRecognitionInfo.stuCandidatesEx[index].stPersonInfo.szFacePicInfo[0].dwOffSet,
faceRecognitionInfo
.stuCandidatesEx[index]
.stPersonInfo
.szFacePicInfo[0]
.dwFileLenth);
ByteArrayInputStream byteArrInputCandidate = new ByteArrayInputStream(bufferCandidate);
try {
candidateBufferedImage = ImageIO.read(byteArrInputCandidate);
if (candidateBufferedImage != null) {
File candidateFile = new File(strCandidatePicPathName);
if (candidateFile != null) {
ImageIO.write(candidateBufferedImage, "jpg", candidateFile);
}
}
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
/**
* 保存人脸对比信息
*/
public void saveFaceDetectInfo(NetSDKLib.DEV_EVENT_FACERECOGNITION_INFO faceMsg) throws IOException {
//人脸信息
if (faceMsg.stuFaceData != null) {
DateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
Date currentDate = new Date();
File path = new File("D:\\test\\" + df.format(currentDate).toString());
if (!path.exists()) {
path.mkdir();
}
String strCandidateInfoPathName =path+ "\\"+ "faceDetectInfo.txt";
File faceDetectInfoFile = new File(strCandidateInfoPathName);
if (faceDetectInfoFile != null) {
FileWriter fileWriter=null;
StringBuilder faceDetectInfoStr=new StringBuilder();
String nAge="";
if(nAge=="-1"){
nAge="未知";
}
faceDetectInfoStr.append("对比信息\r\n")
.append("人脸信息:\r\n")
.append("时间:").append(faceMsg.UTC).append("\r\n")
.append("性别:").append(Res.string().getSex(faceMsg.stuFaceData.emSex)).append("\r\n")
.append("年龄:").append(nAge).append("\r\n")
.append("肤色:").append(Res.string().getColor(faceMsg.stuFaceData.emRace)).append("\r\n")
.append("眼睛:").append(Res.string().getEyeState(faceMsg.stuFaceData.emEye)).append("\r\n")
.append("嘴巴:").append(Res.string().getMouthState(faceMsg.stuFaceData.emMouth)).append("\r\n")
.append("口罩:").append(Res.string().getMaskState(faceMsg.stuFaceData.emMask)).append("\r\n")
.append("胡子:").append(Res.string().getBeardState(faceMsg.stuFaceData.emBeard)).append("\r\n");
if (faceMsg.nRetCandidatesExNum > 0){
for(int i=0;i<faceMsg.nRetCandidatesExNum;i++){
StringBuilder birthday=new StringBuilder();
if(faceMsg.stuCandidatesEx[i].stPersonInfo.wYear!=0){
birthday.append(faceMsg.stuCandidatesEx[i].stPersonInfo.wYear);
}else if(faceMsg.stuCandidatesEx[i].stPersonInfo.byMonth!=0){
birthday.append("-").append(faceMsg.stuCandidatesEx[i].stPersonInfo.byMonth);
}else if(faceMsg.stuCandidatesEx[i].stPersonInfo.byDay!=0){
birthday.append("-").append(faceMsg.stuCandidatesEx[i].stPersonInfo.byDay);
}
faceDetectInfoStr.append("人脸库候选人信息:\r\n")
.append("姓名:").append(new String(faceMsg.stuCandidatesEx[i].stPersonInfo.szPersonName, "GBK")
.trim()).append("\r\n")
.append("性别:").append(Res.string()
.getSex(faceMsg.stuCandidatesEx[i].stPersonInfo.bySex)).append("\r\n")
.append("生日:").append(birthday).append("\r\n")
.append("证件号:").append(new String(faceMsg.stuCandidatesEx[i].stPersonInfo.szID, "GBK")
.trim()).append("\r\n")
.append("人脸库ID:").append(new String(faceMsg.stuCandidatesEx[i].stPersonInfo.szGroupID, "GBK")
.trim()).append("\r\n")
.append("人脸库名称:").append(new String(faceMsg.stuCandidatesEx[i].stPersonInfo.szGroupName, "GBK")
.trim()).append("\r\n")
.append("相似度:").append(faceMsg.stuCandidatesEx[i].bySimilarity).append("\r\n");
}
}
try {
fileWriter=new FileWriter(faceDetectInfoFile,true);
fileWriter.write(faceDetectInfoStr+"\r\n");
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fileWriter!=null){
fileWriter.close();
}
}
}
}
//候选人信息
}
;
/**
* 保存人脸检测事件图片
*
* @param pBuffer 抓拍图片信息
* @param dwBufSize 抓拍图片大小
* @param faceDetectInfo 人脸检测事件信息
*/
public void saveFaceDetectPic(
Pointer pBuffer, int dwBufSize, NetSDKLib.DEV_EVENT_FACEDETECT_INFO faceDetectInfo)
throws FileNotFoundException {
DateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
Date currentDate = new Date();
File path = new File("D:\\" + currentDate);
if (!path.exists()) {
path.mkdir();
}
if (pBuffer == null || dwBufSize <= 0) {
return;
}
// 小图的 stuObject.nRelativeID 来匹配大图的 stuObject.nObjectID,来判断是不是 一起的图片
if (groupId != faceDetectInfo.stuObject.nRelativeID) { // /->保存全景图
personBufferedImage = null;
groupId = faceDetectInfo.stuObject.nObjectID;
String strGlobalPicPathName =
path + "\\" + faceDetectInfo.UTC.toStringTitle() + "_FaceDetection_Global.jpg";
byte[] bufferGlobal = pBuffer.getByteArray(0, dwBufSize);
ByteArrayInputStream byteArrInputGlobal = new ByteArrayInputStream(bufferGlobal);
try {
globalBufferedImage = ImageIO.read(byteArrInputGlobal);
if (globalBufferedImage != null) {
File globalFile = new File(strGlobalPicPathName);
if (globalFile != null) {
ImageIO.write(globalBufferedImage, "jpg", globalFile);
}
}
} catch (IOException e2) {
e2.printStackTrace();
}
} else if (groupId == faceDetectInfo.stuObject.nRelativeID) { // /->保存人脸图
if (faceDetectInfo.stuObject.stPicInfo != null) {
String strPersonPicPathName =
path + "\\" + faceDetectInfo.UTC.toStringTitle() + "_FaceDetection_Person.jpg";
byte[] bufferPerson = pBuffer.getByteArray(0, dwBufSize);
ByteArrayInputStream byteArrInputPerson = new ByteArrayInputStream(bufferPerson);
try {
personBufferedImage = ImageIO.read(byteArrInputPerson);
if (personBufferedImage != null) {
File personFile = new File(strPersonPicPathName);
if (personFile != null) {
ImageIO.write(personBufferedImage, "jpg", personFile);
}
}
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
}
}
// 订阅
public void RealLoadPicture(int channel, int bNeedPicture, NetSDKLib.fAnalyzerDataCallBack callback) {
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 + "]订阅成功!");
}
}
private static boolean bInit = false;
private static boolean bLogopen = false;
//初始化
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 PictureHandle.DisConnectCallBack instance = new PictureHandle.DisConnectCallBack();
}
public static PictureHandle.DisConnectCallBack getInstance() {
return PictureHandle.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 PictureHandle.HaveReConnectCallBack instance = new PictureHandle.HaveReConnectCallBack();
}
public static PictureHandle.HaveReConnectCallBack getInstance() {
return PictureHandle.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);
}
}
}
开发流程:
1、根据sdk 运行人脸识别demo
2、查找对应订阅的代码转成对于的web代码
3、由于是使用 main方法,需加上阻止程序执行完的代码
4、在对于存放地址D盘下能看到 人类对比信息的txt文件和图片
注意:
1、需自己开发调用NetSDKLib里的方法,不能直接调用提供的demo、model里的方法,只能参考,官网的代码是java swing 图形界面开发方式,web方式的需自行参考demo转换。