在前篇,提到了我們在做影像處理時會需要擁有影像的直方圖色彩分布資料,來做一些運算,例如:反投影來比對兩張圖象的色彩分布相似度,並且過濾掉不太可能相似的圖像等
在這篇,我們會使用到EmguCV所提供的專門處理直方圖相關工作的DenseHistogram類別
前言
在前篇,提到了我們在做影像處理時會需要擁有影像的直方圖色彩分布資料,來做一些運算,例如:反投影來比對兩張圖象的色彩分布相似度,並且過濾掉不太可能相似的圖像等
在這篇,我們會使用到EmguCV所提供的專門處理直方圖相關工作的DenseHistogram類別
直方圖介紹
直方圖說穿了其實就是資料的統計圖而已,而在影像上常被用來做色彩分布的統計用。
縱軸我們稱它為樣本數量,橫軸則是樣本的屬性值(例如要計算的屬性是抵達的分鐘),縱軸則代表可能抵達的次數)
而在色彩分布上,橫軸是像素點的數值(從0 – 255 ),縱軸則是像素值在這張影像上各有多少一樣的像素點的總值
或許有人會好奇「直方圖」與「長條圖」的差異在哪裡,其中直方圖的的資料是「是連續的」,所以橫軸的數值會是連續的,有一個順序姓
長條圖則是不連續的(又稱類別資料),橫軸的類別只有相同或不同的關聯,沒有順序性(如下是各國國家的類別)
使用EmguCV的DenseHistorgam計算直方圖
這邊我們程式中使用到的loadImg變數是前一個文章所定義EmguCV保存圖片的資料結構
以下這段程式碼
private DenseHistogram CalHistBlue()
{
//計算Blue單通道
int Bbin = 8; //切割量化的數量
RangeF BRange = new RangeF(0,255);
DenseHistogram blueHist = new DenseHistogram(Bbin, BRange);
//參數一是要計算的顏色資料,這邊分割通道並取得Blue通道的顏色;依序[1]:Green->[2]:Red
blueHist.Calculate(new IImage[] { loadImg.Split()[0] }, false, null);
return blueHist;
}
在這邊我們計算Blue通道的色彩分布,其中你會看到我們初始化DenseHistogram會需要輸入兩個參數,先看第二個BRange其實就是橫軸的起始數值到最大數值,而0-255剛好就是顏色的像素值範圍,所以我們要統計Blue通道的像素值分布狀況
再來是第一個參數,Bbin-是用來量化的數量,也就是我們可以把直方圖的區間切割出來,這邊設定8,換句話說就是約0-32,33-64,64-96等等這樣切出8個區間,最後只要是像素值在0-32中間的就會落到這個區塊,或像是像素值68會落在64-96這個區間,這樣的目的就是看你的色彩分布要記錄的多細緻,如果我只想要知道大概區塊的色彩,Bbin就可以切小一點
而這行則是透過index拿出Blue通道的影像(EmguCV通常使用的順序是Bgr所以index = 0 表示Blue)
blueHist.Calculate(new IImage[] { loadImg.Split()[0] }, false, null);
最後使用內建直方圖繪製工具,就會出現如下的圖片
直方圖的多通道計算或不同色彩空間
1.多通道
除了計算單的通道外,也可同時計算多通道直方圖
如下是我們計算Blue與Green的程式
private DenseHistogram CalHistBlueGreenHist() {
//計算Blue-Green單通道
int[] BGbins = { 16, 16 }; //切割量化的數量
RangeF[] BGRanges = new RangeF[] { new RangeF(0, 255), new RangeF(0, 255) };
DenseHistogram bgHist = new DenseHistogram(BGbins, BGRanges);
//填入Blue-Green通道的顏色圖像
bgHist.Calculate(new IImage[] { loadImg.Split()[0], loadImg.Split()[1] }, false, null);
return bgHist;
}
因為多了一個Green通道,所以也要去多考慮Green通道的Bin與Range
然後在
bgHist.Calculate(new IImage[] { loadImg.Split()[0], loadImg.Split()[1] }, false, null);
我們也要多切割出Green的通道影像資料來計算
2.不同色彩空間計算-HSV色彩空間
HSV色彩空間和RGB的空間分布顏色圖如下
RGB色彩空間: HSV色彩空間:
其中你會看到RGB的色彩分布是混再一起的,單個通道不畫足夠表現出完整的色彩
而HSV(Hue – Saturation - Value)則是把顏色與飽和度還有明暗度分離,所以Hue除了無法表達黑->灰->白以外,其餘的各大色彩足夠表示
借用Wiki的解說
Hue:色相(H)是色彩的基本屬性,就是平常所說的顏色名稱,如紅色、黃色等。(顏色也就是可見光:紅橙黃綠青藍紫)
Saturation :飽和度(S)是指色彩的純度,越高色彩越純,低則逐漸變灰,取0-100%的數值。
Value:明度(V),亮度(L),取0-100%。
所以通常如果你的色彩辨識不希望考慮到明暗度的話,就可以使用HSV空間,並只去辨識一張影像中Hue的色彩分布相似度
以下是HSV色彩空間中的Hue直方圖計算
private DenseHistogram CalHistHueHist()
{
//計算Hsv的H-S
int[] Huebins = { 8}; //切割量化的數量{HBin,SBin}
RangeF[] HueRanges = new RangeF[] { new RangeF(0, 180) }; //H
DenseHistogram hsHist = new DenseHistogram(Huebins, HueRanges);
//填入H-S通道的顏色圖像
hsHist.Calculate(new IImage[] { loadImg.Convert< Hsv, byte >().Split()[0] }, false, null);
}
這邊會看到一個有趣的事情是,色相Hue明明是在0~360度,為何會給他180呢?
因為當我們把色彩空間做轉換後,放到的資料結構預設是8bit,而為了符合在這個大小下,會把Hue/2 => 180度的Range
而飽和度Saturation 與明度Value原本的百分比是以(0-1)表示法也會變成0-255
如下是OpenCV中的CvtColor解釋(EmguCV是從新包裝OpenCV,所以核心要看OpenCV):
另外,以下此行是先轉換到HSV的色彩空間在做計算
hsHist.Calculate(new IImage[] { loadImg.Convert< Hsv, byte >().Split()[0] }, false, null);
然後如下圖會看到色彩分布的圖形不一樣
用有自己繪製的直方圖來看一下會是這樣(和上面的Hue分布很像):
HSV色彩空間中的HS直方圖計算:
private DenseHistogram CalHistHSHist() {
//計算Hsv的H-S
int[] HSbins = { 8, 16 }; //切割量化的數量{HBin,SBin}
RangeF[] HSRanges = new RangeF[] { new RangeF(0, 180), new RangeF(0, 255) }; //H,S
DenseHistogram hsHist = new DenseHistogram(HSbins, HSRanges);
//填入H-S通道的顏色圖像
hsHist.Calculate(new IImage[] { loadImg.Convert< Hsv, byte >().Split()[0], loadImg.Convert< Hsv, byte >().Split()[1] }, false, null);
return hsHist;
}
不過....使用DenseHistogram的資料結構如果是多通道的話,無法在HistogramViewer與HistogramBox顯示(試過行不通),所以這邊我用自己會的結果來看
這邊會看到主要色彩分成八大塊,然後每一塊的顏色會有亮度條(共16條)即是飽和度的Bin數量
HelloHistogramForm_calHistogramByDenseHistogram.zip
結論
希望透過這篇文章讓想要使用、計算直方圖的朋友可以更加瞭解,也希望以後可以不要忘了直方圖這基本的影像應用
下一篇會介紹如何使用CvInvoke(直接調用openCV的函式)來計算直方圖
PS:以上文章圖片如果沒有包含本部落格的簽名,皆是取自網路
參考資料
http://en.wikipedia.org/wiki/Histogram
http://zh.wikipedia.org/wiki/%E6%9D%A1%E5%BD%A2%E7%BB%9F%E8%AE%A1%E5%9B%BE
http://www.945enet.com.tw/main/elementaryschool.asp?U_BC=MATH&U_CCG=A&U_CC=01&FILE_ID=852
http://zh.wikipedia.org/wiki/File:RGB_color_solid_cube.png
http://zh.wikipedia.org/wiki/HSL%E5%92%8CHSV%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4
http://zh.wikipedia.org/wiki/%E9%A2%9C%E8%89%B2
http://en.wikipedia.org/wiki/Hue
文章中的敘述如有觀念不正確錯誤的部分,歡迎告知指正 謝謝 =)
另外要轉載請附上出處 感謝