图像增强是对图像进行处理,使其比原始图像更适合于特定的应用,它需要与实际应用相结合。对于图像的某些特征如边缘、轮廓、对比度等,图像增强是进行强调或锐化,以便于显示、观察或进一步分析与处理。图像增强的方法是因应用不同而不同的,研究内容包括:(参考课件和左飞的《数字图像处理》)
图像平滑是一种区域增强的算法,平滑算法有邻域平均法、中指滤波、边界保持类滤波等。在图像产生、传输和复制过程中,常常会因为多方面原因而被噪声干扰或出现数据丢失,降低了图像的质量(某一像素,如果它与周围像素点相比有明显的不同,则该点被噪声所感染)。这就需要对图像进行一定的增强处理以减小这些缺陷带来的影响。
1.简单平滑-邻域平均法
图像简单平滑是指通过邻域简单平均对图像进行平滑处理的方法,用这种方法在一定程度上消除原始图像中的噪声、降低原始图像对比度的作用。它利用卷积运算对图像邻域的像素灰度进行平均,从而达到减小图像中噪声影响、降低图像对比度的目的。
但邻域平均值主要缺点是在降低噪声的同时使图像变得模糊,特别在边缘和细节处,而且邻域越大,在去噪能力增强的同时模糊程度越严重。
I1 = imread('blood1.tif');
I=imnoise(I1,‘salt & pepper’,0.04); %对图像加椒盐噪声
imshow(I);
h1= [0.1 0.1 0.1; 0.1 0.2 0.1; 0.1 0.1 0.1]; %定义4种模板
h2=1/16.*[1 2 1;2 4 2;1 2 1];
h3=1/8.*[1 1 1;1 0 1;1 1 1];
h4=1/2.*[0 1/4 0;1/4 1 1/4;0 1/4 0];
I2=filter2(h1,I); %用4种模板进行滤波处理
I3=filter2(h2,I);
I4=filter2(h3,I);
I5=filter2(h4,I);
figure,imshow(I2,[]) %显示处理结果
figure,imshow(I3,[])
figure,imshow(I4,[])
figure,imshow(I5,[])
运行效果如下图所示:/**************************************************
第九章--图像增强
图像平滑 普通平滑 模板
float H1[3][3]={{1.0/10,1.0/10,1.0/10}, //模板一:系数1/10
{1.0/10,2.0/10,1.0/10},
{1.0/10,1.0/10,1.0/10}};
float H2[3][3]={{1.0/16,2.0/16,1.0/16}, //模板二:系数1/16
{2.0/16,4.0/16,2.0/16},
{1.0/16,2.0/16,1.0/16}};
float H3[3][3]={{1.0/8,1.0/8,1.0/8}, //模板三:系数1/8,此种情况为把点转为空心矩形
{1.0/8,0.0/8,1.0/8},
{1.0/8,1.0/8,1.0/8}};
float H4[3][3]={{0.0,1.0/8,0.0}, //模板四:系数乘数据后的矩阵
{1.0/8,1.0/2,1.0/8},
{0.0,1.0/8,0.0}};
/**************************************************/
void CImageProcessingView::OnTxzqPtph1()
{
if(numPicture==0) {
AfxMessageBox("载入图片后才能图像增强(平滑)!",MB_OK,0);
return;
}
AfxMessageBox("图像增强(平滑)!选取的模板为:普通平滑 模板一",MB_OK,0);
/******************************************************************/
/* 图想平滑的算法:
/* 1.定义常用的四个模板,它们的维数均为3,矩阵的个数均为9个数据
/* 2.它的思想是把一个点分散到这周围的9个点上,这样使图像更模糊
/* 3.通过卷积计算围绕该点的矩阵像素和,计算其平均值(除9)赋值给点
/* 4.模块不同,处理后的图像也各不相同
/******************************************************************/
/*第一步:先定义数据模板*/
int HWS=3; //模板维数:此四个模板均为3维的
float H1[3][3]={{1.0/10,1.0/10,1.0/10}, //模板一:系数1/10
{1.0/10,2.0/10,1.0/10},
{1.0/10,1.0/10,1.0/10}};
//打开临时的图片
FILE *fpo = fopen(BmpName,"rb");
FILE *fpw = fopen(BmpNameLin,"wb+");
fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);
fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);
fread(m_pImage,m_nImage,1,fpo);
//new和delete有效的进行动态内存的分配和释放
unsigned char *ImageSize;
ImageSize = new unsigned char[m_nImage];
float red,green,blue;
int X,Y; //一维坐标转换为二维坐标
int TR,TG,TB; //记录红绿蓝坐标位置
//图像增强:平滑 它要获取源图像周围9个点的矩阵乘以模板9个点的矩阵,故一维图像转二维
for(int i=0; i=0 && k>=0 && k
运行效果如图所示,图像平滑模糊了,但效果不是很好。
void CImageProcessingView::OnTxzqPtph2()
{
if(numPicture==0) {
AfxMessageBox("载入图片后才能图像增强(平滑)!",MB_OK,0);
return;
}
AfxMessageBox("图像增强(平滑)!选取的模板为:普通平滑 模板二",MB_OK,0);
/*第一步:先定义数据模板*/
int HWS=3;
float H2[3][3]={{1.0/8,1.0/8,1.0/8}, //模板三:系数1/8 此种情况为把点转为空心矩形
{1.0/8,0.0/8,1.0/8},
{1.0/8,1.0/8,1.0/8}};
//打开临时的图片
FILE *fpo = fopen(BmpName,"rb");
FILE *fpw = fopen(BmpNameLin,"wb+");
fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
//重点:图像的每行像素都必须是4的倍数:1*1的图像为 r g b 00H
int num; //记录每行多余的图像素数个数
int sfSize; //补齐后的图像大小
if(m_nWidth*3%4!=0) {
num=(4-m_nWidth*3%4);
sfSize=(m_nWidth*3+num)*m_nHeight; //每行多number个
}
else {
num=0;
sfSize=m_nWidth*m_nHeight*3;
}
/*更改文件头信息 定义临时文件头结构变量*/
BITMAPFILEHEADER bfhsf;
BITMAPINFOHEADER bihsf;
bfhsf=bfh;
bihsf=bih;
bfhsf.bfSize=sfSize+54;
fwrite(&bfhsf,sizeof(BITMAPFILEHEADER),1,fpw);
fwrite(&bihsf,sizeof(BITMAPINFOHEADER),1,fpw);
fread(m_pImage,m_nImage,1,fpo);
//new和delete有效的进行动态内存的分配和释放
unsigned char *ImageSize;
ImageSize = new unsigned char[sfSize];
float red,green,blue;
int X,Y; //一维坐标转换为二维坐标
int TR,TG,TB; //记录红绿蓝坐标位置
int countWidth=0; //记录每行的像素个数,满行时变回0
int place=0; //建立临时坐标 记录起始坐标(0,0)平移过来的位置
//图像增强 平滑
for(int i=0; i=0 && k>=0 && k
你可能注意到了,在图像处理过程中,如果每行的字节数不是4的倍数,可能会出现斜线之类的处理BUG,所以需要手动补0筹齐4的倍数,代码中补0后运行效果如下图所示,我也一直没找到原因,可能是思想和深度还没有达到,以后有机会在解决吧!同时后面的算法都不准备再进行补0处理,主要讲述算法的思想!
//高斯平滑
void CImageProcessingView::OnTxzqGsph()
{
if(numPicture==0) {
AfxMessageBox("载入图片后才能图像增强(平滑)!",MB_OK,0);
return;
}
AfxMessageBox("图像增强(平滑)!选取的模板为:高斯平滑",MB_OK,0);
/*第一步:先定义数据模板*/
int HWS=3; //模板维数为3维
float H[3][3]={{1.0/16,2.0/16,1.0/16}, //高斯模板 系数1/16
{2.0/16,4.0/16,2.0/16},
{1.0/16,2.0/16,1.0/16}};
//打开临时的图片
FILE *fpo = fopen(BmpName,"rb");
FILE *fpw = fopen(BmpNameLin,"wb+");
fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);
fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);
fread(m_pImage,m_nImage,1,fpo);
//new和delete有效的进行动态内存的分配和释放
unsigned char *ImageSize;
ImageSize = new unsigned char[m_nImage];
float red,green,blue;
int X,Y; //一维坐标转换为二维坐标
int TR,TG,TB; //记录红绿蓝坐标位置
//图像增强:平滑
for(int i=0; i=0 && k>=0 && k
运行效果如下图所示:
//中值滤波
void CImageProcessingView::OnTxzqZzlb()
{
if(numPicture==0) {
AfxMessageBox("载入图片后才能图像增强(平滑)!",MB_OK,0);
return;
}
AfxMessageBox("图像增强(平滑)!选取的模板为:中值滤波",MB_OK,0);
//打开临时的图片
FILE *fpo = fopen(BmpName,"rb");
FILE *fpw = fopen(BmpNameLin,"wb+");
fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);
fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);
fread(m_pImage,m_nImage,1,fpo);
//new和delete有效的进行动态内存的分配和释放
unsigned char *ImageSize;
ImageSize = new unsigned char[m_nImage];
int X,Y; //一维坐标转换为二维坐标
int TR,TG,TB; //记录红绿蓝坐标位置
//选取它为中心的周围9个点像素(注意一个点为RGB)
int H[9]={0,0,0,0,0,0,0,0,0};
int HWS=3; //维数为三维
//图像增强:平滑 它要获取源图像周围9个点的矩阵乘以模板9个点的矩阵,故一维图像转二维
for(int i=0; im_nImage) break;
ImageSize[i] = m_pImage[i];
ImageSize[i+1] = m_pImage[i+1];
ImageSize[i+2] = m_pImage[i+2];
continue;
}
//对图像进行像素求和并取平均值 HWS维数
int num=0;
for(int j=Y-HWS/2 ; j=0 && k>=0 && k=H[y])
{
temp=H[x];
H[x]=H[y];
H[y]=temp;
}
}
}
//CString str;
//str.Format("矩阵:%d %d %d, %d %d %d, %d %d %d",H[0],H[1],H[2],H[3],H[4],H[5],H[6],H[7],H[8]);
//AfxMessageBox(str);
//对新图像赋值 灰度图像RGB相同
ImageSize[i]=H[4];
ImageSize[i+1]=H[4];
ImageSize[i+2]=H[4];
}
fwrite(ImageSize,m_nImage,1,fpw);
fclose(fpo);
fclose(fpw);
numPicture = 2;
level=400;
Invalidate();
}
运行效果如下图所示:
有时还需要加强图像中景物的边缘和轮廓,边缘和轮廓通常位于图像中灰度突出的地方,因而可以直观的想到用灰度的差分对边缘和轮廓进行提取,通常可以通过梯度算子进行提取。图像锐化的目的是提高图像的对比度,从而使图像更清晰,通过提高邻域内像素的灰度差来提高图像的对比度。
下面介绍图像锐化的几种算子及效果。
1.拉普拉斯算子(Laplacian)
拉普拉斯算子是图像邻域内像素灰度差分计算的基础,通过二阶微分推导出的一种图像邻域增强算法。它的基本思想是当邻域的中心像素灰度低于它所在邻域内的其他像素的平均灰度时,此中心像素的灰度应该被进一步降低;当高于时进一步提高中心像素的灰度,从而实现图像锐化处理。
在算法实现过程中,通过对邻域中心像素的四方向或八方向求梯度,并将梯度和相加来判断中心像素灰度与邻域内其他像素灰度的关系,并用梯度运算的结果对像素灰度进行调整。
一个连续的二元函数f(x,y),其拉普拉斯运算定义为:
/*****************************************/
/* 图像锐化:我在menu中创建5个子的menu */
/* 防止出现平滑错误,一次只调用一个下拉单 */
/* ID_RH_Laplacian Laplacian拉普拉斯算子 */
/* ID_RH_Sobel Sobel算子 */
/* ID_RH_Prewitt Prewitt算子 */
/* ID_RH_Isotropic Isotropic算子 */
/* ID_RH_GTMB 高通模板H2 */
/*****************************************/
void CImageProcessingView::OnRHLaplacian()
{
if(numPicture==0)
{
AfxMessageBox("载入图片后才能图像增强(锐化)!",MB_OK,0);
return;
}
AfxMessageBox("图像增强(锐化):采用拉普拉斯(Laplacian)算子!");
//模板维数:此四个模板均为3维的
int HWS=3;
int H[3][3]={{0,-1,0}, //模板为拉普拉斯算子(中心为4的Laplacian)
{-1,4,-1},
{0,-1,0}};
//读写文件
FILE *fpo = fopen(BmpName,"rb");
FILE *fpw = fopen(BmpNameLin,"wb+");
fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);
fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);
fread(m_pImage,m_nImage,1,fpo);
//new和delete有效的进行动态内存的分配和释放
unsigned char *ImageSize;
ImageSize=new unsigned char[m_nImage];
int red,green,blue;
int X,Y; //一维坐标转换为二维坐标
int TR,TG,TB; //记录红绿蓝坐标位置
//图像增强 锐化
for(int i=0; i=0 && k>=0 && k=0 && red<256) ImageSize[i]=red;
else if(red<0) ImageSize[i]=0; //ImageSize[i]=-red;
else ImageSize[i]=0;
if(green>=0 && green<256) ImageSize[i+1]=green;
else if(green<0) ImageSize[i+1]=0; //ImageSize[i+1]=-green;
else ImageSize[i+1]=0;
if(blue>=0 && blue<256) ImageSize[i+2]=blue;
else if(blue<0) ImageSize[i+2]=0; //ImageSize[i+2]=-blue;
else ImageSize[i+2]=0;
}
fwrite(ImageSize,m_nImage,1,fpw);
fclose(fpo);
fclose(fpw);
numPicture = 2;
level=400;
Invalidate();
}
运行效果如下图所示:
//高通模板
void CImageProcessingView::OnRhGtmb()
{
if(numPicture==0)
{
AfxMessageBox("载入图片后才能图像增强(锐化)!",MB_OK,0);
return;
}
AfxMessageBox("图像增强(锐化):采用高通模板!");
int HWS=3;
int H[3][3]={{-1,-1,-1},
{-1,8,-1},
{-1,-1,-1}};
FILE *fpo = fopen(BmpName,"rb");
FILE *fpw = fopen(BmpNameLin,"wb+");
fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);
fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);
fread(m_pImage,m_nImage,1,fpo);
unsigned char *ImageSize;
ImageSize=new unsigned char[m_nImage];
int red,green,blue;
int X,Y;
int TR,TG,TB;
//图像增强 锐化
for(int i=0; i=0 && k>=0 && k=0 && red<256) ImageSize[i]=red;
else if(red<0) ImageSize[i]=0; //ImageSize[i]=-red;
else ImageSize[i]=0;
if(green>=0 && green<256) ImageSize[i+1]=green;
else if(green<0) ImageSize[i+1]=0; //ImageSize[i+1]=-green;
else ImageSize[i+1]=0;
if(blue>=0 && blue<256) ImageSize[i+2]=blue;
else if(blue<0) ImageSize[i+2]=0; //ImageSize[i+2]=-blue;
else ImageSize[i+2]=0;
}
fwrite(ImageSize,m_nImage,1,fpw);
fclose(fpo);
fclose(fpw);
numPicture = 2;
level=400;
Invalidate();
}
运行效果如下图所示,该效果相对较好:
//Sobel算子采用PPT上的d(x)d(y)模板
void CImageProcessingView::OnRHSobel()
{
if(numPicture==0)
{
AfxMessageBox("载入图片后才能图像增强(锐化)!",MB_OK,0);
return;
}
AfxMessageBox("图像增强(锐化):采用Sobel算子!");
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}};
FILE *fpo = fopen(BmpName,"rb");
FILE *fpw = fopen(BmpNameLin,"wb+");
fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);
fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);
fread(m_pImage,m_nImage,1,fpo);
unsigned char *ImageSize;
ImageSize=new unsigned char[m_nImage];
int redX,greenX,blueX;
int redY,greenY,blueY;
int X,Y;
int TR,TG,TB;
//图像增强 锐化
for(int i=0; i=0 && k>=0 && k255) ImageSize[i]=255;
else ImageSize[i]=R;
if(greenX<0 && greenY<0) ImageSize[i+1]=0;
else if(G>255) ImageSize[i+1]=255;
else ImageSize[i+1]=G;
if(blueX<0 && blueY<0) ImageSize[i+2]=0;
else if(B>255) ImageSize[i+2]=255;
else ImageSize[i+2]=B;
}
fwrite(ImageSize,m_nImage,1,fpw);
fclose(fpo);
fclose(fpw);
numPicture = 2;
level=400;
Invalidate();
}
运行效果如下图所示:
//Isotropic算子采用PPT上的d(x)模板 d(y)
void CImageProcessingView::OnRHIsotropic()
{
if(numPicture==0)
{
AfxMessageBox("载入图片后才能图像增强(锐化)!",MB_OK,0);
return;
}
AfxMessageBox("图像增强(锐化):采用Isotropic算子!");
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} };
FILE *fpo = fopen(BmpName,"rb");
FILE *fpw = fopen(BmpNameLin,"wb+");
fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);
fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);
fread(m_pImage,m_nImage,1,fpo);
unsigned char *ImageSize;
ImageSize=new unsigned char[m_nImage];
float redX,greenX,blueX;
float redY,greenY,blueY;
int X,Y;
int TR,TG,TB;
//图像增强
for(int i=0; i=0 && k>=0 && k255) ImageSize[i]=255;
else ImageSize[i]=R;
if(greenX<0 && greenY<0) ImageSize[i+1]=0;
else if(G>255) ImageSize[i+1]=255;
else ImageSize[i+1]=G;
if(blueX<0 && blueY<0) ImageSize[i+2]=0;
else if(B>255) ImageSize[i+2]=255;
else ImageSize[i+2]=B;
}
fwrite(ImageSize,m_nImage,1,fpw);
fclose(fpo);
fclose(fpw);
numPicture = 2;
level=400;
Invalidate();
}
运行效果如下图所示,效果与上面的Sobel类似:
//Prewitt算子采用PPT上的d(x)模板,不是d(y)
void CImageProcessingView::OnRHPrewitt()
{
if(numPicture==0)
{
AfxMessageBox("载入图片后才能图像增强(锐化)!",MB_OK,0);
return;
}
AfxMessageBox("图像增强(锐化):采用Prewitt算子!");
int HWS=3;
int H[3][3]={{1,0,-1}, //模板为Prewitt算子
{1,0,-1},
{1,0,-1}};
FILE *fpo = fopen(BmpName,"rb");
FILE *fpw = fopen(BmpNameLin,"wb+");
fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);
fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);
fread(m_pImage,m_nImage,1,fpo);
unsigned char *ImageSize;
ImageSize=new unsigned char[m_nImage];
int red,green,blue;
int X,Y;
int TR,TG,TB;
//图像增强:平滑
for(int i=0; i=0 && k>=0 && k=0 && red<256) ImageSize[i]=red;
else if(red<0) ImageSize[i]=0; //ImageSize[i]=-red;
else ImageSize[i]=0;
if(green>=0 && green<256) ImageSize[i+1]=green;
else if(green<0) ImageSize[i+1]=0; //ImageSize[i+1]=-green;
else ImageSize[i+1]=0;
if(blue>=0 && blue<256) ImageSize[i+2]=blue;
else if(blue<0) ImageSize[i+2]=0; //ImageSize[i+2]=-blue;
else ImageSize[i+2]=0;
}
fwrite(ImageSize,m_nImage,1,fpw);
fclose(fpo);
fclose(fpw);
numPicture = 2;
level=400;
Invalidate();
}
运行效果如下图所示,只选取了X分量: