What are some methods to analyze image brightness using Python?

前端 未结 4 1803
再見小時候
再見小時候 2020-12-22 20:15

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 doi

相关标签:
4条回答
  • 2020-12-22 20:52

    Given that you're just looking for an average across the whole image, and not per-pixel brightness values, averaging PIL's histogram and applying the brightness function to the output seems like the best approach for that library.

    If using ImageMagick (with the PythonMagick bindings), I would suggest using the identify command with the "verbose" option set. This will provide you with a mean value for each channel, saving you the need to sum and average a histogram — you can just multiply each channel directly.

    0 讨论(0)
  • 2020-12-22 20:53

    Using the techniques mentioned in the 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. Convert 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. Convert 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).

    0 讨论(0)
  • 2020-12-22 20:56

    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.

    0 讨论(0)
  • 2020-12-22 21:00

    the code below will give you the brightness level of an image from 0-10

    1- calculate the average brightness of the image after converting the image to HSV format using opencv.

    2- find where this value lies in the list of brightness range.

     import numpy as np
     import cv2
     import sys
     from collections import namedtuple
    
    #brange brightness range
    #bval brightness value
    BLevel = namedtuple("BLevel", ['brange', 'bval'])
    
    #all possible levels
    _blevels = [
        BLevel(brange=range(0, 24), bval=0),
        BLevel(brange=range(23, 47), bval=1),
        BLevel(brange=range(46, 70), bval=2),
        BLevel(brange=range(69, 93), bval=3),
        BLevel(brange=range(92, 116), bval=4),
        BLevel(brange=range(115, 140), bval=5),
        BLevel(brange=range(139, 163), bval=6),
        BLevel(brange=range(162, 186), bval=7),
        BLevel(brange=range(185, 209), bval=8),
        BLevel(brange=range(208, 232), bval=9),
        BLevel(brange=range(231, 256), bval=10),
    ]
    
    
    def detect_level(h_val):
         h_val = int(h_val)
         for blevel in _blevels:
            if h_val in blevel.brange:
                return blevel.bval
        raise ValueError("Brightness Level Out of Range")
    
    
     def get_img_avg_brightness():
         if len(sys.argv) < 2:
            print("USAGE: python3.7 brightness.py <image_path>")
            sys.exit(1)
         img = cv2.imread(sys.argv[1])
         hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
         _, _, v = cv2.split(hsv)
    
         return int(np.average(v.flatten()))
    
     if __name__ == '__main__':
    
         print("the image brightness level is: 
                {0}".format(detect_level(get_img_avg_brightness())))
    
    0 讨论(0)
提交回复
热议问题