Comparar pixels a partir de um ponto

7 respostas
tartaruga.df

Pessoal,

Preciso criar um sistema que busque uma imagem do meu computador e o coloque na tela(já está pronto). Quando eu clicar com o mouse em um ponto da imagem o sistema deve capturar o ponto clicado(também está pronto).

Agora vem o problema, o sistema deve fazer uma comparação dos pontos que estão em em volta do clicado e verificar se são iguais ou se estão dentro de uma faixa estabelecida, marcar os que estão nesta faixa e parar de procurar quando o pixel vizinho não for igual ou não estiver no limiar estabelecido. A busca deve ser feita a partir do campo clicado e apenas em volta dele. Por fim, o sistema deve gerar uma nova imagem mostrando os pixels que foram marcados.

Também tem um erro na imagem que, sempre que clico na borda inferior ou direita mais externa da imagem da um erro, ou seja, se a imagem tem 225 por 225, so funciona quando clico em 224 mas quando clico em 225 da erro, mas a implementação do algoritimo é mais importante e isso ainda quero pesquisar mais.

Caso alguem puder me ajudar agradeço

segue o código que já fiz

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

public class TrabalhaImagem extends JFrame {

	private JPanel painelNorte = new JPanel();

	private JPanel Central = new JPanel();
	private JPanel painelImagem = new JPanel();
	private Container container;
	private FlowLayout layout;
	private JButton botaoCarregar;
	private JButton botaoMatriz;
	private JButton botaoIniciar;

	private BufferedImage imagemOriginal = null;
	private BufferedImage imagemResultado = null;

	private int larguraImagem;
	private int alturaImagem;
	private int imagem[][];
	private int limiar;
	private int pixelLinha;

	private final int BORDER = 10;

	public int getPixelLinha() {
		return pixelLinha;
	}

	public TrabalhaImagem() throws IOException {

		super("Inicio");
		container = getContentPane();
		setLayout(layout);

		botaoCarregar = new JButton("Buscar Imagem Local");
		painelImagem = new JPanel();
		botaoMatriz = new JButton("Gerar Matriz");

		botaoIniciar = new JButton("Iniciar Varredura");

		painelNorte.setLayout(new GridLayout(2, 5));
		painelNorte.setBackground(Color.white);
		painelNorte.add(botaoCarregar);
		painelNorte.add(botaoMatriz);
		painelNorte.add(botaoIniciar);

		Central.add(painelImagem);
		Central.setBackground(Color.gray);

		this.setLayout(new BorderLayout());
		this.add("North", painelNorte);
		this.add("Center", Central);

		botaoCarregar.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				BufferedImage image = null;
				JFileChooser arquivo = new JFileChooser();
				arquivo.setDialogTitle("Escolha uma imagem");

				arquivo.setFileFilter(new javax.swing.filechooser.FileFilter() {

					public boolean accept(File f) {
						return f.getName().toLowerCase().endsWith(".jpg")
								|| f.isDirectory()
								|| f.getName().toLowerCase().endsWith(".png")
								|| f.getName().toLowerCase().endsWith(".gif")
								|| f.getName().toLowerCase().endsWith(".jpeg");
					}

					public String getDescription() {
						return "Arquivos de imagem (.jpg, .png, .gif, .jpeg)";

					}
				});
				int res = arquivo.showOpenDialog(null);

				if (res == JFileChooser.APPROVE_OPTION) {

					File arquivos = arquivo.getSelectedFile();
					{
						try {
							image = ImageIO.read(arquivos);
							imagemOriginal = image;
						} catch (IOException ex) {
							JOptionPane.showMessageDialog(null,
									"Erro ao processar imagem.");
						}
					}

					ImageIcon im = new ImageIcon(image);

					JLabel label1 = new JLabel();
					label1.setPreferredSize(new Dimension(image.getWidth()
							+ BORDER, image.getHeight() + BORDER));

					label1.setVerticalAlignment(SwingConstants.CENTER);
					label1.setHorizontalAlignment(SwingConstants.CENTER);
					label1.setIcon(im);
					painelImagem.setBorder(BorderFactory.createEmptyBorder());
					painelImagem.setPreferredSize(new Dimension(image
							.getWidth() + 2 * BORDER, image.getHeight() + 2
							* BORDER));
					painelImagem.add(label1, null);
					painelImagem.setVisible(true);

				} else
					JOptionPane.showMessageDialog(null,
							"Voce nao selecionou nenhum arquivo.");
			}
		});

		// captura a posição da tela
		painelImagem.addMouseListener(new MouseListener() {
			public void mousePressed(MouseEvent e) {

				int c = imagemOriginal.getRGB(e.getX(), e.getY());

				int red = (c & 0x00ff0000) >> 16;
				int green = (c & 0x0000ff00) >> 8;
				int blue = c & 0x000000ff;

				System.out.println("Cores: Vermelho = " + red + ", Verde = "
						+ green + ", Azul = " + blue);
				System.out.println("RGB da imagem: " + c);
				System.out.println("Posição marcada: " + red + " " + e.getX()
						+ " / " + e.getY());
				System.out.println("Largura da imagem: "
						+ imagemOriginal.getWidth());
				System.out.println("Altura da imagem: "
						+ imagemOriginal.getHeight());

			}

			public void mouseClicked(MouseEvent e) {
			}

			public void mouseEntered(MouseEvent e) {
			}

			public void mouseExited(MouseEvent e) {
			}

			public void mouseReleased(MouseEvent e) {
			}
		});

		// Iniciar comparação de pixels
		botaoIniciar.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

			}
		});
	}
}

