在Matplotlib中对面部颜色使用的颜色映射进行标准化

5 投票
1 回答
6163 浏览
提问于 2025-04-18 15:14

首先,我想在matplotlib中绘制球面谐波,像在mayavi中看到的那样:http://docs.enthought.com/mayavi/mayavi/auto/example_spherical_harmonics.html

这是我目前的进展:

import matplotlib.pyplot as plt
from matplotlib import cm, colors
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy import special

# Create a sphere
r = 3
pi = np.pi
cos = np.cos
sin = np.sin
phi, theta = np.mgrid[0:pi:50j, 0:2*pi:50j]


x = r * sin(phi) * cos(theta)
y = r * sin(phi) * sin(theta)
z = r * cos(phi)

colorfunction=special.sph_harm(3,4,theta,phi).real

norm=colors.Normalize(vmin = np.min(colorfunction), vmax = np.max(colorfunction), clip = False)
print colorfunction



fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z)
ax.plot_surface(
    x, y, z,  rstride=1, cstride=1, norm=norm, cmap=cm.jet, facecolors=cm.jet(colorfunction))
plt.show()

我的想法是使用colorfunction来根据球面谐波给球的表面上色。但是,这个函数的输出是一个包含负数的数组。我需要做的是“归一化”这个数组,以便它能与matplotlib的颜色映射正常工作。不过,不同于这里的回答,Color matplotlib plot_surface command with surface gradient,那个回答只是通过除以最大元素来简单地进行了一次粗略的归一化,但因为我有负数元素,这种方法就不适用了。我理想的做法是使用matplotlib.colors.Normalize,但它在面颜色上不起作用。

我知道归一化是应用在cmap=cm.jet上的,因为如果我完全去掉facecolors参数,我会得到一个新的颜色映射,它的行为符合我的norm函数。

这就是我问题的关键,我无法将我的归一化颜色映射应用到我的面颜色上。有什么想法吗?

这是上述代码当前生成的图形。可以看到,负值完全被截断,信息丢失,因为颜色映射的范围远大于实际值(所以所有东西看起来都是蓝色的)。

1 个回答

8

也许这个问题有点简单,但:

ax.plot_surface(x, y, z,  rstride=1, cstride=1, facecolors=cm.jet(norm(colorfunction)))

这段代码是用来标准化 colorfunction 的。其实,我们只需要通过以下方式来定义标准化函数:

norm = colors.Normalize()

这样就能自动把输入的值缩放到0到1之间。

结果是:

enter image description here

看起来 cmapnorm 这两个关键词是用在用Z数据给表面上色的情况,所以在这里用不上。

撰写回答