Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subtract vignetting template from image in OpenCV Python

I have 750+ images, like this 'test.png', that I need to subtract the vignetting in 'vig-raw.png' from. I just started using opencv-python, so "I don't even know what I don't know".

Using GIMP, I desaturated 'vig-raw.png' to create 'vig-desat.png', which I then converted with Color to Alpha to create 'vig-alpha.png'.

This is my attempt to subtract 'vig-alpha.png' from 'test.png'.

import cv2 as cv
import numpy as np

img1 = cv.imread('test.png',0)
img1 = cv.cvtColor(img1, cv.COLOR_BGR2BGRA) # add alpha channel to RGB image
print(img1[0][0]) # show alpha

img2 = cv.imread('vig-alpha.png',flags=cv.IMREAD_UNCHANGED) # read RGBA image
print(img2[0][0]) #show alpha

img3 = cv.subtract(img1, img2)
img3 = cv.resize(img3, (500,250))
print(img3[0][0]) # show alpha

cv.imshow('result',img3)
cv.waitKey()
cv.destroyAllWindows()

However, this is the 'result'. I need to produce a uniform shading throughout the image while leaving the original colors intact. I don't know the correct terminology for this sort of thing, and it's hard to search for a solution with what I do know. Thanks in advance.

EDIT: As per Rotem's answer, image file format matters. StackOverflow converted the PNG files I posted to JPEG, which did effect results while checking their answer. See the comment I left on Rotem's answer below for more information.

like image 417
Jacob Rose Avatar asked Feb 04 '26 00:02

Jacob Rose


1 Answers

Vignette template is not supposed to be subtracted, it supposed to be scaled.

The vignette correction process is known as Flat-field correction applies:

G = m / (F - D)
C = (R - D) * G

When D is dark field or dark frame.

We don't have dark frame sample - we may assume that the dark frame is all zeros.
Assuming D=zeros, the correction formula is:
G = m / F
C = R * G

m = mean(F), and F applies vig-alpha.
R is test.png.


For computing G (name it inv_vig_norm, we may use the following stages):

  • Read vig-alpha.png as grayscale, and convert it to float in range [0, 1] (vig_norm applies F):

     vig = cv2.imread('vig-alpha.png', cv2.IMREAD_GRAYSCALE)
     vig_norm = vig.astype(np.float32) / 255
    
  • Divide m by F:

     vig_mean_val = cv2.mean(vig_norm)[0]
     inv_vig_norm = vig_mean_val / vig_norm  # Compute G = m/F
    
  • Compute C = R * G - scale img1 by inv_vig_norm:

     inv_vig_norm = cv2.cvtColor(inv_vig_norm, cv2.COLOR_GRAY2BGR)
     img2 = cv2.multiply(img1, inv_vig_norm, dtype=cv2.CV_8U)  # Compute: C = R * G
    

For removing noise and artifacts, we may apply Median Blur and Gaussian Blur over vig (it may be required because the site converted vig-alpha.png to JPEG format).


Code sample:

import cv2
import numpy as np

img1 = cv2.imread('test.png')

vig = cv2.imread('vig-alpha.png', cv2.IMREAD_GRAYSCALE)  # Read vignette template as grayscale

vig = cv2.medianBlur(vig, 15)  # Apply median filter for removing artifacts and extreem pixels.

vig_norm = vig.astype(np.float32) / 255  # Convert vig to float32 in range [0, 1]
vig_norm = cv2.GaussianBlur(vig_norm, (51, 51), 30)  # Blur the vignette template (because there are still artifacts, maybe because SO convered the image to JPEG).
#vig_max_val = vig_norm.max()  # For avoiding "false colors" we may use the maximum instead of the mean.
vig_mean_val = cv2.mean(vig_norm)[0]
# vig_max_val / vig_norm
inv_vig_norm = vig_mean_val / vig_norm  # Compute G = m/F

inv_vig_norm = cv2.cvtColor(inv_vig_norm, cv2.COLOR_GRAY2BGR)  # Convert inv_vig_norm to 3 channels before using cv2.multiply. https://stackoverflow.com/a/48338932/4926757

img2 = cv2.multiply(img1, inv_vig_norm, dtype=cv2.CV_8U)  # Compute: C = R * G

cv2.imshow('inv_vig_norm',  cv2.resize(inv_vig_norm / inv_vig_norm.max(), (500, 250)))  # Show inv_vig_norm for testing
cv2.imshow('img1', cv2.resize(img1, (500, 250)))
cv2.imshow('result', cv2.resize(img2, (500, 250)))
cv2.waitKey()
cv2.destroyAllWindows()

Results:

img1:
enter image description here

inv_vig_norm:
enter image description here

img2:
enter image description here

like image 112
Rotem Avatar answered Feb 06 '26 12:02

Rotem



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!