1. ホーム
  2. python

[解決済み] Python - 画像中の支配色/最大公約数的な色を見つける

2023-04-20 09:13:52

質問

pythonを使用して、画像の中で最も支配的な色/トーンを見つける方法を探しています。平均的な色合いまたはRGBのうち最も一般的なもののいずれかが行われます。私はPython Imagingライブラリを見ましたが、私が彼らのマニュアルで探していたものに関連するものを見つけることができず、またVTKでも簡単に見つけることができました。

しかし、私が必要とするものを行う PHP スクリプトを見つけました。 ここで (ダウンロードにはログインが必要です)。このスクリプトは、画像を150*150にリサイズして、支配的な色を引き出しているようです。しかし、その後、私はかなり失われています。私は、画像を小さなサイズにリサイズして、1ピクセルおきに画像をチェックするようなものを書くことを考えましたが、これは非常に非効率的であると想像します (このアイデアを C python モジュールとして実装することはアイデアかもしれませんが)。

しかし、すべての後に、私はまだ行き詰っています。そこで、私は SO の皆さんに尋ねます。画像内の支配的な色を見つけるための簡単で効率的な方法はないでしょうか。

どのように解決するのですか?

以下は ピロー Scipyのクラスタパッケージ .

簡単のために、ファイル名を "image.jpg" とハードコードしています。 画像のリサイズは速度のためです。もしあなたが待ち時間を気にしないのであれば、リサイズの呼び出しをコメントアウトしてください。 この 青トウガラシのサンプル画像 を実行すると、通常、支配的な色は#d8c865であると言います。これは2つのピーマンの左下にある明るい黄色がかった領域にほぼ対応します。 私が「通常」と言ったのは、この画像が クラスタリングアルゴリズム を使用しているため、ある程度のランダム性があります。 これを変更する方法はいろいろありますが、あなたの目的にはよく合っているかもしれません。 (決定論的な結果が必要な場合は、kmeans2()の変種のオプションをチェックしてください)。

from __future__ import print_function
import binascii
import struct
from PIL import Image
import numpy as np
import scipy
import scipy.misc
import scipy.cluster

NUM_CLUSTERS = 5

print('reading image')
im = Image.open('image.jpg')
im = im.resize((150, 150))      # optional, to reduce time
ar = np.asarray(im)
shape = ar.shape
ar = ar.reshape(scipy.product(shape[:2]), shape[2]).astype(float)

print('finding clusters')
codes, dist = scipy.cluster.vq.kmeans(ar, NUM_CLUSTERS)
print('cluster centres:\n', codes)

vecs, dist = scipy.cluster.vq.vq(ar, codes)         # assign codes
counts, bins = scipy.histogram(vecs, len(codes))    # count occurrences

index_max = scipy.argmax(counts)                    # find most frequent
peak = codes[index_max]
colour = binascii.hexlify(bytearray(int(c) for c in peak)).decode('ascii')
print('most frequent is %s (#%s)' % (peak, colour))

注:クラスタの数を5から10、15と増やしていくと、緑っぽい、青っぽいという結果が頻繁に出ました。 入力画像からすると、それらも妥当な結果なのですが...。その画像でどの色が本当に優勢なのか私にも分からないので、アルゴリズムのせいにはしません!

また、小さなボーナスとして、最も頻繁に使用されるN色のみを含む縮小された画像を保存します。

# bonus: save image using only the N most common colours
import imageio
c = ar.copy()
for i, code in enumerate(codes):
    c[scipy.r_[scipy.where(vecs==i)],:] = code
imageio.imwrite('clusters.png', c.reshape(*shape).astype(np.uint8))
print('saved clustered image')