女人夜夜春高潮爽A∨片传媒_国产精品VIDEOS麻豆_在线精品亚洲一区二区三区_亚洲熟妇无码av

圖像處理
新聞詳情

圖像處理基礎(8):圖像的灰度直方圖、直方圖均衡化、直方圖規定化(匹配)

發布時(shi)間:2021-01-14 14:41:29 最后更新:2021-01-14 15:46:47 瀏覽次數(shu):4788

本文主(zhu)要介紹了灰度直(zhi)方圖相關的處理(li),包括以下(xia)幾個方面的內容:

?   利(li)用OpenCV計(ji)算圖(tu)(tu)像的灰度(du)直方圖(tu)(tu),并繪(hui)制直方圖(tu)(tu)曲線

?   直方圖均(jun)衡化的原(yuan)理及實現

?   直方(fang)圖規定化(匹配)的原理及實現

圖像的灰度直方圖

一幅圖像由不同灰度值的像素組成,圖像中灰度的分布情況是該圖像的一個重要特征。圖像的灰度直方圖就描述了圖像中灰度分布情況,能夠很直觀的展示出圖像中各個灰度級所占的多少。
圖像的灰度直方圖是灰度級的函數,描述的是圖像中具有該灰度級的像素的個數:其中,橫坐標是灰度級,縱坐標是該灰度級出現的頻率。

不過通常會將縱坐標歸一化到區間內,也就是(shi)將灰度級出現(xian)的頻率(像(xiang)素個(ge)數)除以圖像(xiang)中像(xiang)素的總數。灰度直方圖的計算公式如(ru)下(xia):


其中,是像素的灰度級,是具有灰度的像素的個數,是圖像中總的像素個數。

OpenCV灰度直方圖的計算

直方(fang)圖(tu)的(de)計(ji)算(suan)是(shi)很簡單(dan)的(de),無(wu)非是(shi)遍(bian)歷圖(tu)像(xiang)的(de)像(xiang)素,統(tong)計(ji)每個(ge)灰度級的(de)個(ge)數。在OpenCV中封裝(zhuang)了直方(fang)圖(tu)的(de)計(ji)算(suan)函(han)數calcHist,為(wei)(wei)了更為(wei)(wei)通用該(gai)函(han)數的(de)參數有些復雜(za),其(qi)聲明如(ru)下:

void calcHist( const Mat* images, int nimages,
                          const int* channels, InputArray mask,
                          OutputArray hist, int dims, const int* histSize,
                          const float** ranges, bool uniform = true, bool accumulate = false );

該函數能夠同時計算多個圖像,多個通道,不同灰度范圍的灰度直方圖.
其參數如下:

?   images,輸入圖(tu)像的數組,這些圖(tu)像要有相同大大小(xiao),相同的深度(CV_8U CV_16U CV_32F).

?   nimages ,輸(shu)入圖像的個數

?   channels,要計(ji)算直(zhi)方圖的通道個數。

?   mask,可選的掩(yan)碼,不使(shi)用時(shi)可設(she)為(wei)(wei)空(kong)。要(yao)和輸入圖像具有相同的大小(xiao),在進行直方圖計算的時(shi)候,只會統計該掩(yan)碼不為(wei)(wei)0的對應(ying)像素

?   hist,輸出的直(zhi)方圖

?   dims,直方圖的(de)維度

?   histSize,直方圖每個維度的(de)大小

?   ranges,直方圖(tu)每個維度要(yao)統(tong)計的灰(hui)度級的范(fan)圍(wei)

?   uniform,是否進行歸一(yi)化,默認(ren)為true

?   accumulate,累(lei)積標志(zhi),默(mo)認值為false。

