丹東東方測(cè)控技術(shù)股份有限公司 遼寧 丹東 118000
??低暤谋O(jiān)控產(chǎn)品在工業(yè)企業(yè)內(nèi)應(yīng)用十分廣泛,如何利用??低暜a(chǎn)品實(shí)現(xiàn)專(zhuān)有定制化視頻監(jiān)控系統(tǒng)是十分有意義的。Python語(yǔ)言易學(xué)易用,簡(jiǎn)單高效,但目前??倒俜竭€未提供Python版SDK。本文介紹了在Windows系統(tǒng)下Python編程環(huán)境中,結(jié)合??低昐DK設(shè)計(jì)和開(kāi)發(fā)工業(yè)設(shè)備實(shí)時(shí)視頻監(jiān)控軟件的方法。
(1)Python簡(jiǎn)介。Python是一種跨平臺(tái)的計(jì)算機(jī)程序設(shè)計(jì)語(yǔ)言。無(wú)論是桌面開(kāi)發(fā)序、Web開(kāi)發(fā)、人工智能、自動(dòng)化運(yùn)維、科學(xué)運(yùn)算,Python都有著豐富的擴(kuò)展模塊,使用Python開(kāi)發(fā)應(yīng)用程序,無(wú)疑是高效的。
(2)??礢DK。??低昐DK即海康提供的開(kāi)發(fā)包,主要包含設(shè)備網(wǎng)絡(luò)SDK和播放庫(kù)SDK(以下簡(jiǎn)稱(chēng)SDK)。??低曉O(shè)備網(wǎng)絡(luò)SDK是基于設(shè)備私有網(wǎng)絡(luò)通信協(xié)議開(kāi)發(fā)的,為嵌入式網(wǎng)絡(luò)硬盤(pán)錄像機(jī)、網(wǎng)絡(luò)攝像機(jī)等網(wǎng)絡(luò)產(chǎn)品服務(wù)的配套模塊,提供Windows和Linux兩個(gè)版本,用于遠(yuǎn)程訪(fǎng)問(wèn)和控制設(shè)備軟件的二次開(kāi)發(fā)[1]。
模塊Ctypes是Python內(nèi)建的用于調(diào)用動(dòng)態(tài)鏈接庫(kù)函數(shù)的功能模塊,一定程度上可以用于Python與其他語(yǔ)言的混合編程,可以說(shuō)Ctypes模塊是Python應(yīng)用程序與SDK之間的橋梁。
DLL(動(dòng)態(tài)鏈接庫(kù))是Dynamic Link Library的縮寫(xiě),在Windows下Python環(huán)境中使用ctypes.windll.loadLibrary()函數(shù)進(jìn)行DLL的裝載。本例中??礢DK的DLL載入方法為:sdk=windll.LoadLibrary("HCNetSDK.dll")。
Ctypes提供和c語(yǔ)言兼容的數(shù)據(jù)類(lèi)型,可以很方便地調(diào)用DLL中的函數(shù)。如Ctypes中的cbyte對(duì)應(yīng)c語(yǔ)言中的char及Python中的int/long。
海康SDK頭文件中包含了大量的結(jié)構(gòu)體,在Python中,結(jié)構(gòu)體必須繼承自Ctypes模塊的Structure類(lèi)。每個(gè)子類(lèi)必須定義_fields_屬性,該屬性是2元素元組的列表,包含字段名和字段類(lèi)型,其中字段類(lèi)型必須是Ctypes類(lèi)型。
在??礢DK頭文件中存在大量的宏定義,在Python中可用全局變量來(lái)實(shí)現(xiàn)。如云臺(tái)控制:TILT_UP=21,TILT_DOWN=22。
回調(diào)函數(shù)是一個(gè)通過(guò)函數(shù)指針調(diào)用的函數(shù)?;卣{(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用,用于對(duì)該事件或條件進(jìn)行響應(yīng)。如回調(diào)函數(shù)的原型為:CMPFUNC=CFUNCTYPE(c_int,POINTER(c_int),POINTER(c_int)),第一個(gè)參數(shù)c_int表示函數(shù)返回值是int類(lèi)型。
??礢DK調(diào)用流程通常為:初始化SDK,用戶(hù)登錄,預(yù)覽、云臺(tái)控制等操作,注銷(xiāo)設(shè)備,釋放SDK資源。
初始化函數(shù)用于完成初始內(nèi)存分配等工作,Python中調(diào)用方法為sdk.NET_DVR_Init()。
用戶(hù)登錄實(shí)現(xiàn)用戶(hù)的注冊(cè)功能,返回用戶(hù)ID,該用戶(hù)ID具有唯一性,后續(xù)對(duì)設(shè)備的操作都需要通過(guò)此ID實(shí)現(xiàn)。Python調(diào)用方法為,sdk.NET_DVR_Login_V30(sDVRIP,wDVRPort,sUserName,sPassword,Ctypes.byref(DeviceInfo)),byref()用來(lái)傳遞引用參數(shù),DeviceInfo為設(shè)備信息結(jié)構(gòu)體,繼承至Ctypes.Structure。
視頻預(yù)覽模塊實(shí)現(xiàn)從網(wǎng)絡(luò)設(shè)備取實(shí)時(shí)碼流解碼顯示以及播放控制等功能,Python中調(diào)用方法為sdk.NET_DVR_RealPlay_V40(lUserID,Ctypes.byref(lpPreviewInfo),callBack,pUser) 。其中l(wèi)pPreviewInfo是Ctypes構(gòu)造的結(jié)構(gòu)體,結(jié)構(gòu)體中l(wèi)pPreviewInfo.hPlayWnd=hwnd為窗口句柄,用于播放圖像。
云臺(tái)控制實(shí)現(xiàn)攝像機(jī)的鏡頭方位調(diào)整及變焦變倍等操作,Python中的調(diào)用方法為:sdk.NET_DVR_PTZControl(lRealHandle,dwPTZCommand,dwStop)。
建立報(bào)警通道函數(shù)在Python中調(diào)用方法為sdk.NET_DVR_SetupAlarmChan_V41(lUserID,Ctypes.byref(struAlarmParam)),struAlarmParam是Ctypes構(gòu)造的報(bào)警布放參數(shù)結(jié)構(gòu)體。啟動(dòng)布防前,需要調(diào)用注冊(cè)回調(diào)函數(shù)的接口NET_DVR_SetDVRMessageCallBack_V30(),注冊(cè)回調(diào)函數(shù)的格式為“回調(diào)函數(shù)實(shí)例=回調(diào)函數(shù)類(lèi)型(具體回調(diào)函數(shù))”,然后將回調(diào)函數(shù)實(shí)例作為參數(shù)傳給注冊(cè)接口。
用戶(hù)注銷(xiāo)函數(shù)在Python中的調(diào)用方法為sdk.NET_DVR_Logout(lUserID)。
釋放資源函數(shù)在Python中的調(diào)用方法為sdk.NET_DVR_Cleanup(),在程序結(jié)束前使用。
將SDK提供的接口進(jìn)一步封裝到類(lèi)(class)里,從而簡(jiǎn)化SDK接口,解除上層代碼與SDK之間的耦合關(guān)系。由于??礢DK只需初始化一次,故這里將類(lèi)設(shè)計(jì)為單例模式,將類(lèi)的函數(shù)設(shè)計(jì)為靜態(tài)函數(shù)。
利用上述方法實(shí)現(xiàn)了Python語(yǔ)言與海康SDK的聯(lián)合開(kāi)發(fā)。用此方法編寫(xiě)的設(shè)備監(jiān)控應(yīng)用程序運(yùn)行良好,為后續(xù)系統(tǒng)引入智能識(shí)別技術(shù)打下了堅(jiān)實(shí)的基礎(chǔ)。