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

add ! validate image size #104

Closed
wants to merge 1 commit into from
Closed
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
3 changes: 0 additions & 3 deletions src/hope_dedup_engine/apps/api/admin/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,3 @@ def has_add_permission(self, request):

def has_change_permission(self, request, obj=None):
return False

def has_delete_permission(self, request, obj=None):
return obj is not None
7 changes: 4 additions & 3 deletions src/hope_dedup_engine/apps/api/deduplication/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ def find_duplicates(deduplication_set_id: str, serialized_lock: str) -> None:
deduplication_set.state = deduplication_set.State.CLEAN
deduplication_set.save()

if lock_enabled:
lock.release()

except Exception:
deduplication_set.state = DeduplicationSet.State.ERROR
deduplication_set.save()
raise

finally:
if lock_enabled:
lock.release()
9 changes: 9 additions & 0 deletions src/hope_dedup_engine/apps/core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,12 @@ class DownloaderKeyError(Exception):
def __init__(self, key: str) -> None:
self.key = key
super().__init__(f"Downloader key '{key}' does not exist.")


class NotCompliantImageError(Exception):
"""
Exception raised when an image is not compliant with the expected parameters.
"""

def __init__(self, message: str) -> None:
super().__init__(message)
26 changes: 14 additions & 12 deletions src/hope_dedup_engine/apps/faces/services/image_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import numpy as np
from constance import config

from hope_dedup_engine.apps.core.exceptions import NotCompliantImageError
from hope_dedup_engine.apps.faces.managers import DNNInferenceManager, StorageManager


Expand Down Expand Up @@ -97,19 +98,18 @@ def _get_face_detections_dnn(
# Decode image from binary buffer to 3D numpy array (height, width, channels of BlueGreeRed color space)
image = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
(h, w) = image.shape[:2]
_h, _w = (
self.blob_from_image_cfg.shape["height"],
self.blob_from_image_cfg.shape["width"],
)
if h < _h or w < _w:
raise NotCompliantImageError(
f"Image {filename} too small: '{h}x{w}'. It needs to be at least '{_h}x{_w}'."
)
# Create a blob (4D tensor) from the image
blob = cv2.dnn.blobFromImage(
image=cv2.resize(
image,
dsize=(
self.blob_from_image_cfg.shape["height"],
self.blob_from_image_cfg.shape["width"],
),
),
size=(
self.blob_from_image_cfg.shape["height"],
self.blob_from_image_cfg.shape["width"],
),
image=cv2.resize(image, dsize=(_h, _w)),
size=(_h, _w),
scalefactor=self.blob_from_image_cfg.scale_factor,
mean=self.blob_from_image_cfg.mean_values,
)
Expand Down Expand Up @@ -161,7 +161,9 @@ def encode_face(self, filename: str, encodings_filename: str) -> None:
encodings: list[np.ndarray[np.float32, Any]] = []
face_regions = self._get_face_detections_dnn(filename)
if not face_regions:
self.logger.warning("No face regions detected in image %s", filename)
raise NotCompliantImageError(
f"No face regions detected in image '{filename}'."
)
else:
for region in face_regions:
if isinstance(region, (list, tuple)) and len(region) == 4:
Expand Down
2 changes: 1 addition & 1 deletion src/hope_dedup_engine/config/fragments/constance.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
int,
),
"FACE_ENCODINGS_MODEL": (
"small",
"large",
"""
Specifies the model type used for encoding face landmarks. It can be either 'small' which is faster and
detects only 5 key facial landmarks, or 'large' which is more precise and identifies 68 key facial landmarks
Expand Down
Binary file modified tests/extras/demoapp/demo_images/Aaron_Eckhart_0001.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/extras/demoapp/demo_images/Aaron_Guiel_0001.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/extras/demoapp/demo_images/Aaron_Peirsol_0001.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/extras/demoapp/demo_images/Aaron_Peirsol_0002.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/extras/demoapp/demo_images/Cathy_Freeman_0001.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/extras/demoapp/demo_images/Cathy_Freeman_0002.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/extras/demoapp/demo_images/Ziwang_Xu_0001.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/extras/demoapp/demo_images/Zoe_Ball_0001.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/extras/demoapp/demo_images/too_small.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/extras/demoapp/demo_images/without_face.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tests/faces/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def mock_image_processor(
@pytest.fixture
def image_bytes_io():
img_byte_arr = BytesIO()
image = Image.new("RGB", (100, 100), color="red")
image = Image.new("RGB", (300, 300), color="red")
image.save(img_byte_arr, format="JPEG")
img_byte_arr.seek(0)
img_byte_arr.fake_open = lambda *_: BytesIO(img_byte_arr.getvalue())
Expand Down
8 changes: 4 additions & 4 deletions tests/faces/faces_const.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
}
FACE_REGIONS_INVALID: Final[list[list[tuple[int, int, int, int]]]] = [[], [(0, 0, 10)]]
FACE_REGIONS_VALID: Final[list[tuple[int, int, int, int]]] = [
(10, 10, 20, 20),
(30, 30, 40, 40),
(40, 40, 80, 80),
(120, 120, 160, 160),
]
BLOB_FROM_IMAGE_SCALE_FACTOR: Final[float] = 1.0
BLOB_FROM_IMAGE_MEAN_VALUES: Final[tuple[float, float, float]] = (104.0, 177.0, 123.0)
Expand All @@ -56,8 +56,8 @@
(0, 0, 0.15, 0.1, 0.1, 0.2, 0.2), # with confidence 0.15 -> invalid detection
]
IMAGE_SIZE: Final[tuple[int, int, int]] = (
100,
100,
400,
400,
3,
) # Size of the image after decoding (h, w, number of channels)
RESIZED_IMAGE_SIZE: Final[tuple[int, int, int]] = (
Expand Down
Loading