Python コンピューター ビジョン (4) - カメラのキャリブレーション

1. カメラキャリブレーションの原理

    カメラキャリブレーションの目的は、カメラ自体のパラメータを取得することであり、カメラがターゲット情報を正確に取得するには、適切なキャリブレーションパラメータが必要です。この記事では、Zhang Zhengyou のカメラキャリブレーション方法を紹介します。カメラ キャリブレーションのプロセスは、剛体変換を通じて世界座標系をカメラ座標系に変換し、次に投影変換を通じてカメラ座標系を画像座標系に変換し、最後に画像座標系をピクセル座標系に変換します。翻訳変換。カメラ撮影時の座標系変換関係を下図に示します。

座標系変換図

 2.張正佑カメラのキャリブレーション方法

    Zhang Zhengyou キャリブレーションとは、1998 年に Zhang Zhengyou 教授によって提案された単面チェッカーボード カメラのキャリブレーション方法を指します。この方法は、従来の校正方法と自己校正方法の中間に位置し、従来の校正方法で要求される高精度な校正対象物の欠点を克服するだけでなく、自己校正方法に比べて精度が向上し、操作が容易になります。校正方法。したがって、Zhang Zhengyou キャリブレーション方法はコンピューター ビジョンで広く使用されています。

Zhang Zhengyou 校正方法の一般的な手順:

1. 市松模様の A4 紙 (白と黒の間隔がわかっている) を印刷し、平らな板に貼り付けます。

2. チェッカーボード用の写真を数枚撮ります (通常は 10 ~ 20 枚)

3. 画像内の特徴点(ハリスの角)を検出します

4. コーナー位置情報と画像内の座標に従ってホモグラフィック行列を解きます。

5. 分析解推定法を使用して 5 つの内部パラメータと 6 つの外部パラメータを計算します

6. 最尤推定戦略に従って、最適化目標を設計し、パラメータの改良を実現します。

3. 張正佑校正法の数学的原理

3.1 パラメータの導入

2D 画像ポイント:m=\begin{pmatrix} u & v \end{pmatrix}^{T}

3D 空間点:M=\bigl(\begin{smallmatrix} X & Y& Z \end{smallmatrix}\bigr)^{T}

同次座標: \チルダ{m}=\begin{pmatrix} u &v &1 \end{pmatrix}^{T}\チルダ{M}=\begin{pmatrix} X &Y &Z &1 \end{pmatrix}^{T}

空間座標から画像座標へのマッピングを説明します。

s: 世界座標系から画像座標系へのスケール係数

K: カメラ内部パラメータ行列

\begin{pmatrix} R&T \end{pmatrix}: 外部行列

(u_{0}、v_{0}): 主点座標と同様

α、β: 焦点距離とピクセルアスペクト比の融合

γ: 放射状歪みパラメータ 

3.2 内部パラメータの解決

チェッカーボードが Z = 0 にあると仮定します。

回転行列 R の i 番目の列を として定義するとr_{i}、次のようになります。

次に、空間から画像へのマッピングを次のように変更できます。

s\チルダ{m}=H\チルダ{M}     

H=K\bigl(\begin{smallmatrix} r_{1} & r_{2}& t \end{smallmatrix}\bigr)

ここで、H はホモグラフィック行列の記述であり、コーナーの世界座標から画像座標までの最小二乗法によって解くことができます。

H を H = [h1 h2 h3] とします。

ホモグラフィーには 8 つの自由度があり、r1 と r2 の直交性と正規化の制約に従って、上式の行列演算により、次の方程式が得られます。

定義 B=K^{-T}K^{-1}== \begin{pmatrix} B_{11} & B_{21} & B_{31}\\ B_{12}& B_{22} & B_{32}\\ B_{13}& B_{23} & B_{33 } \end{p行列} _

 B は対称行列であり、その未知数は 6D ベクトルとして表現できます。 b=\begin{bmatrix} B_{11} & B_{12} &B_{22} &B_{13} &B_{23} & B_{33} \end{bmatrix}^{T}

H の i 番目の列を h_{i}=\bigl(\begin{smallmatrix} h_{i1} & h_{i2} & h_{i3} \end{smallmatrix}\bigr)^{T}b の定義に従って次のように推定すると、次のようになります。h_{i}^{T}Bh_{j}=v_{ij}^{T}b

次のことが推測できます。\begin{pmatrix} v_{12}^{T}\\ (v_{11}-v_{22})^{T} \end{pmatrix}b=0

観察画像のグループが n 個ある場合、V は 2n x 6 行列 Vb=0 になります。

最小二乗法の定義によれば、V b = 0 の解はV^{T}V最小の固有値に対応する固有ベクトルです。

