今回は、画像の中から色を抽出し、カラーコードの割合を見ることをやってみます。
画像を入力として、このような結果を出力します。
色の重要性
なぜ色が重要なのか?というと、
色は、一目で人の注意を引くのに役立てることができます。
例えば、緑と赤で金銭的価値を示したり、赤と青で温度の高低を表現したりなど、メッセージを効率よく伝えることにも役立ちます。
また、データの可視化においても、色は有効です。
ベーシックな色は、すぐに使えて汎用性が高いので、使い勝手が良いです。
しかしながら、時にはオーダーメイドの色の方が、ストーリーを伝え、作品を際立たせるのに適している場合もあります。
そのためにも、自分の作品(スライド、写真など)にどのような色を使うかは重要な要素となってきます。
私たちが持っている携帯電話やカメラで撮った写真も、色の源になります。
欲しい色が写っているものを撮影してもいいですし、すでに好きな色が写っているものがあるかもしれません。
この記事では、画像から色を抽出する方法について説明します。
また、この方法を応用することで、旅行先で撮った絶景や好きなものなど、お気に入りの写真を楽しく分析することもできるようになります。
それでは、解説に入ります。
画像の色抽出(カラーコード抽出)
ここでは、下記の写真を例にしながら、解説をしていきます。
それでは、まずは色を抽出するための関数を定義します。
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.image as mpimg
import extcolors
from colormap import rgb2hex
from PIL import Image
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
def exact_color(input_image, resize, tolerance, zoom):
# リサイズを実施
output_width = resize
img = Image.open(input_image)
if img.size[0] >= resize:
width_per_c = (output_width / float(img.size[0]))
hsize = int((float(img.size[1]) * float(width_per_c)))
img = img.resize((output_width, hsize), Image.ANTIALIAS)
resize_name = 'resize_' + input_image
img.save(resize_name)
else:
resize_name = input_image
# 背景を設定する
background = 'background.png'
fig, ax = plt.subplots(figsize=(192, 108), dpi=10)
fig.set_facecolor('white')
plt.savefig(background)
plt.close(fig)
# Dataframeの作成
img_real = resize_name
colors_x = extcolors.extract_from_path(img_real, tolerance=tolerance, limit=10)
colors_pre_list = str(colors_x).replace('([(', '').split(', (')[0:-1]
df_rgb = [i.split('), ')[0] + ')' for i in colors_pre_list]
df_percent = [i.split('), ')[1].replace(')', '') for i in colors_pre_list]
# RGBからHEXコードへの変換
df_color_up = [rgb2hex(int(i.split(", ")[0].replace("(", "")),
int(i.split(", ")[1]),
int(i.split(", ")[2].replace(")", ""))) for i in df_rgb]
df_color = pd.DataFrame(zip(df_color_up, df_percent), columns=['c_code', 'occurence'])
# 注釈を付ける
list_color = list(df_color['c_code'])
list_precent = [int(i) for i in list(df_color['occurence'])]
text_c = [c + ' ' + str(round(p * 100 / sum(list_precent), 1)) + '%' for c, p in zip(list_color, list_precent)]
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(160, 120), dpi=10)
# donut plot
wedges, text = ax1.pie(list_precent,
labels=text_c,
labeldistance=1.05,
colors=list_color,
textprops={'fontsize': 150, 'color': 'black'})
plt.setp(wedges, width=0.3)
# donut plotの中心に画像を追加
img = mpimg.imread(resize_name)
imagebox = OffsetImage(img, zoom=zoom)
ab = AnnotationBbox(imagebox, (0, 0))
ax1.add_artist(ab)
# color palette
x_posi, y_posi, y_posi2 = 160, -170, -170
for c in list_color:
if list_color.index(c) <= 5:
y_posi += 180
rect = patches.Rectangle((x_posi, y_posi), 360, 160, facecolor=c)
ax2.add_patch(rect)
ax2.text(x=x_posi + 400, y=y_posi + 100, s=c, fontdict={'fontsize': 190})
else:
y_posi2 += 180
rect = patches.Rectangle((x_posi + 1000, y_posi2), 360, 160, facecolor=c)
ax2.add_artist(rect)
ax2.text(x=x_posi + 1400, y=y_posi2 + 100, s=c, fontdict={'fontsize': 190})
fig.set_facecolor('white')
ax2.axis('off')
bg = plt.imread('bg.png')
plt.imshow(bg)
plt.tight_layout()
fig.savefig('after_' + input_image)
return plt.show()
ここまでで、(input_image, resize, tolerance, zoom)を入力として、カラーコードを抽出したのちに、結果を保存するというコードです。
では実際に使ってみます。
exact_color('sea.jpg', 900, 36, 2.5)
出力結果
このように、画像の中からカラーコードを抜き出し、表示することができます。
他にも、2例お見せします。
例2
# 例2つ目
exact_color('city.jpg', 900, 36, 2.5)
出力結果
例3
3つ目の例です。
# 例3つ目
exact_color('sheep.jpg', 900, 36, 2.5)
出力結果
この記事では、画像を入力して、各カラーコードを抽出する方法について解説しました。
参考文献:
- Extcolors. PyPI. Retrieved May 22, 2022, from https://pypi.org/project/extcolors
- Murray, E. (2019, March 22). The importance of color in data visualizations. Forbes. Retrieved May 23, 2022, from https://www.forbes.com/sites/evamurray/2019/03/22/the-importance-of-color-in-data-visualizations/?sh=fdc72a657ec5
- Image Color Extraction with Python in 4 Steps May 25, 2022 from https://towardsdatascience.com/image-color-extraction-with-python-in-4-steps-8d9370d9216e