Contrast Enhancement:
对比度增强一直是图像处理中的一个恒久话题,一般来说都是基于直方图的,比如直方图均衡化。冈萨雷斯的书里面对这个话题讲的比较透彻。
关于图像增强必须清楚的基本概念
1.图像增强的目的:
1)改善图像的视觉效果,
2)转换为更适合于人或机器分析处理的形式
3)突出对人或机器分析有意义的信息
4)抑制无用信息,提高图像的使用价值
5)增强后的图像并不一定保真
2,图像增强的方法分类:
1)从处理对象分类:灰度图像,(伪)彩色图像
2)从处理策略分类:全局处理,局部处理(ROI ROI,Region of Interest Interest)
3)从处理方法分类:空间域(点域运算,即灰度变换;邻域方法,即空域滤波),频域方法
4)从处理目的分类:图像锐化,平滑去噪,灰度调整(对比度增强)
3.图像增强的方法:
(1). 基于直方图均衡化的图像增强(Histogram Equalization)
a. 基本思想
对于图像中的灰度点做映射,使得整体图像的灰度大致符合均匀分布。增强图像的对比度。
b. 算法
step1:根据图像灰度计算灰度概率密度函数PDF
step2:计算累积概率分布函数CDF
step3:将CDF归一化到原图灰度取值范围,如[0,255]。
step4:之后CDF四舍五入取整,得到灰度转换函数sk=T(rk)
step5:将CDF作为转换函数,将灰度为rk的点转换为sk灰度
直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。
彩色图像的直方图均衡化实现:
#include
#include
using namespace cv;
using namespace std;
int main(int argc, char *argv[])
{
Mat image = imread("D:/picture/opencv/images/Lenna.png", 1);
if (image.empty())
{
cout << "could not load images.." << endl;
return -1;
}
imshow("src", image);
Mat imageRGB[3];
split(image, imageRGB);
for (int i = 0; i < 3; i++)
{
equalizeHist(imageRGB[i], imageRGB[i]);
}
merge(imageRGB, 3, image);
imshow("equalizeHist", image);
waitKey(0);
return 0;
}
(2). 基于拉普拉斯算子的图像增强
使用中心为5的8邻域拉普拉斯算子与图像卷积可以达到锐化增强图像的目的,拉普拉斯算子如下图所示:
#include
#include
using namespace cv;
using namespace std;
int main(int argc, char *argv[])
{
Mat image = imread("D:/picture/opencv/images/Lenna.png", 1);
if (image.empty())
{
cout << "could not load images..." << endl;
return -1;
}
imshow("原图像", image);
Mat imageEnhance;
Mat kernel = (Mat_(3, 3) << 0, -1, 0, 0, 5, 0, 0, -1, 0);
filter2D(image, imageEnhance, CV_8UC3, kernel);
imshow("拉普拉斯算子图像增强效果", imageEnhance);
waitKey(0);
return 0;
}
(3).基于对数Log变换的图像增强
对数变换可以将图像的低灰度值部分扩展,显示出低灰度部分更多的细节,将其高灰度值部分压缩,减少高灰度值部分的细节,从而达到强调图像低灰度部分的目的。变换方法:
对数变换对图像低灰度部分细节增强的功能过可以从对数图上直观理解:
x轴的0.4大约对应了y轴的0.8,即原图上00.4的低灰度部分经过对数运算后扩展到00.8的部分,而整个0.41的高灰度部分被投影到只有0.81的区间,这样就达到了扩展和增强低灰度部分,压缩高灰度部分的值的功能。
从上图还可以看到,对于不同的底数,底数越大,对低灰度部分的扩展就越强,对高灰度部分的压缩也就越强。
#include
#include
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
Mat image = imread("D:/picture/opencv/images/Lenna.png");
Mat imageLog(image.size(), CV_32FC3);
for (int i = 0; i < image.rows; i++)
{
for (int j = 0; j < image.cols; j++)
{
imageLog.at(i, j)[0] = log(1 + image.at(i, j)[0]);
imageLog.at(i, j)[1] = log(1 + image.at(i, j)[1]);
imageLog.at(i, j)[2] = log(1 + image.at(i, j)[2]);
}
}
//归一化到0~255
normalize(imageLog, imageLog, 0, 255, CV_MINMAX);
//转换成8bit图像显示
convertScaleAbs(imageLog, imageLog);
imshow("src", image);
imshow("基于对数Log变换的图像增强", imageLog);
waitKey();
return 0;
}
(4). 基于伽马(Gamma)变换的图像增强
伽马变换主要用于图像的校正,将灰度过高或者灰度过低的图片进行修正,增强对比度。变换公式就是对原图像上每一个像素值做乘积运算:
伽马变换对图像的修正作用其实就是通过增强低灰度或高灰度的细节实现的,从伽马曲线可以直观理解:
γ值以1为分界,值越小,对图像低灰度部分的扩展作用就越强,值越大,对图像高灰度部分的扩展作用就越强,通过不同的γ值,就可以达到增强低灰度或高灰度部分细节的作用。
伽马变换对于图像对比度偏低,并且整体亮度值偏高(对于于相机过曝)情况下的图像增强效果明显。
#include
#include
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
Mat image = imread("D:/picture/opencv/images/Lenna.png");
Mat imageGamma(image.size(), CV_32FC3);
for (int i = 0; i < image.rows; i++)
{
for (int j = 0; j < image.cols; j++)
{
imageGamma.at(i, j)[0] = (image.at(i, j)[0])*(image.at(i, j)[0])*(image.at(i, j)[0]);
imageGamma.at(i, j)[1] = (image.at(i, j)[1])*(image.at(i, j)[1])*(image.at(i, j)[1]);
imageGamma.at(i, j)[2] = (image.at(i, j)[2])*(image.at(i, j)[2])*(image.at(i, j)[2]);
}
}
//归一化到0~255
normalize(imageGamma, imageGamma, 0, 255, CV_MINMAX);
//转换成8bit图像显示
convertScaleAbs(imageGamma, imageGamma);
imshow("原图", image);
imshow("伽马变换图像增强效果", imageGamma);
waitKey();
return 0;
}