DATE: 2019-7-8
1、参考
C语言实现BMP图像处理(直方图均衡化)
直方图均衡化的编程实现
直方图均衡化—算法分析与编程实现(opencv与c++)
2、直方图和直方图均衡化原理
直方图:是图像中像素强度分布的图形表达方式。
直方图均衡化:把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。
算法步骤:
(1)根据图像灰度计算灰度密度函数PDF.
(2)计算积累分布函数CDF。(cumulative distribution function)
(3)将CDF归一化到原图取值范围[0,255]。
(4)将CDF四舍五入取整,得到灰度转换函数SK=T(CK)。
(5)把原图像素点值为rk的变换为sk。
PDF的算法:gk = EQ(fk) = (ni/n) = pf(fi) ,ni表示第K个灰度级的像素点个数。n表示图像的像素点总数。
CDF的算法:。
灰度转化函数:sk=255*ck/k
3、直方图均衡化算法实现
3.1、OpenCV实现
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#define SIGLE_CHANNEL 1
using namespace cv;
using namespace std;
/** @function main */
int main( int argc, char** argv )
{
Mat src, dst;
int i;
char* source_window = "Source image";
char* equalized_window = "Equalized Image";
/// 加载源图像
src = imread( argv[1], 1 );
if( !src.data )
{ cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;
return -1;}
#if SIGLE_CHANNEL
/// 转为灰度图
cvtColor( src, src, CV_BGR2GRAY );
/// 应用直方图均衡化
equalizeHist( src, dst );
#else
std::vector<Mat>splitBGR(src.channels());
split(src, splitBGR);//图像通道分离
for (i = 0; i < src.channels(); i++)
{
equalizeHist(splitBGR[i], splitBGR[i]);//图像灰度均衡化
}
merge(splitBGR, dst);
#endif
/// 显示结果
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
namedWindow( equalized_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, src );
imshow( equalized_window, dst );
/// 等待用户按键退出程序
waitKey(0);
return 0;
}
效果图如下:
(1)灰度图
(2)彩色图
3.2、C实现
// 计算图像直方图
void Hist(const uint8 *image, int width, int height, int pitch, int hist[])
{
memset((void*)hist, 0, 256 * sizeof(int));
for(int ver = 0; ver < height; ++ver) {
for(int hor = 0; hor < width; ++hor) {
int offset = ver * pitch + hor;
++hist[*(image+offset)];
}
}
}
// 求直方图均衡化的映射表
void MapTable(int hist[], uint8 map_table[], int num)
{
int sum = 0;
for(int i = 0; i < 256; ++i) {
sum += hist[i];
map_table[i] = int(255 * sum / num + 0.5);
}
}
void EqualizeHist(const uint8 *src, uint8 *dst, int width, int height, int pitch)
{
int hist[256] = {0};
uint8 map_table[256] = {0};
Hist(src, width, height, pitch, hist);
MapTable(hist, map_table, width * height);
for(int ver = 0; ver < height; ++ver) {
for(int hor = 0; hor < width; ++hor) {
int offset = ver * pitch + hor;
*(dst + offset) = map_table[*(src + offset)];
}
}
}
效果图如下: