KURORO BLOGのロゴ

このエントリーをはてなブックマークに追加
【4選】OpenCVを用いて画像をぼかす方法からサンプルコードまで徹底解説!?

【4選】OpenCVを用いて画像をぼかす方法からサンプルコードまで徹底解説!?

今回はOpenCVを用いて画像をぼかす方法を4選に絞り、サンプルコードを交えながらわかりやすく解説致します。画像をぼかしてみたい、OpenCVを使い始めた方へおすすめです。ぜひ最後までご覧ください。

目次
  1. 画像をぼかすとは?
  2. 【4選】OpenCVを用いて画像をぼかす方法
    1. blur関数を用いて画像をぼかしてみる
    2. GaussianBlur関数を用いて画像をぼかしてみる
    3. medianBlur関数を用いて画像をぼかしてみる
    4. bilateralFilter関数を用いて画像をぼかしてみる
    5. bilateralFilter関数の値入力に困った場合
  3. まとめ
  4. 参考文献
目次を開く⬇︎

執筆者 - おすすめの記事3選

画像をぼかすとは?

画像をぼかすとは、輪郭や色の濃淡の境目をきわだたせないで、ぼんやりさせることを意味します。難しい言葉で言うと、平滑化」すると呼ばれます。

具体的なイメージとしては、以下の「サンプル画像へぼかしを加えたイメージ画像」箇所を、イメージしてもらうと良いでしょう。

【サンプル画像】

【サンプル画像へぼかしを加えたイメージ画像】

画像へぼかしを加えることで、

  • 主役をきわだたせられる
  • 背景が整理される
  • 画像に距離感が生まれる

などの効果が期待できます。

【4選】OpenCVを用いて画像をぼかす方法

OpenCVを用いて画像をぼかす方法として

  • blur
  • GaussianBlur
  • medianBlur
  • bilateralFilter

関数の4種類が挙げられます。順にみていきましょう。

blur関数を用いて画像をぼかしてみる

blur関数は、以下の手順を踏まえて画像をぼかす関数です。

  1. あるn x mの画素(n, mは1以上の整数)について注目する。(画素に関しては、以下の「画素に関する説明を行う画像」を参照ください。今回は、n, mを3, 3と定義します。)
  2. あるn x mの画素(1)内のある画素に注目する。(以下の「ある画素について注目する画像」箇所をご確認ください。)
  3. ある画素(2)の画素値を、あるn x mの画素(1)の平均値とする。(以下の「ある画素について注目する画像」の場合、32の画素値を(3 + 75 + 81 + 22 + 45 + 32 + 65 + 42 + 67) / 9 = 48へ変更します。)
  4. 1~3を繰り返す。

【画素に関する説明を行う画像】

1枚の画像は、複数の画素の集まりで成り立っています。

【ある画素について注目する画像】

blur関数の定義としては、

1# cv2(OpenCV)を利用する宣言を行う。
2import cv2
3
4# blur関数 : 画像をぼかす関数
5# blur関数 - 公式ドキュメント : https://docs.opencv.org/3.4/d4/d86/group__imgproc__filter.html#ga8c45db9afe636703801b0b2e440fce37
6
7# 第一引数(必須) : 多次元配列(画像情報)
8
9# 第二引数(必須) : ぼかすために必要な、n x mの画素領域を指定する。tuple型。
10# tuple型とは? : https://atmarkit.itmedia.co.jp/ait/articles/1906/14/news015.html
11# 例) : (2, 3) ⏩ n x mの画素領域を2 x 3とする。
12
13# <第三引数以降(任意)>
14# anchor : 第二引数(n x mの画素領域)内の、どの画素(あるn x mの画素(1)内のある画素)に注目するのか指定する。tuple型。
15# デフォルトでは(-1, -1)が設定され、自動的に第二引数(n x mの画素領域)の中心を指すように設定される。
16# 例) : (1, 2) ⏩ 第二引数(n x mの画素領域)内の、(1, 2)の画素に注目する。
17
18# 戻り値 : 多次元配列(画像情報)
19
20cv2.blur(img, (n(1以上の整数), m(1以上の整数)), anchor=(0 <= x < n(第二引数)の整数, 0 <= y < m(第二引数)の整数))

で成り立ちます。

