【OpenCV入門】GaussianBlurの引数(カーネルサイズ、sigma)を分かりやすく徹底解説
はじめに
OpenCVを使った画像処理の世界へようこそ!
デジタル画像から情報を抽出し、さまざまなタスクに応用するコンピュータビジョンは、自動運転、医療画像診断、顔認証システムなど、私たちの生活のあらゆる場面で活用されています。その中でも、OpenCVは最も強力でポピュラーなライブラリの一つです。
OpenCVを学び始めると、まず間違いなく出会うのがcv2.GaussianBlur()
という関数です。この関数は、画像を「ぼかす」ためのものですが、その役割は単に画像を不鮮明にするだけではありません。ノイズの除去、エッジ検出や物体認識の前処理など、高度な画像処理の成功を左右する非常に重要なステップなのです。
しかし、多くの初学者がこのGaussianBlur
で最初の壁にぶつかります。
python
dst = cv2.GaussianBlur(src, ksize, sigmaX)
このシンプルなコードに含まれるksize
(カーネルサイズ)やsigmaX
といった引数。これらが一体何を意味し、どのように画像の「ぼけ方」をコントロールしているのか、直感的に理解するのは難しいかもしれません。インターネット上のサンプルコードをコピー&ペーストして「何となく動いた」で済ませてしまっている方も多いのではないでしょうか?
この記事の目的は、その「何となく」を「完全に理解した」に変えることです。
本記事では、以下の内容を、可能な限り専門用語を避け、図や具体的なコード例を交えながら、約5000語というボリュームで徹底的に解説します。
- なぜ画像を「ぼかす」必要があるのか?(画像処理における平滑化の重要性)
- フィルタリングと畳み込みの基本概念(
GaussianBlur
の裏側で何が起きているのか) - ガウシアンフィルタの仕組み(なぜただのぼかしではなく「ガウシアン」なのか)
- 最重要!
ksize
(カーネルサイズ)とsigma
(標準偏差)の役割と関係性ksize
を大きくするとどうなる?sigma
を大きくするとどうなる?- なぜ
ksize
は奇数でなければならないのか? ksize
かsigma
のどちらかを0
に設定するテクニックとその意味
- 実践的なコード例(パラメータを変えながら結果を比較し、理解を深める)
- よくある質問とトラブルシューティング
この記事を読み終える頃には、あなたはGaussianBlur
の引数を自信を持って設定し、自分の目的に合わせてぼかし具合を自在にコントロールできるようになっているはずです。それでは、さっそく画像処理の奥深い世界へ旅立ちましょう!
第1章: 画像フィルタリングと平滑化の基礎
GaussianBlur
の核心に迫る前に、まずはその土台となる基本的な知識から始めましょう。「画像をぼかす」という操作が、コンピュータにとってどのような処理なのかを理解することが、最初のステップです。
1-1. 画像は数字の集まり
私たちの目には一枚の絵として見えるデジタル画像も、コンピュータにとっては単なる数字の羅列です。画像はピクセル(pixel, 画素)と呼ばれる非常に小さな色の点の集まりで構成されています。
-
グレースケール画像: 最もシンプルな形式です。各ピクセルは明るさの情報だけを持ち、通常は0(黒)から255(白)までの256段階の整数で表現されます。これは、縦横に数字が並んだ巨大な行列(マトリックス)と考えることができます。
(ここにグレースケール画像のピクセル値の行列のイメージ図)
[ 210, 215, 220, ... ]
[ 212, 218, 223, ... ]
[ 214, 221, 225, ... ]
[ ... ] -
カラー画像: 一般的には、光の三原色である赤(Red)、緑(Green)、青(Blue)の3つの色の組み合わせで表現されます。これをRGBカラーモデルと呼びます。各ピクセルは、R、G、Bそれぞれについて0から255までの値を持ちます。つまり、グレースケール画像の行列が3枚重なっているような構造です。OpenCVでは、色の順序がB-G-R(青-緑-赤)となっている点に注意が必要ですが、基本的な考え方は同じです。
GaussianBlur
をはじめとする画像フィルタリングは、このピクセル値という数字を、あるルールに基づいて計算し直し、新しい値に置き換える操作のことを指します。
1-2. なぜ画像を「ぼかす」のか?平滑化の目的
なぜわざわざ綺麗な画像をぼかす必要があるのでしょうか?その主な目的は「平滑化(Smoothing)」にあります。平滑化とは、画像の急激な変化をなだらかにすることであり、これには大きく分けて2つの重要な役割があります。
目的1: ノイズ除去
デジタル画像には、撮影時のカメラセンサーの問題や伝送中のエラーなど、様々な原因でノイズが混入することがあります。ノイズとは、本来の画像情報にはない、ランダムで不要なピクセル値の変動のことです。
- 塩コショウノイズ(Salt-and-Pepper Noise): 画像上にランダムに白い点(塩)や黒い点(コショウ)が現れるノイズ。
- ガウシアンノイズ(Gaussian Noise): 全てのピクセルに、ガウス分布に従う微小な値が加算されるノイズ。ザラザラした見た目になります。
これらのノイズは、後の画像処理(例えば、物の輪郭を見つけるエッジ検出など)において、本来のエッジと誤認される原因となり、処理の精度を著しく低下させます。
画像をぼかす(平滑化する)と、あるピクセルの値がその周囲のピクセルの値と混ざり合って平均化されます。これにより、一つだけ突出して明るい(または暗い)ノイズピクセルは、周りの値になじんで目立たなくなり、結果としてノイズが除去されるのです。
目的2: 高度な処理のための前処理
コンピュータビジョンの多くのタスクでは、画像の大まかな構造や主要な特徴を捉えることが重要です。細かすぎるディテールやテクスチャは、むしろ邪魔になることがあります。
例えば、「画像の中から猫を見つける」というタスクを考えてみましょう。私たち人間は猫の毛一本一本を認識しなくても「猫だ」と分かります。むしろ、毛のフワフワした質感よりも、耳の形、目の位置、全体のシルエットといった大局的な特徴が重要です。
画像を適度にぼかすことで、こうした細かすぎる情報(高周波成分と呼びます)を抑制し、物体の形状といった本質的な情報(低周波成分)を際立たせることができます。これにより、エッジ検出や特徴点抽出、物体認識などの後続処理が、より安定して正確に行えるようになるのです。
1-3. フィルタリングと畳み込み演算の概念
では、具体的にどのようにしてピクセル値を計算し直しているのでしょうか。その中心的な操作が「畳み込み(Convolution)」です。
畳み込みと聞くと難しそうに感じるかもしれませんが、やっていることは非常にシンプルです。
- カーネル(Kernel)またはフィルタ(Filter)と呼ばれる、小さな数字の行列を用意します。(例: 3×3の行列)
- このカーネルを、入力画像の左上からスライドさせていきます。
- カーネルを画像のある位置に重ね合わせます。
- カーネルの各要素と、それが重なっている画像のピクセル値をそれぞれ掛け合わせます。
- 掛け合わせた値をすべて足し合わせます(積和演算)。
- この合計値を、カーネルの中心に対応する出力画像のピクセル値とします。
- この操作を、画像全体にわたって繰り返します。
言葉だけでは分かりにくいので、最も簡単な「平均化フィルタ」を例に見てみましょう。
平均化フィルタのカーネルは、すべての要素が同じ値で、合計すると1になるように作られます。例えば3×3の平均化フィルタのカーネルは以下のようになります。
[ 1/9, 1/9, 1/9 ]
K = [ 1/9, 1/9, 1/9 ]
[ 1/9, 1/9, 1/9 ]
このカーネルを画像のある部分に重ねたとします。
(ここに畳み込み演算のイメージ図)
入力画像の一部:
[ 10, 20, 30 ]
[ 40, 50, 60 ]
[ 70, 80, 90 ]
カーネル:
[ 1/9, 1/9, 1/9 ]
[ 1/9, 1/9, 1/9 ]
[ 1/9, 1/9, 1/9 ]
中心のピクセル(値は50)の新しい値を計算してみましょう。
計算:
(10 * 1/9) + (20 * 1/9) + (30 * 1/9) + (40 * 1/9) + (50 * 1/9) + (60 * 1/9) + (70 * 1/9) + (80 * 1/9) + (90 * 1/9)
= (10 + 20 + 30 + 40 + 50 + 60 + 70 + 80 + 90) / 9
= 450 / 9
= 50
この場合、たまたま同じ値になりましたが、要するに、カーネルが重なった領域の9つのピクセル値の単純な平均を計算していることになります。この操作を画像全体で行うと、すべてのピクセルがその周囲のピクセルの平均値に置き換わり、結果として画像がぼやけるわけです。
GaussianBlur
も、この畳み込み演算を利用しています。ただし、使うカーネルが「平均化フィルタ」ではなく、より洗練された「ガウシアンカーネル」であるという点が異なります。
第2章: ガウシアンフィルタとは何か?
平均化フィルタはシンプルで分かりやすいですが、一つ大きな欠点があります。
2-1. 平均化フィルタの問題点
平均化フィルタは、カーネル内のすべてのピクセルを平等に扱います。中心のピクセルも、一番端のピクセルも、同じ 1/9
という重みで計算に寄与します。
これは、ノイズ除去には有効ですが、画像の重要な特徴であるエッジ(輪郭)まで、ぼんやりさせてしまうという副作用があります。エッジとは、明るさが急激に変化する部分です。平均化フィルタを適用すると、この急激な変化が周囲と平均化されてしまい、輪郭が不鮮明になってしまいます。
2-2. ガウシアンフィルタのアイデア:中心に近いほど重要
そこで登場するのがガウシアンフィルタです。そのアイデアは非常に直感的です。
「あるピクセルをぼかす際、そのピクセルのすぐ近くにあるピクセルの情報は重要だが、遠くにあるピクセルの情報はあまり重要ではないだろう」
つまり、単純な平均ではなく、距離に応じた重み付き平均を取ろう、という考え方です。中心ピクセルに最も大きな重みを、中心から離れるにつれて指数関数的に小さな重みを与えます。
この「中心をピークとし、なだらかに減衰していく」重み付けを実現するために使われるのが、統計学でおなじみのガウス分布(正規分布)です。
(ここに1次元ガウス分布の釣鐘型グラフのイメージ図)
この釣鐘型のグラフを2次元に拡張したものが、ガウシアンフィルタの重み(カーネル)の元になります。
(ここに2次元ガウス分布の3Dサーフェスプロットのイメージ図)
この山のような形を上から見ると、中心が最も値が大きく(白く)、外側に行くほど値が小さく(黒く)なっているのが分かります。これがガウシアンカーネルの正体です。
3×3ガウシアンカーネルの例(正規化前):
[ 1, 2, 1 ]
[ 2, 4, 2 ]
[ 1, 2, 1 ]
この行列を、合計値(この場合は16)で割って正規化すると、実際のカーネルになります。
正規化後:
[ 1/16, 2/16, 1/16 ]
[ 2/16, 4/16, 2/16 ]
[ 1/16, 2/16, 1/16 ]
このカーネルを使って畳み込みを行うと、中心のピクセルには 4/16
という最も大きな重みが、その隣には 2/16
、角には 1/16
という小さな重みが掛かります。これにより、平均化フィルタよりもエッジを比較的保持したまま、より自然で滑らかなぼかし効果が得られるのです。
2-3. ガウス関数の数式(軽く触れる程度に)
ガウシアンカーネルを生成する背景には、ガウス関数という数式があります。数式が苦手な方はこのセクションを読み飛ばしても構いませんが、sigma
という引数を理解する上で少しだけ役立ちます。
2次元のガウス関数は以下のように表されます。
G(x, y) = (1 / (2 * π * σ^2)) * exp( - (x^2 + y^2) / (2 * σ^2) )
ここで、
* (x, y)
はカーネルの中心からの座標です。
* π
は円周率です。
* exp()
は自然対数の底eを指数とする指数関数です。
* σ
(シグマ)が、この関数で最も重要なパラメータです。これは標準偏差を表し、釣鐘型のグラフの広がり具合を決定します。
(ここにσが小さい場合と大きい場合のガウス分布グラフの比較図)
σ
が小さい: 釣鐘型は鋭く、急峻になります。つまり、中心の重みが非常に大きく、少し離れるとすぐに重みがゼロに近くなります。結果として、ぼかしの効果は弱くなります。σ
が大きい: 釣鐘型はなだらかで、幅広くなります。つまり、中心から離れたピクセルにも比較的大きな重みが与えられます。結果として、ぼかしの効果は強くなります。
このσ
(シグマ)こそが、cv2.GaussianBlur
関数の引数sigmaX
の正体なのです。
第3章: GaussianBlur
関数の核心!引数を徹底解説
さて、いよいよ本題です。これまでの知識を総動員して、cv2.GaussianBlur
関数の引数を一つずつ解き明かしていきましょう。
3-1. OpenCVのGaussianBlur
関数の基本構文
PythonでのGaussianBlur
関数の基本的な呼び出し方は以下の通りです。
python
dst = cv2.GaussianBlur(src, ksize, sigmaX, sigmaY=None, borderType=None)
src
: 入力画像。グレースケールまたはBGRカラー画像。dst
: 出力画像。src
と同じサイズ、同じ型になります。ksize
: ガウシアンカーネルのサイズ。sigmaX
: X方向(水平方向)のガウスカーネルの標準偏差。sigmaY
: Y方向(垂直方向)のガウスカーネルの標準偏差。(オプション)borderType
: 画像の境界線のピクセルをどう扱うかの設定。(本記事では割愛)
ここでは、最も重要で、初学者が最も混乱するksize
とsigmaX
(およびsigmaY
)に焦点を当てて解説します。
3-2. ksize
(カーネルサイズ):ぼかしの範囲を決める
ksize
は、畳み込み演算で使うガウシアンカーネルのサイズ(幅と高さ)を定義します。
- 指定方法:
(幅, 高さ)
という形のタプルで指定します。例:(5, 5)
- 重要なルール: 幅と高さは、どちらも正の奇数でなければなりません。 例えば、
(3, 3)
,(7, 7)
,(15, 21)
は有効ですが、(4, 4)
や(6, 8)
はエラーになります。
なぜ奇数でなければならないのか?
これは畳み込みの原理を考えれば自然なことです。カーネルには必ず「中心」が必要です。カーネルを画像上のピクセルに重ねたとき、計算結果をどのピクセルに格納するかを決めるためです。
- 3×3のカーネル: 中心は(2, 2)番目の要素です。
- 5×5のカーネル: 中心は(3, 3)番目の要素です。
もしカーネルのサイズが偶数(例: 4×4)だと、明確な中心ピクセルが存在しません。そのため、OpenCVではksize
に奇数を要求します。
ksize
を大きくするとどうなるか?
カーネルサイズを大きくするということは、ぼかしの計算に含める周囲のピクセルの範囲を広げることを意味します。
ksize = (3, 3)
: 対象ピクセルとそのすぐ隣の8ピクセル、合計9ピクセルで計算します。ksize = (11, 11)
: 対象ピクセルを中心とした11×11の範囲、合計121ピクセルで計算します。
一般的に、ksize
を大きくすればするほど、
* ぼかしの効果は強くなります。 より広範囲のピクセルが平均化されるためです。
* 計算コストは増大します。 畳み込みで計算するピクセルの数がksize
の面積に比例して増えるため、処理時間が長くなります。
【コード例と画像比較】
ksize
を(3, 3)
, (11, 11)
, (31, 31)
と変化させた場合の効果を視覚的に見てみましょう。(ここではsigmaX
は0
に設定します。この意味は後ほど詳しく解説します。)
(ここに元画像、ksize=(3,3)の画像、ksize=(11,11)の画像、ksize=(31,31)の画像を並べた比較図)
見ての通り、ksize
が大きくなるにつれて、ぼけ方がどんどん強くなっているのが分かります。
3-3. sigmaX
(X方向の標準偏差):ぼかしの「強さ」を決める
sigmaX
は、第2章で説明したガウス関数の標準偏差σ
に相当します。これは、ガウシアンカーネルの重み付け、つまり釣鐘型の分布の広がり具合を決定します。
sigmaX
が大きい: 釣鐘型はなだらかで幅広くなります。中心から離れたピクセルにも比較的大きな重みが与えられます。これにより、より広い範囲のピクセルが影響を及ぼし合い、ぼかしの効果は強くなります。sigmaX
が小さい: 釣鐘型は鋭く急峻になります。重みは中心ピクセルに集中し、少し離れるとすぐにゼロに近くなります。これにより、影響範囲が限定され、ぼかしの効果は弱くなります。
sigmaX
は、ぼかしの「範囲」を決めるksize
とは異なり、ぼかしの「質」や「強さ」を直接コントロールするパラメータと言えます。
【コード例と画像比較】
今度はksize
を固定(後述する(0,0)
というテクニックを使用)し、sigmaX
を1
, 5
, 10
と変化させてみましょう。
(ここに元画像、sigmaX=1の画像、sigmaX=5の画像、sigmaX=10の画像を並べた比較図)
sigmaX
が大きくなるほど、ぼかしが滑らかかつ強力になっていくのが見て取れます。ksize
の変更と似た結果に見えますが、sigma
はぼかしの数学的な特性そのものを変えているという点が重要です。
3-4. sigmaY
(Y方向の標準偏差):縦方向のぼかし
sigmaY
は、Y方向(垂直方向)のぼかしの強さを決める標準偏差です。
sigmaY
を省略、または0
を指定した場合:sigmaY
はsigmaX
と同じ値に自動的に設定されます。cv2.GaussianBlur(src, ksize, sigmaX)
と書いた場合、内部的にはsigmaY = sigmaX
として扱われます。これにより、円形(対称的)のぼかしがかかります。ほとんどの一般的な用途では、この方法で十分です。sigmaY
にsigmaX
と異なる値を指定した場合: X方向とY方向でぼかしの強さが異なる、非対称なぼかしを作成できます。例えば、sigmaX
がsigmaY
より大きい場合、横方向に強くぼやけた、モーションブラー(動きぼけ)のような効果が得られます。
(ここにsigmaX=10, sigmaY=1
とした場合の横長ぼかし画像の例)
これは特殊な効果を狙う場合に使われる応用的なテクニックです。
3-5. ksize
とsigma
の魔法の関係:どちらかを0
にすると?
ここがGaussianBlur
を使いこなす上で最も重要かつ、初学者がつまずきやすいポイントです。OpenCVのGaussianBlur
には、ksize
とsigma
の関係性を利用した便利な機能が備わっています。
ksize
とsigma
は独立したパラメータではなく、密接な関係があります。
* sigma
が大きければ、そのなだらかな分布を表現するために、より大きなksize
が必要になります。
* ksize
が小さすぎると、sigma
が作る釣鐘型の裾野の部分が切り捨てられてしまい、ガウシアンフィルタとしての精度が落ちます。
この関係性を利用して、OpenCVでは片方のパラメータからもう片方を自動的に計算する機能を提供しています。
ケース1: ksize
を指定し、sigmaX
を0
にする
“`python
ksizeを指定し、sigmaX = 0 とする
blurred_img = cv2.GaussianBlur(src, ksize=(11, 11), sigmaX=0)
“`
この場合、OpenCVは指定されたksize
(この例では11)から、「このカーネルサイズに最適なsigma
はこれくらいだろう」という値を自動で計算して適用します。
その計算式は以下のようになっています。
sigma = 0.3 * ((ksize - 1) * 0.5 - 1) + 0.8
例えば、ksize.width = 11
の場合、
sigma = 0.3 * ((11 - 1) * 0.5 - 1) + 0.8 = 0.3 * (10 * 0.5 - 1) + 0.8 = 0.3 * (5 - 1) + 0.8 = 0.3 * 4 + 0.8 = 1.2 + 0.8 = 2.0
となり、sigmaX = 2.0
が自動的に設定されます。
この方法は、「ぼかしの強さの微調整は気にしないから、とりあえずこのくらいの範囲でぼかしたい」という場合に便利です。
ケース2: ksize
を(0, 0)
にし、sigmaX
を指定する(推奨)
“`python
ksize = (0, 0) とし、sigmaXを指定する
blurred_img = cv2.GaussianBlur(src, ksize=(0, 0), sigmaX=5)
“`
こちらが、より直感的で強く推奨される方法です。
ksize
に(0, 0)
を指定すると、OpenCVは逆に、指定されたsigmaX
(この例では5)の値から、「このsigma
のガウス分布を表現するのに十分なksize
はこれくらいだろう」という値を自動で計算してくれます。
カーネルサイズは、sigma
の値のおおよそ6倍程度の奇数になるように計算されることが多いです(例: ksize = 2 * round(3 * sigma) + 1
)。
なぜこの方法が推奨されるのか?
それは、ぼかしの「強さ」をsigma
という一つのパラメータで直接的にコントロールできるからです。
- ぼかしを少し強くしたい →
sigmaX
の値を少し大きくする。 - ぼかしを少し弱くしたい →
sigmaX
の値を少し小さくする。
このように、私たちの「ぼかし具合を調整したい」という意図と、コードの変更が直接的に結びつきます。ksize
を自分で決める方法だと、「ksize
を11から15に変えたら、ぼけ具合はどれくらい変わるだろう?」というのが直感的に分かりにくいですが、sigma
で調整する方法なら、その効果がより予測しやすくなります。
【結論】
GaussianBlur
を使う際は、特別な理由がない限り、ksize=(0, 0)
と設定し、sigmaX
の値を調整してぼかしの強さをコントロールする方法を基本としましょう。これが最もスマートで意図の伝わりやすいコードの書き方です。
第4章: 実践!コードで学ぶGaussianBlur
理論を学んだところで、実際にPythonとOpenCVを使ってコードを動かし、パラメータが結果にどう影響するかを体感してみましょう。
4-1. 準備:必要なライブラリと画像の読み込み
まず、必要なライブラリをインポートし、処理対象の画像を読み込みます。比較しやすいように、画像表示にはmatplotlib
を使用します。
“`python
import cv2
import numpy as np
import matplotlib.pyplot as plt
Google Colabなどで実行する場合、サンプル画像をダウンロード
!wget https://raw.githubusercontent.com/opencv/opencv/master/samples/data/lena.jpg -O lena.jpg
画像の読み込み
img_bgr = cv2.imread(‘lena.jpg’)
OpenCVはBGR順なので、matplotlibで表示するためにRGB順に変換
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
処理の基本となるグレースケール画像も用意
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
オリジナル画像の表示
plt.figure(figsize=(8, 8))
plt.imshow(img_rgb)
plt.title(‘Original Image’)
plt.axis(‘off’)
plt.show()
“`
4-2. パターン1:カーネルサイズを変えてみる
sigmaX=0
に固定し、ksize
だけを変化させてみます。
“`python
ksizeを変化させる
ksize_list = [(3, 3), (9, 9), (21, 21)]
blurred_images_ksize = []
for ksize in ksize_list:
# sigmaX=0とすることで、ksizeからsigmaを自動計算
blur = cv2.GaussianBlur(img_gray, ksize, sigmaX=0)
blurred_images_ksize.append(blur)
結果の表示
plt.figure(figsize=(15, 5))
元画像
plt.subplot(1, 4, 1)
plt.imshow(img_gray, cmap=’gray’)
plt.title(‘Original Gray’)
plt.axis(‘off’)
ぼかし画像
for i, (img, ksize) in enumerate(zip(blurred_images_ksize, ksize_list)):
plt.subplot(1, 4, i + 2)
plt.imshow(img, cmap=’gray’)
plt.title(f’ksize = {ksize}’)
plt.axis(‘off’)
plt.tight_layout()
plt.show()
``
ksize`が大きくなるにつれてぼかしが強くなる様子がはっきりと確認できます。
このコードを実行すると、
4-3. パターン2:sigmaを変えてみる(推奨される方法)
次に、ksize=(0, 0)
に固定し、sigmaX
を変化させます。こちらが推奨される使い方です。
“`python
sigmaXを変化させる
sigma_list = [1, 4, 8]
blurred_images_sigma = []
for sigma in sigma_list:
# ksize=(0, 0)とすることで、sigmaからksizeを自動計算
blur = cv2.GaussianBlur(img_gray, (0, 0), sigmaX=sigma)
blurred_images_sigma.append(blur)
結果の表示
plt.figure(figsize=(15, 5))
元画像
plt.subplot(1, 4, 1)
plt.imshow(img_gray, cmap=’gray’)
plt.title(‘Original Gray’)
plt.axis(‘off’)
ぼかし画像
for i, (img, sigma) in enumerate(zip(blurred_images_sigma, sigma_list)):
plt.subplot(1, 4, i + 2)
plt.imshow(img, cmap=’gray’)
plt.title(f’sigmaX = {sigma}’)
plt.axis(‘off’)
plt.tight_layout()
plt.show()
``
sigmaXの値を大きくするだけで、滑らかにぼかしが強まっていくことが分かります。
ksize`を直接いじるよりも、ぼかしの度合いをコントロールしやすい感覚が掴めるのではないでしょうか。
4-4. パターン3:非対称なぼかし(応用)
最後に、sigmaX
とsigmaY
に異なる値を設定して、特殊なぼかし効果を見てみましょう。
“`python
sigmaXとsigmaYに異なる値を設定
横方向のモーションブラー
blur_motion_x = cv2.GaussianBlur(img_gray, (0, 0), sigmaX=15, sigmaY=1)
縦方向のモーションブラー
blur_motion_y = cv2.GaussianBlur(img_gray, (0, 0), sigmaX=1, sigmaY=15)
結果の表示
plt.figure(figsize=(18, 6))
plt.subplot(1, 3, 1)
plt.imshow(img_gray, cmap=’gray’)
plt.title(‘Original Gray’)
plt.axis(‘off’)
plt.subplot(1, 3, 2)
plt.imshow(blur_motion_x, cmap=’gray’)
plt.title(‘Horizontal Blur (sigmaX=15, sigmaY=1)’)
plt.axis(‘off’)
plt.subplot(1, 3, 3)
plt.imshow(blur_motion_y, cmap=’gray’)
plt.title(‘Vertical Blur (sigmaX=1, sigmaY=15)’)
plt.axis(‘off’)
plt.tight_layout()
plt.show()
``
sigmaX
このように、と
sigmaY`を個別に設定することで、意図した方向へのぼかしを作り出すことも可能です。
第5章: よくある質問とトラブルシューティング (FAQ)
Q1: ksize
に(4, 4)
のような偶数を指定したらエラーが出ました。なぜですか?
A1: 本文で解説した通り、畳み込み演算ではカーネルの中心を定義する必要があるためです。3×3なら(2,2)番目、5×5なら(3,3)番目が中心となりますが、4×4のような偶数サイズの行列には明確な中心が存在しません。そのため、OpenCVのGaussianBlur
関数では、ksize
の幅と高さに正の奇数を指定することが必須となっています。
Q2: sigma
の値はどれくらいが適切ですか?
A2: これは「ケースバイケース」であり、明確な正解はありません。適切なsigma
の値は、元の画像の解像度、ノイズの量、そしてその後の処理の目的によって大きく異なります。
一般的な指針としては、まずはsigmaX
を1
から10
の範囲で試してみるのが良いでしょう。
* ノイズが少ない画像の軽い前処理: sigmaX = 1
or 2
* 顕著なノイズの除去: sigmaX = 3
to 5
* テクスチャを消して形状だけを抽出したい場合: sigmaX = 7
or more
最終的には、実際に出力結果を見ながら、目的に最も合った値に試行錯誤して調整することが重要です。
Q3: GaussianBlur
と他のぼかしフィルタ(blur
, medianBlur
)との違いは?
A3: OpenCVには複数のぼかしフィルタがあり、それぞれ特性が異なります。
cv2.blur()
(平均化フィルタ):- 長所: 処理が非常に高速。
- 短所: カーネル内の全ピクセルを同等に扱うため、エッジがぼやけやすく、不自然な結果になりがち。
cv2.medianBlur()
(メディアンフィルタ):- 長所: 「塩コショウノイズ」のような突発的なノイズの除去に非常に強い効果を発揮します。エッジの保持性能も比較的高いです。
- 短所: カーネル内のピクセル値をソートして中央値を取るため、計算コストが高く、処理が遅い傾向にあります。
cv2.GaussianBlur()
(ガウシアンフィルタ):- 長所: 中心に近いピクセルに重みを置くため、自然で滑らかなぼかしが得られます。ガウシアンノイズの除去に効果的です。性能と品質のバランスが良く、最も一般的に使われるフィルタです。
- 短所: メディアンフィルタほど塩コショウノイズには強くありません。
用途に応じてこれらを使い分けることが、良い画像処理の鍵となります。
Q4: 処理が重いのですが、速くする方法はありますか?
A4: GaussianBlur
の処理速度は、主に画像サイズとカーネルサイズに依存します。処理を高速化するには、以下のような方法が考えられます。
ksize
またはsigma
を小さくする: 最も直接的な方法です。カーネルサイズが小さければ、畳み込みの計算量が減り、処理は速くなります。ただし、ぼかしの効果も弱まります。- 画像の解像度を下げる: ぼかし処理を行う前に、
cv2.resize()
関数で画像のサイズを小さくする方法です。ピクセル数が減るため、処理は劇的に速くなります。最終的に元のサイズに戻す必要がある場合でも、先に縮小してぼかし、その後で拡大する方が速いことがあります。 - 関心領域 (ROI: Region of Interest) を設定する: 画像全体ではなく、処理が必要な部分だけを切り出して
GaussianBlur
を適用します。
これらの方法を組み合わせ、画質と処理速度のトレードオフを考慮しながら最適なアプローチを選択してください。
まとめ
本記事では、OpenCVのGaussianBlur
関数について、その理論的背景から引数の詳細な意味、そして実践的な使い方まで、深く掘り下げてきました。
最後に、重要なポイントをもう一度おさらいしましょう。
- ぼかし(平滑化)の目的: 画像のノイズを除去し、後続処理(エッジ検出など)のために大まかな構造を際立たせること。
- ガウシアンフィルタの仕組み: 単純な平均ではなく、中心ピクセルからの距離に応じて重みを変える「重み付き平均」。これにより自然なぼかしが実現される。
ksize
(カーネルサイズ): ぼかしの計算に含めるピクセルの範囲を決定する。必ず正の奇数で指定する。大きいほどぼけは強くなるが、処理も重くなる。sigma
(標準偏差): ガウス分布の広がり具合、すなわちぼかしの「強さ」や「質」を決定する。大きいほどぼけは強くなる。- 推奨される使い方:
ksize=(0, 0)
と設定し、sigmaX
の値でぼかしの強さをコントロールする方法。これが最も直感的で、意図をコードに反映させやすい。
GaussianBlur
は、数あるOpenCVの関数の中でも、特に使用頻度が高く、かつ多くの画像処理アルゴリズムの基盤となる、まさに「縁の下の力持ち」です。今日、あなたがこの関数の引数の意味を深く理解したことは、今後のOpenCV学習において非常に大きな一歩となるはずです。
ぜひ、この記事のコードを実際に手元で動かし、ksize
やsigma
の値を様々に変えて、その効果をご自身の目で確かめてみてください。その試行錯誤の経験が、あなたをより優れたコンピュータビジョン技術者へと導いてくれるでしょう。
次のステップとして、このGaussianBlur
で前処理した画像を使って、Cannyエッジ検出(cv2.Canny
)や閾値処理(cv2.threshold
)などに挑戦してみることをお勧めします。きっと、前処理の重要性をさらに実感できるはずです。