0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ZED2i カメラの焦点距離を得る

Last updated at Posted at 2024-08-08

深度情報を取得できたら、それを空間の点群PointCloud のデータに変換したい。
その際に、焦点距離 focal length が必要になる。
StereoLabs のカメラではシリアルナンバーごとに、焦点距離のデータが予め提供されている。

想定する読者

stereolabsのzed2, zed mini, zed x などのステレオカメラの利用者
いまどきのステレオカメラは何ができるのかを知りたい人

前提

ZED SDK 4.0
Ubuntu 20.04
ZED2i
Python 版のAPI

焦点距離 focal length の情報

StereoLabsのZEDカメラは、カメラの特性がキャリブレーションされている。
そのカメラのシリアルナンバーごとにそのファイルが管理されている。
ZED SDK のインストーラーでインストール後に、以下の場所にconfファイルが保存されている。

/usr/local/zed/settings/SN[0-9]+.conf

ZED SDKのカメラでは、カメラの機種ごとに設定可能な解像度が数種類ある。
それにともなって、カメラの左右・カメラの解像度モードごとに値がある。

head -22 SN*.conf
[LEFT_CAM_2K]
fx=1064.82
fy=1065.07
cx=1099.05
cy=628.813
k1=-0.0634518
k2=0.0401532
p1=-0.000375119
p2=0.00074809
k3=-0.0161231

[RIGHT_CAM_2K]
fx=1065.27
fy=1065.34
cx=1133.31
cy=654.957
k1=-0.0587747
k2=0.0322036
p1=5.85653e-05
p2=-0.000297978
k3=-0.0123602

Baselineの値もあるよ

上記のファイルの[STEREO] セッションにBaselineなどのその他の必要な値があります。

どうやら、tomlファイルのようだ。libtoml(python3.11以降)やtoml のライブラリでloadするとdict型で読み込めそうだ。

zed sdk のpythonスクリプトの中からの取得例

.py
import pyzed.sl as sl

# Create a ZED camera object
zed = sl.Camera()

# Set up initial parameters for the camera
init_params = sl.InitParameters()

# Open the camera
status = zed.open(init_params)
if status != sl.ERROR_CODE.SUCCESS:
    print(f"Error opening camera: {status}")
    exit(1)

cam_info = zed.get_camera_information()

left_cam_params = cam_info.camera_configuration.calibration_parameters.left_cam
right_cam_params = cam_info.camera_configuration.calibration_parameters.right_cam

print("Left Camera Parameters:")
print(f"image_size: {left_cam_params.image_size.width} x {left_cam_params.image_size.height}")
print(f"Focal Length (fx, fy): {left_cam_params.fx}, {left_cam_params.fy}")
print(f"Principal Point (cx, cy): {left_cam_params.cx}, {left_cam_params.cy}")
print(f"Distortion Coefficients: {left_cam_params.disto}")

print("\nRight Camera Parameters:")
print(f"image_size: {right_cam_params.image_size.width} x {right_cam_params.image_size.height}")
print(f"Focal Length (fx, fy): {right_cam_params.fx}, {right_cam_params.fy}")
print(f"Principal Point (cx, cy): {right_cam_params.cx}, {right_cam_params.cy}")
print(f"Distortion Coefficients: {right_cam_params.disto}")

zed.close()

実行結果の1例

python3 camerainfo.py 
(中略)
Left Camera Parameters:
image_size: 1280 x 720
Focal Length (fx, fy): 527.9297485351562, 527.9297485351562
Principal Point (cx, cy): 648.6941528320312, 370.4883728027344
Distortion Coefficients: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

Right Camera Parameters:
image_size: 1280 x 720
Focal Length (fx, fy): 527.9297485351562, 527.9297485351562
Principal Point (cx, cy): 648.6941528320312, 370.4883728027344
Distortion Coefficients: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

焦点距離などのカメラパラメータって何って方のために

