Project 1: Image Filtering and Hybrid Images

Algorithm

For this first project, the goal is to implement an algorithm that mirrors MATLAB's imfilter() function with its default configurations and apply it to the creation of hybrid images. When executed, imfilter() takes an image and a filter and returns their convolution; depending on the filter and additional steps taken, this function can be used to find and isolate the high and low frequencies of an image, among other applications. These frequencies, in turn, can be combined to create a hybrid image, an optical illusion such that the user sees a different image depending on from how far they view the image. The algorithm begins by finding the dimensions of the input image and storing their values as ix, iy, and iz, where ix and iy represent the rows and columns of pixels in the image and iz represents the number of color channels. Next, it finds the half-sizes of the filter's x and y directions (we assume that the filter's x and y dimensions are odd for this project) and use those values to create an appropriate amount of padding around the input image. The output image's array is initialized, and the algorithm proceeds to iterate over the stored dimensions of the input image before it was padded. At each pixel per color channel, a 2D selection of the input image equal in size to the filter and centered on the current pixel is copied. The algorithm then finds the dot product of this copied selection and the filter, which is saved to the corresponding pixel and color channel in the output. The algorithm finishes when the iteration through the stored size values is complete.

% Fetch the dimensions of the input image and half-sizes of the filter
[ix, iy, iz] = size(image);
hs = (size(filter)-1)/2;

% Pad the input image and create the output image array
padded = padarray(image, hs);
output = zeros(ix, iy, iz);

% Scan through the input image one pixel and color channel at a time
for i=1:ix
    for j=1:iy
        for k=1:iz
            % Find the section of the image overlapped by the filter
            A = padded(i:i+2*hs(1), j:j+2*hs(2), k);
            % Save the dot product of the section and the filter to output
            B = A.*filter;
            output(i, j, k) = sum(B(:));
        end
    end
end

One of my original designs for this algorithm involved iterating over each pixel of the filter and multiplying values one at a time, but as I became more familiar with the MATLAB interface and options available to me, I was able to find simpler solutions. From there, I removed iteration over the filter in favor of clever index calculation, allowing me to grab and use only the values of the input image and the filter where they overlap. After learning about the padding function, this approach was also retired in favor of a more simplistic code and algorithm. For a while, I considered using an FFT/IFFT approach to the problem in order to further improve the code, but as the code for such a procedure was covered in the slides for the course, I chose to avoid the FFT approach to avoid being labelled for plaigarism. Had I used an FFT approach, however, I intended to add a scaling size for the FFT matrix that would look for the smallest value of 2^N that would be larger than both the dimensions of the image and the dimensions of the filter, to ensure that the function would be able to accept any image and filter of any size.

Results

Initial results were problematic due to poor coding in earlier solutions, but after working out where the code was flawed and making corrections, the output from the algorithm met expectations. For accuracy testing, I ran it against imfilter(), using a matrix of randomly generated values (rand(sizex, sizey)) as the input image and a pixel-shifting filter ([0, 0, 0; 1, 0, 0; 0, 0, 0]). The results from running both matrices through the two functions resulted in the same outcome, and I used this alongside the provided test program to confirm the accuracy of my function whenever edits were made.

Listed below are the outputs from the proj1_test_filtering.m file using the default cat.bmp image to confirm correct functionality of my_imfilter.m. Afterwards are the outputs from the proj1.m file using the five image pair samples provided.

Results from "proj1_test_filtering.m"

"cat.bmp" w/ identity filter

"cat.bmp" w/ average filter

"cat.bmp" w/ Gaussian filter

"cat.bmp" w/ Sobel filter

"cat.bmp" w Laplacian filter

"cat.bmp" w/ high-pass filter


Results from "proj1.m"

Cat and Dog

"cat.bmp"

"dog.bmp"

high frequencies of "cat.bmp"

low frequencies of "dog.bmp"

hybrid image of "cat.bmp" and "dog.bmp" over several sizes

Submarine and Fish

"submarine.bmp"

"fish.bmp"

high frequencies of "submarine.bmp"

low frequencies of "fish.bmp"

hybrid image of "submarine.bmp" and "fish.bmp" over several sizes

Einstein and Marilyn

"einstein.bmp"

"marilyn.bmp"

high frequencies of "einstein.bmp"

low frequencies of "marilyn.bmp"

hybrid image of "einstein.bmp" and "marilyn.bmp" over several sizes

Bicycle and Motorcycle

"bicycle.bmp"

"motorcycle.bmp"

high frequencies of "bicycle.bmp"

low frequencies of "motorcycle.bmp"

hybrid image of "bicycle.bmp" and "motorcycle.bmp" over several sizes

Bird and Plane

"bird.bmp"

"plane.bmp"

high frequencies of "bird.bmp"

low frequencies of "plane.bmp"

hybrid image of "bird.bmp" and "plane.bmp" over several sizes


Extras and Additional Information

No extras were attempted for this project.