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