实现 Gaussian Filter , Laplacian filter等图像处理中的经典算子。
Requirement
You can do this assignment in a Python .py file or in a Jupyter Notebook.
Recall that if you run into problems with code in a Jupyter Notebook, the best
thing would be to try to debug that code in PyCharm (even if you want to copy
it back to a Jupyter Notebook).
Q1
For this question, perform some basic operations on an image that I have
loaded onto Brightspace (nashville.jpg).
- (a) Read in nashville.jpg, display it, and convert it from RGB to grayscale using the following formula to convert from red, green, and blue values to grayscale intensity:
intensity = 0.2989red + 0.5870green + 0.1140*blue
Save the image as a jpg file called nashvillegray.jpg, read it back in, and
display it. You will use this grayscale version in the remaining parts below. - (b) Create a scrambled version of the grayscale image nashvillegray.jpg. Imagine dividing the image into an 8x8 grid. Create a scrambled version of the image where each of the sections in the 8x8 grid is randomly shuffled (a permutation). An example of the grayscale version and one possible scrambled version is shown below. We discussed a way to accomplish this scrambling in class.
Your code should read in the image into a numpy array. Create a function that
takes this numpy array as an argument and takes the number of ways to slice
the image (for example 8 to create an 8x8 grid) and returns a numpy array
containing the scrambled image. Your code should display the scrambled image.
Aside from using a built in permutation function and other non-image-
processing functions in Python, the scrambling of the image should be done by
your code (in other words, do not search for any built-in image/signal
processing functions or existing packages that might do this scrambling for).
Please try to write your code so that you can change the “8” in the 8x8 grid
to some other value, like a 4x4 grid, or a 64x64 grid; you can assume that the
number is chosen to equally divide the image size. Save the resulting
scrambled image to a jpg file. - (c) Add “noise” to an image (in this case nashvillegray.jpg). Your code should read in the image into a numpy array, that numpy array should be passed to a function that adds the noise, with the noise specified by other arguments passed to the function.
The noise should be normally distributed with mean 0 and standard deviation
sigma. This “noise” is added to the intensity (brightness) of each pixel in
the image. This kind of noise is what sometimes called “salt and pepper
noise”, whereby the intensity of each image pixel is jiggled up or down by a
normally distributed random number.
When you add noise, allow for two options (as an optional argument in your
function): one version where added noise that would cause a pixel value to go
above 255 is capped at 255 go below 0 is capped at 0, and another version
where noise is allowed to jump from 255 to 0 or from 0 to 255 when you cast as
an uint8. Your code should show what happens (displaying two images) to
illustrate the two ways of manipulating noise (and capping vs. rolling over at
the extremes).
Your function should return a numpy array as uint8.
For each version, create one image and save it with a low but perceptible
level of noise and create another image and save it with a relatively high
level of noise; you will be saving four images.
Q2
We talked about using the Laplacian of Gaussians filter to find edges in
images. For this question, I would like you to explore the Laplacian, the
Gaussian, and the Laplacian of Gaussians (LoG). This question uses the
convolution computations we talked about in class and illustrated in the
posted Jupyter Notebooks from class.
For this assignment, read in and use nashvillegray.jpg from above, but your
code should work for any image that is read in.
Use this Laplacian filter:
L = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, -1, -1, -1, -1, -1, 0, 0],
[0, 0, -1, -1, -1, -1, -1, 0, 0],
[0, 0, -1, -1, 24, -1, -1, 0, 0],
[0, 0, -1, -1, -1, -1, -1, 0, 0],
[0, 0, -1, -1, -1, -1, -1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]])
Use this Gaussian filter:
G = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 4, 7, 4, 1, 0, 0],
[0, 0, 4, 16, 26, 16, 4, 0, 0],
[0, 0, 7, 26, 41, 26, 7, 0, 0],
[0, 0, 4, 16, 26, 16, 4, 0, 0],
[0, 0, 1, 4, 7, 4, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]])/273
Note that this Gaussian filter is larger than some of the examples shown in
class (and in the Jupyter notebook) because here we are using a higher-
resolution image. Using a 3x3 Gaussian would produce nearly-imperceptible
blur.
- (a) Confirm (in code) that convolution is commutative, using the Laplacian and Gaussian filters, within a reasonable small epsilon [ .000001. Use the epsilon value in some way to support your demonstration (in other words, do not simply print out the resulting convolutions to inspect by eye - show it somehow).
- (b) Confirm that you understand the computations that underlie convolution. Pick a single pixel location (i,j) somewhere in the grayscale image of the Nashville skyline (nashvillegray.jpg) that is sufficiently far away from the edges of the image to avoid dealing with edge effects. First, calculate the convolution of the Laplacian with the image at this pixel location without using the signal.convolve2d() function, i.e., just following the equations for computing the convolution at a particular pixel location (i,j). Confirm that the value you get with your “hand-coded” convolution calculation matches that using the built-in signal.convolve2d function at the same pixel location (i,j) within some epsilon.
Note that your code will need to work with other filters (not just the
Laplacian) so make sure it’s general (not hard-coded). Recall that the
convolution requires a particular way of doing its calculations that makes it
different from a cross-correlation; don’t just rely on getting the same answer
for your code and the signal.convolve2d function; make sure your code does the
correct calculations. - (c) Create a new filter, called LoG, which is the convolution of the Laplacian with the Gaussian. I do not want you to use the LoG filter I defined in class, but create one by actually convolving the Laplacian with the Gaussian (above) in code. You can use signal.convolve2d() function for this.
- (d) Convolve the image with the Laplacian alone, the Gaussian alone, and the Laplacian of Gaussians. You can use the signal.convolve2d() function for this.
Make a 1x4 subplot. Display the original and the results of the convolutions
using imshow().
Recall that the Laplacian and Laplacian of Gaussians (LoG) produces an “image”
of second derivatives. That means that it will contain both positive and
negative values (you can confirm that by looking at the numpy arrays resulting
from the convolution). You will want to play around with ways to visualize the
Laplacian and LoG. If you just display it directly, it might be hard to see
the results of the filtering. For example, you could set a criterion (a step
function) so that values greater than the criterion are white and those less
than the criterion are black (recall that the Laplacian detects “edges” in an
image). Make sure you manipulate the Laplacian and Laplacian of Gaussian
images the same way.