scilus / scilpy

The Sherbrooke Connectivity Imaging Lab (SCIL) Python dMRI processing toolbox
Other
54 stars 59 forks source link

Image correlation correct? #940

Open EmmaRenauld opened 3 months ago

EmmaRenauld commented 3 months ago

Hi!

I tried to add the missing unit test in scil.image.tests.test_volume_math.py for the method correlation. I used:

def test_correlation():
    # Note. Not working on 2D data.
    img_data = np.zeros((3, 3, 3)).astype(float)
    affine = np.eye(4)
    img1 = nib.Nifti1Image(img_data, affine)
    img2 = nib.Nifti1Image(img_data + 1, affine)

    # With patch_radius of 1, we get the correlation for each voxel.
    output = correlation([img1, img2], img1, patch_radius=1)
    assert np.all(output == 1)

This fails. The output correlation is:

[[[-0.20883757 -0.04018329 -0.25135627]
  [-0.10100343 -0.13530837 -0.19371986]
  [ 0.1560971  -0.52060044  0.09855439]]

 [[-0.07638622  0.06555331 -0.15572111]
  [-0.24882393  0.16297379 -0.0308053 ]
  [-0.40140784  0.05187551 -0.09271187]]

 [[ 0.06262147  0.05383836  0.08995959]
  [-0.21807295  0.11019234 -0.26336023]
  [-0.0148444  -0.0608431   0.04018494]]]

which makes no sense to me.

Also, please note that currently, patch_radius is NEVER used in scilpy. To delete?

@frheault, you made the other tests in that file. Can you help?

frheault commented 3 months ago

Can you try putting values everywhere in both image.

Background (0) will have random value to avoid NaN error, so right now you have a image with just background and one with data. That will not give a 1 result

EmmaRenauld commented 3 months ago

If a compare a bunch of zeros with a bunch of one and I print the result for one patch, I get:

CORRELATION BETWEEN  [0.0005 0.0007 0.0006 0.0005 0.0004 0.0006 0.0004 0.0009 0.001  0.0004
 0.0008 0.0005 0.0006 0.0009 0.0001 0.0001 0.     0.0008 0.0008 0.0009
 0.001  0.0008 0.0005 0.0008 0.0001 0.0006 0.0001] 
AND
 [0.0009 0.0005 0.0004 0.0003 0.0008 0.0005 0.0006 0.     0.0006 0.0006
 0.0006 0.0009 0.0007 1.0004 1.0004 0.0007 1.0001 1.0007 0.0007 0.0002
 0.0001 0.0003 1.0004 1.0006 0.0004 1.001  1.0001]
   gives  -0.20883757

So actually, the error comes from the zero-padding around the image. It should maybe be done only when the images do not have the same shape.

If instead I do as you asked and compare a bunch of 1 with a bunch of 2, to make sure I don't have a 0-background, I get:

-
   CORRELATION BETWEEN  [0.0005 0.0007 0.0006 0.0005 0.0004 0.0006 0.0004 0.0009 0.001  0.0004
 0.0008 0.0005 0.0006 1.0009 1.0001 0.0001 1.     1.0008 0.0008 0.0009
 0.001  0.0008 1.0005 1.0008 0.0001 1.0006 1.0001]
AND
 [0.0009 0.0005 0.0004 0.0003 0.0008 0.0005 0.0006 0.     0.0006 0.0006
 0.0006 0.0009 0.0007 2.0004 2.0004 0.0007 2.0001 2.0007 0.0007 0.0002
 0.0001 0.0003 2.0004 2.0006 0.0004 2.001  2.0001]
   gives  1.0

So here the zero-padding is not an issue (although I would change the eps added for a smaller value).

But, in the middle of the image, I get:

  CORRELATION BETWEEN  [1.0001 1.0001 1.0002 1.0001 1.0003 1.0001 1.0001 1.0009 1.0002 1.0006
 1.0008 1.0005 1.0002 1.0002 1.0004 1.0005 1.0003 1.0008 1.0008 1.0009
 1.     1.0009 1.0004 1.0009 1.0007 1.001  1.0008] 
 AND
[2.0004 2.0005 2.0004 2.0004 2.0003 2.0005 2.0007 2.0003 2.0005 2.0001
 3.0002 2.     2.001  2.     2.0002 2.0006 2.0001 2.0009 2.0007 2.001
 2.0005 2.0003 2.0005 2.0009 2.0005 2.0003 2.0009]
   gives  0.1629626

And I'm really not sure why there's a 3 suddenly in the middle of my data.

Do you think you have time to help me understand your patches code? We can check it together if you wish. You can see my PR#942, if you do pytest scilpy/image/tests/test_volume_math.py, it fails.