CS 143 / Project 1 / Image Filtering and Hybrid Images

Function Description

My filtering function is fairly straightforward. Given an image and a filter, it performs the following steps:

  1. Check the filter dimensions and throw an error if either dimension is even
  2. Create a zero matrix with enough space for the original image and the necessary padding
  3. Fill the center of the zero matrix with the original image, creating a padded image
  4. Loop through every non-padding pixel of the padded image on every color channel; for each pixel, calculate what its value should be by multiplying the filter with the filter-sized neighborhood surrounding the pixel
  5. Store the result for each pixel in a new zero matrix with the same dimensions as the original image, and return this matrix at the end

Critical Section

The most involved portion of the function (step 4) is below:

% loop through every relevant pixel on every color channel
for i=1+half_filter_width:(size(image,1)+half_filter_width)
    for j=1+half_filter_height:(size(image,2)+half_filter_height)
        for c = 1:3
            center_x = i; center_y = j; pixel_value = 0;
            filter_width_center = half_filter_width + 1;
            filter_height_center = half_filter_height + 1;            
            % loop through each position in the filter, and update the value for the center pixel
            for x_offset = 0:half_filter_width
                for y_offset = 0:half_filter_height
                    % center pixel
                    if x_offset == 0 && y_offset == 0
                        pixel_value = pixel_value + padded_image(center_x,center_y,c)... 
			.* filter(filter_width_center, filter_height_center);                    
                    % top/bottom neighbors
                    elseif x_offset == 0
                        pixel_value = pixel_value + (padded_image(center_x,center_y+y_offset,c)... 
			.* filter(filter_width_center + x_offset, filter_height_center + y_offset))...
                        + (padded_image(center_x,center_y-y_offset,c)...
			.* filter(filter_width_center + x_offset, filter_height_center - y_offset));
                    % left/right neighbors
                    elseif y_offset == 0
                        pixel_value = pixel_value + (padded_image(center_x+x_offset,center_y,c)...
			.* filter(filter_width_center + x_offset, filter_height_center + y_offset))...
                        + (padded_image(center_x-x_offset,center_y,c)... 
			.* filter(filter_width_center + x_offset, filter_height_center - y_offset)); 
                    % corners
                    else
                        pixel_value = pixel_value + (padded_image(center_x+x_offset,center_y+y_offset,c)...
			.* filter(filter_width_center + x_offset, filter_height_center + y_offset))...
                        + (padded_image(center_x+x_offset,center_y-y_offset,c)...
			.* filter(filter_width_center + x_offset, filter_height_center - y_offset))...
                        + (padded_image(center_x-x_offset,center_y+y_offset,c)... 
			.* filter(filter_width_center - x_offset, filter_height_center + y_offset))...
                        + (padded_image(center_x-x_offset,center_y-y_offset,c)...
			.* filter(filter_width_center - x_offset, filter_height_center - y_offset));
                    end
                end
            end
            
            % set the corresponding pixel in the output image to the proper value
            output_image(i-half_filter_width,j-half_filter_height,c) = pixel_value;
        end
    end
end
output = output_image;

Running Time

My function takes a few seconds to run all the test cases in proj1_test_filtering; it is noticeably slower than the built-in imfilter function, though not unbearably so. It takes around 20 seconds to perform the hybrid image generation done in proj1.

Results

Here are some hybrid images produced using my function and some of the test images provided. I also made a Bruce Willis/Nic Cage mashup, but the images weren't aligned particularly well so it doesn't look fantastic.