Processamento de Imagem OpenCV

Processamento De Imagem Opencv



Vamos estudar os métodos de processamento de imagem neste artigo. Examinaremos alguns tópicos fundamentais, mas críticos, em visão computacional e aprendizado de máquina. Essas técnicas fundamentais de processamento de imagem podem resolver problemas complexos, como conjuntos de dados. Como resultado, existem seis etapas fundamentais no processamento de imagens, listadas a seguir:
  1. Tradução de imagem
  2. Rotação de imagem
  3. Aritmética da imagem
  4. Inversão de imagem
  5. Recorte de Imagem
  6. Redimensionamento de imagem

Agora, explicaremos detalhadamente todos os tópicos de processamento de imagem mencionados acima.

1. Tradução de imagens

A tradução de imagem é um método de processamento de imagem que nos ajuda a mover a imagem ao longo dos eixos x e y. Podemos mover a imagem para cima, para baixo, para a direita, para a esquerda ou qualquer combinação.







Podemos definir a Matriz de Translação com o símbolo M, e podemos representá-la na forma matemática, conforme abaixo:





Podemos entender o conceito da imagem de tradução através deste programa.





Código Python: Manteremos o nome do seguinte programa como translate.py .

# importar pacotes necessários

importar entorpecido Como por exemplo.

importar argparse

importar imutil

importar cv2

# implementamos o analisador de argumentos

ap_obj = argparse. ArgumentParser ( )

ap_obj. add_argument ( '-k' , '--imagem' , requeridos = Verdadeiro ,

ajuda = 'localização do arquivo de imagem' )

argumentos = cujo ( ap_obj. parse_args ( ) )

# carrega a imagem e mostra na tela

imagem = cv2. eu estou lendo ( argumentos [ 'imagem' ] )

cv2. imshow ( 'Imagem original' , imagem )

# A tradução da imagem é uma matriz NumPy que é fornecida abaixo:

# [[1, 0, shiftX], [0, 1, shiftY]]

# Vamos usar a matriz NumPy acima para deslocar as imagens ao longo do

# direções dos eixos x e y. Para isso, temos que simplesmente passar os valores de pixel.

# Neste programa, vamos mover a imagem 30 pixels para a direita

# e 70 pixels na parte inferior.

Translation_mat = por exemplo. float32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

image_translation = cv2. warpAffine ( imagem , Translation_mat ,

( imagem. forma [ 1 ] , imagem. forma [ 0 ] ) )

cv2. imshow ( 'Tradução de imagens para baixo e para a direita' , image_translation )

# agora, vamos usar a matriz NumPy acima para deslocar as imagens ao longo do

# direções do eixo x (esquerda) e do eixo y (para cima).

# Aqui, vamos mover as imagens 50 pixels para a esquerda

# e 90 pixels para cima.

Translation_mat = por exemplo. float32 ( [ [ 1 , 0 , - cinquenta ] , [ 0 , 1 , - 90 ] ] )

image_translation = cv2. warpAffine ( imagem , Translation_mat ,

( imagem. forma [ 1 ] , imagem. forma [ 0 ] ) )

cv2. imshow ( 'Tradução de imagens para cima e para a esquerda' , image_translation )

cv2. esperaKey ( 0 )

Linhas 1 a 5: Estamos importando todos os pacotes necessários para este programa, como OpenCV, argparser e NumPy. Observe que há outra biblioteca que é imutils. Este não é um pacote do OpenCV. Esta é apenas uma biblioteca que mostrará facilmente o mesmo processamento de imagem.



A biblioteca imutils não será incluída automaticamente quando instalarmos o OpenCV. Então para instalar os imutils, temos que usar o seguinte método:

pip instalar imutils

Linhas 8 a 15: Criamos nosso agrparser e carregamos nossa imagem.

Linhas 24 a 25: Esta seção do programa é onde a tradução acontece. A matriz de tradução nos diz quantos pixels a imagem será movida para cima ou para baixo ou para a esquerda ou direita. Como o OpenCV requer que o valor da matriz esteja em uma matriz de ponto flutuante, a matriz de tradução assume valores em matrizes de ponto flutuante.

A primeira linha da matriz de tradução fica assim:

Esta linha da matriz é para o eixo x. o valor de t x decidirá se a imagem será deslocada para o lado esquerdo ou direito. Se passarmos um valor negativo, significa que a imagem será deslocada para o lado esquerdo, e se o valor for positivo, significa que a imagem será deslocada para o lado direito.

Vamos agora definir a segunda linha da matriz da seguinte forma:

Esta linha da matriz é para o eixo y. o valor de t Y decidirá se a imagem será deslocada para cima ou para baixo. Se passarmos um valor negativo, significa que a imagem será deslocada para cima, e se o valor for positivo, significa que a imagem será deslocada para baixo.

No programa anterior na linha 24, definimos o t x = 30 e o t Y = 70. Portanto, estamos movendo a imagem 30 pixels para o lado direito e 70 pixels para baixo.

Mas o principal processo de tradução da imagem ocorre na linha 25, onde definimos a matriz de tradução cv2.warpAffine . Nesta função, estamos passando três parâmetros: o primeiro parâmetro é a imagem, o segundo parâmetro é a matriz de translação e o terceiro parâmetro é a dimensão da imagem.

Linha 27: A linha 27 exibirá o resultado na saída.

Agora, vamos implementar outra matriz de tradução para a esquerda e para cima. Para isso, temos que definir os valores em negativo.

Linha 33 a 34: No programa anterior na linha 33, definimos o t x = -50 e o t Y = -90. Então estamos movendo a imagem 50 pixels para o lado esquerdo e 90 pixels para cima. Mas o principal processo de tradução da imagem ocorre na linha 34, onde definimos a matriz de tradução cv2.warpAffine .

Linha 36 : A linha 36 exibirá o resultado conforme mostrado na saída.

Para executar o código anterior, devemos fornecer o caminho da imagem conforme indicado abaixo.

Saída: python translate.py –image squirrel.jpg

Agora, vamos implementar o mesmo programa de tradução de imagens usando o imutil biblioteca. Esta biblioteca é muito fácil de usar para processamento de imagens. Nesta biblioteca, não temos que pensar sobre o cv2.warpAffine porque esta biblioteca cuidará disso. Então, vamos implementar este programa de tradução de imagens usando a biblioteca imutils.

Código Python: Manteremos o nome do seguinte programa como translate_imutils.py .

# importe os pacotes necessários

importar entorpecido Como por exemplo.

importar argparse

importar imutil

importar cv2

# Esta função implementa a tradução da imagem e

# retorna a imagem traduzida para a função de chamada.

def traduzir ( imagem , x , Y ) :

matriz_tradução = por exemplo. float32 ( [ [ 1 , 0 , x ] , [ 0 , 1 , Y ] ] )

image_translation = cv2. warpAffine ( imagem , matriz_tradução ,

( imagem. forma [ 1 ] , imagem. forma [ 0 ] ) )

Retorna image_translation

# constrói o analisador de argumentos e analisa os argumentos

ap = argparse. ArgumentParser ( )

ap. add_argument ( '-eu' , '--imagem' , requeridos = Verdadeiro , ajuda = 'Caminho para a imagem' )

argumentos = cujo ( ap. parse_args ( ) )

# carrega a imagem e exibe na tela

imagem = cv2. eu estou lendo ( argumentos [ 'imagem' ] )

cv2. imshow ( 'Imagem original' , imagem )

image_translation = imutil. traduzir ( imagem , 10 , 70 )

cv2. imshow ( 'Tradução de imagem para a direita e para baixo' ,

image_translation )

cv2. esperaKey ( 0 )

Linhas 9 a 13: Esta seção do programa é onde a tradução acontece. A matriz de tradução nos informa quantos pixels a imagem será movida para cima ou para baixo ou para a esquerda ou direita.

Essas linhas já foram explicadas, mas agora vamos construir uma função chamada translate () e enviar três parâmetros distintos para ela. A própria imagem serve como o primeiro parâmetro. Os valores x e y da matriz de tradução correspondem ao segundo e terceiro parâmetros.

Observação : Não há necessidade de definir esta função translate dentro do programa porque ela já está incluída no pacote da biblioteca imutils. Eu o usei dentro do programa para fins de explicação direta. Podemos chamar essa função diretamente com os imutils, conforme mostrado na linha 24.

Linha 24: O programa anterior mostrará que na linha 24, definimos o tx = 10 e o ty = 70. Portanto, estamos movendo a imagem 10 pixels para o lado direito e 70 pixels para baixo.

Neste programa, não nos importamos com as funções cv2.warpAffine porque elas já estão dentro do pacote da biblioteca imutils.

Para rodar o código anterior, temos que dar o caminho da imagem, conforme abaixo:

Saída:

python imutils. py --imagem esquilo. jpg

2. Rotação de imagem

Passamos por como traduzir (isto é, deslocar) uma imagem para cima, para baixo, para a esquerda e para a direita na lição anterior (ou qualquer combinação). Em seguida, discutiremos a rotação no que se refere ao processamento de imagem.

Uma imagem é girada por um ângulo, theta, em um processo conhecido como rotação. O ângulo pelo qual estamos girando a imagem será representado por theta. Além disso, posteriormente fornecerei a função de conveniência de rotação para simplificar a rotação de imagens.

Semelhante à translação, e talvez não surpreendentemente, rotação por um ângulo, theta é determinado pela construção de uma matriz M no seguinte formato:

Esta matriz pode girar um vetor teta graus (no sentido anti-horário) em torno da origem dada (x, y)-plano cartesiano. Normalmente, neste cenário, a origem seria o centro da imagem, mas, na realidade, podemos designar qualquer ponto aleatório (x, y) como nosso centro de rotação.

A imagem rotacionada R é então criada a partir da imagem original I usando a multiplicação direta da matriz: R = IM

O OpenCV, por outro lado, também oferece a capacidade de (1) dimensionar (ou seja, redimensionar) uma imagem e (2) oferecer um centro de rotação arbitrário para realizar a rotação ao redor.

Nossa matriz de rotação modificada M é mostrada abaixo:

Vamos começar abrindo e gerando um novo arquivo chamado rotacionar.py :

# importando os pacotes necessários

importar entorpecido Como por exemplo.

importar argparse

importar imutil

importar cv2

# criando o objeto argumentparser e analisando o argumento

apobj = argparse. ArgumentParser ( )

apobj. add_argument ( '-k' , '--imagem' , requeridos = Verdadeiro , ajuda = 'caminho da imagem' )

argumentos = cujo ( apobj. parse_args ( ) )

imagem = cv2. eu estou lendo ( argumentos [ 'imagem' ] )

