Todos os produtos
Search
Central de documentação

Intelligent Media Management:Face clustering

Última atualização: Jun 27, 2026

A clusterização facial agrupa imagens com rostos semelhantes em um conjunto de dados. Cada cluster representa uma pessoa, permitindo localizar todas as fotos de um indivíduo específico em um único cluster.

Casos de uso comuns:

  • Álbuns faciais em unidades na nuvem -- Organize fotos automaticamente por pessoa para gerar álbuns personalizados.

  • Monitoramento residencial -- A clusterização facial registra os rostos dos membros da família. Quando o rosto de um estranho aparece, a clusterização falha e envia um alerta. Isso ajuda a identificar e lidar com pessoas e eventos perigosos o mais rápido possível, garantindo a segurança da sua família.

  • Gestão de clientes no varejo -- Elimine duplicatas de imagens de clientes para obter contagens precisas de tráfego e analise o comportamento de compra para marketing direcionado.

Como funciona

A clusterização facial segue um fluxo de trabalho de API em três etapas:

1. Index images         CreateBinding, IndexFileMeta, or BatchIndexFileMeta
        |
        v
2. Cluster faces        CreateFigureClusteringTask
        |
        v
3. Query results        QueryFigureClusters  -->  SimpleQuery (images per cluster)
  1. Indexe imagens em um conjunto de dados. Use CreateBinding para vinculação automática ou IndexFileMeta / BatchIndexFileMeta para indexação manual. Crie o conjunto de dados com CreateDataset.

  2. Execute a clusterização facial. Chame CreateFigureClusteringTask para agrupar rostos no conjunto de dados. Esta operação é incremental e processa apenas novas imagens desde a última execução.

  3. Consulte clusters e imagens. Utilize QueryFigureClusters para listar todos os clusters e, em seguida, use SimpleQuery para recuperar todas as imagens de um cluster específico.

Pré-requisitos

Antes de começar, certifique-se de que:

  • As imagens estejam indexadas em um conjunto de dados via CreateBinding, IndexFileMeta ou BatchIndexFileMeta

  • O conjunto de dados contenha pelo menos 3 imagens da mesma pessoa

  • Pelo menos 3 dessas imagens atendam aos requisitos de rosto em alta definição listados abaixo

Requisitos para rosto em alta definição

Critério

Limiar

Área do rosto

Maior que 75 x 75 pixels

HeadPose

Valor absoluto de cada elemento (Pitch, Roll, Yaw) menor que 30

FaceQuality

Maior que 0,8

Nota

Chame GetFileMeta para verificar o ângulo do rosto e os valores de qualidade das imagens indexadas.

Após a criação de um cluster, rostos que não atendem a esses limiares ainda podem ser adicionados ao mesmo cluster. Para mais detalhes, consulte FAQ sobre gerenciamento de imagens.

Criar uma tarefa de clusterização facial

Chame CreateFigureClusteringTask para clusterizar rostos nas imagens indexadas em um conjunto de dados. Esta operação gera apenas clusters e não modifica as imagens originais.

Importante

As informações da tarefa são retidas por 7 dias após o início da execução. Após esse período, as informações deixam de estar disponíveis. Use um dos métodos a seguir para recuperar os resultados da tarefa:

Exemplo de solicitação

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

Exemplo de resposta

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

Uma resposta bem-sucedida inclui um TaskId confirmando a criação da tarefa de clusterização.

