質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

3791閲覧

Pythonで色のクラスタリングをしたいです。

mi56

総合スコア14

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2017/06/01 10:03

編集2017/06/02 07:01

###前提・実現したいこと
Pythonでクラスタリングを勉強しています。
コードはhttps://github.com/joelgrus/data-science-from-scratch/blob/master/code/clustering.pyのを使用しています。
実現したいことは、画像の色にクラスタリングをかけて少ない色で画像を表示させたいです。
コード中ではK=5となっているので画像の色を5色で表現したいです。
現在は処理を行うと真っ黒の画像が表示させてしまいます。
mpimg.imreadが画像を配列にしているのはわかったのですがその後、どのような処理が行われているのかも教えていただきたいです。

###発生している問題・エラーメッセージ
画像を指定して実行したみたのですがoverflowとなってしまい結果が出力されません。
またどのように改良すれば良いのかわからず困っています。

/Users/Desktop/Python19-5.py:35: RuntimeWarning: overflow encountered in ubyte_scalars return sum(v_i * w_i for v_i, w_i in zip(v, w)) /Users/Desktop/Python19-5.py:18: RuntimeWarning: overflow encountered in ubyte_scalars return [v_i - w_i for v_i, w_i in zip(v,w)] /Users/Desktop/Python19-5.py:14: RuntimeWarning: overflow encountered in ubyte_scalars return [v_i + w_i for v_i, w_i in zip(v,w)]

###該当のソースコード

Python

1from __future__ import division 2import math, random 3from functools import reduce 4import re, math, random 5from collections import defaultdict, Counter 6import matplotlib.pyplot as plt 7import matplotlib.image as mpimg 8# 9# functions for working with vectors 10# 11 12def vector_add(v, w): 13 """adds two vectors componentwise""" 14 return [v_i + w_i for v_i, w_i in zip(v,w)] 15 16def vector_subtract(v, w): 17 """subtracts two vectors componentwise""" 18 return [v_i - w_i for v_i, w_i in zip(v,w)] 19 20def vector_sum(vectors): 21 return reduce(vector_add, vectors) 22 23def scalar_multiply(c, v): 24 return [c * v_i for v_i in v] 25 26# this isn't right if you don't from __future__ import division 27def vector_mean(vectors): 28 """compute the vector whose i-th element is the mean of the 29 i-th elements of the input vectors""" 30 n = len(vectors) 31 return scalar_multiply(1/n, vector_sum(vectors)) 32 33def dot(v, w): 34 """v_1 * w_1 + ... + v_n * w_n""" 35 return sum(v_i * w_i for v_i, w_i in zip(v, w)) 36 37def sum_of_squares(v): 38 """v_1 * v_1 + ... + v_n * v_n""" 39 return dot(v, v) 40 41def magnitude(v): 42 return math.sqrt(sum_of_squares(v)) 43 44def squared_distance(v, w): 45 return sum_of_squares(vector_subtract(v, w)) 46 47def distance(v, w): 48 return math.sqrt(squared_distance(v, w)) 49 50class KMeans: 51 def __init__(self, k): 52 self.k = k # CLUSTERの数 53 self.means = None # 各CLUSTERの重心 54 55 def classify(self, input): 56 # 入力されたノードのに一番近いCLUSTERの番号(0~k)を返す 57 return min(range(self.k), 58 key=lambda i: squared_distance(input, self.means[i])) 59 60 def train(self, inputs): 61 # 各CLUSTERの重心をランダムに選出 62 self.means = random.sample(inputs, self.k) 63 # 各ノードがどのCLUSTERに属しているかのリストを初期化 64 assignments = None 65 66 while True: 67 # 各ノードがどのCLUSTERに属しているかのリストを作成 68 new_assignments = list(map(self.classify, inputs)) 69 70 # 上記の所属CLUSTERリストが変更していなかったら終了 71 if assignments == new_assignments: 72 return 73 74 # 上記の所属CLUSTERリストを保持 75 assignments = new_assignments 76 77 # CLUSTER番号毎に重心を算出する処理を行う 78 for i in range(self.k): 79 # CLUSTER(i)に属しているノードリストを抽出 80 i_points = [p for p, a in zip(inputs, assignments) if a == i] 81 # 上のCLUSTER(i)のノードリストからCLUSTERの重心を算出 82 if i_points: 83 self.means[i] = vector_mean(i_points) 84 85 86# using clustering to recolor an image 87# 88 89def recolor_image(input_file, k=5): 90 91 path_to_png_file = r"画像のある場所" 92 img = mpimg.imread(path_to_png_file) 93 top_row = img[0] 94 top_left_pixel = top_row[0] 95 red, green, blue = top_left_pixel 96 pixels = [pixel for row in img for pixel in row] 97 clusterer = KMeans(k) 98 clusterer.train(pixels) # this might take a while 99 100 def recolor(pixel): 101 cluster = clusterer.classify(pixel) # index of the closest cluster 102 return clusterer.means[cluster] # mean of the closest cluster 103 104 new_img = [[recolor(pixel) for pixel in row] 105 for row in img] 106 107 plt.imshow(new_img) 108 plt.axis('off') 109 plt.show() 110 111recolor_image("IMG_2155.jpg")

###補足情報(言語/FW/ツール等のバージョンなど)
Python3.5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

coco_bauer

2017/06/02 07:26

「真っ黒の画像が表示」との事ですが、その画像で使われている色は何種類ありますか?
guest

回答1

0

ベストアンサー

3.x用のコードは以下code-python3になりますので、以下で試してみてはいかがでしょうか?
https://github.com/joelgrus/data-science-from-scratch/blob/master/code-python3/clustering.py

実行結果について

まず、Warningについては
[Runtime Warning overflow encountered in ubyte_scalars]((https://stackoverflow.com/questions/32927821/runtime-warning-overflow-encountered-in-ubyte-scalars)

You shouldn't worry about these, what they are essentially telling you is that the range for the uint_8 (unsigned integer) type defined by numpy and generally used for image files, has simply exceeded its acceptable range.

と回答あるので、実行結果には影響ないと思われます。

また、コードの実行結果についてですが
img = mpimg.imread(path_to_png_file)img = mpimg.imread(input_file)と修正し
lenaのカラー画像を64x64に縮小したpng画像で試したところ、以下のような結果を得られました。正常に動作しているようです。

イメージ説明

コード詳細は私には説明できませんが、画像サイズや色数などに制限はないでしょうか?

投稿2017/06/02 00:24

編集2017/06/02 09:05
can110

総合スコア38233

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mi56

2017/06/02 06:06

試してみましたが結果に変化はありませんでした。
can110

2017/06/02 09:05

実行結果を追記しました。コードについては書籍に説明など書かれていないでしょうか?確認ください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問