图像增强的目的:改善图像的视觉效果或使图像更适合于人或机器的分析处理。通过图像增强,可以减少图像噪声,提高目标与背景的对比度,也可以增强或抑制图像中的某些细节。
---------------------------------------------------------------------------------------------------
灰度变换:把原图像的像素灰度经过某个函数变换成新图像的灰度。可分为直线灰度变换法和直方图修正法。
直线灰度变换法:线性、分段线性、非线性变换。
直方图修正法:直方图均衡化、直方图规定化。
---------------------------------------------------------------------------------------------------
图像直方图:是对像素的某种属性(如灰度、颜色、梯度等)分布进行统计分析的重要手段。
灰度直方图:是灰度级的函数,它反映了图像中每一灰度级出现的次数或频率。
直方图均衡化:把原始图像的直方图变换为均匀分布的形式,从而增加图像灰度的动态范围,以达到增强图像对比度的效果。
经过均衡化处理的图像,其灰度级出现的概率相同,此时图像的熵最大,图像所包含的信息量最大。
【注意,离散后是每块区域的概率相等,均衡化后并不是条直线哦。】
细节概念等省略......
---------------------------------------------------------------------------------------------------
线性灰度增强、对数变换、指数变换、直方图均衡化。代码见下(代码略粗糙...)【ImageEnhance.cpp部分代码】
1 //线性灰度增强
2 bool CImageEnhance::GrayLinearTransform(Mat &src, Mat &dst, uchar c, uchar d)
3 {
4 int b=0,a=255;
5 dst = src.clone();
6 int row = dst.rows, col = dst.cols * dst.channels();
7 uchar *cc = dst.data;
8 for(int i = 0; i < row; ++i) {
9 for(int j = 0; j < col; ++j) {
10 int val = *cc;
11 if(a > val) a = val;
12 if(b < val) b = val;
13 cc++;
14 }
15 }
16 cc = dst.data;
17 float k = float(d - c)/(b-a);
18 //CString c1; c1.Format(_T("a=%d,b=%d,c=%d,d=%d,k=%.2f\n"), a,b,c,d,k);MessageBox(c1);
19 for(int i = 0; i < row; ++i) {
20 for(int j = 0; j < col; ++j) {
21 int val = *cc;
22 int s = (int)(k*(val - a) + c);
23 *cc = s;
24 cc++;
25 }
26 }
27 return true;
28 }
29 //对数变换
30 bool CImageEnhance::GraynoLinearlog(Mat &src, Mat &dst) {
31 dst = src.clone();
32 int row = dst.rows, col = dst.cols * dst.channels();
33 uchar *cc = dst.data;
34 double k = 255 / log10(256.0);
35 for(int i = 0; i < row; ++i) {
36 for(int j = 0; j < col; ++j) {
37 int val = *cc;
38 *cc = k * log10(1.0*(val + 1));
39 cc++;
40 }
41 }
42 return true;
43 }
44 //指数变换
45 bool CImageEnhance::GraynoLinearindex(Mat &src, Mat &dst) {
46 dst = src.clone();
47 int row = dst.rows, col = dst.cols * dst.channels();
48 uchar *cc = dst.data;
49 double k = 1.0 / 255;
50 for(int i = 0; i < row; ++i) {
51 for(int j = 0; j < col; ++j) {
52 int val = *cc;
53 *cc = k * val * val;
54 cc++;
55 }
56 }
57 return true;
58 }
59
60 MatND CImageEnhance::getHist1(Mat& image)
61 {
62 MatND hist;
63 int channels[] = {0};
64 int dims = 1;
65 int histSize[] = {256}; //直方图箱子的个数
66 float granges[] = {0, 255};
67 const float *ranges[] = {granges}; //像素值范围
68 //计算直方图
69 calcHist(&image, 1, channels, Mat()/*不使用掩码*/, hist, dims/*这是一维的直方图*/, histSize, ranges);
70 return hist; //这里得到的hiat是256行一列的Mat
71 }
72
73 //直方图均衡化
74 bool CImageEnhance::Equalize_hist(cv::Mat& src,cv::Mat& dst)
75 {
76 //CMFC_Test_lyyDlg pic;
77 MatND hist;
78 int channels[] = {0};
79 int dims = 1;
80 int histSize[] = {256}; //直方图箱子的个数
81 float granges[] = {0, 255};
82 const float *ranges[] = {granges}; //像素值范围
83 //计算直方图
84 Mat image = src.clone();
85 calcHist(&image, 1, channels, Mat()/*不使用掩码*/, hist, dims/*这是一维的直方图*/, histSize, ranges);
86
87 //MatND hist = getHist1(src);//pic.getHist(dst);
88 float s[256];
89 float p[256];
90
91 cv::Mat lookup(cv::Size(1, 256), CV_8U);
92 int pixNum = src.cols * src.rows;//总像素个数
93 for (int i =0; i <256; i++) {
94 s[i] = hist.at<float>(i) / pixNum;
95 if (i ==0) {
96 p[i] = s[i];
97 }
98 else {
99 p[i] = p[i -1] + s[i];
100 }
101 }
102 for (int i =0; i <256; i++) {
103 lookup.at <uchar>(i) = static_cast<uchar>(p[i]*255.0);
104 }
105
106 cv::LUT(src, lookup, dst);//创建矩阵,把一个像素值映射到另一个像素值
107 return true;
108 }
ImageEnhance.cpp
效果如下:
原图像:
线性灰度增强:我这里默认a和b表示原图像灰度值的最小与最大值。以下示例取c=255,d=0,效果为使图像负像,即黑变白,白变黑。
对数变换:(使图像的低灰度范围得以扩展而高灰度范围得以压缩,变换后的图像更符合人的视觉效果,因为人眼对高亮度的分辨率要求高于对低亮度的分辨率)
指数变换:(指数大于1。与对数变换相反。)
直方图均衡化:
求原图像的灰度直方图代码:
1 //获得直方图
2 MatND getHistt(Mat& image){
3 MatND hist;
4 int channels[] = {0};
5 int dims = 1;
6 int histSize[] = {256}; //直方图箱子的个数
7 float granges[] = {0, 255};
8 const float *ranges[] = {granges}; //像素值范围
9 //计算直方图
10 calcHist(&image, 1, channels, Mat()/*不使用掩码*/, hist, dims/*这是一维的直方图*/, histSize, ranges);
11 return hist; //这里得到的hiat是256行一列的Mat
12 }
13 // 将图像的直方图展示出来
14 Mat draw_Hist(Mat &inputImage)
15 {
16 cv::MatND hist = getHistt(inputImage);
17 Mat showImage(256, 256, CV_8U,Scalar(255));
18 int i;
19 double maxValue = 0;
20 minMaxLoc(hist, 0, &maxValue, 0, 0);
21 for(i = 0; i < 256; i++)
22 {
23 float value = hist.at<float>(i);
24 int intensity = saturate_cast<int>(256 - 256 * (value/maxValue));
25 rectangle(showImage, Point(i, 256 - 1), Point((i+1)-1, intensity), Scalar(0));
26 }
27 //namedWindow("gray"); imshow("gray", showImage);
28 //cvMoveWindow("gray", 300, 300);
29 //waitKey(0);
30 return showImage;
31 }
View Code
直方图显示:以下展示的 为以上的原图像以及直方图均衡化后的图像的 灰度直方图。