关于海康相机的SDK包在官网即可下载。
主要界面如下图所示。可对视频流进行实时的显示提取,对车辆进行抓拍并记录该车辆数据为json文件形式,可保存至本地等等。
直接贴上主要功能实现的源码:
/*widget.cpp*/
#include "widget.h"
#include "ui_widget.h"
#include<QtDebug> //调试输出到控制台头文件
#include"offlinedata.h"
#include <QTimer>
#include <QTime>
#include<QFile>
#include<QFileDialog> //保存视频能弹出来对话框
#pragma execution_character_set("utf-8"); // qDebug()可以显示汉字
//QFile *aFile;
std::vector<std::string> vecRealTimeCamera;//实时相机数据
void writeCamera(std::vector<std::string> &vecRealTimeCamera);
QString filestr;
void CALLBACK MSesGCallback(LONG lCommand, NET_DVR_ALARMER* pAlarmer, char* pAlarmInfo, DWORD dwBufLen, void* pUser);
//构造函数
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget) //新建一个Widget界面
{
ui->setupUi(this); //在一个指定的窗口建立起ui
//this->resize(800,600);
userID = -1; //默认值为注销状态
previewID = -1; //默认关闭预览
if(initSDK()){
qDebug() << "SDK init Success!" << endl;
}
putRoad();
cameraTimer = new QTimer;
connect(cameraTimer,SIGNAL(timeout()),this,SLOT(extractCameraRealTime())); //执行extractCameraRealTime()函数
}
Widget::~Widget()
{
if(initSDK()){
qDebug() << "SDK init Success!" << endl;
}
delete ui;
}
void Widget::on_offlinedata_clicked()
{
this->hide();
offlineData *o = new offlineData(); //创建新的ui界面指针
o->setWindowTitle("离线展示界面");
o->show();//显示新的ui界面
}
//初始化
bool Widget::initSDK(){
bool isok = NET_DVR_Init();
if(isok == false){
qDebug() << "NET_DVR_Init error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_Init error;error number " + QString::number(NET_DVR_GetLastError()));//弹出提示框
return isok;
}
//设置连接时间与重连时间
NET_DVR_SetConnectTime(2000, 1);
NET_DVR_SetReconnect(10000, true);
return isok;
}
//退出初始化 //释放SDK资源
bool Widget::uninitSDK(){
bool isok = NET_DVR_Cleanup();
if(isok == false){
qDebug() << "NET_DVR_Cleanup error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_Cleanup error;error number " + QString::number(NET_DVR_GetLastError()));//弹出提示框
return isok;
}
return isok;
}
long Widget::play(HWND hWnd, NET_DVR_PREVIEWINFO struPlayInfo){ //NET_DVR_PREVIEWINFO 预览
//启动预览并设置回调数据流
LONG lRealPlayHandle;
struPlayInfo = {0};
struPlayInfo.hPlayWnd = hWnd; //需要SDK解码时句柄设为有效值,仅取流不解码时可设为空
struPlayInfo.lChannel = 1; //预览通道号
struPlayInfo.dwStreamType = 0; //0-主码流,1-子码流,2-码流3,3-码流4,以此类推
struPlayInfo.dwLinkMode = 0; //0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP
struPlayInfo.bBlocked = 1; //0- 非阻塞取流,1- 阻塞取流
lRealPlayHandle = NET_DVR_RealPlay_V40(userID, &struPlayInfo, NULL, NULL);
if (lRealPlayHandle < 0)
{
qDebug() << "NET_DVR_RealPlay_V40 error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_RealPlay_V40 error;error number " + QString::number(NET_DVR_GetLastError()));//弹出提示框
NET_DVR_Logout(userID);
userID = -1; //注销
return -1;
}
return lRealPlayHandle; //lRealPlayHandle 记为 previewID
}
//登录设备
void Widget::on_LoginButton_clicked()
{
//initSDK();
NET_DVR_DEVICEINFO_V30 struDeviceInfo;
memset(&struDeviceInfo, 0, sizeof(NET_DVR_DEVICEINFO_V30));//存放设备参数的结构体
userID = NET_DVR_Login_V30(const_cast<char*>("192.168.1.66"), 8000, const_cast<char*>("admin"), const_cast<char*>("fh123456"), &struDeviceInfo);
/*//相机参数
char sDVRIP[20] = "192.168.1.66";
short wDVRPort = 8000;
char sUserName[20] = "admin";
char sPassword[20] = "fh123456";
//注册摄像机设备
userID = NET_DVR_Login_V30(sDVRIP, wDVRPort, sUserName, sPassword, &struDeviceInfo);*/
if (userID < 0){
qDebug() << "NET_DVR_DEVICEINFO_V30 error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_DEVICEINFO_V30 error;error number " + QString::number(NET_DVR_GetLastError()));//弹出提示框
return;
}
qDebug() << "Login Success , userID: " << userID << endl;
//uninitSDK();
}
//注销设备
void Widget::on_LogoutButton_clicked()
{
//initSDK();
NET_DVR_Logout(userID);//注销用户
/*if(userID != -1){
if( NET_DVR_Logout(userID) == false){
qDebug() << "NET_DVR_Logout error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_Logout error;error number " + QString::number(NET_DVR_GetLastError()));//弹出提示框
return;
}
userID = -1; //注销
}*/
//uninitSDK();
qDebug() << "Logout Success!" << userID << endl;
ui->graphicsView->close();
//this->close();
}
//开始预览
void Widget::on_PreviewButton_clicked()
{
if(userID == -1){
qDebug() << "Need Login!" << endl;
QMessageBox::warning(this , "error" , "Need Login!");
return;
}
HWND hWnd = (HWND)ui->graphicsView->winId();
NET_DVR_PREVIEWINFO struPlayInfo;
previewID = play(hWnd, struPlayInfo);
if(previewID == -1){
return;
}
qDebug() << "Preview Success!" << userID << endl;
cameraTimer->start(1000);
}
//停止预览
void Widget::on_StopPreviewButton_clicked()
{
//关闭预览
NET_DVR_StopRealPlay(previewID);
/*if(previewID != -1){
if(NET_DVR_StopRealPlay(previewID) == false){
qDebug() << "NET_DVR_StopRealPlay error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_StopRealPlay error;error number " + QString::number(NET_DVR_GetLastError()));//弹出提示框
return;
}
previewID = -1;
}*/
qDebug() << "Stop Preview Success!" << userID << endl;
//ui->graphicsView->close();
}
void Widget::putRoad(){
QImage Image;
Image.load(":/images/image/Road.png");
QPixmap pixmap = QPixmap::fromImage(Image);
//roadLabel = ui->RoadLabel;
//roadLabel->setPixmap(QPixmap("C:\\Users\\LLW\\Desktop\\Qt_HK_camera\\Qt_HK_camera\\image\\Road.png"));
//roadLabel->setScaledContents(true); //设置图片自适应控件大小
//roadLabel->resize(this->size());
wide = ui->RoadLabel->width();
height = ui->RoadLabel->height();
QPixmap fitpixmap = pixmap.scaled(wide, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); //按比例缩放 饱满填充
ui->RoadLabel->setPixmap(fitpixmap);
//roadLabel->setScaledContents(true); //设置图片自适应控件大小
//roadLabel->resize(wide, height);
}
/*void Widget::receiveLogin(){
this->close();
Widget *w = new Widget();
w->show();
}*/
void Widget::on_savedata_clicked()
{
QTime time=QTime::currentTime();
QString strtime;
strtime=time.toString("hhmmss");
QString filestr=("C:\\Users\\LLW\\Desktop\\Qt_HK_camera\\Qt_HK_camera\\data\\20220111_"+strtime+".mp4");
bool save_ReturnValue = NET_DVR_SaveRealData_V30(previewID, 0x1, filestr.toLocal8Bit().data());// 0x1 : PS文件层,主要用于存储,也可用于传输 // 0x2 : 3GPP文件层,用于存储
if(save_ReturnValue == false){
qDebug() << "NET_DVR_SaveRealData_V30 error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_SaveRealData_V30 error;error number " + QString::number(NET_DVR_GetLastError()));//弹出提示框
return;
}
qDebug() << "SaveRealData Success!" << userID << endl;
}
void Widget::on_stopsave_clicked()
{
NET_DVR_StopSaveRealData(previewID);
/*if(NET_DVR_StopSaveRealData(previewID) == false){
qDebug() << "NET_DVR_StopSaveRealData error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_StopSaveRealData error;error number " + QString::number(NET_DVR_GetLastError()));//弹出提示框
return;
}
NET_DVR_StopSaveRealData(previewID) == true;*/
qDebug() << "StopSaveRealData Success!" << userID << endl;
}
//获取相机实时视频流时间
void Widget::extractCameraRealTime(){
//NET_DVR_TIME_V50 CameraRealTime;
bool iRet;
DWORD dwReturnLeo;
NET_DVR_TIME CameraRealTime = { 0 };
iRet = NET_DVR_GetDVRConfig(userID, NET_DVR_GET_TIMECFG, 1, &CameraRealTime, sizeof(NET_DVR_TIME), &dwReturnLeo);
if (!iRet){
printf("NET_DVR_GetDVRConfig NET_DVR_GET_TIMECFG error.\n");
NET_DVR_Logout(userID);
NET_DVR_Cleanup();
}
/*qDebug() <<CameraRealTime.dwYear<<"年"<<CameraRealTime.dwMonth<<"月"<<CameraRealTime.dwDay<<"日"
<<CameraRealTime.dwHour<<":"<<CameraRealTime.dwMinute<<":"<<CameraRealTime.dwSecond<<endl;*/
return;
}
//普通string类型转UTF-8编码格式字符串
std::string string_To_UTF8(const std::string& str)
{
int nwLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
wchar_t* pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然会出现尾巴
ZeroMemory(pwBuf, nwLen * 2 + 2);
::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);
int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
char* pBuf = new char[nLen + 1];
ZeroMemory(pBuf, nLen + 1);
::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
std::string retStr(pBuf);
delete[]pwBuf;
delete[]pBuf;
pwBuf = NULL;
pBuf = NULL;
return retStr;
}
//报警回调函数及HTTP传输
void CALLBACK MSesGCallback(LONG lCommand, NET_DVR_ALARMER* pAlarmer, char* pAlarmInfo, DWORD dwBufLen, void* pUser)
{
//qDebug()<<"MSesGCallback Succeed!";
int i = 0;
char filename[100];
FILE *fSnapPic = NULL;
FILE *fSnapPicPlate = NULL;
//cout << "lCommand=" << lCommand << endl;
switch (lCommand)
{
//交通抓拍结果(新报警消息)
case COMM_ITS_PLATE_RESULT:
{
NET_ITS_PLATE_RESULT struITSPlateResult = { 0 };
memcpy(&struITSPlateResult, pAlarmInfo, sizeof(struITSPlateResult));
//数据内容
//将字符串通过指针存入容器
char zuodakuohao[100] = { 0 };
sprintf(zuodakuohao, "{");
vecRealTimeCamera.push_back(zuodakuohao);
char hkDataTime[100] = { 0 };
sprintf(hkDataTime, "\"snapFirstPicTime\":\"%02d-%02d-%02d% 02d:%02d:%02d:%02d\",", struITSPlateResult.struSnapFirstPicTime.wYear, struITSPlateResult.struSnapFirstPicTime.byMonth, struITSPlateResult.struSnapFirstPicTime.byDay, struITSPlateResult.struSnapFirstPicTime.byHour, struITSPlateResult.struSnapFirstPicTime.byMinute, struITSPlateResult.struSnapFirstPicTime.bySecond, struITSPlateResult.struSnapFirstPicTime.wMilliSec);
vecRealTimeCamera.push_back(hkDataTime);
char hkcarNum[100] = { 0 };
sprintf(hkcarNum, "\"carNum\":\"%s\",", struITSPlateResult.struPlateInfo.sLicense);
qDebug()<<hkcarNum<<endl;std::string carNum = string_To_UTF8((std::string) hkcarNum);
vecRealTimeCamera.push_back(carNum);
char hkcarType[100] = { 0 };
sprintf(hkcarType, "\"carType\":\"%d\",", struITSPlateResult.byVehicleType);
vecRealTimeCamera.push_back(hkcarType);
char hkdriveChan[100] = { 0 };
sprintf(hkdriveChan, "\"driveChan\":\"%d\",", struITSPlateResult.byDriveChan);
vecRealTimeCamera.push_back(hkdriveChan);
char hkcarDirectiontype[100] = { 0 };
sprintf(hkcarDirectiontype, "\"carDirectiontype\":\"%d\",", struITSPlateResult.byCarDirectionType);
vecRealTimeCamera.push_back(hkcarDirectiontype);
char hkcarSpeed[100] = { 0 };
sprintf(hkcarSpeed, "\"carSpeed\":\"%d\",", struITSPlateResult.struVehicleInfo.wSpeed);
vecRealTimeCamera.push_back(hkcarSpeed);
char hkPilotSafebelt[100] = { 0 };
sprintf(hkPilotSafebelt, "\"PilotSafebelt\":\"%d\",", struITSPlateResult.byPilotSafebelt);
vecRealTimeCamera.push_back(hkPilotSafebelt);
char hkIllegalType[100] = { 0 };
sprintf(hkIllegalType, "\"IllegalType\":\"%d\",", struITSPlateResult.wIllegalType);
vecRealTimeCamera.push_back(hkIllegalType);
char hkPendant[100] = { 0 };
sprintf(hkPendant, "\"byPendant\":\"%d\",", struITSPlateResult.byPendant);
vecRealTimeCamera.push_back(hkPendant);
char hkCopilotSafebelt[100] = { 0 };
sprintf(hkCopilotSafebelt, "\"CopilotSafebelt\":\"%d\",", struITSPlateResult.byCopilotSafebelt);
vecRealTimeCamera.push_back(hkCopilotSafebelt);
char hkPilotCall[100] = { 0 };
sprintf(hkPilotCall, "\"PilotCall\":\"%d\",", struITSPlateResult.byPilotCall);
vecRealTimeCamera.push_back(hkPilotCall);
char hkCarColor[100] = { 0 };
sprintf(hkCarColor, "\"CarColor\":\"%d\",", struITSPlateResult.struVehicleInfo.byColor);
vecRealTimeCamera.push_back(hkCarColor);
char hkVehicleLogoRecog[100] = { 0 };
sprintf(hkVehicleLogoRecog, "\"VehicleLogoRecog\":\"%d\"", struITSPlateResult.struVehicleInfo.byVehicleLogoRecog);
vecRealTimeCamera.push_back(hkVehicleLogoRecog);
char youdakuohao[100] = { 0 };
sprintf(youdakuohao, "}");
vecRealTimeCamera.push_back(youdakuohao);
/*sprintf(youdakuohao, "},");
vecRealTimeCamera.push_back(youdakuohao);*/
writeCamera(vecRealTimeCamera);
/*QString str=postParams;//
QByteArray strBytes=str.toUtf8();//转换为字节数组
aFile->write(strBytes,strBytes.length());*/ //写入文件
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
for (i = 0; i < struITSPlateResult.dwPicNum; i++)
{
//保存场景图
//struITSPlateResult.struPicInfo[i].byType:数据类型,0 - 车牌图、1 - 场景图、2 - 合成图、3 - 特写图
//struPicInfo[6]; //图片信息,单张回调,最多6张图,由序号区分
if ((struITSPlateResult.struPicInfo[i].dwDataLen != 0) && (struITSPlateResult.struPicInfo[i].byType == 1) || (struITSPlateResult.struPicInfo[i].byType == 2))
{
sprintf(filename, "C:\\Users\\LLW\\Desktop\\Qt_HK_camera\\Qt_HK_camera\\pic\\%s_%d.jpg", struITSPlateResult.struPlateInfo.sLicense, i);
fSnapPic = fopen(filename, "wb"); //w是以文本方式打开文件,wb是二进制方式打开文件
fwrite(struITSPlateResult.struPicInfo[i].pBuffer, struITSPlateResult.struPicInfo[i].dwDataLen, 1, fSnapPic);
//iNum++;
fclose(fSnapPic);
}
//车牌图
if (struITSPlateResult.struPicInfo[i].dwDataLen != 0 && struITSPlateResult.struPicInfo[i].byType == 0)
{
sprintf(filename, "C:\\Users\\LLW\\Desktop\\Qt_HK_camera\\Qt_HK_camera\\pic\\%s.jpg", struITSPlateResult.struPlateInfo.sLicense);
fSnapPicPlate = fopen(filename, "wb");
fwrite(struITSPlateResult.struPicInfo[i].pBuffer, struITSPlateResult.struPicInfo[i].dwDataLen, 1, fSnapPicPlate);
//iNum++;
fclose(fSnapPicPlate);
}
} //其他信息处理
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
break;
}
default:
{
//std::cout << lCommand << endl;
break;
}
}
return;
}
void Widget::SetMessageCallBack(){
qDebug()<<"SetMessageCallBack Succeed!";
NET_DVR_SetDVRMessageCallBack_V30(MSesGCallback, NULL);//设置报警回调函数
if(NET_DVR_SetDVRMessageCallBack_V30(MSesGCallback, NULL) == false){
qDebug() << "NET_DVR_SetDVRMessageCallBack_V30 error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_SetDVRMessageCallBack_V30 error;error number " + QString::number(NET_DVR_GetLastError()));//弹出提示框
return;
}
return;
}
void Widget::on_SetupAlarm_clicked()
{
//文件命名
QTime time=QTime::currentTime();
QString strtime;
strtime=time.toString("hhmmss");
filestr="C:\\Users\\LLW\\Desktop\\Qt_HK_camera\\Qt_HK_camera\\data\\20220111_"+strtime+"camera.txt";
//启用布防
NET_DVR_SETUPALARM_PARAM struSetupParam = { 0 };
struSetupParam.dwSize = sizeof(NET_DVR_SETUPALARM_PARAM);
struSetupParam.byLevel = 1; //布防优先级:0- 一等级(高),1- 二等级(中)
struSetupParam.byAlarmInfoType = 1; //上传报警信息类型: 0- 老报警信息(NET_DVR_PLATE_RESULT), 1- 新报警信息(NET_ITS_PLATE_RESULT)
lHandle = NET_DVR_SetupAlarmChan_V41(userID, &struSetupParam);
if (lHandle < 0)
{
qDebug()<<"NET_DVR_SetupAlarmChan_V41 failed, error code: %d\n"<< NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_SetupAlarmChan_V41 error;error number " + QString::number(NET_DVR_GetLastError()));//
NET_DVR_Logout(userID);
NET_DVR_Cleanup();
return;
}
else
{
qDebug()<<"SetupAlarm Succeed!\n";
}
/*------------------------------------------------------------------------------------------------------------------------------------------------------------*/
NET_DVR_SetDVRMessageCallBack_V30(MSesGCallback, NULL);//设置报警回调函数
if(NET_DVR_SetDVRMessageCallBack_V30(MSesGCallback, NULL) == false){
qDebug() << "NET_DVR_SetDVRMessageCallBack_V30 error;error number is " << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_SetDVRMessageCallBack_V30 error;error number " + QString::number(NET_DVR_GetLastError()));//
return;
}
//Sleep(60000);
}
void Widget::on_CloseAlarm_clicked()
{
//撤销布防上传通道
NET_DVR_CloseAlarmChan_V30(lHandle);
/*if (NET_DVR_CloseAlarmChan_V30(lHandle) == false) //布防句柄lHandle
{
qDebug() << "NET_DVR_CloseAlarmChan_V30 Failed! Error number:" << NET_DVR_GetLastError();
QMessageBox::warning(this, "Warning","NET_DVR_CloseAlarmChan_V30 error;error number " + QString::number(NET_DVR_GetLastError()));//
NET_DVR_Logout(userID);
NET_DVR_Cleanup();
return;
}*/
lHandle = -1;//布防句柄
qDebug()<<"CloseAlarm Succeed!\n";
}
void Widget::on_Exit_clicked()
{
this->close();
}
/*void Widget::on_savejson_clicked()
{
if(ui->savejson->text()=="SaveJson")
{
ui->savejson->setText("Stop");
QString curPath=QDir::currentPath();//获取系统当前目录
QString dlgTitle="存为一个文件"; //对话框标题
QString filter="文本文件(*.txt);;所有文件(*.*)"; //文件过滤器
QString aFileName=QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
if (aFileName.isEmpty())
return;
//aFile->copy(aFileName);
aFile = new QFile(aFileName);
QString str="postParams";//整个内容作为字符串
QByteArray strBytes=str.toUtf8();//转换为字节数组
aFile->write(strBytes,strBytes.length()); //写入文件
}
else
{
ui->savejson->setText("SaveJson");
aFile->close();
}
}*/
void writeCamera(std::vector<std::string> &vecRealTimeCamera) {
// 写入文件保存
FILE *fp;
fp = fopen(filestr.toLocal8Bit().data(), "w");//打开要输出的文件 w:每次覆盖原文件
for (int i = 0; i < vecRealTimeCamera.size(); i++) {
fwrite(&vecRealTimeCamera[i][0], 1, vecRealTimeCamera[i].size(), fp);
fwrite("\n", 1, 1, fp);
}
fclose(fp);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理