OpenCV ~ extração de recursos

Aqui estão algumas maneiras de extrair recursos de cor, forma e textura de imagens

Como extrair recursos de imagens? A primeira vez que ouvi o termo "extração de recursos" foi em um tutorial em vídeo de aprendizado de máquina no YouTube, que explicava claramente como extraímos recursos em grandes conjuntos de dados.

Simplesmente, as colunas de um conjunto de dados são os recursos. No entanto, quando me deparei com o assunto da visão computacional, fiquei surpreso ao saber que iríamos extrair características das imagens. Você começa a percorrer cada coluna da imagem e remove cada pixel?

Depois de um tempo, entendi o significado da extração de recursos na visão computacional. A extração de recursos faz parte do processo de redução de dimensionalidade, em que um conjunto inicial de dados brutos é particionado e reduzido a grupos mais gerenciáveis.

Em termos simples, para uma imagem, cada pixel é um pedaço de dados, e o que o processamento da imagem faz é extrair informações úteis da imagem, reduzindo assim a quantidade de dados, mas retendo os pixels que descrevem as características da imagem.

Tudo o que o processamento de imagem faz é extrair informações úteis de uma imagem, reduzindo a quantidade de dados, mas preservando os pixels que descrevem os recursos da imagem.

Neste artigo, vamos explorar vários métodos para extrair recursos de cor, forma e textura de imagens. Esses métodos são baseados na experiência de trabalhar com imagens, se houver algum erro, sinta-se à vontade para adicioná-lo ou corrigi-lo!

1. Cor

Os espaços de cores são automaticamente o primeiro lugar a ser explorado sempre que você trabalha em um projeto de imagem. Compreender o espaço de cores no qual o ambiente da imagem é definido é fundamental para extrair os recursos corretos.

Usando o OpenCV, podemos converter o espaço de cores de uma imagem em uma das várias opções fornecidas, como HSV, LAB, Grayscale, YCrCb, CMYK, etc. Uma análise simples de cada espaço de cores:

a. HSV (valor de saturação de matiz)

  • Matiz : Descreve o comprimento de onda dominante e é o canal da cor especificada

  • Saturação : Descreve o matiz/pureza/matiz de uma cor

  • Valor : Descreve a intensidade da cor

import cv2  
from google.colab.patches import cv2\_imshow  
  
image = cv2.imread\(image\_file\)  
hsv\_image = cv2.cvtColor\(image, cv2.COLOR\_BGR2HSV\)  
cv2\_imshow\(hsv\_image\) 

 

Espaços de cores RGB e HSV

b. LAB

  • L : Descreve a leveza de uma cor, usada de forma intercambiável com intensidade

  • A  : Gama de componentes de cor, de verde a magenta

  • B : componentes de cor de azul a amarelo

import cv2  
from google.colab.patches import cv2\_imshow  
  
image = cv2.imread\(image\_file\)  
lab\_image = cv2.cvtColor\(image, cv2.COLOR\_BGR2LAB\)  
cv2\_imshow\(lab\_image\) 

 

Espaços de cores RGB e LAB

YCrCb

  • Y  : Brilho obtido do espaço de cores RGB após a correção gama

  • Cr : Descreve a distância do componente vermelho (R) do brilho

  • Cb : Descreve a distância entre o componente azul (B) e o brilho

import cv2  
from google.colab.patches import cv2\_imshow  
  
image = cv2.imread\(image\_file\)  
ycrcb\_image = cv2.cvtColor\(image, cv2.COLOR\_BGR2YCrCb\)  
cv2\_imshow\(ycrcb\_image\) 

 

Espaços de cores RGB e YCrCb

A importância desses espaços de cores às vezes é subestimada. Para obter informações relevantes das imagens, esses espaços de cores oferecem a oportunidade de identificar se os recursos aparecem mais diferentes em cada imagem. A coisa mais louca sobre os espaços de cores é que podemos realizar adição/subtração com diferentes espaços de cores e você ficará surpreso com os resultados!

Outra função útil para explorar o espaço de cores de uma imagem é simplesmente usar *numpy.mean()*, que fornece a média de cada canal no espaço de cores no conjunto de dados da imagem. Isso é especialmente útil se quisermos ver qual canal no espaço de cores domina o conjunto de dados.

