画像フィルタリング

このセクションで述べる関数およびクラスを利用して, ( Mat() で表現された) 2次元画像に対して,様々な線形・非線形のフィルタリング処理を行います.このフィルタリング処理では,入力画像の各ピクセル位置 (x,y) の近傍領域(通常は矩形)を利用して出力値を求めます.この出力は,線形フィルタの場合はピクセル値の重み付き和,モルフォロジー演算の場合は,最大値・最小値となります.求められた出力は,出力画像上の同じ位置 (x,y)) に保存されます.これはつまり,出力画像が入力画像と同じサイズになることを意味します.また通常,関数はマルチチャンネル配列をサポートしており,各チャンネルが個別に処理されるので,出力画像のチャンネル数も入力画像と同じ数になります.

このセクションで述べる関数とクラスに共通するもう1つの特徴は,これらは単純な算術関数とは異なり,存在しないピクセルの値を外挿する必要があるということです.例えば, 3 \times 3 のガウシアンフィルタを用いて画像の平滑化を行いたい場合,各行の左端のピクセルを処理する際に,さらにその左側,つまり,画像外のピクセルが必要となります.このようなピクセルを,画像の左端のピクセルと同じものだと仮定する(つまり,「複製境界」外挿法),あるいは,存在しないすべてのピクセルを 0 とする(つまり,「定数境界」外挿法)などの処理が可能です. OpenCV では,ユーザがこの外挿手法を指定することができます.関数 borderInterpolate() および,以下で述べる様々な関数のパラメータ borderType の説明を参照してください.

BaseColumnFilter

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列カーネルを用いたフィルタリングのための基底クラスです.このフィルタリングは,必ずしも線形処理である必要はありません.一般的に,この処理は次のように書かれます:

\texttt{dst} (x,y) = F( \texttt{src} [y](x), \; \texttt{src} [y+1](x), \; ..., \; \texttt{src} [y+ \texttt{ksize} -1](x)

ここで F はフィルタリング関数ですが,実際にはクラスとして表現されています.それによる副次的な影響が発生することもありますし,クラスなので以前に処理したデータを記憶しておくことも可能です.このクラスは,インタフェースを定義するだけで直接は利用されません.その代わり,OpenCV には具体的なフィルタリング処理を実装した派生クラスへのポインタを返す関数が複数存在します(そして,ユーザが追加することも可能です).これらのポインタは, FilterEngine() コンストラクタに渡されます.フィルタリング処理のインタフェースは uchar 型を利用しますが,個々の実装は8ビットデータに限定されません.

参考: BaseRowFilter() , BaseFilter() , FilterEngine() , getColumnSumFilter() , getLinearColumnFilter() , getMorphologyColumnFilter()

BaseFilter

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次元カーネルを利用したフィルタリングのための基底クラスです.このフィルタリングは,必ずしも線形処理である必要はありません.一般的に,この処理は次のように書かれます:

\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}

ここで F はフィルタリング関数を表します.このクラスは,インタフェースを定義するだけで直接は利用されません.その代わり,OpenCV には具体的なフィルタリング処理を実装した派生クラスへのポインタを返す関数が複数存在します(そして,ユーザが追加することもできます).これらのポインタは, FilterEngine() コンストラクタに渡されます.フィルタリング処理のインタフェースは uchar 型を利用しますが,個々の実装は8ビットデータに限定されません.

参考: BaseColumnFilter() , BaseRowFilter() , FilterEngine() , getLinearFilter() , getMorphologyFilter()

BaseRowFilter

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行カーネルを用いたフィルタリングのための基底クラスです.このフィルタリングは,必ずしも線形処理である必要はありません.一般的に,この処理は次のように書かれます:

\texttt{dst} (x,y) = F( \texttt{src} [y](x), \; \texttt{src} [y](x+1), \; ..., \; \texttt{src} [y](x+ \texttt{ksize.width} -1))

ここで F はフィルタリング関数を表します.このクラスは,インタフェースを定義するだけで直接は利用されません.その代わり,OpenCV には具体的なフィルタリング処理を実装した派生クラスへのポインタを返す関数が複数存在します(そして,ユーザが追加することもできます).これらのポインタは, FilterEngine() コンストラクタに渡されます.フィルタリング処理のインタフェースは uchar 型を利用しますが,個々の実装は8ビットデータに限定されません.

参考: BaseColumnFilter() , Filter() , FilterEngine() , getLinearRowFilter() , getMorphologyRowFilter() , getRowSumFilter()

FilterEngine

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<BaseFilter>& _filter2D,
                 const Ptr<BaseRowFilter>& _rowFilter,
                 const Ptr<BaseColumnFilter>& _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<BaseFilter>& _filter2D,
              const Ptr<BaseRowFilter>& _rowFilter,
              const Ptr<BaseColumnFilter>& _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<BaseFilter> filter2D;
    Ptr<BaseRowFilter> rowFilter;
    Ptr<BaseColumnFilter> columnFilter;
};

FilterEngine クラスは,画像に任意のフィルタリング処理を適用する目的で利用できます.これは,必要なすべての中間バッファを含み,画像外の「仮想的な」ピクセルを,外挿補間によって求めます.後に述べる様々な create*Filter 関数によって,初期化された FilterEngine インスタンスへのポインタが返されます.これらは, filter2D() , erode() , dilate() などの高レベル関数の内部で利用されます.つまりこのクラスは,OpenCV の多くのフィルタリング関数の要と言えるでしょう.

このクラスによって,フィルタリング処理と,色空間の変換,閾値処理,算術処理などの別の処理とを容易に組み合わせることができます(それでも,非常に簡単になるわけではありませんが).複数の処理を組み合わせるとデータがキャッシュされるので,非常に効率が良くなります.例えば次の例は,浮動小数点型の画像に対するラプラスオペレータであり, 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<FilterEngine> Fxx = createSeparableLinearFilter(src.type(),
        dst.type(), kd, ks, Point(-1,-1), 0, borderType, borderType, Scalar() );
    Ptr<FilterEngine> 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=falseFilterEngine::startFilterEngine::apply に渡すことで,以前の挙動をエミュレートすることは可能です) .ROI を明示的に FilterEngine::apply に渡したり,新しい行列ヘッダを作成したりすることができます:

// src(x,y) における微分 dI/dx を求めます.

// 方法 1:
// 1 つの値のための行列ヘッダを作成します.
float val1 = 0;
Mat dst1(1,1,CV_32F,&val1);

Ptr<FilterEngine> 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 =

データの型に注意してください. 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 となります.

参考: BaseColumnFilter() , BaseFilter() , BaseRowFilter() , createBoxFilter() ,

createDerivFilter() , createGaussianFilter() , createLinearFilter() , createMorphologyFilter() , createSeparableLinearFilter()

cv::bilateralFilter

void bilateralFilter(const Mat& src, Mat& dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)

画像にバイラテラルフィルタを適用します.

パラメタ:
  • src – 8ビットまたは浮動小数点型,1チャンネルまたは3チャンネルの入力画像
  • dstsrc と同じサイズ,同じ型の出力画像
  • d – フィルタリングで利用される,各ピクセル近傍領域の直径.これが正値でない場合, sigmaSpace から求められます
  • sigmaColor – 色空間におけるフィルタシグマ.このパラメータが大きくなると,ピクセル近傍内( sigmaSpace を参照してください)にある,色的により遠くのピクセルが混ぜ合わせられ,結果として同じような色の領域がより大きくなります
  • sigmaSpace – 座標空間におけるフィルタシグマ.このパラメータが大きくなると,より遠くのピクセル同士が影響を及ぼしあいます(ただし,それらの色が十分に近い限ります. sigmaColor を参照してください).そして, d>0 ならば sigmaSpace に関係なく近傍領域のサイズが決まり,そうでなければ sigmaSpace との比率が d となるようにサイズが決まります

関数 bilateralFilter は,入力画像にバイラテラルフィルタを適用します.このフィルタについては, http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html で説明されています.

cv::blur

void blur(const Mat& src, Mat& dst, Size ksize, Point anchor=Point(-1, -1), int borderType=BORDER_DEFAULT)

正規化されたボックスフィルタを用いて画像を平滑化します.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じ型の出力画像
  • ksize – 平滑化カーネルサイズ
  • anchor – アンカー点.デフォルト値の Point(-1,-1) は,アンカーがカーネルの中心にあることを意味します
  • borderType – 画像外のピクセルを外挿するために利用される境界モード

関数 blur は,カーネルを用いて画像の平滑化を行います:

\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) と等価です.

参考: boxFilter() , bilateralFilter() , GaussianBlur() , medianBlur() .

cv::borderInterpolate

int borderInterpolate(int p, int len, int borderType)

外挿されるピクセルの元となる座標を求めます.

パラメタ:
  • p – 外挿されたピクセルの,1つの軸の座標(0基準).これは,<0 または >= len です
  • len – 対応する軸に沿った配列の長さ
  • borderType – 境界の種類. BORDER_TRANSPARENTBORDER_ISOLATED を除いた BORDER_* の内の1つです. borderType==BORDER_CONSTANT の場合,この関数は plen に関わらず常に - 1を返します

関数 borderInterpolate は,指定の外挿境界モードを利用した場合の,指定の外挿ピクセルに対応する元ピクセルの座標を求め,それを返します.例えば,水平方向に BORDER_WRAP ,垂直方向に BORDER_REFLECT_101 モードを用いて,浮動小数点型画像 img の「仮想」ピクセル Point(-5, 100) の値を求めたい場合,次のようになります.

float val = img.at<float>(borderInterpolate(100, img.rows, BORDER_REFLECT_101),
                          borderInterpolate(-5, img.cols, BORDER_WRAP));

通常,この関数が直接呼ばれることはありません.これは,高速に外挿を行うためのテーブルを計算する目的で FilterEngine()copyMakeBorder() の内部で利用されます.

参考: FilterEngine() , copyMakeBorder()

cv::boxFilter

void boxFilter(const Mat& src, Mat& dst, int ddepth, Size ksize, Point anchor=Point(-1, -1), bool normalize=true, int borderType=BORDER_DEFAULT)

