Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Estimate Brightness of an image Opencv

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.

like image 506
Lakshmi Narayanan Avatar asked Jan 09 '13 17:01

Lakshmi Narayanan


4 Answers

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.

like image 188
Ann Orlova Avatar answered Oct 18 '22 10:10

Ann Orlova


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!

like image 24
Valentin H Avatar answered Oct 18 '22 09:10

Valentin H


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)
like image 38
AlexLoss Avatar answered Oct 18 '22 10:10

AlexLoss


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);
}
like image 25
Stéphane Avatar answered Oct 18 '22 08:10

Stéphane