0% acharam este documento útil (0 voto)
166 visualizações146 páginas

Intro Pi Java

Direitos autorais
© Attribution Non-Commercial (BY-NC)
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
166 visualizações146 páginas

Intro Pi Java

Direitos autorais
© Attribution Non-Commercial (BY-NC)
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

Introduo ao Processamento de Imagens Digitais em Java / API JAI

Escola de Vero da Unifesp

Rafael Santos

Fevereiro/2010

[Link]

1 /146

Objetivo

Apresentar conceitos, tcnicas e exemplos bsicos de aplicao de processamento de imagens digitais. Implementaes em Java opcionalmente com a API JAI (Java Advanced Imaging). Parte reduzida do livro on-line Java Image Processing Cookbook ([Link] Cdigo!

Fevereiro/2010

[Link]

2 /146

Introduo

Fevereiro/2010

[Link]

3 /146

Aplicaes de Processamento de Imagens

Sensoriamento Remoto:

Geologia (estudo da composio da superfcie). Agricultura (determinao da cobertura vegetal). Engenharia Florestal (idem). Cartografia (mapeamento da superfcie). Meteorologia.

Medicina e Biologia. Astronomia (macro) e Fsica (micro). Produo e Controle de Qualidade. Segurana e Monitoramento. Documentos, Web, etc.
[Link] 4 /146

Fevereiro/2010

Imagens Digitais

Imagem = matriz de pixels. Pixel = medida, conjunto de medidas ou ndice para tabela de valores. Metadados: dados adicionais sobre a imagem.

Fevereiro/2010

[Link]

5 /146

Imagens e Pixels
34 29 105 12 30 105 34 29 105 34 29 105 34 29 105 12 30 105 34 29 105
Fevereiro/2010

34 42 42 29 49 49 105 97 97 34 14 34 29 48 29 105 97 105 34 69 36 29 76 54 105 97 104 12 85 113 30 103 108 105 85 72 34 58 100 29 53 123 105 105 66 34 42 90 29 49 115 105 97 78 42 35 85 49 41 103 97 105 85

34 29 105 34 29 105 12 30 105 36 54 104 90 115 78 107 136 58 111 132 60

12 42 30 49 105 97 42 34 49 29 97 105 12 42 30 49 105 97 34 34 29 29 105 105 14 34 48 29 97 105 85 42 103 49 85 97 105 42 119 49 86 97


6 /146

[Link]

Tipos mais comuns

Cmera Digital

3264x2448 elementos sensores Resoluo: no se aplica 3 bandas Cada pixel discretizado com valores entre 0 e 255

Scanner

Array mvel de elementos sensores Resoluo: 2400 DPI ou mais 3 bandas Discretizao varivel
[Link] 7 /146

Fevereiro/2010

Outros Tipos de Imagens Digitais

No somos limitados imagens como as de cmeras e scanners!


Pixels podem ter mais que trs valores associados a eles. Pixels podem ter valores fora do tradicional intervalo [0, 255]. Pixels no precisam representar valores inteiros ou positivos! Imagens multispectrais e hiperspectrais. Imagens de modelos de terreno, mdicas (Raio-X), etc.

Exemplos:

Fevereiro/2010

[Link]

8 /146

Outros Tipos de Imagens Digitais

Fevereiro/2010

[Link]

9 /146

Outros Tipos de Imagens Digitais

Fevereiro/2010

[Link]

10 /146

Imagens Digitais: Multiespectrais

Fevereiro/2010

[Link]

11 /146

Imagens Digitais: Hiperespectrais

[Link]

Fevereiro/2010

[Link]

12 /146

Processamento de Imagens em Java

Fevereiro/2010

[Link]

13 /146

Processamento de Imagens em Java

Preciso saber Java?


Ajuda e muito, mas no imprescindvel. Experincia com C++, C#, outras linguagens pode ajudar.

Todo o cdigo est no livro on-line ([Link] completo e comentado.

Fevereiro/2010

[Link]

14 /146

Processamento de Imagens em Java


Popularidade e flexibilidade de Java. Temos APIs para representao, visualizao e I/O simples de imagens como parte do JSE. Temos a API Java Advanced Imaging para operaes muito mais poderosas, flexveis e complexas! E a questo da performance?

Melhor do que esperado! No estou preocupado com real time. Mais valor clareza e simplicidade de cdigo.

Fevereiro/2010

[Link]

15 /146

Processamento de Imagens em Java: JAI


Java (Swing) tem classes e operadores bsicos. Java Advanced Imaging


API adicional (download separado). Projeto do [Link] pblico mas no totalmente aberto.

Muitos operadores especficos para processamento de imagens. Execuo postergada e cadeias de operadores. Representao mais poderosa e flexvel de imagens (tiles). Alguns operadores acelerados (implementao nativa). Dvida: ter apoio da Oracle?

Fevereiro/2010

[Link]

16 /146

Representao de Imagens em Java

Fevereiro/2010

[Link]

17 /146

Representao de Imagens: Java

RenderedImage
ColorModel
ColorSpace

Raster
SampleModel DataBuffer

Formato de representao na memria diferente de formato de arquivo! Existem limitaes mtuas.


[Link] 18 /146

Fevereiro/2010

Representao de Imagens: TiledImage (JAI)

Fevereiro/2010

[Link]

19 /146

Representao de Imagens
RenderedImage

WritableRenderedImage

BufferedImage

ImageJAI

PlanarImage

RenderedOp

API JAI
Fevereiro/2010 [Link]

TiledImage
20 /146

Criando Imagens em Java

Fevereiro/2010

[Link]

21 /146

Criando Imagens (sem JAI) Imagens simples (RGB, puro preto-e-branco, nveis de cinza; pixels so arrays de bytes). 1. Criamos instncia de BufferedImage. 2. Criamos instncia de WritableRaster associada BufferedImage. 3. Manipulamos os pixels do WritableRaster.

Fevereiro/2010

[Link]

22 /146

Criando Imagens (sem JAI)


public static void main(String[] args) throws IOException { int width = 256; int height = 256; BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); WritableRaster raster = [Link](); int[] cor1 = new int[]{255,0,0}; int[] cor2 = new int[]{0,0,255}; int cont=0; for(int h=0;h<height;h++) for(int w=0;w<width;w++) { if ((((w/32)+(h/32)) % 2) == 0) [Link](w,h,cor1); else [Link](w,h,cor2); } [Link](image,"PNG",new File("[Link]")); }
Fevereiro/2010 [Link] 23 /146

Criando Imagens (com JAI) Imagens simples (RGB, puro preto-e-branco, nveis de cinza) ou multibandas; pixels podem ser arrays de qualquer tipo nativo. 1. Criamos instncia de SampleModel usando RasterFactory. 2. Criamos um TiledImage com este SampleModel. 3. Criamos um WritableRaster a partir da TiledImage. 4. Manipulamos os pixels do WritableRaster.

Fevereiro/2010

[Link]

24 /146

Criando Imagens (com JAI)


intwidth=640;intheight=640; SampleModelsampleModel= [Link](DataBuffer.TYPE_BYTE, width,height,1); TiledImagetiledImage= newTiledImage(0,0,width,height,0,0,sampleModel,null); WritableRasterwr=[Link](0,0); for(inth=0;h<height/32;h++) for(intw=0;w<width/32;w++) { int[]fill=newint[32*32];//Ablockofpixels... [Link](fill,(int)([Link]()*256)); [Link](w*32,h*32,32,32,0,fill); } [Link]("filestore",tiledImage, "[Link]","PNG");

Fevereiro/2010

[Link]

25 /146

Criando Imagens (com JAI) Para imagens com tiles um pouco mais complicado... 1. Criamos instncia de SampleModel usando RasterFactory. 2. Criamos um TiledImage com este SampleModel. 3. Para cada tile:
1. criamos um WritableRaster a partir da TiledImage. 2. Manipulamos os pixels do WritableRaster.

Fevereiro/2010

[Link]

26 /146

Criando Imagens (com JAI)


intwidth=483;intheight=483; inttWidth=64;inttHeight=64; SampleModelsampleModel= [Link](DataBuffer.TYPE_BYTE, tWidth,tHeight,3); ColorModelcm=[Link](sampleModel); TiledImagetiledImage= newTiledImage(0,0,width,height,0,0,sampleModel,cm); //Createthecolors. int[]red=newint[]{255,0,0}; int[]green=newint[]{0,255,0}; int[]blue=newint[]{0,0,255}; int[]yellow=newint[]{255,255,0}; int[]black=newint[]{0,0,0};

Fevereiro/2010

[Link]

27 /146

Criando Imagens (com JAI)


for(intth=[Link]();th<=[Link]();th++) for(inttw=[Link]();tw<=[Link]();tw++) { WritableRasterwr=[Link](tw,th); for(intih=0;ih<tHeight;ih++) for(intiw=0;iw<tWidth;iw++) { intw=[Link]()+iw; inth=[Link]()+ih; if((w>=17)&&(w<17+216)&&(h>=17)&&(h<17+216)) [Link](w,h,red); elseif((w>=250)&&(w<250+216)&&(h>=17)&&(h<17+216)) [Link](w,h,green); elseif((w>=17)&&(w<17+216)&&(h>=250)&&(h<250+216)) [Link](w,h,yellow); elseif((w>=250)&&(w<250+216)&&(h>=250)&&(h<250+216)) [Link](w,h,blue); [Link](w,h,black); } }

Fevereiro/2010

[Link]

28 /146

Criando Imagens (com JAI)


TIFFEncodeParamtep=newTIFFEncodeParam(); [Link](true); [Link](tWidth,tHeight); [Link]("filestore",tiledImage,"[Link]","TIFF",tep);

Fevereiro/2010

[Link]

29 /146

Armazenando e Recuperando Imagens

Fevereiro/2010

[Link]

30 /146

Entrada e Sada

Sem JAI (BufferedImage):


public static void main(String[] args) throws IOException { File f = new File(args[0]); BufferedImage image = [Link](f); [Link]("Dimenses: "+ [Link]()+"x"+[Link]()+" pixels"); }

Com JAI (PlanarImage):


public static void main(String[] args) throws IOException { PlanarImage image = [Link]("fileload",args[0]); [Link]("Dimenses: "+ [Link]()+"x"+[Link]()+" pixels"); }

Fevereiro/2010

[Link]

31 /146

Entrada e Sada

Sem JAI (BufferedImage):


public static void main(String[] args) throws IOException { int width = 256; int height = 256; BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); ... [Link](image,"PNG",new File("[Link]")); }

Com JAI (PlanarImage):


public static void main(String[] args) throws IOException { ... TiledImage tiledImage = new TiledImage(0,0,width,height,0,0,sampleModel,colorModel); ... [Link]("filestore",tiledImage,"[Link]","TIFF"); }

Fevereiro/2010

[Link]

32 /146

Acesso Direto a Pixels

Fevereiro/2010

[Link]

33 /146

Acesso a pixels (sem JAI)


public static void main(String[] args) throws IOException { File f = new File(args[0]); BufferedImage imagem = [Link](f); Memria! Raster raster = [Link](); int[] pixel = new int[3]; int brancos = 0; for(int h=0;h<[Link]();h++) for(int w=0;w<[Link]();w++) { [Link](w,h,pixel); if ((pixel[0] == 255) && (pixel[1] == 255) && (pixel[2] == 255)) brancos++; } [Link](brancos+" pixels brancos"); }

Fevereiro/2010

[Link]

34 /146

Acesso a pixels (com JAI)


public static void main(String[] args) throws IOException { File f = new File(args[0]); BufferedImage imagem = [Link](f); RandomIter iterator = [Link](imagem,null); int[] pixel = new int[3]; int brancos = 0; for(int h=0;h<[Link]();h++) for(int w=0;w<[Link]();w++) { [Link](w,h,pixel); if ((pixel[0] == 255) && (pixel[1] == 255) && (pixel[2] == 255)) brancos++; } [Link](brancos+" pixels brancos"); }

Existem tambm RectIter e RookIter.


[Link] 35 /146

Fevereiro/2010

Exibindo Imagens

Fevereiro/2010

[Link]

36 /146

Visualizao de Imagens

Componentes de interfaces grficas para mostrar imagens. Geralmente bem simples, melhorias como interatividade, processamento, etc. ficam por conta do programador...

o que fcil de fazer graas ao mecanismo de herana!

Conhecimentos de programao de interfaces grficas em Java so teis: s conhecimento de design no adiantam.


Componentes de UI JFrame

Fevereiro/2010

[Link]

37 /146

Display de Imagens (sem JAI)


public static void main(String[] args) throws IOException { BufferedImage image = [Link](new File(args[0])); JFrame frame = new JFrame("Display Image: "+args[0]); ImageIcon icon = new ImageIcon(image); JLabel imageLabel = new JLabel(icon); [Link]().add(new JScrollPane(imageLabel)); [Link](JFrame.EXIT_ON_CLOSE); [Link](600,300); [Link](true); }

BufferedImage ImageIcon JLabel (JScrollPane).

Fevereiro/2010

[Link]

38 /146

Display de Imagens (sem JAI)

Fevereiro/2010

[Link]

39 /146

Display de Imagens (com JAI)


public static void main(String[] args) throws IOException { BufferedImage image = [Link](new File(args[0])); JFrame frame = new JFrame("Display Image: "+args[0]); DisplayJAI display = new DisplayJAI(image); [Link]().add(new JScrollPane(display)); [Link](JFrame.EXIT_ON_CLOSE); [Link](600,300); [Link](true); }

DisplayJAI mais flexvel, permite alguma interao (no implementada). No parte da API JAI (!?).

Fevereiro/2010

[Link]

40 /146

Exibindo Imagens (Solues Especficas)

Fevereiro/2010

[Link]

41 /146

Imagens Sincronizadas

Componente que mostra duas imagens sincronizadas:

Modificao no viewport de uma causa modificao no viewport da outra.

Composio de instncias de DisplayJAI.

Fevereiro/2010

[Link]

42 /146

Imagens Sincronizadas

Exibio de duas instncias de DisplayJAI de forma sincronizada.

public class DisplayTwoSynchronizedImages extends JPanel implements AdjustmentListener { protected DisplayJAI dj1; protected DisplayJAI dj2; protected JScrollPane jsp1; protected JScrollPane jsp2;

Fevereiro/2010

[Link]

43 /146

Imagens Sincronizadas
public DisplayTwoSynchronizedImages(RenderedImage im1, RenderedImage im2) { super(); // Cria componente com duas imagens com JScrollPanes setLayout(new GridLayout(1,2)); dj1 = new DisplayJAI(im1); dj2 = new DisplayJAI(im2); jsp1 = new JScrollPane(dj1); jsp2 = new JScrollPane(dj2); add(jsp1); add(jsp2); // Registra listeners para os scroll bars do JScrollPanes [Link]().addAdjustmentListener(this); [Link]().addAdjustmentListener(this); [Link]().addAdjustmentListener(this); [Link]().addAdjustmentListener(this); }

Fevereiro/2010

[Link]

44 /146

Imagens Sincronizadas
public void adjustmentValueChanged(AdjustmentEvent e) { if ([Link]() == [Link]()) [Link]().setValue([Link]()); if ([Link]() == [Link]()) [Link]().setValue([Link]()); if ([Link]() == [Link]()) [Link]().setValue([Link]()); if ([Link]() == [Link]()) [Link]().setValue([Link]()); } }

Fevereiro/2010

[Link]

45 /146

Imagens Sincronizadas: Exemplo


public class Borda { public static void main(String[] args) { PlanarImage imagem = [Link]("fileload", args[0]); float[] kernelMatrix = { -1, -2, -1, 0, 0, 0, 1, 2, 1 }; KernelJAI kernel = new KernelJAI(3,3,kernelMatrix); PlanarImage bordas = [Link]("convolve",imagem,kernel); JFrame frame = new JFrame("Bordas horizontais"); [Link](new DisplayTwoSynchronizedImages(imagem,bordas)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); } }

Fevereiro/2010

[Link]

46 /146

Imagens Sincronizadas: Exemplo

Fevereiro/2010

[Link]

47 /146

Imagens Substitutas

Uso de imagens substitutas (surrogate images): Criamos uma imagem normalizada com pixels entre valores 0-255 Transformamos o tipo da imagem para bytes. Uma classe que herda de DisplayJAI pode executar estes passos.

Fevereiro/2010

[Link]

48 /146

Imagens Substitutas
public class DisplaySurrogateImage extends DisplayJAI { protected PlanarImage surrogateImage; protected int width,height; public DisplaySurrogateImage(PlanarImage image) { width = [Link](); height = [Link](); // Recuperamos valores extremos da imagem. ParameterBlock pbMaxMin = new ParameterBlock(); [Link](image); PlanarImage extrema = [Link]("extrema", pbMaxMin); double[] allMins = (double[])[Link]("minimum"); double[] allMaxs = (double[])[Link]("maximum"); double minValue = allMins[0]; double maxValue = allMaxs[0]; for(int v=1;v<[Link];v++) { if (allMins[v] < minValue) minValue = allMins[v]; if (allMaxs[v] > maxValue) maxValue = allMaxs[v]; }

Fevereiro/2010

[Link]

49 /146

Imagens Substitutas
// Reescalamos os nveis de cinza da imagem. double[] subtract = new double[1]; subtract[0] = minValue; double[] multiplyBy = new double[1]; multiplyBy[0] = 255./(maxValue-minValue); ParameterBlock pbSub = new ParameterBlock(); [Link](image); [Link](subtract); surrogateImage = (PlanarImage)[Link]("subtractconst",pbSub); ParameterBlock pbMult = new ParameterBlock(); [Link](surrogateImage); [Link](multiplyBy); surrogateImage = (PlanarImage)[Link]("multiplyconst",pbMult); // Convertemos para bytes. ParameterBlock pbConvert = new ParameterBlock(); [Link](surrogateImage); [Link](DataBuffer.TYPE_BYTE); surrogateImage = [Link]("format", pbConvert); // Usamos esta imagem para display. set(surrogateImage); } }

Fevereiro/2010

[Link]

50 /146

Imagens Substitutas
public class DemonstraDisplaySurrogateImage { public static void main(String[] args) { PlanarImage image = [Link]("fileload", args[0]); JFrame frame = new JFrame("Mostrando "+args[0]); [Link]().add( new JScrollPane(new DisplaySurrogateImage(image))); [Link](JFrame.EXIT_ON_CLOSE); [Link](); [Link](true); } }

Fevereiro/2010

[Link]

51 /146

Imagens Substitutas: LUTs


Uso de imagens substitutas (surrogate images) com LUTs: Look-up Tables (LUTs): tabela de cores.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 1 2 2 2 1 0 0 0 0 0 0 1 1 2 2 2 3 2 1 1 0 0 0 1 1 1 2 2 3 2 2 1 1 1 0 0 0 1 1 2 3 2 2 2 1 1 0 0 0 0 0 0 1 2 2 2 1 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ndice 0 1 2 3 R G B 1 0

0 131 255 233 0

0 124

255 255 255

Fevereiro/2010

[Link]

52 /146

Imagens Substitutas: LUTs


publicvoidsetLUT(short[][]lut) { SampleModelsampleModel=[Link](); SampleModelnewSampleModel= [Link](DataBuffer.TYPE_BYTE, [Link](),[Link](),3); byte[]reds=newbyte[256]; byte[]greens=newbyte[256]; byte[]blues=newbyte[256]; for(inti=0;i<256;i++) { reds[i]=(byte)lut[i][0]; greens[i]=(byte)lut[i][1]; blues[i]=(byte)lut[i][2]; } ColorModelcolorModel=newIndexColorModel(8,256,reds,greens,blues); ImageLayoutlayout=newImageLayout(surrogateImage); [Link](colorModel); HashMap<[Link],ImageLayout>map= newHashMap<[Link],ImageLayout>(); [Link](JAI.KEY_IMAGE_LAYOUT,layout); RenderingHintshints=newRenderingHints(map); ParameterBlockpb=newParameterBlock(); [Link](surrogateImage); PlanarImagenewSurrogateImage=[Link]("format",pb,hints); set(newSurrogateImage); }

Fevereiro/2010

[Link]

53 /146

Imagens Substitutas: LUTs


/**Theinvertedgraylut*/ publicfinalstaticshort[][]invGray() { short[][]lut=newshort[256][3]; for(shorti=0;i<256;i++) { lut[i][0]=(short)(255i); lut[i][1]=(short)(255i); lut[i][2]=(short)(255i); } returnlut; } /**Thesinlut(rgborder)*/ publicfinalstaticshort[][]sin_rgb() { short[][]lut=newshort[256][3]; for(shorti=0;i<256;i++) { lut[i][0]=(short)(127*(1+[Link]([Link]*(i127)/255))); lut[i][1]=(short)(127*(1+[Link]([Link]*(i)/255))); lut[i][2]=(short)(127*(1+[Link]([Link]*(i+127)/255))); } returnlut; } Fevereiro/2010 [Link] 54 /146

Imagens Substitutas: LUTs

Fevereiro/2010

[Link]

55 /146

Desenhando em Imagens

Podemos obter contextos grficos de BufferedImages e PlanarImages..

.. e us-los para desenhar sobre a imagem.

As imagens so modificadas (na memria) e podem ser visualizadas e/ou armazenadas com os grficos.

Fevereiro/2010

[Link]

56 /146

Desenhando em Imagens
BufferedImagebaseImage=[Link](newFile("sjc_region.png")); int[][]coords=newint[][]{ {714,219}, {822,256}, {797,329}, {710,300}, {711,293}, {666,271}}; [Link]=[Link](); booleanisFirst=true; doublefirstX=0,firstY=0; for(int[]coord:coords) { intx=coord[0];inty=coord[1]; if(isFirst) { [Link](x,y); firstX=x; firstY=y; isFirst=false; } else{[Link](x,y);} } [Link](firstX,firstY); Fevereiro/2010 [Link] 57 /146

Desenhando em Imagens
[Link]=[Link](); [Link](0,0); [Link]([Link](),0); [Link]([Link](),[Link]()); [Link](0,[Link]()); [Link](0,0); AreawholeImage=newArea(pathForWholeImage); [Link](newArea(regionOfInterest)); Graphics2Dg2d=(Graphics2D)[Link](); [Link](RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); [Link](newColor(255,255,255,100)); [Link](wholeImage); [Link](newBasicStroke(5f)); [Link](newColor(255,0,0,200)); [Link](regionOfInterest); JFrameframe=newJFrame("Highlightingimageregions"); ImageIconicon=newImageIcon(baseImage); JLabellabel=newJLabel(icon); [Link]().add(newJScrollPane(label)); [Link](JFrame.EXIT_ON_CLOSE); [Link]();[Link](true); Fevereiro/2010 [Link] 58 /146

Desenhando em Imagens

Fevereiro/2010

[Link]

59 /146

Operadores da API JAI

Fevereiro/2010

[Link]

60 /146

Operadores da API JAI: Introduo


Classe JAI prov mtodo create. Vrios operadores so registrados, chamados de forma unificada. Parmetros (se houver) so passados atravs de instncia de ParameterBlock. Mtodo retorna instncia de RenderedOp cast para PlanarImage se necessrio.

Fevereiro/2010

[Link]

61 /146

Relembrando: Representao de Imagens


RenderedImage

WritableRenderedImage

BufferedImage

ImageJAI

PlanarImage

RenderedOp

API JAI
Fevereiro/2010 [Link]

TiledImage
62 /146

Operadores da API JAI: invert

Inverte os valores dos pixels.


Tipos com sinal: sada = -entrada Tipos sem sinal: sada = mximo - entrada

public static void main(String[] args) { PlanarImage input = [Link]("fileload", args[0]); PlanarImage output = [Link]("invert", input); JFrame frame = new JFrame(); [Link]("Invert image "+args[0]); [Link]().add( new DisplayTwoSynchronizedImages(input,output)); [Link](JFrame.EXIT_ON_CLOSE); [Link](); [Link](true); }

Fevereiro/2010

[Link]

63 /146

Operadores da API JAI: invert

Fevereiro/2010

[Link]

64 /146

Operadores da API JAI: binarize

Transforma pixels em valores binrios por comparao com constante (1 se constante).


public static void main(String[] args) { PlanarImage imagem = [Link]("fileload", args[0]); ParameterBlock pb = new ParameterBlock(); [Link](imagem); [Link](127.0); PlanarImage binarizada = [Link]("binarize", pb); JFrame frame = new JFrame("Imagem binarizada"); [Link](new DisplayTwoSynchronizedImages(imagem,binarizada)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }

Fevereiro/2010

[Link]

65 /146

Operadores da API JAI: binarize

Fevereiro/2010

[Link]

66 /146

Operadores da API JAI: convolve

Convoluo com um kernel.

Este exemplo: suavizao.

public static void main(String[] args) { PlanarImage imagem = [Link]("fileload", args[0]); float[] kernelMatrix = { 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f, 1f/25f}; KernelJAI kernel = new KernelJAI(5,5,kernelMatrix); PlanarImage bordas = [Link]("convolve",imagem,kernel); JFrame frame = new JFrame("Suavizao da imagem"); [Link](new DisplayTwoSynchronizedImages(imagem,bordas)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }

Fevereiro/2010

[Link]

67 /146

Operadores da API JAI: convolve

Fevereiro/2010

[Link]

68 /146

Operadores da API JAI: convolve

Convoluo com um kernel.

Este exemplo: deteco de bordas horizontais (Sobel).

public static void main(String[] args) { PlanarImage imagem = [Link]("fileload", args[0]); float[] kernelMatrix = { -1, -2, -1, 0, 0, 0, 1, 2, 1 }; KernelJAI kernel = new KernelJAI(3,3,kernelMatrix); PlanarImage bordas = [Link]("convolve",imagem,kernel); JFrame frame = new JFrame("Bordas horizontais"); [Link](new DisplayTwoSynchronizedImages(imagem,bordas)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }

Fevereiro/2010

[Link]

69 /146

Operadores da API JAI: convolve

Fevereiro/2010

[Link]

70 /146

Operadores da API JAI: dilate

Expanso de regies da imagem com elemento estrutural.


public static void main(String[] args) { PlanarImage imagem = [Link]("fileload", args[0]); float[] estrutura = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; KernelJAI kernel = new KernelJAI(7,7,estrutura); ParameterBlock p = new ParameterBlock(); [Link](imagem); [Link](kernel); PlanarImage dilatada = [Link]("dilate",p); JFrame frame = new JFrame("Imagem dilatada"); [Link](new DisplayTwoSynchronizedImages(imagem,dilatada)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }

Fevereiro/2010

[Link]

71 /146

Operadores da API JAI: dilate

Regies brancas so dilatadas!


Fevereiro/2010 [Link] 72 /146

Operadores da API JAI: erode

Reduo de regies da imagem com elemento estrutural.


public static void main(String[] args) { PlanarImage imagem = [Link]("fileload", args[0]); float[] estrutura = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; KernelJAI kernel = new KernelJAI(7,7,estrutura); ParameterBlock p = new ParameterBlock(); [Link](imagem); [Link](kernel); PlanarImage erodida = [Link]("erode",p); JFrame frame = new JFrame("Imagem erodida"); [Link](new DisplayTwoSynchronizedImages(imagem,erodida)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }

Fevereiro/2010

[Link]

73 /146

Operadores da API JAI: erode

Regies brancas so dilatadas!


Fevereiro/2010 [Link] 74 /146

Operadores da API JAI: rotate

Rotao dos pixels da imagem em redor de um ponto.


public static void main(String[] args) { PlanarImage imagem = [Link]("fileload",args[0]); float angle = (float)[Link](45); // Usamos o centro da imagem para rotao float centerX = [Link]()/2f; float centerY = [Link]()/2f; ParameterBlock pb = new ParameterBlock(); [Link](imagem); [Link](centerX); [Link](centerY); [Link](angle); [Link](new InterpolationBilinear()); PlanarImage rotacionada = [Link]("rotate", pb); JFrame frame = new JFrame("Imagem rotacionada"); [Link](new DisplayTwoSynchronizedImages(imagem,rotacionada)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }

Fevereiro/2010

[Link]

75 /146

Operadores da API JAI: rotate

Coordenadas dos cantos da imagem rotacionada: (-39, -136) (558, 461)

Fevereiro/2010

[Link]

76 /146

Translao da Origem de Imagens


Original Regio para recorte
Origem 200,200 Tamanho 400x300

Regio recortada
Mnimo 200,200 Tamanho 400x300 Mximo 600,500
Fevereiro/2010

Recorte e translao

Mnimo 0,0 Tamanho 400x300 Mximo 400,300

[Link]

77 /146

Operadores da API JAI: rotate

JAI permite imagens com pixels com coordenadas negativas!


DisplayJAI, ImageIO e [Link](filestore) no. Soluo: mover a origem da imagem com o operador translate.

public static void main(String[] args) { PlanarImage imagem = [Link]("fileload",args[0]); float angle = (float)[Link](45); // Usamos o centro da imagem para rotao float centerX = [Link]()/2f; float centerY = [Link]()/2f; ParameterBlock pb = new ParameterBlock(); [Link](imagem); [Link](centerX); [Link](centerY); [Link](angle); [Link](new InterpolationBilinear()); PlanarImage rotacionada = [Link]("rotate", pb);
Fevereiro/2010 [Link] 78 /146

Operadores da API JAI: rotate


// Ajustamos a origem da imagem pb = new ParameterBlock(); [Link](rotacionada); [Link]((float)-[Link]()); [Link]((float)-[Link]()); PlanarImage rotacionadaOK = [Link]("translate",pb,null); JFrame frame = new JFrame("Imagem rotacionada"); [Link]( new DisplayTwoSynchronizedImages(imagem,rotacionadaOK)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }

Fevereiro/2010

[Link]

79 /146

Operadores da API JAI: rotate

Fevereiro/2010

[Link]

80 /146

Operadores da API JAI: scale

Aumenta ou diminui a quantidade de pixels na imagem.

Valores dos pixels podem ser interpolados.

public static void main(String[] args) { PlanarImage imagem = [Link]("fileload",args[0]); float scale = 0.3f; ParameterBlock pb = new ParameterBlock(); [Link](imagem); [Link](scale); [Link](scale); [Link](0.0F); [Link](0.0F); [Link](new InterpolationNearest()); PlanarImage reescalada = [Link]("scale", pb); JFrame frame = new JFrame("Imagem reescalada"); [Link](new DisplayTwoSynchronizedImages(imagem,reescalada)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }
Fevereiro/2010 [Link] 81 /146

Operadores da API JAI: scale

Fevereiro/2010

[Link]

82 /146

Operadores da API JAI: crop, translate, scale

Pequena aplicao que recorta e amplia uma regio em uma imagem. Parmetros passados pela linha de comando.

public static void main(String[] args) { PlanarImage imagem = [Link]("fileload",args[0]); ParameterBlock pb = new ParameterBlock(); float x = [Link](args[1]); float y = [Link](args[2]); float w = [Link](args[3]); float h = [Link](args[4]); float z = [Link](args[5]);

Fevereiro/2010

[Link]

83 /146

Operadores da API JAI: crop, translate, scale


// Recorta [Link](imagem); [Link](x); [Link](y); [Link](w); [Link](h); PlanarImage recortada = [Link]("crop",pb,null); // Reposiciona pb = new ParameterBlock(); [Link](recortada); [Link]((float)-x); [Link]((float)-y); PlanarImage recortadaOK = [Link]("translate",pb,null);

Fevereiro/2010

[Link]

84 /146

Operadores da API JAI: crop, translate, scale


// Amplia (2 verses) pb = new ParameterBlock(); [Link](recortadaOK); [Link](z); [Link](z); [Link](0.0F); [Link](0.0F); [Link](new InterpolationNearest()); PlanarImage resultado1 = [Link]("scale", pb); pb = new ParameterBlock(); [Link](recortadaOK); [Link](z); [Link](z); [Link](0.0F); [Link](0.0F); [Link](new InterpolationBicubic(2)); PlanarImage resultado2 = [Link]("scale", pb);

Fevereiro/2010

[Link]

85 /146

Operadores da API JAI: crop, translate, scale


JFrame frame = new JFrame("Recorte ampliado"); [Link]( new DisplayTwoSynchronizedImages(resultado1,resultado2)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }

java wvc/operadores/Recorta [Link] 461 896 24 27 20


Fevereiro/2010 [Link] 86 /146

Operadores da API JAI: histogram

Operador sem imagem resultante: calcula histogramas em uma imagem.

Histogramas so recuperadors como propriedades do RenderedOp resultante.

public static void main(String[] args) { PlanarImage image = [Link]("fileload", args[0]); // Primeiro histograma com 256 bins. ParameterBlock pb1 = new ParameterBlock(); [Link](image); [Link](null); [Link](1); [Link](1); [Link](new int[]{256}); [Link](new double[]{0}); [Link](new double[]{256}); PlanarImage dummyImage1 = [Link]("histogram", pb1); Histogram histo1 = (Histogram)[Link]("histogram");
Fevereiro/2010 [Link] 87 /146

Operadores da API JAI: histogram


// Segundo histograma com 32 bins. ParameterBlock pb2 = new ParameterBlock(); [Link](image); [Link](null); [Link](1); [Link](1); [Link](new int[]{32}); [Link](new double[]{0}); [Link](new double[]{256}); PlanarImage dummyImage2 = [Link]("histogram", pb2); Histogram histo2 = (Histogram)[Link]("histogram"); // Exibimos os histogramas usando um componente especfico. JFrame f = new JFrame("Histogramas"); DisplayHistogram dh1 = new DisplayHistogram(histo1,"256 bins"); [Link](2); [Link](160); [Link](1); DisplayHistogram dh2 = new DisplayHistogram(histo2,"32 bins"); [Link](16); [Link](160);[Link](8); [Link](2); [Link]().setLayout(new GridLayout(2,1)); [Link]().add(dh1); [Link]().add(dh2); [Link](JFrame.EXIT_ON_CLOSE); [Link](); [Link](true); }
Fevereiro/2010 [Link] 88 /146

Operadores da API JAI: histogram

Fevereiro/2010

[Link]

89 /146

Aplicao: Pan Sharpening


Alguns satlites tem bandas com resolues diferentes. Podemos usar combinaes de bandas (cores e pancromticas) para obter melhor resoluo espacial.

Fevereiro/2010

[Link]

90 /146

Aplicao: Pan Sharpening


PlanarImageiRed=[Link]("fileload",args[0]); PlanarImageiGreen=[Link]("fileload",args[1]); PlanarImageiBlue=[Link]("fileload",args[2]); PlanarImagepanImage=[Link]("fileload",args[3]); ParameterBlockpb=newParameterBlock(); [Link](iRed); [Link](iGreen); [Link](iBlue); PlanarImagergbImage=[Link]("bandmerge",pb);

pb=newParameterBlock(); [Link](rgbImage); floatscaleX=(1f*[Link]()/[Link]()); floatscaleY=(1f*[Link]()/[Link]()); [Link](scaleX); [Link](scaleY); rgbImage=[Link]("scale",pb);

Fevereiro/2010

[Link]

91 /146

Aplicao: Pan Sharpening


IHSColorSpaceihs=[Link](); ColorModelIHSColorModel= newComponentColorModel(ihs, newint[]{8,8,8}, false,false, [Link], DataBuffer.TYPE_BYTE); pb=newParameterBlock(); [Link](rgbImage); [Link](IHSColorModel); RenderedImageimageIHS=[Link]("colorconvert",pb); PlanarImage[]IHSBands=newPlanarImage[3]; for(intband=0;band<3;band++) { pb=newParameterBlock(); [Link](imageIHS); [Link](newint[]{band}); IHSBands[band]=[Link]("bandselect",pb); }

Fevereiro/2010

[Link]

92 /146

Aplicao: Pan Sharpening


ImageLayoutimageLayout=newImageLayout(); [Link](IHSColorModel); [Link]([Link]()); RenderingHintsrendHints= newRenderingHints(JAI.KEY_IMAGE_LAYOUT,imageLayout); pb=newParameterBlock(); [Link](panImage); [Link](IHSBands[1]); [Link](IHSBands[2]); RenderedImagepanSharpenedIHSImage= [Link]("bandmerge",pb,rendHints); pb=newParameterBlock(); [Link](panSharpenedIHSImage); [Link]([Link]());//RGBcolormodel PlanarImagefinalImage=[Link]("colorconvert",pb); JFrameframe=newJFrame("IHSPanSharpening"); [Link](newDisplayTwoSynchronizedImages(rgbImage,finalImage)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true);
Fevereiro/2010 [Link] 93 /146

Aplicao: Pan Sharpening

Fevereiro/2010

[Link]

94 /146

Aplicao: Pan Sharpening

Fevereiro/2010

[Link]

95 /146

Criando Novos Operadores com a API JAI

Fevereiro/2010

[Link]

96 /146

Criando Novos Operadores

Qual tipo de operao estamos implementando?


SourcelessOpImage: operadores sem imagens de entrada. PointOpImage: pixels da sada dependem dos mesmos pixels da entrada. AreaOpImage: pixels da sada dependem de rea ao redor dos da entrada. GeometricOpImage: pixels da sada podem depender de todos da entrada. StatisticsOpImage: operadores que calculam estatsticas sobre imagem de entrada.

Fevereiro/2010

[Link]

97 /146

Criando Novos Operadores Receita de bolo (relativamente) simples para imagens renderizadas. 1. Criar classe que herda de XXXOpImage.

Como XXXOpImage abstrata, devemos implementar mtodos que fazem o processamento (quase sempre computeTile).

2. Criar classe que implementa RenderedImageFactory.

Implementa mtodo create.

Fevereiro/2010

[Link]

98 /146

Criando Novos Operadores 3. Criar classe que implementa OperationDescriptor ou herda de OperationDescriptorImpl, que descreve os parmetros e valores default do operador. 4. Registrar o novo operador junto ao OperationRegistry e RIFRegistry (podemos criar mtodo para registro na classe do passo anterior).

Fevereiro/2010

[Link]

99 /146

Novo Operador: segmenta3

Segmentador por limiar semelhante a binarize, mas com 2 limiares. Classe que herda de PointOpImage.

Contm construtor para inicializar atributos e mtodo computeTile.

public class Segmenta3OpImage extends PointOpImage { private RenderedImage source; private int threshold1,threshold2;

Passo 1

public Segmenta3OpImage(RenderedImage source,int th1,int th2, ImageLayout layout,RenderingHints hints, boolean b) { super(source,layout,hints,b); [Link] = source; this.threshold1 = th1; this.threshold2 = th2; }
Fevereiro/2010 [Link] 100 /146

Novo Operador: segmenta3


public Raster computeTile(int x,int y) { Raster r = [Link](x,y); int minX = [Link](); int minY = [Link](); int width = [Link](); int height = [Link](); // Criamos um WritableRaster da regio sendo considerada. WritableRaster wr = [Link](minX,minY,width,height); for(int l=0;l<[Link]();l++) for(int c=0;c<[Link]();c++) for(int b=0;b<[Link]();b++) { int p = [Link](c+minX,l+minY,b); if (p < threshold1) p = 0; else if (p > threshold2) p = 255; else p = 127; [Link](c+minX,l+minY,b,p); } return wr; }
Fevereiro/2010 [Link]

Passo 1

101 /146

Novo Operador: segmenta3 Passo 2


public class Segmenta3RIF implements RenderedImageFactory { public RenderedImage create(ParameterBlock paramBlock, RenderingHints hints) { RenderedImage source = [Link](0); int threshold1 = [Link](0); int threshold2 = [Link](1); ImageLayout layout = new ImageLayout(source); return new Segmenta3OpImage(source,threshold1,threshold2, layout,hints,false); } }

Fevereiro/2010

[Link]

102 /146

Novo Operador: segmenta3 Passo 3


public class Segmenta3Descriptor extends OperationDescriptorImpl { private static final String opName = "segmenta3"; private static final String vendorName = "Hypothetical Image Processing Lab"; private static final String[][] resources = { {"GlobalName", opName}, {"LocalName", opName}, {"Vendor", vendorName}, {"Description","A simple 3-level image segmentation operator"}, {"DocURL", "[Link] {"Version", "1.0"}, {"arg0Desc", "First Threshold Value"}, {"arg1Desc", "Second Threshold Value"} }; private static final String[] supportedModes = {"rendered"};

Fevereiro/2010

[Link]

103 /146

Novo Operador: segmenta3 Passo 3


private static final String[] paramNames = {"1st threshold", "2nd threshold"}; private static final Class[] paramClasses = {[Link], [Link]}; private static final Object[] paramDefaults = {new Integer(85), new Integer(170) }; private static final Range[] validParamValues = { new Range([Link], Integer.MIN_VALUE, Integer.MAX_VALUE), new Range([Link], Integer.MIN_VALUE, Integer.MAX_VALUE) }; private static final int numSources = 1; private static boolean registered = false;

Fevereiro/2010

[Link]

104 /146

Novo Operador: segmenta3


public Segmenta3Descriptor() { super(resources,supportedModes,numSources,paramNames, paramClasses,paramDefaults,validParamValues); }

Passo 3/4

public static void register() { if (!registered) { OperationRegistry op = [Link]().getOperationRegistry(); Segmenta3Descriptor desc = new Segmenta3Descriptor(); [Link](desc); Segmenta3RIF rif = new Segmenta3RIF(); [Link](op,opName,vendorName,rif); registered = true; } }

Fevereiro/2010

[Link]

105 /146

Novo Operador: segmenta3


public static void main(String[] args) { [Link](); PlanarImage imagem = [Link]("fileload", args[0]); ParameterBlock p = new ParameterBlock(); [Link](imagem); [Link](new Integer(120)); [Link](new Integer(200)); PlanarImage resultado = [Link]("segmenta3",p); JFrame frame = new JFrame("Imagem binarizada"); [Link](new DisplayTwoSynchronizedImages(imagem,resultado)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); }

Fevereiro/2010

[Link]

106 /146

Novo Operador: contapixels

Conta nmero de pixels com cor semelhante a um parmetro (com tolerncia). Classe que herda de StatisticsOpImage.

Contm construtor para inicializar atributos e vrios mtodos para acumular estatsticas.

public class ContaPixelsOpImage extends StatisticsOpImage { private Color target; private Float tolerance; private Long count;

Passo 1

public ContaPixelsOpImage(RenderedImage source, Color target,Float tolerance) { super(source,null,[Link](),[Link](),1,1); [Link] = target; [Link] = tolerance; count = null; }
Fevereiro/2010 [Link] 107 /146

Novo Operador: contapixels Passo 1


protected void accumulateStatistics(String name, Raster raster, Object stats) { if (count == null) count = new Long(0); int r,g,b; for(int l=0;l<[Link]();l++) for(int c=0;c<[Link]();c++) { int x = [Link]()+c; int y = [Link]()+l; r = [Link](x,y,0); g = [Link](x,y,1); b = [Link](x,y,2); float dist = ([Link]()-r)*([Link]()-r)+ ([Link]()-g)*([Link]()-g)+ ([Link]()-b)*([Link]()-b); if (dist<=tolerance*tolerance) count++; } }
Fevereiro/2010 [Link] 108 /146

Novo Operador: contapixels


protected Object createStatistics(String arg0) { if (count == null) count = new Long(0); return count; } protected String[] getStatisticsNames() { return new String[]{"count"}; } public Object getProperty(String name) { if (count == null) [Link](name); return count; }

Passo 1

Fevereiro/2010

[Link]

109 /146

Novo Operador: contapixels Passo 2


public class ContaPixelsRIF implements RenderedImageFactory { public RenderedImage create(ParameterBlock paramBlock, RenderingHints hints) { RenderedImage source = [Link](0); Color target = (Color)[Link](0); Float tolerance = (Float)[Link](1); return new ContaPixelsOpImage(source,target,tolerance); } }

Fevereiro/2010

[Link]

110 /146

Novo Operador: contapixels Passo 3


public class ContaPixelsDescriptor extends OperationDescriptorImpl { private static final String opName = "contapixels"; private static final String vendorName = "Hypothetical Image Processing Lab"; private static final String[][] attributes = { {"GlobalName", opName}, {"LocalName", opName}, {"Vendor", vendorName}, {"Description", "A simple RGB pixel counting operator"}, {"DocURL", "[Link] {"Version", "1.0"}, {"arg0Desc", "Target value (color used for similarity)"}, {"arg1Desc", "Tolerance value"}, }; private static final String[] modes = {"rendered"};

Fevereiro/2010

[Link]

111 /146

Novo Operador: contapixels Passo 3


private static final int numSources = 1; private static final String[] paramNames = {attributes[6][0], attributes[7][0]}; private static final Class[] paramClasses = {[Link], [Link]}; private static final Object[] paramDefaults = { new Color(0,0,0),new Float(0) }; private static boolean registered = false; public ContaPixelsDescriptor() { super(attributes,modes,numSources,paramNames, paramClasses,paramDefaults,null); }

Fevereiro/2010

[Link]

112 /146

Novo Operador: contapixels Passo 4


public static void register() { if (!registered) { OperationRegistry op = [Link]().getOperationRegistry(); ContaPixelsDescriptor desc = new ContaPixelsDescriptor(); [Link](desc); ContaPixelsRIF rif = new ContaPixelsRIF(); [Link](op,opName,vendorName,rif); registered = true; } }

Fevereiro/2010

[Link]

113 /146

Novo Operador: contapixels


public static void main(String[] args) { [Link](); PlanarImage input = [Link]("fileload", args[0]); int r = [Link](args[1]); int g = [Link](args[2]); int b = [Link](args[3]); float t = [Link](args[4]); Color color = new Color(r,g,b); ParameterBlock p = new ParameterBlock(); [Link](input); [Link](color); [Link](t); PlanarImage output = [Link]("contapixels",p); Long count = (Long)[Link]("count"); [Link]("Existem "+count+ " pixels com cores semelhantes a "+color); }

Fevereiro/2010

[Link]

114 /146

Extras: I/O

Fevereiro/2010

[Link]

115 /146

Que formatos so suportados?


public static void main(String[] args) { String[] iFormatos = [Link](); [Link]("Leitura: "); for(String f:iFormatos) { [Link](f+" "); } [Link]("\nGravao: "); String[] oFormatos = [Link](); for(String f:oFormatos) { [Link](f+" "); } [Link](); }
Leitura: image/jpeg image/png image/x-png image/[Link] image/gif image/bmp Gravao: image/png image/jpeg image/x-png image/[Link] image/bmp image/gif

Fevereiro/2010

[Link]

116 /146

Compactando Imagens

Forma mais simples: abrir imagem em formato menos compactado e salvar em formato mais compactado. Lembrar sempre que existe perda de informaes com JPEG e GIF! Mtodo mais inteligente: controlar a compactao.

Fevereiro/2010

[Link]

117 /146

Como compactar mais?


public static void main(String[] args) throws IOException { // Load the image (it is hard-coded here to make the code // simpler). String imageFile = "/tmp/[Link]"; BufferedImage i = [Link](new File(imageFile)); showImage("Original Image", i); // Show results with different compression ratio. compressAndShow(i, 0.5f); }

Veja mais em [Link] Fevereiro/2010 [Link] 118 /146

Como compactar mais?


public static void compressAndShow(BufferedImage image, float quality) throws IOException { // Get a ImageWriter for jpeg format. Iterator<ImageWriter> writers = [Link]("jpeg"); if (![Link]()) throw new IllegalStateException("No writers found"); ImageWriter writer = (ImageWriter) [Link](); // Create the ImageWriteParam to compress the image. ImageWriteParam param = [Link](); [Link](ImageWriteParam.MODE_EXPLICIT); [Link](quality); // The output will be a ByteArrayOutputStream (in memory) ByteArrayOutputStream bos = new ByteArrayOutputStream(32768); ImageOutputStream ios = [Link](bos); [Link](ios); [Link](null, new IIOImage(image, null, null), param); [Link](); // otherwise the buffer size will be zero! // From the ByteArrayOutputStream create a RenderedImage. ByteArrayInputStream in = new ByteArrayInputStream([Link]()); RenderedImage out = [Link](in); int size = [Link]().length; showImage("Compressed to " + quality + ": " + size + " bytes", out); } Veja mais em [Link] Fevereiro/2010 [Link] 119 /146

Como compactar mais?


private static void showImage(String title,RenderedImage image) { JFrame f = new JFrame(title); [Link]().add(new DisplayJAI(image)); [Link](); [Link](true); [Link](JFrame.EXIT_ON_CLOSE); }

Original

0.5

0.1

Veja mais em [Link] Fevereiro/2010 [Link] 120 /146

Extras: Pixels

Fevereiro/2010

[Link]

121 /146

Mini-aplicao: Converso RGB IHS


IHS: Intensity, Hue and Saturation. Cores representadas por:


Intensity: brilho percebido da cor, 0 a 100% (preto = 0%). Hue (croma): cor bruta, 0 a 359 graus (0 graus = vermelho). Saturation: intensidade da cor, 0 a 100% (branco = 100%).

Variantes: HSV, HSB, HSL, etc.

Fevereiro/2010

[Link]

122 /146

Mini-aplicao: Converso RGB IHS

Integrao de imagens de diferentes sensores

RGB IHS, substitui banda I por banda de maior resoluo, converte novamente IHS RGB RGB IHS, manipula brilho e contraste da banda I, converte novamente IHS RGB

Manipulao de contraste e brilho

Nosso exemplo: converte RGB IHS, substitui I e S por 100% constantes, reconverte para RGB.

Fevereiro/2010

[Link]

123 /146

Mini-aplicao: Converso RGB IHS


public class RGBtoIHS { public static void main(String[] args) { PlanarImage imagem = [Link]("fileload", args[0]); // Converte para o modelo de cores IHS. IHSColorSpace ihs = [Link](); ColorModel modeloIHS = new ComponentColorModel(ihs, new int []{8,8,8}, false,false, [Link], DataBuffer.TYPE_BYTE) ; ParameterBlock pb = new ParameterBlock(); [Link](imagem); [Link](modeloIHS); RenderedImage imagemIHS = [Link]("colorconvert", pb);

Fevereiro/2010

[Link]

124 /146

Mini-aplicao: Converso RGB IHS


// Extramos as bandas I, H e S. RenderedImage[] bandas = new RenderedImage[3]; for(int band=0;band<3;band++) { pb = new ParameterBlock(); [Link](imagemIHS); [Link](new int[]{band}); bandas[band] = [Link]("bandselect",pb); } // Criamos bandas constantes para as bandas I e S. pb = new ParameterBlock(); [Link]((float)[Link]()); [Link]((float)[Link]()); [Link](new Byte[]{(byte)255}); RenderedImage novaIntensidade = [Link]("constant",pb); pb = new ParameterBlock(); [Link]((float)[Link]()); [Link]((float)[Link]()); [Link](new Byte[]{(byte)255}); RenderedImage novaSaturao = [Link]("constant",pb);

Fevereiro/2010

[Link]

125 /146

Mini-aplicao: Converso RGB IHS


// Juntamos as bandas H e as I e S constantes. // Devemos passar um RenderingHint que indica que o modelo // de cor IHS ser usado. ImageLayout imageLayout = new ImageLayout(); [Link](modeloIHS); [Link]([Link]()); RenderingHints rendHints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT,imageLayout); pb = new ParameterBlock(); [Link](novaIntensidade); [Link](bandas[1]); [Link](novaSaturao); RenderedImage imagemIHSModificada = [Link]("bandmerge", pb, rendHints); // Convertemos de volta para RGB. pb = new ParameterBlock(); [Link](imagemIHSModificada); [Link]([Link]()); // Imagem original era em RGB! RenderedImage imagemFinal = [Link]("colorconvert", pb);

Fevereiro/2010

[Link]

126 /146

Mini-aplicao: Converso RGB IHS


JFrame frame = new JFrame("Modificao via IHS"); [Link](new DisplayTwoSynchronizedImages(imagem,imagemFinal)); [Link](); [Link](JFrame.EXIT_ON_CLOSE); [Link](true); } }

Fevereiro/2010

[Link]

127 /146

Extras: Display

Fevereiro/2010

[Link]

128 /146

Mini-aplicao: Visualizador com cone

Mostra imagens grandes com pequeno cone e pan.

public class DisplayThumbnail extends DisplayJAI implements MouseMotionListener,MouseListener { private PlanarImage originalImage; private float scale; private int imageXTiles,imageYTiles; private int imageTileWidth,imageTileHeight; private int imageWidth,imageHeight; private int visibleRegionWidth,visibleRegionHeight; private int thumbWidth,thumbHeight; // The size of the border around the thumbnail. private final int border = 10; // The scaled viewport (dimensions are scaled/translated by the border). private Rectangle2D scaledViewport; private Color viewportColor; // Colors to be used when the mouse is/isn't over the viewport. private static Color viewportOn = new Color(120,255,120); private static Color viewportOff = new Color(0,192,0); // Coordinates obtained when we click (press) the mouse button to start // dragging the viewport. private int lastX,lastY; // Those coordinates represent the region where we can safely drag the // viewport without "falling outside" the image boundaries. private int minValidX,minValidY,maxValidX,maxValidY;

Fevereiro/2010

[Link]

129 /146

Mini-aplicao: Visualizador com cone


public DisplayThumbnail(PlanarImage image,float scale, int width,int height) { [Link] = scale; originalImage = image; visibleRegionWidth = width; visibleRegionHeight = height; // Get some stuff about the image. imageXTiles = [Link](); imageYTiles = [Link](); imageTileWidth = [Link](); imageTileHeight = [Link](); imageWidth = [Link](); imageHeight = [Link](); // Must create a thumbnail image using that scale. ParameterBlock pb = new ParameterBlock(); [Link](image); [Link](scale); [Link](scale); [Link](0.0F); [Link](0.0F); [Link](new InterpolationNearest()); PlanarImage thumbnail = [Link]("scale", pb, null); // Let's get the width and height of the thumbnail. thumbWidth = [Link](); thumbHeight = [Link]();

Fevereiro/2010

[Link]

130 /146

Mini-aplicao: Visualizador com cone


// Now let's add a border. pb = new ParameterBlock(); [Link](thumbnail); [Link](new Integer(border)); [Link](new Integer(border)); [Link](new Integer(border)); [Link](new Integer(border)); [Link](new BorderExtenderConstant(new double[]{0,0,128})); thumbnail = [Link]("border",pb); // Shift the image to the original position pb = new ParameterBlock(); [Link](thumbnail); [Link](1.0f*border); [Link](1.0f*border); thumbnail = [Link]("translate",pb,null); // Use this thumbnail as the image for the DisplayJAI component. set(thumbnail); // We'd like to listen to mouse movements. addMouseMotionListener(this); addMouseListener(this); // Initially the scaled viewport will be positioned at border,border. scaledViewport = new [Link](border,border,width*scale,height*scale); // We assume that the mouse is off the viewport. viewportColor = viewportOff; }

Fevereiro/2010

[Link]

131 /146

Mini-aplicao: Visualizador com cone


public synchronized void paintComponent(Graphics g) { [Link](g); Graphics2D g2d = (Graphics2D)g; // Paint the tile grid. [Link]([Link]); [Link]([Link]( AlphaComposite.SRC_OVER,0.5f)); float x1,x2,y1,y2; // Vertical tiles' boundaries. x1 = x2 = border; y1 = border; y2 = border+thumbHeight; for(int tx=0;tx<=imageXTiles;tx++) { [Link]((int)x1,(int)y1,(int)x2,(int)y2); x1 += imageTileWidth*scale; x2 += imageTileWidth*scale; }

Fevereiro/2010

[Link]

132 /146

Mini-aplicao: Visualizador com cone


// Horizontal tiles' boundaries. x1 = border; x2 = border+thumbWidth; y1 = y2 = border; for(int ty=0;ty<=imageYTiles;ty++) { [Link]((int)x1,(int)y1,(int)x2,(int)y2); y1 += imageTileHeight*scale; y2 += imageTileHeight*scale; } // Paint a red border. [Link]([Link]); [Link](border,border,thumbWidth,thumbHeight); // Paint the viewport. [Link](viewportColor); [Link]([Link](AlphaComposite.SRC_OVER,1f)); Stroke stroke = new BasicStroke(2f); [Link](stroke); [Link](scaledViewport); }

Fevereiro/2010

[Link]

133 /146

Mini-aplicao: Visualizador com cone


public void mouseMoved(MouseEvent e) { int x = [Link](); int y = [Link](); // Ignore events outside the border. if ((x < border) || (y < border) || (x > border+thumbWidth) || (y > border+thumbHeight)) return; // Are we inside the viewport rectangle ? if ([Link](x,y)) viewportColor = viewportOn; else viewportColor = viewportOff; // Hopefully it will repaint only the needed section. Rectangle repaintBounds = new Rectangle((int)[Link]()-5, (int)[Link]()-5, (int)[Link]()+10, (int)[Link]()+10); repaint(repaintBounds); }

Fevereiro/2010

[Link]

134 /146

Mini-aplicao: Visualizador com cone


public void mousePressed(MouseEvent e) { // Store the new dragging starting points. lastX = [Link](); lastY = [Link](); // Calculate the new window w/ viewport movements. minValidX = lastX-(int)[Link]()+border; minValidY = lastY-(int)[Link]()+border; maxValidX = border+thumbWidth-(int)[Link]()+ (lastX-(int)[Link]()); maxValidY = border+thumbHeight-(int)[Link]()+ (lastY-(int)[Link]()); } public void mouseDragged(MouseEvent e) { int x = [Link](); int y = [Link](); if (x > maxValidX) x = maxValidX-1; if (x < minValidX) x = minValidX; if (y > maxValidY) y = maxValidY-1; if (y < minValidY) y = minValidY; if ((x >= minValidX) && (y >= minValidY) && (x <= maxValidX) && (y <= maxValidY)) { updateLocation(x, y); lastX = x; lastY = y; } } Fevereiro/2010 [Link] 135 /146

Mini-aplicao: Visualizador com cone


public void updateLocation(int x,int y) { // Store the approximate region where the viewport was before the change. Rectangle initBounds = new Rectangle((int)[Link]()-5, (int)[Link]()-5, (int)[Link]()+10, (int)[Link]()+10); // Recalculate new position for the viewport, based on mouse coordinates. double origX = [Link]()+x-lastX; double origY = [Link]()+y-lastY; // Reposition the viewport. [Link](origX,origY, [Link](),[Link]()); // Store the approximate region where the viewport is after the change. Rectangle finalBounds = new Rectangle((int)[Link]()-5, (int)[Link]()-5, (int)[Link]()+10, (int)[Link]()+10); // Repaint only that section. repaint([Link](initBounds)); }

Fevereiro/2010

[Link]

136 /146

Mini-aplicao: Visualizador com cone


public PlanarImage getImage() { // Get the boundaries in the original image coordinates. float fromX = (float)[Link](([Link]()-border)/scale); float fromY = (float)[Link](([Link]()-border)/scale); float width = (float)[Link]([Link]()/scale); float height = (float)[Link]([Link]()/scale); // Fix rounding errors to avoid exceptions on the crop. fromX = [Link](fromX,(imageWidth-visibleRegionWidth)); fromY = [Link](fromY,(imageHeight-visibleRegionHeight)); // Create a ParameterBlock with information for the cropping. ParameterBlock pb = new ParameterBlock(); [Link](originalImage); [Link](fromX); [Link](fromY); [Link](width); [Link](height); // Create the output image by cropping the input image. PlanarImage output = [Link]("crop",pb,null); // Translate the image origin. pb = new ParameterBlock(); [Link](output); [Link](-fromX); [Link](-fromY); // Create the output image by translating itself. return [Link]("translate",pb,null); }

Fevereiro/2010

[Link]

137 /146

Mini-aplicao: Visualizador com cone


public Rectangle getCroppedImageBounds() { int fromX = (int)[Link](([Link]()-border)/scale); int fromY = (int)[Link](([Link]()-border)/scale); int width = (int)[Link]([Link]()/scale); int height = (int)[Link]([Link]()/scale); return new Rectangle(fromX,fromY,width,height); } public Rectangle getViewportBounds() { Rectangle temp = [Link](); [Link]((int)[Link]()-border,(int)[Link]()-border, (int)[Link](),(int)[Link]()); return temp; }

Fevereiro/2010

[Link]

138 /146

Mini-aplicao: Visualizador com cone


public class DisplayThumbnailApp extends JFrame implements MouseMotionListener { private DisplayThumbnail dt; private DisplayJAI dj; private JLabel world,view; public DisplayThumbnailApp(PlanarImage image,int dWidth,int dHeight) { super("Interactive Thumbnail Example"); SpringLayout layout = new SpringLayout(); Container contentPane = getContentPane(); [Link](layout); dt = new DisplayThumbnail(image,0.05f,dWidth,dHeight); [Link](this); dj = new DisplayJAI([Link]()); [Link](new Dimension(dWidth,dHeight)); [Link](new Dimension(dWidth,dHeight)); [Link](new Dimension(dWidth,dHeight)); JPanel borderDisplay = new JPanel(new BorderLayout()); [Link](dj); [Link]([Link]([Link])); JLabel worldL = new JLabel("World: "); world = new JLabel(""); JLabel viewL = new JLabel("Thumb: "); view = new JLabel(""); [Link](dt); [Link](borderDisplay); [Link](worldL); [Link](world); [Link](viewL); [Link](view); (organizao do layout removida) setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); pack(); setVisible(true); }

Fevereiro/2010

[Link]

139 /146

Mini-aplicao: Visualizador com cone


public void mouseDragged(MouseEvent e) { [Link]([Link]()); // Gets some information about the viewport and cropped image. Rectangle crop = [Link](); Rectangle viewp = [Link](); // Change the labels' contents with this information. [Link](""+crop.x+","+crop.y+ " ("+[Link]+"x"+[Link]+")"); [Link](""+viewp.x+","+viewp.y+ " ("+[Link]+"x"+[Link]+")"); } public void mouseMoved(MouseEvent e) { } public static void main(String[] args) { PlanarImage image = [Link]("fileload", args[0]); new DisplayThumbnailApp(image,640,640); }

Fevereiro/2010

[Link]

140 /146

Mini-aplicao: Visualizador com cone

Fevereiro/2010

[Link]

141 /146

Outros Tpicos

Fevereiro/2010

[Link]

142 /146

Tpicos para Pesquisa e Desenvolvimento

Processamento por pixels x processamento por regies


Imagens de alta resoluo Novos algoritmos de classificao Modelagem de conhecimento Modelos de mistura Inteligncia artificial

[Link]

Fevereiro/2010

[Link]

143 /146

Para saber mais...

[Link] [Link] Introductory Digital Image Processing: A Remote Sensing Perspective (John R. Jensen) Digital Image Processing Algorithms and Applications (Ioannis Pitas) Digital Image Processing (Rafael C. Gonzalez, Richard E. Woods)

Fevereiro/2010

[Link]

144 /146

Para saber mais...


Fundamentals of Digital Image Processing (Anil K. Jain) Classification Methods for Remotely Sensed Data (Brandt Tso, Paul M. Mather) Pattern Recognition and Image Analysis (Earl Gose, Richard Johnsonbaugh, Steve Jost)

Fevereiro/2010

[Link]

145 /146

Para saber mais...

Fuzzy Algorithms: With Applications to Image Processing and Pattern Recognition (Zheru Chi, H. Yan, Z.R. Chi, Hong Yan, Tuan Pham) The Pocket Handbook of Image Processing Algorithms In C (Harley R. Myler, Arthur R. Weeks) Intelligence: The Eye, the Brain, and the Computer (Martin A. Fischler, Oscar Firschein)

Fevereiro/2010

[Link]

146 /146

Você também pode gostar