Processamento de imagens na prática

Inversão de imagens

Inversão de imagens é um tema bem simples, mas qual foi a minha surpresa ao perceber que a JAI, biblioteca de processamento de imagens da Sun, não lida com isso de forma tão simples como eu pensava. Não tem muito o que explicar sobre inversão, mas quero deixar claro a diferença entre inverter o valor dos pixels e inverter uma tabela de cores, e as consequências para o uso da segunda como artifício de otimização.

A teoria

Inverter uma imagem é fazer com os valores dos pixels invertam seus valores, na escala em que estão. Em imagens tons de cinza de 8-bits os valores dos pixels vão de 0 a 255. A inversão faz com que os pixels que têm valor 0, passem a valer 255, os que tem valor 1 passem a valer 254, e assim por diante. Normalmente representa-se esta operação por uma fórmula simples:

pixel_resultado = valor_máximo – pixel

No caso de imagens RGB (ou muiti-canais em geral), inverte-se cada canal como está descrito acima, e no caso de imagens binárias o zero vira um e o um vira zero.

Inversão de imagens RBG, cinza e binária.

Inversão de imagens RBG, cinza e binária.

A imagem dos grilos é do Thiago Gama Oliveira.

Na JAI

A JAI tem a operação “invert”, que à primeira vista parece resolver isso tudo… mas não é bem assim. Em imagens binárias, o “invert” não modifica os pixels, modifica o mapa de cores. Isto significa que os píxels continuam tendo os mesmos valores que os originais, mas a aparência deles (a cor exibida no monitor) muda.

Na documentação da JAI isto quase não aparece, ou é citado rapidamente como um recurso de otimização. E não seria mesmo algo ruim se todos os usuários estivessem interessados somente no visual da imagem. Mas quando precisa-se dos valores dos pixels para cálculos posteriores a coisa complica.

Procurando por uma solução achei este registro de bug de 2006 lá na JAI, com tudo explicado, inclusive exemplo, e uma tentativa de solução que deveria funcionar, mas não funciona. O registro está lá, mas não foi resolvido ainda – e pela idade acho que não vai ser resolvido nunca.

Em resumo, a JAI inverte a tabela de cores, e não os pixels. Mas ao usar a imagem invertida para outras operações ela desconsidera a tabela de cores! Assim, inverter a imagem e depois somar com outra tem o mesmo resultado de somar as duas sem inverter antes. A operação “not”, que é um tipo de inversão específica para imagens binárias, tem o mesmo problema.

Conclusão: a JAI não inverte imagens binárias corretamente.

Depois de algumas semanas de pesquisa, e daquela conhecida frustração de achar que era eu que não sabia usar os métodos corretamente, resolvi partir para uma implementação independente da inversão. Não ficou otimizada, nem eu me dei ao trabalho de implementá-la estendendo a JAI, como manda o figurino, mas funciona.

Na verdade usei alguns artifícios dos quais não me orgulho, mas fiz porque não encontrei alternativas mais elegantes – provavelmente vou encontrar, a aí publico o código novamente. Mas por hora incluí a minha classe aqui para quem quiser utilizar (com licença GPL).

BinaryInvert.java
Obs: O arquivo está “zipado” porque .java aparentemente é uma ameaça de segurança para o meu provedor.

Bom, se alguém olhar e achar que tem uma foma beeeeem mais fácil de fazer isso, não pense que vai me ofender – por favor me diga! Na verdade estou torcendo para que isto aconteça…

Até mais!

Trackbacks/Pingbacks

           
  1.        

Comente

Você pode usar estas tags e atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>