第 7 章: 画像のスムージング

画像の平滑化は、画像の元の情報を可能な限り維持しながら、画像内のノイズを除去することです。通常、画像の平滑化には画像のぼかしが伴うため、画像の平滑化は画像のぼかしとも呼ばれます。コンピュータでは画像フィルタリングと呼ばれることもあります。これは単なる名前であり、場所によって言い伝えが異なる場合があるので、あまり絡めないでください。

  • 画像のスムージングの目的は、画像の内部ノイズを除去することです。

画像平滑化処理の本質は、周囲の画素とは大きく異なる画像内の画素値を処理し、その値を周囲の画素の画素値の近似値に調整することです。

写真が示すように:

画像-20211014150205518

3 行 3 列目に位置するピクセルは、周囲のピクセル値と明らかに値が異なります。画像に反映されると、この点の周囲のピクセルはすべてグレースケールの点であり、この点の色はより暗く、黒い点はノイズである可能性があり、この点の値は周囲のピクセル値の近似値に調整する必要があります。 。

画像-20211014150330480

画像の平滑化処理にはさまざまな方法がありますが、主な紹介は次のとおりです。

  • 平均フィルタリング
  • ボックスフィルター
  • ガウスフィルター
  • メディアンフィルター
  • 双方向フィルタリング
  • 2D コンボリューション (カスタム フィルタリング)

1. 平均フィルタリング:

平均値フィルタリングとは、現在のピクセル点の周囲の N*N ピクセル値の平均値を使用して、現在のピクセル点を中心として現在のピクセル値を置き換えることを指します。この方法を使用して画像内の各ピクセルを走査して処理すると、画像全体の平均フィルタリングを完了できます。

画像エッジ ピクセルの場合は、画像内の周囲の近傍点のピクセル値の平均値のみを取得できます。画像の端を拡大して、新たに追加した行と列に異なるピクセル値を塗りつぶすことも可能で、これに基づいて、元の画像の近傍 N・N 個のピクセルの平均値を計算します。OpenCV はさまざまな境界処理メソッドを提供しており、実際のニーズに応じてさまざまな境界処理モードを選択できます。

画像-20211014152606976

1. 関数の構文:

  • OpenCV では、平均値を実現する関数は cv2.blur() であり、その構文形式は次のとおりです。

    • dst = cv2.blur(src、ksize、アンカー、borderType)

      • dst: 戻り値、平均値フィルタリング後の処理結果。

      • src: 処理対象の画像、つまり元の画像。チャネルはいくつでも使用でき、各チャネルは独立して処理できます。画像の深さは CV_8U、CV_16U、CV_16S、CV_32F、CV_64F のいずれかである必要があります。

      • ksize: フィルター カーネルのサイズです。フィルター カーネル サイズは、平均処理中の近傍イメージの高さと幅を指します。例えば、その値は(5,5)であり、サイズ5×5の近傍平均値が画像平均値フィルタリングプロセスの結果として使用されることを示す。

        画像-20211014152435585

        M と N はそれぞれ高さと幅に対応します。一般に、M と N は等しいです (より一般的に使用される 3×3、5×5、7×7 など)。M と N の値が大きいほど、演算に関与するピクセル数が多くなり、画像の歪みが大きくなります。

      • Anchor: アンカーポイント、デフォルト値は (-1, -1) で、平均を計算するための現在のポイントがカーネルの中心点に位置し、デフォルト値で十分であることを意味します。 point はアンカーポイントとして指定できます。

      • borderType: 境界線のスタイル。この値は境界線の処理方法を決定します。通常、この値の値を考慮する必要はなく、デフォルトを使用します。

例:

import cv2

img = cv2.imread('../lena512color_noise.tiff')
dst1 = cv2.blur(img, (7, 7))
dst2 = cv2.blur(img, (15, 15))
cv2.imshow('img', img)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

2. ボックスフィルタリング:

