简体   繁体   English

我怎样才能 plot 归一化 RGB map

[英]How can I plot a normalized RGB map

I have a numpy array where each element has 3 values (RGB) from 0 to 255, and it spans from [0, 0, 0] to [255, 255, 255] with 256 elements evenly spaced.我有一个 numpy 数组,其中每个元素具有从 0 到 255 的 3 个值 (RGB),它的范围从 [0, 0, 0] 到 [255, 255, 255],256 个元素均匀分布。 I want to plot it as a 16 by 16 grid but have no idea how to map the colors (as the numpy array) to the data to create the grid.我想将 plot 作为 16 x 16 网格,但不知道如何将 map colors(作为 numpy 数组)添加到数据中以创建网格。

import numpy as np

# create an evenly spaced RGB representation as integers
all_colors_int = np.linspace(0, (255 << 16) + (255 << 8) + 255, dtype=int)

# convert the evenly spaced integers to RGB representation
rgb_colors = np.array(tuple(((((255<<16)&k)>>16), ((255<<8)&k)>>8, (255)&k) for k in all_colors_int))

# data to fit the rgb_colors as colors into a plot as a 16 by 16 numpy array
data = np.array(tuple((k,p) for k in range(16) for p in range(16)))

So, how to map the rgb_colors as colors to the data data into a grid plot?那么,如何将 map 的rgb_colors为 colors 的data数据变成 plot 的网格呢?

There's quite a bit going on here, and I think it's valuable to talk about it.这里发生了很多事情,我认为谈论它很有价值。

linspace林空间

I suggest you read the linspace documentation.我建议您阅读 linspace 文档。 https://numpy.org/doc/stable/reference/generated/numpy.linspace.html https://numpy.org/doc/stable/reference/generated/numpy.linspace.html

If you want a 16x16 grid, then you should start by generating 16x16=256 values, however if you inspect the shape of the all_colors_int array, you'll notice that it's only generated 50 values, which is the default value of the linspace num argument.如果你想要一个 16x16 的网格,那么你应该从生成 16x16=256 个值开始,但是如果你检查all_colors_int数组的形状,你会注意到它只生成了 50 个值,这是 linspace num参数的默认值.

all_colors_int = np.linspace(0, (255 << 16) + (255 << 8) + 255, dtype=int)
print(all_colors_int.shape) # (50,)

Make sure you specify this third 'num' argument to generate the correct quantity of RGB pixels.确保指定第三个“num”参数以生成正确数量的 RGB 像素。

As a further side note, (255 << 16) + (255 << 8) + 255 is equivalent to (2^24)-1 .作为进一步的旁注, (255 << 16) + (255 << 8) + 255相当于(2^24)-1 The 2^N-1 formula is usually what's used to fill the first N bits of an integer with 1's. 2^N-1公式通常用于用 1 填充 integer 的前 N 位。

numpy is faster numpy 更快

On your next line, your for loop manually iterates over all of the elements in python.在下一行中,for 循环手动迭代 python 中的所有元素。

rgb_colors = np.array(tuple(((((255<<16)&k)>>16), ((255<<8)&k)>>8, (255)&k) for k in all_colors_int))

While this might work, this isn't considered the correct way to use numpy arrays.虽然这可能有效,但这并不是使用 numpy arrays 的正确方法。

You can directly perform bitwise operations to the entire numpy array without the python for loop.无需python for循环,可以直接对整个numpy数组进行按位运算。 For example, to extract bits [16, 24) (which is usually the red channel in an RGB integer):例如,要提取位 [16, 24)(通常是 RGB 整数中的红色通道):

# Shift over so the 16th bit is now bit 0, then select only the first 8 bits.
RedChannel = (all_colors_int >> 16) & 255

Building the grid构建网格

There are many ways to do this in numpy, however I would suggest this approach.在 numpy 中有很多方法可以做到这一点,但是我建议使用这种方法。

Images are usually represented with a 3-dimensional numpy array, usually of the form图像通常用 3 维 numpy 数组表示,通常是以下形式

(HEIGHT, WIDTH, CHANNELS)

First, reshape your numpy int array into the 16x16 grid that you want.首先,将 numpy int 数组reshape为您想要的 16x16 网格。

reshaped = all_colors_int.reshape((16, 16))

Again, the numpy documentation is really great, give it a read:同样,numpy 文档真的很棒,请阅读:

https://numpy.org/doc/stable/reference/generated/numpy.reshape.html https://numpy.org/doc/stable/reference/generated/numpy.reshape.html

Now, extract the red, green and blue channels, as described above, from this reshaped array.现在,如上所述,从此重新整形的数组中提取红色、绿色和蓝色通道。 If you operate directly on the numpy array, you won't need a nested for-loop to iterate over the 16x16 grid, numpy will handle this for you.如果您直接对 numpy 数组进行操作,则不需要嵌套的 for 循环来遍历 16x16 网格,numpy 会为您处理。

RedChannel = (reshaped >> 16) & 255
GreenChannel = ... # TODO
BlueChannel = ... # TODO

And then finally, we can convert our 3, 16x16 grids, into a 16x16x3 grid, using the numpy stack function最后,我们可以使用 numpy stack function 将 3 个 16x16 网格转换为 16x16x3 网格

https://numpy.org/doc/stable/reference/generated/numpy.stack.html https://numpy.org/doc/stable/reference/generated/numpy.stack.html

grid_rgb = np.stack((
    RedChannel,
    GreenChannel,
    BlueChannel
), axis=2).astype(np.uint8)

Notice two things here这里注意两件事

  1. When we 'stack' arrays, we create a new dimension.当我们“堆叠”arrays 时,我们创建了一个新维度。 The axis=2 argument tells numpy to add this new dimension at index 2 (eg the third axis). axis=2参数告诉 numpy 在索引 2 处添加这个新维度(例如第三个轴)。 Without this, the shape of our grid would be (3, 16, 16) instead of (16, 16, 3)如果没有这个,我们网格的形状将是(3, 16, 16)而不是(16, 16, 3)
  2. The .astype(np.uint8) casts all of the values in this numpy array into a uint8 data type. .astype(np.uint8)将此 numpy 数组中的所有值转换为 uint8 数据类型。 This is so the grid is compatible with other image manipulation libraries, such as openCV, and PIL.这是为了使网格与其他图像处理库兼容,例如 openCV 和 PIL。

Show the image显示图像

We can use PIL for this.我们可以为此使用 PIL。 If you want to use OpenCV, then remember that OpenCV interprets images as BGR not RGB and so your channels will be inverted.如果您想使用 OpenCV,请记住 OpenCV 将图像解释为BGR而不是RGB ,因此您的通道将被反转。

# Show Image
from PIL import Image
Image.fromarray(grid_rgb).show()

If you've done everything right, you'll see an image... And it's all gray.如果一切都做对了,您会看到一个图像……而且全是灰色的。

Why is it gray?为什么是灰色的?

There are over 16 million possible colours.有超过 1600 万种可能的颜色。 Selecting only 256 of them just so happens to select only pixels with the same R, G and B values which results in an image without any color.仅选择其中的 256 个正好发生在 select 具有相同 R、G 和 B 值的像素,这导致图像没有任何颜色。

If you want to see some colours, you'll need to either show a bigger image (eg 256x256), or alternatively, you can use a dimension that's not a power of two.如果您想看到某些颜色,则需要显示更大的图像(例如 256x256),或者您可以使用不是2 的幂的尺寸。 For example, try a prime number, as this will add a small amount of pseudo-randomness to the RGB selection, eg try 17.例如,尝试素数,因为这会给 RGB 选择添加少量伪随机性,例如尝试 17。

Best of luck.祝你好运。

Based solely on the title 'How to plot a normalized RGB map' rather than the approach you've provided, it appears that you'd like to plot a colour spectrum in RGB.仅基于标题“如何 plot 标准化 RGB 映射”而不是您提供的方法,您似乎想要 plot RGB 色谱。

The following approach can be taken to manually construct this.可以采取以下方法来手动构建它。

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

h = np.repeat(np.arange(0, 180), 180).reshape(180, 180)
s = np.ones((180, 180))*255
v = np.ones((180, 180))*255

hsv = np.stack((h, s, v), axis=2).astype('uint8')
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)

plt.imshow(rgb)

在此处输入图像描述

Explanation:解释:

It's generally easier to construct (and decompose) a colour palette using the HSV (hue, saturation, value) colour scale;使用 HSV(色调、饱和度、明度)色标构建(和分解)调色板通常更容易; where hue is the colour itself, saturation can be thought of as the intensity and value as the distance from black.其中色调是颜色本身,饱和度可以被认为是强度和值与黑色的距离。 Therefore, there's really only one value to worry about, hue .因此,实际上只有一个值需要担心,即hue Saturation and value can be set to 255, for 'full intensity'.饱和度和值可以设置为 255,用于“全强度”。

cv2 is used here to simply convert the constructed HSV colourscale to RGB and matplotlib is used to plot the image.这里使用cv2将构建的 HSV 色标简单地转换为 RGB, matplotlib用于将图像转换为 plot。 (I didn't use cv2 for plotting as it doesn't play nicely with Jupyter.) (我没有使用cv2进行绘图,因为它不能很好地与 Jupyter 配合使用。)

The actual spectrum values are constructed in numpy .实际频谱值构建在numpy中。

Breakdown:分解:

Create the colour spectrum of hue and plug 255 in for the saturation and value.创建色调的色谱并插入 255 作为饱和度和值。 Why is 180 used?为什么使用180?

h = np.repeat(np.arange(0, 180), 180).reshape(180, 180)
s = np.ones((180, 180))*255
v = np.ones((180, 180))*255

Stack the three channels H+S+V into a 3-dimensional array, convert the array values to unsigned 8-bit integers, and have cv2 convert from HSV to RGB for us, to be lazy and save us working out the math.将三个通道 H+S+V 堆叠成一个 3 维数组,将数组值转换为无符号 8 位整数,并让cv2为我们从 HSV 转换为 RGB,为了偷懒,省去了我们计算数学的时间。

hsv = np.stack((h, s, v), axis=2).astype('uint8')
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)

Plot the RGB image. Plot RGB 图像。

plt.imshow(rgb)

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

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