Files
react-native-firebase/packages/ml-vision/ios/RNFBMLVision/RNFBMLVisionFaceDetectorModule.m
2019-08-06 19:59:02 +01:00

150 lines
7.6 KiB
Objective-C

/**
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import <React/RCTUtils.h>
#import <RNFBApp/RNFBSharedUtils.h>
#import "RNFBMLVisionFaceDetectorModule.h"
#import "RNFBMLVisionCommon.h"
@implementation RNFBMLVisionFaceDetectorModule
#pragma mark -
#pragma mark Module Setup
RCT_EXPORT_MODULE();
#pragma mark -
#pragma mark Firebase ML Kit Vision Methods
RCT_EXPORT_METHOD(faceDetectorProcessImage:
(FIRApp *) firebaseApp
: (NSString *)filePath
: (NSDictionary *)faceDetectorOptions
: (RCTPromiseResolveBlock)resolve
: (RCTPromiseRejectBlock)reject
) {
[RNFBMLVisionCommon UIImageForFilePath:filePath completion:^(NSArray *errorCodeMessageArray, UIImage *image) {
if (errorCodeMessageArray != nil) {
[RNFBSharedUtils rejectPromiseWithUserInfo:reject userInfo:(NSMutableDictionary *) @{
@"code": errorCodeMessageArray[0],
@"message": errorCodeMessageArray[1],
}];
return;
}
FIRVisionImage *visionImage = [[FIRVisionImage alloc] initWithImage:image];
FIRVision *vision = [FIRVision visionForApp:firebaseApp];
FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init];
NSInteger *classificationMode = [faceDetectorOptions[@"classificationMode"] pointerValue];
if (classificationMode == (NSInteger *) 1) {
options.classificationMode = FIRVisionFaceDetectorClassificationModeNone;
} else if (classificationMode == (NSInteger *) 2) {
options.classificationMode = FIRVisionFaceDetectorClassificationModeAll;
}
NSInteger *contourMode = [faceDetectorOptions[@"contourMode"] pointerValue];
if (contourMode == (NSInteger *) 1) {
options.contourMode = FIRVisionFaceDetectorContourModeNone;
} else if (contourMode == (NSInteger *) 2) {
options.contourMode = FIRVisionFaceDetectorContourModeAll;
}
NSInteger *landmarkMode = [faceDetectorOptions[@"landmarkMode"] pointerValue];
if (landmarkMode == (NSInteger *) 1) {
options.landmarkMode = FIRVisionFaceDetectorLandmarkModeNone;
} else if (landmarkMode == (NSInteger *) 2) {
options.landmarkMode = FIRVisionFaceDetectorLandmarkModeAll;
}
NSInteger *performanceMode = [faceDetectorOptions[@"performanceMode"] pointerValue];
if (performanceMode == (NSInteger *) 1) {
options.performanceMode = FIRVisionFaceDetectorPerformanceModeFast;
} else if (performanceMode == (NSInteger *) 2) {
options.performanceMode = FIRVisionFaceDetectorPerformanceModeAccurate;
}
options.minFaceSize = (CGFloat) [faceDetectorOptions[@"minFaceSize"] doubleValue];
FIRVisionFaceDetector *faceDetector = [vision faceDetectorWithOptions:options];
[faceDetector processImage:visionImage completion:^(NSArray<FIRVisionFace *> *faces, NSError *error) {
if (error != nil) {
[RNFBSharedUtils rejectPromiseWithUserInfo:reject userInfo:(NSMutableDictionary *) @{
@"code": @"unknown",
@"message": [error localizedDescription],
}];
return;
}
NSMutableArray *facesFormatted = [[NSMutableArray alloc] init];
for (FIRVisionFace *face in faces) {
NSMutableDictionary *visionFace = [[NSMutableDictionary alloc] init];
visionFace[@"boundingBox"] = [RNFBMLVisionCommon rectToIntArray:face.frame];
visionFace[@"headEulerAngleY"] = face.hasHeadEulerAngleY ? @(face.headEulerAngleY) : @(-1);
visionFace[@"headEulerAngleZ"] = face.hasHeadEulerAngleZ ? @(face.headEulerAngleZ) : @(-1);
visionFace[@"leftEyeOpenProbability"] = face.hasLeftEyeOpenProbability ? @(face.leftEyeOpenProbability) : @(-1);
visionFace[@"rightEyeOpenProbability"] = face.hasRightEyeOpenProbability ? @(face.rightEyeOpenProbability) : @(-1);
visionFace[@"smilingProbability"] = face.hasSmilingProbability ? @(face.smilingProbability) : @(-1);
visionFace[@"trackingId"] = face.hasTrackingID ? @(face.trackingID) : @(-1);
// Contours
NSMutableArray *faceContours = [[NSMutableArray alloc] init];
if (contourMode == (NSInteger *) 2) {
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeAll]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeFace]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeLeftEyebrowTop]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeLeftEyebrowBottom]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeRightEyebrowTop]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeRightEyebrowBottom]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeLeftEye]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeRightEye]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeUpperLipTop]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeUpperLipBottom]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeLowerLipTop]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeLowerLipBottom]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeNoseBridge]]];
[faceContours addObject:[RNFBMLVisionCommon contourToDict:[face contourOfType:FIRFaceContourTypeNoseBottom]]];
}
visionFace[@"faceContours"] = faceContours;
// Face Landmarks
NSMutableArray *faceLandmarks = [[NSMutableArray alloc] init];
if (landmarkMode == (NSInteger *) 2) {
[faceLandmarks addObject:[RNFBMLVisionCommon landmarkToDict:[face landmarkOfType:FIRFaceLandmarkTypeMouthBottom]]];
[faceLandmarks addObject:[RNFBMLVisionCommon landmarkToDict:[face landmarkOfType:FIRFaceLandmarkTypeMouthRight]]];
[faceLandmarks addObject:[RNFBMLVisionCommon landmarkToDict:[face landmarkOfType:FIRFaceLandmarkTypeMouthLeft]]];
[faceLandmarks addObject:[RNFBMLVisionCommon landmarkToDict:[face landmarkOfType:FIRFaceLandmarkTypeRightEye]]];
[faceLandmarks addObject:[RNFBMLVisionCommon landmarkToDict:[face landmarkOfType:FIRFaceLandmarkTypeLeftEye]]];
[faceLandmarks addObject:[RNFBMLVisionCommon landmarkToDict:[face landmarkOfType:FIRFaceLandmarkTypeRightCheek]]];
[faceLandmarks addObject:[RNFBMLVisionCommon landmarkToDict:[face landmarkOfType:FIRFaceLandmarkTypeLeftCheek]]];
[faceLandmarks addObject:[RNFBMLVisionCommon landmarkToDict:[face landmarkOfType:FIRFaceLandmarkTypeNoseBase]]];
}
visionFace[@"landmarks"] = faceLandmarks;
[facesFormatted addObject:visionFace];
}
resolve(facesFormatted);
}];
}];
}
@end