Python实现图像GMM聚类时直方图各簇分布绘制异常求助




核心错误点
- 训练了两个完全独立的GMM模型:
gmm_model是用三通道彩色像素(shape为[像素总数, 3])训练的分割模型,gmm是用展平后的单通道亮度值训练的直方图拟合模型,二者参数不通用。绘制单个聚类簇的高斯分布时,错误调用了三通道分割模型的均值、权重、协方差参数,数值和维度都不匹配单通道直方图的场景。 - 绘图逻辑顺序错误:调用
plt.show()渲染完直方图和整体GMM曲线后,才开始循环绘制单个高斯分量,此时会创建全新的空白画布,分量填充效果根本不会和直方图显示在同一张图中。 - 存在语法疏漏:
cv2.imwrite("test_segmented.tif")缺少必填的待保存图像参数,运行时会直接抛出参数错误,无法正常输出分割结果。 - 参数索引逻辑错误:三通道GMM设置
covariance_type='full'时,协方差矩阵维度为(聚类数, 3, 3),直接取[m, 0]拿到的是第一个颜色通道的协方差子矩阵,不是单变量高斯分布的方差,计算出的概率密度结果完全错误。
修正后代码
import matplotlib.pyplot as plt import numpy as np import cv2 from scipy import stats from sklearn.mixture import GaussianMixture as GMM img = cv2.imread("test.tif") # 将MxNx3的图像转换为Kx3的像素数组,K=MxN img2 = img.reshape((-1,3)) k = 7 # 训练三通道GMM用于图像分割 gmm_model = GMM(n_components=k, covariance_type='full', random_state=42).fit(img2) gmm_labels = gmm_model.predict(img2) # 还原分割结果到原始图像尺寸并保存 original_shape = img.shape segmented = gmm_labels.reshape(original_shape[0], original_shape[1]) # 补全imwrite缺失的图像参数 cv2.imwrite("test_segmented.tif", segmented) # 预处理单通道像素值,移除背景 data = img2.ravel() data = data[data != 0] data = data[data != 1] # 训练单通道GMM用于直方图拟合 gmm = GMM(n_components=k, covariance_type='full', random_state=42) gmm = gmm.fit(X=np.expand_dims(data,1)) gmm_x = np.linspace(0,255,256) gmm_y = np.exp(gmm.score_samples(gmm_x.reshape(-1,1))) # 绘制直方图和高斯曲线 fig, ax = plt.subplots() ax.hist(img2.ravel(), 255, [2,256], density=True, stacked=True, alpha=0.5) ax.plot(gmm_x, gmm_y, color="crimson", lw=2, label="整体GMM拟合") # 循环绘制每个聚类对应的独立高斯分量,移到show之前同画布绘制 color_list = ['#ff9999','#66b3ff','#99ff99','#ffcc99','#c2c2f0','#ffb3e6','#c4e17f'] for m in range(gmm.n_components): # 调用单通道拟合GMM的参数计算分量PDF mean = gmm.means_[m, 0] var = gmm.covariances_[m, 0, 0] weight = gmm.weights_[m] pdf = weight * stats.norm(mean, np.sqrt(var)).pdf(gmm_x) ax.fill_between(gmm_x, pdf, facecolor=color_list[m%len(color_list)], alpha=0.4, edgecolor='none', label=f'聚类{m}高斯分量') ax.set_ylabel("频率") ax.set_xlabel("像素亮度值") plt.legend() plt.grid(False) plt.xlim([0, 256]) plt.show()
修正说明
- 统一使用单通道训练得到的
gmm模型参数计算每个聚类的高斯分布概率密度,参数索引匹配单维度输入的协方差矩阵结构 - 将分量绘制逻辑移动到
plt.show()之前,绑定到同一个坐标轴对象渲染,保证所有元素显示在同一张图中 - 补全了图像保存的缺失参数
- 给单个高斯分量添加透明度和区分色,避免遮挡底层直方图,同时增加图例方便识别
内容的提问来源于stack exchange,提问作者Mohamed Hassan
相关产品推荐
相关产品推荐

