20250118-读取并显示彩色图像以及提取彩色图像的 R、G、B 分量

读取并显示彩色图像以及提取彩色图像的 R、G、B 分量

import cv2  # 彩图 R、G、B 的提取
import numpy as np
from PIL import Image
from matplotlib import pyplot as plt

1. 读取并显示彩色图像的三种方法:

img_path = "./data/yndx"

1.1 使用 PIL 读取图像,并使用 plt.imshow 显示图像

# 使用 PIL 读取图像
pil_img = Image.open(img_path + "/color_img.jpg")

# 使用 plt.imshow 显示图像
plt.imshow(pil_img)
plt.axis('off')  # 不显示坐标轴
plt.show()

在这里插入图片描述

1.2 使用 OpenCV 读取图像,并使用 plt.imshow 显示图像

# 使用 OpenCV 读取图像
cv2_img = cv2.imread(img_path + "/color_img.jpg")

# OpenCV 读取的图像是 BGR 格式,需要转换为 RGB 格式
image_rgb = cv2.cvtColor(cv2_img, cv2.COLOR_BGR2RGB)
# 使用 plt.imshow 显示图像
plt.imshow(image_rgb)
plt.axis('off')  # 不显示坐标轴
plt.show()

在这里插入图片描述

# OpenCV 读取的图像是 BGR 格式
plt.imshow(cv2_img)
plt.axis('off')  # 不显示坐标轴
plt.show()

在这里插入图片描述

OpenCV 读取的原始图像(BGR 格式)和转换为 RGB 格式后的图像,显示结果不同的:

  1. 颜色通道顺序不同
  • BGR 格式:OpenCV 默认使用 BGR 格式读取图像。在这种格式下,图像的蓝色通道(B)、绿色通道(G)和红色通道(R)的顺序是 B、G、R。当使用 plt.imshow() 显示 BGR 格式的图像时,由于 matplotlib 库是按照 RGB 格式来解析图像的,所以图像的颜色会出现偏差,蓝色和红色通道的颜色会互换,导致图像整体颜色失真,比如原本红色的物体可能会显示为蓝色,蓝色的物体显示为红色等。
  • RGB 格式:经过 cv2.cvtColor() 函数将 BGR 格式转换为 RGB 格式后,图像的颜色通道顺序变为 R、G、B。此时再使用 plt.imshow() 显示,matplotlib 能正确解析图像的颜色通道,图像的颜色就能正常显示,与我们肉眼看到的图像颜色一致。
  1. 显示效果对比
  • BGR 格式显示效果:如上所述,由于颜色通道顺序错误,图像整体颜色会变得混乱,色彩失真较为明显。例如,一张原本色彩鲜艳、色彩搭配合理的风景照片,在 BGR 格式下显示时,天空可能不再是正常的蓝色,而是呈现出一种奇怪的红色或其他颜色,花朵的颜色也会变得不自然。
  • RGB 格式显示效果:转换为 RGB 格式后,图像的颜色能够准确呈现,色彩鲜艳度、对比度等都能保持正常。同一张风景照片,在 RGB 格式下显示时,天空是正常的蓝色,花朵的颜色也和实际看到的一样,整体视觉效果自然、真实。

1.3 使用 OpenCV 读取图像,并使用 cv2.imshow 显示图像

烦人

# # 使用 cv2.imshow 显示图像
# cv2.imshow("Original", cv2_img)
# # 等待键盘事件
# cv2.waitKey(0)
# # 关闭所有 OpenCV 窗口
# cv2.destroyAllWindows()

2. 提取彩色图像的 R、G、B 分量的两种方法

# 辅助函数:显示原图和 RGB 各个分量图像
def show_rgb(img, R, G, B):
    # 显示各分量
    plt.figure(figsize=(12, 4))

    plt.subplot(1, 4, 1)
    plt.imshow(img)
    plt.title('Original Image')
    plt.axis('off')

    # 显示图像的 RGB 分量
    color_channels = {'Red': R, 'Green': G, 'Blue': B}
    for i, channel in enumerate(color_channels.keys()):
        plt.subplot(1, 4, i + 2)
        single_channel_img = np.zeros_like(img)
        single_channel_img[:, :, i] = color_channels[channel]
        plt.imshow(single_channel_img)  # , cmap='gray'
        plt.title(f'{channel} Channel')
        plt.axis('off')

    # plt.subplot(1, 4, 2)
    # plt.imshow(R)   # , cmap='gray'
    # plt.title('Red Channel')
    # plt.axis('off')

    plt.show()

2.1 使用 PIL(Pillow)

PIL(Pillow)是 Python Imaging Library 的一个分支,它以 RGB 格式读取图像,因此可以直接提取各个分量。

