天天看點

[OpenCV基礎] 直方圖之calcHist使用

原文參考自:http://blog.csdn.net/sydnash/article/details/7451039

以及:http://blog.csdn.net/ljbkiss/article/details/7412787

opencv提供了calcHist函數來計算圖像直方圖。

         其中C++的函數原型如下:void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, OutputArray

hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=

false );

          void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, SparseMat&

hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=

false );

         參數解釋:

        arrays。輸入的圖像的指針,可以是多幅圖像,所有的圖像必須有同樣的深度(CV_8U or CV_32F)。同時每一副圖像可以有多個channes。

        narrays。輸入的圖像的個數。

        channels。用來計算直方圖的通道維數數組,第一個數組的通道由0到arrays[0].channels()-1列出,第二個數組的通道從arrays[0].channels()到arrays[0].channels()+arrays[1].channels()-1以此類推;channels與arrays中的圖像的對應關系,将arrays中的圖像從第0幅開始按照通道攤開排列起來,然後channels中的指定的用于計算直方圖的就是這些攤開的通道;假設有arrays中隻有一幅三通道的圖像image,那麼narrays應該為1,如果是想計算3維直方圖【最大也隻能是3維的】,想将image的通道2作為第一維,通道0作為第二維,通道1作為第三維,則可以将channels設定為channesl={2,0,1};這樣calcHist函數計算時就按照這個順序來統計直方圖。如果channels參數為0,則narrays和dims必須相等,否則彈出assert,此時計算直方圖的時候取數組中每幅圖像的第0通道。channels不為0時narrays可以和dims不相等,隻要保證arrays中至少有channels指定的通道就可以。

        mask。 可選的掩膜,如果該矩陣不是空的,則必須是8位(CV_8U)的并且與arrays[i]的大小相等,掩膜的非零值标記需要在直方圖中統計的數組元素;

        hist。輸出計算出的直方圖,是一個稠密或者稀疏的dims維的數組;

        dims。計算出來的直方圖的維數。必須為正,并且不大于CV_MAX_DIMS(目前的OpenCV版本中為32,即最大可以統計32維的直方圖);(統計的變量個數)

        histSize。 用于指出直方圖數組每一維的大小的數組,即指出每一維的bin的個數的數組;(每維分成多少份),在每一維上直方圖的個數。簡單把直方圖看作一個一個的豎條的話,就是每一維上豎條的個數。

        ranges。用來進行統計的範圍。比如

         float rang1[] = {0, 20};

        float rang2[] = {30, 40};

        const float *rangs[] = {rang1, rang2};那麼就是對0,20和30,40範圍的值進行統計。

        用于指出直方圖每一維的每個bin(份)的上下界範圍數組的數組,當直方圖是均勻的(uniform =true)時,對每一維i指定直方圖的第0個bin的下界(包含)L0和最 後一個即第histSize[i]-1個bin的上界(不包含))U_histSize[i]-1,也就是說對均勻直方圖來說,每一個ranges[i]都是一個兩個元素的數組【指出該維的上下界】。當直方圖不是均勻的時,每一個ranges[i]數組都包含histSize[i]+1個元素:L0,U0=L1,U1=L1,...,U_histSize[i]-2 = L_histSize[i]-1,U_histSize[i]-1.不在L0到U_histSize[i]-1之間的數組元素将不會統計進直方圖中;

       uniform。每一個豎條的寬度是否相等,或說每個bin統計的是否是相同數量的灰階級。

       accumulate。 是否累加。如果為true,在下次計算的時候不會首先清空hist。

<span style="font-size:12px;">    //生成一幅單通道圖像。
    cv::Mat image(imageHeight, imageWidth, CV_8U, imageAddress);

    cv::MatND histogram;
    //256個,範圍是0,255.
    const int histSize = 256;
    float range[] = {0, 255};
    const float *ranges[] = {range};
    const int channels = 0;

    cv::calcHist(image, 1, &channels, cv::Mat(), histogram, 1, &histSize, &ranges[0], true, false);
    int row = histogram.rows;
    int col = histogram.cols;

    float *h = (float*)histogram.data;
    double hh[256];
    if (h) {
        for (int i = 0; i < 256; ++i) {
            hh[i] = h[i];
        }
    }
</span>