為(wei)了計算(suan)的(de)靈活性和通(tong)用性,OpenCV的(de)灰度(du)直方圖(tu)(tu)(tu)(tu)提供了較(jiao)多(duo)的(de)參數,但(dan)對于(yu)只是簡單的(de)計算(suan)一(yi)幅(fu)灰度(du)圖(tu)(tu)(tu)(tu)的(de)直方圖(tu)(tu)(tu)(tu)的(de)話,又(you)顯(xian)得較(jiao)為(wei)累贅。這里對calcHist進行一(yi)次(ci)封裝(zhuang),能(neng)夠方便的(de)得到一(yi)幅(fu)灰度(du)圖(tu)(tu)(tu)(tu)直方圖(tu)(tu)(tu)(tu)。

class Histogram1D
{
private:
    int histSize[1]; // 項的(de)數(shu)量
    float hranges[2]; // 統計像素(su)的(de)最大值和最小值
    const float* ranges[1];
    int channels[1]; // 僅計算一(yi)個通道

public:
    Histogram1D()
    {
        // 準備1D直方圖的參(can)數
        histSize[0] = 256;
        hranges[0] = 0.0f;
        hranges[1] = 255.0f;
        ranges[0] = hranges;
        channels[0] = 0;
    }

    MatND getHistogram(const Mat &image)
    {
        MatND hist;
        // 計算直方圖
        calcHist(&image ,// 要計算圖像的
            1,                // 只計算一幅圖(tu)像的直(zhi)方圖(tu)
            channels,        // 通道數量
            Mat(),            // 不使用掩(yan)碼
            hist,            // 存放直方(fang)圖
            1,                // 1D直方(fang)圖(tu)
            histSize,        // 統(tong)計的灰度的個數
            ranges);        // 灰度值的范(fan)圍
        return hist;
    }

    Mat getHistogramImage(const Mat &image)
    {
        MatND hist = getHistogram(image);

        // 最大值,最小(xiao)值
        double maxVal = 0.0f;
        double minVal = 0.0f;

        minMaxLoc(hist, &minVal, &maxVal);

        //顯示(shi)直方(fang)圖(tu)的(de)圖(tu)像(xiang)
        Mat histImg(histSize[0], histSize[0], CV_8U, Scalar(255));

        // 設(she)置最高(gao)點(dian)為nbins的90%
        int hpt = static_cast<int>(0.9 * histSize[0]);
        //每個(ge)條目(mu)繪制一條垂直線
        for (int h = 0; h < histSize[0]; h++)
        {
            float binVal = hist.at<float>(h);
            int intensity = static_cast<int>(binVal * hpt / maxVal);
            // 兩(liang)點之間繪制一條(tiao)直線(xian)
            line(histImg, Point(h, histSize[0]), Point(h, histSize[0] - intensity), Scalar::all(0));
        }
        return histImg;
    }
};

Histogram1D提供(gong)了兩個方(fang)(fang)法:getHistogram返回統計直(zhi)方(fang)(fang)圖的數組,默認(ren)計算(suan)的灰度范圍是[0,255];getHistogramImage將圖像的直(zhi)方(fang)(fang)圖以線條的形式(shi)畫出來,并返回包含(han)直(zhi)方(fang)(fang)圖的圖像。測試代碼如下(xia):

    Histogram1D hist;
    Mat histImg;
    histImg = hist.getHistogramImage(image);

    imshow("Image", image);
    imshow("Histogram", histImg);

其結果如下:

直方圖均衡化 Histogram Equalization

假如圖像的灰度分布不均勻,其灰度分布集中在較窄的范圍內,使圖像的細節不夠清晰,對比度較低。通常采用直方圖均衡化直方圖規定化兩種變換,使圖像的灰度范圍拉開或使灰度均勻分布,從而增大反差,使圖像細節清晰,以達到增強的目的。
直(zhi)方(fang)圖(tu)(tu)(tu)(tu)(tu)均衡化(hua),對(dui)圖(tu)(tu)(tu)(tu)(tu)像(xiang)進(jin)行非線性拉伸,重(zhong)新(xin)分配圖(tu)(tu)(tu)(tu)(tu)像(xiang)的(de)灰度(du)值(zhi),使一(yi)定(ding)范圍內圖(tu)(tu)(tu)(tu)(tu)像(xiang)的(de)灰度(du)值(zhi)大致相等。這樣,原來直(zhi)方(fang)圖(tu)(tu)(tu)(tu)(tu)中(zhong)間的(de)峰值(zhi)部分對(dui)比度(du)得到增強,而兩側的(de)谷底部分對(dui)比度(du)降低,輸出圖(tu)(tu)(tu)(tu)(tu)像(xiang)的(de)直(zhi)方(fang)圖(tu)(tu)(tu)(tu)(tu)是一(yi)個較為平(ping)坦的(de)直(zhi)方(fang)圖(tu)(tu)(tu)(tu)(tu)。

均衡化算法

直方圖的均衡化實際也是一種灰度的變換過程,將當前的灰度分布通過一個變換函數,變換為范圍更寬、灰度分布更均勻的圖像。也就是將原圖像的直方圖修改為在整個灰度區間內大致均勻分布,因此擴大了圖像的動態范圍,增強圖像的對比度。通常均衡化選擇的變換函數是灰度的累積概率,直方(fang)圖(tu)均衡化(hua)算法的步驟:

?   計算原圖像的灰度直方圖 ,其中為像素總數,為灰度級的像素個數

?   計算原始圖像的累積直方圖 

?   ,其中 是目的圖像的像素,是源圖(tu)像灰度(du)為(wei)i的累(lei)積分布,L是圖(tu)像中最大(da)灰度(du)級(ji)(灰度(du)圖(tu)為(wei)255)

其代碼實現如下:

?   在上面中封裝了求灰(hui)度直(zhi)方圖(tu)(tu)的(de)類(lei),這里直(zhi)接應用該方法得到圖(tu)(tu)像(xiang)的(de)灰(hui)度直(zhi)方圖(tu)(tu);

?   將灰度直方圖進(jin)行歸一化,計算灰度的累積概率;

?   創建灰度變化的查(cha)找(zhao)表

?   應(ying)用查找表,將(jiang)原圖像(xiang)變換(huan)為(wei)灰度均衡的圖像(xiang)

具體代碼如下:

void equalization_self(const Mat &src, Mat &dst)
{
    Histogram1D hist1D;
    MatND hist = hist1D.getHistogram(src);

    hist /= (src.rows * src.cols); // 對得到(dao)的灰度直方圖進行歸(gui)一化
    float cdf[256] = { 0 }; // 灰(hui)度的(de)累(lei)積概(gai)率
    Mat lut(1, 256, CV_8U); // 灰度變(bian)換的查找(zhao)表
    for (int i = 0; i < 256; i++)
    {
        // 計算灰(hui)度級的累積概率
        if (i == 0)
            cdf[i] = hist.at<float>(i);
        else
            cdf[i] = cdf[i - 1] + hist.at<float>(i);

        lut.at(i) = static_cast(255 * cdf[i]); // 創建灰度的查找表
    }

    LUT(src, lut, dst); // 應用查找表,進行灰度(du)變化,得(de)到(dao)均衡(heng)化后的圖像

}

上面代碼只是加深下對均衡化算法流程的理解,實際在OpenCV中也提供了灰度均衡化的函數equalizeHist,該函數的使用很簡單,只有兩個參數:輸入圖像,輸出圖像。下圖為,上述代碼計算得到的均衡化結果和調用equalizeHist的結果對比

最左邊(bian)為(wei)(wei)原圖像,中間為(wei)(wei)OpenCV封裝函數的(de)結果,右邊(bian)為(wei)(wei)上面代碼得(de)到(dao)的(de)結果。

直方圖規定化

從上面可以看出,直方圖的均衡化自動的確定了變換函數,可以很方便的得到變換后的圖像,但是在有些應用中這種自動的增強并不是最好的方法。有時候,需要圖像具有某一特定的直方圖形狀(也就是灰度分布),而不是均勻分布的直方圖,這時候可以使用直方圖規定化
直(zhi)方(fang)圖(tu)規(gui)定(ding)化(hua),也(ye)(ye)叫做直(zhi)方(fang)圖(tu)匹配(pei),用于將圖(tu)像變換(huan)(huan)為某一特定(ding)的(de)(de)(de)灰(hui)度(du)分布,也(ye)(ye)就是(shi)(shi)其(qi)目(mu)的(de)(de)(de)的(de)(de)(de)灰(hui)度(du)直(zhi)方(fang)圖(tu)是(shi)(shi)已(yi)知的(de)(de)(de)。這其(qi)實和均衡(heng)化(hua)很類似,均衡(heng)化(hua)后的(de)(de)(de)灰(hui)度(du)直(zhi)方(fang)圖(tu)也(ye)(ye)是(shi)(shi)已(yi)知的(de)(de)(de),是(shi)(shi)一個(ge)均勻分布的(de)(de)(de)直(zhi)方(fang)圖(tu);而(er)規(gui)定(ding)化(hua)后的(de)(de)(de)直(zhi)方(fang)圖(tu)可以隨意的(de)(de)(de)指定(ding),也(ye)(ye)就是(shi)(shi)在執行規(gui)定(ding)化(hua)操作時,首先要(yao)知道(dao)變換(huan)(huan)后的(de)(de)(de)灰(hui)度(du)直(zhi)方(fang)圖(tu),這樣才(cai)能確定(ding)變換(huan)(huan)函數。規(gui)定(ding)化(hua)操作能夠有目(mu)的(de)(de)(de)的(de)(de)(de)增強某個(ge)灰(hui)度(du)區間,相比于,均衡(heng)化(hua)操作,規(gui)定(ding)化(hua)多了一個(ge)輸(shu)入,但是(shi)(shi)其(qi)變換(huan)(huan)后的(de)(de)(de)結果也(ye)(ye)更靈活。

在理解了上(shang)述的(de)(de)均衡(heng)化(hua)(hua)(hua)過程(cheng)后(hou),直方圖的(de)(de)規定(ding)化(hua)(hua)(hua)也較為(wei)簡(jian)單(dan)。可(ke)以利用均衡(heng)化(hua)(hua)(hua)后(hou)的(de)(de)直方圖作(zuo)為(wei)一(yi)個中間過程(cheng),然后(hou)求取規定(ding)化(hua)(hua)(hua)的(de)(de)變換函數。具體步驟如下:

?   將原始圖像的灰度直方圖進行均衡化,得到一個變換函數,其中s是(shi)(shi)均衡化后的像素(su),r是(shi)(shi)原始像素(su)

?   對規定的直方圖進行均衡化,得到一個變換函數,其中v是(shi)均衡化后(hou)的像素,z是(shi)規定化的像素

?   上面都是對同一圖像的均衡化,其結果應該是相等的,,且

通過,均衡化作為中間結果,將得到原始像素規定化后像素之間的映射(she)關系。

詳解規定化過程

對圖像進行直方圖規定化操作,原始圖像的直方圖和以及規定化后的直方圖是已知的。假設表示原始圖像的灰度概率密度,表示規(gui)定化圖(tu)(tu)像的灰(hui)度(du)(du)概率密度(du)(du)(r和z分別是原(yuan)始圖(tu)(tu)像的灰(hui)度(du)(du)級(ji),規(gui)定化后(hou)圖(tu)(tu)像的灰(hui)度(du)(du)級(ji))。

?   對原始圖像進行均衡化操作,則有

?   對規定化的直方圖進行均衡化操作,則

?   由于是對同一圖像的均衡化操作,所以有

?   規定化操作的目的就是找到原始圖像的像素到規定化后圖像像素的之間的一個映射。有了上一步的等式后,可以得到,因此要想找到相對應的只需要在進行迭代,找到使式子的絕對值最小即可。

?   上述描述只是理論的推導過程,在實際的計算過程中,不需要做兩次的均衡化操作,具體的推導過程如下:$$



文章轉自Brook_icv   //www.cnblogs.com/wangguchangqing/p/7098213.html

在線(xian)客(ke)服(fu)
客服電(dian)話(hua)
  • 0755-23712116
  • 13310869691