1.4 – Translação e rotação de imagem

A edição básica de uma imagem envolve constantemente o deslocamento da imagem (translação), sua rotação ou redimensionamento. Nesse sentido, esse tutorial mostrará como utilizar esses recursos utilizando a OpenCV.

Para acompanhar esse tutorial, recomendo que seja baixada a imagem a seguir, que é a imagem considerada na explicação.

openCVPythonFigura 1. Imagem base do tutorial

O código para carregar e mostrar a imagem é mostrado a seguir. Foi importando o Numpy pois este será utilizado posteriormente. Também é possível ver a forma da imagem (240 x 220 e 3 canais). Como da forma da imagem apenas a largura e altura serão necessárias, na linha 6 foi capturado apenas esses dados e armazenado nas variáveis com o respectivo nome da propriedade (lembrando que na OpenCV, a ordem das propriedades é primeiro a altura e depois a largura).

import numpy as np
import cv2

imagem = cv2.imread("openCVPython.png")
print imagem.shape
altura, largura = imagem.shape[:2]
cv2.imshow("Original", imagem)

cv2.waitKey(0)

Translação (deslocamento)

A translação de uma imagem é realizada utilizando o método da OpenCV chamado warpAffine(). Esse método espera o objeto de imagem que será transladado (primeiro parâmetro informado na linha 3 do código abaixo), uma matriz de deslocamento (segundo parâmetro) e as dimensões da imagem (terceiro parâmetro sendo passado como um array).

A matrix de deslocamento está sendo estabelecida indicando na primeira linha o deslocamento no eixo “x” e na segunda linha o deslocamento a ser aplicado no eixo “y”.

Para o deslocamento deve ser fornecida uma matriz com valores de ponto flutuante, com feito na linha 11. As duas primeira colunas não devem ser alteradas, sendo a última coluna a de interesse para especificar o deslocamento. O valor na primeira linha é o deslocamento no eixo “x”, fazendo com que seja deslocado horizontalmente a quantidade de pixels informada. Já o valor na segunda linha especifica o deslocamento no eixo “y”, fazendo o deslocamento vertical.

Na primeira translação do código abaixo, o deslocamento aplicado foi de 25 pixels para direita. Para deslocar para esquerda é preciso fornecer um valor negativo, como feito na segunda translação. A imagem também foi transladada para baixo 50 pixels e um valor negativo faria um deslocamento para cima.

#translacao (deslocamento)
deslocamento = np.float32([[1, 0, 25], [0, 1, 50]])
deslocado = cv2.warpAffine(imagem, deslocamento, (largura, altura))
cv2.imshow("Baixo e direita", deslocado)

cv2.waitKey(0)

deslocamento = np.float32([[1, 0, -50], [0, 1, -90]])
deslocado = cv2.warpAffine(imagem, deslocamento, (largura, altura))
cv2.imshow("Cima e esquerda", deslocado)

cv2.waitKey(0)

A imagem a seguir (esquerda) ilustra o resultado da aplicação do primeiro deslocamento da figura, onde a figura foi transladada mais para a direita e para baixo de sua posição inicial. Com a aplicação da segunda matriz de deslocamento, a imagem foi deslocada mais para cima e esquerda (imagem da direita).

baixo_direita cima_esquerda

Figura 2. Imagem transladada para direita e para baixo (a) e figura transladada para esquerda e para cima (b)

Se na terceira coluna da primeira linha for fornecido o valor zero, apenas um deslocamento vertical será aplicado a figura, enquanto um valor zero na terceira coluna da segunda linha realizará apenas o deslocamento horizontal.

Rotação da imagem

A rotação de imagem exige um pouco mais do que a translação, sendo preciso fornecer um ponto de fixação para rotacionar a partir desse ponto.

A linha 23 no código mostrado abaixo é responsável por definir esse ponto de fixação, fixando no centro da figura, sendo esse o ponto normalmente utilizado nos rotacionamentos.

Na linha 24 é a definição da rotação que será aplicada. No código foi definido o ponto de fixação especificado na linha anterior, o ângulo de 45 graus e o terceiro parâmetro é a escala, que será mantida com o valor 1 para não alterar o tamanho da imagem.

A seguir, na linha 25, usamos novamente a função warpAffine() da OpenCV que receberá como segundo parâmetro o objeto com a especificação de rotação e aplicará a rotação na imagem e que pode ser visualizada na imagem a esquerda da Figura 3.

