Introdução à manipulação de imagens com a biblioteca openCV
A visão é um dos mais importantes sentidos, pois ela fornece muita informação sobre o mundo que pode determinar se uma ação deve ser tomada ou não. Por esse motivo, cientistas da computação têm se esforçado ao longo de anos para dar essa habilidade aos computadores, pois apesar dos computadores já conseguirem registrar imagens e vídeos com alta fidelidade, isso não é o mesmo do que ver.
Essa área de estudo é chamada de visão computacional e atualmente existem bibliotecas que podem ser usadas para facilitar o trabalho com imagens e vídeos, como é o caso do openCV com o qual trabalharemos ao longo deste artigo.
O que são imagens e vídeos para um computador?
Primeiro, saiba que imagens para um computador são apenas um conjunto de números. A menor unidade de uma foto é chamada de pixel, que é composto de três números: um para representar o vermelho, outro o verde e outro azul. Os valores para cada um estão entre 0 e 255 e, através da variação e combinação deles, podemos obter qualquer cor. Há também o canal alfa, cujo valor representa o nível de transparência daquele pixel.
Já os vídeos, basicamente são um conjunto de imagens colocadas uma atrás da outra, o que chamamos de frames. Ao serem reproduzidos em sequência, dão a impressão de movimento.
O que pode ser feito utilizando visão computacional?
Existem vários projetos interessantes que podem ser feitos através da análise de imagens e vídeos, dentre eles estão:
- Reconhecimento de objetos (classificação).
- Remoção do fundo de um vídeo e adição de filtros (muito utilizado em aplicativos de vídeo chamada).
- Rastreio de objetos.
- Geração de imagens e vídeos (criar posts automaticamente para redes sociais).
- Deep fake (trocar o rosto de uma pessoa em um vídeo por outra).
- Drones inteligentes para seguir objetos ou pessoas e desviar de obstáculos.
- Rastreio das mãos (para dar comandos).
- Reconhecimento facial (pode ser colocado em uma câmera de segurança).
- Leitor de QR code e código de barras.
Diferentes técnicas podem ser utilizadas para cada um desses projetos. Para localizar um objeto em uma imagem, por exemplo, basta indicar os valores das cores dos pixels do objeto. Como um vídeo é uma sequência de imagens, é só repetir o processo a cada frame.
Mas claro, para alguns projetos, como o deep fake, será necessário utilizar algoritmos mais sofisticados como redes neurais em um processo que é conhecido como deep learning que consiste em utilizar várias camadas de neurônios para fazer o que em português conhecemos como aprendizado profundo.
Utilizando a biblioteca openCV
Para começar utilizaremos a linguagem Python como exemplo, mas a biblioteca está disponível em outras linguagens também. É um projeto de código aberto, inicialmente desenvolvido pela Intel, e conta hoje com diversos algoritmos para processamento de imagem, vídeo e criação de interfaces de usuário.
Primeiro vamos configurar o ambiente de desenvolvimento, criando um ambiente virtual e instalando a biblioteca. No terminal, digite:
E em seguida, se estiver utilizando o Windows, ative com o comando a seguir:
Depois instale a biblioteca:
O comando vai instalar automaticamente o numpy que é outra biblioteca que também facilita o trabalho com visão computacional.
Agora crie um arquivo chamado main.py e uma pasta chamada assets e dentro dela coloque alguma imagem. Depois importe as bibliotecas no arquivo main.py:
Comandos básicos para manipulação de imagens
Para manipular as imagens, primeiro é necessário importá-las para dentro do código, faremos isso utilizando a função imread, onde como primeiro parâmetro será passado o caminho até a imagem e o segundo será um número, -1 significa sem o canal alfa, ou seja, qualquer transparência que a imagem tiver será removida, 0 significa para carregar em preto e branco e 1 é para incluir o canal alfa.
Depois é necessário chamar a função imshow e passar uma string com o título e a variável com a imagem. Feito isso, basta chamar a função waitKey para que o programa espere até você pressionar qualquer tecla (passando o número 0, ele vai esperar indefinidamente) e por fim, chamar a função destroyAllWindows para fechar.
Ao executar o programa, uma janela com a imagem será aberta. Você pode agora, por exemplo, manipular as dimensões através do comando resize, passando a imagem e o tamanho no eixo x e y entre parênteses (obs: os comandos para manipular devem ser passados antes do imshow).
Também é possível alterar a dimensão através de porcentagem, basta passar 0 para os dois valores dentro do parênteses e em seguida especificar para fx e fy o quanto deve multiplicar. Por exemplo, passando 0.5 terá a metade do tamanho e 2 será o dobro:
Outra alteração que é possível ser feita é rotacionar a imagem:
Esse comando vai rotacionar 90 graus em sentido horário. Agora, para salvar as alterações, basta chamar a função imwrite, passando o nome do arquivo depois a imagem:
Como as imagens são representadas
A biblioteca openCV armazena as imagens em forma de objetos numpy. O numpy é uma biblioteca que possibilita trabalhar com arrays (listas) de maneira mais otimizada, dando um print com o type é possível verificar e com o shape, você consegue acessar a forma desse objeto:
O shape vai retornar em uma tupla a altura, a largura e os canais respectivamente. É como uma tabela no Excel, uma lista vai conter várias outras listas que seriam as linhas e dentro delas vão conter outras listas que seriam as colunas e dentro de cada coluna vão 3 valores, da seguinte forma:
Como já dito no início, cada pixel da imagem é composto por 3 números, o famoso RGB (Red, Green e Blue), porém o openCV representa ao contrário, então seria o azul primeiro, depois o verde e o vermelho.
Para criar ou modificar uma imagem, tudo o que será feito é para modificar esse estado, seja aumentando ou diminuindo a quantidade de linhas e colunas ou variando o valor da intensidade associada a cada cor dos pixels.
Você pode acessar o valor de cada um individualmente da mesma forma que uma lista no Python:
O código acima diz para acessar a linha 275, coluna 312 e a intensidade do verde, que será definida como 10.
Podemos criar um algoritmo para bagunçar os pixels da imagem, definindo seus valores aleatoriamente como teste.
Primeiro importe a função randint da biblioteca random no início do código e no final, antes de mostrar a imagem, faça um loop para acessar as linhas, depois as colunas e então passe uma lista para esse local na imagem contendo os valores de intensidade do azul, verde e vermelho, mas em vez de colocar um valor fixo, chame a função randint, ela vai receber dois parâmetros que são o início e o fim:
No primeiro loop, o valor está fixo em 100 e no segundo passamos o número total de colunas. O randint recebe o valor 255 pois é o máximo da intensidade da cor.
Ao executar, você pode observar que as primeiras 100 linhas e todas as colunas serão afetadas, cada pixel terá uma cor diferente, mas do pixel 101 em diante a imagem estará normal.
Manipulação de imagem avançada
- Recortar e colar: essa função basicamente consiste em pegar uma parte dos valores de um array numpy, passar eles para uma variável e substituir em um local do mesmo tamanho, seja na mesma imagem ou em outra.
- Mudar perspectiva: quando se obtêm uma imagem de um objeto em um ângulo não muito favorável, existe uma forma de mudar para que fique de frente para você. Primeiro é especificado os pontos da imagem de interesse, depois utilizando as funções getPerspectiveTransform e warpPerspective o openCV vai analisar a distância entre os pontos, rotacionar e escalar os valores para mudar a perspectiva do objeto.
- Aplicar filtros: os filtros são alterações nas cores da imagem, por exemplo, você pode alterar apenas a intensidade do azul dos pixels para dar um tom mais frio ou apenas o vermelho para um tom mais quente. Pode aplicar apenas em algumas partes da imagem ou nela toda. Você também pode usar funções matemáticas para fazer o blur que é borrar a foto e assim por diante.
No código fonte deste artigo existem imagens e exemplos de código de como essas funções podem ser feitas utilizando o openCV.
Criando imagens com texto e formas geométricas simples
Agora podemos criar nossas próprias imagens, para isso, primeiro crie outro arquivo Python, pode chamar de image_generator.py e importe as bibliotecas numpy e openCV. Primeiramente, iniciaremos criando um objeto numpy só com zeros, para isso utilizaremos a função zeros passando uma tupla contendo o valor da altura, largura e as três dimensões de cores. O segundo parâmetro vai ser o tipo de dado, que definiremos como uint8.
Ao executar você verá só uma tela preta. Feito isso, podemos começar a criar retângulos, círculos e polígonos para desenhar uma paisagem. Primeiro criaremos dois retângulos, um para representar o céu e outro o chão.
Para criar o retângulo, o primeiro argumento passado é a imagem, o segundo é uma tupla com as coordenadas de início, o terceiro uma tupla com as coordenadas do fim, depois uma tupla com a intensidade de cada cor e por fim é passado o parâmetro que define a espessura da borda, se esse parâmetro for -1 significa que é para preencher toda a figura, caso seja um número positivo, você estará definindo a espessura da borda, mas o interior não será preenchido.
Feito isso, podemos criar o sol, utilizando dois círculos, o primeiro será menor e preenchido completamente de amarelo e o segundo será maior, definiremos a borda para ele não ser completamente preenchido e vamos alterar o tom de amarelo:
Diferente do retângulo, no círculo passamos como segundo parâmetro as coordenadas do centro do círculo e o terceiro parâmetro é o raio. Agora podemos criar uma árvore. Primeiro começaremos pelo tronco, que vai ser uma linha.
O segundo parâmetro é uma tupla com os valores do início e o terceiro parâmetro os valores do fim. Note que a posição x é a mesma em ambos, logo, essa será uma linha vertical. Depois passamos a cor e por fim a espessura da linha.
Agora vamos criar as folhas, elas serão um triângulo verde. Ele é um pouco diferente das outras figuras, para criá-lo precisamos fazer um array numpy contendo listas que serão as coordenadas dos vértices do triângulo. Você também pode criar outras figuras dessa forma, basta passar mais coordenadas.
A função fillPoly é o que vai colocar o polígono na imagem, o segundo parâmetro é o objeto numpy do triângulo que criamos. Para finalizar, colocaremos um texto:
Primeiro selecionamos uma das fontes disponíveis, depois passamos para a função putText, onde passamos a imagem, o texto, as coordenadas, a fonte, a escala, a cor e a espessura da linha respectivamente.
Para não repetir o código, caso queira criar uma floresta em vez de apenas uma árvore, você pode usar classes e variar cada um dos parâmetros para cada objeto, desde a cor das folhas, tamanho, forma, etc.
Conclusão
Com o que aprendeu neste artigo, você já tem a base para começar a manipular qualquer imagem através da programação. A diferença entre o que fizemos hoje e os aplicativos como o photoshop ou canvas é que eles criaram uma série de comandos como os que vimos aqui e colocam uma interface de usuário mais amigável para facilitar a criação.
Saber manipular imagens através da programação, vai te possibilitar projetar sistemas mais complexos utilizando os mais diferentes tipos de algoritmos para gerar diferentes imagens, por exemplo, as redes adversárias generativas (Generative Adversarial Networks) que consiste em duas redes neurais, uma treinada para criar imagens e a outra para julgar se uma imagem foi feita por um robô ou é uma imagem real.
O objetivo da primeira rede é enganar a segunda e o da segunda é não ser enganada, então depois de processar uma imagem o resultado de quem venceu é revelado para as duas redes e aquela que perdeu tem que atualizar o modelo, dessa forma, é possível aprimorar a rede que gera as imagens, aumentando o nível de detalhes com o passar do tempo.
Também é possível aprimorar a análise da imagem, observando pixel por pixel para identificar todos os objetos presentes nela e juntar isso com, por exemplo, o sistema de copiar e colar para o computador criar imagens relacionando objetos e junto de um algoritmo de redes neurais, começar a contar histórias, a criar projetos complexos. Mas claro, esse tipo de tecnologia não é criado do dia para a noite, mas com um estudo mais aprofundado, a única coisa que vai limitar o seu poder de criação vai ser a sua imaginação :D
Para acessar o código fonte completo deste projeto e as imagens geradas, confira o repositório no GitHub.
Sucesso!
A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.