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

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。