前言

项目采购的海康威视的抓拍机,需要首先获取抓拍图片,之后基于抓拍图片进行图像处理。本文基于海康SDK开发文档,按照开发步骤,咨询海康技术人员,现将开发过程记录如下。

主要过程的c++代码:

/************************************************************************
* Copyright(c) 2016 ZRJ
* All rights reserved.
*
* File: snap.h
* Brief: 抓拍机配置头文件
* Version: 1.0
* Author: ZRJ
* Email: happyamyhope@163.com
* Date: 2016/12/08
* History:
* 20161202: 添加布防级别与退出撤防功能;
* 20161207: 设置抓拍等待时间等;添加系统时间;
* 20161208: 添加复制文件夹操作;
* 20161208: 添加启动程序初始化图片不保存;删除网络触发抓拍部分;
* 20161209: 删除网络触发抓拍部分;
* 20161220: 现场调试增加的功能;
* 20170109: 删除FIFO队列数据;
* 20170123: 添加创建文件夹功能,删除预览取流部分; ************************************************************************/
//-------------------------------------------------------------------------
//头文件
#include <stdio.h>
#include <iostream>
#include "Windows.h"
#include "HCNetSDK.h"
//获取系统时间
#include <time.h> //OPENCV库文件
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2\opencv.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
using namespace std; typedef HWND(WINAPI *PROCGETCONSOLEWINDOW)();
PROCGETCONSOLEWINDOW Getconsolewindow; //-----------------------------------------------------------------------
//调参
int iNum = ;//抓拍图片的数目初始化值
int pic_number = ;//抓拍文件夹存图数目
//int j = 1;//显示抓拍图片的数目
//注册设备
LONG IUserID;//摄像机设备
char *sDVRIP = "10.0.10.3";//抓拍摄像机设备IP地址
short wDVRPort = ;//设备端口号
char* sUserName = "admin";//登录的用户名
char* sPassword = "admin123";//用户密码
//
time_t t;
char now[]; //
int fifo_flag = ;//队列标志;
double interval_time;//当前抓拍图片与前一帧抓拍时间之差;单位是ms;
double interval_time_thres = ;//前后两帧抓拍时间间隔阈值40s;单位是ms;
double pre_time;//系统开始时间;前一次抓拍图片的时间点;
double cur_time; //
LONG IHandle = -;//报警布防;
bool snap_flag = false;//是否抓拍的标志位
NET_DVR_DEVICEINFO_V30 struDeviceInfo;//设备信息 //---------------------------------------------------------------------------------
//函数声明
BOOL SHDeleteFolder(LPCTSTR pstrFolder);//删除指定目录
void CopyFolder(SHFILEOPSTRUCT fop);//抓拍图片文件夹操作
void CreateFolder(char* filename);//不存在则创建文件夹;
void Init();//初始化
void Connect();//设置连接事件与重连时间
bool Login(char *sDVRIP, short wDVRPort, char *sUserName, char *sPassword);//注册摄像机设备
void CALLBACK MSesGCallback(LONG ICommand, NET_DVR_ALARMER *pAlarmer, char *pAlarmInfo, DWORD dwBufLen, void *pUser);//报警回调函数
void SetMessageCallBack();//设置报警回调函数
void SetupAlarm();//报警布防
void CloseAlarm();//报警撤防
void OnExit(void);//退出
extern int snap();//抓拍 //-----------------------------------------------------------------------------------------
//函数定义 //初始化
void Init()
{
NET_DVR_Init();
}
//设置连接事件与重连时间
void Connect()
{
NET_DVR_SetConnectTime(, );
NET_DVR_SetReconnect(, true);
}
//注册摄像机设备
bool Login(char *sDVRIP, short wDVRPort, char *sUserName, char *sPassword)
{
IUserID = NET_DVR_Login_V30(sDVRIP, wDVRPort, sUserName, sPassword, &struDeviceInfo); if (IUserID < )
{
std::cout << "Login Failed! Error number:" << NET_DVR_GetLastError() << std::endl;
NET_DVR_Cleanup();
return false;
}
else
{
std::cout << "Login Successfully!" << std::endl;
return true;
} }
//报警回调函数
void CALLBACK MSesGCallback(LONG ICommand, NET_DVR_ALARMER *pAlarmer, char *pAlarmInfo, DWORD dwBufLen, void *pUser)
{
//unsigned int i = 0;
char filename[];
FILE *fSnapPic = NULL;
//std::cout << "Callback MSesGCallback one time..." << std::endl;
//std::cout << "ICommand:" << ICommand << std::endl;
//以下代码仅供参考,实际应用中不建议在该回调函数中直接处理数据保存文件,
//例如可以使用消息的方式(PostMessage)在消息响应函数里进行处理 switch (ICommand)
{
case COMM_UPLOAD_PLATE_RESULT://交通抓拍结果(老报警消息)
{
NET_DVR_PLATE_RESULT struPlateResult = { };
memcpy(&struPlateResult, pAlarmInfo, sizeof(struPlateResult)); //获取场景图
if (struPlateResult.dwPicLen != && struPlateResult.byResultType == )
{
snap_flag = true;
//计时
cur_time = (double)getTickCount();//当前抓拍图片的时间点;
t = time(NULL);//系统当前时间
strftime(now, sizeof(now), "%Y%m%dT%H%M%S", localtime(&t));
sprintf(filename, ".\\pic\\testpic%d_%s.jpg", iNum, now);
fSnapPic = fopen(filename, "wb");
fwrite(struPlateResult.pBuffer1, struPlateResult.dwPicLen, , fSnapPic); //前后两次抓拍图片的时间差
if (fifo_flag == )//系统开始
{
interval_time = ;
fifo_flag = ;
}
else
{
interval_time = (cur_time - pre_time) * / (getTickFrequency());//单位是ms;
} //fifo标志位转换
if (interval_time > interval_time_thres)
{
if (fifo_flag == )
{
fifo_flag = ;
}
else if (fifo_flag == )
{
fifo_flag = ;
}
}
//std::cout << "fifo_flag: " << fifo_flag << std::endl;
//获取抓拍图片队列
if (fifo_flag == )
{
std::cout << "fifo1 push back one time..." << std::endl;
}
else if (fifo_flag == )
{
std::cout << "fifo2 push back one time..." << std::endl;
} iNum++;
if (pic_number == iNum)
{
iNum = ;
CopyFolder(fop);//抓拍图片文件夹操作
}
else
{ }
pre_time = cur_time;
fclose(fSnapPic);
}
else
{
snap_flag = false;
} //其他信息处理
break; }
case COMM_ITS_PLATE_RESULT://交通抓拍结果(新报警信息)
{
NET_ITS_PLATE_RESULT struITSPlateResult = { };//识别结果结构体;dwPicNum
memcpy(&struITSPlateResult, pAlarmInfo, sizeof(struITSPlateResult));
struITSPlateResult.dwPicNum = ;//图片数量(与byGroupNum不同,代表本条信息附带的图片数量)
//保存场景图
if ((struITSPlateResult.struPicInfo[].dwDataLen != ) && (struITSPlateResult.struPicInfo[].byType == ))
{
snap_flag = true;
//计时
cur_time = (double)getTickCount();
//系统当前时间
t = time(NULL);
strftime(now, sizeof(now), "%Y%m%dT%H%M%S", localtime(&t));
sprintf(filename, ".\\pic\\testITSpic%d_%s.jpg", iNum, now);
fSnapPic = fopen(filename, "wb");
fwrite(struITSPlateResult.struPicInfo[].pBuffer, struITSPlateResult.struPicInfo[].dwDataLen, , fSnapPic); //前后两次抓拍图片的时间差
if (fifo_flag == )//系统开始
{
interval_time = ;
fifo_flag = ;
}
else
{
interval_time = (cur_time - pre_time) * / (getTickFrequency());//单位是ms;
}
//std::cout << "interval_time: " << interval_time << std::endl; //fifo标志位转换
if (interval_time > interval_time_thres)
{
if (fifo_flag == )
{
fifo_flag = ;
}
else if (fifo_flag == )
{
fifo_flag = ;
}
}
//std::cout << "fifo_flag: " << fifo_flag << std::endl;
//获取抓拍图片队列
if (fifo_flag == )
{
std::cout << "fifo1 push back one time..." << std::endl;
}
else if (fifo_flag == )
{
std::cout << "fifo2 push back one time..." << std::endl;
} iNum++;
if (pic_number == iNum)
{
iNum = ;
CopyFolder(fop);//抓拍图片文件夹操作
}
else
{ }
pre_time = cur_time;
//std::cout << "pre_time: " << pre_time << std::endl; fclose(fSnapPic);
}
else
{
snap_flag = false;
}
//其他处理信息......
break;
} default:
break; } return;
}
//设置报警回调函数
void SetMessageCallBack()
{
NET_DVR_SetDVRMessageCallBack_V30(MSesGCallback, NULL);
}
//报警布防
void SetupAlarm()
{
//启动布防
NET_DVR_SETUPALARM_PARAM struSetupParam = { };
struSetupParam.dwSize = sizeof(NET_DVR_SETUPALARM_PARAM); //上传报警信息类型:0-老报警信息(NET_DVR_PLATE_RESULT), 1-新报警信息(NET_ITS_PLATE_RESULT)
struSetupParam.byAlarmInfoType = ;
struSetupParam.byLevel = ;//布防优先级:0- 一等级(高),1- 二等级(中),2- 三等级(低)
//bySupport 按位表示,值:0 - 上传,1 - 不上传; bit0 - 表示二级布防是否上传图片; IHandle = NET_DVR_SetupAlarmChan_V41(IUserID, &struSetupParam);//建立报警上传通道,获取报警等信息。
if (IHandle < )
{
std::cout << "NET_DVR_SetupAlarmChan_V41 Failed! Error number:" << NET_DVR_GetLastError() << std::endl;
NET_DVR_Logout(IUserID);
NET_DVR_Cleanup();
return;
}
std::cout << "\n" << endl; }
//报警撤防
void CloseAlarm()
{
//撤销布防上传通道
if (!NET_DVR_CloseAlarmChan_V30(IHandle))//布防句柄IHandle
{
std::cout << "NET_DVR_CloseAlarmChan_V30 Failed! Error number:" << NET_DVR_GetLastError() << std::endl;
NET_DVR_Logout(IUserID);
NET_DVR_Cleanup();
return;
}
IHandle = -;//布防句柄;
} void OnExit(void)
{
std::cout << "Begin exit..." << std::endl; //报警撤防
CloseAlarm(); //释放相机
NET_DVR_Logout(IUserID);//注销用户
NET_DVR_Cleanup();//释放SDK资源
}
//抓拍
extern int snap()
{
atexit(OnExit);
int CycleCount = ;
bool LoginSuccess = false; //获取控制台窗口句柄
HMODULE hKernel32 = GetModuleHandle("kernel32");
Getconsolewindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32, "GetConsoleWindow"); CreateFolder(picfile);//不存在则创建文件夹;
CreateFolder(savepicfile);//不存在则创建文件夹;
Init();//初始化
Connect();//设置连接事件与重连时间
//注册设备
if (Login(sDVRIP, wDVRPort, sUserName, sPassword))
{
LoginSuccess = true;
SetMessageCallBack();//设置报警回调函数
SetupAlarm();//报警布防
return ;
}
else
{
for (int i = ; i < CycleCount; i++)
{
std::cout << "Begin to Login again......" << std::endl;
if (Login(sDVRIP, wDVRPort, sUserName, sPassword))
{
LoginSuccess = true;
SetMessageCallBack();//设置报警回调函数
SetupAlarm();//报警布防
break;
}
}
if (!LoginSuccess)
{
std::cout << "Failed! The application has tried 10 times to login. But still can not login! Press any key to exit......" << std::endl;
}
}
return -; } int main()
{
atexit(OnExit);
snap();
getchar(); }

注意:

1.第一步需要配置SDK和opencv相关文件;

2.熟悉抓拍机SDk的开发流程,可参见开发文档;

3.布防成功之后,需要添加退出撤防功能;

4.保存图片可能需要用到相关文件夹操作;

5.预览取流部分可以根据需要选择,为了实时性本文没有使用;

6.为了之后的图像处理过程,将图片数据存在FIFO队列中,但一定要记得及时删除相应的队列,否则会造成内存泄漏,从而导致系统崩溃(宝宝就不小心犯了这样的低级错误,以此为戒!!!);

7.布防级别的设置,这个一定要问清楚技术支持,因为你根本就查不到,反正宝宝没有查到!!!宝宝委屈但宝宝不说~~~

体会

第一次接触SDk开发,期间真是各种心酸,说多了都是泪~~~不过,整个过程首先你需要知道大致的框架和流程,认真研读需要部分的开发文档,一般也会有代码示例可以参考,按照文档的思路走你就一定会成功的,相信自己!!!中间过程如果遇到任何问题可以及时咨询技术支持,最好邮件联系,那段时间海康的技术支持可能都记着宝宝啦~~另外,第一次做某件事情担心害怕也是正常的,但是你一定要相信自己,静下心去做,只有真正去实践了,才会遇到问题,遇到问题也不要怕更不要急躁,可以查资料,可以问大神,可以问技术支持,总会解决的!!!无论做什么事情都要一步步去做,在实践的过程中所有问题和答案就会越来越清晰了~~

海康抓拍机SDK开发的更多相关文章

  1. 海康设备网络SDK 编程

    http://www.cnblogs.com/qtblog/p/5366276.html http://www.hikvision.com/Cn/download_more_401.html

  2. C#制作ActiveX控件中调用海康SDK的问题

    事情是这样的,有一台海康威视的摄像头,客户需要一个ActiveX控件嵌入到网页中,通过点击按钮开始录制和结束录制来进行视频的录制和保存,关于海康摄像头的二次开发在此就不多说了,可以参考SDK中的说明. ...

  3. Java 实现 海康摄像头抓拍图像 Windows、Linux

    先抱怨一下,打死都想不到,海康的摄像头SDK居然是一个Java类,还有必须的两个jar包(jna.jar,examples.jar).鬼能想得到会这么命名. 下面开始吧. Windows 把从官网下载 ...

  4. 海康PTZ云台摄像头调试之直接控制云台(C#)

    众所周知,海康的摄像头sdk较为完善,但是对于新手来说还是有点麻烦. 今天写一篇随笔给大家展示下怎么控制海康摄像头的云台(前提是有ptz云台设备) 1.sdk准备 本文基于C#的frame来开发一个p ...

  5. 使用golang对海康sdk进行业务开发

    目录 准备工作 开发环境信息 改写HCNetSDK.h头文件 开发过程 基本数据类型转换 业务开发 参考 项目最近需要改造升级:操作海康摄像头(包括登录,拍照,录像)等基本功能.经过一段时间研究后,发 ...

  6. Java二次开发海康SDK-对接门禁机

    写在最前 SDK版本:CH-HCNetSDKV6.1.6.45_build20210302_win64 参考文档:海康SDK使用手册_V6.1 对接测试设备型号:DS-K1T671M 设备序列号:E5 ...

  7. 海康SDK编程指南(C#二次开发版本)

    海康SDK编程指南 目前使用的海康SDK包括IPC_SDK(硬件设备),Plat_SDK(平台),其中两套SDK都需单独调用海康播放库PlayCtrl.dll来解码视频流,返回视频信息和角度信息.本文 ...

  8. 海康相机SDK二次开发只有视频无声音问题

    海康SDK相信做企业开发的的同仁,在项目中经常会用到,毕竟使用范围这么广. 本次就开发遇到的奇葩问题来说明一下我们的解决方案. 场景 虽然海康有4200客户端,但是对于高度定制化的项目,肯定不能再使用 ...

  9. 海康相机开发(1) SDK安装和开发

    1.1 安装包获取 从官网下载最新版本的MVS安装包,支持Windows xp.Windows 7.Windows 8.Windows 10的32和64位系统.安装过程默认即可. 官网下载链接:htt ...

随机推荐

  1. Shelld5的使用

    Shelld的连接7步   ·   · huhu_k: 想和你相遇.

  2. python3线程启动与停止

    转自: https://blog.csdn.net/weixin_38125866/article/details/76795462 https://www.cnblogs.com/lcchuguo/ ...

  3. C#调用接口返回json数据中含有双引号 或其他非法字符的解决办法

    这几天,调用别人接口返回json数据含有特殊符号(双引号),当转换成json对象总是报错, json字符格式如下 { "BOXINFO":[ { ", "ITE ...

  4. Oracle 当前日期如何添加指定年数、月数、天数、时数、分钟数、秒数

    Oracle 当前时间如何添加指定数,来获取指定的年数.月份或其他的时间日期 --当前时间(2018-10-19 16:51:22)--- select sysdate nowDate from du ...

  5. js 求select option 的值和对应option的内容

    <select onChange="aa(this)" name="a"> <option value="a">1& ...

  6. C++基础知识:操作符重载

    1.C++标准库: C++标准库并不是C++语言的一部分C++标准库是由C++语言编写而成的类库和函数的集合C++标准库中定义的类和对象都位于std命名空间中C++标准库的头文件都不带.h后缀C++标 ...

  7. jquery去重复 如何去除select控件重复的option

    #1.去除select控件重复的option <select id="companyId" onchange="getContract()" name=& ...

  8. JavaScript 基础,登录前端验证

    <script></script>的三种用法: 放在<body>中 放在<head>中 放在外部JS文件 <!DOCTYPE html> & ...

  9. 强震记录和GPS记录,地震波记录的区别

    强震记录的是加速度数据,但gps记录的是位移数据.这样的话,强震记录应该说是近场地震数据: 那么, 为什么不干脆用近场的地震波仪器呢,是因为,地震仪记录会限幅,导致记录不全.

  10. 单字段去重 distinct 返回其他多个字段

    select a.*, group_concat(distinct b.attribute_name) from sign_contract_info a left join sign_temp_at ...