python實(shí)現(xiàn)RGB與YCBCR顏色空間轉(zhuǎn)換
前言:
人類如何感知或者理解顏色是個(gè)非常復(fù)雜的問題,本文不討論如何從生物學(xué)或者心理學(xué)角度來分析顏色,而是分析“數(shù)值大小如何影響顏色”。文中主要介紹了RGB與YCbCr顏色空間概念的與變換關(guān)系。
1、灰度值和亮度的關(guān)系
人類能夠從灰度圖像中獲取理解場景需要的大部分信息,所以看黑白電視機(jī)并不會嚴(yán)重影響人對視頻中場景的理解。圖像的亮度和像素值成正比,如果需要增加圖像的亮度,比如從黑色逐漸過渡到白色,就可以對單通道的灰度圖像素值進(jìn)行增加來實(shí)現(xiàn)。保存灰度圖像的每個(gè)像素值一般采用8個(gè)bit,像素值的范圍為0-255。
下面的例子展示了灰度圖像的像素值增加時(shí)亮度的變化過程,假設(shè)圖像初始像素值為0:

上面顯示了lena圖像像素值增加時(shí)膚色的變化。代碼的實(shí)現(xiàn)比較簡單,讀取圖片,然后不斷的對圖像的每個(gè)像素值增加偏移量:
import numpy as np
import matplotlib.pyplot as plt
import imageio
image = imageio.imread("lena.jpg")
# 設(shè)置每次循環(huán)像素的增加量
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 + shift2、RGB顏色空間與顏色控制
RGB模型在硬件設(shè)備中被廣泛的使用,通過R(紅色)、G(綠色)、B(藍(lán)色)三者進(jìn)行疊加可以形成更多的顏色。RGB顏色空間和后面將要進(jìn)行介紹的YCbCr顏色空間和HSV顏色空間存在線性的變換關(guān)系,所以只要擁有RGB圖像就能得到其它顏色空間的圖像。
一幅圖像中R、G、B分別作為三個(gè)通道,如果某兩個(gè)通道的值為0,圖像的顏色就會被不為零的那個(gè)通道控制。
比如:

實(shí)現(xiàn)上面的效果需要三個(gè)步驟:
- (1)創(chuàng)建一幅3通道的空圖像
- (2)給3通道空圖像的R通道添加一幅單通道圖像
- (3)給3通道圖像的R通道像素值不斷增加偏移量
# 1:創(chuàng)建一幅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但是,由于最終圖像呈現(xiàn)出的顏色是三R\G\B三者的疊加,而現(xiàn)實(shí)中不僅僅是其中之一的顏色,所以很難控制最終圖像的顏色,所以我們需要其它的顏色空間。
3、YCbCr顏色空間及與RGB的變換關(guān)系
YCbCr顏色空間中的Y是亮度通道,Cb是藍(lán)色分量,Cr是紅色分量。它在電視系統(tǒng)中比較常用,比如早期的黑白電視機(jī)使用彩色電視信號線,就可以單獨(dú)使用亮度值;這種功能RGB顏色空間就做不到,因?yàn)槲覀儾荒軆H僅使用RGB中某個(gè)通道作為亮度信號來使用。
由于YCbCr經(jīng)常和YUV顏色空間比較相似,所以二者容易被認(rèn)為是從屬或者等價(jià)關(guān)系,按照維基百科的說法:YUV 是模擬信號,而YCbCr是數(shù)字信號。
YCbCr和RGB存在線性的變換關(guān)系,本文介紹的變換矩陣來自ITU.BT-601,所規(guī)定的變換矩陣Trans形式如下:

實(shí)現(xiàn)rgb2ycbcr()函數(shù)只需要兩個(gè)步驟:(1)創(chuàng)建變換矩陣Trans;(2)遍歷圖像每個(gè)像素點(diǎn),并對三個(gè)通道分別進(jìn)行矩陣計(jì)算。
下面的代碼展示了如何實(shí)現(xiàn)從RGB空間到Y(jié)CBCR變換:
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:創(chuàng)建變換矩陣,和偏移量
? ? 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:遍歷每個(gè)像素點(diǎn)的三個(gè)通道進(jìn)行變換
? ? 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如果想要求逆變換,只需要根據(jù)矩陣求逆法則進(jìn)行就可以了,需要注意的是:逆變換時(shí)偏移矩陣也需要左乘變換矩陣Trans的逆!逆變換只需要將rgb2ycbcr中的transform_matrix求逆即可,再次強(qiáng)調(diào):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)所需要的包以及繪圖代碼如下,繪圖用到的就是上面定義的兩個(gè)函數(shù)。首先將rgb轉(zhuǎn)為ycbcr,在從ycbcr轉(zhuǎn)為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圖像,中間是轉(zhuǎn)換得到的ycbcr空間圖像,右邊是再次轉(zhuǎn)回rgb空間的圖像:

最后,對比了opencv提供的標(biāo)準(zhǔn)庫的轉(zhuǎn)換效果:
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得到的結(jié)果如下:

原始rgb效果和cycle(重構(gòu))效果很接近,而中間結(jié)果不一致是因?yàn)閛pencv采用的是“ycrcb”,而不是“ycbcr”。
到此這篇關(guān)于python實(shí)現(xiàn)RGB與YCBCR顏色空間轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)python顏色空間轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Python實(shí)現(xiàn)批量修改文件的修改日期功能
在日常的文件管理中,您可能需要批量修改文件的修改日期,比如,您可能希望將某個(gè)文件夾中的所有文件的修改日期隨機(jī)設(shè)置為6到8月份之間的日期,這在數(shù)據(jù)整理中可能非常有用,本文將詳細(xì)介紹如何使用Python實(shí)現(xiàn)這一功能,需要的朋友可以參考下2024-10-10
Python實(shí)現(xiàn)批量合并Excel文件的第二張合并Excel
在數(shù)據(jù)處理和分析中,經(jīng)常需要對多個(gè)Excel文件進(jìn)行批量操作,特別是當(dāng)這些文件具有相似的結(jié)構(gòu)時(shí),下面我們就來看看Python如何實(shí)現(xiàn)批量合并文件夾下所有Excel文件的第二張表吧2024-03-03
Django 實(shí)現(xiàn)對已存在的model進(jìn)行更改
這篇文章主要介紹了Django 實(shí)現(xiàn)對已存在的model進(jìn)行更改,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Python的string模塊中的Template類字符串模板用法
通過string.Template我們可以為Python定制字符串的替換標(biāo)準(zhǔn),這里我們就來通過示例解析Python的string模塊中的Template類字符串模板用法:2016-06-06
python創(chuàng)建關(guān)聯(lián)數(shù)組(字典)的方法
這篇文章主要介紹了python創(chuàng)建關(guān)聯(lián)數(shù)組(字典)的方法,涉及Python操作字典的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-05-05
Python 抓取數(shù)據(jù)存儲到Redis中的操作
這篇文章主要介紹了Python 抓取數(shù)據(jù)存儲到Redis中的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
DataFrame.to_excel多次寫入不同Sheet的實(shí)例
今天小編就為大家分享一篇DataFrame.to_excel多次寫入不同Sheet的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12
python利用requests庫模擬post請求時(shí)json的使用教程
這篇文章主要介紹了python利用requests庫模擬post請求時(shí)json的使用 ,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-12-12
Python基于pillow庫實(shí)現(xiàn)生成圖片水印
這篇文章主要介紹了Python基于pillow庫實(shí)現(xiàn)生成圖片水印,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
Python3 shutil(高級文件操作模塊)實(shí)例用法總結(jié)
在本篇文章里小編給大家整理的是一篇關(guān)于Python3 shutil實(shí)例用法內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2020-02-02

