expo-face-detector: Black screen when rendering on detected faces

  1. SDK Version: 38.0.8
  2. Platforms(Android/iOS/web/all): tried only on Android

Hello Geeks…

I am new to react-native, I am trying to hands-on for face detecting with below git repo as ref: https://github.com/NewThingsCo/expo-ar/blob/master/docs/ex3.md

I tried to adapt the code to function style rather than old class type. Thing seems to work for some time, but within a minute screen turns black with the rendered mask component still visible. Below is the modified version of repo:

  1. App.js
import React, { useState, useEffect, createRef } from 'react';
import { Text, View, TouchableOpacity, StyleSheet} from 'react-native';
import { Container, Header, Content, Tab, Tabs } from 'native-base';
import { Camera } from 'expo-camera';
import * as FaceDetector from 'expo-face-detector';
import Mask from './Mask.js';
import ActionSheet from "react-native-actions-sheet";

export default function App() {

  const [hasPermission, setHasPermission] = useState(null);
  const [type, setType] = useState(Camera.Constants.Type.front);
  const [faces,setFaces] = useState([]);
  const [faceDetected,setFaceDetected ]= useState(false);
  const actionSheetRef = createRef();
  
  useEffect(() => {
    (async () => {
      const { status } = await Camera.requestPermissionsAsync();
      setHasPermission(status === 'granted');
    })();
  }, []);

  if (hasPermission === null) {
    return <Container/>;
  }
  if (hasPermission === false) {
    return <Text>No access to camera</Text>;
  }

  const onFacesDetected = async (faces)=>{
    if(faces.faces<1)
      return;
    setFaces(faces.faces);
    setFaceDetected(true)
  }

  const onFaceDetectionError = async(error) => {
    setFaceDetected(false);
    console.log(error);
    
  }
  return (
    <View style={{ flex: 1}}>
      <Camera style={{ flex: 1, flexDirection:'row'}} 
      type={type}
      faceDetectorSettings={{
        mode: FaceDetector.Constants.Mode.fast,
        detectLandmarks: FaceDetector.Constants.Landmarks.all,
        tracking: true,
        minDetectionInterval:300
      }}
      onFacesDetected={onFacesDetected}
      onFacesDetectionError={onFaceDetectionError}
      >
        {
          faceDetected?faces.map(face => {
            return <Mask key={face.faceID} face={face} />
          }):undefined
        } 
      </Camera>
    </View>
  );
}

const Style = new StyleSheet.create(
  {
    bottomContainer : {
    flex: 1,
    height : 100,
    alignSelf: 'flex-end',
    alignItems: "center",
    backgroundColor: 'transparent',
    flexDirection: 'row',
    justifyContent: "space-between"
    },
  }

);
  1. Mask.js
import React,{useState, useEffect} from 'react';
import {View } from 'react-native';

const Mask = ({
    face :{
        bounds:{
            origin:{
                x: contatinerX,
                y: contatinerY,
            },
            size: {width : faceWidth}
        },
        leftEyePosition,
        rightEyePosition,
        leftEarPosition,
        rightEarPosition
    }
    }) => {
               
        const eyeWidth = faceWidth/4
        const pupilWidth = eyeWidth/3

        const translatedEyePositionX = eyePosition => eyePosition.x - eyeWidth/2 - contatinerX
        const translatedEyePositionY = eyePosition => eyePosition.y - eyeWidth/2 - contatinerY
        
        const translatedLeftEyePosition  = {
            x:translatedEyePositionX(leftEyePosition),
            y:translatedEyePositionY(leftEyePosition)
        };

        const translatedRightEyePosition  = {
            x:translatedEyePositionX(rightEyePosition),
            y:translatedEyePositionY(rightEyePosition)
        };

        const leftEarBottomPosition = {
            x: translatedEyePositionX(leftEarPosition),
            y: translatedEyePositionX(leftEarPosition),
          };
        const rightEarBottomPosition = {
              x: translatedEyePositionX(rightEarPosition),
              y: translatedEyePositionX(rightEarPosition),
          };
        
        const eyeStyle = (eyePosition,eyeBorderWidth = eyeWidth /10) =>({
            position:'absolute',
            left: eyePosition.x,
            top: eyePosition.y,
            borderRadius: eyeWidth,
            width:eyeWidth,
            height : eyeWidth,
            borderWidth: eyeBorderWidth,
            borderColor: 'black',
            backgroundColor: 'yellow',
            alignItems: 'center',
            flex:1
        });

        const pupilStyle = (eyePosition) =>({
            borderRadius: pupilWidth,
            width: pupilWidth,
            height : pupilWidth,
            backgroundColor: 'black', 
        });

        return(
            
            <View style={{position:'absolute',left:contatinerX, top :contatinerY}}>
                <View style={{...eyeStyle(translatedLeftEyePosition)}}>
                    <View style={{...pupilStyle(translatedLeftEyePosition)}}/>
                </View>
                <View style={{...eyeStyle(translatedRightEyePosition)}}>
                    <View style={{...pupilStyle(translatedRightEyePosition)}}/>
                </View>
            </View>
        
        );
};

export default Mask

below is the image when it gets stuck: screen stuck after few sec

A new mask component is partly created everytime. I think every time face is detected, react is trying to render a new mask rather than updating the one which already exist. Can someone guide me things I am doing wrong over here to fix it.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.