[RESOLVIDO] Filtro como borrar mais a imagem - Java

Olá! Eu preciso de um filtro de passa-baixa. Onde através de uma imagem de entrada eu devo retornar a mesma borrada. De acordo com o que pesquisei em alguns fóruns consegui este código, mas não compreendi muito bem o que o mesmo efetua dentro do laço for. Ele funciona bem com uma imagem de uma flor por exemplo, mas para borrar uma folha de planta tal como eu preciso não surte efeito, gostaria de saber como borrar ainda mais a imagem.

package passabaixa;

import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

public class Principal {

    public static void main(String[] args) throws IOException{
        File arquivo = null;
        JFileChooser chooser = new JFileChooser();  //Cria uma instância do JFileChooser  
        FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG, PNG & GIF Images", "jpg", "gif", "png");  //Cria um filtro  
        chooser.setFileFilter(filter);  //Altera o filtro do JFileChooser  
        int returnVal = chooser.showOpenDialog(null);
        if(returnVal == JFileChooser.APPROVE_OPTION) {  //Verifica se o usuário clicou no botão OK
            arquivo = chooser.getSelectedFile();
        } else {
            JOptionPane.showMessageDialog(null,"Abertura de arquivo cancelada!\n",""
                +"Cancelar", JOptionPane.INFORMATION_MESSAGE);
            return;//corrrige o erro dos gerados a não escolher um arquivo
        }
        
        BufferedImage image = ImageIO.read(arquivo);//Lendo a imagem (arquivo) que foi escolhida pelo usuário
        
        //pega tamanho da imagem
        int H = image.getHeight(null);//pega a altura
        int W = image.getWidth(null);//pega a largura
        
        //pega 
        int nb = image.getSampleModel().getNumBands();//pega as cores da imagem com getSample e com o getNunBands retorna o número total de bandas(divisão de imgs) de dados de imagem.
        int[] pixel = new int[nb];
        Raster inputRaster = image.getData();
        
        //defenir um vetor para correr tudo
        int[] pixels = new int[nb * W * H];
        
        //vai buscar todos pixeis
        inputRaster.getPixels(0, 0, W, H, pixels);
        
        //Criar nova imagem com novas dimensoes!
        BufferedImage ni = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
        
        WritableRaster outputRaster = ni.getRaster();//percorrea a img (ni) pegando o valor de cada pixel,1 raster (caneta)
        //Raster representa uma matriz retangular de pixels
        
        for (int i = 1; i < W-1; i++) {
            for (int j = 1; j < H-1; j++) {
                int piexel1 = image.getRGB(i, j);
                int blue1 = piexel1 & 0xFF;//blue1 recebe o piexel(com os valoes de RGB) que devem ser inteiros de 0 a 255(0xFF)
                int green1 = (piexel1 >> 8) & 0xFF;
                int red1 = (piexel1 >> 16) & 0xFF;
                
                int pixel2 = image.getRGB(i - 1, j - 1);
                int blue2 = pixel2 & 0xFF;
                int green2 = (pixel2 >> 8) & 0xFF;
                int red2 = (pixel2 >> 16) & 0xFF;
                
                int pixel3 = image.getRGB(i - 1, j);
                int blue3 = pixel3 & 0xFF;
                int green3 = (pixel3 >> 8) & 0xFF;
                int red3 = (pixel3 >> 16) & 0xFF;
                //System.out.println(i + " " + j + " " + H + "  " + W);
                
                int pixel4 = image.getRGB(i - 1, j + 1);
                int blue4 = pixel4 & 0xFF;
                int green4 = (pixel4 >> 8) & 0xFF;
                int red4 = (pixel4 >> 16) & 0xFF;
                
                int pixel5 = image.getRGB(i, j - 1);
                int blue5 = pixel5 & 0xFF;
                int green5 = (pixel5 >> 8) & 0xFF;
                int red5 = (pixel5 >> 16) & 0xFF;
                
                int pixel6 = image.getRGB(i, j + 1);
                int blue6 = pixel6 & 0xFF;
                int green6 = (pixel6 >> 8) & 0xFF;
                int red6 = (pixel6 >> 16) & 0xFF;
                
                int pixel7 = image.getRGB(i + 1, j - 1);
                int blue7 = pixel7 & 0xFF;
                int green7 = (pixel7 >> 8) & 0xFF;
                int red7 = (pixel7 >> 16) & 0xFF;
                
                int pixel8 = image.getRGB(i + 1, j);
                int blue8 = pixel8 & 0xFF;
                int green8 = (pixel8 >> 8) & 0xFF;
                int red8 = (pixel8 >> 16) & 0xFF;
                
                int pixel9 = image.getRGB(i + 1, j - 1);
                int blue9 = pixel9 & 0xFF;
                int green9 = (pixel9 >> 8) & 0xFF;
                int red9 = (pixel9 >> 16) & 0xFF;
                
                int bluefinal = (blue1 + blue2 + blue3 + blue4 + blue5 + blue6 + blue7 + blue8 + blue9) / 9;
                int redfinal = (red1 + red2 + red3 + red4 + red5 + red6 + red7 + red8 + red9) / 9;
                int greenfinal = (green1 + green2 + green3 + green4 + green5 + green6 + green7 + green8 + green9) / 9;
                
                int[] color = {redfinal, greenfinal, bluefinal};
                outputRaster.setPixel(i, j, color);
            }
        }
        ni.setData(outputRaster);
        ImageIO.write(ni, "JPEG", new File("image1.jpg"));
    }
    
}

