Overview

For this project we worked with images and frequencies in the images, such as by "sharpening" an image by increasing the amount of high frequency data in the image, blending two images together, creating hybrid images. We also learned how to make an edge detector using image gradients.

1.1 Finite Difference Operator

We use a simple derivative filter in order to compute the partial x and y (or horizontal and vertical) derivatives in the image. We can then take these partial derivatives to compute the gradient magnitude of the image. By taking the euclidean distance of the two derivatives for each pixel, we get the magnitude of the gradient at that pixel. This gradient we obtain of the image also functions as a sort of edge detector, and by thresholding the values we can remove excess noise in the image.

The partial derivative in the x direction (or horizontal edges)
The partial derivative in the y direction (or vertical edges)
The gradient and the thresholded gradient. As we can see this results in the edges, but also includes a lot of noise.

1.2 Derivative of Gaussian (DoG) Filter

From the previous part, one thing we can notice is that the resulting gradients aren't very smooth and resulted in a lot of noise. We can deal with this by using a gaussian kernel and convolving it with the image to smooth it (and also remove higher frequency data). Then we can convolve the image with the previous derivative filter to compute the partial derivatives and the gradient of this smoothed image.

The gaussian kernel used to convolve the image.
The partial derivative in the x direction (or horizontal edges)
The partial derivative in the y direction (or vertical edges)
The gradient and the thresholded gradient. Similar to before, we get the edges, but this time they're smoother and there is much less noise.

Since this process involves convolving using 2 different filters, we can simplify the process by convolving the two filters together to get a smoothed-derivative filter which can be applied to any image.

The resulting dx dy kernels obtained by convolving the difference filters with the gaussian kernel.
The partial derivative in the x direction (or horizontal edges)
The partial derivative in the y direction (or vertical edges)
The gradient and the thresholded gradient.

As we can see, there is no difference between doing two convolutions, or doing a single convolution with the merged filter between.

2.1 Image "Sharpening"

For image sharpening, we instead want the high frequency portion of the image, while the gaussian kernel gives us the low frequencies of the image. Luckily, we can obtain the high frequency by simply subtracting the low frequency from the image. Then, in order to sharpen the image, we take a multiple of this high frequency and add it to the original image, thereby amplifying the total amount of high frequency in the image.

The original image
The sharpened image

Additionally, given the properties of the convolution, we can actually turn this process into a single filter. This results in the laplacian of a gaussian as the new kernel, which we can verify results in the same image as the previous process.

The unsharp kernel (or the laplacian of the gaussian). Notice the darker region around the center is negative, the yellow is large positive, and the light purple is near 0.
The original image
The sharpened image using the kernel, which looks the same as the sharpened image from above.
The original image
The sharpened image. Notice the eyes "popping" out a bit more
The high frequencies in the image.
The original image
The sharpened image. Mainly look at the tower and you can notice it standing out a bit more, especially with the lighting
The high frequencies in the image.

2.2 Hybrid Images

Hybrid images are images which look like one thing from up close and a a different image from far away. We do this by overlaying the high frequencies of one image (which are more noticeable from up close) on top of the low frequencies of another (which are more noticeable from far away). Using the unsharp filter and the gaussian kernel, we extract the high and low frequencies from the two different images and add them together.

Example we were given.
Combining an owl and a capybara.
Combining an Thor from Pirate Software and a ferret.
A previously failed version of this hybrid image. I flipped which should be high and low, which resulted in some nightmare fuel.
Combining professors Hilfinger and Efros.

Below we have the Fourier analysis of the owl-capybara hybrid image. As we can see, the gaussian removes a large portion of the high frequency, while the laplacian keeps most of it and removes most of the lower frequency from the data, but these filters are not perfect which results in parts of the high/low staying.

The log magnitude of the capybara on the left and the owl on the right.
The log magnitudes of the respective images after filtering. As we can see, the low-pass filter attenuates the frequencies outside of the center (and the axes) whereas the high-pass filter attenuates the opposte, the center and axes.
The resulting log magnitude of the combined hybrid image.

Bells and Whistles: We apply color to the same owl and capybara image. First, we try using the color for the owl (the high frequency) and then for the capybara (the low frequency). When giving the lower frequency the color, the result is noticeably better. This is probably due to the fact we can barely perceive the higher frequencies from afar, but while up close we can still perceive the lower frequencies, which interferes with the colored high frequency.

Using color for the owl. It is cool how the eyes are properly colored, but the effect isn't that great.
Using color for the capybara. The effect is much more noticeable, and the capybara is properly colored at a distance.

2.3 Gaussian and Laplacian Stacks

The goal of the next two sections is to cleanly blend two images together. The first step of this process is to compute a gaussian stack, where each layer of the stack is computed by convolving the previous layer with a gaussian, thereby getting lower and lower frequencies from the image. We can use this to compute a laplacian stack, which is done by taking the difference between two layers of the gaussian stack, obtaining the frequencies which are removed by the gaussian kernel. We do this with the two images we want to blend, as well as compute the gaussian stack for a mask.

The masked gaussian at various levels for the apple
The masked gaussian at various levels for the orange
The masked laplacian at various levels for the apple
The masked laplacian at various levels for the orange
Blending at different levels (top level, level 1, 3, 5, and the bottom level with the gaussians)

2.4 Multiresolution Blending

Once we have the gaussian and laplacian stacks for the images, as well as the gaussian stack for the mask, we can begin blending the images together. This is done by masking each layer of the laplacian stack (through elementwise multiplication) with the gaussian stack layer for the mask and adding them together. These are additionally added to the lowest level gaussians which is also masked by the lowest level gaussian of the mask. This results in a much cleaner blend between the two images, without an abrupt transition.

The example with the orange and apple.

One thing I thought would be cool would be comparing skins in game. These all use the simple vertical mask.

Comparing the default skin for Genji in Overwatch 1 and 2.
Comparing the two recolored skins for Zenyatta.
This one uses a custom mask, where I tried to "replace" the head of the hammer with Torbjorn. While the blending works properly, the result isn't as comedic as I had hoped.