全部產品
Search
文件中心

Intelligent Media Management:人臉聚類

更新時間:Mar 27, 2025

使用人臉聚類功能,您可以將資料集中存在相似人臉的多張圖片進行分組,適用於網盤的人臉相簿、家庭監控的陌生人檢測、甚至新零售的顧客管理等情境。人臉聚類後,您可以根據人臉分組查詢對應人員的所有圖片資訊。

應用情境

網盤人臉相簿

將網盤中的照片進行人臉聚類,按人臉進行分組,產生個人化的人臉相簿。

家庭監控

將家庭成員照片進行人臉聚類,當出現不能聚類的陌生人照片時及時預警,可有效管理環境安全,及時識別並處理危險人員及事件,保障家庭群體人身安全。

新零售顧客管理

將採集到的照片通過人臉聚類和去重可以獲得準確的客流量資料,分析顧客購買偏好進行精準營銷。

前提條件

建立人臉聚類任務

您可以調用CreateFigureClusteringTask - 建立人物聚類任務介面建立一個人臉聚類任務,在您已索引到資料集的圖片中,將屬於不同人物的人臉進行聚類分組。如下以對資料集test-dataset中的圖片進行人臉聚類分組為例。

說明

調用該介面建立分組任務不會對儲存的檔案做更改,僅產生分組資料。

重要

任務開始執行後,任務資訊只儲存7天,超過7天則無法再擷取。您可以通過以下幾種方式及時擷取任務資訊:

請求樣本

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

返回樣本

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

返回如上所示的樣本資訊,表示人臉聚類任務建立成功。

範例程式碼

# -*- 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:
        """
        使用AccessKey ID&AccessKey Secret初始化帳號Client。
        @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
        )
        # 填寫訪問的網域名稱。
        config.endpoint = f'imm.cn-beijing.aliyuncs.com'
        return imm20200930Client(config)

    @staticmethod
    def main() -> None:
        # 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
        # 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
        # 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。如何配置環境變數,請參見https://www.alibabacloud.com/help/document_detail/2361894.html。
        imm_access_key_id = os.getenv("AccessKeyId")
        imm_access_key_secret = os.getenv("AccessKeySecret")
        # 初始化用戶端。
        client = Sample.create_client(imm_access_key_id, imm_access_key_secret)
        # 構造請求。
        create_figure_clustering_task_request = imm_20200930_models.CreateFigureClusteringTaskRequest(
            # 填寫IMM專案名稱。
            project_name='test-project',
            # 填寫資料集名稱.
            dataset_name='test-dataset'
        )
        runtime = util_models.RuntimeOptions()
        try:
            # 複製代碼運行請自行列印API的傳回值.
            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()

查詢人臉分組資訊

人臉聚類任務建立成功後,您可以調用QueryFigureClusters - 查詢人物聚類介面,查詢分組的資訊,包括分組數量、各分組的圖片數量等。如下以查詢資料集test-dataset中的人臉聚類分組資訊為例。

請求樣本

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

返回樣本

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

該返回樣本顯示,此資料集中的人臉圖片被分為2組,其中一個分組ID為Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6,包含16張圖片;另一個分組ID為Cluster-856be781-bf5a-46d7-8494-8d7c44f5e282,包含5張圖片。

範例程式碼

# -*- 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:
        """
        使用AccessKey ID&AccessKey Secret初始化帳號Client。
        @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
        )
        # 填寫訪問的網域名稱。
        config.endpoint = f'imm.cn-beijing.aliyuncs.com'
        return imm20200930Client(config)

    @staticmethod
    def main() -> None:
        # 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
        # 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
        # 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。如何配置環境變數,請參見https://www.alibabacloud.com/help/document_detail/2361894.html。
        imm_access_key_id = os.getenv("AccessKeyId")
        imm_access_key_secret = os.getenv("AccessKeySecret")
        # 初始化用戶端。
        client = Sample.create_client(imm_access_key_id, imm_access_key_secret)
        # 構造請求。
        query_figure_clusters_request = imm_20200930_models.QueryFigureClustersRequest(
            # 填寫IMM專案名稱。
            project_name='test-project',
            # 填寫資料集名稱。
            dataset_name='test-dataset'
        )
        runtime = util_models.RuntimeOptions()
        try:
            # 列印API的傳回值。
            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()

查詢人臉分組中的圖片列表

查詢完分組資訊之後,您可以調用SimpleQuery - 簡單查詢介面,通過分組ID查詢某個分組中包含的所有圖片。如下以查詢資料集test-dataset中分組ID為Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6的人臉分組圖片資訊為例。

請求樣本

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

返回樣本

說明

由於圖片數量和資訊較多,如下樣本僅列舉分組中的一張圖片資訊。

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

返回樣本顯示,該分組中包含一張OSS地址為oss://bucket1/1.jpg的圖片

範例程式碼

# -*- 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:
        """
        使用AccessKey ID&AccessKey Secret初始化帳號Client。
        @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
        )
        # 填寫訪問的網域名稱。
        config.endpoint = f'imm.cn-beijing.aliyuncs.com'
        return imm20200930Client(config)

    @staticmethod
    def main() -> None:
        # 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
        # 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
        # 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。如何配置環境變數,請參見https://www.alibabacloud.com/help/document_detail/2361894.html。
        imm_access_key_id = os.getenv("AccessKeyId")
        imm_access_key_secret = os.getenv("AccessKeySecret")
        # 初始化用戶端。
        client = Sample.create_client(imm_access_key_id, imm_access_key_secret)
        # 構造請求。
        request = imm_20200930_models.SimpleQueryRequest()
        params = {
            # 設定查詢條件。
            "Query": {"Field": "Figures.FigureClusterId", "Operation": "eq", "Value": "Cluster-7bdbcedb-bd79-42e7-a1e2-b29a48532bd6"},
            # 填寫IMM專案名稱。
            "ProjectName": "test-project",
            # 填寫資料集名稱。
            "DatasetName": "test-dataset",
            # 設定最多返回100條查詢結果。
            "MaxResults": 100
        }
        request.from_map(params)
        runtime = util_models.RuntimeOptions()
        try:
            # 列印API的傳回值。
            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()

常見問題

人臉聚類為什麼無法產生人臉分組?

為了確保人臉分組的準確性,產生分組需要滿足如下條件:

  • 使用IndexFileMeta - 索引檔案元資訊介面將圖片添加到資料集。

  • 同一個人物在媒體集中的圖片必須大於或等於3張,並且至少有3張符合如下標準的高清人臉圖片:

    • 人臉尺寸大於75×75像素。

    • 人臉的偏轉角HeadPose的三個子項的絕對值均小於30°。

    • 人臉的品質FaceQuality大於0.8。

分組產生後,資料集中不符合上述高清人臉標準的圖片,仍有可能被劃分為同一組人臉。

如何查詢某個人臉分組中的圖片列表?

調用SimpleQuery - 簡單查詢介面,在參數Query傳入分組ID,可以查詢分組中的圖片列表,具體內容如下所示。

說明

您可以調用QueryFigureClusters - 查詢人物聚類介面擷取FigureClusters參數中的ObjectId,即為分組ID。

{
  "Field ": "Figures.FigureClusterId ",
  "Operation ": "eq ",
  "Value ": "人臉分組ID"
}

為什麼產生的人臉分組無法搜尋到?

由於中繼資料索引機制採用非同步處理,因此從圖片索引到人臉分組能夠被搜尋到需要一定的時間。因此,在設計商務邏輯時,請充分考慮延遲所帶來的資料一致性問題。

  • 圖片索引:通常調用IndexFileMeta - 索引檔案元資訊介面對圖片進行索引需要10秒 。

  • 人臉分組:調用CreateFigureClusteringTask - 建立人物聚類任務介面進行人臉聚類分組操作最多需要180秒。時間與單次索引的圖片數量相關,通常在數秒內完成。

    重要

    CreateFigureClusteringTask介面依賴IndexFileMeta介面來完成圖片中人臉的檢測。如果您通過MNS訊息訂閱了IndexFileMeta介面的調用結果,則在IndexFileMeta介面調用完成後,至少應等待10秒鐘再調用CreateFigureClusteringTask介面,以確保CreateFigureClusteringTask介面能夠擷取到最新的圖片中人臉資訊。

  • 調用IndexFileMeta、CreateFigureClusteringTask等非同步介面完成後,您可以通過SimpleQuery介面搜尋到最新結果,時間間隔為10秒。

每次索引圖片後都需要調用一次CreateFigureClusteringTask介面嗎?

不建議如此操作。CreateFigureClusteringTask - 建立人物聚類任務介面為增量分組介面,您可以在一批圖片完成索引後,一次性調用CreateFigureClusteringTask介面來進行批量聚類。推薦如下兩個方案:

  • 簡單方法:對每一個資料集,每隔固定間隔(例如5分鐘)調用一次CreateFigureClusteringTask介面進行聚類。

  • 更佳方案:每次調用IndexFileMeta - 索引檔案元資訊介面時,將對應的資料集推入一個延遲隊列,定時從該隊列中擷取DatasetName,即可得到有新圖片的資料集。在最後一次調用IndexFileMeta介面的10秒後調用CreateFigureClusteringTask介面。

一張圖片中有很多人會怎麼分組?

人臉聚類是基於人臉特徵維度進行分組的。若一張圖片中包含多個人物,則每個人臉均有可能被歸入某個特定組。

SimpleQuery介面按照聚類分組(FigureClusterId)搜尋,為什麼返回結果中有其他人臉?

SimpleQuery介面返回的維度是圖片,因此圖片內的所有人臉、標籤均會被返回。如果需要找到圖片中所搜尋的組(人物)的人臉資訊,請通過遍曆結果中的Figures欄位,並檢索其中的FigureClusterId和您搜尋的FigureClusterId一致的人臉Object,即可瞭解對應人臉的位置、表情、年齡等資訊。

使用IMM CreateFacesSearchingTask介面建立相似人臉搜尋任務,如果不配置Notification, 如何擷取搜尋結果?

使用CreateFacesSearchingTask介面建立相似人臉搜尋任務,目前只能通過Notification接收結果,GetTask只能查詢任務資訊,但是無法擷取搜尋結果。