1+ import cv2
2+ import numpy as np
3+
4+ def is_blurry (img_path ):
5+ img = cv2 .imread (img_path )
6+ if img is None :
7+ return False
8+ gray = cv2 .cvtColor (img , cv2 .COLOR_BGR2GRAY )
9+ laplacian = cv2 .Laplacian (gray , cv2 .CV_64F )
10+ cv2 .imshow ("img" , img )
11+ cv2 .imshow ("gray" , gray )
12+ cv2 .imshow ("laplacian" , laplacian )
13+ cv2 .waitKey (0 )
14+ cv2 .destroyAllWindows ()
15+ score = laplacian .var ()
16+ return score < 100
17+
18+ def check_contrast_brightness (img_path , min_contrast = 40.0 , min_brightness = 30.0 , max_brightness = 230.0 ):
19+ img = cv2 .imread (img_path )
20+ if img is None :
21+ return {
22+ 'has_sufficient_contrast' : False ,
23+ 'has_good_brightness' : False ,
24+ 'contrast_score' : 0.0 ,
25+ 'brightness_score' : 0.0 ,
26+ 'is_acceptable' : False
27+ }
28+
29+ # Convert to grayscale for analysis
30+ gray = cv2 .cvtColor (img , cv2 .COLOR_BGR2GRAY )
31+
32+ # Calculate contrast (standard deviation of pixel intensities)
33+ # Higher std dev = more contrast between different regions
34+ contrast_score = float (gray .std ())
35+ has_sufficient_contrast = contrast_score >= min_contrast
36+
37+ # Calculate brightness (mean pixel intensity)
38+ # Values range from 0 (black) to 255 (white)
39+ brightness_score = float (gray .mean ())
40+ has_good_brightness = min_brightness <= brightness_score <= max_brightness
41+
42+ is_acceptable = has_sufficient_contrast and has_good_brightness
43+
44+ return {
45+ 'has_sufficient_contrast' : has_sufficient_contrast ,
46+ 'has_good_brightness' : has_good_brightness ,
47+ 'contrast_score' : contrast_score ,
48+ 'brightness_score' : brightness_score ,
49+ 'is_acceptable' : is_acceptable
50+ }
51+
52+ def check_aspect_ratio (img_path , min_ratio = 0.7 , max_ratio = 1.4 ):
53+ img = cv2 .imread (img_path )
54+ if img is None :
55+ return {
56+ 'has_valid_aspect_ratio' : False ,
57+ 'aspect_ratio' : 0.0 ,
58+ 'width' : 0 ,
59+ 'height' : 0 ,
60+ 'ratio_description' : 'invalid'
61+ }
62+
63+ height , width = img .shape [:2 ]
64+
65+ # Calculate min(width, height) / max(width, height)
66+ # This gives a value between 0 and 1, where 1 means square
67+ min_dim = min (width , height )
68+ max_dim = max (width , height )
69+ aspect_ratio = float (min_dim ) / float (max_dim )
70+
71+ # Check if ratio is within valid range: 0.7 ≤ ratio ≤ 1.4
72+ # Note: Since min/max ratio is always ≤ 1.0, the effective range is 0.7 to 1.0
73+ has_valid_aspect_ratio = min_ratio <= aspect_ratio <= max_ratio
74+
75+ # Calculate traditional width:height ratio for description
76+ width_height_ratio = float (width ) / float (height )
77+
78+ # Create a readable description of the ratio
79+ if 0.95 <= width_height_ratio <= 1.05 :
80+ ratio_description = "1:1 (square)"
81+ elif width_height_ratio < 1.0 :
82+ # Portrait orientation (height > width)
83+ simplified_ratio = f"1:{ 1 / width_height_ratio :.2f} "
84+ ratio_description = f"{ simplified_ratio } (portrait)"
85+ else :
86+ # Landscape orientation (width > height)
87+ simplified_ratio = f"{ width_height_ratio :.2f} :1"
88+ ratio_description = f"{ simplified_ratio } (landscape)"
89+
90+ return {
91+ 'has_valid_aspect_ratio' : has_valid_aspect_ratio ,
92+ 'aspect_ratio' : aspect_ratio , # This is min/max ratio
93+ 'width_height_ratio' : width_height_ratio , # Traditional width:height ratio
94+ 'width' : width ,
95+ 'height' : height ,
96+ 'ratio_description' : ratio_description
97+ }
98+
99+ if __name__ == "__main__" :
100+ img_path = "test5.png" # Relative path for cross-platform compatibility
101+
102+ # Blurriness check
103+ blurry = is_blurry (img_path )
104+ print ("blurry" if blurry else "not blurry" )
105+
106+ # Contrast/Brightness check
107+ result = check_contrast_brightness (img_path )
108+ print ("bright/contrasted enough" if result ['is_acceptable' ] else "not bright/contrasted enough" )
109+
110+ # Aspect Ratio check
111+ aspect_result = check_aspect_ratio (img_path )
112+ print ("valid aspect ratio" if aspect_result ['has_valid_aspect_ratio' ] else "invalid aspect ratio" )
0 commit comments