C#海康车牌识别实战指南带源码
前言
车牌识别技术在智能交通、停车场管理等领域有着广泛的应用。海康威视作为国内领先的安防厂商,其车牌识别相机提供了丰富的SDK接口供开发者使用。本文将详细介绍如何使用C#语言结合海康威视SDK实现车牌识别功能,并解析关键代码实现。
一、环境准备
在开始之前,需要准备以下环境:
Visual Studio(推荐2017或更高版本)
海康威视网络SDK(HCNetSDK.dll)
海康威视车牌识别相机设备
.NET Framework 4.0或更高版本
二、项目结构
本项目包含两个核心类文件:
LicenseCameraGroup.cs
- 管理多个车牌识别相机的组类LicenseCameraItem.cs
- 单个车牌识别相机的实现类
三、核心代码解析
1. LicenseCameraGroup类解析
LicenseCameraGroup
类负责管理多个车牌识别相机,主要功能包括初始化SDK、启动监听服务和处理识别结果。
初始化SDK
public bool Init(List<lpr_entity> dataList, List<PictureBox> licenseCameraPicList) { try { LprList = dataList; bool m_bInitSDK = CHCNetSDK.NET_DVR_Init(); if (m_bInitSDK == false) { return false; } else { // 设置SDK日志路径 CHCNetSDK.NET_DVR_SetLogToFile(3, "C:\\SdkLog\\", true); // 设置异常消息回调函数 if (m_fExceptionCB == null) { m_fExceptionCB = new CHCNetSDK.EXCEPYIONCALLBACK(cbExceptionCB); } CHCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, IntPtr.Zero, m_fExceptionCB, IntPtr.Zero); // 设置报警回调函数 if (m_falarmData_V31 == null) { m_falarmData_V31 = new CHCNetSDK.MSGCallBack_V31(MsgCallback_V31); } CHCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(m_falarmData_V31, IntPtr.Zero); } // 初始化每个车牌识别相机 int a = 0; foreach (var item in dataList) { LicenseCameraItem licenseCameraItem = new LicenseCameraItem(); licenseCameraItem.Init(item.ip, item.port, item.serial_port, item.baud_rate, item.license_account, item.license_password, licenseCameraPicList[a], item.communication_mode); a++; } // 启动监听线程 Thread thread = new Thread(StartListen); thread.IsBackground = true; thread.Start(); return true; } catch (Exception ex) { return false; } }
启动监听服务
public void StartListen() { sLocalIP = GetIpV4(); ushort wLocalPort = 7200; if (m_falarmData == null) { m_falarmData = new CHCNetSDK.MSGCallBack(MsgCallback); } iListenHandle = CHCNetSDK.NET_DVR_StartListen_V30(sLocalIP, wLocalPort, m_falarmData, IntPtr.Zero); if (iListenHandle < 0) { iLastErr = CHCNetSDK.NET_DVR_GetLastError(); strErr = "启动监听失败,错误号:" + iLastErr; return; } }
处理车牌识别结果
private void ProcessCommAlarm_ITSPlate(ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser) { CHCNetSDK.NET_ITS_PLATE_RESULT struITSPlateResult = new CHCNetSDK.NET_ITS_PLATE_RESULT(); uint dwSize = (uint)Marshal.SizeOf(struITSPlateResult); struITSPlateResult = (CHCNetSDK.NET_ITS_PLATE_RESULT)Marshal.PtrToStructure(pAlarmInfo, typeof(CHCNetSDK.NET_ITS_PLATE_RESULT)); // 保存抓拍图片 for (int i = 0; i < struITSPlateResult.dwPicNum; i++) { if (struITSPlateResult.struPicInfo[i].dwDataLen != 0) { int iLen = (int)struITSPlateResult.struPicInfo[i].dwDataLen; byte[] by = new byte[iLen]; Marshal.Copy(struITSPlateResult.struPicInfo[i].pBuffer, by, 0, iLen); if (isSavePic) { // 保存图片到指定路径 if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); } string str = path + "\\[" + name + "]_Pictype_" + struITSPlateResult.struPicInfo[i].byType + "_PicNum[" + (i + 1) + "]_" + iFileNumber + ".jpg"; FileStream fs = new FileStream(str, FileMode.Create); fs.Write(by, 0, iLen); fs.Close(); iFileNumber++; } } } // 获取识别到的车牌号码 string stringPlateLicense = System.Text.Encoding.GetEncoding("GBK") .GetString(struITSPlateResult.struPlateInfo.sLicense).TrimEnd('\0'); if (!CardIds.Contains(stringPlateLicense)) { CardIds.Add(stringPlateLicense); } // 触发车牌识别事件 isFront = strIP == LprList[0].ip; GetNumberEvent(CardIds, isFront); CardIds.Clear(); }
2. LicenseCameraItem类解析
LicenseCameraItem
类负责单个车牌识别相机的管理,包括相机初始化、登录、预览和布防等功能。
相机初始化
public bool Init(string ip, string port, string account, string password) { try { _IP = ip; _Port = port; _Account = account; _Password = password; bool m_bInitSDK = CHCNetSDK.NET_DVR_Init(); if (m_bInitSDK == false) { return false; } return true; } catch (Exception ex) { return false; } }
相机登录
public bool CameraLogin1(out int num, string iP, string port, string account, string password) { try { //相机参数不能为空 if (String.IsNullOrEmpty(iP) || String.IsNullOrEmpty(port) || String.IsNullOrEmpty(account) || String.IsNullOrEmpty(password)) { num = 0; return false; } struLogInfo = new CHCNetSDK.NET_DVR_USER_LOGIN_INFO(); //登录 //设备IP地址或者域名 byte[] byIP = System.Text.Encoding.Default.GetBytes(iP); struLogInfo.sDeviceAddress = new byte[129]; byIP.CopyTo(struLogInfo.sDeviceAddress, 0); //设备用户名 byte[] byUserName = System.Text.Encoding.Default.GetBytes(account); struLogInfo.sUserName = new byte[64]; byUserName.CopyTo(struLogInfo.sUserName, 0); //设备密码 byte[] byPassword = System.Text.Encoding.Default.GetBytes(password); struLogInfo.sPassword = new byte[64]; byPassword.CopyTo(struLogInfo.sPassword, 0); struLogInfo.wPort = ushort.Parse(port);//设备服务端口号 if (LoginCallBack == null) { LoginCallBack = new CHCNetSDK.LOGINRESULTCALLBACK(cbLoginCallBack);//注册回调函数 } struLogInfo.cbLoginResult = LoginCallBack; struLogInfo.bUseAsynLogin = false; //是否异步登录:0- 否,1- 是 DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V40(); //登录设备 m_lUserID = CHCNetSDK.NET_DVR_Login_V40(ref struLogInfo, ref DeviceInfo); if (m_lUserID < 0) { iLastErr = CHCNetSDK.NET_DVR_GetLastError(); num = 0; return false; } num = m_lUserID; return true; } catch (Exception ex) { num = 0; return false; } }
打开相机预览
private bool OpenLicenseCamera(PictureBox LicenseCameraPic, string licenseIp, string licensePort, string licenseAccount, string licensePassword) { try { if (Init(licenseIp, licensePort, licenseAccount, licensePassword)) { if (CameraLogin1(out int num, licenseIp, licensePort, licenseAccount, licensePassword)) { m_lUserID = num; } else { return false; } //成功后打开摄像头 CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO(); lpPreviewInfo.hPlayWnd = LicenseCameraPic.Handle;//预览窗口 lpPreviewInfo.lChannel = 1;//预te览的设备通道 lpPreviewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推 lpPreviewInfo.dwLinkMode = 0;//连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP lpPreviewInfo.bBlocked = true; //0- 非阻塞取流,1- 阻塞取流 lpPreviewInfo.dwDisplayBufNum = 1; //播放库播放缓冲区最大缓冲帧数 lpPreviewInfo.byProtoType = 0; lpPreviewInfo.byPreviewMode = 0; if (RealData == null) { RealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack);//预览实时流回调函数 } IntPtr pUser = new IntPtr();//用户数据 //打开预览 m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, null/*RealData*/, pUser); if (m_lRealHandle < 0) { iLastErr = CHCNetSDK.NET_DVR_GetLastError(); return false; } //监听车牌线程 Thread thread = new Thread(LicenseThread); thread.IsBackground = true; thread.Start(); return true; } return false; } catch (Exception ex) { return false; } }
四、使用示例
// 创建车牌识别组 LicenseCameraGroup licenseCameraGroup = new LicenseCameraGroup(); // 订阅车牌识别事件 licenseCameraGroup.GetNumberEvent += (cardIds, isFront) => { foreach (string cardId in cardIds) { Console.WriteLine($"识别到车牌: {cardId}, 方向: {(isFront ? "前" : "后")}"); } }; // 初始化车牌识别相机 List<lpr_entity> lprList = new List<lpr_entity> { new lpr_entity { ip = "192.168.1.64", port = "8000", license_account = "admin", license_password = "12345" } }; List<PictureBox> pictureBoxes = new List<PictureBox> { pictureBox1 }; licenseCameraGroup.Init(lprList, pictureBoxes);
五、注意事项
确保正确引用海康威视的SDK文件(HCNetSDK.dll)
需要先初始化SDK再调用其他功能
确保网络通畅,相机设备可达
注意处理异常情况,如网络断开、设备离线等
合理管理资源,及时释放不需要的连接
注意编码问题,海康SDK通常使用GBK编码
确保相机参数配置正确,包括IP、端口、用户名和密码
六、总结
本文详细介绍了如何使用C#和海康威视SDK实现车牌识别功能。通过分析LicenseCameraGroup
和LicenseCameraItem
两个核心类,我们了解了如何初始化SDK、登录相机、启动预览、设置布防以及处理车牌识别结果。
关键点包括:
使用
NET_DVR_Init
初始化SDK使用
NET_DVR_Login_V40
登录相机设备使用
NET_DVR_RealPlay_V40
开启实时预览使用
NET_DVR_SetupAlarmChan_V41
设置布防通过回调函数处理车牌识别结果
在实际应用中,还需要考虑异常处理、性能优化和资源管理等问题。希望本文对您实现车牌识别功能有所帮助,如有疑问欢迎在评论区留言讨论。