The goal of this project is to demonstrate the creation of hybrid images as explained in this paper. An example of such an image is given above. The novel effect of these hybrid images is that one image is easier to see when the image is closeup/large and the other becomes clearer when the image is far away/small. Watch as the fish becomes a submarine at smaller dimensions.
The core piece needed to do these hybrid images is to create the lowpass and highpass filters. For this project I
implemented a generic my_imfilter()
function to apply any filter to an input image.
function output = my_imfilter(image, filter)
output = zeros(size(image));
% filter dims must be odd, calculate the distance from the center
[fh, fw] = size(filter);
fh = floor(fh/2);
fw = floor(fw/2);
% pad the input image so the convolution works at the borders
padded = padarray(image,[fh,fw],'symmetric');
% iterate through each pixel and color in the input image
[rows, cols, colors] = size(image);
for r = 1:rows
for c = 1:cols
for rgb = 1:colors
target = padded(r:r+2*fh,c:c+2*fw,rgb);
o = sum(sum(target.*filter));
output(r,c,rgb) = o;
end
end
end
The idea here is that every image filter is a matrix, and gets computed the same way. So the low-pass Gaussian filter that gets used to blur the images is no different than an edge detector or sharpening filter as far as my image filtering function is concerned.
The filter goes row-by-row down the input image, multiplying pixels on each RGB channel point-wise by the filter kernel, then summing them to make a single point in the output image.
In order to keep the input and output the same size, I padded the input image by mirroring itself along the edges so that the filter along the edges of the image does not go out of bounds. I chose this particular solution instead of padding with zeros so that there is no weird black-border around the output image. Most of the input images have a uniform color background and the padding is relatively small (half the kernel size), so it actually works to approximate what a true "un-cropped" version of the picture might look like.
Identity | Box blur | High pass | Sharpen |
Gaussian blur | Motion blur | Laplacian high pass | Sobel |
identity_filter =
0 0 0
0 1 0
0 0 0
blur_filter =
0.1111 0.1111 0.1111
0.1111 0.1111 0.1111
0.1111 0.1111 0.1111
high_pass_image = test_image - blur_image; %simply subtract the low frequency content
sharpen_filter =
-0.1250 -0.1250 -0.1250 -0.1250 -0.1250
-0.1250 0.2500 0.2500 0.2500 -0.1250
-0.1250 0.2500 1.0000 0.2500 -0.1250
-0.1250 0.2500 0.2500 0.2500 -0.1250
-0.1250 -0.1250 -0.1250 -0.1250 -0.1250
gaussian_filter = fspecial('Gaussian', [25 25], 10)
motion_blur_filter = diag(ones(1,21)/21);
laplacian_filter =
0 1 0
1 -4 1
0 1 0
sobel_filter =
-1 0 1
-2 0 2
-1 0 1
The results above show some examples of image filters applied using my function. Note that I added the motion blur and sharpening filters which were not part of the sample code.
Below are example hybrid images used by combining low frequencies with high frequencies in two pairs of images. As the images get smaller, the low frequences should stand out. As the images get larger, the high frequencies should stand out. The particular high/low cutoff was determined experimentally, as there is no really objective way to decide what cutoff looks the best, and it varies for each pair of images.
Images that are already relatively similar work the best. Here I also demonstrate a landscape ocean/mountain hybrid that is not one of the provided sample images.
Low Frequencies | High Frequencies | ||
---|---|---|---|
Hybrid Result |
Low Frequencies | High Frequencies | ||
---|---|---|---|
Hybrid Result |
Low Frequencies | High Frequencies | ||
---|---|---|---|
Hybrid Result |
Low Frequencies | High Frequencies | ||
---|---|---|---|
Hybrid Result |
Low Frequencies | High Frequencies | ||
---|---|---|---|
Hybrid Result |
Low Frequencies | High Frequencies | ||
---|---|---|---|
Hybrid Result |