#rotacao
ponto = (largura / 2, altura / 2) #ponto no centro da figura
rotacao = cv2.getRotationMatrix2D(ponto, 45, 1.0)
rotacionado = cv2.warpAffine(imagem, rotacao, (largura, altura))
cv2.imshow("Rotacionado 45 graus", rotacionado)

cv2.waitKey(0)

rotacao = cv2.getRotationMatrix2D(ponto, 120, 1.0)
rotacionado = cv2.warpAffine(imagem, rotacao, (largura, altura))
cv2.imshow("Rotacionado 120 graus", rotacionado)

cv2.waitKey(0)

Na linha 30 do código foi alterado objeto de rotação aplicando o ângulo de 120 graus. O resultado dessa nova rotação é mostrado na imagem da direita da Figura 3.

rotacao_45graus rotacao_120graus

Figura 3. Imagem rotacionada 45 graus (a) e figura rotacionada 120 graus (b)

Para entender melhor como funcionam os ângulos para rotação, veja a Figura 4 abaixo. O ângulo zero é uma orientação que significa para a direita e é a rotação “padrão” que a imagem se encontra. Se for fornecido um ângulo de 180 graus a imagem será rotacionada no sentido anti-horário até ficar de cabeça para baixo. Como na primeira imagem foi especificado um ângulo de 45 graus, isso fez a imagem ficar inclinada para cima.

250px-Polar_graph_paper.svgFigura 4. Ângulos nas coordenadas polares
Fonte: 
http://es.wikipedia.org/wiki/Coordenadas_polares

O código a seguir também faz uma rotação da imagem em 45 graus, mas modifica o ponto de fixação posicionando-o no cando inferior esquerdo. A Figura mostra a diferença entre o ponto de fixação no centro (imagem da esquerda) e seu novo ponto (imagem da direita).

ponto = (0, altura)
rotacao = cv2.getRotationMatrix2D(ponto, 45, 1.0)
rotacionado = cv2.warpAffine(imagem, rotacao, (largura, altura))
cv2.imshow("45 graus com ponto embaixo", rotacionado)

cv2.waitKey(0)

Figura 5. Figura rotacionada 45 graus a partir do seu centro (a) e figura rotacionada 45 graus a partir de seu ponto inferior esquerdo (b)

Para completar, voltamos o ponto para o centro da imagem e dessa vez alteramos o terceiro parâmetro informado para o método getRotationMatrix2D(). O valor informado foi 0.5 que significa que a imagem ficará com metade do tamanho que tinha antes. Essa proporção pode ser reduzida (como foi feito) ou aumentada. Um valor 1.5 aumentaria o tamanho da imagem em 50%, enquanto um valor 2 faria a imagem ficar com o dobro do seu tamanho. A Figura 6 mostra o resultado dessa nova especificação.

ponto = (largura / 2, altura / 2) #o ponto esta no centro
rotacao = cv2.getRotationMatrix2D(ponto, 45, 0.5)
rotacionado = cv2.warpAffine(imagem, rotacao, (largura, altura))
cv2.imshow("45 graus redimensionado", rotacionado)

cv2.waitKey(0)

Figura 6. Figura rotacionada 45 graus e redimensionada para metade do tamanho

Em diversos momentos existe a necessidade de inverter a imagem, fazendo um efeito de espelhamento. Se for aplicado um ângulo de 180 graus isso inverterá a imagem, mas também deixará a imagem de cabeça para baixo. O espelhamento de uma imagem requer o uso de uma função específica na OpenCV, sendo essa a função flip().

O código a seguir realiza o espelhamento da imagem. Veja que a função pede como parâmetros apenas a imagem carregada e um valor. Se o valor 1 é informado, a imagem será invertida no sentido vertical (efeito de espelhamento), enquanto o valor -1 faz com que a inversão seja horizontal.

inverter = cv2.flip(imagem, 1)
cv2.imshow("Espelhado horizontalmente", inverter)

cv2.waitKey(0)

A imagem a esquerda da Figura 7 mostra o resultado do código acima, onde a imagem foi espelhada horizontalmente já que o valor 1 foi informado como parâmetro. A imagem a direita da figura é o resultado da aplicação do valor zero como segundo parâmetro e onde se observa o espelhamento na vertical.

baixo_direita cima_esquerda

Figura 7. Figura girada horizontalmente (a) e figura girada verticalmente (b)

O espelhamento na horizontal é muito utilizado, principalmente na captura de imagens da webcam pois essa pode estar configurada para capturar as imagens espelhadas e é preciso inverte-las para ter o resultado original.