OpenCV圖像處理之直方圖計(jì)算

概念:
圖像直方圖是反映一個(gè)圖像像素分布的統(tǒng)計(jì)表,其橫坐標(biāo)代表了圖像像素的種類(lèi),可以是灰度的,也可以是彩色的卵贱。縱坐標(biāo)代表了每一種顏色值在圖像中的像素總數(shù)或者占所有像素個(gè)數(shù)的百分比瓦侮。
圖像是由像素構(gòu)成艰赞,因?yàn)榉从诚袼胤植嫉闹狈綀D往往可以作為圖像一個(gè)很重要的特征佣谐。在實(shí)際工程中肚吏,圖像直方圖在特征提取、圖像匹配等方面都有很好的應(yīng)用狭魂。

OpenCV的直方圖計(jì)算:
OpenCV提供了一個(gè)簡(jiǎn)單的計(jì)算數(shù)據(jù)集(通常是圖像或分割后的通道)的直方圖函數(shù):

void calcHist(const cv::Mat *images,
     int nimages,
     const int *channels,
     InputArray mask,
     OutputArray hist,
     int dims,
     const int *histSize,
     const float **ranges);

下面直接代碼演示使用該函數(shù)計(jì)算直方圖!

// 命名空間
    using namespace cv;
    using namespace std;
    
    // 加載圖片
    image = [UIImage imageNamed:@"yixiao"];
    
    // UIImage -> Mat
    UIImageToMat(image, cvImage);
    
    if (!cvImage.data) {
        return;
    }

    // 用來(lái)存放分割的單通道圖像:vector(向量): C++中的一種數(shù)據(jù)結(jié)構(gòu),確切的說(shuō)是一個(gè)類(lèi).它相當(dāng)于一個(gè)動(dòng)態(tài)的數(shù)組,當(dāng)程序員無(wú)法知道自己需要的數(shù)組的規(guī)模多大時(shí),用其來(lái)解決問(wèn)題可以達(dá)到最大節(jié)約空間的目的.
    vector<Mat> rgb_planes;
    
    // 分割成R, G, B 3個(gè)單通道圖像
    split(cvImage, rgb_planes);
    /*
     void split(const cv::Mat &src, cv::Mat *mvbegin)
     OpenCV中的通道分離函數(shù)
     參數(shù)說(shuō)明:
     const cv::Mat &src -- 要進(jìn)行分離的圖像矩陣
     cv::Mat *mvbegin -- 輸出的則是Mat類(lèi)型的的向量
     */    

    // 設(shè)定bin數(shù)
    int histSize = 255;
    
    // 設(shè)定像素值范圍
    float rang[] = {0,255};
    
    // 設(shè)定每個(gè)區(qū)間的范圍
    const float *histRange = {rang};
    
    // calcHist函數(shù)的最后兩個(gè)參數(shù)值
    bool uniform = true;
    bool accumulate = false;
    
    Mat r_hist,g_hist,b_hist;
    
    // 計(jì)算直方圖
    calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
    calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
    calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
    /*
     void calcHist(const cv::Mat *images,
     int nimages,
     const int *channels,
     InputArray mask,
     OutputArray hist,
     int dims,
     const int *histSize,
     const float **ranges);
     參數(shù)說(shuō)明:
     const cv::Mat *images -- 輸入數(shù)組(或數(shù)組集)
     int nimages -- 要計(jì)算直方圖的圖像的個(gè)數(shù),此函數(shù)可以為多圖像求直方圖,通常nimages=1罚攀。
     const int *channels -- 圖像的通道党觅,它是一個(gè)數(shù)組,如果是灰度圖像則channels[1]={0};如果是彩色圖像則channels[3]={0,1,2}斋泄;如果是只是求彩色圖像第2個(gè)通道的直方圖杯瞻,則channels[1]={1};
     InputArray mask -- 是一個(gè)遮罩圖像用于確定哪些點(diǎn)參與計(jì)算,實(shí)際應(yīng)用中是個(gè)很好的參數(shù)炫掐,默認(rèn)情況我們都設(shè)置為一個(gè)空?qǐng)D像魁莉,即:Mat()。
     OutArray hist -- 計(jì)算得到的直方圖
     int dim -- 得到的直方圖的維數(shù)募胃,灰度圖像為1維旗唁,彩色圖像為3維。
     const int* histSize -- 每個(gè)維度的bin數(shù)目
     const float** ranges -- 這是一個(gè)二維數(shù)組痹束,用來(lái)指出每個(gè)區(qū)間的范圍检疫。
     后面兩個(gè)參數(shù)都有默認(rèn)值,uniform參數(shù)表明直方圖是否等距祷嘶,最后一個(gè)參數(shù)與多圖像下直方圖的顯示與存儲(chǔ)有關(guān)屎媳。
     */
    
    // 創(chuàng)建直方圖畫(huà)布
    int hist_w = 400; int hist_h = 400;
    int bin_w = cvRound( (double) hist_w/histSize );
    
    Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );
    
    // 將直方圖歸一化到范圍 [ 0, histImage.rows ]
    normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    /*
     歸一化函數(shù):http://blog.csdn.net/lanmeng_smile/article/details/49903865
     為了作圖,原來(lái)很難在一張圖上作出來(lái)论巍,歸一化后就可以很方便的給出圖上的相對(duì)位置等
     void normalize(InputArray src,OutputArray dst, double alpha = 1, double beta = 0, int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray())
     參數(shù)說(shuō)明:把需要處理的數(shù)據(jù)經(jīng)過(guò)處理后(通過(guò)某種算法)限制在你需要的一定范圍內(nèi)
     InputArray src -- 輸入數(shù)組
     OutputArray dst -- 輸出數(shù)組
     double alpha = 1 -- range normalization模式的最小值
     double beta = 0 -- range normalization模式的最大值烛谊,不用于norm normalization(范數(shù)歸一化)模式
     int norm_type -- 歸一化的類(lèi)型,可以有以下的取值:
                      NORM_MINMAX:數(shù)組的數(shù)值被平移或縮放到一個(gè)指定的范圍嘉汰,線性歸一化晒来,一般較常用。
                      NORM_INF: 此類(lèi)型的定義沒(méi)有查到郑现,根據(jù)OpenCV 1的對(duì)應(yīng)項(xiàng)湃崩,可能是歸一化數(shù)組的C-范數(shù)(絕對(duì)值的最大值)
                      NORM_L1 :  歸一化數(shù)組的L1-范數(shù)(絕對(duì)值的和)
                      NORM_L2: 歸一化數(shù)組的(歐幾里德)L2-范數(shù)
     int dtype -- type為負(fù)數(shù)時(shí),輸出數(shù)組的type與輸入數(shù)組的type相同接箫,否則攒读,輸出數(shù)組與輸入數(shù)組只是通道數(shù)相同,而tpye=CV_MAT_DEPTH(dtype)
     InputArray mask -- 操作掩膜辛友,用于指示函數(shù)是否僅僅對(duì)指定的元素進(jìn)行操作
     */
    
    // 在直方圖畫(huà)布上畫(huà)出直方圖
    for( int i = 1; i < histSize; i++ )
    {
        line( histImage, cvPoint( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
             cvPoint( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
             Scalar( 0, 0, 255), 2, 8, 0  );
        
        line( histImage, cvPoint( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
             cvPoint( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
             Scalar( 0, 255, 0), 2, 8, 0  );
        
        line( histImage, cvPoint( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
             cvPoint( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
             Scalar( 255, 0, 0), 2, 8, 0  );
    }
    /*
     int cvRound(double value):對(duì)一個(gè)double型的數(shù)進(jìn)行四舍五入薄扁,并返回一個(gè)整型數(shù)
     
     void cvLine( CvArr* img,CvPoint pt1,CvPoint pt2,CvScalar color,int thickness=1,int line_type=8,int shift=0 )
     參數(shù)說(shuō)明:
     CvArr* img -- 要?jiǎng)澋木€所在的圖像
     CvPoint pt1 -- 直線起點(diǎn)
     CvPoint pt2 -- 直線終點(diǎn)
     CvScalar color -- 直線的顏色
     int thickness -- 線條粗細(xì)
     int line_type -- 線段的類(lèi)型,可以取值8, 4废累, 和CV_AA邓梅, 分別代表8鄰接連接線,4鄰接連接線和反鋸齒連接線邑滨。默認(rèn)值為8鄰接日缨。為了獲得更好地效果可以選用CV_AA(采用了高斯濾波)。
     int shift -- 坐標(biāo)點(diǎn)的小數(shù)點(diǎn)位數(shù)
     */
    
    // 最后就是將畫(huà)布顯示了
    UIImage *hist_image = MatToUIImage(histImage);
    CGRect imgRect = CGRectMake(([UIScreen mainScreen].bounds.size.width - hist_image.size.width)*0.5, 200, hist_image.size.width, hist_image.size.height);
    self.imageView.frame = imgRect;
    self.imageView.image = hist_image;

最后放一張效果圖:
zhifangtu.gif

參考:
OpenCV圖像處理直方圖計(jì)算

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末掖看,一起剝皮案震驚了整個(gè)濱河市匣距,隨后出現(xiàn)的幾起案子面哥,更是在濱河造成了極大的恐慌,老刑警劉巖毅待,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尚卫,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡尸红,警方通過(guò)查閱死者的電腦和手機(jī)吱涉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)外里,“玉大人邑飒,你說(shuō)我怎么就攤上這事〖独郑” “怎么了疙咸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)风科。 經(jīng)常有香客問(wèn)我撒轮,道長(zhǎng),這世上最難降的妖魔是什么贼穆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任题山,我火速辦了婚禮,結(jié)果婚禮上故痊,老公的妹妹穿的比我還像新娘顶瞳。我一直安慰自己,他們只是感情好愕秫,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布慨菱。 她就那樣靜靜地躺著,像睡著了一般戴甩。 火紅的嫁衣襯著肌膚如雪符喝。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天甜孤,我揣著相機(jī)與錄音协饲,去河邊找鬼。 笑死缴川,一個(gè)胖子當(dāng)著我的面吹牛茉稠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播把夸,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼而线,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起吞获,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤况凉,失蹤者是張志新(化名)和其女友劉穎谚鄙,沒(méi)想到半個(gè)月后各拷,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闷营,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年烤黍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片傻盟。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡速蕊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娘赴,到底是詐尸還是另有隱情规哲,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布诽表,位于F島的核電站唉锌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏竿奏。R本人自食惡果不足惜袄简,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泛啸。 院中可真熱鬧绿语,春花似錦、人聲如沸候址。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)岗仑。三九已至昂芜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赔蒲,已是汗流浹背泌神。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舞虱,地道東北人欢际。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像矾兜,于是被迫代替她去往敵國(guó)和親损趋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容