Fun with Filters and Frequencies!

CS 180 Project 2

Jiayang Wang | jiayang.wang@berkeley.edu

Introduction

This project explores ways of image frequency manipulation through various applications, including edge detection (finite difference operators), image "sharpening" (unsharp mask filter), hybrid image (low-pass and high-pass filters), and multi-resolution blending (Gaussian and Laplacian stacks).

Fun with Filters

Finite Difference Operator

Edges in an image can be coarsely detected where neighboring pixels have high differences in their intensity values, and the gradient magnitude image of an image shows exactly this information. To create the gradient magnitude image, I convolved finite difference operators D_x = np.array([[1], [-1]]) and D_y = np.array([[1, -1]]) onto the original image to get the partial derivatives of the image on x-axis and y-axis, and stack them to get the gradient magnitude image. I then binarized the result with the intensity threshold of 71, over the range of 0~255, to filter out the noise while retaining the real edges.

cameraman_dx.jpg

dx

cameraman_dy.jpg

dy

cameraman_magnitude.jpg

Magnitude

cameraman_71.jpg

Edges (Threshold = 71)

Derivative of Gaussian (DoG) Filter

While an appropriate threshold can filter out most of the noises, the result edge image is still relatively noisy, and the edges are also not smooth. To smooth the image, I applied a Gaussian filter (size = 9, sigma = 1.5) on the image that blurred it, thus diffusing the noises to neighboring pixels while smoothing the sharp edges. As the edges are smoothed, the threshold must also be lowered. Repeating the procedure in the previous part on this blurred image with the intensity threshold of 16 shows significant differences between the two result edge images. The edges in the new edge image are smoother and thicker, clearly showing the shape of the cameraman and the camera. The noises that presented in the lower half of the old edge image are almost all filtered out, leaving a cleaner and clearer edge image.

Since the convolution operation is associative, convolving the original image with the finite difference operators and the Gaussian filter separately should result in the same image as convolving the Gaussian filter with the finite difference operators first to create the Derivative of Gaussian (DoG) filter, and then convolve the original image with the DoG filter. I applied the DoG filter method on the same original image, and the result is shown below.

cameraman_16_9.jpg

Finite Difference Operator -> Gaussian Filter
(Threshold = 16)

cameraman_16_9_G.jpg

Derivative of Gaussian (DoG) Filter
(Threshold = 16)

As expected, the two results are identical, apart from some neglectable differences caused by floating point precision errors.

Fun with Frequencies!

Image "Sharpening"

Images with stronger high frequencies often look sharper, and this is the core theory of image "sharpening" - add the high frequencies of the image back to the original image as the fake sharpness. While low-pass filters, such as Gaussian filters, retain only the low frequencies of the image by blurring it and filtering out the details (high frequencies), the high frequencies of the same image can be calculated by subtracting the blurred image from the original image, such that all low frequencies are subtracted from the original image and only the high frequencies are left.

Rewrite the process as a formula, result = image + alpha(image - image * Gaussian) where the Gaussian filter is (size = 9, sigma = 3). Using the properties of convolution, the entire formula can be combined as a single convolution operation called the unsharp mask filter. To combine the formula, replace image with impulse filters since image * Impulse = image. The formula thus becomes result = image * (Impulse + alpha(Impulse - Gaussian)) where Impulse + alpha(Impulse - Gaussian) is the unsharp mask filter.

taj.jpg

Original

taj.jpg_1_9_sharpened.jpg

Sharpened (alpha = 1)

cliff.jpg

Original

cliff.jpg_1_9_sharpened.jpg

Sharpened (alpha = 1)

land.jpg

Original

land.jpg_1_9_sharpened.jpg

Sharpened (alpha = 1)

To confirm that the "sharpness" added using this method is not actually creating details, I picked a sharp image, blurred it using a low-pass Gaussian filter, and then used this method to try sharpening the blurred image. The sharpened image looks sharper than the blurred image, but is still blurry compared to the original image, since this method cannot recover the lost information caused by the low-pass filter filtering out the highest frequencies.

machine.jpg

Original

machine.jpg_blur.jpg

Blurred (size = 9, sigma = 3)

machine.jpg_1_9_blur_sharpened.jpg

Blurred -> Sharpened (alpha = 1)

Hybrid Images

Following the SIGGRAPH 2006 paper by Oliva, Torralba, and Schyns, I used the same method to create hybrid images that change in interpretation when the distance between the image and the viewer changes, such that when the viewing distance is close, the image with high frequencies is dominant, and when the viewing distance is far, only the image with low frequencies can be seen. For each pair of images, the im_low is filtered with a Gaussian low-pass filter with parameters varying between pairs such that only the low frequencies are retained, and the im_high is filtered with the Impulse - Gaussian high-pass filter, also with parameters varying between pairs, such that only the high frequencies are retained. After both images are filtered, simply adding them produces the desired hybrid image.

DerekPicture.jpg

Low-Frequency Image
"DerekPicture.jpg"
(Gaussian size = 19, sigma = 6)

nutmeg.jpg

High-Frequency Image
"nutmeg.jpg"
(Gaussian size = 61, sigma = 20)

DerekPicture.jpg_nutmeg.jpg_hybrid.jpg

Hybrid Image
"Deremeg.jpg"

onigiri.png

Low-Frequency Image
"onigiri.png"
(Gaussian size = 61, sigma = 20)

birb.png

High-Frequency Image
"birb.png"
(Gaussian size = 31, sigma = 10)

onigiri.png_birb.png_hybrid.jpg

