ホームページ >バックエンド開発 >Python チュートリアル >Python はキャリブレーションに OpenCV を使用します

Python はキャリブレーションに OpenCV を使用します

不言
不言オリジナル
2018-05-08 16:17:223194ブラウズ

この記事では、主に Python でのキャリブレーションのための OpenCV の使用方法を紹介します。必要な場合は、それを参考にしてください。公式サンプルを用意し、正常に動作できるようにし、自身で収集したデータの実験や解説を行います。

1. 準備 OpenCV は、下の図に示すように、キャリブレーションにチェッカーボードを使用します。カメラをキャリブレーションするには、一連の 3D ポイントとそれに対応する 2D 画像ポイントを入力する必要があります。白黒のチェッカーボードでは、コーナー検出によって 2 次元の画像点を簡単に見つけることができます。現実世界の 3 次元の点はどうなるでしょうか?収集中、カメラを 1 か所に置き、チェッカーボードの校正プレートを別の位置に移動して、写真を撮影しました。したがって、(X,Y,Z) の値を知る必要があります。しかし、簡単に言えば、チェッカーボードが配置されている平面を XY 平面、つまり Z=0 として定義します。キャリブレーション ボードの場合、チェッカーボードの正方形のサイズ (30 mm など) がわかるので、チェッカーボード上のコーナー ポイントの座標を (0,0,0)、(30,0,0)、( 60、 0,0),...、この結果の単位は mm です。


3D 点はオブジェクト点と呼ばれ、2D 画像点は画像点と呼ばれます。

2. チェッカーボードのコーナーポイントの検出 チェッカーボードのテンプレートを見つけるために、openCV の関数 cv2.findChessboardCorners() を使用します。また、使用しているテンプレートの仕様 (8*8 チェッカーボードや 5*5 チェッカーボードなど) をプログラムに伝える必要があります。x 方向と y 方向の数値が等しくないチェッカーボード テンプレートを使用することをお勧めします。次の実験では、10*7 のチェッカーボードを使用します。各正方形の辺の長さは 20 mm、つまり 9*6 個の内部コーナーが含まれます。この関数がテンプレートを検出すると、対応するコーナーポイントを返し、true を返します。もちろん、すべての画像が必要なテンプレートを見つけることができるわけではないため、キャリブレーションに複数の画像を使用できます。チェッカーボードの使用に加えて、ドット マトリックスも使用できます。対応する関数は cv2.findCirclesGrid() です。


コーナーポイントを見つけたら、cv2.cornerSubPix() を使用して、より正確なコーナーピクセル座標を取得できます。 cv2.drawChessboardCorners() を使用して、表示用に画像上にコーナーを描画することもできます。以下の図に示すように:


3. キャリブレーション 上記の手順を通じて、キャリブレーションに使用する 3 次元点と、画像上の対応する 2 次元点ペアを取得しました。キャリブレーションには cv2.calibrateCamera() を使用します。この関数はキャリブレーション結果、カメラの固有パラメータ行列、歪み係数、回転行列、および平行移動ベクトルを返します。

4. 歪み解消 3 番目のステップでは、画像の歪みを解消する前に、cv.getOptimalNewCameraMatrix() を使用して内部パラメータを最適化することもできます。および歪み係数を設定することにより、フリースケールファクターアルファを定義します。 alpha が 0 に設定されている場合は、歪み除去後に不要なピクセルを削除するトリミングされた内部パラメータと歪み係数が返され、alpha が 1 に設定されている場合は、余分な黒ピクセルを含むトリミングされた内部パラメータと歪み係数が返されます。それを切り取るためのROI。

その後、新しく取得した内部パラメータ行列と歪み係数を使用して、画像の歪みを解消します。歪みを解消するには 2 つの方法があります:

(1) cv2.undistort() を使用します

これは、上記の関数を直接呼び出すだけで歪みを解消した画像を取得できます。歪みを解消した画像を取得します。コードは次のとおりです:

# undistort
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)

# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)

下の図は、画像の歪みを取り除き、黒いピクセルを保持した結果を示しています:


(2) 再マップの使用

これは 2 段階の方法です。では、まず歪んだ画像から歪んでいない画像へのマッピングを計算し、次にこのマッピング関係を使用して画像の歪みを解消します。

コードは次のとおりです:


# undistort
mapx,mapy = cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)

# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)

5. 逆投影誤差 逆投影誤差を通じて、結果の品質を評価できます。 0 に近づくほど、結果はより理想的になります。事前に計算された内部パラメータ行列、歪み係数、回転行列、および平行移動ベクトルを通じて、 cv2.projectPoints() を使用して 3 次元点の 2 次元画像への投影を計算し、次に、次によって取得された点間の誤差を計算します。逆投影と画像上で検出された点。最後に、すべてのキャリブレーション画像の平均誤差を計算します。この値が逆投影誤差となります。

コード

すべてのステップのコードは次のとおりです:

#coding:utf-8
import cv2
import numpy as np
import glob

# 找棋盘格角点
# 阈值
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
#棋盘格模板规格
w = 9
h = 6
# 世界坐标系中的棋盘格点,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐标,记为二维矩阵
objp = np.zeros((w*h,3), np.float32)
objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2)
# 储存棋盘格角点的世界坐标和图像坐标对
objpoints = [] # 在世界坐标系中的三维点
imgpoints = [] # 在图像平面的二维点

images = glob.glob('calib/*.png')
for fname in images:
 img = cv2.imread(fname)
 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 # 找到棋盘格角点
 ret, corners = cv2.findChessboardCorners(gray, (w,h),None)
 # 如果找到足够点对,将其存储起来
 if ret == True:
  cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
  objpoints.append(objp)
  imgpoints.append(corners)
  # 将角点在图像上显示
  cv2.drawChessboardCorners(img, (w,h), corners, ret)
  cv2.imshow('findCorners',img)
  cv2.waitKey(1)
cv2.destroyAllWindows()

# 标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

# 去畸变
img2 = cv2.imread('calib/00169.png')
h, w = img2.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),0,(w,h)) # 自由比例参数
dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# 根据前面ROI区域裁剪图片
#x,y,w,h = roi
#dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)

# 反投影误差
total_error = 0
for i in xrange(len(objpoints)):
 imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
 error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
 total_error += error
print "total error: ", total_error/len(objpoints)

関連推奨事項:


OpenCVcv::Mat のデータは txt ファイルに書き込まれます

OpenCV cv.Mat および .txt ファイルのデータの読み取りおよび書き込み操作


以上がPython はキャリブレーションに OpenCV を使用しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。