import cv2  
from google.colab.patches import cv2\_imshow  
import numpy as np  
import plotly.figure\_factory as ff  
  
# Check the distribution of red values   
red\_values = \[\]  
for i in range\(len\(images\)\):  
  red\_value = np.mean\(images\[i\]\[:, :, 0\]\)  
  red\_values.append\(red\_value\)  
  
# Check the distribution of green values   
green\_values = \[\]  
for i in range\(len\(images\)\):  
  green\_value = np.mean\(images\[i\]\[:, :, 1\]\)  
  green\_values.append\(green\_value\)  
  
# Check the distribution of blue values   
blue\_values = \[\]  
for i in range\(len\(images\)\):  
  blue\_value = np.mean\(images\[i\]\[:, :, 2\]\)  
  blue\_values.append\(blue\_value\)  
    
# Plotting the histogram  
fig = ff.create\_distplot\(\[red\_values, green\_values, blue\_values\], group\_labels=\["R", "G", "B"\], colors=\['red', 'green', 'blue'\]\)  
fig.update\_layout\(showlegend=True, template="simple\_white"\)  
fig.update\_layout\(title\_text='Distribution of channel values across images in RGB'\)  
fig.data\[0\].marker.line.color = 'rgb\(0, 0, 0\)'  
fig.data\[0\].marker.line.width = 0.5  
fig.data\[1\].marker.line.color = 'rgb\(0, 0, 0\)'  
fig.data\[1\].marker.line.width = 0.5  
fig.data\[2\].marker.line.color = 'rgb\(0, 0, 0\)'  
fig.data\[2\].marker.line.width = 0.5  
fig  

Depois de identificar ou explorar o espaço de cores da imagem o suficiente e determinar que estamos interessados ​​apenas em um único canal, podemos usar *cv2.inRange()* para mascarar os pixels indesejados. Isso é especialmente útil no espaço de cores HSV.

import cv2  
from google.colab.patches import cv2\_imshow  
  
# Reading the original image  
image\_spot = cv2.imread\(image\_file\)  
cv2\_imshow\(image\_spot\)  
  
# Converting it to HSV color space  
hsv\_image\_spot = cv2.cvtColor\(image\_spot, cv2.COLOR\_BGR2HSV\)  
cv2\_imshow\(hsv\_image\_spot\)  
  
# Setting the black pixel mask and perform bitwise\_and to get only the black pixels  
mask = cv2.inRange\(hsv\_image\_spot, \(0, 0, 0\), \(180, 255, 40\)\)  
masked = cv2.bitwise\_and\(hsv\_image\_spot, hsv\_image\_spot, mask=mask\)  
cv2\_imshow\(masked\)  

RGB vs HSV vs Imagens mascaradas usam cv2.inRange() para recuperar pontos pretos

Às vezes, podemos até usar *cv2.kmeans()_ para quantizar a cor de uma imagem, basicamente reduzindo a cor a alguns pixels puros. Dependendo do nosso objetivo, podemos usar _cv2.inRange()* para recuperar o pixel de destino. Normalmente, essa função funciona como um encanto na identificação de partes importantes de uma imagem, e sempre verifico essa função antes de passar para outros métodos de extração de recursos de cores.

import cv2  
from google.colab.patches import cv2\_imshow  
  
image\_spot\_reshaped = image\_spot.reshape\(\(image\_spot.shape\[0\] \* image\_spot.shape\[1\], 3\)\)  
  
# convert to np.float32  
Z = np.float32\(image\_spot\_reshaped\)  
# define criteria, number of clusters\(K\) and apply kmeans\(\)  
criteria = \(cv2.TERM\_CRITERIA\_EPS + cv2.TERM\_CRITERIA\_MAX\_ITER, 10, 1.0\)  
K = 2  
ret, label, center = cv2.kmeans\(Z, K, None, criteria, 10, cv2.KMEANS\_RANDOM\_CENTERS\)  
# Now convert back into uint8, and make original image  
center = np.uint8\(center\)  
res = center\[label.flatten\(\)\]  
res2 = res.reshape\(\(image\_spot.shape\)\)  
  
cv2\_imshow\(res2\) 

 

Use cv2.kmeans() para quantização de cores (K=2)

2. Forma

Depois de explorarmos totalmente os recursos de cores, podemos, em algum momento, querer extrair as formas da imagem.

