Processamento de Imagem Digital utilizando software...

50
UNIVERSIDADE DO PORTO FACULDADE DE CIÊNCIAS DA UNIVERSIDADE DO PORTO FACULDADE DE ENGENHARIA DA UNIVERSIDADE DO PORTO Processamento de Imagem Digital utilizando software VTK José Miguel Mesquita Teixeira 21 de Abril de 2005

Transcript of Processamento de Imagem Digital utilizando software...

UNIVERSIDADE DO PORTO

FACULDADE DE CIÊNCIAS DA UNIVERSIDADE DO PORTO

FACULDADE DE ENGENHARIA DA UNIVERSIDADE DO PORTO

Processamento de Imagem Digital utilizando software VTK

José Miguel Mesquita Teixeira

21 de Abril de 2005

2

Conteúdo

1 Introdução 51.1 Objectivo do trabalho . . . . . . . . . . . . . . . . . . . . . . . . 51.2 O que é o processamento de imagem digital? . . . . . . . . . . . 51.3 Qual a sua origem? . . . . . . . . . . . . . . . . . . . . . . . . . . 51.4 Exemplo de áreas que utilizam o processamento de imagem digital 6

2 Tratamento e processamento de imagem 72.1 Operações aritméticas . . . . . . . . . . . . . . . . . . . . . . . . 7

2.1.1 Subtracção e adição de imagens . . . . . . . . . . . . . . . 72.1.2 Multiplicação e divisão de imagens . . . . . . . . . . . . . 9

2.2 Operações de �ltragem . . . . . . . . . . . . . . . . . . . . . . . . 102.2.1 Filtros espaciais de suavização . . . . . . . . . . . . . . . 102.2.2 Sharpening spatial �lters . . . . . . . . . . . . . . . . . . 11

2.3 Thresholding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3 Programa VTK image 2005 153.1 Descrição sumária do programa e resultados . . . . . . . . . . . . 153.2 Listagem do programa . . . . . . . . . . . . . . . . . . . . . . . . 18

3

4 CONTEÚDO

Capítulo 1

Introdução

1.1 Objectivo do trabalho

Pretendeu-se com este trabalho desenvolver um programa em Visual-Tool-Kit(VTK) que permitisse realizar algumas operações de processamento e trata-mento de imagem, nomeadamente operações algébricas e de filtragem essenciaisem diversas áreas científicas, em particular na área de imagiologia magnética(visualização de domínios magnéticos), de que faço parte como investigador.

Pretendo num futuro próximo dar continuidade ao programa desenvolvido,explorando outras funcionalidades disponíveis pelo VTK para processamento deimagem, que se revelam importantes na área da imagiologia magnética.

1.2 O que é o processamento de imagem digital?

Uma imagem pode ser definida como uma função bidimensional, f(x,y), ondex e y são coordenadas espaciais e a amplitude de f em qualquer ponto (x,y)a intensidade ou o nível de cinzento da imagem nesse ponto. Quando x, ye os valores da amplitude de f são quantidades discretas, a imagem é umaimagem digital. A área do processamento de imagem digital, diz respeito aoprocessamento de imagens através de um computador digital. Uma imagemdigital é em geral composta por um número finito de elementos, cada um dosquais tem uma localização e um valor de intensidade particular. Esses elementossão vulgarmente conhecidos como pixeis.

1.3 Qual a sua origem?

Umas das primeiras aplicações de imagens digitais foi na industria dos jornais,quando enviaram pela primeira vez imagens através de um cabo submarino, queligava Londres a Nova York. O desenvolvimento de sistema de transmissão deimagens através de um cabo submarino ("Bartlane cable") em 1920, reduziu o

5

6 CAPÍTULO 1. INTRODUÇÃO

tempo necessário para transportar uma imagem através do Atlântico de maisde uma semana a menos de 3 horas. Um equipamento de impressão especial-izado servia de emissor e receptor, codificando as imagens para o sistema detransmissão por cabo e depois descodificando-as quando chegavam ao destino.

No início o sistema "Bartlane"permitia codificar imagens em 5 níveis distin-tos de cinzento, tendo aumentado para 15 níveis em 1929. Embora o processocitado envolva imagens digitais, estas não podem ser consideradas como re-sultado de um processamento de imagem digital, de acordo com a definiçãomencionada anteriormente, já que os computadores ainda não tinham sido in-ventados e por conseguinte não estiveram envolvidos na construção das imagens.Assim, a história do processamento de imagem digital está intimamente ligadoao desenvolvimento do computador digital, dado que este tipo de imagens requerníveis consideráveis de armazenamento e poder computacional.

Os primeiros computadores capazes de realizar tarefas significativas de pro-cessamento de imagem, surgiram no início da década 60 inseridos num projectoda NASA. Em paralelo com as aplicações em programas espaciais, as técni-cas de processamento de imagem digital começaram também a ser utilizadasno final da década de 60 e princípio da década de 70 na imagiologia médica eastronomia. A invenção no início da década de 70 da tomografia axial com-putorizada (TAC), é um dos acontecimentos mais importantes na aplicação doprocessamento de imagem no diagnóstico médico. Desde 1960 até aos nossosdias, a área do processamento de imagem e as suas diversas aplicações cresceramvertiginosamente.

1.4 Exemplo de áreas que utilizam o processa-mento de imagem digital

Para além de aplicações na medicina e em programas espaciais, as técnicas deprocessamento de imagem digital são agora utilizadas em variadíssimas áreas,tais como: na interpretação de imagens de raios-X ou outro tipo de imagens,através do aumento de contraste ou codificar os seus níveis de intensidade emcor; os geógrafos utilizam as mesmas técnicas ou análogas para estudar padrõesde poluição a partir de imagens aéreas e de satélite; na arqueologia para con-seguir recuperar com sucesso imagens ou figuras esbatidas de artefactos raros;na física e áreas relacionadas, permitindo melhorar a qualidade das imagens re-sultantes de experiências em áreas, tais como a microscopia electrónica, micro-scopia de força atómica e imagiologia magneto-óptica; na astronomia, biologia,força aérea, marinha e exército.

Capítulo 2

Tratamento e processamentode imagem

2.1 Operações aritméticasAs operações de processamento de imagem discutidas nesta secção utilizamduas ou mais imagens para produzir uma nova imagem. Estas operações sãonormalmente designadas como operações aritméticas, uma vez que operadorescomo a adição, subtracção, divisão e multiplicação estão envolvidos no processo.Essas operações são realizadas pixel a pixel, de tal forma que, por exemplo, aadição de duas imagens simplesmente contém pixeis cujo os níveis de intensidade(brilho) são a soma dos níveis de intensidade dos pixeis de cada uma das imagens.

