【计算机视觉—python 】 图像处理入门教程 —— 图像通道的拆分和合并【 openCV 学习笔记 011 to 012】
1、图像通道的拆分
OpenCV里函数cv2.split()将一个彩色图像三通道依次分离成三个 B、G、R 单通道图像。
cv2.split(img[, mv]) -> retval # 函数说明
- img:图像数据,nparray 多维数组。
- mv:指定的分拆通道(可选)。
PS: BGR 彩色图像的数据形状为 (width, height, channels=3),**返回的 B/G/R 通道**的数据形状为 (width, height),不能按照 BGR 彩色图像直接显示,如果直接用 imshow 显示返回的单通道对象,将被视为 (width, height) 形状的灰度图像显示,如果要正确显示某一颜色分量,需要增加另外两个通道值(置 0)转换为 BGR 三通道格式,再用 imshow 才能显示为拆分通道的颜色,具体操作如下:
# cv2.split 图像通道拆分
import cv2
import numpy as np
img1 = cv2.imread("test.jpg") # 读取彩色图像
cv2.imshow("BGR",img1) # 显示
# 测试直接用 imshow 显示返回的split单通道对象
bImg, gImg, rImg = cv2.split(img1) # 拆分为 BGR 独立通道
cv2.imshow("rImg",rImg) # 直接显示红色分量 rImg 显示为灰度图像
# 将单通道扩展为三通道
imgZeros = np.zeros_like(img1) # 创建与 img1 相同形状的黑色图像
imgZeros[:,:,1] = rImg # 在黑色模板中(shape->【高,宽,通道】)将rImg的数值赋予红色通道
cv2.imshow("channel R",imgZeros) # 显示扩展为三通道后的图像
print(img1.shape,rImg.shape,imgZeros.shape)
cv2.waitKey(0)
输出结果:
(676, 716, 3) (676, 716) (676, 716, 3)
根据图像数据结构体特性切片得到分离通道更为简便,而且运行速度比 cv2.split 更快。具体操作如下:
# 根据 图像数据结构体特性 切片分离通道
import cv2
import matplotlib.pyplot as plt
img1 = cv2.imread("test.jpg") # 读取彩色图像
# 获取通道 B 的图像
bImg = img1.copy() # 获取 BGR
bImg[:,:,1] = 0 # 将 G 通道数值置零
bImg[:,:,2] = 0 # 将 R 通道数值置零
# 获取通道 G 的图像
gImg = img1.copy() # 获取 BGR
gImg[:,:,0] = 0 # 将 B 通道数值置零
gImg[:,:,2] = 0 # 将 R 通道数值置零
# 获取通道 R 的图像
rImg = img1.copy() # 获取 BGR
rImg[:,:,0] = 0 # 将 B 通道数值置零
rImg[:,:,1] = 0 # 将 G 通道数值置零
# 获取只含通道 G R 的图像
grImg = img1.copy() # 获取 BGR
grImg[:,:,0] = 0 # B=0
plt.rcParams['font.sans-serif'] = ['FangSong'] # 支持中文标签
# 显示 通道 B
plt.subplot(221),plt.title("1. B 通道"),plt.axis("off") # 2×2个图片 第一个位置(左上) 不显示坐标轴、坐标轴标签
bImg = cv2.cvtColor(bImg,cv2.COLOR_BGR2RGB) # matplotlib 显示的图像格式为RGB
plt.imshow(bImg) # matplotlib 显示 通道 B
# 显示 通道 G
plt.subplot(222),plt.title("2. G 通道"),plt.axis("off") # 2×2个图片 第二个位置(右上) 不显示坐标轴、坐标轴标签
gImg = cv2.cvtColor(gImg,cv2.COLOR_BGR2RGB) # matplotlib 显示的图像格式为RGB
plt.imshow(gImg) # matplotlib 显示 通道 G
# 显示 通道 R
plt.subplot(223),plt.title("3. R 通道"),plt.axis("off") # 2×2个图片 第三个位置(左下) 不显示坐标轴、坐标轴标签
rImg = cv2.cvtColor(rImg,cv2.COLOR_BGR2RGB) # matplotlib 显示的图像格式为RGB
plt.imshow(rImg) # matplotlib 显示 通道 R
# 显示 通道 GR
plt.subplot(224),plt.title("4. GR 通道"),plt.axis("off") # 2×2个图片 第三个位置(右下) 不显示坐标轴、坐标轴标签
grImg = cv2.cvtColor(grImg,cv2.COLOR_BGR2RGB) # matplotlib 显示的图像格式为RGB
plt.imshow(grImg) # matplotlib 显示 通道 GR
plt.show()
2、图像通道的合并
OpenCV里函数cv2.merge()将 B、G、R 单通道合并为 3 通道 BGR 彩色图像。
cv2.merge(mv[, dst]) -> retval # 函数说明
- mv:要合并的单通道
- dst:通道合并的图像,nparray 多维数组
注意:
- 进行合并的 B、G、R 单通道图像分量,数据形状必须为 (width, height),而不是形状为 (width, height, channels=3) 的蓝色/绿色/红色图像。
- 单通道图像分量的图像大小 (width, height) 必须相同才能进行合并。
- 颜色通道要按照 B、G、R 通道次序合并,才能得到 BGR 格式的合并结果。
- cv2.merge() 操作复杂耗时,推荐使用 NumPy 数组合并函数 np.stack() 生成合成图像。
# cv2.merge()和 np.stack()两种图像通道的合并的方法
import cv2
import numpy as np
img1 = cv2.imread("test.jpg", flags=1) # flags=1 读取彩色图像(BGR)
bImg, gImg, rImg = cv2.split(img1) # 拆分为 BGR 独立通道
# cv2.merge 实现图像通道的合并
imgMerge = cv2.merge([bImg, gImg, rImg]) # 注意这里是数组
cv2.imshow("cv2Merge", imgMerge)
# Numpy 拼接实现图像通道的合并
imgStack = np.stack((bImg, gImg, rImg), axis=2) # axis(维度) 具体自查 np.stack 函数用法
cv2.imshow("npStack", imgStack)
print(imgMerge.shape, imgStack.shape) # 查看两个图像属性
print("imgMerge is imgStack?", np.array_equal(imgMerge, imgStack)) # 判断两种 图像通道的合并 结果是否相同
cv2.waitKey(0)
运行结果:
(676, 716, 3) (676, 716, 3)
imgMerge is imgStack? True
声明:本文是向博主「youcans_」OpenCV例程300篇学习的自用学习笔记
原文链接:【youcans@qq.com, youcans的OpenCV例程300篇, https://blog.csdn.net/youcans/category_11459626.html】