图像增强是对图像进行加工,以得到对具体应用来说视觉效果更“好”,或更“有用”的图像的技术。
图像在传输或者处理过程中会引入噪声或使图像变模糊,从而降低了图像质量,甚至淹没了特征,给分析带来了困难。
①改善图像的视觉效果,提高图像的清晰度;
②将图像转换成一种更适合于人或机器分析处理的形式。
③注意:在图像增强的过程中,没有新信息的增加,只是通过压制一部分信息,从而突出另一部分信息。
(1)空域法
直接对图像的像素灰度值进行操作。
包括图像的灰度变换、直方图修正、平滑和锐化处理、彩色增强等。
(2)频域法
在图像的变换域中,对图像的变换值进行操作,然后经逆变换获得所需的增强结果。
常用的方法包括低通滤波、高频提升滤波以及同态滤波法等。
设原图像为f(m,n),处理后为g(m,n),则对比度增强可表示为:
其中,T[i]表示增强图像和原图像的灰度变换关系(函数)。
设原图像灰度值f(m,n)∈[a,b],线性变换后的取值g(m,n)∈[c,d],变换关系为:
其中称为变换函数(直线)的斜率。
(1)扩展兴趣的,牺牲其他
对于感兴趣的[a,b]区间,采用斜率大于1的线性变换来扩展,而把其他区间用a或b来表示。变换函数为
(2)扩展兴趣的,压缩其他
在扩展感兴趣的[a,b]区间的同时,为了保留其他区间的灰度层次,也可以采用其他区间压缩的方法,即有扩有压。变换函数为:
/*对比度拉伸-分段线性变换*/
void Contrast_stretch(Mat& src,Mat& dst,double a,double b,double c,double d)
{
src.copyTo(dst);
dst.convertTo(dst, CV_64F);
double min = 0, max = 0;
minMaxLoc(dst, &min, &max, 0, 0); //在dst矩阵中找到全局最大值和全局最小值(只能用于单通道)
int nr = dst.rows;
int nc = dst.cols * dst.channels();
if (dst.isContinuous()) //若存储连续(行与行之间的存储),则可将图像看做一个一维数组
{
int nr = 1;
int nc = dst.cols * dst.rows * dst.channels();
}
for (int i = 0; i < nr; i++)
{
double* ptr_dst = dst.ptr<double>(i); //指向第i行第一个元素的指针
for (int j = 0; j < nc; j++)
{
if (min <= ptr_dst[j] < a)
{
ptr_dst[j] = (c / a) * ptr_dst[j];
}
else if (a <= ptr_dst[j] < b)
{
ptr_dst[j] = ((d - c) / (b - a)) * ptr_dst[j];
}
else if (b <= ptr_dst[j] < max)
{
ptr_dst[j] = ((max - d) / (max - b)) * ptr_dst[j];
}
}
}
dst.convertTo(dst, CV_8U); //转回无符号八位图像
}
(1)对数变换
其中λ为一个调节常数,用它来调节变换后的灰度值,使其符合实际要求。
对数变换的作用是扩展图像的低灰度范围,同时压缩高灰度范围,使得图像灰度分布均匀,与人的视觉特性相匹配。反对数变换与之相反。
对数函数有个重要特征:它压缩像素值变化较大的图像的动态范围。通常,频谱值的范围从0到106,甚至更高。尽管计算机能毫无问题地处理这一范围的数字,但图像的显示系统通常不能如实地再现如此大范围的灰度值。因而,最终结果是许多重要的灰度细节在典型的傅里叶频谱的显示中丢失了。
/*对数变换*/
void Log_trans(Mat& src, Mat& dst, double c)
{
int nr = src.rows;
int nc = src.cols * src.channels();
src.copyTo(dst);
dst.convertTo(dst, CV_64F);
if (src.isContinuous() && dst.isContinuous())
{
nr = 1;
nc = src.rows * src.cols * src.channels();
}
for (int i = 0; i < nr; i++)
{
const uchar* srcdata = src.ptr<uchar>(i); //获取第i行首地址
double* dstdata = dst.ptr<double>(i);
for (int j = 0; j < nc; j++)
{
dstdata[j] = c * log(double(1.0 + srcdata[j]));
}
}
normalize(dst, dst, 0, 255, NORM_MINMAX); //归一化数据,
dst.convertTo(dst, CV_8U);
}
(2)指数变换
与对数变换的效果相反,指数变换使得高灰度范围得到扩展,而压缩了低灰度范围。
其中λ和γ为常数。为避免底数为0的情况,增加偏移量ε。γ值的选择对于变换函数的特性有很大影响,当γ<1时会将原图像的灰度向高亮度部分映射,当γ>1时向低亮度部分映射,而当γ=1时相当于正比变换。
(3)幂律(伽马)变换
其中c和γ是正常数;
γ<1提高灰度级,在正比函数上方,使图像变亮;
γ>1降低灰度级,在正比函数下方,使图像变暗。
示例:
/*指数变换:c-系数;r-指数*/
void change_index(Mat& src, Mat& dst, double c, double r)
{
int nr = src.rows;
int nc = src.cols;
src.copyTo(dst);
dst.convertTo(dst, CV_64F);
if (src.isContinuous() && dst.isContinuous())
{
nr = 1;
nc = src.rows * src.cols * src.channels();
}
for (int i = 0; i < nr; i++)
{
const uchar* srcdata = src.ptr<uchar>(i); //获取第i行首地址
double* dstdata = dst.ptr<double>(i);
for (int j = 0; j < nc; j++)
{
dstdata[j] = c * pow(srcdata[j], r);
}
}
normalize(dst, dst, 0, 255, NORM_MINMAX); //归一化数据
dst.convertTo(dst, CV_8U);
}
参考文章:https://blog.csdn.net/weixin_40647819/article/details/88014295