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