in packages/ekyc-api/src/ekyc-api/Utils/LivenessChecker.cs [167:283]
public async Task<string> VerifyImageLiveness(string sessionId)
{
AWSXRayRecorder.Instance.BeginSubsegment("LivenessChecker::VerifyImageLiveness");
var config = new DynamoDBOperationConfig
{
OverrideTableName = Globals.SessionTableName
};
var session = await dynamoDbContext.LoadAsync<SessionObject>(sessionId, config);
var imaging = new Imaging(_amazonS3, _documentChecker);
Image nosePointImage;
if (session == null)
return $"Session with ID {sessionId} is not found.";
if (string.IsNullOrEmpty(session.documentImageKey))
return $"Document to verify for session {sessionId} is empty.";
var documentFaceCount = await GetFaceCount(session.documentImageKey, 3);
if (documentFaceCount == 0)
return $"No faces found on the document to verify for session {sessionId}.";
var documentToVerifyImage = await imaging.GetImageFromStorage(session.documentImageKey);
if (documentToVerifyImage == null)
return $"Invalid document to verify for session {sessionId}.";
if (string.IsNullOrEmpty(session.eyesClosedImageKey))
return $"Eyes closed image for session {sessionId} is empty.";
var eyesClosedFacesCount = await GetFaceCount(session.eyesClosedImageKey, 3);
if (eyesClosedFacesCount == 0)
return $"No faces found on the eyes closed image for session {sessionId}.";
var eyesClosedImage = await imaging.GetImageFromStorage(session.eyesClosedImageKey);
if (eyesClosedImage == null)
return $"Invalid eyes closed image for session {sessionId}.";
FaceDetail selfieFaceDetails;
if (string.IsNullOrEmpty(session.selfieImageKey))
return $"Selfie image for session {sessionId} is empty.";
var selfieFaceCount = await GetFaceCount(session.selfieImageKey, 2);
if (selfieFaceCount == 0 || selfieFaceCount > 1)
return $"There can only be one face on the selfie image for session {sessionId}.";
var headOnImage = await imaging.GetImageFromStorage(session.selfieImageKey);
if (headOnImage == null)
return $"Invalid selfie image for session {sessionId}.";
selfieFaceDetails = GetFaces(session.selfieImageKey).GetAwaiter().GetResult().FirstOrDefault();
var selfiePoseError = await VerifySelfieFacePose(selfieFaceDetails);
if (selfiePoseError != null)
return selfiePoseError;
if (string.IsNullOrEmpty(session.nosePointImageKey))
return $"Nose verification image for session {sessionId} is empty.";
var nosePointFaceCount = await GetFaceCount(session.nosePointImageKey);
if (nosePointFaceCount == 0)
return $"No faces found on the nose point image for session {sessionId}.";
nosePointImage = await imaging.GetImageFromStorage(session.nosePointImageKey);
if (nosePointImage == null)
return $"Invalid nose verification image for session {sessionId}.";
// Make sure the selfie image matches the document image
var similarFaces = await CompareFaces(session.selfieImageKey, session.documentImageKey);
if (!similarFaces.IsMatch)
return $"The face on the document does not meet the selfie for session {sessionId}.";
// Check that the eyes are closed on the eyes closed image
similarFaces = await CompareFaces(session.eyesClosedImageKey, session.selfieImageKey);
if (!similarFaces.IsMatch)
return $"Eyes closed image does not match the selfie image for session {sessionId}";
var eyesClosed = await VerifyClosedEyes(session.eyesClosedImageKey);
if (!eyesClosed)
return $"Eyes are not closed for the verification image for session {sessionId}";
// Check that the nose is in the area of the image
similarFaces = await CompareFaces(session.nosePointImageKey, session.selfieImageKey);
if (!similarFaces.IsMatch)
return $"Nose verification image does not match the selfie image for session {sessionId}";
var noseVerifyResponse =
VerifyNoseLocation(session, nosePointImage, selfieFaceDetails).GetAwaiter().GetResult();
AWSXRayRecorder.Instance.EndSubsegment();
return noseVerifyResponse;
}