RoboMaster視覺教程(1)攝像頭

攝像頭參數

攝像頭應該是機器視覺中最重要的部分了,選擇一款成像質量好穩定可靠的攝像頭可以極大地減少識別算法設計的難度。主流的攝像頭分爲CMOS攝像頭和CCD攝像頭。一般而言CCD攝像頭體積大造價高精度高,而CMOS攝像頭由於集成度高造價遠低於CCD攝像頭,同時CMOS攝像頭的體積功耗等參數也相應地優於CCD攝像頭。本文主要總結CMOS攝像頭的選型(因爲沒玩過CCD攝像頭)。

捲簾曝光與全局曝光

通常我們在網上買到的攝像頭都是捲簾曝光的攝像頭,在日常使用時很難看出這兩種攝像頭的區別,但是在對速度要求高的領域這兩種曝光方式的優劣就很明顯了,尤其是對於廉價的攝像頭捲簾曝光的果凍效應更加明顯。
有關捲簾曝光和全局曝光的區別可以參看:聊聊快門:捲簾/全局快門與果凍效應

除了果凍效應外,全局曝光的攝像頭在低曝光時間的情況下的顏色飽和度更高,在實際測試比較中發現同樣將曝光值調到最小,在拍攝裁判系統紅色燈條的時候,KS2A17(200萬像素捲簾曝光攝像頭)與KS1A552(100萬像素全局曝光攝像頭)對比明顯,KS2A17所拍攝的燈條偏暗偏灰,並且會閃爍,而KS1A552色彩鮮豔。如圖1圖2所示:(由於現在已經不做比賽了,就以之前拍攝的視頻截圖舉例)

在這裏插入圖片描述 KS1A552拍攝能量機關
圖 1 KS2A17低曝光拍攝裝甲板 圖2 KS1A552低曝光拍攝能量機關

通過以上兩圖對比,在顏色方面全局曝光攝像頭完爆捲簾曝光攝像頭。

曝光

在裝甲識別中,曝光度是決定能否成功識別到裝甲板的關鍵因素。我大二做比賽時,由於是從零開始並不知道攝像頭有那麼多的參數可以調節,當時以爲分辨率高顏色逼真的攝像頭就是好攝像頭,於是買了個微軟的LifeCam Studio,這個攝像頭應該是我買過的最失敗的攝像頭,又貴又難用。第一次知道調節曝光的威力還是在看了官方開源的代碼後,當時的感覺就是那種突然開竅的感覺。在不知道曝光的時候用的方法是YOLO,這算法很牛逼,但很慢,連電腦上跑起來都卡就別說妙算上了。當時跑YOLO的幀率爲電腦上28fps,妙算上8fps。下面直接上圖對比一下攝像頭正常曝光和低曝光的巨大差別。

在這裏插入圖片描述 在這裏插入圖片描述
圖3 正常曝光下拍攝的圖片 圖4 低曝光下拍攝的圖片

所以當我們拍攝能自主發光的物體時,降低曝光時間可以減少環境光的影響。這時通過閾值處理得到二值圖就可以進一步處理。

Gamma矯正

在降低裝甲板的誤識別率的過程中,我們可以通過各種約束來過濾誤匹配的情況,而更聰明的方法其實是識別裝甲板中間的數字。但是當我們把攝像頭的曝光調到很低的情況下數字就看不見了(如圖5),這時候怎麼辦呢?一種不太容易想到的方法是提高攝像頭的Gamma值。當Gamma提高時圖像中亮度較低的區域的亮度會被提高。如圖5~圖7所示:

在這裏插入圖片描述 在這裏插入圖片描述 在這裏插入圖片描述
圖5 沒有提高Gamma 圖6 提高Gamma 圖7 進一步提高Gamma

圖5中幾乎看不出中間的數字,而在提高Gamma後可以看清中間的數字,當進一步提高Gamma後數字可以明顯被認出。有人可能會有疑問,既然暗的區域的亮度提高了,那不就和降低曝光前是一樣的了嗎。並不一樣,提高Gamma後圖像中被提升亮度的部分爲灰色而紅色部分的燈條沒有明顯變化。如圖8,圖中被提高亮度的部分基本上都爲灰色,由於灰色的rgb值相同,所以只要將圖片的兩個通道相減就能去除背景的干擾。如圖9,要識別紅色只需要紅色通道減去藍色通道,留下來的便是需要的。在找到燈條後框出數字區域給識別函數識別即可。

在這裏插入圖片描述 在這裏插入圖片描述
圖8 Gamma矯正結果 圖9 紅藍通道相減

那攝像頭的Gamma矯正到底做了些什麼呢?其實做的事情很簡單,就是將圖像的每一個像素點通過一個冪函數進行了轉換,而冪函數的指數的倒數就是通常所說的gamma值,該函數的圖像如圖10所示:

在這裏插入圖片描述
圖10 Gamma矯正函數曲線

從曲線中可以看到輸入數值較小時輸出對數入的比值較大,由此可以提高圖像暗處的亮度。
有關曝光和Gamma可以參看這篇博文

幀率與攝像頭選型

對於RoboMaster比賽而言,識別的速度當然是越快越好,所以攝像頭幀率也是越高越好。由於帶寬的限制幀率和分辨率通常互相制約,想要高幀率分辨率就會低。下表是我使用過的攝像頭的分辨率與幀率表:

型號 分辨率 幀率
KS2A17 彩色捲簾 640*480 120
1280*720 60
1920*1080 30
KS1A293 黑白全局 640*480 240
1280*800 120
KS1A552 彩色全局 640*480 60
1280*800 60
WX605 彩色捲簾 640*320 330
1280*720 120
1920*1080 60

可以看到分辨率取最低的時候通常可以達到最大幀率,事實上對於妙算(TK1)而言也僅能處理分辨率爲640*480左右的圖片,分辨率再高就跑不動了,選用WX605時可以達到最快單幅圖片6ms左右的處理速度也就是說妙算最快可以跑到150幀,故綜合考慮在實際使用中結合濾光片選擇了KS1A293兼顧了圖像質量與速度。

鏡頭

鏡頭我覺得是最容易被忽視的一點了,因爲通常買來攝像頭也不會去想到換鏡頭。不同焦距的鏡頭所呈現的視角是不一樣的,焦距越大視角越窄。

在硬件和金錢條件限制下,可以通過選擇適合的鏡頭來提高圖像的成像質量,在實測中戰車槍管上使用6mm或8mm左右的鏡頭比較合適,在這個焦距下3m左右的裝甲板拍的很清楚。使用1280*720分辨率8m的能量機關也可以拍得較清楚。

鏡頭與拍攝視角的關係大致如下圖,由於該圖針對的是數碼相機故數據不適合我們的這個場景,但焦距與視角間的關係還是可以看一看對比一下的。

在這裏插入圖片描述
圖11 鏡頭焦距與視角

濾光片

由於裝甲板只有紅色和藍色,所以在識別的時候我們只需要把這兩種光過濾出來就可以了,其實不用濾光片也是可以的,通過將圖片由BGR轉換到HSV識別顏色或者紅藍通道互減都可以達到過濾顏色的目的。

濾光片主要是用來配合和黑白攝像頭使用的。之前分析各種攝像頭時說道最終選型爲KS1A293全局曝光黑白攝像頭,使用濾光片就可以很好地結合其240fps的幀率和全局曝光的優勢

Linux攝像頭驅動

Linux下的攝像頭驅動是V4L2,這沒什麼好說的。這裏我主要要講一下OpenCV調用攝像頭的方法,以及一些攝像頭相關的工具。

攝像頭調試工具

最好用的工具當屬qv4l2了,通過這個工具可以很方便地調節攝像頭的參數。如果你想在程序運行時調節攝像頭曝光,只要打開這個工具,就可以直接修改攝像頭的曝光、Gamma等參數,非常好用。

在這裏插入圖片描述
圖12 qv4l2軟件截圖

可以看到該軟件幾乎列出了攝像頭的所有參數,調節參數非常方便。

安裝方法:sudo apt install qv4l2

還有一套命令行工具

sudo apt install v4l-utils

安裝後可以使用v4l2-ctl來控制攝像頭。

使用RMVideoCapture類調用攝像頭

DJI在2017年開源了一套視覺代碼,其中包含了一個很好用的攝像頭驅動RMVideoCapture。通過RMVideoCapture,可以繞過OpenCV自帶的VideoCapture來調用攝像頭,進而實現對攝像頭的各種設置包括曝光、分辨率、幀率、圖像格式等,具體的調用方法可以參看2018年東南大學開源的代碼。

使用OpenCV的VideoCapture來調用攝像頭

上面說道DJI搞了一個RMVideoCapture,那麼是不是說VideoCapture就真的不好用呢?不是的,有大概率是參數沒設置對或者編譯OpenCV的時候沒有選中編譯V4L2。

下面來介紹以下怎樣正確使用VideoCapture。
首先必須在編譯OpenCV的時候選中V4L2(我一般是用CMake GUI來編譯OpenCV的)

在這裏插入圖片描述
圖13 CMake添加V4L2

編譯過後就可以正常地使用VideoCapture來更改攝像頭參數了。
之前OpenCV是不支持更改BufferSize的,但是在2018年3月9號以後添加了對更改BUFFERSIZE的支持
查看OpenCV相應的代碼可以看到

12th patch: March 9, 2018, Taylor Lanclos <[email protected]>
 added support for CV_CAP_PROP_BUFFERSIZE
 
    case cv::CAP_PROP_BUFFERSIZE:
        if (bufferSize == value)
            return true;

        if (value > MAX_V4L_BUFFERS || value < 1) {
            fprintf(stderr, "V4L: Bad buffer size %d, buffer size must be from 1 to %d\n", value, MAX_V4L_BUFFERS);
            return false;
        }
        bufferSize = value;
        return v4l2_reset();

也就是說只要用最新的庫之前RMVideoCapture所解決的問題都可以用VideoCapture來解決。
爲了方便我以python說明下如何正確使用。

#顯示OpenCV的編譯信息,可以查看有沒有包含V4L2支持,如果沒有需要重新編譯
print(cv2.getBuildInformation())
#打開攝像頭
cap = cv2.VideoCapture(1)
#顯示緩存數,默認爲4最大爲10
print(cap.get(cv2.CAP_PROP_BUFFERSIZE))
#設置緩存幀爲2
cap.set(cv2.CAP_PROP_BUFFERSIZE,2)
print(cap.get(cv2.CAP_PROP_BUFFERSIZE))
#調節攝像頭分辨率
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 800)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
#設置圖像爲MJPG格式,大多數情況下只有這個格式能達到最大幀率
print('setform', cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M', 'J', 'P', 'G')))
#設置FPS
print('setfps', cap.set(cv2.CAP_PROP_FPS, 60))
#以上兩句打印出來的是設置有沒有成功,成功的話爲True否則是False
gamm = 100
expo = 1
#設置Gamma
cap.set(cv2.CAP_PROP_GAMMA, gamm)
#設置成手動曝光
cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1)
#設置曝光
cap.set(cv2.CAP_PROP_EXPOSURE, expo)
#設置成自動曝光
 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE,2.6) 

所需要設置的參數大概就是上面的這些。這裏我要強調以下CAP_PROP_AUTO_EXPOSURE的設置,這個參數的範圍在OpenCV源碼中寫的時0到4,也就是說設置是否自動曝光的參數並不是0或者1。通過實驗發現在使用KS1A552攝像頭時[0,2.6)範圍爲關閉自動曝光,[2.6,4]爲開啓自動曝光。

OpenCV源代碼中對參數範圍的說明
    if (normalizePropRange) {
        switch(property_id)
        {
        case CAP_PROP_WB_TEMPERATURE:
        case CAP_PROP_AUTO_WB:
        case CAP_PROP_AUTOFOCUS:
            range = Range(0, 1); // do not convert
            break;
        case CAP_PROP_AUTO_EXPOSURE:
            range = Range(0, 4);
        default:
            break;
        }
    }

最近申請了一個微信公衆號,名字叫江達小記。目前還沒有發過文章,打算將自己的學習研究的經驗總結下來幫助他人也方便自己。感興趣的朋友可以關注一下。
在這裏插入圖片描述

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/u010750137/article/details/90698203

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章