Tutorial de Visão Computacional 2: Noções Básicas de Imagem

Este tutorial é a base da visão computacional apresentada como “Lição 2” da série; há mais lições que virão e falarão sobre a extensão de construir seus próprios projetos de visão computacional baseados em aprendizado profundo. Você pode encontrar o programa completo e sumário aqui.

Os principais pontos principais deste artigo:

  • Carregar uma imagem do disco.
  • Obter a ‘altura’, ‘largura’ e ‘profundidade’ da imagem.
  • Encontrar os componentes R, G e B da imagem.
  • Desenhar usando OpenCV.

Carregar uma Imagem do Disco

Antes de realizarmos quaisquer operações ou manipulações de uma imagem, é importante para nós carregarmos uma imagem de nossa escolha no disco. Vamos realizar essa atividade usando OpenCV. Existem duas maneiras de realizarmos essa operação de carregamento. Uma maneira é carregar a imagem simplesmente passando o caminho da imagem e o arquivo da imagem para a função “imread” da OpenCV. A outra maneira é passar a imagem por um argumento de linha de comando usando o módulo python argparse.

Fig 2.1 Loading an Image from Disk by hard coding the image path and name in code.

Python

 

#Carregar Imagem do disco

import cv2
image = cv2.imread(“C:/Sample_program/example.jpg”)
cv2.imshow(‘Image’, image)
cv2.waitKey(0)

Vamos criar um arquivo chamado Loading_image_from_disk.py no Notepad++. Primeiro, importamos a biblioteca OpenCV, que contém nossas funções de processamento de imagens. Importamos a biblioteca usando a primeira linha de código como cv2. A segunda linha de código é onde lemos nossa imagem usando a função cv2.imread em OpenCV, e passamos o caminho da imagem como parâmetro; o caminho também deve conter o nome do arquivo com sua extensão de formato de imagem .jpg, .jpeg, .png ou .tiff.

sintaxe// image=cv2.imread(“path/to/your/image.jpg”) //

É preciso ter muito cuidado ao especificar o nome da extensão do arquivo. É provável que recebamos o erro abaixo se fornecemos a extensão errada.

Python

 

ERROR :

c:\Sample_program>python Loading_image_from_disk.py
Traceback (most recent call last):
File “Loading_image_from_disk.py”, line 4, in <module>
cv2.imshow(‘Image’, image)
cv2.error: OpenCV(4.3.0) C:\projects\opencv-python\opencv\modules\highgui\src\window.cpp:376: error: (-215:Assertion failed) size.width>0 && size.height>0 in function ‘cv::imshow’

A terceira linha de código é onde realmente exibimos a imagem carregada. O primeiro parâmetro é uma string, ou o “nome” da nossa janela. O segundo parâmetro é o objeto para o qual a imagem foi carregada.

Por fim, uma chamada para cv2.waitKey pausa a execução do script até pressionarmos uma tecla no teclado. Usar um parâmetro de “0” indica que qualquer pressionamento de tecla desbloqueará a execução. Sinta-se à vontade para executar seu programa sem ter a última linha de código no seu programa para ver a diferença.

Fig 2.2 Loading an Image using Argparse module.

Python

 

#Lendo Imagem do disco usando Argparse

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])
cv2.imshow(‘Image’, image)
cv2.waitKey(0)

Saber ler uma imagem ou arquivo usando um argumento de linha de comando (argparse) é uma habilidade absolutamente necessária.

As duas primeiras linhas de código são para importar bibliotecas necessárias; aqui, importamos OpenCV e Argparse. Iremos repetir isso ao longo do curso.

Os três primeiros linhas de código lidam com a análise dos argumentos da linha de comando. O único argumento de que precisamos é — image: o caminho para nossa imagem no disco. Por fim, analisamos os argumentos e os armazenamos em um dicionário chamado args.

Vamos tirar um segundo e discutir rapidamente exatamente o que é o — image switch. O — image “switch” (“switch” é sinônimo de “argumento de linha de comando” e os termos podem ser usados de forma intercambiável) é uma string que especificamos na linha de comando. Esse switch informa ao script Loading_image_from_disk.py, onde a imagem que queremos carregar reside no disco.

As três últimas linhas de código foram discutidas anteriormente; a função cv2.imread toma args[“image’] como parâmetro, que nada mais é do que a imagem que fornecemos no prompt de comando. cv2.imshow exibe a imagem, que já está armazenada em um objeto de imagem da linha anterior. A última linha pausa a execução do script até pressionarmos uma tecla no teclado.

Uma das principais vantagens de usar um argparse — argumento de linha de comando é que poderemos carregar imagens de diferentes locais de pasta sem ter que alterar o caminho da imagem em nosso programa, passando dinamicamente o caminho da imagem Ex — “ C:\CV_Material\image\sample.jpg “ no prompt de comando como argumento enquanto executamos nosso programa python.

Fig 2.3 Loading Images from different folder locations using Argparse.

c:\Sample_program>python Loading_image_from_disk.py — image C:\CV_Material\session1.JPG

Aqui, estamos executando o Loading_image_from_disk.py arquivo python a partir do c:\sample_program local, passando o parâmetro “-image” junto com o caminho da imagem C:\CV_Material\session1.JPG.

Obtendo a ‘Altura’, ‘Largura’ e ‘Profundidade’ da Imagem

Uma vez que as imagens são representadas como arrays NumPy, podemos simplesmente usar o atributo .shape para examinar a largura, altura e número de canais.

Ao usar o atributo .shape no objeto de imagem que acabamos de carregar, podemos encontrar a altura, largura e profundidade da imagem. Como discutido na lição anterior — 1, a altura e a largura da imagem podem ser verificadas cruzando-se abrindo a imagem no MS Paint. Consulte a lição anterior. Discutiremos sobre a profundidade da imagem nas próximas lições. A profundidade também é conhecida como canal de uma imagem. As imagens coloridas geralmente têm 3 canais devido à composição RGB em seus pixels e as imagens em escala de cinza têm 1 canal. Isso é algo que discutimos na Lição-1.

Fig 2.4 Prints the Height, Width, and Depth of the Image.

Python

 

#Obtenção da Altura, Largura e Profundidade de uma Imagem

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

# Só diferença em relação aos códigos anteriores — atributo shape aplicado no objeto de imagem

print(f’(Height,Width,Depth) of the image is: {image.shape}’)

image = cv2.imread(args[“image”])
cv2.imshow(‘Image’, image)
cv2.waitKey(0)

Saída:

(Altura, Largura, Profundidade) da imagem é: (538, 723, 3)

A única diferença dos códigos anteriores é a instrução print que aplica o atributo shape ao objeto de imagem carregado. f’ é a string formatada F que aceita variáveis dinamicamente e imprime.

f’ write anything here that you want to see in the print statement: {variables, variables, object, object.attribute,}’

Aqui, utilizamos {object.attribute} dentro dos colchetes para o atributo .shape a fim de calcular a altura, a largura e a profundidade do objeto de imagem.

Python

 

#Obtendo Altura, Largura e Profundidade separadamente

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])

#Fatiamento de array NumPy para obter a altura, a largura e a profundidade separadamente

print(“height: %d pixels” % (image.shape[0]))
print(“width: %d pixels” % (image.shape[1]))
print(“depth: %d” % (image.shape[2]))

cv2.imshow(‘Image’, image)
cv2.waitKey(0)

Saída:

largura: 723 pixels
altura: 538 pixels
profundidade: 3

Aqui, em vez de obter o (altura, largura e profundidade) juntos como uma tupla, realizamos o fatiamento de array e obtemos a altura, a largura e a profundidade da imagem individualmente. O índice 0 do array contém a altura da imagem, o índice 1 contém a largura da imagem e o índice 2 contém a profundidade da imagem.

Encontrando os Componentes R, G e B da Imagem

Fig 2.5 BGR value printed after taking the pixel co-ordinate position (y,x).

Saída:

O valor do componente Azul, Verde, Vermelho da imagem na posição (321, 308) é: (238, 242, 253)

Observe como o valor y é passado antes do valor x — essa sintaxe pode parecer contra-intuitiva no início, mas é consistente com a forma como acessamos valores em uma matriz: primeiro especificamos o número da linha, depois o número da coluna. A partir daí, recebemos uma tupla representando os componentes Azul, Verde e Vermelho da imagem.

Também podemos alterar a cor de um pixel em uma posição específica revertendo a operação.

Python

 

#Encontrando R, B, G da Imagem na Posição (x, y)

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])

#Receber o valor de coordenada de pixel como [y, x] do usuário, para o qual os valores RGB devem ser calculados
[y,x] = list(int(x.strip()) for x in input().split(‘,’))

#Extrair os valores (Azul, verde, vermelho) do coordenada de pixel recebida
(b,g,r) = image[y,x]
print(f’The Blue Green Red component value of the image at position {(y,x)} is: {(b,g,r)}’)

cv2.imshow(‘Image’, image)
cv2.waitKey(0)

(b,g,r) = image[y,x] to image[y,x] = (b,g,r)

Aqui atribuímos a cor em (BGR) à coordenada do pixel da imagem. Vamos tentar atribuindo a cor vermelha ao pixel na posição (321,308) e validamos o mesmo imprimindo o BGR do pixel na posição dada.

Python

 

# Revertendo a Operação para atribuir valor RGB ao pixel da nossa escolha

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])

# Receber o valor da coordenada do pixel como [y,x] do usuário, para o qual os valores RGB devem ser calculados
[y,x] = list(int(x.strip()) for x in input().split(‘,’))

