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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37431599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 19:23:33  来源:igfitidea点击:

How to slice an image into red, green and blue channels with misc.imread

pythonimagenumpymatplotlibscipy

提问by mrGreenBrown

I am trying to slice an image into RGB and I have a problem with plotting these images. I obtain all images from a certain folder with this function:

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

This function creates 4d array (30, 1536, 2048, 3) and I am quite sure that the first value represents number of images, second and third are dimensions and third are RGB values.

此函数创建 4d 数组 (30, 1536, 2048, 3),我很确定第一个值表示图像数量,第二个和第三个是维度,第三个是 RGB 值。

After I obtained all the images, I stored them as a numpy array

获得所有图像后,我将它们存储为一个 numpy 数组

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

After that I tried to use simple slicing on order to take specific colors from these images:

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

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

When I print out the values, everything seems to be fine.

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

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

And I get the following:

我得到以下信息:

[105  97  76]
105
97
76

So far, everything seems to be fine, but the problem arises when I try to display the image. I used matplotlib.pyplot.imshowto display it and I get the image like:

到目前为止,一切似乎都很好,但是当我尝试显示图像时出现问题。我曾经matplotlib.pyplot.imshow显示它,我得到的图像如下:

Image red channel

图像红色通道

Which is reasonable, because I choose red:

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

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

But when I change it to different color channel, like this:

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

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

I get the image like this:

我得到这样的图像:

Image bug channel

图片错误频道

My question is simple. What is happening here?

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

回答by lightalchemist

I think matplotlib is just treating each channel (i.e., intensities) as a "heat map".

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

Pass a color map to the imshow function like so to tell it how you want it to color your image:

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

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

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

Edit

编辑

@mrGreenBrown in response to your comment, I'm assuming that the misc.imreadfunction you used is from scipy, i.e., scipy.misc.imread. That function is no different from that of PIL. See scipy.misc.imread docs. Thanks to @dai for pointing this out.

@mrGreenBrown 针对您的评论,我假设misc.imread您使用的函数来自 scipy,即scipy.misc.imread. 该功能与PIL. 请参阅scipy.misc.imread 文档。感谢@dai 指出这一点。

A single channel of any image is just intensities. It does not have color. For an image expressed in RGB color space, color is obtained by "mixing" amounts (given by the respective channel's intensities) of red, green, and blue. A single channel cannot express color.

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

What happened was Matplotlib by default displays the intensities as a heatmap, hence the "color".

发生的事情是 Matplotlib 默认将强度显示为热图,因此是“颜色”。

When you save a single channel as an image in a format say JPEG, the function merely duplicates the single channel 3 times so that the R, G, and B channels all contain the same intensities. This is the typical behavior unless you save it in a format such as PGM which can handle single channel grayscale image. When you try to visualize this image which has the same channel duplicated 3 times, because the contributions from red, green, and blue are the same at each pixel, the image appears as grey.

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

Passing plt.cm.grayto the cmapargument simply tells imshownot to "color-code" the intensities. So, brighter pixels (pixels approaching white) means there is "more" of that "color" at those locations.

传递plt.cm.graycmap参数只是告诉imshow不要对强度进行“颜色编码”。因此,更亮的像素(接近白色的像素)意味着在这些位置有“更多”的“颜色”。

If you want color, you have to make copies of the 3 channel image and set the other channels to have values of 0.

如果您想要颜色,您必须制作 3 通道图像的副本并将其他通道设置为0.

For e.g., to display a red channel as "red":

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

# 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

A related question from stackoverflow here.

来自此处的stackoverflow 的相关问题。

回答by gboffi

So, you want to show in different colors the different RGB channels of an image...

所以,你想用不同的颜色显示图像的不同 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 hereNote that when you have a dark room with a red pen on a dark table, if you turn on a red lamp you percept the pen as almost white...

在此处输入图片说明请注意,当你有一个黑暗的房间,在黑暗的桌子上放着一支红笔,如果你打开一盏红灯,你会觉得这支笔几乎是白色的......

Another possibility is to create a different image for each color, with the pixel values for the other colors turned to zero. Starting from where we left we define a function to extract a channel into an otherwise black image

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

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

and finally use it...

并最终使用它...

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 hereI can't tell which is the version that I like better, perhaps the 1st one is looking more realisticto me (maybe it looks less artificial) but it's quite subjective...

在此处输入图片说明我不知道我更喜欢哪个版本,也许第一个对我来说看起来更现实(也许它看起来不那么做作)但它很主观......