Hybrid Image
"torigiri.jpg"

anakin-padme1.png

Low-Frequency Image
"anakin-padme1.png"
(Gaussian size = 31, sigma = 10)

anakin-padme2.png

High-Frequency Image
"anakin-padme2.png
(Gaussian size = 151, sigma = 50)

anakin-padme1.png_anakin-padme2.png_hybrid.jpg

Hybrid Image
"padon-mé?.jpg"

This process of creating hybrid image can be illustrated through frequency analysis. The images below show the log magnitude of the Fourier transform of the two input images, the filtered images, and the hybrid image. For onigiri.png, the image is filtered with a low-pass filter so the FFT image has higher intensity around the center and the axes, and much lower intensity elsewhere. For birb.png, the image is filtered with a high-pass filter so the FFT image has lower intensity around the very center, and higher intensity elsewhere. The FFT image of the hybrid image is indeed a combination of the FFT images of the two filtered images.

onigiri.png_original_ft.jpg

Low Frequency Image FFT

onigiri.png_filtered_ft.jpg

Filtered FFT

birb.png_original_ft.jpg

High Frequency Image FFT

brib.png_filtered_ft.jpg

Filtered FFT

onigiri.png_birb.png_hybrid.jpg_ft.jpg.jpg

Hybrid Image FFT

However, when the shape of the two images are too similar, the hybrid effect will be less visible, and the hybrid image will stay the same independent of the viewing distance. Also, when the original high-frequency image is vibrant, the filtered image will lose the high-saturation color, leaving only a transparent shape. Below is one example of the said failure.

cockatoo.jpg

Low-Frequency Image
"cockatoo.jpg"
(Gaussian size = 16, sigma = 5)

gumi.jpg

High-Frequency Image
"gumi.jpg"
(Gaussian size = 31, sigma = 10)

cockatoo.jpg_gumi.jpg_hybrid.jpg

Hybrid Image
"wuewuewaaah.jpg"
Failure, but sooooo cute

Multi-resolution Blending and the Oraple journey

Gaussian and Laplacian Stacks

Gaussian stacks are Gaussian pyramids without the downsampling, such that images in the stack are all the same dimension as the original image. Instead, each level of the Gaussian stack can be created by convolving the original image with Gaussian filters where both size and sigma of the Gaussian filter increase through each level. In my case, the maximum level of stacks is 6, the initial Gaussian filter is (size = 3, sigma = 1), and both the size and sigma double for each level. The Laplacian stack can be calculated by taking the difference between every two consecutive levels of the Gaussian stack, such that laplacian_stack = gaussian_stack[:-1] - gaussian_stack[1:]. The last level of the Laplacian stack is the same as the last level of the Gaussian stack.

The following images are the levels 0, 2, and 4 of the Laplacian stack for both apple.jpeg and orange.jpeg. The full Gaussian stack and Laplacian stack are also presented below, stacked horizontally.

apple.jpeg_0.jpg

apple.jpeg Laplacian Stack Level 0

apple.jpeg_2.jpg

apple.jpeg Laplacian Stack Level 2

apple.jpeg_4.jpg

apple.jpeg Laplacian Stack Level 4

orange.jpeg_0.jpg

orange.jpeg Laplacian Stack Level 0

orange.jpeg_2.jpg

orange.jpeg Laplacian Stack Level 2

orange.jpeg_4.jpg

orange.jpeg Laplacian Stack Level 4

apple.jpeg_gaussian.jpg

apple.jpeg Gaussian Stack

apple.jpeg_laplacian.jpg

apple.jpeg Laplacian Stack

orange.jpeg_gaussian.jpg

orange.jpeg Gaussian Stack

orange.jpeg_laplacian.jpg

orange.jpeg Laplacian Stack

Multiresolution Blending (a.k.a. the oraple!)

Following the 1983 paper by Burt and Adelson, I used the same method of multi-resolution blending that blends two images seamlessly. This method first calculates the Laplacian stacks of the two input images, and the Gaussian stack of the mask image. Then, for each level (frequency band) i, the blended stack is calculated using im_blended[i] = mask_stack[i] * im1_stack[i] + (1 - mask_stack[i]) * im2_stack[i]. The final blended image is produced by summing all levels of the blending stack. For this project, I decided to limit each stack to 6 levels, and use the Gaussian filter with (size = 6, sigma = 2), with both the size and sigma double for each level.

apple.jpeg

apple.jpeg

apple_orange_mask.png

apple_orange_mask.png

orange.jpeg

orange.jpeg

apple.jpeg_orange.jpeg_blended.jpg

oraple.jpg

milkyway.png

milkyway.png

milkyway_blackhole_mask.png

milkyway_blackhole_mask.png

blackhole.png

blackhole.png

milkyway.png_blackhole.png_blended.jpg

lets_hope_that_this_wont_happen_to_us.png

oraple.png

oraple.png

oraple_Efros_mask.png

oraple_Efros_mask.png

Efros.png

Efros.png

./2.4/oraple.png_Efros.png_blended.jpg

Efraple.png

The images below are the Laplacian stacks of my favorite result!

oraple.png_laplacian.jpg

oraple.png Masked Laplacian Stack

Efros.png_laplacian.jpg

Efros.png Masked Laplacian Stack

oraple.png_Efros.png_blended_laplacian.jpg

Efraple.png Masked Laplacian Stack

oraple.png_laplacian_sum.jpg

oraple.png Masked Sum

oraple.png_Efros.png_blended.jpg

Efraple.png

Efros.png_laplacian_sum.jpg

Efros.png Masked Sum