Java 实现高斯模糊算法

JAVA herman 1006浏览 0评论
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领

接上篇文章《高斯模糊算法的原理》,本文我们借助 java 来实现高斯模糊算法,并使用高斯模糊算法处理实际图片。

高斯模糊就是图像和高斯函数的卷积。等价于傅里叶变换后乘上高斯函数再逆变换回来(高斯函数的傅里叶变换也是高斯函数),没错就是低通滤波。实现方式可以按照卷积公式算,复杂度O(n²m²)。考虑到二维高斯函数G(x,y)可以写成两个一维高斯函数G(x)和G(y)的乘积,也就是G(x)δ(y)和G(y)δ(x)的卷积,也就是可以x和y两个方向分别做高斯模糊。O(n²m)卷积核很大的时候也可以用FFT->相乘->IFFT的方式实现,复杂度O((m+n)²log(m+n)),不过高斯模糊的m也就是几个像素,就不要考虑这个了。

下面我们使用 java 来实现一个高斯模糊案例。

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;   
  
public class Test
{
    static float [][]aa;//计算高斯后的权重矩阵
    final static int shu = 1;//高斯模糊半径
    final static int  size = 2*shu+1;//数组大小    
 
 
 /**
     * 简单高斯模糊算法
     * 
     * @param args
     * @throws IOException [参数说明]
     * 
     * @return void [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static void main(String[] args) throws IOException
    {    
        aa = GaosiUtil.get2(GaosiUtil.get2DKernalData(shu,1.5f));//计算高斯权重
        BufferedImage img = ImageIO.read(new File("d:\\1.jpg"));
        System.out.println("图片加载成功"+img);
        int height = img.getHeight();
        int width = img.getWidth();   
   
       
        int[][] matrix = new int[size][size];//基础矩阵
        int[] values = new int[size*size];
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                readPixel(img, i, j, values);//获取周边点的值
                fillMatrix(matrix, values);//将周边点个点的值存到缓存矩阵中               
                img.setRGB(i, j, avgMatrix(matrix));
            }
        }
        ImageIO.write(img, "jpeg", new File("d:/test1.jpg"));//保存在d盘为test1.jpeg文件
    }
      
 
    private static void readPixel(BufferedImage img, int x, int y, int[] pixels)
    {//读取像素
        int xStart = x - shu;
        int yStart = y - shu;
        int current = 0;
        for (int i = xStart; i < size + xStart; i++)
        {
            for (int j = yStart; j < size + yStart; j++)
            {
                int tx = i;
                if (tx < 0)//处理边界情况左溢出
                {
                    tx = -tx;
                }
                else if (tx >= img.getWidth())//处理边界情况右溢出
                {
                    tx = x;
                }
                  
                int ty = j;
                if (ty < 0)
                {
                    ty = -ty;
                }
                else if (ty >= img.getHeight())
                {
                    ty = y;
                }
                pixels[current++] = img.getRGB(tx, ty);//获取
                
            }
        }
    }
      
    private static void fillMatrix(int[][] matrix, int... values)
    {
        int filled = 0;
        for (int i = 0; i < matrix.length; i++)
        {       
            for (int j = 0; j <size; j++)
            {            
                matrix[i][j] = values[filled++];
            }
        }
    }
      
    private static int avgMatrix(int[][] matrix)
    {    
        int r = 0;
        int g = 0;
        int b = 0;
        for (int i = 0; i < matrix.length; i++)
        {
          
            for (int j = 0; j <matrix.length; j++)
            {
    
                Color c = new Color(matrix[i][j]);            
                r += c.getRed()*aa[i][j];              
                g += c.getGreen()*aa[i][j];
                b += c.getBlue()*aa[i][j];
            }
           
        }
        
        return new Color(r, g, b).getRGB();
    }
}
 
public class GaosiUtil {
    //二维高斯算法具体实现
    static float sum=0;
    public static float[][] get2DKernalData(int n, float sigma) {  
       int size = 2*n +1;  
       float sigma22 = 2*sigma*sigma;  
       float sigma22PI = (float)Math.PI * sigma22;  
       float[][] kernalData = new float[size][size];  
        
       
       int row = 0;  
       for(int i=-n; i<=n; i++) {  
           int column = 0;  
           for(int j=-n; j<=n; j++) {  
               float xDistance = i*i;  
               float yDistance = j*j;  
               kernalData[row][column] = (float)Math.exp(-(xDistance + yDistance)/sigma22)/sigma22PI;  
               column++;  
           }  
           row++;  
       }  
       System.out.println("二维高斯结果"); 
       for(int i=0; i<size; i++) {  
           for(int j=0; j<size; j++) {  
               sum +=kernalData[i][j];
               System.out.print("\t" + kernalData[i][j]);  
           }  
           System.out.println();  
           System.out.println("\t ---------------------------");  
       }  
       return kernalData;  
    }  
     
    public static float[][] get2(float[][] kernalData) { 
        System.out.println("均值后"); 
        for(int i=0; i<kernalData.length; i++) {  
           for(int j=0; j<kernalData.length; j++) {  
               kernalData[i][j] = kernalData[i][j]/sum;
               System.out.print("\t" + kernalData[i][j]);  
           }  
           System.out.println();  
           System.out.println("\t ---------------------------");  
       }  
       return kernalData;  
      
    }    
}

最后看看处理后的图片效果:

高斯模糊

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847(已满),QQ3群:187424846(已满)。QQ群进群密码:xttblog,想加微信群的朋友,之前的微信号好友已满,请加博主新的微信号:xttblog,备注:“xttblog”,添加博主微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » Java 实现高斯模糊算法