Autor: Rafael Felício Fernandes | Publicado: 2011-12-14T04:35:00-08:00







Manipulando imagens com JAVA - Binarização,limiar&nbsp;



e&nbsp;threshold







import&nbsp;java.awt.Color;&nbsp;&nbsp;
import&nbsp;java.awt.Graphics2D;&nbsp;&nbsp;
import&nbsp;java.awt.image.BufferedImage;&nbsp;&nbsp;
import&nbsp;java.io.File;&nbsp;&nbsp;
import&nbsp;java.io.IOException;&nbsp;&nbsp;
&nbsp;&nbsp;
import&nbsp;javax.imageio.ImageIO;&nbsp;&nbsp;
import&nbsp;javax.swing.JFileChooser;&nbsp;&nbsp;
import&nbsp;javax.swing.JOptionPane;&nbsp;&nbsp;
import&nbsp;javax.swing.filechooser.FileNameExtensionFilter;&nbsp;&nbsp;
&nbsp;&nbsp;
public&nbsp;class&nbsp;Imagem {&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[] args) {&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JFileChooser chooser =&nbsp;new&nbsp;JFileChooser();&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chooser.setFileFilter(new&nbsp;FileNameExtensionFilter("Image files",&nbsp;"png",&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"jpg",&nbsp;"bmp"));&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chooser.setAcceptAllFileFilterUsed(false);&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(chooser.showOpenDialog(null) != JFileChooser.APPROVE_OPTION)&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Carregamos a imagem do disco&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File img = chooser.getSelectedFile();&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage image = ImageIO.read(img);&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Geramos uma versão em escala de cinza&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage gray = toGrayscale(image);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ImageIO.write(gray,&nbsp;"png", newFile(img,&nbsp;"gray"));&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Geramos uma versão binária a partir da versão em escala de cinza.&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage binary = toBinary(gray,&nbsp;128);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ImageIO.write(binary,&nbsp;"png", newFile(img,&nbsp;"binary"));&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception e) {&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JOptionPane.showMessageDialog(null,&nbsp;"Erro ao processar imagem.");&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * Converte a imagem para escala de cinza.&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * @param image Imagem a ser convertida&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * @return a Imagem convertida.&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;BufferedImage toGrayscale(BufferedImage image)&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws&nbsp;IOException {&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage output =&nbsp;new&nbsp;BufferedImage(image.getWidth(),&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Graphics2D g2d = output.createGraphics();&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.drawImage(image,&nbsp;0,&nbsp;0,&nbsp;null);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.dispose();&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;output;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * Converte a imagem para binário usando um algorítmo de threshold simples.&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * Tudo que estiver abaixo do threshold será convertido para preto. Acima ou&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * igual ao threshold será convertido para branco.&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * @param image&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Imagem a ser convertida (apenas o canal r será considerado).&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Use uma escala já transformada em escala de cinza para&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;melhores resultados.&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * @param t&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Valor do threshold.&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;BufferedImage toBinary(BufferedImage image,&nbsp;int&nbsp;t) {&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;BLACK = Color.BLACK.getRGB();&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;WHITE = Color.WHITE.getRGB();&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage output =&nbsp;new&nbsp;BufferedImage(image.getWidth(),&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Percorre a imagem definindo na saída o pixel como branco se o valor&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// na entrada for menor que o threshold, ou como preto se for maior.&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;y =&nbsp;0; y &lt; image.getHeight(); y++)&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;x =&nbsp;0; x &lt; image.getWidth(); x++) {&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color pixel =&nbsp;new&nbsp;Color(image.getRGB(x, y));&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;output.setRGB(x, y, pixel.getRed() &lt; t ? BLACK : WHITE);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;output;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * Gera um nome de arquivo baseado no nome fornecido. O arquivo terá o mesmo&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * caminho do nome original.&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * &lt;p&gt;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * Exemplo: Se o arquivo for c:\fish.png e a string de detalhe for "gray" a&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * saída será c:\fish-gray.png&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * A extensão final sempre será png.&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * @param file Arquivo original&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * @param detail String de detalhe&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; * @return O nome do arquivo.&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;File newFile(File file, String detail) {&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;File(file.getParentFile(), file.getName().substring(0,&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.getName().indexOf("."))&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;"-"&nbsp;+ detail +&nbsp;".png");&nbsp;&nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;
&nbsp;&nbsp;
} &nbsp;