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