繁体   English   中英

Python 中的 2D 颜色图

[英]2D colormap in Python

我有一个 2d 向量(x,y) ,我需要找到一个 2D 颜色图,将这些坐标映射到一个平滑的颜色图。 颜色代码将仅取决于(x,y)值。 例如,

  • 中心周围的白色,
  • 更红,我们 go 到东北,
  • 更蓝我们go东南,
  • 随着我们向西北方向的 go 更绿,
  • 随着我们 go 向西南方向更绿。

换句话说:

green         red
       white
green         blue

我在matplotlib中没有找到任何符合我需要的东西。 我考虑过将坐标转换为幅度和相位,但问题仍然相同。 我还考虑为向量(x,y)添加一个虚拟维度,使其成为 3d 维度,然后对生成的 3D 向量进行归一化。 然后,将其提供给matplotlib图中的cmap参数。 但是,这会产生不平滑的 colors。 有什么线索吗?

颜色 map 的样本:

样本颜色图

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

所以要重申这个问题以确保我正确理解它:您想要两个不同的颜色图通道,而不是一个?

我在 matplotlib 中没有看到直接的方法,有两种选择:

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

对于“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)

哪个生产

2通道hack图

您可以对自定义 2D 转彩色 function 做任何您想做的事情,但这里有两个建议:

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 区域转换为所需的 colors,以及渐变/混合 ZC1C425268E68385D1AB5074C17A914Zoid 从一个区域到另一个区域的过渡,类似于从一个区域到另一个区域的44F14Z过渡。 在您想要的 map 上面,

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

实现此目的的一种方法可能是在图形程序(如 Gimp 或 Inkscape)中制作具有所需颜色的点网格,调整关键坐标和指定颜色三元组(RGB、HSL 或 HSV)直到您满意外观,然后使用scipy.interpolate.griddata 5为您的 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)

哪个生产

来自 griddata 的 2D 颜色函数图

Note: As long as I was writing my own colorspace conversion function, I could have converted directly from HSL to RGB 3 , but perhaps one of the commenters can explain why matplotlib.colors has hsv_to_rgb but not an hsl_to_rgb (running matplotlib v.3.3. 2)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM