來源:江大白|作者:潘大強(qiáng)
導(dǎo)讀 魚眼相機(jī)的標(biāo)定和矯正,網(wǎng)上已經(jīng)有很多理論文章,但是落實(shí)到代碼層面的并不多,而且大部分代碼都是C++實(shí)現(xiàn)。而本文全面的介紹了魚眼相機(jī)標(biāo)定和校正的原理,并給出了用python語言矯正的代碼包,希望對(duì)大家有所幫助。 1 個(gè)人介紹
大家好,我是潘大強(qiáng),大白多年的好友。
目前博士畢業(yè)4年,主要從事智能安防行業(yè)。
之前也分享過AI從業(yè)的一些心得,個(gè)人介紹鏈接。
應(yīng)大白的邀請(qǐng),從AI從業(yè)者的角度,分享工作中遇到的一些經(jīng)驗(yàn)。
之前在江大白的群里,看到有同學(xué)提問“魚眼相機(jī)標(biāo)定”的問題。
對(duì)于魚眼相機(jī)的標(biāo)定和矯正,網(wǎng)上已經(jīng)有很多理論文章,但是落實(shí)到代碼層面的并不多,而且大部分代碼都是C++實(shí)現(xiàn)。
但是做AI的同學(xué),大多數(shù)都是用python語言,所以本次分享,我用python語言(只依賴opencv-python包和numpy包),把之前做的魚眼矯正和變形的相關(guān)經(jīng)驗(yàn),以實(shí)踐為目的,一步步分享給大家。
首先我們來了解一下魚眼相機(jī),和平時(shí)普通相機(jī)拍攝出的效果不同,魚眼相機(jī)通常固定在空間頂部,所以拍攝出的視角是這樣的:
大家可以看到,魚眼圖像類似于把很大角度范圍內(nèi)的光線,進(jìn)行「壓縮」和「扭曲」,將圖像壓進(jìn)一個(gè)相對(duì)較小的空間內(nèi)。
魚眼相機(jī)采用的是魚眼鏡頭,它的前鏡組具有一個(gè)極凸的鏡片表面,外形上看起來讓人聯(lián)想到魚的眼睛,這就是“魚眼”的由來。
那么在智能安防行業(yè)中,魚眼相機(jī)可以做哪些應(yīng)用呢?
最常見的,還是做目標(biāo)追蹤以及客流統(tǒng)計(jì)。
在目標(biāo)追蹤任務(wù)中,通常的球機(jī)或者槍機(jī)方案,無法避免人群遮擋的問題,從而導(dǎo)致較高的ID Swich,造成追蹤不穩(wěn)定。
但是魚眼相機(jī)的頂視角安裝方式,天然緩解了人群遮擋的問題。
在客流統(tǒng)計(jì)任務(wù)中,魚眼相機(jī)利用視野大的優(yōu)勢(shì),在同一空間中,可以頂X個(gè)槍機(jī)。
當(dāng)然除了降低硬件成本,還能避免多相機(jī)檢測(cè)導(dǎo)致的區(qū)域人數(shù)去重。
了解了魚眼相機(jī)的原理和優(yōu)勢(shì),但在實(shí)際項(xiàng)目中,我們會(huì)對(duì)魚眼圖像進(jìn)行矯正和變形,作為最終應(yīng)用的前置任務(wù)。
2 魚眼相機(jī)的畸變校正
下面就進(jìn)行了今天的正題:如何對(duì)相機(jī)做矯正變形?
無論是單目相機(jī)還是雙目相機(jī),拍攝的圖像都會(huì)存在畸變。
它們和魚眼相機(jī)的畸變矯正原理也是一樣的:核心是求解一個(gè)“好”的重映射矩陣(remap matrix)。
從而將原圖中的部分像素點(diǎn)(或插值點(diǎn))進(jìn)行重新排列,“拼”成一張矩形圖。
“好”是跟最終需求掛鉤的,不同任務(wù)往往采用不同的矯正/變形方案。
比如:
(1)單目相機(jī)的畸變矯正
對(duì)于單目相機(jī),為了得到相機(jī)像素坐標(biāo)系和三維世界坐標(biāo)系的對(duì)應(yīng)關(guān)系,我們需要對(duì)相機(jī)的桶形畸變和枕形畸變進(jìn)行矯正。
(2)雙目相機(jī)的畸變矯正
而對(duì)于雙目相機(jī),為了做極線對(duì)齊,實(shí)現(xiàn)深度估計(jì)。
我們需要將兩個(gè)相機(jī),輸出變換到同一個(gè)坐標(biāo)系下。
張正友老師的棋盤標(biāo)定法,通過標(biāo)志物的位置坐標(biāo),估計(jì)出相機(jī)的內(nèi)外參數(shù)和畸變系數(shù),從而計(jì)算出remap matrix。該方法是目前上述兩類相機(jī),矯正效果最好的方法。
(3)魚眼相機(jī)的矯正變形
對(duì)于魚眼相機(jī),本次主要分享三種方法:棋盤標(biāo)定法、橫向展開法、經(jīng)緯度法。
下面我們先來看一下各種方法的矯正效果。
3 魚眼相機(jī)的三種矯正方法 下圖是某款魚眼相機(jī)的采集圖像,而真正有效的監(jiān)控區(qū)域,是內(nèi)部的圓形區(qū)域。
(1)棋盤標(biāo)定法
棋盤矯正法的目的,是將魚眼圖“天生”的桶形畸變進(jìn)行矯正。 具體效果類似于“用手對(duì)著圓形中心做擠壓,把它壓平”,使得真實(shí)世界中的直線,在矯正后依然是直線。
采用棋盤標(biāo)定法進(jìn)行矯正后:
我們發(fā)現(xiàn): ① 現(xiàn)實(shí)世界中的直線,在魚眼圖中發(fā)生了扭曲(如魚眼圖中的藍(lán)色和綠色曲線),矯正后變成了直線(如正方形圖中的藍(lán)色和綠色直線); ② 矯正圖只占據(jù)了魚眼圖中間的一部分(如魚眼圖中的紅色曲線)。 從這個(gè)矯正效果中,可以看出:棋盤標(biāo)定法的缺點(diǎn),是靠近圓周(外圍區(qū)域)的區(qū)域,會(huì)被拉伸的很嚴(yán)重,視覺效果變差。 所以一般會(huì)進(jìn)行切除,導(dǎo)致矯正后的圖片只保留了原圖的中間區(qū)域。 基于以上特點(diǎn),在實(shí)際使用中,我會(huì)把棋盤標(biāo)定法,作為簡(jiǎn)單測(cè)量的前置任務(wù)(矯正圖中的兩點(diǎn)距離和真實(shí)世界中的兩點(diǎn)距離,存在一一對(duì)應(yīng)的關(guān)系)。 也可以作為魚眼圖像拼接的前置任務(wù)(真實(shí)世界中的三點(diǎn)共線,在拼接圖中依然共線)。
(2)橫向展開法
橫向展開法,主要是利用魚眼相機(jī)的大FOV和俯視拍攝的特點(diǎn),來進(jìn)行變形。
比如我們把上圖中的紅點(diǎn),想象成一個(gè)觀察者,當(dāng)他身體旋轉(zhuǎn)360度,看到的什么樣的畫面呢?
上圖是經(jīng)過橫向展開法,變形后的畫面。 可以看到,從原先的俯視視角變?yōu)榱苏曇暯恰?因此可以根據(jù)區(qū)域功能,進(jìn)行切片,再用普通視角的檢測(cè)模型,做后續(xù)任務(wù)。 但是缺點(diǎn)也一目了然,比如展開圖的左右兩側(cè),在真實(shí)世界中應(yīng)該是連通的。 所以當(dāng)有目標(biāo)在魚眼圖中穿過分界線時(shí),在展開圖中該目標(biāo)會(huì)從左側(cè)消失,右側(cè)出現(xiàn)(或者倒過來),看起來不是很自然。 基于以上特點(diǎn),在實(shí)際使用中,我會(huì)利用魚眼相機(jī),覆蓋面積大的特點(diǎn)(比如3米層高的情況下,至少覆蓋100平米),在“某些場(chǎng)景”中取代槍機(jī)或半球機(jī),畫面展開后用正常的檢測(cè)器去完成后續(xù)任務(wù)。 這里還要補(bǔ)充兩點(diǎn): ① COCO數(shù)據(jù)集上訓(xùn)練的人體檢測(cè)器,在魚眼圖中直接使用是不會(huì)work的; ② 與棋盤標(biāo)定法不同,橫向展開不會(huì)損失像素,所以展開圖也可以再remap回魚眼原圖。
(3)經(jīng)緯度法
經(jīng)緯度法主要分為兩個(gè)方面: ① 經(jīng)度
下圖是魚眼圖沿著經(jīng)度對(duì)齊矯正后的畫面。
該方法與棋盤矯正法相比,沒有像素?fù)p失,也不需要標(biāo)定(人為設(shè)計(jì)規(guī)則求解remap matrix)。 但是缺點(diǎn)也很明顯,它只對(duì)豎直方向(圖中的藍(lán)色線和綠色線)進(jìn)行了矯正,而水平方向(紅色線)依然是扭曲的。 ② 緯度
下圖是魚眼圖沿緯度對(duì)齊矯正后的畫面。
可以看到,只對(duì)水平方向(圖中的藍(lán)色線和綠色線)進(jìn)行了矯正,而豎直方向(紅色線)依然是扭曲的。 基于以上特點(diǎn),在實(shí)際落地中,我沒有采用經(jīng)緯度矯正法。 更多的是在學(xué)習(xí)和研究階段,把它當(dāng)作設(shè)計(jì)和計(jì)算remap matrix的一個(gè)作業(yè)。 4 三種矯正方法的代碼實(shí)現(xiàn) 了解上面三種矯正效果的原理,下面我們?cè)賮砜匆幌戮唧w的算法實(shí)現(xiàn)。 無論采用以上哪種方法,最核心的部分是求解remap matrix,具體到之后的代碼中就是mapx和mapy兩個(gè)變量。 它們反映了矯正圖中的像素坐標(biāo)和原始圖像素坐標(biāo)之間的對(duì)應(yīng)關(guān)系。 如果我們把原圖記為image,mapx和mapy表示以上三種方法求出的不同的映射矩陣,那么通過原圖和映射矩陣,就可以得到矯正/變形后的圖像,記為image_remap。 其中 mapx和mapy 的shape都是 ( image_remap.shape[0], image_remap.shape[1] )。 且“mapx[i, j]=m 和 mapy[i, j]=n” 表示 “image_remap的第i行、第j列的像素值,等于image的第n行、第m列的像素”,其中m, n允許是非整數(shù) 。 下面我針對(duì)以上三種方法,依次貼出代碼實(shí)現(xiàn)和流程解釋。
(1)棋盤標(biāo)定法
① 載入依賴包,和計(jì)算相關(guān)的只有opencv-python和numpy,我用的opencv版本是3.4.2.16, 初次使用建議改成該版本。
② 設(shè)置超參數(shù),主要是 CHECKERBOARD, 保證輸入大小和你的棋盤大小是一致的。
以我的案例圖為例,黑白方塊共有 7*10 個(gè),所以棋盤的內(nèi)點(diǎn)數(shù)量是 w=7-1=6, h=10-1=9。
③按照張正友標(biāo)定法的流程,對(duì)拍攝的各種姿態(tài)棋盤圖,進(jìn)行角點(diǎn)檢測(cè)和亞像素提取。
拍攝數(shù)量一般在50~80之間,保證棋盤的寬高可以占整個(gè)畫面1/4以上。
上述代碼會(huì)將提取的棋盤點(diǎn),繪制在原圖中并做保存,我們可以肉眼檢測(cè)一遍,將提取有誤的圖片從庫中剔除。
④ 根據(jù)提取的棋盤點(diǎn)坐標(biāo),計(jì)算相機(jī)參數(shù)和畸變參數(shù)。
ret表示擬合誤差,如果ret很大,說明在第③步中檢測(cè)的棋盤點(diǎn)不準(zhǔn)確,可以回去再檢查下(比如ret>5)。 K和D分別是相機(jī)內(nèi)參和畸變參數(shù),之后會(huì)用到。rvecs和tvecs是相機(jī)外參。 ⑤ 根據(jù)相機(jī)內(nèi)參和畸變參數(shù)求解remap matrix,并做保存。
至此,“訓(xùn)練”階段結(jié)束。只要相機(jī)不變,這組remap matrix可以重復(fù)使用。 ⑥加載remap matrix,對(duì)輸入的魚眼圖片進(jìn)行remap矯正。
我們來看一下棋盤矯正的效果圖,比如原圖是:
經(jīng)過上面棋盤標(biāo)定法的代碼,矯正后的圖片為:
(2)橫向展開法
① 橫向展開法需要對(duì)魚眼圖片,先crop出圓形有效區(qū)域,再做橫向展開。 比如原始圖像:
我寫了個(gè)簡(jiǎn)單的提取函數(shù)get_useful_area,剔除多余黑邊。代碼為:
這樣操作后,可以更好的得到有效區(qū)域:
當(dāng)然在實(shí)際落地時(shí),相機(jī)型號(hào)一旦確定,完全可以手動(dòng)找到合適的參數(shù),切去“黑邊”。 ②求解remap matrix并保存。
至此,“訓(xùn)練”階段結(jié)束。同樣只要相機(jī)不變,這組remap matrix可以重復(fù)使用。 ③ 加載remap matrix,對(duì)輸入的魚眼圖片,進(jìn)行有效區(qū)域提取和remap變形。
再來看一下橫向展開法的效果圖,比如原圖為:
使用上面的橫向展開法代碼展開后,效果為:
(3)經(jīng)緯度法
經(jīng)緯度法也不需要做相機(jī)標(biāo)定,所以方法流程和橫向展開法一樣,只是remap matrix的計(jì)算公式不同。 ① 經(jīng)度矯正法 經(jīng)度矯正的代碼:
經(jīng)度矯正的效果:
② 緯度矯正法 緯度矯正的代碼:
緯度矯正的效果:
以上就是本次關(guān)于魚眼相機(jī)的畸變與矯正的分享,希望對(duì)大家工作和學(xué)習(xí)有幫助。 大家如果有相關(guān)問題想了解的,也可以進(jìn)行提問,我來給大家解答。 PS:本次分享內(nèi)容中的相關(guān)圖片和完整代碼,公眾號(hào)后臺(tái)回復(fù)“魚眼相機(jī)”,進(jìn)行獲取。
互動(dòng)問答1
Q:想問下,魚眼相機(jī)和平時(shí)常用的槍機(jī),在不同的項(xiàng)目任務(wù)中,如何更好的選擇? A:看任務(wù)需求吧,如果是室內(nèi)場(chǎng)景,并且只是統(tǒng)計(jì)人數(shù)或者目標(biāo)追蹤,可以考慮用魚眼相機(jī)。 但是如果要提取目標(biāo)的屬性特征,比如做人臉識(shí)別,ReID,口罩識(shí)別等,還是得用槍機(jī)。
互動(dòng)問答2
Q:在前面魚眼相機(jī)的校正中,有三種方式,經(jīng)緯度法不太推薦。那么針對(duì)剩下的兩種,棋盤標(biāo)定法和橫向展開法,實(shí)際應(yīng)用中,更傾向于哪一種呢? A:這個(gè)要看需求的吧,剛才分享時(shí)也提到了。棋盤標(biāo)定是真正做到了去畸變,所以適合作為測(cè)量和拼接的前置任務(wù)。 對(duì)于橫向展開法的用處,我就看到一種:如果要對(duì)魚眼圖像做目標(biāo)檢測(cè),但是之前的檢測(cè)器都是正常正視視角的,那可以考慮把魚眼圖橫向展開切片后,再上檢測(cè)器。我找下圖。
正中間的魚眼圖,我用頭肩檢測(cè)器去推理時(shí),沒有檢到任何目標(biāo)。然后我把它橫向展開后,按區(qū)域切成4塊,再用頭肩檢測(cè)器逐一推理,是可以檢測(cè)到目標(biāo)的(圖中的藍(lán)色框)。
互動(dòng)問答3
Q:你剛才說要橫向展開后再做檢測(cè),是因?yàn)橹苯訉?duì)魚眼圖像做目標(biāo)檢測(cè)時(shí),效果不好嗎? A:不是的。 去年有一篇關(guān)于魚眼相機(jī)的目標(biāo)檢測(cè)論文: RAPiD: Rotation-Aware People Detection in Overhead Fisheye Images 它提供了魚眼相機(jī)下的人體檢測(cè)方案,用旋轉(zhuǎn)矩形框代替了正矩形框。是基于YOLOv3改的,增加了對(duì)框的旋轉(zhuǎn)角的regression head。效果如下
代碼和數(shù)據(jù):http://vip.bu.edu/projects/vsns/cossy/fisheye/rapid/ 但當(dāng)時(shí)在私有數(shù)據(jù)集上訓(xùn)練時(shí),遇到兩個(gè)問題:(1)推理時(shí),即使靜止的目標(biāo),他的檢測(cè)框的旋轉(zhuǎn)角抖動(dòng)依然很大 (2)與正的矩形框相比,旋轉(zhuǎn)框的標(biāo)定更耗時(shí)。 后來,我就直接用正矩形框?qū)︻^肩進(jìn)行標(biāo)注和訓(xùn)練了,效果也不錯(cuò)。
互動(dòng)問答4
Q:那對(duì)魚眼圖像進(jìn)行棋盤矯正后,再目標(biāo)檢測(cè),效果如何啊? A:如果采用棋盤矯正,會(huì)把地面上的人體進(jìn)行拉伸,且越到周圍拉伸越嚴(yán)重,所以不推薦用棋盤矯正做目標(biāo)檢測(cè),我找下圖。
矯正后,身體明顯被拉長了。
互動(dòng)問答5
Q:明白了,那我想在魚眼相機(jī)中直接做目標(biāo)檢測(cè),有什么好的訓(xùn)練trick嗎? A:這個(gè)有整理過。 ① 不要選擇“人體”這種長條形物體作為標(biāo)定目標(biāo)。因?yàn)殚L條形物體旋轉(zhuǎn)后,再用正的矩形框標(biāo)定時(shí),相鄰框之間很容易產(chǎn)生大的overlap,并且框內(nèi)有冗余信息。所以選擇人頭(偏圓形)或者頭肩(偏正方形)。 ② 標(biāo)定時(shí),太遠(yuǎn)的目標(biāo)可以不標(biāo),或者mask掉。目的是減少誤檢。 ③ 數(shù)據(jù)預(yù)處理時(shí),可以先去掉多余黑邊。 ④ 數(shù)據(jù)增強(qiáng)時(shí),可以添加360度任意角旋轉(zhuǎn)。在數(shù)據(jù)量不大時(shí),可以有效緩解過擬合。 ⑤ 魚眼相機(jī)本身都是2K以上的分辨率,所以模型訓(xùn)練推理都可以適當(dāng)調(diào)大輸入的尺寸。比如640甚至960.
互動(dòng)問答6
Q:看完分享,感覺對(duì)于每張魚眼圖像都需要矯正或變形,這樣操作的話,對(duì)于圖像處理會(huì)不會(huì)開銷很大? A:剛才代碼中也看到了,推理時(shí)就一個(gè)remap操作,我測(cè)試過用python的cv2.remap處理2K大小魚眼圖,速度在300FPS,如果有專門的工程人員在CUDA上實(shí)現(xiàn)的話,1000FPS都沒問題吧。
互動(dòng)問答7
Q:如果想購買魚眼相機(jī)嘗試的話,價(jià)格貴嗎?: A:??荡笕A宇視都有,像我用的就是500多塊的海康相機(jī),1.16mm的焦距。
互動(dòng)問答8
Q:針對(duì)之前的分享,有一個(gè)問題,代碼實(shí)現(xiàn)的時(shí)候,opencv必須要用特定的版本嗎?因?yàn)橐呀?jīng)裝了其他版本的opencv了,是否也適用呢? A:版本不同,cv2的內(nèi)置函數(shù)的輸入輸出的dtype或者格式可能會(huì)不同。所以最好跟我代碼中的統(tǒng)一,否則報(bào)錯(cuò)了你得一步步去debug。我現(xiàn)在主要用3.4.2和4.5.2。
互動(dòng)問答9
Q:常規(guī)做法是魚眼相機(jī)展開再做檢測(cè)和track來進(jìn)行人流量統(tǒng)計(jì)吧? A:看檢測(cè)器吧。如果頂視角的檢測(cè)器效果不理想,那可以先展開,再用正視角的檢測(cè)器去做,畢竟正視角的數(shù)據(jù)集更多
互動(dòng)問答10
Q:球形的這種畫面下的目標(biāo)追蹤跟槍機(jī)下的是不是也不太一樣,原來的deepsort追蹤算法能直接用嗎?還是有別的trick在里面? A:會(huì)有些不同。比如槍機(jī)下的SORT會(huì)把框的x,y,w,h都做Kalman濾波。魚眼下,我會(huì)去掉w,h,而考慮半徑r ReID 的feature已經(jīng)不明顯了,而且用魚眼的優(yōu)勢(shì)就是減少遮擋,所以不會(huì)用“Deep”。
互動(dòng)問答11
Q:還有一個(gè)疑問,我看你用的魚眼相機(jī)的焦慮是1.16mm,不是說焦慮越小觀測(cè)的目標(biāo)會(huì)越近么?車載前視的大概6mm焦慮,能看15米左右吧,魚眼是想看更大范圍的,為啥選這么小的焦慮呢,還是說魚眼相機(jī)的特性就是和平常的相機(jī)不一樣? A:焦距越小,F(xiàn)OV越大吧,視野越開闊。 比如單反相機(jī)大炮筒長焦200以上的,所謂拍鳥利器,視野窄拍的遠(yuǎn)。
互動(dòng)問答12
Q:主機(jī)廠在車上前裝的環(huán)視相機(jī)也是魚眼相機(jī),那么在進(jìn)行目標(biāo)檢測(cè)任務(wù)時(shí),應(yīng)該以原始畸變圖直接作為訓(xùn)練集還是應(yīng)該先去畸變?cè)儆?xùn)練? A:① 肯定不推薦用棋盤標(biāo)定法去畸變?cè)倌繕?biāo)檢測(cè),因?yàn)檫@種矯正方式會(huì)把 “和相機(jī)平面不平行”的物體進(jìn)行拉伸,比如下圖中的人體。 原圖:
矯正圖:
可以看到,矯正后,身體明顯被拉長了。 而且這種拉伸程度越到周圍越厲害,造成了扭曲,反而不利于檢測(cè)。 ② 如果你的原有檢測(cè)器只是針對(duì)傳統(tǒng)正視視角圖片(比如COCO)訓(xùn)練的,那么在魚眼圖這種俯視視角一般不會(huì)work。 所以有個(gè)辦法就是用橫向展開法,展開后用常規(guī)視角的檢測(cè)器去做。
③ 當(dāng)然,如果你已經(jīng)積累了大量魚眼視角下的標(biāo)簽數(shù)據(jù),那么直接去做目標(biāo)檢測(cè)也是OK的。我在前面也分享了幾個(gè)trick,可以參考,就是針對(duì)不做畸變矯正直接檢測(cè)的case。
互動(dòng)問答13
Q:經(jīng)緯度矯正可以一起用嗎? A:可以一起用,我實(shí)驗(yàn)過,出來的效果會(huì)跟棋盤矯正相似,就是圓周的區(qū)域會(huì)被拉伸的很扭曲。中間區(qū)域沒有棋盤矯正好,所以我沒采用。
編輯:黃飛
-
相機(jī)
+關(guān)注
關(guān)注
4文章
1350瀏覽量
53580 -
AI
+關(guān)注
關(guān)注
87文章
30728瀏覽量
268880 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73618 -
python
+關(guān)注
關(guān)注
56文章
4792瀏覽量
84627
原文標(biāo)題:深入淺出,一文講透魚眼相機(jī)畸變矯正
文章出處:【微信號(hào):3D視覺工坊,微信公眾號(hào):3D視覺工坊】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論