I chose to use the im2col and col2im functions to transform the blocks within the image into columns. This allowed me to avoid manually looping through the pixel matrices when doing multiplication with the filter, and simplified my code.
My general approach was as follows:
function filtered_image = my_imfilter(image, filter)
image_size = size(image);
filtered_image = zeros(image_size); % allocate new image
filter_reshape = reshape(filter, size(filter, 1) * size(filter, 2), 1); % reshape filter into one column for element-wise multiplication
x_pad = (size(filter, 1) - 1) / 2; % determine proper x and y padding
y_pad = (size(filter, 2) - 1) / 2;
for channel = 1 : size(image, 3)
padded_channel_image = padarray(image(:, :, channel), [x_pad, y_pad]); % pad image with zeros
cols = im2col(padded_channel_image, size(filter)); % convert image blocks the size of the filter to columns
filtered_cols = cols .* repmat(filter_reshape, 1, size(cols, 2)); % multiply each column by the filter elementwise
sum_vector = sum(filtered_cols, 1); % sum each column of the matrix together
filtered_image(:, :, channel) = col2im(sum_vector, ... % convert values back to image blocks
[1 1], image_size(:, 1:2)); % (now mapping each value to a single pixel)
end
end
identity-image | blur-image (gaussian) | large-blur-image (large gaussian) |
![]() |
![]() |
![]() |
sobel-image | laplacian-image | high-pass-image |
![]() |
![]() |
![]() |
Original Image #1 | Original Image #2 | |
![]() |
![]() |
|
High Frequencies | Low Frequencies | Hybrid Image |
![]() |
![]() |
![]() |
Original Image #1 | Original Image #2 | |
![]() |
![]() |
|
High Frequencies | Low Frequencies | Hybrid Image |
![]() |
![]() |
![]() |
Original Image #1 | Original Image #2 | |
![]() |
![]() |
|
High Frequencies | Low Frequencies | Hybrid Image |
![]() |
![]() |
![]() |
Although my algorithm was able to filter images relatively quickly (depending on the filter size, of course), it was not nearly as fast as matlab's built in imfilter.
Choosing which image would provide the low or high frequencies (and turning the cutoff frequency) was probably the hardest part of this project -- it was difficult to get any pair of images to match up as well as the dog/cat combination.