したがって、b を直接推定することができ、後で b を介して内部パラメータを解くことができます。

観測画像 n ≥ 3 の場合は b の一意な解が得られ、n = 2 の場合は一般に歪みパラメータ γ = 0 が設定でき、n = 1 の場合は α と β のみを推定でき、このとき一般に、主点座標の合計は 0う_{0}になると想定できますv_{0}

B=K^{-T}K^{-1}、B は b によって構築される対称行列です。

内部パラメータは次の式 (コレスキー分解) で計算できます。

 3.3 外部パラメータの解決

外部パラメータはホモグラフィーによって解くことができ、H=\bigl(\begin{smallmatrix} h_{1} &h_{2} & h_{3} \end{smallmatrix}\bigr)=\lambda K\begin{pmatrix} r_{1} & r_{2} & \end{p行列}、次のように推定できます。

 一般に、この解はR=\begin{pmatrix} r_{1} &r_{2} & r_{3} \end{pmatrix}直交性と正規化の基準を満たしていませんが、実際の動作では、R は SVD 分解によって正規化できます。

4. 実験手順

1. 以下の図に示すように、5X5 の白黒チェッカーボードを準備します。

2. カメラの角度を調整して、さまざまな方向から市松模様の写真を撮影します。画像セットは次の図に示されています

 3. 画像内のチェッカーボードのコーナー ポイントを抽出します。コーナー ポイントの画像セットは次の図に示されています。

以下の図に例を示します。

​​​​​​​

 

4. コード

import cv2
import numpy as np
import glob

# 设置寻找亚像素角点的参数,采用的停止准则是最大循环次数30和最大误差阈值0.001
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 35, 0.001)

# 获取标定板4*4角点的位置
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点

# 获取指定目录下.jpg图像的路径
images = glob.glob(r"/Users/xionglulu/Downloads/project1/BW/*.jpg")
# print(images)

i=0
for fname in images:
    # print(fname)
    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, (1, 1), (-1, -1), criteria)
        #print(corners2)
        if [corners2]:
            img_points.append(corners2)
        else:
            img_points.append(corners)
        # 在黑白棋盘格图像上绘制检测到的角点
        cv2.drawChessboardCorners(img, (4, 4),corners, ret)
        i+=1
        cv2.imwrite('conimg'+str(i)+'.jpg', img)
        cv2.waitKey(10)
print(len(img_points))
cv2.destroyAllWindows()

# 标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)

print('------照相机内参与外参------')
print("ret:", ret) # 标定误差
print("mtx:\n", mtx) # 内参矩阵
print("dist:\n", dist) # 畸变参数 distortion coefficients = (k_1,k_2,p_1,p_2,k_3)
print("rvecs:\n", rvecs) # 旋转向量 # 外参数
print("tvecs:\n", tvecs ) # 平移向量 # 外参数


img = cv2.imread(images[10])
print(images[10])
h, w = img.shape[:2]
# 计算一个新的相机内参矩阵和感兴趣区域(ROI)
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
print('------新内参------')
print (newcameramtx)
print('------畸变矫正后的图像newimg.jpg------')
newimg = cv2.undistort(img,mtx,dist,None,newcameramtx)
x,y,w,h = roi
newimg = newimg[y:y+h,x:x+w]
cv2.imwrite('newimg.jpg', newimg)
print ("newimg的大小为:", newimg.shape)

 5. 実験結果

元の画像

歪み補正後の画像

 6. 実験結果の解析

(1)ret: 再投影誤差の平均または合計を表す校正誤差。再投影誤差とは、キャリブレーション結果をチェッカーボード画像に適用するときに、予測されたピクセル座標と 3D 座標を 2D 平面に投影することによって計算された実際のピクセル座標との間の誤差を指します。再投影誤差が小さいほど、キャリブレーション結果はより正確になります。この実験でのキャリブレーション誤差は 3.3357 ですが、この誤差はまだ非常に大きく、これは画像の枚数が少ないか、撮影角度の傾きが大きいことが原因と考えられます。

(2) 実験結果から、内部参照行列 mtx のパラメータ画素間隔の値は 0 であることがわかり、カメラの画素間隔は均一であることがわかります。イメージプレーンは同等です。

(3) 元の画像と歪み補正後の画像にほとんど差がない場合は、キャリブレーションデータが不足しているか、キャリブレーションプレートの精度が低い可能性があります。プレートが低いと、キャリブレーションの精度と精度に影響します。その結果、歪み補正効果が良くありません。または、カメラ画像の歪みが小さいです。カメラ画像の歪みが小さい場合、歪み補正後の画像は、元のイメージとあまり変わりません。

おすすめ

転載: blog.csdn.net/summer_524/article/details/130875263