基于Qt的海康威视SDK二次开发-摄像头登陆、预览和抓图
最近有個項目涉及海康威視的攝像頭部分,需要在服務器端自動定時抓圖,由于服務器端采用的是Windows系統(tǒng),不熟Windows的api,所以直接采用Qt來編寫。那么攝像頭的激活配置什么的就不再介紹了,直接進入正題。
先下載海康的SDK,https://www.hikvision.com/cn/download_61.html,我的電腦系統(tǒng)是64位的,QT版本5.10.0,QT Creator是32位的,編譯器是mingw32,介于編譯器是32位,同時32位的程序能夠在32、64位的系統(tǒng)下運行,但是64位的就只能在64位系統(tǒng)下運行,因此為了后期的兼容性,我下載了32位的SDK,至于能不能下載64位的SDK,可以自行嘗試。
其次設置硬件設備,網(wǎng)絡攝像頭相當于一個服務器,我們的程序要訪問它并獲取視頻數(shù)據(jù),因此這個攝像頭無論在內(nèi)網(wǎng)還是外網(wǎng),只要能訪問到就行,最簡單的方式就是ping它的IP,能通就行,我的IP是192.168.10.102,然后是服務端口,服務端口可以自行網(wǎng)頁登陸攝像頭查看,我這里是默認值,8000,然后是賬號和密碼,賬號分為兩種,管理員賬號admin和普通賬號,管理員賬號的密碼就是激活的時候讓輸入的密碼,普通賬號是激活后登陸攝像頭自行設置的,我這里還是默認的admin和激活時候設置的密碼。硬件環(huán)境大致就是這個樣子。
然后新建一個Qt工程,我選擇是繼承于QWidget的類,當然其他基類也行,接著從下載的sdk里將頭文件文件夾和庫文件文件夾都拷到Qt工程目錄下,分別修改為英文,我這里是include和libs,注意這里修改的名字應當和程序中對應;接下來是將庫添加到QT工程中,使其編譯時能夠加載,庫目錄中有l(wèi)ib和dll,這兩個都是庫,這里插嘴說一下二者的區(qū)別,當Windows下一個工程編譯成庫時,可以有兩種方式,第一種是靜態(tài)庫,第二種是動態(tài)庫,靜態(tài)庫在編譯時讀取,動態(tài)庫在運行時讀取,生成靜態(tài)庫時只有l(wèi)ib文件,里邊存放的就是函數(shù)的實現(xiàn),生成動態(tài)庫時,lib和dll文件都有,其中l(wèi)ib中沒有函數(shù)的實現(xiàn)代碼,只存放了該實現(xiàn)代碼位于哪個dll中,dll中存放函數(shù)的實現(xiàn)代碼;我們在調(diào)用靜態(tài)庫時,代碼在鏈接階段,將去對應lib中尋找實現(xiàn)代碼,并進行鏈接,結束后,lib就沒用了;而調(diào)用動態(tài)庫時,代碼在鏈接階段也會去lib中尋找,不同的是,它只會留下標記,標識去哪里找運行代碼,而不實際將dll中的實現(xiàn)鏈接進程序里,因此程序運行時不需要lib,但是必須有dll。言歸正傳,海康威視的SDK是動態(tài)庫,我們需要指定lib文件的位置,運行時將dll文件放置在程序運行目錄下即可,在QT中指定lib文件的位置是修改pro文件,添加如下代碼:
LIBS +=-LH:/QTproject/HKDemo/HKDemo/libs -lHCCore -lHCNetSDK -lPlayCtrl LIBS +=-LH:/QTproject/HKDemo/HKDemo/libs/HCNetSDKCom -lHCAlarm -lHCGeneralCfgMgr -lHCPreview和Linux系統(tǒng)的加庫方法非常像,-L表示庫的搜索路徑,-l表示鏈接哪個庫,注意這里的路徑要寫全,我試過相對路徑,沒有成功,至此編譯時的庫加入到了QT工程中。
接下來要做的就是寫代碼了,我們可以根據(jù)海康威視提供的文檔進行編寫,其文檔位于開發(fā)文檔目錄下,我使用的是設備網(wǎng)絡SDK使用手冊.chm,我們可以在里邊看到使用流程,及一些接口的依賴關系:
整個大的框架就是初始化,注冊,預覽,停止預覽,注銷,釋放資源,初始化SDK和釋放SDK資源不必多說,是sdk的基礎操作,然后注冊就是登陸攝像頭,注銷就是退出登陸,注意抓圖分為兩種,預覽抓圖和設備抓圖,預覽抓圖必須先開啟預覽,而設備抓圖不用,因為我是做服務器端程序用的,就使用了設備抓圖,即不需要預覽就可以抓圖。
-
初始化SDK和釋放SDK資源
?
?
SDK中初始化資源函數(shù)為NET_DVR_Init(),資源釋放函數(shù)為NET_DVR_Cleanup()。
由于這是SDK的基礎操作,我們在窗體的構造函數(shù)執(zhí)行初始化SDK的操作,在析構函數(shù)中執(zhí)行釋放SDK資源的操作,初始化SDK和釋放SDK的代碼如下:
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,"error","NET_DVR_Init error;error number is "+QString::number(NET_DVR_GetLastError()));return isok;}//設置連接時間與重連時間NET_DVR_SetConnectTime(2000, 1);NET_DVR_SetReconnect(10000, true);return isok; }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,"error","NET_DVR_Cleanup error;error number "+QString::number(NET_DVR_GetLastError()));return isok;}return isok; }- 登錄和退出登錄
其余接口不再累述,自己查即可,這里我用的是NET_DVR_Login_V30函數(shù)和NET_DVR_Logout,代碼如下:
void Widget::OnClickedLogin() {NET_DVR_DEVICEINFO_V30 DeviceInfoTmp;userID=NET_DVR_Login_V30("192.168.10.102",8000,"admin","1234536asd",&DeviceInfoTmp);//參數(shù)依次為IP地址、服務端口、賬號、密碼,最后一個參數(shù)是為了獲得硬件信息的if(userID<0){qDebug() << "NET_DVR_Login_V30 error;" << "error number is " << NET_DVR_GetLastError();QMessageBox::warning(this,"error","NET_DVR_Login_V30 error;error number "+QString::number(NET_DVR_GetLastError()));return;}qDebug()<<"Login Success,userID:" << userID<<endl; }void Widget::OnClickedLogout() {if(userID!=-1){if(NET_DVR_Logout(userID)==false){qDebug() << "NET_DVR_Logout error;" << "error number is " << NET_DVR_GetLastError();QMessageBox::warning(this,"error","NET_DVR_Logout error;error number "+QString::number(NET_DVR_GetLastError()));return;}userID=-1;qDebug() <<"Logout Success!"<<endl;} }- 預覽和停止預覽
預覽函數(shù)需要獲得窗體句柄,并且是Windows api中定義的句柄,本質(zhì)上來講,QT寫出的窗體也是windows窗體,我們這里直接定義一個label控件,控件中有個成員函數(shù)是專門獲得windows下的窗體句柄的,傳入該句柄后,函數(shù)就會自動向窗體傳遞圖像信息并顯示,不需我們的任何操作,同時也不會阻塞在這個函數(shù),應該是直接利用了windows api的消息機制,代碼如下:
void Widget::OnClickedPreview() {if(userID==-1){qDebug() <<"Need Login!"<<endl;QMessageBox::warning(this,"error","Need Login!");return;}HWND hWnd = (HWND)ui->label->winId();//HWND是windows api的窗體句柄類型NET_DVR_PREVIEWINFO struPlayInfo;previewID = play(hWnd,struPlayInfo);if(previewID==-1){return;}qDebug()<<"Preview Success!" << userID<<endl; }void Widget::OnClickedStopPreview() {if(previewID!=-1){if(NET_DVR_StopRealPlay(previewID)==false){qDebug() << "NET_DVR_StopRealPlay error;" << "error number is " << NET_DVR_GetLastError();QMessageBox::warning(this,"error","NET_DVR_StopRealPlay error;error number "+QString::number(NET_DVR_GetLastError()));return;}previewID=-1;qDebug() <<"Stop Preview Success!"<<endl;} }- 抓圖
這里使用的是設備抓圖,即可以在登錄后直接抓圖,不需要預覽,但是這個函數(shù)只能獲取jpeg圖像,會損失精度,可以采用預覽抓圖函數(shù),其可以設置獲取BMP圖像還是jpeg圖像。注意文件路徑必須包括文件名字,還有Windows下的要加雙斜杠,另外文件路徑中的文件夾應當在該函數(shù)之前創(chuàng)建,代碼如下:
void Widget::OnClickedCapture() {if(userID!=-1){NET_DVR_JPEGPARA IpJpegPara2;IpJpegPara2.wPicQuality=0;IpJpegPara2.wPicSize=0xff;QDateTime current_date_time =QDateTime::currentDateTime();QString current_date =current_date_time.toString("yyyy-MM-dd_hh-mm-ss_zzz");current_date="C:\\Picture\\"+current_date+".jpg";char* fileName;QByteArray ba = current_date.toLatin1(); // mustfileName=ba.data();if(NET_DVR_CaptureJPEGPicture(userID,1,&IpJpegPara2,fileName)==false){qDebug() << "NET_DVR_CaptureJPEGPicture error;" << "error number is " << NET_DVR_GetLastError();QMessageBox::warning(this,"error","NET_DVR_CaptureJPEGPicture error;error number "+QString::number(NET_DVR_GetLastError()));return;}qDebug() <<"Capture Success!"<<endl;} }整體流程就是這個樣子,下面給出完整代碼。
- main.cpp
- widget.h
- widget.cpp
- 發(fā)布應用
發(fā)布應用應當以release模式編譯,然后使用windeployqt 工具進行qt依賴項的導出,接著要將海康威視的dll也放入可執(zhí)行文件目錄下,這里為簡單起見,直接將下載的海康威視的sdk中的庫文件中的所有文件、目錄復制到可執(zhí)行文件目錄下,如下圖所示:
仍無法實現(xiàn)的,可以下載我打包好的,包括源代碼和可執(zhí)行文件及其依賴項。發(fā)布的應用里直接寫死了IP和端口,可以在源碼中修改為窗體輸入。https://download.csdn.net/download/cx296649890/11574696
總結
以上是生活随笔為你收集整理的基于Qt的海康威视SDK二次开发-摄像头登陆、预览和抓图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 整理一篇Linux drm显示系统的文章
- 下一篇: 我学机械的可以转嵌入式吗?