ボックスフィルタを用いて画像を平滑化します.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じ型の出力画像
  • ksize – 平滑化カーネルのサイズ
  • anchor – アンカー点.デフォルト値の Point(-1,-1) は,アンカーがカーネル中心にあることを意味します
  • normalize – カーネルが面積で正規化されているか否かを指定します
  • normalize – カーネルが面積で正規化されているか否かを指定します

関数 boxFilter は,カーネルを用いて画像の平滑化を行います:

\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}

ここで,

\alpha = \fork{\frac{1}{\texttt{ksize.width*ksize.height}}}{when \texttt{normalize=true}}{1}{otherwise}

正規化されていないボックスフィルタは,(密なオプティカルフローアルゴリズムや などで利用される)微分画像の共分散行列などの,各ピクセル近傍領域の全体的特徴を求める際に役立ちます.様々なサイズの窓でピクセル値の合計を求める必要があるならば, integral() を利用してください.

参考: boxFilter() , bilateralFilter() , GaussianBlur() , medianBlur() , integral() .

cv::buildPyramid

void buildPyramid(const Mat& src, vector<Mat>& dst, int maxlevel)

画像のガウシアンピラミッドを作成します.

パラメタ:
  • src – 入力画像.サポートされる型の一覧は pyrDown() をチェックしてください
  • dstmaxlevel+1 個の画像をもつ出力ベクトル.各画像は src と同じ型です. dst[0]src と同じで, dst[1] は次の画像ピラミッド層であり,層が上がるに従い src が段々と平滑化,縮小化されます
  • maxlevel – 画像ピラミッドの最後の層(つまり最小の画像)のインデックス(0基準).これは非負の値でなければいけません

関数 buildPyramid は,画像のベクトルを作成し,ガウシアンピラミッドを構築します.この作業は, dst[0]==src から開始され,1つ前に作られた画像ピラミッド層に pyrDown() を再帰的に適用することで構築されます.

cv::copyMakeBorder

void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int borderType, const Scalar& value=Scalar())

画像のまわりに境界を作成します.

パラメタ:
  • src – 入力画像
  • dstsrc と同じ型の出力画像.サイズは Size(src.cols+left+right, src.rows+top+bottom) となります
  • top, bottom, left, right – 上下左右の各方向に,元の画像矩形から何ピクセル分の境界を作る必要があるかを指定します.例えば, top=1, bottom=1, left=1, right=1 ならば,幅1ピクセルの境界が必要になります
  • borderType – 境界の種類. borderInterpolate() を参照してください
  • valueborderType==BORDER_CONSTANT の場合の,境界のピクセル値

関数 copyMakeBorder は,入力画像を出力画像の中央にコピーします.そして,コピーされた入力画像の上下左右の隙間は,外挿されたピクセルで埋められます.これは, 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);
// 独自のフィルタリングを行う ...
...

参考: borderInterpolate()

cv::createBoxFilter

Ptr<FilterEngine> createBoxFilter(int srcType, int dstType, Size ksize, Point anchor=Point(-1, -1), bool normalize=true, int borderType=BORDER_DEFAULT)
Ptr<BaseRowFilter> getRowSumFilter(int srcType, int sumType, int ksize, int anchor=-1)
Ptr<BaseColumnFilter> getColumnSumFilter(int sumType, int dstType, int ksize, int anchor=-1, double scale=1)

ボックスフィルタエンジン.

パラメタ:
  • srcType – 入力画像の型
  • sumType – 中間出力である水平方向の総和の型. srcType と同じチャンネル数でなければいけません
  • dstType – 出力画像の型. srcType と同じチャンネル数でなければいけません
  • ksize – アパーチャサイズ
  • anchor – カーネルのアンカー位置.負の値は,アンカーがカーネル中心にあることを意味します
  • normalize – 総和が正規化されている否かを示します. boxFilter() を参照してください
  • scale – 低レベル関数 getColumnSumFilter で正規化を指定するためのもう1つの方法
  • borderType – 利用される境界の種類. borderInterpolate() を参照してください

関数 createBoxFilter は,水平方向の総和を求める基本フィルタ getRowSumFilter() と,垂直方向の総和を求める基本フィルタ getColumnSumFilter() を作成し,新たに作成された FilterEngine() に両方の基本フィルタを渡す簡易関数です.作成されたフィルタエンジンは,正規化された,あるいは正規化されていないボックスフィルタを用いた画像フィルタリングに利用できます.

この関数自身は, blur()boxFilter() で利用されます.

参考: FilterEngine() , blur() , boxFilter() .

cv::createDerivFilter

Ptr<FilterEngine> createDerivFilter(int srcType, int dstType, int dx, int dy, int ksize, int borderType=BORDER_DEFAULT)

微分画像を求めるためのエンジンを返します.

パラメタ:
  • srcType – 入力画像の型
  • dstType – 出力画像の型. srcType と同じチャンネル数でなければいけません
  • dx – xに関する微分の次数
  • dy – yに関する微分の次数
  • ksize – アパーチャサイズ. getDerivKernels() を参照してください
  • borderType – 利用される境界の種類. borderInterpolate() を参照してください

関数 createDerivFilter() は, getDerivKernels() を用いて微分画像を求めるための線形フィルタ係数を取得し, createSeparableLinearFilter() によって分離型線形フィルタを作成する小さな簡易関数です.この関数は, Sobel()Scharr() で利用されます.

