Find If Image Is Bright Or Dark

Question:

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.

Asked By: Farhan R.

||

Answers:

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

Answered By: parthagar

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))
Answered By: SpghttCd

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
Answered By: Mark Setchell
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()
Answered By: Ranjit Kathiriya