Imagens
Pessoal nosso objetivo aqui é compreender o que são imagens e como podemos manipular elas. Para isso, vamos descer um pouco mais a fundo no conceito de imagem.
1. O que é uma imagem?
Section titled “1. O que é uma imagem?”Primeiro vamos do ponto mais básico que podemos imaginar: o que é uma imagem? Uma imagem é uma representação visual de algo. Isso pode ser uma fotografia, um desenho, uma pintura, etc. O que importa é que a imagem é uma representação visual de algo que existe ou que foi criado. A figura abaixo traz uma representação de uma imagem que os homens das cavernas faziam para representar a caça. Este tipo de representação é chamada de pintura rupestre.
“Poxa Murilo, mais ai você foi longe demais, eu só queria saber o que era uma imagem e não uma pintura rupestre.”
Ok, você tem um ponto. Mas o que eu quero mostrar aqui é que as pinturas eram a forma de representar a captura de uma momento. Naquele contexto histórico, essa era a ferramenta tecnológica que eles tinham para representar algo. E isso é o que uma imagem é, uma representação de algo. E essa representação pode ser feita de várias formas. A pintura rupestre é uma delas, mas existem outras formas de representar algo visualmente. Vamos continuar avançando e vamos agora observar um outro elemento, a forma como as imagens são representadas dentro ser humano, como nós conseguimos ver uma imagem. Para isso, vamos observar a imagem abaixo:
Aqui podemos observar uma série de fatores que são importantes para a nossa compreensão de como um ser humano vê uma imagem. Primeiro, o olho humano capta a luz que reflete nos objetos. Essa luz é captada pela retina, que é a parte do olho responsável por transformar a luz em impulsos elétricos. Aqui temos um detalhe interessante, essa imagem é capturada inversamente, ou seja, a imagem que chega na retina é invertida. Isso acontece porque a lente do olho humano é convexa, o que faz com que a luz que entra no olho seja focada em um ponto atrás da retina. Esse ponto é chamado de fóvea, e é onde a imagem é mais nítida. A partir daí, os impulsos elétricos são enviados para o cérebro, que interpreta esses sinais e cria a imagem que vemos. Essa interpretação é feita pelo córtex visual, que é a parte do cérebro responsável por processar as informações visuais. O córtex visual é dividido em várias áreas, cada uma responsável por processar diferentes aspectos da imagem, como cor, forma e movimento.
“Ooooo um tanto quanto biológico isso né Murilo?”
Sim, mas da mais uma olhada nesse vídeo:
Legal, agora nós sabemos o que é uma imagem e como o ser humano consegue ver uma imagem. Agora, como nós conseguimos utilizar essas informações para criar representações de imagens? Temos as pinturas, mas além delas, será que conseguimos tentar utilizar alguns dos princípios de como o ser humano vê uma imagem para criar representações de imagens? A resposta é sim, e isso é o que nós vamos ver a seguir.
2. Surge a fotografia
Section titled “2. Surge a fotografia”O conceito de fotografia é muito mais recente do que o conceito de imagem. A fotografia é uma representação visual de algo que existe ou que foi criado, mas com a diferença de que ela é feita através da captura da luz que reflete nos objetos. Isso é feito através de uma câmera, que é um dispositivo que capta a luz e a transforma em uma imagem. As primeiras câmeras eram chamadas de “Câmera Obscura”, que é um dispositivo que projeta uma imagem invertida de um objeto em uma superfície. Existem várias versões da câmera obscura, mas a mais conhecida é a que foi criada por Leonardo da Vinci.
Anos depois, surgiram as câmeras fotográficas, que são dispositivos que capturam a luz e a transformam em uma imagem. As primeiras câmeras fotográficas eram muito grandes e pesadas, e eram usadas principalmente por profissionais. O seu princípio de funcionamento é o mesmo da câmera obscura, mas com a diferença de que elas usam um filme fotográfico para capturar a imagem. O filme fotográfico é um material sensível à luz que é usado para registrar a imagem. Quando a luz atinge o filme, ela provoca uma reação química que cria uma imagem. Essa imagem é então revelada em um processo químico que transforma o filme em uma fotografia. Foi a Kodak a primeira empresa a criar uma câmera fotográfica portátil, que era pequena o suficiente para ser carregada na bolsa. Essa câmera foi um grande sucesso e ajudou a popularizar a fotografia. A partir daí, a fotografia se tornou uma forma de arte e uma maneira de registrar momentos da vida cotidiana.
A figura abaixo mostra como uma camera de filme funciona. A luz entra pela lente e atinge o filme, que é sensível à luz. O filme registra a imagem. Depois, o filme é revelado em um processo químico que transforma o filme em uma fotografia. Esse processo é chamado de revelação. A revelação é feita em um laboratório fotográfico, onde o filme é colocado em um tanque com produtos químicos que transformam o filme em uma fotografia. Esse processo pode levar algumas horas ou até dias, dependendo do tipo de filme e do laboratório.
Algumas vezes, a imagem era capturada de forma errada, e isso pode acontecer por vários motivos. O mais comum é que a luz não tenha atingido o filme de forma correta. Isso pode acontecer porque a lente estava suja, ou porque a câmera estava em movimento quando a foto foi tirada. Outras vezes, a imagem pode ter sido capturada de forma errada porque o filme estava danificado ou porque o processo de revelação não foi feito corretamente. Algumas das imagens mais icônicas da história foram capturadas de forma errada, e isso pode ter sido um erro do fotógrafo ou do laboratório fotográfico. Essas imagens são chamadas de “imagens de erro” e são consideradas obras de arte. Elas mostram que a fotografia é uma forma de arte que pode ser usada para capturar momentos da vida cotidiana, mas também pode ser usada para criar obras de arte.
A Leica, uma câmera fotográfica criada por um engenheiro italiano chamado Giovanni Battista Amici, foi a primeira câmera a usar um filme fotográfico. A Laica era uma câmera pequena e leve, que podia ser carregada na bolsa. Ela tem um papel importante na história da fotografia, pois ela foi utilizada para capturar algumas das imagens mais icônicas da história. A Laica foi usada por fotógrafos como Henri Cartier-Bresson e Robert Capa, que usaram a câmera para capturar imagens de guerra e de pessoas comuns. Essas imagens ajudaram a popularizar a fotografia como uma forma de arte e como uma maneira de registrar momentos da vida cotidiana.
Beleza, agora vamos para o mundo digital, onde as imagens agora não mais são capturadas utilizando filme fotográfico, mas sim utilizando sensores digitais.
3. O mundo digital
Section titled “3. O mundo digital”Legal, agora vamos chegando para o ponto que as imagens não são mais representações analógicas, agora elas são representações digitais. Isso significa que as imagens são representadas por números, e não mais por luz, diretamente. As imagens digitais são compostas por pixels, que são pequenos pontos de luz que formam a imagem. Cada pixel tem uma cor e uma intensidade de luz, e juntos eles formam a imagem. A quantidade de pixels em uma imagem é chamada de resolução, e quanto maior a resolução, mais detalhes a imagem tem. A resolução é medida em pixels por polegada (ppi), e quanto maior o número de pixels por polegada, mais detalhes a imagem tem.
Beleza, agora temos nosso conceito que uma imagem digital é composta por um conjunto de pixels. Mas como esses pixels são representados? Eles são representados por números, e esses números representam a cor e a intensidade de luz de cada pixel. A cor de um pixel é representada por três números, que representam as cores primárias: vermelho, verde e azul (RGB). Cada número varia de 0 a 255, e juntos eles formam a cor do pixel. A intensidade de luz é representada por um número que varia de 0 a 1, e quanto maior o número, mais intensa é a luz. Esses números são organizados em uma grade, e juntos eles formam a imagem.
“Calma ai Murilo, aqui tem uma coisa que está confusa! Você falou que cada pixel tem três números, como assim três números?”
Ótima pergunta! Vamos avaliar esse ponto primeiro! Vamos analisar a imagem abaixo. Ela traz uma representação interessante: onde a cor é branco, ela é representada pelo valor 1, e onde a cor é preta, ela é representada pelo valor 0, essa é uma imagem binária. Vamos tentar ler mais algumas características da nossa imagem, observando ela, podemos ver que a quantidade de linhas é 6 e a quantidade de colunas é 6. Isso significa que a imagem tem 6 linhas e 6 colunas, ou seja, 36 pixels. Essa é a resolução da imagem. Agora, vamos tentar entender como a imagem é representada. A imagem é representada por uma matriz, que é uma tabela com 6 linhas e 6 colunas. Cada célula da tabela representa um pixel da imagem. A célula da linha 1 e coluna 1 representa o pixel da linha 1 e coluna 1 da imagem. A célula da linha 1 e coluna 2 representa o pixel da linha 1 e coluna 2 da imagem, e assim por diante. A célula da linha 6 e coluna 6 representa o pixel da linha 6 e coluna 6 da imagem.
Vamos avançar um pouco mais com esse conceito. Agora vamos considerar uma imagem em escala de cinza. O que é a escala de cinza? A escala de cinza é uma representação de uma imagem onde as cores são representadas por tons de cinza. Isso significa que a imagem é composta por pixels que têm diferentes intensidades de luz, mas não têm cor. A intensidade de luz é representada por um número que varia de 0 a 255, e quanto maior o número, mais intensa é a luz. A imagem abaixo mostra uma representação em escala de cinza:
Boa, agora vamos continuar e chegar nas imagens coloridas. As imagens coloridas são representadas por três números, que representam as cores primárias: vermelho, verde e azul (RGB). Cada número varia de 0 a 255, e juntos eles formam a cor do pixel. A imagem abaixo mostra uma representação colorida:
Um outro ponto interessante de se observar é como navegar nos pixels da imagem. A imagem é representada por uma matriz, que é uma tabela com várias linhas e várias colunas. Cada célula da tabela representa um pixel da imagem. A célula da linha 1 e coluna 1 representa o pixel da linha 1 e coluna 1 da imagem. A célula da linha 1 e coluna 2 representa o pixel da linha 1 e coluna 2 da imagem, e assim por diante. A célula da linha n e coluna m representa o pixel da linha n e coluna m da imagem.
Em outras palavras, quando avançamos nas linhas, estamos avançando na vertical, e quando avançamos m colunas, estamos avançando na horizontal. Conhecer como navegar na imagem é importante para podermos manipular a imagem. Isso é feito através de um processo chamado de “navegação em matriz”, que é um processo que nos permite acessar os elementos de uma matriz. A navegação em matriz é feita através de dois índices, que representam a linha e a coluna da célula que queremos acessar. Por exemplo, se quisermos acessar o pixel da linha 1 e coluna 1 da imagem, usamos os índices [0][0]. Se quisermos acessar o pixel da linha 2 e coluna 3 da imagem, usamos os índices [1][2]. E assim por diante.
Legal, vamos agora trabalhar com um pouco de código e depois voltamos um pouco mais sobre conceitos.
4. Manipulando imagens com Python
Section titled “4. Manipulando imagens com Python”Existem diversas maneiras de manipularmos imagens utilizando Python. Importante destacar aqui também que Python não é a única linguagem de programação que pode ser utilizada para manipular imagens. Existem outras linguagens de programação que também podem ser utilizadas, como Java, C++, C#, entre outras. Mas aqui vamos focar em Python, pois é uma linguagem de programação muito utilizada para manipulação de imagens.
Vamos utilizar uma biblioteca chamada OpenCV. OpenCV é uma biblioteca de código aberto que pode ser utilizada para manipulação de imagens e vídeos. Ela é muito utilizada em projetos de visão computacional, e pode ser utilizada para realizar diversas operações em imagens, como leitura, escrita, redimensionamento, rotação, entre outras.
Para iniciar nosso projeto, antes de qualquer coisa, vamos criar um ambiente virtual. O ambiente virtual é uma forma de isolarmos as dependências do nosso projeto, ou seja, ele vai criar um ambiente separado do seu sistema operacional para que possamos instalar as dependências do nosso projeto. Isso é importante para que possamos ter controle sobre as versões das dependências que estamos utilizando, e também para evitar conflitos entre as dependências de diferentes projetos.
Vou colocar os comandos para o sistema operacional Windows, verificar o seu respectivo sistema operacional.
# Cria um diretório para a soluçãomkdir projeto-opencvcd projeto-opencv# Dentro do diretório do projetopython -m venv venv# Ativa o ambiente virtual.\venv\Scripts\activateAgora, o terminal deve ter mudado para indicar que o venv está ativo. Se você quiser conferir, basta utilizar o comando: which python ou where python no Windows. O resultado deve ser algo como:
# WindowsC:\Users\Usuario\Documents\projeto-opencv\venv\Scripts\python.exe# Linux/home/usuario/Documents/projeto-opencv/venv/bin/pythonAgora, vamos instalar a biblioteca OpenCV. Para isso, vamos utilizar o gerenciador de pacotes do Python, o pip. O pip é um gerenciador de pacotes que permite instalar e gerenciar pacotes Python. Ele é muito utilizado para instalar bibliotecas e dependências de projetos Python.
pip install opencv-pythonpip install opencv-python-headless # Para máquinas sem GUIpip install matplotlib # Para plotar as imagensEstá instalação leva algum tempo para ser concluída, aguardar é viver!! Agora vamos iniciar o nosso projeto. Vamos criar um arquivo chamado main.py, que será o nosso arquivo principal. Esse arquivo vai conter o código que vai manipular a imagem. A primeira coisa que fazemos quando estamos trabalhando com o OpenCV é importar a biblioteca. Para isso, vamos utilizar o seguinte código:
# Traz o OpenCVimport cv2# Traz o Numpy para manipular as matrizes da imagemimport numpy as np# Traz o Matplotlib para plotar as imagensimport matplotlib.pyplot as pltAgora pessoal, vamos avaliar um script um pouco maior, mas que vai nos ajudar a entender como funciona a manipulação de imagens. O código abaixo é um exemplo de como podemos manipular uma imagem utilizando o OpenCV:
# -*- coding: utf-8 -*-
# 1. Importar Bibliotecasimport cv2import numpy as npimport matplotlib.pyplot as plt
print("Bibliotecas importadas com sucesso!")
# --- Certifique-se de ter um arquivo de imagem (ex: 'minha_imagem.jpg') ---# --- no mesmo diretório do script ou forneça o caminho completo. ---caminho_imagem = 'minha_imagem.png' # <-- SUBSTITUA PELO NOME/CAMINHO DA SUA IMAGEM
# 2. Carregar a Imagem# cv2.imread(caminho, flag)# flag pode ser:# cv2.IMREAD_COLOR (1): Carrega imagem colorida (BGR). Transparência é ignorada. (Padrão)# cv2.IMREAD_GRAYSCALE (0): Carrega imagem em escala de cinza.# cv2.IMREAD_UNCHANGED (-1): Carrega imagem como está, incluindo canal alfa (transparência), se existir.img_colorida = cv2.imread(caminho_imagem, cv2.IMREAD_COLOR)
# 3. Verificar Carregamentoif img_colorida is None: print(f"Erro: Não foi possível carregar a imagem em '{caminho_imagem}'.") print("Verifique se o caminho está correto e se o arquivo existe.") exit() # Termina o script se a imagem não for carregadaelse: print(f"Imagem '{caminho_imagem}' carregada com sucesso!")
# 4. Exibir Propriedades Básicasprint("\n--- Propriedades da Imagem ---")
# Tipo do objeto (mostra que é um array NumPy)print(f"Tipo do objeto da imagem: {type(img_colorida)}")
# Dimensões (shape)# Para imagens coloridas (BGR), retorna uma tupla: (altura, largura, numero_de_canais)# Para imagens em escala de cinza, retorna: (altura, largura)forma = img_colorida.shapeprint(f"Dimensões (shape): {forma}")altura = forma[0]largura = forma[1]# Verifica se a imagem é colorida (possui 3 dimensões no shape)if len(forma) == 3: canais = forma[2] print(f" Altura (linhas): {altura} pixels") print(f" Largura (colunas): {largura} pixels") print(f" Canais de cor: {canais} (BGR - Azul, Verde, Vermelho)")else: canais = 1 # Imagem em escala de cinza tem 1 canal implícito print(f" Altura (linhas): {altura} pixels") print(f" Largura (colunas): {largura} pixels") print(" Imagem em escala de cinza (1 canal)")
# Tipo de dados dos pixels (dtype)# Geralmente 'uint8', que significa "unsigned integer de 8 bits"# Cada valor de pixel pode ir de 0 a 255tipo_dados = img_colorida.dtypeprint(f"Tipo de dados dos pixels (dtype): {tipo_dados}")
# Número total de elementos (pixels * canais)total_elementos = img_colorida.sizeprint(f"Número total de elementos (pixels * canais): {total_elementos}")# Verificação: altura * largura * canais (se colorido) == total_elementosif len(forma) == 3: print(f" Verificação: {altura} * {largura} * {canais} = {altura * largura * canais}")else: print(f" Verificação: {altura} * {largura} = {altura * largura}")
# 5. Inspecionar a Representação Interna (Valores dos Pixels)print("\n--- Representação Interna (Array NumPy) ---")print("A imagem é representada como uma matriz (ou tensor) de números.")
# Acessando um pixel específico (ex: na linha 50, coluna 100)# IMPORTANTE: A indexação é [linha, coluna] ou [y, x]# Lembre-se que a contagem começa em 0!y_pixel = 50x_pixel = 100
# Verifica se as coordenadas estão dentro dos limites da imagemif y_pixel < altura and x_pixel < largura: pixel_valor = img_colorida[y_pixel, x_pixel] print(f"Valor do pixel na posição (linha={y_pixel}, coluna={x_pixel}): {pixel_valor}")
# Se a imagem for colorida, pixel_valor será um array [Azul, Verde, Vermelho] if len(forma) == 3: print(f" Valor do canal Azul (B): {pixel_valor[0]}") print(f" Valor do canal Verde (G): {pixel_valor[1]}") print(f" Valor do canal Vermelho (R): {pixel_valor[2]}") # Acessando um canal específico diretamente: img[y, x, canal_index] (0=B, 1=G, 2=R) valor_verde = img_colorida[y_pixel, x_pixel, 1] # Índice 1 para Verde print(f" Acessando diretamente o canal Verde (G) no pixel ({y_pixel},{x_pixel}): {valor_verde}") else: # Se for escala de cinza, será um único valor de intensidade print(f" Intensidade (escala de cinza): {pixel_valor}")
else: print(f"Atenção: As coordenadas ({y_pixel},{x_pixel}) estão fora dos limites da imagem ({altura}x{largura}).")
# Mostrando uma pequena seção da imagem (ex: canto superior esquerdo 3x3 pixels)print("\nValores dos pixels no canto superior esquerdo (primeiras 3 linhas, 3 colunas):")# Usando slicing do NumPy: [linha_inicio:linha_fim, coluna_inicio:coluna_fim]secao_imagem = img_colorida[0:3, 0:3]print(secao_imagem)
# 6. (Opcional) Exibir a Imagem
# Opção 1: Usando OpenCV (abre uma janela separada)print("\nExibindo a imagem em uma janela OpenCV. Pressione qualquer tecla para fechar.")cv2.imshow('Minha Imagem Colorida (OpenCV)', img_colorida)cv2.waitKey(0) # Espera indefinidamente por uma tecla ser pressionadacv2.destroyAllWindows() # Fecha todas as janelas abertas pelo OpenCV
# # Opção 2: Usando Matplotlib (melhor para notebooks)# # Atenção: OpenCV carrega em BGR, Matplotlib espera RGB. É preciso converter!# print("\nExibindo a imagem usando Matplotlib (convertendo BGR para RGB)...")# img_rgb = cv2.cvtColor(img_colorida, cv2.COLOR_BGR2RGB)# plt.imshow(img_rgb)# plt.title('Minha Imagem (Matplotlib - RGB)')# plt.axis('off') # Opcional: remove os eixos x e y# plt.show()
print("\n--- Fim do Tutorial Básico ---")“Eita! Murilo, mas esse código é muito grande! Não entendi nada!”
Calma! Vamos avaliar ele com calma em conjunto:
- Linha 12: aqui estamos indicando o arquivo que vamos abrir. Esse arquivo deve estar na mesma pasta que o nosso script. Caso contrário, você pode colocar o caminho completo do arquivo. O OpenCV suporta diversos formatos de imagem, como JPG, PNG, BMP, entre outros.
- Linhas 14 até linha 20: aqui estamos carregando a imagem. O OpenCV possui uma função chamada
imread, que é responsável por carregar a imagem. Essa função recebe como parâmetro o caminho da imagem e um flag, que indica como a imagem deve ser carregada. O flag pode sercv2.IMREAD_COLOR, que carrega a imagem em cores (BGR),cv2.IMREAD_GRAYSCALE, que carrega a imagem em escala de cinza, oucv2.IMREAD_UNCHANGED, que carrega a imagem como está, incluindo o canal alfa (transparência), se existir. O padrão écv2.IMREAD_COLOR, que carrega a imagem em cores. - Linhas 22 até 28: aqui estamos verificando se a imagem foi carregada corretamente. Se a imagem não for carregada, o OpenCV retorna
None, e nesse caso, o código imprime uma mensagem de erro e encerra o script. - Linha 34: exibe o tipo dos dados que representam a imagem quando ela foi carregada pelo OpenCV. Aqui é legal observar que a imagem é representada como um array NumPy. O NumPy é uma biblioteca do Python que permite trabalhar com arrays e matrizes de forma eficiente. O OpenCV utiliza o NumPy para representar as imagens, pois isso facilita a manipulação dos pixels da imagem.
- Linhas 36 até 53: aqui a propriedade
shapeda imagem é acessada. As imagens são armazenadas como objetos, portanto, possuem propriedades. A propriedadeshaperetorna uma tupla com as dimensões da imagem. Para imagens coloridas (BGR), a tupla tem três valores: altura, largura e número de canais. Para imagens em escala de cinza, a tupla tem dois valores: altura e largura. O número de canais para imagens coloridas é 3 (BGR), e para imagens em escala de cinza é 1. - Linhas 55 até 61: aqui estamos acessando o tipo de dados dos pixels da imagem. O OpenCV utiliza o tipo
uint8, que significa “unsigned integer de 8 bits”. Isso significa que cada pixel pode ter um valor entre 0 e 255. O valor 0 representa a cor preta, e o valor 255 representa a cor branca. Os valores intermediários representam os tons de cinza. - Linhas 63 até 69: aqui estamos acessando o número total de elementos da imagem. O número total de elementos é o número de pixels multiplicado pelo número de canais. Para imagens coloridas, o número total de elementos é igual à altura multiplicada pela largura multiplicada pelo número de canais. Para imagens em escala de cinza, o número total de elementos é igual à altura multiplicada pela largura.
- Linhas 71 até 81: aqui estamos acessando o valor de um pixel específico da imagem. O OpenCV utiliza a indexação [linha, coluna] ou [y, x] para acessar os pixels da imagem. A contagem começa em 0, então o pixel da linha 1 e coluna 1 é acessado com os índices [0][0]. O valor do pixel é retornado como um array NumPy. Para imagens coloridas, o array tem três valores: azul, verde e vermelho (BGR). Para imagens em escala de cinza, o array tem um único valor de intensidade.
- Linhas 102 até 105: aqui estamos acessando uma seção da imagem. O OpenCV utiliza o slicing do NumPy para acessar seções da imagem. O slicing é uma forma de acessar uma parte de um array ou matriz. No caso da imagem, o slicing é feito com os índices [linha_inicio:linha_fim, coluna_inicio:coluna_fim]. Isso retorna uma nova matriz que contém apenas os pixels da seção especificada.
- Linhas 107 até 113: aqui estamos exibindo a imagem utilizando o OpenCV. O OpenCV possui uma função chamada
imshow, que é responsável por exibir a imagem em uma janela separada. Essa função recebe como parâmetro o nome da janela e a imagem a ser exibida. A funçãowaitKeyespera indefinidamente por uma tecla ser pressionada, e a funçãodestroyAllWindowsfecha todas as janelas abertas pelo OpenCV. - Linhas 115 até 120: aqui estamos exibindo a imagem utilizando o Matplotlib. O Matplotlib é uma biblioteca do Python que permite criar gráficos e plotar dados. O Matplotlib possui uma função chamada
imshow, que é responsável por exibir a imagem em um gráfico. Essa função recebe como parâmetro a imagem a ser exibida. A funçãoshowexibe o gráfico.
Pessoal, tem bastante coisa aqui. Minha recomendação: executar esse código, modificar ele, testar variações e ver os efeitos dessas mudanças.
Vamos avaliar o que acontece quando modificamos o valor dentro dos próprios pixels da imagem:
# -*- coding: utf-8 -*-
import cv2import numpy as np
caminho_imagem = 'minha_imagem.png' # Substitua pelo caminho da sua imagemimg = cv2.imread(caminho_imagem)
if img is None: print(f"Erro: Imagem '{caminho_imagem}' não encontrada ou não pôde ser carregada.")else: fator_escurecimento = 0.5 # Valores entre 0 e 1 (quanto menor, mais escuro) img_escura = (img * fator_escurecimento).astype(np.uint8)
# Salvar a imagem modificada cv2.imwrite('imagem_escura.png', img_escura) print("Imagem escurecida salva como 'imagem_escura.png'")
# Exibir as imagens (opcional) cv2.imshow('Imagem Original', img) cv2.imshow('Imagem Escurecida', img_escura) cv2.waitKey(0) cv2.destroyAllWindows()Vamos avaliar este código:
- Linha 12: aqui estamos carregando a imagem. O OpenCV possui uma função chamada
imread, que é responsável por carregar a imagem, como já vimos. Quando nenhuma flag é passada, o OpenCV carrega a imagem em cores (BGR). - Linha 14: aqui estamos definindo o fator de escurecimento da imagem. Esse fator deve ser um número entre 0 e 1. Quanto menor o número, mais escura a imagem ficará. O valor 0 representa a cor preta, e o valor 1 representa a cor original da imagem.
- Linha 15: aqui estamos escurecendo a imagem. Aqui estamos multiplicando todos os pixels da imagem pelo fator de escurecimento. Isso significa que todos os pixels da imagem serão multiplicados pelo mesmo número, o que vai escurecer a imagem. O resultado é convertido para o tipo
uint8, que é o tipo de dados utilizado pelo OpenCV para representar os pixels da imagem. - Linha 18: aqui estamos salvando a imagem escurecida. O OpenCV possui uma função chamada
imwrite, que é responsável por salvar a imagem em um arquivo. Essa função recebe como parâmetro o nome do arquivo e a imagem a ser salva.
Agora, comparando esse código com o anterior, podemos ver que muitas das funções são as mesmas. Não só isso, o fluxo para trabalhar com a imagem é o mesmo. O que muda é a forma como manipulamos os pixels da imagem. No primeiro código, nós apenas acessamos os pixels da imagem, e no segundo código, nós modificamos os pixels da imagem. Isso é muito legal, pois podemos fazer diversas operações em cima dos pixels da imagem, como escurecer, clarear, rotacionar, redimensionar, entre outras.
Vamos ver mais alguns exemplos de manipulação de imagens utilizando o OpenCV. O código abaixo é um exemplo de como podemos redimensionar uma imagem:
# -*- coding: utf-8 -*-
import cv2import numpy as npimport matplotlib.pyplot as pltimport os
# Verifica se a imagem existe
caminho_imagem = 'minha_imagem.png' # Substitua pelo caminho da sua imagemif not os.path.exists(caminho_imagem): print(f"Erro: A imagem '{caminho_imagem}' não foi encontrada.") exit()
# Carrega a imagemimg = cv2.imread(caminho_imagem)
if img is None: print(f"Erro: A imagem '{caminho_imagem}' não pôde ser carregada.") exit()
# Exibe as dimensões originais da imagemprint(f"Dimensões originais: {img.shape} (Altura, Largura, Canais)")
# Redimensiona a imagem para 50% do tamanho originallargura_nova = int(img.shape[1] * 0.5) # 50% da largura originalaltura_nova = int(img.shape[0] * 0.5) # 50% da altura originalimg_redimensionada = cv2.resize(img, (largura_nova, altura_nova))
# Exibe as dimensões da imagem redimensionadaprint(f"Dimensões redimensionadas: {img_redimensionada.shape} (Altura, Largura, Canais)")
# Salva a imagem redimensionadacv2.imwrite('imagem_redimensionada.png', img_redimensionada)
# Exibir as imagens (opcional)cv2.imshow('Imagem Original', img)cv2.imshow('Imagem Redimensionada', img_redimensionada)cv2.waitKey(0)cv2.destroyAllWindows()Aqui pessoal, algumas coisas diferentes:
- Utilizamos a biblioteca
ospara verificar se a imagem existe. Isso é importante para evitar erros ao tentar carregar uma imagem que não existe. - Utilizamos a função
cv2.resizepara redimensionar a imagem. Essa função recebe como parâmetro a imagem e as novas dimensões da imagem. As novas dimensões devem ser passadas como uma tupla (largura, altura). O OpenCV redimensiona a imagem utilizando interpolação bilinear, que é um método de interpolação que utiliza os pixels vizinhos para calcular os novos valores dos pixels. Esse método é utilizado para evitar que a imagem fique pixelizada ao ser redimensionada. O OpenCV também possui outros métodos de interpolação, como a interpolação bicúbica e a interpolação vizinho mais próximo. Esses métodos podem ser utilizados passando um parâmetro adicional para a funçãocv2.resize. O parâmetro éinterpolation, e os valores possíveis são:cv2.INTER_LINEAR,cv2.INTER_CUBICecv2.INTER_NEAREST. O padrão écv2.INTER_LINEAR, que é o método mais utilizado. - O OpenCV também possui uma função chamada
cv2.getRotationMatrix2D, que pode ser utilizada para rotacionar a imagem. Essa função recebe como parâmetro o centro da rotação, o ângulo de rotação e o fator de escala. O ângulo de rotação deve ser passado em graus, e o fator de escala deve ser um número entre 0 e 1. O OpenCV utiliza a matriz de transformação afim para rotacionar a imagem.
Agora vamos para mais um ponto que é utilizar o OpenCV com a câmera do nosso dispositivo!
5. Utilizando uma camera com o OpenCV
Section titled “5. Utilizando uma camera com o OpenCV”Vamos acessar a webcam utilizando a função cv2.VideoCapture(). O parâmetro
0 indica que estamos acessando a webcam padrão do sistema.
import cv2cap = cv2.VideoCapture(0)while True: # Captura o quadro ret, frame = cap.read()
# Verifica se a captura foi bem-sucedida if not ret: break
# Exibe o quadro em uma janela cv2.imshow('Webcam', frame)
# Aguarda a tecla 'q' para sair if cv2.waitKey(1) & 0xFF == ord('q'): break
# Libera a captura e fecha as janelascap.release()cv2.destroyAllWindows()Analisando:
- Importação: Importamos a biblioteca
cv2. - Acessar a Webcam: Utilizamos
cv2.VideoCapture(0)para acessar a webcam padrão. - Loop de Captura: Dentro do loop, lemos cada quadro da webcam usando
cap.read().ret: Um booleano que indica se a captura foi bem-sucedida.frame: O quadro capturado.
- Exibição: Utilizamos
cv2.imshow('Webcam', frame)para exibir cada quadro em uma janela chamada “Webcam”. - Espera por Tecla:
cv2.waitKey(1)aguarda por 1 milissegundo. Se a teclaqfor pressionada, o loop é interrompido. - Liberação de Recursos: Após sair do loop, liberamos a captura da webcam
(
cap.release()) e fechamos todas as janelas abertas (cv2.destroyAllWindows()).
Pessoal, aqui abordamos o básico de manipulação de imagem utilizando o OpenCV e o Python. Espero que vocês tenham gostado! Até as próximas!🤖👓💻