Lab1: Histogram Equalization
Calculate the histogram H for src
Normalize the histogram.
std::array<double, 256> calNormalizedHist(cv::Mat& source) {
std::array<double, 256> acc{0};
// Calculate the histogram H for src
for(int i = 0; i < source.rows; i++)
for (int j = 0; j < source.cols; j++)
acc[ source.ptr<uchar>(i)[j]] ++;
// Normalize the histogram.
for(int i = 0; i < acc.size(); i++)
acc[i] /= source.rows * source.cols;
return acc;
}
Compute the integral of the histogram: H‘
Transform the image using H′ as a look-up table: \[??????(x,y)=H′(??????(x,y)) * 255\]
void equalizeHist(cv::Mat& source, cv::Mat& result) {
source.copyTo(result);
auto hist = calNormalizedHist(source);
// Compute the integral of the histogram: H'
for(int i = 1; i < 256; i++) hist[i] += hist[i-1];
// Transform the image using H′ as a look-up table: ??????(x,y)=H′(??????(x,y)) * 255
for(int i = 0; i < source.rows; i++)
for (int j = 0; j < source.cols; j++)
result.ptr<uchar>(i)[j] = hist[source.ptr<uchar>(i)[j]] * 255;
}
Test Code:
cv::Mat cv, lab, m = cv::imread("../data/lena.png", cv::IMREAD_GRAYSCALE);
cv::equalizeHist(m, cv);
equalizeHist(m, lab);
cv::imwrite("../out/m.png", m);
cv::imwrite("../out/cv.png", cv);
cv::imwrite("../out/lab.png", lab);
cv::imwrite("../out/cv-m.png", abs(cv-m));
cv::imwrite("../out/lab-m.png", abs(lab-m));
cv::imwrite("../out/lab-cv.png", abs(lab-cv));
cv::imwrite("../out/hist.m.png", drawHist(calNormalizedHist(m)));
cv::imwrite("../out/hist.cv.png", drawHist(calNormalizedHist(cv)));
cv::imwrite("../out/hist.lab.png", drawHist(calNormalizedHist(lab)));
cv::imwrite("../out/acchist.m.png", drawHist(calNormalizedHist(m), true));
cv::imwrite("../out/acchist.cv.png", drawHist(calNormalizedHist(cv), true));
cv::imwrite("../out/acchist.lab.png", drawHist(calNormalizedHist(lab),true));
明显本文实现的算法与OpenCV实现的高度一致(不考虑指令集优化: SIMD|SEE4 etc.)
由Histogram与Accumulate Histogram上看, 连续变量的均匀分布意味着概率分布函数满足线性分布, 与理论推导得出的性质一致
从直方图直观观察和算法分析, 易知基于直接灰度映射(点对点映射)的经典直方图均衡算法会导致灰阶的减少.因而加剧色带(Banding)现象:
所以这个意义上, 直方图的均衡是一个可以把相邻柱子合并的挪动柱子的游戏~
本部分是附加部分, 主要回答实验课程上与老师的一个小小的 argument:
怎么得到均衡后的直方图 ?
比较常见的方法: 图像均衡后再统计一次直方图
比较少用的方法: 直接均衡原直方图
std::array<double, 256> equalizeHist(std::array<double, 256>&& hist) {
std::array<double, 256> hist_eq{0}, hist_acc{0};
hist_acc[0] = hist[0];
// Compute the integral of the histogram: H'
for(int i = 1; i < 256; i++) hist_acc[i] = hist_acc[i-1] + hist[i];
for(int i = 0; i < 256; i++)
hist_eq[hist_acc[i]*255] += hist[i];
return hist_eq;
}
先计算均衡后的直方图再均衡图像对吗?
直方图均衡的均衡指什么?
均衡一种概率变换, 可以将线性的目标概率分布函数拓展到任意的分布函数:
? Transformation between two distribution funtion.
\[y=e^{x-1}\]
原文:https://www.cnblogs.com/xiconxi/p/11770899.html