matplotlib Python中的2D色彩Map

nvbavucw  于 2023-08-06  发布在  Python
关注(0)|答案(3)|浏览(128)

我有一个2D向量(x,y),我需要找到一个2D色彩Map表,将这些坐标Map到一个平滑的色彩Map表。颜色代码将仅取决于(x,y)值。比如说

  • 白色围绕中心
  • 越往东北越红
  • 越往东南方向越蓝
  • 我们向西北方向走的时候会有更多的绿色
  • 越往西南方向绿色

换句话说:

green         red
       white
green         blue

字符串
我在matplotlib中没有找到任何符合我需要的东西。我想把坐标转换成幅度和相位,但问题仍然是一样的。我还考虑了在向量(x,y)中添加一个虚拟维度,使其成为3d维度,然后对生成的3D向量进行归一化。然后,将其馈送到matplotlib图中的cmap参数。然而,这将产生不平滑的颜色。有什么线索吗
颜色Map的示例:


的数据

xoshrz7s

xoshrz7s1#

为了确保我正确理解这个问题,我重新陈述一下:你想有两个不同的色彩Map表通道,而不是一个?
我在matplotlib中看不到直接的方法,有两种选择:

  • 使用不同的颜色通道/色彩Map表/透明度多次绘制相同的数据
  • 定义您自己的自定义2D到RGB颜色Map,并将RGB三元组数组传递给绘图函数

对于“hack-y”多重绘图解决方案:

import numpy as np
from matplotlib.colors import hsv_to_rgb, rgb_to_hsv
import matplotlib.pyplot as plt

xydata = np.array([(x,y) for x in np.arange(-1.,1.1,0.1) for y in np.arange(-1.,1.1,0.1)], dtype=float)
x_colorfunc = lambda xy: xy.T[0].max() - np.abs(xy.T[0])
y_colorfunc = lambda xy: np.abs(xy.T[1])
y_colormap_coord = y_colorfunc(xydata)
x_colormap_coord = x_colorfunc(xydata)
x_colormap = "plasma"
y_colormap = "Greys"

plt.figure("2d_colormap_hack")
plt.scatter(xydata.T[0], xydata.T[1], c=x_colormap_coord, cmap= x_colormap, alpha=1.0)
plt.scatter(xydata.T[0], xydata.T[1], c=y_colormap_coord, cmap= y_colormap, alpha=0.6)

字符串
它产生
x1c 0d1x的数据
你可以对自定义2D到颜色函数做任何你想做的事情,但这里有两个建议:

def xy_color_func(xy):
    # using np.divide handles `RuntimeWarning: divide by zero encountered in true_divide`
    xy_ratio = np.divide(xy.T[1], xy.T[0], out=np.ones_like(xy.T[0]), where=(xy.T[0]!=0) )
    xy_angle_frac = (4/np.pi)*np.abs(np.arctan(xy_ratio))
    xy_mag = np.linalg.norm(xy, axis=-1)
    hsl_hue = 1 - 1./6*xy_angle_frac   # hue goes from red to blue 
    hsl_sat = 1 - xy_mag/xy_mag.max()  # 0 is full color saturation, 1 is equal RGB values
    hsl_luminance = 0.75 - 0.25*(xy_mag/xy_mag.max())  # brighter at the "target" point of (0, 0)
    hsv = hsl_to_hsv(hsl_hue, hsl_sat, hsl_luminance)
    rgb = hsv_to_rgb(hsv)
    return rgb

def hsl_to_hsv(hsl_hue, hsl_sat, hsl_luminance):
    hsv_hue = hsl_hue
    hsv_v = hsl_luminance + hsl_sat*np.minimum(hsl_luminance, 1-hsl_luminance)
    hsv_sat = 2*(1-np.divide(hsl_luminance, hsv_v, out=np.ones_like(hsv_v), where=(hsv_v!=0) ))
    hsv = np.vstack((hsv_hue, hsv_sat, hsv_v)).T
    return hsv

xy_colors = xy_color_func(xydata)
plt.figure("2d_colormap_func")
plt.scatter(xydata.T[0], xydata.T[1], c=xy_colors)


它产生



看起来你想要的颜色Map需要更多的规则来将XY区域转换为所需的颜色,以及渐变/混合功能来从一个区域过渡到另一个区域,类似于4中所示的梯形混合。在上面的Map中,

  • “绿色”是x<=0
  • “红色”是x >0 & y < 0
  • “蓝色”是x > 0 & y >= 0,并且
  • white1-magnitude(x,y)

实现此目的的一种方法可能是在图形程序(如Gimp或Inkscape)中使用所需颜色制作点网格,调整关键坐标和指定的颜色三元组(RGB,HSL或HSV),直到您对外观满意,然后使用scipy.interpolate.griddata5为XY数据插入3个颜色通道中的每一个,如下所示:

key_xy_points = np.array([[0,0],[1,0],[1,1],[1,-1],[-1,1], [-1,-1]],dtype=float)
key_xy_RGBs = np.array([[1,1,1], [1,1,1], [0,0,1], [1,0,0], [0,1,0], [0,1,0]],dtype=float)

from scipy.interpolate import griddata

reds = griddata(key_xy_points, key_xy_RGBs.T[0], xydata)
greens = griddata(key_xy_points, key_xy_RGBs.T[1], xydata)
blues = griddata(key_xy_points, key_xy_RGBs.T[2], xydata)

xy_colors_griddata = np.vstack((reds, greens, blues)).T
plt.figure("2d_colormap_griddata")
plt.scatter(xydata.T[0], xydata.T[1], c=xy_colors_griddata)


它产生



注:只要我在写自己的色彩空间转换函数,我就可以直接从HSL转换到RGB 3,但也许有一位评论者可以解释为什么matplotlib.colors有hsv_to_rgb而不是hsl_to_rgb(运行matplotlib v.3.3.2)。

fcipmucu

fcipmucu2#

我会使用像hsl或hsv这样的颜色空间,固定亮度值(l或v),并使用x作为h,y作为s来表示所有的颜色。您需要规范化x和y的值,使其与颜色空间组件兼容。

nbewdwxp

nbewdwxp3#

要做到这一点的方法是将色彩Map表格式化为具有RGB值的3D数组,即形状为(256,256,3)的阵列cmap。使用颜色值填充此数组以组成颜色Map表。然后将两个变量(x,y)调整到0→255的范围,并将它们转换为dtype = int,(x_int, y_int)
然后根据(x_int, y_int)cmap进行采样

image = cmap[y_int,x_int]

字符串
然后,您可以可视化色彩Map表和图像:

fig, axes = plt.subplots(1,2)
axes[0].imshow(image)
axes[0].imshow(cmap)


如果你不想手动做这个,你可以在https://colorstamps.readthedocs.io/en/latest/(pip install colorstamps) checkout 软件包

import matplotlib.pyplot as plt
import colorstamps
# img = (100,200,2) example data
img = colorstamps.helpers.get_random_data()
# map data to colormap
rgb, stamp = colorstamps.apply_stamp(img[:,:,0], img[:,:,1], 'peak',
                                   vmin_0 = -1.2, vmax_0 = 1.2,
                                   vmin_1 = -1, vmax_1 = 1,
                                 )
fig, axes = plt.subplots(1,2,figsize=(10,3), dpi = 100)
axes[0].imshow(rgb)
# show colormap as overlay
overlaid_ax = stamp.overlay_ax(axes[0],
                lower_left_corner = [0.7,0.85], width = 0.2)
overlaid_ax.set_ylabel(r'$\phi$')
overlaid_ax.set_xlabel(r'$\omega$')
# also show colormap as in separate ax to illustrate functionality
stamp.show_in_ax(axes[1])
axes[1].set_ylabel(r'$\phi$')
axes[1].set_xlabel(r'$\omega$')


的数据
这是我构建的一个包,因为我有与提问者相同的需求。

相关问题