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