scikit-learnのextract_patches_2dで画像を小さいパッチに切り出す

2021.11.24

データアナリティクス事業本部の鈴木です。

scikit-learnのextract_patches_2dを使うと、画像を小さいパッチに切り出すことができます。 どのような挙動をするのか、例が少なかったため、試してみました。

ユーザーガイドは以下にあります。

6.2. Feature extraction — scikit-learn 1.0.1 documentation

前提

検証した環境

  • コンテナ:jupyter/datascience-notebook
  • scikit-learn:1.0

使用する画像

以下の画像をColinkySquash.jpgとして使用しました。 検証に使用した画像

やってみる

パッチの作成

まず、パッチの作成から行っていきます。

Pillowで読み込んだ画像をNumpy配列に変換し、extract_patches_2dで(200, 200)の大きさのパッチをmax_patches個作成します。

import numpy as np
from PIL import Image
from sklearn.feature_extraction import image

# 画像を読み込む
im = Image.open("./ColinkySquash.jpg")

# Numpy配列に変換する
im_arr  = np.array(im)

# (200, 200)の大きさのパッチをmax_patches個作成する
# 大きめのサイズのパッチを作るので、max_patchesを指定した。
patches = image.extract_patches_2d(im_arr, (200, 200),
                                   max_patches=10000,
                                   random_state=2021)

一つ目のパッチを表示してみます。指定した大きさで、元の画像からパッチが作成されていることが分かります。

作成したパッチの例

パッチから画像の復元

reconstruct_from_patches_2dでパッチから画像の復元することが可能です。

import numpy as np
from PIL import Image
from sklearn.feature_extraction import image

# 画像を読み込む
im = Image.open("./ColinkySquash.jpg")

# Numpy配列に変換する
im_arr  = np.array(im)

# パッチを作成する
patches = image.extract_patches_2d(im_arr, (7, 7),  random_state=2021)

# パッチから画像を復元する
reconstructed = image.reconstruct_from_patches_2d(patches, im_arr.shape)

# 復元した画像を表示する
Image.fromarray(reconstructed.astype("uint8")).show()

復元した画像は以下のようになります。 復元した画像

パッチを作成する際にmax_patchesを指定していると復元が上手くいかないようでした。また、reconstruct_from_patches_2dimage_sizeは元の画像の大きさと同じ必要がありました。

max_patchesを指定したとき

▲max_patchesを指定したとき

復元後の画像サイズを元の半分にしたとき

▲復元後の画像サイズを元の半分にしたとき

パッチから画像を復元する際のユースケースは、以下の例のように、パッチごとに処理してから復元する手法の適用などがあります。

Image denoising using dictionary learning — scikit-learn 1.0.1 documentation

最後に

scikit-learnのextract_patches_2dを使って画像から小さいパッチを作成し、reconstruct_from_patches_2dで復元する際の方法をご紹介しました。

機械学習手法と組み合わせるようなケースもありますが、単に元画像から部分的に切り抜いた小さい画像をたくさん作りたいようなケースに便利に使えそうです。