2018年8月18日土曜日

OpenCVのcv::calibrationMatrixValuesで焦点距離を求める

OpenCVの"opencv_interactive-calibration"やカメラキャリブレーションで求めたカメラパラメータからmm単位での焦点距離などを求めたいときがある。
自作している3Dスキャナーでも使用したい。

(OenCVでは)カメラパラメータのfx, fyはピクセル単位で扱われるため、以下のように計算すればmm単位での焦点距離は求められる。

焦点距離(mm) = fx × W ÷ w
 fx : 焦点距離(pixel)
 W  : イメージセンサーの幅(mm)
 w  : 画像の幅(pixel)

電卓で計算すればよいのだけど、OpenCVにはcv::calibrationMatrixValuesのAPIで焦点距離を含むカメラのスペックを計算してくれる。

せっかくなので、このAPIをPythonで使って見ようと思う。

使い方

まず、カメラパラメータと画像の解像度を読み込む。
これは、"opencv_interactive-calibration"で出力したファイルから読み込んでいる。
fs = cv2.FileStorage("PathToCameraParameterFile", cv2.FILE_STORAGE_READ)
if fs.isOpened():
        width = (int)(camera_fs.getNode("cameraResolution").at(0).real())
        height = (int)(camera_fs.getNode("cameraResolution").at(1).real())
        camera_matrix = camera_fs.getNode("cameraMatrix").mat()


そして、calibrationMatrixValuesを呼び出す。
fovx, fovy, focal_length, principal_point, aspect_ratio = cv2.calibrationMatrixValues(camera_matrix,
            (width, height), aperture_width, aperture_height)

print("  FOVX = ", "{:.6f}".format(fovx))
print("  FOVY = ", "{:.6f}".format(fovy))
print("  Focal length    = ", "{:.6f}".format(focal_length))
print("  Principal point = ", "{:.6f}, {:6f}".format(*principal_point))
print("  Aspect ratio    = ", "{:.6f}".format(aspect_ratio))
引数には以下を指定する。
  • cameraMatrix  カメラパラメータ(先程ファイルから得たパラメータ)
  • imageSize    画像の解像度(先程ファイルから得たパラメータ, 単位:pixel)
  • apertureWidth    イメージセンサーの幅(単位:mm)
  • apertureHeight    イメージセンサーの高さ(単位:mm)
戻り値にはカメラのスペックが返る。
  • fovx    垂直画角(単位:度)
  • fovy    水平画角(単位:度)
  • focalLength    焦点距離(単位:mm)
  • principalPoint    主点(単位:mm)
  • aspectRatio    fy / fz

試してみる

PiCamera V2.1でカメラキャリブレーションを行った結果で試してみる。
キャリブレーションした結果は以下の通りだった(chArucoパターンでキャリブレーション)。
<cameraResolution>
  640 480</cameraResolution>
<cameraMatrix type_id="opencv-matrix">
  <rows>3</rows>
  <cols>3</cols>
  <dt>d</dt>
  <data>
    5.3447832911092576e+02 0. 3.1759911211440613e+02 0.
    5.3447832911092576e+02 2.3505836099223782e+02 0. 0. 1.</data></cameraMatrix>

cv::calibrationMatrixValuesでカメラのスペックを出力してみる。
イメージセンサーのサイズは、公式ドキュメントから3.68 x 2.76 mm を指定。
FOVX =  61.818399
FOVY =  48.360546
Focal length    =  3.073250
Principal point =  1.826195, 1.351586
Aspect ratio    =  1.000000

公式のドキュメントからと比較すると
  • Sensor image area    3.68 x 2.76 mm (4.6 mm diagonal)
  • Focal length    3.04 mm
  • Horizontal field of view    62.2 degrees
  • Vertical field of view    48.8 degrees
なので、まずまず良いカメラキャリブレーションができたかな?

0 件のコメント:

コメントを投稿