圖像處理---圖像白化

圖像處理---圖像白化

我們從逐像素處理來開始講訴圖像預處理。我們將代表原始圖像的二維矩陣標記為,其中的代表第行和第列的像素值,代表該像素點的灰度強度。逐像素處理返回的就是和尺寸大小一樣包含的二維矩陣。

1.Whitening(白化處理)

一幅圖像最終成像會受環境照明強度、物體反射、拍攝相機等多因素的影響。為了能獲得圖像中包含的那些不受外界影響的恆定信息,我們需要對圖像進行白化處理。(圖像白化(whitening)可用於對過度曝光或低曝光的圖片進行處理,處理的方式就是改變圖像的平均像素值為 0 ,改變圖像的方差為單位方差 1。)一般為了去除這些因素的影響,我們將它的像素值轉化成零均值和單位方差。所以我們首先計算原始灰度圖像

的像素平均值和方差值。

接下來我們將使用和來對原始灰度圖像的每個像素值進行轉化:

對於彩色圖像,我們需要在三個通道分別計算和,然後根據公式(3)分別進行像素轉化。

當然這種簡單的轉換可能會妨礙之後的圖像處理,因為這些去除的信息有可能就是我們接下來需要的。

下面我們通過一段代碼來展示一下白化處理的效果。

OpenCV 實現

用 OpenCV 的內置函數計算均值和方差,然後對遍歷每個像素值並對每個像素做變換。這裡需要注意的是變換後的像素值肯定是有一部分會是負值(小於均值的那部分),我們需要把變換後的像素值重新映射到 [0, 255] 的範圍內。因為 OpenCV 中的 normalize 函數無法實現這種任意範圍內的映射,我們需要自己去實現這類映射。我們需要找出變換後圖像中的最小 min 和最大像素值 max, 假設需要映射的範圍為 [a, b]。 該映射可用函數(b-a)*(xij-min)/(max-min) 實現。關鍵部分實現代碼如下所示:

 1 void whitening() {
2 Mat image = imread("test.jpg",IMREAD_GRAYSCALE);
3
4 double mean, stddev;
5 Mat temp_m, temp_sd;
6 meanStdDev(image, temp_m, temp_sd);
7 mean = temp_m.at<double>(0, 0)/255.0;
8 stddev = temp_sd.at<double>(0, 0)/255.0;
9 Mat temp_image( image.rows, image.cols, CV_64F);
10 for (int i = 0; i < image.rows; i++)
11 for (int j = 0; j < image.cols; j++) {
12 double pixelVal = image.at<uchar>(i, j)/255.0;
13 double temp = (pixelVal - mean) / stddev;
14 temp_image.at<double>(i, j) = temp;
15 }
16
17 double max, min;
18 minMaxLoc(temp_image, &min, &max);
19 for (int i = 0; i < image.rows; i++)
20 for (int j = 0; j < image.cols; j++) {
21 double pixelVal = temp_image.at<double>(i, j);
22 image.at<uchar>(i, j) = (uchar)round(255.0 * (pixelVal - min) / (max - min));
23 }

24
25 imshow("New Image", image);
26 waitKey(0);
27 }
/<uchar>/<double>/<double>/<uchar>/<double>/<double>

結果

如下圖所示,可以看到對左邊過度曝光的圖片經過白化處理後圖片的曝光程度減弱了。再看圖像直方圖,白化變換似乎是對原來的直方圖做了一個橫向的拉伸,使得像素值的分佈更加的均勻,而不是集中在一個有限的(高曝光的)範圍內。

圖像處理---圖像白化

圖像處理---圖像白化

圖像處理---圖像白化

圖像處理---圖像白化


分享到:


相關文章: