問題の説明
1. 与えられた画像に対して、Python を使用して K-means クラスタリング アルゴリズムを実装します。画像の色をクラスタリングするには、クラスタの数を指定する必要があります。 2. 画像の情報エントロピーを計算し、色を付けます
。 、最後に色をハフマンコーディングします。結果は 3 列のテーブルとして表されます。最初の列はカラー RGB (または BGR) コード、2 列目は色の出現確率、3 列目は対応するカラーコーディングのハフマン。
記事ディレクトリ
K 平均法
将n个样本依据最小化类内距离的准则分到K个聚类中
アルゴリズムの手順は次のとおりです。
1. まず最初に K 個の初期クラスター中心をランダムに選択します。
2. 各サンプルと k 個のクラスター中心の間の距離を計算し、最近接原理に従ってこれらの点を K 個のクラスターに分割します。
3. 平均を再計算します。各クラスターの値を計算し、
クラスタリング結果が変化しなくなるまで 4 で割ると、アルゴリズムは収束します。
K 平均法アルゴリズムは実装が比較的簡単で、スペースも計算量も少なく、限られたステップ数でクラスタリング出力を得るために収束できますが、最終結果は最初のクラスタリング平均の選択によって影響を受けます。異なる局所最小解では収束につながりますが、このアルゴリズムではクラスターの数を事前に設定する必要がありますが、実際の使用では判断が困難です。
情報エントロピー
情報エントロピー: 離散確率変数 X のエントロピー H(X) は次のとおりです。
画像エントロピーは特徴の統計形式であり、画像内の情報の平均量を反映します。画像の一次元エントロピーは、画像内のグレースケール分布の集合特徴に含まれる情報量を表し、各グレースケール値の数と発生確率は、画像のグレースケール値を数学的に数えることによって取得できます次に、グレースケール イメージは次のように定義されます。 単項グレー エントロピーは次のようになります。
画像の情報エントロピーは、情報エントロピーの計算式を用いて計算することができ、任意の離散情報源のエントロピー(平均自己情報量)を求めることができる。自己情報は確率変数であり、ソースによって送信されたメッセージに含まれる情報の量を指します。発信するメッセージも異なりますし、そこに含まれる情報量も異なります。メッセージの自己情報の量は、ソースに含まれる自己情報の平均量を表すことはできません。
情報エントロピーの意味:情報源全体の統計的性質から情報源の情報エントロピーHを考える。これは、ソースの全体的な特徴を平均的な意味で特徴づけます。特定の情報ソースに対して、情報エントロピーは 1 つだけです。統計的特性が異なるため、情報ソースが異なればエントロピーも異なります。
画像の 1 次元エントロピーは、画像のグレー分布の集合特性を表すことはできますが、画像のグレー分布の空間特性を反映することはできません。特徴量は、画像の 2 次元エントロピーを形成するために使用されます。画像。画像の近傍グレー値をグレー分布の空間特徴量として選択し、( i, j ) で示される画像のピクセル グレーとの特徴ペアを形成します。ここで、 i はピクセル (0) のグレー値を表します。 <= I <= 255)、j は近傍グレー レベルを表します (0 <= j <= 255)
ハフマン符号化
ハフマン符号化の具体的な方法: まず、発生確率に従って整列し、最小の 2 つの確率を加算し、新しい確率と残りの確率として再キューに入れます。次に、最小の 2 つの確率を追加して、次の確率が得られるまで再キューに入れます。最後は1になります。毎回足し算をするとき、足し算の2つの確率に「0」と「1」が割り当てられます。読み込むときは、この記号からスタートして最後の「1」まで進み、途中で出会った「0」と「1」を読みます。 1」を最下位ビットから最上位ビットまで順番に並べたものがシンボルのハフマン符号です。
平均符号長: L=∑p(si)*li (単位: コードシンボル/ソースシンボル) このうち、p(si) はソース si が q 個のソース内に出現する確率、li はソース si の確率 バイナリハフマンエンコーディング。
符号化効率:η=H(S)/L このうち、H(S)は情報エントロピー、Lは平均符号長である。
K 平均法アルゴリズムを使用して画像上の色をクラスター化します。
まず画像データを平坦化して img.shape[0]*img.shape[1] 行 3 列の行列を取得し、そこから K 個の中心点の色をランダムに選択し、各ピクセルへの最も近い距離を保存する bestAssignment 行列を作成します。中心点をループに入り、別の lastAssignment 行列を作成し、最後のループ後の結果である bestAssignment に初期化してから、各ピクセルと各中心点の間の距離を計算し、bestAssignment とlastAssignment 要素が等しい場合、つまり、前の 2 つのループの結果が変化していない場合にループを終了します。終了条件が満たされない場合は、まず中心点の値を更新して、再度ループに入ります。
# K-means算法实现
def k_means(X, K):
N, d = X.shape
# 没有这步不行,因为图像的数据类型为uint8
X = X.astype(np.int32)
temp = np.arange(N)
np.random.shuffle(temp)
C = X[temp[:K]]
bestAssignment = np.zeros((N, 1), dtype=np.int32)
while True:
lastAssignment = bestAssignment.copy()
#
mindist = np.inf * np.ones((N, 1))
for k in range(K):
for n in range(N):
dist = np.sum((X[n, :] - C[k, :]) ** 2)
if dist < mindist[n]:
mindist[n] = dist
bestAssignment[n] = k
if all(bestAssignment == lastAssignment):
break
for k in range(K):
index = np.where(bestAssignment == k)
C[k, :] = np.mean(X[index[0], :], axis=0)
# print(C)
return bestAssignment.squeeze(), C
結果を示す
Kを2、3、5、10とすると以下の結果が得られ、図によればKが大きいほどクラスタが増え、色が豊かになり、同時にプログラムの実行時間も短くなります。も大幅に増加します。
情報エントロピーとハフマン符号化の計算
上の図はクラスタリング結果のみを示していますが、情報エントロピーとハフマン符号化の計算には他の画像が使用されます。画像には多くの色が存在する可能性があるため、最初に上記の K 平均法アルゴリズムを使用して色をクラスター化し、ここでは 10 個のカテゴリを選択し、式を使用して画像の色の情報エントロピーを計算します。
def calculate_p(img):
result_dic = {
}
line = img.shape[0]
row = img.shape[1]
num = img.shape[0] * img.shape[1]
H = 0.0
# 得到每个颜色的数量
for i in range(line):
for j in range(row):
if str(img[i][j]) in result_dic:
result_dic[str(img[i][j])] += 1.0
else:
result_dic[str(img[i][j])] = 1.0
for key, value in result_dic.items():
result_dic[key] = value / num
value /= num
H += -value * (math.log2(value))
return result_dic, H
次に、各色のハフマン コードを計算します。具体的な方法は、発生確率に従って並べて、最も小さい 2 つの確率を加算し、新しい確率と残りの確率として再キューし、最も小さい 2 つの確率を加算します。最後に 1 になるまで再度キューに入れます。毎回足し算をするとき、足し算の2つの確率に「0」と「1」が割り当てられます。読み込むときは、この記号からスタートして最後の「1」まで進み、途中で出会った「0」と「1」を読みます。 1"を最下位ビットから最上位ビットの順に並べたもので、これがシンボルのハフマンコードです。パンダで処理した最終結果は、下の図の結果として表示できます。確率が高い色発生したコードの長さが短いほど。
次に、ハフマンによってエンコードされた画像の各ピクセルに必要な平均ビット数、圧縮率、およびファイルが占有するスペースを計算します。エンコード後の各ピクセルに必要なビット数を計算するときは、対応するエンコードを乗算するだけで済みます。各色のコード長、その色の出現確率を合計し、最後に四捨五入する必要があります。次に圧縮率を計算すると、各ピクセルが 24 から 3 に減らされるため、圧縮率は (24-3)/24 となり、結果は 87.5% になります。次に、元の画像とエンコードされたファイルのサイズを計算します。ここで、各ピクセルのサイズに画像のサイズを掛けます。結果は、エンコードされたファイルのサイズが元の画像よりもはるかに小さいことがわかります。
ハフマンコードのキー関数を計算する
# 输入节点构造哈夫曼树的函数
def createHuffmanTree(nodes):
queue = nodes[:]
while len(queue) > 1:
queue.sort(key=lambda item: item.freq)
node_left = queue.pop(0)
node_right = queue.pop(0)
node_father = Node(node_left.freq + node_right.freq)
node_father.left = node_left
node_father.right = node_right
node_left.father = node_father
node_right.father = node_father
queue.append(node_father)
queue[0].father = None
return queue[0]