カメラキャリブレーションと3次元再構成 ======================================================= .. highlight:: c このセクションで述べる関数は,いわゆるピンホールカメラモデルを取り扱います.つまりこのモデルでは,3次元座点を透視投影変換を用いて画像平面に射影することで,シーンのビューが構成されています. .. math:: s \; m' = A [R|t] M' または .. math:: s \vecthree{u}{v}{1} = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1} \begin{bmatrix} r_{11} & r_{12} & r_{13} & t_1 \\ r_{21} & r_{22} & r_{23} & t_2 \\ r_{31} & r_{32} & r_{33} & t_3 \end{bmatrix} \begin{bmatrix} X \\ Y \\ Z \\ 1 \end{bmatrix} ここで :math:`(X, Y, Z)` はワールド座標系の3次元座標を表し :math:`(u, v)` は画像平面に投影された点の座標を表します. :math:`A` は,カメラ行列,またはカメラの内部パラメータ行列と呼ばれます. :math:`(cx, cy)` は主点(通常は画像中心), :math:`fx, fy` はピクセル単位で表される焦点距離です. したがって, あるファクタによってカメラ画像がスケーリングされている場合, このすべてのパラメータを同じファクタでスケーリング(それぞれが,拡大または縮小)する必要があります. 内部パラメータ行列はビューに依存しないので,一度推定すれば(ズームレンズの場合)焦点距離を固定している限りは繰返し使用することができます. 並進-回転の同次変換行列である :math:`[R|t]` は,外部パラメータ行列と呼ばれます. これは,静的環境に対するカメラの動き,または逆に,固定カメラの前の物体の剛体運動を表します. つまり :math:`[R|t]` は,点座標 :math:`(X, Y, Z)` をそれぞれのカメラの座標系に変換します. 上述の変換は,以下の式(で :math:`z \ne 0` の場合)と等価です. .. math:: \begin{array}{l} \vecthree{x}{y}{z} = R \vecthree{X}{Y}{Z} + t \\ x' = x/z \\ y' = y/z \\ u = f_x*x' + c_x \\ v = f_y*y' + c_y \end{array} 実際のカメラレンズは,主に半径方向の歪みや,わずかに円周方向の歪みを持っているので,上のモデルは以下のように拡張されます. .. math:: \begin{array}{l} \vecthree{x}{y}{z} = R \vecthree{X}{Y}{Z} + t \\ x' = x/z \\ y' = y/z \\ x'' = x' (1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + 2 p_1 x' y' + p_2(r^2 + 2 x'^2) \\ y'' = y' (1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + p_1 (r^2 + 2 y'^2) + 2 p_2 x' y' \\ \text{where} \quad r^2 = x'^2 + y'^2 \\ u = f_x*x'' + c_x \\ v = f_y*y'' + c_y \end{array} :math:`k_1` , :math:`k_2` , :math:`k_3` は半径方向の歪み係数, :math:`p_1` , :math:`p_2` は円周方向の歪み係数です. OpenCV では高次の係数は考慮されません.以降の関数では,歪み係数は .. math:: (k_1, k_2, p_1, p_2[, k_3]) というベクトルとして,渡されたり返されたりします.つまり,ベクトルが4つの要素をもつならば, :math:`k_3=0` であることを意味します. 歪み係数はシーンのビューに依存しないので,カメラの内部パラメータに属します. *また,キャプチャされた画像の解像度に関わらず同じ値のままになります.* つまり,例えば,あるカメラが :math:`320 \times 240` の画像でキャリブレーションされた場合,同じカメラの :math:`640 \times 480` の画像に対してもまったく同じ歪み係数を用いることができます ( :math:`f_x` , :math:`f_y` , :math:`c_x` , :math:`c_y` は適切にスケーリングされなければいけませんが). 以降の関数は,このようなモデルを用いて,次のようなことを行います: * 内部パラメータ,外部パラメータが与えられた場合に,3次元座標を画像平面上に投影します. * 内部パラメータ,少数の3次元点,その投影点が与えられた場合に,外部パラメータを求めます. * 既知のキャリブレーションパターンを写した複数のビュー(つまり,各ビューが,複数の3次元点と2次元点の対応として記述できます)から,カメラの内部パラメータ,外部パラメータを推定します. * ステレオカメラ「ヘッド」の相対位置と相対姿勢を推定し,カメラの光軸を平行にする *平行化* 変換を求めます. .. index:: CalcImageHomography cv::CalcImageHomography ----------------------- .. cfunction:: void cvCalcImageHomography( float* line, CvPoint3D32f* center, float* intrinsic, float* homography ) 楕円平面状の物体(例えば,腕)に対するホモグラフィ行列を求めます. :param line: 物体の主軸方向.(ベクトル(dx,dy,dz)) :param center: 物体中心 ((cx,cy,cz)) :param intrinsic: カメラの内部パラメータ (3x3 の行列) :param homography: 出力されるホモグラフィ行列 (3x3) この関数は,3次元楕円体の主軸で定義されるような,画像平面から平面への変換を行うホモグラフィ行列を求めます (OpenCV Guide の 3D Reconstruction の章にある図6-10を参照してください). .. index:: CalibrateCamera2 cv::CalibrateCamera2 -------------------- .. cfunction:: double cvCalibrateCamera2( const CvMat* objectPoints, const CvMat* imagePoints, const CvMat* pointCounts, CvSize imageSize, CvMat* cameraMatrix, CvMat* distCoeffs, CvMat* rvecs=NULL, CvMat* tvecs=NULL, int flags=0 ) キャリブレーションパターンを写した複数のビューから,カメラの内部・外部パラメータを求めます. :param objectPoints: 物体上の点群,つまりモデル座標空間におけるキャリブレーションパターンの特徴点座標,の結合行列.これは浮動小数点型で, 3xN または Nx3 の1チャンネル,あるいは 1xN または Nx1 の3チャンネル配列です.ここで N は全てのビューにおける点の総数を表します :param imagePoints: 物体上の点群をカメラビューに投影した点群の結合行列.これは浮動小数点型で,2xN または Nx2 の1チャンネル,あるいは 1xN または Nx1 の2チャンネル配列です.ここで N は全てのビューにおける点の総数を表します :param pointCounts: 各ビューにおける点の個数を表す,1xM または Mx1 の整数型ベクトル(ここで M はキャリブレーションパターンのビューの数を表します).ベクトル要素の合計値は, ``objectPoints`` および ``imagePoints`` (=N) と一致しなければいけません :param imageSize: 画像サイズ.カメラの内部行列を初期化するためだけに利用されます :param cameraMatrix: 入出力用の,カメラの内部パラメータ行列 :math:`A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}` . ``CV_CALIB_USE_INTRINSIC_GUESS`` および/または ``CV_CALIB_FIX_ASPECT_RATIO`` が指定される場合, ``fx, fy, cx, cy`` のいくつか,あるいはすべてが初期化されていなければなりません :param distCoeffs: 4x1, 1x4, 5x1 または 1x5 の歪み係数 :math:`(k_1, k_2, p_1, p_2[, k_3])` の出力ベクトル :param rvecs: 出力される 3x *M* または *M* x3 のシングルチャンネル,あるいは 1x *M* または *M* x1 の3チャンネル配列 .各ビューにおいて推定された回転ベクトルを表します( :ref:`Rodrigues2` を参照してください).つまり,k番目の回転ベクトルとk番目の並進ベクトル(下の出力パラメータの説明を参照してください)によって,キャリブレーションパターンが,モデル座標空間(物体上の点が指定される空間)からワールド座標空間,つまり,k番目のビューにおけるキャリブレーションパターンの実際の位置に移動することになります(k=0.. *M* -1) :param tvecs: 出力される 3x *M* または *M* x3 でシングルチャンネル,あるいは 1x *M* または *M* x1 で3チャンネルの配列 .各ビューにおいて推定された並進ベクトルを表します :param flags: 様々なフラグ.0,あるいは以下の値の組み合わせ: * **CV_CALIB_USE_INTRINSIC_GUESS** ``cameraMatrix`` が ``fx, fy, cx, cy`` の有効な初期値を含み,これらが最適化されます.そうでない場合は, ``(cx, cy)`` には初期値として画像中心(これは入力の ``imageSize`` から求められます)がセットされ,焦点距離は最小二乗法で計算されます.もし内部パラメータが既知ならば,外部パラメータを推定するためだけにこの関数を使う必要はないことに注意してください.代わりに :ref:`FindExtrinsicCameraParams2` を利用しましょう * **CV_CALIB_FIX_PRINCIPAL_POINT** 大域的最適化中に,主点が変更されません.主点は画像中心か,あるいは ``CV_CALIB_USE_INTRINSIC_GUESS`` が同時にセットされている場合は,別のの指定位置にとどまります * **CV_CALIB_FIX_ASPECT_RATIO** この関数は ``fy`` だけを自由パラメータとみなして,入力の ``cameraMatrix`` で指定された比率 ``fx/fy`` を保ちます. ``CV_CALIB_USE_INTRINSIC_GUESS`` がセットされていない場合, ``fx`` と ``fy`` の実際の入力値は無視され,その比率だけが計算されて利用されます * **CV_CALIB_ZERO_TANGENT_DIST** 円周方向の歪み係数 :math:`(p_1, p_2)` が0にセットされ,そのまま変更されません この関数は,カメラの内部パラメータ,および各ビューにおける外部パラメー タを推定します.各画像における,3次元点の座標と,それに対応する2次元の 投影点の座標を指定する必要があります.これは,幾何的な特徴が既知で,容 易に特徴点を検出できるような物体を用いて行われます. そのような物体は,キャリブレーション器具またはキャリブレーションパターンと呼ばれます.OpenCVは元々,キャリブレーション器具としてチェスボードをサポートしています( :ref:`FindChessboardCorners` を参照してください).現在のところ,内部パラメータの初期化は,(物体上の点群のz-座標がすべて0になる)平面キャリブレーションパターンに対してのみ実装されています( ``CV_CALIB_USE_INTRINSIC_GUESS`` がセットされない場合).初期 ``cameraMatrix`` が与えられれば,3次元のキャリブレーション器具も利用することができます. このアルゴリズムは,次のようになります: #. まず,内部パラメータの初期値を,計算する(これは,平面キャリブレーションパターンを利用した場合のみ可能)か,あるいは入力パラメータから読み込みます.歪み係数は,( ``CV_CALIB_FIX_K?`` で指定されているものを除いて)すべて0にセットされます. #. 内部パラメータが既知であるかのように,カメラの初期姿勢を推定します.この推定には, :ref:`FindExtrinsicCameraParams2` を利用します. #. 再投影誤差を最小にするように,大域的な Levenberg-Marquardt 最適化アルゴリズムが実行されます.つまり,観測された特徴点 ``imagePoints`` と,(内部パラメータとカメラ姿勢の現在の推定値を利用した)投影点 ``objectPoints`` との距離の2乗和を最小にします. :ref:`ProjectPoints2` を参照してください. この関数は,最終的な再投影誤差を返します. 注意:正方ではない(NxN ではない)グリッドを使用して, :func:`findChessboardCorners` でキャリブレーションを行う場合に, ``calibrateCamera`` が不正な値(つまり,歪み係数が0,画像中心が :math:`(w/2-0.5,h/2-0.5)` から遠く離れている,さらに/または, :math:`f_x` と :math:`f_y` が大きく異なる(比率が 10:1 以上))を返すとすると, :ref:`FindChessboardCorners` で ``patternSize=cvSize(rows,cols)`` としている可能性があります.正しくは, ``patternSize=cvSize(cols,rows)`` となります. 参考: :ref:`FindChessboardCorners` , :ref:`FindExtrinsicCameraParams2` , :func:`initCameraMatrix2D` , :ref:`StereoCalibrate` , :ref:`Undistort2` .. index:: ComputeCorrespondEpilines cv::ComputeCorrespondEpilines ----------------------------- .. cfunction:: void cvComputeCorrespondEpilines( const CvMat* points, int whichImage, const CvMat* F, CvMat* lines) ステレオペアの片方の画像上の点に対して,それに対応する別の画像上のエピポーラ線を求めます. :param points: 入力点. ``2xN, Nx2, 3xN`` または ``Nx3`` の配列(ここで ``N`` は点の個数).マルチチャンネルの ``1xN`` または ``Nx1`` 配列も同様に渡すことができます :param whichImage: ``points`` を含む画像のインデックス(1または2) :param F: :ref:`FindFundamentalMat` または :ref:`StereoRectify` によって指定されるF行列 :param lines: 出力されるエピポーラ線. ``3xN`` または ``Nx3`` の配列. 各エピポーラ線 :math:`ax + by + c=0` は,3つの数値 :math:`(a, b, c)` で符号化されます この関数は,ステレオペアの2つの画像の片方に存在する点それぞれに対して,対応する別の画像上のエピポーラ線を求めます. F行列の定義から( :ref:`FindFundamentalMat` を参照してください),1番目の画像(つまり, ``whichImage=1`` )上の点 :math:`p^{(1)}_i` に対する,2番目の画像上の線 :math:`l^{(2)}_i` は次のように求められます: .. math:: l^{(2)}_i = F p^{(1)}_i そして,逆に ``whichImage=2`` の場合, :math:`l^{(1)}_i` は, :math:`p^{(2)}_i` から,次のように求められます: .. math:: l^{(1)}_i = F^T p^{(2)}_i エピポーラ線の係数には,スケールが定義されています.これらは :math:`a_i^2+b_i^2=1` というように正規化されます. .. index:: ConvertPointsHomogeneous cv::ConvertPointsHomogeneous ---------------------------- .. cfunction:: void cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst ) 点座標と同次座標を,互いに変換します. :param src: 入力点の配列. ``2xN, Nx2, 3xN, Nx3, 4xN または Nx4(ここで ``N`` は,点の個数を表します)`` .マルチチャンネルで ``1xN`` または ``Nx1`` の配列も同様に渡すことができます :param dst: 出力点の配列.必ず入力と同じ数の点を含んでいます.次元数は同じ入力と同じ,1つ小さい,または1つ大きいのいずれかで,2から4の間の数となります この関数は, 2次元または3次元の点と,同次座標を相互に変換,あるいは単に コピーや転置 を行います.入力配列の次元数が出力よりも大きい場合は,各座標値が最後の座標値で割られます: .. math:: \begin{array}{l} (x,y[,z],w) -> (x',y'[,z']) \\ \text{where} \\ x' = x/w \\ y' = y/w \\ z' = z/w \quad \text{(if output is 3D)} \end{array} 出力配列の次元数の方が大きい場合は,各入力点に値1が付け加えられます.それ以外の場合は単に,入力配列が出力配列にコピーされます(転置することもできます). **注意** :この関数は様々な形式の配列を入力にとるので,入出力配列の次元があいまいな場合はエラーが起こることもあります. :math:`\texttt{N} \ge 5` 個の点,あるいは,マルチチャンネルで ``Nx1`` または ``1xN`` の配列,に対して利用する場合は,常に安全です .. index:: CreatePOSITObject cv::CreatePOSITObject --------------------- .. cfunction:: CvPOSITObject* cvCreatePOSITObject( CvPoint3D32f* points, int point_count ) 物体情報を含む構造体を初期化します. :param points: 3次元物体モデルの点座標へのポインタ :param point_count: 物体点座標の個数 この関数は,物体情報構造体のメモリを確保し,物体逆行列を計算します. 事前に処理された物体データは,OpenCV 内部で構造体 :ref:`CvPOSITObject` に格納されるので,ユーザが構造体データに直接アクセスすることはできません.つまり,ユーザはこの構造体を作成し,そのポインタをこの関数に渡すだけです. 物体は,ある座標系の点座標の集合として定義されます.そして,関数 :ref:`POSIT` は,カメラ座標系の中心から,物体の ``points[0]`` へのベクトルを計算します. 与えられた物体に対する処理が終わった後は,関数 :ref:`ReleasePOSITObject` を呼んでメモリを解放しなければいけません. .. index:: CreateStereoBMState cv::CreateStereoBMState ----------------------- .. cfunction:: CvStereoBMState* cvCreateStereoBMState( int preset=CV_STEREO_BM_BASIC, int numberOfDisparities=0 ) ブロックマッチングステレオ対応点探索の構造体を作成します. :param preset: あらかじめ定義されたパラメータセットのID.どのパラメータも,この構造体を作成した後に上書きすることができます.この値は次のようになります * **CV_STEREO_BM_BASIC** 一般的なカメラに適合するパラメータ * **CV_STEREO_BM_FISH_EYE** 広角カメラに適合するパラメータ * **CV_STEREO_BM_NARROW** 狭角カメラに適合するパラメータ } :param numberOfDisparities: 視差数.このパラメータが0の場合,preset から取得した値を利用します.そうでない場合,この値が preset の値を上書きします この関数は,ステレオ対応点探索の構造体を作成し,それを初期化します.また, :ref:`FindStereoCorrespondenceBM` 呼び出しまでの間ならばいつでも,すべてのパラメータを上書きすることが可能です. .. index:: CreateStereoGCState cv::CreateStereoGCState ----------------------- .. cfunction:: CvStereoGCState* cvCreateStereoGCState( int numberOfDisparities, int maxIters ) グラフカットに基づくステレオ対応点探索アルゴリズムの構造体を作成します. :param numberOfDisparities: 視差数.視差の探索範囲は :math:`\texttt{state->minDisparity} \le disparity < \texttt{state->minDisparity} + \texttt{state->numberOfDisparities}` となります :param maxIters: 反復処理の最大数.各試行で,取り得るすべての(あるいは,適度な数の)α拡張を行います.このアルゴリズムは,コスト関数全体を減少させるα拡張が見つからなかった場合は,そこで終了します.詳しくは, Kolmogorov03 を参照してください この関数は,ステレオ対応点探索の構造体を作成し,それを初期化します.また, :ref:`FindStereoCorrespondenceGC` 呼び出しまでの間ならばいつでも,すべてのパラメータを上書きすることが可能です. .. index:: CvStereoBMState .. _CvStereoBMState: CvStereoBMState --------------- .. ctype:: CvStereoBMState ブロックマッチングステレオ対応点探索アルゴリズムのための構造体. :: typedef struct CvStereoBMState { // 事前フィルタ(入力画像を正規化します): int preFilterType; // 現在は 0 int preFilterSize; // 約 5x5..21x21 int preFilterCap; // 約 31 までの値 // 絶対値の差の合計(SAD)を用いて対応点探索を行います: int SADWindowSize; // おそらく 5x5..21x21 int minDisparity; // 最小視差 (=0) int numberOfDisparities; // 最大視差 - 最小視差 // 事後フィルタ(不良なマッチを除外します): int textureThreshold; // テクスチャがない領域を無視します. int uniquenessRatio; // 別の視差でもステレオ対応するようなピクセルを, // 視差が無効なものとします. int speckleWindowSize; // 除去されるスペックルの最大面積 // ( 0 にするとスペックルフィルタリングは無効になります) int speckleRange; // 各連結成分において,許容される視差範囲 int trySmallerWindows; // 利用されません CvRect roi1, roi2; // クリッピングするための ROI int disp12MaxDiff; // left-right チェックを行う際の,最大許容視差 // 内部データ ... } CvStereoBMState; .. .. attribute:: preFilterType 事前フィルタの種類. ``CV_STEREO_BM_NORMALIZED_RESPONSE`` あるいは,デフォルトかつ推奨値である ``CV_STEREO_BM_XSOBEL`` のどちらか, int .. attribute:: preFilterSize 5x5..21x21,int .. attribute:: preFilterCap 31 までの値,int .. attribute:: SADWindowSize 5x5..21x21 あるいは,それ以上の値.ただし,21x21 以下のサイズの窓であれば,処理がだいぶ高速です,int .. attribute:: minDisparity 最小視差 (=0),int .. attribute:: numberOfDisparities 最大視差 - 最小視差,int .. attribute:: textureThreshold テクスチャ閾値.つまり, ``SADWindowSize`` × ``SADWindowSize`` の近傍で求められた x-微分の絶対値の総和がこのパラメータよりも小さければ,その対象ピクセルでは視差が計算されません,int .. attribute:: uniquenessRatio 求められた視差が有功になるための,最良(最小)のコスト関数値と2番目に良い値との最小マージン(パーセント単位) .. attribute:: speckleWindowSize 除去されるスペックルの最大面積( 0 にするとスペックルフィルタリングは無効になります),int .. attribute:: speckleRange 各連結成分において,許容される視差範囲,int .. attribute:: trySmallerWindows 現在は利用されていません(0),int .. attribute:: roi1, roi2 左右の画像をクリッピングするためのROI.関数 :ref:`StereoRectify` は,左右の画像の最大の矩形を返します.また,この平行化変換後もすべてのピクセルが有効になります.これらの矩形を ``CvStereoBMState`` 構造体にコピーすると,ステレオ対応点探索関数は自動的に, :ref:`GetValidDisparityROI` によって求められた「有効な」視差矩形の外側のピクセルをクリアします.よって,通常よりも「無効な視差」ピクセルが多くなりますが,残ったピクセルは,より有効である可能性が高いものになります .. attribute:: disp12MaxDiff 明示的に求められた左から右への視差マップと,黙示的に( :ref:`ValidateDisparity` によって)求められた右から左への視差マップとの間の,許容される最大の差.この差が指定の閾値よりも大きいピクセルでの視差は無効になります.デフォルトでは,このパラメータは(-1)にセットされており,これは left-right チェックが行われないことを意味します Kurt Konolige によるブロックマッチングによるステレオ対応点探索アルゴリズムは,非常に高速なシングルパスのステレオマッチングアルゴリズムです.これは,左右の画像において比較するピクセル位置のずれを( ``minDisparity`` から ``minDisparity+numberOfDisparities`` まで)変化させながら,輝度値の差の絶対値の総和を画像全体に渡って計算します.このアルゴリズムは, :math:`W \times H` の画像のペアにおいて,その視差を ``O(W*H*numberOfDisparities)`` 回計算します.また,このアルゴリズムは,視差画像の質と信頼性を向上させるために,事前フィルタおよび事後フィルタを導入しています. このアルゴリズムは,対応するブロックを,x-軸方向にのみ探索する事に注意してください.つまり,この関数の適用対象となるのは,平行化されたステレオペアです.また,垂直ステレオは直接はサポートされていませんが,そのような場合,ユーザは画像を転置させればよいでしょう. .. index:: CvStereoGCState .. _CvStereoGCState: CvStereoGCState --------------- .. ctype:: CvStereoGCState グラフカットに基づく,ステレオ対応点探索アルゴリズムのための構造体. :: typedef struct CvStereoGCState { int Ithreshold; // データ項の閾値(デフォルトでは 5) int interactionRadius; // 平滑化項の範囲(デフォルトでは 1 ,つまり Potts モデル) float K, lambda, lambda1, lambda2; // コスト関数のパラメータ // (通常は,入力データから適応的に求められます) int occlusionCost; // デフォルトでは 10000 int minDisparity; // デフォルトでは 0 .CvStereoBMState を参照してください int numberOfDisparities; // ユーザが定義します. CvStereoBMState を参照してください int maxIters; // 反復計算回数.ユーザが定義します. // internal buffers CvMat* left; CvMat* right; CvMat* dispLeft; CvMat* dispRight; CvMat* ptrLeft; CvMat* ptrRight; CvMat* vtxBuf; CvMat* edgeBuf; } CvStereoGCState; .. Kolmogrov03 で( **KZ1** として)紹介されたグラフカットステレオ対応点探索アルゴリズムは,非リアルタイムのステレオマッチングアルゴリズムであり,通常,明確なオブジェクト境界を示す非常に正確な奥行き画像を求めます.このアルゴリズムは,ステレオ問題を2値最適化問題のシーケンスとして扱い,それぞれを最大流アルゴリズム(max flow algorithm)を用いて解きます.上述の構造体は,手動で確保,初期化されるべきではりません.その代わりに, :ref:`cvCreateStereoGCState` を利用し,必要ならばパラメータを上書きしてください. .. index:: DecomposeProjectionMatrix cv::DecomposeProjectionMatrix ----------------------------- .. cfunction:: void cvDecomposeProjectionMatrix( const CvMat *projMatrix, CvMat *cameraMatrix, CvMat *rotMatrix, CvMat *transVect, CvMat *rotMatrX=NULL, CvMat *rotMatrY=NULL, CvMat *rotMatrZ=NULL, CvPoint3D64f *eulerAngles=NULL) 射影行列を,回転行列とカメラ行列に分解します. :param ProjMatrix: 3x4 の入力射影行列 P :param cameraMatrix: 3x3 の出力カメラ行列 K :param rotMatrix: 3x3 の出力回転行列 R :param transVect: 4x1 の出力並進ベクトル T :param rotMatrX: オプション.3x3 の x-軸周りの回転行列 :param rotMatrY: オプション.3x3 の y-軸周りの回転行列 :param rotMatrZ: オプション.3x3 の z-軸周りの回転行列 :param eulerAngles: オプション.回転を表す3つのオイラー角 この関数は,射影行列をカメラ行列と回転行列,カメラの位置に分解します. またオプションとして,各軸周りの3つの回転行列,そしてOpenGLで利用できる3つのオイラー角を得ることができます. この関数は, :ref:`RQDecomp3x3` に基づいています. .. index:: DrawChessboardCorners cv::DrawChessboardCorners ------------------------- .. cfunction:: void cvDrawChessboardCorners( CvArr* image, CvSize patternSize, CvPoint2D32f* corners, int count, int patternWasFound ) 検出されたチェスボードのコーナーを描画します. :param image: 出力画像.8ビットのカラー画像 :param patternSize: チェスボード内の,行と列毎の内側コーナー数.(patternSize = cvSize(points _ per _ row,points _ per _ colum) = cvSize(columns,rows) ) :param corners: 検出されたコーナーの配列 :param count: コーナーの個数 :param patternWasFound: チェスボードが完全に検出された :math:`(\ne 0)` か否 :math:`(=0)` かを示します.ここでは単に :ref:`FindChessboardCorners` の戻り値を渡すことができます この関数は,検出された個々のチェスボードを描画します.チェスボードが不完全に検出された場合は,コーナーが赤い丸で描画され,完全に検出された場合は,色付きのコーナーが線で結ばれます. .. index:: FindChessboardCorners cv::FindChessboardCorners ------------------------- .. cfunction:: int cvFindChessboardCorners( const void* image, CvSize patternSize, CvPoint2D32f* corners, int* cornerCount=NULL, int flags=CV_CALIB_CB_ADAPTIVE_THRESH ) チェスボードの内側コーナー位置を求めます. :param image: チェスボードのビュー.8ビットグレースケール画像,またはカラー画像でなければいけません :param patternSize: チェスボードの行と列毎の,内側コーナーの個数( patternSize = cvSize(points _ per _ row,points _ per _ colum) = cvSize(columns,rows) ) :param corners: 検出されたコーナーの出力配列 :param cornerCount: 出力コーナーカウンタ.これがNULLでなければ,ここに検出されたコーなの個数が格納されます :param flags: 様々な処理フラグ.0または以下の値の組み合わせ: * **CV_CALIB_CB_ADAPTIVE_THRESH** 入力画像を白黒画像に変換する際に,(画像の明るさの平均値から計算された)固定閾値の代わりに適応的閾値を利用します. * **CV_CALIB_CB_NORMALIZE_IMAGE** 固定あるいは適応的閾値を適用する前に, :ref:`EqualizeHist` を用いて画像のガンマ値を正規化します * **CV_CALIB_CB_FILTER_QUADS** 輪郭抽出の際に検出された誤った四角を除外するために,(輪郭領域面積,周囲長,正方形度合い,のような)追加の基準を利用します この関数は,入力画像がチェスボードパターンを写すビューであるかどうかを判断し,もしそうならば,チェスボードの内側コーナーの位置を検出しようとします.これは,すべてのチェスボードコーナーが検出された場合は真値を返し,そのコーナーは特定の順序(1行ごとに,各行は左から右に)で格納されます.そうでない場合,つまり,コーナーの完全な検出や順序づけに失敗した場合は,0を返します.例えば,標準的なチェスボードは, 8 x 8 マスで 7 x 7 個の内側コーナー,つまり黒い正方形が別の黒い正方形と接触する点,をもちます.検出される座標は近似されたもので,より正確な位置を決定するために,関数 :ref:`FindCornerSubPix` を利用する場合があります. **注意:** この関数では,様々な環境下でロバストな検出を行うために,チェスボードの周囲に(太い枠淵のような,広ければ広いほど良い)空白が必要です(もし,この空白がなく背景が暗ければ,外側の黒い正方形が適切に分離されず,正方形のグルーピングと順序付けアルゴリズムは失敗するでしょう). .. index:: FindExtrinsicCameraParams2 cv::FindExtrinsicCameraParams2 ------------------------------ .. cfunction:: void cvFindExtrinsicCameraParams2( const CvMat* objectPoints, const CvMat* imagePoints, const CvMat* cameraMatrix, const CvMat* distCoeffs, CvMat* rvec, CvMat* tvec, int useExtrinsicGuess=0) 3次元-2次元の対応点から,物体の姿勢を求めます. :param objectPoints: 物体座標空間における物体上の点座標の配列.3xN または Nx3 のシングルチャンネル配列,あるいは 1xN または Nx1 の3チャンネル配列.ここで N は点の個数を表します. :param imagePoints: 画像上の対応点の配列.2xN または Nx2 のシングルチャンネル配列,あるいは 1xN または Nx1 の2チャンネル配列.ここで N は点の個数を表します. :param cameraMatrix: 入力されるカメラ行列 :math:`A = \vecthreethree{fx}{0}{cx}{0}{fy}{cy}{0}{0}{1}` :param distCoeffs: 入力される 4x1, 1x4, 5x1 または 1x5 の歪み係数ベクル :math:`(k_1, k_2, p_1, p_2[, k_3])` . これが NULL の場合は,すべての歪み係数が0にセットされます :param rvec: 出力される回転ベクトル( :ref:`Rodrigues2` を参照してください).( ``tvec`` とともに用いることで)点をモデル座標系からカメラ座標系に移動します :param tvec: 出力される並進ベクトル :param useExtrinsicGuess: これが真(1)の場合,この関数は,与えられた ``rvec`` と ``tvec`` を,それぞれ回転ベクトルと並進ベクトルの初期近似値として利用し,それらを最適化します この関数は,カメラ行列や歪み係数と共に,物体上の点座標とそれに対応する画像上の投影点の集合が与えられた場合に,物体の姿勢を推定します.そのような姿勢は,再投影誤差を最小にするように求められます.つまり,観測された投影点 ``imagePoints`` と( :ref:`ProjectPoints2` を用いて) ``objectPoints`` を投影した点との距離の2乗和を最小にします. .. index:: FindFundamentalMat cv::FindFundamentalMat ---------------------- .. cfunction:: int cvFindFundamentalMat( const CvMat* points1, const CvMat* points2, CvMat* fundamentalMatrix, int method=CV_FM_RANSAC, double param1=1., double param2=0.99, CvMat* status=NULL) 2つの画像の対応点からF行列を求めます. :param points1: 1番目の画像中の ``N`` 個の点の配列. ``2xN, Nx2, 3xN`` または ``Nx3`` のシングルチャンネル配列,あるいは ``1xN`` または ``Nx1`` の2チャンネル,3チャンネル配列 .点座標は,浮動小数点型(単精度または倍精度)です :param points2: 2番目の画像中対応点の配列. ``points1`` と同じサイズ,同じフォーマット :param fundamentalMatrix: 出力されるF行列.サイズは 3x3 または 9x3 (7-point アルゴリズムは3つまでの行列を返します) :param method: F行列を計算する手法 * **CV_FM_7POINT** 7-point アルゴリズム. :math:`N = 7` * **CV_FM_8POINT** 8-point アルゴリズム. :math:`N \ge 8` * **CV_FM_RANSAC** RANSAC アルゴリズム. :math:`N \ge 8` * **CV_FM_LMEDS** LMedS アルゴリズム. :math:`N \ge 8` :param param1: RANSAC の場合のみ利用されるパラメータ.点からエピポーラ線までの最大距離をピクセル単位で表します.その距離を超えるものは外れ値であると判断され,最終的なF行列の計算に使用されません.点座標の精度,画像の解像度,画像のノイズなどに依存して,1-3程度の値にセットされます :param param2: RANSAC または LMedS の場合にのみ使用されるパラメータ.推定されるF行列がどれほど正しいかを示す信頼(確率)値の要求値を表します :param status: オプション. N要素の出力配列.各要素は対応する点が外れ値ならば0にセットされ,そうでなければ1にセットされます.この配列は, RANSAC または LMedS の場合のみ計算されます.その他の手法の場合は,すべて1にセットされます エピポーラ幾何は,次の式で説明されます: .. math:: [p_2; 1]^T F [p_1; 1] = 0 ここで, :math:`F` はF行列, :math:`p_1` と :math:`p_2` はそれぞれ,1番目と2番目の画像での対応点を表します. この関数は,上述の4つの手法の内の1つを用いてF行列を計算し, 求められたF行列の個数(1または3)を返し,求まらなかった場合は0 を返します. 通常,行列は1つだけ求められますが,7-point アルゴリズムを利用する場合,この関数は3つまでの解(すべての行列を順番に格納した :math:`9 \times 3` の行列)を返すことがあります 計算されたF行列はさらに,指定された点に対応するエピポーラ線を求める関数 :ref:`ComputeCorrespondEpilines` に渡される場合があります.また,平行化変換を求めるために :ref:`StereoRectifyUncalibrated` に渡すこともできます. :: int point_count = 100; CvMat* points1; CvMat* points2; CvMat* status; CvMat* fundamental_matrix; points1 = cvCreateMat(1,point_count,CV_32FC2); points2 = cvCreateMat(1,point_count,CV_32FC2); status = cvCreateMat(1,point_count,CV_8UC1); /* ここで点座標を埋めます ... */ for( i = 0; i < point_count; i++ ) { points1->data.fl[i*2] = ; points1->data.fl[i*2+1] = ; points2->data.fl[i*2] = ; points2->data.fl[i*2+1] = ; } fundamental_matrix = cvCreateMat(3,3,CV_32FC1); int fm_count = cvFindFundamentalMat( points1,points2,fundamental_matrix, CV_FM_RANSAC,1.0,0.99,status ); .. .. index:: FindHomography cv::FindHomography ------------------ .. cfunction:: void cvFindHomography( const CvMat* srcPoints, const CvMat* dstPoints, CvMat* H int method=0, double ransacReprojThreshold=0, CvMat* status=NULL) 2つの画像間の透視変換を求めます. :param srcPoints: 元平面の点群の座標.2xN, Nx2, 3xN または Nx3 のシングルチャンネル配列(後者2つは同次座標系における表現).ここで N は点の個数を表します.1xN または Nx1 の2チャンネル配列,3チャンネル配列も同様に渡すことができます :param dstPoints: 目的平面の点群の座標.2xN, Nx2, 3xN または Nx3 のシングルチャンネル配列,あるいは 1xN または Nx1 の2チャンネル配列,3チャンネル配列 :param H: 出力される 3x3 のホモグラフィ行列 :param method: ホモグラフィ行列を求めるための手法:以下の内の1つ: * **0** 全ての点の組を利用する通常の手法 * **CV_RANSAC** RANSACアルゴリズムに基づくロバストな手法 * **CV_LMEDS** LMedS推定(Least-Median)によるロバストな手法 :param ransacReprojThreshold: 点の組を,インライア値(外れ値ではないもの)として扱うために許容される逆投影誤差の最大値(これは,RANSACメソッドでのみ利用されます).つまり,もし .. math:: \| \texttt{dstPoints} _i - \texttt{convertPointHomogeneous} ( \texttt{H} \texttt{srcPoints} _i) \| > \texttt{ransacReprojThreshold} であれば,点 :math:`i` は外れ値であるとみなされます. ``srcPoints`` と ``dstPoints`` がピクセル単位で表されているならば,このパラメータは1から10の範囲内の値が妥当です :param status: ロバスト手法( ``CV_RANSAC`` または ``CV_LMEDS`` )を利用した場合に,オプションとして出力されるマスク. *入力マスク値は無視されることに注意してください* この関数 は,元平面と目的平面との間の透視変換 :math:`H` を求め ます: .. math:: s_i \vecthree{x'_i}{y'_i}{1} \sim H \vecthree{x_i}{y_i}{1} つまり,以下の逆投影誤差を最小化します. .. math:: \sum _i \left ( x'_i- \frac{h_{11} x_i + h_{12} y_i + h_{13}}{h_{31} x_i + h_{32} y_i + h_{33}} \right )^2+ \left ( y'_i- \frac{h_{21} x_i + h_{22} y_i + h_{23}}{h_{31} x_i + h_{32} y_i + h_{33}} \right )^2 パラメータ method がデフォルト値の 0 にセットされた場合,この関数はすべての点の組を利用して,単純な最小二乗法によりホモグラフィ行列を推定します. しかし,透視投影変換ですべての点の組( :math:`srcPoints_i` , :math:`dstPoints_i` )を一致させることができない(つまり,外れ値がある)場合でも,ロバストな手法を選択することで正しい変換を推定することができます. ``RANSAC`` と ``LMedS`` のどちらの手法も,対応する点の組のランダムな部分集合(各4組)を繰り返し生成し,この部分集合と単純な最小二乗法を用いてホモグラフィ行列を推定します.そして,求められたホモグラフィ行列の質/状態(RANSACの場合はインライアの数,LMedS推定の場合は中央値の逆投影誤差)を計算します. この最適な部分集合から,ホモグラフィ行列の初期推定値とインライア/アウトライアのマスクが生成されます. 手法がロバストかどうかにかかわらず,求められたホモグラフィ行列は,逆投影誤差がより小さくなるように,Levenberg-Marquardt 法を用いてさらに(ロバスト推定の場合はインライア値のみを利用して)高精度化されます. ``RANSAC`` を指定すると,実際にはどれだけアウトライアが混ざったデータも扱うことができますが,インライアとアウトライアを区別するための閾値が必要となります. ``LMedS`` を指定すると,この様な閾値は必要なくなりますが,データの50 % 以上がインライアでなければ正しく動作しません. また,計算された特徴点列内存在するノイズが僅かであり,アウトライアがないことが分かっている場合は,デフォルトの手法が最も良い選択です. %-- correctly only when there are more than 50 % of inliers. Finally, この関数は,内部および外部パラメータ行列の初期推定値を求めるために利用されます. ホモグラフィ行列は,スケールに依存するので, :math:`h_{33} =1` となるように正規化されます. 参考: :ref:`GetAffineTransform` , :ref:`GetPerspectiveTransform` , :ref:`EstimateRigidMotion` , :ref:`WarpPerspective` , :ref:`PerspectiveTransform` .. index:: FindStereoCorrespondenceBM cv::FindStereoCorrespondenceBM ------------------------------ .. cfunction:: void cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right, CvArr* disparity, CvStereoBMState* state ) ブロックマッチングアルゴリズムを用いて視差画像を求めます. :param left: シングルチャンネル,8ビットの左画像 :param right: 左画像と同じサイズ,同じ型の右画像 :param disparity: 出力視差マップ.シングルチャンネル,16ビット符号あり整数型,または32ビット浮動小数点型で,入力画像と同じサイズのマップです.前者の場合,計算される視差は小数点以下が4ビットの固定小数点数として表現されます(つまり,求められる視差値が16倍され,整数へと丸められたものです) :param state: ステレオ対応点探索構造体 この関数は,入力された平行化されたステレオ画像ペアに対する視差マップを計算します.(視差が計算できないような)無効なピクセルの値は ``state->minDisparity - 1`` (16ビット固定小数点視差マップの場合は, ``(state->minDisparity-1)*16`` )にセットされます .. index:: FindStereoCorrespondenceGC cv::FindStereoCorrespondenceGC ------------------------------ .. cfunction:: void cvFindStereoCorrespondenceGC( const CvArr* left, const CvArr* right, CvArr* dispLeft, CvArr* dispRight, CvStereoGCState* state, int useDisparityGuess = CV_DEFAULT(0) ) グラフカットアルゴリズムを用いて視差マップを求めます. :param left: シングルチャンネル,8ビットの左画像 :param right: 左画像と同じサイズ,同じ型の右画像 :param dispLeft: 出力オプション.シングルチャンネル,16ビット,符号あり整数.入力画像と同じサイズの左視差画像 :param dispRight: 出力オプション.シングルチャンネル,16ビット,符号あり整数.入力画像と同じサイズの右視差画像 :param state: ステレオ対応点探索構造体 :param useDisparityGuess: このパラメータが 0 でない場合,あらかじめ定義された視差マップを利用して計算が開始されます.つまり,dispLeft と dispRight が共に,妥当な視差画像である必要があります.そうでない場合,(すべてのピクセルがオクルージョンとなっている)空の視差マップから開始されます この関数は,平行化された入力ステレオ画像ペアに対する視差マップを計算します.左視差画像は,次の範囲の値を含むことに注意してください: .. math:: - \texttt{state->numberOfDisparities} - \texttt{state->minDisparity} < dispLeft(x,y) \le - \texttt{state->minDisparity} , または .. math:: dispLeft(x,y) == \texttt{CV\_STEREO\_GC\_OCCLUSION} そして,右視差画像は,次の範囲の値を含みます: .. math:: \texttt{state->minDisparity} \le dispRight(x,y) < \texttt{state->minDisparity} + \texttt{state->numberOfDisparities} または .. math:: dispRight(x,y) == \texttt{CV\_STEREO\_GC\_OCCLUSION} つまり,右視差画像と左視差画像では範囲が逆になっています.そして,マッチング結果がよくないピクセルは,オクルージョンとして処理されます. 以下は,この関数の使用例です: :: // image_left と image_right はそれぞれ, // 左右のカメラの 8 ビット,シングルチャンネルの入力画像です CvSize size = cvGetSize(image_left); CvMat* disparity_left = cvCreateMat( size.height, size.width, CV_16S ); CvMat* disparity_right = cvCreateMat( size.height, size.width, CV_16S ); CvStereoGCState* state = cvCreateStereoGCState( 16, 2 ); cvFindStereoCorrespondenceGC( image_left, image_right, disparity_left, disparity_right, state, 0 ); cvReleaseStereoGCState( &state ); // 計算された視差画像を使って,以下で好きな処理を行います ... .. 以下は,有名な Tsukuba ステレオ画像ペアから計算された出力左視差画像を,-16 倍したものです(通常,左視差画像は負の値を持つので): :: CvMat* disparity_left_visual = cvCreateMat( size.height, size.width, CV_8U ); cvConvertScale( disparity_left, disparity_left_visual, -16 ); cvSave( "disparity.pgm", disparity_left_visual ); .. .. image:: ../../pics/disparity.png .. index:: GetOptimalNewCameraMatrix cv::GetOptimalNewCameraMatrix ----------------------------- .. cfunction:: void cvGetOptimalNewCameraMatrix( const CvMat* cameraMatrix, const CvMat* distCoeffs, CvSize imageSize, double alpha, CvMat* newCameraMatrix, CvSize newImageSize=cvSize(0,0), CvRect* validPixROI=0 ) フリースケーリングパラメータに基づいて,新たなカメラ行列を返します :param cameraMatrix: 入力されるカメラ行列 :param distCoeffs: 入力される 4x1, 1x4, 5x1 または 1x5 の歪み係数ベクトル :math:`(k_1, k_2, p_1, p_2[, k_3])` :param imageSize: 最適画像サイズ :param alpha: フリースケーリングパラメータ.0(歪み補正された画像のすべてのピクセルが有効)から1(歪み補正された画像においても,元画像のすべてのピクセルを保持)の間の値をとります. :ref:`StereoRectify` を参照してください :param newCameraMatrix: 出力される新たなカメラ行列 :param newImageSize: 平行化された後の画像サイズ.デフォルトでは ``imageSize`` にセットされます :param validPixROI: オプション出力.歪み補正された画像中のすべての有効なピクセル領域を囲む矩形. :ref:`StereoRectify` の ``roi1, roi2`` の説明を参照してください この関数は,フリースケーリングパラメータに基づいて,最適な新しいカメラ行列を求め ます.このパラメータを変化させることで,ユーザは目的にあうピクセルだけを取り出したり ``alpha=0`` ,コーナーを重要視して,すべての元画像ピクセルを保持したり ``alpha=1`` ,あるいはその中間で,何か別のピクセルを得たりします.また, ``alpha>0`` の場合,歪み補正された結果には,補正前の画像の外側にある「仮想」ピクセルに対応した黒いピクセルが含まれる可能性があります.元のカメラ行列,歪み係数,求められた新しいカメラ行列,そして ``newImageSize`` は, :ref:`Remap` 用のマップを生成するために :ref:`InitUndistortRectifyMap` に渡されるべきものです. .. index:: InitIntrinsicParams2D cv::InitIntrinsicParams2D ------------------------- .. cfunction:: void cvInitIntrinsicParams2D( const CvMat* objectPoints, const CvMat* imagePoints, const CvMat* npoints, CvSize imageSize, CvMat* cameraMatrix, double aspectRatio=1.) 3次元-2次元の対応点から,カメラの内部パラメータ行列を求めます. :param objectPoints: 物体上の座評点が結合された配列. :ref:`CalibrateCamera2` を参照してください :param imagePoints: 物体上の座評の投影点が結合された配列. :ref:`CalibrateCamera2` を参照してください :param npoints: 点の個数の配列. :ref:`CalibrateCamera2` を参照してください :param imageSize: ピクセル単位で表された画像サイズ.主点を初期化するために利用されます :param cameraMatrix: 出力されるカメラ行列 :math:`\vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}` :param aspectRatio: これが0以下の場合, :math:`f_x` と :math:`f_y` は独立に推定されます.そうでない場合, :math:`f_x = f_y * \texttt{aspectRatio}` となります この関数は,キャリブレーション処理のためのカメラ行列の初期値を推定します. 現在のところ,平面のキャリブレーション器具,つまり,物体上の点の z-座標=0 となるようなもののみをサポートします. .. index:: InitUndistortMap cv::InitUndistortMap -------------------- .. cfunction:: void cvInitUndistortMap( const CvMat* cameraMatrix, const CvMat* distCoeffs, CvArr* map1, CvArr* map2 ) 歪み補正マップを求めます. :param cameraMatrix: 入力されるカメラ行列 :math:`A = \vecthreethree{fx}{0}{cx}{0}{fy}{cy}{0}{0}{1}` :param distCoeffs: 入力される 4x1, 1x4, 5x1 または 1x5 の歪み係数ベクトル :math:`(k_1, k_2, p_1, p_2[, k_3])` :param map1: 1番目の出力マップ. 型は ``CV_32FC1`` または ``CV_16SC2`` - 後者の方がより効率的です :param map2: 2番目の出力マップ. 型は ``CV_32FC1`` または ``CV_16UC1`` - 後者の方がより効率的です この関数は, :ref:`InitUndistortRectifyMap` を単純化した形式です.ここでは,平行化変換 ``R`` が単位行列と ``newCameraMatrix=cameraMatrix`` になっています. .. index:: InitUndistortRectifyMap cv::InitUndistortRectifyMap --------------------------- .. cfunction:: void cvInitUndistortRectifyMap( const CvMat* cameraMatrix, const CvMat* distCoeffs, const CvMat* R, const CvMat* newCameraMatrix, CvArr* map1, CvArr* map2 ) 歪み補正および平行化変換のマップを求めます. :param cameraMatrix: 入力されるカメラ行列 :math:`A=\vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}` :param distCoeffs: 入力される 4x1, 1x4, 5x1 または 1x5 の歪み係数ベクトル :math:`(k_1, k_2, p_1, p_2[, k_3])` :param R: オプション.物体空間における平行化変換(3x3 の行列).ここでは :ref:`StereoRectify` によって求められた ``R1`` または ``R2`` を渡すことができます.この行列が NULL だった場合,恒等変換が仮定されます :param newCameraMatrix: 新しいカメラ行列 :math:`A'=\vecthreethree{f_x'}{0}{c_x'}{0}{f_y'}{c_y'}{0}{0}{1}` :param map1: 1番目の出力マップ. 型は ``CV_32FC1`` または ``CV_16SC2`` - 後者の方がより効率的です :param map2: 2番目の出力マップ. 型は ``CV_32FC1`` または ``CV_16UC1`` - 後者の方がより効率的です この関数は,歪み補正変換と平行化変換を結合させた変換を求め,その結果を :ref:`Remap` 用のマップの形式で表現します.歪み補整された画像は,まるで,カメラ行列が ``=newCameraMatrix`` で歪みを持たないカメラで撮影したかのような画像に見えます.単眼カメラの場合,通常, ``newCameraMatrix`` は ``cameraMatrix`` と等しくなるか,あるいはスケーリングを制御する必要があれば :ref:`GetOptimalNewCameraMatrix` によって求められます.ステレオカメラの場合,通常, ``newCameraMatrix`` は :ref:`StereoRectify` によって求められた ``P1`` または ``P2`` にセットされます. また,この新しいカメラは, ``R`` に従って,個別に座標空間内での方向が決められます.これにより,例えば,ステレオカメラの両方の画像のエピポーラ線が平行で,同じy-座標を持つように各カメラを揃えることができるようになります (これは,横に並んだステレオカメラの場合です). この関数は,実際に :ref:`Remap` で利用される逆マッピングアルゴリズム用のマップを生成ます.すなわち,この関数は,(歪み補正,平行化された)出力画像の各ピクセル :math:`(u, v)` 毎に,それに対応する元画像(つまり,カメラからのオリジナル画像)の座標を求めます.その処理は,以下のようになります: .. math:: \begin{array}{l} x \leftarrow (u - {c'}_x)/{f'}_x \\ y \leftarrow (v - {c'}_y)/{f'}_y \\{[X\,Y\,W]} ^T \leftarrow R^{-1}*[x \, y \, 1]^T \\ x' \leftarrow X/W \\ y' \leftarrow Y/W \\ x" \leftarrow x' (1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + 2p_1 x' y' + p_2(r^2 + 2 x'^2) \\ y" \leftarrow y' (1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + p_1 (r^2 + 2 y'^2) + 2 p_2 x' y' \\ map_x(u,v) \leftarrow x" f_x + c_x \\ map_y(u,v) \leftarrow y" f_y + c_y \end{array} ここで :math:`(k_1, k_2, p_1, p_2[, k_3])` は,歪み係数を表します. ステレオカメラの場合,この関数は,各カメラ毎に1度ずつ,2度呼ばれます. :ref:`StereoCalibrate` の後 :ref:`StereoRectify` が呼ばれ,そしてこの関数が呼び出されます.しかし,ステレオカメラがキャリブレーションされていなかった場合でも, :ref:`StereoRectifyUncalibrated` を用いてF行列から直接,平行化変換を求めることが可能です.この関数は,各カメラに対して,3次元空間における回転行列 ``R`` ではなく,ピクセル領域における平行化変換として,ホモグラフィ行列 ``H`` を求めます. ``R`` は, ``H`` から次のようにして求めることができます: .. math:: \texttt{R} = \texttt{cameraMatrix} ^{-1} \cdot \texttt{H} \cdot \texttt{cameraMatrix} ここで ``cameraMatrix`` は,任意に選ぶことができます. .. index:: POSIT cv::POSIT --------- .. cfunction:: void cvPOSIT( CvPOSITObject* posit_object, CvPoint2D32f* imagePoints, double focal_length, CvTermCriteria criteria, CvMatr32f rotationMatrix, CvVect32f translation_vector ) POSITアルゴリズムを実行します. :param posit_object: 物体情報構造体へのポインタ :param imagePoints: 物体座標点の2次元画像平面への投影点,へのポインタ :param focal_length: 利用されるカメラの焦点距離 :param criteria: POSITアルゴリズムの反復計算に対する停止基準 :param rotationMatrix: 回転行列 :param translation_vector: 並進ベクトル この関数は,POSITアルゴリズムの実装です.画像座標は,カメラ座標系で与えられます.また,焦点距離は,カメラキャリブレーション関数を利用して取得できます.このアルゴリズムの各試行において,新たな推定姿勢の透視投影が計算されます. (前の試行と今の試行の)2つの投影間の差分ノルムは,それぞれに対応する点間の最大距離です.パラメータ ``criteria.epsilon`` は,この差が小さくなった場合にアルゴリズムを停止するために利用されます. .. index:: ProjectPoints2 cv::ProjectPoints2 ------------------ .. cfunction:: void cvProjectPoints2( const CvMat* objectPoints, const CvMat* rvec, const CvMat* tvec, const CvMat* cameraMatrix, const CvMat* distCoeffs, CvMat* imagePoints, CvMat* dpdrot=NULL, CvMat* dpdt=NULL, CvMat* dpdf=NULL, CvMat* dpdc=NULL, CvMat* dpddist=NULL ) 3次元点を画像平面に投影します. :param objectPoints: 3次元物体上の点群座標の入力配列.これは,3xN または Nx3 のシングルチャンネル配列,あるいは 1xN または Nx1 の3チャンネル配列 です.ここで N はビューの点の個数 :param rvec: 回転ベクトル. :ref:`Rodrigues2` を参照してください :param tvec: 並進ベクトル :param cameraMatrix: カメラ行列 :math:`A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}` :param distCoeffs: 入力 4x1, 1x4, 5x1 または 1x5 の歪み係数ベクトル :math:`(k_1, k_2, p_1, p_2[, k_3])` .これが NULL の場合,すべての歪み係数が0とみなされる :param imagePoints: 出力される,画像上の点の 2xN または Nx2 の1チャンネル配列,あるいは 1xN または Nx1 の2チャンネル配列. :param dpdrot: オプション.画像点を回転ベクトルの各要素に関して微分した 2Nx3 の行列 :param dpdt: オプション.画像点を並進ベクトルの各要素に関して微分した 2Nx3 の行列 :param dpdf: オプション.画像点を :math:`f_x` と :math:`f_y` に関して微分した 2Nx2 の行列 :param dpdc: オプション.画像点を :math:`c_x` と :math:`c_y` に関して微分した 2Nx2 の行列 :param dpddist: オプション.画像点を各歪み係数に関して微分した 2Nx4 の行列 この関数は,カメラの内部・外部パラメータが与えられると,3次元点を画像平面に投影します. オプションとして,この関数はヤコビ行列,つまり画像点を入力パラメータすべての関数とみなし,特定のカメラパラメータ,内部および/または外部パラメータで偏微分した行列,を求めます. 求められたヤコビ行列は, :ref:`CalibrateCamera2` , :ref:`FindExtrinsicCameraParams2` そして :ref:`StereoCalibrate` での大域的最適化において利用されます.この関数自身も,現在の内部・外部パラメータが与えられた場合の再投影誤差を求めるために利用されます. ``rvec=tvec=(0,0,0)`` ,または 3x3 の単位行列にするために ``distCoeffs=Mat()`` とセットすることによって,この関数を利用した様々な部分事例を得ることができることに注意してください.つまり,疎な点集合に対する歪んだ座標を求めたり,歪みのない理想的なものとして透視変換を適用したり(そして,その微分を求めたりも)できます. .. index:: ReprojectImageTo3D cv::ReprojectImageTo3D ---------------------- .. cfunction:: void cvReprojectImageTo3D( const CvArr* disparity, CvArr* _3dImage, const CvMat* Q, int handleMissingValues=0) 視差画像を3次元空間に再投影します. :param disparity: 入力される,シングルチャンネル,16ビット符号付き,または32ビット浮動小数点型の視差画像 :param _3dImage: 出力される,3チャンネルで ``disparity`` と同じサイズの浮動小数点型画像. ``_3dImage(x,y)`` の各要素は,視差マップから求められた点 ``(x,y)`` の3次元座標を含みます :param Q: :ref:`StereoRectify` によって得られる :math:`4 \times 4` の透視変換行列 :param handleMissingValues: これが真の場合,最小の視差を持つピクセル(これは外れ値に対応します. :ref:`FindStereoCorrespondenceBM` を参照してください)は,非常に大きいZの値(現在は 10000 にセットされています)を持つ3次元点に変換されます この関数は,1チャンネルの視差マップを,3次元面を表現する3チャンネルの画像に変換します.つまり,各ピクセル ``(x,y)`` と,それに対応する視差 ``d=disparity(x,y)`` に対して,次のように計算されます: .. math:: \begin{array}{l} [X \; Y \; Z \; W]^T = \texttt{Q} *[x \; y \; \texttt{disparity} (x,y) \; 1]^T \\ \texttt{\_3dImage} (x,y) = (X/W, \; Y/W, \; Z/W) \end{array} 行列 ``Q`` は,例えば, :ref:`StereoRectify` によって求められるような任意の :math:`4 \times 4` 行列です.疎な点集合 {(x,y,d),...} を3次元空間に再投影するためには, :ref:`PerspectiveTransform` を利用します. .. index:: RQDecomp3x3 cv::RQDecomp3x3 --------------- .. cfunction:: void cvRQDecomp3x3( const CvMat *M, CvMat *R, CvMat *Q, CvMat *Qx=NULL, CvMat *Qy=NULL, CvMat *Qz=NULL, CvPoint3D64f *eulerAngles=NULL) 3x3 行列の 'RQ' 分解を行います. :param M: 入力される :math:`3 \times 3` の浮動小数点型行列 :param R: 出力される :math:`3 \times 3` の上三角行列 :param Q: 出力される :math:`3 \times 3` の直行行列 :param Qx: オプション.x-軸周りの 3x3 の回転行列 :param Qy: オプション.y-軸周りの 3x3 の回転行列 :param Qz: オプション.z-軸周りの 3x3 の回転行列 :param eulerAngles: オプション.回転を表す3つのオイラー角 この関数は,ギブンス回転を利用して RQ 分解を行います.これは, :ref:`DecomposeProjectionMatrix` において,射影行列の左 3x3 部分行列を,カメラ行列と回転行列に分解するために利用されます. またオプションとして,各軸周りの3つの回転行列,そしてOpenGLで利用できる3つのオイラー角を 得ることができます. .. index:: ReleasePOSITObject cv::ReleasePOSITObject ---------------------- .. cfunction:: void cvReleasePOSITObject( CvPOSITObject** posit_object ) 3次元物体情報構造体を解放します. :param posit_object: 構造体 ``CvPOSIT`` へのダブルポインタ この関数は,事前に関数 :ref:`CreatePOSITObject` によって確保されたメモリを解放します. .. index:: ReleaseStereoBMState cv::ReleaseStereoBMState ------------------------ .. cfunction:: void cvReleaseStereoBMState( CvStereoBMState** state ) ブロックマッチングステレオ対応点探索構造体を解放します. :param state: 解放される構造体へのダブルポインタ この関数は,ステレオ対応点探索構造体と,関連する全ての内部バッファを解放します. .. index:: ReleaseStereoGCState cv::ReleaseStereoGCState ------------------------ .. cfunction:: void cvReleaseStereoGCState( CvStereoGCState** state ) グラフカットに基づくステレオ対応点探索アルゴリズムのための状態構造体を解放します. :param state: 解放される構造体へのダブルポインタ この関数は,ステレオ対応点探索構造体と,関連する全ての内部バッファを解放します. .. index:: Rodrigues2 cv::Rodrigues2 -------------- .. cfunction:: int cvRodrigues2( const CvMat* src, CvMat* dst, CvMat* jacobian=0 ) 回転行列と回転ベクトルを相互に変換します. :param src: 入力回転ベクトル(3x1 または 1x3),または入力回転行列(3x3) :param dst: 出力回転行列(3x3),または出力回転ベクトル(3x1 または 1x3) :param jacobian: オプションとして出力される, 3x9 または 9x3 のヤコビ行列.出力配列要素を入力配列要素で偏微分したものです .. math:: \begin{array}{l} \theta \leftarrow norm(r) \\ r \leftarrow r/ \theta \\ R = \cos{\theta} I + (1- \cos{\theta} ) r r^T + \sin{\theta} \vecthreethree{0}{-r_z}{r_y}{r_z}{0}{-r_x}{-r_y}{r_x}{0} \end{array} 以下の関係から,逆変換も簡単に行うことができます. .. math:: \sin ( \theta ) \vecthreethree{0}{-r_z}{r_y}{r_z}{0}{-r_x}{-r_y}{r_x}{0} = \frac{R - R^T}{2} 回転ベクトルは,便利で最もコンパクトな回転行列の表現方法です(すべての回転行列は丁度3自由度なので). この表現方法は, :ref:`CalibrateCamera2` , :ref:`StereoCalibrate` または :ref:`FindExtrinsicCameraParams2` のような3次元幾何学の大域的最適化処理において利用されます. .. index:: StereoCalibrate cv::StereoCalibrate ------------------- .. cfunction:: double cvStereoCalibrate( const CvMat* objectPoints, const CvMat* imagePoints1, const CvMat* imagePoints2, const CvMat* pointCounts, CvMat* cameraMatrix1, CvMat* distCoeffs1, CvMat* cameraMatrix2, CvMat* distCoeffs2, CvSize imageSize, CvMat* R, CvMat* T, CvMat* E=0, CvMat* F=0, CvTermCriteria term_crit=cvTermCriteria( CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6), int flags=CV_CALIB_FIX_INTRINSIC ) ステレオカメラのキャリブレーションを行います. :param objectPoints: 物体座標,つまり,モデル座標空間におけるキャリブレーションパターンの特徴点の結合行列.浮動小数点型の 3xN または Nx3 のシングルチャンネル配列,あるいは 1xN または Nx1 の3チャンネル配列です.ここで N は,全てのビューでの点の総数を表します :param imagePoints1: 物体座標の1番目のカメラビューへの投影点の結合行列.浮動小数点型の 2xN または Nx2 のシングルチャンネル配列,あるいは 1xN または Nx1 の2チャンネル配列です.ここで N は,全てのビューでの点の総数を表します :param imagePoints2: 物体座標の2番目のカメラビューへの投影点の結合行列.浮動小数点型の 2xN または Nx2 のシングルチャンネル配列,あるいは 1xN または Nx1 の2チャンネル配列です.ここで N は,全てのビューでの点の総数を表します :param pointCounts: 整数型で 1xM または Mx1 のベクトル(ここで Mは,キャリブレーションパターンのビューの個数を表します).この要素は,各ビューに写る座標点の個数です.ベクトル要素の合計値は, ``objectPoints`` および ``imagePoints*`` のサイズ (=N) と一致しなければいけません :param cameraMatrix1: 入出力.1番目のカメラ行列: :math:`\vecthreethree{f_x^{(j)}}{0}{c_x^{(j)}}{0}{f_y^{(j)}}{c_y^{(j)}}{0}{0}{1}` , :math:`j = 0,\, 1` もし, ``CV_CALIB_USE_INTRINSIC_GUESS`` , ``CV_CALIB_FIX_ASPECT_RATIO`` , ``CV_CALIB_FIX_INTRINSIC`` あるいは ``CV_CALIB_FIX_FOCAL_LENGTH`` のいずれかが指定される場合は,いくつかの,あるいはすべての行列要素が初期化される必要があります.flags の説明を参照してください :param distCoeffs1: 1番目のカメラに対するレンズ歪み係数.4x1, 5x1, 1x4 あるいは 1x5 の浮動小数点型ベクトル :math:`(k_1^{(j)}, k_2^{(j)}, p_1^{(j)}, p_2^{(j)}[, k_3^{(j)}])` , :math:`j = 0,\, 1` . ``CV_CALIB_FIX_K1`` , ``CV_CALIB_FIX_K2`` または ``CV_CALIB_FIX_K3`` のいずれかが指定される場合,対応する歪み係数の要素は初期化されていなければいけません :param cameraMatrix2: 入出力.2番目のカメラ行列.cameraMatrix1 と同様 :param distCoeffs2: 入出力.2番目のカメラに対するレンズ歪み係数.distCoeffs1 と同様 :param imageSize: 画像サイズ.カメラの内部行列を初期化するためだけに利用されます :param R: 出力される,1番目と2番目のカメラ座標系間の回転行列 :param T: 出力される,それぞれのカメラ座標系間の並進ベクトル :param E: オプション. 出力されるE行列 :param F: オプション. 出力されるF行列 :param term_crit: 反復最適化アルゴリズムの停止基準 :param flags: 様々なフラグ.0または以下の値の組み合わせ: * **CV_CALIB_FIX_INTRINSIC** これが指定された場合, ``distCoeffs?`` と同じく ``cameraMatrix?`` も固定され, ``R, T, E`` と ``F`` だけが推定されます * **CV_CALIB_USE_INTRINSIC_GUESS** これが指定されると,いくつかの,またはすべての(これは他のフラグに依存します)内部パラメータが最適化されます.しかし,初期値はユーザが与える必要があります * **CV_CALIB_FIX_PRINCIPAL_POINT** 最適化の間,主点が固定されます * **CV_CALIB_FIX_FOCAL_LENGTH** :math:`f^{(j)}_x` と :math:`f^{(j)}_y` が固定されます * **CV_CALIB_FIX_ASPECT_RATIO** :math:`f^{(j)}_y` が最適化されますが,比率 :math:`f^{(j)}_x/f^{(j)}_y` は固定されます * **CV_CALIB_SAME_FOCAL_LENGTH** 強制的に :math:`f^{(0)}_x=f^{(1)}_x` かつ :math:`f^{(0)}_y=f^{(1)}_y` となります * **CV_CALIB_FIX_K1, CALIB_FIX_K2, CALIB_FIX_K3** 対応する半径方向歪み係数が固定されます(その係数の値を関数に渡す必要があります) この関数は,ステレオペアを構成する2つのカメラ間の変換を推定します.2つのカメラの相対位置と相対姿勢が固定されたステレオカメラがあり,1番目のカメラと2番目のカメラに対する物体の姿勢 (R1, T1) と (R2, T2) をそれぞれ計算したとすると,これらの姿勢は明らかに互いに関係があります.つまり, ( :math:`R_1` , :math:`T_1` ) が与えられると, ( :math:`R_2` , :math:`T_2` ) を求めることができるので,我々は,2番目のカメラの1番目のカメラに対する位置と姿勢さえ知っていればよいことになります.これが,この関数の働きです.これは ( :math:`R` , :math:`T` ) を次のように求めます: .. math:: R_2=R*R_1 T_2=R*T_1 + T, またオプションとして,E 行列を求めます. .. math:: E= \vecthreethree{0}{-T_2}{T_1}{T_2}{0}{-T_0}{-T_1}{T_0}{0} *R ここで :math:`T_i` は,並進ベクトル :math:`T` : :math:`T=[T_0, T_1, T_2]^T` の要素を表します.さらに,この関数は F行列も求めることができます. .. math:: F = cameraMatrix2^{-T} E cameraMatrix1^{-1} この関数は,ステレオカメラの位置姿勢関係を求めるだけでなく,2つのカメラそれぞれの完全なキャリブレーションも行うことができます.しかし,パラメータ空間の次元が大きすぎる事や,入力データのノイズなどが原因で,最適解を得られない可能性もあります.したがって,各カメラの内部パラメータを(例えば :ref:`CalibrateCamera2` を用いて)個々に高精度に推定できるならば,そちらの方法が推奨されます.その後に,その計算された内部パラメターと ``CALIB_FIX_INTRINSIC`` フラグをこの関数に渡せばよいです.それが無理で,全てのパラメータを一度に計算する場合,いくつかのパラメータに制限を与えると良いでしょう.例えば, ``CV_CALIB_SAME_FOCAL_LENGTH`` フラグと ``CV_CALIB_ZERO_TANGENT_DIST`` フラグを指定することは,通常は妥当な仮定と言えます. :ref:`CalibrateCamera2` と同様に,この関数は,両方のカメラのすべてのビューのすべての点の再投影誤差の和を最小化します. また,この関数は,最終的な再投影誤差を返します. .. index:: StereoRectify cv::StereoRectify ----------------- .. cfunction:: void cvStereoRectify( const CvMat* cameraMatrix1, const CvMat* cameraMatrix2, const CvMat* distCoeffs1, const CvMat* distCoeffs2, CvSize imageSize, const CvMat* R, const CvMat* T, CvMat* R1, CvMat* R2, CvMat* P1, CvMat* P2, CvMat* Q=0, int flags=CV_CALIB_ZERO_DISPARITY, double alpha=-1, CvSize newImageSize=cvSize(0,0), CvRect* roi1=0, CvRect* roi2=0) キャリブレーション済みステレオの,それぞれのカメラの平行化変換を求めます. :param cameraMatrix1, cameraMatrix2: カメラ行列 :math:`\vecthreethree{f_x^{(j)}}{0}{c_x^{(j)}}{0}{f_y^{(j)}}{c_y^{(j)}}{0}{0}{1}` . :param distCoeffs1, distCoeffs2: 入力される,各カメラの歪み係数, :math:`{k_1}^{(j)}, {k_2}^{(j)}, {p_1}^{(j)}, {p_2}^{(j)} [, {k_3}^{(j)}]` :param imageSize: ステレオキャリブレーションに利用された画像サイズ :param R: 1番目と2番目のカメラの座標系間の回転行列 :param T: 1番目と2番目のカメラの座標系間の並進ベクトル :param R1, R2: 出力.それぞれ,1番目と2番目のカメラに対する :math:`3 \times 3` の平行化変換(回転行列) :param P1, P2: 出力.新しい(平行化された)座標系における :math:`3 \times 4` の射影行列 :param Q: 出力. :math:`4 \times 4` の視差-デプス間のマッピング行列. :func:`reprojectImageTo3D` を参照してください :param flags: 処理フラグ.0または ``CV_CALIB_ZERO_DISPARITY`` .このフラグがセットされている場合,関数は各カメラの主点を,平行化されたビューの同じピクセル座標にします.このフラグがセットされていない場合,関数は有効画像領域が最大になるように,画像を水平または垂直方向(これはエピポーラ線の方向に依存します)にずらす場合があります :param alpha: フリースケーリングパラメータ.これが -1 の場合,関数はデフォルトのスケーリングを行います.そうでない場合,パラメータは0から1の間の値でなくてはいけません. ``alpha=0`` は,有効なピクセルのみが見えるように,平行化された画像を拡大・並進することを意味します(つまり,平行化を行った後には黒い領域が残りません). ``alpha=1`` は,カメラから得られた元画像のすべてのピクセルが平行化後の画像にも残っているように,平行化された画像を縮小・並進することを意味します(つまり,元画像のピクセルがまったく削除されません).もちろん,中間の値は,これらの対極のケースの中間の結果を生成します :param newImageSize: 平行化後の新しい画像の解像度.これと同じサイズが :ref:`InitUndistortRectifyMap` に渡されるべきです.OpenCV サンプルディレクトリの ``stereo_calib.cpp`` を参照してください.デフォルト,つまり (0, 0) が渡された場合は,これは元画像サイズ ``imageSize`` にセットされます.より大きな値をセットすると,大きな歪みがある場合は特に,元画像のディテールを保つことができるようになります :param roi1, roi2: オプション出力.平行化された画像内の,すべてのピクセルが有効である領域を示す矩形. ``alpha=0`` の場合,ROIは画像全体を含みます.そうでない場合,おそらく,よりも小さいサイズになるでしょう.以下の図を参照してください この関数は,各カメラの回転行列を求めます.この回転行列によって,両方のカメラの画像平面が(仮想的に)同一平面に乗るように変換されます.その結果,すべてのエピポーラ線が平行になるので,多数のステレオ対応点探索問題が単純化されます.この関数は, :func:`stereoCalibrate` によって求められた行列を入力にとり,2つの回転行列と,新しい座標系における2つの投影行列を出力します.この関数は,次の2つの場合を区別します: #. 水平ステレオ.1番目のカメラと2番目のカメラのビューが互いに,主に x 軸に沿った方向にずれている状態(多少は垂直方向の移動もあるかもしれません). 平行化された画像では,左右のカメラ間のエピポーラ線は,水平,かつ,同じ y-座標(高さ)になる.P1 と P2 は,以下のようになります: .. math:: \texttt{P1} = \begin{bmatrix} f & 0 & cx_1 & 0 \\ 0 & f & cy & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} .. math:: \texttt{P2} = \begin{bmatrix} f & 0 & cx_2 & T_x*f \\ 0 & f & cy & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} , ここで, :math:`T_x` はカメラ間の水平方向のずれであり, ``CV_CALIB_ZERO_DISPARITY`` がセットされている場合は :math:`cx_1=cx_2` となります. #. 垂直ステレオ.1番目のカメラと2番目のカメラのビューが互いに,主に y 軸に沿った方向にずれている状態(これも,多少は水平方向の移動があるかもしれません). 平行化された画像でのエピポーラ線は,垂直,かつ,同じ x-座標になる.P1 と P2 は,以下のようになります: .. math:: \texttt{P1} = \begin{bmatrix} f & 0 & cx & 0 \\ 0 & f & cy_1 & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} .. math:: \texttt{P2} = \begin{bmatrix} f & 0 & cx & 0 \\ 0 & f & cy_2 & T_y*f \\ 0 & 0 & 1 & 0 \end{bmatrix} , ここで, :math:`T_y` はカメラ間の垂直方向のずれであり, ``CALIB_ZERO_DISPARITY`` がセットされている場合は :math:`cy_1=cy_2` となります. 見ての通り, ``P1`` と ``P2`` の最初の3列は,「平行化された」新たなカメラ行列そのものです. The matrices, together with ``R1`` and ``R2`` , can then be passed to :ref:`InitUndistortRectifyMap` to initialize the rectification map for each camera. 以下は, ``stereo_calib.cpp`` サンプルのスクリーンショットです.ここに示される赤い水平線は,対応する画像領域を通過しています.つまり,(多くのステレオ対応点探索アルゴリズムが前提とするように)両方の画像が綺麗に平行化されていることが分かります.また,緑の矩形は, ``roi1`` と ``roi2`` を示し,その中が確かにすべて有効なピクセルであることが分かります. .. image:: ../../pics/stereo_undistort.jpg .. index:: StereoRectifyUncalibrated cv::StereoRectifyUncalibrated ----------------------------- .. cfunction:: void cvStereoRectifyUncalibrated( const CvMat* points1, const CvMat* points2, const CvMat* F, CvSize imageSize, CvMat* H1, CvMat* H2, double threshold=5 ) キャリブレーションされていないステレオの,それぞれのカメラの平行化変換を求めます. :param points1, points2: 対応する2次元点を表すの2つの配列. :ref:`FindFundamentalMat` でサポートされるものと同じフォーマットです :param F: 入力されるF行列. :ref:`FindFundamentalMat` を利用して,これと同じ点ペアの集合から計算することができます :param imageSize: 画像サイズ :param H1, H2: 出力される,1番目と2番目の画像に対する平行化ホモグラフィ行列 :param threshold: 外れ値を除外するために用いられるオプションの閾値.このパラメータが0より大きい場合,ホモグラフィ行列を計算する前に,エピポーラ幾何に十分に従わない(つまり, :math:`|\texttt{points2[i]}^T*\texttt{F}*\texttt{points1[i]}|>\texttt{threshold}` となる)すべての点ペアが棄却されます.そうでない場合,つまりパラメータが0以下の場合は,すべての点がインライアであると見なされます この関数は,カメラの内部パラメータや空間の相対的位置を必要とすることな く,平行化変換を求めます.なので,「Uncalibrated」という接尾辞がついています. :ref:`StereoRectify` とのもう一つの違いとして,関数の出力が,物体(3次元)空間における平行化変換ではなく,ホモグラフィ行列 ``H1`` と ``H2`` によってエンコードされた平面透視変換となることが挙げられます.この関数は,アルゴリズム Hartley99 の実装です. このアルゴリズムは,カメラの内部パラメータを知る必要はありませんが,エピポーラ幾何に大きく依存していることに注意してください.したがって,カメラレンズが大きく歪んでいる場合は,F行列を計算してこの関数を呼び出すよりも前に,歪みを補正しておくのが賢明です.例えば,ステレオの各カメラの歪み係数は, :ref:`CalibrateCamera2` を用いて個別に推定できます.画像は :ref:`Undistort2` によって,点座標だけならば :ref:`UndistortPoints` によって補正することが可能です. .. index:: Undistort2 cv::Undistort2 -------------- .. cfunction:: void cvUndistort2( const CvArr* src, CvArr* dst, const CvMat* cameraMatrix, const CvMat* distCoeffs, const CvMat* newCameraMatrix=0 ) レンズ歪みを補正するように画像を変形させます. :param src: (歪んだ)入力画像 :param dst: (補正された)出力画像. ``src`` と同じサイズ,同じ型 :param cameraMatrix: 入力されるカメラ行列 :math:`A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}` :param distCoeffs: 歪み係数ベクトル, :math:`(k_1^{(j)}, k_2^{(j)}, p_1^{(j)}, p_2^{(j)}[, k_3^{(j)}])` この関数は,半径方向および円周方向のレンズ歪みを補正するように画像を変換します. この関数は,単に :ref:`InitUndistortRectifyMap` ( ``R`` は単位行列)と :ref:`Remap` (バイリニア補間)を組み合わせたものです.変換の詳細については,前述の関数を参照してください. 元画像に対応するピクセルが存在しないような出力画像のピクセルは,0(黒色)で埋められます. 補正された画像内に残っている元画像の部分画像は ``newCameraMatrix`` で制御できます.ユーザは,必要に応じた適切な ``newCameraMatrix`` を求めるために :ref:`GetOptimalNewCameraMatrix` を利用することができます. これらのカメラ行列と歪みパラメータは :ref:`CalibrateCamera2` を用いて決定できます. 画像の解像度がキャリブレーション時と異なる場合,歪み係数はそのままで構いませんが, :math:`f_x, f_y, c_x` および :math:`c_y` を適宜スケーリングする必要があります .. index:: UndistortPoints cv::UndistortPoints ------------------- .. cfunction:: void cvUndistortPoints( const CvMat* src, CvMat* dst, const CvMat* cameraMatrix, const CvMat* distCoeffs, const CvMat* R=NULL, const CvMat* P=NULL) 観測された点座標から,理想的な点座標を求めます. :param src: 観測された点座標. :ref:`ProjectPoints2` の ``imagePoints`` と同じフォーマット :param dst: 歪み補正および逆透視変換された後に出力される,理想的な点座標. ``src`` と同じフォーマット :param cameraMatrix: カメラ行列 :math:`\vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}` :param distCoeffs: 歪み係数のベクトル :math:`(k_1^{(j)}, k_2^{(j)}, p_1^{(j)}, p_2^{(j)}[, k_3^{(j)}])` :param R: 物体空間における平行化変換(3x3 の行列). :func:`StereoRectify` によって求められる ``R1`` または ``R2`` のどちらかが,ここに渡されます.この行列が空の場合,単位行列が変換行列として利用されます :param P: 新たなカメラ行列(3x3)または,新たな射影行列(3x4). :func:`StereoRectify` によって求められる ``P1`` or ``P2`` のどちらかが,ここに渡されます.この行列がemptyの場合,単位行列が新たなカメラ行列として利用されます この関数は, :ref:`Undistort2` や :ref:`InitUndistortRectifyMap` と似ていますが,ラスタ画像の代わりに,疎な点集合を扱います.また, :ref:`ProjectPoints2` に対する逆変換のような処理も行います(3次元物体の場合は,当然その3次元座標を再構成するわけではありません.しかし,平面物体の場合は,適切な ``R`` が指定されれば,並進ベクトル次第で,そのようなことも起こります). :: // (u,v) は入力点座標, (u', v') は出力点座標 // camera_matrix=[fx 0 cx; 0 fy cy; 0 0 1] // P=[fx' 0 cx' tx; 0 fy' cy' ty; 0 0 1 tz] x" = (u - cx)/fx y" = (v - cy)/fy (x',y') = undistort(x",y",dist_coeffs) [X,Y,W]T = R*[x' y' 1]T x = X/W, y = Y/W u' = x*fx' + cx' v' = y*fy' + cy', .. ここで undistort() は,正規化された歪んだ点座標から,正規化されたオリジナルの点座標を推定する,反復近似アルゴリズムです(「正規化された」というのは,座標がカメラ行列に依存しないという意味です). この関数は,ステレオの各カメラや単眼カメラに対して用いることができます(Rは NULL ).