图像锐化处理的目的是使模糊的图像变得更加清晰起来,通常针对引起图像模糊的原因而进行相应地锐化操作属于图像复原的内容。图像的模糊实质就是图像受到平均或积分运算造成的,因此可以对图像进行还原运算如微分运算来使图像清晰化。从频谱角度来分析,图像模糊的实质是其高频分量被衰减,因而可以通过高通滤波操作来清晰图像。但要注意,能够进行锐化处理的图像必须有较高的信噪比,否则锐化后图像信噪比反而更低,从而使噪声的增加得比信号还要多,因此一般是先取出或减轻噪声后再进行锐化处理。下面对图像锐化的集中算子进行学习。
拉普拉斯算子是图像邻域内像素灰度差分计算的基础,通过二阶微分推导出的一种图像邻域增强算法。它的基本思想是当邻域的中心像素灰度低于它所在邻域内的其他像素的平均灰度时,此中心像素的灰度应该进一步降低;当高于时进一步提高中心像素的灰度,从而实现图像锐化处理。
在算法实现过程中,通过对邻域中心像素的四方向或八方向求梯度,并将梯度和相加来判断中心像素灰度与邻域内其他像素灰度的关系,并用梯度运算的结果对像素灰度进行调整。
一个连续的二元函数f(x,y),其拉普拉斯运算定义为:
对于数字图像,拉普拉斯算子可以简化为:
也可以按卷积形式表示:
其中K=1,I=1时H(r,s)取下式,四方面模板:
通过模板可以发现,当邻域内像素灰度相同时,模板的卷积运算结果为0;当中心像素灰度高于邻域内其他像素的平均灰度时,模板的卷积运算结果为正数;当中心像素的灰度低于邻域内其他像素的平均灰度时,模板的卷积的负数。对卷积运算的结果用适当的衰弱因子处理并加在原中心像素上,就可以实现图像的锐化处理。
代码如下:
//拉普拉斯算子
void LaplacianFilter(BYTE *SrcImage, BYTE *DstImage, int nWidth, int nHeight)
{
int HWS=3;//模板维数:此四个模板均为3维的
int H[3][3]={{0,-1,0},//模板是个中心为4的拉普拉斯算子
{-1,4,-1},
{0,-1,0}};
int red, green, blue;
int X,Y;//一维坐标转换为二维坐标
int TR, TG, TB;//记录红绿蓝坐标位置
//图像增强 锐化
for (int i=0;i<nWidth*nHeight;i=i+3)
{
X=(i/3)%nWidth;//x列
Y=(i/3)/nHeight;//y行
red=green=blue=0;
//对图像进行像素求和并取平均值HWS维数
for (int j=Y-HWS/2; j<Y+HWS/2+1 ; j++)//第j行
{
for (int k=X-HWS/2 ; k<X+HWS/2+1 ; k++)//第k列
{
if (j>=0 && k>=0 && k<nWidth && j<nHeight)
{
TR = j*nWidth*3+k*3;
red+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TR]);
TG = j*nWidth*3+k*3+1;
green+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TG]);
TB = j*nWidth*3+k*3+2;
blue+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TB]);
}
}
}
//对新图像进行赋值
if (red>=0 && red<256)
{
DstImage[i]=red;
}
else if (red < 0)
{
DstImage[i]=0;
}
else DstImage[i]=0;
if (green>=0 && green<256)
{
DstImage[i+1]=green;
}
else if (green<0)
{
DstImage[i+1]=0;
}
else DstImage[i+1]=0;
if (blue>=0 && blue<256)
{
DstImage[i+2]=blue;
}
else if (blue<0)
{
DstImage[i+2]=0;
}
else DstImage[i+2]=0;
}
}
常用的高通模板如下所示,其中H2有的书上又称为拉普拉斯八方向的锐化模板。
选取H2模板,代码如下所示:
//高通滤波
void HighpassFilter(BYTE *SrcImage, BYTE *DstImage, int nWidth, int nHeight)
{
int HWS = 3;
int H[3][3]={{-1,-1,-1},
{-1,8,-1},
{-1,-1,-1}};
int red, green, blue;
int X,Y;
int TR,TG,TB;
//图像增强 锐化
for (int i=0; i<nWidth*nHeight; i=i+3)
{
X=(i/3)%nWidth;
Y=(i/3)/nHeight;
red=green=blue=0;
//对图像进行像素求和并取平均值 HWS维数
for (int j=Y-HWS/2;j<Y+HWS/2+1;j++)
{
for (int k=X-HWS/2;k<X+HWS/2+1;k++)
{
if (j>=0 && k>=0 && k<nWidth && j<nHeight)
{
TR = j*nWidth*3+k*3;
red+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TR]);
TG = j*nWidth*3+k*3+1;
green+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TG]);
TB = j*nWidth*3+k*3;
blue+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TB]);
}
}
}
//对新图像赋值
if (red>=0 && red<256)
{
DstImage[i]=red;
}
else if (red<0)
{
DstImage[i]=0;
}
else DstImage[i]=0;
if (green>=0 && green<256)
{
DstImage[i+1]=green;
}
else if (green<0)
{
DstImage[i+1]=0;
}
else DstImage[i+1]=0;
if (blue>=0 && blue<256)
{
DstImage[i+2]=blue;
}
else if (blue<0)
{
DstImage[i+2]=0;
}
else DstImage[i+2]=0;
}
}
模板表示如下:
需要注意X和Y两个方向的模板处理,代码如下所示:
//Sobel算子
void SobelFilter(BYTE *SrcImage, BYTE *DstImage, int nWidth , int nHeight)
{
int HWS=3;
//Sobel算子模板
int HX[3][3]={{1,0,-1},{2,0,-2},{1,0,-1}};
int HY[3][3]={{-1,-2,-1},{0,0,0},{1,2,1}};
int redX,greenX,blueX;
int redY,greenY,blueY;
int X,Y;
int TR, TG, TB;
//图像增强 锐化
for (int i=0;i<nWidth*nHeight;i=i+3)
{
X=(i/3)%nWidth;
Y=(i/3)/nHeight;
redX=greenX=blueX=0;
redY=greenY=blueY=0;
//对图像进行像素求和并取平均值 HWS维数
for (int j=Y-HWS/2; j<Y+HWS/2+1; j++)
{
for (int k=X-HWS/2; k<X+HWS/2+1;k++)
{
if (j>=0 && k>=0 && k<nWidth && j<nHeight)
{
TR = j*nWidth*3+k*3;
redX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TR]);
redY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TR]);
TG = j*nWidth*3+k*3+1;
greenX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TG]);
greenY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TG]);
TB = j*nWidth*3+k*3+2;
blueX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TB]);
blueY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TB]);
}
}
}
int R,G,B;
R= (int)(sqrt(redX*redX*1.0+redY*redY*1.0));
G=(int)(sqrt(greenX*greenX*1.0+greenY*greenY*1.0));
B=(int)(sqrt(blueX*blueX*1.0+blueY*blueY*1.0));
if (redX<0 && redY<0)
{
DstImage[i]=0;
}
else if (R>255)
{
DstImage[i]=255;
}
else DstImage[i]=R;
if (greenX<0 && greenY<0)
{
DstImage[i+1]=0;
}
else if (G>255)
{
DstImage[i+1]=255;
}
else DstImage[i+1]=G;
if (blueX<0 && blueY<0 )
{
DstImage[i+2]=0;
}
else if (B>255)
{
DstImage[i+2]=255;
}
else DstImage[i+2]=B;
}
}
//Isotropic算子
void IsotropicFilter(BYTE *SrcImage, BYTE *DstImage, int nWidth, int nHeight)
{
int HWS=3;
//Isotropic算子
float HX[3][3]={{1,0,-1},{sqrt(2.0),0,-sqrt(2.0)},{1,0,-1}};
float HY[3][3]={{-1,-sqrt(2.0),-1},{0,0,0},{1,sqrt(2.0),1}};
float redX,greenX,blueX;
float redY,greenY,blueY;
int X,Y;
int TR, TG, TB;
//图像增强
for (int i=0;i<nWidth*nHeight; i=i+3)
{
X=(i/3)%nWidth;
Y=(i/3)/nHeight;
redX = greenX = blueX =0;
redY = greenY = blueY =0;
//对图像进行像素求和并取均值HWS维数
for (int j=Y-HWS/2 ; j<Y+HWS/2+1 ; j++)
{
for (int k=X-HWS/2 ; k<X+HWS/2+1 ; k++)
{
if (j>=0 && k>=0 && k<nWidth && j<nHeight)
{
TR = j*nWidth*3+k*3;
redX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(SrcImage[TR]);
redY+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(SrcImage[TR]);
TG = j*nWidth*3+k*3+1;
greenX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(SrcImage[TG]);
greenY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(SrcImage[TG]);
TB = j*nWidth*3+k*3+2;
blueX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(SrcImage[TB]);
blueY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(SrcImage[TB]);
}
}
}
int R,G,B;
R= (int)(sqrt(redX*redX*1.0+redY*redY*1.0));
G=(int)(sqrt(greenX*greenX*1.0+greenY*greenY*1.0));
B=(int)(sqrt(blueX*blueX*1.0+blueY*blueY*1.0));
if (redX<0 && redY<0)
{
DstImage[i]=0;
}
else if (R>255)
{
DstImage[i]=255;
}
else DstImage[i]=R;
if (greenX<0 && greenY<0)
{
DstImage[i+1]=0;
}
else if (G>255)
{
DstImage[i+1]=255;
}
else DstImage[i+1]=G;
if (blueX<0 && blueY<0 )
{
DstImage[i+2]=0;
}
else if (B>255)
{
DstImage[i+2]=255;
}
else DstImage[i+2]=B;
}
}
//Prewitt算子
void PrewittFilter(BYTE *SrcImage, BYTE *DstImage, int nWidth, int nHeight)
{
int HWS=3;
int H[3][3]={{1,0,-1},{1,0,-1},{1,0,-1}};//模板为prewitt算子
int red, green, blue;
int X,Y;
int TR, TG, TB;
//图像增强
for (int i=0; i<nWidth*nHeight;i=i+3)
{
X=(i/3)%nWidth;
Y=(i/3)/nHeight;
red=green=blue=0;
//对图像进行像素求和并取平均值HWS维数
for (int j=Y-HWS/2;j<Y+HWS/2+1;j++)
{
for (int k=X-HWS/2; k<X+HWS/2+1;k++)
{
if (j>=0 && k>=0 && k<nWidth && j<nHeight)
{
TR= j*nWidth*3+k*3;
red+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TR]);
TG=j*nWidth*3+k*3+1;
green+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TG]);
TB=j*nWidth*3+k*3+2;
blue+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(SrcImage[TB]);
}
}
}
//对新图像赋值
if (red>=0 && red<256)
{
DstImage[i]=red;
}
else if (red<0)
{
DstImage[i]=0;
}
else DstImage[i]=0;
if (green>=0 && green<256)
{
DstImage[i+1]=green;
}
else if (green<0)
{
DstImage[i+1]=0;
}
else DstImage[i+1]=0;
if (blue>=0 && blue<256)
{
DstImage[i+2]=blue;
}
else if (blue<0)
{
DstImage[i+2]=0;
}
else DstImage[i+2]=0;
}
}