在OpenCV中,图像装载后以矩阵保存,对于灰度图矩阵为二维矩阵,对于彩色图像则为三维矩阵。彩色图像又分为BGR格式和BGRA格式,BGR格式对于像素的蓝、绿、红三个通道,BGRA格式蓝、绿、红三个颜色通道加一个代表透明度的阿尔法通道。有时出于处理需要,需要针对图像矩阵的单个通道进行处理,这时就需要进行图像单通道数据的访问。
OpenCV提供了专门的通道拆分的函数split,调用语法如下:
split(img, mv=None)
其中的参数为输入图像矩阵,mv是可选的拆分后结果,一般不需要,因为该函数返回的就是拆分的结果。
返回值为一个列表对象,对象的元素个数为输入图像的通道数,每个元素为一个二维矩阵,内容为每个通道的数据。如BGRA格式的图像,则返回4个元素,每个元素分别对应B、G、R、A四个通道的数据。
示例代码:
>>> import cv2
>>> img = cv2.imread(r'f:\pic\ring.png',cv2.IMREAD_UNCHANGED)
>>> img.shape
(742, 1156, 4)
>>> ret = cv2.split(img)
>>> len(ret)
4
>>> B,G,R,A = ret
>>> B
array([[28, 28, 28, ..., 29, 29, 29],
[28, 28, 28, ..., 29, 29, 29],
[28, 28, 28, ..., 29, 29, 29],
...,
[35, 35, 35, ..., 35, 35, 35],
[35, 35, 35, ..., 35, 35, 35],
[35, 35, 35, ..., 35, 35, 35]], dtype=uint8)
>>> B.shape
(742, 1156)
拆分的通道可以通过merge将其合并成一个图像矩阵,例如对上面拆分的4个通道的BGR通道进行合并,可以执行如下代码:
>>> imgBGR = cv2.merge((B,G,R))
>>> imgBGR.shape
(742, 1156, 3)
由于图像在OpenCV中为矩阵,就可以直接使用numpy的矩阵索引来进行矩阵数据的访问。例如要针对输入图像img分别获取BGR通道的数据,可以执行如下代码:
imgBlueC0 = img[:,:,0]
imgBlueC1 = img[:, :, 1]
imgBlueC2 = img[:, :, 2]
针对如下图像(文件名:手握蓝球.JPG):
我们使用两种通道拆分方式分别拆分,然后对比一下拆分结果:
import cv2
import numpy as np
from opencvPublic import preparePreviewImg,previewImgList,previewImg,cmpMatrix,readImgFile
def main():
imgFName = r'f:\pic\手握蓝球.JPG'
img = readImgFile(imgFName, False) #自定义读入图片文件的函数,readImgFile(filename,bConvertGray=False,bConvertBinImg=False,bConvertKernal = False)
imgBlue,imgGreen,imgRed = cv2.split(img)
imgBlueAnd = cv2.bitwise_and(img,255)
imgBlueC0 = img[:,:,0]
imgBlueC1 = img[:, :, 1]
imgBlueC2 = img[:, :, 2]
preparePreviewImg(img, imgFName + ': 原图')
preparePreviewImg(imgBlue, '原图split后B通道')
preparePreviewImg(imgGreen, '原图split后G通道')
preparePreviewImg(imgRed, '原图split后R通道')
preparePreviewImg(imgBlueAnd, 'imgBlueAnd')
preparePreviewImg(imgBlueC0, '原图0号通道(B通道)')
preparePreviewImg(imgBlueC1, '原图1号通道(G通道)')
preparePreviewImg(imgBlueC2, '原图2号通道(R通道)')
retB = cmpMatrix(imgBlue, imgBlueC0)
retG = cmpMatrix(imgGreen, imgBlueC1)
retR = cmpMatrix(imgRed, imgBlueC2)
print(f"split拆分图像3通道与图像矩阵数字3通道访问图像比对结果如下:{(retB,retG,retR)}")
previewImgList()
cv2.waitKey(5000)
main()
上述代码中从opencvPublic模块导入的函数请参考《https://blog.csdn.net/LaoYuanPython/article/details/111351901:OpenCV-Python图形图像处理:自用的一些工具函数功能及调用语法介绍》的介绍。
执行程序后,运行后显示的图像如下:
系统输出的文本信息如下:
split拆分图像3通道与图像矩阵数字3通道访问图像比对结果如下:(True, True, True)
从以上结果可以看到,两种拆分方式的通道数据完全相同。另外由于拆分后的通道数据被作为灰度图像对待,因此显示的图像为灰度图。上图中imgBlueAnd 对应图像为彩色图像位于255标量后的结果图像,因为值保留了蓝色通道的值,其他通道的值被置为0,因此显示为整体蓝色的图像。
本文介绍了OpenCV图像通道拆分的两种方式,可以看到,OpenCV的split函数和numpy的矩阵索引两种拆分方式得到的结果数据是相同的,但numpy矩阵索引方式性能更好。因此图像通道的拆分非必要不执行,如果要执行,尽量采用numpy矩阵操作。
昨天到今天休假两天,既要处理家里事情,又要处理单位事情,还要写测试代码和博文。写博不易,敬请支持!
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
更多OpenCV-Python的介绍请参考专栏《OpenCV-Python图形图像处理 》
专栏网址:https://blog.csdn.net/laoyuanpython/category_9979286.html
前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。