灰度线性变换公式: D0=EH(D1) = aD1+b (变换后的像素点等于原像素点经一次线性变换得到)
包括:反色,折线变换 ,窗口变换
非线性变换 公式:D0=EH(D1)=Clog(1+|D1|)
包括:log 动态压缩变换,
将24位位图转换成灰度图:
/************************************************************************/
// 函数名称: GetGray()
// 参数: MyBitmap myBmp --------待处理的24位bmp位图
// unsigned char* srcchar --------存放灰度图像的数组
// 返回值 无
// 说明 : 该函数用来得到24位位图的灰度图像
/************************************************************************/
void MyProcess::GetGray(MyBitmap myBmp,unsignedchar*srcchar
{
if(myBmp.GetBitCount()!=24)return;
int i,j;
for(i=0;i<myBmp.GetHeight();i++)
for(j=0;j<myBmp.GetWidth();j+=3)
{
unsignedchar b=myBmp.GetBmp()[i*myBmp.GetWidth()+j];
unsignedchar g=myBmp.GetBmp()[i*myBmp.GetWidth()+j+1];
unsignedchar r=myBmp.GetBmp()[i*myBmp.GetWidth()+j+2];
unsignedchar h=(r*30+g*59+b*11)/100;
srcchar[i*myBmp.GetBmpWidth()+j/3]= h;
}
}
灰度直方图:
/************************************************************************
函数名称: GetGrayIntensity()
参数: unsigned char *gray --------待处理的灰度图
int *grayInt --------存放灰度直方图的数组
LONG width,LONG height-------图像的宽度和高度
返回值 无
说明 : 该函数用来得到灰度图像的直方图
************************************************************************/
void GetGrayIntensity(unsignedchar*gray,int*grayInt,LONG width,LONG height);//得到灰度图的灰度直方图
voidMyProcess::GetGrayIntensity(unsignedchar*gray,int*grayInt,LONG width,LONG height)
{
int i,j;
for(i=0;i<height;i++)
for(j=0;j<width;j++)
{
int temp = gray[i*width+j];
grayInt[temp]++;
}
}
反色:
/************************************************************************
函数名称: PointInvert()
参数: unsigned char *bmp --------待处理的图像
int x, int y ----------显示的位置
LONG width,LONG height-------图像的宽度和高度
返回值 无
说明 : 该函数将图像进行反色变换处理,注意:会改变原图片
************************************************************************/
void PointInvert(unsignedchar*bmp,LONG width,LONG height);
void MyProcess::PointInvert(unsignedchar*bmp,LONG width,LONG height)
{
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
bmp[i*width+j]=255-bmp[i*width+j];
}
}
灰度折线变换:
/************************************************************************
函数名称: GrayStretch()
参数: unsigned char *bmp --------待处理的图像
LONG width,LONG height-------图像的宽度和高度
BYTE bx1 -------折线1的原始灰度
BYTE by1
返回值 无
说明 : 该函数将图像进行灰度折线变换
************************************************************************/
void GrayStretch(unsignedchar*bmp,LONG width,LONG height,BYTE bx1,BYTE by1,BYTE bx2,BYTE by2);
void MyProcess::GrayStretch(unsignedchar*bmp,LONG width,LONG height,BYTE bx1,BYTE by1,BYTE bx2,BYTE by2)
{
LONG i,j;//循环变量
BYTE bMap[256];
for(i=0;i<=bx1;i++)
{
//判断bx1是否大于0(防止分母为0)
if(bx1>0)
{
//线性变换
bMap[i]=(BYTE) by1*i/bx1;
}else
{
bMap[i]=0;
}
}
for(;i<=bx2;i++)
{
//判断bx2是否大于0(防止分母为0)
if(bx2!=bx1)
{
//线性变换
bMap[i]=(BYTE)(by2-by1)*(i-bx1)/(bx2-bx1);
}else
{
bMap[i]=by1;
}
}
for(;i<256;i++)
{
if(bx2!=255)
{
bMap[i]=by2+(BYTE)((255-by2)*(i-bx2)/(255-bx2));
}else
{
bMap[i]=255;
}
}
for(i=0;i<height;i++)
for(j=0;j<width;j++)
{
BYTE temp = bmp[i*width+j];
bmp[i*width+j]= bMap[temp];
}
}
灰度窗口变换:
/************************************************************************
函数名称: GrayStretch()
参数: unsigned char *bmp --------待处理的图像
LONG width,LONG height-------图像的宽度和高度
BYTE bLow -------- 窗口下限
BYTE bUp -------- 窗口上限
返回值 无
说明 : 对图像进行灰度窗口变换,即小于下限为0,大于上限为255,中间线性变换
************************************************************************/
voidWindowTrans(BYTE *bmp,LONG width,LONG height ,BYTE bLow,BYTE bUp);
voidMyProcess::WindowTrans(BYTE *bmp,LONG width,LONG height ,BYTE bLow,BYTE bUp)
{
LONG i,j;//循环变量
for(i=0;i<height;i++)
for(j=0;j<width;j++)
{
BYTE temp = bmp[i*width+j];
if(temp < bLow) bmp[i*width+j]=0;
else if(temp > bUp) bmp[i*width+j]=255;
}
}
灰度非线性变换:
/************************************************************************
函数名称: DynamicCompress()
参数: unsigned char *bmp --------待处理的图像
LONG width,LONG height-------图像的宽度和高度
int C --------- 非线性变换比例常数
返回值 无
说明 : 对图像进行非线性变换 公式:D0=EH(D1)=Clog(1+|D1|),用于动态范围过大时
************************************************************************/
void DynamicCompress(BYTE *bmp,LONG width,LONG height,int C);
void MyProcess::DynamicCompress(BYTE *bmp,LONG width,LONG height,int C)
{
LONG i,j;//循环变量
for(i=0;i<height;i++)
for(j=0;j<width;j++)
{
bmp[i*width+j]= C*log(1+bmp[i*width+j]);
}
}
均衡变换:
/************************************************************************
函数名称: PointEqua()
参数: BYTE *bmp --------待处理的图像
LONG width,LONG height-------图像的宽度和高度
int type --------图像类型,0:24位彩色,1:灰度
返回值 无
说明 : 对图像进行均衡变换
************************************************************************/
void PointEqua(BYTE *bmp,LONG width,LONG height,int type=0);
void MyProcess::PointEqua(BYTE *bmp,LONG width,LONG height,int type)
{
LONG i,j;
int R[256],G[256],B[256];
memset(R,0,sizeof(R));
memset(G,0,sizeof(G));
memset(B,0,sizeof(B));
//统计各个变量的个数
if(type==0)GetIntensity(bmp,width,height,R,G,B);
else if(type==1)GetGrayIntensity(bmp,R,width,height);
float temp_r[256],temp_g[256],temp_b[256];
memset(temp_r,0,sizeof(temp_r));
memset(temp_g,0,sizeof(temp_g));
memset(temp_b,0,sizeof(temp_b));
double sum ;
if(type==0) sum = width*height/3;
else if(type==1) sum=width*height;
//获得各个变量的百分比
for(i=0;i<256;i++)
{
if(i==0)
{
if(type==0)
{
temp_r[0]=(double)R[0]/sum;
temp_g[0]=(double)G[0]/sum;
temp_b[0]=(double)B[0]/sum;
}else if(type==1)
{
temp_r[0]=(double)R[0]/sum;
}
}
else
{
if(type==0)
{
temp_r[i]=temp_r[i-1]+(double)R[i]/sum;
temp_g[i]=temp_g[i-1]+(double)G[i]/sum;
temp_b[i]=temp_b[i-1]+(double)B[i]/sum;
}elseif(type==1)
{
temp_r[i]=temp_r[i-1]+(double)R[i]/sum;
}
}
}
//计算均衡值
for(i=0;i<256;i++)
{
if(type==0)
{
temp_r[i]=(int)(255.0f*temp_r[i]+0.5);
temp_g[i]=(int)(255.0f*temp_g[i]+0.5);
temp_b[i]=(int)(255.0f*temp_b[i]+0.5);
}else if(type==1)
{
temp_r[i]=(int)(255.0f*temp_r[i]+0.5);
}
}
for(i=0;i<height;i++)
for(j=0;j<width;j++)
{
if(type==0)
{
bmp[i*width+j]=temp_r[bmp[i*width+j]];
j++;
bmp[i*width+j]=temp_g[bmp[i*width+j]];
j++;
bmp[i*width+j]=temp_b[bmp[i*width+j]];
}else if(type==1)
{
bmp[i*width+j]=temp_r[bmp[i*width+j]];
}
}
}
灰度匹配变换
/************************************************************************
函数名称: PointEqua()
参数: BYTE *bmp --------待处理的图像
LONG width,LONG height-------图像的宽度和高度
BYTE bNum ----规定直方图灰度级数
int *Nu-------规定直方图灰度映射关系
float *Pu-----规定直方图各灰度的分布概率
int type --------图像类型,0:24位彩色,1:灰度
返回值 无
说明 : 对图像进行单映射规则直方图规定化变换
************************************************************************/
void PointSML(BYTE *bmp,LONG width,LONG height,BYTE bNum,int*Nu,float*Pu,int type=0);
void MyProcess::PointSML(BYTE *bmp,LONG width,LONG height,BYTE bNum,int*Nu,float*Pu,int type)
{
LONG i,j;
int R[256],G[256],B[256];
int mMap_r[256],mMap_g[256],mMap_b[256];
memset(R,0,sizeof(R));
memset(G,0,sizeof(G));
memset(B,0,sizeof(B));
if(type==0)GetIntensity(bmp,width,height,R,G,B);
else if(type==1)GetGrayIntensity(bmp,R,width,height);
float temp_r[256],temp_g[256],temp_b[256];
double sum ;
if(type==0) sum = width*height/3;
elseif(type==1) sum=width*height;
//计算原始累计直方图
for(i=0;i<256;i++)
{
if(i==0)
{
if(type==0)
{
temp_r[0]=(double)R[0]/sum;
temp_g[0]=(double)G[0]/sum;
temp_b[0]=(double)B[0]/sum;
}elseif(type==1)
{
temp_r[0]=(double)R[0]/sum;
}
}
else
{
if(type==0)
{
temp_r[i]=temp_r[i-1]+(double)R[i]/sum;
temp_g[i]=temp_g[i-1]+(double)G[i]/sum;
temp_b[i]=temp_b[i-1]+(double)B[i]/sum;
}else if(type==1)
{
temp_r[i]=temp_r[i-1]+(double)R[i]/sum;
}
}
}
//计算规定累计直方图
for(i=1;i<bNum;i++)
{
Pu[i]=Pu[i-1]+Pu[i];
}
//确定映射对应关系
for(i=0;i<256;i++)
{
//最接近的规定直方图灰度级
int m_r=0,m_g=0,m_b=0;
//最小差值
float f_r=1,f_g=1,f_b=1;
//寻找最小差值
for(j=0;j<bNum;j++)
{
float f_now=abs(temp_r[i]-Pu[j]);
if(f_now < f_r)
{
f_r=f_now;
mMap_r[i]=j;
}
if(type==0)
{
float f_now_g=abs(temp_g[i]-Pu[j]);
if(f_now < f_g)
{
f_g=f_now;
mMap_g[i]=j;
}
float f_now_b=abs(temp_b[i]-Pu[j]);
if(f_now < f_b)
{
f_b=f_now;
mMap_b[i]=j;
}
}
}
}
for(i=0;i<height;i++)
for(j=0;j<width;j++)
{
if(type==0)
{
bmp[i*width+j]=mMap_r[bmp[i*width+j]];
j++;
bmp[i*width+j]=mMap_g[bmp[i*width+j]];
j++;
bmp[i*width+j]=mMap_b[bmp[i*width+j]];
}else if(type==1)
{
bmp[i*width+j]=mMap_r[bmp[i*width+j]];
}
}
}