Então… Como posso fazer com que a imagem seja ainda mais borrada? E se alguém entender o conteúdo de dentro do for e puder explicar fico grata! Espero que possam me ajudar!

Esse laço pega as cores do pixel atual e de seus 8 pixels vizinhos;
Em seguida calcula a média dessas cores;
E finalmente altera a cor do pixel atual para essa média calculada.

Como o seu algoritmo é todo monolítico, acredito que o jeito mais fácil para “borrar” mais seja executar esse algoritmo mais de uma vez.

Muito obrigada @staroski
O laço for pega as cores vizinhas, não estava conseguindo visualizar isto.
Com relação a conseguir “borrar” mais imagem, sua dica foi de muita vália também, realmente não pensei em passar mais de uma vez. Testei isto a mão mesmo e possui resultado na minha imagem de uma folha (após passar 20 vezes pelo algoritmo), como isso demanda bastante tempo foi implementado para o algoritmo pegar a quantidade de interações necessárias (pelo usuário) e conseguir borrar a imagem melhor =D

Portanto, RESOLVIDO! Mais uma vez, muito obrigada!

1 curtida

Tomei a liberdade de simplificar sua implementação, tornando-a mais legível, dê uma olhada:

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.filechooser.FileNameExtensionFilter;

public class Embassador {

