Search code examples
javaswingconvolution

How to use Convolution Kernel to Blur Image


So, the first thing I found when I was researching was this. I mimicked the code from that website (as you can see below), and when I tried it, the image was blurred so slightly it wasn't visible. Further research on the internet did not tell me anything I didn't already know. I am using ConvolveOp and Kernels in my Java code. I am assuming that the reason it didn't blur the image as much as I wanted it to has something to do with the Kernel's matrix, but I don't know what values it requires in order to blur the image. What I'm looking for is the pattern in the values of the array, and the size of the array that will make it blurred on a sliding scale number, as well as keeping it fast.


Solution

  • It takes a larger array to produce more blur, and I figured out how to blur everything more using a dynamically calculated array with the code below and a sliding value array size. You might find this website useful as well with the different types of convolutions.

    
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.awt.image.ConvolveOp;
    import java.awt.image.Kernel;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    
    public class ConvolveOpTest extends JFrame{
        JScrollPane scrollPane;
        BufferedImage image;
        
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable(){
                @Override
                public void run(){
                    new ConvolveOpTest();
                }
            });
        }
        
        public ConvolveOpTest(){
            try{
                long timePrev = System.currentTimeMillis();
                image = ImageIO.read(new File("a.jpg"));
                int arrSize = 50;
                float matrix[][] = new float[arrSize][arrSize];
                for(int x = 0 ; x < matrix.length ; x++){
                    for(int y = 0 ; y < matrix[0].length ; y++){
                        matrix[x][y] = 1f / matrix.length / matrix[0].length;
                    }
                }
                
                ArrayList<Float> list = new ArrayList<>();
                for (int i = 0; i < matrix.length; i++) {
                    for (int j = 0; j < matrix[i].length; j++) { 
                        list.add(matrix[i][j]); 
                    }
                }
    
                float[] vector = new float[list.size()];
                for (int i = 0 ; i < vector.length; i++) {
                    vector[i] = list.get(i);
                }
                
                ConvolveOp op = new ConvolveOp(new Kernel(matrix.length, matrix[0].length, vector));
                BufferedImage output = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
                image = op.filter(image, output);
                System.out.println(System.currentTimeMillis() - timePrev);
            }catch(IOException e){
                e.printStackTrace();
            }
            
            JPanel panel = new JPanel(){
                @Override
                public void paintComponent(Graphics g){
                    super.paintComponent(g);
                    Graphics2D g2 = (Graphics2D)g;
                    g2.scale(0.5, 0.5);
                    g2.drawImage(image, 0, 0, null);
                }
                
                @Override
                public Dimension getPreferredSize(){
                    return new Dimension((int)(image.getWidth() * 0.5), (int)(image.getHeight() * 0.5));
                }
                
            };
            
            scrollPane = new JScrollPane(panel);
            
            setSize(new Dimension(1200,700));
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            add(scrollPane);
            setVisible(true);
        }
        
        @Override
        public Dimension getPreferredSize(){
            return new Dimension(1200, 700);
        }
        
    }