レンズ歪みの補正

2015/8/14

Python2.7.6, OpenCV3.0.0

OpenCVにはチェスボードからカメラのレンズ歪みを補正するキャリブレーションという機能がある。

Webカメラから画像を取得して、キャリブレーション

import numpy as np
import 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.

capture = cv2.VideoCapture(0)

if capture.isOpened() is False:
    raise("IO Error")

cv2.namedWindow('Before', cv2.WINDOW_AUTOSIZE)
cv2.namedWindow('After', cv2.WINDOW_AUTOSIZE)

for i in range(10): #安定するまで何回か取得
    ret, src_img = capture.read()
    if ret == False:
        continue

copy_img = src_img.copy()
cv2.imshow('Before', src_img)

gray = cv2.cvtColor(copy_img,cv2.COLOR_BGR2GRAY)

# Find the chess board corners
ret, corners = cv2.findChessboardCorners(gray,(7,6),None)

if ret == False:
    cv2.destroyAllWindows()
    print('Error')
    exit()

# If found, add object points, image points (after refining them)
objpoints.append(objp)

corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
imgpoints.append(corners2)

# Draw and display the corners
# img = cv2.drawChessboardCorners(copy_img, (7,6), corners2, ret)

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

h,  w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))

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

cv2.imshow('After',dst)

while True: #キーを押すまで待機
    if cv2.waitKey(33) >= 0:
        break

cv2.destroyAllWindows()


取りあえず、ここの情報を頼りに意味も分からず、コピペしてみたら、一応できたっぽい。

Docs » OpenCV-Python Tutorials » Camera Calibration and 3D Reconstruction » Camera Calibration
http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html

チェスボードのほかにもcv2.findCirclesGrid()という関数もある。


各種関数

findChessboardCorners

retval, corners = cv2.findChessboardCorners(image, patternSize, flags) 

チェスボードの交点を探す

  • image ・・・ カラー画像かグレースケール画像
  • patternSize ・・・ チェスボードの交点数(行, 列)
  • flags ・・・ 操作フラグ(?)
  • corners ・・・ 検出されたコーナーの出力配列
  • retval ・・・ 処理結果

OpenCV API Reference » calib3d. Camera Calibration and 3D Reconstruction
docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#findchessboardcorners

OpenCV3.0.0 : Camera Calibration and 3D Reconstruction
http://docs.opencv.org/3.0.0/d9/d0c/group__calib3d.html#ga93efa9b0aa890de240ca32b11253dd4a

OpenCVでチェスボードの交点を検出する
http://venuschjp.blogspot.jp/2015/02/opencv.html


cornerSubPix

corners2 = cornerSubPix(image, corners, winSize, zeroZone, criteria)

コーナー位置を高精度化

  • image ・・・  グレースケール画像
  • corners ・・・ 入力コーナーの初期座標.
  • winSize ・・・ 探索窓のサイズの半分.(5,5) の場合,52+1×52+1 = 11×11 サイズの探索窓が利用される.要は判定範囲?
  • zeroZone ・・・ 探索領域の中心に存在する対象外領域の半分のサイズ. (-1,-1) は,対象外領域はないということ
  • criteria ・・・ コーナー位置高精度化のための繰り返し処理の停止基準.最大反復数と要求精度のどちらか,あるいは両方を指定
  • corners2 ・・・ 高精度化されたコーナー座標

opencv v2.1 documentation » cv. 画像処理とコンピュータビジョン » 特徴検出
http://opencv.jp/opencv-2.1/cpp/feature_detection.html#cv-cornersubpix

OpenCV 3.0.0 : Feature Detection
http://docs.opencv.org/3.0.0/dd/d1a/group__imgproc__feature.html#ga354e0d7c86d0d9da75de9b9701a9a87e

OpenCVでチェスボードの交点を検出する
http://venuschjp.blogspot.jp/2015/02/opencv.html


calibrateCamera

retval, cameraMatrix, distCoeffs, rvecs, tvecs = cv2.calibrateCamera(objectPoints, imagePoints, imageSize, flags=0)

各種補正用のパラメータを取得

  • objectPoints ・・・ 交点の点群座標.
  • imagePoints ・・・ objectPointsに対応する特徴点の画像上での座標値.
  • imageSize ・・・ 画像サイズ.
  • cameraMatrix ・・・ 歪み係数の出力ベクトル入出力用のカメラの内部パラメータ行列.
  • distCoeffs ・・・ 歪み係数の出力ベクトル
  • rvecs ・・・ 推定された回転ベクトル
  • tvecs ・・・ 推定された並進ベクトル
  • flags ・・・ 様々なフラグ.
  • retval ・・・ 処理結果

