• java调用海康威视SDK实现车牌识别


    我采用的是 报警布防方式  SDK版本为 CH-HCNetSDKV6.1.9.48_build20230410_win32

    如何引用dll 我用的是jna 就不描述了  SDK在官网自行下载  以下代码亲测可用 自行参考~

    1.1接口调用流程

    虚线框的内容是可选的,设备事先安装配置好,能力集和配置接口可不调用,不会影响其他接口功能的使用。

    • 初始化NET_DVR_Init接口在程序开始是调用,只需要调用一次。
    • 用户注册即登录设备,调用NET_DVR_Login_V40接口,每一台设备只需要登录一次。
    • 登录设备之后,可以通过NET_DVR_GetDeviceAbility获取智能交通能力集可以判断设备是否支持相关功能,能力集类型:DEVICE_ABILITY_INFO,能力集:ITDeviceAbility,节点:
    • 车牌识别包括IO触发、虚拟线圈触发等自动触发抓拍模式和网络触发等手动抓拍模式。
      如果是自动触发模式,一般建议通过WEB网页登录设备进行配置调试,也可以通过SDK接口进行配置,相关接口:NET_DVR_GetDVRConfig(命令:NET_ITC_GET_TRIGGERCFG)、NET_DVR_SetDVRConfig(命令:NET_ITC_SET_TRIGGERCFG)、NET_DVR_GetDeviceConfig(命令:NET_DVR_GET_TRIGGEREX_CFG)、NET_DVR_SetDeviceConfig(命令:NET_DVR_SET_TRIGGEREX_CFG)等。
      如果是手动抓拍,有两种方式:1)通过NET_DVR_ManualSnap可以在接口直接返回结果信息;2)通过NET_DVR_ContinuousShoot发送网络触发连拍命令,抓拍结果跟自动触发模式一样,通过报警布防方式在报警回调函数里面返回。
    • 配置好设备相关参数,车辆通过时进行抓拍和识别,结果信息通过报警布防方式获取,具体实现方法:
      1) 先调用NET_DVR_SetDVRMessageCallBack_V50设置报警回调函数(V31、V30接口也支持,新接口兼容老接口),在SDK初始化之后即可以调用,多台设备对接时也只需要调用一次设置一个回调函数,回调函数里面接收数据之后可以通过报警设备信息(NET_DVR_ALARMER)中lUserID等参数判断区分设备。
      2) 每台设备分别登录,分别调用NET_DVR_SetupAlarmChan_V41进行布防,布防即建立设备跟客户端之间报警上传的连接通道,这样设备发生报警之后通过该连接上传报警信息,SDK在报警回调函数中接收和处理报警信息数据即可。对接智能交通摄像机,布防时可以选择布防等级,一级布防(byLevel为0)最大连接数为1个,二级布防(byLevel为1)最大连接数为3个,如果已经达到上限了,再布防就会失败,SDK将返回28的错误号。
      3) 程序退出前或者不需要接收报警信息时调用NET_DVR_CloseAlarmChan_V30进行撤防,释放资源,此时连接断开,设备将不再上传报警信息。
    • 车牌识别的报警信息类型为COMM_ITS_PLATE_RESULT(新报警信息)和COMM_UPLOAD_PLATE_RESULT(老报警信息),分别对应接口NET_DVR_SetupAlarmChan_V41中布防参数byAlarmInfoType=1和byAlarmInfoType=0。建议使用新的报警信息类型。
      1)设备是否支持新报警信息可从注册返回的能力获知,详见NET_DVR_DEVICEINFO_V30结构中bySupport1&0x80(表示是否支持车牌新报警信息),如果注册返回能力不支持,设备仅支持老报警信息上传。
      2)COMM_UPLOAD_PLATE_RESULT:兼容旧型号(976/986/966等)抓拍机,一次回调只上传一张图片信息,对应报警信息结构体:NET_DVR_PLATE_RESULT
      3)COMM_ITS_PLATE_RESULT:应用于违章图片组一次性上传以及合成图片上传等新功能,对应报警信息结构体:NET_ITS_PLATE_RESULT
    • 退出程序时调用NET_DVR_Logout注销设备,每一台设备调用一次。最后调用NET_DVR_Cleanup释放SDK所有资源。

    1.2示例代码

    初始化+登录

    1. private boolean init(String ip, int port, String userName, String password) {
    2. /**加载日志*/
    3. if (!NET_DVR_Init()) {
    4. logger.error("摄像头初始化失败!错误码为" + hCNetSDK.NET_DVR_GetLastError());
    5. return false;
    6. }
    7. hCNetSDK.NET_DVR_SetLogToFile(3, "./sdklog", false);
    8. userId = NET_DVR_Login_V30(ip, port, userName, password);
    9. if (userId > -1) {
    10. isinitialized = true;
    11. }
    12. return isinitialized;
    13. }

     设置回调+布防

    1. public boolean licensePlateRecognition(CarNumRecognizerConfig carNumRecognizerConfig) {
    2. logger.debug("*********************licensePlateRecognition**************************");
    3. String ip = carNumRecognizerConfig.getCarNumRecognizerIP();
    4. int port = carNumRecognizerConfig.getPort();
    5. String userName = carNumRecognizerConfig.getUserName();
    6. String password = carNumRecognizerConfig.getPassword();
    7. if (StringUtil.isNotBlank(carNumRecognizerConfig.getEncoding())) {
    8. encode = carNumRecognizerConfig.getEncoding();
    9. }
    10. if (StringUtil.isNotBlank(carNumRecognizerConfig.getImageDir())) {
    11. imageDirPath = carNumRecognizerConfig.getImageDir();
    12. }
    13. if (!init(ip, port, userName, password)) {
    14. logger.error("摄像头初始化失败!");
    15. return false;
    16. }
    17. carNumRecognizerDevices = deviceManager.getCarNumRecognizerDevices();
    18. //设置连接时间与重连时间
    19. hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
    20. hCNetSDK.NET_DVR_SetReconnect(100000, true);
    21. //设备信息, 输出参数
    22. //设置报警回调函数
    23. if (fMSFCallBack_V31 == null) {
    24. fMSFCallBack_V31 = new FMSGCallBack_V31();
    25. String UserData = "UserData";
    26. HCNetSDK.BYTE_ARRAY UserDataByte = new HCNetSDK.BYTE_ARRAY(25);
    27. UserDataByte.read();
    28. UserDataByte.byValue = UserData.getBytes();
    29. UserDataByte.write();
    30. Pointer pUserDataByte = UserDataByte.getPointer();
    31. if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(fMSFCallBack_V31, pUserDataByte)) {
    32. logger.error("设置回调函数失败!+" + hCNetSDK.NET_DVR_GetLastError());
    33. return false;
    34. } else {
    35. logger.info("设置回调函数成功!");
    36. }
    37. }
    38. HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG struNET_DVR_LOCAL_GENERAL_CFG = new HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG();
    39. struNET_DVR_LOCAL_GENERAL_CFG.byAlarmJsonPictureSeparate = 1; //设置JSON透传报警数据和图片分离
    40. struNET_DVR_LOCAL_GENERAL_CFG.write();
    41. Pointer pStrNET_DVR_LOCAL_GENERAL_CFG = struNET_DVR_LOCAL_GENERAL_CFG.getPointer();
    42. hCNetSDK.NET_DVR_SetSDKLocalCfg(17, pStrNET_DVR_LOCAL_GENERAL_CFG);
    43. //尚未布防,需要布防
    44. if (lAlarmHandle < 0) {
    45. //报警布防参数设置
    46. HCNetSDK.NET_DVR_SETUPALARM_PARAM m_strAlarmInfo = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
    47. m_strAlarmInfo.dwSize = m_strAlarmInfo.size();
    48. m_strAlarmInfo.byLevel = 0; //布防等级
    49. m_strAlarmInfo.byAlarmInfoType = 1; // 智能交通报警信息上传类型:0- 老报警信息(NET_DVR_PLATE_RESULT),1- 新报警信息(NET_ITS_PLATE_RESULT)
    50. m_strAlarmInfo.byDeployType = 1; //布防类型:0-客户端布防,1-实时布防
    51. m_strAlarmInfo.write();
    52. lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(Integer.valueOf(userId + ""), m_strAlarmInfo);
    53. logger.info("lAlarmHandle: " + lAlarmHandle);
    54. if (lAlarmHandle == -1) {
    55. logger.info("布防失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());
    56. return false;
    57. } else {
    58. logger.info("布防成功");
    59. }
    60. } else {
    61. logger.info("设备已经布防,请先撤防!");
    62. }
    63. return true;
    64. }

    回调

    1. public class FMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
    2. //报警信息回调函数
    3. public boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
    4. logger.info("报警事件类型: lCommand:" + Integer.toHexString(lCommand));
    5. //lCommand是传的报警类型
    6. switch (lCommand) {
    7. case 3058:
    8. logger.info("报警事件类型: 0x3058 车辆黑白名单数据需要同步报警上传");
    9. case HCNetSDK.COMM_UPLOAD_PLATE_RESULT:
    10. logger.info("报警事件类型: COMM_UPLOAD_PLATE_RESULT");
    11. case HCNetSDK.COMM_ITS_PLATE_RESULT://交通抓拍结果(新报警信息)
    12. logger.info("报警事件类型: COMM_ITS_PLATE_RESULT");
    13. HCNetSDK.NET_ITS_PLATE_RESULT strItsPlateResult = new HCNetSDK.NET_ITS_PLATE_RESULT();
    14. strItsPlateResult.write();
    15. Pointer pItsPlateInfo = strItsPlateResult.getPointer();
    16. pItsPlateInfo.write(0, pAlarmInfo.getByteArray(0, strItsPlateResult.size()), 0, strItsPlateResult.size());
    17. strItsPlateResult.read();
    18. try {
    19. String sLicense = new String(strItsPlateResult.struPlateInfo.sLicense, encode);
    20. String carNum = StringUtil.extractTheLicensePlateNumber(sLicense);//这个方法是提取车牌号 因为我接收到的车牌号会带颜色在前面 比如 蓝京A---- 这样子
    21. logger.info("识别车号:{},提取车号:{}",sLicense,carNum);
    22. CarNumRecognizerResult carNumRecognizerResult = new CarNumRecognizerResult();
    23. carNumRecognizerResult.setCarNum(carNum);
    24. boolean isOK = carNumRecognizerDevices.notifyCarNumResult(carNumRecognizerResult);
    25. logger.info("isOK:::" + isOK);
    26. } catch (UnsupportedEncodingException e1) {
    27. e1.printStackTrace();
    28. logger.error(e1.getMessage(),e1);
    29. } catch (IOException e) {
    30. e.printStackTrace();
    31. logger.error(e.getMessage(),e);
    32. }
    33. /**
    34. * 报警图片保存,车牌,车辆图片
    35. */
    36. if (StringUtil.isNotBlank(imageDirPath)){
    37. File imageDir = new File(imageDirPath);
    38. if(!imageDir.exists() || !imageDir.isDirectory()){
    39. imageDir.mkdirs();
    40. }
    41. for (int i = 0; i < strItsPlateResult.dwPicNum; i++) {
    42. if (strItsPlateResult.struPicInfo[i].dwDataLen > 0) {
    43. String baseName = DateUtil.getTimeStr((int)(System.currentTimeMillis()/1000), "yyyyMMddHHmmss");
    44. File imageFile = getImageFilePath(i+"", baseName, imageDir);
    45. FileOutputStream fout;
    46. try {
    47. fout = new FileOutputStream(imageFile);
    48. //将字节写入文件
    49. long offset = 0;
    50. ByteBuffer buffers = strItsPlateResult.struPicInfo[i].pBuffer.getByteBuffer(offset, strItsPlateResult.struPicInfo[i].dwDataLen);
    51. byte[] bytes = new byte[strItsPlateResult.struPicInfo[i].dwDataLen];
    52. buffers.rewind();
    53. buffers.get(bytes);
    54. fout.write(bytes);
    55. fout.close();
    56. } catch (FileNotFoundException e) {
    57. e.printStackTrace();
    58. } catch (IOException e) {
    59. e.printStackTrace();
    60. }
    61. }
    62. }
    63. }
    64. break;
    65. default:
    66. logger.info("报警类型:" + Integer.toHexString(lCommand));
    67. break;
    68. }
    69. return true;
    70. }
    71. }

    重点是这里  我起初选择0  就不起作用  可能是客户端没配置好?不懂

    m_strAlarmInfo.byDeployType = 1;   //布防类型:0-客户端布防,1-实时布防

    总结两点:

    1 确认摄像机客户端中可以识别到车号!!!

    2 确认使用哪种布防!!!

    再提一嘴 我个人认为海康的车牌识别做的不好,因为我开发其他车牌识别产品 例如文通、VM、大华  这些设备的车牌识别都是采用自动识别 主动推送的方式到http接口 更好处理 还不占资源。

    海康也有监听方法 但我没研究明白 不会用..

  • 相关阅读:
    python-opencv车牌检测和定位
    [附源码]计算机毕业设计springboot旅游度假村管理系统
    ubuntu18.04配置Java环境与安装RCS库
    Qt鼠标事件全面解析:从基础到实战
    SE38 程序/事务码修改日志报表
    Kafka系列之:安装具有安全认证的kafka-2.8.2分布式集群
    qt状态机QtState
    Vue3【Composition API 的优势、新的组件(Fragment、Teleport、Suspense)、全局API的转移】
    2310D库功能还是语言功能
    怎么使用 Go 语言操作 Apache Doris
  • 原文地址:https://blog.csdn.net/m0_59680416/article/details/139957902