【问题标题】:How to slice an image into red, green and blue channels with misc.imread如何使用 misc.imread 将图像切成红色、绿色和蓝色通道
【发布时间】:2016-09-22 17:32:43
【问题描述】:

我正在尝试将图像切片为 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

这个函数创建 4d 数组 (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 来显示它,我得到的图像如下:

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

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

但是当我将其更改为不同的颜色通道时,如下所示:

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

我得到这样的图像:

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

【问题讨论】:

    标签: python image numpy matplotlib scipy


    【解决方案1】:

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

    像这样将颜色映射传递给 imshow 函数,告诉它您希望它如何为图像着色:

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

    编辑

    @mrGreenBrown 回应您的评论,我假设您使用的 misc.imread 函数来自 scipy,即 scipy.misc.imread。该功能与PIL 的功能没有什么不同。见scipy.misc.imread docs。感谢@dai 指出这一点。

    任何图像的单个通道只是强度。它没有颜色。对于以 RGB 颜色空间表示的图像,颜色是通过“混合”红色、绿色和蓝色的量(由相应通道的强度给出)获得的。 单一通道无法表达颜色

    默认情况下,Matplotlib 将强度显示为热图,因此是“颜色”。

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

    plt.cm.gray 传递给cmap 参数只是告诉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 的一个相关问题here

    【讨论】:

    • 不是这样的,红色只是因为我想要红色。并且不想要灰色,我想要 [n,0,0] 只获得红色的值。蓝色也一样link
    • 我忘了在一个问题中提到我也使用了 misc.imsave('trying.jpg',temp[29,:,:,0]) 并将图像保存为灰度
    • @mrGreenBrown 我已根据您的评论编辑了我的答案。
    • matplotlib.pyplot.imread 和 scipy.misc.imread 不相同 - pyplot 例程不能处理“alpha”层,至少不能处理我安装的版本(1.5.1)
    【解决方案2】:

    因此,您希望以不同的颜色显示图像的不同 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')
    

    请注意,当您在黑暗的桌子上有一支红色笔的黑暗房间时,如果您打开一盏红色的灯,您会感觉到笔几乎是白色的......

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

    ...
    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')
    

    我不知道哪个版本我更喜欢,也许第一个在我看来更现实(也许它看起来不那么人工)但它是相当主观的。 ..

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    • 1970-01-01
    • 1970-01-01
    • 2022-12-06
    • 1970-01-01
    • 2015-12-29
    • 2011-10-28
    相关资源
    最近更新 更多