OpenCV 3.0.0 Documentation : Camera Calibration and 3D Reconstruction
http://docs.opencv.org/3.0.0/d9/d0c/group__calib3d.html#ga687a1ab946686f0d85ae0363b5af1d7b

opencv 2.2 documentation » カメラキャリブレーションと3次元再構成
http://opencv.jp/opencv-2svn/cpp/camera_calibration_and_3d_reconstruction.html#cv-getoptimalnewcameramatrix

OpenCV2系のAPIを使って歪み補正を行う
http://qiita.com/tunepolo/items/76058121238be386bb21


getOptimalNewCameraMatrix

newCameraMatrix, roi = cv2.getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha, newImageSize)

画像に適応する行列パラメータを生成する

  • cameraMatrix – 入力されるカメラ行列.
  • distCoeffs – 入力される歪み係数ベクトル
  • imageSize – 最適画像サイズ.
  • alpha – 0~1の値.1だと元画像で計測できていない部分(中央上端,中央下端)は0が埋められる
  • newCameraMatrix – 出力される新たなカメラ行列.
  • newImageSize – 平行化された後の画像サイズ.デフォルトでは imageSize と同じになる.
  • validPixROI – 歪み補正された画像中のすべての有効なピクセル領域を囲む矩形

OpenCVのundistort(レンズ歪み補正)で端っこが欠けてしまうのをなんとかする
http://qiita.com/jellied_unagi/items/36796d48d7d8a5fb3e42

opencv 2.2 documentation » カメラキャリブレーションと3次元再構成
http://opencv.jp/opencv-2svn/cpp/camera_calibration_and_3d_reconstruction.html#cv-getoptimalnewcameramatrix

OpenCV 3.0.0 Documentation : Camera Calibration and 3D Reconstruction
http://docs.opencv.org/3.0-beta/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#getoptimalnewcameramatrix


initUndistortRectifyMap

レンズ歪みを補正する。cv2.undistort()という関数もあって、こちらも補正するけど、補正が効く部分を切り取ってしまう。
もとの画像サイズのままにしたいときは、この関数とremap()を使う。

map1, map2 = cv2.initUndistortRectifyMap(cameraMatrix, distCoeffs, R, newCameraMatrix, size , m1type)

補正マップ作成

  • cameraMatrix ・・・ 入力されるカメラ行列
  • distCoeffs ・・・ 入力される歪み係数ベクトル
  • R ・・・ 物体空間における平行化変換(3x3 の行列).Noneの場合,恒等変換が仮定される
  • newCameraMatrix ・・・ 新しいカメラ行列
  • size ・・・ 歪み補整された画像サイズ.
  • m1type ・・・ 1番目の出力マップの型.
  • map1 ・・・ 1番目の出力マップ.
  • map2 ・・・ 2番目の出力マップ.

OpenCVのundistort(レンズ歪み補正)で端っこが欠けてしまうのをなんとかする
http://qiita.com/jellied_unagi/items/36796d48d7d8a5fb3e42

opencv 2.2 documentation » カメラキャリブレーションと3次元再構成
http://opencv.jp/opencv-2svn/cpp/camera_calibration_and_3d_reconstruction.html#cv-initundistortrectifymap

OpenCV 3.0.0 Documentation : Geometric Image Transformations
http://docs.opencv.org/3.0.0/da/d54/group__imgproc__transform.html#ga7dfb72c9cf9780a347fbe3d1c47e5d5a


remap

dst = cv2.remap(src, map1,map2, interpolation, borderMode, borderValue)

画像に対して,汎用的な幾何学変換を適用

  • src      ・・・ 入力画像
  • dst      ・・・ 出力画像. map1 と同じサイズ, src と同じタイプ
  • map1     ・・・ 型 CV_16SC2 , CV_32FC1 あるいは CV_32FC2 である座標点 (x,y) ,または単なる値 x の1番目のマップ
  • map2     ・・・ 型 CV_16UC1 , CV_32FC1 あるいは none(map1 が (x,y) である場合は空のマップ) である値 y の2番目のマップ
  • interpolation ・・・ 補間手法. cv2.INTER_LINEARはバイリニア補間
  • borderMode ・・・ ピクセル外挿手法. デフォルトではBORDER_TRANSPARENT。
  • borderValue ・・・ 定数境界モードで利用されるピクセル値.デフォルトでは 0

opencv 2.2 documentation » 画像の幾何学変換
http://opencv.jp/opencv-2svn/cpp/imgproc_geometric_image_transformations.html?highlight=remap#remap

OpenCV 3.0.0 Documentation : Geometric Image Transformations http://docs.opencv.org/3.0.0/da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4


ただのコピペだけど、頑張った!