I would like to know how to write a function in Python 3 using OpenCV which takes in an image and a threshold and returns either 'dark' or 'light' after heavily blurring it and reducing quality (faster the better). This might sound vague , but anything that just works will do.
-
What did you try so far? – inetphantom Sep 25 '18 at 20:15
-
3Why not just type an **ImageMagick** 1-liner into the terminal that tells you the mean intensity of an image as a percentage `convert image.jpg -format "%[fx:int(mean*100)]" info:` – Mark Setchell Sep 25 '18 at 20:28
-
Not sure why you feel you need to blur? – Mark Setchell Sep 25 '18 at 20:52
-
Why not simply use a histogram based approach? – SilverMonkey Sep 25 '18 at 21:44
-
1You could use `libvips` directly in Terminal `vips avg someImage.png` – Mark Setchell Sep 25 '18 at 22:35
4 Answers
Personally, I would not bother writing any Python, or loading up OpenCV for such a simple operation. If you absolutely have to use Python, please just disregard this answer and select a different one.
You can just use ImageMagick at the command-line in your Terminal to get the mean brightness of an image as a percentage, where 100 means "fully white" and 0 means "fully black", like this:
convert someImage.jpg -format "%[fx:int(mean*100)]" info:
Alternatively, you can use libvips
which is less common, but very fast and very lightweight:
vips avg someImage.png
The vips
answer is on a scale of 0..255 for 8-bit images.
Note that both these methods will work for many image types, from PNG, through GIF, JPEG and TIFF.
However, if you really want Python/OpenCV code, I note none of the existing answers do that - some use a different library, some are incomplete, some do superfluous blurring and some read video cameras for some unknown reason, and none handle more than one image or errors. So, here's what you actually asked for:
#!/usr/bin/env python3
import cv2
import sys
import numpy as np
# Iterate over all arguments supplied
for filename in sys.argv[1:]:
# Load image as greyscale
im = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
if im is None:
print(f'ERROR: Unable to load {filename}')
continue
# Calculate mean brightness as percentage
meanpercent = np.mean(im) * 100 / 255
classification = "dark" if meanpercent < 50 else "light"
print(f'{filename}: {classification} ({meanpercent:.1f}%)')
Sample Output
OpenCVBrightOrDark.py g*png nonexistant
g30.png: dark (30.2%)
g80.png: light (80.0%)
ERROR: Unable to load nonexistant

- 191,897
- 31
- 273
- 432
You could try this :
import imageio
import numpy as np
f = imageio.imread(filename, as_gray=True)
def img_estim(img, thrshld):
is_light = np.mean(img) > thrshld
return 'light' if is_light else 'dark'
print(img_estim(f, 127))

- 2,642
- 1
- 20
- 37

- 10,510
- 2
- 20
- 25
-
-
1even thought that solution works i could not distinguish between light and dark images. since the difference is very small. e.g dark images some times are 136 while light images sometimes are 136 as well.. need a more smart way to figure out the grayscale than the light images – TharsDimitris Mar 04 '19 at 11:56
-
You could try this, considering image
is a grayscale image -
blur = cv2.blur(image, (5, 5)) # With kernel size depending upon image size
if cv2.mean(blur) > 127: # The range for a pixel's value in grayscale is (0-255), 127 lies midway
return 'light' # (127 - 255) denotes light image
else:
return 'dark' # (0 - 127) denotes dark image
Refer to these -
Smoothing, Mean, Thresholding

- 880
- 1
- 7
- 18
-
1The mean before and after blurring should be the same (if a proper boundary condition is used). – Cris Luengo Sep 25 '18 at 22:30
-
2Its important to note that 127 is ~ half 255, and everything.Please comment your code. – Loïc Sep 25 '18 at 22:38
-
@CrisLuengo that is true for blur() but other blurring techniques change the mean(). – parthagar Sep 26 '18 at 09:48
import numpy as np
import cv2
def algo_findDark(image):
blur = cv2.blur(image, (5, 5))
mean = np.mean(blur)
if mean > 85:
return 'light'
else:
return 'dark'
cam = cv2.VideoCapture(0)
while True:
check, frame = cam.read()
frame_gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
ans = algo_findDark(frame_gray)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame, ans, (10, 450), font, 3, (0, 0, 255), 2, cv2.LINE_AA)
cv2.imshow('video', frame)
key = cv2.waitKey(1)
if key == 27:
break
cam.release()
cv2.destroyAllWindows()

- 131
- 1
- 5