这篇文章上次修改于 248 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

图像截取

首先定义一个图像显示函数:

import cv2
def cv_show(name,img):
    cv2.imshow(name,img) 
    cv2.waitKey(0) 
    cv2.destroyAllWindows()

前面说过,图像的本质是数组,因此,对于图像的截取也就是对于数组的切割,那么,简单的使用python自带的切片功能即可完成对于图像的截取操作:

img=cv2.imread('cat.jpg')
cat=img[0:300,0:200,1] 
cv_show('cat',cat)

这里同样是载入前一文章所使用的猫的图片,使用python的切片功能,对图像y轴0-300范围,x轴0-200范围的图像,第二个通道进行切割,并显示切割后的图像:
image.png

颜色通道提取

通道提取

之前我所操作的图片均为将原始图片转化后的灰度图,因为灰度图属于二维数组,便于操作。
而对于彩色图片而言,其实质拥有BGR三通道的颜色通道,在对彩色图片进行处理分析的时候,需要将其BGR颜色通道进行提取分离:

b,g,r=cv2.split(img)#三个通道分离
cv_show('R',r)

可以看出,单通道的显示效果:
image.png

这里显示出来的图像是一个灰度图像,到这里可能会有一个疑问,RGB三通道是红绿蓝三个底色,为什么单通道是一个灰度图?
我们所谓的RGB图片,即由红色、绿色、蓝色三个通道组成的图片,在表达每个像素点时用三个值表示,每个值取0~255,这个值可以理解能量的强弱,单通道图片如(0,255,0)是最深的绿色,(0,200,0)是相对浅的绿色,但是在显示成照片时,opencv读取的值在0-255之间,因此显示的就是灰度图。其他通道也有值的话就是复合颜色,比如(255,255,255)就是白色,因为红绿蓝组合一起就是白色。
而对于多通道而言,如果将多通道的图片转化为灰度图,并非是只有一个通道有数值。比如BGR图片的灰度图,是将三个通道的值变成一样的。这一点要尤为重要,我在CSDN上看到有人在开发产品的过程中,同时选取单通道图片和多通道图片的灰度图进行数值操作,导致出错,就是因为这个原因。

通道拼接

使用以下代码将三个通道进行拼接:

img=cv2.merge((b,g,r))#三个通道拼接
img.shape
cv_show('merge',img)

shape结果:(414, 500, 3)

可以看到,图片被重新拼接成了三通道的彩色图片

image.png

对于BGR图像,不同的通道拼接顺序带来的显示效果不同:
(xxx,xxx,xxx)的顺序不同
如下代码:

import cv2
lena=cv2.imread("lena.jpg")
b,g,r=cv2.split(lena)
bgr=cv2.merge([b,g,r])#z注意OpenCV通道顺序
rgb=cv2.merge([r,g,b])
gbr=cv2.merge([g,b,r])
cv2.imshow("lena",lena)
cv2.imshow("bgr",bgr)
cv2.imshow("rgb",rgb)
cv2.imshow("gbr",gbr)
cv2.waitKey()
cv2.destroyAllWindows()

显示效果:
image.png

只保留单个通道:

# 只保留R
cur_img = img.copy()
cur_img[:,:,0] = 0
cur_img[:,:,1] = 0
cv_show('R',cur_img)

现在对原图像查看下标为0的通道:

img[:,:,0]

array([[142, 146, 151, ..., 156, 155, 154],
       [107, 112, 117, ..., 155, 154, 153],
       [108, 112, 118, ..., 154, 153, 152],
       ...,
       [162, 157, 142, ..., 181, 170, 149],
       [140, 147, 139, ..., 167, 123, 104],
       [154, 154, 121, ..., 185, 130, 129]], dtype=uint8)

可以看到此时该通道是有数值的,对其置为0后:

cur_img[:,:,0]

array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)

因此其显示效果为只有一个通道的值:
image.png

对于其他两个通道,可以采用类似的方法:

# 只显示红色通道
cur_img = image.copy()
cur_img[:, :, 0] = 0
cur_img[:, :, 1] = 0
cv_show('R', cur_img)
# 只显示绿色通道
cur_img = image.copy()
cur_img[:, :, 1] = 0
cur_img[:, :, 2] = 0
cv_show('B', cur_img)
# 只显示蓝色通道
cur_img = image.copy()
cur_img[:, :, 0] = 0
cur_img[:, :, 2] = 0
cv_show('G', cur_img)

这里再举个例子:

import numpy as np
import cv2
img=np.zeros((300,300,3),dtype=np.uint8)
img[:,0:100,0]=255
img[:,100:200,1]=255
img[:,200:300,2]=255
print("img=\n",img)
cv2.imshow("img",img)
cv2.waitKey()
cv2.destroyAllWindows()

image.png