fix: address 3 quality review findings — flush_batch finally guard, _laplacian_var helper, has_frigate_scores no-copy
This commit is contained in:
@@ -600,7 +600,10 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
try:
|
||||||
flush_batch(UPLOAD_TRACKER_FILE)
|
flush_batch(UPLOAD_TRACKER_FILE)
|
||||||
|
except Exception as _flush_exc:
|
||||||
|
logger.warning("flush_batch failed during cleanup — batch will be recovered on next begin_batch: %s", _flush_exc)
|
||||||
|
|
||||||
# Batch-map Frigate filenames to asset IDs now that all uploads are done.
|
# Batch-map Frigate filenames to asset IDs now that all uploads are done.
|
||||||
if actually_uploaded and not _skip_reconcile:
|
if actually_uploaded and not _skip_reconcile:
|
||||||
|
|||||||
+8
-6
@@ -14,6 +14,11 @@ from PIL import Image
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _laplacian_var(img_np: np.ndarray) -> float:
|
||||||
|
gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY) if img_np.ndim == 3 else img_np
|
||||||
|
return float(cv2.Laplacian(gray, cv2.CV_64F).var())
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class QualityResult:
|
class QualityResult:
|
||||||
"""Result of quality assessment on a face/image crop."""
|
"""Result of quality assessment on a face/image crop."""
|
||||||
@@ -32,8 +37,7 @@ def check_blur(img_np: np.ndarray, threshold: float = 100.0) -> tuple[bool, str]
|
|||||||
|
|
||||||
Lower variance = blurrier image. ArcFace needs clear facial features.
|
Lower variance = blurrier image. ArcFace needs clear facial features.
|
||||||
"""
|
"""
|
||||||
gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY) if img_np.ndim == 3 else img_np
|
variance = _laplacian_var(img_np)
|
||||||
variance = cv2.Laplacian(gray, cv2.CV_64F).var()
|
|
||||||
if variance < threshold:
|
if variance < threshold:
|
||||||
return False, f"Blurry (laplacian={variance:.1f}, threshold={threshold})"
|
return False, f"Blurry (laplacian={variance:.1f}, threshold={threshold})"
|
||||||
return True, ""
|
return True, ""
|
||||||
@@ -115,8 +119,7 @@ def assess_quality(
|
|||||||
reasons = []
|
reasons = []
|
||||||
|
|
||||||
# Compute laplacian variance once (used by check_blur and stored as blur_score)
|
# Compute laplacian variance once (used by check_blur and stored as blur_score)
|
||||||
gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY) if img_np.ndim == 3 else img_np
|
blur_score = _laplacian_var(img_np)
|
||||||
blur_score = float(cv2.Laplacian(gray, cv2.CV_64F).var())
|
|
||||||
|
|
||||||
checks = [
|
checks = [
|
||||||
(
|
(
|
||||||
@@ -154,8 +157,7 @@ def blur_score_from_image(img: Image.Image, max_dim: int = 1440) -> float | None
|
|||||||
if score_img.width > max_dim or score_img.height > max_dim:
|
if score_img.width > max_dim or score_img.height > max_dim:
|
||||||
score_img = score_img.copy()
|
score_img = score_img.copy()
|
||||||
score_img.thumbnail((max_dim, max_dim), Image.LANCZOS)
|
score_img.thumbnail((max_dim, max_dim), Image.LANCZOS)
|
||||||
gray = cv2.cvtColor(np.array(score_img), cv2.COLOR_RGB2GRAY)
|
return _laplacian_var(np.array(score_img))
|
||||||
return float(cv2.Laplacian(gray, cv2.CV_64F).var())
|
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.debug("blur_score_from_image failed: %s", exc)
|
logger.debug("blur_score_from_image failed: %s", exc)
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -281,9 +281,11 @@ def get_tracked_frigate_filenames(person_name: str) -> set[str]:
|
|||||||
def has_frigate_scores(person_name: str) -> bool:
|
def has_frigate_scores(person_name: str) -> bool:
|
||||||
"""Return True if any mapped file for this person has a stored Frigate recognition score."""
|
"""Return True if any mapped file for this person has a stored Frigate recognition score."""
|
||||||
data = _load(UPLOAD_TRACKER_FILE)
|
data = _load(UPLOAD_TRACKER_FILE)
|
||||||
entry = _migrate_entry(data.get("by_person", {}).get(person_name, {}))
|
raw = data.get("by_person", {}).get(person_name)
|
||||||
frigate_files = entry.get("frigate_files", {})
|
if not raw or isinstance(raw, list):
|
||||||
frigate_scores = entry.get("frigate_scores", {})
|
return False
|
||||||
|
frigate_files = raw.get("frigate_files", {})
|
||||||
|
frigate_scores = raw.get("frigate_scores", {})
|
||||||
return any(asset_id in frigate_scores for asset_id in frigate_files.values())
|
return any(asset_id in frigate_scores for asset_id in frigate_files.values())
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user