Clasificación de objetos en GPUs compatibles con OpenCL#
APOC se basa en pyclesperanto y scikit-learn. Permite clasificar objetos según propiedades/características medidas como intensidad, forma y número de células vecinas.
import apoc
from skimage.io import imread, imsave
import pyclesperanto_prototype as cle
import numpy as np
import matplotlib.pyplot as plt
Para la clasificación de objetos, necesitamos una imagen de intensidad y una imagen de etiquetas como entrada.
# load intensity image
image = imread('../../data/blobs.tif')
# segment the image
labels = cle.label(cle.threshold_otsu(image))
fig, axs = plt.subplots(1, 2)
cle.imshow(image, color_map="Greys_r", plot=axs[0])
cle.imshow(labels, labels=True, plot=axs[1])
Entrenamiento#
También necesitamos una imagen de anotación de verdad de terreno. Esta imagen es también una imagen de etiquetas con una anotación dispersa. Se dibujó una línea con valor 1 a través de todos los objetos que se supone que pertenecen a la clase 1. Se dibujó una línea con valor 2 a través de todos los objetos que deberían clasificarse como clase 2. Si la línea cruza el fondo, esto se ignora. En este ejemplo, los objetos se anotaron en tres clases:
Objetos alargados
Objetos redondeados
Objetos pequeños
annotation = cle.push(imread('../../data/label_annotation.tif'))
fig, axs = plt.subplots(1, 2)
cle.imshow(labels, labels=True, plot=axs[0])
cle.imshow(annotation, labels=True, plot=axs[1])
A continuación, necesitamos definir qué características queremos usar para clasificar objetos. Usaremos el área, la forma y la desviación estándar de la intensidad.
features = 'area mean_max_distance_to_centroid_ratio standard_deviation_intensity'
# Create an object classifier
filename = "../../data/blobs_object_classifier.cl"
classifier = apoc.ObjectClassifier(filename)
# train it; after training, it will be saved to the file specified above
classifier.train(features, labels, annotation, image)
Después de que el clasificador ha sido entrenado, podemos usarlo inmediatamente para predecir la clasificación de los objetos en la imagen.
# determine object classification
classification_result = classifier.predict(labels, image)
cle.imshow(classification_result, labels=True)
Predicción#
También puedes recargar el clasificador desde el disco y aplicarlo a otras imágenes. Simularemos esto rotando la imagen original. Esto es, por cierto, una buena comprobación de cordura para ver si la clasificación depende de la orientación de la imagen.
image2 = cle.rotate(image, angle_around_z_in_degrees=90)
labels2 = cle.rotate(labels, angle_around_z_in_degrees=90)
classifier2 = apoc.ObjectClassifier("../../data/blobs_object_classifier.cl")
classification_result2 = classifier2.predict(labels2, image2)
cle.imshow(classification_result2, labels=True)
Características disponibles para la clasificación de objetos#
Podemos imprimir todas las características disponibles. Los parámetros con un ? esperan un número en esa posición y se pueden especificar múltiples veces con múltiples valores.
apoc.list_available_object_classification_features()
['label',
'original_label',
'bbox_min_x',
'bbox_min_y',
'bbox_min_z',
'bbox_max_x',
'bbox_max_y',
'bbox_max_z',
'bbox_width',
'bbox_height',
'bbox_depth',
'min_intensity',
'max_intensity',
'sum_intensity',
'area',
'mean_intensity',
'sum_intensity_times_x',
'mass_center_x',
'sum_intensity_times_y',
'mass_center_y',
'sum_intensity_times_z',
'mass_center_z',
'sum_x',
'centroid_x',
'sum_y',
'centroid_y',
'sum_z',
'centroid_z',
'sum_distance_to_centroid',
'mean_distance_to_centroid',
'sum_distance_to_mass_center',
'mean_distance_to_mass_center',
'standard_deviation_intensity',
'max_distance_to_centroid',
'max_distance_to_mass_center',
'mean_max_distance_to_centroid_ratio',
'mean_max_distance_to_mass_center_ratio',
'touching_neighbor_count',
'average_distance_of_touching_neighbors',
'average_distance_of_n_nearest_neighbors=?',
'average_distance_of_n_nearest_neighbors=?']