参考: createSeparableLinearFilter() , getDerivKernels() , Scharr() , Sobel() .

cv::createGaussianFilter

Ptr<FilterEngine> createGaussianFilter(int type, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT)

ガウシアンフィルタによる画像の平滑化を行うエンジンを返します.

パラメタ:
  • type – 入力および出力される画像の型
  • ksize – アパーチャサイズ. getGaussianKernel() を参照してください
  • sigmaX – 水平方向のガウシアンシグマ. getGaussianKernel() を参照してください
  • sigmaY – 垂直方向のガウシアンシグマ.0ならば, sigmaY \leftarrow sigmaX となります
  • borderType – 利用される境界の種類. borderInterpolate() を参照してください

関数 createGaussianFilter() は,ガウシアンカーネルを求め,そのカーネルを利用した分離型線形フィルタを返します.この関数は GaussianBlur() で利用されます.この関数は入力と出力に共通する1つのデータ型しか取りませんが, getGaussianKernel() を呼び出した後に直接 createSeparableFilter() を呼ぶことで,この制限を回避できます.

参考: createSeparableLinearFilter() , getGaussianKernel() , GaussianBlur() .

cv::createLinearFilter

Ptr<FilterEngine> 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())
Ptr<BaseFilter> getLinearFilter(int srcType, int dstType, const Mat& kernel, Point anchor=Point(-1, -1), double delta=0, int bits=0)

非分離型線形フィルタエンジンを作成します.

パラメタ:
  • srcType – 入力画像の型
  • dstType – 出力画像の型. srcType と同じチャンネル数でなければいけません
  • kernel – フィルタ係数の2次元配列
  • anchor – カーネル内のアンカー点.特別な値である Point(-1,-1) は,アンカーがカーネル中心にあることを意味します
  • delta – フィルタ結果に足される値
  • bits – カーネルが,浮動小数点型フィルタ係数を表す整数型行列の場合,このパラメータは小数点以下のビット数を表します
  • rowBorderType, columnBorderType – 水平方向,垂直方向におけるピクセル外挿手法. borderInterpolate() を参照してください
  • borderValue – 定数境界モードで利用されるピクセル値

関数 getLinearFilter は,指定のカーネルを利用し,入出力配列の型を満たす2次元線形フィルタへのポインタを返します.関数 createLinearFilter は, getLinearFilter を呼び出し,そこから取得した2次元フィルタを FilterEngine() のコンストラクタに渡す高レベル関数です.

参考: createSeparableLinearFilter() , FilterEngine() , filter2D()

cv::createMorphologyFilter

Ptr<FilterEngine> createMorphologyFilter(int op, int type, const Mat& element, Point anchor=Point(-1, -1), int rowBorderType=BORDER_CONSTANT, int columnBorderType=-1, const Scalar& borderValue=morphologyDefaultBorderValue())
Ptr<BaseFilter> getMorphologyFilter(int op, int type, const Mat& element, Point anchor=Point(-1, -1))
Ptr<BaseRowFilter> getMorphologyRowFilter(int op, int type, int esize, int anchor=-1)
Ptr<BaseColumnFilter> getMorphologyColumnFilter(int op, int type, int esize, int anchor=-1)
static inline Scalar morphologyDefaultBorderValue(){ return Scalar::all(DBL_MAX) }

非分離型モルフォロジー演算を行うエンジンを作成します.

パラメタ:
  • op – モルフォロジー演算ID. MORPH_ERODE あるいは MORPH_DILATE
  • type – 入出力画像の型
  • element – モルフォロジー演算で用いる,2次元,8ビットの構造要素.ここでの 非0 の要素が,構造要素に属するピクセルを示します
  • esize – 分離型モルフォロジー演算で用いる構造要素の水平方向あるいは垂直方向のサイズ
  • anchor – カーネルのアンカー位置.負の値は,アンカーがカーネル中心にあることを意味します
  • rowBorderType, columnBorderType – 水平方向,垂直方向におけるピクセル外挿手法. borderInterpolate() を参照してください
  • borderValue – 定数境界モードで利用されるピクセル値.デフォルト値の morphologyDefaultBorderValue は特別な意味を持ちます.この場合,収縮では +\inf に,膨張では -\inf に変換されるので,画像内ピクセルの最小値(最大値)を効率的に求めることができます

これらの関数は,基本的なモルフォロジー演算,または,それに基づくフィルタエンジンを作成します.通常は, createMorphologyFilter() ,あるいは同等の高レベル関数 erode() , dilate() , morphologyEx() を用いれば十分でしょう. createMorphologyFilter() は,構造要素の形状を分析し,構造要素が正方形である場合は分離型モルフォロジーフィルタエンジンを構築することに注意してください.

参考: erode() , dilate() , morphologyEx() , FilterEngine()

cv::createSeparableLinearFilter

Ptr<FilterEngine> 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())
Ptr<BaseColumnFilter> getLinearColumnFilter(int bufType, int dstType, const Mat& columnKernel, int anchor, int symmetryType, double delta=0, int bits=0)
Ptr<BaseRowFilter> getLinearRowFilter(int srcType, int bufType, const Mat& rowKernel, int anchor, int symmetryType)

分離型線形フィルタエンジンを作成します.

パラメタ:
  • srcType – 入力画像の型
  • dstType – 出力画像の型. srcType と同じチャンネル数でなければいけません
  • bufType – 中間出力バッファの型. srcType と同じチャンネル数でなければいけません
  • rowKernel – 各行をフィルタリングるための係数
  • columnKernel – 各列をフィルタリングるための係数
  • anchor – カーネルのアンカー位置.負の値は,アンカーがカーネル中心にあることを意味します
  • delta – フィルタ結果に足される値
  • bits – カーネルが,浮動小数点型フィルタ係数を表す整数型行列の場合,このパラメータは小数点以下のビット数を表します
  • rowBorderType, columnBorderType – 水平方向,垂直方向におけるピクセル外挿手法. borderInterpolate() を参照してください
  • borderValue – 定数境界モードで利用されるピクセル値
  • symmetryType – それぞれの行カーネル,列カーネルの型. getKernelType() を参照してください

これらの関数は,基本的な分離型線形フィルタリング処理,またはそれに基づくフィルタエンジンを作成します.通常は, createSeparableLinearFilter() または同等の高レベル関数 sepFilter2D() を用いれば十分でしょう.関数 createMorphologyFilter() は賢いので,それぞれのカーネルに対する symmetryType ,中間値の bufType ,そして整数演算でフィルタリングされた場合にフィルタ係数にエンコードするための bits 数を算出します.これがうまく動作しないならば, getLinearColumnFilter , getLinearRowFilter を直接呼び出して,これらを FilterEngine() のコンストラクタに渡すこともできます.

参考: sepFilter2D() , createLinearFilter() , FilterEngine() , getKernelType()

cv::dilate

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())

指定の構造要素を用いて画像の膨張を行います.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じ型の出力画像
  • element – 膨張に用いられる構造要素. element=Mat() の場合, 3\times 3 の矩形構造要素が用いられます
  • anchor – 構造要素内のアンカー位置.デフォルト値の (-1, -1) は,アンカーが構造要素の中心にあることを意味します
  • iterations – 膨張が行われる回数
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください
  • borderValue – 定数境界モードで利用されるピクセル値.デフォルト値は特別な意味を持ちます. createMorphologyFilter() を参照してください

関数 dilate は,ピクセル近傍領域の形状を決定し,そこから最大値を取り出すような指定構造要素を用いて,入力画像の膨張を行います:

\texttt{dst} (x,y) =  \max _{(x',y'):  \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')

この関数は,置換モードをサポートします.膨張は複数( iterations )回適用することができます.また,マルチチャンネル画像の場合,各チャンネルは個別に処理されます.

参考: erode() , morphologyEx() , createMorphologyFilter()

cv::erode

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())

指定の構造要素を用いて画像の収縮を行います.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じ型の出力画像
  • element – 収縮に用いられる構造要素. element=Mat() の場合, 3\times 3 の矩形の構造要素が用いられます
  • anchor – 構造要素内のアンカー位置.デフォルト値の (-1, -1) は,アンカーが構造要素の中心にあることを意味します
  • iterations – 収縮が行われる回数
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください
  • borderValue – 定数境界モードで利用されるピクセル値.デフォルト値は特別な意味を持ちます. createMorphologyFilter() を参照してください

関数 erode は,ピクセル近傍領域の形状を決定し,そこから最小値を取り出すような指定構造要素を用いて,入力画像の収縮を行います:

\texttt{dst} (x,y) =  \min _{(x',y'):  \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')

この関数は,置換モードをサポートします.収縮は複数( iterations )回適用することができます.また,マルチチャンネル画像の場合,各チャンネルは個別に処理されます.

参考: dilate() , morphologyEx() , createMorphologyFilter()

cv::filter2D

void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel, Point anchor=Point(-1, -1), double delta=0, int borderType=BORDER_DEFAULT)

カーネルを用いて画像の畳み込みを行います.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じ型の出力画像
  • ddepth – 出力画像に求めるビット深度.負の場合は, src.depth() と同じになります
  • kernel – シングルチャンネルの浮動小数点型行列である畳み込みカーネル(厳密に言えば,相関カーネル).チャンネル毎に別のカーネルを適用したい場合は, split() を用いて画像を個別の色平面に分割し,それを別々に処理してください
  • anchor – カーネル内のフィルタ対象点の相対位置を表すカーネルアンカー.アンカーはカーネル内に存在する必要があります.特別なデフォルト値 (-1,-1) は,アンカーがカーネルの中心にあることを意味します
  • delta – オプション. dst に格納する前に,フィルタ結果に足される値
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください

関数 filter2D は,任意の線形フィルタを画像に適用します.また,置換モードがサポートされます.アパーチャが部分的に画像外にはみ出す場合,関数は指定された境界モードに基づいてピクセル値を外挿補間します.

この関数は,実際には畳み込みではなく相関を求めます:

\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} )

つまり,カーネルはアンカー点周りで対称ではありません.本当の畳み込みが必要ならば, flip() を用いてカーネルを反転し,新しいアンカー (kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1) をセットしてください.

この関数は,十分に大きいカーネル( ~ 11\times11 )の場合は に基づくアルゴリズムを利用し,小さいカーネルの場合は( createLinearFilter() によって取得されるエンジンを用いる)直接アルゴリズムを利用します.

参考: sepFilter2D() , createLinearFilter() , dft() , matchTemplate()

cv::GaussianBlur

void GaussianBlur(const Mat& src, Mat& dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT)

ガウシアンフィルタを用いて画像の平滑化を行います.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じ型の出力画像
  • ksize – ガウシアンカーネルサイズ. ksize.widthksize.height は別の値を取ることができますが,両方とも正の奇数でなければいけません.または 0 をとることも可能で,その場合のサイズは sigma* から算出されます
  • sigmaX, sigmaY – ガウシアンカーネルの,XとY方向の標準偏差. sigmaY が 0 ならば, sigmaX と等しくなるようにセットされます.両方の値が 0 の場合は,それぞれ ksize.widthksize.height から求められます. getGaussianKernel() を参照してください.将来これらの引数の意味が変更されたとしても,それに関係なく結果を完全に制御するために, ksize , sigmaX および sigmaY のすべての値を指定することが推奨されます
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください

この関数は,指定のガウシアンかーネルを用いて入力画像の畳み込みを行います.また,置換モードのフィルタリングがサポートされます.

参考: sepFilter2D() , filter2D() , blur() , boxFilter() , bilateralFilter() , medianBlur()

cv::getDerivKernels

void getDerivKernels(Mat& kx, Mat& ky, int dx, int dy, int ksize, bool normalize=false, int ktype=CV_32F)

画像の空間微分を求めるためのフィルタ係数を返します.

パラメタ:
  • kx – 行フィルタ係数が出力される行列.型は ktype
  • ky – 列フィルタ係数が出力される行列.型は ktype
  • dx – x に関する微分の次数
  • dy – y に関する微分の次数
  • ksize – アパーチャサイズ. CV_SCHARR , 1, 3, 5, 7 のいずれか
  • normalize – フィルタ係数を正規化(スケールダウン)するか否かを指定します.理論上は,係数の分母は =2^{ksize*2-dx-dy-2} となるべきです.浮動小数点型の画像をフィルタリングしようとする場合は,正規化されたカーネルを使いたいと思うでしょう.しかし,8ビット画像を微分し,その結果を16ビット画像に格納して小数部分の全ビットを保存したい場合など, normalize=false の設定を望む場合もあります
  • ktype – フィルタ係数の型. CV_32f あるいは CV_64F

関数 getDerivKernels は,画像の空間微分を求めるためのフィルタ係数を求め,それを返します. ksize=CV_SCHARR の場合は, 3 \times 3 の Scharr カーネルが生成されます. Scharr() を参照してください.そうでない場合は,Sobel カーネルが生成されます.同じく Sobel() を参照してください.これらのフィルタは通常, sepFilter2D()createSeparableLinearFilter() に渡されます.

cv::getGaussianKernel

Mat getGaussianKernel(int ksize, double sigma, int ktype=CV_64F)

ガウシアンフィルタの係数を返します.

パラメタ:
  • ksize – アパーチャサイズ.これは正の奇数( \texttt{ksize} \mod 2 = 1 )です
  • sigma – ガウシアンの標準偏差.これが正値でない場合, ksize を用いて sigma = 0.3*(ksize/2 - 1) + 0.8 という様に求められます
  • ktype – フィルタ係数の型. CV_32f あるいは CV_64F

関数 getGaussianKernel は, \texttt{ksize} \times 1 のガウシアンフィルタ係数行列を求め,それを返します.

G_i= \alpha *e^{-(i-( \texttt{ksize} -1)/2)^2/(2* \texttt{sigma} )^2},

ここで, i=0..\texttt{ksize}-1 であり, \alpha\sum_i G_i=1 となるように選ばれたスケールファクタです.

このように生成されたカーネルを2つ, sepFilter2D() あるいは createSeparableLinearFilter() に渡すことができます.これらは,渡されたカーネルが平滑化カーネルであることを自動的に検出して適切に扱います.また,高レベル関数 GaussianBlur() を使うこともできます.

参考: sepFilter2D() , createSeparableLinearFilter() , getDerivKernels() , getStructuringElement() , GaussianBlur() .

cv::getKernelType

int getKernelType(const Mat& kernel, Point anchor)

カーネルの種類を返す..

パラメタ:
  • kernel – 分析されるカーネル係数の1次元配列
  • anchor – カーネル内のアンカー位置

The function analyzes the kernel coefficients and returns the corresponding kernel type:

  • KERNEL_GENERAL 汎用カーネル - 対称でもなく,他の特徴もない場合
  • KERNEL_SYMMETRICAL カーネルが対称: \texttt{kernel}_i == \texttt{kernel}_{ksize-i-1} かつ,アンカーが中心にある
  • KERNEL_ASYMMETRICAL カーネルが非対称: \texttt{kernel}_i == -\texttt{kernel}_{ksize-i-1} かつ,アンカーが中央にある
  • KERNEL_SMOOTH すべてのカーネル要素が非負で,その合計が1.例えば,ガウシアンカーネルは smooth かつ symmetrical であるので,この関数は KERNEL_SMOOTH | KERNEL_SYMMETRICAL を返します
  • KERNEL_INTEGER すべてのカーネル係数が整数値.このフラグは KERNEL_SYMMETRICAL あるいは KERNEL_ASYMMETRICAL と組み合わせることができます

