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