数字图像处理之图像获取与直方图均衡化

前言

咕了一个学期,终于有时间也有东西可写了,虽然只是大三上修的数字图像处理的实验而已。

实验要求

  1. 统计每个灰度下的像素个数
  2. 绘制出直方图
  3. 计算累计密度
  4. 重新计算均衡化后的灰度值,四舍五入
  5. 直方图均衡化,更新原图每个点的像素值

直方图均衡化

直方图均衡化是常用的图像增强处理技术,其原理为:
r:原图像灰度级
s:均衡化后的图像灰度级
$ P_r(w)$:图像灰度概率分布
$ P_s(w)$:均衡化后的图像灰度概率分布
设直方图均衡化变换函数为,有
其中C(r)为累计分布函数
若期望变换后输出图像的灰度概率密度均匀分布,即,则
所以可得

代码

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
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int p_cnt[256];
float p_sum[256];
int s[256];
int rows,cols;
void DrawHistogram(string name,Mat src){
for(int i=0;i<256;i++)p_cnt[i]=0;

int maxvalue = 0;
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
int p = src.at<uchar>(i,j);
p_cnt[p]+=1;
if(p_cnt[p]>maxvalue){
maxvalue=p_cnt[p];
}
}
}
cv::Mat histogram(Size(256,256),CV_8U,Scalar(0));
for(int i=0;i<256;i++){
int h=p_cnt[i]*255/maxvalue;//归一化
line(histogram,Point(i,255),Point(i,255-h),Scalar(255));
}
imshow(name,histogram);
}
int main(int argc,char **argv){
Mat img_in,img_out;
//读取原始图像
img_in=imread(argv[1],IMREAD_UNCHANGED);
//检查是否读取图像
if(img_in.empty()){
cout<<"Error! Input image cannot be read...\n";
return -1;
}

imshow("src",img_in);
//转化为灰度图
//code
cv::Mat grayimg;
cv::cvtColor(img_in,grayimg,CV_BGR2GRAY);
imshow("均衡化前的图像",grayimg);
rows = grayimg.rows;
cols = grayimg.cols;
int N = cols*rows;

DrawHistogram("均衡化前的直方图",grayimg);

//直方图均衡化
for(int i=0;i<256;i++){

if(i==0){
p_sum[i]=1.0*p_cnt[i]/N;
}
else p_sum[i]=p_sum[i-1]+1.0*p_cnt[i]/N;
s[i] = p_sum[i]*255+0.5;
}
//更新像素灰度值
cv::Mat finaimg(grayimg);
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
int p = grayimg.at<uchar>(i,j);
finaimg.at<uchar>(i,j) = s[p];
}
}
imshow("均衡化后的图像",finaimg);

DrawHistogram("均衡化后的直方图",finaimg);
cout << "Press any key to exit...\n";
waitKey(); // Wait for key press
return 0;
}

运行结果

原图
原图
原图
原图
原图