Tous les produits
Search
Centre de documentation

Intelligent Media Management:Regroupement de visages

Dernière mise à jour :Oct 13, 2026

Le regroupement de visages rassemble les images contenant des visages similaires au sein d'un jeu de données. Chaque cluster représente une personne, ce qui vous permet de retrouver toutes les images d'une personne spécifique à partir d'un seul cluster.

Cas d'utilisation courants :

  • Albums photo cloud -- Organisez automatiquement les photos par personne pour générer des albums personnalisés.

  • Surveillance domestique -- Le regroupement de visages enregistre les visages des membres de la famille. Lorsqu'un visage inconnu apparaît, le processus échoue et envoie une alerte. Cela vous aide à identifier et gérer les personnes et événements dangereux dès que possible, garantissant ainsi la sécurité de vos proches.

  • Gestion de la clientèle dans le commerce de détail -- Dédupliquez les images clients pour obtenir des comptages de trafic précis, puis analysez le comportement d'achat pour un marketing ciblé.

Fonctionnement

Le regroupement de visages suit un flux de travail API en trois étapes :

1. Index images         CreateBinding, IndexFileMeta, or BatchIndexFileMeta
        |
        v
2. Cluster faces        CreateFigureClusteringTask
        |
        v
3. Query results        QueryFigureClusters  -->  SimpleQuery (images per cluster)
  1. Indexez les images dans un dataset. Utilisez CreateBinding pour une liaison automatique, ou IndexFileMeta / BatchIndexFileMeta pour une indexation manuelle. Créez le dataset avec CreateDataset.

  2. Exécutez le regroupement de visages. Appelez CreateFigureClusteringTask pour regrouper les visages du dataset. Cette opération est incrémentale : elle ne traite que les nouvelles images depuis la dernière exécution.

  3. Interrogez les clusters et les images. Utilisez QueryFigureClusters pour lister tous les clusters, puis utilisez SimpleQuery pour récupérer toutes les images d'un cluster spécifique.

Prérequis

Avant de commencer, assurez-vous que :

  • Les images sont indexées dans un dataset via CreateBinding, IndexFileMeta ou BatchIndexFileMeta

  • Le dataset contient au moins 3 images de la même personne

  • Au moins 3 de ces images répondent aux exigences de haute définition des visages listées ci-dessous

Exigences pour les visages haute définition

Critère Seuil
Zone du visage Supérieure à 75 x 75 pixels
HeadPose Valeur absolue de chaque élément (Pitch, Roll, Yaw) inférieure à 30
FaceQuality Supérieure à 0,8
Remarque

Appelez GetFileMeta pour vérifier l'angle et la qualité des visages pour les images indexées.

Une fois un cluster créé, les visages ne répondant pas à ces seuils peuvent toujours être ajoutés au même cluster. Pour plus de détails, consultez la rubrique FAQ sur la gestion des images.

Créer une tâche de regroupement de visages

Appelez CreateFigureClusteringTask pour regrouper les visages parmi les images indexées dans un dataset. Cette opération génère uniquement des clusters ; elle ne modifie pas les images originales.

Important

Les informations de tâche sont conservées pendant 7 jours après le démarrage de la tâche. Passé ce délai, les informations de tâche ne sont plus disponibles. Utilisez l'une des méthodes suivantes pour récupérer les résultats de la tâche :

Exemple de requête

{
    "ProjectName": "test-project",
    "DatasetName": "test-dataset"
}

Exemple de réponse

{
    "TaskId": "CreateFigureClusteringTask-ba5784b8-f61e-485d-8ea0-****",
    "RequestId": "42F4F8FD-006D-0EF0-8F2A-****",
    "EventId": "140-1L5dh6eSUErqdxV1ZvJ****"
}

Une réponse réussie inclut un TaskId confirmant la création de la tâche de regroupement.

Exemple de code (Python)

# -*- coding: utf-8 -*-

import os
from alibabacloud_imm20200930.client import Client as imm20200930Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_imm20200930 import models as imm_20200930_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient

class Sample:
    def __init__(self):
        pass

    @staticmethod
    def create_client(
        access_key_id: str,
        access_key_secret: str,
    ) -> imm20200930Client:
        """
        Initialize the IMM client with an AccessKey pair.
        @param access_key_id:
        @param access_key_secret:
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config(
            access_key_id=access_key_id,
            access_key_secret=access_key_secret
        )
        # Set the endpoint. Replace cn-beijing with your region.
        config.endpoint = f'imm.cn-beijing.aliyuncs.com'
        return imm20200930Client(config)

    @staticmethod
    def main() -> None:
        # Read AccessKey pair from environment variables.
        # Use a RAM user instead of the Alibaba Cloud account for security.
        # For details, see https://www.alibabacloud.com/help/document_detail/2361894.html
        imm_access_key_id = os.getenv("AccessKeyId")
        imm_access_key_secret = os.getenv("AccessKeySecret")
        # Initialize the client.
        client = Sample.create_client(imm_access_key_id, imm_access_key_secret)
        # Build the clustering request.
        create_figure_clustering_task_request = imm_20200930_models.CreateFigureClusteringTaskRequest(
            # IMM project name
            project_name='test-project',
            # Dataset name
            dataset_name='test-dataset'
        )
        runtime = util_models.RuntimeOptions()
        try:
            response = client.create_figure_clustering_task_with_options(
                create_figure_clustering_task_request, runtime)
            print(response.body.to_map())
        except Exception as error:
            UtilClient.assert_as_string(error.message)
            print(error)

if __name__ == '__main__':
    Sample.main()

Interroger les clusters de visages

Une fois le regroupement terminé, appelez QueryFigureClusters pour lister tous les clusters d'un dataset. La réponse inclut les métadonnées suivantes pour chaque cluster :

Champ Description
ObjectId ID du cluster
FaceCount Nombre de visages dans le cluster
ImageCount Nombre d'images dans le cluster
Gender Genre estimé
AverageAge, MinAge, MaxAge Statistiques d'âge
Cover Image de couverture avec attributs détaillés du visage

Exemple de requête

{
    "ProjectName": "test-project",
    "DatasetName": "test-dataset"
}

Exemple de réponse

{
    "FigureClusters": [
        {
            "AverageAge": 27.125,
            "Cover": {
                "Addresses": [],
                "AudioCovers": [],
                "AudioStreams": [],
                "CroppingSuggestions": [],
                "Figures": [
                    {
                        "Attractive": 0.9980000257492065,
                        "Beard": "none",
                        "BeardConfidence": 0.9959999918937683,
                        "Boundary": {
                            "Height": 270,
                            "Left": 573,
                            "Top": 104,
                            "Width": 202
                        },
                        "FaceQuality": 1.0,
                        "FigureId": "d7365ab8-1378-4bec-83cb-eccad8d11e0b",
                        "FigureType": "face",
                        "Glasses": "none",
                        "GlassesConfidence": 0.9990000128746033,
                        "Hat": "none",
                        "HatConfidence": 1.0,
                        "HeadPose": {
                            "Pitch": -0.7369999885559082,
                            "Roll": 2.5399999618530273,
                            "Yaw": 9.138999938964844
                        },
                        "Mask": "none",
                        "MaskConfidence": 0.7269999980926514,
                        "Mouth": "open",
                        "MouthConfidence": 0.9959999918937683,
                        "Sharpness": 1.0
                    }
                ],
                "ImageHeight": 683,
                "ImageWidth": 1024,
                "Labels": [],
                "OCRContents": [],
                "ObjectId": "170ffdeb36cec846f4214c78a0f3a0d4b7e37d0305370216ae780f7b8c72f871",
                "Subtitles": [],
                "URI": "oss://bucket1/photos/2.jpg",
                "VideoStreams": []
            },
            "CreateTime": "2022-07-12T16:41:19.336825716+08:00",
            "DatasetName": "dataset1",
            "FaceCount": 16,
            "Gender": "female",
            "ImageCount": 16,
            "MaxAge": 30.0,
            "MinAge": 23.0,
            "ObjectId": "Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6",
            "ObjectType": "figure-cluster",
            "OwnerId": "*****",
            "ProjectName": "test-project",
            "UpdateTime": "2022-09-19T17:08:59.374781532+08:00",
            "VideoCount": 0
        },
        {
            "AverageAge": 24.200000762939453,
            "Cover": {
                "Addresses": [],
                "AudioCovers": [],
                "AudioStreams": [],
                "CroppingSuggestions": [],
                "Figures": [
                    {
                        "Attractive": 0.9990000128746033,
                        "Beard": "none",
                        "BeardConfidence": 0.9990000128746033,
                        "Boundary": {
                            "Height": 266,
                            "Left": 301,
                            "Top": 218,
                            "Width": 196
                        },
                        "FaceQuality": 0.8859999775886536,
                        "FigureId": "f58bbdce-f3d1-4674-be6b-43d4b47c08e1",
                        "FigureType": "face",
                        "Glasses": "none",
                        "GlassesConfidence": 1.0,
                        "Hat": "none",
                        "HatConfidence": 1.0,
                        "HeadPose": {
                            "Pitch": 13.963000297546387,
                            "Roll": -12.21399974822998,
                            "Yaw": -6.2210001945495605
                        },
                        "Mask": "none",
                        "MaskConfidence": 0.7490000128746033,
                        "Mouth": "open",
                        "MouthConfidence": 0.9940000176429749,
                        "Sharpness": 1.0
                    }
                ],
                "ImageHeight": 1024,
                "ImageWidth": 683,
                "Labels": [],
                "OCRContents": [],
                "ObjectId": "b9c80e51aa95072413e2a0a6e5262644bc3cba14a4754f54f3fa9850c4d244f1",
                "Subtitles": [],
                "URI": "oss://bucket1/photos/11.jpg",
                "VideoStreams": []
            },
            "CreateTime": "2022-09-19T17:08:59.374932448+08:00",
            "DatasetName": "test-dataset",
            "FaceCount": 5,
            "Gender": "female",
            "ImageCount": 5,
            "MaxAge": 26.0,
            "MinAge": 22.0,
            "ObjectId": "Cluster-856be781-bf5a-46d7-8494-8d7c44f5e282",
            "ObjectType": "figure-cluster",
            "OwnerId": "*****",
            "ProjectName": "test-project",
            "UpdateTime": "2022-09-19T17:08:59.374932448+08:00",
            "VideoCount": 0
        }
    ],
    "NextToken": "",
    "TotalCount": 2,
    "RequestId": "42B3DD92-FE0D-09B7-B582-*****"
}

Dans cet exemple, le dataset contient 2 clusters. Le cluster Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6 contient 16 images, et le cluster Cluster-856be781-bf5a-46d7-8494-8d7c44f5e282 contient 5 images.

Exemple de code (Python)

# -*- coding: utf-8 -*-

import os
from alibabacloud_imm20200930.client import Client as imm20200930Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_imm20200930 import models as imm_20200930_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient

class Sample:
    def __init__(self):
        pass

    @staticmethod
    def create_client(
        access_key_id: str,
        access_key_secret: str,
    ) -> imm20200930Client:
        """
        Initialize the IMM client with an AccessKey pair.
        @param access_key_id:
        @param access_key_secret:
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config(
            access_key_id=access_key_id,
            access_key_secret=access_key_secret
        )
        # Set the endpoint. Replace cn-beijing with your region.
        config.endpoint = f'imm.cn-beijing.aliyuncs.com'
        return imm20200930Client(config)

    @staticmethod
    def main() -> None:
        # Read AccessKey pair from environment variables.
        # Use a RAM user instead of the Alibaba Cloud account for security.
        # For details, see https://www.alibabacloud.com/help/document_detail/2361894.html
        imm_access_key_id = os.getenv("AccessKeyId")
        imm_access_key_secret = os.getenv("AccessKeySecret")
        # Initialize the client.
        client = Sample.create_client(imm_access_key_id, imm_access_key_secret)
        # Build the query request.
        query_figure_clusters_request = imm_20200930_models.QueryFigureClustersRequest(
            # IMM project name
            project_name='test-project',
            # Dataset name
            dataset_name='test-dataset'
        )
        runtime = util_models.RuntimeOptions()
        try:
            response = client.query_figure_clusters_with_options(query_figure_clusters_request, runtime)
            print(response.body.to_map())
        except Exception as error:
            UtilClient.assert_as_string(error.message)
            print(error)

if __name__ == '__main__':
    Sample.main()

Interroger les images d'un cluster

Après avoir récupéré les informations du cluster, appelez SimpleQuery avec l'ID du cluster pour lister toutes les images de ce cluster. L'exemple suivant récupère les images du cluster Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6.

Exemple de requête

{
    "ProjectName": "test-project",
    "DatasetName": "test-dataset",
    "Query": "{\"Field\": \"Figures.FigureClusterId\", \"Operation\": \"eq\", \"Value\": \"Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6\"}",
    "MaxResults": 100
}

Exemple de réponse

Remarque

Le cluster contient de nombreuses images. L'exemple suivant montre les données d'une seule image.

{
    "Aggregations": [],
    "Files": [
        {
            "Addresses": [],
            "AudioCovers": [],
            "AudioStreams": [],
            "ContentMd5": "ViAbCBHAZgNU4zvs5****==",
            "ContentType": "image/jpeg",
            "CreateTime": "2022-07-12T15:57:47.792615815+08:00",
            "CroppingSuggestions": [],
            "DatasetName": "test-dataset",
            "ETag": "\"56201B0811C0660354E33BECE4C****\"",
            "EXIF": "****",
            "Figures": [
                {
                    "FaceQuality": 1.0,
                    "FigureClusterId": "Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6",
                    "FigureConfidence": 1.0,
                    "FigureId": "cd9139bf-f339-4ec2-b5fd-****",
                    "FigureType": "face",
                    "Glasses": "none",
                    "GlassesConfidence": 0.9990000128746033,
                    "Hat": "none",
                    "HatConfidence": 1.0,
                    "HeadPose": {
                        "Pitch": -0.8999999761581421,
                        "Roll": 1.1660000085830688,
                        "Yaw": 7.932000160217285
                    },
                    "Mask": "none",
                    "MaskConfidence": 0.6830000281333923,
                    "Mouth": "close",
                    "MouthConfidence": 0.7879999876022339,
                    "Sharpness": 1.0
                }
            ],
            "FileHash": "\"56201B0811C0660354E33BECE****\"",
            "FileModifiedTime": "2022-07-12T15:56:41+08:00",
            "Filename": "3.jpg",
            "ImageHeight": 1024,
            "ImageScore": {
                "OverallQualityScore": 0.7490000128746033
            },
            "ImageWidth": 683,
            "Labels": [
                {
                    "CentricScore": 0.8349999785423279,
                    "LabelConfidence": 1.0,
                    "LabelLevel": 2,
                    "LabelName": "\u7167\u7247\u62cd\u6444",
                    "Language": "zh-Hans",
                    "ParentLabelName": "\u827a\u672f\u54c1"
                }
            ],
            "MediaType": "image",
            "OCRContents": [],
            "OSSCRC64": "3400224321778591044",
            "OSSObjectType": "Normal",
            "OSSStorageClass": "Standard",
            "OSSTaggingCount": 0,
            "ObjectACL": "default",
            "ObjectId": "d132a61122c659f6fc1b42ecee1662aff358c7f1720027bead225****",
            "ObjectType": "file",
            "Orientation": 1,
            "OwnerId": "****",
            "ProduceTime": "2014-02-21T00:03:36+08:00",
            "ProjectName": "test-project",
            "Size": 187674,
            "Subtitles": [],
            "URI": "oss://bucket1/1.jpg",
            "UpdateTime": "2022-07-12T16:41:19.336736388+08:00",
            "VideoStreams": []
        }
    ],
    "NextToken": "",
    "RequestId": "84E4D242-8D15-0312-B976-****"
}

Ce résultat indique que le cluster inclut une image située à l'adresse oss://bucket1/1.jpg.

Exemple de code (Python)

# -*- coding: utf-8 -*-

import os
from alibabacloud_imm20200930.client import Client as imm20200930Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_imm20200930 import models as imm_20200930_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient

class Sample:
    def __init__(self):
        pass

    @staticmethod
    def create_client(
        access_key_id: str,
        access_key_secret: str,
    ) -> imm20200930Client:
        """
        Initialize the IMM client with an AccessKey pair.
        @param access_key_id:
        @param access_key_secret:
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config(
            access_key_id=access_key_id,
            access_key_secret=access_key_secret
        )
        # Set the endpoint. Replace cn-beijing with your region.
        config.endpoint = f'imm.cn-beijing.aliyuncs.com'
        return imm20200930Client(config)

    @staticmethod
    def main() -> None:
        # Read AccessKey pair from environment variables.
        # Use a RAM user instead of the Alibaba Cloud account for security.
        # For details, see https://www.alibabacloud.com/help/document_detail/2361894.html
        imm_access_key_id = os.getenv("AccessKeyId")
        imm_access_key_secret = os.getenv("AccessKeySecret")
        # Initialize the client.
        client = Sample.create_client(imm_access_key_id, imm_access_key_secret)
        # Build the query request.
        request = imm_20200930_models.SimpleQueryRequest()
        params = {
            # Filter by cluster ID
            "Query": {"Field": "Figures.FigureClusterId", "Operation": "eq", "Value": "Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6"},
            # IMM project name
            "ProjectName": "test-project",
            # Dataset name
            "DatasetName": "test-dataset",
            # Return up to 100 results
            "MaxResults": 100
        }
        request.from_map(params)
        runtime = util_models.RuntimeOptions()
        try:
            response = client.simple_query_with_options(request, runtime)
            print(response.body.to_map())
        except Exception as error:
            UtilClient.assert_as_string(error.message)
            print(error)

if __name__ == '__main__':
    Sample.main()

Bonnes pratiques

Choisir une fréquence de regroupement

CreateFigureClusteringTask est incrémental : il n'est pas nécessaire de l'appeler après chaque indexation d'image. Deux approches recommandées :

Approche Fonctionnement Quand l'utiliser
Interrogation planifiée Appelez CreateFigureClusteringTask sur chaque dataset à intervalles réguliers (par exemple, toutes les 5 minutes). Configurations simples avec un faible volume d'indexation
Piloté par les événements avec file d'attente différée (recommandé) À chaque appel de IndexFileMeta, poussez le DatasetName dans une file d'attente différée. Récupérez périodiquement les noms de datasets et appelez CreateFigureClusteringTask au moins 10 secondes après le dernier appel IndexFileMeta pour ce dataset. Environnements de production avec indexation fréquente

Prendre en compte la latence asynchrone

L'indexation des métadonnées est asynchrone. Concevez la logique de votre application en tenant compte de ces délais typiques :

Opération Latence typique
IndexFileMeta ~10 secondes
CreateFigureClusteringTask Jusqu'à 180 secondes (généralement quelques secondes)
SimpleQuery (après opérations asynchrones) Attendez au moins 10 secondes après la fin de l'opération
Important

CreateFigureClusteringTask dépend de IndexFileMeta pour détecter les visages. Si vous vous abonnez aux résultats de IndexFileMeta via Simple Message Queue (anciennement MNS), attendez au moins 10 secondes après la fin de IndexFileMeta avant d'appeler CreateFigureClusteringTask. Cela garantit que les dernières informations sur les visages sont disponibles.

FAQ

Pourquoi le regroupement de visages ne génère-t-il aucun cluster ?

Le dataset ne répond pas aux exigences minimales. Il doit contenir au moins 3 images de la même personne, et au moins 3 de ces images doivent présenter :

  • Une zone de visage supérieure à 75 x 75 pixels

  • Des valeurs HeadPose (Pitch, Roll, Yaw) dont la valeur absolue est inférieure à 30

  • Une FaceQuality supérieure à 0,8

Une fois un cluster créé, des visages supplémentaires ne répondant pas à ces seuils peuvent toujours être ajoutés à ce cluster.

Comment trouver l'ID du cluster ?

Appelez QueryFigureClusters et examinez le champ ObjectId dans chaque entrée du tableau FigureClusters.

Comment interroger les images d'un cluster spécifique ?

Appelez SimpleQuery avec le paramètre Query suivant, en remplaçant l'ID du cluster par la valeur obtenue via QueryFigureClusters :

{
    "Field": "Figures.FigureClusterId",
    "Operation": "eq",
    "Value": "Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6"
}

Pourquoi les clusters générés ne sont-ils pas immédiatement consultables ?

L'indexation et le regroupement sont asynchrones. Après la fin de IndexFileMeta et CreateFigureClusteringTask, attendez au moins 10 secondes avant d'interroger les résultats avec SimpleQuery.

Comment les images contenant plusieurs visages sont-elles gérées ?

Chaque visage d'une image est évalué indépendamment. Si une image contient plusieurs visages, chaque visage peut être attribué à un cluster différent en fonction de ses caractéristiques.

Pourquoi SimpleQuery renvoie-t-il des visages d'autres clusters lors du filtrage par FigureClusterId ?

SimpleQuery renvoie des résultats au niveau de l'image, donc tous les visages et libellés d'une image correspondante sont inclus. Pour trouver le visage spécifique appartenant au cluster, parcourez le tableau Figures de chaque résultat et faites correspondre la valeur FigureClusterId. Cela vous donne la position, l'expression, l'âge et d'autres attributs du visage correspondant.

Comment obtenir les résultats d'une tâche CreateFacesSearchingTask sans configurer de notifications ?

L'opération CreateFacesSearchingTask renvoie les résultats uniquement via des canaux de notification (Simple Message Queue, ApsaraMQ for RocketMQ ou EventBridge). GetTask récupère les informations sur le statut de la tâche mais n'inclut pas les résultats de recherche.

Opérations connexes

Opération Description
CreateDataset Créer un dataset
CreateBinding Lier une source de données OSS à un dataset pour une indexation automatique
IndexFileMeta Indexer les métadonnées de fichier dans un dataset
BatchIndexFileMeta Indexer par lot les métadonnées de fichier
CreateFigureClusteringTask Créer une tâche de regroupement de visages
QueryFigureClusters Interroger tous les clusters de visages d'un dataset
SimpleQuery Interroger des fichiers selon des conditions (par exemple, filtrer par ID de cluster)
GetFileMeta Obtenir les métadonnées de fichier, y compris la qualité et l'angle du visage
GetTask Obtenir le statut et les informations d'une tâche
ListTasks Lister les tâches d'un projet