Tratar imagens digitalmente é uma coisa cada vez mais comum, seja para fazer correções de luz, cor, retirar imperfeições ou tratá-las para uma determinada finalidade, como identificar elementos na imagem de forma automática (ex: identificar uma placa de carro em uma imagem).
Para tal, é necessária a utilização de um ou de vários filtros para que o objetivo seja alcançado. A seguir, uma lista com alguns dos filtros mais usados e uma breve explicação sobre eles:
- Desaturação (escala de cinza): deixa uma imagem em escala de cinza, ou seja, uma imagem colorida terá apenas pixels brancos, pretos ou cinzas;
- Binarização (Threshold): consiste em deixar uma imagem em preto e branco, cada pixel da imagem original se transforma em um pixel totalmente branco (RGB #FFFFFF) ou totalmente preto (RGB #000000). Para determinar se um pixel da imagem original se tornará preto ou branco é usado um limiar, um valor que determina a partir de qual ponto um pixel se tornará preto ou se tornará branco. A imagem tratada por este filtro não contém pixel cinza, apenas preto e/ou branco, diferente da desaturação;
- Negativo: este filtro faz com que a cor de cada pixel da imagem original se transforme na cor inversa (ex: pixel branco se transforma em pixel preto). A cor inversa é o valor da subtração entre 255 e o valor RGB. Ex: para um amarelo com valor RGB 255, 240, 0, sua cor inversa é o RGB 0, 15, 255.
- Mediana: filtro usado para eliminar ruídos da imagem. O algoritmo faz um cálculo da média de cores de uma certa região de pixels e determina a cor média daquele trecho da imagem. Se houver um pixel preto (ruído) em meio há vários pixels brancos a aplicação do filtro eliminará este pixel preto, tirando o ruído da imagem.
Saiba mais sobre tratamento digital de imagens: PDI
Conheça os principais filtros do Adobe Photoshop: Filtros Photoshop
Bom, agora vamos ao que interessa: criar os filtros utilizando a linguagem JAVA!
Vou criar uma classe chamada App1 que simplesmente vai aplicar o filtro para deixar uma imagem em escala de cinza, e outra classe chamada Filtro que conterá os algoritmos dos filtros. A classe Exibicao servirá apenas para exibir as imagens utilizadas em um componente JFrame, nada muito funcional, apenas para deixar o exemplo mais “bonitinho”.
fonte (oxenteexception)
App1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| public class App1 { public static void main(String[] args) throws IOException { try { //carrega nova imagem BufferedImage imagem1 = ImageIO.read( new File( "images/imagem1.jpg" )); //instancia um filtro e aplica a escala de cinza Filtro filtro = new Filtro(); filtro.escalaDeCinza(imagem1); //gera uma nova imagem a partir da imagem1 ImageIO.write(imagem1, "jpg" , new File( "images/imagem2.jpg" )); //aqui apenas para demonstração, //carreguei novamente as duas imagens para exibi-las dentro de um JFrame imagem1 = ImageIO.read( new File( "images/imagem1.jpg" )); BufferedImage imagem2 = ImageIO.read( new File( "images/imagem2.jpg" )); Exibicao show = new Exibicao(); show.exibirImagem(imagem1, imagem2); System.out.println( "Filtro aplicado com sucesso!" ); } catch (IOException e){ System.out.println( "Erro! Verifique se o arquivo especificado existe e tente novamente." ); } catch (Exception e){ System.out.println( "Erro! " + e.getMessage()); } } } |
Filtro.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
| public class Filtro { //método de aplicação do filtro escala de cinza //recebe como parâmetro uma imagem public static BufferedImage escalaDeCinza(BufferedImage imagem) { //pegar largura e altura da imagem int width = imagem.getWidth(); int height = imagem.getHeight(); int media = 0 ; //laço para varrer a matriz de pixels da imagem for ( int i = 0 ; i < width; i++) { for ( int j = 0 ; j < height; j++) { //rgb recebe o valor RGB do pixel em questão int rgb = imagem.getRGB(i, j); int r = (int)((rgb&0x00FF0000)>>>16); //R int g = ( int )((rgb& 0x0000FF00 )>>> 8 ); //G int b = ( int ) (rgb& 0x000000FF ); //B //media dos valores do RGB //será o valor do pixel na nova imagem media = (r + g + b) / 3 ; //criar uma instância de Color Color color = new Color(media, media, media); //setar o valor do pixel com a nova cor imagem.setRGB(i, j, color.getRGB()); } } return imagem; } public static BufferedImage negativo(BufferedImage image) { int width = image.getWidth(); int height = image.getHeight(); for ( int i = 0 ; i < width; i++) { for ( int j = 0 ; j < height; j++) { int rgb = image.getRGB(i, j); //a cor inversa é dado por 255 menos o valor da cor int r = 255 - (int)((rgb&0x00FF0000)>>>16); int g = 255 - ( int )((rgb& 0x0000FF00 )>>> 8 ); int b = 255 - ( int ) (rgb& 0x000000FF ); Color color = new Color(r, g, b); image.setRGB(i, j, color.getRGB()); } } return image; } public static BufferedImage threshold(BufferedImage image, int limiar) { int width = image.getWidth(); int height = image.getHeight(); for ( int i = 0 ; i < width; i++) { for ( int j = 0 ; j < height; j++) { int rgb = image.getRGB(i, j); int r = ( int )((rgb& 0x00FF0000 )>>> 16 ); int g = ( int )((rgb& 0x0000FF00 )>>> 8 ); int b = ( int ) (rgb& 0x000000FF ); int media = (r + g + b) / 3 ; Color white = new Color( 255 , 255 , 255 ); Color black = new Color( 0 , 0 , 0 ); //como explicado no artigo, no threshold definimos um limiar, //que é um valor "divisor de águas" //pixels com valor ABAIXO do limiar viram pixels PRETOS, //pixels com valor ACIMA do limiar viram pixels BRANCOS if (media < limiar) image.setRGB(i, j, black.getRGB()); else image.setRGB(i, j, white.getRGB()); } } return image; } |
Exibicao.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| public class Exibicao { public static void exibirImagem(BufferedImage image) { ImageIcon icon = new ImageIcon(image); JLabel imageLabel = new JLabel(icon); JFrame frame = new JFrame(); Container contentPane = frame.getContentPane(); contentPane.setLayout( new GridLayout()); contentPane.add( new JScrollPane(imageLabel)); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize( 800 , 600 ); frame.setVisible( true ); } public static void exibirImagem(BufferedImage image, BufferedImage image2) { ImageIcon icon = new ImageIcon(image); JLabel imageLabel = new JLabel(icon); ImageIcon icon2 = new ImageIcon(image2); JLabel imageLabel2 = new JLabel(icon2); JFrame frame = new JFrame(); Container contentPane = frame.getContentPane(); contentPane.setLayout( new GridLayout()); contentPane.add( new JScrollPane(imageLabel)); contentPane.add( new JScrollPane(imageLabel2)); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize( 1100 , 680 ); frame.setVisible( true ); } } |
E a classe "Color"???????