24

I have been trying to obtain the image brightness in Opencv, and so far I have used calcHist and considered the average of the histogram values. However, I feel this is not accurate, as it does not actually determine the brightness of an image. I performed calcHist over a gray scale version of the image, and tried to differentiate between the avergae values obtained from bright images over that of moderate ones. I have not been successful so far. Could you please help me with a method or algorithm, that can be realised through OpenCv, to estimate brightness of an image? Thanks in advance.

Lakshmi Narayanan
  • 5,220
  • 13
  • 50
  • 92
  • 3
    What exactly do you mean by brightness? Can you post examples of the bright and moderate images you're working with? Ideally alongside their histograms? – Brandon Jackson Jan 09 '13 at 23:07
  • 1
    http://stackoverflow.com/questions/4876315/determining-image-luminance-brightness Possibly this could help – 2vision2 Jan 10 '13 at 12:30
  • Thanks for your help and reply. I have to try it with either HSV as suggested or the YUV given by the link. I am gonna try them now. sorry for the late response. – Lakshmi Narayanan Jan 10 '13 at 16:05
  • @Brandon : By bright images, I mean the images exposed to more white light, in comparison to images that don't strike as brightly white, but with better contrast. I will shortly upload the examples as you requested. – Lakshmi Narayanan Jan 10 '13 at 16:07
  • @LakshmiNarayanan If possible check and lemme know. – 2vision2 Jan 11 '13 at 12:23
  • @2vision2 : I tried both HSV and YUV. But am facing issues computing the average values to determine the brightness. Could you please help me here? – Lakshmi Narayanan Jan 16 '13 at 00:42
  • @LakshmiNarayanan have you calculated the brightness value? And which method you used? – 2vision2 Feb 05 '13 at 12:32
  • @2vision2 I do not know if this is the exact brightness value. Thus, I did not want to reply until I confirm. I calculated using both hsv 'V' channel values and YUvV yuma channel values. There's isn't much of scale difference in yuma channel, but hsv channel 'V' channel values gave much different scale. Different scale as in, there was significant value difference between a bright image and a dark one. – Lakshmi Narayanan Feb 05 '13 at 16:18
  • @2vision2 There's another method which I tried. Computing the histogram of the hsv image, and extracting the 0th channel of the hist, gives me the hist values. Averaging them also gave another scale for brightness, where lower the value, greater was the brightness. The image set I used were not digital images. So maybe they work better for digital images. – Lakshmi Narayanan Feb 05 '13 at 16:22
  • @LakshmiNarayanan Actually jus now I implemented the below answer (HSV ). Have you calculated Histogram of the third channel "V" or just Mean? – 2vision2 Feb 05 '13 at 16:24
  • I calculated the hist of the 'v' channel, then the mean of the values of the hist values alone from histogram, after splitting from the bins. I think that would the the 1st, or 0th by index, channel, after splitting the hist. – Lakshmi Narayanan Feb 05 '13 at 16:33
  • @2vision2 frankly, these methods are not accurate. Please let me know if you used for digital images or normal , any images. – Lakshmi Narayanan Feb 05 '13 at 16:38
  • @LakshmiNarayanan Am using it for ipad video frames. – 2vision2 Feb 05 '13 at 16:41
  • Well, for such a case, I think the hsv would be better. Or try this method @2vision2. Compute the laplacian of the gray scale of the image. obtain the max value using minMacLoc. call it maxval. Estimate your sharpness/brightness index as - (maxval * average V channel values) / (average of the hist values from 0th channel), as said above. This would give you certain values. low bright images are usually below 30. 30 - 50 can b taken as ok images. and above 50 as bright images. – Lakshmi Narayanan Feb 05 '13 at 17:22
  • @2vision2 pls try it and let me know if it works fine. – Lakshmi Narayanan Feb 05 '13 at 17:24
  • @2vision2 it is no standard algorithm, I just arrived at it, after solving for sharpness issue. I trsted it and it had 87% success rate. I want to know from your side. – Lakshmi Narayanan Feb 05 '13 at 17:33
  • @2vision2 http://stackoverflow.com/questions/14690265/dft-frequency-components-opencv/14704033#14704033. I can get some help for this question. If you know, please help me there. – Lakshmi Narayanan Feb 05 '13 at 17:35
  • @LakshmiNarayanan I dont know about that. Have you calculated sharpness of an image? And does it gives good results? – 2vision2 Feb 05 '13 at 18:02
  • @2vision2 : Yes. As I stated it is 87% success rate. And to increase it is why I need to solve that dft question issue which I posted here. You got any answer for tht? "Please help me there. I want to obtain the high frequency component or the average frequency, to estimate its blurness index and combining it with the formula I arrived at above, I think it would be pretty accurate. – Lakshmi Narayanan Feb 05 '13 at 18:05
  • @Lakshmi Narayanan Ya We need to use fftw library. – 2vision2 Feb 05 '13 at 18:12
  • http://stackoverflow.com/questions/13966674/calculate-blurness-and-sharpness-of-an-image You can see here. And even you can answer your 87% solution there , bit briefly. – 2vision2 Feb 05 '13 at 18:17
  • @2vision2 created a room. sharpness brightness keywords. – Lakshmi Narayanan Feb 05 '13 at 18:39
  • This could help - https://github.com/imneonizer/How-to-find-if-an-image-is-bright-or-dark – Sahil Singh Jan 08 '21 at 15:55

4 Answers4

22

I suppose, that HSV color model will be usefull in your problem, where channel V is Value:

"Value is the brightness of the color and varies with color saturation. It ranges from 0 to 100%. When the value is ’0′ the color space will be totally black. With the increase in the value, the color space brightness up and shows various colors."

So use OpenCV method cvCvtColor(const CvArr* src, CvArr* dst, int code), that converts an image from one color space to another. In your case code = CV_BGR2HSV.Than calculate histogram of third channel V.

Ann Orlova
  • 1,338
  • 15
  • 24
  • 8
    Note that HSV assigns the same value to e.g. white and blue pixels, although white pixels are clearly brighter than blue pixels. – Niki Jan 10 '13 at 08:17
  • 2
    @Ann Orlova http://stackoverflow.com/questions/4876315/determining-image-luminance-brightness your thoughts on this? – 2vision2 Jan 10 '13 at 12:31
  • 1
    Thanks for your help and reply. I have to try it with either HSV as suggested or the YUV given by the link. I am gonna try them now. sorry for the late response. – Lakshmi Narayanan Jan 10 '13 at 16:06
  • CIE-LAB color space may also work https://github.com/imneonizer/How-to-find-if-an-image-is-bright-or-dark – Sahil Singh Jan 11 '21 at 05:27
11

I was about to ask the same, but then found out, that similar question gave no satisfactory answers. All answers I've found on SO deal with human observation of a single pixel RGB vs HSV.

From my observations, the subjective brightness of an image also depends strongly on the pattern. A star in a dark sky may look more bright than a cloudy sky by day, while the average pixel value of the first image will be much smaller.

The images I use are grey-scale cell-images produced by a microscope. The forms vary considerably. Sometimes they are small bright dots on very black background, sometimes less bright bigger areas on not so dark background.

My approach is:

  • Find histogram maximum (HMax) using threshold for removing hot pixels.
  • Calculate mean values of all pixel between HMax * 2/3 and HMax

The ratio 2/3 could be also increased to 3/4 (which reduces the range of pixels considered as bright).

The approach works quite well, as different cell-patterns with same titration produce similar brightness.

P.S.: What I actually wanted to ask is, whether there is a similar function for such a calculation in OpenCV or SimpleCV. Many thanks for any comments!

Valentin H
  • 7,240
  • 12
  • 61
  • 111
11

I prefer Valentin's answer, but for 'yet another' way of determining average-per-pixel brightness, you can use numpy and a geometric mean instead of arithmetic. To me it has better results.

from numpy.linalg import norm

def brightness(img):
    if len(img.shape) == 3:
        # Colored RGB or BGR (*Do Not* use HSV images with this function)
        # create brightness with euclidean norm
        return np.average(norm(img, axis=2)) / np.sqrt(3)
    else:
        # Grayscale
        return np.average(img)
AlexLoss
  • 491
  • 4
  • 13
4

A bit of OpenCV C++ source code for a trivial check to differentiate between light and dark images. This is inspired by the answer above provided years ago by @ann-orlova:

const int darkness_threshold = 128; // you need to determine what threshold to use

cv::Mat mat = get_image_from_device();

cv::Mat hsv;
cv::cvtColor(mat, hsv, CV_BGR2HSV);
const auto result = cv::mean(hsv);

// cv::mean() will return 3 numbers, one for each channel:
//      0=hue
//      1=saturation
//      2=value (brightness)

if (result[2] < darkness_threshold)
{
    process_dark_image(mat);
}
else
{
    process_light_image(mat);
}
Stéphane
  • 19,459
  • 24
  • 95
  • 136