【数字图像处理】七.MFC图像增强之图像普通平滑、高斯平滑、Laplacian、Sobel、Prewitt锐化详解

  • 时间:
  • 浏览:4
  • 来源:5分3D_5分排列5

       2.普通平滑 模板二

        该算法采用的模板如下:



        代码如下:

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<m_nImage; )
	{
		//原图一维矩阵转换为二维矩阵
		X=(i/3)%m_nWidth;    //图像在X列
		Y=(i/3)/m_nWidth;    //图像在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<m_nWidth && j<m_nHeight )      //解决越界
				{			
					//模板二 进行模板平均,把该点像素分散到四周
					TR=j*m_nWidth*3+k*3;	
					red+=H2[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TR]);
					TG=j*m_nWidth*3+k*3+1;
					green+=H2[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TG]);
					TB=j*m_nWidth*3+k*3+2;
					blue+=H2[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TB]);
				}
			}
		}
		//对新图像赋值
		//通过变量place赋值变换后的图像 i始终指向原图3的倍数 为了补0而加上place变量
		ImageSize[place]=(unsigned char)(red);
		i++; place++;
		ImageSize[place]=(unsigned char)(green);
		i++; place++;
		ImageSize[place]=(unsigned char)(blue);
		i++; place++;
		countWidth=countWidth+3;
		
		if(countWidth==m_nWidth*3)    
        {    
			if(num==0)  
            {  
                countWidth=0;    
                place=Y*m_nWidth*3;
            }  
            else //num为补0  
            {  
                for(int n=0;n<num;n++)  
                {    
                    ImageSize[place]=0;  
					place++;  
                }  
                countWidth=0;   
                place=Y*(m_nWidth*3+num); //重点 加上Num  
            }  
		} 
	}
		
	fwrite(ImageSize,sfSize,1,fpw);  
	fclose(fpo);
	fclose(fpw);
	numPicture=2;
	level=1000;
	Invalidate();
}
        你不可能 注意到了,在图像解决过程中,不可能 每行的字节数就让4的倍数,不可能 会再次跳出斜线例如的解决BUG,就让我时需手动补0筹齐4的倍数,代码中补0后运行效果如下图所示,我也老会 没找到原应 ,不可能 是思想和淬硬层 还可不可以了达到,完后 有不可能 在解决吧!共同后边的算法就让准备再进行补0解决,主要讲述算法的思想!

         3.高斯平滑

         采用的模板如下:



        代码如下图所示:

//高斯平滑
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<m_nImage ; i=i+3 )
	{
		//原图:一维矩阵转换为二维矩阵
		X=(i/3)%m_nWidth;    //图像在X列
		Y=(i/3)/m_nWidth;    //图像在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<m_nWidth && j<m_nHeight )      //解决越界
				{			
					//模板二 进行模板平均,把该点像素分散到四周
					TR=j*m_nWidth*3+k*3;	
					red+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TR]);
					TG=j*m_nWidth*3+k*3+1;
					green+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TG]);
					TB=j*m_nWidth*3+k*3+2;
					blue+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TB]);
				}
			}
		}
		//对新图像赋值
		ImageSize[i]=(unsigned char)(red);
		ImageSize[i+1]=(unsigned char)(green);
		ImageSize[i+2]=(unsigned char)(blue);
	}
		
	fwrite(ImageSize,m_nImage,1,fpw);  
	fclose(fpo);
	fclose(fpw);
	numPicture = 2;
	level=1000;
	Invalidate();
}
        运行效果如下图所示:

        4.中值滤波

        中值滤波我的理解是:它不但都时需去除孤点噪声,就让都时需保持图像的边缘社会形态,不需要产生显著的模糊;它的最好的方法是把局部区域的像素按灰度等级进行排序,再取该邻域中灰度的中值作为当前像素的灰度值。其步骤如下:

        (1).将滤波模板(含若干个点的滑动窗口)在图像中漫游,并将模板中心与图像中的某个像素位置重合;

        (2).读取模板中各对应像素的灰度值;

        (3).将什么灰度值从小到大排序;

        (4).取這個 列数据的后边数据,将其赋值给对应模板中心位置的像素。


        我采用的是3*3的模本,取矩阵后边位置像素替代原像素。代码如下:

//中值滤波
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; i<m_nImage ; i=i+3 )
	{
		//原图:一维矩阵转换为二维矩阵
		X=(i/3)%m_nWidth;    //图像在X列
		Y=(i/3)/m_nWidth;    //图像在Y行
		
		//第一行 第一列 最后一行 最后一列 直接克隆qq
		if(X==0 || Y==0 || X==m_nWidth*3 || Y==m_nHeight) 
		{
			if(i+2>m_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<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<m_nWidth && j<m_nHeight )      //解决越界
				{			
					//获取当前位置Red像素 k一次增加RGB一还还有一个



像素 R=G=B
					TR = j*m_nWidth*3+k*3;	
					H[num] = m_pImage[TR];
					num++;
				}
			}
		}
		//排序获取后边值
		int temp=0;
		for(int x=0;x<9;x++)
		{
			for(int y=x;y<9;y++)
			{
				if(H[x]>=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=1000;
	Invalidate();
}
        运行效果如下图所示:



        PS:这次责总算讲述完成,算法就让根据本人的理解用底层代码实现的,而就让向其它的通过调用GDI+库实现。不可能 趋于稳定不可能 理解匮乏或其它的错误,欢迎提出修改~

        推荐资料:

        图像平滑解决——OpenCV

二. 图像平滑

        图像平滑是三种生活区域增强的算法,平滑算法有邻域平均法、中指滤波、边界保持类滤波等。在图像产生、传输和克隆qq过程中,常常会不可能 多方面原应 而被噪声干扰或再次跳出数据丢失,降低了图像的质量(某一像素,不可能 它与符近像素点相比有明显的不同,则该点被噪声所感染)。这就时需对图像进行一定的增强解决以减小什么匮乏带来的影响。

        3.中值滤波

        在使用邻域平均法去噪的共同也使得边界变得模糊。而中值滤波是非线性的图像解决最好的方法,在去噪的共同都时需兼顾到边界信息的保留。

        选一还还有一个 中有 奇数点的窗口W,将這個 窗口在图像上扫描,把窗口中中有 的像素点按灰度级的升或降序排列,取趋于稳定后边的灰度值来代替该点的灰度值。



        例如选择滤波的窗口如下图,是一还还有一个 一维的窗口,待解决像素的灰度取這個 模板中灰度的中值,滤波过程如下:



        常用的窗口还有方形、十字形、圆形和环形。不同社会形态的窗口产生不同的滤波效果,方形和圆形窗口适合外轮廓线较长的物体图像,而十字形窗口对有尖顶角状的图像效果好。

        中值滤波对于消除孤立点和线段的干扰十分有用,尤其是对于二进噪声,但对消除高斯噪声的影响效果不佳。对于或多或少细节较多的多样化图像,都时需多次使用不同的中值滤波。matlab实现参考:http://blog.csdn.net/timidsmile/article/details/6904381

        4.边界保持类滤波

       1.简单平滑-邻域平均法

        图像简单平滑是指通过邻域简单平均对图像进行平滑解决的最好的方法,用這個 最好的方法在一定程度上消除原始图像中的噪声、降低原始图像对比度的作用。它利用卷积运算对图像邻域的像素灰度进行平均,从而达到减小图像中噪声影响、降低图像对比度的目的。

        但邻域平均值主要缺点是在降低噪声的共同使图像变得模糊,很重在边缘和细节处,就让邻域越大,在去噪能力增强的共同模糊程度越严重。

        图像增强是对图像进行解决,使其比原始图像更适合于特定的应用,它时需与实际应用相结合。对于图像的或多或少社会形态如边缘、轮廓、对比度等,图像增强是进行强调或锐化,以便于显示、观察或进一步分析与解决。图像增强的最好的方法是因应用不同而不同的,研究内容包括:(参考课件和左飞的《数字图像解决》)

        也都时需表示为卷积的形式:

        其中K=1,I=1时H(r,s)取下式,四方向模板:

       3.Sobel算子



        代码如下所示,时需注意X和Y一还还有一个 方向的模板解决:

//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<m_nImage ; i=i+3 )
	{
		X=(i/3)%m_nWidth;    //X列
		Y=(i/3)/m_nWidth;    //Y行
		redX=greenX=blueX=0;
		redY=greenY=blueY=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<m_nWidth && j<m_nHeight )
				{			
					
					TR=j*m_nWidth*3+k*3;	
					redX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TR]);
					redY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TR]);
					TG=j*m_nWidth*3+k*3+1;
					greenX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TG]);
					greenY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TG]);
					TB=j*m_nWidth*3+k*3+2;
					blueX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TB]);
					blueY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TB]);
				}
			}
		}
		//s=(d(x)*d(x)+d(y)*d(y))开根号
		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) ImageSize[i]=0;
		else if(R>255) 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=1000;	
	Invalidate();
}
        运行效果如下图所示:

        不可能 采用Sobel边缘细化,建议二值化(0和255阈值化)解决后再锐化,彩色图建议先灰度解决再进行或多或少解决。

      4.Isotropic算子



        代码实现如下:

//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<m_nImage ; i=i+3 )
	{
		X=(i/3)%m_nWidth;    //X列
		Y=(i/3)/m_nWidth;    //Y行
		redX=greenX=blueX=0;
		redY=greenY=blueY=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<m_nWidth && j<m_nHeight )
				{			
					
					TR=j*m_nWidth*3+k*3;	
					redX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TR]);
					redY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TR]);
					TG=j*m_nWidth*3+k*3+1;
					greenX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TG]);
					greenY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TG]);
					TB=j*m_nWidth*3+k*3+2;
					blueX+=HX[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TB]);
					blueY+=HY[(j-Y+HWS/2)][(k-X+HWS/2)]*(float)(m_pImage[TB]);
				}
			}
		}
		//对新图像赋值 s=(d(x)*d(x)+d(y)*d(y))开根号
		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) ImageSize[i]=0;
		else if(R>255) 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=1000;	
	Invalidate();
}
        运行效果如下图所示,效果与后边的Sobel例如:

       5.Prewitt算子

        代码如下图所示:

//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<m_nImage ; i=i+3 )
	{
		X=(i/3)%m_nWidth;    //X列
		Y=(i/3)/m_nWidth;    //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<m_nWidth && j<m_nHeight )
				{			
					
					TR=j*m_nWidth*3+k*3;	
					red+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TR]);
					TG=j*m_nWidth*3+k*3+1;
					green+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TG]);
					TB=j*m_nWidth*3+k*3+2;
					blue+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TB]);
				}
			}
		}
		//对新图像赋值
		if(red>=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=1000;	
	Invalidate();
}
        运行效果如下图所示,只选择了X分量:

        最后还是希望文章对你有所帮助,不可能 文章有匮乏或错误之处,请海涵。本人给本人点个赞,挺不容易的,但就让继续写完~共同后边的图像解决准备研究些感兴趣的东西,而就让原来的长篇大论了,例如何如实现验证码提取、何如实现图像恢复、DICOM图像等知识吧!

       有时还时需加强图像中景物的边缘和轮廓,边缘和轮廓通常趋于稳定图像中灰度突出的地方,因而都时需直观的想到用灰度的差分对边缘和轮廓进行提取,通常都时需通过梯度算子进行提取。图像锐化的目的是提高图像的对比度,从而使图像更清晰,通过提高邻域内像素的灰度差来提高图像的对比度。

       下面介绍图像锐化的几种算子及效果。        1.拉普拉斯算子(Laplacian)

        拉普拉斯算子是图像邻域内像素灰度差分计算的基础,通过二阶微分推导出的三种生活图像邻域增强算法。它的基本思想是当邻域的中心像素灰度低于它所在邻域内的或多或少像素的平均灰度时,此中心像素的灰度应该被进一步降低;当高于时进一步提高中心像素的灰度,从而实现图像锐化解决。

        对于数字图像,拉普拉斯算子都时需多样化为:

        在K近旁均值滤波器(KNNMF)中,不选K个邻近像素的平均灰度来替代,而选K个邻近像素的中值灰度来替代,上图中2,3,3中选择3即可。

        下面介绍具体MFC VC++6.0代码实现过程。

        2.高斯平滑

       
为了克服简单局部平均法的弊端(图像模糊),目前已提出或多或少保持边缘、细节的局部平滑算法。它们的出发点都集中在何如选择邻域的大小、社会形态和方向、参数加平均及邻域各店的权重系数等。

        图像高斯平滑也是邻域平均的思想对图像进行平滑的三种生活最好的方法,在图像高斯平滑中,对图像进行平均时,不同位置的像素被赋予了不同的权重。         在图像简单平滑中,算法利用卷积模板逐一解决图像中每个像素,這個 过程都时需形象地比作对原始图像的像素一一进行过滤埋点,在图像解决中把邻域像素逐一解决的算法过程称为滤波器。平滑线性滤波器的工作原理是利用模板对邻域内像素灰度进行加权平均,也称为均值滤波器。

        其中实现过程步骤如下:        加上子菜单和类向导加上实现函数



        代码如下:

/*****************************************/
/* 图像锐化:我在menu中创建一还还有一个子的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<m_nImage ; i=i+3 )
	{
		X=(i/3)%m_nWidth;    //X列
		Y=(i/3)/m_nWidth;    //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<m_nWidth && j<m_nHeight )
				{			
					
					TR=j*m_nWidth*3+k*3;	
					red+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TR]);
					TG=j*m_nWidth*3+k*3+1;
					green+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TG]);
					TB=j*m_nWidth*3+k*3+2;
					blue+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TB]);
				}
			}
		}
		//对新图像赋值
		if(red>=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=1000;	
	Invalidate();
}
        运行效果如下图所示:

        2.高通滤波

        常用的高通模板如下所示,其中H2有的书又称为拉普拉斯八方向的锐化模板。



        选择H2模板,代码如下所示:

//高通模板
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<m_nImage ; i=i+3 )
	{
		X=(i/3)%m_nWidth;    //X列
		Y=(i/3)/m_nWidth;    //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<m_nWidth && j<m_nHeight )
				{			
					
					TR=j*m_nWidth*3+k*3;	
					red+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TR]);
					TG=j*m_nWidth*3+k*3+1;
					green+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TG]);
					TB=j*m_nWidth*3+k*3+2;
					blue+=H[(j-Y+HWS/2)][(k-X+HWS/2)]*(m_pImage[TB]);
				}
			}
		}
		
		//对新图像赋值
		if(red>=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=1000;	
	Invalidate();	
}
        运行效果如下图所示,该效果相对较好:

        其中实现的具体原理如下:

        首先将图像像素矩阵转换为(X,Y)的二维矩阵进行操作,共同获取(X,Y)坐标为中心的3*3矩阵,再通过它与3*3模板进行像素平均操作,就让我我一还还有一个 3*3矩阵互乘。时需注意的是矩阵一还还有一个 格子是RGB三字节(24位BMP),共同获取该中心点位置时,通过两层循环for(k=n-1;k<=n+1;k++)实现获取矩阵中九个点的像素。最后对该点(X,Y)的RGB进行赋值操作即可。