top of page

Geometria Primitiva e Transformações 2D com Python

  • Foto do escritor: Vinicius Goia
    Vinicius Goia
  • 25 de set. de 2023
  • 5 min de leitura

Designed by Freepik

Entender como as imagens são formadas e o que as compõem são conhecimentos necessários para uma jornada em Visão Computacional. A partir do momento em que a principal matéria-prima do trabalho é baseada em imagem, fixar os princípios e as transformações tornam-se elementos úteis.


Aqui neste breve artigo você verá alguns conceitos, fórmulas e algumas aplicações simples utilizando a linguagem de programação Python.


Ponto, Linha e Formas Geométricas


Um ponto 2D, que também pode ser considerado um pixel em uma imagem, é representado por um par de valores:

Em geometria computacional, costuma-se utilizar as coordenadas homogêneas, que nada mais é do que uma maneira de facilitar certas operações e representações. Sendo assim, um ponto 2D representado através de coordenadas homogêneas possui a seguinte forma:

O elemento de valor 1 comumente é representado pela letra w.


Uma equação linear homogênea é representada pela seguinte equação:

Em Python, podemos representar um ponto em um gráfico através dos seguintes comandos:

#Importação de bibliotecas necessárias
import numpy as np
import matplotlib.pyplot as plt
#Definição da matriz de um ponto
ponto = np.array([5,3,1]).transpose()

#Definição do plano de imagem
fig, ax = plt.subplots()

#Plotagem da figura original
plt.plot(ponto[0],ponto[1],'r*')

fig.tight_layout()
plt.show()

Como observado acima, através do numpy array criou-se a matriz de um ponto homogêneo e aplicou-se a transposta para que nossos valores assumissem o formato padrão apresentado no início do artigo. Na plotagem, indicamos em qual posição se encontra o elemento x e y, obtendo o seguinte resultado.



Seguindo esta lógica, iremos criar uma matriz para 3 pontos que simulem um triângulo equilátero. Para melhorar a visualização, iremos adicionar um parâmetro na plotagem que realiza a ligação dos pontos através de uma reta. Um detalhe importante aqui é que adicionaremos o primeiro par de pontos ao final de nossa matriz para que a figura seja devidamente representada.

#Definição de uma matriz qualquer. Neste caso, um triângulo. Observe que adicionamos o primeiro par de pontos ao final da matriz para uma melhor representação na plotagem.
triangle = np.array([[1,1,1],[1,2,1],[2,1,1],[1,1,1]]).transpose()

#Definição do plano de imagem
fig, ax = plt.subplots()

#Plotagem da figura original
plt.plot(triangle[0],triangle[1],'r')

fig.tight_layout()
plt.show()


Transformações 2D


TRANSLAÇÃO


A translação é a movimentação da figura pelo gráfico, preservando sua orientação, tamanho, ângulos, paralelismos e linhas retas. Desta maneira, tem-se apenas dois graus de liberdade: a movimentação pelo eixo x e y.


É representada pela seguinte equação:

Sendo I uma matriz identidade. Desta forma, temos:

Utilizando nossa matriz que representa um triângulo, criaremos uma função que recebe os pares de coordenadas x e y de cada ponto e aplica a transformação de translação. Ao final, é plotado a imagem original e a imagem transformada.

def translation (matriz,x,y):
   """Função para translação. Retorna um gráfico com a figura original e a figura deslocada"""

   #Definição do elemento de translação
   tf = np.array([[1,0,x],[0,1,y],[0,0,1]])

   #Definição do plano de imagem
   fig, ax = plt.subplots()

   #Fixação dos eixos para que as imagens possuam a mesma proporção.
   ax.axis('equal')

   #Novos elementos vazios para receber os valores deslocados
   newx= []
   newy= []

   #Loop de deslocamento para cada ponto
   for i in matriz.transpose():

    #Operação de deslocamento
    new = tf @ i

    #Novos elementos fixados
    newx.append(new[0])
    newy.append(new[1])

   #Plotagem da nova figura deslocada
   plt.plot(newx,newy,'go-')

   #Plotagem da figura original
   plt.plot(matriz[0],matriz[1],'ro-')

   fig.tight_layout()
   plt.show()
#Execução da função
translation(triangle,1,1)


ROTAÇÃO E TRANSLAÇÃO


Neste caso, o desenho é movido e rotacionado no gráfico a partir do ponto de origem, preservando seu tamanho, ângulos, paralelismos e linhas retas. Desta maneira, tem-se 3 graus de liberdade: a movimentação pelo eixo x e y e a orientação.


É representada pela seguinte equação:

Desta forma, temos:

Através da criação de uma função em Python, testaremos a fórmula acima para transformar nossa matriz inicial, a qual referencia a forma de um triângulo.

#Importação de biblioteca necessária para conversão de ângulos
import math
def rotation_translation (matriz,x,y,an):
  """Função para rotação juntamente com translação. Retorna um gráfico com a figura original e a figura rotacionada e deslocada"""

  #Conversão do ângulo de rotação em radianos
  rad = math.radians (an)

  #Definição do elemento de rotação e translação
  tf = np.array([[math.cos(rad),-math.sin(rad),x],[math.sin(rad),math.cos(rad),y],[0,0,1]])

  #Definição do plano de imagem
  fig, ax = plt.subplots()

  #Fixação dos eixos para que as imagens possuam a mesma proporção.
  ax.axis('equal')

  #Novos elementos vazios para receber os valores deslocados
  newx= []
  newy= []

 #Loop de deslocamento e rotação para cada ponto
  for i in matriz.transpose():

    #Operação de deslocamento e rotação
    new = tf @ i.transpose()

    #Novos elementos fixados
    newx.append(new[0])
    newy.append(new[1])

  #Plotagem da nova figura rotacionada e deslocada
  plt.plot(newx,newy,'go-')

  #Plotagem da figura original
  plt.plot(matriz[0],matriz[1],'ro-')

  fig.tight_layout()
  plt.show() 
#Execução da função
rotation_translation(triangle,0.5,0.5,10)


Observa-se que a figura foi deslocada e rotacionada a partir de ponto de origem (0,0). Nessa operação vale atentar-se na transformação do ângulo para radianos.



ESCALA, ROTAÇÃO E TRANSLAÇÃO


Adicionaremos às nossas transformações um coeficiente de escala. Representado pela letra s, é um número arbitrário que multiplica os valores da matriz, aumentando ou diminuindo seu tamanho.


A sequência de transformações é representada pela seguinte equação:

Desta forma, com a nossa função anterior escrita em Python, conseguimos adicionar esse coeficiente multiplicador e ajustar a equação para aumentar a imagem, preservando ângulos, paralelismos e linhas retas.

def scale_rotation_translation (matriz,x,y,an,s):
    """Função para escala e rotação juntamente com translação. Retorna um gráfico com a figura original e a figura em escala, rotacionada e deslocada"""

    #Conversão do ângulo de rotação em radianos
    rad = math.radians (an)

    #Definição do elemento de rotação e translação
    tf = np.array([[math.cos(rad),-math.sin(rad),x],[math.sin(rad),math.cos(rad),y],[0,0,1]])

    #Definição do plano de imagem
    fig, ax = plt.subplots()

    #Fixação dos eixos para que as imagens possuam a mesma proporção.
    ax.axis('equal')

    #Novos elementos vazios para receber os valores deslocados
    newx= []
    newy= []

    #Loop de escala, deslocamento e rotação para cada ponto
    for i in matriz.transpose():

      #Operação de escala, deslocamento e rotação
      new = s*tf @ i.transpose()

      #Novos elementos fixados
      newx.append(new[0])
      newy.append(new[1])

    #Plotagem da nova figura rotacionada e deslocada
    plt.plot(newx,newy,'go-')

    #Plotagem da figura original
    plt.plot(matriz[0],matriz[1],'ro-')

    fig.tight_layout()
    plt.show()
#Execução da função
scale_rotation_translation(triangle,0.5,0.5,10,2)


TRANSFORMAÇÃO AFIM


Consiste na deformação da imagem através da multiplicação de uma matriz arbitrária. Diferentemente da escala, onde mantinha-se a proporção da multiplicação para todos os componentes da matriz, essa transformação altera os pontos através da matriz de entrada.


A transformação afim é representada pela equação abaixo:

Onde A é uma matriz arbitrária.


Desta maneira, iremos definir uma matriz qualquer para criarmos uma função de transformação afim, desta vez na representação de um quadrado.

#Criação de uma matriz (quadrado)
square = np.array([[1,1,1],[1,2,1],[2,2,1],[2,1,1],[1,1,1]]).transpose()
#Criação de uma matriz qualquer
matriz_a = np.array([[1,2,1],[3,3,1],[3,1,1],[3,2,1]])
def affine (square,matriz_a):
  """Função para deformação. Retorna um gráfico com a figura original e a figura deformada"""

  #Definição do plano de imagem
  fig, ax = plt.subplots()

  #Fixação dos eixos para que as imagens possuam a mesma proporção
  ax.axis('equal')

  #Novos elementos vazios para receber os valores deslocados
  newx= []
  newy= []

  #Loop de deformação
  for i in matriz.transpose():

    #Operação de deformação
    new = matriz_a @ i.transpose()

    #Novos elementos fixados
    newx.append(new[0])
    newy.append(new[1])

  #Plotagem da nova figura rotacionada e deslocada
  plt.plot(newx,newy,'go-')

  #Plotagem da figura original
  plt.plot(matriz[0],matriz[1],'ro-')
#Execução da função
affine (triangle,matriz_a)


Observa-se, na transformação, que mantivemos apenas os paralelismos e linhas retas.



Conclusão


Apesar dos conceitos e funções apresentados possuírem uma abordagem simples, serão de extrema utilidade nas aplicações de Visão Computacional e Processamento de Imagens. Estas são áreas as quais as tecnologias atuais tornam o processo de desenvolvimento mais dinâmico e prático. Porém, a base deve ser solidificada para que as implementações sejam realizadas de forma ágil, precisa e criativa, o que, sem essas ferramentas, não seriam possíveis.

Comments


©2023 by Natural Engines. Flowing Knowledge.

bottom of page