cv2. imshow ( 'Imagem original' , imagem )

# Calcule o centro da imagem usando as dimensões da imagem.

( altura , largura ) = imagem. forma [ : 2 ]

( centroX , centro Y ) = ( largura / 2 , altura / 2 )

# Agora, usando cv2, vamos girar a imagem em 55 graus para

# determine a matriz de rotação usando getRotationMatrix2D()

RotationMatrix = cv2. getRotationMatrix2D ( ( centroX , centroY ) , 55 , 1,0 )

imagem rotacionada = cv2. warpAffine ( imagem , RotationMatrix , ( largura , altura ) )

cv2. imshow ( 'Giro a imagem em 55 graus' , imagem rotacionada )

cv2. esperaKey ( 0 )

# A imagem agora será girada em -85 graus.

RotationMatrix = cv2. getRotationMatrix2D ( ( centroX , centroY ) , - 85 , 1,0 )

imagem rotacionada = cv2. warpAffine ( imagem , RotationMatrix , ( largura , altura ) )

cv2. imshow ( 'Giro a imagem em -85 graus' , imagem rotacionada )

cv2. esperaKey ( 0 )

Linhas 1 a 5: Estamos importando todos os pacotes necessários para este programa, como OpenCV, argparser e NumPy. Observe que há outra biblioteca que é imutils. Este não é um pacote do OpenCV. Esta é apenas uma biblioteca que será usada para mostrar facilmente o mesmo processamento de imagem.

A biblioteca imutils não será incluída automaticamente quando instalarmos o OpenCV. O OpenCV instala os imutils. Devemos usar o seguinte método:

pip instalar imutils

Linhas 8 a 14: Criamos nosso agrparser e carregamos nossa imagem. Neste argparser, usamos apenas um argumento de imagem, que nos dirá o caminho da imagem que usaremos neste programa para demonstrar a rotação.

Ao girar uma imagem, devemos definir o ponto de pivô da rotação. Na maioria das vezes, você deseja girar uma imagem em torno de seu centro, mas o OpenCV permite que você escolha qualquer ponto aleatório. Vamos simplesmente girar a imagem em torno de seu centro.

Linhas 17 a 18 pegue a largura e a altura da imagem, respectivamente, e então divida cada dimensão por dois para estabelecer o centro da imagem.

Construímos uma matriz para girar uma imagem da mesma forma que definimos uma matriz para traduzir uma imagem. Vamos apenas chamar o cv2.getRotationMatrix2D função na linha 22 em vez de criar manualmente a matriz usando NumPy (o que pode ser um pouco complicado).

o cv2.getRotationMatrix2D função requer três parâmetros. A primeira entrada é o ângulo de rotação desejado (neste caso, o centro da imagem). Theta é então usado para especificar quantos graus (no sentido anti-horário) iremos girar a imagem. Aqui, vamos girar a imagem em 45 graus. A opção final está relacionada ao tamanho da imagem.

Independentemente do fato de ainda não termos discutido o dimensionamento de uma imagem, você pode fornecer um número de ponto flutuante aqui com 1,0 indicando que a imagem deve ser usada em suas proporções originais. No entanto, se você digitar um valor de 2,0, a imagem dobrará de tamanho. Um número de 0,5 reduz o tamanho da imagem dessa forma.

Linha 22 a 23: Depois de receber nossa matriz de rotação M do cv2.getRotationMatrix2D função, rotacionamos nossa imagem usando o cv2.warpAffine técnica na Linha 23. A primeira entrada da função é a imagem que queremos girar. A largura e a altura de nossa imagem de saída são então definidas, juntamente com nossa matriz de rotação M. Na linha 23, a imagem é então girada em 55 graus.

Você pode notar que nossa imagem foi girada.

Linhas 28 a 30 constituem a segunda rotação. As linhas 22–23 do código são idênticas, exceto que desta vez estamos girando em -85 graus em vez de 55.

Simplesmente giramos uma imagem em torno de seu centro até este ponto. E se quiséssemos girar a imagem em torno de um ponto aleatório?

Vamos começar abrindo e gerando um novo arquivo chamado rotacionar.py:

# importando os pacotes necessários

importar entorpecido Como por exemplo.

importar argparse

importar imutil

importar cv2

# criando o objeto argumentparser e analisando o argumento

ap_obj = argparse. ArgumentParser ( )

ap_obj. add_argument ( '-k' , '--imagem' , requeridos = Verdadeiro , ajuda = 'caminho da imagem' )

argumento = cujo ( ap_obj. parse_args ( ) )

# carrega a imagem e exibe na tela

imagem = cv2. eu estou lendo ( argumento [ 'imagem' ] )

cv2. imshow ( 'Imagem original' , imagem )

# Calcule o centro da imagem usando as dimensões da imagem.

( altura , largura ) = imagem. forma [ : 2 ]

( centroX , centroY ) = ( largura / 2 , altura / 2 )

# Agora, usando cv2, vamos girar a imagem em 55 graus para

# determine a matriz de rotação usando getRotationMatrix2D()

RotationMatrix = cv2. getRotationMatrix2D ( ( centroX , centroY ) , 55 , 1,0 )

imagem rotacionada = cv2. warpAffine ( imagem , RotationMatrix , ( largura , altura ) )

cv2. imshow ( 'Giro a imagem em 55 graus' , imagem rotacionada )

cv2. esperaKey ( 0 )

# A imagem agora será girada em -85 graus.

RotationMatrix = cv2. getRotationMatrix2D ( ( centroX , centroY ) , - 85 , 1,0 )

imagem rotacionada = cv2. warpAffine ( imagem , RotationMatrix , ( largura , altura ) )

cv2. imshow ( 'Giro a imagem em -85 graus' , imagem rotacionada )

cv2. esperaKey ( 0 )

# rotação da imagem de algum ponto arbitrário, não do centro

RotationMatrix = cv2. getRotationMatrix2D ( ( centroX - 40 , centro Y - 40 ) , 55 , 1,0 )

imagem rotacionada = cv2. warpAffine ( imagem , RotationMatrix , ( largura , altura ) )

cv2. imshow ( 'Rotação de imagem de pontos arbitrários' , imagem rotacionada )

cv2. esperaKey ( 0 )

Linha 34 a 35: Agora, esse código deve parecer bastante comum para girar um objeto. Para girar a imagem em torno de um ponto 40 pixels à esquerda e 40 pixels acima de seu centro, instruímos o cv2.getRotationMatrix2D função para prestar atenção ao seu primeiro parâmetro.

A imagem produzida quando aplicamos esta rotação é mostrada abaixo:

Podemos ver claramente que o centro da rotação agora é a coordenada (x, y), que está 40 pixels à esquerda e 40 pixels acima do centro calculado da imagem.

3. Aritmética de imagem

Na verdade, a aritmética de imagens é apenas adição de matrizes com algumas restrições adicionais nos tipos de dados que abordaremos posteriormente.

Vamos dedicar um momento para examinar alguns fundamentos da álgebra linear.

Considere combinar as próximas duas matrizes:

Que resultado a adição de matriz produziria? A resposta simples é a soma das entradas da matriz, elemento por elemento:

Bastante simples, certo?

Todos nós entendemos as operações fundamentais de adição e subtração neste momento. No entanto, devemos estar atentos às restrições impostas pelo nosso espaço de cores e tipo de dados ao trabalhar com imagens.

Os pixels em imagens RGB, por exemplo, ficam entre [0, 255]. O que acontece se tentarmos adicionar 10 a um pixel com intensidade de 250 enquanto olhamos para ele?

Chegaríamos a um valor de 260 se aplicássemos princípios aritméticos padrão. 260 não é um valor válido, pois as imagens RGB são representadas como números inteiros sem sinal de 8 bits.

Então, o que deveria ocorrer? Devemos executar uma verificação para garantir que nenhum pixel esteja além do intervalo de [0, 255], cortando cada pixel para ter um valor entre 0 e 255?

Ou nós “envolvemos” e realizamos uma operação de módulo? De acordo com as regras de módulo, adicionar 10 a 255 resultaria apenas em um valor de 9.

Como as adições e subtrações de imagens além do intervalo de [0, 255] devem ser tratadas?

A verdade é que não existe técnica certa ou errada; tudo depende de como você está trabalhando com seus pixels e o que espera alcançar.

Mas lembre-se de que existem diferenças entre adição no OpenCV e adição no NumPy. A aritmética do módulo e o “wrap around” serão feitos pelo NumPy. Em contraste, o OpenCV executará o recorte e garantirá que os valores de pixel nunca saiam do intervalo [0, 255].

Vamos começar criando um novo arquivo chamado aritmética.py e abrindo:

# python arithmetic.py --image squirrel.jpg

# importando os pacotes necessários

importar entorpecido Como por exemplo.

importar argparse

importar imutil

importar cv2

# criando o objeto argumentparser e analisando o argumento

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-k' , '--imagem' , requeridos = Verdadeiro , ajuda = 'caminho da imagem' )

argumentos = cujo ( apObj. parse_args ( ) )

imagem = cv2. eu estou lendo ( argumentos [ 'imagem' ] )

cv2. imshow ( 'Imagem original' , imagem )

'''

Os valores de nossos pixels estarão no intervalo [0, 255]

já que as imagens são matrizes NumPy, que são armazenadas como números inteiros de 8 bits não assinados.

Ao usar funções como cv2.add e cv2.subtract, os valores serão cortados

a este intervalo, mesmo que sejam adicionados ou subtraídos de fora do

[0, 255] intervalo. Aqui está uma ilustração:

'''


impressão ( 'máximo de 255: {}' . formato ( str ( cv2. adicionar ( por exemplo. uint8 ( [ 201 ] ) ,

por exemplo. uint8 ( [ 100 ] ) ) ) ) )

impressão ( 'mínimo de 0: {}' . formato ( str ( cv2. subtrair ( por exemplo. uint8 ( [ 60 ] ) ,

por exemplo. uint8 ( [ 100 ] ) ) ) ) )

'''

Ao fazer operações aritméticas com esses arrays usando NumPy,

o valor será agrupado em vez de ser recortado no

[0, 255]intervalo. Ao usar imagens, é essencial manter isso

em mente.

'''


impressão ( 'envolver em torno: {}' . formato ( str ( por exemplo. uint8 ( [ 201 ] ) + por exemplo uint8 ( [ 100 ] ) ) ) )

impressão ( 'envolver em torno: {}' . formato ( str ( por exemplo. uint8 ( [ 60 ] ) - por exemplo. uint8 ( [ 100 ] ) ) ) )

'''

Vamos multiplicar o brilho de cada pixel da nossa imagem por 101.

Para fazer isso, geramos um array NumPy do mesmo tamanho da nossa matriz,

preenchido com uns e multiplique por 101 para produzir uma matriz preenchida

com 101s. Por fim, mesclamos as duas imagens.

Você notará que a imagem agora está 'mais clara'.

'''


Matriz = por exemplo. uns ( imagem. forma , dtype = 'uint8' ) * 101

image_added = cv2. adicionar ( imagem , Matriz )

cv2. imshow ( 'Resultado de imagem adicionada' , image_added )

#De maneira semelhante, podemos escurecer nossa imagem tomando

# 60 longe de todos os pixels.

Matriz = por exemplo. uns ( imagem. forma , dtype = 'uint8' ) * 60

image_subtracted = cv2. subtrair ( imagem , Matriz )

cv2. imshow ( 'Resultado da imagem subtraída' , image_subtracted )

cv2. esperaKey ( 0 )

Linhas 1 a 16 será usado para realizar nosso processo normal, que envolve importar nossos pacotes, configurar nosso analisador de argumentos e carregar nossa imagem.

Lembre-se de como discuti anteriormente a distinção entre adição de OpenCV e NumPy? Agora que o cobrimos completamente, vamos examinar um caso específico para garantir que o compreendemos.

Duas matrizes NumPy inteiras sem sinal de 8 bits são definidas em linha 26 . Um valor de 201 é o único elemento na primeira matriz. Embora apenas um membro esteja na segunda matriz, ele tem um valor de 100. Os valores são adicionados usando a função cv2.add do OpenCV.

O que você espera que seja o resultado?

De acordo com os princípios aritméticos convencionais, a resposta deve ser 301. Mas lembre-se de que estamos lidando com inteiros sem sinal de 8 bits, que só podem estar no intervalo [0, 255]. Como estamos utilizando o método cv2.add, o OpenCV lida com o recorte e garante que a adição retorne apenas um resultado máximo de 255.

A primeira linha da listagem abaixo mostra o resultado da execução deste código:

aritmética. py

máximo de 255 : [ [ 255 ] ]

A soma realmente produziu um número de 255.

Seguindo aquilo, linha 26 usa cv2.subtract para realizar uma subtração. Mais uma vez, definimos dois arrays NumPy de inteiros não assinados de 8 bits com um único elemento em cada um. O valor da primeira matriz é 60, enquanto o valor da segunda matriz é 100.

Nossa aritmética determina que a subtração deve resultar em um valor de -40, mas o OpenCV lida com o recorte para nós mais uma vez. Descobrimos que o valor foi ajustado para 0. Nosso resultado abaixo demonstra isso:

aritmética. py

mínimo de 0 : [ [ 0 ] ]

Usando cv2, subtraia 100 de 60, produzindo o valor 0.

Mas o que acontece se utilizarmos o NumPy no lugar do OpenCV para realizar os cálculos?

Linhas 38 e 39 abordar esta questão.

Primeiro, dois arrays NumPy inteiros não assinados de 8 bits com um único elemento cada são definidos. O valor da primeira matriz é 201, enquanto o valor da segunda matriz é 100. Nossa adição seria reduzida e um valor de 255 seria retornado se usássemos a função cv2.add.

O NumPy, por outro lado, “envolve” e faz aritmética de módulo em vez de recortar. O NumPy retorna a zero quando um valor de 255 é atingido e, em seguida, retoma a contagem até que 100 etapas sejam alcançadas. Isso é confirmado pela primeira linha de saída, que é mostrada abaixo:

aritmética. py
envolver em torno: [ Quatro cinco ]

Em seguida, mais dois arrays NumPy são definidos, um com valor 50 e outro com 100. Essa subtração seria cortada pelo método cv2.subtract para retornar um resultado 0. Mas sabemos que, em vez de recortar, o NumPy executa módulo aritmético. Em vez disso, os procedimentos de módulo envolvem e começam a contagem regressiva de 255, uma vez que 0 é alcançado durante a subtração. Podemos ver isso na seguinte saída:

aritmética. py

envolver em torno: [ 207 ]

Mais uma vez, nossa saída de terminal demonstra a distinção entre recortar e envolver:

É crucial manter o resultado desejado em mente ao realizar aritmética inteira. Você deseja que algum valor fora do intervalo [0, 255] seja cortado? Use as técnicas aritméticas de imagem integradas do OpenCV depois disso.

Você deseja que os valores sejam agrupados se estiverem fora do intervalo de [0, 255] e das operações aritméticas de módulo? As matrizes NumPy são simplesmente adicionadas e subtraídas como de costume.

Linha 48 define um array NumPy unidimensional com as mesmas dimensões da nossa imagem. Mais uma vez, garantimos que nosso tipo de dados seja inteiros sem sinal de 8 bits. Apenas multiplicamos nossa matriz de valores de um dígito por 101 para preenchê-la com valores de 101 em vez de 1. Finalmente, usamos a função cv2.add para adicionar nossa matriz de 100s à imagem original. Isso aumenta a intensidade de cada pixel em 101, ao mesmo tempo em que garante que quaisquer valores que tentem exceder 255 sejam cortados no intervalo [0, 255].

Observe como a imagem é visivelmente mais brilhante e parece mais “desbotada” do que o original. Isso ocorre porque estamos direcionando os pixels para cores mais brilhantes aumentando suas intensidades de pixel em 101.

Para subtrair 60 de cada intensidade de pixel da imagem, primeiro estabelecemos uma segunda matriz NumPy na linha 54 que é preenchida com os 60s.

Os resultados desta subtração são descritos na imagem a seguir:

Os itens ao nosso redor parecem significativamente mais escuros do que antes. Isso ocorre porque, ao subtrair 60 de cada pixel, estamos movendo os pixels no espaço de cores RGB para as regiões mais escuras.

4. Inversão de imagem

Semelhante à rotação, inverter uma imagem em seu eixo x ou y é outra opção oferecida pelo OpenCV. Mesmo que as operações de inversão não sejam utilizadas com tanta frequência, conhecê-las é incrivelmente benéfico por vários motivos que você pode não ver imediatamente.

Estamos desenvolvendo um classificador de aprendizado de máquina para uma pequena empresa iniciante que busca identificar rostos em imagens. Para nosso sistema “aprender” o que é um rosto, precisaríamos de algum tipo de conjunto de dados com amostras de rostos. Infelizmente, a empresa nos forneceu apenas um pequeno conjunto de dados de 40 rostos e não podemos coletar mais informações.

O que, então, fazemos?

Uma vez que um rosto continua sendo um rosto, seja espelhado ou não, somos capazes de inverter horizontalmente cada imagem de um rosto e usar as versões espelhadas como dados extras de treinamento.

Este exemplo pode parecer estúpido e artificial, mas não é. Inverter é uma estratégia deliberada usada por fortes algoritmos de aprendizado profundo para produzir mais dados durante a fase de treinamento.

Está claro do anterior que os métodos de processamento de imagem que você aprende neste módulo servem como base para sistemas de visão computacional maiores.

Objetivos.

Usando o cv2.flip função, você aprenderá como virar uma imagem horizontal e verticalmente nesta sessão.

A inversão é a próxima manipulação de imagem que estudaremos. Os eixos x e y de uma imagem podem ser invertidos ou até mesmo ambos. Antes de mergulharmos na codificação, é melhor primeiro observar os resultados de uma inversão de imagem. Veja uma imagem que foi invertida horizontalmente na imagem a seguir:


Observe como nossa imagem original está à esquerda e como a imagem foi espelhada horizontalmente à direita.

Vamos começar criando um novo arquivo chamado lançando.py .

Você viu um exemplo de inversão de imagem, então vamos examinar o código:

# python flipping.py --image quirrel.jpg

# importando os pacotes necessários

importar argparse

importar cv2

# criando o objeto do analisador de argumento e analisando o argumento

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-eu' , '--imagem' , requeridos = Verdadeiro , ajuda = 'caminho da imagem' )

argumento = cujo ( apObj. parse_args ( ) )

imagem = cv2. eu estou lendo ( argumento [ 'imagem' ] )

cv2. imshow ( 'Original' , imagem )

# vira a imagem horizontalmente

imagem invertida = cv2. virar ( imagem , 1 )

cv2. imshow ( 'Imagem invertida horizontalmente' , imagem invertida )

# vira a imagem verticalmente

imagem invertida = cv2. virar ( imagem , 0 )

cv2. imshow ( 'Imagem invertida verticalmente' , imagem invertida )

# flip de imagem ao longo de ambos os eixos

imagem invertida = cv2. virar ( imagem , - 1 )

cv2. imshow ( 'Virado horizontalmente e verticalmente' , imagem invertida )

cv2. esperaKey ( 0 )

As etapas que seguimos para importar nossos pacotes, analisar nossas entradas e carregar nossa imagem do disco são tratadas em l ines 1 a 12 .

Chamando a função cv2.flip no Linha 15 , é simples virar uma imagem horizontalmente. A imagem que procuramos inverter e um código ou sinalizador específico que especifica como inverter a imagem são os dois argumentos necessários para o método cv2.flip.

Um valor de flip code de 1 significa que vamos girar a imagem em torno do eixo y para invertê-la horizontalmente ( Linha 15 ). Se especificarmos um flip code de 0, desejamos girar a imagem em torno do eixo x ( Linha 19 ). Um flip code negativo ( Linha 23 ) gira a imagem em ambos os eixos.

Um dos exemplos mais fáceis neste assunto é inverter uma imagem, o que é básico.

Em seguida, discutiremos o corte de imagens e o uso de fatias de matriz NumPy para extrair partes específicas da imagem.

5. Recorte de imagem

Cropping, como o nome já diz, é o processo de escolha e retirada da Região de Interesse (ou simplesmente ROI), que é a área da imagem que nos interessa.

O rosto teria que ser cortado de uma imagem para um aplicativo de detecção de rosto. Além disso, se estivéssemos criando um script Python para localizar cachorros em imagens, poderíamos cortar o cachorro da imagem ao localizá-lo.

Metas: Nosso principal objetivo é familiarizar-se e sentir-se à vontade usando o fatiamento de matriz NumPy para cortar áreas de uma imagem.

Corte : Quando cortamos uma imagem, nosso objetivo é eliminar os elementos externos que não nos interessam. O processo de escolha de nosso ROI costuma ser chamado de escolha de nossa região de interesse.

Crie um novo arquivo chamado de cabeça raspada , abra-o e adicione o seguinte código:

# python crop.py

# importando os pacotes necessários

importar cv2

# carga de imagem e exibição na tela

imagem = cv2. eu estou lendo ( 'esquilo.jpg' )

impressão ( imagem. forma )

cv2. imshow ( 'Original' , imagem )

# Fatias de matriz NumPy são usadas para cortar rapidamente uma imagem

# vamos recortar a cara do esquilo da imagem

cara de esquilo = imagem [ 35 : 90 , 35 : 100 ]

cv2. imshow ( 'cara de esquilo' , cara de esquilo )

cv2. esperaKey ( 0 )

# E agora, aqui vamos recortar todo o corpo

# do esquilo

corpo de esquilo = imagem [ 35 : 148 , 23 : 143 ]

cv2. imshow ( 'Corpo de Esquilo' , corpo de esquilo )

cv2. esperaKey ( 0 )

Mostraremos o recorte em Python e OpenCV usando uma imagem que carregamos do disco em Linhas 5 e 6 .

Imagem original que vamos recortar

Usando apenas técnicas básicas de corte, pretendemos separar o rosto do esquilo e o corpo do esquilo da área circundante.

Usaremos nosso conhecimento prévio da imagem e forneceremos manualmente as fatias da matriz NumPy de onde existem o corpo e o rosto. Em condições normais, geralmente empregaríamos aprendizado de máquina e algoritmos de visão computacional para reconhecer o rosto e o corpo na imagem. Mas vamos manter as coisas simples por enquanto e evitar o emprego de qualquer modelo de detecção.

Podemos identificar o rosto na imagem com apenas uma linha de código. Linha 13 , Para extrair uma parte retangular da imagem, começando em (35, 35), fornecemos fatias de matriz NumPy (90, 100). Pode parecer confuso alimentarmos o corte com os índices na ordem de altura primeiro e largura segundo que fazemos, mas lembre-se de que o OpenCV armazena imagens como matrizes NumPy. Como resultado, devemos fornecer os valores para o eixo y antes do eixo x.

O NumPy requer os quatro índices a seguir para realizar nosso corte:

Início: A coordenada y no início. Para esta instância, começamos em y=35.

Fim: A coordenada y no final. Nossa colheita irá parar quando y = 90.

Início x: A coordenada x inicial da fatia. A colheita é iniciada em x=35.

Fim x: A coordenada final do eixo x da fatia. Em x=100, nossa fatia está terminada.

Da mesma forma, cortamos as regiões (23, 35) e (143, 148) da imagem original para extrair o corpo inteiro da imagem em Linha 19 .

Você pode observar que a imagem foi cortada para mostrar apenas o corpo e o rosto.

6. Redimensionamento de imagem

O processo de aumentar ou diminuir a largura e a altura de uma imagem é conhecido como dimensionamento ou simplesmente redimensionamento. A proporção, que é a proporção entre a largura e a altura de uma imagem, deve ser considerada ao redimensionar uma imagem. Negligenciar a proporção pode resultar em imagens que foram dimensionadas que aparecem comprimidas e distorcidas:

Nossa imagem inicial está à esquerda. À direita, você verá duas imagens que foram dimensionadas sem manter a proporção, distorcendo a proporção entre a largura e a altura da imagem. Ao redimensionar suas imagens, você geralmente deve considerar a proporção.

A técnica de interpolação usada por nosso algoritmo de redimensionamento também deve considerar o objetivo da função de interpolação de usar essas vizinhanças de pixels para aumentar ou diminuir o tamanho da imagem.

Em geral, diminuir o tamanho da imagem é muito mais eficaz. Isso ocorre porque a remoção de pixels de uma imagem é tudo o que a função de interpolação precisa fazer. Por outro lado, o método de interpolação precisaria “preencher as lacunas” entre os pixels que não existiam anteriormente se o tamanho da imagem fosse aumentado.

Temos nossa imagem original à esquerda. A imagem foi reduzida à metade de seu tamanho original no centro, mas, fora isso, não houve perda de “qualidade” da imagem. No entanto, o tamanho da imagem foi consideravelmente aumentado à direita. Agora parece “ampliado” e “pixelado”.

Como afirmei anteriormente, você normalmente deseja reduzir o tamanho de uma imagem em vez de aumentá-la. Ao reduzir o tamanho da imagem, analisamos menos pixels e temos que lidar com menos “ruído”, o que torna os algoritmos de processamento de imagem mais rápidos e precisos.

Translação e rotação são as duas transformações de imagem abordadas até agora. Vamos agora examinar como redimensionar uma imagem.

Sem surpresa, redimensionaremos nossas imagens usando o método cv2.resize. Como indiquei anteriormente, devemos considerar a proporção da imagem ao utilizar este método. Mas antes de entrarmos muito profundamente nos detalhes, permita-me dar-lhe uma ilustração:

# python resize.py --image squirrel.jpg

# importando os pacotes necessários

importar argparse

importar cv2

# criando o objeto do analisador de argumento e analisando o argumento

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-k' , '--imagem' , requeridos = Verdadeiro , ajuda = 'caminho da imagem' )

argumentos = cujo ( apObj. parse_args ( ) )

# carrega a imagem e exibe na tela

imagem = cv2. eu estou lendo ( argumentos [ 'imagem' ] )

cv2. imshow ( 'Original' , imagem )

# Para evitar que a imagem apareça distorcida, a proporção

# deve ser considerado ou deformado; portanto, descobrimos o que

# a proporção da nova imagem para a imagem atual.

# Vamos fazer com que a largura da nossa nova imagem seja de 160 pixels.

aspecto = 160,0 / imagem. forma [ 1 ]

