OpenCVオープニング(opening)とクロージング(closing)でマスク画像を加工

オープニングとクロージング

オープニングとは白黒画像の細かいごみを取り除く手法です。縮小→拡大という処理を行います。クロージングとは白黒画像の細かい穴を取り除く手法です。

OpenCVでオープニング処理とクロージング処理

cv2.morphologyExを使うとオープニング処理とクロージング処理を行えます。

cv2.morphologyEx(img, flag, kernel)

imgは処理を行う画像です。flagでcv2.MORPH_OPENを指定するとオープニング処理ができます。flagでcv2.MORPH_CLOSEを指定するとクロージング処理ができます。kernelはオープニング処理の場合、消したいくずの形、クロージング処理の場合、埋めたい穴の形を表す各成分が1または0の行列です。

オープニング処理、クロージング処理でマスク画像を加工

準備

まずはマスク画像を用意します。前景を抽出するためにHSV分解と2値化で作ったマスク画像です。詳しいマスク画像の作り方については OpenCV(Python)2値化の使い方で紹介しています。

jeans-564089_640 jeans_mask

オープニング処理でくずを除去

赤で囲んでいるくずをオープニング処理で取り除きます。

jeans_mask_openning

引数に画像のパスを指定するとオープニング処理が実行されます。

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

filename = sys.argv[1]
img = cv2.imread(filename, 1)
kernel = np.ones((2,2),np.uint8)
result = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.imwrite(filename[:filename.rfind(".")] + "_opening.png", result)

オープニング処理の結果

小さいくずが消えているのがわかると思います。

jeans_mask_opening

クロージング処理で穴を除去

ジーンズのしわの部分が穴になっているので埋めていきます。大きい穴なのでkernelを大きくしています。

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

filename = sys.argv[1]
img = cv2.imread(filename, 1)
kernel = np.ones((25,25),np.uint8)
result = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imwrite(filename[:filename.rfind(".")] + "_closing.png", result)

クロージングの実行結果

オープニング処理をした先ほどの画像を引数に渡してスクリプトを実行すると下記のような画像が生成されます。

jeans_mask_opening_closing

HSV分解+2値化+オープニング処理+クロージング処理で前景抽出

OpenCV(Python)2値化の使い方で紹介したスクリプトにクロージング処理とオープニング処理を行って前景抽出を行います。

サンプルコード

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

filename = sys.argv[1]
#画像を読み込む
img = cv2.imread(filename)
#BGR画像をHSV画像に変換
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
#HSVに分解
h_img, s_img, v_img = cv2.split(hsv)
#彩度のレイヤーを2値化してマスク画像を生成
_, mask_img = cv2.threshold(s_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
#オープニングとクロージング
kernel = np.ones((2,2),np.uint8)
mask_img = cv2.morphologyEx(mask_img, cv2.MORPH_OPEN, kernel)
kernel = np.ones((25,25),np.uint8)
mask_img = cv2.morphologyEx(mask_img, cv2.MORPH_CLOSE, kernel)
#マスク画像を合成
result = cv2.merge(cv2.split(img) + [mask_img])
#「マスク部分を透明化した結果画像」とマスク画像を書き出す
cv2.imwrite(filename[:filename.rfind(".")] + "_result.png", result)
cv2.imwrite(filename[:filename.rfind(".")] + "_mask.png", mask_img)

結果

左の画像が入力で右の画像が出力です。ざっくりと前景が抽出できています。

jeans-564089_640jeans_result

コメント

タイトルとURLをコピーしました