Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Azure AI Face SDK beta2 #37044

Merged
merged 31 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2979994
codegen update
Han-msft Aug 27, 2024
269e116
Update client _patch
Han-msft Aug 27, 2024
6f89e05
Update version
Han-msft Aug 27, 2024
ed8876b
Update assets
Han-msft Aug 27, 2024
4a19c27
Update codegen
Han-msft Aug 28, 2024
492b67b
Sample for large face list
Han-msft Aug 28, 2024
0fc87db
Add LPG sample
Han-msft Aug 28, 2024
ae592ed
Update codegen
Han-msft Sep 2, 2024
d7a0393
Remove unused testcase
Han-msft Sep 2, 2024
99837e6
Add findsimilar test
Han-msft Sep 2, 2024
9315435
Add identify test
Han-msft Sep 3, 2024
453f812
Remove FL and PG
Han-msft Sep 6, 2024
2cf5745
Fix test
Han-msft Sep 6, 2024
d29b753
Update codegen
Han-msft Sep 9, 2024
c5d7ed8
Remove _operations
Han-msft Sep 9, 2024
a1d365e
Add changelog
Han-msft Sep 9, 2024
0ec1f1e
Codegen
Han-msft Sep 9, 2024
b96d74a
Add new content to README
Han-msft Sep 10, 2024
b0f98e5
Merge remote-tracking branch 'origin/main' into hachiang/face-v1.1
Han-msft Sep 13, 2024
3c2367c
Regen
Han-msft Sep 13, 2024
5fd08b6
Update model enum
Han-msft Sep 19, 2024
3b4be0b
Update typo in generated test
Han-msft Sep 19, 2024
8c39cc2
Add enum breaking change schangelog
Han-msft Sep 24, 2024
af693ed
Merge remote-tracking branch 'origin/main' into hachiang/face-v1.1
Han-msft Oct 9, 2024
e2cb5ac
update codegen
Han-msft Oct 9, 2024
6900326
Fix customization
Han-msft Oct 9, 2024
efb967b
Suppress verifytypes
Han-msft Oct 9, 2024
3d21d99
Update to latest tsp
Han-msft Oct 9, 2024
fc3fb85
Pause verifytypes
Han-msft Oct 9, 2024
7d58902
Update release date
Han-msft Oct 22, 2024
4fa8355
Update date
Han-msft Oct 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion sdk/face/azure-ai-vision-face/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,24 @@

### Features Added

- Added support for the Large Face List and Large Person Group:
- Added operation groups `LargeFaceListOperations` and `LargePersonGroupOperations` to `FaceAdministrationClient`.
- Added operations `find_similar_from_large_face_list`, `identify_from_large_person_group` and `verify_from_large_person_group` to `FaceClient`.
msyyc marked this conversation as resolved.
Show resolved Hide resolved
- Added models for supporting Large Face List and Large Person Group.
- Added support for latest Detect Liveness Session API:
- Added operations `get_session_image` and `detect_from_session_image` to `FaceSessionClient`.
- Added properties `enable_session_image` and `liveness_single_modal_model` to model `CreateLivenessSessionContent`.
- Added model `CreateLivenessWithVerifySessionContent`.

### Breaking Changes

### Bugs Fixed
- Changed the parameter of `create_liveness_with_verify_session` from model `CreateLivenessSessionContent` to `CreateLivenessWithVerifySessionContent`.
- Changed the enum value of `FaceDetectionModel`, `FaceRecognitionModel`, `LivenessModel` and `Versions`.

### Other Changes

- Change the default service API version to `v1.2-preview.1`.

## 1.0.0b1 (2024-05-28)

This is the first preview of the `azure-ai-vision-face` client library that follows the [Azure Python SDK Design Guidelines](https://azure.github.io/azure-sdk/python_design.html).
Expand Down
125 changes: 123 additions & 2 deletions sdk/face/azure-ai-vision-face/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The Azure AI Face service provides AI algorithms that detect, recognize, and ana
- Liveness detection
- Face recognition
- Face verification ("one-to-one" matching)
- Face identification ("one-to-many" matching)
- Find similar faces
- Group faces

Expand Down Expand Up @@ -130,6 +131,18 @@ face_client = FaceClient(endpoint, credential)
- Finding similar faces from a smaller set of faces that look similar to the target face.
- Grouping faces into several smaller groups based on similarity.

### FaceAdministrationClient

`FaceAdministrationClient` is provided to interact with the following data structures that hold data on faces and
person for Face recognition:

- `large_face_list`: It is a list of faces which can hold faces and used by [find similar faces][find_similar].
- It can up to 1,000,000 faces.
- Training (`begin_train()`) is required before calling `find_similar_from_large_face_list()`.
- `large_person_group`: It is a container which can hold person objects, and is used by face recognition.
- It can up to 1,000,000 person objects, with each person capable of holding up to 248 faces. The total person objects in all `large_person_group` should not exceed 1,000,000,000.
- For [face verification][face_verification], call `verify_from_large_person_group()`.
- For [face identification][face_identification], training (`begin_train()`) is required before calling `identify_from_large_person_group()`.

### FaceSessionClient

Expand All @@ -139,12 +152,23 @@ face_client = FaceClient(endpoint, credential)
- Query the liveness and verification result.
- Query the audit result.

### Long-running operations

Long-running operations are operations which consist of an initial request sent to the service to start an operation,
followed by polling the service at intervals to determine whether the operation has completed or failed, and if it has
succeeded, to get the result.

Methods that train a group (LargeFaceList or LargePersonGroup) are modeled as long-running operations.
The client exposes a `begin_<method-name>` method that returns an `LROPoller` or `AsyncLROPoller`. Callers should wait
for the operation to complete by calling `result()` on the poller object returned from the `begin_<method-name>` method.
Sample code snippets are provided to illustrate using long-running operations [below](#examples "Examples").

## Examples

The following section provides several code snippets covering some of the most common Face tasks, including:

* [Detecting faces in an image](#face-detection "Face Detection")
* [Identifying the specific face from a LargePersonGroup](#face-recognition-from-largepersongroup "Face Recognition from LargePersonGroup")
* [Determining if a face in an video is real (live) or fake (spoof)](#liveness-detection "Liveness Detection")

### Face Detection
Expand Down Expand Up @@ -173,8 +197,8 @@ with FaceClient(endpoint=endpoint, credential=AzureKeyCredential(key)) as face_c

result = face_client.detect(
file_content,
detection_model=FaceDetectionModel.DETECTION_03, # The latest detection model.
recognition_model=FaceRecognitionModel.RECOGNITION_04, # The latest recognition model.
detection_model=FaceDetectionModel.DETECTION03, # The latest detection model.
recognition_model=FaceRecognitionModel.RECOGNITION04, # The latest recognition model.
return_face_id=True,
return_face_attributes=[
FaceAttributeTypeDetection03.HEAD_POSE,
Expand All @@ -192,6 +216,103 @@ with FaceClient(endpoint=endpoint, credential=AzureKeyCredential(key)) as face_c
print(f"Face: {face.as_dict()}")
```

### Face Recognition from LargePersonGroup

Identify a face against a defined LargePersonGroup.

First, we have to use `FaceAdministrationClient` to create a `LargePersonGroup`, add a few `Person` to it, and then register faces with these `Person`.

```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.vision.face import FaceAdministrationClient, FaceClient
from azure.ai.vision.face.models import FaceDetectionModel, FaceRecognitionModel


def read_file_content(file_path: str):
with open(file_path, "rb") as fd:
file_content = fd.read()

return file_content


endpoint = "<your endpoint>"
key = "<your api key>"

large_person_group_id = "lpg_family"

with FaceAdministrationClient(endpoint=endpoint, credential=AzureKeyCredential(key)) as face_admin_client:
print(f"Create a large person group with id: {large_person_group_id}")
face_admin_client.large_person_group.create(
large_person_group_id, name="My Family", recognition_model=FaceRecognitionModel.RECOGNITION04
)

print("Create a Person Bill and add a face to him.")
bill_person_id = face_admin_client.large_person_group.create_person(
large_person_group_id, name="Bill", user_data="Dad"
).person_id
bill_image_file_path = "./samples/images/Family1-Dad1.jpg"
face_admin_client.large_person_group.add_face(
large_person_group_id,
bill_person_id,
read_file_content(bill_image_file_path),
detection_model=FaceDetectionModel.DETECTION03,
user_data="Dad-0001",
)

print("Create a Person Clare and add a face to her.")
clare_person_id = face_admin_client.large_person_group.create_person(
large_person_group_id, name="Clare", user_data="Mom"
).person_id
clare_image_file_path = "./samples/images/Family1-Mom1.jpg"
face_admin_client.large_person_group.add_face(
large_person_group_id,
clare_person_id,
read_file_content(clare_image_file_path),
detection_model=FaceDetectionModel.DETECTION03,
user_data="Mom-0001",
)
```

Before doing the identification, we need to train the LargePersonGroup first.
```python
print(f"Start to train the large person group: {large_person_group_id}.")
poller = face_admin_client.large_person_group.begin_train(large_person_group_id)

# Wait for the train operation to be completed.
# If the training status isn't succeed, an exception will be thrown from the poller.
training_result = poller.result()
```

When the training operation is completed successfully, we can identify the faces in this LargePersonGroup through
`FaceClient`.
```python
with FaceClient(endpoint=endpoint, credential=AzureKeyCredential(key)) as face_client:
# Detect the face from the target image.
target_image_file_path = "./samples/images/identification1.jpg"
detect_result = face_client.detect(
read_file_content(target_image_file_path),
detection_model=FaceDetectionModel.DETECTION03,
recognition_model=FaceRecognitionModel.RECOGNITION04,
return_face_id=True,
)
target_face_ids = list(f.face_id for f in detect_result)

# Identify the faces in the large person group.
result = face_client.identify_from_large_person_group(
face_ids=target_face_ids, large_person_group_id=large_person_group_id
)
for idx, r in enumerate(result):
print(f"----- Identification result: #{idx+1} -----")
print(f"{r.as_dict()}")
```

Finally, use `FaceAdministrationClient` to remove the large person group if you don't need it anymore.
```python
with FaceAdministrationClient(endpoint=endpoint, credential=AzureKeyCredential(key)) as face_admin_client:
print(f"Delete the large person group: {large_person_group_id}")
face_admin_client.large_person_group.delete(large_person_group_id)
```

### Liveness detection
Face Liveness detection can be used to determine if a face in an input video stream is real (live) or fake (spoof).
The goal of liveness detection is to ensure that the system is interacting with a physically present live person at
Expand Down
2 changes: 1 addition & 1 deletion sdk/face/azure-ai-vision-face/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "python",
"TagPrefix": "python/face/azure-ai-vision-face",
"Tag": "python/face/azure-ai-vision-face_f787b7aa30"
"Tag": "python/face/azure-ai-vision-face_0b4013000f"
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

from ._client import FaceAdministrationClient
from ._patch import FaceClient
from ._patch import FaceSessionClient
from ._version import VERSION
Expand All @@ -16,6 +17,7 @@
from ._patch import patch_sdk as _patch_sdk

__all__ = [
"FaceAdministrationClient",
Han-msft marked this conversation as resolved.
Show resolved Hide resolved
"FaceClient",
"FaceSessionClient",
]
Expand Down
120 changes: 109 additions & 11 deletions sdk/face/azure-ai-vision-face/azure/ai/vision/face/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,120 @@

from copy import deepcopy
from typing import Any, TYPE_CHECKING, Union
from typing_extensions import Self

from azure.core import PipelineClient
from azure.core.credentials import AzureKeyCredential
from azure.core.pipeline import policies
from azure.core.rest import HttpRequest, HttpResponse

from ._configuration import FaceClientConfiguration, FaceSessionClientConfiguration
from ._operations import FaceClientOperationsMixin, FaceSessionClientOperationsMixin
from ._configuration import (
FaceAdministrationClientConfiguration,
FaceClientConfiguration,
FaceSessionClientConfiguration,
)
from ._serialization import Deserializer, Serializer
from .operations import (
FaceClientOperationsMixin,
FaceSessionClientOperationsMixin,
LargeFaceListOperations,
LargePersonGroupOperations,
)

if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
from azure.core.credentials import TokenCredential


class FaceClient(FaceClientOperationsMixin): # pylint: disable=client-accepts-api-version-keyword
class FaceAdministrationClient:
"""FaceAdministrationClient.

:ivar large_face_list: LargeFaceListOperations operations
:vartype large_face_list: azure.ai.vision.face.operations.LargeFaceListOperations
:ivar large_person_group: LargePersonGroupOperations operations
:vartype large_person_group: azure.ai.vision.face.operations.LargePersonGroupOperations
:param endpoint: Supported Cognitive Services endpoints (protocol and hostname, for example:
https://{resource-name}.cognitiveservices.azure.com). Required.
:type endpoint: str
:param credential: Credential used to authenticate requests to the service. Is either a
AzureKeyCredential type or a TokenCredential type. Required.
:type credential: ~azure.core.credentials.AzureKeyCredential or
~azure.core.credentials.TokenCredential
:keyword api_version: API Version. Known values are "v1.2-preview.1" and None. Default value is
"v1.2-preview.1". Note that overriding this default value may result in unsupported behavior.
:paramtype api_version: str or ~azure.ai.vision.face.models.Versions
:keyword int polling_interval: Default waiting time between two polls for LRO operations if no
Retry-After header is present.
"""

def __init__(self, endpoint: str, credential: Union[AzureKeyCredential, "TokenCredential"], **kwargs: Any) -> None:
_endpoint = "{endpoint}/face/{apiVersion}"
self._config = FaceAdministrationClientConfiguration(endpoint=endpoint, credential=credential, **kwargs)
_policies = kwargs.pop("policies", None)
if _policies is None:
_policies = [
policies.RequestIdPolicy(**kwargs),
self._config.headers_policy,
self._config.user_agent_policy,
self._config.proxy_policy,
policies.ContentDecodePolicy(**kwargs),
self._config.redirect_policy,
self._config.retry_policy,
self._config.authentication_policy,
self._config.custom_hook_policy,
self._config.logging_policy,
policies.DistributedTracingPolicy(**kwargs),
policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
self._config.http_logging_policy,
]
self._client: PipelineClient = PipelineClient(base_url=_endpoint, policies=_policies, **kwargs)

self._serialize = Serializer()
self._deserialize = Deserializer()
self._serialize.client_side_validation = False
self.large_face_list = LargeFaceListOperations(self._client, self._config, self._serialize, self._deserialize)
self.large_person_group = LargePersonGroupOperations(
self._client, self._config, self._serialize, self._deserialize
)

def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs: Any) -> HttpResponse:
"""Runs the network request through the client's chained policies.

>>> from azure.core.rest import HttpRequest
>>> request = HttpRequest("GET", "https://www.example.org/")
<HttpRequest [GET], url: 'https://www.example.org/'>
>>> response = client.send_request(request)
<HttpResponse: 200 OK>

For more information on this code flow, see https://aka.ms/azsdk/dpcodegen/python/send_request

:param request: The network request you want to make. Required.
:type request: ~azure.core.rest.HttpRequest
:keyword bool stream: Whether the response payload will be streamed. Defaults to False.
:return: The response of your network call. Does not do error handling on your response.
:rtype: ~azure.core.rest.HttpResponse
"""

request_copy = deepcopy(request)
path_format_arguments = {
"endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
"apiVersion": self._serialize.url("self._config.api_version", self._config.api_version, "str"),
}

request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments)
return self._client.send_request(request_copy, stream=stream, **kwargs) # type: ignore

def close(self) -> None:
self._client.close()

def __enter__(self) -> Self:
self._client.__enter__()
return self

def __exit__(self, *exc_details: Any) -> None:
self._client.__exit__(*exc_details)


class FaceClient(FaceClientOperationsMixin):
"""FaceClient.

:param endpoint: Supported Cognitive Services endpoints (protocol and hostname, for example:
Expand All @@ -33,8 +131,8 @@ class FaceClient(FaceClientOperationsMixin): # pylint: disable=client-accepts-a
AzureKeyCredential type or a TokenCredential type. Required.
:type credential: ~azure.core.credentials.AzureKeyCredential or
~azure.core.credentials.TokenCredential
:keyword api_version: API Version. Default value is "v1.1-preview.1". Note that overriding this
default value may result in unsupported behavior.
:keyword api_version: API Version. Known values are "v1.2-preview.1" and None. Default value is
"v1.2-preview.1". Note that overriding this default value may result in unsupported behavior.
:paramtype api_version: str or ~azure.ai.vision.face.models.Versions
"""

Expand Down Expand Up @@ -94,15 +192,15 @@ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs:
def close(self) -> None:
self._client.close()

def __enter__(self) -> "FaceClient":
def __enter__(self) -> Self:
self._client.__enter__()
return self

def __exit__(self, *exc_details: Any) -> None:
self._client.__exit__(*exc_details)


class FaceSessionClient(FaceSessionClientOperationsMixin): # pylint: disable=client-accepts-api-version-keyword
class FaceSessionClient(FaceSessionClientOperationsMixin):
"""FaceSessionClient.

:param endpoint: Supported Cognitive Services endpoints (protocol and hostname, for example:
Expand All @@ -112,8 +210,8 @@ class FaceSessionClient(FaceSessionClientOperationsMixin): # pylint: disable=cl
AzureKeyCredential type or a TokenCredential type. Required.
:type credential: ~azure.core.credentials.AzureKeyCredential or
~azure.core.credentials.TokenCredential
:keyword api_version: API Version. Default value is "v1.1-preview.1". Note that overriding this
default value may result in unsupported behavior.
:keyword api_version: API Version. Known values are "v1.2-preview.1" and None. Default value is
"v1.2-preview.1". Note that overriding this default value may result in unsupported behavior.
:paramtype api_version: str or ~azure.ai.vision.face.models.Versions
"""

Expand Down Expand Up @@ -173,7 +271,7 @@ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs:
def close(self) -> None:
self._client.close()

def __enter__(self) -> "FaceSessionClient":
def __enter__(self) -> Self:
self._client.__enter__()
return self

Expand Down
Loading