dimensão = ( 160 , int ( imagem. forma [ 0 ] * aspecto ) )

# esta linha mostrará as operações de redimensionamento reais

imagem redimensionada = cv2. redimensionar ( imagem , dimensão , interpolação = cv2. INTER_AREA )

cv2. imshow ( 'Largura da imagem redimensionada' , imagem redimensionada )

# E se quiséssemos mudar a altura da imagem? — usando o

# mesmo princípio, podemos calcular a proporção com base

# na altura em vez da largura. Vamos fazer a escala

# altura da imagem 70 pixels.

aspecto = 70,0 / imagem. forma [ 0 ]

dimensão = ( int ( imagem. forma [ 1 ] * aspecto ) , 70 )

# realiza o redimensionamento

imagem redimensionada = cv2. redimensionar ( imagem , dimensão , interpolação = cv2. INTER_AREA )

cv2. imshow ( 'Altura da imagem redimensionada' , imagem redimensionada )

cv2. esperaKey ( 0 )

Linhas 1-14 , Depois de importar nossos pacotes e configurar nosso analisador de argumentos, iremos carregar e exibir nossa imagem.

Linhas 20 e 21: A codificação relevante começa nestas linhas . A proporção da imagem deve ser levada em consideração ao redimensioná-la. A proporção entre a largura e a altura da imagem é conhecida como proporção.

Altura largura é a proporção.

Se não levarmos em consideração a proporção, os resultados do nosso redimensionamento ficarão distorcidos.

Sobre Linha 20 , o cálculo da proporção redimensionada é feito. Fornecemos a largura de nossa nova imagem como 160 pixels nesta linha de código. Simplesmente definimos nossa proporção (aspectratio) como a nova largura (160 pixels) dividida pela largura antiga, que acessamos usando image, para calcular a proporção da nova altura para a altura antiga. forma[1].

As novas dimensões da imagem em Linha 21 pode ser calculado agora que conhecemos nossa proporção. Mais uma vez, a nova imagem terá uma largura de 160 pixels. Depois de multiplicar a altura antiga pela nossa proporção e converter o resultado em um número inteiro, a altura é calculada. Podemos manter a proporção original da imagem realizando esta operação.

Linha 24 é onde a imagem é realmente redimensionada. A imagem que queremos redimensionar é o primeiro argumento e o segundo são as dimensões que calculamos para a nova imagem. Nosso método de interpolação, que é o algoritmo para redimensionar a imagem real, é o último parâmetro.

Finalmente, em Linha 25 , exibimos nossa imagem em escala.

Redefinimos nossa proporção (aspectratio) em Linha 31 . A altura da nossa nova imagem será de 70 pixels. Dividimos 70 pela altura original para obter a nova relação entre altura e altura original.

Em seguida, estabelecemos as dimensões da nova imagem. A nova imagem terá uma altura de 70 pixels, que já é conhecida. Podemos mais uma vez manter a proporção original da imagem multiplicando a largura antiga pela proporção para produzir a nova largura.

A imagem é realmente redimensionada em Linha 35 , e é exibido em Linha 36.

Aqui, podemos ver que reduzimos a largura e a altura de nossa imagem original, mantendo a proporção. Nossa imagem pareceria distorcida se a proporção não fosse mantida.

Conclusão

Neste blog, estudamos os diferentes conceitos básicos de processamento de imagem. Vimos a tradução de imagens com a ajuda do pacote OpenCV. Vimos os métodos para mover a imagem para cima, para baixo, para a direita e para a esquerda. Esses métodos são muito úteis quando criamos um conjunto de dados de imagens semelhantes para fornecer como conjunto de dados de treinamento, para que a máquina veja imagens diferentes, mesmo que sejam iguais. Este artigo também ensinou como girar uma imagem em torno de qualquer ponto no espaço cartesiano usando uma matriz de rotação. Então você descobriu como o OpenCV gira imagens usando esta matriz e viu algumas ilustrações de imagens giratórias.

As duas operações aritméticas de imagem fundamentais (mas significativas) de adição e subtração foram examinadas nesta seção. Como você pode ver, adicionar e subtrair matrizes fundamentais é tudo o que as operações aritméticas de imagem implicam.

Além disso, usamos OpenCV e NumPy para investigar as peculiaridades da aritmética de imagens. Essas restrições devem ser lembradas ou você corre o risco de obter resultados inesperados ao executar operações aritméticas em suas imagens.

É importante lembrar que, embora o NumPy execute uma operação de módulo e “enrole”, a adição e a subtração do OpenCV cortam valores além do intervalo [0, 255] para caber dentro do intervalo. Ao desenvolver seus próprios aplicativos de visão computacional, lembrar disso ajudará você a evitar a caça de bugs complicados.

A inversão de imagens é, sem dúvida, uma das ideias mais simples que exploraremos neste curso. A inversão é freqüentemente empregada no aprendizado de máquina para gerar mais amostras de dados de treinamento, resultando em classificadores de imagem mais potentes e confiáveis.

Também aprendemos como usar o OpenCV para redimensionar uma imagem. É crucial considerar o método de interpolação que você está empregando e a proporção da imagem original ao redimensioná-la para que o resultado não pareça distorcido.

Finalmente, é importante lembrar que, se a qualidade da imagem for um problema, é sempre melhor mudar de uma imagem maior para uma menor. Na maioria dos casos, ampliar uma imagem cria artefatos e degrada sua qualidade.