【Python/OpenCV】膨張・収縮フィルタ処理(dilate, erode)

この記事では、Python版OpenCV(cv2.dilate, cv2.erode)もしくはNumPyで膨張・収縮フィルタ処理を実装する方法をソースコード付きで解説します。

膨張・収縮フィルタ

膨張・収縮フィルタとは、二値画像からノイズ除去したりするのに使われるアルゴリズムです。

処理内容
膨張処理 白色(255)の領域を膨張
収縮処理 白色(255)の領域を収縮
参考記事 膨張・収縮処理の原理・特徴・計算式

今回は、以下の2通りの方法で処理を実装してみました。

概要
方法① NumPyで膨張・収縮フィルタのアルゴリズムを書いて実装
方法② cv2.Cannyで簡単に実装(1行で書けちゃうので楽チン)

書式

dst = cv2.dilate(src, kernel, iterations) # 膨張処理
dst = cv2.erode(src, kernel, iterations) # 収縮処理
パラメータ名 説明
src 入力画像
kernel カーネル(1の近傍画素を膨張・収縮処理に利用)
dst 出力画像

ソースコード(Python3+OpenCV3)

サンプルプログラムのソースコードです。

方法①

#-*- coding:utf-8 -*-
import cv2
import numpy as np

# 膨張処理
def dilate(src, ksize=3):
    # 入力画像のサイズを取得
    h, w = src.shape
    # 入力画像をコピーして出力画像用配列を生成
    dst = src.copy()
    # 注目領域の幅
    d = int((ksize-1)/2)

    for y in range(0, h):
        for x in range(0, w):
            # 近傍に白い画素が1つでもあれば、注目画素を白色に塗り替える
            roi = src[y-d:y+d+1, x-d:x+d+1]
            if np.count_nonzero(roi) > 0:
                dst[y][x] = 255

    return dst

# 収縮処理
def erode(src, ksize=3):
    # 入力画像のサイズを取得
    h, w = src.shape
    # 入力画像をコピーして出力画像用配列を生成
    dst = src.copy()
    # 注目領域の幅
    d = int((ksize-1)/2)

    for y in range(0, h):
        for x in range(0, w):
            # 近傍に黒い画素が1つでもあれば、注目画素を黒色に塗り替える
            roi = src[y-d:y+d+1, x-d:x+d+1]
            if roi.size - np.count_nonzero(roi) > 0:
                dst[y][x] = 0

    return dst

def main():
    # 入力画像を読み込み
    img = cv2.imread("input.png")

    # グレースケール変換
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

    # 二値化処理
    gray[gray<127] = 0
    gray[gray>=127] = 255

    # 膨張・収縮処理(方法1)
    dilate_img = dilate(gray, ksize=6)
    erode_img = erode(dilate_img, ksize=6)

    # 結果を出力
    cv2.imwrite("dilate.png", dilate_img)
    cv2.imwrite("erode.png", erode_img)


if __name__ == "__main__":
    main()

方法②

#-*- coding:utf-8 -*-
import cv2
import numpy as np

def main():
    # 入力画像を読み込み
    img = cv2.imread("input.png")

    # グレースケール変換
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

    # 二値化処理
    gray[gray<127] = 0
    gray[gray>=127] = 255

    # カーネルの定義
    kernel = np.ones((6, 6), np.uint8)

    # 膨張・収縮処理(方法2)
    dilate = cv2.dilate(gray, kernel)
    erode = cv2.erode(dilate, kernel)

    # 結果を出力
    cv2.imwrite("dilate.png", dilate)
    cv2.imwrite("erode.png", erode)


if __name__ == "__main__":
    main()

※動作には、OpenCVライブラリのインストールが必要です。

実行結果

サンプルプログラムの実行結果です。

■入力画像(左)→膨張画像(中央)→収縮画像(右)

お借りした画像:プロ生ちゃん(暮井 慧)

関連記事
1 PythonでOpenCV入門 サンプル集
2 【Python】画像処理プログラミング入門
3 【画像処理入門】アルゴリズム&プログラミング
関連記事

コメント

  1. 中村和樹 より:

    参考にさせていただきました。
    ありがとうございます。
    1つ質問したいことがあります。
    カーネルの値が6に設定されていますが、8近傍の場合3×3のカーネルサイズのため、値を3に設定するべきではないのでしょうか?
    よろしくお願いします。

    • 管理人 より:

      ※中村和樹 様
      ご報告ありがとうございます。
      ご指摘頂いたとおり、「8近傍」という記載は誤りですね。
      該当箇所は修正致しました。