1. 程式人生 > >計算機視覺(一):基礎篇

計算機視覺(一):基礎篇

一、光和電磁波譜

      1666年,艾薩克牛頓發現,當一束太陽光通過一個玻璃稜鏡後,顯示的光束不再是白光,而是由一端為紫色而另一段為紅色的連續色譜組成。如圖1所示,我們感受到的可見光的彩色範圍只佔電磁波的一小部分。在波譜的一端是無線電波,其波長是可見波長的幾十億倍。波譜的另一端是伽馬射線,其波長比可見光小几百萬倍。電磁波譜可用波長、頻率或能量來描述。波長( λ

λ )和頻率( v v )的關係可見下式描述:
λ = c / v
λ=c/v
式中 c c 是光速( 2.998 × 1 0 8 m / s 2.998×10^8m/s )。電磁波譜的各個分量的能量由下式給出:
E = h v E=hv 式中 h h 是普朗克常數。
在這裡插入圖片描述

圖1    電磁波譜    為便於解釋,可見光譜已被放大,但請注意,可見光譜是電磁波譜中相當窄的一部分

    電磁波可視為以波長 λ λ 傳播的正弦波,從上面的式子可以看出,能量與頻率成正比,因此更高頻率(更短波長)的電磁現象的每個光子攜帶更多的能量。



二、彩色模型

1.RGB彩色模型

      在RGB模型中,每種顏色出現在紅(Red)、綠(Green)、藍(Blue)的原色光譜成分中。該模型基於笛卡兒座標系。在RGB彩色模型中表示的影象由3個分量影象組成,每種原色一幅分量影象。當送入RGB監視器時,這3幅影象在螢幕上混合生成一幅合成的彩色影象。
      見圖2,為方便起見,假定所有顏色值均已歸一化,即R、G和B的所有值都在區間[0,1]中。0表示不發光,1表示完全發光。以(1,0,0)為例,R為1即完全發光,G與B為0即不發光,最終顏色為紅色;以(1,1,0)為例,R與G為1即完全發光,B為0即不發光,即紅色跟綠色完全發光,藍色不發光,最終顏色為黃色。
在這裡插入圖片描述

圖2    RGB彩色立方體示意圖    沿主對角線的點有從原點的黑點至點(1,1,1)的白色的灰度值
2.HSV彩色模型

      通常用以區別不同顏色特性的是明度、色調和飽和度。明度具體表達了無色的強度概念;色調是光波混合中與主波長有關的屬性,表示觀察者感知的主要顏色,當我們說一個物體是紅色、橙色時,指的是其色調;飽和度指的是相對純淨度,或一種顏色混合白光的數量,所加白光越少飽和度越高。色調與飽和度一起稱為色度,因此,顏色可用其明度和色度來表徵。
      HSV(色調、飽和度、明度)彩色模型,正是由這三個分量組成的影象。

3.從RGB到HSV的彩色轉換

下式中RGB的值需歸一化,即所有值在區間[0,1]中。
先定義: m a x = m a x ( R , G , B )       m i n = m i n ( R , G , B ) max = max(R,G,B) \ \ \ \ \ min = min(R,G,B)
① 色調H,範圍 [0,360]
在這裡插入圖片描述
② 飽和度S,範圍 [0,1]
a) m a x = 0 max = 0
S = 0 S = 0 b) m a x 0 max ≠ 0
S = ( m a x m i n ) / m a x S=(max-min)/max

③ 亮度V,範圍 [0,1]
V = m a x ( R , G , B ) V=max(R,G,B)

4.從HSV到RGB的彩色轉換

其中 H H 的取值範圍為[0,360], S V R G B S、V、R、G、B 的取值範圍為[0,1]
h i h 60 ( m o d 6 ) h_{i}\equiv \left\lfloor {\frac {h}{60}}\right\rfloor {\pmod {6}} f = h 60 h i f={\frac {h}{60}}-h_{i} p = v × ( 1 s )   p=v\times (1-s)\, q = v × ( 1 f × s )   q=v\times (1-f\times s)\, t = v × ( 1 ( 1 f ) × s )   t=v\times (1-(1-f)\times s)\,
對於每個顏色向量 ( r , g , b ) (r, g, b)
在這裡插入圖片描述

5.RGB和HSI的互換程式碼實現(Python+OpenCV)

OpenCV的cvtColor()函式能支援各種彩色模型的轉換,其中包括RGB和HSI的轉換,部分用法如下:

cv2.cvtColor(src, code)
src為要轉換的圖片,code為轉換的格式,code引數:
1、BGR <=> RGB : COLOR_BGR2RGB、COLOR_RGB2BGR
2、BGRA <=> RGBA :COLOR_BGRA2RGBA、 COLOR_RGBA2BGRA
3、BGR 和 RGB 新增 alpha 通道 : COLOR_BGR2BGRA、COLOR_RGB2RGBA
4、BGRA 和 RGBA 刪除 alpha 通道 :COLOR_BGRA2BGR、 COLOR_RGBA2RGB
5、BGR 和 RGB <=> HSV :  COLOR_BGR2HSV、COLOR_RGB2HSV、COLOR_HSV2BGR、COLOR_HSV2RGB(轉換後H的取值範圍為[0,180],S和V的取值範圍為[0,255])

現用一張8位的圖片01.jpg演示程式碼:

import cv2

img = cv2.imread('01.jpg') # 獲取位元組順序為BGR的圖片
img1 = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA) # 新增 alpha 通道
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # BGR轉HSV
img3 = cv2.cvtColor(img2, cv2.COLOR_HSV2RGB) # HSV 轉 RGB

img[0][0]
img1[0][0]
img2[0][0]
img3[0][0]

# 顯示結果如下:
array([119, 203, 238], dtype=uint8) 
array([119, 203, 238, 255], dtype=uint8)  # 增加了第4個分量即 alpha 通道

'''
根據上文演算法將 BGR 轉換成 HSV
H = (G-B) / (max-min) * 60 = (203-119) / (238-119) * 60 = 42.35,H的取值範圍在[0,360],需轉換到[0,180],得42.35/2 = 21
S =  (max-min) / max = (238-119) / 238 = 0.5,0.5 * 255 = 128
V = max(R,G,B) = 238
'''
array([ 21, 128, 238], dtype=uint8) 

'''
根據上文演算法將 HSV 轉換成 RGB
將hsv分別轉換到範圍[0,180]、[0,1]、[0,1] 得 [21*2, 128/255, 238/255] = [42, 0.502, 0.933]
hi = h/60 mod 6 = 42 / 60 mod 6 = 0
f = h/60 - hi = 42 / 60 - 0 = 0.7
p = v*(1-s) =  0.933*(1-0.502) = 0.4646
q = v*(1-f*s) =  0.933*(1-0.7*0.502) = 0.6051
t = v*(1-(1-f)*s) = 0.933*(1-(1-0.7)*0.502) = 0.7925
因為hi = 0,RGB = [v, t, p] = [0.933, 0.7925, 0.4646],轉換到範圍[0,255] 得 [238, 202, 118]
'''
array([238, 202, 118], dtype=uint8) 


三、灰度影象

1.灰度級與灰度影象

    沒有顏色的光稱為單色光或無色光。單色光的唯一屬性是其強度或大小。因為感知單色光的強度從黑色到灰色變化,最後到白色,灰度級一次通常用來表示單色光的強度。
    從黑到白的單色光的度量值範圍通常稱為灰度級,而單色影象通常稱為灰度影象。

2.RGB轉灰度影象

    使用不同的演算法,會得到不同的灰度影象,例如若要檢視紅色在影象的分佈情況,可使用:
G r a y = 1 × R + 0 × G + 0 × B Gray = 1×R + 0×G + 0×B     從上式可知,選擇不同的係數,可得到不同的灰度影象,目前常使用下面的一個心理學公式:
G r a y = 0.299 × R + 0.587 × G + 0.114 × B          ( 1 ) Gray = 0.299×R + 0.587×G + 0.114×B\ \ \ \ \ \ \ \ (1)

3. RGB轉灰度影象程式碼實現(Python+OpenCV)

① cv2.imread()實現RGB轉灰度
OpenCV的imread()函式能支援各種靜態影象檔案格式,其中包括RGB轉灰度,部分用法如下:

cv2.imread(filename[, flags])
該函式返回的影象格式為BGR,與RGB表示的色彩空間相同,但是位元組順序相反。
filename為圖片路徑,flags表示用何種方式讀取圖片,預設為IMREAD_COLOR ,flags引數:
1、IMREAD_COLOR = 1 : 載入彩色影象,最多8位
2、IMREAD_GRAYSCALE = 0 : 以灰度模式載入影象,演算法為式(1),最多8位
3、IMREAD_UNCHANGED = -1: 包含alpha通道,可載入8位和16點陣圖像

現用兩張8位的圖片01.jpg和02.png演示程式碼:

import cv2

img1 = cv2.imread('01.jpg', cv2.IMREAD_COLOR)
img2 = cv2.imread('01.jpg', cv2.IMREAD_GRAYSCALE) # 轉換成灰度影象
img3 = cv2.imread('01.jpg', cv2.IMREAD_UNCHANGED)
img4 = cv2.imread('02.png', cv2.IMREAD_UNCHANGED)

img1[0][0]
img2[0][0:1]
img3[0][0]
img4[0][0]

# 顯示結果如下:
array([119, 203, 238], dtype=uint8) # 8位彩色圖片,若圖片為16位也會轉換成8位
array([204], dtype=uint8) # 計算式(1)得 0.299*238+0.587*203+0.114* 119 = 204
array([119, 203, 238], dtype=uint8) # 無alpha通道
array([119, 203, 238, 255], dtype=uint8) # 第4個分量為alpha通道,若圖片為16位則可保留16位

② cv2.cvtColor()實現RGB轉灰度
OpenCV的cvtColor()函式能支援各種彩色模型的轉換,其中包括RGB和灰度的轉換,部分用法如下:

cv2.cvtColor(src, code)
src為要轉換的圖片,code為轉換的格式,code引數:
1、BGR => 灰度 : COLOR_BGR2GRAY

現用一張8位的圖片01.jpg演示程式碼:

import cv2

img = cv2.imread('01.jpg') # 獲取位元組順序為BGR的圖片
img1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # BGR轉灰度

img[0][0]
img1[0][0:1]

# 顯示結果如下:
array([119, 203, 238], dtype=uint8)
array([204], dtype=uint8) # 計算式(1)得 0.299*238+0.587*203+0.114* 119 = 204





以上全部內容參考書籍如下:
岡薩雷斯《數字影象處理(第三版)》
HSL和HSV色彩空間