例えば以下のようなコードを作成すると、

1import cv2
2import sys
3
4# blur関数を実行する関数
5def exec_blur(img):
6    # blur関数 : 画像をぼかす関数
7    # 第一引数(必須) : 多次元配列(numpy.ndarray)
8    # 第二引数(必須) : ぼかすために必要な、n x mの画素領域を指定する。
9    # 戻り値 : 多次元配列(numpy.ndarray)
10    return cv2.blur(img, (10, 10))
11
12# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
13# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
14# 第一引数 : 画像のファイルパス
15# 戻り値 : 行 x 列 x 色の三次元配列(numpy.ndarray)が返される。
16img = cv2.imread("xxx.xxx")
17
18# 画像ファイルが正常に読み込めなかった場合、プログラムを終了する。
19if img is None:
20    sys.exit("Could not read the image.")
21
22# hconcat : 画像を連結する関数
23imgs = cv2.hconcat([img, exec_blur(img)])
24
25# imwrite : 画像の保存を行う関数
26# 第一引数 : 保存先の画像ファイル名
27# 第二引数 : 多次元配列(numpy.ndarray)
28# <第二引数の例>
29# [
30# [
31# [234 237 228]
32# ...
33# [202 209 194]
34# ]
35# [
36# [10 27 16]
37# ...
38# [36 67 46]
39# ]
40# [
41# [34 51 40]
42# ...
43# [50 81 60]
44# ]
45# ]
46# imwriteについて : https://kuroro.blog/python/i0tNE1Mp8aEz8Z7n6Ggg/
47cv2.imwrite('output.jpg', imgs)

以下の画像のように、画像が描画されます。

imreadに関しては、OpenCVで使われるimreadとは?使い方から配列が画像になる仕組みを解説でまとめていますので、詳しく知りたい方は是非ご確認ください。

imwriteに関しては、OpenCVで使われるimwriteとは?imwriteの定義から使用例をご紹介でまとめていますので、詳しく知りたい方は是非ご確認ください。

GaussianBlur関数を用いて画像をぼかしてみる

GaussianBlur関数は、以下の手順を踏まえて画像をぼかす関数です。

  1. n x mの画素領域(n, mは1以上の奇数)に注目する。(今回n, mを5, 5とする。以下の「GaussianBlur関数をわかりやすく解説するための画像」の黄緑色箇所とする。)
  2. n x mの画素領域(1)の1つとn x mの中心画素を比較していき、どれくらい色の違い(差分)があるのか計算する。(n x mの中心画素は、以下の「GaussianBlur関数をわかりやすく解説するための画像」の赤色箇所とする。)
  3. 「GaussianBlur関数をわかりやすく解説するための画像」の重みづけ情報(1/256や36/256など)を利用して、ぼかしを加える。 (((2 * 画素A-画素B) x 各重みつけ情報)を足し合わせた値を、n x mの中心画素とする。)
  4. 1~4を繰り返す。

【GaussianBlur関数をわかりやすく解説するための画像】

GaussianBlur関数の定義としては、

1# cv2(OpenCV)を利用する宣言を行う。
2import cv2
3
4# GaussianBlur関数 : 画像をぼかす関数
5# GaussianBlur関数 - 公式ドキュメント : https://docs.opencv.org/3.4/d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1
6
7# 第一引数(必須) : 多次元配列(画像情報)
8
9# 第二引数(必須) : ぼかすために必要な、n x mの画素領域を指定する。tuple型。
10# tuple型とは? : https://atmarkit.itmedia.co.jp/ait/articles/1906/14/news015.html
11# 例) : (1, 3) ⏩ n x mの画素領域を1 x 3とする。
12
13# 第三引数(必須) : 画像のx軸(横)方向へのぼかしを調節する値を設定する。
14# 値が小さいほど、よりn x mの中心画素に強いぼかしが入り、逆に、値が大きいほど、より均一にn x mの画素全体にぼかしが入ります。
15# 0とした場合、第二引数の値から自動的に算出される。
16
17# 第四引数(任意) : 画像のy軸(縦)方向へのぼかしを調節する値を設定する。
18# 値が小さいほど、よりn x mの中心画素に強いぼかしが入り、逆に、値が大きいほど、より均一にn x mの画素全体にぼかしが入ります。
19# 第四引数が入力されない場合、第三引数の情報を元に、自動的に値が設定されます。
20
21# 戻り値 : 多次元配列(画像情報)
22
23cv2.GaussianBlur(img, (n(1以上の奇数), m(1以上の奇数)), 数字, 数字)

で成り立ちます。

例えば以下のようなコードを作成すると、

1import cv2
2import sys
3
4# GaussianBlur関数を実行する関数
5def exec_gaussian_blur(img):
6    # GaussianBlur関数 : 画像をぼかす関数
7    # 第一引数(必須) : 多次元配列(numpy.ndarray)
8    # 第二引数(必須) : ぼかすために必要な、n x mの画素領域を指定する。
9    # 第三引数(必須) : 画像のx軸(横)方向へのぼかしを調節する値を設定する。
10    # 第四引数(任意) : 画像のy軸(縦)方向へのぼかしを調節する値を設定する。
11    # 戻り値 : 多次元配列(numpy.ndarray)
12    return cv2.GaussianBlur(img, (5, 5), 10, 10)
13
14# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
15# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
16# 第一引数 : 画像のファイルパス
17# 戻り値 : 行 x 列 x 色の三次元配列(numpy.ndarray)が返される。
18img = cv2.imread("xxx.jpg")
19
20# 画像ファイルが正常に読み込めなかった場合、プログラムを終了する。
21if img is None:
22    sys.exit("Could not read the image.")
23
24# hconcat : 画像を連結する関数
25imgs = cv2.hconcat([img, exec_gaussian_blur(img)])
26
27# imwrite : 画像の保存を行う関数
28# 第一引数 : 保存先の画像ファイル名
29# 第二引数 : 多次元配列(numpy.ndarray)
30# <第二引数の例>
31# [
32# [
33# [234 237 228]
34# ...
35# [202 209 194]
36# ]
37# [
38# [10 27 16]
39# ...
40# [36 67 46]
41# ]
42# [
43# [34 51 40]
44# ...
45# [50 81 60]
46# ]
47# ]
48# imwriteについて : https://kuroro.blog/python/i0tNE1Mp8aEz8Z7n6Ggg/
49cv2.imwrite('output.jpg', imgs)

以下の画像のように、画像が描画されます。

medianBlur関数を用いて画像をぼかしてみる

medianBlur関数は、以下の手順を踏まえて画像をぼかす関数です。

  1. n x nの画素(nは1以上の奇数)について注目する。(今回nを3とする。以下の「medianBlur関数をわかりやすく解説するための画像」の緑色箇所とする。)
  2. n x nの中心の画素に注目する。(以下の「medianBlur関数をわかりやすく解説するための画像」の赤色箇所とする。)
  3. n x nの中心の画素の画素値を、n x nの画素の中央値に変換する。(以下の「medianBlur関数をわかりやすく解説するための画像」の場合、34の画素値を42へ変更します。)
  4. 1~3を繰り返す。

【medianBlur関数をわかりやすく解説するための画像】

medianBlur関数の定義としては、

1# cv2(OpenCV)を利用する宣言を行う。
2import cv2
3
4# medianBlur関数 : 画像をぼかす関数
5# medianBlur関数 - 公式ドキュメント : https://docs.opencv.org/3.4/d4/d86/group__imgproc__filter.html#ga564869aa33e58769b4469101aac458f9
6
7# 第一引数(必須) : 多次元配列(画像情報)
8# 第二引数(必須) : n x nの画素領域を指定する。
9
10# 戻り値 : 多次元配列(画像情報)
11cv2.medianBlur(img, n(1以上の奇数))

で成り立ちます。

例えば以下のようなコードを作成すると、

1import cv2
2import sys
3
4# medianBlur関数を実行する関数
5def exec_median_blur(img):
6    # medianBlur関数 : 画像をぼかす関数
7    # 第一引数(必須) : 多次元配列(numpy.ndarray)
8    # 第二引数(必須) : n x nの画素領域を指定する。
9    # 戻り値 : 多次元配列(numpy.ndarray)
10    return cv2.medianBlur(img, 5)
11
12# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
13# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
14# 第一引数 : 画像のファイルパス
15# 戻り値 : 行 x 列 x 色の三次元配列(numpy.ndarray)が返される。
16img = cv2.imread("xxx.jpg")
17
18# 画像ファイルが正常に読み込めなかった場合、プログラムを終了する。
19if img is None:
20    sys.exit("Could not read the image.")
21
22# hconcat : 画像を連結する関数
23imgs = cv2.hconcat([img, exec_median_blur(img)])
24
25# imwrite : 画像の保存を行う関数
26# 第一引数 : 保存先の画像ファイル名
27# 第二引数 : 多次元配列(numpy.ndarray)
28# <第二引数の例>
29# [
30# [
31# [234 237 228]
32# ...
33# [202 209 194]
34# ]
35# [
36# [10 27 16]
37# ...
38# [36 67 46]
39# ]
40# [
41# [34 51 40]
42# ...
43# [50 81 60]
44# ]
45# ]
46# imwriteについて : https://kuroro.blog/python/i0tNE1Mp8aEz8Z7n6Ggg/
47cv2.imwrite('output.jpg', imgs)

以下の画像のように、画像が描画されます。

bilateralFilter関数を用いて画像をぼかしてみる

bilateralFilter関数は、GaussianBlur関数のぼかし技術を駆使しながら、エッジを残すことのできる関数です。

GaussianBlur関数の動作に加えて、エッジを残すための処理を行うため、他の関数よりも処理速度が遅いです。

bilateralFilter関数の定義としては、

1# cv2(OpenCV)を利用する宣言を行う。
2import cv2
3
4# bilateralFilter関数 : 画像をぼかす関数
5# bilateralFilter関数 - 公式ドキュメント : https://docs.opencv.org/3.4/d4/d86/group__imgproc__filter.html#ga9d7064d478c95d60003cf839430737ed
6
7# 第一引数(必須) : 多次元配列(画像情報)
8
9# 第二引数(必須) : 中心画素をぼかすために、利用する画素領域を指定する。int型。
10# 0以下の整数が入力される場合、第四引数の値をもとに自動計算される。
11# 値が大きくなるほど、ぼかしが強くなる。
12
13# 第三引数(必須) : 第二引数で指定する画素領域内で、中心の画素値と周辺の画素値の比較を行いますが、その画素値の差を許容できる値とするのか、しきい値を指定します。double型。
14# しきい値とは? : https://wa3.i-3-i.info/word15002.html
15# 値を大きくすると、中心の画素値と差分の大きい周辺の画素値を許容すること(均一的にぼかす方向)に繋がります。
16
17# 第四引数(必須) : 中心画素をぼかすために、利用する画素領域を指定する。double型。
18# ただし、第二引数が0以下の場合にのみ、働きます。
19# > 参考:公式ドキュメントより引用 : When d > 0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is proportional to sigmaSpace.
20
21# 戻り値 : 多次元配列(画像情報)
22cv2.bilateralFilter(img, 整数, 数字, 数字)

で成り立ちます。

例えば以下のようなコードを作成すると、

1import cv2
2import sys
3
4# bilateralFilter関数を実行する関数
5def exec_bilateral_filter(img):
6    # bilateralFilter関数 : 画像をぼかす関数
7    # 第一引数(必須) : 多次元配列(numpy.ndarray)
8    # 第二引数(必須) : 中心画素をぼかすために、利用する画素領域を指定する。
9    # 第三引数(必須) : 第二引数で指定する画素領域内で、中心の画素値と周辺の画素値の比較を行いますが、その画素値の差を許容できる値とするのか、しきい値を指定します。
10    # 第四引数(必須) : 中心画素をぼかすために、利用する画素領域を指定する。
11    # 戻り値 : 多次元配列(numpy.ndarray)
12    return cv2.bilateralFilter(img, 40, 50, 50)
13
14# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
15# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
16# 第一引数 : 画像のファイルパス
17# 戻り値 : 行 x 列 x 色の三次元配列(numpy.ndarray)が返される。
18img = cv2.imread("xxx.jpg")
19
20# 画像ファイルが正常に読み込めなかった場合、プログラムを終了する。
21if img is None:
22    sys.exit("Could not read the image.")
23
24# hconcat : 画像を連結する関数
25imgs = cv2.hconcat([img, exec_bilateral_filter(img)])
26
27# imwrite : 画像の保存を行う関数
28# 第一引数 : 保存先の画像ファイル名
29# 第二引数 : 多次元配列(numpy.ndarray)
30# <第二引数の例>
31# [
32# [
33# [234 237 228]
34# ...
35# [202 209 194]
36# ]
37# [
38# [10 27 16]
39# ...
40# [36 67 46]
41# ]
42# [
43# [34 51 40]
44# ...
45# [50 81 60]
46# ]
47# ]
48# imwriteについて : https://kuroro.blog/python/i0tNE1Mp8aEz8Z7n6Ggg/
49cv2.imwrite('output.jpg', imgs)