# Extrair os valores (Azul, Verde, Vermelho) da coordenada do pixel recebida
image[y,x] = (0,0,255)
(b,g,r) = image[y,x]
print(f’The Blue Green Red component value of the image at position {(y,x)} is: {(b,g,r)}’)

cv2.imshow(‘Image’, image)
cv2.waitKey(0)

Saída:

Os valores das componentes Azul, Verde e Vermelho da imagem na posição (321, 308) são (0, 0, 255)

No código acima, recebemos a coordenada do pixel através do prompt de comando inserindo o valor como mostrado na Figura 2.6 abaixo e atribuímos a cor vermelha à coordenada do pixel atribuindo (0,0,255) ou seja, (Azul, Verde, Vermelho) e validamos o mesmo imprimindo a coordenada do pixel de entrada.

Desenho Usando OpenCV

Vamos aprender a desenhar diferentes formas como retângulos, quadrados e círculos usando OpenCV desenhando círculos para mascarar meus olhos, retângulos para mascarar meus lábios e retângulos para mascarar o peixe manta-ray ao meu lado.

A saída deve ser assim:

Fig 2.6 Masked Photo of me with the mantra-ray fish.

Esta foto está mascarada com formas usando o MS Paint; tentaremos fazer o mesmo usando OpenCV desenhando círculos em torno dos meus olhos e retângulos para mascarar meus lábios e o peixe matra-ray ao meu lado.

Usamos o método cv2.rectangle para desenhar um retângulo e o método cv2.circle para desenhar um círculo no OpenCV.

cv2.rectangle(image, (x1, y1), (x2, y2), (Blue, Green, Red), Thickness)

O método cv2.rectangle recebe uma imagem como seu primeiro argumento, na qual queremos desenhar nosso retângulo. Queremos desenhar na imagem carregada, então a passamos para o método. O segundo argumento é a posição inicial (x1, y1) do nosso retângulo — aqui, estamos começando nosso retângulo nos pontos (156 e 340). Em seguida, devemos fornecer um ponto final (x2, y2) para o retângulo. Decidimos terminar nosso retângulo em (360, 450). O argumento seguinte é a cor do retângulo que queremos desenhar; aqui, neste caso, estamos passando a cor preta no formato BGR, ou seja, (0,0,0). Finalmente, o último argumento que passamos é a espessura da linha. Damos -1 para desenhar formas sólidas, como visto na Fig 2.6.

Da mesma forma, usamos o método cv2.circle para desenhar o círculo.

cv2.circle(image, (x, y), r, (Blue, Green, Red), Thickness)

O método cv2.circle recebe uma imagem como seu primeiro argumento, na qual queremos desenhar nosso retângulo. Queremos desenhar na imagem que carregamos, então a passamos para o método. O segundo argumento é a posição central (x, y) do nosso círculo — aqui, tomamos nosso círculo no ponto (343, 243). O argumento seguinte é o raio do círculo que queremos desenhar. O argumento seguinte é a cor do círculo; aqui, neste caso, estamos passando a cor VERMELHA no formato BGR, ou seja, (0,0,255). Finalmente, o último argumento que passamos é a espessura da linha. Damos -1 para desenhar formas sólidas, como visto na Fig 2.6.

Ok! Com base em tudo isso, vamos tentar cumprir o que começamos. Para desenhar as formas na imagem, precisamos identificar as coordenadas de início e fim (x, y) da região de máscara para passá-las ao método apropriado.

Como?

Vamos recorrer mais uma vez ao MS Paint. Ao posicionar o cursor sobre uma das coordenadas (canto superior esquerdo) ou (canto inferior direito) da região a ser mascarada, as coordenadas são mostradas na parte destacada do MS Paint, conforme mostrado na Figura 2.7.

Fig 2.7 MSPaint to find the co-ordinates of the masking region.

Da mesma forma, coletaremos todas as coordenadas (x1, y1) (x2, y2) para todas as regiões de máscara, conforme mostrado na Figura 2.8.

Fig 2.8 (x.y) Co-ordinates of masking regions.

Python

 

#Desenho usando OpenCV para mascarar olhos, boca e objetos próximos

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])

cv2.rectangle(image, (415, 168), (471, 191), (0, 0, 255), -1)
cv2.circle(image, (425, 150), 15, (0, 0, 255), -1)
cv2.circle(image, (457, 154), 15, (0, 0, 255), -1)
cv2.rectangle(image, (156, 340), (360, 450), (0, 0, 0), -1)

#Mostrar a imagem de saída
cv2.imshow(“Output drawing “, image)
cv2.waitKey(0)

Resultado:



Fig 2.9 Desired Output.

Source:
https://dzone.com/articles/computer-vision-tutorial-2-image-basics