画像の色(RGB)を抽出する


はじめに

画像から使用されている色(RGB)を抽出する機会があったので、そのメモです。

環境

言語、パッケージ

言語、パッケージ バージョン
Python 3.7.4
numpy 1.16.4
OpenCV 3.4.2

画像

lena.jpg

画像のサイズを確認

使用する画像を確認します。

import cv2
import numpy as np

bgr_array = cv2.imread('lena.jpg')
print(bgr_array.shape)
# (512, 512, 3)

OpenCVを用いて画像を読み込むと、色はBGRの順番になります。
そのため、各512×512のB, G, R行列が3つ並んでいるイメージとなります。

GBRの取得

例えば、一番左上のBGR値の取得は下記で行います。

print(bgr_array[0, 0, :])
# [128 138 225]

画像のリサイズ

上記の方法だとBGR値の取得を512×512回行う必要があります。
効率よく行うために下記の行列を作成します。

\left[
    \begin{array}{rrr}
      b_{0} & g_{0} & r_{0} \\
      \vdots & \vdots &  \vdots \\
      b_{n} & g_{n} & r_{n}
    \end{array}
  \right]

ここでn=512*512-1です。
そして、行方向でユニークな値を抽出していきます。

reshaped_bgr_array = bgr_array.reshape(512*512, 3)

# axis=0で行方向のユニーク化を指定
unique_bgr_array = np.unique(reshaped_bgr_array, axis=0)

# ユニークなbgr値の一覧
print(unique_bgr_array)
"""
[[ 29  14  76]
 [ 31  11  86]
 [ 31  27 146]
 ...
 [224 175 191]
 [224 180 197]
 [225 247 253]]
"""

# ユニークなbgr値の数
print(len(unique_bgr_array))
# 73852

# 全ピクセル数に対するユニークなbgr値の割合
print(len(unique_bgr_array)/(512*512))
# 0.2817230224609375

関数化

上記のコードでは画像のサイズに依存しているので、再利用できるように関数化します。

def extract_unique_color(img_path, rgb=False):
    bgr_array = cv2.imread(img_path)
    row, col, _ = bgr_array.shape
    reshaped_bgr_array = bgr_array.reshape(row * col, 3)
    unique_color_array = np.unique(reshaped_bgr_array, axis=0)

    if rgb:
        # rgbに要素を並び替え
        unique_color_array = unique_color_array[:, [2, 1, 0]]

    return unique_color_array

最後に

画像内のユニークな色の抽出方法を紹介しました。