※当サイトではアフィリエイト広告を利用しています。

画像処理

【opencv】マスクをかけたい部分のみ透過させる方法

こんにちは、タナカです。

この記事では、opencvを使ってマスクをかけたい部分のみ透過させる方法を紹介します。

【opencv】マスク画像を作成する方法の記事でマスク画像を作る方法を解析しましたが、マスクをかけた部分は真っ黒になっています。

その部分を透過させて、どの部分をマスクさせたか確認しようという話です。

ではいきましょう。

この記事の内容
  • 透過画像の作成方法がわかる

1. 透過画像

透過画像とは、RGBA形式で表現された画像のことです。RGBA(Red Green Blue Alpha)形式の画像とは、色の3原色(Red, Green, Blue)に加えて、透過度(alpha)を追加した画像のことです。

透過度は8ビットのデータ容量を持つため、0~255までの数値で表現されます。透過度が0のとき、透過率100%を意味しています。

例えば、元画像の透過度を変化させた画像がこちらになります。

2. マスクをかけた部分を透過させる

ここからが本題のマスクをかけた部分のみ透過させる方法についてです。

早速、マスクをかけた部分のみ透過させるコードがこちらになります。

import cv2
import numpy as np

# 元画像
img = cv2.imread('people-gbe1f8f837_640.jpg')

# rgba形式に変換
rgba = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)

# マスク画像の元となる画像を生成(マスク画像をかけたい画像サイズと同じ)
mask = np.zeros(rgba.shape[:2], dtype = np.uint8)

# マスク以外の領域を作成
cv2.circle(mask, (310, 200), 100, 255, thickness = -1)

# 透過させたい領域を255にする(マスク領域以外を反転)
mask = cv2.bitwise_not(mask)

# 画像の合成
rgba_not = cv2.bitwise_not(rgba, rgba, mask = mask)
rgba_not[:, :, 3] = np.where(rgba_not[:, :, 3] == 0, 50, 255)

 

上のコードでは、以下の流れに沿って処理が行われています。

  1. ライブラリのインポート
  2. 画像の読み込み
  3. RGBA形式に変換
  4. マスク画像の準備
  5. マスクをかけない領域を作成
  6. 透過させたい領域を255にする
  7. 画像の合成

①のライブラリのインポートでは、今回opencvとnumpyを使っています。

②では、まず初めに元画像をBGR形式で読み込みます。opencvの仕様上、引数にパスのみを指定した場合、デフォルトでBGR形式になります。

③ではBGR形式をBGRA形式に変換するためにcvtColorメソッドを使っています。

④では元画像と同じサイズのマスク画像を生成しています。生成された段階では、すべての画素値が0のグレースケール画像(8ビットのシングルチャンネル)になっています。

⑤では、円形でマスクをかけない領域を作成しています。

⑥では、透過させたい領域を255にして、透過させない部分を0にしています。つまり、マスクの領域とそうでない部分を反転するということです。

なぜこのような処理をするかというと、後々画像合成する際にnot処理で黒丸のみの残してあとは透過させるためです。

⑦で、opencvのbitwise_notというメソッドを使って画像を合成しています。最後の行は、合成した画像のalphaにあたる要素(rgba_not[:, :, 3])にalphaが0の場合、50を代入し、そうでない場合は255を代入するという処理をしています。

最終的にマスクの部分のみ透過させた画像がこちらになります。

alphaの値は50ではなくても、大丈夫です。

まとめ

今回は、マスクをかけたい部分のみ透過させる方法を紹介しました。

ただ、真っ黒な画像でマスクをかけるよりは、マスクをかけた部分がどうだったかを見えた方が可視化という観点からは良いのではないでしょうか。