前言: c#调用海康威视SDK实现车牌识别
原本以为海康威视sdk的Demo里面没有车牌识别的实例,后来发现自己肤浅了,官方是有提供的,只是车牌识别是通过安防布警的方式实现的.程序主动监听,触发告警后获取到车牌信息.
一、接口调用的流程:
首先初始化sdk -> 开始监听包进上传->停止监听报警上传->释放SDK资源, 过程比较简单,官方文档中的流程图如下,虚线框的内容是可选的,设备事先安装配置好,登录、能力集和配置接口可不调用,不会影响其他接口功能的使用。
二、车牌警告类型:
车牌上传的报警类型(lCommand)有COMM_ITS_PLATE_RESULT(0x3050)和COMM_PLATE_RESULT_V50(0x3063) 两种:当lCommand为COMM_ITS_PLATE_RESULT时,pAlarmInfo对应报警信息结构体为:NET_ITS_PLATE_RESULT;当lCommand为COMM_PLATE_RESULT_V50时,pAlarmInfo对应的报警信息结构体为: NET_DVR_PLATE_RESULT_V50。
三、监控设置告警服务器地址:
需要配置报警服务器的IP和端口,这个再下面代码里面是需要用到的。
四、代码实现:
1. copy 库文件到生成程序目录,以及官方提供的CHCNetSDK.cs拷贝到项目下。如之前的调用接口拍照过程。
2. 一些属性和方法委托的定义
private Int32 m_lUserID = -1;
private Int32[] m_lAlarmHandle = new Int32[200];
private Int32 iListenHandle = -1;
private int iDeviceNumber = 0; //添加设备个数
private int iFileNumber = 0; //保存的文件个数
private uint iLastErr = 0;
private string strErr;
public CHCNetSDK.LOGINRESULTCALLBACK LoginCallBack = null;
private CHCNetSDK.EXCEPYIONCALLBACK m_fExceptionCB = null;
private CHCNetSDK.MSGCallBack_V31 m_falarmData_V31 = null;
private CHCNetSDK.MSGCallBack m_falarmData = null;
public delegate void UpdateTextStatusCallback(string strLogStatus, IntPtr lpDeviceInfo);
public delegate void UpdateListBoxCallback(string strAlarmTime, string strDevIP, string strAlarmMsg);
public delegate void UpdateListBoxCallbackException(string strAlarmTime, int lUserID, string strAlarmMsg);
CHCNetSDK.NET_VCA_TRAVERSE_PLANE m_struTraversePlane = new CHCNetSDK.NET_VCA_TRAVERSE_PLANE();
CHCNetSDK.NET_VCA_AREA m_struVcaArea = new CHCNetSDK.NET_VCA_AREA();
CHCNetSDK.NET_VCA_INTRUSION m_struIntrusion = new CHCNetSDK.NET_VCA_INTRUSION();
CHCNetSDK.UNION_STATFRAME m_struStatFrame = new CHCNetSDK.UNION_STATFRAME();
CHCNetSDK.UNION_STATTIME m_struStatTime = new CHCNetSDK.UNION_STATTIME();
3. 类的构造函数中初始化SDK:
bool m_bInitSDK = CHCNetSDK.NET_DVR_Init();
if (m_bInitSDK == false)
{
MessageBox.Show("NET_DVR_Init error!");
return;
}
else
{
byte[] strIP = new byte[16 * 16];
uint dwValidNum=0;
Boolean bEnableBind=false;
//获取本地PC网卡IP信息
if (CHCNetSDK.NET_DVR_GetLocalIP(strIP, ref dwValidNum, ref bEnableBind))
{
if (dwValidNum > 0)
{
//取第一张网卡的IP地址为默认监听端口
textBoxListenIP.Text = System.Text.Encoding.UTF8.GetString(strIP, 0, 16);
//CHCNetSDK.NET_DVR_SetValidIP(0,true); //绑定第一张网卡
}
}
//保存SDK日志 To save the SDK log
CHCNetSDK.NET_DVR_SetLogToFile(3, "C:\\SdkLog\\", true);
//设置透传报警信息类型
CHCNetSDK.NET_DVR_LOCAL_GENERAL_CFG struLocalCfg = new CHCNetSDK.NET_DVR_LOCAL_GENERAL_CFG();
struLocalCfg.byAlarmJsonPictureSeparate = 1;//控制JSON透传报警数据和图片是否分离,0-不分离(COMM_VCA_ALARM返回),1-分离(分离后走COMM_ISAPI_ALARM回调返回)
Int32 nSize = Marshal.SizeOf(struLocalCfg);
IntPtr ptrLocalCfg = Marshal.AllocHGlobal(nSize);
Marshal.StructureToPtr(struLocalCfg, ptrLocalCfg, false);
if (!CHCNetSDK.NET_DVR_SetSDKLocalCfg(17, ptrLocalCfg)) //NET_DVR_LOCAL_CFG_TYPE_GENERAL
{
iLastErr = CHCNetSDK.NET_DVR_GetLastError();
strErr = "NET_DVR_SetSDKLocalCfg failed, error code= " + iLastErr;
MessageBox.Show(strErr);
}
Marshal.FreeHGlobal(ptrLocalCfg);
for (int i = 0; i < 200; i++)
{
m_lAlarmHandle[i] = -1;
}
//设置异常消息回调函数
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);
}
4. 绑定网卡监听:
string sLocalIP = textBoxListenIP.Text;
ushort wLocalPort = ushort.Parse(textBoxListenPort.Text);
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; //撤防失败,输出错误号
MessageBox.Show(strErr);
}
else
{
MessageBox.Show("成功启动监听!");
btnStopListen.Enabled = true;
btnStartListen.Enabled = false;
}
5. 接收事件,将事件写入到list中
private void ProcessCommAlarm_ISAPIAlarm(ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser)
{
CHCNetSDK.NET_DVR_ALARM_ISAPI_INFO struISAPIAlarm = new CHCNetSDK.NET_DVR_ALARM_ISAPI_INFO();
uint dwSize = (uint)Marshal.SizeOf(struISAPIAlarm);
struISAPIAlarm = (CHCNetSDK.NET_DVR_ALARM_ISAPI_INFO)Marshal.PtrToStructure(pAlarmInfo, typeof(CHCNetSDK.NET_DVR_ALARM_ISAPI_INFO));
//报警设备IP地址
string strIP = System.Text.Encoding.UTF8.GetString(pAlarmer.sDeviceIP).TrimEnd('\0');
//保存XML或者Json数据
string str = "";
if ((struISAPIAlarm.dwAlarmDataLen != 0) && (struISAPIAlarm.pAlarmData != IntPtr.Zero))
{
if (struISAPIAlarm.byDataType == 1) // 0-invalid,1-xml,2-json
{
str = ".\\picture\\ISAPI_Alarm_XmlData_[" + strIP + "]_lUerID_[" + pAlarmer.lUserID + "]_" + iFileNumber + ".xml";
}
if (struISAPIAlarm.byDataType == 2) // 0-invalid,1-xml,2-json
{
str = ".\\picture\\ISAPI_Alarm_JsonData_[" + strIP + "]_lUerID_[" + pAlarmer.lUserID + "]_" + iFileNumber + ".json";
}
FileStream fs = new FileStream(str, FileMode.Create);
int iLen = (int)struISAPIAlarm.dwAlarmDataLen;
byte[] by = new byte[iLen];
Marshal.Copy(struISAPIAlarm.pAlarmData, by, 0, iLen);
fs.Write(by, 0, iLen);
fs.Close();
iFileNumber++;
}
for (int i = 0; i < struISAPIAlarm.byPicturesNumber; i++)
{
CHCNetSDK.NET_DVR_ALARM_ISAPI_PICDATA struPicData = new CHCNetSDK.NET_DVR_ALARM_ISAPI_PICDATA();
struPicData.szFilename = new byte[256];
Int32 nSize = Marshal.SizeOf(struPicData);
struPicData = (CHCNetSDK.NET_DVR_ALARM_ISAPI_PICDATA)Marshal.PtrToStructure((IntPtr)((Int64)(struISAPIAlarm.pPicPackData) + i * nSize), typeof(CHCNetSDK.NET_DVR_ALARM_ISAPI_PICDATA));
//保存图片数据
if ((struPicData.dwPicLen != 0) && (struPicData.pPicData != IntPtr.Zero))
{
str = ".\\picture\\ISAPI_Alarm_Pic_[" + strIP + "]_lUerID_[" + pAlarmer.lUserID + "]_"
+ "_" + iFileNumber + ".jpg";
FileStream fs = new FileStream(str, FileMode.Create);
int iLen = (int)struPicData.dwPicLen;
byte[] by = new byte[iLen];
Marshal.Copy(struPicData.pPicData, by, 0, iLen);
fs.Write(by, 0, iLen);
fs.Close();
iFileNumber++;
}
}
string stringAlarm = "ISAPI报警信息,byDataType:" + struISAPIAlarm.byDataType + ",图片张数:" + struISAPIAlarm.byPicturesNumber;
if (InvokeRequired)
{
object[] paras = new object[3];
paras[0] = DateTime.Now.ToString(); //当前PC系统时间
paras[1] = strIP;
paras[2] = stringAlarm;
listViewAlarmInfo.BeginInvoke(new UpdateListBoxCallback(UpdateClientList), paras);
}
else
{
//创建该控件的主线程直接更新信息列表
UpdateClientList(DateTime.Now.ToString(), strIP, stringAlarm);
}
}
public void UpdateClientList(string strAlarmTime, string strDevIP, string strAlarmMsg)
{
//列表新增报警信息
listViewAlarmInfo.Items.Add(new ListViewItem(new string[] { strAlarmTime, strDevIP, strAlarmMsg }));
}