Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid importing dlib when it is not used #865

Merged
merged 2 commits into from
Dec 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions viseron/components/codeprojectai/face_recognition.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
import codeprojectai.core as cpai
import cv2
import requests
from face_recognition.face_recognition_cli import image_files_in_folder

from viseron.domains.camera.shared_frames import SharedFrame
from viseron.domains.face_recognition import AbstractFaceRecognition
from viseron.domains.face_recognition.const import CONFIG_FACE_RECOGNITION_PATH
from viseron.helpers import calculate_absolute_coords, letterbox_resize
from viseron.helpers import (
calculate_absolute_coords,
get_image_files_in_folder,
letterbox_resize,
)

from .const import (
COMPONENT,
Expand Down Expand Up @@ -146,7 +149,7 @@ def train(self) -> None:

# Loop through each training image for the current person
try:
img_paths = image_files_in_folder(os.path.join(train_dir, face_dir))
img_paths = get_image_files_in_folder(os.path.join(train_dir, face_dir))
except NotADirectoryError as error:
LOGGER.error(
f"{train_dir} can only contain directories. "
Expand Down
5 changes: 2 additions & 3 deletions viseron/components/compreface/face_recognition.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
import cv2
from compreface import CompreFace
from compreface.collections import FaceCollection, Subjects
from face_recognition.face_recognition_cli import image_files_in_folder

from viseron.domains.camera.shared_frames import SharedFrame
from viseron.domains.face_recognition import AbstractFaceRecognition
from viseron.domains.face_recognition.binary_sensor import FaceDetectionBinarySensor
from viseron.domains.face_recognition.const import CONFIG_FACE_RECOGNITION_PATH
from viseron.helpers import calculate_absolute_coords
from viseron.helpers import calculate_absolute_coords, get_image_files_in_folder

from .const import (
COMPONENT,
Expand Down Expand Up @@ -218,7 +217,7 @@ def train(self) -> None:

# Loop through each training image for the current person
try:
img_paths = image_files_in_folder(os.path.join(train_dir, face_dir))
img_paths = get_image_files_in_folder(os.path.join(train_dir, face_dir))
except NotADirectoryError as error:
LOGGER.error(
f"{train_dir} can only contain directories. "
Expand Down
5 changes: 2 additions & 3 deletions viseron/components/deepstack/face_recognition.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
import cv2
import deepstack.core as ds
import requests
from face_recognition.face_recognition_cli import image_files_in_folder

from viseron.domains.camera.shared_frames import SharedFrame
from viseron.domains.face_recognition import AbstractFaceRecognition
from viseron.domains.face_recognition.const import CONFIG_FACE_RECOGNITION_PATH
from viseron.helpers import calculate_absolute_coords
from viseron.helpers import calculate_absolute_coords, get_image_files_in_folder

from .const import (
COMPONENT,
Expand Down Expand Up @@ -141,7 +140,7 @@ def train(self) -> None:

# Loop through each training image for the current person
try:
img_paths = image_files_in_folder(os.path.join(train_dir, face_dir))
img_paths = get_image_files_in_folder(os.path.join(train_dir, face_dir))
except NotADirectoryError as error:
LOGGER.error(
f"{train_dir} can only contain directories. "
Expand Down
5 changes: 3 additions & 2 deletions viseron/components/dlib/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@

import face_recognition
import PIL
from face_recognition.face_recognition_cli import image_files_in_folder
from sklearn import neighbors

from viseron.helpers import get_image_files_in_folder

LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -72,7 +73,7 @@ def train(

# Loop through each training image for the current person
try:
img_paths = image_files_in_folder(
img_paths = get_image_files_in_folder(
os.path.join(face_recognition_path, face_dir)
)
except NotADirectoryError as error:
Expand Down
50 changes: 31 additions & 19 deletions viseron/components/webserver/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import importlib
import logging
from functools import cache
from pathlib import Path
from typing import TYPE_CHECKING, Any

import tornado.routing
Expand All @@ -18,6 +20,33 @@
LOGGER = logging.getLogger(__name__)


@cache
def get_handler(api_version: str, endpoint: str):
"""Get handler for endpoint."""
version_path = Path(__file__).parent / api_version

if not version_path.is_dir():
return APINotFoundHandler

module_path = version_path / f"{endpoint}.py"
if not module_path.is_file():
return APINotFoundHandler

try:
module = importlib.import_module(
f"viseron.components.webserver.api.{api_version}.{endpoint}"
)
handler_name = f"{endpoint.title()}APIHandler"
if hasattr(module, handler_name):
return getattr(module, handler_name)
except ImportError as error:
LOGGER.warning(
f"Error importing API handler {endpoint}: {error}",
exc_info=True,
)
return APINotFoundHandler


class APIRouter(tornado.routing.Router):
"""Catch-all API Router."""

Expand Down Expand Up @@ -46,29 +75,12 @@ def find_handler(
target_kwargs={"vis": self._vis},
)

endpoint_handler = f"{endpoint.title()}APIHandler"
try:
handler = getattr(
importlib.import_module(
f"viseron.components.webserver.api.{api_version}".format(
api_version
)
),
endpoint_handler,
)
except AttributeError:
handler = get_handler(api_version, endpoint)
if handler == APINotFoundHandler:
LOGGER.warning(
f"Unable to find handler for path: {request.path}",
exc_info=True,
)
handler = APINotFoundHandler
except ModuleNotFoundError as error:
LOGGER.warning(
f"Error importing API endpoint module: {error}", exc_info=True
)
handler = APINotFoundHandler

# Return handler
return self._application.get_handler_delegate(
request=request,
target_class=handler,
Expand Down
22 changes: 0 additions & 22 deletions viseron/components/webserver/api/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1 @@
"""Viseron API."""

from viseron.components.webserver.api.v1.auth import AuthAPIHandler
from viseron.components.webserver.api.v1.camera import CameraAPIHandler
from viseron.components.webserver.api.v1.cameras import CamerasAPIHandler
from viseron.components.webserver.api.v1.compreface import ComprefaceAPIHandler
from viseron.components.webserver.api.v1.config import ConfigAPIHandler
from viseron.components.webserver.api.v1.events import EventsAPIHandler
from viseron.components.webserver.api.v1.hls import HlsAPIHandler
from viseron.components.webserver.api.v1.onboarding import OnboardingAPIHandler
from viseron.components.webserver.api.v1.recordings import RecordingsAPIHandler

__all__ = (
"AuthAPIHandler",
"CameraAPIHandler",
"CamerasAPIHandler",
"ComprefaceAPIHandler",
"ConfigAPIHandler",
"EventsAPIHandler",
"HlsAPIHandler",
"OnboardingAPIHandler",
"RecordingsAPIHandler",
)
10 changes: 10 additions & 0 deletions viseron/helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import math
import multiprocessing as mp
import os
import re
import socket
import time
import tracemalloc
Expand Down Expand Up @@ -670,6 +671,15 @@ def parse_size_to_bytes(size_str: str) -> int:
)


def get_image_files_in_folder(folder) -> list[str]:
"""Return all files with JPG, JPEG or PNG extension."""
return [
os.path.join(folder, f)
for f in os.listdir(folder)
if re.match(r".*\.(jpg|jpeg|png)", f, flags=re.I)
]


def memory_usage_profiler(logger, key_type="lineno", limit=5) -> None:
"""Print a table with the lines that are using the most memory."""
snapshot = tracemalloc.take_snapshot()
Expand Down
Loading