画像の幾何学変換 ======================== .. highlight:: cpp このサブセクションで述べる関数は,2次元画像の様々な幾何学変換を行います.つまり,画像の内容は変更せずにピクセルグリッドだけを変形し,変形したグリッドを出力画像にマッピングします.実際には,サンプリングによる余計な値や不定な値を排除するために,出力画像から入力画像という逆方向へのマッピングが行われます.つまり,出力画像の各ピクセル :math:`(x, y)` に対して,入力画像中の対応する「ドナー」ピクセルの座標を求め,そのピクセル値をコピーします: .. math:: \texttt{dst} (x,y)= \texttt{src} (f_x(x,y), f_y(x,y)) ユーザが正順のマッピング: :math:`\left: \texttt{src} \rightarrow \texttt{dst}` を指定した場合,OpenCV の関数は最初に,対応する逆マッピング: :math:`\left: \texttt{dst} \rightarrow \texttt{src}` を求めてから上述の式を利用します. 幾何学変換の実際の実装では,最も汎用的な :func:`remap` から,最も単純で高速な :func:`resize` まで,上述の式を用いて2つの主な問題を解く必要があります: #. 存在しないピクセルの外挿. フィルタリング関数 と同様に,ある :math:`(x,y)` に対して, :math:`f_x(x,y)` または :math:`f_y(x,y)` のどちらか,あるいは両方が画像の外側にはみ出してしまう可能性があります.この場合,何らかの外挿手法が必要になります.OpenCVでは,フィルタリング関数の場合と同じく,いくつかの外挿手法が提供されています.さらに別の手法も追加されており,その ``BORDER_TRANSPARENT`` は,出力画像中の対応するピクセルが全く変更されないことを意味します. #. ピクセル値の内挿.通常 :math:`f_x(x,y)` と :math:`f_y(x,y)` は,浮動小数点数(つまり, :math:`\left` は,アフィン変換,透視変換,または半径方向のレンズ歪み係数など)です.よって,小数点座標上に存在するピクセル値が必要になります.最も単純なケースでは,この座標は単に最も近い整数値の座標に丸められ,そこのピクセル値が利用されます.これは,最近傍補間と呼ばれます.しかし,より洗練された `補間手法 `_ を用いることで,より良い結果が得られます.この場合,求められたピクセル :math:`(f_x(x,y), f_y(x,y))` 近傍に対して多項式関数をフィッティングし, :math:`(f_x(x,y), f_y(x,y))` における多項式の値を,補間されたピクセル値として利用します.OpenCVでは,複数の補間手法から選択することができます.詳しくは :func:`resize` を参照してください. .. index:: convertMaps cv::convertMaps --------------- `id=0.175523867635 Comments from the Wiki `__ .. cfunction:: void convertMaps( const Mat\& map1, const Mat\& map2, Mat\& dstmap1, Mat\& dstmap2, int dstmap1type, bool nninterpolation=false ) 画像変換マップを,ある表現から別の表現へ変換します. :param map1: 1番目の入力マップ.型は ``CV_16SC2`` , ``CV_32FC1`` , ``CV_32FC2`` のいずれか :param map2: 2番目の入力マップ.型は ``CV_16SC1`` , ``CV_32FC1`` , あるいはそれぞれに対する none (空の行列) のいずれか :param dstmap1: 1番目の出力マップ. ``dstmap1type`` で指定される型, ``src`` と同じサイズ :param dstmap2: 2番目の出力マップ :param dstmap1type: 1番目の出力マップの型. ``CV_16SC2`` , ``CV_32FC1`` あるいは ``CV_32FC2`` のいずれか :param nninterpolation: 最近傍補間,または,より複雑な補間手法に対して,浮動小数点型のマップが利用されるか否かを指定します この関数は, :func:`remap` 用のマップの組を,ある表現から別の表現へ変換します.以下のオプション( ``(map1.type(), map2.type())`` :math:`\rightarrow` ``(dstmap1.type(), dstmap2.type())`` )がサポートされます: #. :math:`\texttt{(CV\_32FC1, CV\_32FC1)} \rightarrow \texttt{(CV\_16SC2, CV\_16UC1)}` . これは,最も頻繁に利用される変換処理です.元の浮動小数点型マップ( :func:`remap` を参照してください)は,よりコンパクトで非常に高速な浮動小数点型の表現に変換されます.1番目の出力配列は丸められた座標値を表し,2番目の出力配列(ただし, ``nninterpolation=false`` の場合のみ作られます)は,補間テーブルのインデックスを表します. #. :math:`\texttt{(CV\_32FC2)} \rightarrow \texttt{(CV\_16SC2, CV\_16UC1)}` . 上述の場合と同じですが,元のマップは1つの2チャンネル行列に格納されます. #. 逆変換.当然ながら,再構成された浮動小数点型マップは元のマップとは正確には一致しません. 参考: :func:`remap` , :func:`undisort` , :func:`initUndistortRectifyMap` .. index:: getAffineTransform cv::getAffineTransform ---------------------- `id=0.381209834291 Comments from the Wiki `__ .. cfunction:: Mat getAffineTransform( const Point2f src[], const Point2f dst[] ) 3組の対応点からアフィン変換を求めます. :param src: 入力画像上の三角形の頂点の座標 :param dst: 出力画像上の対応する三角形の頂点の座標 この関数は,アフィン変換を表す :math:`2 \times 3` の行列を求めます: .. math:: \begin{bmatrix} x'_i \\ y'_i \end{bmatrix} = \texttt{map\_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix} ここで .. math:: dst(i)=(x'_i,y'_i), src(i)=(x_i, y_i), i=0,1,2 となります. 参考: :func:`warpAffine` , :func:`transform` .. index:: getPerspectiveTransform cv::getPerspectiveTransform --------------------------- `id=0.509584426975 Comments from the Wiki `__ .. cfunction:: Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] ) 4組の対応点から透視変換を求めます. :param src: 入力画像上の四角形の頂点の座標 :param dst: 出力画像上の対応する四角形の頂点の座標 この関数は,透視変換を表す :math:`3 \times 3` の行列を求めます: .. math:: \begin{bmatrix} t_i x'_i \\ t_i y'_i \\ t_i \end{bmatrix} = \texttt{map\_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix} ここで .. math:: dst(i)=(x'_i,y'_i), src(i)=(x_i, y_i), i=0,1,2 となります 参考: :func:`findHomography` , :func:`warpPerspective` , :func:`perspectiveTransform` .. index:: getRectSubPix cv::getRectSubPix ----------------- `id=0.781577743342 Comments from the Wiki `__ .. cfunction:: void getRectSubPix( const Mat\& image, Size patchSize, Point2f center, Mat\& dst, int patchType=-1 ) 画像から,矩形領域のピクセル値をサブピクセル精度で取得します. :param src: 入力画像 :param patchSize: 抽出される部分のサイズ :param center: 入力画像から抽出される矩形の中心を表す,浮動小数点型の座標.この中心は,画像内に存在しなければいけません :param dst: 抽出される部分.サイズは ``patchSize`` で, ``src`` と同じチャンネル数になります :param patchType: 抽出されるピクセルのビット深度.デフォルトでは, ``src`` のビット深度と同じになります 関数 ``getRectSubPix`` は, ``src`` からピクセルを抽出します: .. math:: dst(x, y) = src(x + \texttt{center.x} - ( \texttt{dst.cols} -1)*0.5, y + \texttt{center.y} - ( \texttt{dst.rows} -1)*0.5) ここで,非整数の座標におけるピクセル値は,バイリニア補間を用いて取得されます.また,マルチチャンネル画像の各チャンネルは,それぞれ個別に処理されます.矩形領域の中心は,必ず画像内部になければいけませんが,矩形領域の一部が画像外部にはみ出していても構いません.その場合は,画像外にある領域のピクセル値を取得するために,複製境界モード( :func:`borderInterpolate` を参照してください)が利用されます. 参考: :func:`warpAffine` , :func:`warpPerspective` .. index:: getRotationMatrix2D cv::getRotationMatrix2D ----------------------- `id=0.0411010852488 Comments from the Wiki `__ .. cfunction:: Mat getRotationMatrix2D( Point2f center, double angle, double scale ) 2次元回転を表すアフィン変換を求めます. :param center: 入力画像中にある回転中心 :param angle: 度単位で表される回転角度.正の値は反時計回りを意味します(座標原点が,左上コーナーにあると仮定されます) :param scale: 等方性のスケールファクタ この関数は,以下の行列を求める: .. math:: \begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot \texttt{center.x} - \beta \cdot \texttt{center.y} \\ - \beta & \alpha & \beta \cdot \texttt{center.x} - (1- \alpha ) \cdot \texttt{center.y} \end{bmatrix} ここで .. math:: \begin{array}{l} \alpha = \texttt{scale} \cdot \cos \texttt{angle} , \\ \beta = \texttt{scale} \cdot \sin \texttt{angle} \end{array} となります. この変換は,回転中心をそれ自身にマップします.そうしたくない場合は,シフトによる調整を行う必要があります. 参考: :func:`getAffineTransform` , :func:`warpAffine` , :func:`transform` .. index:: invertAffineTransform cv::invertAffineTransform ------------------------- `id=0.0468821932591 Comments from the Wiki `__ .. cfunction:: void invertAffineTransform(const Mat\& M, Mat\& iM) アフィン変換の逆変換を求めます. :param M: 元のアフィン変換 :param iM: 出力される逆アフィン変換 この関数は, :math:`2 \times 3` の行列 ``M`` で表されたアフィン変換の逆変換を求めます: .. math:: \begin{bmatrix} a_{11} & a_{12} & b_1 \\ a_{21} & a_{22} & b_2 \end{bmatrix} その結果は, ``M`` と同じ型の :math:`2 \times 3` の行列になります. .. index:: remap cv::remap --------- `id=0.0945619001266 Comments from the Wiki `__ .. cfunction:: void remap( const Mat\& src, Mat\& dst, const Mat\& map1, const Mat\& map2, int interpolation, int borderMode=BORDER_CONSTANT, const Scalar\& borderValue=Scalar()) 画像に対して,汎用的な幾何学変換を適用します. :param src: 入力画像 :param dst: 出力画像. ``map1`` と同じサイズ, ``src`` と同じタイプ :param map1: 型 ``CV_16SC2`` , ``CV_32FC1`` あるいは ``CV_32FC2`` である座標点 ``(x,y)`` ,または単なる値 ``x`` の1番目のマップ.高速化のために浮動小数点表現から固定小数点表現に変換する方法については, :func:`convertMaps` を参照してください :param map2: 型 ``CV_16UC1`` , ``CV_32FC1`` あるいは none(map1 が ``(x,y)`` である場合は空のマップ) である値 ``y`` の2番目のマップ :param interpolation: 補間手法. :func:`resize` を参照してください. ``INTER_AREA`` メソッドは,この関数ではサポートされません :param borderMode: ピクセル外挿手法. :func:`borderInterpolate` を参照してください. \ borderMode= ``BORDER_TRANSPARENT`` の場合,入力画像中の「はずれ値」に対応する出力画像中のピクセルが,この関数によって変更されないことを意味します :param borderValue: 定数境界モードで利用されるピクセル値.デフォルトでは 0 関数 ``remap`` は,指定されたマップを用いて入力画像を変換します: .. math:: \texttt{dst} (x,y) = \texttt{src} (map_x(x,y),map_y(x,y)) 非整数の座標値を持つピクセルの値は,有効な補間手法の1つを用いて求められます. :math:`map_x` と :math:`map_y` は,それぞれ個別の浮動小数点型マップ :math:`map_1` と :math:`map_2` としてエンコードされるか,または :math:`(x,y)` のインタリーブされた1つの浮動小数点型マップ :math:`map_1` ,あるいは :func:`convertMaps` を利用して作成された固定小数点型マップとしてエンコードされます.マップが浮動小数点表現から固定小数点表現に変換されるとすれば,その理由は幾何学変換処理が大幅に高速化される(約2倍)からです.変換された場合, :math:`map_1` は ``(cvFloor(x), cvFloor(y))`` というペアを表し, :math:`map_2` は補間係数テーブルのインデックスを表します. この関数は,置換モードでは動作しません. .. index:: resize cv::resize ---------- `id=0.792931809116 Comments from the Wiki `__ .. cfunction:: void resize( const Mat\& src, Mat\& dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR ) 画像のサイズを変更します. :param src: 入力画像 :param dst: 出力画像.サイズは ``dsize`` (0でない場合)か,または ``src.size()`` , ``fx`` , ``fy`` から計算される値になります. ``dst`` の型は, ``src`` と同じになります :param dsize: 出力画像サイズ.これが0の場合,次のように計算されます: .. math:: \texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))} . 必ず ``dsize`` が非0,あるいは ``fx`` と ``fy`` の両方が非0,でなければいけません :param fx: 水平軸方向のスケールファクタ.これが0の場合,次のように計算されます: .. math:: \texttt{(double)dsize.width/src.cols} :param fy: 垂直軸方向のスケールファクタ.これが0の場合,次のように計算されます: .. math:: \texttt{(double)dsize.height/src.rows} :param interpolation: 補間手法: * **INTER_NEAREST** 最近傍補間 * **INTER_LINEAR** バイリニア補間(デフォルト) * **INTER_AREA** ピクセル領域の関係を利用したリサンプリング.画像を大幅に縮小する場合は,モアレを避けることができる良い手法です.しかし,画像を拡大する場合は, ``INTER_NEAREST`` メソッドと同様になります * **INTER_CUBIC** 4x4 の近傍領域を利用するバイキュービック補間 * **INTER_LANCZOS4** 8x8 の近傍領域を利用する Lanczos法の補間 関数 ``resize`` は,画像 ``src`` を指定されたサイズに縮小,あるいは拡大します. ``dst`` の型やサイズは考慮されないことに注意してください.その代わり,型やサイズは ``src`` , ``dsize`` , ``fx`` そして ``fy`` から求められます.あらかじめ用意しておいた ``dst`` とぴったり同じになるように ``src`` のサイズを変更したい場合,次のような関数呼び出しができます: .. code-block:: c // dsize=dst.size(); を明示的に指定します. fx と fy はここから計算されます. resize(src, dst, dst.size(), 0, 0, interpolation); .. 各方向に二分の一に縮小したい場合は,次のような関数呼び出しができます: .. code-block:: c // fx とfy を定して,関数に出力画像サイズを計算させます. resize(src, dst, Size(), 0.5, 0.5, interpolation); .. 参考: :func:`warpAffine` , :func:`warpPerspective` , :func:`remap` . .. index:: warpAffine cv::warpAffine -------------- `id=0.548138954586 Comments from the Wiki `__ .. cfunction:: void warpAffine( const Mat\& src, Mat\& dst, const Mat\& M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar\& borderValue=Scalar()) 画像のアフィン変換を行います. :param src: 入力画像 :param dst: サイズが ``dsize`` で ``src`` と同じタイプの出力画像 :param M: :math:`2\times 3` の変換行列 :param dsize: 出力画像のサイズ :param flags: 補間手法( :func:`resize` を参照してください)と, ``M`` が逆変換( ``dst`` :math:`\rightarrow` ``src`` )であることを意味するオプションフラグ ``WARP_INVERSE_MAP`` の組み合わせ :param borderMode: ピクセル外挿手法. :func:`borderInterpolate` を参照してください. \ ``borderMode = BORDER_TRANSPARENT`` の場合,入力画像中の「はずれ値」に対応する出力画像中のピクセルが,この関数では変更されないことを意味します :param borderValue: 定数境界モードで利用されるピクセル値.デフォルトでは 0 です 関数 ``warpAffine`` は,指定された行列を用いて入力画像を変換します: .. math:: \texttt{dst} (x,y) = \texttt{src} ( \texttt{M} _{11} x + \texttt{M} _{12} y + \texttt{M} _{13}, \texttt{M} _{21} x + \texttt{M} _{22} y + \texttt{M} _{23}) ここでは,フラグ ``WARP_INVERSE_MAP`` が設定されています.そうでない場合は,まず :func:`invertAffineTransform` によって逆変換が求められ,それが上式の ``M`` の代わりに利用されます. この関数は,置換モードでは動作しません. 参考: :func:`warpPerspective` , :func:`resize` , :func:`remap` , :func:`getRectSubPix` , :func:`transform` .. index:: warpPerspective cv::warpPerspective ------------------- `id=0.405908350864 Comments from the Wiki `__ .. cfunction:: void warpPerspective( const Mat\& src, Mat\& dst, const Mat\& M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar\& borderValue=Scalar()) 画像の透視変換を行います. :param src: 入力画像 :param dst: サイズが ``dsize`` で ``src`` と同じタイプの出力画像 :param M: :math:`2\times 3` の変換行列 :param dsize: 出力画像のサイズ :param flags: 補間手法( :func:`resize` を参照)と, ``M`` が逆変換( ``dst`` :math:`\rightarrow` ``src`` )であることを意味するオプションフラグ ``WARP_INVERSE_MAP`` の組み合わせ :param borderMode: ピクセル外挿手法. :func:`borderInterpolate` を参照してください. \ ``borderMode=BORDER_TRANSPARENT`` の場合,入力画像中の「はずれ値」に対応する出力画像中のピクセルが,この関数では変更されないことを意味します :param borderValue: 定数境界モードで利用されるピクセル値.デフォルトでは 0 です 関数 ``warpPerspective`` は,指定された行列を用いて入力画像を変換します: .. math:: \texttt{dst} (x,y) = \texttt{src} \left ( \frac{M_{11} x + M_{12} y + M_{13}}{M_{31} x + M_{32} y + M_{33}} , \frac{M_{21} x + M_{22} y + M_{23}}{M_{31} x + M_{32} y + M_{33}} \right ) ここでは,フラグ ``WARP_INVERSE_MAP`` が設定されています.そうでない場合は,まず :func:`invert` によって逆変換が求められ,それが上式の ``M`` の代わりに利用されます. この関数は,置換モードでは動作しない. 参考: :func:`warpAffine` , :func:`resize` , :func:`remap` , :func:`getRectSubPix` , :func:`perspectiveTransform`