Repository: scikit-image/scikit-image

Issue:
Inpaint biharmonic with 3d image now fails
Hello,

As referred to in : https://forum.image.sc/t/inpaint-biharmonic-with-3d-image-now-fails/63615/4


I am attempting to use inpaint biharmonic on a 3d greyscale image. In the past, the command worked with the argument multichannel=False. Now, with v 0.19.2, either when specifying multichannel=False or not specifying it, the inpaint function fails. When running on a computer cluster (also fails locally--see below) I get the error:
```
(rt) [robbwh@badger scripts209]$ python 0_209_glob_R2LagsNan.py 18
18
235269
0
235269
/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/scipy/sparse/linalg/_dsolve/linsolve.py:206: MatrixRankWarning: Matrix is exactly singular
  warn("Matrix is exactly singular", MatrixRankWarning)
*** Error in `python': corrupted size vs. prev_size: 0x0000563121921400 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7f474)[0x7ff267622474]
/lib64/libc.so.6(+0x8156b)[0x7ff26762456b]
/home/robbwh/.local/lib/python3.8/site-packages/numpy/core/_multiarray_umath.cpython-38-x86_64-linux-gnu.so(+0x6d781)[0x7ff2604d9781]
/home/robbwh/.local/lib/python3.8/site-packages/numpy/core/_multiarray_umath.cpython-38-x86_64-linux-gnu.so(+0x70cca)[0x7ff2604dccca]
/home/robbwh/.local/lib/python3.8/site-packages/numpy/core/_multiarray_umath.cpython-38-x86_64-linux-gnu.so(+0x70efd)[0x7ff2604dcefd]
python(+0xfb178)[0x56311db4d178]
python(_PyFunction_Vectorcall+0x1dc)[0x56311dc01f3c]
python(_PyEval_EvalFrameDefault+0x93f)[0x56311dc1f8cf]
python(_PyEval_EvalCodeWithName+0x2c3)[0x56311dc00cf3]
python(_PyFunction_Vectorcall+0x378)[0x56311dc020d8]
python(PyObject_Call+0x5e)[0x56311db76dae]
python(_PyEval_EvalFrameDefault+0x2118)[0x56311dc210a8]
python(_PyEval_EvalCodeWithName+0x2c3)[0x56311dc00cf3]
python(_PyFunction_Vectorcall+0x378)[0x56311dc020d8]
python(PyObject_Call+0x5e)[0x56311db76dae]
python(_PyEval_EvalFrameDefault+0x2118)[0x56311dc210a8]
python(_PyEval_EvalCodeWithName+0x2c3)[0x56311dc00cf3]
python(_PyFunction_Vectorcall+0x378)[0x56311dc020d8]
python(_PyEval_EvalFrameDefault+0x4d93)[0x56311dc23d23]
python(_PyEval_EvalCodeWithName+0x2c3)[0x56311dc00cf3]
python(PyEval_EvalCodeEx+0x39)[0x56311dc01d59]
python(PyEval_EvalCode+0x1b)[0x56311dca6b5b]
python(+0x254bf3)[0x56311dca6bf3]
python(+0x26e5b3)[0x56311dcc05b3]
python(+0x2735d2)[0x56311dcc55d2]
python(PyRun_SimpleFileExFlags+0x1b2)[0x56311dcc57b2]
python(Py_RunMain+0x36d)[0x56311dcc5d2d]
python(Py_BytesMain+0x39)[0x56311dcc5ee9]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7ff2675c5555]
python(+0x1e7989)[0x56311dc39989]
======= Memory map: ========
56311da52000-56311dab1000 r--p 00000000 00:29 258710027                  /gpfs52/home/robbwh/miniconda3/envs/rt/bin/python3.8
56311dab1000-56311dcc6000 r-xp 0005f000 00:29 258710027                  /gpfs52/home/robbwh/miniconda3/envs/rt/bin/python3.8
56311dcc6000-56311ddb9000 r--p 00274000 00:29 258710027                  /gpfs52/home/robbwh/miniconda3/envs/rt/bin/python3.8
56311ddba000-56311ddbf000 r--p 00367000 00:29 258710027                  /gpfs52/home/robbwh/miniconda3/envs/rt/bin/python3.8
56311ddbf000-56311ddf7000 rw-p 0036c000 00:29 258710027                  /gpfs52/home/robbwh/miniconda3/envs/rt/bin/python3.8
56311ddf7000-56311de17000 rw-p 00000000 00:00 0 
56311e577000-563121fcd000 rw-p 00000000 00:00 0                          [heap]
7ff149206000-7ff14986d000 rw-p 00000000 00:00 0 
7ff14a525000-7ff14bf19000 rw-p 00000000 00:00 0 
7ff14bf19000-7ff14df19000 rw-p 00000000 00:00 0 
7ff14df19000-7ff14df1a000 ---p 00000000 00:00 0 
7ff14df1a000-7ff14e71a000 rw-p 00000000 00:00 0 
7ff14e71a000-7ff14e71b000 ---p 00000000 00:00 0 
7ff14e71b000-7ff14ef1b000 rw-p 00000000 00:00 0 
7ff14ef1b000-7ff14ef1c000 ---p 00000000 00:00 0 
7ff14ef1c000-7ff14f71c000 rw-p 00000000 00:00 0 
7ff14f71c000-7ff14f71d000 ---p 00000000 00:00 0 
7ff14f71d000-7ff14ff1d000 rw-p 00000000 00:00 0 
7ff14ff1d000-7ff14ff1e000 ---p 00000000 00:00 0 
7ff14ff1e000-7ff15071e000 rw-p 00000000 00:00 0 
7ff15071e000-7ff15071f000 ---p 00000000 00:00 0 
7ff15071f000-7ff150f1f000 rw-p 00000000 00:00 0 
7ff150f1f000-7ff150f20000 ---p 00000000 00:00 0 
7ff150f20000-7ff151720000 rw-p 00000000 00:00 0 
7ff151720000-7ff151721000 ---p 00000000 00:00 0 
7ff151721000-7ff151f21000 rw-p 00000000 00:00 0 
7ff151f21000-7ff151f22000 ---p 00000000 00:00 0 
7ff151f22000-7ff152722000 rw-p 00000000 00:00 0 
7ff152722000-7ff152723000 ---p 00000000 00:00 0 
7ff152723000-7ff152f23000 rw-p 00000000 00:00 0 
7ff152f23000-7ff152f24000 ---p 00000000 00:00 0 
7ff152f24000-7ff153724000 rw-p 00000000 00:00 0 
7ff153724000-7ff153725000 ---p 00000000 00:00 0 
7ff153725000-7ff153f25000 rw-p 00000000 00:00 0 
7ff153f25000-7ff153f26000 ---p 00000000 00:00 0 
7ff153f26000-7ff154726000 rw-p 00000000 00:00 0 
7ff154726000-7ff154727000 ---p 00000000 00:00 0 
7ff154727000-7ff154f27000 rw-p 00000000 00:00 0 
7ff154f27000-7ff154f28000 ---p 00000000 00:00 0 
7ff154f28000-7ff155728000 rw-p 00000000 00:00 0 
7ff155728000-7ff155729000 ---p 00000000 00:00 0 
7ff155729000-7ff155f29000 rw-p 00000000 00:00 0 
7ff155f29000-7ff155f2a000 ---p 00000000 00:00 0 
7ff155f2a000-7ff15672a000 rw-p 00000000 00:00 0 
7ff15672a000-7ff15672b000 ---p 00000000 00:00 0 
7ff15672b000-7ff156f2b000 rw-p 00000000 00:00 0 
7ff156f2b000-7ff156f2c000 ---p 00000000 00:00 0 
7ff156f2c000-7ff15772c000 rw-p 00000000 00:00 0 
7ff15772c000-7ff15772d000 ---p 00000000 00:00 0 
7ff15772d000-7ff157f2d000 rw-p 00000000 00:00 0 
7ff157f2d000-7ff157f2e000 ---p 00000000 00:00 0 
7ff157f2e000-7ff15872e000 rw-p 00000000 00:00 0 
7ff15872e000-7ff15872f000 ---p 00000000 00:00 0 
7ff15872f000-7ff158f2f000 rw-p 00000000 00:00 0 
7ff158f2f000-7ff158f30000 ---p 00000000 00:00 0 
7ff158f30000-7ff15a12c000 rw-p 00000000 00:00 0 
7ff15a12c000-7ff15a137000 r--p 00000000 00:29 272812758                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/zstandard/backend_c.cpython-38-x86_64-linux-gnu.so
7ff15a137000-7ff15a1d0000 r-xp 0000b000 00:29 272812758                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/zstandard/backend_c.cpython-38-x86_64-linux-gnu.so
7ff15a1d0000-7ff15a1e3000 r--p 000a4000 00:29 272812758                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/zstandard/backend_c.cpython-38-x86_64-linux-gnu.so
7ff15a1e3000-7ff15a1e4000 r--p 000b6000 00:29 272812758                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/zstandard/backend_c.cpython-38-x86_64-linux-gnu.so
7ff15a1e4000-7ff15a1e8000 rw-p 000b7000 00:29 272812758                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/zstandard/backend_c.cpython-38-x86_64-linux-gnu.so
7ff15a1e8000-7ff15a1ef000 r--p 00000000 00:29 268747836                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_rolling_ball_cy.cpython-38-x86_64-linux-gnu.so
7ff15a1ef000-7ff15a21b000 r-xp 00007000 00:29 268747836                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_rolling_ball_cy.cpython-38-x86_64-linux-gnu.so
7ff15a21b000-7ff15a223000 r--p 00033000 00:29 268747836                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_rolling_ball_cy.cpython-38-x86_64-linux-gnu.so
7ff15a223000-7ff15a224000 ---p 0003b000 00:29 268747836                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_rolling_ball_cy.cpython-38-x86_64-linux-gnu.so
7ff15a224000-7ff15a225000 r--p 0003b000 00:29 268747836                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_rolling_ball_cy.cpython-38-x86_64-linux-gnu.so
7ff15a225000-7ff15a229000 rw-p 0003c000 00:29 268747836                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_rolling_ball_cy.cpython-38-x86_64-linux-gnu.so
7ff15a229000-7ff15a26a000 rw-p 00000000 00:00 0 
7ff15a26a000-7ff15a271000 r--p 00000000 00:29 268747835                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_inpaint.cpython-38-x86_64-linux-gnu.so
7ff15a271000-7ff15a294000 r-xp 00007000 00:29 268747835                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_inpaint.cpython-38-x86_64-linux-gnu.so
7ff15a294000-7ff15a29b000 r--p 0002a000 00:29 268747835                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_inpaint.cpython-38-x86_64-linux-gnu.so
7ff15a29b000-7ff15a29c000 ---p 00031000 00:29 268747835                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_inpaint.cpython-38-x86_64-linux-gnu.so
7ff15a29c000-7ff15a29d000 r--p 00031000 00:29 268747835                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_inpaint.cpython-38-x86_64-linux-gnu.so
7ff15a29d000-7ff15a2a0000 rw-p 00032000 00:29 268747835                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/restoration/_inpaint.cpython-38-x86_64-linux-gnu.so
7ff15a2a0000-7ff15a2a1000 rw-p 00000000 00:00 0 
7ff15a2a1000-7ff15a2a5000 r--p 00000000 00:29 268747825                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_ccomp.cpython-38-x86_64-linux-gnu.so
7ff15a2a5000-7ff15a2b6000 r-xp 00004000 00:29 268747825                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_ccomp.cpython-38-x86_64-linux-gnu.so
7ff15a2b6000-7ff15a2b9000 r--p 00015000 00:29 268747825                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_ccomp.cpython-38-x86_64-linux-gnu.so
7ff15a2b9000-7ff15a2ba000 ---p 00018000 00:29 268747825                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_ccomp.cpython-38-x86_64-linux-gnu.so
7ff15a2ba000-7ff15a2bb000 r--p 00018000 00:29 268747825                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_ccomp.cpython-38-x86_64-linux-gnu.so
7ff15a2bb000-7ff15a2bd000 rw-p 00019000 00:29 268747825                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_ccomp.cpython-38-x86_64-linux-gnu.so
7ff15a2bd000-7ff15a2c3000 r--p 00000000 00:29 268747833                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_pnpoly.cpython-38-x86_64-linux-gnu.so
7ff15a2c3000-7ff15a2e3000 r-xp 00006000 00:29 268747833                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_pnpoly.cpython-38-x86_64-linux-gnu.so
7ff15a2e3000-7ff15a2ea000 r--p 00026000 00:29 268747833                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_pnpoly.cpython-38-x86_64-linux-gnu.so
7ff15a2ea000-7ff15a2eb000 r--p 0002c000 00:29 268747833                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_pnpoly.cpython-38-x86_64-linux-gnu.so
7ff15a2eb000-7ff15a2ee000 rw-p 0002d000 00:29 268747833                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_pnpoly.cpython-38-x86_64-linux-gnu.so
7ff15a2ee000-7ff15a2ef000 rw-p 00000000 00:00 0 
7ff15a2ef000-7ff15a2f6000 r--p 00000000 00:29 268747834                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_moments_cy.cpython-38-x86_64-linux-gnu.so
7ff15a2f6000-7ff15a317000 r-xp 00007000 00:29 268747834                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_moments_cy.cpython-38-x86_64-linux-gnu.so
7ff15a317000-7ff15a31e000 r--p 00028000 00:29 268747834                  /gpfs52/home/robbwh/miniconda3/envs/rt/lib/python3.8/site-packages/skimage/measure/_moments_cy.cpython-38-x86_64-linux-gnu.soAborted (core dumped)
```


When I download the numpy arrays and run locally using 

```
import numpy as np
import matplotlib.pyplot as plt
from skimage.restoration import inpaint_biharmonic


mask = np.load("/Users/hudson/Jefferson/BOLD_CVR/outputs/rt_feb16_22/temp/mask.npy")

mask.dtype

mask = mask.astype(np.int16)
mask.dtype


#to see if there are 1s in mask
print(mask[27,66,19])
#true


#load the image
img = np.load("/Users/hudson/Jefferson/BOLD_CVR/outputs/rt_feb16_22/temp/toinpaint.npy")


inpainted = inpaint_biharmonic(img,mask,multichannel=False)

```

I get /Applications/Spyder.app/Contents/Resources/lib/python3.9/spyder/plugins/ipythonconsole/scripts/conda-activate.sh: line 14: 12035 Segmentation fault: 11  $CONDA_ENV_PYTHON -m spyder_kernels.console -f $SPYDER_KERNEL_SPEC

and my python crashes. 



Here are the files:

toinpaint: https://vanderbilt.box.com/s/8ljb8dzsib51z3cfr9zv00l64rs47sgg
mask : https://vanderbilt.box.com/s/3vjvse1rkmo3oovzpnyubftqn2o9tkp0


EDIT:
By the way, this works if I'm using 0.18.3 but not with the latest version of scikit-image




Discussion:
This issue has been mentioned on **Image.sc Forum**. There might be relevant details there:

https://forum.image.sc/t/inpaint-biharmonic-with-3d-image-now-fails/63615/5

Hello @robbwh,

Thanks for reporting. As @grlee77 asked on the forum:

> Is it possible to provide a dataset that we could use to reproduce the issue? If the data itself cannot be shared, then perhaps just the mask you are using would help. Once we can reliably reproduce the issue on our end, we should be able to debug it.
Hi @mkcor , in my post I attached two .npy files corresponding to the mask and image (both 3d arrays). Please let me know if those don't work for you. Thanks

edit: Linked, not attached. 


>Here are the files:
>
>toinpaint: https://vanderbilt.box.com/s/8ljb8dzsib51z3cfr9zv00l64rs47sgg
>mask : https://vanderbilt.box.com/s/3vjvse1rkmo3oovzpnyubftqn2o9tkp0

I also wrote the code I was using with those files
Thanks @robbwh, I can reproduce the issue with the files you provided. 
Okay, I found the issue and a temporary workaround until the next patch release. The specific problem is related to the strides of the array in memory. Some code in the functions assume `img.flags.c_contiguous` is True. However, your arrays are Fortran-contiguous.

We need to add a check inside the function that will make a copy when the input doesn't meet these assumptions.

For now you just need to do:
```Python
img = np.ascontiguousarray(img)
mask = np.ascontiguousarray(mask)
```
before calling
```Python
inpainted = inpaint_biharmonic(img,mask,multichannel=False)
```

With that change I got a result that seems to be the same as on v0.18.x.
This nice part for v0.19.2 is that this takes only 66 ms to compute (vs. 1.27 seconds on v0.18.3), so it is good to see that the refactoring of the code was also beneficial in this case! 


This issue has been mentioned on **Image.sc Forum**. There might be relevant details there:

https://forum.image.sc/t/inpaint-biharmonic-with-3d-image-now-fails/63615/6


Resolving patch:
diff --git a/skimage/restoration/inpaint.py b/skimage/restoration/inpaint.py
--- a/skimage/restoration/inpaint.py
+++ b/skimage/restoration/inpaint.py
@@ -265,7 +265,7 @@ def inpaint_biharmonic(image, mask, multichannel=False, *,
     mask = mask.astype(bool, copy=False)
     if not multichannel:
         image = image[..., np.newaxis]
-    out = np.copy(image)
+    out = np.copy(image, order='C')
 
     # Create biharmonic coefficients ndarray
     radius = 2


Test patch:
diff --git a/skimage/restoration/tests/test_inpaint.py b/skimage/restoration/tests/test_inpaint.py
--- a/skimage/restoration/tests/test_inpaint.py
+++ b/skimage/restoration/tests/test_inpaint.py
@@ -144,9 +144,10 @@ def test_invalid_input():
 
 
 @testing.parametrize('dtype', [np.uint8, np.float32, np.float64])
+@testing.parametrize('order', ['C', 'F'])
 @testing.parametrize('channel_axis', [None, -1])
 @testing.parametrize('split_into_regions', [False, True])
-def test_inpaint_nrmse(dtype, channel_axis, split_into_regions):
+def test_inpaint_nrmse(dtype, order, channel_axis, split_into_regions):
     image_orig = data.astronaut()[:, :200]
     float_dtype = np.float32 if dtype == np.float32 else np.float64
     image_orig = image_orig.astype(float_dtype, copy=False)
@@ -187,6 +188,7 @@ def test_inpaint_nrmse(dtype, channel_axis, split_into_regions):
     image_orig = image_orig.astype(dtype, copy=False)
     image_defect = image_defect.astype(dtype, copy=False)
 
+    image_defect = np.asarray(image_defect, order=order)
     image_result = inpaint.inpaint_biharmonic(
         image_defect, mask, channel_axis=channel_axis,
         split_into_regions=split_into_regions