开发者

Determine if an image needs contrasting automatically in OpenCV

OpenCV has a handy cvEqualizeHist() function that works great on faded/low-contrast images. However when an already high-contrast image is given, the result is a low-contrast one. I got the reason - the histogram being distributed evenly and stuff.

Question is - how do I get to know the difference between a low-contrast and a high-contrast image?

I'm operating on Grayscale images and setting their contrast properly so that thresholding them won't delete the text i'm supposed to extract (thats a different story). Suggestions welcome - esp on how to find out if the majority of the pixels in the image are light gray (which means that the equalise hist is to be performed) Please help!

EDIT: thanks everyone for many informative answers. But the standard deviation calculation was sufficient for my requirem开发者_开发百科ents and hence I'm taking that to be the answer to my query.


You can probably just use a simple statistical measure of the image to determine whether an image has sufficient contrast. The variance of the image would probably be a good starting point. If the variance is below a certain threshold (to be empirically determined) then you can consider it to be "low contrast".


If you're adjusting contrast just so you can threshold later on, you may be able to avoid the contrast adjustment step if you set your threshold adaptively using Ohtsu's method.

If you're still interested in finding out the image contrast, then read on.

While there are a number of different ways to calculate "contrast". Often, those metrics are applied locally as opposed to the entire image, to make the result more sensitive to image content:

  • Divide the image into adjacent non-overlaying neighborhoods.
  • Pick neighborhood sizes that are approximate to size of the features of your image (e.g. if your main feature is horizontal text, make neighborhoods tall enough to capture 2 lines of text, and just as wide).
  • Apply the metric to each neighborhood individually
  • Threshold the metric result to separate low and high variance blocks. This will prevent such things as large, blank areas of page skewing your contrast estimates.

From there, you can use a number of features to determine contrast:

  • The proportion of high metric blocks to low metric blocks
  • High metric block mean
  • Intensity distance between the high and low metric blocks (using means, modes, etc)

This may serve as a better indication of image contrast than global image variance alone. Here's why:

Determine if an image needs contrasting automatically in OpenCV

(stddev: 50.6)

Determine if an image needs contrasting automatically in OpenCV

(stddev: 7.9)

The two images are perfectly in contrast (the grey background is just there to make it obvious it's an image), but their standard deviations (and thus variance) are completely different.


  1. Calculate cumulative histogram of image.
  2. Make linear regression of cumulative histogram in the form y(x) = A*x + B.
  3. Calculate RMSE of real_cumulative_frequency(x)-y(x).
  4. If that RMSE is close to zero - image is already equalized. (That means that for equalized images cumulative histograms must be linear)

Idea is taken from here.

EDIT: I've illustrated this approach in my blog (C example code included).


There is a support provided in skimage for this. skimage.exposure.is_low_contrast. reference

example :

>>> image = np.linspace(0, 0.04, 100)
>>> is_low_contrast(image)
    True
>>> image[-1] = 1
>>> is_low_contrast(image)
    True
>>> is_low_contrast(image, upper_percentile=100)
    False
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