简体   繁体   中英

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?

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:

在此处输入图像描述

grain_background.png:

在此处输入图像描述

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

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM