From 098699d91e37598512ad256bd99f99b897a7779f Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 27 Nov 2024 12:48:39 -0700 Subject: [PATCH] Face recognition fixes (#15222) * Fix nginx max upload size * Close upload dialog when done and add toasts * Formatting * fix ruff --- .../rootfs/usr/local/nginx/conf/nginx.conf | 5 ++- frigate/util/model.py | 9 +++-- web/src/pages/FaceLibrary.tsx | 37 +++++++++++++++---- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf index fa487a0838..61b5988596 100644 --- a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf +++ b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf @@ -81,6 +81,9 @@ http { open_file_cache_errors on; aio on; + # file upload size + client_max_body_size 10M; + # https://github.com/kaltura/nginx-vod-module#vod_open_file_thread_pool vod_open_file_thread_pool default; @@ -246,8 +249,6 @@ http { proxy_no_cache $should_not_cache; add_header X-Cache-Status $upstream_cache_status; - client_max_body_size 10M; - location /api/vod/ { include auth_request.conf; proxy_pass http://frigate_api/vod/; diff --git a/frigate/util/model.py b/frigate/util/model.py index 2b7cf1848c..6a0ec43311 100644 --- a/frigate/util/model.py +++ b/frigate/util/model.py @@ -162,7 +162,9 @@ class FaceClassificationModel: def __init__(self, config: FaceRecognitionConfig, db: SqliteQueueDatabase): self.config = config self.db = db - self.recognizer = cv2.face.LBPHFaceRecognizer_create(radius=4, threshold=(1 - config.threshold) * 1000) + self.recognizer = cv2.face.LBPHFaceRecognizer_create( + radius=4, threshold=(1 - config.threshold) * 1000 + ) self.label_map: dict[int, str] = {} def __build_classifier(self) -> None: @@ -190,11 +192,12 @@ def classify_face(self, face_image: np.ndarray) -> Optional[tuple[str, float]]: if not self.label_map: self.__build_classifier() - index, distance = self.recognizer.predict(cv2.equalizeHist(cv2.cvtColor(face_image, cv2.COLOR_BGR2GRAY))) + index, distance = self.recognizer.predict( + cv2.equalizeHist(cv2.cvtColor(face_image, cv2.COLOR_BGR2GRAY)) + ) if index == -1: return None score = 1.0 - (distance / 1000) return self.label_map[index], round(score, 2) - diff --git a/web/src/pages/FaceLibrary.tsx b/web/src/pages/FaceLibrary.tsx index e955a17de6..5ea215dfd3 100644 --- a/web/src/pages/FaceLibrary.tsx +++ b/web/src/pages/FaceLibrary.tsx @@ -20,7 +20,7 @@ export default function FaceLibrary() { // face data - const { data: faceData } = useSWR("faces"); + const { data: faceData, mutate: refreshFaces } = useSWR("faces"); const faces = useMemo( () => (faceData ? Object.keys(faceData) : []), @@ -47,13 +47,36 @@ export default function FaceLibrary() { (file: File) => { const formData = new FormData(); formData.append("file", file); - axios.post(`faces/${pageToggle}`, formData, { - headers: { - "Content-Type": "multipart/form-data", - }, - }); + axios + .post(`faces/${pageToggle}`, formData, { + headers: { + "Content-Type": "multipart/form-data", + }, + }) + .then((resp) => { + if (resp.status == 200) { + setUpload(false); + refreshFaces(); + toast.success( + "Successfully uploaded iamge. View the file in the /exports folder.", + { position: "top-center" }, + ); + } + }) + .catch((error) => { + if (error.response?.data?.message) { + toast.error( + `Failed to upload image: ${error.response.data.message}`, + { position: "top-center" }, + ); + } else { + toast.error(`Failed to upload image: ${error.message}`, { + position: "top-center", + }); + } + }); }, - [pageToggle], + [pageToggle, refreshFaces], ); return (