以下の画像のように、画像が描画されます。

bilateralFilter関数の値入力に困った場合

bilateralFilter関数の第二引数~第四引数へ具体的にどのような値を入れるべきか、悩んでいる方も多いかと思います。

上記の問題を解決するために、筆者の場合ipywidgetsというJupyter Notebookで使える拡張機能を使って、第二引数~第四引数の値を調整しています。

【ipywidgetsを利用するために準備したこと】

上記で作成した空のJupyter Notebookへ、以下のコードを貼り付けて、実行(▶️を選択)してみてください。

1import cv2
2from IPython.display import Image, display
3from ipywidgets import widgets
4
5def imshow(img):
6    """画像をJupyter Notebook上に表示する。"""
7    _, encoded = cv2.imencode(".jpg", img)
8    display(Image(encoded))
9
10def execute(d, sigmaColor, sigmaSpace):
11    print('d: ' + str(d))
12    print('sigmaColor: ' + str(sigmaColor))
13    print('sigmaSpace: ' + str(sigmaSpace))
14
15    img_blur = cv2.bilateralFilter(img, d, sigmaColor, sigmaSpace)
16    imshow(img_blur)
17
18# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
19# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
20# 第一引数 : 画像のファイルパス
21# 戻り値 : 多次元配列(numpy.ndarray)が返される。
22# ※ 画像を設定ください。
23img = cv2.imread("xxx.jpg")
24
25# 部品情報を格納する。
26parts = {}
27
28# bilateralFilterの第二引数を調整するスライダー
29# 参考 : https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html?highlight=IntSlider#IntSlider
30# min : 第二引数の最小値
31# mix : 第二引数の最大値
32# step : 第二引数の増減値
33# value : 第二引数の初期値
34# description : スライダーの説明文
35parts["d"] = widgets.IntSlider(
36    min=-500,
37    max=500,
38    step=1,
39    value=0,
40    description="d: "
41)
42
43# bilateralFilterの第三引数を調整するスライダー
44# 参考 : https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html?highlight=IntSlider#FloatSlider
45# min : 第三引数の最小値
46# mix : 第三引数の最大値
47# step : 第三引数の増減値
48# value : 第三引数の初期値
49# description : スライダーの説明文
50parts["sigmaColor"] = widgets.FloatSlider(
51    min=-100,
52    max=100,
53    step=1.5,
54    value=0,
55    description="sigmaColor: "
56)
57
58# bilateralFilterの第四引数を調整するスライダー
59# 参考 : https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html?highlight=IntSlider#FloatSlider
60# min : 第三引数の最小値
61# mix : 第三引数の最大値
62# step : 第三引数の増減値
63# value : 第三引数の初期値
64# description : スライダーの説明文
65parts["sigmaSpace"] = widgets.FloatSlider(
66    min=-500,
67    max=500,
68    step=3.5,
69    value=0,
70    description="sigmaSpace: "
71)
72
73# 部品の大きさを設定する。
74for part in parts.values():
75    part.layout.width = "400px"
76
77widgets.interactive(execute, **parts)

すると以下の画像のような画面が現れます。

実際に部品(スライダー)を動かしてみると、それぞれの値に応じて画像にぼかしを加えて、画像が変更されます。(※ 画像のぼかしのために、画像表示に時間がかかることがあります。)

まとめ

  • 画像をぼかすとは、輪郭や色の濃淡の境目をきわだたせないで、ぼんやりさせることを意味します。
  • 難しい言葉で言うと、「平滑化」すると言われる。
  • 画像にぼかしを加えることで、主役をきわだたせられる・背景が整理される・画像に距離感が生まれる等の効果があります。

参考文献

記事に関するお問い合わせ