使用自定义颜色绘制二维numpy数组

Bra*_*tra 3 python matplotlib

我有一个要绘制的二维numpy数组,因此我可以看到每个类别在网格上的位置。矩阵(mat)看起来像这样:

156 138 156
1300 137 156
138 138 1300
137 137 137
Run Code Online (Sandbox Code Playgroud)

我将其绘制如下:

 plt.imshow(mat, cmap='tab20', interpolation='none')
Run Code Online (Sandbox Code Playgroud)

但是,我想要自定义颜色。我有一个csv,其中id与矩阵中的值相对应:

id,R,G,B
156,200,200,200
138,170,255,245
137,208,130,40
1300,63,165,76
Run Code Online (Sandbox Code Playgroud)

有没有办法让矩阵中的值与csv文件中的R,G,B值相对应?

编辑:有人要求澄清,但整个答案已删除。

每行都有一个ID和3列,分别代表R,G和B值。因此,第一行的ID 156(域特定代码)具有R 200,G 200和B 200(为灰色)。

现在,我要绘制一个二维矩阵,并且在每个坐标值为156的坐标上,我都希望该像素为灰色。与ID 1300相同,其中颜色63、165和76代表我要在矩阵中使用的绿色。

gbo*_*ffi 5

它不是特别优雅,但很简单

In [72]: import numpy as np
In [73]: import matplotlib.pyplot as plt
In [74]: a = np.mat("156 138 156;1300 137 156;138 138 1300;137 137 137")
In [75]: d = {   156:  [200,  200,  200],
    ...:         138:  [170,  255,  245],
    ...:         137:  [208,  130,   40],
    ...:        1300:   [63,  165,   76]}
In [76]: image = np.array([[d[val] for val in row] for row in a], dtype='B')
In [77]: plt.imshow(image);
Run Code Online (Sandbox Code Playgroud)

情节在这里

关键是生成一个dtype包含正确(和解包)RGB 元组的正确数组('B' 编码短无符号整数)。


附录

在本附录中的原始问题之后交换意见之后,我将提出一个可能的解决方案来解决使用绘制相同类型数据plt.scatter()的问题(问题比我预期的要困难一些......)

import numpy as np
import matplotlib.pyplot as plt
from random import choices, randrange

######## THIS IS FOR IMSHOW ######################################
# the like of my previous answer
values = [20,150,900,1200]
rgb = lambda x=255:(randrange(x), randrange(x), randrange(x))
colord = {v:rgb() for v in values}

nr, nc = 3, 5
data = np.array(choices(values, k=nr*nc)).reshape((nr,nc))
c = np.array([[colord[v] for v in row] for row in data], dtype='B')

######## THIS IS FOR SCATTER ######################################
# This is for having the coordinates of the scattered points, note that rows' indices
# map to y coordinates and columns' map to x coordinates
y, x = np.array([(i,j) for i in range(nr) for j in range(nc)]).T
# Scatter does not expect a 3D array of uints but a 2D array of RGB floats
c1 = (c/255.0).reshape(nr*nc,3)

######## THIS IS FOR PLOTTING ######################################
# two subplots, plot immediately the imshow
f, (ax1, ax2) = plt.subplots(nrows=2)
ax1.imshow(c)
# to make a side by side comparison we set the boundaries and aspect
# of the second plot to mimic imshow's
ax2.set_ylim(ax1.get_ylim())
ax2.set_xlim(ax1.get_xlim())
ax2.set_aspect(1)
# and finally plot the data --- the size of dots `s=900` was by trial and error
ax2.scatter(x, y, c=c1, s=900)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


Imp*_*est 5

使用颜色图

原则上,具有RGB值的矩阵是某种颜色图。这是有道理的使用颜色表中matplotlib得到颜色的曲线。在这里,这使事情变得更加复杂的原因是,这些值之间的间距不大。因此,一个想法是将它们首先映射到从0开始的整数。然后创建由这些值一个颜色表,并使用其与BoundaryNorm允许具有等距离彩条。最后,可以将颜色条的刻度标签设置回初始值。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors

a =np.array([[156, 138, 156],
             [1300, 137, 156],
             [138, 138, 1300],
             [137, 137, 137]])

ca = np.array([[156,200,200,200],
               [138,170,255,245],
               [137,208,130,40],
               [1300,63,165,76]])

u, ind = np.unique(a, return_inverse=True)
b = ind.reshape((a.shape))

colors = ca[ca[:,0].argsort()][:,1:]/255.
cmap = matplotlib.colors.ListedColormap(colors)
norm = matplotlib.colors.BoundaryNorm(np.arange(len(ca)+1)-0.5, len(ca))

plt.imshow(b, cmap=cmap, norm=norm)

cb = plt.colorbar(ticks=np.arange(len(ca)))
cb.ax.set_yticklabels(np.unique(ca[:,0]))

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

绘制RGB阵列

您可以根据数据创建一个RGB数组,直接绘制为imshow。为此,您可以使用颜色数组中的颜色对原始数组进行索引,然后对所得数组进行整形,以使其具有正确的形状以使用imshow进行绘制。

import numpy as np
import matplotlib.pyplot as plt


a =np.array([[156, 138, 156],
             [1300, 137, 156],
             [138, 138, 1300],
             [137, 137, 137]])

ca = np.array([[156,200,200,200],
               [138,170,255,245],
               [137,208,130,40],
               [1300,63,165,76]])

u, ind = np.unique(a, return_inverse=True)
c = ca[ca[:,0].argsort()][:,1:]/255.

b =  np.moveaxis(c[ind][:,:,np.newaxis],1,2).reshape((a.shape[0],a.shape[1],3))
plt.imshow(b)
plt.show()
Run Code Online (Sandbox Code Playgroud)

结果与上面相同,但没有颜色条(因为此处没有要映射的数量)。