2.1.1 Subtracção e adição de imagensDas quatro operações aritméticas acima mencionadas, a subtracção e a adição(nesta ordem) são as mais utilizadas no tratamento e processamento de imagens.A diferença entre duas imagens f(x, y) e h(x, y), expressa como

g(x, y) = f(x, y)− h(x, y), (2.1)é obtida realizando a subtracção entre todos os pares de pixeis correspondentesde f e h. Nesta operação o intervalo de valores possíveis para os níveis deintensidade da imagem subtraída, cujo o intervalo inicial é de 0-255 (8 bits) paraas imagens iniciais, é de -255 a +255. Isto excede a capacidade de memória daimagem. Uma das possibilidades é simplesmente somar 255 a todos os pixeis edepois dividir por 2. Este método é simples de implementar mas tem as suaslimitações. Por exemplo a totalidade dos níveis de intensidade pode não seraproveitada e a truncagem inerente à divisão por dois irá em geral originarperdas de precisão. Outra possibilidade mais precisa e que cubra a totalidadedo intervalo de 8 bits, é realizar o seguinte conjunto de operações em cada pixelda imagem subtraída (sub)

7

8 CAPÍTULO 2. TRATAMENTO E PROCESSAMENTO DE IMAGEM

Figura 2.1: Ilustração da diferença entre duas imagens a partir da operação desubtracção. (a) Imagem inicial. (b) Imagem após o movimento de uma moeda.(c) Imagem diferença após subtracção pixel a pixel.

Novovalorpixel = intervalo× sub−min

max−min, (2.2)

onde o intervalo representa a capacidade de memória da imagem (nº bits) tipi-camente 255 para imagens de 8 bits; max e min de�nem o valor do pixel máximoe mínimo associado à imagem subtraída. É evidente que esta possibilidade éconsideravelmente mais complexa e difícil de implementar.

A primeira possibilidade pode ser realizada através do programa desen-volvido (VTK image 2005), pretendendo implementar num futuro próximo asegunda possibilidade. Uma terceira possibilidade já implementada no pro-grama e que evita efectuar os cálculos anteriores, é a realização em módulo dadiferença entre duas imagens.

A operação de subtracção é particularmente importante pois permite re-mover todos os componentes estáticos de uma imagem enquanto realça aquelesque se alteram ao longo do tempo. A Fig.2.1 ilustra esta situação. Esta car-acterística é particularmente importante na área de investigação a que estouligado, pois trata-se da visualização de domínios magnéticos que se alteram aolongo do tempo devido à presença de um campo magnético variável.

A adição de duas imagens f(x, y) e h(x, y), representada pela eq.2.3 é obtidarealizando a adição entre todos os pares de pixeis correspondentes de f e h. Seduas imagens de 8-bits (com valores de intensidade entre 0-255 em cada pixel)são adicionadas, o intervalo de níveis de cinzento estará entre 0-510. Mais umavez isto excede a capacidade de memória da imagem. Uma das possibilidades ésimplesmente dividir o resultado por dois, obtendo uma imagem correctamenteescalonada entre 0-255, ou utilizar a 2ª possibilidade (eq.2.2) descrita acimapara a subtracção.

g(x, y) = f(x, y) + h(x, y). (2.3)

A operação de adição é particularmente útil quando pretendemos fazer mé-dias sobre imagens para eliminar ruído. Considere-se por exemplo uma imagemcom ruído g(x, y), que analíticamente pode ser de�nida como

g(x, y) = f(x, y) + η(x, y), (2.4)

2.1. OPERAÇÕES ARITMÉTICAS 9

Figura 2.2: Multiplicação de duas imagens para sobrepor textura. (a) Globo.(b) Padrão de níveis de cinzento. (c) Produto de a por b.

onde f(x, y) representa a imagem sem o ruído η(x, y). Supondo que para todosos pontos de imagem de coordenadas (x,y) o ruído não está correlacionado etem valor médio nulo, a imagem g(x, y) formada pela média de K imagens comruído diferente,

g(x, y) =1K

K∑

i=1

gi(x, y), (2.5)

tem um valor esperado que é simplesmente f(x, y), ou seja:

E{g(x, y)} = f(x, y). (2.6)

Uma vez que E{g(x, y)} = f(x, y), isto signi�ca que g(x, y) aproxima-se def(x, y) à medida que o número de imagens com ruído utilizadas na média au-menta. Assim, a operação de adição revela-se importante na eliminação destetipo de ruído, encontrando-se disponível no programa desenvolvido.

2.1.2 Multiplicação e divisão de imagensA multiplicação é talvez das operações menos utilizadas no tratamento e pro-cessamento de imagens, mas foi incluída no programa para completar as outrasoperações aritméticas. Analíticamente a multiplicação de duas imagens podeser de�nida de acordo com a eq.2.7. Como exemplo de utilização desta oper-ação considere-se as imagens ilustradas na Fig.2.2. De acordo com esta �gura,a multiplicação da imagem (a) pela imagem (b) permite sobrepor o padrão decinzentos da imagem (b) à esfera da imagem (a), resultando assim uma imagemcom textura.

g(x, y) = f(x, y)× h(x, y). (2.7)

Uma das di�culdades associadas à multiplicação é o elevado intervalo deníveis de cinzento que pode ser gerado. Por exemplo em imagens de 8-bits amultiplicação de duas imagens origina uma imagem �nal cujos pixeis podem terum intervalo de valores compreendido entre 0-65000. Deste modo, a imagem re-sultante apresenta uma informação de 2-bytes (16 bits). Para poder armazenar

10 CAPÍTULO 2. TRATAMENTO E PROCESSAMENTO DE IMAGEM

essa informação numa imagem de 8-bits é necessário recorrer novamente a op-erações de rescalonamento, com todos os inconvenientes associados.

A operação de divisão também cria problemas quanto ao nível de intensidadedos pixeis que estão envolvidos na divisão. Em termos analíticos podemos defini-la como

g(x, y) =f(x, y)h(x, y)

, (2.8)

onde cada pixel de coordenadas (x,y) da imagem f é dividido pelos pixeis decoordenadas (x,y) correspondentes da imagem h. Portanto a divisão por zerodeve ser evitada, adicionando 1 a todos os valores de intensidade, de tal modoque imagens de 8-bits são interpretadas como tendo níveis de inatensidade com-preendidos entre 1-256 em vez de 0-255. Em seguida, é necessário multiplicarcada pixel do numerador por um factor que produza quocientes no intervalo0-255.

