Exemples d’images ouvertes avec détection d’objet, segmentation d’instance et étiquettes de classification chargées dans l’application FiftyOne. Image reproduite avec l’aimable autorisation d’Open Images
L’ensemble de données Open Images de Google vient de bénéficier d’une mise à jour majeure. L’ensemble de données qui nous a donné plus d’un million d’images avec des annotations de détection, de segmentation, de classification et de relation visuelle en a ajouté 22,6 millions étiquettes de points couvrant 4171 classes.
Avec Open Images V7, les chercheurs de Google évoluent vers un nouveau paradigme de segmentation sémantique : plutôt que d’étiqueter de manière dense chaque pixel d’une image, ce qui entraîne des annotations coûteuses et chronophages, dans l’article qui l’accompagne, ils montrent que des annotations clairsemées d’un variété qu’ils dub pointillisme peut conduire à des performances de modèle comparables. Cet ajout à Open Images reflète l’évolution continue de la vision par ordinateur vers des approches centrées sur les données.
Dans cet article, nous allons vous montrer comment commencer à travailler avec Open Images V7 et les étiquettes de points et explorer certaines fonctionnalités du jeu de données. Pour cette exploration, nous utiliserons la bibliothèque open-source de vision par ordinateur FiftyOne, qui est l’un des outils officiels de téléchargement et de visualisation recommandés par l’équipe Open Images.
Pour une plongée approfondie dans Open Images V6, consultez cet article et ce didacticiel Medium. Continuez à lire pour un aperçu des étiquettes de points et comment naviguer dans les nouveautés d’Open Images V7 !
Chargement dans les données
La façon la plus simple de commencer est d’importer FiftyOne et de télécharger Open Images V7 depuis le FiftyOne Dataset Zoo.
## install if you haven't already
!pip install fiftyone
import fiftyone as fo
import fiftyone.zoo as foz
## load dataset
dataset = foz.load_zoo_dataset("open-images-v7")
Par défaut, cela téléchargera (si nécessaire) toutes les divisions des données – formation, test et validation – y compris tous les types d’étiquettes disponibles pour chacun et les métadonnées associées.
Comme pour l’ensemble de données Open Images V6 dans le FiftyOne Dataset Zoo, nous pouvons également spécifier les sous-ensembles de données que nous aimerions télécharger et charger ! Dans cet article, nous travaillerons avec la division de validation, qui se compose de 41 620 images. On peut télécharger et charger dans ce split dans FiftyOne en passant dans le split
argument:
import fiftyone as fo
import fiftyone.zoo as foz
dataset = foz.load_zoo_dataset(
"open-images-v7",
split="validation",
)
Si nous voulions seulement télécharger un millier d’images dans le but d’avoir une idée des données, nous pourrions le spécifier avec le max_samples
argument:
dataset = foz.load_zoo_dataset(
"open-images-v7",
split="validation",
max_samples=1000,
)
Examinons ces données en lançant l’application FiftyOne, une puissante interface utilisateur graphique qui vous permet de visualiser, de parcourir et d’interagir directement avec vos ensembles de données :
session = fo.launch_app(dataset)
Comme nous pouvons le voir, il se passe beaucoup de choses ici. Chacune de ces images comporte des cadres de délimitation d’objet, des masques de segmentation, des étiquettes de classification, des étiquettes de relation et des étiquettes de point. Cependant, toutes les images du jeu de données Open Images ne sont pas annotées avec chacun de ces types d’étiquettes. certaines images, par exemple, n’ont pas d’étiquettes de points. La raison pour laquelle les données que nous avons chargées contiennent tout cela est que, par défaut, FiftyOne donne la priorité au téléchargement d’images qui ont autant de types d’étiquettes que possible !
Si nous ne nous soucions que de certains types d’annotations, nous pouvons les isoler de plusieurs façons. Nous pouvons utiliser la barre latérale sur le côté gauche pour activer/désactiver les types d’étiquette :

Ou nous pouvons créer une vue des données en utilisant select_labels()
pour choisir les types d’étiquettes que nous voulons, puis les afficher dans l’application FiftyOne :
# create a view containing only point labels
points_view = dataset.select_labels(fields=”points”)
session.view = points_view.view()
Une autre alternative consiste à spécifier explicitement les types d’étiquettes que nous voulons lors du chargement de l’ensemble de données :
# only load point labels and detection labels
dataset = foz.load_zoo_dataset(
"open-images-v7",
split="validation",
max_samples=1000,
label_types=["points", "detections"],
)
À quoi ça sert?
Maintenant que nous avons chargé les données, essayons de mieux comprendre ce que sont ces étiquettes de points et ce qu’elles signifient réellement. Dans l’application FiftyOne, cliquez sur l’une des images dans l’exemple de grille et survolez l’un des points de l’image. Vous verrez une boîte qui répertorie les propriétés de cette étiquette de point. Dans un instant, nous les passerons en revue un par un, mais d’abord, un point crucial (sans jeu de mots) doit être fait.