ボックス フィルタリングはピクセル平均値を計算しないという点で、ボックス フィルタリングは平均フィルタリングとは異なります。平均値フィルタリングでは、フィルタリング結果は任意の点の近傍平均です。ボックス フィルタリングでは、平均フィルタリングの結果を正規化するかどうかを自由に選択でき、フィルタリング構造が近傍の合計であるか、近傍の合計の平均であるかを自由に選択できます。

1. ボックス フィルターの構文:

OpenCV では、ボックス フィルタリングを実装する関数は cv2.boxFilter() で、その構文形式は次のとおりです。

dst = cv2.boxFilter(src, d Depth, ksize, アンカー, 正規化, borderType)

  • dst: 戻り値、平均値フィルタリング後の処理結果。

  • src: 処理対象の画像、つまり元の画像。チャネルはいくつでも使用でき、各チャネルは独立して処理できます。画像の深さは CV_8U、CV_16U、CV_16S、CV_32F、CV_64F のいずれかである必要があります。

  • d Depth: 結果イメージのイメージ深度。通常、元のイメージと同じイメージ深度を示すには -1 を使用します。

  • ksize: フィルター カーネルのサイズです。フィルター カーネル サイズは、平均処理中の近傍イメージの高さと幅を指します。例えば、その値は(5,5)であり、サイズ5×5の近傍平均値が画像平均値フィルタリングプロセスの結果として使用されることを示す。

ここに画像の説明を挿入

  • アンカー: アンカーポイント、デフォルト値は (-1, -1) です。これは、現在の計算ポイントがカーネルの中心点に位置することを意味します。デフォルト値は変更に使用でき、別のポイントを指定できます。特殊な場合のアンカーポイントとして。

  • Normalize: フィルタリング時に正規化処理(正規化:ここでは演算結果を妥当な範囲に正規化すること、つまり演算結果を現在の画素値の範囲内の値に正規化することを指します)を行うかどうかを示します。このパラメータは論理値です。

    • パラメータnormalize=1の場合は正規化処理を行うことを意味し、周囲の画素と処理領域の値を使用します。
    • パラメータnormalize=0の場合は、正規化処理が不要であることを意味し、隣接する画素値の合計がそのまま使用されます。(合計が255を超える場合は255)

    通常、ボックス フィルタリングの場合、畳み込みカーネルは次のように表現できます。
    ここに画像の説明を挿入

上記の対応関係は次のとおりです。
f ( n ) = { 1 / width ⋅ height , Normalize=1 1 , Normalize=0 f(n)= \begin{cases} 1/width·height, & \text{normalize=1} \ \ 1,& \text{normalize=0} \end{cases}f ( n )={ 1 /_ _ _ __ _ _ _1正規化=1正規化= 0

  • borderType: 境界線のスタイル。この値は境界線の処理方法を決定します。

通常、ボックスフィルタ機能を使用する場合、パラメータanchor、normalize、borderTypeはデフォルト値をそのまま使用できます。

例:

import cv2

img = cv2.imread('../lena512color_noise.tiff')
rst = cv2.boxFilter(img, -1, (7, 7))
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

3. ガウスフィルター:

平均値フィルタリングとボックス フィルタリングでは、近傍の各ピクセルの重みは等しくなります。ガウス フィルタリングでは、中心点に近いほど重みが大きくなり、中心点から遠いほど重みが小さくなり、これに基づいて、近傍の各ピクセル値の異なる重みの合計が計算されます。

1. 基本原則

  • ガウス フィルタリングでは、コンボリューション カーネルの値がすべて 1 になるわけではありません。写真のように

    画像-20211016234515733

  • ガウス フィルタリングでは、コンボリューション カーネルの幅と高さは異なっていてもかまいませんが、それらは奇数である必要があります。

    画像-20211016234617059

  • コンボリューション カーネルの各サイズは、さまざまな形式でさまざまな重量比を持つことができます。図に示すように、これは 5x5 コンボリューション カーネルでもあります。

    画像-20211016234752725

    さまざまなマテリアルで、コンボリューション カーネルはさまざまな表現を持ちます。それらは表に書かれてもよいし、マトリックスに示されてもよい。実際の計算では、コンボリューションカーネルは正規化されており、10進数形式または分数形式のコンボリューションカーネルとして表現できます。正規化を行わない畳み込みカーネルを使用して、問題を説明します。厳密に言えば、フィルタリング用に正規化されていないコンボリューション カーネルを使用すると、結果が間違っていることがよくあります。

2. 関数の構文:

OpenCV では、ガウス フィルタリングを実装する関数 cv2.GaussianBlur() の構文形式は次のとおりです。

dst = cv2.GauusianBlur(src, ksize, sigmaX, sigmaY, borderType)

  • dst: 戻り値、平均値フィルタリング後の処理結果。

  • src: 処理対象の画像、つまり元の画像。チャネルはいくつでも使用でき、各チャネルは独立して処理できます。画像の深さは CV_8U、CV_16U、CV_16S、CV_32F、CV_64F のいずれかである必要があります。

  • ksize: フィルター カーネルのサイズです。フィルター カーネル サイズは、平均処理中の近傍イメージの高さと幅を指します。ただし、フィルター カーネルの値は奇数でなければならないことに注意してください。

  • sigmaX: コンボリューションカーネルの水平方向(X軸方向)の標準偏差で、重み比を制御します。

  • sigmaY: 垂直方向 (Y 軸方向) のコンボリューション カーネルの標準偏差。この値を 0 に設定すると、sigmaX の値のみが使用されます。sigmaX と sigmaY の両方が 0 の場合は、ksize.width と sigmaY を渡します。 ksize.height を計算して取得します。

    • sigmaX = 0.3 × [(ksize.width-1) × 0.5-1] + 0.8
    • sigmaY = 0.3 × [(ksize.height-1) × 0.5-1] + 0.8
  • borderType: 境界線のスタイル。この値は境界線の処理方法を決定します。通常の状況では、この値を考慮する必要はなく、デフォルト値が直接使用されます。

注: sigmaY と borderType は、この関数のオプションのパラメーターです。sigmaX は必須パラメータですが、0 に設定すると、関数が sigmaX の特定の値を独自に計算できるようになります。

公式ドキュメントでは、将来のパラメーターの変更によって発生する可能性のある構文エラーを避けるために、ksize、sigmaX、sigmaY の 3 つのパラメーターの値を指定することを推奨しています。もちろん、実際の処理において表示できる指定のsigmaX、sigmaYはデフォルト値の0です。したがって、関数 cv2.GaussianBlur() の一般的な形式は次のようになります。

  • dst = cv2.GaussianBlur(src, ksize, 0, 0)

import cv2
o=cv2.imread("image\\lenaNoise.png")
r=cv2.GaussianBlur(o,5,5,0,0)
cv2.imshow("original",o)
cv2.imshow("result",r)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

4. メディアンフィルタリング

メディアン フィルタリングは以前のフィルタリング方法とは異なり、フィルタリング結果の計算にフィルタ値は使用されなくなりました。近傍のすべてのピクセル値の中央値を使用して、現在のピクセルのピクセル値を置き換えます。

1. 基本原則:

メディアン フィルタリングは、現在のピクセルとその周囲の隣接ピクセル (奇数ピクセルの合計) のピクセル値を取得して並べ替え、中央の位置のピクセル値を現在のピクセルのピクセル値として使用します。

2. 関数の構文:

OpenCV では、メディアン フィルタリングを実装する関数は cv2.medianBlur() で、その構文形式は次のとおりです。

dst = cv2.medianBlur(src, ksize)

  • dst: 戻り値、平均値フィルタリング後の処理結果。

  • src: 処理対象の画像、つまり元の画像。チャネルはいくつでも使用でき、各チャネルは独立して処理できます。画像の深さは CV_8U、CV_16U、CV_16S、CV_32F、CV_64F のいずれかである必要があります。

  • ksize: フィルター カーネルのサイズです。フィルター カーネル サイズは、平均処理中の近傍イメージの高さと幅を指します。ただし、フィルター カーネルの値は 3、5、7 など、1 より大きい奇数でなければならないことに注意してください。

例:

import cv2

img = cv2.imread('../lena512color_noise.tiff')
rst = cv2.medianBlur(img, 5)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

この結果から、メディアンフィルターには平均値処理が実行されないため、平均値フィルターなどのフィルター手法によって引き起こされる詳細の曖昧さの問題がないことがわかります。メディアンフィルター処理ではノイズ成分の選別が難しいため、元の画像に影響を与えることなくノイズをすべて抽出することができます。ただし、メディアンフィルターはソートなどの操作が必要なため、計算量が多くなるのがデメリットです。

5、双方向フィルタリング:

バイラテラルフィルタリングは、空間情報と色情報を総合的に考慮したフィルタリング方法であり、フィルタリングプロセス中に画像内のエッジ情報を効果的に保護できます。

1. 基本原則:

以前のフィルタリング方法は空間重み情報のみを考慮しており、計算には便利ですが、エッジ情報を処理する場合に大きな問題が発生します。たとえば、画像の左側は黒、右側は白で、中央に鋭いエッジがあります。

画像-20211017103641068

平均値フィルタリング、ボックス フィルタリング、ガウス フィルタリングでは、エッジ上の各ピクセルの加重平均を計算し、エッジ情報をぼかします。次の図は、ガウス フィルタリングによって処理された画像です。

画像-20211017104218213

ピクセルの新しい値を計算するとき、バイラテラル フィルタリングでは距離情報 (距離が遠いほど重みが小さくなります) だけでなく、色情報 (色差が大きいほど重みが小さくなります) も考慮されます。バイラテラルフィルタリングは、距離と色の重み構造を包括的に考慮し、効果的にノイズを除去するだけでなく、エッジ情報をより適切に保護します。

バイラテラル フィルタリングでは、エッジにある場合、現在の点と色が似ている (色の距離が非常に近い) ピクセルには、より大きな重み値が与えられますが、現在の色とより異なるピクセル ( color distance is far ) には、より小さい重み値が与えられます (極端な場合には重みが 0 になる可能性があります。この点は無視してください)。これにより、エッジ情報が保護されます。

2. 関数の構文:

OpenCV では、双方向フィルタリングを実装する関数は cv2.bi LateralFilter() です。この関数の構文は次のとおりです。

dst = cv2.bi LateralFilter(src, d, sigmaColor, sigmaSpace, borderType)

  • dst: 戻り値、平均値フィルタリング後の処理結果。
  • src: 処理対象の画像、つまり元の画像。チャネルはいくつでも使用でき、各チャネルは独立して処理できます。画像の深さは CV_8U、CV_16U、CV_16S、CV_32F、CV_64F のいずれかである必要があります。
  • d: フィルタリング中に選択された空間距離パラメータ。ここでは現在の中心点の直径を表します。値が正でない場合はパラメータ sigmaSpace から自動的に計算されますが、フィルタリング スペースが大きい (d>5) と速度が遅くなります。したがって、実際のアプリケーションでは d=5 が推奨されます。ノイズが大きいオフライン フィルタリングの場合は、d=9 を選択できます。
  • sigmaColor: フィルタリング中に選択された色差範囲。これにより、周囲のどのピクセルがフィルタリングに参加できるかが決まります。現在のピクセルとのピクセル値の差が sigmaColor より小さいピクセルは、現在のフィルタリングに参加できます。値が大きいほど、より多くの周囲のピクセルが計算に参加できます。値が 0 の場合、フィルタリングは無意味です。値が 255 の場合、指定された直径内のすべての点が計算に参加できます。
  • sigmaSpagce: 座標空間内のシグマ値です。値が大きいほど、より多くのポイントがフィルタリング計算に参加できます。d > 0 の場合、d は sigmaSpace の値に関係なく近傍サイズを指定します。それ以外の場合、d は sigmaSpace の値に比例します。
  • borderType: 境界線のスタイル。この値は境界線の処理方法を決定します。通常の状況では、この値を考慮する必要はなく、デフォルト値が直接使用されます。

簡単にするために、sigmaColor と sigmaSpagce の値を同じに設定できます。値が比較的小さい場合 (10 未満)、フィルタリング効果は明ら​​かではありませんが、値が比較的大きい場合 (たとえば、150 より大きい)、フィルタリング効果はより明白になり、漫画効果が現れます。生産されます。

cv2.ternateFilter() 関数では、borderType がオプションのパラメータであることを除き、他のパラメータはすべて必須です。

import cv2

img = cv2.imread('../lena512color_noise.tiff')
rst = cv2.bilateralFilter(img, 25, 100, 100)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

上記の結果から、バイラテラル フィルタリングはノイズの除去に効果的ではないことがわかります。双方向フィルタリングの利点は、エッジ情報の処理に反映されます。

import cv2
import numpy as np

img = np.zeros((500, 500), dtype=np.uint8)
img[:, :250] = 255
rst = cv2.bilateralFilter(img, 25, 100, 100)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211017104837702

6、2D コンボリューション

OpenCV は、平均値フィルタリング、ボックス フィルタリング、ガウス フィルタリング、メディアン フィルタリングなど、画像を平滑化する効果を実現するさまざまなフィルタリング方法を提供します。ほとんどのフィルタリング手法で使用されるコンボリューション カーネルにはある程度の柔軟性があり、コンボリューション カーネルのサイズと数は簡単に設定できます。ただし、特定の畳み込みカーネルを使用して畳み込み演算を実装したい場合があります。たとえば、次の畳み込みカーネルを使用して畳み込み演算を実行します。

画像-20211017105649221

上記で紹介したフィルター関数はいずれも上記の形式のようにコンボリューション カーネルを決定できないため、OpenCV のカスタム コンボリューション関数を使用する必要があります。

OpenCV では、ユーザーは畳み込み演算を実現するために畳み込みカーネルをカスタマイズすることができます。畳み込み演算を実現するためにカスタム 畳み込みカーネルを使用する関数は cv2.filer2D() であり、その構文形式は次のとおりです。

dst = cv2.filter2D(src, d Depth, カーネル, アンカー, デルタ, borderType)

  • dst: 戻り値、平均値フィルタリング後の処理結果。

  • src: 処理対象の画像、つまり元の画像。チャネルはいくつでも使用でき、各チャネルは独立して処理できます。画像の深さは CV_8U、CV_16U、CV_16S、CV_32F、CV_64F のいずれかである必要があります。

  • d Depth: 結果イメージのイメージ深度。通常、元のイメージと同じイメージ深度を示すには -1 を使用します。

  • kenel: 畳み込みカーネルは単一チャネル配列です。カラー画像を処理するときにチャネルごとに異なるカーネルを使用したい場合は、カラー画像を分解し、異なるカーネルを使用して操作する必要があります。

  • アンカー: アンカーポイント、デフォルト値は (-1, -1) です。これは、現在の計算ポイントがカーネルの中心点に位置することを意味します。デフォルト値は変更に使用でき、別のポイントを指定できます。特殊な場合のアンカーポイントとして。

  • デルタ:補正値。オプション。この値が存在する場合、最終的なフィルタリング結果として基本フィルタリング結果に追加されます。

  • borderType: 境界線のスタイル。この値は境界線の処理方法を決定します。通常の状況では、この値を考慮する必要はなく、デフォルト値が直接使用されます。

通常、フィルター関数 cv2.filter2D() を使用する場合、パラメーターアンカー、デルタ、およびボーダータイプのデフォルト値を直接使用できます。

例:コンボリューション カーネルをカスタマイズし、コンボリューション カーネルを適用して関数 cv2.filter2D() を通じて画像をフィルターし、フィルター結果を表示します。

画像-20211017110708632

import cv2
import numpy as np

img = cv2.imread('../lena512color_noise.tiff')
kernal = np.ones((9, 9), dtype=np.float32) / 81
rst = cv2.filter2D(img, -1, kernal)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

【外部リンク画像転送...(img-m8umG3dN-1642887693106)】

おすすめ

転載: blog.csdn.net/weixin_57440207/article/details/122646994