如何在matplotlib 3D散点图上表示密度信息

4
我正在尝试将图像的r、g、b通道绘制为3D散点图。
当我有一张黑白图像时,这个方法运作良好,因为我可以得到一个只有两个不同聚类的散点图。
然而,对于彩色图像,散点图在视觉上并没有太多意义,因为图像中的许多点都对应着颜色空间中的r、g、b值。
所以最终我得到了如下所示的图像。

3-D scatter plot without density information

我的目标是以某种方式呈现密度信息。例如,如果与(255,255,255)对应的点数为1000,而与(0,0,0)对应的点数仅为500,则我希望(255,255,255)为深红色,而(0,0,0)为黄色/橙色。

我该如何在matplotlib中实现这一点呢?我可以接受某种气泡效果,其中(255,255,255)表示为比(0,0,0)更大的气泡,但我觉得将密度信息编码为颜色信息会更具视觉吸引力。

1个回答

4
这里尝试使用高斯KDE(核密度估计)。但结果远非完美,很大程度上取决于估算参数(bw_method)。也许有一种更简单的方法,可能使用np.unique来获取每个唯一颜色的频率。
想法是将颜色密度分布估计为多元高斯混合,并将其用作散点图的彩色地图。
对于任何严肃的工作,速度有点慢,但我认为它在足够小的图像上会产生不错的效果。也许某些基于FFT +卷积的估算方法可以更快。
让我们看一些代码。没什么花哨:它将图像数据扁平化并重塑成gaussian_kde喜欢的形式,并返回RGB和密度组件。您可以使用bw_method进行调整,查看结果如何变化,值越大,您将获得更平滑的密度。
from scipy.stats import gaussian_kde

def img_to_rgbk(img, bw=0.1):
    rgb = img.reshape(-1, 3).T
    k = gaussian_kde(rgb, bw_method=bw)(rgb)
    r, g, b = rgb

    return r, g, b, k

这是一个玩具图像的结果。
img = chelsea()[100:200, 100:200]

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

r, g, b, k = img_to_rgbk(img, bw=0.5)
ax.scatter(r, g, b, c=k, alpha=0.2)

注意,c=k用于将地图标记颜色设置为密度信息,alpha需要使云朵透明一些。

切尔西

切尔西猫的颜色密度

随机颜色

随机均匀颜色密度

梯度

请注意,选择错误的带宽可能会产生误导性。足够小的bw_method应该在每列中显示实质上相同的颜色,沿着行重复。因此,每个点的颜色都应该相同(使用正确的带宽将实现此目的)。 光谱颜色图密度

梯度+噪声

这里使用更好的带宽和一些噪声来扩散颜色。请注意,白色区域周围的密度更大,在无噪声情况下,不连续性在该区域变成密度最大值。 光谱+噪声=有趣


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接