前言
什么是直方圖?
直方圖是對數(shù)據(jù)的集合做統(tǒng)計(jì)秋茫,并將統(tǒng)計(jì)結(jié)果分布于一系列預(yù)定義的bins中史简。
例如:?
如果我按照某種方式去統(tǒng)計(jì)通道中的這些數(shù)字,會發(fā)生什么情況呢肛著?既然以知數(shù)字的范圍是包含256個(gè)色值(這里是8bit無符號四通道圖像 2^8 = 256)圆兵,我們可以將這個(gè)范圍分割成子區(qū)域(稱作 bins), 如:
[0, 255] = { [0, 15] U [16, 31]U ....U[240,255] }?
range = { bin_{1} U bin_{2} U ....U bin_{n = 15} }
然后在統(tǒng)計(jì)掉入每個(gè)bin中的像素?cái)?shù)目枢贿。采用這一方法來統(tǒng)計(jì)上面的數(shù)字矩陣殉农,我們可以得到下圖:(x軸表示bin,y軸表示各個(gè)bin中的像素個(gè)數(shù))局荚。
以上只是一個(gè)說明直方圖如何工作以及它的用處的簡單示例超凳。直方圖可以統(tǒng)計(jì)的不僅僅是顏色灰度, 它可以統(tǒng)計(jì)任何圖像特征 (如 梯度, 方向等等)耀态。
讓我們再來搞清楚直方圖的一些具體細(xì)節(jié):
dims: 需要統(tǒng)計(jì)的特征的數(shù)目轮傍, 在上例中, dims = 1 因?yàn)槲覀儍H僅統(tǒng)計(jì)了灰度值(灰度圖像)首装。
bins: 每個(gè)特征空間 子區(qū)段 的數(shù)目创夜,在上例中, bins = 16
range: 每個(gè)特征空間的取值范圍,在上例中仙逻, range = [0,255]
怎樣去統(tǒng)計(jì)兩個(gè)特征呢? 在這種情況下驰吓, 直方圖就是3維的了,x軸和y軸分別代表一個(gè)特征系奉, z軸是掉入 (bin_{x}, bin_{y}) 組合中的樣本數(shù)目檬贰。 同樣的方法適用于更高維的情形 (當(dāng)然會變得很復(fù)雜。
OpenCV的直方圖計(jì)算
OpenCV提供了一個(gè)簡單的計(jì)算數(shù)組集(通常是圖像或分割后的通道)的直方圖函數(shù) calcHist 喜最。 支持高達(dá) 32 維的直方圖。下面的代碼演示了如何使用該函數(shù)計(jì)算直方圖!
基本的邏輯就是將一張圖像通道化庄蹋,計(jì)算各通道圖像的直方圖并返回顯示瞬内。
首先將UIImage對象轉(zhuǎn)成OpenCV Mat 數(shù)據(jù)結(jié)構(gòu):
Mat img = [FaceDetection CVMatFromUIImage:image];//這段代碼OpenCV已經(jīng)寫好了
然后我們需要將Mat圖像數(shù)據(jù)通道化:
cv::split(img, img_channels);
CV_EXPORTS void split(const Mat& src, Mat* mvbegin);
@param src input multi-channel array.
@param mvbegin output array; the number of arrays must match src.channels(); the arrays themselves arereallocated, if needed.
意思就是傳一個(gè)多通道圖像迷雪,傳出一個(gè)裝載各通道的數(shù)組。
接著就需要通過直方圖CvHistogram類來處理每一個(gè)通道數(shù)據(jù)虫蝶。
CVAPI(CvHistogram*)? cvCreateHist( int dims, int* sizes, int type,float** ranges CV_DEFAULT(NULL),int uniform CV_DEFAULT(1));API是有這個(gè)函數(shù)??
@param dims Number of histogram dimensions.這參數(shù)前言中已經(jīng)提到過章咧。
@param sizes Array of the histogram dimension sizes. 就相當(dāng)于 bins?
@param type Histogram representation format. CV_HIST_ARRAY means that the histogram data is?represented as a multi-dimensional dense array CvMatND. CV_HIST_SPARSE means that histogram data?is represented as a multi-dimensional sparse array CvSparseMat.直方圖疏密程度
@param ranges Array of ranges for the histogram bins. Its meaning depends on the uniform parameter?value. The ranges are used when the histogram is calculated or backprojected to determine which .
@param uniform.....這里看都不用看了??因?yàn)橥ㄟ^我的實(shí)驗(yàn)OpenCV 3.2里只有下邊這個(gè)函數(shù)
那我說如果我?guī)拙托枰肦ange uniform這些呢?
CVAPI(void)? cvSetHistBinRanges( CvHistogram* hist, float** ranges,int uniform CV_DEFAULT(1));
cvSetHistBinRanges(CvHistogram *hist, float **ranges)
又騙我能真???赁严。我感覺它這些函數(shù)有規(guī)律的,只要有CV_DEFAULT的這些參數(shù)的粉铐,就不需要填疼约,它知道你也填DEFAULT,就幫你填好了蝙泼,當(dāng)然你填了就調(diào)用的你填的參數(shù)程剥,很強(qiáng)!
接下來就需要調(diào)用Histogram類的計(jì)算直方圖方法:
CVAPI(void)? cvCalcArrHist( CvArr** arr, CvHistogram* hist,int accumulate CV_DEFAULT(0),const CvArr* mask CV_DEFAULT(NULL) );/** @overload */
CV_INLINE? void? cvCalcHist( IplImage** image, CvHistogram* histint accumulate CV_DEFAULT(0),const CvArr* mask CV_DEFAULT(NULL) ){
cvCalcArrHist( (CvArr**)image, hist, accumulate, mask );
}
給了一個(gè)重載方法汤踏。我們用重載函數(shù)就好了织鲸。需要說的是 CvArr,IplImage溪胶,CvMat搂擦,其實(shí)是一個(gè)東西,它自己沒說哗脖,但確實(shí)有人說了??:
§ CvArr -This is the "metatype" used only as a function parameter.
It denotes that the function accepts arrays of multiple types, such as IplImage*, CvMat* or even CvSeq* sometimes. The particular array type is determined at runtime by analyzing the first 4 bytes of the header. In C++ interface the role of CvArr is played by InputArray and OutputArray.
我們就可以這樣想:到這里channel里的圖像數(shù)據(jù)已經(jīng)被Histogram做好Collection了瀑踢,現(xiàn)在需要做的就是拿出bins繪制圖像。需要注意的是懒熙,在IplImage結(jié)構(gòu)體中有這樣一個(gè)屬性int origin.
int? origin;? ? ? ? ? ? /**< 0 - top-left origin,1 - bottom-left origin (Windows bitmaps style).? */我是這樣理解的:你給我的圖片有可能是從下邊開始計(jì)算的丘损,不一定所有的IplImage都是從左上角開始計(jì)算的。
然后就比如我現(xiàn)在創(chuàng)建一個(gè)畫布:
IplImage *image = cvCreateImage(cvSize(256, 80), 8, 1);cvSetZero(image);
獲取bins開始繪圖工扎。
float histValue? ? = cvGetReal1D(hist->bins, i);
float histNextVable = cvGetReal1D(hist->bins, i+1);
這個(gè)畫出來的圖像如果使用cvFillConvexPoly填充的時(shí)候就是藍(lán)色線條上半部分徘钥。
cvFillConvexPoly(image, points, numPts, cvScalar(255));
那畫下半部分就很簡單了,將得到第i個(gè)點(diǎn) 使用size Max y - i.bins 就是相反的圖像么肢娘。???
OpenCV的直方圖均衡化
直方圖均衡化處理的“中心思想”是把原始圖像的灰度直方圖從比較集中的某個(gè)灰度區(qū)間變成在全部灰度范圍內(nèi)的均勻分布呈础。
使用起來很簡單
那么效果怎樣呢?
基本邏輯:將一張圖像均衡化橱健,然后輸出顯示而钞。
po:我突然發(fā)現(xiàn),只要代碼思路清晰拘荡,寫起代碼很舒服??臼节。
OpenCV的直方圖對比
其實(shí)對于直方圖對比,就是按照enum cv::HistCompMethods標(biāo)準(zhǔn)取相似度。拿出待比對的bins與基準(zhǔn)圖像的bins求交集嘛??网缝。
就單單兩張相同的圖片巨税,如果調(diào)整一下亮度,相似度就下來了粉臊。
需要注意的是相關(guān)性不能證明因果關(guān)系,盡管它可能符合因果關(guān)系草添。下面就介紹一下這幾個(gè)Methods??。
HISTCMP_CORREL
Correlation (co-relation) refers to the degree of relationship (or dependency) between two variables.
Linear correlation refers to straight-line relationships between two variables.
A correlation can range between -1 (perfect negative relationship) and +1 (perfect positive relationship), with 0 indicating no straight-line relationship. -出處?學(xué)術(shù)文檔看起來總是很清晰扼仲。
相關(guān)系數(shù)是用以反映變量之間相關(guān)關(guān)系密切程度的統(tǒng)計(jì)指標(biāo).
??解釋一下吧:
HISTCMP_CHISQR
A Pearson's chi-square test can be used as an inferential test of the independence of two nominal variables.出處 這個(gè)屌,尤其是對例子的解析??屠凶。
用來監(jiān)測實(shí)際觀測值與理論推斷值之間的偏離程度驰后。其根本思想就是在于比較理論頻數(shù)和實(shí)際頻數(shù)的吻合程度或擬合優(yōu)度問題。
If you wanted to test a die to see whether it’s a fair die, what would you do?
Class Answers: Roll it over and over and see what kind of distribution you get
此處很經(jīng)典阅畴,我叫我王牌翻譯來翻譯一下:
王牌翻譯說:如果你想要測試一個(gè)死之人是否害怕死亡你會怎么做倡怎???一遍一遍去實(shí)驗(yàn)。
我覺得我得把文檔中的這個(gè)example用我的語言Roll一次贱枣。
如果你要推測一場死亡屬于正常死亡监署,你會怎么做?讓他再活一次纽哥?
假設(shè)我們使他復(fù)活了60次钠乏,那你會用什么樣的理由去接受其中的一次死亡屬于正常死亡?對數(shù)據(jù)分組 1/6 春塌?取其中的10次晓避?很顯然這個(gè)方法很愚蠢。本來60次就不怎么可靠只壳,然后你再去隨機(jī)取其中的10次俏拱?
??解釋一下吧:
我覺得我解釋明白了,如果你還沒有看明白吼句,點(diǎn)這里吧锅必。
HISTCMP_INTERSECT
這個(gè)就不用說了,單單就這個(gè)英文單詞就能解釋:交集么惕艳。
HISTCMP_BHATTACHARYYA
在統(tǒng)計(jì)中搞隐,Bhattacharyya距離測量兩個(gè)離散或連續(xù)概率分布的相似性。它與衡量兩個(gè)統(tǒng)計(jì)樣品或種群之間的重疊量的Bhattacharyya系數(shù)密切相關(guān)远搪。原文點(diǎn)這里
HISTCMP_HELLINGER
在概率論和統(tǒng)計(jì)理論中劣纲,Hellinger距離被用來度量兩個(gè)概率分布的相似度。它是f散度的一種(f散度——度量兩個(gè)概率分布相似度的指標(biāo))
總之谁鳍,這些屬性都是來判斷兩組數(shù)據(jù)的相關(guān)性癞季。
總結(jié)
那么圖像直方圖有什么用劫瞳?其實(shí)我也是百度了好多的文章,說的意思很多绷柒。
對圖像進(jìn)行分析柠新、觀察,形成一個(gè)有效的處理方法
就我的理解:
1.對于純色圖像來說辉巡,在直方圖中只顯示一條柱狀,一個(gè)bins蕊退。
2.對于圖像來說郊楣,如果圖像的峰值偏左,bins 集合會偏向0瓤荔;相反净蚤,如果圖像的峰值偏右,圖像bins集合偏向255输硝;
3.直方圖具有二峰性今瀑,這表明這個(gè)圖像有較亮和較暗的區(qū)域。
最重要的一點(diǎn)是這個(gè)可以做特征提取点把。
我感覺檢測某個(gè)圖像中: 是真實(shí)的人臉橘荠、還是照片中的人臉,判斷背景區(qū)域的直方圖就好了郎逃。如果拿著照片去充當(dāng)人臉哥童,那么直方圖中會出現(xiàn)多個(gè)峰值。
對于前景圖像和背景圖像比較接近的圖像可以使用直方圖均衡化褒翰,修改對比度贮懈。