OpenCV 图像处理:白化(whitening)

原理

图像白化(whitening)可用于对过度曝光或低曝光的图片进行处理,处理的方式就是改变图像的平均像素值为 0 ,改变图像的方差为单位方差 1。我们需要先计算原图像的均值和方差,然后对原图像的每个像素值做变换。假设图像 P 有 I 行 J 列,每个像素的值为 pij, 均值和方差的计算公式如下。

变换后新图像的每个像素值 xij

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 }
复制代码

结果

如下图所示,可以看到对左边过度曝光的图片经过白化处理后图片的曝光程度减弱了。再看图像直方图,白化变换似乎是对原来的直方图做了一个横向的拉伸,使得像素值的分布更加的均匀,而不是集中在一个有限的(高曝光的)范围内。

                     

                                          

参考

[1] Computer vision: models, learning and inference, Simon J. D. Prince.

posted @   ToBeDeveloper  阅读(7123)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示