画像フィルタリング

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

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

IplConvKernel

IplConvKernel

IplConvKernel は, CreateStructuringElementEx によって作成される,矩形の畳み込みカーネルです.

cv::CopyMakeBorder

void cvCopyMakeBorder(const CvArr* src, CvArr* dst, CvPoint offset, int bordertype, CvScalar value=cvScalarAll(0))

画像をコピーし,その周りに境界を作成します.

パラメタ:
  • src – 入力画像
  • dst – 出力画像
  • offset – 入力画像(あるいは,そのROI)のコピー先となる出力矩形領域の,左上のコーナー座標(画像の原点が左下の場合は,左下コーナーの座標).この矩形領域のサイズは,入力画像サイズ/ROIサイズと一致します
  • bordertype

    コピーされた入力画像の周りに作成される境界領域の種類.以下のいずれか(IPLでサポートされていた別の2種類の境界, IPL_BORDER_REFLECT および IPL_BORDER_WRAP は,現在はサポートされていません):

    • IPL_BORDER_CONSTANT 境界領域は,この関数の最後の引数として渡された定数で埋められます
    • IPL_BORDER_REPLICATE 境界領域は,画像の上下の1行,左右の1列の画素値が複製されたもので埋められます
  • valuebordertypeIPL_BORDER_CONSTANT である場合の,境界領域の値

この関数は,2次元の入力配列を出力配列の内側にコピーし,その周りに指定された種類の境界領域を作成します.この関数は,特定のアルゴリズム内部で利用される境界領域とは別のものをエミュレートする必要がある場合に役立ちます.例えば,モルフォロジー演算の関数は,OpenCVの多くのフィルタリング関数と同様に内部では複製境界を使用していますが,ユーザにとって境界が不要だったり,あるいは 1 や 255 の値で埋められた境界が必要な場合もあるかもしれません.

cv::CreateStructuringElementEx

IplConvKernel* cvCreateStructuringElementEx(int cols, int rows, int anchorX, int anchorY, int shape, int* values=NULL)

構造要素を作成します.

パラメタ:
  • cols – 構造要素の列数
  • rows – 構造要素の行数
  • anchorX – アンカーポイントの水平方向の相対オフセット値
  • anchorY – アンカーポイントの垂直方向の相対オフセット値
  • shape

    構造要素の形状.以下のような値をとります:

    • CV_SHAPE_RECT 矩形の構造要素
    • CV_SHAPE_CROSS 十字の構造要素
    • CV_SHAPE_ELLIPSE 楕円の構造要素
    • CV_SHAPE_CUSTOM ユーザー定義形状の構造要素.この場合,パラメータ values がマスク(つまり,構成要素の点と見なされるピクセルの周辺領域)を指定します
  • values – 平面配列である構造要素データへのポインタであり,構造要素行列を行毎に走査したものを表しています.データが0以外の値の場合は構造要素を構成する点であることを示します.このポインタが NULL の場合は,全ての値が0ではないと見なされ,構造要素は矩形形状となります.なお,このパラメータは,shape が CV_SHAPE_CUSTOM の場合にのみ有効です

この関数は,モルフォロジー演算の構造要素として利用する構造体 IplConvKernel の領域を確保し,それを初期化します.

cv::Dilate

void cvDilate(const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1)

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

パラメタ:
  • src – 入力画像
  • dst – 出力画像
  • element – 膨張に用いる構造要素.これが NULL の場合, 3\times 3 の矩形形状の構造要素が用いられます
  • iterations – 膨張が適用される回数

この関数は,ピクセル近傍領域の形状を決定する任意の構造要素を用いて,画像を膨張させます.以下のように,対象ピクセルの近傍領域の最大値をそのピクセル値とします:

\max _{(x',y')  \, in  \, \texttt{element} }src(x+x',y+y')

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

cv::Erode

void cvErode(const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1)

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

パラメタ:
  • src – 入力画像
  • dst – 出力画像
  • element – 収縮に用いる構造要素.これが NULL の場合, 3\times 3 の矩形形状の構造要素が用いられます
  • iterations – 収縮が適用される回数

この関数は,ピクセル近傍領域の形状を決定する任意の構造要素を用いて,画像を収縮させます.以下のように,対象ピクセルの近傍領域の最小値をそのピクセル値とします:

\min _{(x',y')  \, in  \, \texttt{element} }src(x+x',y+y')

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

cv::Filter2D

void cvFilter2D(const CvArr* src, CvArr* dst, const CvMat* kernel, CvPoint anchor=cvPoint(-1, -1))

指定されたカーネルで,画像の畳み込みを行います.

パラメタ:
  • src – 入力画像
  • dst – 出力画像
  • kernel – 畳み込みカーネル.シングルチャンネル,浮動小数点型の行列.異なるチャンネルに異なるカーネルを適用したい場合は, Split を用いて画像を色平面に分解し,それぞれを個別に処理します
  • anchor – フィルタ対象となる点のカーネル内での相対位置を示す,カーネルのアンカー.アンカーはカーネル内に存在します.デフォルト値である (-1,-1) は,カーネル中心を表す特別な値です

この関数は,画像に任意の線形フィルタを適用します.また,置換モードでの処理がサポートされます.フィルタ範囲が部分的に画像外に出てしまった場合,この関数は,画像内にある最近傍のピクセルから範囲外のピクセル値を補間します.

cv::Laplace

void cvLaplace(const CvArr* src, CvArr* dst, int apertureSize=3)

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

パラメタ:
  • src – 入力画像
  • dst – 出力画像
  • apertureSize – アパーチャサイズ( Sobel の場合と同じ)

この関数は,以下のように Sobel オペレータを使って計算されたxとyの2次微分を足し合わせることで,入力画像のラプラシアンを求めます:

\texttt{dst} (x,y) =  \frac{d^2 \texttt{src}}{dx^2} +  \frac{d^2 \texttt{src}}{dy^2}

apertureSize = 1 を指定すると,画像と以下のカーネルの畳み込み処理と同じ処理を,最も高速に計算できます:

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

関数 Sobel と同様にスケーリングは行われなず,サポートする入出力画像のフォーマットも同じです.

cv::MorphologyEx

void cvMorphologyEx(const CvArr* src, CvArr* dst, CvArr* temp, IplConvKernel* element, int operation, int iterations=1)

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

パラメタ:
  • src – 入力画像
  • dst – 出力画像
  • temp – いくつかの場合で必要とされる,テンポラリな画像
  • element – 構造要素
  • operation

    モルフォロジー演算の種類,以下のいずれか:

    • CV_MOP_OPEN オープニング
    • CV_MOP_CLOSE クロージング
    • CV_MOP_GRADIENT モルフォロジー勾配
    • CV_MOP_TOPHAT トップハット変換
    • CV_MOP_BLACKHAT ブラックハット変換
  • iterations – 収縮および膨張の適用回数

この関数は,収縮および膨張を組み合わせた高度なモルフォロジー変換を行うことができます.

オープニング:

dst=open(src,element)=dilate(erode(src,element),element)

クロージング:

dst=close(src,element)=erode(dilate(src,element),element)

モルフォロジー勾配:

dst=morph \_ grad(src,element)=dilate(src,element)-erode(src,element)

トップハット変換:

dst=tophat(src,element)=src-open(src,element)

ブラックハット変換:

dst=blackhat(src,element)=close(src,element)-src

モルフォロジー勾配,およびトップハット変換とブラックハット変換の置換モードでは,テンポラリな画像 temp が必要です.

cv::PyrDown

void cvPyrDown(const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5)

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

パラメタ:
  • src – 入力画像
  • dst – 出力画像.幅と高さは,入力画像の半分
  • filter – 畳み込みフィルタの種類.現在は, CV_GAUSSIAN_5x5 だけがサポートされています

この関数は,ガウシアンピラミッド分解の1ステップであるダウンサンプリングを行います.まず,入力画像と指定されたフィルタの畳み込みを行い,画像の偶数行と偶数列を間引くことでダウンサンプリングを行います.

cv::ReleaseStructuringElement

void cvReleaseStructuringElement(IplConvKernel** element)

構造要素を削除します.

Parameter:element – 削除される構造要素へのポインタ

この関数は,不要になった構造体 IplConvKernel を解放します. *elementNULL の場合は,この関数は何もしません.

cv::Smooth

void cvSmooth(const CvArr* src, CvArr* dst, int smoothtype=CV_GAUSSIAN, int param1=3, int param2=0, double param3=0, double param4=0)

指定の手法で画像を平滑化します.

