# [SciPy-User] moving window (2D) correlation coefficient

Wed Feb 10 15:24:53 CST 2010

```I think Josef's nailed it - if you can live with subtracting a moving mean from each pixel [calculated using a correlation/convolution with (1.0/(windowsize*windowsize))*ones((windowsize, windowsize))] rather than taking the mean across the actual window used for the correlation, you'll be home free. Not only do you save yourself the loops, but you're also going to be doing significantly less multiplications than if you calculated the correlation separately for each window.

I suspect that this approach would even be considerably faster than coding your loops and the windowed correlation up in cython.

cheers,
David

----- Original Message ----
From: "josef.pktd@gmail.com" <josef.pktd@gmail.com>
To: SciPy Users List <scipy-user@scipy.org>
Sent: Thu, 11 February, 2010 8:48:23 AM
Subject: Re: [SciPy-User] moving window (2D) correlation coefficient

On Wed, Feb 10, 2010 at 2:36 PM, Vincent Schut <schut@sarvision.nl> wrote:
> On 02/10/2010 05:53 PM, josef.pktd@gmail.com wrote:
>> On Wed, Feb 10, 2010 at 11:42 AM, Zachary Pincus
>> <zachary.pincus@yale.edu>  wrote:
>>> I bet that you could construct an array with shape (x,y,5,5), where
>>> array[i,j,:,:] would give the 5x5 window around (i,j), as some sort of
>>> mind-bending view on an array of shape (x,y), using a positive offset
>>> and some dimensions having negative strides. Then you could compute
>>> the correlation coefficient between the two arrays directly. Maybe?
>>>
>>> Probably cython would be more maintainable...
>>>
>>> Zach
>>>
>>>
>>> On Feb 10, 2010, at 10:45 AM, Vincent Schut wrote:
>>>
>>>> Hi,
>>>>
>>>> I need to calculate the correlation coefficient of a (simultaneously)
>>>> moving window over 2 images, such that the resulting pixel x,y (center
>>>> of the window) is the corrcoef((a 5x5 window around x,y for image
>>>> A), (a
>>>> 5x5 window around x,y for image B)).
>>>> Currently, I just loop over y, x, and then call corrcoef for each x,y
>>>> window. Would there be a better way, other than converting the loop to
>>>> cython?
>>>>
>>>>
>>>> For clarity (or not), the relevant part from my code:
>>>>
>>>>
>>>> for y in range(d500shape[2]):
>>>>      for x in range(d500shape[3]):
>>>>          if valid500[d,y,x]:
>>>>              window = spectral500Bordered[d,:,y:y+5, x:x
>>>> +5].reshape(7, -1)
>>>>              for b in range(5):
>>>>                  nonzeroMask = (window[0]>  0)
>>>>                  b01corr[0,b,y,x] =
>>>>                  b01corr[1,b,y,x] =
>>>>
>>>>
>>>> forget the 'if valid500' and 'nonzeroMask', those are to prevent
>>>> calculating pixels that don't need to be calculated, and to feed only
>>>> valid pixels from the window into corrcoef
>>>> spectral500Bordered is essentially a [d dates, 7 images, ysize, xsize]
>>>> array. I work per date (d), then calculate the corrcoef for images[0]
>>>> versus images[2:], and for images[1] versus images[2:]
>>
>> I wrote a moving correlation for time series last november (scipy user
>> and preceding discussion on numpy mailing list)
>> I don't work with pictures, so I don't know if this can be extended to
>> your case. Since signal.correlate or convolve work in all directions
>> it might be possible
>>
>>     def yxcov(self):
>>         xys = signal.correlate(self.x*self.y, self.kern,
>> mode='same')[self.sslice]
>>         return xys/self.n - self.ymean*self.xmean
>>
>> Josef
>
> I saw that when searching on this topic, but didn't think it would work
> for me as I supposed it was purely 1-dimensional, and I thought that in
> your implementation, though the window moves, the kernel is the same all
> the time? I'm no signal processing pro (alas) so please correct me if
> I'm wrong. I'll try to find the discussion you mentioned tomorrow. Damn
> time zones... ;-)

correlation is just  sum(x*y)/sqrt(sum(x*x))/sqrt(sum(y*y))   but
subtracting moving mean which makes it slightly tricky.

the moving sum can be done with any nd convolve or correlate (ndimage
or signal) which goes in all directions

the window is just np.ones((windowsize,windowsize)) for symmetric
picture, or if nan handling is not necessary than the averaging window
can be used directly.

I'm pretty sure now it works, with 5 or so intermediate arrays in the
same size as the original array

Josef

>>
>>>>
>>>> Thanks,
>>>> Vincent.
>>>>
>>>> _______________________________________________
>>>> SciPy-User mailing list
>>>> SciPy-User@scipy.org
>>>> http://mail.scipy.org/mailman/listinfo/scipy-user
>>>
>>> _______________________________________________
>>> SciPy-User mailing list
>>> SciPy-User@scipy.org
>>> http://mail.scipy.org/mailman/listinfo/scipy-user
>>>
>
>
> _______________________________________________
> SciPy-User mailing list
> SciPy-User@scipy.org
> http://mail.scipy.org/mailman/listinfo/scipy-user
>
_______________________________________________
SciPy-User mailing list
SciPy-User@scipy.org
http://mail.scipy.org/mailman/listinfo/scipy-user

```