unit Azure.CognitiveServices.FaceDetection.Types;

interface

uses
  System.SysUtils, System.Types;

{$SCOPEDENUMS ON}

type

  TAcsFaceAttributeType = (Accessories, Age, Blur, Emotion, Exposure,
    FacialHair, Gender, Glasses, Hair, HeadPose, Makeup, Noise, Occlusion,
    Smile, Mask);

  TAcsFaceAttributesTypes = set of TAcsFaceAttributeType;

  TAcsFaceRecognitionModel = (Recognition01, Recognition02, Recognition03,
    Recognition04);

  TAcsFaceDetectionModel = (Detection01, Detection02, Detection03);

  TAcsFaceDetectRequest = record
    ReturnFaceId: Boolean;
    ReturnFaceLandmarks: Boolean;
    ReturnFaceAttributes: TAcsFaceAttributesTypes;
    RecognitionModel: TAcsFaceRecognitionModel;
    ReturnRecognitionModel: Boolean;
    DetectionModel: TAcsFaceDetectionModel;
    FaceIdTimeToLive: Integer;
    ImageUrl: string;
    ImageData: TBytes;
    function GetDetectionModelName: string;
    function GetRecognitionModelName: string;
    function GetReturnFaceAttributesList: string;
  end;

  TAcsFaceRectangle = record
    Available: Boolean;
    Left: Integer;
    Top: Integer;
    Height: Integer;
    Width: Integer;
    function AsRect(): TRect;
  end;

  TAcsFaceLandmark = record
    Available: Boolean;
    X: Double;
    Y: Double;
  end;

  TAcsFaceLandmarks = record
    Available: Boolean;
    PupilLeft: TAcsFaceLandmark;
    PupilRight: TAcsFaceLandmark;
    NoseTip: TAcsFaceLandmark;
    MouthLeft: TAcsFaceLandmark;
    MouthRight: TAcsFaceLandmark;
    EyebrowLeftOuter: TAcsFaceLandmark;
    EyebrowLeftInner: TAcsFaceLandmark;
    EyeLeftOuter: TAcsFaceLandmark;
    EyeLeftTop: TAcsFaceLandmark;
    EyeLeftBottom: TAcsFaceLandmark;
    EyeLeftInner: TAcsFaceLandmark;
    EyebrowRightInner: TAcsFaceLandmark;
    EyebrowRightOuter: TAcsFaceLandmark;
    EyeRightInner: TAcsFaceLandmark;
    EyeRightTop: TAcsFaceLandmark;
    EyeRightBottom: TAcsFaceLandmark;
    EyeRightOuter: TAcsFaceLandmark;
    NoseRootLeft: TAcsFaceLandmark;
    NoseRootRight: TAcsFaceLandmark;
    NoseLeftAlarTop: TAcsFaceLandmark;
    NoseRightAlarTop: TAcsFaceLandmark;
    NoseLeftAlarOutTip: TAcsFaceLandmark;
    NoseRightAlarOutTip: TAcsFaceLandmark;
    UpperLipTop: TAcsFaceLandmark;
    UpperLipBottom: TAcsFaceLandmark;
    UnderLipTop: TAcsFaceLandmark;
    UnderLipBottom: TAcsFaceLandmark;
  end;

  TAcsFaceHeadPoseAttribute = record
    Available: Boolean;
    Pitch: Double;
    Roll: Double;
    Yaw: Double;
  end;

  TAcsFaceFacialHairAttribute = record
    Available: Boolean;
    Moustache: Double;
    Beard: Double;
    Sideburns: Double;
  end;

  TAcsFaceGenderType = (Male, Female);

  TAcsFaceGenderAttribute = record
    Available: Boolean;
    Gender: TAcsFaceGenderType;
  end;

  TAcsFaceGlassesType = (NoGlasses, ReadingGlasses, Sunglasses,
    SwimmingGoogles);

  TAcsFaceGlassesAttribute = record
    Available: Boolean;
    Glasses: TAcsFaceGlassesType;
  end;

  TAcsFaceEmotionAttribute = record
    Available: Boolean;
    Anger: Double;
    Contempt: Double;
    Disgust: Double;
    Fear: Double;
    Happiness: Double;
    Neutral: Double;
    Sadness: Double;
    Surprise: Double;
  end;

  TAcsFaceBlurLevel = (Low, Medium, High);

  TAcsFaceBlurAttribute = record
    Available: Boolean;
    BlurLevel: TAcsFaceBlurLevel;
    Value: Double;
  end;

  TAcsFaceExposureLevel = (GoodExposure, OverExposure, UnderExposure);

  TAcsFaceExposureAttribute = record
    Available: Boolean;
    ExposureLevel: TAcsFaceExposureLevel;
    Value: Double;
  end;

  TAcsFaceNoiseLevel = (Low, Medium, High);

  TAcsFaceNoiseAttribute = record
    Available: Boolean;
    NoiseLevel: TAcsFaceNoiseLevel;
    Value: Double;
  end;

  TAcsFaceMakeupAttribute = record
    Available: Boolean;
    EyeMakeup: Boolean;
    LipMakeup: Boolean;
  end;

  TAcsFaceOcclusionAttribute = record
    Available: Boolean;
    ForeheadOccluded: Boolean;
    EyeOccluded: Boolean;
    MouthOccluded: Boolean;
  end;

  TAcsFaceMaskType = (NoMask, FaceMask, OtherMaskOrOcclusion, Uncertain);

  TAcsFaceMaskAttribute = record
    Available: Boolean;
    MaskType: TAcsFaceMaskType;
    NoseAndMouthCovered: Boolean;
  end;

  TAcsFaceAccessory = record
    Available: Boolean;
    AccessoryType: string;
    Confidence: Double;
  end;

  TAcsFaceAccessories = array of TAcsFaceAccessory;

  TAcsFaceHairColor = record
    Available: Boolean;
    Color: string;
    Confidence: Double;
  end;

  TAcsFaceHairColors = array of TAcsFaceHairColor;

  TAcsFaceHairAttribute = record
    Available: Boolean;
    Bald: Double;
    Invisible: Boolean;
    HairColors: TAcsFaceHairColors;
  end;

  TAcsFaceSmileAttribute = record
    Available: Boolean;
    Smile: Double;
  end;

  TAcsFaceAgeAttribute = record
    Available: Boolean;
    Age: Double;
  end;

  TAcsFaceAttributes = record
    Available: Boolean;
    Smile: TAcsFaceSmileAttribute;
    HeadPose: TAcsFaceHeadPoseAttribute;
    Gender: TAcsFaceGenderAttribute;
    Age: TAcsFaceAgeAttribute;
    FacialHair: TAcsFaceFacialHairAttribute;
    Glasses: TAcsFaceGlassesAttribute;
    Emotion: TAcsFaceEmotionAttribute;
    Blur: TAcsFaceBlurAttribute;
    Exposure: TAcsFaceExposureAttribute;
    Noise: TAcsFaceNoiseAttribute;
    Makeup: TAcsFaceMakeupAttribute;
    Occlusion: TAcsFaceOcclusionAttribute;
    Hair: TAcsFaceHairAttribute;
    Accessories: TAcsFaceAccessories;
    Mask: TAcsFaceMaskAttribute;
  end;

  TAcsFaceRecognitionAttribute = record
    Available: Boolean;
    RecognitionModel: TAcsFaceRecognitionModel;
  end;

  TAcsFaceDetectResult = record
    FaceId: string;
    FaceRectangle: TAcsFaceRectangle;
    FaceLandmarks: TAcsFaceLandmarks;
    FaceAttributes: TAcsFaceAttributes;
    RecognitionAttribute: TAcsFaceRecognitionAttribute;
  end;

  TAcsFaceDetectResponse = record
    Faces: array of TAcsFaceDetectResult;
  end;
      
implementation

uses
  System.Rtti,
  Azure.CognitiveServices.ResourceStrings;

function TAcsFaceDetectRequest.GetDetectionModelName: string;
begin
  case DetectionModel of
    TAcsFaceDetectionModel.Detection01:
      Result := 'detection_01';
    TAcsFaceDetectionModel.Detection02:
      Result := 'detection_02';
    TAcsFaceDetectionModel.Detection03:
      Result := 'detection_03';
  else
    raise EArgumentException.Create(StrErrDetectionModelInvalid);
  end;
end;

function TAcsFaceDetectRequest.GetRecognitionModelName: string;
begin
  case RecognitionModel of
    TAcsFaceRecognitionModel.Recognition01:
      Result := 'recognition_01';
    TAcsFaceRecognitionModel.Recognition02:
      Result := 'recognition_02';
    TAcsFaceRecognitionModel.Recognition03:
      Result := 'recognition_03';
    TAcsFaceRecognitionModel.Recognition04:
      Result := 'recognition_04';
  else
    raise EArgumentException.Create(StrErrRecognitionModelInvalid);
  end;
end;

function TAcsFaceDetectRequest.GetReturnFaceAttributesList: string;
var
  LBuilder: TStringBuilder;
  LAttribute: TAcsFaceAttributeType;
begin
  LBuilder := TStringBuilder.Create;
  try
    for LAttribute in ReturnFaceAttributes do
    begin
      if LBuilder.Length > 0 then
        LBuilder.Append(',');
      LBuilder.Append(TRttiEnumerationType.GetName(LAttribute).ToLower());
    end;
    Result := LBuilder.ToString();
  finally
    LBuilder.Free;
  end;
end;

function TAcsFaceRectangle.AsRect: TRect;
begin
  Result := Rect(Left, Top, Left + Width, Top + Height);
end;

end.
