OpenCV直方图均衡化
直方图均衡化,是对图像进行非线性拉伸,使得一定范围内像素值的数量的大致相同。这样原来直方图中的封顶部分对比度得到了增强,而两侧波谷的对比度降低,输出的直方图是一个较为平坦的分段直方图。直方图均衡化适用于增强直方图呈尖峰分布的图像。
几种图片的的直方图均衡化处理效果
欠曝

过曝

从上面两个图片可以看到,直方图均衡化对于背景和前景都太亮或者太暗的图像效果较好,而且这是一个可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图。但缺点是直方图均衡化对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度;变换后图像的灰度级减少,某些细节消失;某些图像,如直方图有高峰,经处理后对比度不自然的过分增强。
下面再贴一张Luna的处理图:

代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #include <iostream> #include<opencv2/opencv.hpp>
using namespace cv; using namespace std;
Mat Histogramequalization(Mat src) { int R[256] = {0}; int G[256] = {0}; int B[256] = {0}; int rows = src.rows; int cols = src.cols; int sum = rows * cols; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { B[src.at<Vec3b>(i, j)[0]]++; G[src.at<Vec3b>(i, j)[1]]++; R[src.at<Vec3b>(i, j)[2]]++; } } double val[3] = {0}; for (int i = 0; i < 256; i++) { val[0] += B[i]; val[1] += G[i]; val[2] += R[i]; B[i] = val[0] * 255 / sum; G[i] = val[1] * 255 / sum; R[i] = val[2] * 255 / sum; } Mat dst(rows, cols, CV_8UC3); for(int i = 0; i < rows; i++) { for(int j = 0; j < cols; j++) { dst.at<Vec3b>(i, j)[0] = B[src.at<Vec3b>(i, j)[0]]; dst.at<Vec3b>(i, j)[1] = G[src.at<Vec3b>(i, j)[1]]; dst.at<Vec3b>(i, j)[2] = R[src.at<Vec3b>(i, j)[2]]; } } return dst; }
int main() { Mat luna = imread("./luna.jpg"); imshow("Luna——原始图像", luna); imshow("Luna——直方图均衡化", Histogramequalization(luna));
Mat guobao = imread("./guobao.jpg"); imshow("过曝光——原始图像", guobao); imshow("过曝光——直方图均衡化", Histogramequalization(guobao));
Mat qianbao = imread("./qianbao.jpg"); imshow("欠曝光——原始图像", qianbao); imshow("欠曝光——直方图均衡化", Histogramequalization(qianbao));
waitKey(); return 0; }
|