「pythonで画像から色を抽出したい」と検索すると
Image Color Extraction with Python in 4 Steps | by Boriharn K | Towards Data Science
のような記事が出てくるが冗長である。処理ごとにコードを書かれるとコピペの手間もかかるしもったいぶらずにコードを全部載せてほしいし色を抜き出すところだけ見せてほしい。なのでこの記事にもっとずっと短いものを載せた。
上の記事で具体的に色を抽出する箇所は一行だけであり、それは、extcolorsの
extcolors.extract_from_image(img, tolerance = 10, limit = 5)
のような関数で実現できる。imgはPILの画像、toleranceは色をまとめる強度(0から100をとり、100で一色になる)、limitは色数の上限である。パスから直接読み込む場合は
extcolors.extract_from_path(img_url, tolerance = 10, limit = 5)
を使う。
これらの関数は色のタプルを含むちょっと入れ子になっているタプルを返す。
([((181, 198, 218), 18953), ((123, 152, 194), 18193), ((76, 83, 89), 8629), ((36, 46, 108), 5575), ((117, 118, 121), 4289)], 65536)
((赤, 青, 緑), ピクセル数)という構造が色の数だけ続いていて、最後に総ピクセル数がある。このタプルから割合を出すにはちょっと計算がいる。
このタプルを扱いやすい配列にしてグラフにするコード例↓
1.pngから5つの代表的な色を抜き出してグラフにしたいとする
import PIL import matplotlib.pyplot as plt import extcolors filename = "1.png" n = 5 img = PIL.Image.open(filename).resize((256,256)) #軽量化のため、縮小 colors, pixelCount = extcolors.extract_from_image(img, tolerance = 12, limit = n) colorCodes = ['#{:02x}{:02x}{:02x}'.format(*rgb[0]) for rgb in colors] colorRates = [rgb[1] for rgb in colors] plt.pie(colorRates,labels=colorCodes,colors=colorCodes) plt.savefig(filename+"_Color.png") plt.show()
pillowは優秀なので、1.jpgとか1.jfifとか他フォーマットでも処理できる
出力
色分布を三次元散布図にする
from matplotlib import pyplot as plt import cv2 as cv2 import numpy as np img = cv2.imread("1.png") img = cv2.resize(img,(64,64)) print(img) r = img[:,:,2] g = img[:,:,1] b = img[:,:,0] rgb = np.dstack((r, g, b)) rgb_flat = rgb.reshape((rgb.shape[0]*rgb.shape[1], 3)) def rgb_to_hex(rgb): return '#{:02x}{:02x}{:02x}'.format(*rgb) cCodes = np.apply_along_axis(rgb_to_hex, 1, rgb_flat) # print(cCodes) fig = plt.figure() ax = fig.add_subplot(1, 1, 1, projection='3d') ax.scatter(b, g, r, c=cCodes,alpha=1) plt.show()
出力