「実践コンピュータビジョン」4章 カメラモデルと拡張現実感

その中で、キャリブレーション行列Kと焦点距離・カメラ中心の座標とが書かれています。

K-matrix2.png

ステレオ平行化済みの画像がえられる範囲では、この本の記述がわかりやすいです。

英語が苦にならない方ならば、次にpdfファイルがおすすめです。

Programming Computer Vision With Pyhon
http://programmingcomputervision.com/downloads/ProgrammingComputerVision_CCdraft.pdf

「詳解 OpenCV コンピュータビジョンライブラリを使った画像処理・認識」

この本では、カメラキャリブレーションもステレオ平行化もされていないカメラから、カメラキャリブレーションをするまでの過程について詳細がかかれている書籍です。
うれしいことには、この書籍に書かれている内容を使ってカメラキャリブレーションをするためのソフトウエアがOpenCV の実装として用意されているということです。
ただ、ZED2iを使う限りには、その必要はありません。

関連情報

【Python】深度画像から点群を作成する

.py
    points = []    
    for v in range(rgb.size[1]):
        for u in range(rgb.size[0]):
            color = rgb.getpixel((u,v))
            Z = depth.getpixel((u,v)) / scalingFactor
            if Z==0: continue
            X = (u - centerX) * Z / focalLength
            Y = (v - centerY) * Z / focalLength
            points.append("%f %f %f %d %d %d 0\n"%(X,Y,Z,color[0],color[1],color[2]))

コードの断片
このコードでは、numpyを使っていないものです。
この例ではfx, fy の区別がなく共通の値focalLengthとしています。

qiita 深度から点群

Screenshot from 2024-08-10 22-07-11.png

の利用例になっています。

利用例のgithb https://github.com/torupati/o3d_depth2pcd

解説:

u, v はイメージセンサ上のpixelの位置(水平、垂直)
u, vは整数です。
z = d / depth_scaleとなっているので、
ライブラリの使い方の中で想定している長さのスケールになっています。
[mm] かもしれませんし、[m]かもしれません。
Xは水平方向の位置です。右側が+になります。
yは鉛直方向の位置です。下側が+になります。
上記の式から見てわかるように、焦点距離fx,fyの単位は無次元量になっています。
実際には、pixelの大きさを単位とした量になります。

ZED2i のカメラの場合には、これらのカメラパラメータが提供されているので、
すんなりと、変換作業を行うことができます。

付記:標準によせることの大事さ

depthをpointcloudに変換することができるライブラリは多数あるだろう。
その中で、できるだけ標準のライブラリを選ぼう。
標準のライブラリは、GPUへの対応もされていたり、CPUの種類のサポートもある。
標準によせることで、自分がテストしてメンテナンスしなくちゃならないコードが減る。
標準としてのライブラリ・データ形式であることで、それを利用する追加のライブラリが作りやすくなる。

Open3D-ML

注意:

depth は欠損値(nan, posinf, neginfなどのisfiniteではない値)を持つことがふつうです。
欠損点が0の場合もあります。IEEE 754のfloatに対応していないデータ形式の場合には, depth を0として表現している場合もあります。上記のpyhtonスクリプトはその例です。
そのため、欠損値に対応したライブラリの作りになっているか、自分で確かめて見てください。

補足:disparity(視差) からdepth(深度)への変換

Disparity map to point cloud using Open3d? #1744

depth = baseline * focal_length / disparity

ここで、focal_lengthとdisparity の単位は[pixel] です。
depthの単位は baseline(基線長) の単位と同じになります。

付記:

なお、ZED SDK の場合、点群を算出するのに焦点距離を意識しなくても十分です。
ZED SDKを使いこなす point_cloud
に書いたやり方で、点群を取得できます。

にもかかわらず、焦点距離を明示的に利用する記事を書いたのは、ZED SDK 以外のライブラリを使って、視差計算・深度計算を行いたい場合に、同様に点群を算出できるようにするためです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?