GoProで魚眼撮影しつつ、同時に映像をPCに取り込んでキャリブレーションし、魚眼を取り除いた状態で画像解析したい。
しかし、いきなりキャリブレーションのためのチェスボード認識でつまづきました。
認識がシビアなようです。
OpenCVでチェスボード認識
OpenCV3-Python チュートリアル「カメラ・キャリブレーション」を参考にして実験しましょう。
チュートリアルの内容が私には難しいので、とりあえず感覚で試します。
※OpenCV・Python初心者で、これから画像解析に手を出そうとしているくらいのレベルの人が対象の記事となります。
開発環境
Windows10
Python・・・3.6.4
OpenCV・・・3.4.0
チェスボード印刷
適当にPhotoshopなどでチェスボードを作ります。
チェスボードの画像ダウンロードは後述しますが、印刷したのち、アクリル板に貼り付けています。※硬い板ならなんでもOK。
キャリブレーション用画像の用意
上の写真はGoProで撮影していますが、盛大に湾曲しています。
キャリブレーションをする場合、この湾曲したチェスボードの写真を、最低10枚は必要とするようです。
動画で撮影して、適当なフレームで静止が保存し、15枚ほど用意しました。
チェスボード認識コード実行
OpenCV3-Python チュートリアルに掲載してあるサンプルコードを実行します。
どの画像が認識に成功したか確認するため、28行目に「print(fname)」を追加しています。コメントも英語だったので、おおざっぱな日本語に書き換えています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
import numpy as np import cv2 import glob # 終了基準 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) # チェスボードで6×7の交点を検出しよう objp = np.zeros((6*7,3), np.float32) objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2) # 検出した交点を格納する配列 objpoints = [] # 3次元点 imgpoints = [] # 2次元点 images = glob.glob('chessboards/*.jpg') for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # チェスボードの交点を検出 ret, corners = cv2.findChessboardCorners(gray, (7,6),None) # 交点が検出された場合 if ret == True: # 成功したファイル名を出力 print(fname) objpoints.append(objp) corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria) imgpoints.append(corners2) # 交点を描画する img = cv2.drawChessboardCorners(img, (7,6), corners2,ret) cv2.imshow('img',img) cv2.waitKey(500) cv2.destroyAllWindows() |
実行するPythonファイルと同じ階層に「chessboards」というディレクトリをつくり、その中に先ほどの15枚の画像を入れています。
チェスボードのマスの数が、オリジナルサンプルと違うのが、ちょっと気になります。
1つも認識しない!
上記コードを実行しても、何も起こりません。
とりあえず、サンプルサイトのようにグレースケールにしてみましょう。
これでもダメです。
マスの数の問題かな・・・。
コードをいじるより、チェスボードを作り直す方が楽だと判断し、サンプルと同じものを作りました。
印刷して、ご自由にお使いください。※追記:印刷するとき余白を十分に設定してください。
ブレない240fps撮影で画像用意
再度、画像を用意し直します。
ブレがほとんど起こらない、240fpsで撮影しました。
ちょっと暗くなってしまいましたが、これでいけるでしょうか?
また15枚、静止画として用意しました。
3分の1認識!
再度コードを実行します。
ようやく認識してくれました!
認識に成功したファイルはコマンドプロントに出力されるようにしています。
1 2 3 4 5 6 |
C:\opencv\calibration>python chess.py chessboards\11.jpg chessboards\2.jpg chessboards\3.jpg chessboards\4.jpg chessboards\9.jpg |
5つ成功。
うれしいような。足りないような。
認識した画像の特徴は?
認識成功の画像に◎を付けました。
比較的カメラから遠いときに、認識しています。
カメラに近い9.jpgが認識しているので、確かな法則は見つけられません。
おそらくカメラからチェスボードを離して、上下左右まんべんなく画像を用意したほうが、認識されやすいのだと思います。チェッカーボード画像の周囲に余白をつくると認識されるようになるとのことです。(吾妻健夫様より情報を頂きました)
私も同じことでひっかかりました。交点検出のアルゴリズムが、チェッカーボード画像の周囲に余白があることを前提としている様です。ですので、gimp等で白塗りしてやれば検出する様になりますよ。
[参考URL] https://kamino.hatenablog.com/entry/opencv_calibrate_camera
貴重な情報をありがとうございます!周囲余白が必要だったのですね。余白を作って再度試してみます。