# 使用 PIL 读取图像
# 将图像转换为 NumPy 数组
image_np = np.array(pil_img)

# 提取 R、G、B 分量
R = image_np[:, :, 0]
G = image_np[:, :, 1]
B = image_np[:, :, 2]

print(f"pil_img.shape: {image_np.shape} B.shape : {B.shape} G.shape: {G.shape} R.shape: {R.shape}")
pil_img.shape: (3468, 4624, 3) B.shape : (3468, 4624) G.shape: (3468, 4624) R.shape: (3468, 4624)
# 显示各分量
show_rgb(image_np, R, G, B)

在这里插入图片描述

2.2 使用 OpenCV

OpenCV 是一个功能强大的图像处理库,它以 BGR 格式读取图像,但我们可以轻松地将其转换为 RGB 格式,并提取各个分量。

2.2.1 使用 cv2.split() 提取 B、G、R 分量
  • 功能:将图像按通道分割成多个单通道图像。
  • 返回值:返回一个包含三个单通道图像的元组,分别是 B、G、R 分量。
  • 用途:主要用于需要分别处理每个通道的情况,例如对每个通道进行独立的滤波、阈值处理等操作。
# 使用 OpenCV 读取图像
# 使用 cv2.split() 提取 B、G、R 分量
(B, G, R) = cv2.split(cv2_img)

# 另存图像
cv2.imwrite(img_path + "/blue_img.jpg", B)
cv2.imwrite(img_path + "/green_img.jpg", G)
cv2.imwrite(img_path + "/red_img.jpg", R)

print(f"cv2_img.shape: {cv2_img.shape} B.shape: {B.shape} G.shape: {G.shape} R.shape: {R.shape}")
cv2_img.shape: (3468, 4624, 3) B.shape: (3468, 4624) G.shape: (3468, 4624) R.shape: (3468, 4624)
# 显示各分量
show_rgb(image_rgb, R, G, B)

在这里插入图片描述

2.2.2 使用 cv2.cvtColor() 提取 R、G、B 分量
  • 功能:将图像从一种颜色空间转换到另一种颜色空间。
  • 返回值:返回一个转换后的图像,仍然是一个三通道图像。
  • 用途:主要用于将图像从 BGR 格式转换为 RGB 格式,以便在 matplotlib 等库中正确显示图像。也可以用于其他颜色空间的转换,如从 BGR 转换为 HSV、YCrCb 等。
# 读取图像
# 使用 cv2.cvtColor() 将 BGR 图像转换为 RGB 图像
# image_rgb = cv2.cvtColor(cv2_img, cv2.COLOR_BGR2RGB)

# 提取 R、G、B 分量
R = image_rgb[:, :, 0]
G = image_rgb[:, :, 1]
B = image_rgb[:, :, 2]

print(f"cv2_img.shape: {image_rgb.shape} B.shape: {B.shape} G.shape: {G.shape} R.shape: {R.shape}")
cv2_img.shape: (3468, 4624, 3) B.shape: (3468, 4624) G.shape: (3468, 4624) R.shape: (3468, 4624)
# 显示各分量
show_rgb(image_rgb, R, G, B)

在这里插入图片描述

使用 cv2.split()cv2.cvtColor() 提取彩色图像的 R、G、B 分量在功能和用途上有一些区别,以下是详细对比:

  • 返回值类型:

cv2.split() 返回三个单通道图像(B、G、R)。

cv2.cvtColor() 返回一个三通道图像(例如 RGB)。

  • 用途:

cv2.split() 适用于需要分别处理每个通道的情况。

cv2.cvtColor() 适用于需要将图像从一种颜色空间转换到另一种颜色空间的情况,特别是从 BGR 转换为 RGB 以便在 matplotlib 中显示。

  • 显示效果:

cv2.split() 提取的单通道图像在 matplotlib 中需要使用 cmap='gray' 显示为灰度图。

cv2.cvtColor() 转换后的 RGB 图像可以直接在 matplotlib 中显示为彩色图。

  • 选择建议

如果需要分别处理每个通道,使用 cv2.split()

如果需要在 matplotlib 中显示图像,使用 cv2.cvtColor() 将 BGR 图像转换为 RGB 图像。
示。

  • 显示效果:

cv2.split() 提取的单通道图像在 matplotlib 中需要使用 cmap='gray' 显示为灰度图。

cv2.cvtColor() 转换后的 RGB 图像可以直接在 matplotlib 中显示为彩色图。

  • 选择建议

如果需要分别处理每个通道,使用 cv2.split()

如果需要在 matplotlib 中显示图像,使用 cv2.cvtColor() 将 BGR 图像转换为 RGB 图像。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈晨辰熟稳重

让我看看是哪个靓仔支持了我!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值