OpenCV-Python教程:通道分離、通道合並(split、merge)


原文鏈接:http://www.juzicode.com/archives/5612

返回Opencv-Python教程

彩色圖像是包含多通道的圖像,比如用BGR三通道表示的彩色圖像,或者是包含了alpha通道的BGRA四通道圖像。有時做圖像處理時如果多通道同時處理,可能並不能達到很好的效果,但是如果分離出某一個通道出來處理可能會有更好的效果,一個例子是在 來看看怎么用OpenCV解構Twitter大牛jagarikin的視覺錯覺圖 一文中可以看到在做二值化時只處理HSV色彩空間中的S分量效果更好。

1、通道分離split()

通道分離可以用於彩色圖像的處理,圖像對象可以是普通的3通道BGR彩色圖像,分離后分別為b、g、r的3個通道。如果是帶alpha通道的BGRA 4通道圖像,分離后分別為b、g、r、a。如果圖像是其他色彩空間的圖像比如HSV圖像,分離后的3個圖像則分別為h、s、v。

下面的例子將lena.jpg和opencv-logo.png做通道分離,並將各分量顯示出來,在代碼中加入了通道數的判斷,如果是3通道返回結果用b,g,r= cv2.split(img)接收分離結果,如果是4通道用b,g,r,a = cv2.split(img)接收分離結果:

import cv2
print('VX公眾號: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)

def show_img(win_name,img,wait_time=0,img_ratio=0.5,is_show=True):
    if is_show is not True:
        return 
    rows = img.shape[0]
    cols = img.shape[1]
    cv2.namedWindow(win_name, cv2.WINDOW_NORMAL )#cv2.WINDOW_AUTOSIZE)
    cv2.resizeWindow(win_name,(int(cols*img_ratio),int(rows*img_ratio)))
    cv2.imshow(win_name,img)
    if wait_time >= 0:
        cv2.waitKey(wait_time)

img = cv2.imread('..\\lena.jpg')
#img = cv2.imread('..\\opencv-logo.png',cv2.IMREAD_UNCHANGED)
if img is not None and len(img.shape)==3: #彩色圖像才可以做通道分離
    print('img.shape:',img.shape)
    show_img('img',img,-1)  
    if img.shape[2] == 3:                 #如果是3通道,分離出3個圖像實例
        b,g,r = cv2.split(img)     
        show_img('b',b,-1)
        show_img('g',g,-1)
        show_img('r',r,-1)
        cv2.waitKey(0)
    elif img.shape[2] == 4:               #如果是4通道
        b,g,r,a = cv2.split(img)
        show_img('b',b,-1)
        show_img('g',g,-1)
        show_img('r',r,-1)
        show_img('a',a,-1) 
        cv2.waitKey(0)

lena.jpg運行結果: 

opencv-logo.png運行結果: 

 

2、索引方式通道分離

另外一種方法是利用numpy數組的切片或索引操作,比如用img[:,:,0]分離出0通道或b通道,img[:,:,1]對應g通道,img[:,:,2]對應r通道,如果有img[:,:,3]則對應alpha通道。

    if img.shape[2] == 3:                 #如果是3通道,分離出3個圖像實例
        b = img[:,:,0]
        g = img[:,:,1]    
        r = img[:,:,2]             
        show_img('b',b,-1)
        show_img('g',g,-1)
        show_img('r',r,-1)
        cv2.waitKey(0)
    elif img.shape[2] == 4:               #如果是4通道
        b = img[:,:,0]
        g = img[:,:,1]    
        r = img[:,:,2]    
        a = img[:,:,3] 
        show_img('b',b,-1)
        show_img('g',g,-1)
        show_img('r',r,-1)
        show_img('a',a,-1) 
        cv2.waitKey(0)

 

3、通道合並merge()

用已有的多個通道圖像構造成一個元組傳遞給merge(),可以實現圖像的合並。

下面這個例子先分離出bgr通道再合並后顯示合成圖像:

import cv2
print('VX公眾號: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)

img = cv2.imread('..\\lena.jpg')  
b = img[:,:,0]
g = img[:,:,1]    
r = img[:,:,2]             
img2 = cv2.merge((b,g,r)) #傳入bgr構成的元組
cv2.imshow('merged',img2) 
cv2.waitKey(0)

運行結果:

下面這個例子特意將bgr通道順序做調換再合並:

img = cv2.imread('..\\lena.jpg')  
b = img[:,:,0]
g = img[:,:,1]    
r = img[:,:,2]             
img2 = cv2.merge((b,g,r)) #傳入bgr構成的元組
cv2.imshow('merged',img2) 
 
img2 = cv2.merge((r,g,b)) 
cv2.imshow('merged-rgb',img2) 
img2 = cv2.merge((r,b,g))  
cv2.imshow('merged-rbg',img2) 
img2 = cv2.merge((g,b,r))  
cv2.imshow('merged-gbr',img2) 
cv2.waitKey(0)

合並后圖像的效果和原圖對比:

 

4、索引方式通道合並

和用索引方式進行通道分離一樣,也可以用索引方式完成通道合並:

import numpy as np
import cv2
print('VX公眾號: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)

img = cv2.imread('..\\lena.jpg')  
b,g,r = cv2.split(img) 
rows,cols,channels = img.shape[0],img.shape[1],img.shape[2]
img2 = np.zeros((rows,cols,channels),np.uint8)  #創建全0的numpy數組
img2[:,:,0]=b  #填充各個通道
img2[:,:,1]=g
img2[:,:,2]=r  
cv2.imshow('merged',img2) 
cv2.waitKey()

 

5、“分離”灰度圖

在前面介紹的圖像分離中都是針對彩色圖像做多通道的分離,如果被分離的圖像是單通道的灰度圖,會是什么結果呢?

下面這個例子讀入lena.jpg時轉換為灰度圖,再使用split()進行分離:

import cv2
print('VX公眾號: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)

img = cv2.imread('..\\lena.jpg',cv2.IMREAD_GRAYSCALE) 
print('img.shape:',img.shape)
res = cv2.split(img)
print(type(res))
print(res)

運行結果:

cv2.__version__: 4.5.2
img.shape: (512, 512)
<class 'list'>
[array([[163, 162, 161, ..., 170, 154, 130],
       [162, 162, 162, ..., 173, 155, 126],
       [162, 162, 163, ..., 170, 155, 128],
       ...,
       [ 43,  42,  51, ..., 103, 101,  99],
       [ 41,  42,  55, ..., 103, 105, 106],
       [ 42,  44,  57, ..., 102, 106, 109]], dtype=uint8)]

從運行結果看,單通道的灰度圖用split()分離后,實際得到的是一個包含了array類型的list,效果和對一個numpy數組做split操作是類似的。

下面這個例子展示的是對一個numpy數組做split操作,不過numpy的split()方法還需要傳入第2個位置參數,表示要切割成多少個array。

import numpy as np
a = np.arange(0,50,1,np.uint8).reshape(5,10)
print(type(a))
print(a)
x = np.split(a,1) #切割成1個array
print(type(x))
print(x)
x = np.split(a,5) #切割成5個array
print(type(x))
print(x)

運行結果:

<class 'numpy.ndarray'>
[[ 0  1  2  3  4  5  6  7  8  9]
 [10 11 12 13 14 15 16 17 18 19]
 [20 21 22 23 24 25 26 27 28 29]
 [30 31 32 33 34 35 36 37 38 39]
 [40 41 42 43 44 45 46 47 48 49]]

<class 'list'>
[array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49]], dtype=uint8)]

<class 'list'>
[array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]], dtype=uint8), array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]], dtype=uint8), array([[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]], dtype=uint8), array([[30, 31, 32, 33, 34, 35, 36, 37, 38, 39]], dtype=uint8), array([[40, 41, 42, 43, 44, 45, 46, 47, 48, 49]], dtype=uint8)]

 

小結:split()可以用來對彩色圖像進行通道分離,merge()方法可以用來合並圖像,注意傳入給merge()的入參為多通道圖像組成的一個元組;因為圖像表示為numpy數組,所以也可以用numpy數組的索引方式對圖像進行分離和合並。

 

擴展閱讀:

  1. Opencv-Python教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM