views:

419

answers:

4

I have two waveforms in the time domain, of which I need to measure the cross-correlation coefficient in MATLAB. I have tried max(abs(xcorr(m,n,'coeff'))) but it doesn't seem to be working properly.

Also I need to measure the cross correlation coefficient for different sections of the waveform, e.g. measure the cross correlation coefficient at 1 minute intervals. And if possible output these values to a matrix or something.

I know this is a lot to ask but I'm a MATLAB novice and find this task daunting!
Any help you could give me on any section of this question would be gratefully received.


EDIT: This is the code I used to test the correlation code:

x = rand(1,14400);
y = rand(1,14400);
r = max( abs(xcorr(x,y,'coeff')) )
A: 

I have tried max(abs(xcorr(m,n,'coeff'))) but it doesn't seem to be working properly.

What do you mean by that? What does it output, and what do you expect?

One possible gotcha in cross correlation is that a DC bias in the waveform will corrupt the result. And as far as I know, there's no universal way to do anything about it. You have to somehow ensure that your waveforms do not contain any DC bias.

Joonas Pulakka
Well I'm hoping for a value between 0 and 1, visually the signals are very similar, with a slight lag. but the code I typed above gives a value of 0.77 which is good, however if I use that code on two random signals that I create in Matlab it gives a higher correlation coefficient of about 0.83, suggesting that they are very similar.
Scott
Please post the code (by editing your question above). It's hard to believe that the correlation coefficient between two random signals was much anything other than approximately zero - unless they 1) are very short, or 2) have a DC bias.
Joonas Pulakka
+1  A: 
According to equations in [this article][1] you can count the cross-correlation coefficient in this way: % Assuming: m and n are your signals organized as row vectors r = cov([m;n]) / (std(m)*std(n)); if you want to compute the coefficient only for some part of the signals, just use: r = cov([m(1:100);n(1:100)]) / (std(m(1:100))*std(n(1:100)));

Have you also tried the corrcoef function?

Edit Ok, I have checked the corrcoef function and it seems to be working properly, take a look:

>> x = 100*randn(1000,1);
>> y=34*randn(1000,1);
>> corrcoef(x,y)

ans =

    1.0000   -0.0543
   -0.0543    1.0000

So the correlation coefficient is equal -0.0543 - small similarity (as expected).
To check that, let's compute the coefficient for identical signals:

>> y=x;
>> corrcoef(x,y)

ans =

     1     1
     1     1

As expected, it's equal 1.

Edit. As you can see, the result of corrcoef is a matrix of all possible correlation coefficients between these two signals:

       x        y
x    1.0000   -0.0543
y   -0.0543    1.0000

So for cross-correlation you need to select one of the elements outside the main diagonal (there are located self-correlation coefficients, in this case always equal 1).
There is no difference if you would select ans(2,1) or ans(1,2) - there is no difference, if you compute the correlation of x and y, or correlation of y and x.

So the final code should look similar to this:

R = corrcoef(x,y); % Correlation matrix
r = R(2,1); % this is your Cross-Correlation coefficient
Gacek
Hi, thanks, but this returns lots of numbers, most of which are above one. I'm looking for a single value which represents the similarity. Any other suggestions that might help?
Scott
you need ans(1,2)
Ofri Raviv
I assumed Scott is smart enough to do it on himself ;) OK -> Edit
Gacek
A: 

This is the code I used to test the correlation code:

x = rand(1,14400);
y = rand(1,14400);
r = max( abs(xcorr(x,y,'coeff')) )

The problem is that rand returns numbers that are are uniformly distributed in the interval (0,1). In other words, you have a DC bias (mean) of 0.5! That's why you get high correlation coefficient for seemingly random signals: they are not quite random, since each has a similar constant component that shows up in the correlation coefficient.

So, try using randn instead: it returns random numbers whose elements are normally distributed with mean 0, which is what you want here.

Joonas Pulakka
Even removing the DC bias with something like: x = rand(1,14400) - 0.5; y = rand(1,14400) - 0.5; r = max( abs(xcorr(x,y,'coeff')) )will fix this "problem." However, the suggestion to use randn is good; approximately normal/Gaussian noise is very common in real signals (thanks largely to the Central Limit Theorem), while uniform noise is not.
+1  A: 

Try using Cross-Covariance instead

x = rand(1,14400);
y = rand(1,14400);
r = max( abs(xcov(x,y,'coeff')) )

cross-covariance sequence is the cross-correlation of mean-removed sequences. Like Joonas mentioned, rand has a DC offset at 0.5 and will give you an "incorrect" results.

sjchoi