fix: address 8 code review findings (round 4)
- diversity: remove erroneous break outside if-faces in _scale_bbox_to_thumbnail (broke people-loop early for first unannotated person, defeating scale fix) - diversity: increment quality_filtered for face-too-small crop skips so the summary log counts them alongside assess_quality failures - diversity: fix hard-example log count to use original confidence_scores[i] instead of synthetic conf_array default (0.5), eliminating false 100% hard-example reports for persons with no Immich confidence data - cache: add EOFError to except tuple in EmbeddingCache.get() so truncated .npy files return None instead of crashing the embedding pipeline - embeddings: wrap each os.dup2 restore in its own try/except OSError in _suppress_output finally block so stderr is always restored even if the stdout restore raises - executor: gate recognize_face on effective_count > 0 (post-stale-cleanup) instead of pre_run_count > 0 so recognize_face is not called against an untrained Frigate model after the user manually deletes all training files - executor: document actually_uploaded trade-off in comment (appending unconditionally on tracker failure risks a Frigate duplicate but prevents permanent filename unmapping which breaks quality-replacement scoring) - jobs: check strategy == "skip" before the has_embedding and custom_limit early-returns in _resolve_strategy so STRATEGY=skip is always honoured
This commit is contained in:
+9
-4
@@ -393,7 +393,7 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
# Pre-upload Frigate score — clean measurement (image not yet in training set).
|
||||
# Called for all below-cap uploads (seeds frigate_scores for future at-cap
|
||||
# replacement) and for at-cap uploads when scores already exist. Skipped on
|
||||
# the first run (pre_run_count == 0) since Frigate has no model yet.
|
||||
# skipped when effective_count == 0 since Frigate has no model yet.
|
||||
# recognize_face returns (face_name, score); we only use the score when the
|
||||
# best match is for the correct person. Mismatches (or "unknown") are treated
|
||||
# as None so a wrong-person score never drives a ceiling skip or replacement.
|
||||
@@ -409,7 +409,7 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
# rebuild-complete signal, poll it between recognize calls during replacement
|
||||
# sequences rather than accepting stale/None scores.
|
||||
pre_fscore: float | None = None
|
||||
if Config.ENABLE_FRIGATE_SCORES and pre_run_count > 0:
|
||||
if Config.ENABLE_FRIGATE_SCORES and effective_count > 0:
|
||||
if not at_cap or person_has_fscores:
|
||||
_result = recognize_face(fpath)
|
||||
if _result is not None and (_result[0] or "").casefold() == name.casefold():
|
||||
@@ -417,8 +417,8 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
|
||||
# Below-cap novelty gate: skip candidates already covered by the Frigate model,
|
||||
# including conditions learned from manually-added images winnow can't track.
|
||||
# pre_fscore is None on the first run (pre_run_count == 0 skips recognize_face
|
||||
# above), so this block never fires on the first run without an extra guard.
|
||||
# pre_fscore is None when effective_count == 0 (no Frigate model yet),
|
||||
# so this block never fires on the first run without an extra guard.
|
||||
if not at_cap and pre_fscore is not None:
|
||||
_ceiling = Config.FRIGATE_SCORE_CEILING
|
||||
if _ceiling is None:
|
||||
@@ -535,6 +535,11 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
person_has_fscores = True
|
||||
# Always record for reconcile so the Frigate filename→asset_id
|
||||
# mapping is created even when the tracker write fails.
|
||||
# Trade-off: if mark_uploaded failed, this asset_id is not in
|
||||
# the upload set, so it may be re-selected next run (Frigate
|
||||
# duplicate). The alternative — not appending — leaves the file
|
||||
# permanently unmapped, breaking quality-replacement scoring.
|
||||
# Frigate duplicate is the lesser consequence.
|
||||
actually_uploaded.append((fname, asset_id))
|
||||
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user