パラメタ:
  • src – 入力画像
  • dst – 出力画像
  • smoothtype

    平滑化の手法:

    • CV_BLUR_NO_SCALE \texttt{param1}\times \texttt{param2} のボックスカーネル(すべてが1)との線形畳み込み.異なるピクセルを異なるサイズのボックスフィルタで平滑化したい場合は, Integral によって求められるインテグラルイメージを利用します
    • CV_BLUR \texttt{param1}\times\texttt{param2} のボックスカーネル(すべてが1)との線形畳み込み.その後に, 1/(\texttt{param1}\cdot\texttt{param2}) のスケーリングを行います
    • CV_GAUSSIAN \texttt{param1}\times\texttt{param2} のガウシアンカーネルとの線形畳み込み
    • CV_MEDIAN \texttt{param1}\times\texttt{param1} の正方アパーチャのメディアンフィルタ
    • CV_BILATERAL \texttt{param1}\times\texttt{param1} の正方アパーチャのバイラテラルフィルタ.パラメータは, color sigma= param3 , spatial sigma= param4 です. param1=0 ならば,アパーチャの1辺は cvRound(param4*1.5)*2+1 にセットされます.バイラテラルフィルタに関する情報は, http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html を参照してください
  • param1 – 1番目の平滑化パラメータである,アパーチャの幅.正の奇数 (1, 3, 5, ...) でなければいけません
  • param2 – 平滑化パラメータ2.平滑化手法が,スケーリング有り/無しの単純平滑またはガウシアン平滑化の場合,この param2 が 0 ならば,ここには param1 の値がセットされます
  • param3

    ガウシアン平滑化の場合,このパラメータがガウス分布の \sigma (標準偏差)を示します.これが0の場合,以下のようにカーネルサイズから計算されます:

    \sigma  = 0.3 (n/2 - 1) + 0.8  \quad   \text{where}   \quad  n= \begin{array}{l l} \mbox{\texttt{param1} for horizontal kernel} \\ \mbox{\texttt{param2} for vertical kernel} \end{array}

    小さいサイズのカーネル( 3\times 3 から 7\times 7 )の場合は,標準の sigma を用いた方が高速に計算できます.この param3 が 0 ではなく,かつ param1param2 が 0 の場合,(処理に十分な精度を得るために)カーネルサイズは sigma から計算されます

この関数は,指定された手法を用いて画像の平滑化を行います.各手法には,以下に示すような特徴と制限があります.

スケーリングなしの平滑化は,シングルチャンネル画像に対してのみ適用でき,( SobelLaplace と同様に)8ビットから16ビットフォーマットへの累積計算や,32ビット浮動小数点数から32ビット浮動小数点数への累積計算をサポートします.

単純平滑化とガウシアン平滑化は,1チャンネル,あるいは3チャンネル,8ビット,16ビット,32ビット浮動小数点型の画像をサポートします.また,これら2つの手法は,置換モードで画像を処理することができます.

メディアンフィルタとバイラテラルフィルタは,1チャンネル,あるいは3チャンネル,8ビット画像に適用でき,置換モードでの処理は行えません.

cv::Sobel

void cvSobel(const CvArr* src, CvArr* dst, int xorder, int yorder, int apertureSize=3)

拡張 Sobel オペレータを用いて1次,2次,3次または混合次数の微分画像を求めます.

パラメタ:
  • src – CvArr* 型の入力画像
  • dst – 出力画像
  • xorder – x 方向の微分次数
  • yorder – y 方向の微分次数
  • apertureSize – 拡張 Sobel カーネルのサイズ,1,3,5,7 のいずれか

aperatureSize = 1 の場合を除いて, \texttt{apertureSize} \times \texttt{apertureSize} の,(2つのベクトルの積に)分離可能なカーネルが微分画像の計算に用いられます. \texttt{apertureSize} = 1 の場合は, 3 \times 1 または 1 \times 3 のカーネルが用いられます(ガウシアンによる平滑化は行われません).また,特別な値である CV_SCHARR (-1) は, 3\times3 の Sobel より精度が良い 3\times3 の Scharr フィルタに対応します.この Scharr のアパーチャは以下のようになります

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

これは x-方向微分に対するカーネルであり,転置すれば y-方向微分に対するカーネルとなります.

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

\texttt{dst} (x,y) =  \frac{d^{xorder+yorder} \texttt{src}}{dx^{xorder} \cdot dy^{yorder}}

Sobel オペレータは,ガウシアンによる平滑化と微分の組み合わせなので,その結果はノイズに対して多少は頑健です.1次の x-あるいは,y-微分画像を求める場合は大抵,この関数は次のような引数で呼び出されます:( xorder = 1, yorder = 0, apertureSize = 3) あるいは ( xorder = 0, yorder = 1, apertureSize = 3).最初の例は,以下のカーネルに対応します:

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

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

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

または,

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

どちらのカーネルになるかは,元画像の原点(構造体 IplImage のフィールド origin )に依存します.スケーリングは行われないので,出力画像の各ピクセル値は,ほとんどの場合入力画像のそれよりも大きな値になります.そこでオーバーフローを避けるために,例えば入力画像が8ビットの場合,出力画像として16ビット画像を指定する必要があります.このような16ビット画像は,関数 ConvertScaleConvertScaleAbs を用いて 8ビット画像に戻すことができます.またこの関数は,8ビット画像だけでなく32ビット浮動小数点型画像も処理可能です.ただし,入力画像,出力画像共に,同じサイズ,あるいは同じ ROI サイズのシングルチャンネル画像である必要があります.