OpenCV實(shí)現(xiàn)相機(jī)標(biāo)定
本文實(shí)例為大家分享了OpenCV實(shí)現(xiàn)相機(jī)標(biāo)定的具體代碼,供大家參考,具體內(nèi)容如下
一、相機(jī)與針孔相機(jī)模型
1.相機(jī)模型
現(xiàn)代科技加持下的相機(jī)已經(jīng)成為制造精密設(shè)計(jì)巧妙的消費(fèi)品,相機(jī)的光學(xué)結(jié)構(gòu)也比誕生之初復(fù)雜了許多
典型單反相機(jī)光學(xué)結(jié)構(gòu):

在眾多相機(jī)模型中,針孔相機(jī)又稱(chēng)投影相機(jī)模型是相對(duì)簡(jiǎn)單而常用的模型。簡(jiǎn)單的說(shuō),針孔相機(jī)模型就是把相機(jī)簡(jiǎn)化成單純的小孔成像,可想而知,這種簡(jiǎn)化對(duì)于精度要求高的情況或者特殊鏡頭的相機(jī)是不適用的。
小孔成像原理:

2.引入透鏡
單純的小孔成像模型中沒(méi)有考慮鏡頭,現(xiàn)實(shí)條件下,由一片或多片透鏡組成的鏡頭才能讓利用了小孔成像原理的相機(jī)成像清晰的同時(shí)保持畫(huà)面亮度。所以我們需要向模型引入透鏡。
透鏡成像原理:

但是,新的問(wèn)題也隨之而來(lái):虛焦、畸變
一般我們稱(chēng)之為徑向畸變,即光線(xiàn)在院里透鏡中的地方比靠近中心的地方更加彎曲。徑向畸變又分為中短焦距、近距離的桶形畸變和長(zhǎng)焦距、遠(yuǎn)距離會(huì)出現(xiàn)的枕形畸變。
二、相機(jī)參數(shù)
1.坐標(biāo)系約定
我們約定三個(gè)坐標(biāo)系
1、世界坐標(biāo)系矩陣:X
2、攝像機(jī)坐標(biāo)系:Xc,
3、圖像(像素)坐標(biāo)系:x
4、相機(jī)矩陣:P
2.像平面到像素平面的投影
將三維空間中一點(diǎn),過(guò)該點(diǎn)取一平面與像素平面平行,該平面就是像平面。設(shè)該三位點(diǎn)P,齊次坐標(biāo)為X。投影為圖像點(diǎn)P’,平面坐標(biāo)x。
針孔相機(jī)模型:

在針孔相機(jī)模型中,像素坐標(biāo)和像坐標(biāo)之間的關(guān)系:
λx = PX
其中,λ是三位點(diǎn)的逆深度。P為相機(jī)矩陣,可以分解為:
P = R[K|t]
R 是描述照相機(jī)方向的旋轉(zhuǎn)矩陣,t 是描述照相機(jī)中心位置的三維平移向量,內(nèi)標(biāo)定矩陣K 描述照相機(jī)的投影性質(zhì)。標(biāo)定矩陣僅和照相機(jī)自身的情況有關(guān),通??梢詫?xiě)成:

焦距f是像在平面到像素平面中心的距離。s是傾斜參數(shù),α是縱橫比例參數(shù)。
在像素?cái)?shù)組在傳感器上沒(méi)有偏斜且像素是正方形的時(shí)候,可以設(shè) s = 0,α = 1。標(biāo)定矩陣可以簡(jiǎn)化為:

三、相機(jī)標(biāo)定
實(shí)驗(yàn)圖片如下:

