- Algoritmo
- Módulos
- Percorrer os pixels
- Verificação e comparação de cores
- Filtro de correção de contagem
- Testes
- Referências
O algoritmo do contador consiste em:
- O algoritmo recebe a imagem do usuário
- Ocorre o redimensionamento da imagem
- Todos os pixels da imagem são percorridos
- Ocorre a checagem de todos os pixels
- Aplica-se o filtro de "condição"
- Aplica-se o filtro de "correção de contagem"
- O algoritmo abre a nova imagem
- Exibe o resultado da contagem de objetos
O desenvolvimento do algoritmo foi feito em Python com o auxílio do seguintes módulos:
- OpenCV[1]
- Argparse[2]
- Numpy[3]
O módulo OpenCV foi usado para receber, redimensionar, percorrer e checar todos os pixels da imagem.
img = cv.imread('image.png',cv.IMREAD_COLOR)
exemplo de leitura de imagem com OpenCV.
Sabendo que a imagem é uma matriz NxM, N sua largura e M sua altura, o algoritmo sempre irá usar as configurações da imagem recebida, então imagens com diferentes resoluções, por exemplo 512x512 e 1280x720, podem ser testadas sem a necessidade de alteração no código.
O módulo Argparse teve a função de receber como argumento de linha de comando, juntamente com o argumento:
user@computer:~$ python programa.py image.png
exemplo de execução python com o argumento extra do caminho/nome da imagem.
O módulo Numpy foi usado para realizar a comparação entre as cores dos pixels com a condição de objeto lúminoso.
Para haver a checagem de todos os pixels é necessário o uso de dois laços de repetição, dois for's, um para ir por cada linha, e outro por cada coluna:
for i in range(0, height):
for j in range(0, width):
O valor de i vai de 0 até o valor máximo de altura e o de j de 0 até o valor máximo de largura.
Numpy arrays, são estruturas de dados do módulo Numpy, e com essas estruturas é possível a manipulação, verificação e operações com multiplos arrays, que no caso são usados para armazenar as cores de cada pixel. Por exemplo: [R,G,B]
light_condition = np.array([12,12,12])
A variável 'light_condition' é um numpy array que tem como valores em cada índice um valor de R,G ou B :
light_condition[0] = R
light_condition[1] = G
light_condition[2] = B
Então a verificação das cores é feita analisando o padrão RGB de cada pixel e comparando com a variável 'light_condition'.
if numpy.all(img[i, j] > light_condition):
cont += 1
Então, se o padrão RGB do pixel(X, Y ; sendo X e Y as coordenadas do pixel) for maior que o padrão RGB da variável 'light_condition' a contagem irá ser realizada.
Há objetos que na imagem possuem mais de 1px(pixel) de 'tamanho' então, esse filtro foi feito com o objetivo de minimizar a contagem extra do mesmo objeto.
O filtro foi desenvolvido com a lógica de haver a verificação de todos os pixels 'vizinhos' , no caso superior, inferior, esquerdo e direito. e caso todos forem classificados como objetos hávera uma subtração na contagem a fim de buscar um valor mais próximo do real.
if (
np.all(img[i, j+1]>= light_condition)
and np.all(img[i-1, j]>= light_condition)
and np.all(img[i+1, j]>= light_condition)
and np.all(img[i, j-1]>= light_condition)
):
cont = cont - 4
Após a checagem de cores de cada pixel 'vizinho', e confirmar que todos são objetos também, ocorre uma diminuição de 4 unidades na contagem.
# Importando módulos
import cv2 as cv
import argparse as arg
import numpy as np
# Adicionando argumento de comando para receber imagem
img = arg.ArgumentParser()
img.add_argument('image')
imgs = vars(img.parse_args())
# Definindo Main do programa
if __name__ == '__main__':
# Configurando a imagem
img = cv.imread(imgs['image'],cv.IMREAD_COLOR)
height, width, _ = img.shape
# Contador de corpos
cont = 0
# Definição de estrela
stars_condition = np.array([12,12,12])
# Checagem de todos os pixels
for i in range(0, height):
for j in range(0, width):
if np.all(img[i, j] >= stars_condition):
cont = cont + 1
print("Está secção possui: {} corpos celestes que emitem ou refletem luz".format(cont))
print("Aplicar filtro?[y/n]")
filter = input()
if filter == 'y' :
for i in range(0, height):
for j in range(0, width):
if np.all(img[i, j] >= stars_condition):
if (
np.all(img[i, j+1]>= stars_condition)
and np.all(img[i-1, j]>= stars_condition)
and np.all(img[i+1, j]>= stars_condition)
and np.all(img[i, j-1]>= stars_condition)):
cont = cont - 4
print("Está secção possui: {} corpos celestes que emitem ou refletem luz (Filtro aplicado)".format(cont))
Todas as linhas que iniciam com '#' são comentários que são ignoradas pelo programa.
Todos os testes realizados estão neste link: https://github.com/Lucasmaia435/PE.1/blob/master/Testes.md
Ao realizar o testes, pode-se perceber que em imagens com poucos e pequenos objetos, a contagem obtém um maior êxito, graças a precisão em objetos que tem uma área menor que 3px², porém esse problema da precisão pode ser resolvido usando a detecção de áreas, afim de deixar a contagem mais precisa.
[1] - https://opencv.org/
[2] - https://docs.python.org/3/library/argparse.html
[3] - https://docs.scipy.org/doc/numpy/reference/generated/numpy.std.html