您好,登錄后才能下訂單哦!
小編給大家分享一下python如何實現RGB與YCBCR顏色空間轉換,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
人類能夠從灰度圖像中獲取理解場景需要的大部分信息,所以看黑白電視機并不會嚴重影響人對視頻中場景的理解。圖像的亮度和像素值成正比,如果需要增加圖像的亮度,比如從黑色逐漸過渡到白色,就可以對單通道的灰度圖像素值進行增加來實現。保存灰度圖像的每個像素值一般采用8個bit,像素值的范圍為0-255。
下面的例子展示了灰度圖像的像素值增加時亮度的變化過程,假設圖像初始像素值為0:
上面顯示了lena圖像像素值增加時膚色的變化。代碼的實現比較簡單,讀取圖片,然后不斷的對圖像的每個像素值增加偏移量:
import numpy as np import matplotlib.pyplot as plt import imageio image = imageio.imread("lena.jpg") # 設置每次循環像素的增加量 shift = 6*np.ones(shape=(64, 64)) plt.figure() for i in range(1, 17): plt.subplot(4, 4, i) plt.imshow(image/255, cmap="gray", vmin=0, vmax=1) plt.axis("off") image = image + shift
RGB模型在硬件設備中被廣泛的使用,通過R(紅色)、G(綠色)、B(藍色)三者進行疊加可以形成更多的顏色。RGB顏色空間和后面將要進行介紹的YCbCr顏色空間和HSV顏色空間存在線性的變換關系,所以只要擁有RGB圖像就能得到其它顏色空間的圖像。
一幅圖像中R、G、B分別作為三個通道,如果某兩個通道的值為0,圖像的顏色就會被不為零的那個通道控制。
比如:
實現上面的效果需要三個步驟:
(1)創建一幅3通道的空圖像
(2)給3通道空圖像的R通道添加一幅單通道圖像
(3)給3通道圖像的R通道像素值不斷增加偏移量
# 1:創建一幅3通道的空圖像 = np.zeros(shape=(64, 64, 3)) r = imageio.imread("lena.jpg")/2 # 2:給3通道空圖像的R通道添加一幅單通道圖像 image[:, :, 0] = image[:, :, 0] + r shift = 4*np.ones(shape=(64, 64)) plt.figure() for i in range(1, 17): plt.subplot(4, 4, i) plt.imshow(image/255, vmin=0, vmax=1) plt.axis("off") # (3)給3通道圖像的R通道像素值不斷增加偏移量 image[:, :, 0] = image[:, :, 0] + shift
但是,由于最終圖像呈現出的顏色是三R\G\B三者的疊加,而現實中不僅僅是其中之一的顏色,所以很難控制最終圖像的顏色,所以我們需要其它的顏色空間。
YCbCr顏色空間中的Y是亮度通道,Cb是藍色分量,Cr是紅色分量。它在電視系統中比較常用,比如早期的黑白電視機使用彩色電視信號線,就可以單獨使用亮度值;這種功能RGB顏色空間就做不到,因為我們不能僅僅使用RGB中某個通道作為亮度信號來使用。
由于YCbCr經常和YUV顏色空間比較相似,所以二者容易被認為是從屬或者等價關系,按照維基百科的說法:YUV 是模擬信號,而YCbCr是數字信號。
YCbCr和RGB存在線性的變換關系,本文介紹的變換矩陣來自ITU.BT-601,所規定的變換矩陣Trans形式如下:
實現rgb2ycbcr()函數只需要兩個步驟:(1)創建變換矩陣Trans;(2)遍歷圖像每個像素點,并對三個通道分別進行矩陣計算。
下面的代碼展示了如何實現從RGB空間到YCBCR變換:
def rgb2ycbcr(rgb_image): """convert rgb into ycbcr""" if len(rgb_image.shape)!=3 or rgb_image.shape[2]!=3: raise ValueError("input image is not a rgb image") rgb_image = rgb_image.astype(np.float32) # 1:創建變換矩陣,和偏移量 transform_matrix = np.array([[0.257, 0.564, 0.098], [-0.148, -0.291, 0.439], [0.439, -0.368, -0.071]]) shift_matrix = np.array([16, 128, 128]) ycbcr_image = np.zeros(shape=rgb_image.shape) w, h, _ = rgb_image.shape # 2:遍歷每個像素點的三個通道進行變換 for i in range(w): for j in range(h): ycbcr_image[i, j, :] = np.dot(transform_matrix, rgb_image[i, j, :]) + shift_matrix return ycbcr_image
如果想要求逆變換,只需要根據矩陣求逆法則進行就可以了,需要注意的是:逆變換時偏移矩陣也需要左乘變換矩陣Trans的逆!逆變換只需要將rgb2ycbcr
中的transform_matrix
求逆即可,再次強調:shift_matrix也需要乘以transform_matrix的逆,而不是直接減去shift_matrix!
def ycbcr2rgb(ycbcr_image): """convert ycbcr into rgb""" if len(ycbcr_image.shape)!=3 or ycbcr_image.shape[2]!=3: raise ValueError("input image is not a rgb image") ycbcr_image = ycbcr_image.astype(np.float32) transform_matrix = np.array([[0.257, 0.564, 0.098], [-0.148, -0.291, 0.439], [0.439, -0.368, -0.071]]) transform_matrix_inv = np.linalg.inv(transform_matrix) shift_matrix = np.array([16, 128, 128]) rgb_image = np.zeros(shape=ycbcr_image.shape) w, h, _ = ycbcr_image.shape for i in range(w): for j in range(h): rgb_image[i, j, :] = np.dot(transform_matrix_inv, ycbcr_image[i, j, :]) - np.dot(transform_matrix_inv, shift_matrix) return rgb_image.astype(np.uint8)
所需要的包以及繪圖代碼如下,繪圖用到的就是上面定義的兩個函數。首先將rgb轉為ycbcr,在從ycbcr轉為rgb:
import numpy as np import imageio import matplotlib.pyplot as plt rgb_image = imageio.imread("lena.jpg") ycbcr_image = rgb2ycbcr(rgb_image) cycle_image = ycbcr2rgb(ycbcr_image) images = [rgb_image, ycbcr_image, cycle_image] titles = ["orignal", "ycbcr", "cycle"] for i in range(1, len(images)+1): plt.subplot(1, 3, i) plt.title(titles[i-1]) plt.imshow(images[i-1]/255)
下圖中左邊是原始的rgb圖像,中間是轉換得到的ycbcr空間圖像,右邊是再次轉回rgb空間的圖像:
最后,對比了opencv提供的標準庫的轉換效果:
import cv2 rgb_image = imageio.imread("lena.jpg") ycrcb_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2YCR_CB) cycle_image = cv2.cvtColor(ycbcr_image, cv2.COLOR_YCR_CB2RGB) images = [rgb_image, ycrcb_image, cycle_image] titles = ["orignal", "ycrcb", "cycle"] for i in range(1, len(images)+1): plt.subplot(1, 3, i) plt.title(titles[i-1]) plt.imshow(images[i-1]/255)
opencv得到的結果如下:
原始rgb效果和cycle(重構)效果很接近,而中間結果不一致是因為opencv采用的是“ycrcb”,而不是“ycbcr”。
以上是“python如何實現RGB與YCBCR顏色空間轉換”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。