色彩描述 Color descriptor

        說書人將故事說得活靈活現、素描家把人物畫得栩栩如生,那麼將圖片描述得維妙維肖的角色就是Image descriptor了,只不過它的對象是只懂0與1的電腦,因此必須先將圖片內容予以量化才行。在影像辨識及電腦視覺中,這樣針對整體物件進行抽象描述量化取得資訊的方法,我們稱為「Descriptor」,若用於描述整張相片,稱為「Image descriptor」,用於描述圖片中某部份的特徵,則稱為「Feature descriptor」。

        這所謂descriptor的過程中,最重要的步驟是「Feature extraction」特徵萃取,它使用到各種複雜的規則、理論模型和方法,將一個實體物件抽像並量化,代之以一串數字來表示,這用以描述物件的數值被稱為feature vectors,或簡稱為我們熟知的features,它可能代表的是相片中某物體的形狀、顏色、材質…等等,我們也能將多種features合併使用,透過一串數字來描述物件的多種特徵。

        例如,假設我讀入一張500×800的相片,亦即給予電腦500×800個像素值,透過descriptor的運算,它會吐出一個長度為12(代表12維度)的陣列,每一維均代表其一種特徵值,我們可以把這串feature vectors陣列簡寫為12-d。

如下圖,我們可以透過descriptor得到整張相片的Feature vectors(箭頭右側),我們稱為Image descriptor,或是各個不同部位的feature vectors(箭頭下方),稱為Feature descriptor。

        Feature descriptor比起Image descriptor來說更為複雜,因為需要從整張相片中去描述某特定物件的特徵,而且這些物件常受到光影、色溫、旋轉、角度、移動…等等外在的影響而改變。常用的Feature descriptor手法有SIFT、SURF、ORB、BRISK、BRIEF、以及FREAK,每一種都相當值得深入分析及應用。

        下面我們將從影像中最單純也最簡單的Color特性,介紹並示範如何取得它的color feature來製作Descriptor。

Color Space

色彩是最直覺也最容易處理的特徵,而所謂的色彩空間Color space便是用來演繹色彩的工具。目前最常使用的Color space有RGB、L*A*B*、HSV、HSL以及LUV這幾種,其中以RGB最為常見,而HSV和L*A*B*相較之下更適合應用於電腦視覺領域。

以下面這張相片為例,這是由最近剛成立的Farmbot開源社群所提供的一張農地的蔬菜相片,我們試看看這張相片透過這三種色彩空間的角度,詮釋起來有什麼不同。

RGB 色彩空間

        其實上面這張圖就是用RGB來呈現的,這也是我們日常生活上最頻繁使用的格式,我們可以把RGB格式的相片拆解為如下的Red、Green、Blue三個color channels。

  

        這三個channels,圖中愈黑的代表該點像素強度愈低,愈亮(或愈白)則表示強度愈高。以下的各個色彩空間也是同樣的概念。

L*A*B* 色彩空間

        這是由透過LAB色彩空間所看到的樣子。

        我們一樣可以把它拆解為三個Channels:

        L:色彩的亮度(值愈大愈亮)

        A:由綠色到紅色的彩度(值愈大愈偏紅)

        B:由藍色到黃色的彩度(值愈大愈偏黃)

        下方由左至右依次為L、A、B channels。

  

L是純粹的亮度圖形,A channel中愈白的代表愈紅,愈黑的代表愈綠。B channel愈白的代表偏黃,反之愈黑的代表偏藍。

HSV 色彩空間

        透過HSV色彩空間所看到的相片如下。

        它也是由三個Channels所組成:

  • H:Hue,翻譯為色相,指的是顏色的顏色屬性,如紅、黑、黃色等等(不同顏色其值不同)。
  • S:指的是Saturation飽和度,越鮮豔的顏色代表其純度較高,S數值也愈高。
  • V:Value,指的是亮度或明度,數值愈大顏色愈亮。也有人用LLightness來取代Value,因此我們也會看到名稱為HSL色彩空間,但兩者稍有不同,可參考維基的說明: https://zh.wikipedia.org/wiki/HSL%E5%92%8CHSV%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4

分解各channel(由左至右分別為HSV channel)

  

        H channel代表各種不同的顏色值。S chennel代表鮮艷度,愈白的愈鮮艷,也就是愈接近純色。V channel則類似LBA色彩空間的L channel,也是指亮度。

HSL色彩空間

        HSL與HSV對色彩的詮釋相當類似,但是HSV應畫成圓錐形會更適合,因為它的明度是傾斜往中心愈亮而不是往上方。

