What does padding do in 2d convolution of images? - matlab

Having two images , A and B of sizes n-by-m , k-by-l.
When doing convolution via Fourier transform , it is said that we have to pad with zeros the signals. What does this exactly mean?
When I get ifft2(A, B, n+k-1, m+l-1) its like padded is done? Thanks in advance

To zero-pad, you must increase the size of A and B until they are both n+k-1, m+l-1 (or greater) in size by adding rows and columns of zeros to these array/matrix variables. If you don't zero-pad, the convolution effect will wrap around (top-to-bottom and left-to-right) thus messing up your result (unless you actually want this circular convolution wrap-around effect).

Related

effect of padding on cross correlation

To find displacement of a particle, I calculated the cross correlation between two instants (represented by two images with the same size). Then, I padded the images with zeros to see if a translation will have an effect on the displacement.
Thus I found a difference in displacement vector( the difference can reach 1.5 pixel and the size of image is 56x56 pixels)
Is it normal to find a difference after padding?
N.B: To pad the image, I used
new_image(end+1:56,end+1:56)=0;
EDIT
The difference can even be more for some cases (22 px)
Yes, this is weird. The cross-correlation is calculated by multiplying values in both matrices with eachother and taking the sum of these. Adding zeros should not result in a greater sum.
The problem in the code you've posted is that end+1:56 should likely be end+1:end+56, since you pad it with 56 extra zeros below and to the right of the image this way.
Since your goal appears to be to get the cross-correlation of 2 matrices, I recommend you to look at the xcorr2() and xcorr() functions in Matlab. An explanation for xcorr2() and why zero padding should not have any influence (besides searching a larger image) can be found here.

How to compute the mean value of all sub-imges in image I

I have a task that is compute the mean value of a sub-image that extract from input image I. Let explain my task. I have a image I (i.e, 9x9), and a window (i.e size 3x3). The window will be run from top-left to bottom-right of image. Hence, it will extract the input image into many subimage. I want to compute the mean value of these sub-images. Could you suggest to me some matlab code to compute it.
This is my solution. But it does not work.
First, I defined a window as Gaussian
Second, the Gaussian function will run from top-left to bottom-right using convolution function. (Note that, it must be use Gaussian Kernel)
Compute the mean value of each sub-window
%% Given Image I,Defined a Gaussian Kernel
sigma=3;
K=fspecial('gaussian',round(2*sigma)*2+1,sigma);
KI=conv2(I,K,'same');
%% mean value
mean(KI)
The problem in here is that mean value off all sub-image will have size similar image I. Because each pixel in image will made a sub-image. But my code returns only a value. What is problem?
If it is your desire to compute the average value in each sub-image once you filter your image with a Gaussian kernel, simply convolve your image with a mean or average filter. This will collect sub-images within your original image and for each output location, you will compute the average value.
Going with your initial assumption that the mask size is 3 x 3, simply use conv2 in conjunction with a 3 x 3 mask that has all 1/9 coefficients. In other words:
%// Your code
%% Given Image I,Defined a Gaussian Kernel
sigma=3;
K=fspecial('gaussian',round(2*sigma)*2+1,sigma);
KI=conv2(I,K,'same');
%// New code
mask = (1/9)*ones(3,3);
out = conv2(KI, mask, 'same');
Each location in out will give you what the average value was for each 3 x 3 sub-image in your Gaussian filtered result.
You can also create the averaging mask by using fspecial with the flag average and specifying the size / width of your mask. Given that you are already using it in your code, you already know of its existence. As such, you can also do:
mask = fspecial('average', 3);
The above code assumes the width and height of the mask are the same, and so it'll create a 3 x 3 mask of all 1/9 coefficients.
Aside
conv2 is designed for general 2D signals. If you are looking to filter an image, I recommend you use imfilter instead. You should have access to it, since fspecial is part of the Image Processing Toolbox, and so is imfilter. imfilter is known to be much more efficient than conv2, and also makes use of Intel Integrated Performance Primitives (Intel IPP) if available (basically if you are running MATLAB on a computer that has an Intel processor that supports IPP). Therefore, you should really perform your filtering this way:
%// Your code
%% Given Image I,Defined a Gaussian Kernel
sigma=3;
K=fspecial('gaussian',round(2*sigma)*2+1,sigma);
KI=imfilter(I,K,'replicate'); %// CHANGE
%// New code
mask = fspecial('average', 3);
out = imfilter(KI, mask, 'replicate'); %// CHANGE
The replicate flag is for handling the boundary conditions. When your mask goes out of bounds of the original image, replicate simply replicates the border of each side of your image so that the mask can fit comfortably within the image when performing your filtering.
Edit
Given your comment, you want to extract the subimages that are seen in KI. You can use the very powerful im2col function that's part of the Image Processing Toolbox. You call it like so:
B = im2col(A,[m n]);
A will be your input image, and B will be a matrix that is of size mn x L where L would be the total number of possible sub-images that exist in your image and m, n are the height and width of each sub-image respectively. How im2col works is that for each sub-image that exists in your image, it warps them so that it fits into a single column in B. Therefore, each column in B produces a single sub-image that is warped into a column. You can then use each column in B for your GMM modelling.
However, im2col only returns valid sub-images that don't go out of bounds. If you want to handle the edge and corner cases, you'll need to pad the image first. Use padarray to facilitate this padding. Therefore, to do what you're asking, we simply do:
Apad = padarray(KI, [1 1], 'replicate');
B = im2col(Apad, [3 3]);
The first line of code will pad the image so that you have a 1 pixel border that surrounds the image. This will allow you to extract 3 x 3 sub-images at the border locations. I use the replicate flag so that you can simply duplicate the border pixels. Next, we use im2col so that you get 3 x 3 sub-images that are then stored in B. As such, B will become a 9 x L matrix where each column gives you a 3 x 3 sub-image.
Be mindful that im2col warps these columns in column-major format. That means that for each sub-image that you have, it takes each column in the sub-image and stacks them on top of each other giving you a 9 x 1 column. You will have L total sub-images, and these are concatenated horizontally to produce a 9 x L matrix. Also, keep in mind that the sub-images are read top-to-bottom, then left-to-right as this is the nature of MATLAB operating in column-major order.

