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

时间:2016-05-25 08:24:10

标签: python image numpy matplotlib scipy

我正在尝试将图像切割成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来显示它,我得到的图像如下:

Image red channel

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

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

但是当我把它改成不同的颜色通道时,就像这样:

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

我得到的图像是这样的:

Image bug channel

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

2 个答案:

答案 0 :(得分:12)

我认为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中的相关问题。

答案 1 :(得分:4)

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

enter image description here 我不知道哪个是我更喜欢的版本,也许第一个版本对我来说看起来更像逼真(也许它看起来不那么人为)但它是非常主观的。 ..