Rotação e Interpolação
Resumo Os pixels que compõem uma imagem digital possuem coordenadas com valores do tipo inteiro e positivo. Quando alguma operação em cima das coordenadas de um pixel de uma imagem é realizada, o valor nem sempre é inteiro. Por exemplo, a operação de divisão pode trazer um valor do tipo real. Então, qual coordenada escolher? O objetivo deste artigo é apresentar alguns métodos para resolver esse problema, chamado de interpolação. 1- Introdução - Rotação de Imagem Suponha que você possua uma imagem centrada e deseja rotacioná-la de 45 graus para a esquerda. Os sistemas que transformam as coordenadas, supondo-se o centro de coordenadas no centro da tela são os seguintes: x ' =x CentroX y ' =CentroY y (1), x ' =x cos θ y sen θ y ' = x sen θ y cos θ (2) e x ' =x CentroX y ' =CentroY y (3) Onde o primeiro sistema transporta as coordenadas da imagem para o centro da tela e inverte o sentido do eixo y. O segundo aplica a rotação na imagem e o terceiro retoma o sistema de coordenadas original. A figura 1 mostra uma figura, onde o centro da imagem se localiza em 152,104. Figura 1 - Imagem e seu respectivo centro de coordenada.
Quando há transformação entre sistemas de coordenadas, deve-se partir da imagem de destino e procurar o pixel na imagem de origem, justamente o contrário do que muitos imaginam. Isto se deve ao fato de que, ao percorrermos o loop x,y na imagem original, nem sempre garantimos que todos os pontos da imagem destino serão preenchidos. O resultado são vários pontos vazios na imagem e podem ser observados na imagem 2. Do contrário, ao percorremos o loop na imagem destino, todos os pontos são visitados e é garantida alguma cor para eles. Para partir da imagem destino, é necessário inverter o sinal do ângulo theta. O resultado pode ser observado na imagem 3. Figura 2 - Imagem rotacionada a partir da imagem original. Figura 3 - Imagem rotacionada a partir da imagem destino. Pode-se observar, de acordo com a equação 2, que o resultado da conta é um número real e este número é propagado no restante do sistema. A questão é: caso as novas coordenadas sejam calculadas, por exemplo 15,78; 102,056, qual será o valor de x e de y? Deve-se truncar os valores? Arredondar? Tirar uma média ponderada das cores dos vizinhos? Esse é o assunto abordado nas seções seguintes.
2- Vizinho mais próximo (nearest neighbor) A interpolação por vizinho mais próximo assume a cor do pixel onde é feito o arredondamento das coordenadas, cujos valores são reais. No exemplo citado anteriormente, as coordenadas de 15,78; 102,056 seriam: arredonde(15,78) = 16 arredonde(102,056) = 102 Ou seja a coordenada assumida seria 16,102. Esta interpolação é a mais simples de se implementar, porém traz efeitos negativos no resultado como o efeito de escadinhas nos pixels. O resultado desta interpolação pode ser observado na figura 3. 3- Interpolação Bilinear A interpolação bilinear faz uma média ponderada dos quatro pixels vizinhos da região onde o resultado aparece. O valor da intensidade do pixel é calculado: f x, y = f 0,0 1 x 1 y f 1,0 x 1 y f 0,1 1 x y f 1,1 x y (4) Para cada vizinho, é considerado o inverso da distância, uma vez que quanto menor a distância, mais aquele pixel contribui para a formação da cor final do ponto. Para melhor exemplificar esta interpolação, supõe-se que um pixel caia na posição (150,4; 200,3). Os quatro vizinhos são os seguintes: P 1 (150,200), P 2 (151,200), P 3 (150,201) e P 4 (151,201). Normalizando-se, tem-se os valores P 1 (0, 0), P 2 (1, 0), P 3 (0, 1), P 4 (1, 1) e P(0,4; 0,3). A figura 4 apresenta o ponto entre os pixels e a figura 5 as respectivas intensidades dos pixels vizinhos a P. Figura 4 Localização do Pixel. Figura 5 Intensidades dos vizinhos. Aplicando-se a fórmula 4, tem-se: f(x,y) = 192*(1-0.4)*(1-0.3)+46*0.4*(1-0.3)+95*(1-0.4)*0.3+255*0.4*0.3 f(x,y) = 141.2200 f(x,y) = arredonda(141.2200)
f(x,y) = 141 Como o pixel tem intensidade com o valor inteiro, arredonda-se o valor encontrado. 4- Comparação dos resultados As figuras 6 e 7 apresentam uma comparação entre os resultados da interpolação por vizinho mais próximo e bilinear, respectivamente. Figura 6 - Interpolação Vizinho mais Próximo. Figura 7- Interpolação Bilinear Observa-se que o resultado da interpolação bilinear é melhor que o do vizinho mais próximo, porém o custo computacional é maior, problema este acentuado em computadores de 8 bits e um clock de 3 MHz. Outro problema para a interpolação bilinear, para o MSX, é a questão da média ponderada de cores. Somente a screen 8 poderia fazê-lo com sucesso, uma vez que a screen 12 apresenta um sistema complexo de cores e as demais telas possuem apenas 16 cores tabeladas. 5- Fontes para testes em Matlab Código para interpolação por vizinho mais próximo: % Rotation % Marcelo Teixeira Silveira br=imread('flag.bmp'); [a b c]=size(br); br2 = zeros(a,b,c); br2=uint8(br2); theta = -0.78539816339744830961566084581988; % 45 degrees centerx=153;
centery=105; for x=1 : b for y=1 : a % From screen system to center system % Center coordinate system cx = x-centerx; cy = centery-y; % Rotate nx = cx*cos(theta)-cy*sin(theta); ny = cx*sin(theta)+cy*cos(theta); % Nearest neighbor nx=ceil(nx); ny=ceil(ny); % Return old system cx=nx+centerx; cy=centery-ny; if (cx>0) if (cy>0) if (cx<=b) if (cy<=a) br2(y,x,:) = br(cy,cx,:); ; ; figure(1); subplot(1,2,1); imshow(br); subplot(1,2,2); imshow(br2); Código fonte para a interpolação bilinear: % Rotation % Marcelo Teixeira Silveira br=imread('flag.bmp'); [a b c]=size(br); br2 = zeros(a,b,c); br2=uint8(br2); theta = -0.78539816339744830961566084581988; % 45 degrees centerx=153;
centery=105; for x=1 : b for y=1 : a % From screen system to center system % Center coordinate system cx = x-centerx; cy = centery-y; % Rotate nx = cx*cos(theta)-cy*sin(theta); ny = cx*sin(theta)+cy*cos(theta); % Return old system cx=nx+centerx; cy=centery-ny; % Pick up neighbors coordinates origin and float value of % coordinate Pox = floor(cx); Poy = floor(cy); xn = cx-floor(cx); yn = cy-floor(cy); if (cx>1) if (cy>1) if (cx<b) if (cy<a) % Bilinear br2(y,x,1) = ceil(br(poy,pox,1)*(1- xn)*(1-yn)+br(poy,pox+1,1)*xn*(1-yn)+br(poy+1,pox,1)*(1- xn)*yn+br(poy+1,pox+1,1)*xn*yn); br2(y,x,2) = ceil(br(poy,pox,2)*(1- xn)*(1-yn)+br(poy,pox+1,2)*xn*(1-yn)+br(poy+1,pox,2)*(1- xn)*yn+br(poy+1,pox+1,2)*xn*yn); br2(y,x,3) = ceil(br(poy,pox,3)*(1- xn)*(1-yn)+br(poy,pox+1,3)*xn*(1-yn)+br(poy+1,pox,3)*(1- xn)*yn+br(poy+1,pox+1,3)*xn*yn); ; ; figure(1); subplot(1,2,1); imshow(br); subplot(1,2,2); imshow(br2);
6- Créditos e referências Este artigo foi escrito por Marcelo Teixeira Silveira, formado em Engenharia de Sistemas e Computação pela UERJ e atual desenvolverdor do projeto E-FOTO. Site: http://www.eng.uerj.br/~marcelo/msx E-mail: flamar98@hotmail.com Referências: Wikipédia em inglês: http://en.wikipedia.org - Artigo sobre interpolação bilinear - Artigo sobre rotação Projeto E-FOTO: http://www.efoto.eng.uerj.br - E-BOOK