計算機視覺(二) 常用顏色空間及其轉換

2021-08-21 07:42:11 字數 3955 閱讀 4290

在【計算機視覺(一)影象資料表示】中,我介紹了rgb灰度兩種顏色空間,並且介紹了畫素的概念以及在程式上如何訪問。

接下來介紹從rgb到灰度的轉換,以及兩種我常用的顏色空間hsv二值空間(嚴格來說屬於灰度,只是只有0和255兩個值)。

假如先不談原理,rgb轉灰度你會怎麼做?先從我們知道的資訊入手,rgb是三通道的,灰度只有乙個通道,很自然的會聯想到怎麼把三個通道「融合」成乙個通道,最直接的想法,也許是對於同乙個rgb畫素值,我們把這三個通道值求乙個平均值作為灰度值。用公式表示一下就是:gray = r * 1/3 + g * 1/ 3 + b * 1/3 。

好,那我們先來寫這個程式看看效果。

# coding: utf-8

import cv2

import numpy as np

'''函式名:rgb2gray_mean

功能:通過求通道平均值得到灰度圖

輸入:img 輸入的彩圖

返回:result 灰度圖

'''def

rgb2gray_mean

(img):

ratio = 1.0 / 3

# 轉換型別

int_img = img.astype(np.int32)

result = ratio * (int_img[...,0]+int_img[...,1]+int_img[...,2])

return result.astype(np.uint8)

# 程式入口

defmain

():# 讀取lena圖

# 轉灰度

gray = rgb2gray_mean(color)

# 顯示

cv2.imshow('color', color)

cv2.imshow('gray', gray)

cv2.waitkey(0)

if __name__ == '__main__':

main()

注意:在rgb2gray_mean函式中我對img做了乙個型別轉換並存放在int_img中,img的型別是numpy.uint8,也就是8位無符號整數,直接對裡面的值進行相加很可能造成數值溢位,也就是255+1會變成0,因此要先用乙個能容納更大的值範圍的矩陣裝起來,比如int32型別的。這是新手經常會遇到的坑,切記切記。

好那我們來看看執行效果,再一次使用lena測試。

執行的結果:

看起來還行。

opencv中也有自帶的轉換灰度的函式,cvtcolor,**也貼在這裡:

gray = cv2.cvtcolor(color, cv2.color_bgr2gray)
注意第二個引數是bgr2gray,是的,opencv中預設的彩圖通道排列是bgr(藍綠紅)而不是rgb,具體原因我也是道聽途說,是因為一開始相機製造商從sensor拿到的資料就是bgr的,這是他們制定的標準,儘管後來有很多軟體也是預設採用rgb。

那麼這個cvtcolor的效果怎麼樣呢,請看

不知道你能否看出區別,不能的話請注意看頭髮的明暗交界處,cvtcolor在本來該黑的地方更黑,該白的地方更白,就是對比度更強烈,還是看不出來的話用程式幫我們看看,數一下灰度值不相等的地方有多少個。

print np.sum(gray !=cv_gray)
結果是:244157, 原圖的大小是512x512,也就是總共262144個畫素點,那這麼看下來絕大部分的畫素值都不一樣,雖然我們看起來也要費點力才能看出來不同。這就說明opencv轉灰度的方法跟我們拍腦門想的是不一樣的,也就是對應到三個通道各自乘的係數是不一樣的,假設:

gray = a * r + b * g + c * b (a + b + c = 1)
a、b、c三個值應該怎麼取能讓影象看起來比較舒服呢?其實人眼對三原色的「偏好」是不一樣的,研究表明人眼對紅綠藍的權重接近3:6:1,更精確的,對於上面的公式,a=0.299,b=0.587,c=0.114,這就是通常所說的心理學模型。在opencv中,為了減少浮點運算(浮點運算在一般的cpu中很耗時),使用了類似下面的轉換方式:

''

'函式名:心理學模型轉換灰度

輸入:img 輸入的彩圖

返回:result 灰度圖'''

def rgb2gray_mental(img):

# 轉換型別

int_img = img.astype(np.int32)

result = (int_img[...,2]*299 + int_img[...,1]*587 + int_img[...,0]*114 + 500) / 1000

return result.astype(np.uint8)

經過測試,這跟opencv自帶的轉換函式cvtcolor的效果是一模一樣的。

hsv的值域跟rgb的並不一樣,其中h維度的值域是0-180,其他兩個維度都是0-255,h不取到0-360也許是因為超過了uchar的範圍。

hsv空間對顏色的描述是使用者友好的,而rgb是硬體友好的。hsv空間在我日常學習中更多是作為顏色篩選的基礎,人眼能區分的不同顏色的範圍對應hsv的值都比較固定,下面是乙個對照表:

現在舉個實際應用的案例,比如我要對下面的做車牌識別,我的第一步是要把車牌的區域摳出來,車牌的底色是藍色的,當然寶馬的標誌也有藍色,但我們可以不管三七二十一先把藍色的東西都摳出來再做篩選,這時候就可以用hsv空間。

剛讀入的時候是bgr格式的,這時候又要用到cvtcolor轉換到hsv,示例**如:

hsv = cv2.cvtcolor(bgr, cv2.color_bgr2hsv)
顯示hsv的效果如下:

現在我們要的是藍色區域,查詢上面的對照表就可以知道,我們要的是h值在100到124,s值在43到255,v值在46到255之間的畫素點。怎麼表達這個「要」跟「不要」呢?我們可以這麼考慮,對於每個畫素點只有「要」和「不要」兩種狀態,就像一盞燈的開關一樣,於是我們可以建立一幅等大的圖,在上面,「要」的畫素點設為乙個值,「不要」的畫素點設為另乙個值,這就是接下來要說的二值圖,我也喜歡稱其為掩碼圖。

二值圖本質上是灰度圖,只是只用了0和255兩個值,用0表示「不要」,255表示「要」,整幅圖看起來就是符合條件的區域是白色的,不符合的是黑色的。對上面的hsv圖作這種條件篩選處理,叫做二值化,opencv已經為我們準備了對應的函式cv2.inrange,示例**如下:

mask = cv2.inrange(hsv, np.array([100,43,46]), np.array([124,255,255]))
處理完的結果如下圖:

計算機視覺常用演算法整理

影象預處理演算法 1.影象梯度演算法sobel scharr 2.角點檢測演算法harris 3.邊緣檢測演算法canny 4.z直線檢測演算法hough 影象特徵處理演算法 1.sift 尺度不變特徵變換 2.surf 加速穩健特徵 3.hog 梯度直方圖 4.histogram 直方圖 5.lb...

python計算機視覺程式設計(二)

通過contour繪製影象輪廓以及list函式繪製影象直方圖 from pilimport image from pylab import 讀取影象到陣列中 新建乙個影象 figure 不使用顏色資訊 gray 在原點的左上角顯示輪廓影象 contour im,origin image axis e...

全景視覺空間直線檢測 計算機視覺 演算法與應用

2 塞利斯基,艾海舟.計算機視覺 演算法與應用 m 清華大學出版社,2012.作者給出的章節結構圖如下 從左至右分別是基於影象 2d 基於幾何形狀 3d 和基於光度學 表現 從上至下,建模和抽象的層次在增加,下層的方法基於上面所提的演算法基礎上發展。其中的處理和依賴關係不是嚴格有序的,還存在其它精細...