OpenCV ~ extracción de características

Aquí hay algunas formas de extraer características de color, forma y textura de las imágenes.

¿Cómo extraer características de las imágenes? La primera vez que escuché el término "extracción de características" fue en un video tutorial de aprendizaje automático en YouTube, que explicaba claramente cómo extraemos características en grandes conjuntos de datos.

Sencillamente, las columnas de un conjunto de datos son las características. Sin embargo, cuando me topé con el tema de la visión artificial, me quedé desconcertado cuando escuché que íbamos a extraer características de las imágenes. ¿Empiezas recorriendo cada columna de la imagen y sacas cada píxel?

Después de un tiempo, entendí el significado de la extracción de características en la visión artificial. La extracción de características es parte del proceso de reducción de dimensionalidad, donde un conjunto inicial de datos sin procesar se divide y reduce a grupos más manejables.

En términos simples, para una imagen, cada píxel es un dato, y lo que hace el procesamiento de imágenes es extraer información útil de la imagen, reduciendo así la cantidad de datos pero reteniendo los píxeles que describen las características de la imagen.

Todo lo que hace el procesamiento de imágenes es extraer información útil de una imagen, reduciendo la cantidad de datos pero preservando los píxeles que describen las características de la imagen.

En este artículo, exploremos varios métodos para extraer características de color, forma y textura de las imágenes. Estos métodos se basan en la experiencia de trabajar con imágenes, si hay algún error, no dude en agregarlo o corregirlo.

1. Color

Los espacios de color son automáticamente el primer lugar para explorar cada vez que trabaja en un proyecto de imagen. Comprender el espacio de color en el que se establece el entorno de la imagen es fundamental para extraer las características correctas.

Con OpenCV, podemos convertir el espacio de color de una imagen en una de varias opciones proporcionadas, como HSV, LAB, escala de grises, YCrCb, CMYK, etc. Un desglose simple de cada espacio de color:

a. HSV (valor de saturación de matiz)

  • Matiz : Describe la longitud de onda dominante y es el canal del color especificado

  • Saturación : describe el tono/pureza/tono de un color

  • Valor : Describe la intensidad del color.

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\) 

 

Espacios de color RGB y HSV

b. LABORATORIO

  • L : Describe la luminosidad de un color, usado indistintamente con intensidad

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

  • B : componentes de color de azul a amarillo

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\) 

 

Espacios de color RGB y LAB

YCrCb

  • Y  : Brillo obtenido del espacio de color RGB después de la corrección gamma

  • Cr : Describe la distancia del componente rojo (R) del brillo

  • Cb : Describe la distancia entre el componente azul (B) y el brillo

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\) 

 

Espacios de color RGB y YCrCb

A veces se subestima la importancia de estos espacios de color. Para obtener información relevante de las imágenes, estos espacios de color brindan la oportunidad de identificar si las características aparecen más diferentes en cada imagen. Lo más loco de los espacios de color es que podemos realizar sumas/restas con diferentes espacios de color y ¡te sorprenderán los resultados!

Otra función útil para explorar el espacio de color de una imagen es simplemente usar *numpy.mean()*, que proporciona la media de cada canal en el espacio de color del conjunto de datos de la imagen. Esto es especialmente útil si queremos ver qué canal en el espacio de color domina el conjunto de datos.

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  

Una vez que hayamos identificado o explorado lo suficiente el espacio de color de la imagen y determinado que solo estamos interesados ​​en un solo canal, podemos usar *cv2.inRange()* para enmascarar los píxeles no deseados. Esto es especialmente útil en el espacio de color 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\)  

Las imágenes RGB vs HSV vs Masked usan cv2.inRange() para recuperar puntos negros

A veces, incluso podemos usar *cv2.kmeans()_ para cuantificar el color de una imagen, esencialmente reduciendo el color a unos pocos píxeles limpios. Dependiendo de nuestro objetivo, podemos usar _cv2.inRange()* para recuperar el píxel objetivo. Por lo general, esta función funciona de maravilla para identificar partes importantes de una imagen, y siempre verifico esta función antes de pasar a otros métodos de extracción de características de color.

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 la cuantificación de color (K=2)

2. Forma

Una vez que hayamos explorado completamente las características de color, es posible que en algún momento queramos extraer las formas de la imagen.

Por ejemplo, su tarea es distinguir diferentes tipos de copas de vino. Puede que los colores no importen aquí, pero las formas pueden decirnos mucho sobre ellos.

Nuevamente, lo que haría sería convertir la imagen a un espacio de color diferente y ver si algún espacio de color hace que los bordes o las formas de los objetos se destaquen más. Luego, podemos usar *cv2.findContours()* para recuperar todos los contornos de la imagen. A partir de aquí, examinaremos todas las propiedades del contorno de interés.

Idealmente, una vez que podamos extraer los atributos correctos que definen la forma de los contornos, aplicaremos esto a todas las imágenes en el conjunto de datos, y los dígitos extraídos se convertirán en nuestro nuevo conjunto de datos sin imágenes. ¿Ve cómo podemos reducir la cantidad de datos a una sola columna de características de forma y aún así poder explicar nuestra imagen de copa de vino?

Exploremos los muchos atributos que podemos extraer de los contornos usando OpenCV. Como se ha mostrado antes, proporcionaré el enlace aquí como referencia:

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. aproximación de contorno

  5. casco convexo

  6. detección de convexidad

  7. borde rectangular

  8. Círculo circunscrito mínimo

  9. ajuste elipse

  10. Ajuste de una línea recta

En muchos casos, se encontró que tanto cv2.HoughCircles() como cv2.SimpleBlobDetector() no dieron resultados precisos al detectar círculos. Una de las razones puede ser que los círculos en la imagen preprocesada no son lo suficientemente obvios. Sin embargo, cv2.SimpleBlobDetector() todavía proporciona algunos filtros integrados útiles como inercia, convexidad, circularidad y área para recuperar círculos con la mayor precisión posible.

3. Textura

En algún momento, es posible que queramos extraer características de textura ya que hemos agotado las características de color y forma. Tanto la matriz de co-ocurrencia de nivel de gris (GLCM) como el patrón binario local (LBP) son características de textura que he usado, pero otras características de textura que usa comúnmente también se pueden comentar a continuación, ¡me gustaría saber!

a. GLCM

Es difícil entender el concepto de GLCM específicamente en términos de imágenes. Estadísticamente hablando, GLCM es un método de inspección de texturas que considera la relación espacial de los píxeles. Funciona contando con qué frecuencia se producen en una imagen pares de píxeles con ciertos valores y ciertas relaciones espaciales, creando un GLCM y luego extrayendo medidas estadísticas de esta matriz.

Un paquete fácil de usar que incluye la funcionalidad GLCM es el paquete _scikit-image_. En GLCM, también podemos derivar algunas estadísticas que describen más sobre la textura, como:

  • Contraste : mide la variación local de la matriz de coocurrencia en escala de grises.

  • Correlación : Mide la probabilidad conjunta de ocurrencia de un par de píxeles especificado.

  • Cuadrado : Proporciona la suma de los cuadrados de los elementos en el GLCM. También conocido como uniformidad o segundo momento angular.

  • Homogeneidad : mide qué tan cerca está la distribución de elementos en un GLCM a la diagonal del 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 obtenidas de Gray Level Co-occurrence Matrix (GLCM)

b. LBP

Como ya hay muchos artículos que explican el modo binario nativo, aquí para ahorrar tiempo y compartir el enlace de referencia aquí:

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

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

En pocas palabras, LBP es un operador de textura que etiqueta los píxeles de una imagen mediante el umbral de los píxeles circundantes y representándolos con números binarios. Para nuestra sorpresa, el LBP devolvió una imagen en escala de grises que mostraba claramente las texturas de la imagen. Aquí, tratamos de desglosar las operaciones dentro de LBP según nuestro entendimiento:

Para cada píxel central, tratamos de comparar con los píxeles circundantes y les damos una etiqueta si el píxel central es más grande o más pequeño que los píxeles circundantes. Como resultado, tenemos 8 etiquetas alrededor y, al mantener un patrón constante de sentido horario o antihorario en toda la imagen, las organizamos en una matriz 2d y las convertimos en números binarios. 

Tal matriz aparece después de que realizamos operaciones en cada píxel de la imagen completa. 

Desde aquí, podemos ver que la matriz resultante tiene la misma forma que nuestra imagen original, y podemos dibujar y mostrar el LBP como si fuera una imagen. ¿Qué software  es?  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\)  

 

Imagen en escala de grises y representación LBP

De manera similar, podemos almacenar LBP en un histograma y tratarlo como una característica, que podemos introducir en un clasificador para su clasificación. ¡Adrian Rosebrock de PyImageSearch hizo un increíble ejemplo de esto!

No tengo mucha experiencia con las funciones de textura, pero estoy interesado en profundizar en ellas después de recopilar más información e intentar implementarlas en mi proyecto.

en conclusión

En resumen, en este artículo se comparte la experiencia de tres características que se han utilizado en proyectos anteriores, principalmente las características de color, forma y textura. Junto con el código y los resultados, tratando de explicar por qué tomé cada paso. Con suerte, pudo aprender algo de las características de la imagen, comenzando con el color, la forma y la textura.

 

Supongo que te gusta

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