1. カメラキャリブレーションの原理
1.1 カメラが画像を生成する仕組み:
カメラ画像系には、ワールド座標系、カメラ座標系、画像座標系、ピクセル座標系の合計 4 つの座標系が含まれます。
1.1.1 世界座標系:
世界座標系 (世界座標) は、測定座標系とも呼ばれ、カメラと測定対象の空間位置を記述することができる 3 次元の直交座標系です。世界座標系の位置は、実際の状況に応じて自由に決定できます。
1.1.2 カメラ座標系:
カメラ座標系も 3 次元直交座標系であり、原点はレンズの光学中心にあり、x 軸と y 軸はそれぞれ位相面の両側に平行です。 z 軸はレンズの光軸であり、画像と位置合わせされています 平面垂直
1.1.3 ピクセル座標系、画像座標系:
ピクセル座標系(ピクセル座標)
は上図の通りで、カメラのCCD/CMOSチップ内の画素の配置を反映した2次元の直交座標系です。原点は画像の左上隅にあり、軸と軸は画像平面の両側に平行です。ピクセル座標系における座標軸の単位はピクセル(整数)です。
ピクセル座標系は座標変換に適さないため、画像座標系を確立する必要があります。その座標軸の単位は通常ミリメートル (mm) です。原点はカメラの光軸と位相面 (と呼ばれる) の交点です。主点)、これは画像の中心点です。軸と軸はそれぞれ軸と軸に平行です。したがって、2 つの座標系は実際には並進関係にあり、これは並進によって取得できます。
1.2 カメラ キャリブレーションの目的:
カメラの内部パラメータと外部パラメータ、および歪みパラメータを見つけること。
カメラをキャリブレーションした後、通常は 2 つのことを行う必要があります: 1 つは、各レンズの歪みの程度が異なるため、カメラ キャリブレーションによってレンズの歪みを補正し、補正された画像を生成すること、もう 1 つは、レンズの歪みに基づいて画像を再構成することです。得られた画像から 3 次元シーンを構築します。
1.2 カメラ キャリブレーションの全体原理:
カメラ キャリブレーション (カメラ キャリブレーション) は、単純に世界座標系から画像座標系に変更するプロセスであり、最終的な投影行列を見つけるプロセスです。
2. カメラのキャリブレーション手順
1) 張正佑の校正方法用のチェッカーボードを準備します。チェッカーボードのサイズは既知であり、カメラを使用してさまざまな角度から撮影して一連の画像を取得します。
2) 画像中のキャリブレーションボードの角点などの特徴点を検出して、キャリブレーションボードの角点のピクセル座標を取得し、既知のチェッカーボードのサイズと世界座標系の原点に基づいて、物理的な座標を計算します。 ; キャリブレーションボードの角点の座標。
3) 内部パラメータ行列と外部パラメータ行列を解きます。
物理座標値とピクセル座標値の関係に従って、H 行列を計算し、次に V 行列を構築し、B 行列を解き、B 行列を使用してカメラの内部パラメータ行列 A を解き、最後にカメラの外部パラメータを解きます。各画像に対応するパラメータ行列:
4) 歪みパラメータを求めます。
D マトリックスを構築し、放射状歪みパラメータを計算します。
5) LM (Levenberg-Marquardt) アルゴリズムを使用して上記のパラメーターを最適化します。
3.
3.1 データ準備の実装
さまざまな角度でキャリブレーション プレートの写真を撮り、10 枚の写真を取得します。次のような画像を取得します。
3.2 コード (Python+OpenCV)
import cv2
import numpy as np
import glob
# 设置寻找亚像素角点的参数,采用的停止准则是最大循环次数30和最大误差容限0.001
criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)
# 获取标定板角点的位置
objp = np.zeros((4 * 4, 3), np.float32)
objp[:, :2] = np.mgrid[0:4, 0:4].T.reshape(-1, 2) # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y
obj_points = [] # 存储3D点
img_points = [] # 存储2D点
images = glob.glob(r"D:\software\pycharm\PycharmProjects\computer-version\biaoding\images\*.jpg")
i = 0
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
size = gray.shape[::-1]
ret, corners = cv2.findChessboardCorners(gray, (4, 4), None)
# print(corners)
if ret:
obj_points.append(objp)
corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria) # 在原角点的基础上寻找亚像素角点
# print(corners2)
if [corners2]:
img_points.append(corners2)
else:
img_points.append(corners)
cv2.drawChessboardCorners(img, (4, 4), corners, ret) # 记住,OpenCV的绘制函数一般无返回值
i += 1
cv2.imwrite('conimg' + str(i) + '.jpg', img)
cv2.waitKey(1500)
print(len(img_points))
cv2.destroyAllWindows()
# 标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)
print("内参数矩阵:\n", mtx) # 内参数矩阵
print("畸变系数:\n", dist) # 畸变系数 distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print("旋转向量:\n", rvecs) # 旋转向量 # 外参数
print("平移向量:\n", tvecs) # 平移向量 # 外参数
print("-----------------------------------------------------")
img = cv2.imread(images[2])
h, w = img.shape[:2]
# 获取新的相机矩阵和ROI
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))
# 进行畸变校正
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
# 裁剪校正后的图片,去掉黑边
x, y, w, h = roi
dst = dst[y:y + h, x:x + w]
# 保存校正后的图片
cv2.imwrite('undistorted.jpg', dst)
print("校正后的图片已保存到文件 'undistorted.jpg'")
結果は次のとおりです。
D:\software\anaconda3\envs\homework\python.exe D:\software\pycharm\PycharmProjects\computer-version\biaoding\biaoding.py
10
内参数矩阵:
[[2.96560599e+04 0.00000000e+00 1.14649373e+03]
[0.00000000e+00 2.27193976e+04 2.23086118e+03]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]]
畸变系数:
[[-2.89172774e+00 -7.08266723e+02 -8.71069820e-02 9.23282091e-03
2.69077473e+04]]
旋转向量:
(array([[ 0.00393121],
[-0.55572922],
[ 0.00146949]]), array([[-0.24713914],
[-0.62161368],
[ 1.12164248]]), array([[0.03655035],
[0.72426273],
[0.58207192]]), array([[ 0.03267646],
[-0.81493845],
[ 0.33111165]]), array([[ 0.10136185],
[-0.8188412 ],
[ 0.0126507 ]]), array([[ 0.07815116],
[-0.45667052],
[ 0.04574239]]), array([[-0.06538785],
[-0.45146705],
[ 0.29559633]]), array([[0.19950015],
[0.59439631],
[1.05909245]]), array([[-0.61847323],
[-0.65382223],
[ 1.44780297]]), array([[-0.56075885],
[-0.65910126],
[ 1.21835979]]))
平移向量:
(array([[-1.88349377],
[-2.34826569],
[79.07381781]]), array([[-3.71964945e-03],
[-2.09696872e+00],
[ 9.57830776e+01]]), array([[ 2.82236969],
[-10.16609008],
[105.50710577]]), array([[ 2.4498244 ],
[ -9.91592803],
[113.69245822]]), array([[ 1.94032193],
[ -9.41660327],
[118.34213194]]), array([[ 3.29323168],
[-10.37799624],
[150.0005035 ]]), array([[ 1.90004234],
[ -9.89181093],
[136.81120801]]), array([[ 3.81109485],
[ -9.80118203],
[131.55206487]]), array([[ 0.12140321],
[ -3.0523607 ],
[114.3591686 ]]), array([[ 0.17173674],
[-2.75540486],
[80.26443015]]))
-----------------------------------------------------
校正后的图片已保存到文件 'undistorted.jpg'
Process finished with exit code 0
歪み補正前の画像:
歪み補正後の画像:
分析します:
プログラムを実行した後、携帯電話のパラメータを正常に校正し、カメラの内部パラメータと外部パラメータを計算しました。今回の実験を通じて、張正佑氏の校正法の素晴らしさがさらに分かりました。