Не удается прочитать свойства null (чтение «видео»)

Я пытаюсь создать веб-приложение для обнаружения эмоций, используя Реагировать и лицо-api.js.

У меня есть переключатель, который включает веб-камеру, загружает модели face-api.js и начинает определять лицо и эмоции. Моя проблема заключается в том, что всякий раз, когда я «выключаю» переключатель или оставляю компонент Camera.jsx, я получаю спам в консоли:

enter image description here

Это код компонента Camera.jsx:

import React, { useEffect, useState, useRef } from 'react'
import * as face from 'face-api.js';
import Switch from '@mui/material/Switch';
import './Camera.css';
import Webcam from 'react-webcam';

const Camera = () => {
    const camHeight = 720;
    const camWidth = 1280;
    const videoRef = useRef(null);
    const canvasRef = useRef(null);
    const displaySize = {
        width: camWidth,
        height: camHeight
    }

    const [checked, setChecked] = useState(false);

    const handleChange = (event) => {
        setChecked(event.target.checked);
      };

    useEffect(() => {
        if (checked) {
            const MODEL_URL = `/models`
            const initModels = async () => {
                Promise.all([
                    face.loadTinyFaceDetectorModel(MODEL_URL),
                    face.loadFaceLandmarkModel(MODEL_URL),
                    face.loadFaceRecognitionModel(MODEL_URL),
                    face.loadFaceExpressionModel(MODEL_URL)
                ]);
            }
            initModels();
        }
    }, [checked]);

    const faceAnalysis = () => {
        face.matchDimensions(canvasRef.current, displaySize);
        setInterval(async () => {
            const detections = await face.detectAllFaces(videoRef.current.video, new face.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions();
            const resizedDetections = face.resizeResults(detections, displaySize);
            canvasRef.current.getContext('2d').clearRect(0, 0, camWidth, camHeight);
            face.draw.drawDetections(canvasRef.current, resizedDetections);
            face.draw.drawFaceLandmarks(canvasRef.current, resizedDetections);
            face.draw.drawFaceExpressions(canvasRef.current, resizedDetections);
        }, 50);
    }

    return (
        <div className="analysis">
            <Switch
                checked={checked}
                onChange={handleChange}
                inputProps={{ 'aria-label': 'controlled' }}
            />
            { checked ?  
            <div className="camera">
                <Webcam 
                    ref={videoRef} 
                    videoConstraints={displaySize}
                    onUserMedia={faceAnalysis} 
                />
                <canvas ref={canvasRef} />
            </div>
            : null}
        </div>
    )
}

export default Camera;

Будет ли это проблемой с тем, как я загружаю модели для обнаружения эмоций?

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
0
21
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нашел решение, создав функцию в компоненте Camera.jsx и окружив ее блоком try/catch и очистив интервал в catch следующим образом:

    const drawFaceInterval = () => {
        setInterval(async () => {
            try {
                const detections = await face.detectAllFaces(videoRef.current.video, new face.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions();
                const resizedDetections = face.resizeResults(detections, displaySize);
                canvasRef.current.getContext('2d').clearRect(0, 0, camWidth, camHeight);
                face.draw.drawDetections(canvasRef.current, resizedDetections);
                face.draw.drawFaceLandmarks(canvasRef.current, resizedDetections);
                face.draw.drawFaceExpressions(canvasRef.current, resizedDetections);
            } catch (error) {
                clearInterval(drawFaceInterval);
            }
        }, 50);
    }


И вызываю его обратно в моей функции faceAnalysis():

    const faceAnalysis = () => {
        face.matchDimensions(canvasRef.current, displaySize);
        drawFaceInterval();
    }

Другие вопросы по теме