图像直方图的高斯混合模型
Posted
技术标签:
【中文标题】图像直方图的高斯混合模型【英文标题】:Gaussian Mixture Models of an Image's Histogram 【发布时间】:2018-01-30 00:18:39 【问题描述】:我正在尝试根据像素强度值对 2D MR 图像的不同区域进行自动图像分割。第一步是在图像的直方图上实现高斯混合模型。
我需要将从score_samples
方法获得的结果高斯绘制到直方图上。我已尝试按照 (Understanding Gaussian Mixture Models) 答案中的代码进行操作。
但是,生成的高斯函数根本无法匹配直方图。如何让高斯与直方图匹配?
import numpy as np
import cv2
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture
# Read image
img = cv2.imread("test.jpg",0)
hist = cv2.calcHist([img],[0],None,[256],[0,256])
hist[0] = 0 # Removes background pixels
# Fit GMM
gmm = GaussianMixture(n_components = 3)
gmm = gmm.fit(hist)
# Evaluate GMM
gmm_x = np.linspace(0,255,256)
gmm_y = np.exp(gmm.score_samples(gmm_x.reshape(-1,1)))
# Plot histograms and gaussian curves
fig, ax = plt.subplots()
ax.hist(img.ravel(),255,[1,256])
ax.plot(gmm_x, gmm_y, color="crimson", lw=4, label="GMM")
ax.set_ylabel("Frequency")
ax.set_xlabel("Pixel Intensity")
plt.legend()
plt.show()
我还尝试用总和手动构造高斯。
import numpy as np
import cv2
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture
def gauss_function(x, amp, x0, sigma):
return amp * np.exp(-(x - x0) ** 2. / (2. * sigma ** 2.))
# Read image
img = cv2.imread("test.jpg",0)
hist = cv2.calcHist([img],[0],None,[256],[0,256])
hist[0] = 0 # Removes background pixels
# Fit GMM
gmm = GaussianMixture(n_components = 3)
gmm = gmm.fit(hist)
# Evaluate GMM
gmm_x = np.linspace(0,255,256)
gmm_y = np.exp(gmm.score_samples(gmm_x.reshape(-1,1)))
# Construct function manually as sum of gaussians
gmm_y_sum = np.full_like(gmm_x, fill_value=0, dtype=np.float32)
for m, c, w in zip(gmm.means_.ravel(), gmm.covariances_.ravel(), gmm.weights_.ravel()):
gauss = gauss_function(x=gmm_x, amp=1, x0=m, sigma=np.sqrt(c))
gmm_y_sum += gauss / np.trapz(gauss, gmm_x) * w
# Plot histograms and gaussian curves
fig, ax = plt.subplots()
ax.hist(img.ravel(),255,[1,256])
ax.plot(gmm_x, gmm_y, color="crimson", lw=4, label="GMM")
ax.plot(gmm_x, gmm_y_sum, color="black", lw=4, label="Gauss_sum", linestyle="dashed")
ax.set_ylabel("Frequency")
ax.set_xlabel("Pixel Intensity")
plt.legend()
plt.show()
与ax.hist(img.ravel(),255,[1,256], normed=True)
【问题讨论】:
抱歉,请问有什么问题? 如何让生成的高斯函数正确地拟合直方图?目前,高斯(“GMM”)看起来像一条接近 0 的水平线。 【参考方案1】:问题在于将直方图而不是像素强度数组传递给 GaussianMixture.fit gmm = gmm.fit(hist)
。
我还发现至少需要n_components = 6
才能在视觉上适合这个特定的直方图。
import numpy as np
import cv2
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture
# Read image
img = cv2.imread("test.jpg",0)
hist = cv2.calcHist([img],[0],None,[256],[0,256])
hist[0] = 0 # Removes background pixels
data = img.ravel()
data = data[data != 0]
data = data[data != 1] #Removes background pixels (intensities 0 and 1)
# Fit GMM
gmm = GaussianMixture(n_components = 6)
gmm = gmm.fit(X=np.expand_dims(data,1))
# Evaluate GMM
gmm_x = np.linspace(0,253,256)
gmm_y = np.exp(gmm.score_samples(gmm_x.reshape(-1,1)))
# Plot histograms and gaussian curves
fig, ax = plt.subplots()
ax.hist(img.ravel(),255,[2,256], normed=True)
ax.plot(gmm_x, gmm_y, color="crimson", lw=4, label="GMM")
ax.set_ylabel("Frequency")
ax.set_xlabel("Pixel Intensity")
plt.legend()
plt.show()
【讨论】:
以上是关于图像直方图的高斯混合模型的主要内容,如果未能解决你的问题,请参考以下文章