From 9610ce5b8cb355ae39e4b64f6ce114d9a69e905a Mon Sep 17 00:00:00 2001 From: DacongDA Date: Sun, 9 Mar 2025 01:29:25 +0800 Subject: [PATCH] feat: can add faceId by uploading images (#3641) --- web/src/common/modal/FaceRecognitionModal.js | 224 ++++++++++++++----- web/src/table/FaceIdTable.js | 6 +- 2 files changed, 169 insertions(+), 61 deletions(-) diff --git a/web/src/common/modal/FaceRecognitionModal.js b/web/src/common/modal/FaceRecognitionModal.js index 00fd2af8..3a324d5a 100644 --- a/web/src/common/modal/FaceRecognitionModal.js +++ b/web/src/common/modal/FaceRecognitionModal.js @@ -14,11 +14,12 @@ import * as faceapi from "face-api.js"; import React, {useState} from "react"; -import {Button, Modal, Progress, Spin, message} from "antd"; +import {Button, Modal, Progress, Space, Spin, message} from "antd"; import i18next from "i18next"; +import Dragger from "antd/es/upload/Dragger"; const FaceRecognitionModal = (props) => { - const {visible, onOk, onCancel} = props; + const {visible, onOk, onCancel, withImage} = props; const [modelsLoaded, setModelsLoaded] = React.useState(false); const [isCameraCaptured, setIsCameraCaptured] = useState(false); @@ -28,6 +29,10 @@ const FaceRecognitionModal = (props) => { const mediaStreamRef = React.useRef(null); const [percent, setPercent] = useState(0); + const [files, setFiles] = useState([]); + const [currentFaceId, setCurrentFaceId] = React.useState(); + const [currentFaceIndex, setCurrentFaceIndex] = React.useState(); + React.useEffect(() => { const loadModels = async() => { // const MODEL_URL = process.env.PUBLIC_URL + "/models"; @@ -50,6 +55,9 @@ const FaceRecognitionModal = (props) => { }, []); React.useEffect(() => { + if (withImage) { + return; + } if (visible) { setPercent(0); if (modelsLoaded) { @@ -75,6 +83,9 @@ const FaceRecognitionModal = (props) => { }, [visible, modelsLoaded]); React.useEffect(() => { + if (withImage) { + return; + } if (isCameraCaptured) { let count = 0; const interval = setInterval(() => { @@ -98,6 +109,9 @@ const FaceRecognitionModal = (props) => { }, [isCameraCaptured]); const handleStreamVideo = () => { + if (withImage) { + return; + } let count = 0; let goodCount = 0; if (!detection.current) { @@ -148,73 +162,163 @@ const FaceRecognitionModal = (props) => { } }; - return ( -
- { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve(reader.result); + reader.onerror = (error) => reject(error); + }); + }; + + if (!withImage) { + return ( +
+ + Cancel + , + ]} + > + +
+ { + modelsLoaded ? +
+ +
+ + + +
+ +
+ : +
+ +
+ +
+ } +
+ +
+ ); + } else { + return
+ - Cancel + , - ]} - > - -
+ , + ]}> + + { + getBase64(file).then(res => { + file.base64 = res; + files.push(file); + }); + setCurrentFaceId([]); + return false; + }} + onRemove={(file) => { + const index = files.indexOf(file); + const newFileList = files.slice(); + newFileList.splice(index, 1); + setFiles(newFileList); + setCurrentFaceId([]); + }} + > +

{i18next.t("general:Click to Upload")}

+
{ - modelsLoaded ? -
- -
- - - -
- -
- : -
- -
- -
+ modelsLoaded ? : null } -
+
+ { + currentFaceId && currentFaceId.length !== 0 ? ( + +
{i18next.t("application:Select")}:{files[currentFaceIndex]?.name}
+
selected
+
+ ) : null + } -
- ); +
; + } }; export default FaceRecognitionModal; diff --git a/web/src/table/FaceIdTable.js b/web/src/table/FaceIdTable.js index 4777b904..8bb18c7f 100644 --- a/web/src/table/FaceIdTable.js +++ b/web/src/table/FaceIdTable.js @@ -97,12 +97,16 @@ class FaceIdTable extends React.Component { title={() => (
{i18next.t("user:Face IDs")}     - + { this.addFaceId(table, faceIdData); this.setState({openFaceRecognitionModal: false});