画像フィルタリング =========================== .. highlight:: cpp このセクションで述べる関数およびクラスを利用して, ( :func:`Mat` で表現された) 2次元画像に対して,様々な線形・非線形のフィルタリング処理を行います.このフィルタリング処理では,入力画像の各ピクセル位置 :math:`(x,y)` の近傍領域(通常は矩形)を利用して出力値を求めます.この出力は,線形フィルタの場合はピクセル値の重み付き和,モルフォロジー演算の場合は,最大値・最小値となります.求められた出力は,出力画像上の同じ位置 :math:`(x,y))` に保存されます.これはつまり,出力画像が入力画像と同じサイズになることを意味します.また通常,関数はマルチチャンネル配列をサポートしており,各チャンネルが個別に処理されるので,出力画像のチャンネル数も入力画像と同じ数になります. このセクションで述べる関数とクラスに共通するもう1つの特徴は,これらは単純な算術関数とは異なり,存在しないピクセルの値を外挿する必要があるということです.例えば, :math:`3 \times 3` のガウシアンフィルタを用いて画像の平滑化を行いたい場合,各行の左端のピクセルを処理する際に,さらにその左側,つまり,画像外のピクセルが必要となります.このようなピクセルを,画像の左端のピクセルと同じものだと仮定する(つまり,「複製境界」外挿法),あるいは,存在しないすべてのピクセルを 0 とする(つまり,「定数境界」外挿法)などの処理が可能です. OpenCV では,ユーザがこの外挿手法を指定することができます.関数 :func:`borderInterpolate` および,以下で述べる様々な関数のパラメータ ``borderType`` の説明を参照してください. .. index:: BaseColumnFilter .. _BaseColumnFilter: BaseColumnFilter ---------------- .. ctype:: BaseColumnFilter 1列カーネルを用いたフィルタの基底クラス. :: class BaseColumnFilter { public: virtual ~BaseColumnFilter(); // ユーザによってオーバーライドされます. // // 入力の "dstcount + ksize - 1" 行目と, // 出力の "dstcount" 行目という // 行の集合に対して,フィルタリングオペレータを実行します. // 各入力行と出力行は, "width" 個の要素をもちます. // フィルタリング処理された行は "dst" バッファに書き込まれます. virtual void operator()(const uchar** src, uchar* dst, int dststep, int dstcount, int width) = 0; // フィルタ状態をリセットします( IIR フィルタで必要になる場合がある) virtual void reset(); int ksize; // アパーチャサイズ int anchor; // アンカー点の位置, // 通常,処理中には利用されません. }; .. ``BaseColumnFilter`` クラスは,1列カーネルを用いたフィルタリングのための基底クラスです.このフィルタリングは,必ずしも線形処理である必要はありません.一般的に,この処理は次のように書かれます: .. math:: \texttt{dst} (x,y) = F( \texttt{src} [y](x), \; \texttt{src} [y+1](x), \; ..., \; \texttt{src} [y+ \texttt{ksize} -1](x) ここで :math:`F` はフィルタリング関数ですが,実際にはクラスとして表現されています.それによる副次的な影響が発生することもありますし,クラスなので以前に処理したデータを記憶しておくことも可能です.このクラスは,インタフェースを定義するだけで直接は利用されません.その代わり,OpenCV には具体的なフィルタリング処理を実装した派生クラスへのポインタを返す関数が複数存在します(そして,ユーザが追加することも可能です).これらのポインタは, :func:`FilterEngine` コンストラクタに渡されます.フィルタリング処理のインタフェースは ``uchar`` 型を利用しますが,個々の実装は8ビットデータに限定されません. 参考: :func:`BaseRowFilter` , :func:`BaseFilter` , :func:`FilterEngine` , :func:`getColumnSumFilter` , :func:`getLinearColumnFilter` , :func:`getMorphologyColumnFilter` .. index:: BaseFilter .. _BaseFilter: BaseFilter ---------- .. ctype:: BaseFilter 2次元画像フィルタの基底クラス. :: class BaseFilter { public: virtual ~BaseFilter(); // ユーザによってオーバーライドされます. // // 入力の "dstcount + ksize.height - 1" 行目と, // 出力の "dstcount" 行目という // 行の集合に対して,フィルタリングオペレータを実行します. // 各入力行は "(width + ksize.width-1)*cn" 個の要素をもち, // 各出力行は "width*cn" 個の要素をもちます. // フィルタリング処理された行は "dst" バッファに書き込まれます. virtual void operator()(const uchar** src, uchar* dst, int dststep, int dstcount, int width, int cn) = 0; // フィルタ状態をリセットします( IIR フィルタで必要になる場合がある) virtual void reset(); Size ksize; Point anchor; }; .. ``BaseFilter`` クラスは,2次元カーネルを利用したフィルタリングのための基底クラスです.このフィルタリングは,必ずしも線形処理である必要はありません.一般的に,この処理は次のように書かれます: .. math:: \begin{array}{l} \texttt{dst} (x,y) = F( \texttt{src} [y](x), \; \texttt{src} [y](x+1), \; ..., \; \texttt{src} [y](x+ \texttt{ksize.width} -1), \\ \texttt{src} [y+1](x), \; \texttt{src} [y+1](x+1), \; ..., \; \texttt{src} [y+1](x+ \texttt{ksize.width} -1), \\ ......................................................................................... \\ \texttt{src} [y+ \texttt{ksize.height-1} ](x), \\ \texttt{src} [y+ \texttt{ksize.height-1} ](x+1), \\ ... \texttt{src} [y+ \texttt{ksize.height-1} ](x+ \texttt{ksize.width} -1)) \end{array} ここで :math:`F` はフィルタリング関数を表します.このクラスは,インタフェースを定義するだけで直接は利用されません.その代わり,OpenCV には具体的なフィルタリング処理を実装した派生クラスへのポインタを返す関数が複数存在します(そして,ユーザが追加することもできます).これらのポインタは, :func:`FilterEngine` コンストラクタに渡されます.フィルタリング処理のインタフェースは ``uchar`` 型を利用しますが,個々の実装は8ビットデータに限定されません. 参考: :func:`BaseColumnFilter` , :func:`BaseRowFilter` , :func:`FilterEngine` , :func:`getLinearFilter` , :func:`getMorphologyFilter` .. index:: BaseRowFilter .. _BaseRowFilter: BaseRowFilter ------------- .. ctype:: BaseRowFilter 1行カーネルを用いたフィルタの基底クラス. :: class BaseRowFilter { public: virtual ~BaseRowFilter(); // ユーザによってオーバーライドされます. // // "width" 個の要素を持つ1入力行に対して,フィルタリング処理を行います. // 各要素は, "cn" チャンネルをもちます. // フィルタリング処理された行は "dst" バッファに書き込まれます. virtual void operator()(const uchar* src, uchar* dst, int width, int cn) = 0; int ksize, anchor; }; .. ``BaseRowFilter`` クラスは,1行カーネルを用いたフィルタリングのための基底クラスです.このフィルタリングは,必ずしも線形処理である必要はありません.一般的に,この処理は次のように書かれます: .. math:: \texttt{dst} (x,y) = F( \texttt{src} [y](x), \; \texttt{src} [y](x+1), \; ..., \; \texttt{src} [y](x+ \texttt{ksize.width} -1)) ここで :math:`F` はフィルタリング関数を表します.このクラスは,インタフェースを定義するだけで直接は利用されません.その代わり,OpenCV には具体的なフィルタリング処理を実装した派生クラスへのポインタを返す関数が複数存在します(そして,ユーザが追加することもできます).これらのポインタは, :func:`FilterEngine` コンストラクタに渡されます.フィルタリング処理のインタフェースは ``uchar`` 型を利用しますが,個々の実装は8ビットデータに限定されません. 参考: :func:`BaseColumnFilter` , :func:`Filter` , :func:`FilterEngine` , :func:`getLinearRowFilter` , :func:`getMorphologyRowFilter` , :func:`getRowSumFilter` .. index:: FilterEngine .. _FilterEngine: FilterEngine ------------ .. ctype:: FilterEngine 汎用画像フィルタリングクラス. :: class FilterEngine { public: // 引数をとらないコンストラクタ FilterEngine(); // 2次元の非分離型フィルタ (!_filter2D.empty()) あるいは // 分離型フィルタ (!_rowFilter.empty() && !_columnFilter.empty()) を作成します. // 入力データの型は "srcType" ,出力データの型は "dstType" // 中間データの型は "bufType" となります. // _rowBorderType と_columnBorderType は,画像外の値が // どのように外挿補間されるかを決定します. // _borderValue は, _rowBorderType と _columnBorderType の片方, // あるいは両方が == cv::BORDER_CONSTANT である場合にのみ利用されます. FilterEngine(const Ptr& _filter2D, const Ptr& _rowFilter, const Ptr& _columnFilter, int srcType, int dstType, int bufType, int _rowBorderType=BORDER_REPLICATE, int _columnBorderType=-1, // デフォルトでは _rowBorderType を利用 const Scalar& _borderValue=Scalar()); virtual ~FilterEngine(); // フィルタリングエンジン初期化のための別関数 void init(const Ptr& _filter2D, const Ptr& _rowFilter, const Ptr& _columnFilter, int srcType, int dstType, int bufType, int _rowBorderType=BORDER_REPLICATE, int _columnBorderType=-1, const Scalar& _borderValue=Scalar()); // サイズ "wholeSize" の画像中の ROI に対してフィルタリングを開始します. // 元画像における開始点の y 座標を返します. virtual int start(Size wholeSize, Rect roi, int maxBufRows=-1); // "wholeSize" の代わりに画像自身を引数にとる, // start のもう1つの形式.isolated を true に設定すると, // ROI の外側には実際のピクセルが存在しないことになります. // (指定の境界モードで,ピクセルを外挿補間したい場合に利用します) virtual int start(const Mat& src, const Rect& srcRoi=Rect(0,0,-1,-1), bool isolated=false, int maxBufRows=-1); // 入力画像の次の部分画像,つまり // "src" から始まる "srcCount" 行分を処理し, // 結果を "dst" に格納します. // また,作成された行数を返します. virtual int proceed(const uchar* src, int srcStep, int srcCount, uchar* dst, int dstStep); // ROI 全体,あるいは画像全体を, // 一度の関数呼び出しで処理する高レベル関数 virtual void apply( const Mat& src, Mat& dst, const Rect& srcRoi=Rect(0,0,-1,-1), Point dstOfs=Point(0,0), bool isolated=false); bool isSeparable() const { return filter2D.empty(); } // 入力画像のうち,まだ処理されていない行数 int remainingInputRows() const; // 出力行のうち,まだ作成されていない行数 int remainingOutputRows() const; ... // 入力画像における,開始行と終了行 int startY, endY; // フィルタへのポインタ Ptr filter2D; Ptr rowFilter; Ptr columnFilter; }; .. ``FilterEngine`` クラスは,画像に任意のフィルタリング処理を適用する目的で利用できます.これは,必要なすべての中間バッファを含み,画像外の「仮想的な」ピクセルを,外挿補間によって求めます.後に述べる様々な ``create*Filter`` 関数によって,初期化された ``FilterEngine`` インスタンスへのポインタが返されます.これらは, :func:`filter2D` , :func:`erode` , :func:`dilate` などの高レベル関数の内部で利用されます.つまりこのクラスは,OpenCV の多くのフィルタリング関数の要と言えるでしょう. このクラスによって,フィルタリング処理と,色空間の変換,閾値処理,算術処理などの別の処理とを容易に組み合わせることができます(それでも,非常に簡単になるわけではありませんが).複数の処理を組み合わせるとデータがキャッシュされるので,非常に効率が良くなります.例えば次の例は,浮動小数点型の画像に対するラプラスオペレータであり, :func:`Laplacian` を単純化したものです. :: void laplace_f(const Mat& src, Mat& dst) { CV_Assert( src.type() == CV_32F ); dst.create(src.size(), src.type()); // d2I/dx2 の微分平滑化カーネルを得ます. // d2I/dy2 に対しても,kd と ks を入れ替えただけの同じカーネルが利用できます. Mat kd, ks; getSobelKernels( kd, ks, 2, 0, ksize, false, ktype ); // 10 行を一度に処理します. int DELTA = std::min(10, src.rows); Ptr Fxx = createSeparableLinearFilter(src.type(), dst.type(), kd, ks, Point(-1,-1), 0, borderType, borderType, Scalar() ); Ptr Fyy = createSeparableLinearFilter(src.type(), dst.type(), ks, kd, Point(-1,-1), 0, borderType, borderType, Scalar() ); int y = Fxx->start(src), dsty = 0, dy = 0; Fyy->start(src); const uchar* sptr = src.data + y*src.step; // 空間微分画像のためのバッファを確保します. // 最後の反復で,出力は入力よりも大きい // max(kd.rows-1,ks.rows-1) 行となるので, // このバッファは, DELTA 行より大きい必要があります. Mat Ixx( DELTA + kd.rows - 1, src.cols, dst.type() ); Mat Iyy( DELTA + kd.rows - 1, src.cols, dst.type() ); // ループ内部では,常に DELTA 行がフィルタに渡されます // ( "start" メソッド内で実際の画像の高さが与えられているので, // "proceed" メソッドはオーバーフローの危険にも対処できます) // 出力として,次のような値が得られます: // * < DELTA rows (初期のバッファ累積段階) // * = DELTA rows (途中の安定状態) // * > DELTA rows (そして,入力画像の最後に到達した状態. // 境界モードを利用して「仮想的な」行を生成し,それをフィルタリングします) // この出力行数を表す変数は dy です. // dsty は,現在の出力行, // sptr は,処理される最初の入力行へのポインタ,となります. for( ; dsty < dst.rows; sptr += DELTA*src.step, dsty += dy ) { Fxx->proceed( sptr, (int)src.step, DELTA, Ixx.data, (int)Ixx.step ); dy = Fyy->proceed( sptr, (int)src.step, DELTA, d2y.data, (int)Iyy.step ); if( dy > 0 ) { Mat dstripe = dst.rowRange(dsty, dsty + dy); add(Ixx.rowRange(0, dy), Iyy.rowRange(0, dy), dstripe); } } } .. フィルタリング処理の細かい制御が不要ならば,単純に ``FilterEngine::apply`` メソッドを利用することができます.ここでは,このメソッドが実際にどのように実装されているのかを示します: :: void FilterEngine::apply(const Mat& src, Mat& dst, const Rect& srcRoi, Point dstOfs, bool isolated) { // 行列の型をチェックします. CV_Assert( src.type() == srcType && dst.type() == dstType ); // 「画像全体」を扱う場合 Rect _srcRoi = srcRoi; if( _srcRoi == Rect(0,0,-1,-1) ) _srcRoi = Rect(0,0,src.cols,src.rows); // 出力先の ROI が dst 内部に収まっているかどうかチェックしてください. // FilterEngine::start は,元の ROI が src 内部に収まっているかをチェックします. CV_Assert( dstOfs.x >= 0 && dstOfs.y >= 0 && dstOfs.x + _srcRoi.width <= dst.cols && dstOfs.y + _srcRoi.height <= dst.rows ); // フィルタリング開始 int y = start(src, _srcRoi, isolated); // ROI 全体を処理する. "endY - startY" は, // 処理対象となる入力行の総数であることに注意してください // (srcRoi の外側,かつ元画像の内側にある行も含みます). proceed( src.data + y*src.step, (int)src.step, endY - startY, dst.data + dstOfs.y*dst.step + dstOfs.x*dst.elemSize(), (int)dst.step ); } .. 以前のバージョンの OpenCV とは異なり,現在のフィルタリング処理は,画像の ROI 記法を完全にサポートします.つまり,ROI の外側かつ画像の内側にあるピクセルは,フィルタリング処理に利用されます.例えば,1ピクセルのROIに対してフィルタリング処理を行うことが可能で,つまり個々のピクセルに対するフィルタ応答を得ることができます(しかし, ``isolated=false`` を ``FilterEngine::start`` や ``FilterEngine::apply`` に渡すことで,以前の挙動をエミュレートすることは可能です) .ROI を明示的に ``FilterEngine::apply`` に渡したり,新しい行列ヘッダを作成したりすることができます: :: // src(x,y) における微分 dI/dx を求めます. // 方法 1: // 1 つの値のための行列ヘッダを作成します. float val1 = 0; Mat dst1(1,1,CV_32F,&val1); Ptr Fx = createDerivFilter(CV_32F, CV_32F, 1, 0, 3, BORDER_REFLECT_101); Fx->apply(src, Rect(x,y,1,1), Point(), dst1); // 方法 2: // 1 つの値のための行列ヘッダを作成します. float val2 = 0; Mat dst2(1,1,CV_32F,&val2); Mat pix_roi(src, Rect(x,y,1,1)); Sobel(pix_roi, dst2, dst2.type(), 1, 0, 3, 1, 0, BORDER_REFLECT_101); printf("method1 = .. データの型に注意してください. :func:`BaseFilter` の説明で述べたように, ``Base*Filter::operator()`` が ``uchar`` ポインタしかとることができないのに対して,個別のフィルタはあらゆる型のデータを処理することができます.よって,実際の型に関する情報は存在しません.これを機能させるために,以下のルールが利用されています: * 分離型フィルタの場合,まず最初に ``FilterEngine::rowFilter`` が適用されます.これは,(型 ``srcType`` の)入力画像データを,(型 ``bufType`` の)中間結果に変換し内部バッファに格納します.そしてこれらの中間結果は, ``FilterEngine::columnFilter`` によって *シングルチャンネルデータとして* 処理され,(型 ``dstType`` の)出力画像に格納されます.したがって, ``rowFilter`` に対する入力型は ``srcType`` であり,出力型は ``bufType`` となります.また, ``columnFilter`` に対する入力型は ``CV_MAT_DEPTH(bufType)`` となり,出力型は ``CV_MAT_DEPTH(dstType)`` となります. * 非分離型フィルタの場合, ``bufType`` は必ず ``srcType`` と同じでなければいけません.必要ならば,入力データはテンポラリバッファにコピーされ,そのまま ``FilterEngine::filter2D`` に渡されます.つまり, ``filter2D`` に対する入力型は ``srcType`` (= ``bufType`` ) であり,出力型は ``dstType`` となります. 参考: :func:`BaseColumnFilter` , :func:`BaseFilter` , :func:`BaseRowFilter` , :func:`createBoxFilter` , :func:`createDerivFilter` , :func:`createGaussianFilter` , :func:`createLinearFilter` , :func:`createMorphologyFilter` , :func:`createSeparableLinearFilter` .. index:: bilateralFilter cv::bilateralFilter ------------------- .. cfunction:: void bilateralFilter( const Mat\& src, Mat\& dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT ) 画像にバイラテラルフィルタを適用します. :param src: 8ビットまたは浮動小数点型,1チャンネルまたは3チャンネルの入力画像 :param dst: ``src`` と同じサイズ,同じ型の出力画像 :param d: フィルタリングで利用される,各ピクセル近傍領域の直径.これが正値でない場合, ``sigmaSpace`` から求められます :param sigmaColor: 色空間におけるフィルタシグマ.このパラメータが大きくなると,ピクセル近傍内( ``sigmaSpace`` を参照してください)にある,色的により遠くのピクセルが混ぜ合わせられ,結果として同じような色の領域がより大きくなります :param sigmaSpace: 座標空間におけるフィルタシグマ.このパラメータが大きくなると,より遠くのピクセル同士が影響を及ぼしあいます(ただし,それらの色が十分に近い限ります. ``sigmaColor`` を参照してください).そして, ``d>0`` ならば ``sigmaSpace`` に関係なく近傍領域のサイズが決まり,そうでなければ ``sigmaSpace`` との比率が ``d`` となるようにサイズが決まります 関数 ``bilateralFilter`` は,入力画像にバイラテラルフィルタを適用します.このフィルタについては, http://www.dai.ed.ac.uk/CVonline/LOCAL\_COPIES/MANDUCHI1/Bilateral\_Filtering.html で説明されています. .. index:: blur cv::blur -------- .. cfunction:: void blur( const Mat\& src, Mat\& dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT ) 正規化されたボックスフィルタを用いて画像を平滑化します. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じ型の出力画像 :param ksize: 平滑化カーネルサイズ :param anchor: アンカー点.デフォルト値の ``Point(-1,-1)`` は,アンカーがカーネルの中心にあることを意味します :param borderType: 画像外のピクセルを外挿するために利用される境界モード 関数 ``blur`` は,カーネルを用いて画像の平滑化を行います: .. math:: \texttt{K} = \frac{1}{\texttt{ksize.width*ksize.height}} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \end{bmatrix} ``blur(src, dst, ksize, anchor, borderType)`` の呼び出しは, ``boxFilter(src, dst, src.type(), anchor, true, borderType)`` と等価です. 参考: :func:`boxFilter` , :func:`bilateralFilter` , :func:`GaussianBlur` , :func:`medianBlur` . .. index:: borderInterpolate cv::borderInterpolate --------------------- .. cfunction:: int borderInterpolate( int p, int len, int borderType ) 外挿されるピクセルの元となる座標を求めます. :param p: 外挿されたピクセルの,1つの軸の座標(0基準).これは,<0 または >= ``len`` です :param len: 対応する軸に沿った配列の長さ :param borderType: 境界の種類. ``BORDER_TRANSPARENT`` と ``BORDER_ISOLATED`` を除いた ``BORDER_*`` の内の1つです. ``borderType==BORDER_CONSTANT`` の場合,この関数は ``p`` と ``len`` に関わらず常に - 1を返します 関数 ``borderInterpolate`` は,指定の外挿境界モードを利用した場合の,指定の外挿ピクセルに対応する元ピクセルの座標を求め,それを返します.例えば,水平方向に ``BORDER_WRAP`` ,垂直方向に ``BORDER_REFLECT_101`` モードを用いて,浮動小数点型画像 ``img`` の「仮想」ピクセル ``Point(-5, 100)`` の値を求めたい場合,次のようになります. :: float val = img.at(borderInterpolate(100, img.rows, BORDER_REFLECT_101), borderInterpolate(-5, img.cols, BORDER_WRAP)); .. 通常,この関数が直接呼ばれることはありません.これは,高速に外挿を行うためのテーブルを計算する目的で :func:`FilterEngine` や :func:`copyMakeBorder` の内部で利用されます. 参考: :func:`FilterEngine` , :func:`copyMakeBorder` .. index:: boxFilter cv::boxFilter ------------- .. cfunction:: void boxFilter( const Mat\& src, Mat\& dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), bool normalize=true, int borderType=BORDER_DEFAULT ) ボックスフィルタを用いて画像を平滑化します. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じ型の出力画像 :param ksize: 平滑化カーネルのサイズ :param anchor: アンカー点.デフォルト値の ``Point(-1,-1)`` は,アンカーがカーネル中心にあることを意味します :param normalize: カーネルが面積で正規化されているか否かを指定します :param normalize: カーネルが面積で正規化されているか否かを指定します 関数 ``boxFilter`` は,カーネルを用いて画像の平滑化を行います: .. math:: \texttt{K} = \alpha \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \end{bmatrix} ここで, .. math:: \alpha = \fork{\frac{1}{\texttt{ksize.width*ksize.height}}}{when \texttt{normalize=true}}{1}{otherwise} 正規化されていないボックスフィルタは,(密なオプティカルフローアルゴリズムや などで利用される)微分画像の共分散行列などの,各ピクセル近傍領域の全体的特徴を求める際に役立ちます.様々なサイズの窓でピクセル値の合計を求める必要があるならば, :func:`integral` を利用してください. 参考: :func:`boxFilter` , :func:`bilateralFilter` , :func:`GaussianBlur` , :func:`medianBlur` , :func:`integral` . .. index:: buildPyramid cv::buildPyramid ---------------- .. cfunction:: void buildPyramid( const Mat\& src, vector\& dst, int maxlevel ) 画像のガウシアンピラミッドを作成します. :param src: 入力画像.サポートされる型の一覧は :func:`pyrDown` をチェックしてください :param dst: ``maxlevel+1`` 個の画像をもつ出力ベクトル.各画像は ``src`` と同じ型です. ``dst[0]`` は ``src`` と同じで, ``dst[1]`` は次の画像ピラミッド層であり,層が上がるに従い ``src`` が段々と平滑化,縮小化されます :param maxlevel: 画像ピラミッドの最後の層(つまり最小の画像)のインデックス(0基準).これは非負の値でなければいけません 関数 ``buildPyramid`` は,画像のベクトルを作成し,ガウシアンピラミッドを構築します.この作業は, ``dst[0]==src`` から開始され,1つ前に作られた画像ピラミッド層に :func:`pyrDown` を再帰的に適用することで構築されます. .. index:: copyMakeBorder cv::copyMakeBorder ------------------ .. cfunction:: void copyMakeBorder( const Mat\& src, Mat\& dst, int top, int bottom, int left, int right, int borderType, const Scalar\& value=Scalar() ) 画像のまわりに境界を作成します. :param src: 入力画像 :param dst: ``src`` と同じ型の出力画像.サイズは ``Size(src.cols+left+right, src.rows+top+bottom)`` となります :param top, bottom, left, right: 上下左右の各方向に,元の画像矩形から何ピクセル分の境界を作る必要があるかを指定します.例えば, ``top=1, bottom=1, left=1, right=1`` ならば,幅1ピクセルの境界が必要になります :param borderType: 境界の種類. :func:`borderInterpolate` を参照してください :param value: ``borderType==BORDER_CONSTANT`` の場合の,境界のピクセル値 関数 ``copyMakeBorder`` は,入力画像を出力画像の中央にコピーします.そして,コピーされた入力画像の上下左右の隙間は,外挿されたピクセルで埋められます.これは, :func:`FilterEngine` や,それに基づくフィルタリング関数(これらは,実行中にピクセルを外挿します)が行うようなものとは異なります.ユーザ定義関数を含む,より複雑な別の関数で画像境界を簡単に扱えるするためのものです. この関数は ``src`` が既に ``dst`` の中央に存在するようなケースをサポートします.この場合, ``src`` 自身はコピーされず,単に境界だけ作成されます.例えば: :: // 全方向の境界が同じ幅になるようにします. int border=2; // 画像と境界を合わせたものがフィットする大きな画像を作成します. Mat gray_buf(rgb.rows + border*2, rgb.cols + border*2, rgb.depth()); // それの中央部分を選択します(データはコピーされません) Mat gray(gray_buf, Rect(border, border, rgb.cols, rgb.rows)); // 画像を RGB からグレースケールに変換します cvtColor(rgb, gray, CV_RGB2GRAY); // 置換モードで境界を作成します copyMakeBorder(gray, gray_buf, border, border, border, border, BORDER_REPLICATE); // 独自のフィルタリングを行う ... ... .. 参考: :func:`borderInterpolate` .. index:: createBoxFilter cv::createBoxFilter ------------------- .. cfunction:: Ptr createBoxFilter( int srcType, int dstType, Size ksize, Point anchor=Point(-1,-1), bool normalize=true, int borderType=BORDER_DEFAULT) .. cfunction:: Ptr getRowSumFilter(int srcType, int sumType, int ksize, int anchor=-1) .. cfunction:: Ptr getColumnSumFilter(int sumType, int dstType, int ksize, int anchor=-1, double scale=1) ボックスフィルタエンジン. :param srcType: 入力画像の型 :param sumType: 中間出力である水平方向の総和の型. ``srcType`` と同じチャンネル数でなければいけません :param dstType: 出力画像の型. ``srcType`` と同じチャンネル数でなければいけません :param ksize: アパーチャサイズ :param anchor: カーネルのアンカー位置.負の値は,アンカーがカーネル中心にあることを意味します :param normalize: 総和が正規化されている否かを示します. :func:`boxFilter` を参照してください :param scale: 低レベル関数 ``getColumnSumFilter`` で正規化を指定するためのもう1つの方法 :param borderType: 利用される境界の種類. :func:`borderInterpolate` を参照してください 関数 ``createBoxFilter`` は,水平方向の総和を求める基本フィルタ :func:`getRowSumFilter` と,垂直方向の総和を求める基本フィルタ :func:`getColumnSumFilter` を作成し,新たに作成された :func:`FilterEngine` に両方の基本フィルタを渡す簡易関数です.作成されたフィルタエンジンは,正規化された,あるいは正規化されていないボックスフィルタを用いた画像フィルタリングに利用できます. この関数自身は, :func:`blur` や :func:`boxFilter` で利用されます. 参考: :func:`FilterEngine` , :func:`blur` , :func:`boxFilter` . .. index:: createDerivFilter cv::createDerivFilter --------------------- .. cfunction:: Ptr createDerivFilter( int srcType, int dstType, int dx, int dy, int ksize, int borderType=BORDER_DEFAULT ) 微分画像を求めるためのエンジンを返します. :param srcType: 入力画像の型 :param dstType: 出力画像の型. ``srcType`` と同じチャンネル数でなければいけません :param dx: xに関する微分の次数 :param dy: yに関する微分の次数 :param ksize: アパーチャサイズ. :func:`getDerivKernels` を参照してください :param borderType: 利用される境界の種類. :func:`borderInterpolate` を参照してください 関数 :func:`createDerivFilter` は, :func:`getDerivKernels` を用いて微分画像を求めるための線形フィルタ係数を取得し, :func:`createSeparableLinearFilter` によって分離型線形フィルタを作成する小さな簡易関数です.この関数は, :func:`Sobel` や :func:`Scharr` で利用されます. 参考: :func:`createSeparableLinearFilter` , :func:`getDerivKernels` , :func:`Scharr` , :func:`Sobel` . .. index:: createGaussianFilter cv::createGaussianFilter ------------------------ .. cfunction:: Ptr createGaussianFilter( int type, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT) ガウシアンフィルタによる画像の平滑化を行うエンジンを返します. :param type: 入力および出力される画像の型 :param ksize: アパーチャサイズ. :func:`getGaussianKernel` を参照してください :param sigmaX: 水平方向のガウシアンシグマ. :func:`getGaussianKernel` を参照してください :param sigmaY: 垂直方向のガウシアンシグマ.0ならば, ``sigmaY`` :math:`\leftarrow` ``sigmaX`` となります :param borderType: 利用される境界の種類. :func:`borderInterpolate` を参照してください 関数 :func:`createGaussianFilter` は,ガウシアンカーネルを求め,そのカーネルを利用した分離型線形フィルタを返します.この関数は :func:`GaussianBlur` で利用されます.この関数は入力と出力に共通する1つのデータ型しか取りませんが, :func:`getGaussianKernel` を呼び出した後に直接 :func:`createSeparableFilter` を呼ぶことで,この制限を回避できます. 参考: :func:`createSeparableLinearFilter` , :func:`getGaussianKernel` , :func:`GaussianBlur` . .. index:: createLinearFilter cv::createLinearFilter ---------------------- .. cfunction:: Ptr createLinearFilter(int srcType, int dstType, const Mat\& kernel, Point _anchor=Point(-1,-1), double delta=0, int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1, const Scalar\& borderValue=Scalar()) .. cfunction:: Ptr getLinearFilter(int srcType, int dstType, const Mat\& kernel, Point anchor=Point(-1,-1), double delta=0, int bits=0) 非分離型線形フィルタエンジンを作成します. :param srcType: 入力画像の型 :param dstType: 出力画像の型. ``srcType`` と同じチャンネル数でなければいけません :param kernel: フィルタ係数の2次元配列 :param anchor: カーネル内のアンカー点.特別な値である ``Point(-1,-1)`` は,アンカーがカーネル中心にあることを意味します :param delta: フィルタ結果に足される値 :param bits: カーネルが,浮動小数点型フィルタ係数を表す整数型行列の場合,このパラメータは小数点以下のビット数を表します :param rowBorderType, columnBorderType: 水平方向,垂直方向におけるピクセル外挿手法. :func:`borderInterpolate` を参照してください :param borderValue: 定数境界モードで利用されるピクセル値 関数 ``getLinearFilter`` は,指定のカーネルを利用し,入出力配列の型を満たす2次元線形フィルタへのポインタを返します.関数 ``createLinearFilter`` は, ``getLinearFilter`` を呼び出し,そこから取得した2次元フィルタを :func:`FilterEngine` のコンストラクタに渡す高レベル関数です. 参考: :func:`createSeparableLinearFilter` , :func:`FilterEngine` , :func:`filter2D` .. index:: createMorphologyFilter cv::createMorphologyFilter -------------------------- .. cfunction:: Ptr createMorphologyFilter(int op, int type, const Mat\& element, Point anchor=Point(-1,-1), int rowBorderType=BORDER_CONSTANT, int columnBorderType=-1, const Scalar\& borderValue=morphologyDefaultBorderValue()) .. cfunction:: Ptr getMorphologyFilter(int op, int type, const Mat\& element, Point anchor=Point(-1,-1)) .. cfunction:: Ptr getMorphologyRowFilter(int op, int type, int esize, int anchor=-1) .. cfunction:: Ptr getMorphologyColumnFilter(int op, int type, int esize, int anchor=-1) .. cfunction:: static inline Scalar morphologyDefaultBorderValue(){ return Scalar::all(DBL_MAX) } 非分離型モルフォロジー演算を行うエンジンを作成します. :param op: モルフォロジー演算ID. ``MORPH_ERODE`` あるいは ``MORPH_DILATE`` :param type: 入出力画像の型 :param element: モルフォロジー演算で用いる,2次元,8ビットの構造要素.ここでの 非0 の要素が,構造要素に属するピクセルを示します :param esize: 分離型モルフォロジー演算で用いる構造要素の水平方向あるいは垂直方向のサイズ :param anchor: カーネルのアンカー位置.負の値は,アンカーがカーネル中心にあることを意味します :param rowBorderType, columnBorderType: 水平方向,垂直方向におけるピクセル外挿手法. :func:`borderInterpolate` を参照してください :param borderValue: 定数境界モードで利用されるピクセル値.デフォルト値の \ ``morphologyDefaultBorderValue`` は特別な意味を持ちます.この場合,収縮では :math:`+\inf` に,膨張では :math:`-\inf` に変換されるので,画像内ピクセルの最小値(最大値)を効率的に求めることができます これらの関数は,基本的なモルフォロジー演算,または,それに基づくフィルタエンジンを作成します.通常は, :func:`createMorphologyFilter` ,あるいは同等の高レベル関数 :func:`erode` , :func:`dilate` , :func:`morphologyEx` を用いれば十分でしょう. :func:`createMorphologyFilter` は,構造要素の形状を分析し,構造要素が正方形である場合は分離型モルフォロジーフィルタエンジンを構築することに注意してください. 参考: :func:`erode` , :func:`dilate` , :func:`morphologyEx` , :func:`FilterEngine` .. index:: createSeparableLinearFilter cv::createSeparableLinearFilter ------------------------------- .. cfunction:: Ptr createSeparableLinearFilter(int srcType, int dstType, const Mat\& rowKernel, const Mat\& columnKernel, Point anchor=Point(-1,-1), double delta=0, int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1, const Scalar\& borderValue=Scalar()) .. cfunction:: Ptr getLinearColumnFilter(int bufType, int dstType, const Mat\& columnKernel, int anchor, int symmetryType, double delta=0, int bits=0) .. cfunction:: Ptr getLinearRowFilter(int srcType, int bufType, const Mat\& rowKernel, int anchor, int symmetryType) 分離型線形フィルタエンジンを作成します. :param srcType: 入力画像の型 :param dstType: 出力画像の型. ``srcType`` と同じチャンネル数でなければいけません :param bufType: 中間出力バッファの型. ``srcType`` と同じチャンネル数でなければいけません :param rowKernel: 各行をフィルタリングるための係数 :param columnKernel: 各列をフィルタリングるための係数 :param anchor: カーネルのアンカー位置.負の値は,アンカーがカーネル中心にあることを意味します :param delta: フィルタ結果に足される値 :param bits: カーネルが,浮動小数点型フィルタ係数を表す整数型行列の場合,このパラメータは小数点以下のビット数を表します :param rowBorderType, columnBorderType: 水平方向,垂直方向におけるピクセル外挿手法. :func:`borderInterpolate` を参照してください :param borderValue: 定数境界モードで利用されるピクセル値 :param symmetryType: それぞれの行カーネル,列カーネルの型. :func:`getKernelType` を参照してください これらの関数は,基本的な分離型線形フィルタリング処理,またはそれに基づくフィルタエンジンを作成します.通常は, :func:`createSeparableLinearFilter` または同等の高レベル関数 :func:`sepFilter2D` を用いれば十分でしょう.関数 :func:`createMorphologyFilter` は賢いので,それぞれのカーネルに対する ``symmetryType`` ,中間値の ``bufType`` ,そして整数演算でフィルタリングされた場合にフィルタ係数にエンコードするための ``bits`` 数を算出します.これがうまく動作しないならば, ``getLinearColumnFilter`` , ``getLinearRowFilter`` を直接呼び出して,これらを :func:`FilterEngine` のコンストラクタに渡すこともできます. 参考: :func:`sepFilter2D` , :func:`createLinearFilter` , :func:`FilterEngine` , :func:`getKernelType` .. index:: dilate cv::dilate ---------- .. cfunction:: void dilate( const Mat\& src, Mat\& dst, const Mat\& element, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar\& borderValue=morphologyDefaultBorderValue() ) 指定の構造要素を用いて画像の膨張を行います. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じ型の出力画像 :param element: 膨張に用いられる構造要素. ``element=Mat()`` の場合, :math:`3\times 3` の矩形構造要素が用いられます :param anchor: 構造要素内のアンカー位置.デフォルト値の :math:`(-1, -1)` は,アンカーが構造要素の中心にあることを意味します :param iterations: 膨張が行われる回数 :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください :param borderValue: 定数境界モードで利用されるピクセル値.デフォルト値は特別な意味を持ちます. :func:`createMorphologyFilter` を参照してください 関数 ``dilate`` は,ピクセル近傍領域の形状を決定し,そこから最大値を取り出すような指定構造要素を用いて,入力画像の膨張を行います: .. math:: \texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y') この関数は,置換モードをサポートします.膨張は複数( ``iterations`` )回適用することができます.また,マルチチャンネル画像の場合,各チャンネルは個別に処理されます. 参考: :func:`erode` , :func:`morphologyEx` , :func:`createMorphologyFilter` .. index:: erode cv::erode --------- .. cfunction:: void erode( const Mat\& src, Mat\& dst, const Mat\& element, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar\& borderValue=morphologyDefaultBorderValue() ) 指定の構造要素を用いて画像の収縮を行います. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じ型の出力画像 :param element: 収縮に用いられる構造要素. ``element=Mat()`` の場合, :math:`3\times 3` の矩形の構造要素が用いられます :param anchor: 構造要素内のアンカー位置.デフォルト値の :math:`(-1, -1)` は,アンカーが構造要素の中心にあることを意味します :param iterations: 収縮が行われる回数 :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください :param borderValue: 定数境界モードで利用されるピクセル値.デフォルト値は特別な意味を持ちます. :func:`createMorphologyFilter` を参照してください 関数 ``erode`` は,ピクセル近傍領域の形状を決定し,そこから最小値を取り出すような指定構造要素を用いて,入力画像の収縮を行います: .. math:: \texttt{dst} (x,y) = \min _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y') この関数は,置換モードをサポートします.収縮は複数( ``iterations`` )回適用することができます.また,マルチチャンネル画像の場合,各チャンネルは個別に処理されます. 参考: :func:`dilate` , :func:`morphologyEx` , :func:`createMorphologyFilter` .. index:: filter2D cv::filter2D ------------ .. cfunction:: void filter2D( const Mat\& src, Mat\& dst, int ddepth, const Mat\& kernel, Point anchor=Point(-1,-1), double delta=0, int borderType=BORDER_DEFAULT ) カーネルを用いて画像の畳み込みを行います. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じ型の出力画像 :param ddepth: 出力画像に求めるビット深度.負の場合は, ``src.depth()`` と同じになります :param kernel: シングルチャンネルの浮動小数点型行列である畳み込みカーネル(厳密に言えば,相関カーネル).チャンネル毎に別のカーネルを適用したい場合は, :func:`split` を用いて画像を個別の色平面に分割し,それを別々に処理してください :param anchor: カーネル内のフィルタ対象点の相対位置を表すカーネルアンカー.アンカーはカーネル内に存在する必要があります.特別なデフォルト値 (-1,-1) は,アンカーがカーネルの中心にあることを意味します :param delta: オプション. ``dst`` に格納する前に,フィルタ結果に足される値 :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください 関数 ``filter2D`` は,任意の線形フィルタを画像に適用します.また,置換モードがサポートされます.アパーチャが部分的に画像外にはみ出す場合,関数は指定された境界モードに基づいてピクセル値を外挿補間します. この関数は,実際には畳み込みではなく相関を求めます: .. math:: \texttt{dst} (x,y) = \sum _{ \stackrel{0\leq x' < \texttt{kernel.cols},}{0\leq y' < \texttt{kernel.rows}} } \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} ) つまり,カーネルはアンカー点周りで対称ではありません.本当の畳み込みが必要ならば, :func:`flip` を用いてカーネルを反転し,新しいアンカー ``(kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1)`` をセットしてください. この関数は,十分に大きいカーネル( ~ :math:`11\times11` )の場合は に基づくアルゴリズムを利用し,小さいカーネルの場合は( :func:`createLinearFilter` によって取得されるエンジンを用いる)直接アルゴリズムを利用します. 参考: :func:`sepFilter2D` , :func:`createLinearFilter` , :func:`dft` , :func:`matchTemplate` .. index:: GaussianBlur cv::GaussianBlur ---------------- .. cfunction:: void GaussianBlur( const Mat\& src, Mat\& dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT ) ガウシアンフィルタを用いて画像の平滑化を行います. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じ型の出力画像 :param ksize: ガウシアンカーネルサイズ. ``ksize.width`` と ``ksize.height`` は別の値を取ることができますが,両方とも正の奇数でなければいけません.または 0 をとることも可能で,その場合のサイズは ``sigma*`` から算出されます :param sigmaX, sigmaY: ガウシアンカーネルの,XとY方向の標準偏差. ``sigmaY`` が 0 ならば, ``sigmaX`` と等しくなるようにセットされます.両方の値が 0 の場合は,それぞれ ``ksize.width`` と ``ksize.height`` から求められます. :func:`getGaussianKernel` を参照してください.将来これらの引数の意味が変更されたとしても,それに関係なく結果を完全に制御するために, ``ksize`` , ``sigmaX`` および ``sigmaY`` のすべての値を指定することが推奨されます :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください この関数は,指定のガウシアンかーネルを用いて入力画像の畳み込みを行います.また,置換モードのフィルタリングがサポートされます. 参考: :func:`sepFilter2D` , :func:`filter2D` , :func:`blur` , :func:`boxFilter` , :func:`bilateralFilter` , :func:`medianBlur` .. index:: getDerivKernels cv::getDerivKernels ------------------- .. cfunction:: void getDerivKernels( Mat\& kx, Mat\& ky, int dx, int dy, int ksize, bool normalize=false, int ktype=CV_32F ) 画像の空間微分を求めるためのフィルタ係数を返します. :param kx: 行フィルタ係数が出力される行列.型は ``ktype`` :param ky: 列フィルタ係数が出力される行列.型は ``ktype`` :param dx: x に関する微分の次数 :param dy: y に関する微分の次数 :param ksize: アパーチャサイズ. ``CV_SCHARR`` , 1, 3, 5, 7 のいずれか :param normalize: フィルタ係数を正規化(スケールダウン)するか否かを指定します.理論上は,係数の分母は :math:`=2^{ksize*2-dx-dy-2}` となるべきです.浮動小数点型の画像をフィルタリングしようとする場合は,正規化されたカーネルを使いたいと思うでしょう.しかし,8ビット画像を微分し,その結果を16ビット画像に格納して小数部分の全ビットを保存したい場合など, ``normalize=false`` の設定を望む場合もあります :param ktype: フィルタ係数の型. ``CV_32f`` あるいは ``CV_64F`` 関数 ``getDerivKernels`` は,画像の空間微分を求めるためのフィルタ係数を求め,それを返します. ``ksize=CV_SCHARR`` の場合は, :math:`3 \times 3` の Scharr カーネルが生成されます. :func:`Scharr` を参照してください.そうでない場合は,Sobel カーネルが生成されます.同じく :func:`Sobel` を参照してください.これらのフィルタは通常, :func:`sepFilter2D` か :func:`createSeparableLinearFilter` に渡されます. .. index:: getGaussianKernel cv::getGaussianKernel --------------------- .. cfunction:: Mat getGaussianKernel( int ksize, double sigma, int ktype=CV_64F ) ガウシアンフィルタの係数を返します. :param ksize: アパーチャサイズ.これは正の奇数( :math:`\texttt{ksize} \mod 2 = 1` )です :param sigma: ガウシアンの標準偏差.これが正値でない場合, ``ksize`` を用いて \ ``sigma = 0.3*(ksize/2 - 1) + 0.8`` という様に求められます :param ktype: フィルタ係数の型. ``CV_32f`` あるいは ``CV_64F`` 関数 ``getGaussianKernel`` は, :math:`\texttt{ksize} \times 1` のガウシアンフィルタ係数行列を求め,それを返します. .. math:: G_i= \alpha *e^{-(i-( \texttt{ksize} -1)/2)^2/(2* \texttt{sigma} )^2}, ここで, :math:`i=0..\texttt{ksize}-1` であり, :math:`\alpha` は :math:`\sum_i G_i=1` となるように選ばれたスケールファクタです. このように生成されたカーネルを2つ, :func:`sepFilter2D` あるいは :func:`createSeparableLinearFilter` に渡すことができます.これらは,渡されたカーネルが平滑化カーネルであることを自動的に検出して適切に扱います.また,高レベル関数 :func:`GaussianBlur` を使うこともできます. 参考: :func:`sepFilter2D` , :func:`createSeparableLinearFilter` , :func:`getDerivKernels` , :func:`getStructuringElement` , :func:`GaussianBlur` . .. index:: getKernelType cv::getKernelType ----------------- .. cfunction:: int getKernelType(const Mat\& kernel, Point anchor) カーネルの種類を返す.. :param kernel: 分析されるカーネル係数の1次元配列 :param anchor: カーネル内のアンカー位置 The function analyzes the kernel coefficients and returns the corresponding kernel type: * **KERNEL_GENERAL** 汎用カーネル - 対称でもなく,他の特徴もない場合 * **KERNEL_SYMMETRICAL** カーネルが対称: :math:`\texttt{kernel}_i == \texttt{kernel}_{ksize-i-1}` かつ,アンカーが中心にある * **KERNEL_ASYMMETRICAL** カーネルが非対称: :math:`\texttt{kernel}_i == -\texttt{kernel}_{ksize-i-1}` かつ,アンカーが中央にある * **KERNEL_SMOOTH** すべてのカーネル要素が非負で,その合計が1.例えば,ガウシアンカーネルは smooth かつ symmetrical であるので,この関数は ``KERNEL_SMOOTH | KERNEL_SYMMETRICAL`` を返します * **KERNEL_INTEGER** すべてのカーネル係数が整数値.このフラグは ``KERNEL_SYMMETRICAL`` あるいは ``KERNEL_ASYMMETRICAL`` と組み合わせることができます .. index:: getStructuringElement cv::getStructuringElement ------------------------- .. cfunction:: Mat getStructuringElement(int shape, Size esize, Point anchor=Point(-1,-1)) モルフォロジー演算のために,指定されたサイズと形状の構造要素を返します. :param shape: 要素の形状.以下の中の1つ: * ``MORPH_RECT`` - 矩形構造要素 .. math:: E_ {ij} =1 * ``MORPH_ELLIPSE`` - 楕円構造要素.つまり次の矩形に内接する楕円 ``Rect(0, 0, esize.width, 0.esize.height)`` * ``MORPH_CROSS`` - 十字形構造要素 .. math:: E_ {ij} = \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise} :param esize: 構造要素のサイズ :param anchor: カーネル内のアンカー位置.デフォルト値の :math:`(-1, -1)` は,アンカーが構造要素の中心にあることを意味します.十字形構造要素の形状だけは,アンカー位置に依存することに注意してください.その他の場合は,単にモルフォロジー演算の結果をどれだけシフトするかによって調整されます 関数 ``getStructuringElement`` は, :func:`createMorphologyFilter` , :func:`erode` , :func:`dilate` または :func:`morphologyEx` に渡される構造要素を作成し,それを返します.しかし,任意の2値マスクを作成し,それを構造要素として利用することもできます. .. index:: medianBlur cv::medianBlur -------------- .. cfunction:: void medianBlur( const Mat\& src, Mat\& dst, int ksize ) メディアンフィルタを用いて画像の平滑化を行います. :param src: 1-, 3- あるいは 4-チャンネルの入力画像. ``ksize`` が 3 または 5 ならば,この画像のビット深度は ``CV_8U`` , ``CV_16U`` または ``CV_32F`` となります.それ以上のアパーチャサイズの場合は ``CV_8U`` だけが可能です :param dst: ``src`` と同じサイズ,同じ型の出力画像 :param ksize: アパーチャサイズ.1より大きな奇数,例えば 3, 5, 7 ... でなければいけません 関数 ``medianBlur`` は,アパーチャサイズが :math:`\texttt{ksize} \times \texttt{ksize}` であるメディアンフィルタを用いて,画像の平滑化を行います.マルチチャンネル画像の各チャンネルは,個別に処理されます.また,置換モード処理がサポートされます. 参考: :func:`bilateralFilter` , :func:`blur` , :func:`boxFilter` , :func:`GaussianBlur` .. index:: morphologyEx cv::morphologyEx ---------------- .. cfunction:: void morphologyEx( const Mat\& src, Mat\& dst, int op, const Mat\& element, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar\& borderValue=morphologyDefaultBorderValue() ) 高度なモルフォロジー変換を行います. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じ型の出力画像 :param element: 構造要素 :param op: モルフォロジー演算の種類.以下のうちの1つ: * **MORPH_OPEN** オープニング * **MORPH_CLOSE** クロージング * **MORPH_GRADIENT** モルフォロジー勾配 * **MORPH_TOPHAT** 「トップハット変換」 * **MORPH_BLACKHAT** 「ブラックハット変換」 :param iterations: 収縮と膨張が適用される回数 :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください :param borderValue: 定数境界モードで利用されるピクセル値.デフォルト値は特別な意味を持ちます. :func:`createMorphologyFilter` を参照してください 関数 ``morphologyEx`` は,収縮と膨張を基本演算として利用する高度なモルフォロジー変換を行います. オープニング: .. math:: \texttt{dst} = \mathrm{open} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \mathrm{erode} ( \texttt{src} , \texttt{element} )) クロージング: .. math:: \texttt{dst} = \mathrm{close} ( \texttt{src} , \texttt{element} )= \mathrm{erode} ( \mathrm{dilate} ( \texttt{src} , \texttt{element} )) モルフォロジー勾配: .. math:: \texttt{dst} = \mathrm{morph\_grad} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \texttt{src} , \texttt{element} )- \mathrm{erode} ( \texttt{src} , \texttt{element} ) 「トップハット変換」: .. math:: \texttt{dst} = \mathrm{tophat} ( \texttt{src} , \texttt{element} )= \texttt{src} - \mathrm{open} ( \texttt{src} , \texttt{element} ) 「ブラックハット変換」: .. math:: \texttt{dst} = \mathrm{blackhat} ( \texttt{src} , \texttt{element} )= \mathrm{close} ( \texttt{src} , \texttt{element} )- \texttt{src} いずれの演算も置換モードをサポートします. 参考: :func:`dilate` , :func:`erode` , :func:`createMorphologyFilter` .. index:: Laplacian cv::Laplacian ------------- .. cfunction:: void Laplacian( const Mat\& src, Mat\& dst, int ddepth, int ksize=1, double scale=1, double delta=0, int borderType=BORDER_DEFAULT ) 画像のラプラシアンを求めます. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じチャンネル数の出力画像 :param ddepth: 出力画像に求めるビット深度 :param ksize: 2次微分フィルタを求めるために利用されるアパーチャのサイズ. :func:`getDerivKernels` を参照してください.これは正の奇数でなければいけません :param scale: オプション.求められたラプラシアンに対するスケールファクタ(デフォルトではスケーリングされません. :func:`getDerivKernels` を参照してください) :param delta: ``dst`` に格納する前に,結果に足されるオプション値 :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください 関数 ``cvLaplace`` は,Sobelオペレータを用いて計算される x および y に関する2次微分を足し合わせることで,入力画像のラプラシアンを求めます. .. math:: \texttt{dst} = \Delta \texttt{src} = \frac{\partial^2 \texttt{src}}{\partial x^2} + \frac{\partial^2 \texttt{src}}{\partial y^2} ``ksize > 1`` の場合は,上述のように動作します.また, ``ksize == 1`` の場合は, :math:`3 \times 3` のアパーチャを用いたフィルタリングによってラプラシアンを求めます. .. math:: \vecthreethree {0}{1}{0}{1}{-4}{1}{0}{1}{0} 参考: :func:`Sobel` , :func:`Scharr` .. index:: pyrDown cv::pyrDown ----------- .. cfunction:: void pyrDown( const Mat\& src, Mat\& dst, const Size\& dstsize=Size()) 画像の平滑化とダウンサンプリングを行います. :param src: 入力画像 :param dst: 指定されたサイズで, ``src`` と同じ型の出力画像 :param dstsize: 出力画像のサイズ.デフォルトでは, ``Size((src.cols+1)/2, (src.rows+1)/2)`` として求められます.しかし,いずれの場合も,以下の条件を満足しなければいけません: .. math:: \begin{array}{l} | \texttt{dstsize.width} *2-src.cols| \leq 2 \\ | \texttt{dstsize.height} *2-src.rows| \leq 2 \end{array} 関数 ``pyrDown`` は,ガウシアンピラミッド作成におけるダウンサンプリング部分を実行します.まず,以下のカーネルで入力画像の畳み込みを行います: .. math:: \frac{1}{16} \begin{bmatrix} 1 & 4 & 6 & 4 & 1 \\ 4 & 16 & 24 & 16 & 4 \\ 6 & 24 & 36 & 24 & 6 \\ 4 & 16 & 24 & 16 & 4 \\ 1 & 4 & 6 & 4 & 1 \end{bmatrix} そして,偶数行と偶数列を読み飛ばすことで,画像のダウンサンプリングを行います. .. index:: pyrUp cv::pyrUp --------- .. cfunction:: void pyrUp( const Mat\& src, Mat\& dst, const Size\& dstsize=Size()) 画像のアップサンプリングと平滑化を行います. :param src: 入力画像 :param dst: 指定されたサイズで, ``src`` と同じ型の出力画像 :param dstsize: 出力画像のサイズ.デフォルトでは, ``Size(src.cols*2, src.rows*2)`` として求められます.しかし,いずれの場合も,以下の条件を満足しなければいけません: .. math:: \begin{array}{l} | \texttt{dstsize.width} -src.cols*2| \leq ( \texttt{dstsize.width} \mod 2) \\ | \texttt{dstsize.height} -src.rows*2| \leq ( \texttt{dstsize.height} \mod 2) \end{array} 関数 ``pyrUp`` は,ガウシアンピラミッド作成におけるアップサンプリング部分を実行します(実際にラプラシアンピラミッドの作成に利用できます).まず,入力画像に 0 で埋められた偶数行,偶数列を挿入してアップサンプリングを行い, :func:`pyrDown` のときと同じカーネルを4倍したもので,その結果を畳み込みます. .. index:: sepFilter2D cv::sepFilter2D --------------- .. cfunction:: void sepFilter2D( const Mat\& src, Mat\& dst, int ddepth, const Mat\& rowKernel, const Mat\& columnKernel, Point anchor=Point(-1,-1), double delta=0, int borderType=BORDER_DEFAULT ) 画像に分離型線形フィルタを適用します. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じチャンネル数の出力画像 :param ddepth: 出力画像のビット深度 :param rowKernel: 各行をフィルタリングするための係数 :param columnKernel: 各列をフィルタリングするための係数 :param anchor: カーネル内のアンカー位置.デフォルト値の :math:`(-1, -1)` は,アンカーがカーネルの中心にあることを意味します :param delta: フィルタ結果に足される値 :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください この関数は,画像に分離型線形フィルタを適用します.つまり,まず, ``src`` の各行に1次元カーネル ``rowKernel`` でフィルタリングを行います.次に,その結果の各列に対して1次元カーネル ``columnKernel`` でフィルタリングを行い,最終的な結果を ``delta`` だけシフトしたものが ``dst`` に格納されます. 参考: :func:`createSeparableLinearFilter` , :func:`filter2D` , :func:`Sobel` , :func:`GaussianBlur` , :func:`boxFilter` , :func:`blur` . .. index:: Sobel cv::Sobel --------- .. cfunction:: void Sobel( const Mat\& src, Mat\& dst, int ddepth, int xorder, int yorder, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT ) 拡張 Sobel オペレータを用いて,1次,2次,3次または混合次数の微分画像を求めます. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じチャンネル数の出力画像 :param ddepth: 出力画像のビット深度 :param xorder: xに関する微分の次数 :param yorder: yに関する微分の次数 :param ksize: 拡張Sobelカーネルのサイズ. 1, 3, 5 あるいは 7 のいずれか :param scale: オプション.求められた微分値に対するスケールファクタ(デフォルトではスケーリングされません. :func:`getDerivKernels` を参照してください) :param delta: ``dst`` に格納する前に,結果に足されるオプション値 :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください カーネルサイズ1を除くすべての場合で,微分画像を求めるために :math:`\texttt{ksize} \times \texttt{ksize}` の分離型カーネルが用いられます. :math:`\texttt{ksize = 1}` の場合は, :math:`3 \times 1` または :math:`1 \times 3` のカーネルが用いられます(つまり,ガウシアン平滑化は行われません). ``ksize = 1`` は,1次または2次の,x- あるいは y-微分に関してのみ利用されます. 特別な値 ``ksize = CV_SCHARR`` (-1) も存在し,これは :math:`3\times3` の Sobel よりも正確な結果を得ることができる :math:`3\times3` のScharr フィルタを意味します.この Scharr アパーチャは以下のようになります. .. math:: \vecthreethree{-3}{0}{3}{-10}{0}{10}{-3}{0}{3} これは x-導関数に対するカーネルであり,転置すれば y-導関数に対するカーネルとなります. 関数 ``sobel`` は,以下のように,画像と適切なカーネルの畳み込みによって微分画像を求めます: .. math:: \texttt{dst} = \frac{\partial^{xorder+yorder} \texttt{src}}{\partial x^{xorder} \partial y^{yorder}} Sobel オペレータは,ガウシアンによる平滑化と微分の組み合わせなので,その結果はノイズに対して多少は頑健です. 1次の x-あるいは,y-微分画像を求める場合は大抵,この関数は次のような引数で呼び出されます: ( ``xorder`` = 1, ``yorder`` = 0, ``ksize`` = 3) あるいは ( ``xorder`` = 0, ``yorder`` = 1, ``ksize`` = 3). 最初の例は,以下のカーネルに対応します: .. math:: \vecthreethree{-1}{0}{1}{-2}{0}{2}{-1}{0}{1} また,2番目の例は,以下のカーネルに対応します: .. math:: \vecthreethree{-1}{-2}{-1}{0}{0}{0}{1}{2}{1} 参考: :func:`Scharr` , :func:`Lapacian` , :func:`sepFilter2D` , :func:`filter2D` , :func:`GaussianBlur` .. index:: Scharr cv::Scharr ---------- .. cfunction:: void Scharr( const Mat\& src, Mat\& dst, int ddepth, int xorder, int yorder, double scale=1, double delta=0, int borderType=BORDER_DEFAULT ) Scharr オペレータを用いて,1次の x- あるいは y-微分画像を求めます. :param src: 入力画像 :param dst: ``src`` と同じサイズ,同じチャンネル数の出力画像 :param ddepth: 出力画像のビット深度 :param xorder: xに関する微分の次数 :param yorder: yに関する微分の次数 :param scale: オプション.求められた微分値に対するスケールファクタ(デフォルトではスケーリングされません. :func:`getDerivKernels` を参照してください) :param delta: ``dst`` に格納する前に,結果に足されるオプション値 :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください この関数は,Scharrオペレータを用いて,1次のx-あるいはy-微分画像を求めます.次の関数呼び出し .. math:: \texttt{Scharr(src, dst, ddepth, xorder, yorder, scale, delta, borderType)} は,以下と等価になります. .. math:: \texttt{Sobel(src, dst, ddepth, xorder, yorder, CV\_SCHARR, scale, delta, borderType)} .