1import { FaceFeature, Point } from 'expo-face-detector'; 2import React from 'react'; 3import { StyleSheet, Text, View } from 'react-native'; 4 5const landmarkSize = 2; 6 7export const scaledFace = 8 (scale: number) => 9 ({ faceID, bounds, rollAngle, yawAngle }: FaceFeature) => 10 ( 11 <View 12 key={`face-${faceID || yawAngle}`} 13 style={[ 14 styles.face, 15 { 16 width: bounds.size.width * scale, 17 height: bounds.size.height * scale, 18 left: bounds.origin.x * scale, 19 top: bounds.origin.y * scale, 20 transform: [ 21 { perspective: 600 }, 22 { rotateZ: `${rollAngle!.toFixed(0)}deg` }, 23 { rotateY: `${yawAngle!.toFixed(0)}deg` }, 24 ], 25 }, 26 ]}> 27 <Text style={styles.faceText}>ID: {faceID}</Text> 28 <Text style={styles.faceText}>rollAngle: {rollAngle!.toFixed(0)}</Text> 29 <Text style={styles.faceText}>yawAngle: {yawAngle!.toFixed(0)}</Text> 30 </View> 31 ); 32 33export const scaledLandmarks = (scale: number) => (face: FaceFeature) => { 34 const renderLandmark = (position?: Point) => 35 position && ( 36 <View 37 key={`${position?.x ?? 'no-x'}${position?.y ?? 'no-y'}`} 38 style={[ 39 styles.landmark, 40 { 41 left: (position.x - landmarkSize / 2) * scale, 42 top: (position.y - landmarkSize / 2) * scale, 43 }, 44 ]} 45 /> 46 ); 47 console.log('landmark', face); 48 return ( 49 <View key={`landmarks-${face.faceID || face.yawAngle}`}> 50 {renderLandmark(face.leftEyePosition)} 51 {renderLandmark(face.rightEyePosition)} 52 {renderLandmark(face.leftEarPosition)} 53 {renderLandmark(face.rightEarPosition)} 54 {renderLandmark(face.leftCheekPosition)} 55 {renderLandmark(face.rightCheekPosition)} 56 {renderLandmark(face.leftMouthPosition)} 57 {renderLandmark(face.mouthPosition)} 58 {renderLandmark(face.rightMouthPosition)} 59 {renderLandmark(face.noseBasePosition)} 60 {renderLandmark(face.bottomMouthPosition)} 61 </View> 62 ); 63}; 64 65export const face = scaledFace(1); 66export const landmarks = scaledLandmarks(1); 67 68const styles = StyleSheet.create({ 69 face: { 70 padding: 10, 71 borderWidth: 2, 72 borderRadius: 2, 73 position: 'absolute', 74 borderColor: '#FFD700', 75 justifyContent: 'center', 76 backgroundColor: 'rgba(0, 0, 0, 0.5)', 77 }, 78 landmark: { 79 width: landmarkSize, 80 height: landmarkSize, 81 position: 'absolute', 82 backgroundColor: 'red', 83 }, 84 faceText: { 85 color: '#FFD700', 86 fontWeight: 'bold', 87 textAlign: 'center', 88 margin: 10, 89 backgroundColor: 'transparent', 90 }, 91}); 92