1import { UnavailabilityError } from 'expo-modules-core'; 2 3import ExpoFaceDetector from './ExpoFaceDetector'; 4 5declare const global: any; 6 7// @docsMissing 8export type Point = { x: number; y: number }; 9 10// @needsAudit 11export type FaceFeature = { 12 /** 13 * An object containing face bounds. 14 */ 15 bounds: FaceFeatureBounds; 16 /** 17 * Probability that the face is smiling. Returned only if detection classifications property is 18 * set to `FaceDetectorClassifications.all`. 19 */ 20 smilingProbability?: number; 21 /** 22 * Position of the left ear in image coordinates. Returned only if detection classifications 23 * property is set to `FaceDetectorLandmarks.all`. 24 */ 25 leftEarPosition?: Point; 26 /** 27 * Position of the right ear in image coordinates. Returned only if detection classifications 28 * property is set to `FaceDetectorLandmarks.all`. 29 */ 30 rightEarPosition?: Point; 31 /** 32 * Position of the left eye in image coordinates. Returned only if detection classifications 33 * property is set to `FaceDetectorLandmarks.all`. 34 */ 35 leftEyePosition?: Point; 36 /** 37 * Probability that the left eye is open. Returned only if detection classifications property is 38 * set to `FaceDetectorClassifications.all`. 39 */ 40 leftEyeOpenProbability?: number; 41 /** 42 * Position of the right eye in image coordinates. Returned only if detection classifications 43 * property is set to `FaceDetectorLandmarks.all`. 44 */ 45 rightEyePosition?: Point; 46 /** 47 * Probability that the right eye is open. Returned only if detection classifications property is 48 * set to `FaceDetectorClassifications.all`. 49 */ 50 rightEyeOpenProbability?: number; 51 /** 52 * Position of the left cheek in image coordinates. Returned only if detection classifications 53 * property is set to `FaceDetectorLandmarks.all`. 54 */ 55 leftCheekPosition?: Point; 56 /** 57 * Position of the right cheek in image coordinates. Returned only if detection classifications 58 * property is set to `FaceDetectorLandmarks.all`. 59 */ 60 rightCheekPosition?: Point; 61 /** 62 * Position of the left edge of the mouth in image coordinates. Returned only if detection 63 * classifications property is set to `FaceDetectorLandmarks.all`. 64 */ 65 leftMouthPosition?: Point; 66 /** 67 * Position of the center of the mouth in image coordinates. Returned only if detection 68 * classifications property is set to `FaceDetectorLandmarks.all`. 69 */ 70 mouthPosition?: Point; 71 /** 72 * Position of the right edge of the mouth in image coordinates. Returned only if detection 73 * classifications property is set to `FaceDetectorLandmarks.all`. 74 */ 75 rightMouthPosition?: Point; 76 /** 77 * Position of the bottom edge of the mouth in image coordinates. Returned only if detection 78 * classifications property is set to `FaceDetectorLandmarks.all`. 79 */ 80 bottomMouthPosition?: Point; 81 /** 82 * Position of the nose base in image coordinates. Returned only if detection classifications 83 * property is set to `FaceDetectorLandmarks.all`. 84 */ 85 noseBasePosition?: Point; 86 /** 87 * Yaw angle of the face (heading, turning head left or right). 88 */ 89 yawAngle?: number; 90 /** 91 * Roll angle of the face (bank). 92 */ 93 rollAngle?: number; 94 /** 95 * A face identifier (used for tracking, if the same face appears on consecutive frames it will 96 * have the same `faceID`). 97 */ 98 faceID?: number; 99}; 100 101// @needsAudit 102export type FaceFeatureBounds = { 103 /** 104 * Size of the square containing the face in image coordinates, 105 */ 106 size: { 107 width: number; 108 height: number; 109 }; 110 /** 111 * Position of the top left corner of a square containing the face in image coordinates, 112 */ 113 origin: Point; 114}; 115 116// @docsMissing 117export enum FaceDetectorMode { 118 fast = 1, 119 accurate = 2, 120} 121 122// @docsMissing 123export enum FaceDetectorLandmarks { 124 none = 1, 125 all = 2, 126} 127 128// @docsMissing 129export enum FaceDetectorClassifications { 130 none = 1, 131 all = 2, 132} 133 134// @needsAudit 135export type Image = { 136 /** 137 * URI of the image. 138 */ 139 uri: string; 140 /** 141 * Width of the image in pixels. 142 */ 143 width: number; 144 /** 145 * Height of the image in pixels. 146 */ 147 height: number; 148 /** 149 * Orientation of the image (value conforms to the EXIF orientation tag standard). 150 */ 151 orientation: number; 152}; 153 154// @needsAudit 155/** 156 * In order to configure detector's behavior modules pass a settings object which is then 157 * interpreted by this module. 158 */ 159export type DetectionOptions = { 160 /** 161 * Whether to detect faces in fast or accurate mode. Use `FaceDetector.FaceDetectorMode.{fast, accurate}`. 162 */ 163 mode?: FaceDetectorMode; 164 /** 165 * Whether to detect and return landmarks positions on the face (ears, eyes, mouth, cheeks, nose). 166 * Use `FaceDetector.FaceDetectorLandmarks.{all, none}`. 167 */ 168 detectLandmarks?: FaceDetectorLandmarks; 169 /** 170 * Whether to run additional classifications on detected faces (smiling probability, open eye 171 * probabilities). Use `FaceDetector.FaceDetectorClassifications.{all, none}`. 172 */ 173 runClassifications?: FaceDetectorClassifications; 174 /** 175 * Minimal interval in milliseconds between two face detection events being submitted to JS. 176 * Use, when you expect lots of faces for long time and are afraid of JS Bridge being overloaded. 177 * @default 0 178 */ 179 minDetectionInterval?: number; 180 /** 181 * Flag to enable tracking of faces between frames. If true, each face will be returned with 182 * `faceID` attribute which should be consistent across frames. 183 * @default false 184 */ 185 tracking?: boolean; 186}; 187 188// @needsAudit 189export type DetectionResult = { 190 /** 191 * Array of faces objects. 192 */ 193 faces: FaceFeature[]; 194 // @docsMissing 195 image: Image; 196}; 197// @needsAudit 198/** 199 * Detect faces on a picture. 200 * @param uri `file://` URI to the image. 201 * @param options A map of detection options. 202 * @return Returns a Promise which fulfils with [`DetectionResult`](#detectionresult) object. 203 */ 204export async function detectFacesAsync( 205 uri: string, 206 options: DetectionOptions = {} 207): Promise<DetectionResult> { 208 if (!ExpoFaceDetector || !ExpoFaceDetector.detectFaces) { 209 if (global.expo?.modules?.ExponentConstants?.appOwnership === 'expo') { 210 console.warn( 211 [ 212 "ExpoFaceDetector has been removed from Expo Go. To use this functionality, you'll have to create a development build or prebuild using npx expo run:android|ios commands.", 213 'Learn more: https://expo.fyi/face-detector-removed', 214 'Learn more about development builds: https://docs.expo.dev/develop/development-builds/create-a-build/', 215 'Learn more about prebuild: https://docs.expo.dev/workflow/prebuild/', 216 ].join('\n\n') 217 ); 218 } 219 throw new UnavailabilityError('expo-face-detector', 'detectFaces'); 220 } 221 return await ExpoFaceDetector.detectFaces({ ...options, uri }); 222} 223