2.2 Operações de filtragemAs operações de processamento de imagem discutidas até ao momento en-volveram pelo menos duas imagens. Nesta secção irão ser abordadas operaçõesque actuam numa dada imagem. Estas operações trabalham com os valores dospixeis na vizinhança de um dado pixel. O conceito de filtragem tem a sua origemna utilização da transformada de Fourier no processamento de sinal no domíniodas frequências. Nesta secção, discute-se apenas operações de filtragem que sãorealizadas directamente nos pixeis de uma imagem. O termo filtragem espacialé utilizado para diferenciar este tipo de processo da tradicional filtragem nodomínio das frequências.

O processo de filtragem espacial consiste simplesmente em movimentar ofiltro de ponto para ponto na imagem. Em cada ponto (x,y), a resposta do filtroé calculada utilizando uma relação pré-definida.

2.2.1 Filtros espaciais de suavizaçãoUm dos filtros de suavização muito utilizado no tratamento e processamentode imagem é o filtro gaussiano. Este filtro quando aplicado a uma imagemprovoca um esbatimento nesta, conhecido na literatura inglesa como "bluring",sendo o grau desse esbatimento parametrizado pelo desvio padrão σ da funçãogaussiana. Quanto maior for σ maior será a vizinhança influenciada pelo filtroGaussiano. A matriz de filtragem tem valores bidimensionais, que são obtidosatravés da normalização dos valores dados pela função Gaussiana

G(x, y) = exp(− (x− u)2 + (y − v)2

2σ2), (2.9)

em que (x,y) representa cada pixel da matriz e (u,v) diz respeito ao centro damatriz.

2.2. OPERAÇÕES DE FILTRAGEM 11

Figura 2.3: (a) Imagem de raio-X de um circuito electrónico integrado cor-rompido por ruído sal e pimenta. (b) Redução de ruído através de um filtromediana de dimensão 3x3.

Outro tipo de filtro espacial, cuja a resposta é baseada no ordenamento dospixeis contidos na área da imagem envolvida pelo filtro, substituem o valor dopixel central pelo valor resultante da operação de ordenamento. O exemplomais conhecido nesta categoria é o filtro mediana, o qual, como o próprio nomeindica, substitui o valor da intensidade de um pixel pela mediana dos níveis decinzento na vizinhança desse pixel. Os filtros mediana são bastante conhecidosuma vez que para certos tipos de ruído aletório, fornecem excelentes capacidadesde redução desse ruído, com muito menos esbatimento ("bluring") do que o filtrogaussiano. Os filtros mediana são particularmente eficazes na presença de ruídosal e pimenta, assim designado devido à sua aparência (pontos brancos e pretossobrepostos à imagem). A Fig.2.3 ilustra uma imagem de raio-x de um circuitoelectrónico integrado com ruído sal e pimenta.

2.2.2 Sharpening spatial filters

O principal objectivo dos "Sharpening spatial filters"é realçar finos detalhesnuma imagem ou evidenciar detalhes que foram esbatidos, por exemplo, numaoperação de suavização. Estes filtros são baseados em operações de diferenci-ação de 1ª e 2ª ordem, respectivamente. As derivadas de uma função digital sãodefinidas em termos de diferenças finitas, existindo várias formas de as definir.Contudo, é necessário que independentemente da definição usada, a 1ª derivadadeverá ser zero em zonas de níveis de intensidade constante e diferente de zero emregiões que apresentem degraus ou rampas. Analogamente, qualquer definiçãode 2ª derivada deverá ser nula em áreas de intensidade constante ou que apre-sentem rampas de declive constante e não nula no ínicio e no final de um degrauou rampa. Uma vez que se lida com quantidades discretas (digitalizadas) cujosos valores são finitos, a máxima alteração possível de níveis de cinzento numaimagem também é finita, e a menor distância sobre a qual essa alteração podeocorrer é entre pixeis adjacentes. Na Fig.2.4 é ilustrada o efeito da diferenciação(1ª e 2ª ordem) para um perfil horizontal de níveis de cinzento localizado ao

12 CAPÍTULO 2. TRATAMENTO E PROCESSAMENTO DE IMAGEM

Figura 2.4: (a) Uma simples imagem. (b) Perfil horizontal de níveis de cinzentolocalizado ao longo do centro de uma imagem. (c) Perfil simplificado (os pontossão unidos por linhas a tracejado para simplificar a interpretação).

longo do centro de uma imagem.De acordo com a Fig.2.4 observa-se que a 1ª derivada é diferente de zero

ao longo de toda a rampa, enquanto a 2ª derivada não é nula apenas no ínicioe no final da rampa. Como os extremos de uma imagem relembram este tipode transição, concluí-se que as derivadas de 2ª ordem conseguem definir commais detalhe as fronteiras de uma imagem do que as derivadas de 1ª ordem.Em seguida, verifica-se que a resposta no ponto de ruído isolado e entorno desteé muito mais forte para a 2ª derivada do que para a 1ª, pois a 2ª derivada émuito mais agressiva do que a 1ª no realçe de alterações súbitas. Assim, é deesperar que a 2ª derivada realçe muito mais os detalhes finos (incluindo ruído)do que a 1ª derivada. A linha estreita surge na imagem como um detalhe fino eportanto o mesmo tipo de diferenças entre a 2ª e a 1ª derivadas são observadas.Por último, neste caso, a resposta das duas derivadas é a mesma no ínicio dodegrau e diferente no final.

Em suma, comparando as respostas entre a 1ª e a 2ª derivadas, chega-se àconclusão que a 2ª tem uma resposta muito mais forte a detalhes finos, tais comolinhas estreitas e pontos isolados, do que a 1ª derivada. É precisamente essacaracterística exibida pela 2ª derivada que é importante na área da imagiologiamagnética, quando pretendemos realçar as fronteiras entre domínios magnéticos.Por essa razão, foi implementado no programa o filtro Laplaciano, que como opróprio nome indica é definido pelo operador Laplaciano (∇2). Deste modo,

2.3. THRESHOLDING 13

para uma imagem bidimensional f(x, y) o operador é definido pela seguinteequação:

∇2f(x, y) =∂2f

∂x2+

∂2f

∂y2, (2.10)

A implementação digital deste operador em imagens bidimensionais é assimexpressa da seguinte forma:

∇2f(x, y) = [f(x+1, y)+f(x−1, y)+f(x, y+1)+f(x, y−1)]−4f(x, y). (2.11)

É precisamente baseado nesta equação que o filtro é construído.

