├── LICENSE ├── README.md ├── actionscript └── src │ └── com │ └── marpies │ └── ane │ └── facedetection │ ├── Face.as │ ├── FaceDetection.as │ ├── FaceDetectionAccuracy.as │ └── FaceDetectionOptions.as ├── android ├── AndroidManifest.xml ├── build.gradle ├── libs │ ├── FlashRuntimeExtensions.jar │ ├── play-services-base-9.2.1.jar │ ├── play-services-basement-9.2.1.jar │ └── play-services-vision-9.2.1.jar └── src │ └── com │ └── marpies │ └── ane │ └── facedetection │ ├── FaceDetectionExtension.java │ ├── FaceDetectionExtensionContext.java │ ├── data │ └── FaceDetectionEvent.java │ ├── functions │ ├── BaseFunction.java │ ├── DetectFacesFunction.java │ ├── IsAvailableFunction.java │ ├── IsOperationalFunction.java │ └── SetLogEnabledFunction.java │ └── utils │ ├── AIR.java │ ├── BitmapDataUtils.java │ ├── FREObjectUtils.java │ ├── SafeFaceDetector.java │ └── StringUtils.java ├── bin ├── com.marpies.ane.facedetection.ane └── com.marpies.ane.facedetection.swc ├── build ├── build.properties ├── build.xml ├── extension.xml └── platform-ios.xml ├── docs ├── AC_OETags.js ├── all-classes.html ├── all-index-A.html ├── all-index-B.html ├── all-index-C.html ├── all-index-D.html ├── all-index-E.html ├── all-index-F.html ├── all-index-G.html ├── all-index-H.html ├── all-index-I.html ├── all-index-J.html ├── all-index-K.html ├── all-index-L.html ├── all-index-M.html ├── all-index-N.html ├── all-index-O.html ├── all-index-P.html ├── all-index-Q.html ├── all-index-R.html ├── all-index-S.html ├── all-index-T.html ├── all-index-U.html ├── all-index-V.html ├── all-index-W.html ├── all-index-X.html ├── all-index-Y.html ├── all-index-Z.html ├── asdoc.js ├── class-summary.html ├── com │ └── marpies │ │ └── ane │ │ └── facedetection │ │ ├── Face.html │ │ ├── FaceDetection.html │ │ ├── FaceDetectionAccuracy.html │ │ ├── FaceDetectionOptions.html │ │ ├── class-list.html │ │ └── package-detail.html ├── cookies.js ├── help.js ├── images │ ├── AirIcon12x12.gif │ ├── P_AlternativeMetadataIndicator_30x28_N.png │ ├── collapsed.gif │ ├── detailHeaderRule.jpg │ ├── detailSectionHeader.jpg │ ├── expanded.gif │ ├── inherit-arrow.gif │ ├── inheritedSummary.gif │ ├── logo.jpg │ ├── titleTableBottom.jpg │ ├── titleTableMiddle.jpg │ └── titleTableTop.jpg ├── index-list.html ├── index.html ├── override.css ├── package-frame.html ├── package-list.html ├── package-summary.html ├── print.css ├── style.css └── title-bar.html └── ios ├── FaceDetection.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── marpies.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── marpies.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── FaceDetection.xcscheme │ └── xcschememanagement.plist └── FaceDetection ├── Data └── FaceDetectionEvent.h ├── FaceDetection.h ├── FaceDetection.m ├── Frameworks └── AIRExtHelpers.framework │ ├── AIRExtHelpers │ └── Headers │ ├── FlashRuntimeExtensions.h │ ├── MPBitmapDataUtils.h │ ├── MPFREObjectUtils.h │ ├── MPMediaSource.h │ ├── MPStringUtils.h │ ├── MPUIApplicationDelegate.h │ └── MPUIApplicationListener.h ├── Functions ├── DetectFacesFunction.h ├── DetectFacesFunction.m ├── IsAvailableFunction.h ├── IsAvailableFunction.m ├── IsOperationalFunction.h ├── IsOperationalFunction.m ├── SetLogEnabledFunction.h └── SetLogEnabledFunction.m └── Utils ├── FaceDetectionHelper.h └── FaceDetectionHelper.m /README.md: -------------------------------------------------------------------------------- 1 | # Face Detection | Native extension for Adobe AIR (iOS & Android) 2 | 3 | #### Native extension providing ActionScript interface for [Google's Mobile Vision](https://developers.google.com/vision/) and [Apple's CoreImage](https://developer.apple.com/library/ios/documentation/CoreImage/Reference/CIDetector_Ref/index.html#//apple_ref/occ/cl/CIDetector) face detector APIs. 4 | 5 | Development of this extension is supported by [Master Tigra, Inc.](https://github.com/mastertigra) 6 | 7 | ## Getting started 8 | 9 | ### Additions to AIR descriptor 10 | 11 | First, add the extension's ID to the `extensions` element. 12 | 13 | ```xml 14 | 15 | com.marpies.ane.facedetection 16 | 17 | ``` 18 | 19 | If you are targeting Android, add the following extensions from [this repository](https://github.com/marpies/android-dependency-anes) as well (unless you know these libraries are included by some other extensions): 20 | 21 | ```xml 22 | 23 | com.marpies.ane.androidsupport 24 | com.marpies.ane.googleplayservices.base 25 | com.marpies.ane.googleplayservices.basement 26 | com.marpies.ane.googleplayservices.tasks 27 | com.marpies.ane.googleplayservices.vision 28 | 29 | ``` 30 | 31 | For Android support, modify `manifestAdditions` element so that it contains the following permission and meta data: 32 | 33 | ```xml 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | ]]> 49 | 50 | 51 | 52 | ``` 53 | 54 | > Adding the vision functionality dependency to your app's manifest will indicate to the installer that it should download the dependency on app install time. Although this is not strictly required, it can make the user experience better when initially running your app. 55 | 56 | > However, even if this is supplied, in some cases the dependencies required to run the detectors may be downloaded on demand when your app is run for the first time rather than at install time. 57 | 58 | Finally, add the [FaceDetection ANE](bin/com.marpies.ane.facedetection.ane) or [SWC](bin/com.marpies.ane.facedetection.swc) package from the [bin directory](bin/) to your project so that your IDE can work with it. The additional Android library ANEs are only necessary during packaging. 59 | 60 | ### API overview 61 | 62 | #### Debug logs 63 | 64 | You can enable extension debug logs during development using: 65 | 66 | ```as3 67 | FaceDetection.setLogEnabled( true ); 68 | ``` 69 | 70 | #### Detection 71 | 72 | When detecting faces in an image, you can provide [FaceDetectionOptions](actionscript/src/com/marpies/ane/facedetection/FaceDetectionOptions.as) object with the following properties: 73 | 74 | ```as3 75 | var options:FaceDetectionOptions = new FaceDetectionOptions(); 76 | // Face detection accuracy (high vs low) 77 | options.accuracy = FaceDetectionAccuracy.HIGH; 78 | // Set to true to enable detection of open eyes 79 | options.detectOpenEyes = true; 80 | // Set to true to enable detection of smile 81 | options.detectSmile = true; 82 | // (Android only) Indicates whether to detect all faces, or to only detect the most prominent face 83 | options.prominentFaceOnly = true; 84 | ``` 85 | 86 | To run the detection, call the [detect](actionscript/src/com/marpies/ane/facedetection/FaceDetection.as#L79-L106) method by passing in `BitmapData` of the image you want to process, a callback method and, optionally, the options object: 87 | 88 | ```as3 89 | FaceDetection.detect( bitmapData, onDetectionComplete, options ); 90 | ``` 91 | 92 | The detection process is asynchronous; the callback method is called once the process is finished successfully or with an error. The callback is expected to accept list of detected faces and a `String` that specifies an error message, in cases when a problem occurs. 93 | 94 | ```as3 95 | function onDetectionComplete( faces:Vector., errorMessage:String ):void { 96 | if( errorMessage == null ) { 97 | // process faces 98 | } else { 99 | // there was an error 100 | } 101 | } 102 | ``` 103 | 104 | #### Face object 105 | 106 | The [Face](actionscript/src/com/marpies/ane/facedetection/Face.as) object provides the following properties: 107 | 108 | ```as3 109 | // Rectangle representing the face's position and size 110 | face.bounds : Rectangle 111 | // Returns a value between 0.0 and 1.0 giving a probability that the face is smiling / has left/right eye open, 112 | // or -1.0 if the value was not computed. On iOS, these values are always either 0 or 1 113 | face.isSmilingProbability : Number 114 | face.leftEyeOpenProbability : Number 115 | face.rightEyeOpenProbability : Number 116 | // Position of the mouth in the image 117 | face.mouthPosition : Point 118 | // Eye positions - these are relative to the subject (person), i.e. left eye is the subject's left eye, 119 | // not the eye that is on the left when viewing the image 120 | face.leftEyePosition : Point 121 | face.rightEyePosition : Point 122 | 123 | // Android only - again, left/right are relative to the subject 124 | face.leftMouthPosition : Point 125 | face.leftEarPosition : Point 126 | face.leftEarTipPosition : Point 127 | face.leftCheekPosition : Point 128 | face.rightMouthPosition : Point 129 | face.rightEarPosition : Point 130 | face.rightEarTipPosition : Point 131 | face.rightCheekPosition : Point 132 | face.noseBasePosition : Point 133 | ``` 134 | 135 | #### isOperational : Boolean 136 | 137 | Checks whether the internal detector is operational. On Android, it checks whether necessary libraries have been downloaded, which means the detection may not work shortly after launching an app for the very first time. Unfortunately, there is no callback to find out when the libraries are ready, so *try again later* approach must be used. On iOS, it is always `true`. 138 | 139 | #### isAvailable : Boolean 140 | 141 | Checks whether *Google Play Services* APK is installed on the device. It is necessary for the detector to function properly. On iOS, it is always `true`. 142 | 143 | ## Requirements 144 | 145 | * iOS 7+ 146 | * Android 4+ 147 | * Adobe AIR 20+ 148 | 149 | ## Documentation 150 | Generated ActionScript documentation is available in the [docs](docs/) directory, or can be generated by running `ant asdoc` from the [build](build/) directory. 151 | 152 | ## Build ANE 153 | ANT build scripts are available in the [build](build/) directory. Edit [build.properties](build/build.properties) to correspond with your local setup. 154 | 155 | ## Author 156 | The ANE has been written by [Marcel Piestansky](https://twitter.com/marpies) and is distributed under [Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). 157 | 158 | ## Changelog 159 | 160 | #### March 22, 2018 (v1.0.3) 161 | 162 | * FIXED incorrect error message parsing (Android) 163 | 164 | #### August 25, 2016 (v1.0.2) 165 | 166 | * ADDED additional landmark positions to `Face` object 167 | 168 | #### August 10, 2016 (v1.0.1) 169 | 170 | * REMOVED `flash.external.ExtensionContext` dependency from SWC and SWF targeting default platform 171 | 172 | #### August 7, 2016 (v1.0.0) 173 | 174 | * Public release 175 | -------------------------------------------------------------------------------- /actionscript/src/com/marpies/ane/facedetection/FaceDetectionAccuracy.as: -------------------------------------------------------------------------------- 1 | package com.marpies.ane.facedetection { 2 | 3 | /** 4 | * Constants used to specify detection accuracy. 5 | */ 6 | public class FaceDetectionAccuracy { 7 | 8 | /** 9 | * Low accuracy detection settings. This will tend to detect fewer faces 10 | * and may be less precise in determining values such as position, but will run faster. 11 | */ 12 | public static const LOW:int = 0; 13 | /** 14 | * High accuracy detection settings. This will tend to detect more faces 15 | * and may be more precise in determining values such as position, at the cost of speed. 16 | */ 17 | public static const HIGH:int = 1; 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /actionscript/src/com/marpies/ane/facedetection/FaceDetectionOptions.as: -------------------------------------------------------------------------------- 1 | package com.marpies.ane.facedetection { 2 | 3 | /** 4 | * Object allowing to specify several face detection options. 5 | */ 6 | public class FaceDetectionOptions { 7 | 8 | private var mAccuracy:int; 9 | private var mDetectOpenEyes:Boolean; 10 | private var mDetectSmile:Boolean; 11 | private var mProminentFaceOnly:Boolean; 12 | 13 | /** 14 | * @private 15 | */ 16 | public function FaceDetectionOptions() { 17 | mAccuracy = FaceDetectionAccuracy.HIGH; 18 | } 19 | 20 | /** 21 | * Face detection accuracy. High accuracy will generally result in longer runtime. 22 | * Lower accuracy will generally result in detecting fewer faces. 23 | * 24 | * @default FaceDetectionAccuracy.HIGH 25 | * 26 | * @see com.marpies.ane.facedetection.FaceDetectionAccuracy 27 | */ 28 | public function get accuracy():int { 29 | return mAccuracy; 30 | } 31 | 32 | /** 33 | * @private 34 | */ 35 | public function set accuracy( value:int ):void { 36 | mAccuracy = value; 37 | } 38 | 39 | /** 40 | * Set to true to enable detection of open eyes. 41 | * 42 | * @default false 43 | */ 44 | public function get detectOpenEyes():Boolean { 45 | return mDetectOpenEyes; 46 | } 47 | 48 | /** 49 | * @private 50 | */ 51 | public function set detectOpenEyes( value:Boolean ):void { 52 | mDetectOpenEyes = value; 53 | } 54 | 55 | /** 56 | * Set to true to enable detection of smile. 57 | * 58 | * @default false 59 | */ 60 | public function get detectSmile():Boolean { 61 | return mDetectSmile; 62 | } 63 | 64 | /** 65 | * @private 66 | */ 67 | public function set detectSmile( value:Boolean ):void { 68 | mDetectSmile = value; 69 | } 70 | 71 | /** 72 | * Android only - Indicates whether to detect all faces, or to only detect the most prominent 73 | * face (i.e., a large face that is most central within the frame). By default, there is no limit in the number 74 | * of faces detected. Setting this value to true can increase the speed of the detector since the 75 | * detector does not need to search exhaustively for all faces. 76 | * 77 | * @default false 78 | */ 79 | public function get prominentFaceOnly():Boolean { 80 | return mProminentFaceOnly; 81 | } 82 | 83 | /** 84 | * @private 85 | */ 86 | public function set prominentFaceOnly( value:Boolean ):void { 87 | mProminentFaceOnly = value; 88 | } 89 | 90 | /** 91 | * @private 92 | */ 93 | internal function get isValid():Boolean { 94 | return (mAccuracy == FaceDetectionAccuracy.HIGH) || (mAccuracy == FaceDetectionAccuracy.LOW); 95 | } 96 | 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | 3 | buildscript { 4 | repositories { 5 | mavenCentral() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.1.+' 9 | } 10 | } 11 | 12 | 13 | apply plugin: 'com.android.library' 14 | 15 | dependencies { 16 | compile "com.google.android.gms:play-services-vision:9.2.1" 17 | compile files('libs/FlashRuntimeExtensions.jar') 18 | } 19 | 20 | android { 21 | defaultConfig { 22 | minSdkVersion 14 23 | targetSdkVersion 23 24 | } 25 | compileSdkVersion 23 26 | buildToolsVersion "23.0.3" 27 | 28 | lintOptions { 29 | abortOnError false 30 | } 31 | 32 | sourceSets { 33 | main { 34 | manifest { 35 | srcFile 'AndroidManifest.xml' 36 | } 37 | java { 38 | srcDir 'src' 39 | } 40 | } 41 | } 42 | } 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /android/libs/FlashRuntimeExtensions.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/android/libs/FlashRuntimeExtensions.jar -------------------------------------------------------------------------------- /android/libs/play-services-base-9.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/android/libs/play-services-base-9.2.1.jar -------------------------------------------------------------------------------- /android/libs/play-services-basement-9.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/android/libs/play-services-basement-9.2.1.jar -------------------------------------------------------------------------------- /android/libs/play-services-vision-9.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/android/libs/play-services-vision-9.2.1.jar -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/FaceDetectionExtension.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection; 18 | 19 | import com.adobe.fre.FREContext; 20 | import com.adobe.fre.FREExtension; 21 | import com.marpies.ane.facedetection.utils.AIR; 22 | 23 | public class FaceDetectionExtension implements FREExtension { 24 | 25 | @Override 26 | public void initialize() { } 27 | 28 | @Override 29 | public FREContext createContext( String s ) { 30 | AIR.setContext( new FaceDetectionExtensionContext() ); 31 | return AIR.getContext(); 32 | } 33 | 34 | @Override 35 | public void dispose() { 36 | AIR.setContext( null ); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/FaceDetectionExtensionContext.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection; 18 | 19 | import com.adobe.fre.FREContext; 20 | import com.adobe.fre.FREFunction; 21 | import com.marpies.ane.facedetection.functions.*; 22 | import com.marpies.ane.facedetection.utils.AIR; 23 | 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | 27 | public class FaceDetectionExtensionContext extends FREContext { 28 | 29 | @Override 30 | public Map getFunctions() { 31 | Map functions = new HashMap(); 32 | 33 | functions.put( "detect", new DetectFacesFunction() ); 34 | functions.put( "setLogEnabled", new SetLogEnabledFunction() ); 35 | functions.put( "isOperational", new IsOperationalFunction() ); 36 | functions.put( "isAvailable", new IsAvailableFunction() ); 37 | 38 | return functions; 39 | } 40 | 41 | @Override 42 | public void dispose() { 43 | AIR.setContext( null ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/data/FaceDetectionEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.data; 18 | 19 | public class FaceDetectionEvent { 20 | 21 | public static final String FACE_DETECTION_COMPLETE = "faceDetectionComplete"; 22 | public static final String FACE_DETECTION_ERROR = "faceDetectionError"; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/functions/BaseFunction.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.functions; 18 | 19 | import com.adobe.fre.FREContext; 20 | import com.adobe.fre.FREFunction; 21 | import com.adobe.fre.FREObject; 22 | import com.marpies.ane.facedetection.FaceDetectionExtensionContext; 23 | import com.marpies.ane.facedetection.utils.AIR; 24 | 25 | public class BaseFunction implements FREFunction { 26 | 27 | @Override 28 | public FREObject call( FREContext context, FREObject[] args ) { 29 | AIR.setContext( (FaceDetectionExtensionContext) context ); 30 | return null; 31 | } 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/functions/DetectFacesFunction.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.functions; 18 | 19 | import android.app.Activity; 20 | import android.graphics.Bitmap; 21 | import android.util.SparseArray; 22 | import com.adobe.fre.FREBitmapData; 23 | import com.adobe.fre.FREContext; 24 | import com.adobe.fre.FREObject; 25 | import com.google.android.gms.vision.Detector; 26 | import com.google.android.gms.vision.Frame; 27 | import com.google.android.gms.vision.face.Face; 28 | import com.google.android.gms.vision.face.FaceDetector; 29 | import com.google.android.gms.vision.face.Landmark; 30 | import com.marpies.ane.facedetection.data.FaceDetectionEvent; 31 | import com.marpies.ane.facedetection.utils.*; 32 | import org.json.JSONArray; 33 | import org.json.JSONException; 34 | import org.json.JSONObject; 35 | 36 | import java.util.List; 37 | 38 | public class DetectFacesFunction extends BaseFunction { 39 | 40 | @Override 41 | public FREObject call( FREContext context, FREObject[] args ) { 42 | super.call( context, args ); 43 | 44 | AIR.log( "FaceDetection::detect" ); 45 | 46 | final int callbackId = FREObjectUtils.getInt( args[1] ); 47 | final Bitmap image; 48 | try { 49 | image = BitmapDataUtils.getBitmap( (FREBitmapData) args[0] ); 50 | } catch( Exception e ) { 51 | e.printStackTrace(); 52 | AIR.log( "Error creating Bitmap out of FREBitmapData" ); 53 | AIR.dispatchEvent( 54 | FaceDetectionEvent.FACE_DETECTION_ERROR, 55 | StringUtils.getEventErrorJSON( callbackId, "Error creating Bitmap out of FREBitmapData" ) 56 | ); 57 | return null; 58 | } 59 | /* Mode (accuracy) */ 60 | final int accuracy = FREObjectUtils.getInt( args[2] ); // Comes in as a ready-to-use value 61 | boolean detectOpenEyes = FREObjectUtils.getBoolean( args[3] ); 62 | boolean detectSmile = FREObjectUtils.getBoolean( args[4] ); 63 | final boolean prominentFaceOnly = FREObjectUtils.getBoolean( args[5] ); 64 | /* Classification type (detect open eyes, detect smile) */ 65 | final int classification = (detectOpenEyes || detectSmile) ? FaceDetector.ALL_CLASSIFICATIONS : FaceDetector.NO_CLASSIFICATIONS; 66 | 67 | final Activity activity = AIR.getContext().getActivity(); 68 | 69 | new Thread( 70 | new Runnable() { 71 | @Override 72 | public void run() { 73 | AIR.log( "Running FaceDetection in new thread" ); 74 | FaceDetector.Builder fb = new FaceDetector.Builder( activity.getApplicationContext() ); 75 | fb.setClassificationType( classification ) 76 | .setMode( accuracy ) 77 | .setTrackingEnabled( false ) 78 | .setLandmarkType( FaceDetector.ALL_LANDMARKS ) // We want to know about eye/mouth positions 79 | .setProminentFaceOnly( prominentFaceOnly ); 80 | 81 | /* Wrap the detector in SafeFaceDetector */ 82 | final FaceDetector detector = fb.build(); 83 | Detector sd = new SafeFaceDetector( detector ); 84 | if( !sd.isOperational() ) { 85 | sd.release(); 86 | AIR.log( "Error, detector is not operational." ); 87 | AIR.dispatchEvent( 88 | FaceDetectionEvent.FACE_DETECTION_ERROR, 89 | StringUtils.getEventErrorJSON( -1, "Detector is not operational. Dependencies may have not been downloaded yet. Please, try again later." ) 90 | ); 91 | return; 92 | } 93 | 94 | /* Create Frame with bitmap */ 95 | final Frame frame = new Frame.Builder().setBitmap( image ).build(); 96 | SparseArray faces = sd.detect( frame ); 97 | 98 | /* Build faces JSONArray */ 99 | JSONArray facesResult = getFacesJSONArray( faces ); 100 | dispatchResponse( facesResult, callbackId ); 101 | 102 | sd.release(); 103 | } 104 | } 105 | ).start(); 106 | 107 | return null; 108 | } 109 | 110 | private JSONArray getFacesJSONArray( SparseArray faces ) { 111 | int numFaces = faces.size(); 112 | JSONArray facesResult = new JSONArray(); 113 | for( int i = 0; i < numFaces; i++ ) { 114 | Face face = faces.valueAt( i ); 115 | String faceJSON = getFaceJSON( face ); 116 | if( faceJSON != null ) { 117 | facesResult.put( faceJSON ); 118 | } else { 119 | AIR.log( "Error making JSON out of Face object" ); 120 | } 121 | } 122 | AIR.log( "Parsed " + facesResult.length() + " faces" ); 123 | return facesResult; 124 | } 125 | 126 | private void dispatchResponse( JSONArray facesResult, int callbackId ) { 127 | JSONObject response = new JSONObject(); 128 | try { 129 | response.put( "faces", facesResult.toString() ); 130 | response.put( "callbackId", callbackId ); 131 | AIR.dispatchEvent( FaceDetectionEvent.FACE_DETECTION_COMPLETE, response.toString() ); 132 | } catch( JSONException e ) { 133 | e.printStackTrace(); 134 | AIR.log( "Error creating JSON response" ); 135 | AIR.dispatchEvent( 136 | FaceDetectionEvent.FACE_DETECTION_ERROR, 137 | StringUtils.getEventErrorJSON( callbackId, "Error creating JSON response" ) 138 | ); 139 | } 140 | } 141 | 142 | private String getFaceJSON( Face face ) { 143 | JSONObject json = new JSONObject(); 144 | try { 145 | json.put( "faceX", face.getPosition().x ); 146 | json.put( "faceY", face.getPosition().y ); 147 | json.put( "faceWidth", face.getWidth() ); 148 | json.put( "faceHeight", face.getHeight() ); 149 | json.put( "leftEyeOpenProbability", face.getIsLeftEyeOpenProbability() ); 150 | json.put( "rightEyeOpenProbability", face.getIsRightEyeOpenProbability() ); 151 | json.put( "isSmilingProbability", face.getIsSmilingProbability() ); 152 | List landmarks = face.getLandmarks(); 153 | for( Landmark landmark : landmarks ) { 154 | addLandmark( landmark, json ); 155 | } 156 | } catch( JSONException e ) { 157 | e.printStackTrace(); 158 | return null; 159 | } 160 | return json.toString(); 161 | } 162 | 163 | private void addLandmark( Landmark landmark, JSONObject json ) throws JSONException { 164 | /* Mouth position */ 165 | int landmarkType = landmark.getType(); 166 | String landmarkKey = getLandmarkKey( landmarkType ); 167 | if( landmarkKey != null ) { 168 | json.put( landmarkKey + "X", landmark.getPosition().x ); 169 | json.put( landmarkKey + "Y", landmark.getPosition().y ); 170 | } 171 | } 172 | 173 | private String getLandmarkKey( int landmarkType ) { 174 | switch( landmarkType ) { 175 | case Landmark.BOTTOM_MOUTH: return "mouth"; 176 | case Landmark.LEFT_EYE: return "leftEye"; 177 | case Landmark.RIGHT_EYE: return "rightEye"; 178 | case Landmark.LEFT_EAR: return "leftEar"; 179 | case Landmark.LEFT_EAR_TIP: return "leftEarTip"; 180 | case Landmark.LEFT_CHEEK: return "leftCheek"; 181 | case Landmark.LEFT_MOUTH: return "leftMouth"; 182 | case Landmark.RIGHT_EAR: return "rightEar"; 183 | case Landmark.RIGHT_EAR_TIP: return "rightEarTip"; 184 | case Landmark.RIGHT_CHEEK: return "rightCheek"; 185 | case Landmark.RIGHT_MOUTH: return "rightMouth"; 186 | case Landmark.NOSE_BASE: return "noseBase"; 187 | default: return null; 188 | } 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/functions/IsAvailableFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.functions; 18 | 19 | import android.app.Activity; 20 | import android.content.Context; 21 | import com.adobe.fre.FREContext; 22 | import com.adobe.fre.FREObject; 23 | import com.adobe.fre.FREWrongThreadException; 24 | import com.google.android.gms.common.ConnectionResult; 25 | import com.google.android.gms.common.GoogleApiAvailability; 26 | import com.marpies.ane.facedetection.utils.AIR; 27 | 28 | public class IsAvailableFunction extends BaseFunction { 29 | 30 | @Override 31 | public FREObject call( FREContext context, FREObject[] args ) { 32 | super.call( context, args ); 33 | 34 | AIR.log( "FaceDetection::isAvailable" ); 35 | Activity activity = AIR.getContext().getActivity(); 36 | 37 | try { 38 | return FREObject.newObject( checkPlayServices( activity ) ); 39 | } catch( FREWrongThreadException e ) { 40 | e.printStackTrace(); 41 | } 42 | 43 | return null; 44 | } 45 | 46 | private boolean checkPlayServices( Context context ) { 47 | GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); 48 | int resultCode = apiAvailability.isGooglePlayServicesAvailable( context ); 49 | return resultCode == ConnectionResult.SUCCESS; 50 | } 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/functions/IsOperationalFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.functions; 18 | 19 | import android.app.Activity; 20 | import com.adobe.fre.FREContext; 21 | import com.adobe.fre.FREObject; 22 | import com.adobe.fre.FREWrongThreadException; 23 | import com.google.android.gms.vision.Detector; 24 | import com.google.android.gms.vision.face.Face; 25 | import com.google.android.gms.vision.face.FaceDetector; 26 | import com.marpies.ane.facedetection.utils.AIR; 27 | import com.marpies.ane.facedetection.utils.SafeFaceDetector; 28 | 29 | public class IsOperationalFunction extends BaseFunction { 30 | 31 | @Override 32 | public FREObject call( FREContext context, FREObject[] args ) { 33 | super.call( context, args ); 34 | 35 | AIR.log( "FaceDetection::isOperational" ); 36 | 37 | Activity activity = AIR.getContext().getActivity(); 38 | 39 | FaceDetector.Builder fb = new FaceDetector.Builder( activity.getApplicationContext() ); 40 | final FaceDetector detector = fb.build(); 41 | try { 42 | return FREObject.newObject( detector.isOperational() ); 43 | } catch( FREWrongThreadException e ) { 44 | e.printStackTrace(); 45 | } 46 | 47 | return null; 48 | } 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/functions/SetLogEnabledFunction.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.functions; 18 | 19 | import com.adobe.fre.FREContext; 20 | import com.adobe.fre.FREObject; 21 | import com.marpies.ane.facedetection.utils.AIR; 22 | import com.marpies.ane.facedetection.utils.FREObjectUtils; 23 | 24 | public class SetLogEnabledFunction extends BaseFunction { 25 | 26 | @Override 27 | public FREObject call( FREContext context, FREObject[] args ) { 28 | super.call( context, args ); 29 | 30 | boolean enableLogs = FREObjectUtils.getBoolean( args[0] ); 31 | AIR.setLogEnabled( enableLogs ); 32 | AIR.log( "FaceDetection::setLogEnabled " + enableLogs ); 33 | 34 | return null; 35 | } 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/utils/AIR.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.utils; 18 | 19 | import android.util.Log; 20 | import com.marpies.ane.facedetection.FaceDetectionExtensionContext; 21 | 22 | public class AIR { 23 | 24 | private static final String TAG = "FaceDetection"; 25 | private static boolean mLogEnabled = false; 26 | 27 | private static FaceDetectionExtensionContext mContext; 28 | 29 | public static void log( String message ) { 30 | if( mLogEnabled ) { 31 | Log.i( TAG, message ); 32 | } 33 | } 34 | 35 | public static void dispatchEvent( String eventName, String message ) { 36 | mContext.dispatchStatusEventAsync( eventName, message ); 37 | } 38 | 39 | /** 40 | * 41 | * 42 | * Getters / Setters 43 | * 44 | * 45 | */ 46 | 47 | public static FaceDetectionExtensionContext getContext() { 48 | return mContext; 49 | } 50 | public static void setContext( FaceDetectionExtensionContext context ) { 51 | mContext = context; 52 | } 53 | 54 | public static void setLogEnabled( boolean value ) { 55 | mLogEnabled = value; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/utils/BitmapDataUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.utils; 18 | 19 | import android.graphics.*; 20 | import com.adobe.fre.FREBitmapData; 21 | import com.adobe.fre.FREInvalidObjectException; 22 | import com.adobe.fre.FREWrongThreadException; 23 | 24 | public class BitmapDataUtils { 25 | 26 | private static final float[] mBGRToRGBColorTransform = 27 | { 28 | 0, 0, 1f, 0, 0, 29 | 0, 1f, 0, 0, 0, 30 | 1f, 0, 0, 0, 0, 31 | 0, 0, 0, 1f, 0 32 | }; 33 | private static final ColorMatrixColorFilter mColorFilter = new ColorMatrixColorFilter( 34 | new ColorMatrix( mBGRToRGBColorTransform ) 35 | ); 36 | 37 | /** 38 | * Switch color channels 39 | * http://stackoverflow.com/questions/17314467/bitmap-channels-order-different-in-android 40 | */ 41 | public static Bitmap getBitmap( FREBitmapData bitmapData ) throws FREWrongThreadException, FREInvalidObjectException { 42 | bitmapData.acquire(); 43 | Bitmap bitmap = Bitmap.createBitmap( bitmapData.getWidth(), bitmapData.getHeight(), Bitmap.Config.ARGB_8888 ); 44 | Canvas canvas = new Canvas( bitmap ); 45 | Paint paint = new Paint(); 46 | paint.setColorFilter( mColorFilter ); 47 | bitmap.copyPixelsFromBuffer( bitmapData.getBits() ); 48 | bitmapData.release(); 49 | canvas.drawBitmap( bitmap, 0, 0, paint ); 50 | return bitmap; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/utils/FREObjectUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.utils; 18 | 19 | import android.os.Bundle; 20 | import com.adobe.fre.*; 21 | import org.json.JSONException; 22 | import org.json.JSONObject; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | import java.util.Set; 27 | 28 | public class FREObjectUtils { 29 | 30 | public static Integer getInt( FREObject object ) { 31 | try { 32 | return object.getAsInt(); 33 | } catch( Exception e ) { 34 | e.printStackTrace(); 35 | return null; 36 | } 37 | } 38 | 39 | public static Double getDouble( FREObject object ) { 40 | try { 41 | return object.getAsDouble(); 42 | } catch( Exception e ) { 43 | e.printStackTrace(); 44 | return null; 45 | } 46 | } 47 | 48 | public static String getString( FREObject object ) { 49 | try { 50 | return object.getAsString(); 51 | } catch( Exception e ) { 52 | e.printStackTrace(); 53 | return null; 54 | } 55 | } 56 | 57 | public static Boolean getBoolean( FREObject object ) { 58 | try { 59 | return object.getAsBool(); 60 | } catch( Exception e ) { 61 | e.printStackTrace(); 62 | return false; 63 | } 64 | } 65 | 66 | public static List getListOfString( FREArray array ) { 67 | List result = new ArrayList(); 68 | 69 | try { 70 | for( long i = 0; i < array.getLength(); i++ ) { 71 | try { 72 | result.add( getString( array.getObjectAt( i ) ) ); 73 | } catch( Exception e ) { 74 | e.printStackTrace(); 75 | } 76 | } 77 | } catch( Exception e ) { 78 | e.printStackTrace(); 79 | return null; 80 | } 81 | 82 | return result; 83 | } 84 | 85 | public static String[] getArrayOfString( FREArray array ) { 86 | String[] result = null; 87 | 88 | try { 89 | int length = ((Long) array.getLength()).intValue(); 90 | result = new String[length]; 91 | for( int i = 0; i < length; i++ ) { 92 | try { 93 | result[i] = getString( array.getObjectAt( (long) i ) ); 94 | } catch( Exception e ) { 95 | e.printStackTrace(); 96 | } 97 | } 98 | } catch( FREInvalidObjectException e ) { 99 | e.printStackTrace(); 100 | } catch( FREWrongThreadException e ) { 101 | e.printStackTrace(); 102 | } 103 | 104 | return result; 105 | } 106 | 107 | public static Bundle getBundle( FREArray array ) { 108 | Bundle result = null; 109 | 110 | try { 111 | long length = array.getLength(); 112 | if( length > 0 ) { 113 | result = new Bundle(); 114 | for( long i = 0; i < length; ) { 115 | String key = getString( array.getObjectAt( i++ ) ); 116 | String value = getString( array.getObjectAt( i++ ) ); 117 | result.putString( key, value ); 118 | } 119 | } 120 | } catch( FREInvalidObjectException e ) { 121 | e.printStackTrace(); 122 | } catch( FREWrongThreadException e ) { 123 | e.printStackTrace(); 124 | } 125 | 126 | return result; 127 | } 128 | 129 | public static JSONObject getJSONObject( FREArray array ) { 130 | JSONObject result = null; 131 | 132 | try { 133 | long length = array.getLength(); 134 | if( length > 0 ) { 135 | result = new JSONObject(); 136 | for( long i = 0; i < length; ) { 137 | String key = getString( array.getObjectAt( i++ ) ); 138 | String value = getString( array.getObjectAt( i++ ) ); 139 | result.put( key, value ); 140 | } 141 | } 142 | } catch( FREInvalidObjectException e ) { 143 | e.printStackTrace(); 144 | } catch( FREWrongThreadException e ) { 145 | e.printStackTrace(); 146 | } catch( JSONException e ) { 147 | e.printStackTrace(); 148 | } 149 | 150 | return result; 151 | } 152 | 153 | public static FREArray getVectorFromSet( int numElements, boolean fixed, Set set ) { 154 | try { 155 | FREArray vector = FREArray.newArray( "String", numElements, fixed ); 156 | long i = 0; 157 | for( String element : set ) { 158 | vector.setObjectAt( i++, FREObject.newObject( element ) ); 159 | } 160 | return vector; 161 | } catch( FREASErrorException e ) { 162 | e.printStackTrace(); 163 | } catch( FREWrongThreadException e ) { 164 | e.printStackTrace(); 165 | } catch( FRENoSuchNameException e ) { 166 | e.printStackTrace(); 167 | } catch( FREInvalidObjectException e ) { 168 | e.printStackTrace(); 169 | } catch( FRETypeMismatchException e ) { 170 | e.printStackTrace(); 171 | } 172 | return null; 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/utils/SafeFaceDetector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.marpies.ane.facedetection.utils; 17 | 18 | import android.graphics.ImageFormat; 19 | import android.util.Log; 20 | import android.util.SparseArray; 21 | 22 | import com.google.android.gms.vision.Detector; 23 | import com.google.android.gms.vision.Frame; 24 | import com.google.android.gms.vision.face.Face; 25 | 26 | import java.nio.ByteBuffer; 27 | import java.util.Arrays; 28 | 29 | /** 30 | * This is a workaround for a bug in the face detector, in which either very small images (i.e., 31 | * most images with dimension < 147) and very thin images can cause a crash in the native face 32 | * detection code. This will add padding to such images before face detection in order to avoid 33 | * this issue.