Código de exemplo (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()

Consultar clusters faciais

Após a conclusão da clusterização, chame QueryFigureClusters para listar todos os clusters em um conjunto de dados. A resposta inclui os seguintes metadados para cada cluster:

Campo

Descrição

ObjectId

ID do cluster

FaceCount

Número de rostos no cluster

ImageCount

Número de imagens no cluster

Gender

Gênero estimado

AverageAge, MinAge, MaxAge

Estatísticas de idade

Cover

Imagem de capa com atributos faciais detalhados

Exemplo de solicitação

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

Exemplo de resposta

{
    "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-*****"
}

Neste exemplo, o conjunto de dados contém 2 clusters. O cluster Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6 possui 16 imagens, enquanto o cluster Cluster-856be781-bf5a-46d7-8494-8d7c44f5e282 contém 5 imagens.

Código de exemplo (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()

Consultar imagens em um cluster

Após obter as informações do cluster, chame SimpleQuery com o ID do cluster para listar todas as imagens nele contidas. O exemplo a seguir recupera imagens do cluster Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6.

Exemplo de solicitação

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

Exemplo de resposta

Nota

O cluster contém muitas imagens. O exemplo a seguir mostra os dados de uma única imagem.

{
    "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-****"
}

Este resultado indica que o cluster inclui uma imagem em oss://bucket1/1.jpg.

Código de exemplo (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()

Melhores práticas

Escolher uma frequência de clusterização

A operação CreateFigureClusteringTask é incremental, portanto não é necessário chamá-la após cada indexação de imagem. Duas abordagens recomendadas:

Abordagem

Como funciona

Quando usar

Polling agendado

Chame CreateFigureClusteringTask em cada conjunto de dados em intervalos regulares (por exemplo, a cada 5 minutos).

Configurações simples com baixo volume de indexação

Orientado a eventos com fila de atraso (recomendado)

Sempre que IndexFileMeta for chamado, envie o DatasetName para uma fila de atraso. Recupere os nomes dos conjuntos de dados periodicamente e chame CreateFigureClusteringTask pelo menos 10 segundos após a última chamada de IndexFileMeta para aquele conjunto de dados.

Ambientes de produção com indexação frequente

Considerar a latência assíncrona

A indexação de metadados é assíncrona. Projete a lógica da sua aplicação considerando estes atrasos típicos:

Operação

Latência típica

IndexFileMeta

~10 segundos

CreateFigureClusteringTask

Até 180 segundos (geralmente alguns segundos)

SimpleQuery (após operações assíncronas)

Aguarde pelo menos 10 segundos após a conclusão

Importante

A operação CreateFigureClusteringTask depende da IndexFileMeta para detectar rostos. Se você estiver inscrito nos resultados da IndexFileMeta via Simple Message Queue (anteriormente MNS), aguarde pelo menos 10 segundos após a conclusão da IndexFileMeta antes de chamar CreateFigureClusteringTask. Isso garante que as informações faciais mais recentes estejam disponíveis.

Perguntas frequentes

Por que a clusterização facial não gera nenhum cluster?

O conjunto de dados não atende aos requisitos mínimos. Deve haver pelo menos 3 imagens da mesma pessoa, e pelo menos 3 dessas imagens devem ter:

  • Área do rosto maior que 75 x 75 pixels

  • Valores de HeadPose (Pitch, Roll, Yaw) com valor absoluto menor que 30 cada

  • FaceQuality maior que 0,8

Depois que um cluster é criado, rostos adicionais que não atendem a esses limiares ainda podem ser adicionados a ele.

Como encontro o ID do cluster?

Chame QueryFigureClusters e verifique o campo ObjectId dentro de cada entrada no array FigureClusters.

Como consulto imagens em um cluster específico?

Chame SimpleQuery com o seguinte parâmetro Query, substituindo o ID do cluster pelo valor obtido em QueryFigureClusters:

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

Por que os clusters gerados não são pesquisáveis imediatamente?

A indexação e a clusterização são processos assíncronos. Após a conclusão de IndexFileMeta e CreateFigureClusteringTask, aguarde pelo menos 10 segundos antes de consultar resultados com SimpleQuery.

Como são tratadas imagens com múltiplos rostos?

Cada rosto em uma imagem é avaliado independentemente. Se uma imagem contiver vários rostos, cada um poderá ser atribuído a um cluster diferente com base em suas características.

Por que SimpleQuery retorna rostos de outros clusters ao filtrar por FigureClusterId?

SimpleQuery retorna resultados no nível da imagem, portanto todos os rostos e rótulos de uma imagem correspondente são incluídos. Para encontrar o rosto específico que pertence ao cluster, itere pelo array Figures em cada resultado e faça a correspondência pelo valor FigureClusterId. Isso fornece a posição, expressão, idade e outros atributos do rosto correspondente.

Como obtenho resultados de CreateFacesSearchingTask sem configurar notificações?

A operação CreateFacesSearchingTask retorna resultados apenas através de canais de notificação (Simple Message Queue, ApsaraMQ for RocketMQ ou EventBridge). GetTask recupera informações sobre o status da tarefa, mas não inclui os resultados da pesquisa.

Operações relacionadas

Operação

Descrição

CreateDataset

Criar um conjunto de dados

CreateBinding

Vincular uma source de dados OSS a um conjunto de dados para indexação automática

IndexFileMeta

Indexar metadados de arquivo em um conjunto de dados

BatchIndexFileMeta

Indexar metadados de arquivo em lote

CreateFigureClusteringTask

Criar uma tarefa de clusterização facial

QueryFigureClusters

Consultar todos os clusters faciais em um conjunto de dados

SimpleQuery

Consultar arquivos por condições (ex.: filtrar por ID de cluster)

GetFileMeta

Obter metadados de arquivo, incluindo qualidade e ângulo do rosto

GetTask

Obter status e informações da tarefa

ListTasks

Listar tarefas em um projeto