En générant cet ensemble de données, les créateurs ont commencé à poser des questions oui/non pour savoir si un point donné correspond à une étiquette de classe donnée. Cela signifie que ces étiquettes de points sont pas étiquettes pour les classes qu’ils spécifient. Les étiquettes de points sont plutôt les étiquettes de classe sur lesquelles portaient les questions oui/non.
Si vous connaissez les versions précédentes de l’ensemble de données Open Images, cette notion vous est peut-être familière, car les étiquettes de classification suivent un modèle similaire, avec des étiquettes négatives et des étiquettes positives. Les étiquettes de points, cependant, sont légèrement plus nuancées que les étiquettes de classification.
Tout d’abord, différents points ont reçu différents nombres de votes totaux. Deuxièmement, les annotateurs ont été autorisés à voter comme des votes « oui », « non » ou « incertain » pour la même étiquette de classe. En conséquence, certaines étiquettes de points sont estimées comme incertaines !
Une dernière différence est que ces étiquettes de points ont été générées via deux méthodes différentes. Certaines des questions oui / non ont été répondues par des annotateurs humains, tandis que d’autres ont été «répondues» par un modèle qui prédit une classe de candidats.
Propriétés
label
: la classe de choses/choses à propos de laquelle la question oui/non a été poséeyes_votes
: le nombre de votes « oui » exprimés par les annotateursno_votes
: le nombre de votes « non » exprimés par les annotateursunsure_votes
: le nombre de votes « incertains » exprimés par les annotateursestimated_yes_no
: la meilleure estimation pour savoir si l’étiquette de classe correspond au point, compte tenu des votes expriméssource
: la méthode utilisée pour évaluer (voter pour) l’étiquette de classe, avec « ih » pour les annotateurs humains et « cc » pour la classe candidate prédite par le modèleid
: identifiant unique au sein de FiftyOne
A l’exception de la id
, toutes ces propriétés sont extraites directement des données brutes d’Open Images. Pour plus de détails sur ces propriétés, consultez l’article Open Images V7.
Dans FiftyOne, ces étiquettes de points sont représentées par des étiquettes de points clés, ce qui nous permet d’accéder, de filtrer et d’effectuer facilement des opérations sur ces étiquettes.
Pour un échantillon individuel, il est facile de lire ces données :

Nous pouvons également utiliser la classe d’agrégation et les capacités de filtrage de FiftyOne pour obtenir rapidement des statistiques récapitulatives sur l’ensemble de données (la répartition de validation que nous avons téléchargée dans la première section).
Nous pouvons calculer le nombre total de votes « oui », « non » et « incertain » sur tous les points :
Le nombre de votes « oui », « non » et « incertain » a été exprimé sur tous les échantillons dans la division de validation Open Images V7.
Et le nombre de fois qu’un point a eu un certain nombre de votes pour ces trois options :
Le vote compte pour les étiquettes de points individuelles dans la division de validation Open Images V7.
Utilisation de ViewField de FiftyOne avec from fiftyone import ViewField as F
nous pouvons également faire des choses comme compter le nombre total d’étiquettes de points :
dataset.sum(F("points.keypoints").length())
## 1483322
Et calculez efficacement le nombre d’étiquettes de points qui ont reçu au moins un vote « oui » et au moins un vote « non » :
dataset.filter_labels(
"points",
(F("yes_votes")!=0) & (F("no_votes")!=0)
).sum(F("point.keypoints").length())
## 147223
Points d’interêts
Maintenant que nous comprenons ce que sont ces étiquettes de points et comment accéder à leurs propriétés de base, discutons de la manière de masser les données sous une forme potentiellement plus utile pour le traitement en aval.
Une chose que nous pourrions vouloir faire est d’extraire un sous-ensemble de l’ensemble de données avec des étiquettes de points pour des classes particulières. Par exemple, supposons que nous travaillions sur un projet de conservation de la faune et que nous voulions former un modèle pour identifier les tortues et les tortues. Dans FiftyOne, il existe plusieurs façons d’y parvenir !
Si nous avons déjà chargé l’ensemble de données complet, nous pouvons filtrer les étiquettes de points pour les instances de « Tortue » ou « Tortue » et soit utiliser select_labels()
pour obtenir uniquement les étiquettes de points et peut-être les étiquettes de classification positive, ou nous pouvons désactiver le reste des étiquettes dans l’application FiftyOne, comme nous l’avons fait ici :

load_zoo_dataset()
méthode:turtle_dataset = foz.load_zoo_dataset(
"open-images-v7",
split="validation",
label_types=["points", "classifications"],
classes=["Turtle", "Tortoise"],
dataset_name="oi-turtle",
)
Une autre chose que nous pourrions vouloir faire est de transformer les votes bruts «oui», «non» et «incertain» qui ont été exprimés pour ces étiquettes de points en quelque chose de plus concret que nous pouvons utiliser pour former des modèles. Par souci de simplicité, disons que plutôt que d’utiliser le estimated_yes_no
données par les auteurs de l’ensemble de données, nous voulons générer des étiquettes de points « positives » et « négatives » en analogie directe avec les étiquettes de classification.
À titre d’exemple de flux de travail, nous pourrions imaginer que nous ne nous intéressons qu’aux votes d’étiquette de point exprimés par des annotateurs humains, et non aux classes candidates générées par des modèles. Et supposons en outre que pour garantir avec une forte probabilité que nos étiquettes de vérité terrain sont exactes, nous n’étiqueterons les points comme « positifs » ou « négatifs » que s’il y a au moins deux votes humains exprimés et que tous les votes sont d’accord. Voici une façon de procéder dans FiftyOne :
Tout d’abord, nous filtrerons les étiquettes de points pour les points avec plusieurs votes positifs, aucun vote négatif ou incertain, et source="ih"
et clonez cette vue dans un nouvel ensemble de données positive_dataset
,…