Skip to content

Commit 399e55a

Browse files
committed
Tune photo quality thresholds
1 parent e55aa19 commit 399e55a

2 files changed

Lines changed: 31 additions & 25 deletions

File tree

evaluation_function/evaluation_test.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -153,25 +153,28 @@ def test_image_quality_rejects_low_single_component_score(self):
153153
)
154154
self.assertLessEqual(
155155
quality["sharpness_score_100"],
156-
quality["quality_min_component_score"],
156+
quality["quality_min_sharpness_score"],
157157
)
158158
self.assertFalse(quality["quality_pass"])
159159

160160
def test_image_quality_soft_warning_does_not_request_retake(self):
161161
image = np.full((120, 160), 130, dtype=np.uint8)
162-
for y in range(0, 120, 20):
163-
image[y:y + 10, :] = 170
164-
for x in range(0, 160, 20):
165-
image[:, x:x + 10] = 90
166-
image = cv2.GaussianBlur(image, (3, 3), 0)
162+
for y in range(0, 120, 8):
163+
image[y:y + 4, :] = 155
164+
for x in range(0, 160, 8):
165+
image[:, x:x + 4] = 105
166+
image = cv2.GaussianBlur(image, (5, 5), 0)
167167
image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
168168

169169
quality = compute_image_quality_metrics(image)
170170
advice = " ".join(quality["quality_advice"]).lower()
171171

172172
self.assertTrue(quality["quality_pass"])
173-
self.assertGreater(quality["sharpness_score_100"], quality["quality_min_component_score"])
174-
self.assertLessEqual(quality["sharpness_score_100"], 50)
173+
self.assertGreater(quality["sharpness_score_100"], quality["quality_min_sharpness_score"])
174+
self.assertLessEqual(
175+
quality["sharpness_score_100"],
176+
quality["quality_warning_sharpness_score"],
177+
)
175178
self.assertIn("a little blurry", advice)
176179
self.assertNotIn("retake", advice)
177180

@@ -180,7 +183,7 @@ def test_quality_advice_soft_warnings_cover_all_components(self):
180183
brightness_mean=50.0,
181184
brightness_component=0.35,
182185
contrast_component=0.35,
183-
sharpness_component=0.35,
186+
sharpness_component=0.20,
184187
noise_component=0.35,
185188
)).lower()
186189

evaluation_function/yolo_pipeline.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@
7171
# not rejected while obviously dark/blurry/noisy ones are sent back for retake.
7272
QUALITY_ACCEPT_SCORE: int = int(os.environ.get("QUALITY_ACCEPT_SCORE", "40"))
7373
QUALITY_MIN_COMPONENT_SCORE: int = int(os.environ.get("QUALITY_MIN_COMPONENT_SCORE", "20"))
74+
QUALITY_MIN_SHARPNESS_SCORE: int = int(os.environ.get("QUALITY_MIN_SHARPNESS_SCORE", "10"))
75+
QUALITY_WARNING_COMPONENT_SCORE: int = int(os.environ.get("QUALITY_WARNING_COMPONENT_SCORE", "50"))
76+
QUALITY_WARNING_SHARPNESS_SCORE: int = int(os.environ.get("QUALITY_WARNING_SHARPNESS_SCORE", "25"))
7477
QUALITY_BRIGHTNESS_USABLE_MIN: float = 35.0
7578
QUALITY_BRIGHTNESS_IDEAL_MIN: float = 60.0
7679
QUALITY_BRIGHTNESS_IDEAL_MAX: float = 210.0
@@ -790,22 +793,22 @@ def _quality_advice(
790793

791794
if brightness_score <= QUALITY_MIN_COMPONENT_SCORE:
792795
advice.append(brightness_fail)
793-
elif brightness_score <= 50:
796+
elif brightness_score <= QUALITY_WARNING_COMPONENT_SCORE:
794797
advice.append(brightness_warn)
795798

796799
if contrast_score <= QUALITY_MIN_COMPONENT_SCORE:
797800
advice.append("The parts do not stand out clearly enough for reliable checking. Please retake the photo with a plain background and fewer shadows.")
798-
elif contrast_score <= 50:
801+
elif contrast_score <= QUALITY_WARNING_COMPONENT_SCORE:
799802
advice.append("The parts do not stand out very clearly. Use a plain background and avoid shadows next time.")
800803

801-
if sharpness_score <= QUALITY_MIN_COMPONENT_SCORE:
804+
if sharpness_score <= QUALITY_MIN_SHARPNESS_SCORE:
802805
advice.append("The photo is too blurry for reliable checking. Please retake it after holding the camera still and refocusing.")
803-
elif sharpness_score <= 50:
806+
elif sharpness_score <= QUALITY_WARNING_SHARPNESS_SCORE:
804807
advice.append("The photo is a little blurry. For better results, hold the camera still and refocus next time.")
805808

806809
if noise_score <= QUALITY_MIN_COMPONENT_SCORE:
807810
advice.append("The photo is too noisy or grainy for reliable checking. Please retake it with better lighting and avoid digital zoom.")
808-
elif noise_score <= 50:
811+
elif noise_score <= QUALITY_WARNING_COMPONENT_SCORE:
809812
advice.append("The photo looks a little noisy or grainy. Use better lighting and avoid digital zoom next time.")
810813

811814
if not advice:
@@ -848,24 +851,21 @@ def compute_image_quality_metrics(img_bgr: np.ndarray) -> Dict[str, Any]:
848851
)
849852
quality_score = int(round(100.0 * (
850853
0.25 * brightness_component
851-
+ 0.20 * contrast_component
852-
+ 0.40 * sharpness_component
853-
+ 0.15 * noise_component
854+
+ 0.25 * contrast_component
855+
+ 0.25 * sharpness_component
856+
+ 0.25 * noise_component
854857
)))
855858
if contrast_component <= 0.0 and sharpness_component <= 0.0:
856859
quality_score = min(quality_score, QUALITY_ACCEPT_SCORE - 1)
857860
brightness_score_100 = _score100(brightness_component)
858861
contrast_score_100 = _score100(contrast_component)
859862
sharpness_score_100 = _score100(sharpness_component)
860863
noise_score_100 = _score100(noise_component)
861-
component_pass = all(
862-
score > QUALITY_MIN_COMPONENT_SCORE
863-
for score in (
864-
brightness_score_100,
865-
contrast_score_100,
866-
sharpness_score_100,
867-
noise_score_100,
868-
)
864+
component_pass = (
865+
brightness_score_100 > QUALITY_MIN_COMPONENT_SCORE
866+
and contrast_score_100 > QUALITY_MIN_COMPONENT_SCORE
867+
and sharpness_score_100 > QUALITY_MIN_SHARPNESS_SCORE
868+
and noise_score_100 > QUALITY_MIN_COMPONENT_SCORE
869869
)
870870
advice = _quality_advice(
871871
brightness_mean=brightness_mean,
@@ -888,6 +888,9 @@ def compute_image_quality_metrics(img_bgr: np.ndarray) -> Dict[str, Any]:
888888
"quality_score_max": 100,
889889
"quality_accept_score": QUALITY_ACCEPT_SCORE,
890890
"quality_min_component_score": QUALITY_MIN_COMPONENT_SCORE,
891+
"quality_min_sharpness_score": QUALITY_MIN_SHARPNESS_SCORE,
892+
"quality_warning_component_score": QUALITY_WARNING_COMPONENT_SCORE,
893+
"quality_warning_sharpness_score": QUALITY_WARNING_SHARPNESS_SCORE,
891894
"quality_pass": quality_score >= QUALITY_ACCEPT_SCORE and component_pass,
892895
"quality_advice": advice,
893896
}

0 commit comments

Comments
 (0)