DIP-图像增强
第二节:图像增强(Digital Image Enhancement)前言
遇到一些朦胧图片显示效果不够清晰怎么办?如大雾天气下细节缺失的图片,或夜间成像过于黑暗而丢失很多细节的图片等。图像增强可以有效解决这个问题。一、图像增强是什么?
图像增强是在处理前对原始数据进行质量和信息量的提高。
常见的做法包括对比度增强、空间滤波、密度切片和FCC。
对比度增强或拉伸是通过线性变换扩大原有的灰度范围来实现的。
空间滤波改进了自然发生的线性特征,如断层、剪切带和轮廓线。
密度切片将连续的灰色调范围转换为一系列密度间隔,用单独的颜色或符号来表示不同的特征。
这里我们着重讲解对比度增强以及其中常用的三种方法:线性对比度展宽、非线性动态范围调整、灰度直方图均衡化。
二、方法介绍
1.线性对比度展宽
目的:通过将亮暗差异(即对比度)扩大,来把人所关心的部分强调出来。
算法思想:f(i,j)为旧的位图矩阵函数,g(i,j)为新的位图矩阵函数。他们的对应关系如图所示。
代码如下(示例):
void linearContrastStretch(RGBQUAD** dataOfBmp_src, RGBQUAD** dataOfBmp_dst, DWORD width, DWORD height)
{
double ka = 0.2,kb = 8,kc = 0.2;
int a = 60,b = 120;//范围不应过小
double ga = a*ka;
double gb = b*kb+ga;
for(DWORD i=0;i<height;i++)
for(DWORD j=0;j<width;j++)
{
//printf("%d ",dataOfBmp_dst[i][j].rgbRed);
if(dataOfBmp_src[i][j].rgbRed<a)
dataOfBmp_dst[i][j].rgbRed = (dataOfBmp_dst[i][j].rgbRed * ka + 0.5);
if(dataOfBmp_src[i][j].rgbGreen<a)
dataOfBmp_dst[i][j].rgbGreen = (dataOfBmp_dst[i][j].rgbGreen * ka + 0.5);
if(dataOfBmp_src[i][j].rgbBlue<a)
dataOfBmp_dst[i][j].rgbBlue = (dataOfBmp_dst[i][j].rgbBlue * ka + 0.5);
if(dataOfBmp_src[i][j].rgbRed >= b)
dataOfBmp_dst[i][j].rgbRed = (kc*(dataOfBmp_src[i][j].rgbRed-b) + gb + 0.5);
if(dataOfBmp_src[i][j].rgbGreen >= b)
dataOfBmp_dst[i][j].rgbGreen = (kc*(dataOfBmp_src[i][j].rgbGreen-b) + gb + 0.5);
if(dataOfBmp_src[i][j].rgbBlue >= b)
dataOfBmp_dst[i][j].rgbBlue = (kc*(dataOfBmp_src[i][j].rgbBlue-b) + gb + 0.5);
if(dataOfBmp_src[i][j].rgbRed >= a && dataOfBmp_src[i][j].rgbRed < b)
dataOfBmp_dst[i][j].rgbRed = (kb*(dataOfBmp_src[i][j].rgbRed-a) + ga + 0.5);
if(dataOfBmp_src[i][j].rgbGreen >= a && dataOfBmp_src[i][j].rgbGreen < b)
dataOfBmp_dst[i][j].rgbGreen = (kb*(dataOfBmp_src[i][j].rgbGreen-a) + ga + 0.5);
if(dataOfBmp_src[i][j].rgbBlue >= a && dataOfBmp_src[i][j].rgbBlue < b)
dataOfBmp_dst[i][j].rgbBlue = (kb*(dataOfBmp_src[i][j].rgbBlue-a) + ga + 0.5);
}
}}
效果图:
2.非线性动态范围调整
目的:将暗的部分扩展,而将亮的部分抑制。
算法思想:通过动态范围的压缩,可以将所关心部分的灰度级的变化范围扩大。
动态范围调整方法分为以下两种:
1.线性动态范围调整
2.非线性动态范围调整
线性动态范围调整与上文第一种方法大同小异,这里着重介绍非线性动态范围调整方法
代码如下:
void dynamicRangeAdjustment(RGBQUAD** dataOfBmp_src, RGBQUAD** dataOfBmp_dst, DWORD width, DWORD height)
{
double c = 105.8865;//数值较低时,将暗的部分扩展,将亮的部分抑制 数值高的时候相反
for(DWORD i=0;i<height;i++)
for(DWORD j=0;j<width;j++)
{
dataOfBmp_dst[i][j].rgbRed = (c*log10(dataOfBmp_src[i][j].rgbRed + 1) + 0.5);
dataOfBmp_dst[i][j].rgbGreen = (c*log10(dataOfBmp_src[i][j].rgbGreen + 1) + 0.5);
dataOfBmp_dst[i][j].rgbBlue = (c*log10(dataOfBmp_src[i][j].rgbBlue + 1) + 0.5);
}
}
效果图:
3.非线性动态范围调整灰度直方图均衡化
算法思想:对图像中像素个数多的灰度级进行展宽,而对像素个数少的灰度级进行缩减,从而达到清晰图像的目的。
void histogramEqualization(RGBQUAD** dataOfBmp_src, RGBQUAD** dataOfBmp_dst, DWORD width, DWORD height)
{
printf("%d x %d\n",width,height);
DWORD Nf = width*height;//图像总体像素个数
printf("%d\n",Nf);
DWORD greyRange_R[256] = {
0};//灰度分级 0-255 起初设置int 造成溢出
DWORD greyRange_G[256] = {
0};
DWORD greyRange_B[256] = {
0};
for(DWORD i=0;i<height;i++)
for(DWORD j=0;j<width;j++)
{
greyRange_R[dataOfBmp_src[i][j].rgbRed]++;//统计所有灰度分级的频数
greyRange_G[dataOfBmp_src[i][j].rgbGreen]++;
greyRange_B[dataOfBmp_src[i][j].rgbBlue]++;
}
double hsR[256] = {
0.0};//每个灰度级的分布概率 R G B
double hsG[256] = {
0.0};
double hsB[256] = {
0.0};
for(int i = 0;i<256;i++){
hsR[i] = greyRange_R[i] /(Nf*1.0);
hsG[i] = greyRange_G[i]/(Nf*1.0);
hsB[i] = greyRange_B[i]/(Nf*1.0);
}
//求直方图
double temp1 = 0,temp2 = 0,temp3 = 0;
for(int i=0;i<256;i++){
hsR[i] += temp1;
temp1 = hsR[i];
hsG[i] += temp2;
temp2 = hsG[i];
hsB[i] += temp3;
temp3 = hsB[i];
}
//hs中存放R G B各灰度级的累积分布hp
for(DWORD i=0;i<height;i++)
for(DWORD j=0;j<width;j++)
{
if(dataOfBmp_src[i][j].rgbRed == 0)
dataOfBmp_dst[i][j].rgbRed = 0;
else if(dataOfBmp_src[i][j].rgbRed != 0)
dataOfBmp_dst[i][j].rgbRed = (255*hsR[dataOfBmp_src