7 Respostas

E

Dê uma pesquisada sobre algorítimo flood fill, deve resolver seu caso.

ViniGodoy

Sobre o erro de clicar nas bordas, já expliquei no outro tópico. O mesmo que expliquei como simplificar os operadores de bits usados de forma desnecessária nas linhas 143-145.

Quanto aos seus outros problemas. Bem.
Você deve começar definindo o que são dois pixels “parecidos”, pois esse conceito é extremamente subjetivo, especialmente se você estiver lidando com cores. Sem esse conceito, será impossível traçar o que é um limiar.

Para selecionar os pixels iterativamente, procure por algoritmos chamados de “algoritmos de floodfill”, citados pelo Elisson. Eles é que vão te ajudar nesse caso.

tartaruga.df

Bem,

Inicialmente obrigado pela dica. A intenção neste momento é trabalhar apenas com imagens em escala de cinza e desta forma, como nas imagens em escala de cinza o R, o G e o B são iguais eu posso trabalhar apenas com um dos parâmetros.

Neste caso, a minha intenção é definir uma escala de tolerância por meio de um parâmetro que chamei de limiar. Se o limiar for 10, qualquer pixel em que a cor (o R, o G ou o B) variar entre 10 acima ou 10 abaixo serão considerados iguais e portanto serão pintados.
Isso é bem tranquilo, o problema maior é analisar os pixels em volta do que foi escolhido e parar quando o pixel não entrar na escala do limiar.

ViniGodoy

Eu sei o que é limiar. E geralmente, só se aplica aos pixels abaixo do limiar.

Nesse caso, é só usar qualquer algoritmo de flood fill:

tartaruga.df

ViniGodoy:
Eu sei o que é limiar. E geralmente, só se aplica aos pixels abaixo do limiar.

Nesse caso, é só usar qualquer algoritmo de flood fill:
http://en.wikipedia.org/wiki/Flood_fill

Obrigado, já dei uma olhada rápida no flood fill e parece que vai atender exatamente o que preciso. Quanto ao limiar só expliquei porque achei que não tinha sido claro o suficiente e porque tinha a particularidade de considerar tanto para cima quanto para baixo mas valeu.

Depois que implementar coloco o código aqui.

E

Na minha cabeça, se os valores pudessem ser analisado por hsv, seria mais fácil, pois daí era mais simples lidar com cores que parecidas. Até mesmo nesse caso de imagens branco e preto, basta pegar e analisar o valor de saturação que fica tudo certo.

ViniGodoy

No caso de uma imagem em tons de cinza faz pouca diferença usar RGB ou HSV. Todos os valores de R, G e B serão iguais ao L do HSV.

Criado 9 de novembro de 2012
Ultima resposta 12 de nov. de 2012
Respostas 7
Participantes 3