views:

93

answers:

3

I'd like some advice on performing a simple image analysis in python. I need to calculate a value for the "brightness" of an image. I know PIL is the goto library for doing something like this. There is a built-in histogram function.

What I need is a "perceived brightness" values I can decide if further adjustments to the image are necessary. So what are something of the basic techniques that will work in this situation? Should I just work with the RGB values, or will histogram give me something close enough?

One possible solution might be to combine the two, and generate average R,G,and B values using the histogram, then apply the "perceived brightness" formula.

+1  A: 
Andrew
As one who tried to maintain PythonMagick and provided 0.9.1 version, I would not recommend using it in its current state. Recent changes in ImageMagick broken a lot of PythonMagick code. Package's original author came up with another ImageMagick python bindings, http://public.procoders.net/PythonMagickWand/docs/html/index.html, it is preferrable over current PythonMagick
Daniel Kluev
+2  A: 

Using the techniques mentioned in question, I came up with a few different versions.

Each method returns a value close, but not exactly the same as the others. Also, all methods run about the same speed except for the last one, which is much slower depending on the image size.

  1. Covert image to greyscale, return average pixel brightness.

    def brightness( im_file ):
       im = Image.open(im_file).convert('L')
       stat = ImageStat.Stat(im)
       return stat.mean[0]
    
  2. Covert image to greyscale, return RMS pixel brightness.

    def brightness( im_file ):
       im = Image.open(im_file).convert('L')
       stat = ImageStat.Stat(im)
       return stat.rms[0]
    
  3. Average pixels, then transform to "perceived brightness".

    def brightness( im_file ):
       im = Image.open(im_file)
       stat = ImageStat.Stat(im)
       r,g,b = stat.mean
       return math.sqrt(0.241*(r**2) + 0.691*(g**2) + 0.068*(b**2))
    
  4. RMS of pixels, then transform to "perceived brightness".

    def brightness( im_file ):
       im = Image.open(im_file)
       stat = ImageStat.Stat(im)
       r,g,b = stat.rms
       return math.sqrt(0.241*(r**2) + 0.691(g**2) + 0.068*(b**2))
    
  5. Calculate "perceived brightness" of pixels, then return average.

    def brightness( im_file ):
       im = Image.open(im_file)
       stat = ImageStat.Stat(im)
       gs = (math.sqrt(0.241*(r**2) + 0.691*(g**2) + 0.068*(b**2)) 
             for r,g,b in im.getdata())
       return sum(gs)/stat.count[0]
    

Update Test Results I ran a simulation against 200 images. I found that methods #2,#4 gave almost identical results. Also methods #3,#5 were also nearly identical. Method #1 closely followed #3,#5 (with a few exceptions).

Casey
+1  A: 

I think your best result would come from converting the RGB to grayscale using your favorite formula, then taking the histogram of that result. I'm not sure if the mean or the median of the histogram would be more appropriate, but on most images they are probably similar.

I'm not sure how to do the conversion to grayscale in PIL using an arbitrary formula, but I'm guessing it's possible.

Mark Ransom
Sounds like a good idea. I'll try that as well.
Casey