2.3 ThresholdingA selecção de determinados aspectos de uma imagem é um importante pré-requesito na compreensão dessa imagem. Tradicionalmente, uma forma simplesde esta selecção ser realizada é definir um intervalo de valores de intensidade naimagem inicial, escolher os pixeis pertencentes a este intervalo como pertencendoao 1º plano, e rejeitar todos os outros pixeis para 2º plano. Constroi-se assimuma imagem binária com dois níveis de cinzento, utilizando a cor preta e brancaoutras cores para distinguir as duas regiões. Esta operação é conhecida como"thresholding".

14 CAPÍTULO 2. TRATAMENTO E PROCESSAMENTO DE IMAGEM

Capítulo 3

Programa VTK image 2005

3.1 Descrição sumária do programa e resultados

O programa desenvolvido (VTK image 2005) utiliza algumas funcionalidadesdisponíveis pelo VTK para processamento de imagem, nomeadamente operaçõesalgébricas e de filtragem. De entre as operações algébricas (subtracção, adição,divisão e multiplicação) destaco a subtracção como a mais relevante para oestudo que desenvolvo recentemente como investigador. A operação de adiçãotambém pode vir a revelar-se de extrema importância na eliminação de ruídonão correlacionado e de valor médio nulo, que eventualmente possa surgir nasimagens. Na Fig.3.1, são ilustradas três imagens de 8-bits cada de domíniosmagnéticos numa amostra de CoFe de espessura 200 Å, que se encontra sob acçãode um campo magnético variável ao longo do tempo. As duas primeiras sãoobtidas directamente por uma câmara CCD em instantes de tempo diferentes,enquanto que a terceira resulta da subtracção das duas primeiras.

A operação de subtracção permite realçar de forma clara a presença dosdomínios magnéticos (regiões claras e escuras), contrariamente às imagens obti-das por observação directa, onde é extremamente difícil ver a presença destasestruturas magnéticas.

Das três operações de filtragem disponíveis no programa (filtros gaussiano,mediana e laplaciano) foram aplicados à imagem (c) da Fig.3.1 os filtros gaus-siano e mediana. Os resultados obtidos são ilustrados na Fig.3.2.

A Fig.3.2a mostra uma sequência de imagens obtidas através da aplicação dofiltro de Gauss para vários valores do desvio padrão (σ). Em todas as imagenso raio foi mantido constante e igual à unidade. De acordo com a Fig.3.2a,verifica-se a presença de esbatimento para os valores de σ superiores. Por outrolado, a sequência de imagens ilustradas na Fig.3.2b, onde foi aplicado o filtromediana para várias dimensões da janela (1x1; 3x3; 5x5 e 10x10), mostra queas fronteiras ou contornos dos domínios magnéticos (regiões de transição claro-escuro) são preservadas à medida que a dimensão da janela aumenta.

Como exemplo de aplicação da operação de "threshold", considere-se as ima-

15

16 CAPÍTULO 3. PROGRAMA VTK IMAGE 2005

Figura 3.1: (a) e (b) Imagem de domínios magnéticos adquiridos directamentepor uma câmara CCD em instantes de tempo diferentes. (c) Subtracção daimagem (a) pela imagem (b).

Figura 3.2: (a) Sequência de imagens obtidas após a aplicação de um filtrogaussiano de raio unitário e desvio padrão (σ) de 1.0, 3.0, 5.0 e 10.0. (b)Sequência de imagens obtidas após a aplicação de um filtro mediana de dimensão1x1, 3x3, 5x5 e 10x10.

3.1. DESCRIÇÃO SUMÁRIA DO PROGRAMA E RESULTADOS 17

Figura 3.3: (a) Imagem inicial. (b) Imagem �nal após a aplicação da operaçãode "threshold by lower".

gens de domínios de 8-bits, representadas na Fig.3.3. Nesta situação foi aplicadauma operação de "threshold by lower"em torno do nível 128.0 de intensidade.O resultado obtido é ilustrado na Fig.3.3. Veri�ca-se uma inversão dos níveis decinzento das imagens, o que signi�ca que esta operação atribui-o zero à regiãoacima do nível 128 e um abaixo desse valor.

3.2. LISTAGEM DO PROGRAMA 18

// VTK Image 2005 realized by José Miguel Mesquita Teixeira - FCUP/FEUP - 21/4/2005 // includes #include <iostream.h> #include <stdlib.h> #include "vtkBMPReader.h" #include "vtkBMPWriter.h" #include "vtkImageActor.h" #include "vtkImageMathematics.h" #include "vtkImageThreshold.h" #include "vtkImageGaussianSmooth.h" #include "vtkImageMedian3D.h" #include "vtkImageLaplacian.h" #include "vtkRenderer.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowinteractor.h" /* Standard error macro for reporting API errors */ #define PERR(bSuccess, api){if(!(bSuccess)) printf("%s:Error %d from %s \ on line %d\n", __FILE__, GetLastError(), api, __LINE__);} void cls( HANDLE hConsole ) { COORD coordScreen = { 0, 0 }; /* here's where we'll home the cursor */ BOOL bSuccess; DWORD cCharsWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ DWORD dwConSize; /* number of character cells in the current buffer */ /* get the number of character cells in the current buffer */ bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi ); PERR( bSuccess, "GetConsoleScreenBufferInfo" ); dwConSize = csbi.dwSize.X * csbi.dwSize.Y; /* fill the entire screen with blanks */ bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten ); PERR( bSuccess, "FillConsoleOutputCharacter" ); /* get the current text attribute */ bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi ); PERR( bSuccess, "ConsoleScreenBufferInfo" ); /* now set the buffer's attributes accordingly */

3.2. LISTAGEM DO PROGRAMA

19

bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten ); PERR( bSuccess, "FillConsoleOutputAttribute" ); /* put the cursor at (0, 0) */ bSuccess = SetConsoleCursorPosition( hConsole, coordScreen ); PERR( bSuccess, "SetConsoleCursorPosition" ); return; } int Menu(); int Menu2(); int Menu3(); int Menu() { cout << endl; cout << "\t This program was realized by: Jose Miguel Mesquita Teixeira" << endl; cout << endl; cout << "\t******************************************************" << endl; cout << "\t* *" << endl; cout << "\t* Scientific Visualization *" << endl; cout << "\t* *" << endl; cout << "\t* Program Name: VTK Image 2005 *" << endl; cout << "\t* *" << endl; cout << "\t* 1. Unary Operation (operation on a single image) *" << endl; cout << "\t* *" << endl; cout << "\t* 2. Binary Operation (operation on two images) *" << endl; cout << "\t* *" << endl; cout << "\t* 3. Exit *" << endl; cout << "\t* *" << endl; cout << "\t******************************************************" << endl; return 0; } int Menu2() { cout << endl; cout << endl; cout << "\t********************************************************" << endl; cout << "\t* *" << endl; cout << "\t* 1. Add a constant intensity to the image *" << endl; cout << "\t* *" << endl; cout << "\t* 2. Multiply an image by a constant *" << endl; cout << "\t* *" << endl; cout << "\t* 3. Threshold operation *" << endl; cout << "\t* *" << endl; cout << "\t* 4. Gaussian Filter operation *" << endl; cout << "\t* *" << endl; cout << "\t* 5. Median Filter operation *" << endl; cout << "\t* *" << endl;

3.2. LISTAGEM DO PROGRAMA 20

cout << "\t* 6. Laplacian Filter operation *" << endl; cout << "\t* *" << endl; cout << "\t* 7. Exit *" << endl; cout << "\t* *" << endl; cout << "\t********************************************************" << endl; return 0; } int Menu3() { cout << endl; cout << endl; cout << "\t********************************************************" << endl; cout << "\t* *" << endl; cout << "\t* 1. Image Subtraction *" << endl; cout << "\t* *" << endl; cout << "\t* 2. Image Absolute Subtraction *" << endl; cout << "\t* *" << endl; cout << "\t* 3. Image Addition *" << endl; cout << "\t* *" << endl; cout << "\t* 4. Image Division *" << endl; cout << "\t* *" << endl; cout << "\t* 5. Image Multiplication *" << endl; cout << "\t* *" << endl; cout << "\t* 6. Exit *" << endl; cout << "\t* *" << endl; cout << "\t********************************************************" << endl; return 0; } // main function int main() { char op[2]; char StringVariable1[51], StringVariable2[51], StringVariable3[51], StringVariable4[51], StringVariable5[51]; double constant, threshold_value, sigma, radius; int window_dimension; do { cls(GetStdHandle(STD_OUTPUT_HANDLE)); // clear screen // Menu(); printf("\n\t Option => "); gets(op); if (op[0] == '1') { do { cls(GetStdHandle(STD_OUTPUT_HANDLE)); // clear screen //

3.2. LISTAGEM DO PROGRAMA

21

Menu2(); printf("\n\t Option => "); gets(op); if (op[0] == '1') { // print input and output filenames printf("\n\t Insert filename for the input image => "); gets(StringVariable1); printf("\n\t Insert filename for the output image => "); gets(StringVariable2); // read input bmp image vtkBMPReader *imgInReader = vtkBMPReader::New(); imgInReader->SetFileName(StringVariable1); // build input image actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader->GetOutput()); // Add a constant to the input image vtkImageMathematics *outImg = vtkImageMathematics::New(); outImg->SetInput1((vtkImageData *) imgInReader->GetOutput()); printf("\n\t Insert the constant value (0-255) => "); scanf("%lf",&constant); outImg->SetConstantC(constant); outImg->SetOperationToAddConstant(); // build output image actor vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(outImg->GetOutput()); // Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(outImg->GetOutput());

3.2. LISTAGEM DO PROGRAMA 22

bmpoutImg->SetFileName(StringVariable2); bmpoutImg->Write(); // build renderer for input image actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderwindow and set window size for input image actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build interactor window for input image vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for output image vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // start render renWin1->Render(); renWin2->Render(); interactor->Start(); // delete build objects imgInReader->Delete();

3.2. LISTAGEM DO PROGRAMA

23

imgActor->Delete(); outImg->Delete(); imgActor2->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); renWin1->Delete(); renWin2->Delete(); interactor->Delete(); interactor2->Delete(); } else if (op[0] == '2') { // print input and output filenames printf("\n\t Insert filename for the input image => "); gets(StringVariable1); printf("\n\t Insert filename for the output image => "); gets(StringVariable2); // read input bmp image vtkBMPReader *imgInReader = vtkBMPReader::New(); imgInReader->SetFileName(StringVariable1); // build input image actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader->GetOutput()); // Multiply the input image by a constant vtkImageMathematics *outImg = vtkImageMathematics::New(); outImg->SetInput1((vtkImageData *) imgInReader->GetOutput()); printf("\n\t Insert the constant value (0-255) => "); scanf("%lf",&constant); outImg->SetConstantK(constant); outImg->SetOperationToMultiplyByK(); // build output image actor vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(outImg->GetOutput());

3.2. LISTAGEM DO PROGRAMA 24

// Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(outImg->GetOutput()); bmpoutImg->SetFileName(StringVariable2); bmpoutImg->Write(); // build renderer for input image actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderwindow and set window size for input image actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build interactor window for input image vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for output image vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // start render

3.2. LISTAGEM DO PROGRAMA

25

renWin1->Render(); renWin2->Render(); interactor->Start(); // delete build objects imgInReader->Delete(); imgActor->Delete(); outImg->Delete(); imgActor2->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); renWin1->Delete(); renWin2->Delete(); interactor->Delete(); interactor2->Delete(); } else if (op[0] == '3') { // print input and output filenames printf("\n\t Insert filename for the input image => "); gets(StringVariable1); printf("\n\t Insert filename for the output image => "); gets(StringVariable2); // read input bmp image vtkBMPReader *imgInReader = vtkBMPReader::New(); imgInReader->SetFileName(StringVariable1); // build input image actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader->GetOutput()); // compute Threshold vtkImageThreshold *imgThres = vtkImageThreshold::New(); imgThres->SetInput(imgInReader->GetOutput()); imgThres->ReplaceInOn(); imgThres->SetInValue(0); imgThres->SetOutValue(255); printf("\n\t Insert the threshold value (0-255) => "); scanf("%lf",&threshold_value);

3.2. LISTAGEM DO PROGRAMA 26

imgThres->ThresholdByLower(threshold_value); // build output image actor vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(imgThres->GetOutput()); // Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(imgThres->GetOutput()); bmpoutImg->SetFileName(StringVariable2); bmpoutImg->Write(); // build renderer for input image actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderwindow and set window size for input image actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build interactor window for input image vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New();

3.2. LISTAGEM DO PROGRAMA

27

interactor->SetRenderWindow(renWin1); // build interactor window for output image vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // start render renWin1->Render(); renWin2->Render(); interactor->Start(); // delete build objects imgInReader->Delete(); imgActor->Delete(); imgThres->Delete(); imgActor2->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); renWin1->Delete(); renWin2->Delete(); interactor->Delete(); interactor2->Delete(); } else if (op[0] == '4') { // print input and output filenames printf("\n\t Insert filename for the input image => "); gets(StringVariable1); printf("\n\t Insert filename for the output image => "); gets(StringVariable2); // read input bmp image vtkBMPReader *imgInReader = vtkBMPReader::New(); imgInReader->SetFileName(StringVariable1); // build input image actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader->GetOutput()); // compute Gaussian smooth

3.2. LISTAGEM DO PROGRAMA 28

vtkImageGaussianSmooth *imgGauss = vtkImageGaussianSmooth::New(); imgGauss->SetInput(imgInReader->GetOutput()); printf("\n\n\t Set the standard deviation in pixel units => "); scanf("%lf",&sigma); imgGauss->SetStandardDeviations(sigma,sigma,sigma); printf("\n\n\t Set the radium in pixel units => "); scanf("%lf",&radius); imgGauss->SetRadiusFactors(radius, radius, radius); // build output image actor vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(imgGauss->GetOutput()); // Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(imgGauss->GetOutput()); bmpoutImg->SetFileName(StringVariable2); bmpoutImg->Write(); // build renderer for input image actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderwindow and set window size for input image actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300);

3.2. LISTAGEM DO PROGRAMA

29

// build renderwindow and set window size for output image actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build interactor window for input image vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for output image vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // start render renWin1->Render(); renWin2->Render(); interactor->Start(); // delete build objects imgInReader->Delete(); imgActor->Delete(); imgGauss->Delete(); imgActor2->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); renWin1->Delete(); renWin2->Delete(); interactor->Delete(); interactor2->Delete(); } else if (op[0] == '5') { // print input and output filenames printf("\n\t Insert filename for the input image => "); gets(StringVariable1); printf("\n\t Insert filename for the output image => "); gets(StringVariable2); // read input bmp image

3.2. LISTAGEM DO PROGRAMA 30

vtkBMPReader *imgInReader = vtkBMPReader::New(); imgInReader->SetFileName(StringVariable1); // build input image actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader->GetOutput()); // compute Median smooth // vtkImageMedian3D *imgMedian = vtkImageMedian3D::New(); imgMedian->SetInput(imgInReader->GetOutput()); printf("\n\n\t Set the window dimension of the median filter => "); scanf("%d",&window_dimension); imgMedian->SetKernelSize(window_dimension, window_dimension, window_dimension); // build output image actor vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(imgMedian->GetOutput()); // Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(imgMedian->GetOutput()); bmpoutImg->SetFileName(StringVariable2); bmpoutImg->Write(); // build renderer for input image actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1);

3.2. LISTAGEM DO PROGRAMA

31

// build renderwindow and set window size for input image actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build interactor window for input image vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for output image vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // start render renWin1->Render(); renWin2->Render(); interactor->Start(); // delete build objects imgInReader->Delete(); imgActor->Delete(); imgMedian->Delete(); imgActor2->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); renWin1->Delete(); renWin2->Delete(); interactor->Delete(); interactor2->Delete(); } else if (op[0] == '6') { // print input and output filenames printf("\n\t Insert filename for the input image => ");

3.2. LISTAGEM DO PROGRAMA 32

gets(StringVariable1); printf("\n\t Insert filename for the output image => "); gets(StringVariable2); // read input bmp image vtkBMPReader *imgInReader = vtkBMPReader::New(); imgInReader->SetFileName(StringVariable1); // build input image actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader->GetOutput()); // compute Laplacian sharpening // vtkImageLaplacian *imgLaplacian = vtkImageLaplacian::New(); imgLaplacian->SetInput(imgInReader->GetOutput()); imgLaplacian->SetDimensionality(2); // build output image actor vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(imgLaplacian->GetOutput()); // Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(imgLaplacian->GetOutput()); bmpoutImg->SetFileName(StringVariable2); bmpoutImg->Write(); // build renderer for input image actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white

3.2. LISTAGEM DO PROGRAMA

33

vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderwindow and set window size for input image actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build interactor window for input image vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for output image vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // start render renWin1->Render(); renWin2->Render(); interactor->Start(); // delete build objects imgInReader->Delete(); imgActor->Delete(); imgLaplacian->Delete(); imgActor2->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); renWin1->Delete(); renWin2->Delete(); interactor->Delete(); interactor2->Delete(); } } while (op[0] != '7');

3.2. LISTAGEM DO PROGRAMA 34

if (op[0] == '7') exit(-1); /* end if */ } else if (op[0] == '2') { do { cls(GetStdHandle(STD_OUTPUT_HANDLE)); // clear screen // Menu3(); printf("\n\t Option => "); gets(op); if (op[0] == '1') { // print the two input and output filenames printf("\n\t Insert filename for the input image1 => "); gets(StringVariable3); printf("\n\t Insert filename for the input image2 => "); gets(StringVariable4); printf("\n\n\t Insert filename for the output image => "); gets(StringVariable5); // read input bmp image1 vtkBMPReader *imgInReader1 = vtkBMPReader::New(); imgInReader1->SetFileName(StringVariable3); // read input bmp image2 vtkBMPReader *imgInReader2 = vtkBMPReader::New(); imgInReader2->SetFileName(StringVariable4); // build input image1 actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader1->GetOutput()); // build input image2 actor

3.2. LISTAGEM DO PROGRAMA

35

vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(imgInReader2->GetOutput()); // compute subtraction between two images vtkImageMathematics *imgSubtraction = vtkImageMathematics::New(); imgSubtraction->SetInput1((vtkImageData *) imgInReader1->GetOutput()); imgSubtraction->SetInput2((vtkImageData *) imgInReader2->GetOutput()); imgSubtraction->SetOperationToSubtract(); // build output image actor vtkImageActor *imgActor3 = vtkImageActor::New(); imgActor3->SetInput(imgSubtraction->GetOutput()); // Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(imgSubtraction->GetOutput()); bmpoutImg->SetFileName(StringVariable5); bmpoutImg->Write(); // build renderer for input image1 actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for input image2 actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white vtkRenderer *ren3= vtkRenderer::New(); ren3->AddActor(imgActor3); ren3->SetBackground(1, 1, 1);

3.2. LISTAGEM DO PROGRAMA 36

// build renderwindow and set window size for input image1 actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300); // build renderwindow and set window size for input image2 actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin3 = vtkRenderWindow::New(); renWin3->AddRenderer(ren3); renWin3->SetSize(300, 300); // build interactor window for input image1 vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for input image2 vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // build interactor window for output image vtkRenderWindowInteractor *interactor3 = vtkRenderWindowInteractor::New(); interactor3->SetRenderWindow(renWin3); // start render renWin1->Render(); renWin2->Render(); renWin3->Render(); interactor->Start(); // delete build objects imgInReader1->Delete(); imgInReader2->Delete(); imgActor->Delete();

3.2. LISTAGEM DO PROGRAMA

37

imgActor2->Delete(); imgSubtraction->Delete(); imgActor3->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); ren3->Delete(); renWin1->Delete(); renWin2->Delete(); renWin3->Delete(); interactor->Delete(); interactor2->Delete(); interactor3->Delete(); } else if (op[0] == '2') { // print the two input and output filenames printf("\n\t Insert filename for the input image1 => "); gets(StringVariable3); printf("\n\t Insert filename for the input image2 => "); gets(StringVariable4); printf("\n\n\t Insert filename for the output image => "); gets(StringVariable5); // read input bmp image1 vtkBMPReader *imgInReader1 = vtkBMPReader::New(); imgInReader1->SetFileName(StringVariable3); // read input bmp image2 vtkBMPReader *imgInReader2 = vtkBMPReader::New(); imgInReader2->SetFileName(StringVariable4); // build input image1 actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader1->GetOutput()); // build input image2 actor vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(imgInReader2->GetOutput());

3.2. LISTAGEM DO PROGRAMA 38

// compute subtraction between two images vtkImageMathematics *imgSubtraction = vtkImageMathematics::New(); imgSubtraction->SetInput1((vtkImageData *) imgInReader1->GetOutput()); imgSubtraction->SetInput2((vtkImageData *) imgInReader2->GetOutput()); imgSubtraction->SetOperationToSubtract(); // compute absolute subtraction between two images vtkImageMathematics *imgAbsoluteSubtraction = vtkImageMathematics::New(); imgAbsoluteSubtraction->SetInput1((vtkImageData *) imgSubtraction->GetOutput()); imgAbsoluteSubtraction->SetOperationToAbsoluteValue(); // build output image actor vtkImageActor *imgActor3 = vtkImageActor::New(); imgActor3->SetInput(imgAbsoluteSubtraction->GetOutput()); // Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(imgAbsoluteSubtraction->GetOutput()); bmpoutImg->SetFileName(StringVariable5); bmpoutImg->Write(); // build renderer for input image1 actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for input image2 actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white

3.2. LISTAGEM DO PROGRAMA

39

vtkRenderer *ren3= vtkRenderer::New(); ren3->AddActor(imgActor3); ren3->SetBackground(1, 1, 1); // build renderwindow and set window size for input image1 actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300); // build renderwindow and set window size for input image2 actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin3 = vtkRenderWindow::New(); renWin3->AddRenderer(ren3); renWin3->SetSize(300, 300); // build interactor window for input image1 vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for input image2 vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // build interactor window for output image vtkRenderWindowInteractor *interactor3 = vtkRenderWindowInteractor::New(); interactor3->SetRenderWindow(renWin3); // start render renWin1->Render(); renWin2->Render(); renWin3->Render(); interactor->Start(); // delete build objects

3.2. LISTAGEM DO PROGRAMA 40

imgInReader1->Delete(); imgInReader2->Delete(); imgActor->Delete(); imgActor2->Delete(); imgSubtraction->Delete(); imgAbsoluteSubtraction->Delete(); imgActor3->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); ren3->Delete(); renWin1->Delete(); renWin2->Delete(); renWin3->Delete(); interactor->Delete(); interactor2->Delete(); interactor3->Delete(); } else if (op[0] == '3') { // print the two input and output filenames printf("\n\t Insert filename for the input image1 => "); gets(StringVariable3); printf("\n\t Insert filename for the input image2 => "); gets(StringVariable4); printf("\n\n\t Insert filename for the output image => "); gets(StringVariable5); // read input bmp image1 vtkBMPReader *imgInReader1 = vtkBMPReader::New(); imgInReader1->SetFileName(StringVariable3); // read input bmp image2 vtkBMPReader *imgInReader2 = vtkBMPReader::New(); imgInReader2->SetFileName(StringVariable4); // build input image1 actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader1->GetOutput()); // build input image2 actor

3.2. LISTAGEM DO PROGRAMA

41

vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(imgInReader2->GetOutput()); // compute Addition between two images vtkImageMathematics *imgAddition = vtkImageMathematics::New(); imgAddition->SetInput1((vtkImageData *) imgInReader1->GetOutput()); imgAddition->SetInput2((vtkImageData *) imgInReader2->GetOutput()); imgAddition->SetOperationToAdd(); // build output image actor vtkImageActor *imgActor3 = vtkImageActor::New(); imgActor3->SetInput(imgAddition->GetOutput()); // Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(imgAddition->GetOutput()); bmpoutImg->SetFileName(StringVariable5); bmpoutImg->Write(); // build renderer for input image1 actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for input image2 actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white vtkRenderer *ren3= vtkRenderer::New(); ren3->AddActor(imgActor3); ren3->SetBackground(1, 1, 1);

3.2. LISTAGEM DO PROGRAMA 42

// build renderwindow and set window size for input image1 actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300); // build renderwindow and set window size for input image2 actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin3 = vtkRenderWindow::New(); renWin3->AddRenderer(ren3); renWin3->SetSize(300, 300); // build interactor window for input image1 vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for input image2 vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // build interactor window for output image vtkRenderWindowInteractor *interactor3 = vtkRenderWindowInteractor::New(); interactor3->SetRenderWindow(renWin3); // start render renWin1->Render(); renWin2->Render(); renWin3->Render(); interactor->Start(); // delete build objects imgInReader1->Delete(); imgInReader2->Delete(); imgActor->Delete(); imgActor2->Delete();

3.2. LISTAGEM DO PROGRAMA

43

imgAddition->Delete(); imgActor3->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); ren3->Delete(); renWin1->Delete(); renWin2->Delete(); renWin3->Delete(); interactor->Delete(); interactor2->Delete(); interactor3->Delete(); } else if (op[0] == '4') { // print the two input and output filenames printf("\n\t Insert filename for the input image1 => "); gets(StringVariable3); printf("\n\t Insert filename for the input image2 => "); gets(StringVariable4); printf("\n\n\t Insert filename for the output image => "); gets(StringVariable5); // read input bmp image1 vtkBMPReader *imgInReader1 = vtkBMPReader::New(); imgInReader1->SetFileName(StringVariable3); // read input bmp image2 vtkBMPReader *imgInReader2 = vtkBMPReader::New(); imgInReader2->SetFileName(StringVariable4); // build input image1 actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader1->GetOutput()); // build input image2 actor vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(imgInReader2->GetOutput());

3.2. LISTAGEM DO PROGRAMA 44

// compute division between two images vtkImageMathematics *imgDivision = vtkImageMathematics::New(); imgDivision->SetInput1((vtkImageData *) imgInReader1->GetOutput()); imgDivision->SetInput2((vtkImageData *) imgInReader2->GetOutput()); imgDivision->SetOperationToDivide(); // build output image actor vtkImageActor *imgActor3 = vtkImageActor::New(); imgActor3->SetInput(imgDivision->GetOutput()); // Write the output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(imgDivision->GetOutput()); bmpoutImg->SetFileName(StringVariable5); bmpoutImg->Write(); // build renderer for input image1 actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for input image2 actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white vtkRenderer *ren3= vtkRenderer::New(); ren3->AddActor(imgActor3); ren3->SetBackground(1, 1, 1); // build renderwindow and set window size for input image1 actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1);

3.2. LISTAGEM DO PROGRAMA

45

renWin1->SetSize(300, 300); // build renderwindow and set window size for input image2 actor vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin3 = vtkRenderWindow::New(); renWin3->AddRenderer(ren3); renWin3->SetSize(300, 300); // build interactor window for input image1 vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for input image2 vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // build interactor window for output image vtkRenderWindowInteractor *interactor3 = vtkRenderWindowInteractor::New(); interactor3->SetRenderWindow(renWin3); // start render renWin1->Render(); renWin2->Render(); renWin3->Render(); interactor->Start(); // delete build objects imgInReader1->Delete(); imgInReader2->Delete(); imgActor->Delete(); imgActor2->Delete(); imgDivision->Delete(); imgActor3->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); ren3->Delete();

3.2. LISTAGEM DO PROGRAMA 46

renWin1->Delete(); renWin2->Delete(); renWin3->Delete(); interactor->Delete(); interactor2->Delete(); interactor3->Delete(); } else if (op[0] == '5') { // print the two input and output filenames printf("\n\t Insert filename for the input image1 => "); gets(StringVariable3); printf("\n\t Insert filename for the input image2 => "); gets(StringVariable4); printf("\n\n\t Insert filename for the output image => "); gets(StringVariable5); // read input bmp image1 vtkBMPReader *imgInReader1 = vtkBMPReader::New(); imgInReader1->SetFileName(StringVariable3); // read input bmp image2 vtkBMPReader *imgInReader2 = vtkBMPReader::New(); imgInReader2->SetFileName(StringVariable4); // build input image1 actor vtkImageActor *imgActor = vtkImageActor::New(); imgActor->SetInput(imgInReader1->GetOutput()); // build input image2 actor vtkImageActor *imgActor2 = vtkImageActor::New(); imgActor2->SetInput(imgInReader2->GetOutput()); // compute multiplication between two images vtkImageMathematics *imgMultiplication = vtkImageMathematics::New(); imgMultiplication->SetInput1((vtkImageData *) imgInReader1->GetOutput());

3.2. LISTAGEM DO PROGRAMA

47

imgMultiplication->SetInput2((vtkImageData *) imgInReader2->GetOutput()); imgMultiplication->SetOperationToMultiply(); // build output image actor vtkImageActor *imgActor3 = vtkImageActor::New(); imgActor3->SetInput(imgMultiplication->GetOutput()); // make output image vtkBMPWriter *bmpoutImg = vtkBMPWriter::New(); bmpoutImg->SetInput(imgMultiplication->GetOutput()); bmpoutImg->SetFileName(StringVariable3); bmpoutImg->Write(); // build renderer for input image1 actor and set background to white vtkRenderer *ren1= vtkRenderer::New(); ren1->AddActor(imgActor); ren1->SetBackground(1, 1, 1); // build renderer for input image2 actor and set background to white vtkRenderer *ren2= vtkRenderer::New(); ren2->AddActor(imgActor2); ren2->SetBackground(1, 1, 1); // build renderer for output image actor and set background to white vtkRenderer *ren3= vtkRenderer::New(); ren3->AddActor(imgActor3); ren3->SetBackground(1, 1, 1); // build renderwindow and set window size for input image1 actor vtkRenderWindow *renWin1 = vtkRenderWindow::New(); renWin1->AddRenderer(ren1); renWin1->SetSize(300, 300); // build renderwindow and set window size for input image2 actor

3.2. LISTAGEM DO PROGRAMA 48

vtkRenderWindow *renWin2 = vtkRenderWindow::New(); renWin2->AddRenderer(ren2); renWin2->SetSize(300, 300); // build renderwindow and set window size for output image actor vtkRenderWindow *renWin3 = vtkRenderWindow::New(); renWin3->AddRenderer(ren3); renWin3->SetSize(300, 300); // build interactor window for input image1 vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New(); interactor->SetRenderWindow(renWin1); // build interactor window for input image2 vtkRenderWindowInteractor *interactor2 = vtkRenderWindowInteractor::New(); interactor2->SetRenderWindow(renWin2); // build interactor window for output image vtkRenderWindowInteractor *interactor3 = vtkRenderWindowInteractor::New(); interactor3->SetRenderWindow(renWin3); // start render renWin1->Render(); renWin2->Render(); renWin3->Render(); interactor->Start(); // delete build objects imgInReader1->Delete(); imgInReader2->Delete(); imgActor->Delete(); imgActor2->Delete(); imgMultiplication->Delete(); imgActor3->Delete(); bmpoutImg->Delete(); ren1->Delete(); ren2->Delete(); ren3->Delete(); renWin1->Delete(); renWin2->Delete(); renWin3->Delete(); interactor->Delete(); interactor2->Delete();

3.2. LISTAGEM DO PROGRAMA

49

interactor3->Delete(); } } while (op[0] != '6'); if (op[0] == '6') exit(-1); /* end if */ } } while (op[0] != '3'); if (op[0] == '3') exit(-1); /* end if */ return 0; }

Bibliogra�a

[1] Rafael C. Gonzalez, Richard E. Woods; Digital Image Processing 2th ed ;Prentice-Hall, Inc. New Jersey (2002).

[2] John C. Russ; The Image Processing Handbook 4th ed ; CRC Press LLC,Florida (2002).

[3] William K. Pratt; Digital Image Processing ; Wiley-Interscience publication,New York (1978).

[4] João Manuel R. S. Tavares, Jorge Gomes Barbosa; Apontamentos teóricos dacadeira de Visualização Cientí�ca do Mestrado de Métodos Computacionaisem Ciências e Engenharia; Faculdade de Engenharia da Universidade doPorto (2003/2004).

19