高斯模糊滤镜效果

高斯模糊滤镜

高斯模糊是一个对图像处理的方法,原理的话其实非常简单,用一个词来说的话也就是加权平均
用一句话来总结的话:
对于一张图片上的每一个像素点,以这个像素点为中心,用周围的像素点的RGB分量加权平均后的RGB分量替代这个像素点的RGB分量,重新绘出这个像素点,就可以得到高斯模糊效果
其实很好来理解:
跟求平均值是一个道理,假如我们,取得范围为中心像素点临近的8个像素点(类似于九宫格,也可以理解为一个3X3的方阵或者是3行3列的二维数组)
图1
在这里插入图片描述
对于第一张图的3X3矩阵,每一个位置表示一个像素点,然后每一个网格中对应的值为R分量,我们按照等概率求R分量的平均值,得到的平均值给中间位置的像素点,对G分量,B分量也是同样的操作,在得到三个分量的平均值后,画出中心那个像素点,然后对每个像素点都进行同样的操作,就会出现张模糊的图片了,但是我们知道用等概率矩阵的话是不够科学的,因为生活中很多事情的发生都不会是等概率的,事实说明,越靠近中心的像素点权值越高,因此我们可以用到高中正态分布的知识进行处理
在这里插入图片描述
对于图像像素点的处理的话,显然用一元正态分布函数不够合理,需要用到推导出来的二元正态分布函数,并且对于图像的处理,我们只需要用到顶点在(0,0),x与y的方差相同的一个标准正态分布函数:
在这里插入图片描述
函数表达式为:
在这里插入图片描述
然后用这个公式计算在模糊半径(选取的矩阵大小,模糊半径为一就是3X3矩阵,依此类推)内的权值,计算出来周围各个像素点的权值之后,对应像素点的RGB分量乘以对应位置的权值,并且求和(特别注意的是,算出来的权值矩阵需要处理,因为这些权值的总和不为1,所以要让他们的总和为1)
在这里插入图片描述
算出来的权值如下图
在这里插入图片描述
加权平均后得到的RGB分量平均值给中心像素点,绘出中心像素点,并且对每个像素点执行同样的操作(如果像素点在边缘的话,超出图像像素点范围的RGB值就是0)绘出图像,效果如图所示
在这里插入图片描述
在这里插入图片描述
代码:

	//获取绝对文件名的对应的jpg文件上面的像素点数组用此方法
	public  void getImagePixel(String image) { 
		 
		try {
			//1、获取filename文件路径上的jpg图像文件
			Image=ImageIO.read(new File(image));
			//2、给newImage赋值,使他的长度,宽度,和图像文件类型与Image的属性一样
			newImage=new BufferedImage(Image.getWidth(), Image.getHeight(), Image.getType());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	 }

说明:在代码块中Image,newImage都是之前定义的BufferImage对象

//获取newImage上面得画布对象
	    		 Graphics2D newgraphics=(Graphics2D)newImage.getGraphics();	    			    		 	    		 
	    		 //然后遍历Image上的像素点,获取每个像素点周围的RGB值,RGB值的话,我们将其放在三个二维数组中
	    		 for(int i=0;i<Image.getWidth();i++) {
	    			 for(int j=0;j<Image.getHeight();j++) {
	    				 //首先定义三个二维矩阵存储RGB值,权重矩阵,总权值变量
	    				 //并且我的想法是使二维数组矩阵的大小与模糊半径有关
	    				 double[][]  weight_matrix=new double[2*matrix_R+1][2*matrix_R+1];
	    	    		 double ALL_weight_data=0;//首先总权值ALL_weight_data=0
	    				 int[][] color_R=new int[2*matrix_R+1][2*matrix_R+1];
	    				 int[][] color_G=new int[2*matrix_R+1][2*matrix_R+1];
	    				 int[][] color_B=new int[2*matrix_R+1][2*matrix_R+1];
	    				 for(int row=0;row<weight_matrix.length;row++) {
	    					 for(int lie=0;lie<weight_matrix[row].length;lie++) {
	    						 //首先判断获取RGB值得坐标是否超出了Image的weight和height,如果没有超出的话
	    						 //将RGB三个值分别传入三个二维矩阵对应的位置上,并且计算该位置的高斯权值
	    						 if(i-matrix_R+row>=0&&j-matrix_R+lie>=0&&i-matrix_R+row<Image.getWidth()&&j-matrix_R+lie<Image.getHeight()) {
	    							 color_R[row][lie]=getcolor_data(Image, i-matrix_R+row,j-matrix_R+lie )[0];
		    						 color_G[row][lie]=getcolor_data(Image, i-matrix_R+row,j-matrix_R+lie )[1];
		    						 color_B[row][lie]=getcolor_data(Image, i-matrix_R+row,j-matrix_R+lie )[2];
		    						 weight_matrix[row][lie]=Gauss_formula(1.50, (double)(row-matrix_R), (double)(lie-matrix_R));
	    						 }
	    						 else {
	    							 weight_matrix[row][lie]=0;
	    							 color_R[row][lie]=0;
	    							 color_G[row][lie]=0;
	    							 color_B[row][lie]=0;
	    						 }
	    						 
	    					 }
	    				 }
	    				 //用两个双重for循环来重新分配权值
	    				 for(int row=0;row<weight_matrix.length;row++) {
	    	    			 for(int lie=0;lie<weight_matrix[row].length;lie++) {
	    	    				 ALL_weight_data+=Gauss_formula(1.50, (double)(row-matrix_R), (double)(lie-matrix_R));	    				 
	    	    			 }	    			 
	    	    		 }	    	    		 
	    	    		 for(int row=0;row<weight_matrix.length;row++) {
	    	    			 for(int lie=0;lie<weight_matrix[row].length;lie++) {
	    	    				weight_matrix[row][lie]=Gauss_formula(1.50, (double)(row-matrix_R), (double)(lie-matrix_R))/ ALL_weight_data;	    				 
	    	    			 }	    			 
	    	    		 }
	    				 //定义一个三个平均值变量
	    	    		 int aver_R=0,aver_G=0,aver_B=0;
	    	    		 //再次用一个双重for循环计算RGB值得加权平均
	    	    		 for(int row=0;row<weight_matrix.length;row++) {
	    	    			 for(int lie=0;lie<weight_matrix[row].length;lie++) {
	    	    				 aver_R+=(int)(color_R[row][lie]*weight_matrix[row][lie]);
	    	    				 aver_G+=(int)(color_G[row][lie]*weight_matrix[row][lie]);
	    	    				 aver_B+=(int)(color_B[row][lie]*weight_matrix[row][lie]);
	    	    			 }
	    	    		 }
	    	    		 //setColor 
	    	    		 Color color=new Color(aver_R,aver_G,aver_B);
	    	    		 newgraphics.setColor(color);
	    	    		 newgraphics.drawLine(i, j, i, j);
	    	    		 k.setColor(color);
	    	    		 k.drawLine(i, j, i, j);
	    			 }
	    		 }	    		    			    		
  public double Gauss_formula(double cgm,double x,double y ) {
	    	 double Gauss_price;
	    	 Gauss_price=(1/(2*Math.PI*Math.pow(cgm, 2)))*Math.exp(-(Math.pow(x, 2)+Math.pow(y, 2))/(2*Math.pow(cgm, 2)));
	    	 return Gauss_price;
	     }
//这个方法的用处是用于获取Image对象的RGB参数值并且获得他的r,g,b分量
		public  int[] getcolor_data(BufferedImage Image,int i,int j) {
			int getcolor=Image.getRGB(i, j);
			int[] rgb_group_data=new int[3];
			Color c=new Color(getcolor);
			rgb_group_data[0]=c.getRed();
			rgb_group_data[1]=c.getGreen();
			rgb_group_data[2]=c.getBlue();
			return rgb_group_data;
		}

猜你喜欢

转载自blog.csdn.net/qq_48201696/article/details/107502161