日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

OpenCV 相机校正过程中,calibrateCamera函数projectPoints函数的重投影误差的分析

發(fā)布時(shí)間:2023/11/27 生活经验 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV 相机校正过程中,calibrateCamera函数projectPoints函数的重投影误差的分析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

OpenCV 校正過程中,calibrateCamera函數(shù)的ret和重投影誤差的分析

OpenCV對(duì)相機(jī)進(jìn)行校正的過程中,校正返回值retval和重投影誤差的計(jì)算公式表示和分析。

  • OpenCV 校正過程中,calibrateCamera函數(shù)的ret和重投影誤差的分析
  • 一、前言
  • 二、calibrateCamera( )函數(shù)分析
  • 三、projectPoints()函數(shù)分析
  • 四、具體實(shí)驗(yàn)和算法對(duì)比
  • 五、參考附錄


一、前言

本文主要是講解Python利用OpenCV進(jìn)行相機(jī)校正過程中,幾個(gè)重點(diǎn)參數(shù)的分析。標(biāo)定的過程就不再一一贅述了,很多博客和網(wǎng)站都在講解怎么進(jìn)行標(biāo)定。本文章主要分析,標(biāo)定過程中的誤差計(jì)算公式,和對(duì)calibrateCamera( )projectPoints( ) 兩個(gè)函數(shù)得到的誤差不同的原因進(jìn)行分析。

本文重點(diǎn)分析重投影誤差的計(jì)算方式。準(zhǔn)確描述OpenCV自帶的函數(shù),和各個(gè)文檔,教程里面所說的重投影誤差計(jì)算的流程進(jìn)行分析和對(duì)比,描述官方的重投影誤差和教程實(shí)現(xiàn)重投影誤差的差別。 我認(rèn)為OpenCV官方和其他大多數(shù)地方的教程,給的重新計(jì)算重投影誤差的結(jié)果,其計(jì)算的表達(dá)式,也是不準(zhǔn)確的。

正確的方法是相機(jī)校正的方法輸出的重投影誤差ret。使用的是RMS均方根誤差。另外教程和博客,給的是MSE均方誤差

二、calibrateCamera( )函數(shù)分析

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(x_world, y_voltage, (224, 224), None, None)

這里,ret表示的是重投影誤差;mtx是相機(jī)的內(nèi)參矩陣;dist表述的相機(jī)畸變參數(shù);rvecs表示標(biāo)定棋盤格世界坐標(biāo)系到相機(jī)坐標(biāo)系的旋轉(zhuǎn)參數(shù):rotation vectors,需要進(jìn)行羅德里格斯轉(zhuǎn)換;tvecs表示translation vectors,主要是平移參數(shù)。
其他幾個(gè)參數(shù),OpenCV的官網(wǎng)都進(jìn)行了仔細(xì)分析,在這個(gè)網(wǎng)站上去仔細(xì)的看,每個(gè)參數(shù)對(duì)應(yīng)的數(shù)學(xué)公式。https://docs.opencv.org/3.4/dc/dbb/tutorial_py_calibration.html

主要分析ret這個(gè)值,也就是retval,這個(gè)是重投影誤差。

import numpy as np
import cv2 as 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, cv.COLOR_BGR2GRAY)# Find the chess board cornersret, 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(corners)# Draw and display the cornerscv2.drawChessboardCorners(img, (7,6), corners2, ret)cv2.imshow('img', img)cv2.waitKey(500)
cv2.destroyAllWindows()# Calibration, Now that we have our object points and image points, we are ready to go for 
# calibration. We can use the function, cv.calibrateCamera() which returns the camera matrix, 
# distortion coefficients, rotation and translation vectors etc.
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
print("ret:", ret)
print("Camera matrix : \n")
print(mtx)
print("dist : \n")
print(dist)
print("rvecs : \n")
print(rvecs)
print("tvecs : \n")
print(tvecs)

其中,這個(gè)ret也就是retval,表示的是重投影誤差,是算法自動(dòng)返回的,其表達(dá)式為:
Reppointsx′=k[R∣T]X.Reppoints \ x'= k [R|T]X \,. Reppoints?x=k[RT]X.
其中,Reppoints x’是[Nx2],表示的圖像像素平面的2維坐標(biāo)點(diǎn),X是[Nx3]表示的3D世界坐標(biāo)系下的3維坐標(biāo)點(diǎn)。也就是棋盤格所構(gòu)造的3D坐標(biāo)系的大小。
ret=repro_error=∣∣x′?x∣∣22total_points=∣∣x′?x∣∣2total_pointsret =repro \_error =\sqrt{\frac{ ||x'-x||_{2}^2}{total\_points}}={\frac{ ||x'-x||_{2}}{\sqrt{total\_points}}} ret=repro_error=total_pointsx?x22???=total_points?x?x2??
這就是cv2.calibrateCamera()返回的值中,ret也就是重投影誤差的計(jì)算公式。求的是RMS均方根誤差,對(duì)所有的點(diǎn),求二范數(shù),然后求平均再開根號(hào),得到RMS誤差。