cv::getStructuringElement

Mat getStructuringElement(int shape, Size esize, Point anchor=Point(-1, -1))

モルフォロジー演算のために,指定されたサイズと形状の構造要素を返します.

パラメタ:
  • shape

    要素の形状.以下の中の1つ:

    • MORPH_RECT - 矩形構造要素

      E_ {ij} =1

    • MORPH_ELLIPSE - 楕円構造要素.つまり次の矩形に内接する楕円
      Rect(0, 0, esize.width, 0.esize.height)
    • MORPH_CROSS - 十字形構造要素

      E_ {ij}  =  \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}

  • esize – 構造要素のサイズ
  • anchor – カーネル内のアンカー位置.デフォルト値の (-1, -1) は,アンカーが構造要素の中心にあることを意味します.十字形構造要素の形状だけは,アンカー位置に依存することに注意してください.その他の場合は,単にモルフォロジー演算の結果をどれだけシフトするかによって調整されます

関数 getStructuringElement は, createMorphologyFilter() , erode() , dilate() または morphologyEx() に渡される構造要素を作成し,それを返します.しかし,任意の2値マスクを作成し,それを構造要素として利用することもできます.

cv::medianBlur

void medianBlur(const Mat& src, Mat& dst, int ksize)

メディアンフィルタを用いて画像の平滑化を行います.

パラメタ:
  • src – 1-, 3- あるいは 4-チャンネルの入力画像. ksize が 3 または 5 ならば,この画像のビット深度は CV_8U , CV_16U または CV_32F となります.それ以上のアパーチャサイズの場合は CV_8U だけが可能です
  • dstsrc と同じサイズ,同じ型の出力画像
  • ksize – アパーチャサイズ.1より大きな奇数,例えば 3, 5, 7 ... でなければいけません

関数 medianBlur は,アパーチャサイズが \texttt{ksize} \times \texttt{ksize} であるメディアンフィルタを用いて,画像の平滑化を行います.マルチチャンネル画像の各チャンネルは,個別に処理されます.また,置換モード処理がサポートされます.

参考: bilateralFilter() , blur() , boxFilter() , GaussianBlur()

cv::morphologyEx

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())

高度なモルフォロジー変換を行います.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じ型の出力画像
  • element – 構造要素
  • op

    モルフォロジー演算の種類.以下のうちの1つ:

    • MORPH_OPEN オープニング
    • MORPH_CLOSE クロージング
    • MORPH_GRADIENT モルフォロジー勾配
    • MORPH_TOPHAT 「トップハット変換」
    • MORPH_BLACKHAT 「ブラックハット変換」
  • iterations – 収縮と膨張が適用される回数
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください
  • borderValue – 定数境界モードで利用されるピクセル値.デフォルト値は特別な意味を持ちます. createMorphologyFilter() を参照してください

関数 morphologyEx は,収縮と膨張を基本演算として利用する高度なモルフォロジー変換を行います.

オープニング:

\texttt{dst} = \mathrm{open} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \mathrm{erode} ( \texttt{src} , \texttt{element} ))

クロージング:

\texttt{dst} = \mathrm{close} ( \texttt{src} , \texttt{element} )= \mathrm{erode} ( \mathrm{dilate} ( \texttt{src} , \texttt{element} ))

モルフォロジー勾配:

\texttt{dst} = \mathrm{morph\_grad} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \texttt{src} , \texttt{element} )- \mathrm{erode} ( \texttt{src} , \texttt{element} )

「トップハット変換」:

\texttt{dst} = \mathrm{tophat} ( \texttt{src} , \texttt{element} )= \texttt{src} - \mathrm{open} ( \texttt{src} , \texttt{element} )

「ブラックハット変換」:

\texttt{dst} = \mathrm{blackhat} ( \texttt{src} , \texttt{element} )= \mathrm{close} ( \texttt{src} , \texttt{element} )- \texttt{src}

いずれの演算も置換モードをサポートします.

参考: dilate() , erode() , createMorphologyFilter()

cv::Laplacian

void Laplacian(const Mat& src, Mat& dst, int ddepth, int ksize=1, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)

画像のラプラシアンを求めます.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じチャンネル数の出力画像
  • ddepth – 出力画像に求めるビット深度
  • ksize – 2次微分フィルタを求めるために利用されるアパーチャのサイズ. getDerivKernels() を参照してください.これは正の奇数でなければいけません
  • scale – オプション.求められたラプラシアンに対するスケールファクタ(デフォルトではスケーリングされません. getDerivKernels() を参照してください)
  • deltadst に格納する前に,結果に足されるオプション値
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください

関数 cvLaplace は,Sobelオペレータを用いて計算される x および y に関する2次微分を足し合わせることで,入力画像のラプラシアンを求めます.

\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 の場合は, 3 \times 3 のアパーチャを用いたフィルタリングによってラプラシアンを求めます.

\vecthreethree {0}{1}{0}{1}{-4}{1}{0}{1}{0}

参考: Sobel() , Scharr()

cv::pyrDown

void pyrDown(const Mat& src, Mat& dst, const Size& dstsize=Size())

画像の平滑化とダウンサンプリングを行います.

パラメタ:
  • src – 入力画像
  • dst – 指定されたサイズで, src と同じ型の出力画像
  • dstsize

    出力画像のサイズ.デフォルトでは, Size((src.cols+1)/2, (src.rows+1)/2) として求められます.しかし,いずれの場合も,以下の条件を満足しなければいけません:

    \begin{array}{l}
| \texttt{dstsize.width} *2-src.cols| \leq  2  \\ | \texttt{dstsize.height} *2-src.rows| \leq  2 \end{array}

関数 pyrDown は,ガウシアンピラミッド作成におけるダウンサンプリング部分を実行します.まず,以下のカーネルで入力画像の畳み込みを行います:

\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}

そして,偶数行と偶数列を読み飛ばすことで,画像のダウンサンプリングを行います.

cv::pyrUp

void pyrUp(const Mat& src, Mat& dst, const Size& dstsize=Size())

画像のアップサンプリングと平滑化を行います.

パラメタ:
  • src – 入力画像
  • dst – 指定されたサイズで, src と同じ型の出力画像
  • dstsize

    出力画像のサイズ.デフォルトでは, Size(src.cols*2, src.rows*2) として求められます.しかし,いずれの場合も,以下の条件を満足しなければいけません:

    \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 で埋められた偶数行,偶数列を挿入してアップサンプリングを行い, pyrDown() のときと同じカーネルを4倍したもので,その結果を畳み込みます.

cv::sepFilter2D

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)

画像に分離型線形フィルタを適用します.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じチャンネル数の出力画像
  • ddepth – 出力画像のビット深度
  • rowKernel – 各行をフィルタリングするための係数
  • columnKernel – 各列をフィルタリングするための係数
  • anchor – カーネル内のアンカー位置.デフォルト値の (-1, -1) は,アンカーがカーネルの中心にあることを意味します
  • delta – フィルタ結果に足される値
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください

この関数は,画像に分離型線形フィルタを適用します.つまり,まず, src の各行に1次元カーネル rowKernel でフィルタリングを行います.次に,その結果の各列に対して1次元カーネル columnKernel でフィルタリングを行い,最終的な結果を delta だけシフトしたものが dst に格納されます.

参考: createSeparableLinearFilter() , filter2D() , Sobel() , GaussianBlur() , boxFilter() , blur() .

cv::Sobel

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次または混合次数の微分画像を求めます.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じチャンネル数の出力画像
  • ddepth – 出力画像のビット深度
  • xorder – xに関する微分の次数
  • yorder – yに関する微分の次数
  • ksize – 拡張Sobelカーネルのサイズ. 1, 3, 5 あるいは 7 のいずれか
  • scale – オプション.求められた微分値に対するスケールファクタ(デフォルトではスケーリングされません. getDerivKernels() を参照してください)
  • deltadst に格納する前に,結果に足されるオプション値
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください

カーネルサイズ1を除くすべての場合で,微分画像を求めるために \texttt{ksize} \times \texttt{ksize} の分離型カーネルが用いられます. \texttt{ksize = 1} の場合は, 3 \times 1 または 1 \times 3 のカーネルが用いられます(つまり,ガウシアン平滑化は行われません). ksize = 1 は,1次または2次の,x- あるいは y-微分に関してのみ利用されます.

特別な値 ksize = CV_SCHARR (-1) も存在し,これは 3\times3 の Sobel よりも正確な結果を得ることができる 3\times3 のScharr フィルタを意味します.この Scharr アパーチャは以下のようになります.

\vecthreethree{-3}{0}{3}{-10}{0}{10}{-3}{0}{3}

これは x-導関数に対するカーネルであり,転置すれば y-導関数に対するカーネルとなります.

関数 sobel は,以下のように,画像と適切なカーネルの畳み込みによって微分画像を求めます:

\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). 最初の例は,以下のカーネルに対応します:

\vecthreethree{-1}{0}{1}{-2}{0}{2}{-1}{0}{1}

また,2番目の例は,以下のカーネルに対応します:

\vecthreethree{-1}{-2}{-1}{0}{0}{0}{1}{2}{1}

参考: Scharr() , Lapacian() , sepFilter2D() , filter2D() , GaussianBlur()

cv::Scharr

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-微分画像を求めます.

パラメタ:
  • src – 入力画像
  • dstsrc と同じサイズ,同じチャンネル数の出力画像
  • ddepth – 出力画像のビット深度
  • xorder – xに関する微分の次数
  • yorder – yに関する微分の次数
  • scale – オプション.求められた微分値に対するスケールファクタ(デフォルトではスケーリングされません. getDerivKernels() を参照してください)
  • deltadst に格納する前に,結果に足されるオプション値
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください

この関数は,Scharrオペレータを用いて,1次のx-あるいはy-微分画像を求めます.次の関数呼び出し

\texttt{Scharr(src, dst, ddepth, xorder, yorder, scale, delta, borderType)}

は,以下と等価になります.

\texttt{Sobel(src, dst, ddepth, xorder, yorder, CV\_SCHARR, scale, delta, borderType)} .