Detecção de borda OpenCV em Python com cv2.Canny() PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Detecção de borda OpenCV em Python com cv2.Canny()

Introdução

A detecção de bordas é algo que fazemos naturalmente, mas não é tão fácil quando se trata de definir regras para computadores. Embora vários métodos tenham sido desenvolvidos, o método reinante foi desenvolvido por John F. Canny em 1986, e é apropriadamente chamado de método Canny.

É rápido, bastante robusto e funciona da melhor maneira possível para o tipo de técnica que é. Ao final do guia, você saberá como realizar a detecção de bordas em tempo real em vídeos e produzir algo como:

Detecção de borda inteligente

O que é o método Canny? Consiste em quatro operações distintas:

  • Suavização gaussiana
  • Gradientes de computação
  • Supressão não máxima
  • Limite de histerese

Suavização gaussiana é usado como o primeiro passo para “alisar” a imagem de entrada e suavizar o ruído, tornando a saída final muito mais limpa.

Gradientes de imagem foram usados ​​em aplicações anteriores para detecção de bordas. Mais notavelmente, os filtros Sobel e Scharr dependem de gradientes de imagem. O filtro Sobel se resume a dois kernels (Gx e Gy), Onde Gx detecta mudanças horizontais, enquanto Gy detecta mudanças verticais:

G

x

=

[

-
1

0

+
1

-
2

0

+
2

-
1

0

+
1

]

G

y

=

[

-
1

-
2

-
1

0

0

0

+
1

+
2

+
1

]

Quando você os desliza sobre uma imagem, cada um deles “pegará” (enfatizará) as linhas em sua respectiva orientação. Os kernels Scharr funcionam da mesma maneira, com valores diferentes:

G

x

=

[

+
3

0

-
3

+
10

0

-
10

+
3

0

-
3

]

G

y

=

[

+
3

+
10

+
3

0

0

0

-
3

-
10

-
3

]

Esses filtros, uma vez envolvidos na imagem, produzirão mapas de recursos:

Detecção de borda OpenCV em Python com cv2.Canny() PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Crédito da imagem: Davidwkennedy

Para esses mapas de recursos, você pode calcular o magnitude do gradiente e orientação de gradiente – ou seja, quão intensa é a mudança (qual é a probabilidade de que algo seja uma borda) e em que direção a mudança está apontando. Como Gy denota a mudança vertical (gradiente Y), e Gx denota a mudança horizontal (gradiente X) – você pode calcular a magnitude simplesmente aplicando o teorema de Pitágoras, para obter a hipotenusa do triângulo formado pelos lados “esquerdo” e direções “certas”:

$$
{G} ={quadrado {{{G} _{x}}^{2}+{{G} _{y}}^{2}}}
$$

Usando a magnitude e a orientação, você pode produzir uma imagem com suas bordas destacadas:

Detecção de borda OpenCV em Python com cv2.Canny() PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Crédito da imagem: Davidwkennedy

No entanto – você pode ver quanto ruído também foi capturado pela textura dos tijolos! Os gradientes de imagem são muito sensíveis ao ruído. É por isso que os filtros de Sobel e Scharr foram usados ​​como componente, mas não a única abordagem no método de Canny. A suavização gaussiana também ajuda aqui.

Supressão não máxima

Um problema notável com o filtro Sobel é que as bordas não são muito claras. Não é como se alguém pegasse um lápis e desenhasse uma linha para criar uma lineart da imagem. As bordas geralmente não são tão nítidas nas imagens, pois a luz se difunde gradualmente. No entanto, podemos encontrar a linha comum nas bordas e suprimir o restante dos pixels ao redor dela, produzindo uma linha de separação limpa e fina. Isso é conhecido como supressão não-máxima! Os pixels não máximos (os menores que o que estamos comparando em um campo local pequeno, como um kernel 3×3) são suprimidos. O conceito é aplicável a mais tarefas do que isso, mas vamos vinculá-lo a esse contexto por enquanto.

Limite de histerese

Muitas não arestas podem e provavelmente serão avaliadas como arestas, devido às condições de iluminação, aos materiais na imagem, etc. não. Você pode limitar os gradientes e incluir apenas os mais fortes, assumindo que as bordas “reais” são mais intensas do que as bordas “falsas”.

O limite funciona da mesma maneira que de costume – se o gradiente estiver abaixo de um limite inferior, remova-o (zero) e, se estiver acima de um determinado limite superior, mantenha-o. Tudo entre o limite inferior e o limite superior está na “zona cinza”. Se alguma borda entre os limites estiver conectada a um borda definitiva (aqueles acima do limite) – eles também são considerados bordas. Se não estiverem conectados, provavelmente são arficats de uma vantagem mal calculada.

Isso é limiar de histerese! Na verdade, ele ajuda a limpar a saída final e remover bordas falsas, dependendo do que você classifica como borda falsa. Para encontrar bons valores de limite, você geralmente experimentará diferentes limites inferiores e superiores para os limites ou empregará um método automatizado, como o método de Otsu ou o método do triângulo.

Vamos carregar uma imagem e colocá-la em escala de cinza (Canny, assim como Sobel/Scharr exige que as imagens sejam em escala de cinza):

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('finger.jpg', cv2.IMREAD_GRAYSCALE)
img_blur = cv2.GaussianBlur(img, (3,3), 0)

plt.imshow(img_blur, cmap='gray')

Detecção de borda OpenCV em Python com cv2.Canny() PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

A imagem aproximada de um dedo servirá como um bom campo de teste para detecção de bordas – não é fácil distinguir uma impressão digital da imagem, mas podemos aproximar uma.

Detecção de borda em imagens com cv2.Canny()

O algoritmo de Canny pode ser aplicado usando OpenCV's Canny() método:

cv2.Canny(input_img, lower_bound, upper_bound)

Confira nosso guia prático e prático para aprender Git, com práticas recomendadas, padrões aceitos pelo setor e folha de dicas incluída. Pare de pesquisar comandos Git no Google e realmente aprender -lo!

Encontrar o equilíbrio certo entre o limite inferior e o limite superior pode ser complicado. Se ambos forem baixos – você terá poucas arestas. Se o limite inferior for baixo e o superior for alto – você terá ruído. Se ambos estiverem altos e próximos um do outro – você terá poucas arestas. O ponto certo tem espaço suficiente entre os limites e os tem na escala certa. Experimentar!

A imagem de entrada será desfocada pelo método Canny, mas muitas vezes você se beneficiará ao desfocá-la antes também entra. O método aplica um desfoque gaussiano 5×5 à entrada antes de passar pelo resto das operações, mas mesmo com esse desfoque, algum ruído ainda pode vazar, então desfocamos a imagem antes de alimentá-la no algoritmo:


edge = cv2.Canny(img_blur, 20, 30)

fig, ax = plt.subplots(1, 2, figsize=(18, 6), dpi=150)
ax[0].imshow(img, cmap='gray')
ax[1].imshow(edge, cmap='gray')

Isto resulta em:

Detecção de borda OpenCV em Python com cv2.Canny() PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Os valores de 20 e 30 aqui não são arbitrários – testei o método em vários parâmetros e escolhi um conjunto que parecia produzir um resultado decente. Podemos tentar automatizar isso?

Limite automatizado para cv2.Canny()?

Você pode encontrar um conjunto ideal de valores de limite? Sim, mas nem sempre funciona. Você pode fazer seu próprio cálculo para um bom valor e, em seguida, ajustar o intervalo com um sigma em torno desse limite:

lower_bound = (1-sigma)*threshold
upper_bound = (1+sigma)*threshold

Quando sigma, é dizer, 0.33 - os limites serão 0.66*threshold e 1.33*threshold, permitindo um intervalo de ~1/3 em torno dele. Embora, encontrando o threshold é o que é mais difícil. O OpenCV nos fornece o método de Otsu (funciona muito bem para imagens bimodais) e o método Triangle. Vamos experimentar os dois, além de tomar uma mediana simples dos valores de pixel como a terceira opção:

otsu_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_OTSU)
triangle_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_TRIANGLE)
manual_thresh = np.median(img_blur)

def get_range(threshold, sigma=0.33):
    return (1-sigma) * threshold, (1+sigma) * threshold

otsu_thresh = get_range(otsu_thresh)
triangle_thresh = get_range(triangle_thresh)
manual_thresh = get_range(manual_thresh)

print(f"Otsu's Threshold: {otsu_thresh} nTriangle Threshold: {triangle_thresh} nManual Threshold: {manual_thresh}")

Isto resulta em:

Otsu's Threshold: (70.35, 139.65) 
Triangle Threshold: (17.419999999999998, 34.58) 
Manual Threshold: (105.18999999999998, 208.81)

Esses são bem diferentes! A partir dos valores que vimos antes, podemos antecipar que o método Triangle funciona melhor aqui. O threshold manual não é muito informado, pois ele apenas pega o valor mediano do pixel, e acaba tendo um threshold de base alto que é multiplicado ainda mais em uma ampla faixa para esta imagem. O método de Otsu sofre menos com isso, mas sofre mesmo assim.

Se executarmos o Canny() método com estes intervalos de limite:

edge_otsu = cv2.Canny(img_blur, *otsu_thresh)
edge_triangle = cv2.Canny(img_blur, *triangle_thresh)
edge_manual = cv2.Canny(img_blur, *manual_thresh)

fig, ax = plt.subplots(1, 3, figsize=(18, 6), dpi=150)
ax[0].imshow(edge_otsu, cmap='gray')
ax[1].imshow(edge_triangle, cmap='gray')
ax[2].imshow(edge_manual, cmap='gray')

Observação: A função espera vários argumentos e nossos limites são uma única tupla. Podemos desestruturar a tupla em vários argumentos prefixando-a com *. Isso também funciona em listas e conjuntos, e é uma ótima maneira de fornecer vários argumentos após obtê-los por meios programáticos.

Isto resulta em:

Detecção de borda OpenCV em Python com cv2.Canny() PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

O método Triangle funcionou muito bem aqui! Isso não é garantia de que funcionará bem em outros casos também.

Detecção de borda em tempo real em vídeos com cv2.Canny()

Finalmente, vamos aplicar a detecção de bordas do Canny a um vídeo em tempo real! Vamos exibir o vídeo que está sendo processado (cada quadro conforme é feito) usando cv2.imshow() que exibe uma janela com o quadro que gostaríamos de exibir. No entanto, também salvaremos o vídeo em um arquivo MP4 que poderá ser inspecionado e compartilhado posteriormente.

Para carregar um vídeo usando OpenCV, usamos o VideoCapture() método. Se passarmos 0 – ele gravará da webcam atual, para que você também possa executar o código na sua webcam! Se você passar um nome de arquivo, ele carregará o arquivo:

def edge_detection_video(filename):
    cap = cv2.VideoCapture(filename)
    
    fourcc = cv2.VideoWriter_fourcc(*'MP4V')
    out = cv2.VideoWriter('output.mp4', fourcc, 30.0, (int(cap.get(3)), int(cap.get(4))), isColor=False)
    
    while cap.isOpened():
        (ret, frame) = cap.read()
        if ret == True:
            frame = cv2.GaussianBlur(frame, (3, 3), 0)
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            edge = cv2.Canny(frame, 50, 100)
            out.write(edge)
            cv2.imshow('Edge detection', edge)
        else:
            break

        if cv2.waitKey(10) & 0xFF == ord('q'):
            break

    cap.release()
    out.release()
    cv2.destroyAllWindows()

edge_detection_video('secret_video.mp4')

A VideoWriter aceita vários parâmetros – o nome do arquivo de saída, o FourCC (quatro códigos de codec, denotando o codec usado para codificar o vídeo), a taxa de quadros e a resolução como uma tupla. Para não adivinhar ou redimensionar o vídeo - usamos a largura e a altura do vídeo original, obtidas através do VideoCapture instância que contém dados sobre o próprio vídeo, como largura, altura, número total de quadros etc.

Enquanto a captura é aberta, tentamos ler o próximo quadro com cap.read(), que retorna um código de resultado e o próximo quadro. O código do resultado é True or False, denotando a presença do próximo quadro ou a falta dele. Somente quando houver um quadro, tentaremos processá-lo ainda mais, caso contrário, interromperemos o loop. Para cada quadro válido, passamos por um desfoque gaussiano, convertemos em escala de cinza, executamos cv2.Canny() nele e escrevê-lo usando o VideoWriter para o disco e exibir usando cv2.imshow() para uma visualização ao vivo.

Por fim, liberamos o gravador de captura e vídeo, pois ambos estão trabalhando com arquivos no disco e destruímos todas as janelas existentes.

Quando você executa o método com um secret_video.mp4 input – você verá uma janela pop-up e, quando terminar, um arquivo em seu diretório de trabalho:

Detecção de borda OpenCV em Python com cv2.Canny() PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Conclusão

Neste guia, vimos como funciona a detecção de bordas do Canny e suas partes constituintes – suavização gaussiana, filtros Sobel e gradientes de imagem, supressão não máxima e limite de histerese. Por fim, exploramos métodos para pesquisa automatizada de limites de limite para detecção de bordas do Canny com cv2.Canny(), e empregou a técnica em um vídeo, fornecendo detecção de borda em tempo real e salvando os resultados em um arquivo de vídeo.

Indo além - Aprendizado profundo prático para visão computacional

Sua natureza curiosa faz você querer ir mais longe? Recomendamos verificar nosso Para: “Aprendizado Profundo Prático para Visão Computacional com Python”.

Detecção de borda OpenCV em Python com cv2.Canny() PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Outro curso de visão computacional?

Não faremos classificação de dígitos MNIST ou moda MNIST. Eles cumpriram sua parte há muito tempo. Muitos recursos de aprendizado estão se concentrando em conjuntos de dados básicos e arquiteturas básicas antes de permitir que arquiteturas de caixa preta avançadas carreguem o fardo do desempenho.

Queremos focar em desmistificação, praticidade, compreensão, intuição e projetos reais. Quero aprender como você pode fazer a diferença? Vamos levá-lo em um passeio desde a maneira como nossos cérebros processam imagens para escrever um classificador de aprendizado profundo de nível de pesquisa para câncer de mama até redes de aprendizado profundo que “alucinam”, ensinando os princípios e a teoria por meio de trabalho prático, equipando você com o know-how e ferramentas para se tornar um especialista na aplicação de aprendizado profundo para resolver a visão computacional.

O que tem dentro?

  • Os primeiros princípios da visão e como os computadores podem ser ensinados a “ver”
  • Diferentes tarefas e aplicações de visão computacional
  • As ferramentas do comércio que facilitarão seu trabalho
  • Encontrar, criar e utilizar conjuntos de dados para visão computacional
  • A teoria e aplicação das Redes Neurais Convolucionais
  • Lidar com mudança de domínio, coocorrência e outros vieses em conjuntos de dados
  • Transferir Aprendizagem e utilizar o tempo de treinamento e recursos computacionais de outros para seu benefício
  • Construindo e treinando um classificador de câncer de mama de última geração
  • Como aplicar uma dose saudável de ceticismo às ideias dominantes e entender as implicações de técnicas amplamente adotadas
  • Visualizando o “espaço conceitual” de um ConvNet usando t-SNE e PCA
  • Estudos de caso de como as empresas usam técnicas de visão computacional para obter melhores resultados
  • Avaliação adequada do modelo, visualização do espaço latente e identificação da atenção do modelo
  • Realizando pesquisas de domínio, processando seus próprios conjuntos de dados e estabelecendo testes de modelo
  • Arquiteturas de ponta, a progressão das ideias, o que as torna únicas e como implementá-las
  • KerasCV – uma biblioteca WIP para criar pipelines e modelos de última geração
  • Como analisar e ler artigos e implementá-los você mesmo
  • Selecionando modelos dependendo da sua aplicação
  • Criando um pipeline de aprendizado de máquina de ponta a ponta
  • Paisagem e intuição na detecção de objetos com R-CNNs, RetinaNets, SSDs e YOLO mais rápidos
  • Segmentação de instância e semântica
  • Reconhecimento de objetos em tempo real com YOLOv5
  • Treinamento de detectores de objetos YOLOv5
  • Trabalhando com Transformers usando KerasNLP (biblioteca WIP de força da indústria)
  • Integrando Transformers com ConvNets para gerar legendas de imagens
  • Deepdream
  • Otimização de modelo de Deep Learning para visão computacional

Carimbo de hora:

Mais de Abuso de pilha