OpenCVのundistort(レンズ歪み補正)で端っこが欠けてしまうのをなんとかする

More than 1 year has passed since last update.

OpenCVのcv2.undistortでレンズ歪みを補正しようとすると,端っこが欠けてしまう問題がある.

import matplotlib.pyplot as plt
import cv2


img_und = cv2.undistort(img, camera_mat, dist_coef)
plt.subplot(1,2,1)
plt.imshow(img)
plt.subplot(1,2,2)
plt.imshow(img_und)

download.png

ちなみにカメラは今流行の http://panasonic.jp/wearable/a500/index.html を使った.
この画像では,チェスボード部分のレンズ歪みはとれているものの,周りの情報が失われている.どれくらいの情報が失われているのか.

import numpy as np

w,h=np.meshgrid(range(0, img.shape[1], 10), range(0, img.shape[0], 10))
pts = (np.vstack((w.flatten(), h.flatten())).T).astype('float32')
pts_new = cv2.undistortPoints(np.array([pts]), camera_mat, dist_coef, P=camera_mat)[0]

plt.scatter(pts[:,0], pts[:,1], 20, 'r', alpha=.5)
plt.scatter(pts_new[:,0], pts_new[:,1], 20, 'b', alpha=.5)

download (1).png
赤点が入力画像のグリッド,青点がレンズ歪みを取り除くことによって変形したグリッドを示している.cv2.undistortではこの青グリッドの内,赤グリッドの範囲のみが切り出されたものが出力される.これは,端っこにも重要なものが映っている場合,あまり嬉しくない.

こういう時には,cv2.initUndistortRectifyMapcv2.remapを使うと良い.

new_cammat = cv2.getOptimalNewCameraMatrix(camera_mat, dist_coef, (img.shape[1], img.shape[0]), 1)[0]
map = cv2.initUndistortRectifyMap(camera_mat, dist_coef, np.eye(3), new_cammat, (img.shape[1], img.shape[0]), cv2.cv.CV_32FC1)
img_und = cv2.remap(img, map[0], map[1], cv2.cv.CV_INTER_AREA)

plt.subplot(1,2,1)
plt.imshow(img)
plt.subplot(1,2,2)
plt.imshow(img_und)

download (2).png

うまくいった,あと,チェスボード以外の外側部分では歪みがちゃんと補正しきれてないことも分かった.ちなみに,元画像で計測できていない部分(中央上端,中央下端)は0が埋められる.その部分が必要ない場合,
cv2.getOptimalNewCameraMatrix(camera_mat, dist_coef, (img.shape[1], img.shape[0]), 0)とすれば良い. 詳しくは http://opencv.jp/opencv-2svn/cpp/camera_calibration_and_3d_reconstruction.html#cv-getoptimalnewcameramatrix を参照.

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.