Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Limite OpenCV em Python com cv2.threshold()

Introdução

Thresholding é uma técnica simples e eficiente para realizar a segmentação básica em uma imagem e binarizá-la (transformá-la em uma imagem binária) onde os pixels são 0 or 1 (ou 255 se você estiver usando números inteiros para representá-los).

Normalmente, você pode usar o limiar para realizar uma segmentação simples de plano de fundo em uma imagem e se resume a variantes de uma técnica simples para cada pixel:

if pixel_value > threshold:
    pixel_value = MAX
else:
    pixel_value = 0

Esse processo essencial é conhecido como Limite Binário. Agora – existem várias maneiras de ajustar essa ideia geral, incluindo inverter as operações (alternar o > assine com um < sinal), definindo o pixel_value ao threshold em vez de um valor máximo/0 (conhecido como truncar), mantendo a pixel_value em si se estiver acima do threshold ou se estiver abaixo do threshold.

Todos eles foram convenientemente implementados no OpenCV como:

  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV

… respectivamente. Estes são métodos relativamente “ingênuos” pois são bastante simples, não levam em conta o contexto nas imagens, têm conhecimento de quais formas são comuns, etc. técnicas.

Agora, mesmo com os métodos “ingênuos” – alguns heurísticas podem ser postas em prática, para encontrar bons limites, e estes incluem o método Otsu e o método Triângulo:

  • cv2.THRESH_OTSU
  • cv2.THRESH_TRIANGLE

Observação: O thresholding OpenCV é uma técnica rudimentar e é sensível a mudanças de iluminação e gradientes, heterogeneidade de cores, etc. É melhor aplicado em imagens relativamente limpas, depois de desfocá-las para reduzir o ruído, sem muita variação de cor nos objetos que você deseja segmentar.

Outra maneira de superar alguns dos problemas com limites básicos com um único valor de limite é usar limiar adaptativo que aplica um valor limite em cada pequena região em uma imagem, em vez de globalmente.

Limite simples com OpenCV

O limite na API Python do OpenCV é feito através do cv2.threshold() método – que aceita uma imagem (matriz NumPy, representada com números inteiros), o limite, valor máximo e método de limite (como o threshold e maximum_value são usados):

img = cv2.imread('objects.jpg')

img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)


blurred = cv2.GaussianBlur(img, (7, 7), 0)

ret, img_masked = cv2.threshold(blurred, 220, 255, cv2.THRESH_BINARY)

O código de retorno é apenas o limite aplicado:

print(f"Threshold: {ret}") 

Aqui, como o limite é 220 e usamos o THRESH_BINARY método – cada valor de pixel acima 220 será aumentado para 255, enquanto cada valor de pixel abaixo 220 será rebaixado para 0, criando uma imagem em preto e branco, com uma “máscara”, cobrindo os objetos em primeiro plano.

Por que 220? Saber como é a imagem permite que você faça algumas estimativas aproximadas sobre qual limite você pode escolher. Na prática, você raramente desejará definir um limite manual, e abordaremos a seleção automática de limite em breve.

Vamos plotar o resultado! As janelas do OpenCV podem ser um pouco complicadas, então vamos plotar a imagem original, a imagem borrada e os resultados usando o Matplotlib:

fig, ax = plt.subplots(1, 3, figsize=(12, 8))
ax[0].imshow(img)
ax[1].imshow(blurred)
ax[2].imshow(img_masked)

Métodos de limite

Como mencionado anteriormente, existem várias maneiras de usar o limite e o valor máximo em uma função. Demos uma olhada no limite binário inicialmente. Vamos criar uma lista de métodos e aplicá-los um a um, plotando os resultados:

methods = [cv2.THRESH_BINARY, cv2.THRESH_BINARY_INV, cv2.THRESH_TRUNC, cv2.THRESH_TOZERO, cv2.THRESH_TOZERO_INV]
names = ['Binary Threshold', 'Inverse Binary Threshold', 'Truncated Threshold', 'To-Zero Threshold', 'Inverse To-Zero Threshold']

def thresh(img_path, method, index):
    img = cv2.imread(img_path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    blurred = cv2.GaussianBlur(img, (7, 7), 0)
    ret, img_masked = cv2.threshold(blurred, 220, 255, method)

    fig, ax = plt.subplots(1, 3, figsize=(12, 4))
    fig.suptitle(names[index], fontsize=18)
    ax[0].imshow(img)
    ax[1].imshow(blurred)
    ax[2].imshow(img_masked)
    plt.tight_layout()

for index, method in enumerate(methods):
    thresh('coins.jpeg', method, index)

THRESH_BINARY e THRESH_BINARY_INV são inversas entre si e binarizam uma imagem entre 0 e 255, atribuindo-os ao plano de fundo e primeiro plano, respectivamente, e vice-versa.

THRESH_TRUNC binariza a imagem entre threshold e 255.

THRESH_TOZERO e THRESH_TOZERO_INV binarizar entre 0 e o valor de pixel atual (src(x, y)). Vamos dar uma olhada nas imagens resultantes:

Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

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!

Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.
Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.
Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.
Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Esses métodos são intuitivos o suficiente - mas como podemos automatizar um bom valor de limite e o que significa um valor de "bom limite"? A maioria dos resultados até agora tinha máscaras não ideais, com marcas e manchas nelas. Isso acontece por causa da diferença nas superfícies refletivas das moedas – elas não são uniformemente coloridas devido à diferença em como os sulcos refletem a luz.

Podemos, até certo ponto, combater isso encontrando um limiar global melhor.

Limite Automático/Otimizado com OpenCV

O OpenCV emprega dois métodos eficazes de pesquisa de limiar global – o método de Otsu e o método Triangle.

O método de Otsu assume que está funcionando bimodal imagens. As imagens bimodais são imagens cujos histogramas de cores contêm apenas dois picos (ou seja, têm apenas dois valores de pixel distintos). Considerando que os picos pertencem cada um a uma classe como “fundo” e “primeiro plano” – o limiar ideal está bem no meio deles.

Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.
Crédito da imagem: https://scipy-lectures.org/

Você pode tornar algumas imagens mais bimodais com desfoques gaussianos, mas não todas.

Um algoritmo alternativo, muitas vezes com melhor desempenho, é o algoritmo do triângulo, que calcula a distância entre o máximo e o mínimo do histograma de nível de cinza e desenha uma linha. O ponto em que essa linha é maximamente distante do resto do histograma é escolhido como o limite:

Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Ambos assumem uma imagem em escala de cinza, então precisaremos converter a imagem de entrada em cinza via cv2.cvtColor():

img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)

ret, mask1 = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU)
ret, mask2 = cv2.threshold(blurred, 0, 255, cv2.THRESH_TRIANGLE)

masked = cv2.bitwise_and(img, img, mask=mask1)

Vamos executar a imagem com os dois métodos e visualizar os resultados:

methods = [cv2.THRESH_OTSU, cv2.THRESH_TRIANGLE]
names = ['Otsu Method', 'Triangle Method']

def thresh(img_path, method, index):
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (7, 7), 0)

    ret, img_masked = cv2.threshold(blurred, 0, 255, method)
    print(f"Threshold: {ret}")

    fig, ax = plt.subplots(1, 3, figsize=(12, 5))
    fig.suptitle(names[index], fontsize=18)
    ax[0].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    ax[1].imshow(cv2.cvtColor(gray, cv2.COLOR_BGR2RGB))
    ax[2].imshow(cv2.cvtColor(img_masked, cv2.COLOR_BGR2RGB))

for index, method in enumerate(methods):
    thresh('coins.jpeg', method, index)

Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.
Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Aqui, o método do triângulo supera o método de Otsu, porque a imagem não é bimodal:

import numpy as np

img = cv2.imread('coins.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)

histogram_gray, bin_edges_gray = np.histogram(gray, bins=256, range=(0, 255))
histogram_blurred, bin_edges_blurred = np.histogram(blurred, bins=256, range=(0, 255))

fig, ax = plt.subplots(1, 2, figsize=(12, 4))

ax[0].plot(bin_edges_gray[0:-1], histogram_gray)
ax[1].plot(bin_edges_blurred[0:-1], histogram_blurred)

Limite OpenCV em Python com cv2.threshold() PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

No entanto, fica claro como o método do triângulo conseguiu trabalhar com a imagem e produzir um resultado mais satisfatório.

Limitações do Limite do OpenCV

Limiar com OpenCV é simples, fácil e eficiente. No entanto, é bastante limitado. Assim que você introduz elementos coloridos, fundos não uniformes e mudanças nas condições de iluminação – o limiar global como um conceito se torna muito rígido.

As imagens geralmente são muito complexas para que um único limite seja suficiente, e isso pode ser parcialmente resolvido por meio de limiar adaptativo, onde muitos limites locais são aplicados em vez de um único global. Embora também limitado, o limiar adaptativo é muito mais flexível do que o limiar global.

Conclusão

Nos últimos anos, a segmentação binária (como o que fizemos aqui) e a segmentação multi-rótulo (onde você pode ter um número arbitrário de classes codificadas) foram modeladas com sucesso com redes de aprendizado profundo, que são muito mais poderosas e flexíveis. Além disso, eles podem codificar o contexto global e local nas imagens que estão segmentando. A desvantagem é que você precisa de dados para treiná-los, além de tempo e experiência.

Para limites simples e rápidos, você pode usar o OpenCV. Para uma segmentação precisa em nível de produção, convém usar redes neurais.

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”.

Limite OpenCV em Python com cv2.threshold() 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