	public static void main(String[] args) throws IOException {
		try {
			// fazer as telas terem o aspecto nativo do sistema operacional
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Throwable t) {
			t.printStackTrace();
		}
		try {
			Embassador programa = new Embassador();
			programa.executar();
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

	private JFileChooser chooser;

	public void executar() throws IOException {
		File arquivo = abrirArquivo();
		if (arquivo == null) {
			JOptionPane.showMessageDialog(null, "Abertura de arquivo cancelada!", "Atenção", JOptionPane.INFORMATION_MESSAGE);
			return;
		}
		int vezes = perguntar("Quantas vezes deseja executar o algoritmo?");
		if (vezes < 1) {
			JOptionPane.showMessageDialog(null, "Quantidade inválida!", "Atenção", JOptionPane.INFORMATION_MESSAGE);
			return;
		}
		BufferedImage imagem = ImageIO.read(arquivo);
		for (int i = 0; i < vezes; i++) {
			imagem = embassar(imagem);
		}
		arquivo = salvarArquivo();
		ImageIO.write(imagem, "JPEG", arquivo);
	}

	private File abrirArquivo() {
		JFileChooser chooser = getFileChooser();
		int returnVal = chooser.showOpenDialog(null);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			return chooser.getSelectedFile();
		}
		return null;
	}

	// Para entender a posição dos pixels
	//
	//     |x-1| x0|x+1|
	//     +---+---+---+
	// y-1 | 7 | 8 | 9 |
	// ----+---+---+---+
	//  y0 | 6 | 1 | 2 |
	// ----+---+---+---+
	// y+1 | 5 | 4 | 3 |
	//     +---+---+---+
	//     
	private int[] corMedia(BufferedImage original, int x, int y) {
		Color px1 = pixel(original,  x     ,  y    );
		Color px2 = pixel(original,  x + 1 ,  y    );
		Color px3 = pixel(original,  x + 1 ,  y + 1);
		Color px4 = pixel(original,  x     ,  y + 1);
		Color px5 = pixel(original,  x - 1 ,  y + 1);
		Color px6 = pixel(original,  x - 1 ,  y    );
		Color px7 = pixel(original,  x - 1 ,  y - 1);
		Color px8 = pixel(original,  x     ,  y - 1);
		Color px9 = pixel(original,  x + 1 ,  y - 1);

		int mediaR = media(px1.getRed(),   px2.getRed(),   px3.getRed(),   px4.getRed(),   px5.getRed(),   px6.getRed(),   px7.getRed(),   px8.getRed(),   px9.getRed());
		int mediaG = media(px1.getGreen(), px2.getGreen(), px3.getGreen(), px4.getGreen(), px5.getGreen(), px6.getGreen(), px7.getGreen(), px8.getGreen(), px9.getGreen());
		int mediaB = media(px1.getBlue(),  px2.getBlue(),  px3.getBlue(),  px4.getBlue(),  px5.getBlue(),  px6.getBlue(),  px7.getBlue(),  px8.getBlue(),  px9.getBlue());

		return new int[] { mediaR, mediaG, mediaB };
	}

	private BufferedImage embassar(BufferedImage original) {
		int altura = original.getHeight(null);
		int largura = original.getWidth(null);

		BufferedImage nova = new BufferedImage(largura, altura, BufferedImage.TYPE_INT_RGB);
		WritableRaster raster = nova.getRaster();
		for (int x = 1; x < largura - 1; x++) {
			for (int y = 1; y < altura - 1; y++) {
				raster.setPixel(x, y, corMedia(original, x, y));
			}
		}
		nova.setData(raster);
		return nova;
	}

	private JFileChooser getFileChooser() {
		if (chooser == null) {
			chooser = new JFileChooser();
			FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG, PNG & GIF Images", "jpg", "gif", "png");
			chooser.setFileFilter(filter);
		}
		return chooser;
	}

	private int media(int... valores) {
		int quantidade = valores.length;
		int soma = 0;
		for (int i = 0; i < quantidade; i++) {
			soma += valores[i];
		}
		return soma / quantidade;
	}

	private int perguntar(String mensagem) {
		String valor = JOptionPane.showInputDialog(null, mensagem, "Pergunta", JOptionPane.QUESTION_MESSAGE);
		return Integer.parseInt(valor);
	}

	private Color pixel(BufferedImage img, int x, int y) {
		int rgb = img.getRGB(x, y);
		int r = (rgb >> 16) & 0xFF;
		int g = (rgb >> 8) & 0xFF;
		int b = rgb & 0xFF;
		return new Color(r, g, b);
	}

	private File salvarArquivo() {
		JFileChooser chooser = getFileChooser();
		int returnVal = chooser.showSaveDialog(null);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			return chooser.getSelectedFile();
		}
		return null;
	}
}

Perfeito! Mais uma vez, muito obrigada.
Me ajudou bastante =D