Main Content

Corregir una iluminación no uniforme y analizar objetos del primer plano

Este ejemplo muestra cómo mejorar una imagen como paso de preprocesamiento antes del análisis. En este ejemplo, se corrige la iluminación de fondo no uniforme y se convierte la imagen a una imagen binaria para que sea más fácil identificar objetos en el primer plano (granos individuales de arroz). Después, puede analizar los objetos, como encontrar el área de cada grano de arroz, y calcular estadísticas para todos los objetos de la imagen.

Preprocesar la imagen

Lea una imagen en el espacio de trabajo.

I = imread('rice.png');
imshow(I)

Figure contains an axes object. The axes object contains an object of type image.

La iluminación de fondo es más brillante en el centro de la imagen que en la parte inferior. Preprocese la imagen para hacer que la iluminación de fondo sea más uniforme.

Como primer paso, elimine todo el primer plano (granos de arroz) utilizando la apertura morfológica. La operación de apertura elimina objetos pequeños que no pueden contener por completo el elemento estructurante. Defina un elemento estructurante con forma de disco y con un radio de 15 que quepa por completo dentro de un único grano de arroz.

se = strel('disk',15)
se = 
strel is a disk shaped structuring element with properties:

      Neighborhood: [29x29 logical]
    Dimensionality: 2

Para realizar la apertura morfológica, utilice imopen con el elemento estructurante.

background = imopen(I,se);
imshow(background)

Figure contains an axes object. The axes object contains an object of type image.

Reste la imagen de aproximación de fondo, background, de la imagen original, I, y visualice la imagen resultante. Después de restar la imagen con el fondo ajustado de la imagen original, la imagen resultante tiene un fondo uniforme, pero es un poco oscura para el análisis.

I2 = I - background;
imshow(I2)

Figure contains an axes object. The axes object contains an object of type image.

Utilice imadjust para aumentar el contraste de la imagen procesada I2 saturando el 1% de los datos en las intensidades tanto bajas como elevadas y estirando los valores de intensidad para que abarquen el intervalo dinámico uint8.

I3 = imadjust(I2);
imshow(I3)

Figure contains an axes object. The axes object contains an object of type image.

Observe que los dos pasos anteriores se pueden sustituir por un paso único utilizando imtophat, que calcula primero la apertura morfológica y, después, la resta de la imagen original.

I2 = imtophat(I,strel('disk',15));

Cree una versión binaria de la imagen procesada para poder usar funciones de la toolbox para el análisis. Utilice la función imbinarize para convertir la imagen en escala de grises en una imagen binaria. Elimine el ruido de fondo de la imagen con la función bwareaopen.

bw = imbinarize(I3);
bw = bwareaopen(bw,50);
imshow(bw)

Figure contains an axes object. The axes object contains an object of type image.

Identificar objetos en la imagen

Ahora que ha creado una versión binaria de la imagen original, puede realizar análisis de objetos de la imagen.

Encuentre todos los componentes conectados (objetos) en la imagen binaria. La precisión de los resultados depende del tamaño de los objetos, del parámetro de conectividad (4, 8 o arbitrario) y de si hay objetos que se tocan (en cuyo caso se pueden etiquetar como un único objeto). Algunos de los granos de arroz de la imagen binaria bw se tocan.

cc = bwconncomp(bw,4)
cc = struct with fields:
    Connectivity: 4
       ImageSize: [256 256]
      NumObjects: 95
    PixelIdxList: {1x95 cell}

cc.NumObjects
ans = 95

Visualice el grano de arroz con la etiqueta 50 en la imagen.

grain = false(size(bw));
grain(cc.PixelIdxList{50}) = true;
imshow(grain)

Figure contains an axes object. The axes object contains an object of type image.

Visualice todos los componentes conectados en la imagen creando una matriz de etiquetas y, después, visualizándola como una imagen indexada de pseudocolor.

Utilice labelmatrix para crear una matriz de etiquetas a partir de la salida de bwconncomp. Observe que labelmatrix almacena la matriz de etiquetas en la clase numérica más pequeña necesaria para el número de objetos.

labeled = labelmatrix(cc);
whos labeled
  Name           Size             Bytes  Class    Attributes

  labeled      256x256            65536  uint8              

Utilice label2rgb para elegir el mapa de colores, el color de fondo y cómo los objetos de la matriz de etiquetas se asignan a los colores del mapa de colores. En la imagen de pseudocolor, la etiqueta que identifica cada objeto en la matriz de etiquetas se asigna a un color diferente en una matriz de mapa de colores asociada.

RGB_label = label2rgb(labeled,'spring','c','shuffle');
imshow(RGB_label)

Figure contains an axes object. The axes object contains an object of type image.

Calcular estadísticas basadas en áreas

Calcule el área de cada objeto de la imagen utilizando regionprops. Cada grano de arroz es un componente conectado en la estructura cc.

graindata = regionprops(cc,'basic')
graindata=95×1 struct array with fields:
    Area
    Centroid
    BoundingBox

Cree un vector grain_areas nuevo que contenga la medida de área de cada grano.

grain_areas = [graindata.Area];

Encuentre el área del componente n.º 50.

grain_areas(50)
ans = 194

Encuentre y muestre el grano con el área más pequeña.

[min_area, idx] = min(grain_areas)
min_area = 61
idx = 16
grain = false(size(bw));
grain(cc.PixelIdxList{idx}) = true;
imshow(grain)

Figure contains an axes object. The axes object contains an object of type image.

Utilice el comando histogram para crear un histograma de áreas de granos de arroz.

histogram(grain_areas)
title('Histogram of Rice Grain Area')

Figure contains an axes object. The axes object with title Histogram of Rice Grain Area contains an object of type histogram.

Consulte también

| | | | | | | | |