Search code examples
matlabsignal-processingconvolutioncross-correlation

Cross Correlation of two sequences with different length using convolution in Matlab


Assume that we have two simple sequences with different lengths:

x = rand(3,1);
y = rand(2,1);

I calculated the cross correlation between them and plot it such below:

r_1 = xcorr(x,(y));

tx = 1:length(x);
ty = 1:length(y);
tr = ceil(-(length(x)+length(y)-1)/2) :  floor((length(x)+length(y)-1)/2);

subplot(2,2,1); stem(tr,r_1); title('XC');

I wanted to calculate the cross correlation using convolution and show that it's result is equal to the result when using xcorr(). But when I implemented it like this:

r_2 = conv(x,fliplr(y));

tx = 1:length(x);
ty = 1:length(y);
tr = ceil(-(length(x)+length(y)-1)/2) :  floor((length(x)+length(y)-1)/2);

subplot(2,2,1); stem(tr,r_2); title('XC');

the length of r_1 and r_2 are different and I got this error:

Error using stem (line 43) X must be same length as Y.

Thanks for your helps.


Solution

  • There are three issues in your code:

    1. You are applying fliplr to y, but y is a column vector, so you are not really flipping it. You should apply flipud; or flip if you want it to work for any vector in general.

    2. From the documentation of xcorr:

      C = xcorr(A,B) [...] > If Aand B are of different length, the shortest one is zero-padded.

      So, to make the result of conv equal to that of xcorr you need to zero-pad the shorter vector.

      In the general case, for column vectors x and y you can use [x; zeros(numel(y)-numel(x),1)] instead of x and [y; zeros(numel(x)-numel(y),1)] instead of y. This will extend the shorter vector and leave the other as is. Note that this works because, according to the documentation of zeros,

      zeros(M,N,P,...) [...] The size inputs M, N, and P... should be nonnegative integers. Negative integers are treated as 0.

    3. The correlation applies a complex conjugate to the second input. You should do the same with convolution. In your example it doesn't matter because inputs are real, but it should be done in general.

    Combining the three items above:

    r_1 = xcorr(x, y);
    r_2 = conv([x; zeros(numel(y)-numel(x),1)], conj(flip([y; zeros(numel(x)-numel(y),1)])));
    

    should give the same result.

    Example:

    x = [3.1; -4.3; 5.6];
    y = [2.6; -8.4];
    

    give

    r_1 =
       0.000000000000004
     -26.040000000000006
      44.180000000000000
     -58.219999999999999
      14.559999999999999
    r_2 =
                       0
     -26.040000000000003
      44.180000000000000
     -58.219999999999999
      14.559999999999999
    

    which are the same up to numerical precision errors.