海康威视py和c++调用全(超精髓,亲测)
前言
做这个之前是因为客户是海康威视的存储器,所以对海康威视完完全全了解,也是踩了很多坑,和很多经验,再次做经验分享,老样子,代码和动态库需要完全请添加后面博主的微信,完全免费
一、海康威视需要的SDK
老样子需要sdk请到最后加博主微信,我暂时没有github那些哈哈哈。
二、海康威视常见报错
一些高难度的错误博主暂时没涉及,我主要讲解一些常用的错误,用我的白语去解释
- Login error 7(这个意思就是你账号密码端口号输入错了,没有例外)
- Login error 11(这个意思我的解释就是超时,原因是你的通道数错误,怎么找通道我后面会教)
- Login error 10(这个就是连接超时,千万不要随意改重置端数,老样子,报这个错就去看看自己的)
- 有些可能找不到ip地址,这个问题也可以解决,你需要进入存储器-》设置里面通道配置,然后将新的摄像头添加进去就可以了,具体的话,可以私聊我,我可以帮助你解决
三、python调用海康威视摄像头
说白了就是调入流,具体我也不知道为什么python为什么这么方便c++却不行
import cv2
cap =cv2.VideoCapture("rtsp://admin:pwd@192.168.1.53:8000/h264/ch1/main/av_stream")
i=0
while True:
i+=1
c,f =cap.read()
f = cv2.resize(f,(1920,1080))
cv2.imshow("aaa",f)
# cv2.imwrite("new/{}.jpg".format(i),f)
cv2.waitKey(30)
cap.release()
解析代码:
admin是账号 pwd是密码 192.168.1.53是ip 8000是端口 h264一般都是固定的
ch1的1是通道数 main是主码流 av_stream默认
这里我特别强调一下通道数,不好找,所以接下来我会贴一个找通道数的代码
四、c++调用海康威视找通道数以及设备数
#include <iostream>
#include <thread>
#include "HCNetSDK.h"
#pragma comment(lib,"GdiPlus.lib")
#pragma comment(lib,"HCCore.lib")
#pragma comment(lib,"HCNetSDK.lib")
#pragma comment(lib,"PlayCtrl.lib")
int aa(int argc, char** argv)
{
NET_DVR_Init();
NET_DVR_SetConnectTime(2000, 1);
NET_DVR_SetReconnect(10000, true);
NET_DVR_USER_LOGIN_INFO struLoginInfo = { 0 };
struLoginInfo.bUseAsynLogin = 0; //同步登录方式
strcpy_s(struLoginInfo.sDeviceAddress, "192.168.1.99"); //设备IP地址
struLoginInfo.wPort = 8000; //设备服务端口
strcpy_s(struLoginInfo.sUserName, "admin"); //设备登录用户名
strcpy_s(struLoginInfo.sPassword, "asd72310"); //设备登录密码
//设备信息, 输出参数
NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = { 0 };
int userId = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);
if (userId == -1)
{
DWORD code = NET_DVR_GetLastError();
std::cout << "NET_DVR_Login_V40 failed " << NET_DVR_GetErrorMsg((LONG*)(&code)) << std::endl;
NET_DVR_Logout(userId);
//释放SDK资源
NET_DVR_Cleanup();
::getchar();
return -1;
}
std::cout << "login success user " << userId << std::endl;
DWORD bytesReturned = 0;
NET_DVR_DEVICECFG devCfg;
devCfg.dwSize = sizeof(NET_DVR_DEVICECFG);
bool resCode = NET_DVR_GetDVRConfig(userId, NET_DVR_GET_DEVICECFG, -1, &devCfg, sizeof(NET_DVR_DEVICECFG), &bytesReturned);
if (!resCode)
{
DWORD code = NET_DVR_GetLastError();
std::cout << "NET_DVR_GetDVRConfig failed " << NET_DVR_GetErrorMsg((LONG*)(&code)) << std::endl;
NET_DVR_Logout(userId);
//释放SDK资源
NET_DVR_Cleanup();
::getchar();
return -1;
}
std::cout << "设备名: " << devCfg.sDVRName << " 序列号: " << devCfg.sSerialNumber << " 设备ID号: " << devCfg.dwDVRID << " 设备类型: " << (int)devCfg.byDVRType << std::endl;
NET_DVR_IPPARACFG_V40 ipcfg;
bytesReturned = 0;
ipcfg.dwSize = sizeof(NET_DVR_IPPARACFG_V40);
int iGroupNO = 0;
resCode = NET_DVR_GetDVRConfig(userId, NET_DVR_GET_IPPARACFG_V40, iGroupNO, &ipcfg, sizeof(NET_DVR_IPPARACFG_V40), &bytesReturned);
if (!resCode)
{
DWORD code = NET_DVR_GetLastError();
std::cout << "NET_DVR_GetDVRConfig failed " << NET_DVR_GetErrorMsg((LONG*)(&code)) << std::endl;
NET_DVR_Logout(userId);
//释放SDK资源
NET_DVR_Cleanup();
::getchar();
return -1;
}
std::cout << "设备组 " << ipcfg.dwGroupNum << " 数字通道个数 " << ipcfg.dwDChanNum << " 起始通道 " << ipcfg.dwStartDChan << std::endl;
for (int i = 0; i < ipcfg.dwDChanNum; i++)
{
switch (ipcfg.struStreamMode[i].byGetStreamType)
{
case 0:
if (ipcfg.struStreamMode[i].uGetStream.struChanInfo.byEnable)
{
int byIPID = ipcfg.struStreamMode[i].uGetStream.struChanInfo.byIPID;
int byIPIDHigh = ipcfg.struStreamMode[i].uGetStream.struChanInfo.byIPIDHigh;
int iDevInfoIndex = byIPIDHigh * 256 + byIPID - 1 - iGroupNO * 64;
printf("通道号%d 在线 摄像头取流, IP: %s\n", i + 1, ipcfg.struIPDevInfo[iDevInfoIndex].struIP.sIpV4);
}
else {
int byIPID = ipcfg.struStreamMode[i].uGetStream.struChanInfo.byIPID;
int byIPIDHigh = ipcfg.struStreamMode[i].uGetStream.struChanInfo.byIPIDHigh;
int iDevInfoIndex = byIPIDHigh * 256 + byIPID - 1 - iGroupNO * 64;
std::cout << "IP: " << ipcfg.struIPDevInfo[iDevInfoIndex].struIP.sIpV4 << " 离线" << std::endl;
}
break;
case 1:
if (ipcfg.struStreamMode[i].uGetStream.struPUStream.struStreamMediaSvrCfg.byValid)
{
printf("IP channel %d connected with the IP device by stream server.\n", i + 1);
printf("IP of stream server: %s, IP of IP device: %s\n", ipcfg.struStreamMode[i].uGetStream.\
struPUStream.struStreamMediaSvrCfg.struDevIP.sIpV4, ipcfg.struStreamMode[i].uGetStream.\
struPUStream.struDevChanInfo.struIP.sIpV4);
}
break;
}
NET_DVR_RECORD_CHECK_COND recordChk;
NET_DVR_STREAM_INFO sInfo;
::memset(sInfo.byID, 0, STREAM_ID_LEN);
sInfo.dwChannel = i + 1;
sInfo.dwSize = sizeof(NET_DVR_STREAM_INFO);
NET_DVR_TIME_EX startT, endT;
startT.wYear = 2020;
startT.byMonth = 7;
startT.byDay = 1;
startT.byHour = 0;
startT.byMinute = 0;
startT.bySecond = 0;
endT.wYear = 2020;
endT.byMonth = 7;
endT.byDay = 1;
endT.byHour = 23;
endT.byMinute = 59;
endT.bySecond = 59;
recordChk.dwSize = sizeof(NET_DVR_RECORD_CHECK_COND);
recordChk.struStreamInfo = sInfo;
recordChk.byCheckType = 0;
recordChk.struBeginTime = startT;
recordChk.struEndTime = endT;
LONG recordHandle = NET_DVR_StartRemoteConfig(userId, NET_DVR_RECORD_CHECK, &recordChk, sizeof(NET_DVR_RECORD_CHECK_COND), [](DWORD dwType, void* lpBuffer, DWORD dwBufLen, void* pUserData) {
switch (dwType)
{
case NET_SDK_CALLBACK_TYPE_STATUS:
std::cout << "status len " << dwBufLen << std::endl;
break;
case NET_SDK_CALLBACK_TYPE_PROGRESS:
std::cout << "progress len " << dwBufLen << std::endl;
break;
case NET_SDK_CALLBACK_TYPE_DATA:
std::cout << "data len " << dwBufLen << std::endl;
break;
default:
break;
}
}, nullptr);
NET_DVR_RECORD_SEGMENT_RET recordData;
recordData.dwSize = sizeof(NET_DVR_RECORD_SEGMENT_RET);
LONG code = 1000;
while (code == 1000)
{
code = NET_DVR_GetNextRemoteConfig(recordHandle, &recordData, sizeof(NET_DVR_RECORD_SEGMENT_RET));
while (code == 1001)
{
code = NET_DVR_GetNextRemoteConfig(recordHandle, &recordData, sizeof(NET_DVR_RECORD_SEGMENT_RET));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
std::cout << "录像大小 " << recordData.dwRecordTotalSize << std::endl;
recordData.dwRecordTotalSize = 0;
}
std::cout << "用户名 " << ipcfg.struIPDevInfo[i].sUserName << " 密码 " << ipcfg.struIPDevInfo[i].sPassword << " 设备ID " << (int)ipcfg.struIPDevInfo[i].szDeviceID << " ip地址 " << ipcfg.struIPDevInfo[i].struIP.sIpV4 << " 端口 " << ipcfg.struIPDevInfo[i].wDVRPort << std::endl << std::endl;
}
::getchar();
NET_DVR_Logout(userId);
//释放SDK资源
NET_DVR_Cleanup();
return 0;
}
记得修改账号密码,然后运行出来会显示你当前的通道数。
比如你要192.168.1.11的,你就从当前通道数一个一个往下数就可以咯,具体的话,需要连接海康服务器,我暂时就补贴图了,如果有问题,请添加下方微信进行咨询就可,不收费!!!
代码讲解也是有问题就问,我不会超过一天不回复的这里就不过多讲解了
c++调用海康威视实现抓图效果
#include <cstdlib>
#include <cstring>
#include <iostream>
#include "Windows.h"
#include "HCNetSDK.h"
#include "plaympeg4.h"
#include <opencv2\opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <time.h>
using namespace std;
using namespace cv;
void main()
{
//---------------------------------------
// 初始化
NET_DVR_Init();
//设置连接时间与重连时间
NET_DVR_SetConnectTime(2000, 1);
NET_DVR_SetReconnect(10000, true);
//---------------------------------------
//登录参数,包括设备地址、登录用户、密码等
NET_DVR_USER_LOGIN_INFO struLoginInfo = { 0 };
struLoginInfo.bUseAsynLogin = 0; //同步登录方式
strcpy_s(struLoginInfo.sDeviceAddress, "192.168.1.99"); //设备IP地址
struLoginInfo.wPort = 8000; //设备服务端口
strcpy_s(struLoginInfo.sUserName, "admin"); //设备登录用户名
strcpy_s(struLoginInfo.sPassword, "asd72310"); //设备登录密码
// 注册设备
LONG lUserID;
//设备信息, 输出参数
NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = { 0 };
lUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);
if (lUserID < 0)
{
printf("Login error, %d\n", NET_DVR_GetLastError());
NET_DVR_Cleanup();
return;
}
LPNET_DVR_JPEGPARA JpegPara = new NET_DVR_JPEGPARA;
JpegPara->wPicQuality = 0;
JpegPara->wPicSize = 3;
char* Jpeg = new char[1920 * 1080];
DWORD len = 1920 * 1080;
LPDWORD Ret = new DWORD;
vector<char>data(1920 * 1080);
bool capture = NET_DVR_CaptureJPEGPicture_NEW(lUserID, 41, JpegPara, Jpeg, len, Ret);
cout << "return size =" << *Ret << endl;
cout << capture;
for (int i = 0; i < 1920 * 1080; i++)
data[i] = Jpeg[i];
Mat img = imdecode(Mat(data), 1);
cout << "-----------111-------" << img.cols << "\t" << img.rows << endl;
//imwrite("a.jpg", img);
//注销用户
NET_DVR_Logout(lUserID);
//释放SDK资源
NET_DVR_Cleanup();
return;
}
小提示
不仅于抓图,实时预览报警都是能实现的哦,这里只做抓图示范,需要的话,就联系博主进行索取,实时流回调的功能各方面的,都可以实现
总结
总之尼,博客写的轻松,但是尝试过程依然艰辛,我的所有博客都是根据自己的经验写的,没有任何弯路,如果有问题欢迎加微信探讨,如果有新技术方面,也可以一起交流
感谢支持,掰掰┏(^0^)┛