「HSL color space」的圖片搜尋結果

        這是HSL的圖形,與屬性相近的HSV在色彩表現上有所差異。

分解各channel(由左至右分別為HSL channel),可看出HSV與HSL兩者在飽和度以及明亮度的詮釋上有所差異,亮度 channel的表現則相當接近。

  

LUV色彩空間

        LUV color space與LAB相當類似,都是一組channel定義亮度,另外二組channels定義色彩,但在影像處理的應用上使用Lab比較普遍,而LUV則多應用在照明系統。

        LUV色彩空間的三個channels,第一個channel是亮度(無顏色的強度),後兩個皆為色度(色彩的強度)。

  

        您可能注意到,為什麼以上這些色彩空間都是由三個channels(或視為三個維度)所組成的呢?因為這幾種方式都是屬於三度空間的色彩表示法,每一種顏色皆能由三種數值來表示。

image Color Descriptor

        實務上有這麼多種Color space,表示我們能透過各種對顏色表達的方式來取出相片中各種資訊。因此接下來,我們來試著作一個Descriptor,透過它將相片轉為指定的色彩空間,然後取出其中某部份或全部channels轉為可用的特徵值。此外,我們也能它也能針對相片中特定的物件取得其色彩特徵值,而不僅限於整張相片。

這個Color descriptor的步驟是:

  1. 將圖片依所選擇的color space分拆為三個channels,例如RGB圖片,我們可取得Red、Green、Blue channels,L*a*b*則可分成L、A、B Channels。
  2. 使用不同的方法計算各channel的統計值,例如直方圖、平均、標準差、峰值…等等。
  3. 將各統計值合併成list,作為描述該圖片的feature vectors。

程式說明

在libCH/descriptor.py檔案中,我們定義了一個描述色彩資訊的class:colorDescriptor,它可以載入相片、分析輪廓(contours)、轉換為特定的色彩空間、輸出該相片的色彩特徵值,另外,我們還可以指定要用計算Color channels的平均、標準差等數值,還是直方圖統計資訊的方式來產生特徵值。

第二種取用直方圖統計資訊的方式,相信會比僅取色彩的平均與標準差值能提供更多的特徵資訊,在描述相片上更能精確的反映圖片特徵。下列示範的程式已放置於https://github.com/ch-tseng/chlib 請自行參考,下面僅取其中一部份作說明:        


class colorDescriptor:
def __init__(self, debug=False):
self.image = None
#傳入的相片預設皆為RGB format
self.colorSpace = "RGB"
#使用者可選擇是否開啟偵錯,可得到更多的訊息
self.debug = debug

def getImage(self):
return self.image

#使用者在載入相片時,可選擇給予路徑名稱或圖片物件,也可對相片尺寸縮放。
def loadImage(self, objImage=None, imgPath=None, resize_w=None):
if ((objImage is None) and (imgPath is None)):
raise Exception('Please assign a value to objImage or imgPath.')
else:
if(objImage is None):
objImage = cv2.imread(imgPath)

objImage = imutils.resize(objImage, width = resize_w)
self.image = objImage

#第一種取色彩特徵的方式,使用cv2.meanStdDev計算指定channels的平均及變異數,組合起來化為一維陣列後回傳。
def channelFeatures1(self, colorSpace="RGB", channelSelect=(1,1,1)):
if(self.debug==True):
cv2.imshow("Original image", self.image)
cv2.waitKey(0)

self.image = toColorSpace(self.image, colorSpace, channelSelect, debug=self.debug)

(means, stds) = cv2.meanStdDev(self.image)
features = np.concatenate([means, stds]).flatten()

return features

#第二種取色彩特徵的方式,使用cv2.calcHis取得指定channels的直方圖統計資訊,組合起來化為一維陣列後回傳。
def histogramsFeatures1(self, colorSpace="RGB", channelSelect=(1,1,1), bins=[8,8,8], range=[0, 256, 0, 256, 0, 256]): #example: describe(channelSelect=(1,0,0))
if(self.debug==True):
cv2.imshow("Original image", self.image)
cv2.waitKey(0)

self.image = toColorSpace(self.image, colorSpace, channelSelect, self.debug)

hist = cv2.calcHist(self.image, [channelSelect[0], channelSelect[1], channelSelect[2]], None, bins, range)
features = cv2.normalize(hist).flatten()

return features

<p style="text-align: left; line-height: 1;">

Color descriptor的使用


#載入必要modules
import argparse
from libCH.descriptor import colorDescriptor

#提供以參數方式帶入相片
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())

#產生colorDescriptor物件,如果我們僅想要影像中的shapes特徵而非整張影像,那麼就要加入這些shapes開頭的參數, 否則便可不需設定
colorFeature = colorDescriptor(shapesBlur=11, shapesThreshold=(140,140,140), shapesInvert=False, debug=True)
#載入相片,尺寸縮小為800px寬度。
colorFeature.loadImage(imgPath=args["image"], resize_w=800)

接下來,您可以加入下方的指令範例來執行看看


#取得其LUV色彩空間,整張相片的三個channels的特徵值(使用平均和變異數)。

print colorFeature.channelFeatures1(colorSpace="LUV", channelSelect=(1,1,1))

開啟debug的執行結果:

取得的特徵值:[ 132.36014947 96.1513879 168.02029181 40.58375962 8.44855058 22.39251577]


#使用LAB色彩空間,取用A channels並抓取紅葉的蔬菜部份,取特徵值(使用平均和變異數)。

print colorFeature.channelFeatures1(colorSpace="LAB", putRGBLayers=True, onlyShapes=True, channelSelect=(0,1,0))

取得的特徵值:[ 0. 128.66947331    0. 0. 3.94719746 0. ]


#使用HSV色彩空間,取整張相片的H,S channels特徵值(使用直方圖資訊,各channel皆分為8個統計區段,數值範圍皆為0~256)。

print colorFeature.histogramsFeatures1(colorSpace="HSV", channelSelect=(1,1,0), bins=[8,8,8], range=[0, 256, 0, 256, 0, 256])

取得的特徵值:[ 0.90635216 0.03878825 0. 0.……中間省略 ….. 0.00129294 0.00905059 0.0465459 ]


#使用LAB色彩空間,取A,B channels,抓取紅葉與綠色植物部份的特徵值(使用直方圖資訊,各channel皆分為8個統計區段,數值範圍皆為0~256)。

print colorFeature.histogramsFeatures1(colorSpace="LAB", onlyShapes=True, channelSelect=(0,1,1), bins=[8,8,8], range=[0, 256, 0, 256, 0, 256])

取得的特徵值: [ 0.66450834  0.  0.  0.  ……中間省略….. 0.00398705  0.  0.  0. 0.05448968  0.  0. ]

實際應用

        最後,我們把剛剛寫好的color descriptor應用到之前曾用過的例子:使用非監督式學習的K-means來自動分類會議室的照片。注意下方的describe function,內容換成了呼叫我們剛剛所撰寫的descriptor library。

        將descriptor獨立出來,我們就可以像組合積木一樣,很方便的抽換某個機器學習模型的特徵描述來跑出不同的結果。例如下方範例為使用HSV colorspace,我們可以換成RGB、LAB…等色彩空間,也可以換成Histogram,或以後所增加的各類descriptor。


from sklearn.cluster import KMeans

import imutils

from imutils import paths

import numpy as np

import argparse

import cv2

from libCH.descriptor import colorDescriptor

&nbsp;

def describe(image):

colorFeature = colorDescriptor(shapesBlur=11, shapesThreshold=(140,140,150), shapesInvert=False, debug=False)

colorFeature.loadImage(objImage=image, resize_w=300)

return colorFeature.channelFeatures1(colorSpace="HSV", putRGBLayers=False, onlyShapes=False, channelSelect=(1,1,1))

&nbsp;

ap = argparse.ArgumentParser()

ap.add_argument("-d", "--dataset", required=True, help="path to the input dataset directory")

ap.add_argument("-k", "--clusters", type=int, default=2, help="# of clusters to generate")

args = vars(ap.parse_args())

&nbsp;

data = []

&nbsp;

imagePaths = list(paths.list_images(args["dataset"]))

imagePaths = np.array(sorted(imagePaths))

&nbsp;

for imagePath in imagePaths:

image = cv2.imread(imagePath)

image = imutils.resize(image, width = 350)

hist = describe(image)

data.append(hist)

執行:python ch-category.py -d office -k 7

第一組:

第二組:

第三組:

第四組:(下方僅列出其中15張)

第五組:(下方僅列出其中15張)

第六組:(下方僅列出其中15張)

第七組:

        分類結果與之前文章介紹K-means非監督式學習的結果相同,只不過我們這次是將Descriptor獨立出來,另外去引用並呼叫。

廣告

發表迴響

Please log in using one of these methods to post your comment:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s