彩色空間HSV|RGB|灰度圖的理解與OpenCV中的轉換【DataWhale瑣碎知識點】

參考文獻:基於OpenCV的彩色空間互轉圖像處理之灰色圖轉化爲RGB圖像.

1 色彩空間

1.1 GRAY色彩空間

  1. GARY色彩空間(灰度圖像)通常指8位灰度圖,具有256個灰度級,像素值的範圍是[0,255]。不同數值表示不同程度的灰色。像素值越低,灰色越深。0表示純黑色,255表示純白色
  2. GARY色彩空間爲單通道,所以通常用二維數組表示一幅灰度圖像
  3. 其中二值圖像:只有0和255兩種像素值的灰度圖像。

1.2 RGB色彩空間

  1. 於神經生理學角度出發,即視網膜的三種不同的顏色感受器。能夠感受三種不同的顏色:紅色、綠色、藍色,即三基色。
  2. 自然界中常見的大部分顏色都可以通過將三基色按照一定比例混合得到。而在RGB色彩空間中,存在R(red)、G(green)、B(blue)三個通道。每個色彩通道值的範圍都在[0,255]之間,我們用這三個色彩通道的組合表示顏色。下圖表示不同RGB對應的顏色:不同RGB對應的顏色
  3. 三個通道都是0表示黑色,三個通道都是255表示白色。RGB空間共可以表示256×256×256種顏色。RGB顏色空間基於顏色的加法混色原理,從黑色不斷疊加Red,Green,Blue的顏色,最終可以得到白色。
    RGB顏色空間
  4. RGB的空間模型
    將R、G、B三個通道作爲笛卡爾座標系中的X、Y、Z軸,就得到了一種對於顏色的空間描述:
    RGB空間模型
    而形象化的RGB顏色空間立方體:
    形象化的RGB顏色空間立方體
    其中,需要提前說一句後面會看到的一句話:這個RGB顏色空間立方體在主對角線上的顏色都爲灰色。因此只要比例恰當RGB模型也可以從視覺感受器的角度表現爲灰色,類似灰度圖的視覺感受效果。
  5. 在應用領域需要注意的事情
    首先,不同的Python處理庫對彩色圖像的通道處理順序不一致:一般情況下,RGB色彩空間的通道順序是R→G→B。但是在OpenCV中,通道順序是B→G→R,而在Matplotlib中是R→G→B。
    其次,RGB色彩空間雖然可以識別大部分的顏色,但是不適合科學研究:原因在於RGB(紅綠藍)是依據人眼識別的顏色定義出的空間,可表示大部分顏色。但在科學研究一般不採用RGB顏色空間,因爲它的細節難以進行數字化的調整。它將色調,亮度,飽和度三個量放在一起表示,很難分開
    最後,它是最通用的面向硬件的彩色模型。該模型用於彩色監視器和一大類彩色視頻攝像

1.3 HSV色彩空間

  1. 與RGB色彩空間不同的是,HSV色彩空間是從心理學和視覺的綜合角度出發。
  2. 它提出人眼的色彩知覺的三要素:H:色調(Hue)S:飽和度(Saturation)V:亮度(Value)。
    首先,色調(H)色調是色彩的基本屬性,就是平常說的顏色的名稱,如“赤橙黃綠青藍紫”等。色調與混合光譜中的主要波長相關,從波長的角度考慮,不同波長的光變現爲不同的顏色,實際上體現的是色調的差異。色調的取值區間爲[0,360]。色調取不同值,所代表的顏色如下表:
    色調的取值對應表
    其中,兩個角度之間的角度對應兩個顏色之間的過渡色。(之所以稱之爲角度,是因爲H的取值範圍是0-360。)
    其次,飽和度(S)飽和度指色彩的純度,通俗的說就是顏色的深淺。飽和度越高色彩越純,飽和度越低則逐漸變灰。飽和度與所加白光的數量成反比。飽和度的取值區間是[0,1]。灰度顏色的飽和度值是0。如果顏色的飽和度很低,那麼它計算所得的色調不可靠。在OpenCV內,飽和度要映射到[0,255]範圍內
    然後,亮度(V)反應的是人眼感受到的光的明暗程度。如果其中摻入的白色越多,則亮度越高;如果在其中摻入的黑色越多,則亮度越低。亮度的取值區間是[0,1]。當亮度值是0時,圖象是純黑色。在OpenCV內,亮度也要映射到[0,255]範圍內。
  3. RGB色彩空間與HSV色彩空間的另外一點不同:RGB顏色空間中,三種顏色分量的取值與所生成的顏色之間的聯繫並不直觀。而HSV顏色空間,更類似於人類感覺顏色的方式,封裝了關於顏色的信息:“這是什麼顏色?深淺如何?明暗如何?
  4. HSV空間模型
    HSV顏色空間可以用一個倒圓錐體空間模型來描述。圓錐的頂點處,V=0,H和S無定義,代表黑色。圓錐的底面中心處V=360,S=0,H無定義,代表白色。
    倒圓錐空間模型
    這個模型就是按色彩、深淺、明暗來描述的:
    HSV計算空間
  5. 應用領域:可以用於偏光矯正、去除陰影、圖像分割等。

2 顏色空間互轉

2.1 可以發生互轉的理由

對於一張圖片,進行色彩空間轉換,只是把它每個像素點的表示形式改變了,不管用RGB的表示形式,還是HSV的表示形式,把像素值按相應色彩空間的規則轉換成對應的顏色後,表示的還是這張圖片。

2.2 RGB與灰度圖互轉

Gray向RGB的互轉規則
**注意:**這裏的灰度圖在向RGB圖像轉換時,RGB值均一樣,也就是說雖然轉換後的圖像的通道從灰度圖的一層轉換爲三層,但是從視覺感受上,轉換後的圖像仍舊爲灰色圖像。

2.3 RGB與HSV互轉

RGB-HSV
HSV-RGB

3 Python實現

3.1 將BGR轉換爲GRAY,再轉換回BGR

import cv2
import numpy as np
if __name__ == "__main__":
   img = cv2.imread('D:/yt/pictures2/dog.jpg', cv2.IMREAD_UNCHANGED)
   gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
   bgr = cv2.cvtColor(gray,cv2.COLOR_GRAY2BGR)
   # 顯示圖像
   cv2.imshow("origin image", img)
   cv2.imshow("gray image", gray)
   cv2.imshow("bgr image", bgr)
   # 保存圖像
   cv2.imwrite("D:/yt/pictures2/bgr-gray-dog.jpg", gray)
   cv2.imwrite("D:/yt/pictures2/gray-bgr-dog.jpg", bgr)
   cv2.waitKey(0)
   cv2.destroyAllWindows()

效果
效果1
此時會發現一個問題:爲什麼由RGB轉換爲灰度圖,再轉換回RGB時,圖像是灰色而不是彩色了?
解釋
另外一個問題是如何使得灰度圖能夠恢復到原來的彩色圖像呢?
答案是:逆向處理我們要將RGB表示轉換爲gGB表示,也就是用灰度分量g取代藍色分量R,藍色分量B和綠色分量G不變。我們可以從gGB計算出紅色分量R,因爲灰度g=pR+qG+tB(其中p=0.2989,q=0.5870,t=0.1140),於是R=(g-qG-t*B)/p。於是我們只要保留B和G兩個顏色分量,再加上灰度圖g,就可以回覆原來的RGB圖像。
代碼如下:

from __future__ import division
import numpy as np
import cv2
src = cv2.imread("C:/Users/12914/Pictures/messi.jpg")
src_gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# RGB在opencv中存儲爲BGR的順序,數據結構爲一個3D的numpy.array,索引的順序是行,列,通道:
B = src[:,:,0]
G = src[:,:,1]
R = src[:,:,2]
# 灰度g=p*R+q*G+t*B(其中p=0.2989,q=0.5870,t=0.1140),於是B=(g-p*R-q*G)/t。於是我們只要保留R和G兩個顏色分量,再加上灰度圖g,就可以回覆原來的RGB圖像。
g = src_gray[:]
p = 0.2989; q = 0.5870; t = 0.1140
B_new = (g-p*R-q*G)/t
B_new = np.uint8(B_new)
src_new = np.zeros((src.shape)).astype("uint8")
src_new[:,:,0] = B_new
src_new[:,:,1] = G
src_new[:,:,2] = R
# 顯示圖像
cv2.imshow("input", src)
cv2.imshow("output", src_gray)
cv2.imshow("result", src_new)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果
效果圖
認真思考過的學友可能會有看出一件事情:這個回覆的過程,不僅僅需要灰度圖像的數據,而且還需要原來彩色圖像的數據。那麼如果我知道了原來彩色圖像的數據,那我爲什麼還要通過轉換這種方式得到一張本身就存在的彩色圖像呢?所以這樣的答案並不適合應用情況,只是用作理解互轉過程,換句話說,灰度圖可以轉換爲RGB圖像,但是無法恢復到本來的彩色圖像。

3.2 將BGR轉換爲HSV,再轉換回BGR

import cv2
import numpy as np
if __name__ == "__main__":
   img = cv2.imread('D:/yt/pictures2/dog.jpg', cv2.IMREAD_UNCHANGED)
   hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
   bgr = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR)
   # 顯示圖像
   cv2.imshow("origin image", img)
   cv2.imshow("hsv image", hsv)
   cv2.imshow("bgr image", bgr)
   # 保存圖像
   cv2.imwrite("D:/yt/pictures2/bgr-hsv-dog.jpg", hsv)
   cv2.imwrite("D:/yt/pictures2/hsv-bgr-dog.jpg", bgr)
   cv2.waitKey(0)
   cv2.destroyAllWindows()

效果
效果圖2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章