You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关运行截图1
参考PDF示例
预期实现效果
实际错误输出

核心错误点
  • 训练了两个完全独立的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 17:51:22