1、直方图
-
介绍 : 直方图描述的是图像的各个灰度级的统计学特性,它反映了一副图像中各个灰度级出现的次数或概率。
- 只反映该图像中不同灰度值出现的次数(或频数),而未反映某一灰度值像素所在位置。丢失了位置的信息。
- 图像与直方图之间是多对一的映射关系。例如:镜像图像与原图的直方图信息一致。
- 由于直方图是对具有相同灰度值的像素统计得到的,因此,一幅图像各子区的直方图之和等于该图像全图的直方图。
-
Matlab 中实现并显示
代码部分:
img = imread('E:\BMP\GaryFrameTest.bmp'); % 读取图像
[height, width] = size(img); % 获取图像尺寸
[counts, x] = imhist(img); % 得到图像的直方图信息;counts - 灰度区间内的像素数目;x - 对应的灰度区间向量
counts = counts / height / width; % 直方图信息进行归一化(概率)
figure; % 绘制结果信息
stem(x, counts, 'filled');
效果图:

从直方图中可以得到的信息:

哪个区域的像素统计数量较多,那么图像就偏向那个区域。
- 实现
// 像素直方图,统计每个像素值出现的次数
uint32_t pixelCounts[256] = { 0 };
for (int i = 0; i < img.height; i++) {
for (int j = 0; j < img.width; j++) {
uint8_t pixelValue = img.arr[i][j];
pixelCounts[pixelValue]++; // 直接统计的结果值,未进行归一化处理
}
}
2、直方图均衡化
- 介绍: 直方图均衡化是一种利用图像直方图对图像对比度进行调整的方法。
- Matlab 中实现并显示
代码部分:
img = imread('E:\BMP\GaryFrameTest.bmp');
[height, width] = size(img);
[counts, x] = imhist(img);
counts = counts / height / width;
subplot(1, 2, 1);
stem(x, counts, 'filled');
dstImg = histeq(img); % 直方图均衡化
[dstCounts, dst_x] = imhist(dstImg);
dstCounts = dstCounts / height / width;
subplot(1, 2, 2);
stem(dst_x, dstCounts, 'filled');
效果图:

相关性质:

- 相关具体的公式证明可以查看该博文:matlab 直方图均衡化
- 简洁说明:因为截图不清楚,可以查看 简洁计算公式说明 这篇博客的内容。
- 代码实现
/************************************************************
*Function: histogramEqualization
*Description: 直方图均衡化
*Params: img - GrayFrame 结构体
*Return: dstImg - 结果图像
************************************************************/
struct GrayFrameInfo histogramEqualization(struct GrayFrameInfo img)
{
GrayFrameInfo dstImg = dstImg.createNewImgSpace(img);
// 得到总的像素个数
uint32_t Num = img.width * img.height;
// 像素直方图,统计每个像素值出现的次数
uint32_t pixelCounts[256] = { 0 };
for (int i = 0; i < img.height; i++) {
for (int j = 0; j < img.width; j++) {
uint8_t pixelValue = img.arr[i][j];
pixelCounts[pixelValue]++;
}
}
// 得到像素直方图的累加和
double histMap = 255.0 / Num;
uint32_t sum = 0, sumCounts[256] = { 0 };
uint8_t histMapCounts[256] = { 0 };
for (int i = 0; i < 256; i++) {
sum += pixelCounts[i];
sumCounts[i] = sum;
histMapCounts[i] = (uint8_t)(sumCounts[i] * histMap + 0.5); // 计算映射值
}
// 循环赋值结果图像像素
for (int i = 0; i < img.height; i++) {
for (int j = 0; j < img.width; j++) {
dstImg.arr[i][j] = histMapCounts[img.arr[i][j]];
}
}
return dstImg;
}
-
结果说明:
与 Matlab 的结果相比仍有不小差距。。。中间的凹谷不知道该如何处理。。。