其中,二范數(shù)用的是:cv2.norm(data1, data2, cv2.NORM_L2)計(jì)算得到:
norm(x,x′)=∣∣x?x′∣∣2=∣∣x?x′∣∣22=(x1?x1′)2+...+(xn?xn′)2norm(x,x')=||x-x'||_2=\sqrt{|| x-x'||_{2}^2}=\sqrt{(x_1-x'_1)^2+...+(x_n-x'_n)^2} norm(x,x)=x?x2?=x?x22??=(x1??x1?)2+...+(xn??xn?)2?

三、projectPoints()函數(shù)分析

imgpoints2, _ = cv.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
  1. 原始的計(jì)算方法,大多數(shù)教程和博客,以及OpenCV文檔,給出的重投影誤差計(jì)算方法。

對(duì)相機(jī)標(biāo)定得到的參數(shù),帶回原始的投影公式,重新計(jì)算從3D世界坐標(biāo)系投影到2D圖像平面坐標(biāo)系的新的圖像像素值,然后計(jì)算重投影誤差。其中,objpoints表示世界坐標(biāo)系的坐標(biāo),也就是棋盤格的坐標(biāo)系,rvecs,tvecs,mtx,dist就是相機(jī)標(biāo)定得到的那些參數(shù)。

mean_error = 0
for i in range(len(objpoints)):imgpoints2, _ = cv.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)error = cv.norm(imgpoints[i], imgpoints2, cv.NORM_L2)/len(imgpoints2)mean_error += error
print( "total error: {}".format(mean_error/len(objpoints)) )

這里計(jì)算誤差的方式,我們將得到的值和上面相機(jī)校正返回的值ret,不一樣。因此,需要考慮,將這個(gè)官方給定的計(jì)算方式,進(jìn)行重新計(jì)算。如果你不在意準(zhǔn)確的值,就不用進(jìn)行優(yōu)化。

本文是準(zhǔn)確的探索,重投影誤差的計(jì)算方式。按照上面的算法流程,我們可以得到以下的計(jì)算重投影誤差的公式:
repro_error=∣∣x′?x∣∣2total_pointsrepro\_error={\frac{ {||x'-x||_{2}}}{total\_points}} repro_error=total_pointsx?x2??
很明顯,均方誤差的計(jì)算,按照上述的表達(dá)式,是不準(zhǔn)確的。誤差開根號(hào),然后除以點(diǎn)數(shù)多少,只能說是每個(gè)點(diǎn)的平均歐式誤差。MSE誤差。

  1. 校正之后的重投影誤差計(jì)算方法或者代碼。

因此,需要求得準(zhǔn)確的均方根誤差,我們應(yīng)該是先求平方,求平均,在開根號(hào)。因此,需要將代碼改為:

mean_error = 0
for i in range(len(objpoints)):imgpoints2, _ = cv.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)error = cv.norm(imgpoints[i], imgpoints2, cv.NORM_L2)total_error += error*error
print( "rms error: {}".format(np.sqrt(total_error/(len(objpoints)*len(imgpoints2))))

上述的流程才是:
repro_error=(∣∣x?x′∣∣22total_pointsrepro\_error=\sqrt{\frac{(||x-x'||_2^2}{total\_points}} repro_error=total_points(x?x22???

  • 與我們的cv2.calibrateCamera()返回的值是一樣的。

四、具體實(shí)驗(yàn)和算法對(duì)比

  1. 相機(jī)校正返回的值

  2. 函數(shù)的返回值
    其中的返回的誤差項(xiàng),真實(shí)值:ret 為 ret: 0.008683449668964258

  3. 使用大多數(shù)教程和博客的算法來計(jì)算的誤差值,是有差別的:

  4. 參考代碼給出的輸出誤差結(jié)果
    total error: 0.0018512112930950482

  5. 按照自己修正的代碼,來進(jìn)行重投影誤差計(jì)算:

    輸出的重投影誤差為:total error: 0.008683459017710442

因此,和我們相機(jī)校正輸出的=重投影誤差是一樣的。

五、參考附錄

下面是原始C++函數(shù),計(jì)算重投影誤差的流程,我上面的公式就是按照這個(gè)算法來解釋的:

static double computeReprojectionErrors(const vector<vector<Point3f> >& objectPoints,const vector<vector<Point2f> >& imagePoints,const vector<Mat>& rvecs, const vector<Mat>& tvecs,const Mat& cameraMatrix, const Mat& distCoeffs,vector<float>& perViewErrors )
{vector<Point2f> imagePoints2;int i, totalPoints = 0;double totalErr = 0, err;perViewErrors.resize(objectPoints.size());for( i = 0; i < (int)objectPoints.size(); i++ ){projectPoints(Mat(objectPoints[i]), rvecs[i], tvecs[i],cameraMatrix, distCoeffs, imagePoints2);err = norm(Mat(imagePoints[i]), Mat(imagePoints2), NORM_L2);int n = (int)objectPoints[i].size();perViewErrors[i] = (float)std::sqrt(err*err/n);totalErr += err*err;totalPoints += n;}return std::sqrt(totalErr/totalPoints);
}

需要準(zhǔn)確描述如何計(jì)算重投影誤差的同學(xué),需要仔細(xì)修改你的代碼,因?yàn)镽MS誤差來描述的,是需要求平方差,然后求平均,再求平方根。

正確的方法是相機(jī)校正的方法輸出的重投影誤差,而不是大多數(shù),包括OpenCV官方,給出的,都是不一樣的,或者是不準(zhǔn)確的重投影誤差的計(jì)算函數(shù)。

參考網(wǎng)站:

  1. https://stackoverflow.com/questions/29628445/meaning-of-the-retval-return-value-in-cv2-calibratecamera
  2. https://docs.opencv.org/master/dc/dbb/tutorial_py_calibration.html

如果有用,記得點(diǎn)贊👍加收藏哦。!!!!

總結(jié)

以上是生活随笔為你收集整理的OpenCV 相机校正过程中,calibrateCamera函数projectPoints函数的重投影误差的分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。