不同的工業相機提供不同的程式設計介面(SDK),儘管不同介面不同相機間程式設計介面各不相同,他們實際的API結構和程式設計模型很相似,瞭解了這些再對工業相機程式設計就很簡單了。

DMA技術

DMA是一種高速的資料傳輸操作,允許在外部裝置和儲存器之間直接讀寫資料,既不通過CPU,也不需要CPU干預。整個資料傳輸操作在一個稱為"DMA控制器"的控制下進行的。CPU除了在資料傳輸開始和結束時做一點處理外,在傳輸過程中CPU可以進行其他的工作。這樣,在大部分時間裡,CPU和輸入輸出都處於並行操作。因此,使整個計算機系統的效率大大提高。

對於工業相機來說,當CMOS或CCD晶片曝光然後將資料轉到相機快取後,這時候DMA會負責將快取中資料儲存到硬碟上指定位置,正好滿足相機高速大資料的傳輸。一般都會使用DMA來完成實時的資料採集和儲存。

多數時候,DMA控制器存在各種介面的影象採集卡中,包括1394/GigE/USB/Camera Link等,這些採集卡有自己的時間控制單元完成和相機曝光的同步,並控制DMA的存取行為。

工作流程

當相機工作時,就是連續的採集-處理-採集-處理...的過程,但是這就存在一個問題,如果採集的速度比處理速度快,處理不過來,怎麼辦?在實際中,我們使用佇列來解決這個問題,當前幀沒有處理完,下一幀到來時直接放入佇列等待當前處理完成後再處理它。
如下圖
這裡使用三個佇列完成採集和處理同步。
DMA佇列:當CMOS或CCD晶片曝光然後將資料轉到相機快取後,這時候DMA會負責將快取中資料寫入到“DMA佇列”頭Buffer中。
準備佇列:一旦“DMA佇列”頭Buffer被填充完成,會被加到“準備佇列”尾後,這時候會發送中斷通知使用者程式:當前又有一幀資料採集完成,您看著處理吧。
處理佇列:當用戶接收到中斷會自動跳轉到中斷函式中,使用GetFrame拿取“準備佇列”頭Buffer,然後加到當前使用者程式“處理佇列”尾,使用者程式從“處理佇列”頭拿取Buffer處理完成後使用PutFrame將Buffer再新增到原始的“DMA佇列”尾。
需要說明如下幾點:
1.這裡的初始佇列為1-10,都是初始分配為DMA佇列的,這個記憶體分配和釋放過程有的SDK是自己負責的,有的則需要使用者自己分配和釋放,SDK只負責託管使用。
2.一般最開始註冊一箇中斷處理函式,當“準備佇列”填充完成會自動跳轉到中斷函式中,藉此完成同步操作。也可以是使用者自己維護同步結構體,使用查詢和等待的方式判斷“準備佇列”頭是否填充完成,是否該使用者程式獲取資料和處理了。
3.如果使用者處理任務非常簡單,可以去掉“處理佇列”,每次直接GetFrame->處理->PutFrame。如果使用者處理任務比較複雜而不希望出現丟幀的現象,則需要使用者使用“處理佇列”來儲存所有可用的Buffer。
4.這裡佇列也只是能夠解決處理速度比採集速度慢少許的情況,主要是對不同處理速度做平均來保證採集和處理同步。如果每一幀的處理時間太長,這時候“DMA佇列” Buffer全部轉移到“處理佇列” Buffer,就會出現異常情況,這時不同的相機會有不同的處理方法。

資料傳輸和顯示流程


如圖,每個相機可能有不同的流採集器(Grab Streamer)或同一介面上安裝了多個相機(也對應多個流採集器),對應多個通道(Channel)。對每個通道來說,在實際採集時資料傳輸實際上是拆分成如圖的資料包(Packet) RawData形式傳遞的,記憶體中儲存形式為一維陣列,在每一幀影象的起始存在不同的標識表明一幀的開始和結束,每一個Packet都有標識表明當前所屬的通道。為了顯示影象,使用者程式需要重新將一維陣列資料拼裝成影象形式,這一過程由使用者完成,通常可藉助OpenCV或MIL等影象處理包完成該操作。

程式設計模型和流程

對於相機來說,常見程式設計時我們關注三個物件——相機物件、採集物件、引數物件。
相機物件(Camera Object):負責相機的連線、斷開等工作。
採集物件(Grab Streamer):負責相機的採集佇列分配、相機單幀、連續採集。
引數物件(Parameter Object):負責相機引數的設定。
不同的SDK可能安排不一樣,一般來說要不是三種物件的功能合併到“相機物件”中,要不是分為三種物件,其實採集物件和引數物件都是在“相機物件”上封裝而來。
通用程式設計流程如下圖:

可以看到相機程式設計需要做三方面工作:

1.初始化操作

首先初始化相機驅動Com環境,然後遍歷得到當前的相機列表,根據相機ID或List 編號選擇對應相機。
之後連線指定相機,首先設定本次採集的相機引數(幀速、影象大小、縮放比等),然後是分配和註冊當前DMA佇列,這裡有的是使用者完成,有的是SDK完成
之後先開啟DMA邏輯等待相機採圖,然後使相機開始工作採圖,整個系統就按照之前工作流程運作起來了,許多SDK將“開啟DMA”和“相機開始工作”合併為“開始採集”

2.結束操作

先停止相機工作再關閉DMA邏輯,許多SDK將“開啟DMA”和“相機開始工作”合併為“結束採集”
然後清理DMA佇列,和分配時對應,這裡有的是使用者完成,有的是SDK完成
最後斷開相機並清理工作環境。

3.中斷響應操作

當相機一幀採集完成後,自動跳轉進入中斷回撥函式,這裡分了兩種中斷回撥函式。
第一種為簡單的取Buffer->處理->放回。
第二種結合Windows的訊息佇列,在此處再給一個“處理佇列”,給處理一個緩衝時間。
這裡的處理包括常見的影象處理、計算和顯示及RawData拼裝為影象等用到Buffer的地方。
前面也說過,常用的是中斷響應處理,除此之外,自己去查詢Buffer填充狀態並作相關同步操作在某些場合也會用到,這個請查詢不同相機SDK給出的同步方案。
差不多所有的工業相機SDK都是這樣的程式設計模型和流程,AVT 1394相機和Basler Camera Link相機AVT GigE相機相關程式碼在筆者網站可下載,還有之前講的Basler Pylon SDK相機程式設計,他們基本流程都是一樣,恕不詳述!