溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

發(fā)布時(shí)間:2020-08-04 14:22:57 來(lái)源:億速云 閱讀:367 作者:小豬 欄目:開(kāi)發(fā)技術(shù)

小編這次要給大家分享的是Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定,文章內(nèi)容豐富,感興趣的小伙伴可以來(lái)了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。

相機(jī)標(biāo)定相機(jī)標(biāo)定的目的

獲取攝像機(jī)的內(nèi)參和外參矩陣(同時(shí)也會(huì)得到每一幅標(biāo)定圖像的選擇和平移矩陣),內(nèi)參和外參系數(shù)可以對(duì)之后相機(jī)拍攝的圖像就進(jìn)行矯正,得到畸變相對(duì)很小的圖像。

相機(jī)標(biāo)定的輸入

標(biāo)定圖像上所有內(nèi)角點(diǎn)的圖像坐標(biāo),標(biāo)定板圖像上所有內(nèi)角點(diǎn)的空間三維坐標(biāo)(一般情況下假定圖像位于Z=0平面上)。

相機(jī)標(biāo)定的輸出

攝像機(jī)的內(nèi)參、外參系數(shù)。

拍攝的物體都處于三維世界坐標(biāo)系中,而相機(jī)拍攝時(shí)鏡頭看到的是三維相機(jī)坐標(biāo)系,成像時(shí)三維相機(jī)坐標(biāo)系向二維圖像坐標(biāo)系轉(zhuǎn)換。不同的鏡頭成像時(shí)的轉(zhuǎn)換矩陣不同,同時(shí)可能引入失真,標(biāo)定的作用是近似地估算出轉(zhuǎn)換矩陣和失真系數(shù)。為了估算,需要知道若干點(diǎn)的三維世界坐標(biāo)系中的坐標(biāo)和二維圖像坐標(biāo)系中的坐標(biāo),也就是拍攝棋盤的意義。

相機(jī)成像

相機(jī)的成像原理:小孔成像

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

相機(jī)的內(nèi)參相機(jī)的外參

在實(shí)際由于設(shè)計(jì)工藝問(wèn)題、相機(jī)安裝環(huán)境或物體擺放位置等影響,會(huì)照成成像與實(shí)際圖像不一樣的現(xiàn)象。

由于設(shè)計(jì)工藝照成的影響是無(wú)法改變的事實(shí),所以這將是相機(jī)的內(nèi)參;

由環(huán)境或安裝方式照成的影響是可以改變的,這就是相機(jī)的外參。

張正友標(biāo)定相機(jī)原理

    1.求得相機(jī)內(nèi)參數(shù):

      用于標(biāo)定的棋盤格是特制的,其角點(diǎn)坐標(biāo)已知。標(biāo)定棋盤格是三維場(chǎng)景中的一個(gè)平面∏,棋盤格在成像平面為π(知道了∏與π的對(duì)應(yīng)點(diǎn)坐標(biāo)之后,可求解兩個(gè)平面1對(duì)應(yīng)的單應(yīng)矩陣H)。

根據(jù)相機(jī)成像模型,P為標(biāo)定的棋盤坐標(biāo),p為其像素點(diǎn)坐標(biāo)。則Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定,通過(guò)對(duì)應(yīng)的點(diǎn)坐標(biāo)求解H后,可用于求K,R,T。

    2.設(shè)棋盤格所在平面為世界坐標(biāo)系上XOY平面,則棋盤格上任一角點(diǎn)P世界坐標(biāo)系為(X,Y,0)。

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

    3、內(nèi)參約束條件

      Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

      Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

實(shí)驗(yàn)步驟打印棋盤圖片(網(wǎng)上找一張)

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

將打印出的紙固定放到一個(gè)平面上,使用同一相機(jī)從不同的位置,不同的角度,拍攝標(biāo)定板的多張照片(我拍了15張)手機(jī)型號(hào)是華為mate9

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

提取標(biāo)定板的世界坐標(biāo)

標(biāo)定板的大小是標(biāo)定板在水平和豎直方向上內(nèi)角點(diǎn)的個(gè)數(shù)。內(nèi)角點(diǎn)指的是,標(biāo)定板上不挨著邊界的角點(diǎn)。

我打印的是6x9的標(biāo)定板。

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

標(biāo)定相機(jī)

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定

mtx -->內(nèi)參數(shù)矩陣

dist --> 畸變系數(shù)

rvecs --> 旋轉(zhuǎn)向量

tvecs --> 平移向量

我們可以通過(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)定圖像的平均誤差即反投影誤差

我的棋盤打印出來(lái)有些不平整,可能是打印的紙張沒(méi)有放正,導(dǎo)致有些地方翹著,效果不是很好,誤差值有些大了,把紙張貼平整應(yīng)該會(huì)好很多。而且我可能拍照的角度變化不是太大,可以試著把拍照的角度更加差異些,結(jié)果會(huì)更明顯。

import cv2
import numpy as np
import glob
# 設(shè)置尋找亞像素角點(diǎn)的參數(shù),采用的停止準(zhǔn)則是最大循環(huán)次數(shù)30和最大誤差容限0.001
criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)
# 獲取標(biāo)定板角點(diǎn)的位置
objp = np.zeros((6 * 9, 3), np.float32)
objp[:, :2] = np.mgrid[0:9, 0:6].T.reshape(-1, 2) # 將世界坐標(biāo)系建在標(biāo)定板上,所有點(diǎn)的Z坐標(biāo)全部為0,所以只需要賦值x和y
obj_points = [] # 存儲(chǔ)3D點(diǎn)
img_points = [] # 存儲(chǔ)2D點(diǎn)
images = glob.glob("E:/test_pic/qipan/*.jpg")
for fname in images:
  img = cv2.imread(fname)
  cv2.imshow('img',img)
  gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  size = gray.shape[::-1]
  ret, corners = cv2.findChessboardCorners(gray, (6, 9), None)
  print(ret)
  if ret:
    obj_points.append(objp)
    corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria) # 在原角點(diǎn)的基礎(chǔ)上尋找亞像素角點(diǎn)
    #print(corners2)
    if [corners2]:
      img_points.append(corners2)
    else:
      img_points.append(corners)

    cv2.drawChessboardCorners(img, (8, 6), corners, ret) # 記住,OpenCV的繪制函數(shù)一般無(wú)返回值
    cv2.imshow('img', img)
    cv2.waitKey(2000)
print(len(img_points))
cv2.destroyAllWindows()
# 標(biāo)定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)
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ù)
print("-----------------------------------------------------")

看完這篇關(guān)于Python opencv如何實(shí)現(xiàn)相機(jī)標(biāo)定的文章,如果覺(jué)得文章內(nèi)容寫得不錯(cuò)的話,可以把它分享出去給更多人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI