1//
2//  EXFaceDetectorUtils.m
3//  Exponent
4//
5//  Created by Stanisław Chmiela on 22.11.2017.
6//  Copyright © 2017 650 Industries. All rights reserved.
7//
8
9#import <EXFaceDetector/EXFaceDetectorUtils.h>
10#import <EXFaceDetector/EXCSBufferOrientationCalculator.h>
11
12NSString *const EXGMVDataOutputWidthKey = @"Width";
13NSString *const EXGMVDataOutputHeightKey = @"Height";
14
15static const NSString *kModeOptionName = @"mode";
16static const NSString *kDetectLandmarksOptionName = @"detectLandmarks";
17static const NSString *kRunClassificationsOptionName = @"runClassifications";
18static const NSString *kTrackingEnabled = @"tracking";
19
20@implementation EXFaceDetectorUtils
21
22+ (NSDictionary *)constantsToExport
23{
24  return @{
25           @"Mode" : @{
26               @"fast" : @(MLKFaceDetectorPerformanceModeFast),
27               @"accurate" : @(MLKFaceDetectorPerformanceModeAccurate)
28               },
29           @"Landmarks" : @{
30               @"all" : @(MLKFaceDetectorLandmarkModeAll),
31               @"none" : @(MLKFaceDetectorLandmarkModeNone)
32               },
33           @"Classifications" : @{
34               @"all" : @(MLKFaceDetectorClassificationModeAll),
35               @"none" : @(MLKFaceDetectorClassificationModeNone)
36               }
37           };
38}
39
40+ (BOOL)didOptionsChange:(MLKFaceDetectorOptions *)options
41             comparingTo:(MLKFaceDetectorOptions *)other
42{
43  return options.performanceMode == other.performanceMode &&
44  options.classificationMode == other.classificationMode &&
45  options.contourMode == other.contourMode &&
46  options.minFaceSize == other.minFaceSize &&
47  options.landmarkMode == other.landmarkMode &&
48  options.trackingEnabled == other.trackingEnabled;
49}
50
51+ (MLKFaceDetectorOptions *)createCopy:(MLKFaceDetectorOptions *)from
52{
53  MLKFaceDetectorOptions *options = [MLKFaceDetectorOptions new];
54  options.performanceMode = from.performanceMode;
55  options.classificationMode = from.classificationMode;
56  options.contourMode = from.contourMode;
57  options.minFaceSize = from.minFaceSize;
58  options.landmarkMode = from.landmarkMode;
59  options.trackingEnabled = from.trackingEnabled;
60  return options;
61}
62
63
64+ (MLKFaceDetectorOptions *) mapOptions:(NSDictionary*)options {
65  return [self newOptions:[MLKFaceDetectorOptions new] withValues:options];
66}
67
68+ (MLKFaceDetectorOptions *) newOptions:(MLKFaceDetectorOptions*)options withValues:(NSDictionary *)values
69{
70  MLKFaceDetectorOptions *result = [self createCopy:options];
71  if([values objectForKey:kModeOptionName]) {
72    result.performanceMode = [values[kModeOptionName] longValue];
73  }
74  if([values objectForKey:kDetectLandmarksOptionName]) {
75    result.landmarkMode = [values[kDetectLandmarksOptionName] longValue];
76  }
77  if([values objectForKey:kRunClassificationsOptionName]) {
78    result.classificationMode = [values[kRunClassificationsOptionName] longValue];
79  }
80  if([values objectForKey:kTrackingEnabled]) {
81    result.trackingEnabled = [values[kTrackingEnabled] boolValue];
82  }
83  return result;
84}
85
86+ (BOOL)areOptionsEqual:(MLKFaceDetectorOptions *)first to:(MLKFaceDetectorOptions*)second {
87  return [self didOptionsChange:first comparingTo:second];
88}
89
90+ (NSDictionary *)defaultFaceDetectorOptions
91{
92  return @{
93           kModeOptionName: @(MLKFaceDetectorPerformanceModeFast),
94           kDetectLandmarksOptionName: @(MLKFaceDetectorLandmarkModeNone),
95           kRunClassificationsOptionName: @(MLKFaceDetectorClassificationModeNone)
96           };
97}
98
99+ (int)toCGImageOrientation:(UIImageOrientation)imageOrientation
100{
101  switch (imageOrientation) {
102    case UIImageOrientationUp:
103      return kCGImagePropertyOrientationUp;
104    case UIImageOrientationUpMirrored:
105      return kCGImagePropertyOrientationUpMirrored;
106    case UIImageOrientationDown:
107      return kCGImagePropertyOrientationDown;
108    case UIImageOrientationDownMirrored:
109      return kCGImagePropertyOrientationDownMirrored;
110    case UIImageOrientationRight:
111      return kCGImagePropertyOrientationRight;
112    case UIImageOrientationRightMirrored:
113      return kCGImagePropertyOrientationRightMirrored;
114    case UIImageOrientationLeft:
115      return kCGImagePropertyOrientationLeft;
116    case UIImageOrientationLeftMirrored:
117      return kCGImagePropertyOrientationLeftMirrored;
118  }
119};
120
121# pragma mark - Encoder helpers
122
123+ (EXFaceDetectionAngleTransformBlock)angleTransformerFromTransform:(CGAffineTransform)transform
124{
125  return ^(float angle) {
126    return (float)(angle - (atan2(transform.b, transform.a) * (180 / M_PI)));
127  };
128}
129
130@end
131