【相機(jī)標(biāo)定+測(cè)距+動(dòng)手設(shè)計(jì)】用matlab標(biāo)定攝像機(jī)以后,用python在標(biāo)定平面內(nèi)建立世界坐標(biāo)系并測(cè)距
點(diǎn)擊下方卡片,關(guān)注“新機(jī)器視覺(jué)”公眾號(hào)
視覺(jué)/圖像重磅干貨,第一時(shí)間送達(dá)
您需要的基礎(chǔ)知識(shí):1.相機(jī)成像原理2.計(jì)算機(jī)標(biāo)定3.Matlab python編程基礎(chǔ)
先給大家看看總目錄
1.1任務(wù)要求 1.2任務(wù)分析
2.1相機(jī)的成像原理
2.2深度的測(cè)量原理
3.1硬件部分設(shè)計(jì)
3.1.1標(biāo)定板的制作
3.1.2標(biāo)定圖像的制作
3.2軟件部分設(shè)計(jì)
3.2.1程序總流程圖設(shè)計(jì)
3.2.2拍攝圖像部分流程圖設(shè)計(jì)
3.2.3相機(jī)標(biāo)定的流程圖設(shè)計(jì)
3.2.4測(cè)量的流程圖設(shè)計(jì)
3.2.5計(jì)算距離的流程圖設(shè)計(jì)
3.3部分重要代碼分析
3.3.1拍攝部分
3.3.2相機(jī)內(nèi)參標(biāo)定部分
3.3.3測(cè)量部分
4.1程序運(yùn)行結(jié)果
4.1.1拍攝部分
4.1.2相機(jī)標(biāo)定部分
4.1.3測(cè)量部分:
4.2結(jié)果分析
4.2.1相機(jī)部分
4.2.2標(biāo)定部分
4.2.3測(cè)量部分
4.3總結(jié)
5.1相機(jī)拍照部分代碼
5.2相機(jī)標(biāo)定部分代碼
5.3測(cè)量部分代碼
一、設(shè)計(jì)任務(wù)
1.1 任務(wù)要求
攝像機(jī)標(biāo)定使用自制標(biāo)定板,使用工業(yè)攝像機(jī)或手機(jī)攝像頭進(jìn)行標(biāo)定。將標(biāo)定的攝像機(jī)內(nèi)參和外參進(jìn)行保存。設(shè)計(jì)測(cè)量方案,使用標(biāo)定過(guò)的攝像機(jī)對(duì)包含垂直邊緣的物品(直尺刻度線,矩形物體邊緣等)進(jìn)行距離或邊長(zhǎng)的測(cè)量。標(biāo)定過(guò)程和測(cè)量過(guò)程,均需要保持?jǐn)z像機(jī)與測(cè)量平面之間的距離固定,物品高度不能過(guò)高,否則影響測(cè)量結(jié)果。完成以下設(shè)計(jì)任務(wù):
系統(tǒng)整體方案設(shè)計(jì),包括
結(jié)合Halcon(或open CV)軟件,寫(xiě)出各功能模塊的實(shí)現(xiàn)及相應(yīng)的代碼。
1. 標(biāo)定板制作
2. 攝像機(jī)標(biāo)定
3. 對(duì)設(shè)計(jì)方案中垂直于測(cè)量矩形框的直邊進(jìn)行提取,并測(cè)量直邊之間的距離,從而得到平面測(cè)量對(duì)象的尺寸
4. 對(duì)測(cè)量值與實(shí)際尺寸誤差進(jìn)行一定的分析和改進(jìn)5. 多次測(cè)量,計(jì)算出測(cè)量的平均值和標(biāo)準(zhǔn)差
本次任務(wù)主程序可以分為三塊:相機(jī)拍攝,相機(jī)標(biāo)定,測(cè)量三大塊。
其中,相機(jī)拍攝為相機(jī)標(biāo)定主要任務(wù),是獲取圖像,存儲(chǔ)的是圖像的參數(shù);
相機(jī)標(biāo)定的主要任務(wù)是獲取相機(jī)的內(nèi)參;
在測(cè)量里面,我們需要用
標(biāo)定板來(lái)確定相機(jī)的外參,
然后由于我們?cè)跍y(cè)量圖像外參的時(shí)候,
默認(rèn)將標(biāo)定板作為參考坐標(biāo)系,
所以只要將相機(jī)成像平面中的點(diǎn)投影到Z=0時(shí)的成像平面就可以了。
大致方案如下所示:

