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