原理
圖像白化(whitening)可用於對過分曝光或低曝光的圖片進行處理,處理的方式就是改變圖像的平均像素值爲 0 ,改變圖像的方差爲單位方差 1。咱們須要先計算原圖像的均值和方差,而後對原圖像的每一個像素值作變換。假設圖像 P 有 I 行 J 列,每一個像素的值爲 pij, 均值和方差的計算公式以下。函數
變換後新圖像的每一個像素值 xij 爲spa
OpenCV 實現
用 OpenCV 的內置函數計算均值和方差,而後對遍歷每一個像素值並對每一個像素作變換。這裏須要注意的是變換後的像素值確定是有一部分會是負值(小於均值的那部分),咱們須要把變換後的像素值從新映射到 [0, 255] 的範圍內。由於 OpenCV 中的 normalize 函數沒法實現這種任意範圍內的映射,咱們須要本身去實現這類映射。咱們須要找出變換後圖像中的最小 min 和最大像素值 max, 假設須要映射的範圍爲 [a, b]。 該映射可用函數(b-a)*(xij-min)/(max-min) 實現。關鍵部分實現代碼以下所示:3d
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 }
結果
以下圖所示,能夠看到對左邊過分曝光的圖片通過白化處理後圖片的曝光程度減弱了。再看圖像直方圖,白化變換彷佛是對原來的直方圖作了一個橫向的拉伸,使得像素值的分佈更加的均勻,而不是集中在一個有限的(高曝光的)範圍內。code
參考
[1] Computer vision: models, learning and inference, Simon J. D. Prince.orm