Skip to content
Advertisement

Luminance Correction (Prospective Correction)

When I was searching internet for an algorithm to correct luminance I came across this article about prospective correction and retrospective correction. I’m mostly interested in the prospective correction. Basically we take pictures of the scene with image in it(original one), and two other ,one bright and one dark, pictures where we only see the background of the original picture.

My problem is that I couldn’t find any adaptation of these formulas in openCV or code example. I tried to use the formulas as they were in my code but this time I had a problem with data types. This happened when I tried to find C constant by applying operations on images.

This is how I implemented the formula in my code:

def calculate_C(im, im_b):
    fx_mean = cv.mean(im)

    fx_over_bx = np.divide(im,im_b)

    mean_fx_bx = cv.mean(fx_over_bx)

    c = np.divide(fx_mean, mean_fx_bx)

    return c

#Basic image reading and resizing

# Original image
img = cv.imread(image_path)
img = cv.resize(img, (1000,750))

# Bright image
b_img = cv.imread(bright_image_path)
b_img = cv.resize(b_img, (1000,750))

# Calculating C constant from the formula
c_constant = calculate_C(img, b_img)

# Because I have only the bright image I am using second formula from the article
img = np.multiply(np.divide(img,b_img), c_constant)

When I try to run this code I get the error:

img = np.multiply(np.divide(img,b_img), c_constant) ValueError: operands could not be broadcast together with shapes (750,1000,3) (4,)

So, is there anything I can do to fix my code? or is there any hints that you can share with me to handle luminance correction with this method or better methods?

Advertisement

Answer

You are using cv2.mean function which returns array with shape (4,) – mean value for each channel. You may need to ignore last channel and correctly broadcast it to numpy.

Or you could use numpy for calculations instead of opencv.

I just take example images from provided article.

grain.png:

enter image description here

grain_background.png:

enter image description here

Complete example:

import cv2
import numpy as np
from numpy.ma import divide, mean

f = cv2.imread("grain.png")
b = cv2.imread("grain_background.png")

f = f.astype(np.float32)
b = b.astype(np.float32)

C = mean(f) / divide(f, b).mean()
g = divide(f, b) * C

g = g.astype(np.uint8)
cv2.imwrite("grain_out.png", g)

Your need to use masked divide operation because ordinary operation could lead to division by zero => nan values.

Resulting image (output.png):

enter image description here

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement