如何使用misc.imread将图像切分成红色、绿色和蓝色通道

11

我正在尝试将一张图片切割成RGB,并且在绘制这些图片时遇到了问题。我使用以下函数从特定文件夹获取所有图片:

def get_images(path, image_type):
image_list = []
for filename in glob.glob(path + '/*'+ image_type):
    im=misc.imread(filename, mode='RGB')
    image_list.append(im)
return image_list

这个函数创建了一个4维数组(30, 1536, 2048, 3),我相信第一个数代表图像数量,第二和第三个数是尺寸,第四个是RGB值。

在获取所有图像后,我将它们存储为numpy数组。

image_list = get_images('C:\HDR\images', '.jpg')
temp = np.array(image_list)

之后,我尝试使用简单的切片来从这些图片中获取特定颜色:

red_images = temp[:,:,:,0]
green_images = temp[:,:,:,1]
blue_images = temp[:,:,:,2]

当我打印出这些值时,一切似乎都很正常。

print(temp[11,125,311,:])
print(red_images[11,125,311])
print(green_images[11,125,311])
print(blue_images[11,125,311])

我得到了以下内容:

[105  97  76]
105
97
76

目前为止,一切似乎都很好,但当我尝试显示图像时问题就出现了。我使用了matplotlib.pyplot.imshow来显示它,然后我得到了这样的图像:

Image red channel

这是合理的,因为我选择了红色通道:

 plt.imshow(temp[29,:,:,0])

但是当我将它改为不同的颜色通道,就像这样:

plt.imshow(temp[29,:,:,2])

我获得的图像如下:

图像缺陷频道

我的问题很简单。这里发生了什么?

2个回答

16

我认为Matplotlib将每个通道(即强度)视为“热图”。

像这样向imshow函数传递一个颜色映射,告诉它如何给图像上色:

plt.imshow(image_slice, cmap=plt.cm.gray)

编辑:@mrGreenBrown回应您的评论,我假设您使用的函数是来自scipy,即scipy.misc.imread。该函数与PIL没有区别。请参见scipy.misc.imread文档。感谢@dai指出这一点。

任何图像的单个通道都只是强度。它没有颜色。对于用RGB颜色空间表示的图像,颜色是通过“混合”红色、绿色和蓝色的量(由各个通道的强度给出)获得的。单个通道不能表示颜色

发生了什么事情是Matplotlib默认显示强度作为热图,因此出现了“颜色”。

当您将单个通道保存为格式为JPEG的图像时,该函数仅将单个通道复制3次,以便R、G和B通道都包含相同的强度。这是典型行为,除非您将其保存在可以处理单通道灰度图像的格式(例如PGM)中。当您尝试可视化具有相同通道3次复制的图像时,因为红、绿和蓝的贡献在每个像素处相同,所以该图像看起来是灰色的。

plt.cm.gray传递给参数只是告诉imshow不要“彩色编码”强度。因此,亮度较高的像素(接近白色的像素)表示在这些位置上有“更多”的该“颜色”。

如果你想要颜色,你必须复制3通道的图像,并设置其他通道的值为0

例如,要将红色通道显示为“红色”:

# Assuming I is numpy array with 3 channels in RGB order
I_red = image.copy()  # Duplicate image
I_red[:, :, 1] = 0    # Zero out contribution from green
I_red[:, :, 2] = 0    # Zero out contribution from blue

这里有一个来自stackoverflow的相关问题


这并不是事实,红色只是因为我想要红色。而且我不想要灰色,我想要[n,0,0]来获取红色的值。对于蓝色也是一样的,可以在这里查看链接 - mrGreenBrown
我在一个问题中忘了提到我还使用了misc.imsave('trying.jpg',temp[29,:,:,0]),它将图像保存为灰度。 - mrGreenBrown
@mrGreenBrown 我已根据您的评论编辑了我的回答。 - lightalchemist
matplotlib.pyplot.imread和scipy.misc.imread不相同 - pyplot例程无法处理“alpha”层,至少我安装的版本(1.5.1)无法处理。 - Dai

9

所以,您想以不同的颜色显示图像的不同RGB通道...

import matplotlib.pyplot as plt
from matplotlib.cbook import get_sample_data

image = plt.imread(get_sample_data('grace_hopper.jpg'))

titles = ['Grace Hopper', 'Red channel', 'Green channel', 'Blue channel']
cmaps = [None, plt.cm.Reds_r, plt.cm.Greens_r, plt.cm.Blues_r]

fig, axes = plt.subplots(1, 4, figsize=(13,3))
objs = zip(axes, (image, *image.transpose(2,0,1)), titles, cmaps)

for ax, channel, title, cmap in objs:
    ax.imshow(channel, cmap=cmap)
    ax.set_title(title)
    ax.set_xticks(())
    ax.set_yticks(())

plt.savefig('RGB1.png')

enter image description here 请注意,当您在黑暗的桌子上使用红色笔时,如果您打开一盏红灯,您会感知到这支笔几乎是白色的...

另一个可能性是为每种颜色创建不同的图像,将其他颜色的像素值设置为零。从我们离开的地方开始,我们定义一个函数来提取通道到否则为黑色的图像中。

...
from numpy import array, zeros_like
def channel(image, color):
    if color not in (0, 1, 2): return image
    c = image[..., color]
    z = zeros_like(c)
    return array([(c, z, z), (z, c, z), (z, z, c)][color]).transpose(1,2,0)

最后使用它...

colors = range(-1, 3)
fig, axes = plt.subplots(1, 4, figsize=(13,3))
objs = zip(axes, titles, colors)
for ax, title, color in objs:
    ax.imshow(channel(image, color))
    ax.set_title(title)
    ax.set_xticks(())
    ax.set_yticks(())

plt.savefig('RGB2.png')

在此输入图片描述 我无法确定哪个版本更好,也许第一个版本看起来更加逼真(可能看起来不那么人工),但这是非常主观的...


“Reds”和“Reds_r”的区别是什么? 编辑:在此处找到 - https://matplotlib.org/stable/api/cm_api.html - Gajraj Singh Chouhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接