二、設(shè)計(jì)原理
2.1 相機(jī)成像原理
我們熟知的攝像機(jī)是由光線透過(guò)透鏡折射,反射到成像平面形成的,
本質(zhì)是利用二維圖像獲取三維信息的過(guò)程。
所以我們可以通過(guò)成像的狀況來(lái)反映三維世界中的信息。

但是,現(xiàn)實(shí)模型總會(huì)與理想模型存在一些偏差,
這里的偏差主要就是相機(jī)內(nèi)參與畸變系數(shù)所導(dǎo)致的。
由于每一個(gè)相機(jī)都是利用的透鏡成像原理,所以很容易產(chǎn)生桶形畸變或者是枕形畸變。
所以一個(gè)三維的圖像到OpenCV顯示的畫(huà)面需要經(jīng)歷三個(gè)變化,這三個(gè)變化對(duì)應(yīng)的參數(shù)分別是相機(jī)位姿參數(shù),畸變技術(shù),相機(jī)內(nèi)參。
具體的內(nèi)容,請(qǐng)參看我之前的推文:
相機(jī)標(biāo)定究竟在標(biāo)定什么???
2.2 深度的測(cè)量原理
這里我使用的是一個(gè)單目攝像機(jī)。
如果不移動(dòng)相機(jī),我們是無(wú)法獲取三維平面內(nèi)的尺度信息和深度信息的。
但是我們可以獲取三維平面內(nèi)的比例關(guān)系。
這時(shí)候我們需要知道更多的參數(shù)。在這次的任務(wù)里面,我們需要的參數(shù)有兩個(gè):
一個(gè)是相機(jī)的位姿參數(shù),一個(gè)是成像平面。
知道了這兩個(gè)參數(shù),我們就可以將攝像機(jī)內(nèi)二維平面內(nèi)的點(diǎn)投射到三維的坐標(biāo)中去,再利用三維坐標(biāo)輕松算出點(diǎn)與點(diǎn)之間的距離。
默認(rèn)將世界坐標(biāo)系的原點(diǎn)放在標(biāo)定板第一個(gè)角點(diǎn)上。
所以,我們只需要將成像平面設(shè)置為Z=0,即XOY面就可以了,這時(shí)我們便獲得了需要計(jì)算深度信息的所有參數(shù)。
三、方案整理及各個(gè)功能模塊的設(shè)計(jì)
3.1 硬件部分設(shè)計(jì)
3.1.1標(biāo)定板的制作
可能大家不知道Matlab還可以制作標(biāo)定板吧
cb=(checkerboard(300,4,5)>0.5);figure,imshow(cb);
得到的標(biāo)定板如下:

將其打印下來(lái),或者放在ipad/pc上,
(這個(gè)時(shí)候要知道ipad和電腦的尺寸)
3.1.2 標(biāo)定圖像的制作
為了方便測(cè)量,我選用了一個(gè)紅色的長(zhǎng)方形來(lái)做測(cè)量的模塊。如下圖所示:

實(shí)際長(zhǎng)度在118.4-118.5毫米。
3.2 軟件部分
3.2.1 程序總流程圖設(shè)計(jì)

3.2.2 相機(jī)標(biāo)定流程

相機(jī)標(biāo)定主要是對(duì)棋盤(pán)角點(diǎn)的尋找,然后再儲(chǔ)存角點(diǎn),
(這里就需要角點(diǎn)檢測(cè)的知識(shí),如果不太懂,大家可以去百度一下)
如果儲(chǔ)存到了足夠多的角點(diǎn)的話,就退出程序的循環(huán),進(jìn)行標(biāo)定。
3.2.3 計(jì)算距離流程
之前為什么要用紅色物體作為被測(cè)物體
是因?yàn)榧t色在HSV模式下更容易被分離出來(lái)

3.3 重要代碼部分
拍攝部分
if key == ord('s'):cv.imwrite(filepath +img_name + str(a)+'.png',frame) # 按s截取圖像a = a + 1 # 改變截取圖像的名稱if key == ord('q'):break # 如果檢測(cè)到按鍵為esc,就退出攝像
相機(jī)參數(shù)標(biāo)定部分
ret, corners = cv2.findChessboardCorners(gray, (7, 5), None)# 如果找出角點(diǎn),把角點(diǎn)加入坐標(biāo)系內(nèi)if ret == True:objpoints.append(objp * 30)# 參照criteria進(jìn)行亞像素檢驗(yàn)corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)imgpoints.append(corners2)# 將角點(diǎn)顯示出來(lái)img = cv2.drawChessboardCorners(img, (7, 5), corners2, ret)cv2.imwrite(sys.path[0] + "/標(biāo)定結(jié)果/" + "result" + str(a) + ".png", img)a = a + 1
findChessboardCorners是一個(gè)檢測(cè)標(biāo)定板角點(diǎn)的函數(shù),
如果檢測(cè)到了角點(diǎn),
就以criteria的規(guī)則進(jìn)行亞像素檢驗(yàn),
然后再將所有的角點(diǎn)儲(chǔ)存下來(lái),
將檢測(cè)到的角點(diǎn)顯示并且將顯示角點(diǎn)的圖像保存下來(lái)。
測(cè)量部分
f Find:# 獲取更精確的角點(diǎn)位置(亞像素精度)exact_corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)# 獲取外參,其中rvec是旋轉(zhuǎn)矩陣,tvec是平移矩陣rvec, tvec, inliers = cv2.solvePnPRansac(world_point, exact_corners, IntrinsicMatrix, distC# 獲取兩個(gè)平面(像素平面與實(shí)際平面)的映射關(guān)系,其中RMat是相機(jī)平面到Z=0軸的投影Mat = cv2.findHomography(D_2_point, exact_corners)[0]RMat = cv2.findHomography(exact_corners, D_2_point)[0]# print(np.transpose(np.dot(Mat,[[24.575*3,0],[0,24.575*3],[1,1]])))# 這里打印的是一個(gè)投影的值# 根據(jù)3D坐標(biāo),獲取投影的二維坐標(biāo)jac = cv2.projectPoints(axis, rvec, tvec, IntrinsicMatrix, distCoeffs)# 可視化角點(diǎn),畫(huà)出圖像img = draw(image, corners, imgpts)# cv2.imshow('img', img)return [Mat, RMat, corners, imgpts]
同樣的,這里依然進(jìn)行攝像機(jī)標(biāo)定,
不過(guò)這里進(jìn)行的是攝像機(jī)外參的標(biāo)定,
通過(guò)投影的方法找到相機(jī)的內(nèi)參和外參,
再返回一個(gè)相機(jī)位姿矩陣。
contours, hierarchy = cv2.findContours(image_2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)for contour in contours:arclength = cv2.arcLength(contour, True)# print(arclength)a.append(arclength) # 長(zhǎng)度保存在數(shù)組中maxlen = max(a)for contour in contours:arclength = cv2.arcLength(contour, True)if arclength == maxlen:dot = cv2.approxPolyDP(contour,5,True)dot = np.int0(dot)cv2.drawContours(image, [dot], 0, (0, 0, 0), 1)
用HSV參數(shù)進(jìn)行閾值化處理后,findContours作用是找出目標(biāo)物體的外輪廓,返回的contour是輪廓的點(diǎn)集。
考慮到在圖像里面會(huì)有很多干擾點(diǎn),所以我們要將最大的輪廓給過(guò)濾出來(lái)。approxPolyDP表示的是多邊形擬合,在這個(gè)函數(shù)中,返回的是圖像中四邊形的四個(gè)角點(diǎn)。
根據(jù)圖像里面返回的四個(gè)角點(diǎn),以及相機(jī)位姿及其內(nèi)參,三維空間里平面參數(shù),我們很容易將圖像的幾個(gè)點(diǎn)在三維空間里面描述出來(lái)。也就很容易知道四邊形對(duì)應(yīng)的矩形幾個(gè)邊的邊長(zhǎng)了。
四、結(jié)果展示和分析
拍出來(lái)以下的圖像以備相機(jī)內(nèi)參標(biāo)定:

拍出以下圖片準(zhǔn)備外參標(biāo)定:

拍出以下圖片準(zhǔn)備測(cè)量長(zhǎng)度:

MATLAB結(jié)合標(biāo)定出來(lái)的位姿,
用MATLAB作圖如下,一共選取了5張圖像作為標(biāo)定的圖像

得到的內(nèi)參矩陣:

畸變矩陣:

測(cè)量結(jié)果:

今天的教程就到這里為止了
—版權(quán)聲明—
僅用于學(xué)術(shù)分享,版權(quán)屬于原作者。
若有侵權(quán),請(qǐng)聯(lián)系微信號(hào):yiyang-sy 刪除或修改!
