[EmguCV|C#]使用EmguCV的DenseHistogram類別計算與紀錄圖像直方圖-直方圖(Histogram)系列(2)

来源:互联网 发布:梦里花落知多少李茉莉 编辑:程序博客网 时间:2024/06/15 21:30

http://www.dotblogs.com.tw/v6610688/archive/2013/12/21/emgucv_calculate_histogram_by_densehistogram.aspx

前言


在前篇,提到了我們在做影像處理時會需要擁有影像的直方圖色彩分布資料,來做一些運算,例如:反投影來比對兩張圖象的色彩分布相似度,並且過濾掉不太可能相似的圖像等

在這篇,我們會使用到EmguCV所提供的專門處理直方圖相關工作的DenseHistogram類別

直方圖介紹


直方圖說穿了其實就是資料的統計圖而已,而在影像上常被用來做色彩分布的統計用。

Histogram_of_arrivals_per_minute.svg

縱軸我們稱它為樣本數量,橫軸則是樣本的屬性值(例如要計算的屬性是抵達的分鐘),縱軸則代表可能抵達的次數)

而在色彩分布上,橫軸是像素點的數值(從0 – 255 ),縱軸則是像素值在這張影像上各有多少一樣的像素點的總值

或許有人會好奇「直方圖」與「長條圖」的差異在哪裡,其中直方圖的的資料是「是連續的」,所以橫軸的數值會是連續的,有一個順序姓

長條圖則是不連續的(又稱類別資料),橫軸的類別只有相同或不同的關聯,沒有順序性(如下是各國國家的類別)

Incarceration_Rates_Worldwide_ZP.svg

使用EmguCV的DenseHistorgam計算直方圖


這邊我們程式中使用到的loadImg變數是前一個文章所定義EmguCV保存圖片的資料結構

以下這段程式碼

view source
print?
01private DenseHistogram CalHistBlue()
02        {
03            //計算Blue單通道
04            intBbin = 8; //切割量化的數量
05            RangeF BRange =new RangeF(0,255);
06            DenseHistogram blueHist =new DenseHistogram(Bbin, BRange);
07            //參數一是要計算的顏色資料,這邊分割通道並取得Blue通道的顏色;依序[1]:Green->[2]:Red
08            blueHist.Calculate(newIImage[] { loadImg.Split()[0] }, false,null);
09            returnblueHist;
10        }

在這邊我們計算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)

view source
print?
1blueHist.Calculate(newIImage[] { loadImg.Split()[0] }, false,null);

最後使用內建直方圖繪製工具,就會出現如下的圖片

show 8 bin blue channel histogram

直方圖的多通道計算或不同色彩空間


1.多通道

除了計算單的通道外,也可同時計算多通道直方圖

如下是我們計算Blue與Green的程式

view source
print?
01private DenseHistogram CalHistBlueGreenHist() {
02    //計算Blue-Green單通道
03    int[] BGbins = { 16, 16 };//切割量化的數量
04    RangeF[] BGRanges =new RangeF[] {new RangeF(0, 255),new RangeF(0, 255) };
05    DenseHistogram bgHist =new DenseHistogram(BGbins, BGRanges);
06    //填入Blue-Green通道的顏色圖像
07    bgHist.Calculate(newIImage[] { loadImg.Split()[0], loadImg.Split()[1] }, false, null);
08 
09    returnbgHist;
10}

因為多了一個Green通道,所以也要去多考慮Green通道的Bin與Range

然後在

view source
print?
1bgHist.Calculate(newIImage[] { loadImg.Split()[0], loadImg.Split()[1] }, false, null);

我們也要多切割出Green的通道影像資料來計算

2.不同色彩空間計算-HSV色彩空間

HSV色彩空間和RGB的空間分布顏色圖如下

RGB色彩空間:                                                                 HSV色彩空間:

RGB_color_solid_cube      330px-HSV_cone

其中你會看到RGB的色彩分布是混再一起的,單個通道不畫足夠表現出完整的色彩

而HSV(Hue – Saturation - Value)則是把顏色與飽和度還有明暗度分離,所以Hue除了無法表達黑->灰->白以外,其餘的各大色彩足夠表示

借用Wiki的解說

Hue:色相(H)是色彩的基本屬性,就是平常所說的顏色名稱,如紅色、黃色等。(顏色也就是可見光:紅橙黃綠青藍紫)

Saturation :飽和度(S)是指色彩的純度,越高色彩越純,低則逐漸變灰,取0-100%的數值。

Value:明度(V),亮度(L),取0-100%。

所以通常如果你的色彩辨識不希望考慮到明暗度的話,就可以使用HSV空間,並只去辨識一張影像中Hue的色彩分布相似度

以下是HSV色彩空間中的Hue直方圖計算

view source
print?
01private DenseHistogram CalHistHueHist()
02{
03          //計算Hsv的H-S
04          int[] Huebins = { 8};//切割量化的數量{HBin,SBin}
05          RangeF[] HueRanges =new RangeF[] {new RangeF(0, 180) };//H
06          DenseHistogram hsHist =new DenseHistogram(Huebins, HueRanges);
07          //填入H-S通道的顏色圖像
08          hsHist.Calculate(newIImage[] { loadImg.Convert< Hsv, byte>().Split()[0] }, false,null);
09 
10}

這邊會看到一個有趣的事情是,色相Hue明明是在0~360度,為何會給他180呢?

因為當我們把色彩空間做轉換後,放到的資料結構預設是8bit,而為了符合在這個大小下,會把Hue/2 => 180度的Range

而飽和度Saturation 與明度Value原本的百分比是以(0-1)表示法也會變成0-255

如下是OpenCV中的CvtColor解釋(EmguCV是從新包裝OpenCV,所以核心要看OpenCV):

hsv range in data type

另外,以下此行是先轉換到HSV的色彩空間在做計算

view source
print?
1hsHist.Calculate(newIImage[] { loadImg.Convert< Hsv, byte>().Split()[0] }, false,null);

然後如下圖會看到色彩分布的圖形不一樣

show_hue_blue color

用有自己繪製的直方圖來看一下會是這樣(和上面的Hue分布很像):

hsv_h_histogram

HSV色彩空間中的HS直方圖計算:

view source
print?
01private DenseHistogram CalHistHSHist() {
02            //計算Hsv的H-S
03            int[] HSbins = { 8, 16 };//切割量化的數量{HBin,SBin}
04            RangeF[] HSRanges =new RangeF[] {new RangeF(0, 180),new RangeF(0, 255) };//H,S
05            DenseHistogram hsHist =new DenseHistogram(HSbins, HSRanges);
06            //填入H-S通道的顏色圖像
07            hsHist.Calculate(newIImage[] { loadImg.Convert< Hsv, byte>().Split()[0], loadImg.Convert< Hsv, byte>().Split()[1] }, false,null);
08 
09            returnhsHist;
10}

不過....使用DenseHistogram的資料結構如果是多通道的話,無法在HistogramViewer與HistogramBox顯示(試過行不通),所以這邊我用自己會的結果來看

這邊會看到主要色彩分成八大塊,然後每一塊的顏色會有亮度條(共16條)即是飽和度的Bin數量

hsv_hs_histogram

HelloHistogramForm_calHistogramByDenseHistogram.zip

結論


希望透過這篇文章讓想要使用、計算直方圖的朋友可以更加瞭解,也希望以後可以不要忘了直方圖這基本的影像應用

下一篇會介紹如何使用CvInvoke(直接調用openCV的函式)來計算直方圖

PS:以上文章圖片如果沒有包含本部落格的簽名,皆是取自網路

0 0
原创粉丝点击