Python, scikit-learn

【scikit-learn】k-means法を用いた減色処理

クラスタリングの活用事例の一つに画像の減色処理があります。

本記事では、代表的なクラスタリング手法であるk-means法を用いた減色処理を実装する方法について書きます。

そもそも「減色処理」とは?

まずは減色処理とは何かについて簡単に説明します。

より少ない色で画像を表現するための処理

元々の画像と可能な限り同じような見た目を保ちつつ、画像内で使われる色の種類を少なくする処理のことです。

限られた種類の色しか使用できないデバイス上で画像を表示する際などに行われます。

減色処理のアルゴリズムはいくつかありますが、どのアルゴリズムでもやっていることは大きく分けて以下の二つです。

  1. 使用する色をいくつか選ぶ(自動で決まるように実装する場合が多い)
  2. 各ピクセルの色を1で選んだ色の中で最も近いものに置き換える

使用する色をどのように選ぶか、何を基準に色の近さを判断するかによって、出来上がる画像の見た目には大きな差が生じます。

実際にプログラムを作成してみる

それでは実際に減色処理を行うプログラムを作成してみます。

プログラム作成の手順

ここでは、以下の手順で処理を実装します。

  1. 使用する色の数を指定する
  2. 1で指定した数をクラスタ数として、対象の画像の各ピクセルを色情報に基づいてクラスタリングする(k-means法)
  3. 各ピクセルの色をそのピクセルが属するクラスタの中心のピクセルの色に置き換える

実装例

上記の手順に従ってプログラムを作成します。使用する言語はPythonです。

from sklearn.datasets import load_sample_image
from sklearn.cluster import KMeans

import matplotlib.pyplot as plt
import numpy as np

# 各ピクセルの色を変換するメソッド
def color_quantization(codebook, labels, w, h):
    d = codebook.shape[1]
    image = np.zeros((w, h, d))
    index = 0
    for i in range(w):
        for j in range(h):
            image[i][j] = codebook[labels[index]]
            index += 1
    return image

# 対象の画像を表示するメソッド
def plot_images(images,titles):
    for i, (image, title) in enumerate( zip(images,titles) ):
        plt.figure(i)
        plt.clf()
        plt.axis('off')
        plt.title(title)
        plt.imshow(image)
    plt.show()

if __name__ == '__main__':

    # 使用する色の数を指定する
    n_colors = 8

    # 画像データを読み込む
    image = load_sample_image('china.jpg')
    image = np.array(image, dtype=np.float64) / 255

    w, h, d = tuple(image.shape)

    # カラー画像の場合のみ減色処理を行う(モノクロ画像はd==1になる)
    if d==3:

        # 画像を1次元のリストデータに変換する
        image_array = np.reshape(image, (w * h, d))

        # 色情報に基づいたクラスタリングを行う
        kmeans = KMeans(n_clusters=n_colors).fit(image_array)

        # クラスタリング結果をリファレンスとしてピクセルの色を変換する
        cq_image = color_quantization(kmeans.cluster_centers_, kmeans.labels_, w, h)

        # 画像を表示する
        images = [image, cq_image]
        titles = ['input', 'output']
        plot_images(images, titles)

このプログラムを実行すると以下の出力結果が得られます。

減色処理によって色の種類を8種類まで削減しましたが、それほど違和感のない見た目になっていると思います。