Mick Greener
Mick Greener

Reputation: 93

How can I remove the effects of Vignetting from an image in Python?

I’m a level 2 student currently undertaking the research-led investigation labs. I am studying sunspots, and as part of the task I am coding a Python module that will (amongst other things) remove the effect of vignetting upon the image – that is, the gradual dimming of light towards the edges of the photo due to effects of the camera. I would like to try and remove this using Python.

My approach to this problem so far has been to take a photo of a background that should be uniform, correct the effect that Vignetting has caused, and divide the array of the image we actually care about by this ‘test’ image (please see the code for more detailed doc strings). However, this isn’t quite working and I’m not sure why. I would guess the problem lies in line 18 – I am simply ‘combining’ the image arrays incorrectly – but I am unsure of how to progress to solve this problem.

As you can probably guess, I’ve given this problem a fair old stab and am currently at a loss as to what to do next – so any advice, help, guidance or hints would be very much appreciated!

Here is my attempt so far:

from __future__ import division
import numpy
from PIL import Image
import matplotlib.pyplot as pyplot

IMAGE_1 = Image.open("Vignette test.jpg") #Import a grayscale test image of a uniform background.
ARRAY_1 = numpy.array(IMAGE_1) #Convert into array and slice into just 2 dimensions.
GRAYSCALE_ARRAY_1 = ARRAY_1[:,:,0]
MAX_PIXEL_1 = numpy.amax(GRAYSCALE_ARRAY_1) #Standardise grayscale array by setting max pixel value to 1.
STANDARDISED_ARRAY_1 = GRAYSCALE_ARRAY_1 / MAX_PIXEL_1

IMAGE_2 = Image.open("IMG_1982.jpg") #Import the image we wish to remove the vignette effect from.
ARRAY_2 = numpy.array(IMAGE_2) #Convert into array and slice into just 2 dimensions.
GRAYSCALE_ARRAY_2 = ARRAY_2[:,:,0]
MAX_PIXEL_2 = numpy.amax(GRAYSCALE_ARRAY_2) #Standardise grayscale array by setting max pixel value to 1.
STANDARDISED_ARRAY_2 = GRAYSCALE_ARRAY_2 / MAX_PIXEL_2

CORRECTED_ARRAY = STANDARDISED_ARRAY_2 / STANDARDISED_ARRAY_1 #Divide the two arrays to remove vignetting.
MAX_PIXEL_3 = numpy.amax(CORRECTED_ARRAY) #Standardise corrected array by setting max pixel value to 1.
STANDARDISED_ARRAY_3 = CORRECTED_ARRAY / MAX_PIXEL_3
ARRAY_3 = STANDARDISED_ARRAY_3 * MAX_PIXEL_2 #Ensure that the max pixel value does not exceed 255.
IMAGE_3 = Image.fromarray(ARRAY_3) #Convert into image

pyplot.figure(figsize=(10,12))
pyplot.subplot(211)
IMGPLOT = pyplot.imshow(IMAGE_2) #Represent orignal image graphically with colour bar
IMGPLOT.set_cmap('gray')
pyplot.colorbar()

pyplot.subplot(212)
IMGPLOT = pyplot.imshow(IMAGE_3) #Represent corrrected image graphically with colour bar
IMGPLOT.set_cmap('gray')
pyplot.colorbar()
pyplot.show()

Here's what is generated by pyplot - the original images are too large to attach. The top image is the original 'image of interest'; and the bottom one should be the 'corrected image'.

Upvotes: 3

Views: 2314

Answers (1)

Mick Greener
Mick Greener

Reputation: 93

It turns out that the 'test' image and the image that we care about must have the same exposure time in order for this to work - nothing necessarily wrong with the code itself.

Upvotes: 2

Related Questions