2

Iam working on understanding the image with image luminance check and i tried to find the brightness of the image by the code below

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))

Would like to understand how could i get an entire image calculating the luminance of each pixel or a set of them, something similar to what is implemented here at photo-forensics - Luminance Gradient


Error with the implementation

import cv2
import numpy as np

im = cv2.imread('image.jpeg')  
lum = cv2.imread('image.jpeg',cv2.IMREAD_GRAYSCALE)

gradX = cv2.Sobel(lum,cv2.CV_64F,1,0,ksize=5)
gradY = cv2.Sobel(lum,cv2.CV_64F,0,1,ksize=5)

grad  = np.sqrt(gradX**2 + gradY**2)

fraction = 0.3
mixed = cv2.addWeighted(im, fraction, grad, 1.0-fraction,0)

cv2.error: OpenCV(3.4.2) /io/opencv/modules/core/src/arithm.cpp:659: error: (-209:Sizes of input arguments do not match) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function 'arithm_op'

1 Answers1

2

Without further description/clarification from you, I assume you want the gradient of the luminance of the image. So, first we need the luminance image, then the gradient. Note that the example code below is not at all tested, it just gives the general idea of how to proceed.

The luminance is just a synonym for the greyscale image, so depending on your library of choice, you can do:

from PIL import Image
lum = Image.open('image.png').convert('L')            # PIL method

Or:

import cv2
lum = cv2.imread('image.png',cv2.IMREAD_GRAYSCALE)    # OpenCV method

You could alternatively convert to HSV and take third channel:

im = Image.open(f).convert('HSV')                     # PIL method
H, S, lum = im.split()

Or:

im = cv2.imread('image.png')                          # OpenCV method
lum = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)[...,2]

Now you want the gradient of that, so that could be Sobel, or Scharr:

# Calculate gradient in x-direction
gradX = cv2.Sobel(... 0,1, ...)
# And y-direction
gradY = cv2.Sobel(... 1,0, ...)
# And get combined gradient
grad  = np.sqrt(gradX**2 + gradY**2)

It looks like the website you link to is mixing that with the original, I am guessing that can be done with something like:

fraction = 0.3
mixed = cv2.AddWeighted(im, fraction, grad, 1.0-fraction, ...)
My Work
  • 2,143
  • 2
  • 19
  • 47
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • 1
    Not at a suitable computer, but `im` is 3-channel `uint8` and `grad` is 1-channel `float`, so you probably want to promote `im` to `float` and stack `grad` to 3-channel, something like `mixed = cv2.addWeighted(im.astype(np.float64), fraction, np.dstack((grad,grad,grad)), 1.0-fraction,0) ` – Mark Setchell Dec 11 '19 at 12:31
  • Hi, I have a question to @Mark Setchell's answer. What the conversion returns is still an object (namely `PIL.Image.Image`) whenever I use `PIL`. How do I get a luminance of the image from it? And more precisely, I believe that the `lum` is not luminanance but brightness of the image. So how would you get luminance? – My Work Dec 09 '20 at 11:59
  • Please ask questions in the normal way by asking a question rather than tagging a new question onto an old answer where relatively few people will see it. Thank you. You'll get a better answer that way. – Mark Setchell Dec 09 '20 at 12:21