LoginSignup
7
11

More than 3 years have passed since last update.

画像をマスキングするためのnumpyのTips

Last updated at Posted at 2018-12-16

OpenCVでカラー画像を読み込み、グレースケール、二値化処理、というながれでマスク画像を作ります。

1. 画像読み込み

OpenCVで画像を読み込みます。
OpenCVはBGR(Blue/Green/Red)カラーモデル(3色のチャネルの順番の話です)でデータを読み込みますが、
一般的にはRGBカラーモデルであり、またmatplotlib.pyplotの表示はRGBカラーモデルのため、オリジナルの画像と色合いを合わせるためにRGBカラーモデルへの変換を行います。

>>> import cv2  # 読み込みOpenCVライブラリ
>>> import matplotlib.pyplot as plt # 出力

>>> img = cv2.imread('sample.JPG')
>>> img.shape
(240, 400, 3)

>>> rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
>>> plt.imshow(rgb_img)
>>> plt.show()

rgb_img
image.png

2. グレースケール処理

(RGB)カラー画像は1ピクセルごとに3層のパラメータにより色合いが決まっています。
グレー画像に変換すると1ピクセルごとに1つのパラメータにより色合いが決まります。
ではカラー画像からグレー画像へ変換してみます。

>>> gray_img = cv2.cvtColor(rgb_img,cv2.COLOR_RGB2GRAY)
>>> plt.imshow(gray_img)
>>> plt.show()

gray_img
image.png

3. 二値化処理

グレー画像のパラメータについて、基準値を設定して、1ピクセルごとに0か1に変換します。
では適当に基準値を設定してグレー画像からバイナリー画像へ変換してみます。

>>> bin_threshold = 175
>>> ret, bin_img = cv2.threshold(gray_img ,bin_threshold, 1, cv2.THRESH_BINARY_INV)
>>> bin_img
array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [1, 1, 1, ..., 1, 1, 1],
       [1, 1, 1, ..., 1, 1, 1],
       [1, 1, 1, ..., 1, 1, 1]], dtype=uint8)
>>> plt.imshow(bin_img)
>>> plt.show()

bin_img
image.png

booleanな配列・リストの0と1の反転

booleannumpy.arraylistの0と1の反転は、方法はいろいろありますが、次の方法がシンプルです。

1 - np.array(対象の配列やリスト)

for文でぐるぐるまわしたり、内包表記を使うに及びません。
numpyでスッキリかけます。

リストにしたい場合はこの結果にtolist()という関数で変換すればよいです。

booleanな配列・リストの反転

例として簡単な配列、リストに対して上記方法により0と1を反転してみます。

>>> import numpy as np

>>> array1 = np.array([1,0,0])
>>> array1_not = 1 - array1
>>> array1_not
array([0, 1, 1])

>>> array2 = np.array([[1,0,0],[0,1,0]])
>>> array2_not = 1 - array2
>>> array2_not
array([[0, 1, 1],
       [1, 0, 1]])

>>> list1 = [1,0,0]
>>> list1_not = (1 - np.array(list1)).tolist()
>>> list1_not
[0, 1, 1]

>>> list2 = [[1,0,0],[0,1,0]]
>>> list2_not = (1 - np.array(list2)).tolist()
>>> list2_not
[[0, 1, 1], [1, 0, 1]]

バイナリー画像の反転

binary画像の反転も配列・リストと同じです。
サイズが変わろうが、行う方法は同じでシンプルです。

1 - np.array(対象の配列やリスト)

それでは、作成したバイナリー画像の0と1を反転してみます。

>>> bin_img_not = 1 - bin_img

bin_img_not
image.png

画像のマスキングの方法

バイナリー画像のマスクイメージを作って、イメージに沿って情報をマスキングします。
必要な個所のみを切り取るCropではなく、同じサイズの画像から必要な情報のみを残す方法です。

グレー画像のマスキング

グレー画像もバイナリー画像も同じ次元であり、バイナリー画像は0と1で構成されるため、
対応するピクセル同士の数値を掛け算してあげれば、簡単にマスキングできます。
numpy.array で構成されるグレー画像、バイナリー画像であれば、その掛け算も簡単にできます。

作成したバイナリー画像をマスクイメージとしてグレー画像からマスキングを実施してみます。

>>> gray_img_masked = gray_img * bin_img
>>> gray_img_masked_not = gray_img * (1 - bin_img)

gray_img_masked
image.png

gray_img_masked_not
image.png

カラー画像のマスキング

同じピクセル数でもRGBカラーモデルでは、1ピクセルごとに3層分のデータを保有するため、バイナリー画像で単純に掛け算するにはひと工夫必要です。
numpy.stack を使って、層の数を合わせることができます。

これにより同じ値のマスクイメージ(バイナリー画像)を3層もつ状態が表現できます。
カラー画像とこの3層に対応したマスクイメージを掛け合わせるとカラー画像のマスキングができます。

それではカラー画像のマスキングを実施してみます。

>>> rgb_img_masked = rgb_img * np.stack([bin_img]*3, axis=2)
>>> rgb_img_masked_not = rgb_img * np.stack([1 - bin_img]*3, axis=2)

rgb_img_masked
image.png|

rgb_img_masked_not
image.png

(参考)
カラー画像のマスキングについて
OpenCVで cv2.bitwise_and という関数を使っても同じ結果が得られます。
cv2.bitwise_and(img, img, mask=bin_img)

まとめ

  • numpybooleanな配列やリストの0と1の反転が簡単にできる!
    1 - np.array(対象の配列やリスト)

  • numpyで画像のマスキングが簡単にできる!
    画像×マスクイメージ
     ただし、マスクイメージは、バイナリー画像で画像のチャネルと合わせる工夫が必要

7
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
11