Por exemplo, sua tarefa é distinguir diferentes tipos de taças de vinho. As cores podem não importar aqui, mas as formas podem nos dizer muito sobre elas.

Novamente, o que eu faria é converter a imagem em um espaço de cores diferente e ver se algum espaço de cores faz com que as bordas ou formas dos objetos se destaquem mais. Então, podemos usar *cv2.findContours()* para recuperar todos os contornos da imagem. A partir daqui, examinaremos todas as propriedades do contorno de interesse.

Idealmente, quando formos capazes de extrair os atributos corretos que definem a forma dos contornos, aplicaremos isso a todas as imagens no conjunto de dados e os dígitos extraídos se tornarão nosso novo conjunto de dados não-imagem. Veja como podemos reduzir a quantidade de dados para apenas uma coluna de recursos de forma e ainda ser capaz de explicar nossa imagem de taça de vinho?

Vamos explorar os muitos atributos que podemos extrair de contornos usando o OpenCV. Como foi mostrado antes, vou fornecer o link aqui para referência:

https://docs.opencv.org/3.4/dd/d49/tutorial_py_contour_features.html

  1. momento

  2. área de contorno

  3. perímetro de contorno

  4. aproximação de contorno

  5. casco convexo

  6. detecção de convexidade

  7. borda retangular

  8. Círculo circunscrito mínimo

  9. ajustar a elipse

  10. Ajustando uma linha reta

Em muitos casos, descobriu-se que cv2.HoughCircles() e cv2.SimpleBlobDetector() não forneciam resultados precisos ao detectar círculos. Uma das razões pode ser que os círculos na imagem pré-processada não são óbvios o suficiente. No entanto, cv2.SimpleBlobDetector() ainda fornece alguns filtros embutidos úteis, como inércia, convexidade, circularidade e área para recuperar círculos com a maior precisão possível.

3. Textura

Em algum momento, podemos querer extrair recursos de textura, pois esgotamos os recursos de cor e forma. Tanto a matriz de co-ocorrência de nível de cinza (GLCM) quanto o padrão binário local (LBP) são recursos de textura que usei, mas outros recursos de textura que você costuma usar também podem ser comentados abaixo, gostaria de saber!

a. GLCM

É difícil entender o conceito de GLCM especificamente em termos de imagens. Estatisticamente falando, o GLCM é um método de inspeção de textura que considera a relação espacial dos pixels. Ele funciona contando com que frequência pares de pixels com determinados valores e certas relações espaciais ocorrem em uma imagem, criando um GLCM e, em seguida, extraindo medidas estatísticas dessa matriz.

Um pacote fácil de usar que inclui a funcionalidade GLCM é o pacote _scikit-image_. No GLCM, também podemos derivar algumas estatísticas que descrevem mais sobre a textura, como:

  • Contraste : Mede a variação local da matriz de co-ocorrência em escala de cinza.

  • Correlação : Mede a probabilidade conjunta de ocorrência de um par de pixels especificado.

  • Quadrado : Fornece a soma dos quadrados dos elementos no GLCM. Também conhecido como uniformidade ou segundo momento angular.

  • Homogeneidade : Mede quão próxima a distribuição de elementos em um GLCM está da diagonal do GLCM.

import cv2  
from google.colab.patches import cv2\_imshow  
  
image\_spot = cv2.imread\(image\_file\)  
gray = cv2.cvtColor\(image\_spot, cv2.COLOR\_BGR2GRAY\)  
  
# Find the GLCM  
import skimage.feature as feature  
  
# Param:  
# source image  
# List of pixel pair distance offsets - here 1 in each direction  
# List of pixel pair angles in radians  
graycom = feature.greycomatrix\(gray, \[1\], \[0, np.pi/4, np.pi/2, 3\*np.pi/4\], levels=256\)  
  
# Find the GLCM properties  
contrast = feature.greycoprops\(graycom, 'contrast'\)  
dissimilarity = feature.greycoprops\(graycom, 'dissimilarity'\)  
homogeneity = feature.greycoprops\(graycom, 'homogeneity'\)  
energy = feature.greycoprops\(graycom, 'energy'\)  
correlation = feature.greycoprops\(graycom, 'correlation'\)  
ASM = feature.greycoprops\(graycom, 'ASM'\)  
  
print\("Contrast: \{\}".format\(contrast\)\)  
print\("Dissimilarity: \{\}".format\(dissimilarity\)\)  
print\("Homogeneity: \{\}".format\(homogeneity\)\)  
print\("Energy: \{\}".format\(energy\)\)  
print\("Correlation: \{\}".format\(correlation\)\)  
print\("ASM: \{\}".format\(ASM\)\)

Características obtidas da Matriz de Coocorrência de Nível de Cinza (GLCM)

b. LBP

Como já existem muitos artigos explicando o modo binário nativo, aqui para economizar seu tempo e compartilhar o link de referência aqui:

  • https://www.pyimagesearch.com/2015/12/07/local-binary-patterns-with-python-opencv/

  • https://towardsdatascience.com/face-recognition-how-lbph-works-90ec258c3d6b

Resumindo, LBP é um operador de textura que rotula os pixels de uma imagem limitando os pixels circundantes e representando-os com números binários. Para nossa surpresa, o LBP retornou uma imagem em tons de cinza que mostrava claramente as texturas da imagem. Aqui, tentamos dividir as operações dentro do LBP com base em nosso entendimento:

Para cada pixel central, tentamos comparar com os pixels circundantes e atribuir-lhes um rótulo se o pixel central for maior ou menor que os pixels circundantes. Como resultado, temos 8 rótulos ao redor e, mantendo um padrão consistente de sentido horário ou anti-horário em toda a imagem, os organizamos em uma matriz 2d e os convertemos em números binários. 

Essa matriz aparece depois que realizamos operações em cada pixel de toda a imagem. 

A partir daqui, podemos ver que a matriz resultante tem a mesma forma de nossa imagem original e podemos desenhar e exibir o LBP como se fosse uma imagem. whaosoft  aiot  http://143ai.com

import cv2  
from google.colab.patches import cv2\_imshow  
  
class LocalBinaryPatterns:  
  def \_\_init\_\_\(self, numPoints, radius\):  
    self.numPoints = numPoints  
    self.radius = radius  
  
  def describe\(self, image, eps = 1e-7\):  
    lbp = feature.local\_binary\_pattern\(image, self.numPoints, self.radius, method="uniform"\)  
    \(hist, \_\) = np.histogram\(lbp.ravel\(\), bins=np.arange\(0, self.numPoints+3\), range=\(0, self.numPoints + 2\)\)  
  
    # Normalize the histogram  
    hist = hist.astype\('float'\)  
    hist /= \(hist.sum\(\) + eps\)  
  
    return hist, lbp  
  
image = cv2.imread\(image\_file\)  
gray = cv2.cvtColor\(image, cv2.COLOR\_BGR2GRAY\)  
desc = LocalBinaryPatterns\(24, 8\)  
hist, lbp = desc.describe\(gray\)  
print\("Histogram of Local Binary Pattern value: \{\}".format\(hist\)\)  
  
contrast = contrast.flatten\(\)  
dissimilarity = dissimilarity.flatten\(\)  
homogeneity = homogeneity.flatten\(\)  
energy = energy.flatten\(\)  
correlation = correlation.flatten\(\)  
ASM = ASM.flatten\(\)  
hist = hist.flatten\(\)  
  
features = np.concatenate\(\(contrast, dissimilarity, homogeneity, energy, correlation, ASM, hist\), axis=0\)   
cv2\_imshow\(gray\)  
cv2\_imshow\(lbp\)  

 

Imagem em tons de cinza e representação LBP

Da mesma forma, podemos armazenar LBP em um histograma e tratá-lo como um recurso, que podemos inserir em um classificador para classificação. Adrian Rosebrock do PyImageSearch fez um exemplo incrível disso!

Não tenho muita experiência com recursos de textura, mas estou interessado em me aprofundar nisso depois de reunir mais informações e tentar implementá-los em meu projeto.

para concluir

Para resumir, neste artigo, é compartilhada a experiência de três recursos que foram utilizados em projetos anteriores, principalmente recursos de cor, forma e textura. Junto com o código e os resultados, tentando explicar por que dei cada passo. Espero que você tenha aprendido algo com os recursos da imagem, começando com cor, forma e textura.

 

Acho que você gosta

Origin blog.csdn.net/qq_29788741/article/details/131928623
Recomendado
Clasificación