OpenCV-Python教程:46.攝像頭標(biāo)定

基礎(chǔ)

今天的針孔攝像頭對(duì)圖像做了很多扭曲翻具,兩個(gè)主要的扭曲是徑向畸變和切向畸變悼嫉。

由于徑向畸變艇潭,直線會(huì)顯示成曲線,當(dāng)直線離圖像中心越遠(yuǎn)時(shí)越明顯戏蔑。比如下面顯示的這張圖蹋凝,棋盤(pán)的兩個(gè)用紅色標(biāo)出來(lái)的邊緣,你可以看到棋盤(pán)不是直線总棵,也不和紅線匹配鳍寂。所有的直線都凸了。

扭曲可以用下面的來(lái)解決:

類似的情龄,另一個(gè)切向畸變是因?yàn)槌上竦墓饩€不是完全平行的到達(dá)鏡像平面伐割。所以有些區(qū)域比期望的要看上去離的近候味。可以用下面的方式解決:

簡(jiǎn)單說(shuō)隔心,我們需要找到5個(gè)參數(shù),叫做畸變參數(shù):

除此之外尚胞,我們需要找到更多的信息硬霍,比如攝像頭的內(nèi)部和外部參數(shù),內(nèi)部參數(shù)是攝像頭特定的參數(shù)笼裳。包括焦距(fx, fy)唯卖。光學(xué)中心(cx, cy)。也叫攝像機(jī)矩陣躬柬。它只依賴攝像頭本身拜轨。一旦算出來(lái)就可以保存下來(lái)為以后使用,它應(yīng)該是一個(gè)3x3的矩陣:

外部參數(shù)對(duì)應(yīng)了旋轉(zhuǎn)和平移向量來(lái)反應(yīng)一個(gè)3維的點(diǎn)到2維的系統(tǒng)里允青。

對(duì)于立體的應(yīng)用橄碾,這些扭曲需要首先被矯正燕耿。要找到所有的這些參數(shù)颖变,我們得做的是提供一些有良好定義模式的樣例圖像(比如棋盤(pán))。我們找到特定的點(diǎn)(棋盤(pán)的四個(gè)角)饮焦,我們知道他們的真實(shí)世界的坐標(biāo)琼掠,我們知道他們?cè)趫D像里的坐標(biāo)拒垃。通過(guò)這些數(shù)據(jù),后臺(tái)就能解決一些數(shù)學(xué)問(wèn)題以得到畸變參數(shù)瓷蛙。

編碼

上面提到的悼瓮,我們需要10個(gè)測(cè)試模式來(lái)做攝像機(jī)矯正。重要的輸入數(shù)據(jù)是3D真實(shí)世界的點(diǎn)和他們對(duì)應(yīng)的2D圖像的點(diǎn)艰猬。2D圖像點(diǎn)好辦我們可以很容易的從圖像里的得到横堡。

3D真實(shí)世界的點(diǎn)呢?那些圖像是從靜態(tài)攝像機(jī)拍攝姥宝,棋盤(pán)放在另一個(gè)位置和方向翅萤。所以我們需要知道(X, Y, Z)的值腊满。但是為了簡(jiǎn)單套么,我們可以說(shuō)棋盤(pán)靜止在XY平面。(所以Z=0)且攝像機(jī)相應(yīng)的移動(dòng)碳蛋。這個(gè)考慮幫我們找到X胚泌,Y值,現(xiàn)在對(duì)于X肃弟,Y值玷室,我們可以簡(jiǎn)單的傳入點(diǎn)(0, 0), (1, 0)零蓉, (2, 0)穷缤,... 表示點(diǎn)的位置敌蜂。在這種情況下,我們得到的結(jié)果是棋盤(pán)的大小量度津肛。但是如果我們知道面積章喉,(比如30毫米),我們可以傳入值(0,0), (30,0), (60, 0)身坐,...,我們可以用mm來(lái)表示結(jié)果秸脱。

3D的點(diǎn)被叫做物體點(diǎn),而2D的圖像點(diǎn)被叫做圖像點(diǎn)部蛇。

設(shè)置

要找到棋盤(pán)的模式摊唇,我們用函數(shù)cv2.findChessboardCorners()。我們也需要傳我們要找的模式的類型涯鲁,比如8x8網(wǎng)格巷查,5x5網(wǎng)格等,在這個(gè)例子里撮竿,我們使用7x6網(wǎng)格(一般來(lái)說(shuō)棋盤(pán)都是8x8的方塊7x7的內(nèi)角)吮便,它返回角點(diǎn)。這些角點(diǎn)會(huì)按照從左到右幢踏,從上到下的順序放好髓需。

這個(gè)函數(shù)可能沒(méi)法在所有圖像里找到需要的模式,所以一個(gè)號(hào)的選擇是寫(xiě)代碼房蝉,啟動(dòng)攝像機(jī)僚匆,然后檢查每幀,找需要的模式搭幻,當(dāng)取得了模式咧擂,找到角點(diǎn),并存在列表里檀蹋。同時(shí)提供一些間隔松申,然后在讀下面的幀的時(shí)候我們可以調(diào)整我們的棋盤(pán)的方向。不斷進(jìn)行這個(gè)過(guò)程知道需要的好的模式都獲取到了俯逾。即使在這個(gè)例子里贸桶,我們也不知道多少是好的,所以我們讀入所有的圖像取里面好的桌肴。

除了棋盤(pán)皇筛,我們可以使用一些環(huán)形濾線。但是之后使用函數(shù)cv2.findCirclesGrid()來(lái)找模式坠七,據(jù)說(shuō)使用環(huán)形濾線的時(shí)候回用更少的圖像水醋。

