支配的な色の定義:Pythonとk-Meansメソッド



アソリウム



Habréでは、画像の主要な色を選択するためのアルゴリズムとスクリプトを使用したいくつかの記事が公開されました: 1、2、3 。 これらの記事へのコメントには、同様のプログラムおよびサービスへのリンクがあります。 しかし、完璧に制限はありません-そして、最適な方法を検討してみませんか? 私たちは、k-meansメソッド(k-means)を使用したクラスタリングの使用について話しています。



彼の前の多くの人と同様に、アメリカのWeb開発者Charles Leifer は、k-means法を使用して画像の色をクラスタリングしました。 データをクラスタリングする方法の考え方は、これらのクラスターの中心からのクラスターのポイントの二次偏差の合計を最小化することです。 最初の段階では、開始点(重心)がランダムに選択され、特定の中心への各要素の所属が計算されます。 次に、アルゴリズムの各反復で、アルゴリズムが収束するまで重心が再計算されます。



結果は次のようになります。 点はクラスターの色に応じて色付けされ、黒い点は重心を表します。







画像に適用されると、各ピクセルは3次元RGB空間に配置され、重心までの距離が計算されます。 最適化のために、 PILライブラリを使用して画像を200x200に縮小します。 また、RGB値の抽出にも使用されます。



コード

from collections import namedtuple from math import sqrt import random try: import Image except ImportError: from PIL import Image Point = namedtuple('Point', ('coords', 'n', 'ct')) Cluster = namedtuple('Cluster', ('points', 'center', 'n')) def get_points(img): points = [] w, h = img.size for count, color in img.getcolors(w * h): points.append(Point(color, 3, count)) return points rtoh = lambda rgb: '#%s' % ''.join(('%02x' % p for p in rgb)) def colorz(filename, n=3): img = Image.open(filename) img.thumbnail((200, 200)) w, h = img.size points = get_points(img) clusters = kmeans(points, n, 1) rgbs = [map(int, c.center.coords) for c in clusters] return map(rtoh, rgbs) def euclidean(p1, p2): return sqrt(sum([ (p1.coords[i] - p2.coords[i]) ** 2 for i in range(p1.n) ])) def calculate_center(points, n): vals = [0.0 for i in range(n)] plen = 0 for p in points: plen += p.ct for i in range(n): vals[i] += (p.coords[i] * p.ct) return Point([(v / plen) for v in vals], n, 1) def kmeans(points, k, min_diff): clusters = [Cluster([p], p, pn) for p in random.sample(points, k)] while 1: plists = [[] for i in range(k)] for p in points: smallest_distance = float('Inf') for i in range(k): distance = euclidean(p, clusters[i].center) if distance < smallest_distance: smallest_distance = distance idx = i plists[idx].append(p) diff = 0 for i in range(k): old = clusters[i] center = calculate_center(plists[i], old.n) new = Cluster(plists[i], center, old.n) clusters[i] = new diff = max(diff, euclidean(old.center, new.center)) if diff < min_diff: break return clusters
      
      





























支配的な色の識別は、常に使用できる非常に便利なものです。 これは、Webサイトまたは一部のUI要素のパレット選択です。 たとえば、Chromeブラウザ k-meansメソッドを使用して、ファビコンから主要な色を選択します。










All Articles