How can I calculate the sum of the two matrices have not the same size?

I have 2 matrices ;
size A is 256x256 and B is 32x32 ;
How can I calculate the sum of the two matrices have not the same size ?
please help me .
It depends on how you define the sum. The usual definition of matrix addition, in which corresponding entries are added together, is only defined for matrices of the same size. The Wikipedia article on matrix addition mentions two additional types of addition:
The direct sum merely embeds the two operands on the diagonal of a new matrix, in your case creating a 288 x 288 matrix.
The Kronecker sum is essentially a block matrix consisting of multiples of B formed from individual elements of A using scalar multiplication.
I've come up with two options, if you have a 32x32 matrix image1, and a 256x256 matrix image2, you could do either imresize(image1,size(image2))+image2 or kron(image1,ones(8)) (because 256/32=8).
The imresize method does interpolation and has no requirements on the size of the matrices, but the kron method requires that the size of the matrices are integer multiples of each other, so 32 and 256 is fine, but 32 and 300 wouln't be.
Here is my first (32x32) image
and here is my 256x256 image
then here is imresize(image1,size(image2))
and here is imresize(image1,size(image2))+image2
here is kron(image1,ones(8))
and here is kron(image1,ones(8))+image2

MATLAB: partial convolution

I have two equally-sized data-arrays (mainly zeros, and sparsely filled with ones), and make the conv of it. As a result I get this.
Now one can see a peak around -10^{-5}. My question is, how can I do the convolution such that I only get a small region around that peak?
I know that the convolution is defined from minus infinity to infinity. Mathematically I would want to change those limits to (in my example) [-1.5*10^5,-0.5*10^-5].
Thanks alot for your help!
edit
I found the solution: One can use xcorr(a,fliplr(b)) instead of conv(a,b). Now xcorr has the option "maxlags", which is exactly the thing I was searching for.
You can reduce the number of output values of conv, but not arbitrarily. Try 'same' or 'valid' options:
C = CONV(A, B, SHAPE) returns a subsection of the convolution with size specified by SHAPE:
'full' - (default) returns the full convolution,
'same' - returns the central part of the convolution
that is the same size as A.
'valid' - returns only those parts of the convolution
that are computed without the zero-padded edges.
LENGTH(C)is MAX(LENGTH(A)-MAX(0,LENGTH(B)-1),0).
To specify arbitrary output limits, you probably need to do the convolution manually with a user-defined function. But it may be more efficient to use conv and then trim the output.

computing PCA matrix for set of sift descriptors

I want to compute a general PCA matrix for a dataset, and I will use it to reduce dimensions of sift descriptors. I have already found some algorithms to compute it, but I couldn't find a way to compute it by using MATLAB.
Can someone help me?
[coeff, score] = princomp(X)
is the right thing to do, but knowing how to use it is a little tricky.
My understanding is that you did something like:
sift_image = sift_fun(img)
which gives you a binary image: sift_feature?
(Even if not binary, this still works.)
Inputs, formulating X:
To use princomp/pca formulate X so that each column is a numel(sift_image) x 1 vector (i.e. sift_image(:))
Do this for all your images and line them up as columns in X. So X will be numel(sift_image) x num_images.
If your images aren't the same size (e.g. pixel dimensions different, more or less of a scene in the images), then you'll need to bring them into some common space, which is a whole different problem.
Unless your stuff is binary, you'll probably want to de-mean/normalize X, both in the column direction (i.e. normalizing each individual image) and row direction (de-meaning the whole dataset).
Outputs
score is the set of eigen vectors: it will be num_pixels * num_images.
To get, say the first eigen vector back into an image shape, do:
first_component = reshape(score(:,1),size(im));
And so on for the rest of the components. There are as many components as input images.
Each row of coeff is the num_images (equal to num_components) set of weights that can be applied to generate each input image. i.e.
input_image_1 = reshape(score * coeff(:,1) , size(original_im));
where input_image_1 is the correct, original shape
coeff(1,:) is a vector (num_images x 1)
score is pixels x num_images
(Disclaimer: I may have the columns/rows mixed up, but the descriptions are correct.)
Does that help?
If you have access to Statistics Toolbox, you can use the command princomp, or in recent versions the command pca.