我采用的是 報警布防方式? 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,節點:<ITCAbility>。
- 車牌識別包括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示例代碼
初始化+登錄
private boolean init(String ip, int port, String userName, String password) {/**加載日志*/if (!NET_DVR_Init()) {logger.error("攝像頭初始化失敗!錯誤碼為" + hCNetSDK.NET_DVR_GetLastError());return false;}hCNetSDK.NET_DVR_SetLogToFile(3, "./sdklog", false);userId = NET_DVR_Login_V30(ip, port, userName, password);if (userId > -1) {isinitialized = true;}return isinitialized;}
?設置回調+布防
public boolean licensePlateRecognition(CarNumRecognizerConfig carNumRecognizerConfig) {logger.debug("*********************licensePlateRecognition**************************");String ip = carNumRecognizerConfig.getCarNumRecognizerIP();int port = carNumRecognizerConfig.getPort();String userName = carNumRecognizerConfig.getUserName();String password = carNumRecognizerConfig.getPassword();if (StringUtil.isNotBlank(carNumRecognizerConfig.getEncoding())) {encode = carNumRecognizerConfig.getEncoding();}if (StringUtil.isNotBlank(carNumRecognizerConfig.getImageDir())) {imageDirPath = carNumRecognizerConfig.getImageDir();}if (!init(ip, port, userName, password)) {logger.error("攝像頭初始化失敗!");return false;}carNumRecognizerDevices = deviceManager.getCarNumRecognizerDevices();//設置連接時間與重連時間hCNetSDK.NET_DVR_SetConnectTime(2000, 1);hCNetSDK.NET_DVR_SetReconnect(100000, true);
//設備信息, 輸出參數//設置報警回調函數if (fMSFCallBack_V31 == null) {fMSFCallBack_V31 = new FMSGCallBack_V31();String UserData = "UserData";HCNetSDK.BYTE_ARRAY UserDataByte = new HCNetSDK.BYTE_ARRAY(25);UserDataByte.read();UserDataByte.byValue = UserData.getBytes();UserDataByte.write();Pointer pUserDataByte = UserDataByte.getPointer();if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(fMSFCallBack_V31, pUserDataByte)) {logger.error("設置回調函數失敗!+" + hCNetSDK.NET_DVR_GetLastError());return false;} else {logger.info("設置回調函數成功!");}}HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG struNET_DVR_LOCAL_GENERAL_CFG = new HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG();struNET_DVR_LOCAL_GENERAL_CFG.byAlarmJsonPictureSeparate = 1; //設置JSON透傳報警數據和圖片分離struNET_DVR_LOCAL_GENERAL_CFG.write();Pointer pStrNET_DVR_LOCAL_GENERAL_CFG = struNET_DVR_LOCAL_GENERAL_CFG.getPointer();hCNetSDK.NET_DVR_SetSDKLocalCfg(17, pStrNET_DVR_LOCAL_GENERAL_CFG);
//尚未布防,需要布防if (lAlarmHandle < 0) {//報警布防參數設置HCNetSDK.NET_DVR_SETUPALARM_PARAM m_strAlarmInfo = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();m_strAlarmInfo.dwSize = m_strAlarmInfo.size();m_strAlarmInfo.byLevel = 0; //布防等級m_strAlarmInfo.byAlarmInfoType = 1; // 智能交通報警信息上傳類型:0- 老報警信息(NET_DVR_PLATE_RESULT),1- 新報警信息(NET_ITS_PLATE_RESULT)m_strAlarmInfo.byDeployType = 1; //布防類型:0-客戶端布防,1-實時布防m_strAlarmInfo.write();lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(Integer.valueOf(userId + ""), m_strAlarmInfo);logger.info("lAlarmHandle: " + lAlarmHandle);if (lAlarmHandle == -1) {logger.info("布防失敗,錯誤碼為" + hCNetSDK.NET_DVR_GetLastError());return false;} else {logger.info("布防成功");}} else {logger.info("設備已經布防,請先撤防!");}return true;}
回調
public class FMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {//報警信息回調函數public boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {logger.info("報警事件類型: lCommand:" + Integer.toHexString(lCommand));//lCommand是傳的報警類型switch (lCommand) {case 3058:logger.info("報警事件類型: 0x3058 車輛黑白名單數據需要同步報警上傳");case HCNetSDK.COMM_UPLOAD_PLATE_RESULT:logger.info("報警事件類型: COMM_UPLOAD_PLATE_RESULT");case HCNetSDK.COMM_ITS_PLATE_RESULT://交通抓拍結果(新報警信息)logger.info("報警事件類型: COMM_ITS_PLATE_RESULT");HCNetSDK.NET_ITS_PLATE_RESULT strItsPlateResult = new HCNetSDK.NET_ITS_PLATE_RESULT();strItsPlateResult.write();Pointer pItsPlateInfo = strItsPlateResult.getPointer();pItsPlateInfo.write(0, pAlarmInfo.getByteArray(0, strItsPlateResult.size()), 0, strItsPlateResult.size());strItsPlateResult.read();try {String sLicense = new String(strItsPlateResult.struPlateInfo.sLicense, encode);String carNum = StringUtil.extractTheLicensePlateNumber(sLicense);//這個方法是提取車牌號 因為我接收到的車牌號會帶顏色在前面 比如 藍京A---- 這樣子logger.info("識別車號:{},提取車號:{}",sLicense,carNum);CarNumRecognizerResult carNumRecognizerResult = new CarNumRecognizerResult();carNumRecognizerResult.setCarNum(carNum);boolean isOK = carNumRecognizerDevices.notifyCarNumResult(carNumRecognizerResult);logger.info("isOK:::" + isOK);} catch (UnsupportedEncodingException e1) {e1.printStackTrace();logger.error(e1.getMessage(),e1);} catch (IOException e) {e.printStackTrace();logger.error(e.getMessage(),e);}/*** 報警圖片保存,車牌,車輛圖片*/if (StringUtil.isNotBlank(imageDirPath)){File imageDir = new File(imageDirPath);if(!imageDir.exists() || !imageDir.isDirectory()){imageDir.mkdirs();}for (int i = 0; i < strItsPlateResult.dwPicNum; i++) {if (strItsPlateResult.struPicInfo[i].dwDataLen > 0) {String baseName = DateUtil.getTimeStr((int)(System.currentTimeMillis()/1000), "yyyyMMddHHmmss");File imageFile = getImageFilePath(i+"", baseName, imageDir);FileOutputStream fout;try {fout = new FileOutputStream(imageFile);//將字節寫入文件long offset = 0;ByteBuffer buffers = strItsPlateResult.struPicInfo[i].pBuffer.getByteBuffer(offset, strItsPlateResult.struPicInfo[i].dwDataLen);byte[] bytes = new byte[strItsPlateResult.struPicInfo[i].dwDataLen];buffers.rewind();buffers.get(bytes);fout.write(bytes);fout.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}}break;default:logger.info("報警類型:" + Integer.toHexString(lCommand));break;}return true;}}
重點是這里? 我起初選擇0? 就不起作用? 可能是客戶端沒配置好?不懂
m_strAlarmInfo.byDeployType = 1; //布防類型:0-客戶端布防,1-實時布防
總結兩點:
1 確認攝像機客戶端中可以識別到車號!!!
2 確認使用哪種布防!!!
再提一嘴 我個人認為海康的車牌識別做的不好,因為我開發其他車牌識別產品 例如文通、VM、大華? 這些設備的車牌識別都是采用自動識別 主動推送的方式到http接口 更好處理 還不占資源。
海康也有監聽方法 但我沒研究明白 不會用..