34 | *

35 | * This is not necessary for use with the camera, which doesn't ever create these types of 36 | * images.

37 | *

38 | * This detector should wrap the underlying FaceDetector instance, like this: 39 | *

40 | * Detector safeDetector = new SafeFaceDetector(faceDetector); 41 | *

42 | * Replace all remaining occurrences of faceDetector with safeDetector. 43 | */ 44 | public class SafeFaceDetector extends Detector { 45 | 46 | private static final String TAG = "SafeFaceDetector"; 47 | private Detector mDelegate; 48 | 49 | /** 50 | * Creates a safe face detector to wrap and protect an underlying face detector from images that 51 | * trigger the face detector bug. 52 | */ 53 | public SafeFaceDetector( Detector delegate ) { 54 | mDelegate = delegate; 55 | } 56 | 57 | @Override 58 | public void release() { 59 | mDelegate.release(); 60 | } 61 | 62 | /** 63 | * Determines whether the supplied image may cause a problem with the underlying face detector. 64 | * If it does, padding is added to the image in order to avoid the issue. 65 | */ 66 | @Override 67 | public SparseArray detect( Frame frame ) { 68 | final int kMinDimension = 147; 69 | final int kDimensionLower = 640; 70 | int width = frame.getMetadata().getWidth(); 71 | int height = frame.getMetadata().getHeight(); 72 | 73 | if( height > (2 * kDimensionLower) ) { 74 | // The image will be scaled down before detection is run. Check to make sure that this 75 | // won't result in the width going below the minimum 76 | double multiple = (double) height / (double) kDimensionLower; 77 | double lowerWidth = Math.floor( (double) width / multiple ); 78 | if( lowerWidth < kMinDimension ) { 79 | // The width would have gone below the minimum when downsampling, so apply padding 80 | // to the right to keep the width large enough. 81 | int newWidth = (int) Math.ceil( kMinDimension * multiple ); 82 | frame = padFrameRight( frame, newWidth ); 83 | } 84 | } else if( width > (2 * kDimensionLower) ) { 85 | // The image will be scaled down before detection is run. Check to make sure that this 86 | // won't result in the height going below the minimum 87 | double multiple = (double) width / (double) kDimensionLower; 88 | double lowerHeight = Math.floor( (double) height / multiple ); 89 | if( lowerHeight < kMinDimension ) { 90 | int newHeight = (int) Math.ceil( kMinDimension * multiple ); 91 | frame = padFrameBottom( frame, newHeight ); 92 | } 93 | } else if( width < kMinDimension ) { 94 | frame = padFrameRight( frame, kMinDimension ); 95 | } 96 | 97 | return mDelegate.detect( frame ); 98 | } 99 | 100 | @Override 101 | public boolean isOperational() { 102 | return mDelegate.isOperational(); 103 | } 104 | 105 | @Override 106 | public boolean setFocus( int id ) { 107 | return mDelegate.setFocus( id ); 108 | } 109 | 110 | /** 111 | * Creates a new frame based on the original frame, with additional width on the right to 112 | * increase the size to avoid the bug in the underlying face detector. 113 | */ 114 | private Frame padFrameRight( Frame originalFrame, int newWidth ) { 115 | Frame.Metadata metadata = originalFrame.getMetadata(); 116 | int width = metadata.getWidth(); 117 | int height = metadata.getHeight(); 118 | 119 | Log.i( TAG, "Padded image from: " + width + "x" + height + " to " + newWidth + "x" + height ); 120 | 121 | ByteBuffer origBuffer = originalFrame.getGrayscaleImageData(); 122 | int origOffset = origBuffer.arrayOffset(); 123 | byte[] origBytes = origBuffer.array(); 124 | 125 | // This can be changed to just .allocate in the future, when Frame supports non-direct 126 | // byte buffers. 127 | ByteBuffer paddedBuffer = ByteBuffer.allocateDirect( newWidth * height ); 128 | int paddedOffset = paddedBuffer.arrayOffset(); 129 | byte[] paddedBytes = paddedBuffer.array(); 130 | Arrays.fill( paddedBytes, (byte) 0 ); 131 | 132 | for( int y = 0; y < height; ++y ) { 133 | int origStride = origOffset + y * width; 134 | int paddedStride = paddedOffset + y * newWidth; 135 | System.arraycopy( origBytes, origStride, paddedBytes, paddedStride, width ); 136 | } 137 | 138 | return new Frame.Builder() 139 | .setImageData( paddedBuffer, newWidth, height, ImageFormat.NV21 ) 140 | .setId( metadata.getId() ) 141 | .setRotation( metadata.getRotation() ) 142 | .setTimestampMillis( metadata.getTimestampMillis() ) 143 | .build(); 144 | } 145 | 146 | /** 147 | * Creates a new frame based on the original frame, with additional height on the bottom to 148 | * increase the size to avoid the bug in the underlying face detector. 149 | */ 150 | private Frame padFrameBottom( Frame originalFrame, int newHeight ) { 151 | Frame.Metadata metadata = originalFrame.getMetadata(); 152 | int width = metadata.getWidth(); 153 | int height = metadata.getHeight(); 154 | 155 | Log.i( TAG, "Padded image from: " + width + "x" + height + " to " + width + "x" + newHeight ); 156 | 157 | ByteBuffer origBuffer = originalFrame.getGrayscaleImageData(); 158 | int origOffset = origBuffer.arrayOffset(); 159 | byte[] origBytes = origBuffer.array(); 160 | 161 | // This can be changed to just .allocate in the future, when Frame supports non-direct 162 | // byte buffers. 163 | ByteBuffer paddedBuffer = ByteBuffer.allocateDirect( width * newHeight ); 164 | int paddedOffset = paddedBuffer.arrayOffset(); 165 | byte[] paddedBytes = paddedBuffer.array(); 166 | Arrays.fill( paddedBytes, (byte) 0 ); 167 | 168 | // Copy the image content from the original, without bothering to fill in the padded bottom 169 | // part. 170 | for( int y = 0; y < height; ++y ) { 171 | int origStride = origOffset + y * width; 172 | int paddedStride = paddedOffset + y * width; 173 | System.arraycopy( origBytes, origStride, paddedBytes, paddedStride, width ); 174 | } 175 | 176 | return new Frame.Builder() 177 | .setImageData( paddedBuffer, width, newHeight, ImageFormat.NV21 ) 178 | .setId( metadata.getId() ) 179 | .setRotation( metadata.getRotation() ) 180 | .setTimestampMillis( metadata.getTimestampMillis() ) 181 | .build(); 182 | } 183 | } -------------------------------------------------------------------------------- /android/src/com/marpies/ane/facedetection/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.marpies.ane.facedetection.utils; 18 | 19 | public class StringUtils { 20 | 21 | public static String getEventErrorJSON( final int listenerID, String errorMessage ) { 22 | return String.format( "{ \"listenerID\": %d, \"errorMessage\": \"%s\" }", 23 | listenerID, 24 | /* The error message may contain line breaks - these need 25 | * to be removed so that JSON parsing errors do not occur */ 26 | removeLineBreaks( errorMessage ) ); 27 | } 28 | 29 | private static String removeLineBreaks( String message ) { 30 | return message.replace( "\n", "" ).replace( "\r", "" ); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /bin/com.marpies.ane.facedetection.ane: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/bin/com.marpies.ane.facedetection.ane -------------------------------------------------------------------------------- /bin/com.marpies.ane.facedetection.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/bin/com.marpies.ane.facedetection.swc -------------------------------------------------------------------------------- /build/build.properties: -------------------------------------------------------------------------------- 1 | name = FaceDetection 2 | packageName = com.marpies.ane.facedetection 3 | 4 | air.sdk = /PATH/TO/AIR_SDK_20+ 5 | 6 | bin.ext = 7 | 8 | ios.sdkversion = iphoneos 9 | 10 | gradle.exec = /PATH/TO/GRADLE_BINARY -------------------------------------------------------------------------------- /build/extension.xml: -------------------------------------------------------------------------------- 1 | 2 | com.marpies.ane.facedetection 3 | 1.0.3 4 | 5 | 6 | 7 | libFaceDetection.a 8 | FaceDetectionInitializer 9 | FaceDetectionFinalizer 10 | 11 | 12 | 13 | 14 | 15 | libFaceDetection.jar 16 | com.marpies.ane.facedetection.FaceDetectionExtension 17 | com.marpies.ane.facedetection.FaceDetectionExtension 18 | 19 | 20 | 21 | 22 | 23 | libFaceDetection.jar 24 | com.marpies.ane.facedetection.FaceDetectionExtension 25 | com.marpies.ane.facedetection.FaceDetectionExtension 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /build/platform-ios.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | AIRExtHelpers.framework 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/AC_OETags.js: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // ADOBE SYSTEMS INCORPORATED 4 | // Copyright 2008 Adobe Systems Incorporated 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Adobe permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | //v1.0 14 | function AC_AddExtension(src, ext) 15 | { 16 | if (src.indexOf('?') != -1) 17 | return src.replace(/\?/, ext+'?'); 18 | else 19 | return src + ext; 20 | } 21 | 22 | function AC_Generateobj(objAttrs, params, embedAttrs) 23 | { 24 | var str = ' '; 30 | str += ' 2 | 3 | 4 | All Classes - API Documentation 5 | 6 | 7 | 8 | 9 | 10 | 11 |

All Classes

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
Face
FaceDetection
FaceDetectionAccuracy
FaceDetectionOptions
26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/all-index-E.html: -------------------------------------------------------------------------------- 1 | E 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-G.html: -------------------------------------------------------------------------------- 1 | G 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-J.html: -------------------------------------------------------------------------------- 1 | J 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-K.html: -------------------------------------------------------------------------------- 1 | K 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-O.html: -------------------------------------------------------------------------------- 1 | O 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-Q.html: -------------------------------------------------------------------------------- 1 | Q 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-T.html: -------------------------------------------------------------------------------- 1 | T 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-W.html: -------------------------------------------------------------------------------- 1 | W 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-X.html: -------------------------------------------------------------------------------- 1 | X 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-Y.html: -------------------------------------------------------------------------------- 1 | Y 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/all-index-Z.html: -------------------------------------------------------------------------------- 1 | Z 6 |

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  
A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  

-------------------------------------------------------------------------------- /docs/class-summary.html: -------------------------------------------------------------------------------- 1 | All Classes 6 |

Documentation for classes includes syntax, usage information, and code samples for methods, properties, and event handlers and listeners for those APIs that belong to a specific class in ActionScript. The classes are listed alphabetically. If you are not sure to which class a certain method or property belongs, you can look it up in the Index.


 ClassPackageDescription
 Face
com.marpies.ane.facedetection 14 | Object representing detected face.
 FaceDetection
com.marpies.ane.facedetection 15 | Class providing APIs for face detection.
 FaceDetectionAccuracy
com.marpies.ane.facedetection 16 | Constants used to specify detection accuracy.
 FaceDetectionOptions
com.marpies.ane.facedetection 17 | Object allowing to specify several face detection options.

-------------------------------------------------------------------------------- /docs/com/marpies/ane/facedetection/FaceDetectionAccuracy.html: -------------------------------------------------------------------------------- 1 | com.marpies.ane.facedetection.FaceDetectionAccuracy 6 |
Packagecom.marpies.ane.facedetection
Classpublic class FaceDetectionAccuracy
InheritanceFaceDetectionAccuracy Inheritance Object

14 | Constants used to specify detection accuracy. 15 |



Public Constants
 ConstantDefined By
  HIGH : int = 1
[static] 16 | High accuracy detection settings.
FaceDetectionAccuracy
  LOW : int = 0
[static] 17 | Low accuracy detection settings.
FaceDetectionAccuracy
Constant Detail
HIGHConstant
public static const HIGH:int = 1

20 | High accuracy detection settings. This will tend to detect more faces 21 | and may be more precise in determining values such as position, at the cost of speed. 22 |

LOWConstant 
public static const LOW:int = 0

23 | Low accuracy detection settings. This will tend to detect fewer faces 24 | and may be less precise in determining values such as position, but will run faster. 25 |





-------------------------------------------------------------------------------- /docs/com/marpies/ane/facedetection/class-list.html: -------------------------------------------------------------------------------- 1 | com.marpies.ane.facedetection - API Documentation

Package com.marpies.ane.facedetection

Classes
Face
FaceDetection
FaceDetectionAccuracy
FaceDetectionOptions
-------------------------------------------------------------------------------- /docs/com/marpies/ane/facedetection/package-detail.html: -------------------------------------------------------------------------------- 1 | com.marpies.ane.facedetection Summary 6 |



Classes
 ClassDescription
 Face 14 | Object representing detected face.
 FaceDetection 15 | Class providing APIs for face detection.
 FaceDetectionAccuracy 16 | Constants used to specify detection accuracy.
 FaceDetectionOptions 17 | Object allowing to specify several face detection options.

-------------------------------------------------------------------------------- /docs/cookies.js: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // ADOBE SYSTEMS INCORPORATED 4 | // Copyright 2006-2008 Adobe Systems Incorporated 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Adobe permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | /** 13 | * Read the JavaScript cookies tutorial at: 14 | * http://www.netspade.com/articles/javascript/cookies.xml 15 | */ 16 | 17 | /** 18 | * Sets a Cookie with the given name and value. 19 | * 20 | * name Name of the cookie 21 | * value Value of the cookie 22 | * [expires] Expiration date of the cookie (default: end of current session) 23 | * [path] Path where the cookie is valid (default: path of calling document) 24 | * [domain] Domain where the cookie is valid 25 | * (default: domain of calling document) 26 | * [secure] Boolean value indicating if the cookie transmission requires a 27 | * secure transmission 28 | */ 29 | function setCookie(name, value, expires, path, domain, secure) 30 | { 31 | document.cookie= name + "=" + escape(value) + 32 | ((expires) ? "; expires=" + expires.toGMTString() : "") + 33 | ((path) ? "; path=" + path : "") + 34 | ((domain) ? "; domain=" + domain : "") + 35 | ((secure) ? "; secure" : ""); 36 | } 37 | 38 | /** 39 | * Gets the value of the specified cookie. 40 | * 41 | * name Name of the desired cookie. 42 | * 43 | * Returns a string containing value of specified cookie, 44 | * or null if cookie does not exist. 45 | */ 46 | function getCookie(name) 47 | { 48 | var dc = document.cookie; 49 | var prefix = name + "="; 50 | var begin = dc.indexOf("; " + prefix); 51 | if (begin == -1) 52 | { 53 | begin = dc.indexOf(prefix); 54 | if (begin != 0) return null; 55 | } 56 | else 57 | { 58 | begin += 2; 59 | } 60 | var end = document.cookie.indexOf(";", begin); 61 | if (end == -1) 62 | { 63 | end = dc.length; 64 | } 65 | return unescape(dc.substring(begin + prefix.length, end)); 66 | } 67 | 68 | /** 69 | * Deletes the specified cookie. 70 | * 71 | * name name of the cookie 72 | * [path] path of the cookie (must be same as path used to create cookie) 73 | * [domain] domain of the cookie (must be same as domain used to create cookie) 74 | */ 75 | function deleteCookie(name, path, domain) 76 | { 77 | if (getCookie(name)) 78 | { 79 | document.cookie = name + "=" + 80 | ((path) ? "; path=" + path : "") + 81 | ((domain) ? "; domain=" + domain : "") + 82 | "; expires=Thu, 01-Jan-70 00:00:01 GMT"; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /docs/images/AirIcon12x12.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/AirIcon12x12.gif -------------------------------------------------------------------------------- /docs/images/P_AlternativeMetadataIndicator_30x28_N.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/P_AlternativeMetadataIndicator_30x28_N.png -------------------------------------------------------------------------------- /docs/images/collapsed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/collapsed.gif -------------------------------------------------------------------------------- /docs/images/detailHeaderRule.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/detailHeaderRule.jpg -------------------------------------------------------------------------------- /docs/images/detailSectionHeader.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/detailSectionHeader.jpg -------------------------------------------------------------------------------- /docs/images/expanded.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/expanded.gif -------------------------------------------------------------------------------- /docs/images/inherit-arrow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/inherit-arrow.gif -------------------------------------------------------------------------------- /docs/images/inheritedSummary.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/inheritedSummary.gif -------------------------------------------------------------------------------- /docs/images/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/logo.jpg -------------------------------------------------------------------------------- /docs/images/titleTableBottom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/titleTableBottom.jpg -------------------------------------------------------------------------------- /docs/images/titleTableMiddle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/titleTableMiddle.jpg -------------------------------------------------------------------------------- /docs/images/titleTableTop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/docs/images/titleTableTop.jpg -------------------------------------------------------------------------------- /docs/index-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | API Documentation 4 | 5 | 6 | 7 | 8 | 9 |

Index

10 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
AN
BO
CP
DQ
ER
FS
GT
HU
IV
JW
KX
LY
MZ
70 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | API Documentation 4 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | <body> 31 | <h2>Frame Alert</h2> 32 | <p> 33 | This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. 34 | <br> 35 | Link to <a href="package-summary.html">Non-frame version.</a> 36 | </p> 37 | </body> 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/override.css: -------------------------------------------------------------------------------- 1 | /* 2 | //////////////////////////////////////////////////////////////////////////////// 3 | // 4 | // ADOBE SYSTEMS INCORPORATED 5 | // Copyright 2008 Adobe Systems Incorporated 6 | // All Rights Reserved. 7 | // 8 | // NOTICE: Adobe permits you to use, modify, and distribute this file 9 | // in accordance with the terms of the license agreement accompanying it. 10 | // 11 | //////////////////////////////////////////////////////////////////////////////// 12 | */ -------------------------------------------------------------------------------- /docs/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | API Documentation 4 | 5 | 6 | 7 | 8 | 9 | <body> 10 | <h2>Frame Alert</h2> 11 | <p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. 12 | <br> 13 | Link to<a href="package-summary.html">Non-frame version.</a> 14 | </p> 15 | </body> 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/package-list.html: -------------------------------------------------------------------------------- 1 | Package List - API Documentation

Packages

com.marpies.ane.facedetection
-------------------------------------------------------------------------------- /docs/package-summary.html: -------------------------------------------------------------------------------- 1 | All Packages 6 |


 packageDescription
 com.marpies.ane.facedetection

-------------------------------------------------------------------------------- /docs/print.css: -------------------------------------------------------------------------------- 1 | /* 2 | //////////////////////////////////////////////////////////////////////////////// 3 | // 4 | // ADOBE SYSTEMS INCORPORATED 5 | // Copyright 2005-2008 Adobe Systems Incorporated 6 | // All Rights Reserved. 7 | // 8 | // NOTICE: Adobe permits you to use, modify, and distribute this file 9 | // in accordance with the terms of the license agreement accompanying it. 10 | // 11 | //////////////////////////////////////////////////////////////////////////////// 12 | */ 13 | 14 | body { 15 | color: #000000; 16 | background: #ffffff; 17 | font-family: "Times New Roman", Times, serif; 18 | font-size: 12pt; 19 | } 20 | a { 21 | text-decoration: none; 22 | color: #000000; 23 | } 24 | pre { 25 | white-space: -moz-pre-wrap; /* Mozilla */ 26 | white-space: -pre-wrap; /* Opera 4-6 */ 27 | white-space: -o-pre-wrap; /* Opera 7 */ 28 | word-wrap: break-word; /* IE */ 29 | } 30 | .titleTableTopNav, .titleTableSubNav, .logoImage { 31 | display: none; 32 | } 33 | .packageFrame { 34 | display: none; 35 | } 36 | .titleTableSubTitle { 37 | font-weight: bold; 38 | } 39 | .classHeaderTableLabel { 40 | padding-right: 10px; 41 | vertical-align: top; 42 | } 43 | .showHideLinks { 44 | display: none; 45 | } 46 | html>body code { 47 | font-size: 10pt; 48 | } 49 | .summaryTableTitle, .detailSectionHeader { 50 | font-size: 14pt; 51 | font-weight: bold; 52 | padding-top: 15px; 53 | padding-bottom: 5px; 54 | } 55 | .summaryTable { 56 | border: 1px solid #000000; 57 | border-collapse: collapse; 58 | width: 100%; 59 | } 60 | .summaryTableDescription { 61 | padding-bottom: 20px; 62 | } 63 | .summaryTableSignatureCol, .summaryTableOwnerCol, .summaryTableLastCol, .summaryTableCol { 64 | border: 1px solid #000000; 65 | } 66 | .summaryTablePaddingCol { 67 | border: 1px solid #000000; 68 | border-right: 0px; 69 | } 70 | .summaryTableInheritanceCol, .summaryTableOperatorCol, .summaryTableStatementCol, .summaryTableSecondCol { 71 | border: 1px solid #000000; 72 | border-left: 0px; 73 | } 74 | .summaryTableLastCol { 75 | vertical-align: top; 76 | } 77 | .detailHeader { 78 | font-size: 13pt; 79 | padding-top: 100px; 80 | } 81 | .detailHeaderName { 82 | font-weight: bold; 83 | } 84 | .detailHeaderType { 85 | padding-left: 5px; 86 | } 87 | .detailHeaderRule { 88 | background: #FF0000; 89 | } 90 | .seeAlso { 91 | padding-bottom: 20px; 92 | margin-top: -20px; 93 | } 94 | .innertable { 95 | border-collapse: collapse; 96 | } 97 | .innertable td,.innertable th { 98 | border: 1px solid #000000; 99 | padding-left: 5px; 100 | padding-right: 5px; 101 | } 102 | .listing { 103 | font-size: 10pt; 104 | } 105 | .feedbackLink { 106 | display: none; 107 | } 108 | .copyright { 109 | font-size: 10pt; 110 | } -------------------------------------------------------------------------------- /docs/title-bar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | API Documentation 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 22 | 23 | 24 | 25 | 38 | 39 |
13 | 14 | 15 | 16 | 19 | 20 |
API Documentation  17 | All Packages  |  All Classes  |  Index  |  No Frames 18 |
21 |
26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 |
 
 
37 |
40 | 41 | -------------------------------------------------------------------------------- /ios/FaceDetection.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/FaceDetection.xcodeproj/project.xcworkspace/xcuserdata/marpies.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/ios/FaceDetection.xcodeproj/project.xcworkspace/xcuserdata/marpies.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ios/FaceDetection.xcodeproj/project.xcworkspace/xcuserdata/marpies.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/FaceDetection.xcodeproj/xcuserdata/marpies.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ios/FaceDetection.xcodeproj/xcuserdata/marpies.xcuserdatad/xcschemes/FaceDetection.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 79 | 85 | 86 | 87 | 88 | 89 | 90 | 96 | 97 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /ios/FaceDetection.xcodeproj/xcuserdata/marpies.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FaceDetection.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | C35331DD1B7BCE8A003A7521 16 | 17 | primary 18 | 19 | 20 | C35331E81B7BCE8A003A7521 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ios/FaceDetection/Data/FaceDetectionEvent.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef FaceDetectionEvent_h 18 | #define FaceDetectionEvent_h 19 | 20 | #import 21 | 22 | static NSString* const FACE_DETECTION_COMPLETE = @"faceDetectionComplete"; 23 | static NSString* const FACE_DETECTION_ERROR = @"faceDetectionError"; 24 | 25 | #endif /* FaceDetectionEvent_h */ 26 | -------------------------------------------------------------------------------- /ios/FaceDetection/FaceDetection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | #import 19 | 20 | @interface FaceDetection : NSObject 21 | 22 | + (void) dispatchEvent:(nullable const NSString*) eventName; 23 | + (void) dispatchEvent:(nullable const NSString*) eventName withMessage:(nonnull NSString*) message; 24 | + (void) log:(nullable const NSString*) message; 25 | + (void) showLogs:(BOOL) showLogs; 26 | + (BOOL) isLogEnabled; 27 | 28 | @end -------------------------------------------------------------------------------- /ios/FaceDetection/FaceDetection.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "FaceDetection.h" 18 | #import "Functions/DetectFacesFunction.h" 19 | #import "Functions/SetLogEnabledFunction.h" 20 | #import "Functions/IsAvailableFunction.h" 21 | #import "Functions/IsOperationalFunction.h" 22 | 23 | static BOOL FaceDetectionLogEnabled = NO; 24 | FREContext FaceDetectionExtContext = nil; 25 | 26 | @implementation FaceDetection 27 | 28 | + (void) dispatchEvent:(const NSString*) eventName { 29 | [self dispatchEvent:eventName withMessage:@""]; 30 | } 31 | 32 | + (void) dispatchEvent:(const NSString*) eventName withMessage:(NSString*) message { 33 | NSString* messageText = message ? message : @""; 34 | FREDispatchStatusEventAsync( FaceDetectionExtContext, (const uint8_t*) [eventName UTF8String], (const uint8_t*) [messageText UTF8String] ); 35 | } 36 | 37 | + (void) log:(const NSString*) message { 38 | if( FaceDetectionLogEnabled ) { 39 | NSLog( @"[iOS-FaceDetection] %@", message ); 40 | } 41 | } 42 | 43 | + (void) showLogs:(BOOL) showLogs { 44 | FaceDetectionLogEnabled = showLogs; 45 | } 46 | 47 | + (BOOL) isLogEnabled { 48 | return FaceDetectionLogEnabled; 49 | } 50 | 51 | @end 52 | 53 | /** 54 | * 55 | * 56 | * Context initialization 57 | * 58 | * 59 | **/ 60 | 61 | FRENamedFunction FaceDetection_extFunctions[] = { 62 | { (const uint8_t*) "detect", 0, fd_detectFaces }, 63 | { (const uint8_t*) "setLogEnabled", 0, fd_setLogEnabled }, 64 | { (const uint8_t*) "isAvailable", 0, fd_isAvailable }, 65 | { (const uint8_t*) "isOperational", 0, fd_isOperational } 66 | }; 67 | 68 | void FaceDetectionContextInitializer( void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToSet, const FRENamedFunction** functionsToSet ) { 69 | *numFunctionsToSet = sizeof( FaceDetection_extFunctions ) / sizeof( FRENamedFunction ); 70 | 71 | *functionsToSet = FaceDetection_extFunctions; 72 | 73 | FaceDetectionExtContext = ctx; 74 | } 75 | 76 | void FaceDetectionContextFinalizer( FREContext ctx ) { } 77 | 78 | void FaceDetectionInitializer( void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet ) { 79 | *extDataToSet = NULL; 80 | *ctxInitializerToSet = &FaceDetectionContextInitializer; 81 | *ctxFinalizerToSet = &FaceDetectionContextFinalizer; 82 | } 83 | 84 | void FaceDetectionFinalizer( void* extData ) { } 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/FaceDetection/Frameworks/AIRExtHelpers.framework/AIRExtHelpers: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marpies/face-detection-ane/8f41f49e5b99bf5312b70466a728c4967fa6aebd/ios/FaceDetection/Frameworks/AIRExtHelpers.framework/AIRExtHelpers -------------------------------------------------------------------------------- /ios/FaceDetection/Frameworks/AIRExtHelpers.framework/Headers/MPBitmapDataUtils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "FlashRuntimeExtensions.h" 18 | #import 19 | #import 20 | 21 | @interface MPBitmapDataUtils : NSObject 22 | 23 | + (UIImage*) getUIImageFromFREBitmapData:(FREBitmapData2) bitmapData; 24 | 25 | @end -------------------------------------------------------------------------------- /ios/FaceDetection/Frameworks/AIRExtHelpers.framework/Headers/MPFREObjectUtils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef AIR_MPFREObjectUtils_h 18 | #define AIR_MPFREObjectUtils_h 19 | 20 | #import "FlashRuntimeExtensions.h" 21 | #import 22 | 23 | @interface MPFREObjectUtils : NSObject 24 | 25 | /** 26 | * From FREObject to Objective C 27 | */ 28 | 29 | + (NSString*) getNSString:(FREObject) object; 30 | + (NSArray*) getNSArray:(FREObject) object; 31 | + (BOOL) getBOOL:(FREObject) object; 32 | + (int) getInt:(FREObject) object; 33 | + (NSDictionary*) getNSDictionary:(FREObject) object; 34 | + (double) getDouble:(FREObject) object; 35 | + (NSArray*) getMediaSourcesArray:(FREObject) object; 36 | 37 | /** 38 | * From Objective C to FREObject 39 | */ 40 | 41 | + (FREObject) getFREObjectFromBOOL:(BOOL) value; 42 | + (FREObject) getFREObjectFromNSString:(NSString*) value; 43 | + (FREObject) getFREObjectFromNSSet:(NSSet*) set; 44 | + (FREObject) getFREObjectFromDouble:(double) value; 45 | 46 | @end 47 | 48 | #endif -------------------------------------------------------------------------------- /ios/FaceDetection/Frameworks/AIRExtHelpers.framework/Headers/MPMediaSource.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | #import 19 | 20 | @interface MPMediaSource : NSObject 21 | 22 | @property (nonatomic) NSString* url; 23 | @property (nonatomic) UIImage* image; 24 | @property (nonatomic, readonly) BOOL isImage; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ios/FaceDetection/Frameworks/AIRExtHelpers.framework/Headers/MPStringUtils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | @interface MPStringUtils : NSObject 20 | 21 | + (NSString*) getEventErrorJSONString:(int) listenerID errorMessage:(NSString*) errorMessage; 22 | 23 | + (NSString*) getSingleValueJSONString:(int) listenerID key:(NSString*) key value:(NSString*) value; 24 | 25 | + (NSString*) getListenerJSONString:(int) listenerID; 26 | 27 | + (NSString*) getJSONString:(NSDictionary*) json; 28 | 29 | @end -------------------------------------------------------------------------------- /ios/FaceDetection/Frameworks/AIRExtHelpers.framework/Headers/MPUIApplicationDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | #import "MPUIApplicationListener.h" 19 | 20 | @interface MPUIApplicationDelegate : NSObject 21 | 22 | + (id) sharedInstance; 23 | + (NSDictionary*) launchOptions; 24 | 25 | - (void) addListener:(id) listener; 26 | - (void) removeListener:(id) listener; 27 | 28 | @end -------------------------------------------------------------------------------- /ios/FaceDetection/Frameworks/AIRExtHelpers.framework/Headers/MPUIApplicationListener.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015-2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | #import 19 | 20 | @protocol MPUIApplicationListener 21 | 22 | @optional 23 | 24 | - (BOOL)application:(nullable UIApplication *)application openURL:(nullable NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nullable id)annotation; 25 | 26 | - (void)applicationDidBecomeActive:(nullable UIApplication *)application; 27 | - (void)applicationDidEnterBackground:(nullable UIApplication *)application; 28 | 29 | - (void)application:(nullable UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(nullable NSData *)deviceToken; 30 | - (void)application:(nullable UIApplication *)application didRegisterUserNotificationSettings:(nullable UIUserNotificationSettings *)notificationSettings; 31 | - (void)application:(nullable UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(nullable NSError *)error; 32 | - (void)application:(nullable UIApplication *)application didReceiveRemoteNotification:(nullable NSDictionary *)userInfo; 33 | - (void)application:(nullable UIApplication *)application didReceiveRemoteNotification:(nullable NSDictionary *)userInfo fetchCompletionHandler:(nullable void (^)(UIBackgroundFetchResult result))completionHandler; 34 | - (void)application:(nullable UIApplication *)application handleActionWithIdentifier:(nullable nullable NSString *)identifier forRemoteNotification:(nullable NSDictionary *)userInfo completionHandler:(nullable void(^)())completionHandler; 35 | 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /ios/FaceDetection/Functions/DetectFacesFunction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | FREObject fd_detectFaces( FREContext context, void* functionData, uint32_t argc, FREObject argv[] ); -------------------------------------------------------------------------------- /ios/FaceDetection/Functions/DetectFacesFunction.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "FaceDetection.h" 18 | #import "DetectFacesFunction.h" 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import "FaceDetectionHelper.h" 24 | #import "FaceDetectionEvent.h" 25 | 26 | FREObject fd_detectFaces( FREContext context, void* functionData, uint32_t argc, FREObject argv[] ) { 27 | FREObject imageObject = argv[0]; 28 | FREBitmapData2 bitmapData; 29 | [FaceDetection log:@"fd_detectFaces"]; 30 | 31 | int callbackId = [MPFREObjectUtils getInt:argv[1]]; 32 | if( FREAcquireBitmapData2( imageObject, &bitmapData ) == FRE_OK ) { 33 | int accuracy = [MPFREObjectUtils getInt:argv[2]]; 34 | BOOL detectOpenEyes = [MPFREObjectUtils getBOOL: argv[3]]; 35 | BOOL detectSmile = [MPFREObjectUtils getBOOL: argv[4]]; 36 | 37 | [[FaceDetectionHelper sharedInstance] detectFaces:bitmapData accuracy:accuracy detectOpenEyes:detectOpenEyes detectSmile:detectSmile callbackId:callbackId]; 38 | FREReleaseBitmapData( imageObject ); 39 | } else { 40 | [FaceDetection log:@"Error acquiring BitmapData"]; 41 | [FaceDetection dispatchEvent:FACE_DETECTION_ERROR withMessage:[MPStringUtils getEventErrorJSONString:callbackId errorMessage:@"Error acquiring BitmapData"]]; 42 | } 43 | return nil; 44 | } 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /ios/FaceDetection/Functions/IsAvailableFunction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | FREObject fd_isAvailable( FREContext context, void* functionData, uint32_t argc, FREObject argv[] ); 20 | -------------------------------------------------------------------------------- /ios/FaceDetection/Functions/IsAvailableFunction.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "IsAvailableFunction.h" 18 | #import 19 | 20 | FREObject fd_isAvailable( FREContext context, void* functionData, uint32_t argc, FREObject argv[] ) { 21 | // stub, iOS detector is always available 22 | return [MPFREObjectUtils getFREObjectFromBOOL:YES]; 23 | } -------------------------------------------------------------------------------- /ios/FaceDetection/Functions/IsOperationalFunction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | FREObject fd_isOperational( FREContext context, void* functionData, uint32_t argc, FREObject argv[] ); 20 | -------------------------------------------------------------------------------- /ios/FaceDetection/Functions/IsOperationalFunction.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "IsOperationalFunction.h" 18 | #import 19 | 20 | FREObject fd_isOperational( FREContext context, void* functionData, uint32_t argc, FREObject argv[] ) { 21 | // stub, iOS detector is always operational 22 | return [MPFREObjectUtils getFREObjectFromBOOL:YES]; 23 | } -------------------------------------------------------------------------------- /ios/FaceDetection/Functions/SetLogEnabledFunction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | FREObject fd_setLogEnabled( FREContext context, void* functionData, uint32_t argc, FREObject argv[] ); 20 | -------------------------------------------------------------------------------- /ios/FaceDetection/Functions/SetLogEnabledFunction.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "SetLogEnabledFunction.h" 18 | #import 19 | #import "FaceDetection.h" 20 | 21 | FREObject fd_setLogEnabled( FREContext context, void* functionData, uint32_t argc, FREObject argv[] ) { 22 | BOOL enableLogs = [MPFREObjectUtils getBOOL:argv[0]]; 23 | [FaceDetection showLogs:enableLogs]; 24 | [FaceDetection log:[NSString stringWithFormat:@"fd_setLogEnabled = %d", enableLogs]]; 25 | return nil; 26 | } -------------------------------------------------------------------------------- /ios/FaceDetection/Utils/FaceDetectionHelper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | #import 19 | #import 20 | 21 | @interface FaceDetectionHelper : NSObject 22 | 23 | + (nonnull id) sharedInstance; 24 | 25 | - (void) detectFaces:(FREBitmapData2) bitmap accuracy:(int) accuracy detectOpenEyes:(BOOL) detectOpenEyes detectSmile:(BOOL) detectSmile callbackId:(int) callbackId; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ios/FaceDetection/Utils/FaceDetectionHelper.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Marcel Piestansky (http://marpies.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "FaceDetectionHelper.h" 18 | #import "FaceDetection.h" 19 | #import "FaceDetectionEvent.h" 20 | #import 21 | #import 22 | 23 | static const int kFaceDetectionAccuracyLow = 0; 24 | static const int kFaceDetectionAccuracyHigh = 1; 25 | 26 | static FaceDetectionHelper* airFdSharedInstance = nil; 27 | 28 | @implementation FaceDetectionHelper 29 | 30 | + (nonnull id) sharedInstance { 31 | if( airFdSharedInstance == nil ) { 32 | airFdSharedInstance = [[FaceDetectionHelper alloc] init]; 33 | } 34 | return airFdSharedInstance; 35 | } 36 | 37 | - (void) detectFaces:(FREBitmapData2) bitmap accuracy:(int) accuracy detectOpenEyes:(BOOL) detectOpenEyes detectSmile:(BOOL) detectSmile callbackId:(int) callbackId { 38 | [FaceDetection log:@"FaceDetectionHelper::detectFaces"]; 39 | 40 | dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{ 41 | CIImage* coreImage = [[CIImage alloc] initWithCGImage:[self getCGImageRefFromFREBitmapData:bitmap]]; 42 | 43 | CIContext* context = [CIContext contextWithOptions:nil]; 44 | NSDictionary* config = @{ CIDetectorAccuracy : (accuracy == kFaceDetectionAccuracyHigh) ? CIDetectorAccuracyHigh : CIDetectorAccuracyLow }; 45 | CIDetector* detector = [CIDetector detectorOfType:CIDetectorTypeFace 46 | context:context 47 | options:config]; 48 | 49 | NSMutableDictionary* opts = [NSMutableDictionary dictionary]; 50 | if( [[coreImage properties] valueForKey:kCGImagePropertyOrientation] != nil ) { 51 | opts[CIDetectorImageOrientation] = [[coreImage properties] valueForKey:kCGImagePropertyOrientation]; 52 | } 53 | if( detectOpenEyes ) { 54 | opts[CIDetectorEyeBlink] = @(YES); 55 | } 56 | if( detectSmile ) { 57 | opts[CIDetectorSmile] = @(YES); 58 | } 59 | 60 | // Y positions have origin at the bottom 61 | uint32_t imageHeight = bitmap.height; 62 | NSArray* features = [detector featuresInImage:coreImage options:opts]; 63 | [FaceDetection log:[NSString stringWithFormat:@"Got CGImage and num of faces: %lu", (unsigned long)[features count]]]; 64 | NSMutableArray* facesResult = [NSMutableArray array]; 65 | for( CIFaceFeature* face in features ) { 66 | if( [FaceDetection isLogEnabled] ) { 67 | [self printFace:face imageHeight:imageHeight]; 68 | } 69 | [facesResult addObject:[self getFaceJSON:face imageHeight:imageHeight]]; 70 | } 71 | 72 | dispatch_async( dispatch_get_main_queue(), ^{ 73 | NSMutableDictionary* response = [NSMutableDictionary dictionary]; 74 | response[@"faces"] = facesResult; 75 | response[@"callbackId"] = @(callbackId); 76 | [FaceDetection dispatchEvent:FACE_DETECTION_COMPLETE withMessage:[MPStringUtils getJSONString:response]]; 77 | }); 78 | }); 79 | } 80 | 81 | - (NSString*) getFaceJSON:(CIFaceFeature*) face imageHeight:(uint32_t) imageHeight { 82 | NSMutableDictionary* json = [NSMutableDictionary dictionary]; 83 | json[@"faceX"] = @(face.bounds.origin.x); 84 | json[@"faceY"] = @(imageHeight - face.bounds.origin.y - face.bounds.size.height); 85 | json[@"faceWidth"] = @(face.bounds.size.width); 86 | json[@"faceHeight"] = @(face.bounds.size.height); 87 | json[@"leftEyeOpenProbability"] = face.leftEyeClosed ? @(0) : @(1); 88 | json[@"rightEyeOpenProbability"] = face.rightEyeClosed ? @(0) : @(1); 89 | json[@"isSmilingProbability"] = face.hasSmile ? @(1) : @(0); 90 | /* Eye position is returned as relative to the subject, i.e. left 91 | * eye position given by the detector is the subject's right eye. */ 92 | if( face.hasLeftEyePosition ) { 93 | json[@"rightEyeX"] = @(face.leftEyePosition.x); 94 | json[@"rightEyeY"] = @(imageHeight - face.leftEyePosition.y); 95 | } 96 | if( face.hasRightEyePosition ) { 97 | json[@"leftEyeX"] = @(face.rightEyePosition.x); 98 | json[@"leftEyeY"] = @(imageHeight - face.rightEyePosition.y); 99 | } 100 | if( face.hasMouthPosition ) { 101 | json[@"mouthX"] = @(face.mouthPosition.x); 102 | json[@"mouthY"] = @(imageHeight - face.mouthPosition.y); 103 | } 104 | return [MPStringUtils getJSONString:json]; 105 | } 106 | 107 | - (CGImageRef) getCGImageRefFromFREBitmapData:(FREBitmapData2) bitmapData { 108 | size_t width = bitmapData.width; 109 | size_t height = bitmapData.height; 110 | 111 | CGDataProviderRef provider = CGDataProviderCreateWithData( NULL, bitmapData.bits32, (width * height * 4), NULL ); 112 | 113 | size_t bitsPerComponent = 8; 114 | size_t bitsPerPixel = 32; 115 | size_t bytesPerRow = 4 * width; 116 | CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 117 | CGBitmapInfo bitmapInfo; 118 | 119 | if( bitmapData.hasAlpha ) { 120 | if( bitmapData.isPremultiplied ) { 121 | bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst; 122 | } else { 123 | bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaFirst; 124 | } 125 | } else { 126 | bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst; 127 | } 128 | 129 | CGImageRef imageRef = CGImageCreate( width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, kCGRenderingIntentDefault ); 130 | return imageRef; 131 | } 132 | 133 | - (void) printFace:(CIFaceFeature*) face imageHeight:(uint32_t)imageHeight { 134 | [FaceDetection log:@"-- FaceFeature"]; 135 | [FaceDetection log:[NSString stringWithFormat:@"hasSmile: %d", face.hasSmile]]; 136 | [FaceDetection log:[NSString stringWithFormat:@"left Eye closed: %d", face.leftEyeClosed]]; 137 | [FaceDetection log:[NSString stringWithFormat:@"right Eye closed: %d", face.rightEyeClosed]]; 138 | [FaceDetection log:[NSString stringWithFormat:@"Face pos: %g at %g | %g x %g", face.bounds.origin.x, face.bounds.origin.y, face.bounds.size.width, face.bounds.size.height]]; 139 | if( face.hasLeftEyePosition ) { 140 | [FaceDetection log:[NSString stringWithFormat:@"has Left Eye pos: %g at %g", face.leftEyePosition.x, (imageHeight - face.leftEyePosition.y)]]; 141 | } 142 | if( face.hasRightEyePosition ) { 143 | [FaceDetection log:[NSString stringWithFormat:@"has Right Eye pos: %g at %g", face.rightEyePosition.x, (imageHeight - face.rightEyePosition.y)]]; 144 | } 145 | if( face.hasMouthPosition ) { 146 | [FaceDetection log:[NSString stringWithFormat:@"has Mouth pos: %g at %g", face.mouthPosition.x, (imageHeight - face.mouthPosition.y)]]; 147 | } 148 | [FaceDetection log:@""]; 149 | } 150 | 151 | @end 152 | --------------------------------------------------------------------------------