Python에서 이미지의 대표 색상 (?)을 취하는 연습
게다가 자신 나름대로 대표색을 찾는 방법을 생각하고 그것을 구현해 보는 연습을 하고 싶다고 생각했다.
큰 프레임에서 다음과 같은 방식을 생각해 실장했다.
k-means보다 뛰어난 감색 알고리즘이 다수 있어, 그쪽을 사용하는 것도 손일지도 모르지만,
자신은 일요일 프로그래밍으로 구현할 수 있는 자신이 없었기 때문에, 구현도 간단하고 scipy 에도 포함되어 있는 k-means 를 사용했다.
픽셀을 클러스터에 할당하는 것도 scipy의 vq (Vector Quantization)를 그대로 사용하기로 했기 때문에 꽤 낭비했다.
결과
wkhtmltoimage 명령을 사용하여 여러 웹 페이지의 이미지를 가져 와서 대표 색상을 추출했습니다.
빼낸 것만으로는 직관적으로는 모르기 때문에, 적당한 직사각형에 대표색을 같은 크기로 표시하기로 했다.
이하, 근거는 없지만 「좋은 느낌」이라고 생각했다.
Qiita
Facebook
코카콜라 공식 브랜드 사이트
스크립트
다음이 Python 3으로 작성된 스크립트.
다른 numpy, scipy, pillow가 필요합니다.
#!/usr/bin/env python
import argparse
import numpy
import PIL
import PIL.ImageDraw
import scipy
import scipy.cluster
import scipy.misc
def main():
parser = argparse.ArgumentParser()
parser.add_argument('source_image')
parser.add_argument('summary_image')
parser.add_argument('-n', type=int, default=4)
args = parser.parse_args()
img = PIL.Image.open(args.source_image)
c = args.n + 1
colors = top_n_colors(img, top_n=args.n, num_of_clusters=c)
save_summary_image(args.summary_image, colors)
def pillow_image_to_simple_bitmap(pillow_image):
small_img = pillow_image.resize((100, 100))
bitmap = scipy.misc.fromimage(small_img)
shape = bitmap.shape
bitmap = bitmap.reshape(scipy.product(shape[:2]), shape[2])
bitmap = bitmap.astype(numpy.float)
return bitmap
def top_n_colors(pillow_image, top_n, num_of_clusters):
clustering = scipy.cluster.vq.kmeans
bitmap = pillow_image_to_simple_bitmap(pillow_image)
clusters, _ = clustering(bitmap, num_of_clusters)
quntized, _ = scipy.cluster.vq.vq(bitmap, clusters)
histgrams, _ = scipy.histogram(quntized, len(clusters))
order = numpy.argsort(histgrams)[::-1][:top_n]
for idx in range(top_n):
rgb = clusters.astype(int)[order[idx]].tolist()
yield '#{:02x}{:02x}{:02x}'.format(*rgb)
def save_summary_image(path, color_codes, width=300, height=100):
color_codes = tuple(color_codes)
image = PIL.Image.new('RGB', (width, height))
draw = PIL.ImageDraw.Draw(image)
single_width = width / len(color_codes)
for i, color_code in enumerate(color_codes):
starting = (int(single_width * i), 0)
ending = (int(single_width * (i + 1)), height)
draw.rectangle([starting, ending], fill=color_code)
image.save(path, format='png')
if __name__ == '__main__':
main()
사용법
$ python ./image_top_n_color.py input.png output.png
-n
선택적으로 클러스터 수를 지정할 수 있습니다.
Reference
이 문제에 관하여(Python에서 이미지의 대표 색상 (?)을 취하는 연습), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/kitsuyui/items/e8ea67770c45011c7aca
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
다음이 Python 3으로 작성된 스크립트.
다른 numpy, scipy, pillow가 필요합니다.
#!/usr/bin/env python
import argparse
import numpy
import PIL
import PIL.ImageDraw
import scipy
import scipy.cluster
import scipy.misc
def main():
parser = argparse.ArgumentParser()
parser.add_argument('source_image')
parser.add_argument('summary_image')
parser.add_argument('-n', type=int, default=4)
args = parser.parse_args()
img = PIL.Image.open(args.source_image)
c = args.n + 1
colors = top_n_colors(img, top_n=args.n, num_of_clusters=c)
save_summary_image(args.summary_image, colors)
def pillow_image_to_simple_bitmap(pillow_image):
small_img = pillow_image.resize((100, 100))
bitmap = scipy.misc.fromimage(small_img)
shape = bitmap.shape
bitmap = bitmap.reshape(scipy.product(shape[:2]), shape[2])
bitmap = bitmap.astype(numpy.float)
return bitmap
def top_n_colors(pillow_image, top_n, num_of_clusters):
clustering = scipy.cluster.vq.kmeans
bitmap = pillow_image_to_simple_bitmap(pillow_image)
clusters, _ = clustering(bitmap, num_of_clusters)
quntized, _ = scipy.cluster.vq.vq(bitmap, clusters)
histgrams, _ = scipy.histogram(quntized, len(clusters))
order = numpy.argsort(histgrams)[::-1][:top_n]
for idx in range(top_n):
rgb = clusters.astype(int)[order[idx]].tolist()
yield '#{:02x}{:02x}{:02x}'.format(*rgb)
def save_summary_image(path, color_codes, width=300, height=100):
color_codes = tuple(color_codes)
image = PIL.Image.new('RGB', (width, height))
draw = PIL.ImageDraw.Draw(image)
single_width = width / len(color_codes)
for i, color_code in enumerate(color_codes):
starting = (int(single_width * i), 0)
ending = (int(single_width * (i + 1)), height)
draw.rectangle([starting, ending], fill=color_code)
image.save(path, format='png')
if __name__ == '__main__':
main()
사용법
$ python ./image_top_n_color.py input.png output.png
-n
선택적으로 클러스터 수를 지정할 수 있습니다.
Reference
이 문제에 관하여(Python에서 이미지의 대표 색상 (?)을 취하는 연습), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/kitsuyui/items/e8ea67770c45011c7aca텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)