代碼如下:
import cv2
import numpy as np
import glob
# 找棋盤(pán)格角點(diǎn)
# 閾值
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
#棋盤(pán)格模板規(guī)格
w = 7 ? #內(nèi)角點(diǎn)個(gè)數(shù),內(nèi)角點(diǎn)是和其他格子連著的點(diǎn)
h = 7
# 世界坐標(biāo)系中的棋盤(pán)格點(diǎn),例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐標(biāo),記為二維矩陣
objp = np.zeros((w*h,3), np.float32)
objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2)
# 儲(chǔ)存棋盤(pán)格角點(diǎn)的世界坐標(biāo)和圖像坐標(biāo)對(duì)
objpoints = [] # 在世界坐標(biāo)系中的三維點(diǎn)
imgpoints = [] # 在圖像平面的二維點(diǎn)
images = glob.glob('picture/*.jpg')
for fname in images:
? ? img = cv2.imread(fname)
? ? gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
? ? # 找到棋盤(pán)格角點(diǎn)
? ? # 棋盤(pán)圖像(8位灰度或彩色圖像) ?棋盤(pán)尺寸 ?存放角點(diǎn)的位置
? ? ret, corners = cv2.findChessboardCorners(gray, (w,h),None)
? ? # 如果找到足夠點(diǎn)對(duì),將其存儲(chǔ)起來(lái)
? ? if ret == True:
? ? ? ? # 角點(diǎn)精確檢測(cè)
? ? ? ? # 輸入圖像 角點(diǎn)初始坐標(biāo) 搜索窗口為2*winsize+1 死區(qū) 求角點(diǎn)的迭代終止條件
? ? ? ? cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
? ? ? ? objpoints.append(objp)
? ? ? ? imgpoints.append(corners)
? ? ? ? # 將角點(diǎn)在圖像上顯示
? ? ? ? cv2.drawChessboardCorners(img, (w,h), corners, ret)
? ? ? ? cv2.imshow('findCorners',img)
? ? ? ? cv2.waitKey(1000)
cv2.destroyAllWindows()
#標(biāo)定、去畸變
# 輸入:世界坐標(biāo)系里的位置 像素坐標(biāo) 圖像的像素尺寸大小 3*3矩陣,相機(jī)內(nèi)參數(shù)矩陣 畸變矩陣
# 輸出:標(biāo)定結(jié)果 相機(jī)的內(nèi)參數(shù)矩陣 畸變系數(shù) 旋轉(zhuǎn)矩陣 平移向量
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
# mtx:內(nèi)參數(shù)矩陣
# dist:畸變系數(shù)
# rvecs:旋轉(zhuǎn)向量 (外參數(shù))
# tvecs :平移向量 (外參數(shù))
print (("ret:"),ret)
print (("mtx:\n"),mtx) ? ? ? ?# 內(nèi)參數(shù)矩陣
print (("dist:\n"),dist) ? ? ?# 畸變系數(shù) ? distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print (("rvecs:\n"),rvecs) ? ?# 旋轉(zhuǎn)向量 ?# 外參數(shù)
print (("tvecs:\n"),tvecs) ? ?# 平移向量 ?# 外參數(shù)
# 去畸變
img2 = cv2.imread('picture/6.jpg')
h,w = img2.shape[:2]
# 我們已經(jīng)得到了相機(jī)內(nèi)參和畸變系數(shù),在將圖像去畸變之前,
# 我們還可以使用cv.getOptimalNewCameraMatrix()優(yōu)化內(nèi)參數(shù)和畸變系數(shù),
# 通過(guò)設(shè)定自由自由比例因子alpha。當(dāng)alpha設(shè)為0的時(shí)候,
# 將會(huì)返回一個(gè)剪裁過(guò)的將去畸變后不想要的像素去掉的內(nèi)參數(shù)和畸變系數(shù);
# 當(dāng)alpha設(shè)為1的時(shí)候,將會(huì)返回一個(gè)包含額外黑色像素點(diǎn)的內(nèi)參數(shù)和畸變系數(shù),并返回一個(gè)ROI用于將其剪裁掉
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),0,(w,h)) # 自由比例參數(shù)
dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# 根據(jù)前面ROI區(qū)域裁剪圖片
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.jpg',dst)
# 反投影誤差
# 通過(guò)反投影誤差,我們可以來(lái)評(píng)估結(jié)果的好壞。越接近0,說(shuō)明結(jié)果越理想。
# 通過(guò)之前計(jì)算的內(nèi)參數(shù)矩陣、畸變系數(shù)、旋轉(zhuǎn)矩陣和平移向量,使用cv2.projectPoints()計(jì)算三維點(diǎn)到二維圖像的投影,
# 然后計(jì)算反投影得到的點(diǎn)與圖像上檢測(cè)到的點(diǎn)的誤差,最后計(jì)算一個(gè)對(duì)于所有標(biāo)定圖像的平均誤差,這個(gè)值就是反投影誤差。
total_error = 0
for i in range(len(objpoints)):
? ? imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
? ? error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
? ? total_error += error
print (("total error: "), total_error/len(objpoints))以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python實(shí)現(xiàn)bilibili時(shí)間長(zhǎng)度查詢(xún)的示例代碼
這篇文章主要介紹了Python實(shí)現(xiàn)bilibili時(shí)間長(zhǎng)度查詢(xún)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
python關(guān)于多值參數(shù)的實(shí)例詳解
在本篇內(nèi)容里小編給大家整理了一篇關(guān)于python關(guān)于多值參數(shù)的實(shí)例詳解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2021-07-07
使用python實(shí)現(xiàn)excel的Vlookup功能
這篇文章主要介紹了使用python實(shí)現(xiàn)excel的Vlookup功能,當(dāng)我們想要查找的數(shù)據(jù)量較大時(shí),這時(shí)則有請(qǐng)我們的主角VLookup函數(shù)出場(chǎng),那么如何用python實(shí)現(xiàn)VLookup呢,需要的朋友可以參考下2023-04-04
python實(shí)現(xiàn)自動(dòng)解數(shù)獨(dú)小程序
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)自動(dòng)解數(shù)獨(dú)小程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
Python實(shí)現(xiàn)多格式文本轉(zhuǎn)為word
在現(xiàn)代工作中,我們常常需要處理不同格式的文件,其中Word文檔是最為常見(jiàn)的一種,本文主要介紹了如何使用Python創(chuàng)建一個(gè)全能的文件處理工具,能夠?qū)⒍喾N格式的文件轉(zhuǎn)換為Word文檔,需要的可以參考下2023-11-11
Windows10下Tensorflow2.0 安裝及環(huán)境配置教程(圖文)
這篇文章主要介紹了Windows10下Tensorflow2.0 安裝及環(huán)境配置教程(圖文),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
python3安裝及pip3報(bào)ERROR:No?matching?distribution?found?for解
這篇文章主要給大家介紹了關(guān)于python3安裝及pip3報(bào)ERROR:No?matching?distribution?found?for解決的相關(guān)資料,文中通過(guò)代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08

