カニカニクラブライフ

Python系技術メモ、書評とか

Zhangのカメラキャリブレーションで、きちんとチェスボードの交点を検出できているか確かめるコード

russeng.hatenablog.jp


でパクったキャリブレーションのコードですが、


OpenCV を利用した非接触 3 次元座標測定技術に関する研究

この報告によれば、チェスボードの角度がカメラの視線方向に対して斜め15度を超えると、

"検出した交点座標が画像上の交点位置と異なる"

"全ての交点座標が検出できない"             などの問題が発生するそう。


そこで、

  • 目視により検出したポイントを表示
  • ボタンにより画像を使用するか否かを人の目で判別する   という機能をつけます。
上記コードにつけたし
# -*- coding: utf-8 -*-

import numpy
import cv2
from glob import glob
import Tkinter
import tkMessageBox


square_size = 23.0      # 正方形のサイズ
pattern_size = (10, 7)  # 模様のサイズ
pattern_points = numpy.zeros( (numpy.prod(pattern_size), 3), numpy.float32 ) #チェスボード(X,Y,Z)座標の指定 (Z=0)
pattern_points[:,:2] = numpy.indices(pattern_size).T.reshape(-1, 2)
pattern_points *= square_size
obj_points = []
img_points = []
 
for fn in glob("*.jpg"):
    # 画像の取得
    im = cv2.imread(fn, 0)
    print "loading..." + fn
    # チェスボードのコーナーを検出
    found, corner = cv2.findChessboardCorners(im, pattern_size)
    # コーナーがあれば
    if found:
        term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
        cv2.cornerSubPix(im, corner, (5,5), (-1,-1), term)    #よくわからないがサブピクセル処理(小数点以下のピクセル単位まで精度を求める)
        cv2.drawChessboardCorners(im, pattern_size, corner,found)
        cv2.imshow('found corners in' + fn,im)
    # コーナーがない場合のエラー処理
    if not found:
        print 'chessboard not found'
        continue
    # 選択ボタンを表示
    root = Tkinter.Tk()
    root.withdraw()
    if tkMessageBox.askyesno('askyesno','この画像の値を採用しますか?'):
         img_points.append(corner.reshape(-1, 2))   #appendメソッド:リストの最後に因数のオブジェクトを追加 #corner.reshape(-1, 2) : 検出したコーナーの画像内座標値(x, y)
         obj_points.append(pattern_points)
         print 'found corners in ' + fn + ' is adopted'
    else:
         print 'found corners in ' + fn + ' is not adopted'        
    cv2.destroyAllWindows()
    
    
# 内部パラメータを計算
rms, K, d, r, t = cv2.calibrateCamera(obj_points,img_points,(im.shape[1],im.shape[0]))
# 計算結果を表示
print "RMS = ", rms
print "K = \n", K
print "d = ", d.ravel()
# 計算結果を保存
numpy.savetxt("K.csv", K, delimiter =',',fmt="%0.14f") #カメラ行列の保存
numpy.savetxt("d.csv", d, delimiter =',',fmt="%0.14f") #歪み係数の保存

コーナーの描画には、opencv出来合いの関数を使用*1

めんどくさいので、main関数にする表記も外しました*2



結果はこんな。

f:id:russENG:20150620120548p:plain

*1:tutorialにあるように代入表記すると僕の環境(opencv2系)だと戻り値はNoneなのでエラ―を吐きます。

*2:main関数にするメリット、いまだによくわからない