當(dāng)我們找到了角點(diǎn)旗笔,我們用cv2.cornerSubPix()函數(shù)增加他們的準(zhǔn)確度.我們也可以用cv2.drawChessboardCorners()來(lái)畫(huà)出模式,所有這些步驟用下面的代碼:

import numpy as np
import cv2
import glob

# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

images = glob.glob('*.jpg')

for fname in images:
? ? img = cv2.imread(fname)
? ? gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

? ? # Find the chess board corners
? ? ret, corners = cv2.findChessboardCorners(gray, (7,6),None)

? ? # If found, add object points, image points (after refining them)
? ? if ret == True:
? ? ? ? objpoints.append(objp)

? ? ? ? corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
? ? ? ? imgpoints.append(corners2)

? ? ? ? # Draw and display the corners
? ? ? ? img = cv2.drawChessboardCorners(img, (7,6), corners2,ret)
? ? ? ? cv2.imshow('img',img)
? ? ? ? cv2.waitKey(500)

cv2.destroyAllWindows()

一個(gè)畫(huà)了模式的圖像:


標(biāo)定

所以現(xiàn)在我們有了物體點(diǎn)拄踪,和圖像點(diǎn)蝇恶,我們可以標(biāo)定了。我們使用函數(shù)cv2.calibrateCamera()惶桐。它返回?cái)z像機(jī)矩陣艘包,畸變參數(shù)。旋轉(zhuǎn)和平移向量等耀盗。

ret,mtx,dist,rvecs,tvecs=cv2.calibrateCamera(objpoints,imgpoints,gray.shape[::-1],None,None)

反畸變

我們得到了我們要的,現(xiàn)在我們可以拿個(gè)圖像把它反畸變了卦尊。OpenCV提供了兩個(gè)方法叛拷,我們都看看,但是在此之前岂却,我們可以打磨一下攝像機(jī)矩陣忿薇,用一個(gè)cv2.getOptimalNewCameraMatrix()。如果參數(shù)alpha = 0, 它返回含有最小不需要像素的非扭曲圖像躏哩,所以它可能移除一些圖像角點(diǎn)署浩。如果alpha = 1, 所有像素都返回扫尺。

img=cv2.imread('left12.jpg')
h,w=img.shape[:2]
newcameramtx,roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))

1. 使用cv2.undistort()

這是個(gè)捷徑筋栋。只用調(diào)用函數(shù),使用ROI

# undistort
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)

# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png', dst)

2.使用重測(cè)圖

這是曲線救國(guó)正驻,首先找到從扭曲圖像到非扭曲圖像的映射函數(shù)弊攘。然后使用重測(cè)函數(shù)。

# undistort
mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx,(w,h), 5)
dst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)

# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png', dst)

兩個(gè)方法都返回同樣的結(jié)果姑曙〗蠼唬看下面:

你可以看到在結(jié)果里所有的邊都是直的

現(xiàn)在你可以把攝像機(jī)矩陣和畸變參數(shù)存下來(lái),使用Numpy的寫(xiě)函數(shù)(np.savez, np.savetxt等)伤靠,為以后使用

重投影差

重投影差給了找到的參數(shù)是否準(zhǔn)確的一個(gè)好的估計(jì)捣域。這個(gè)應(yīng)該越接近0越好。對(duì)于內(nèi)在的宴合,扭曲的焕梅,旋轉(zhuǎn)和平移矩陣,我們首先用cv2.projectPoints()轉(zhuǎn)換物體點(diǎn)到圖像點(diǎn)形纺,然后我們計(jì)算轉(zhuǎn)換和找角點(diǎn)算法之間的絕對(duì)范數(shù)丘侠。要找到平均差我們計(jì)算所有校對(duì)圖像的算術(shù)平均值。

mean_error = 0
for i in xrange(len(objpoints)):
? ? imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
? ? error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2)/len(imgpoints2)
? ? tot_error += error
? ? print "total error: ", mean_error/len(objpoints)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末逐样,一起剝皮案震驚了整個(gè)濱河市蜗字,隨后出現(xiàn)的幾起案子打肝,更是在濱河造成了極大的恐慌,老刑警劉巖挪捕,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粗梭,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡级零,警方通過(guò)查閱死者的電腦和手機(jī)断医,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)奏纪,“玉大人鉴嗤,你說(shuō)我怎么就攤上這事⌒虻鳎” “怎么了醉锅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)发绢。 經(jīng)常有香客問(wèn)我硬耍,道長(zhǎng),這世上最難降的妖魔是什么边酒? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任经柴,我火速辦了婚禮,結(jié)果婚禮上墩朦,老公的妹妹穿的比我還像新娘坯认。我一直安慰自己,他們只是感情好介杆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布鹃操。 她就那樣靜靜地躺著,像睡著了一般春哨。 火紅的嫁衣襯著肌膚如雪荆隘。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天赴背,我揣著相機(jī)與錄音椰拒,去河邊找鬼。 笑死凰荚,一個(gè)胖子當(dāng)著我的面吹牛燃观,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播便瑟,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼缆毁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了到涂?” 一聲冷哼從身側(cè)響起脊框,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤颁督,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后浇雹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體沉御,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年昭灵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吠裆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烂完,死狀恐怖试疙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抠蚣,我是刑警寧澤效斑,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站柱徙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏奇昙。R本人自食惡果不足惜护侮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望储耐。 院中可真熱鬧羊初,春花似錦、人聲如沸什湘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)闽撤。三九已至得哆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哟旗,已是汗流浹背贩据。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闸餐,地道東北人饱亮。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像舍沙,于是被迫代替她去往敵國(guó)和親近上。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容