Classification d’objets sur des GPU compatibles OpenCL#
APOC est basé sur pyclesperanto et scikit-learn. Il permet de classer des objets selon des propriétés / caractéristiques mesurées telles que l’intensité, la forme et le nombre de cellules voisines.
import apoc
from skimage.io import imread, imsave
import pyclesperanto_prototype as cle
import numpy as np
import matplotlib.pyplot as plt
Pour la classification d’objets, nous avons besoin d’une image d’intensité et d’une image d’étiquettes en entrée.
# 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])
Entraînement#
Nous avons également besoin d’une image d’annotation de vérité terrain. Cette image est aussi une image d’étiquettes avec une annotation éparse. Une ligne avec la valeur 1 a été tracée à travers tous les objets qui sont censés appartenir à la classe 1. Une ligne avec la valeur 2 a été tracée à travers tous les objets qui devraient être classés comme classe 2. Si la ligne traverse l’arrière-plan, cela est ignoré. Dans cet exemple, les objets ont été annotés en trois classes :
Objets allongés
Objets arrondis
Petits objets
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])
Ensuite, nous devons définir quelles caractéristiques nous voulons utiliser pour classer les objets. Nous utiliserons la surface, la forme et l’écart-type de l’intensité.
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)
Une fois que le classificateur a été entraîné, nous pouvons l’utiliser immédiatement pour prédire la classification des objets dans l’image.
# determine object classification
classification_result = classifier.predict(labels, image)
cle.imshow(classification_result, labels=True)
Prédiction#
Vous pouvez également recharger le classificateur depuis le disque et l’appliquer à d’autres images. Nous allons simuler cela en faisant pivoter l’image originale. C’est d’ailleurs un bon test de santé pour voir si la classification dépend de l’orientation de l’image.
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)
Caractéristiques disponibles pour la classification d’objets#
Nous pouvons afficher toutes les caractéristiques disponibles. Les paramètres avec un ? attendent un nombre à cette position et peuvent être spécifiés plusieurs fois avec plusieurs valeurs.
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=?']