一、工業相機編程模型和流程
不同的工業相機提供不同的編程接口(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相機編程,他們基本流程都是一樣,恕不詳述!
二、 工業相機SDK接口使用總結
相機調用 ?:
我們利用相機采集圖像,首先要對相機進行相關參數設置及控制,這需要對相機的SDK包比較了解,一般相機廠家都會提供相機SDK,其中包含用戶手冊和調用Demo,這些都大大降低了調用門檻,提高了二次開發用戶的效率。目前用過Balser、海康、大華等相機,其實都是一個套路,都是按照下面幾個步驟進行的。
1)枚舉設備
2)創建句柄
3)打開設備
4)開始抓圖
5)獲取一幀并保存圖像
6)停止抓圖
7)關閉設備
8)銷毀句柄
相機同步:
若是開發過程中用到雙目或者多目的話,則需要外接同步觸發器或者外部觸發信號,通過相機同步觸發線來實現同步問題。以實際應用過的Basler acA1300-200uc為例,其相機同步觸發線具體類型如下:
1 -—— ? +12 VDC ?紅
2 —— I/O Input 1 ?黃
3 —— VCC(加電阻) 藍
4 —— ?I/O Out 1 ? ?綠
6 —— DCcam Power GND 黑
0000—— I/O GND ?白
三、 Basler Pylon工業相機SDK的使用
Pylon庫有C++ .Net等各種封裝版本,一般用C++版本,功能全面效率高,但對于不同接口(GigE USB3.0 CameraLink)的相機必須對應使用不同的類,之間不能通用。
基于GenAPI通用相機抽象接口使用的是Node結構,以字符串形式訪問相機參數,可以統一管理不同接口類型的相機。但效率低,使用不方便。
Pylon高層用C++封裝,形成本地相機對象
如何管理多個相機,最靠譜的方法是按相機ID標定順序,需要讀一個配置文件,比如XML或JSON,然而一開始不知道ID,需要先列舉出來。
四、Pylon 以實時圖像采集講解PylonC SDK使用流程
一般的對于提供硬件編程來說,硬件生產廠家都會提供好SDK使用的手冊和實例。手冊中一般包括安裝和配置流程,一些基本概念的介紹,SDK每個函數使用,SDK使用流程和實例(有些硬件實例直接寫在手冊中,有些會以單獨文件存在,還有的兩者皆有)。對于上位機軟件開發人員來說拿到一個硬件上位機編程任務。
首先應該閱讀了解其SDK概念,再按照其介紹的SDK開發流程閱讀其提供的實例,修改相應的實例為自己所用,有不懂的函數查詢一下其用法即可。有些開發人員習慣性的去記其API,這是費時費力的做法,并不推薦。下面主要以實時圖像采集講解Basler相機的PylonC SDK的使用流程。
PylonC SDK的使用的總體流程圖如下
▼
下面是其中對于不同的工作要求,加載相機對象和卸載相機對象是通用的。而要使用其他模塊,如事件對象時,相應的改為加載事件對象和卸載事件對象,以及使用事件對象完成相關任務即可。編程時一定要對整個流程做好規劃,特別是硬件編程時一定留意內存泄露,前面分配的資源一定要在后面釋放。
下面是五個大流程的詳細解析,需要的地方已經加以說明,并注解了需要用到的函數
加載相機對象:
卸載相機對象:
加載數據流抓取對象:
卸載數據流抓取對象:
單幀或連續抓圖過程:
按照以上介紹的流程即可實現實時圖像采集:
在工業控制當中,用到basler工業相機sdk編程,主要是使用c或者c++,當項目龐大時,又需要良好的用戶界面,用C++是不錯的選擇。
以實例和看過的一些參照講講PylonCppSDK使用流程。
首先,同C一樣,這里給出一個bolg鏈接,寫的不錯,即上面文大俠這篇http://blog.csdn.net/wenzhou1219/article/details/7543420。
從中我們知道,總的開發流程圖如下
▼
那么,用C++開發也大抵如此。
這里我們看一個basler的cpp sample:
把這個和上面的流程圖對比理解,再看看文檔和sdk的結構,理解起來就容易多了。
五、關于使用維視工業相機 SDK 采集圖像的問題
問:最近一直在研究怎么用相機的SDK采集圖像且能實時采集。用的維視MV-1300UC,它提供了DEMO,還有說明文檔(一些函數的定義),我發現例子里面沒有給出類,就直接定義類中的函數,看不明白。有開發經驗的老師嗎?給點指導,自己一個人學習一點進展也沒有,謝謝!
答:
引用
工業相機的SDK,為了通用性應該提供的是C接口
既然如此,例子中的類應該就只限那個例子有效,并不是使用該相機必須的
只要你看懂了每個函數的功能,用不著照抄例子中使用的類
有包含文件(.h)和靜態鏈接庫(.lib)我看了例子都沒有看到主函數基本都是void 類名::函數名(){ }這種形式。
所以說你的問題在于看不懂例程,而不是看不懂相機開發包
一般工控領域提供的例程都是MFC程序,你到里面找main函數當然找不到
問:哦,這樣啊,老師你有這方面的經驗嗎?這個東西我都弄了兩周了,還是無從下手,難怪我還一直找主函數。給的說明文檔我都看了好幾遍了,感覺例子里面用到的也不多,自己想把里面的函數單獨拿出來來實現功能,參數經常發生錯誤。
答:你說的這款相機我沒用過。
建議你簡單學習一下MFC。工控方面的編程用MFC比較多,畢竟搞工控的都不是專業程序員,沒精力去專研那些復雜先進的軟件技術,MFC算是最普及最簡單的圖形界面庫了。
相機的話,應該是程序啟動時【Open】,關閉時【Close】,采集圖像前需要【設置采集參數】,采集單幅圖像可以隨時【采集】,采集連續圖像的話需要【Start】和【Stop】,Start前要【設置連續采集參數】大多還需要【設置回調函數】。你可以去找這些功能的函數以及它們在例程中的位置和用法,配合MFC簡單編程的學習,應該能快一點上手吧。
轉自:CSDN論壇
六、工業相機SDK之opencv二次開發
做視覺的第一步是選好相機鏡頭等硬件設備,接下來就是將自己開發的算法在硬件上實現。我最近做一個項目,實現了一下Opencv在相機SDK上的運用,下面小結一下具體實現步驟.
1. 安裝相機自帶的驅動和SDK開發包;
2. 用VS2010新建一個工程,配置好SDK的動態鏈接庫(或者靜態),具體動態鏈接庫的使用可參見孫鑫的那本書,這里不多說;
3. 條用SDK開發包中的函數建立相機和PC機件的鏈接;
4. 建立視頻流數據,設立一個回調函數(具體參見各SDK),并將數據拷貝到Mat中的data中;
5. 有了opencv中的Mat數據結構,接下來就可以實現我們的各種算法了。
審核編輯:黃飛
評論
查看更多