[OpenCV] 直方圖均衡化

直方圖是圖像處理中最最最最基本的操作之一,這個基本操作是在太太太太常見了,同時也是很容易理解的操作,對於一些對比度稍微較低的圖像,這是一個還挺不錯的預處理操作。

1、直方圖

先說直方圖,直方圖就是圖像像素的統計表,這個表裏記錄着一幅圖像中每個像素值在圖像中出現的個數,一幅圖只有一個灰度直方圖,但是多幅圖可能有相同的直方圖,這是N對1的關係。所以在製作直方圖的時候就很容易啦,創建一個包含所有像素灰階的數組(比如,0到255),然後遍歷圖像,對應像素的在數組中的值加一即可。

2、直方圖均衡化

最普通最常見最簡單也是比較有效的直方圖均衡化,就是在得到直方圖後,將直方圖的值逐個累加得到一個累計直方圖,累計直方圖的每個值除以圖像總的像素個數,這樣就得到了每階像素在這個圖像中的佔比,以這個佔比乘以255就得到均衡化處理過後的像素值。

在代碼實現上也比較簡單,先申請一塊大小爲256的內存,然後遍歷原圖像,統計並記錄像素:

cv::Mat histMat = cv::Mat::zeros(1, 256, CV_32FC1);
float *ptrHis = histMat.ptr<float>(0);
for (int i = 0; i < src.rows; i++)
{
    uchar *ptrSrc = src.ptr<uchar>(i);
    for (int j = 0; j < src.cols; j++)
    {
        int pix = (int)*(ptrSrc + j);
        *(ptrHis + pix) = *(ptrHis + pix) +  1;
    }
}

然後計算累計直方圖:

cv::Mat cHistMat = cv::Mat::zeros(1, 256, CV_32FC1);
*(cHistMat.ptr<float>(0)) = *(histMat.ptr<float>(0));
for (int i = 1; i < 256; i++)
{
    *(cHistMat.ptr<float>(0) + i) = *(cHistMat.ptr<float>(0) + i - 1) + *(histMat.ptr<float>(0) + i);
}
for (int i = 0; i < 256; i++)
{
    *(cHistMat.ptr<float>(0) + i) = *(cHistMat.ptr<float>(0) + i) / src.rows / src.cols * 255;
}

然後重新遍歷圖像,將新的像素值代替原來的像素值:

cv::Mat dst;
src.copyTo(dst);
for (int i = 0; i < src.rows; i++)
{
    uchar *ptrDst = dst.ptr<uchar>(i);
    for (int j = 0; j < src.cols; j++)
    {
        int pix = (int)*(ptrDst + j);
        *(ptrDst + j) = (uchar)(*(cHistMat.ptr<float>(0) + pix));
    }
}

完成,測試結果:

 

洛陽城裏見秋風,

欲作家書意萬重。

復恐匆匆說不盡,

行人臨發又開封。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章