Created
July 15, 2025 11:00
-
-
Save mattak/aaf2665fd3a0720e124df10f90d99d18 to your computer and use it in GitHub Desktop.
calibrate_fisheye.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cv2 | |
import numpy as np | |
import glob | |
import os | |
import argparse | |
def calibrate_fisheye(folder_path, pattern_size=(9, 6), square_size=1.0, save_path='fisheye_camera_params.npz'): | |
# 3D座標の準備(Z=0平面) | |
objp = np.zeros((1, pattern_size[0] * pattern_size[1], 3), np.float32) | |
objp[0, :, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2) | |
objp *= square_size | |
objpoints = [] # 3D点 | |
imgpoints = [] # 2D点 | |
# 画像取得(再帰的に) | |
image_paths = glob.glob(os.path.join(folder_path, '**', '*.jpg'), recursive=True) | |
image_paths += glob.glob(os.path.join(folder_path, '**', '*.png'), recursive=True) | |
print(f"{len(image_paths)} 枚の画像が見つかりました") | |
if not image_paths: | |
print("画像が見つかりませんでした") | |
return | |
for path in image_paths: | |
img = cv2.imread(path) | |
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
ret, corners = cv2.findChessboardCorners( | |
gray, pattern_size, | |
cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE | |
) | |
if ret: | |
corners2 = cv2.cornerSubPix( | |
gray, corners, (3, 3), (-1, -1), | |
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.01) | |
) | |
imgpoints.append(corners2) | |
objpoints.append(objp) | |
print(f"OK: {path}") | |
else: | |
print(f"NG: {path}") | |
if len(objpoints) < 3: | |
print("十分な有効な画像がありません。最低3枚以上必要です。") | |
return | |
N_OK = len(objpoints) | |
img_shape = gray.shape[::-1] | |
K = np.zeros((3, 3)) | |
D = np.zeros((4, 1)) | |
rvecs = [np.zeros((1, 1, 3)) for _ in range(N_OK)] | |
tvecs = [np.zeros((1, 1, 3)) for _ in range(N_OK)] | |
flags = ( | |
cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC + | |
cv2.fisheye.CALIB_CHECK_COND + | |
cv2.fisheye.CALIB_FIX_SKEW | |
) | |
rms, K, D, rvecs, tvecs = cv2.fisheye.calibrate( | |
objpoints, | |
imgpoints, | |
img_shape, | |
K, | |
D, | |
rvecs, | |
tvecs, | |
flags, | |
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-6) | |
) | |
print("\n=== FishEye キャリブレーション結果 ===") | |
print("RMS 誤差:", rms) | |
print("Camera Matrix (K):\n", K) | |
print("Distortion Coefficients (D):\n", D.ravel()) | |
# 保存 | |
np.savez(save_path, K=K, D=D) | |
print(f"\n保存しました: {save_path}") | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser(description='OpenCV FishEye カメラキャリブレーションスクリプト') | |
parser.add_argument('--folder', type=str, required=True, help='チェスボード画像のフォルダパス') | |
parser.add_argument('--cols', type=int, default=9, help='チェスボードの列数(交点数)') | |
parser.add_argument('--rows', type=int, default=6, help='チェスボードの行数(交点数)') | |
parser.add_argument('--square-size', type=float, default=1.0, help='1マスのサイズ(mm)') | |
parser.add_argument('--output', type=str, default='fisheye_camera_params.npz', help='出力ファイル名') | |
args = parser.parse_args() | |
pattern_size = (args.cols, args.rows) | |
calibrate_fisheye( | |
folder_path=args.folder, | |
pattern_size=pattern_size, | |
square_size=args.square_size, | |
save_path=args.output | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment