Spaces:
Sleeping
Sleeping
Commit ·
9231da6
1
Parent(s): 0c44fdd
Implementada versión mejorada de check_image_quality y validate_image_dimensions para cálculo dinámico y preciso de brillo y contraste
Browse files- services/image_service.py +51 -8
services/image_service.py
CHANGED
|
@@ -158,7 +158,6 @@ class ImageService:
|
|
| 158 |
def validate_image_dimensions(self, img: np.ndarray) -> Dict[str, Any]:
|
| 159 |
"""
|
| 160 |
Validates image dimensions for facial processing.
|
| 161 |
-
Part of Step 3: Validation of dimensions and size.
|
| 162 |
|
| 163 |
This method analyzes the image dimensions to ensure they meet
|
| 164 |
the requirements for effective facial detection and analysis.
|
|
@@ -170,12 +169,14 @@ class ImageService:
|
|
| 170 |
Returns:
|
| 171 |
Dict with validation results including:
|
| 172 |
- valid: True if dimensions are acceptable, False otherwise
|
|
|
|
| 173 |
- width, height: Image dimensions
|
| 174 |
- warnings: List of warnings if dimensions are not optimal
|
| 175 |
- messages: List of informational messages
|
| 176 |
"""
|
| 177 |
result = {
|
| 178 |
"valid": True,
|
|
|
|
| 179 |
"width": 0,
|
| 180 |
"height": 0,
|
| 181 |
"aspect_ratio": 0,
|
|
@@ -209,6 +210,7 @@ class ImageService:
|
|
| 209 |
if self.min_width <= width < self.optimal_width or self.min_height <= height < self.optimal_height:
|
| 210 |
result["messages"].append(f"Acceptable but not optimal dimensions. Ideal: {self.optimal_width}x{self.optimal_height}")
|
| 211 |
elif width >= self.optimal_width and height >= self.optimal_height:
|
|
|
|
| 212 |
result["messages"].append(f"Optimal dimensions for facial analysis: {width}x{height}")
|
| 213 |
|
| 214 |
# Verify aspect ratio (very elongated can be problematic)
|
|
@@ -243,7 +245,8 @@ class ImageService:
|
|
| 243 |
"brightness": 0.0,
|
| 244 |
"contrast": 0.0,
|
| 245 |
"warnings": [],
|
| 246 |
-
"suggestions": []
|
|
|
|
| 247 |
}
|
| 248 |
|
| 249 |
if img is None:
|
|
@@ -251,7 +254,7 @@ class ImageService:
|
|
| 251 |
return result
|
| 252 |
|
| 253 |
# Convert to grayscale for some metrics
|
| 254 |
-
gray = cv2.cvtColor(img, cv2.
|
| 255 |
|
| 256 |
# Evaluate sharpness (using Laplacian variance)
|
| 257 |
laplacian_var = cv2.Laplacian(gray, cv2.CV_64F).var()
|
|
@@ -271,23 +274,63 @@ class ImageService:
|
|
| 271 |
contrast_score = min(1.0, result["contrast"] * 3) # higher contrast is better
|
| 272 |
|
| 273 |
# Total quality (0-1)
|
| 274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 275 |
|
| 276 |
# Generate warnings and suggestions based on metrics
|
| 277 |
if result["is_blurry"]:
|
| 278 |
result["warnings"].append("The image appears to be blurry.")
|
| 279 |
-
|
|
|
|
|
|
|
| 280 |
|
| 281 |
if result["brightness"] < 0.2:
|
| 282 |
result["warnings"].append("The image is too dark.")
|
| 283 |
-
|
|
|
|
|
|
|
| 284 |
elif result["brightness"] > 0.8:
|
| 285 |
result["warnings"].append("The image is too bright.")
|
| 286 |
-
|
|
|
|
|
|
|
| 287 |
|
| 288 |
if result["contrast"] < 0.1:
|
| 289 |
result["warnings"].append("The image has very low contrast.")
|
| 290 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
|
| 292 |
return result
|
| 293 |
|
|
|
|
| 158 |
def validate_image_dimensions(self, img: np.ndarray) -> Dict[str, Any]:
|
| 159 |
"""
|
| 160 |
Validates image dimensions for facial processing.
|
|
|
|
| 161 |
|
| 162 |
This method analyzes the image dimensions to ensure they meet
|
| 163 |
the requirements for effective facial detection and analysis.
|
|
|
|
| 169 |
Returns:
|
| 170 |
Dict with validation results including:
|
| 171 |
- valid: True if dimensions are acceptable, False otherwise
|
| 172 |
+
- is_optimal: True if dimensions are optimal for processing
|
| 173 |
- width, height: Image dimensions
|
| 174 |
- warnings: List of warnings if dimensions are not optimal
|
| 175 |
- messages: List of informational messages
|
| 176 |
"""
|
| 177 |
result = {
|
| 178 |
"valid": True,
|
| 179 |
+
"is_optimal": False, # Default to false, set to true if dimensions are optimal
|
| 180 |
"width": 0,
|
| 181 |
"height": 0,
|
| 182 |
"aspect_ratio": 0,
|
|
|
|
| 210 |
if self.min_width <= width < self.optimal_width or self.min_height <= height < self.optimal_height:
|
| 211 |
result["messages"].append(f"Acceptable but not optimal dimensions. Ideal: {self.optimal_width}x{self.optimal_height}")
|
| 212 |
elif width >= self.optimal_width and height >= self.optimal_height:
|
| 213 |
+
result["is_optimal"] = True # Set to true as dimensions are optimal
|
| 214 |
result["messages"].append(f"Optimal dimensions for facial analysis: {width}x{height}")
|
| 215 |
|
| 216 |
# Verify aspect ratio (very elongated can be problematic)
|
|
|
|
| 245 |
"brightness": 0.0,
|
| 246 |
"contrast": 0.0,
|
| 247 |
"warnings": [],
|
| 248 |
+
"suggestions": [],
|
| 249 |
+
"recommendations": [] # For compatibility
|
| 250 |
}
|
| 251 |
|
| 252 |
if img is None:
|
|
|
|
| 254 |
return result
|
| 255 |
|
| 256 |
# Convert to grayscale for some metrics
|
| 257 |
+
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) if len(img.shape) == 3 else img
|
| 258 |
|
| 259 |
# Evaluate sharpness (using Laplacian variance)
|
| 260 |
laplacian_var = cv2.Laplacian(gray, cv2.CV_64F).var()
|
|
|
|
| 274 |
contrast_score = min(1.0, result["contrast"] * 3) # higher contrast is better
|
| 275 |
|
| 276 |
# Total quality (0-1)
|
| 277 |
+
quality_value = (sharpness_score * 0.5 + brightness_score * 0.25 + contrast_score * 0.25)
|
| 278 |
+
result["quality_score"] = quality_value
|
| 279 |
+
|
| 280 |
+
# Add backwards compatibility: convert to 0-100 scale and add label
|
| 281 |
+
result["score"] = int(quality_value * 100) # For compatibility with previous code
|
| 282 |
+
|
| 283 |
+
# Add a text label for the quality
|
| 284 |
+
if result["score"] >= 80:
|
| 285 |
+
result["label"] = "Excellent"
|
| 286 |
+
elif result["score"] >= 60:
|
| 287 |
+
result["label"] = "Good"
|
| 288 |
+
elif result["score"] >= 40:
|
| 289 |
+
result["label"] = "Fair"
|
| 290 |
+
elif result["score"] >= 20:
|
| 291 |
+
result["label"] = "Poor"
|
| 292 |
+
else:
|
| 293 |
+
result["label"] = "Very Poor"
|
| 294 |
+
|
| 295 |
+
# Add sharpness label for UI
|
| 296 |
+
if sharpness_score >= 0.8:
|
| 297 |
+
result["sharpness_label"] = "Excellent"
|
| 298 |
+
elif sharpness_score >= 0.6:
|
| 299 |
+
result["sharpness_label"] = "Good"
|
| 300 |
+
elif sharpness_score >= 0.4:
|
| 301 |
+
result["sharpness_label"] = "Fair"
|
| 302 |
+
elif sharpness_score >= 0.2:
|
| 303 |
+
result["sharpness_label"] = "Poor"
|
| 304 |
+
else:
|
| 305 |
+
result["sharpness_label"] = "Very Poor"
|
| 306 |
|
| 307 |
# Generate warnings and suggestions based on metrics
|
| 308 |
if result["is_blurry"]:
|
| 309 |
result["warnings"].append("The image appears to be blurry.")
|
| 310 |
+
suggestion = "Use a sharper image to improve facial detection accuracy."
|
| 311 |
+
result["suggestions"].append(suggestion)
|
| 312 |
+
result["recommendations"].append(suggestion) # For compatibility
|
| 313 |
|
| 314 |
if result["brightness"] < 0.2:
|
| 315 |
result["warnings"].append("The image is too dark.")
|
| 316 |
+
suggestion = "Try using a better illuminated image."
|
| 317 |
+
result["suggestions"].append(suggestion)
|
| 318 |
+
result["recommendations"].append(suggestion) # For compatibility
|
| 319 |
elif result["brightness"] > 0.8:
|
| 320 |
result["warnings"].append("The image is too bright.")
|
| 321 |
+
suggestion = "Try using an image with more balanced lighting."
|
| 322 |
+
result["suggestions"].append(suggestion)
|
| 323 |
+
result["recommendations"].append(suggestion) # For compatibility
|
| 324 |
|
| 325 |
if result["contrast"] < 0.1:
|
| 326 |
result["warnings"].append("The image has very low contrast.")
|
| 327 |
+
suggestion = "An image with higher contrast will improve facial feature detection."
|
| 328 |
+
result["suggestions"].append(suggestion)
|
| 329 |
+
result["recommendations"].append(suggestion) # For compatibility
|
| 330 |
+
|
| 331 |
+
# Convert brightness and contrast to percentage for UI display
|
| 332 |
+
result["brightness"] = float(result["brightness"]) * 100
|
| 333 |
+
result["contrast"] = float(result["contrast"]) * 100
|
| 334 |
|
| 335 |
return result
|
| 336 |
|