MarcoForte / knn-matting

Python implementation of KNN Matting, CVPR 2012 / TPAMI 2013 http://dingzeyu.li/projects/knn/
MIT License
128 stars 29 forks source link

Singular matrix error #2

Closed MarcoForte closed 7 years ago

MarcoForte commented 7 years ago

Raised in email by students from Computer Science, Shanghai Jiaotong University. We run the demo successfully, but we have some problems with other pictures. When we use our pictures(PNG), we get a warning at this line: alpha = np.minimum(np.maximum(scipy.sparse.linalg.spsolve(H,c),0),1).reshape(m,n)

The warning information: /Users/liuqinghao/anaconda/lib/python3.5/site-packages/scipy/sparse/linalg/dsolve/linsolve.py:155: MatrixRankWarning: Matrix is exactly singular warn("Matrix is exactly singular", MatrixRankWarning)

Then the result printed is just a white picture with the warning information as follows: /Users/liuqinghao/anaconda/lib/python3.5/site-packages/scipy/misc/pilutil.py:98: RuntimeWarning: invalid value encountered in greater bytedata[bytedata > high] = high /Users/liuqinghao/anaconda/lib/python3.5/site-packages/scipy/misc/pilutil.py:99: RuntimeWarning: invalid value encountered in less bytedata[bytedata < 0] = 0 /Users/liuqinghao/anaconda/lib/python3.5/site-packages/numpy/ma/core.py:4144: UserWarning: Warning: converting a masked element to nan. warnings.warn("Warning: converting a masked element to nan.”)

We have tried many pictures. But we have no idea where the mistake takes. But everything is fine when using the data set of the original author`s data set.

MarcoForte commented 7 years ago

The problem was resolved by lowing image resolution from 800x600 to 640x480. The donkey image works at the 800*600 resolution so the root cause of the problem is still unknown.

rubychilds commented 7 years ago

Hello Marco,

Have also been having the same issue on portraits. I've attached a document which contains images plus trimaps - the trimaps have been generated by a NN, so apologies if they aren't great - they do work on images in most cases (I've attempted this on 200+ portraits, with 10% failure due to singularity matrix issue). The one's I've attached are failures which create the singular matrix issue as others have stated above. It also shows when changing resolution, the singular matrix issue is resolved, but matting output is extremely poor.

singular_matrix_issue.zip

I've began looking into cause and effect. From knowledge singularity is created and means the matrix is non-invertible. Seems others are suggesting to use an alternate function in this case linalg.lsqr. More can be read in the solution below...

http://stackoverflow.com/questions/13795682/numpy-error-singular-matrix

Note - all images used are from http://www.cse.cuhk.edu.hk/~leojia/projects/automatting/ so are OS images.

rubychilds commented 7 years ago

Found a solution - will do PR later today:

    warnings.filterwarnings('error')
    alpha = []
    try:
        alpha = np.minimum(np.maximum(scipy.sparse.linalg.spsolve(H, c), 0), 1).reshape(m, n)
    except Warning:
        x = scipy.sparse.linalg.lsqr(H, c)
        alpha = np.minimum(np.maximum(x[0], 0), 1).reshape(m, n)

Note - scipy provides warnings, which are not caught, hence must use warnings lib so that it becomes caught. Uses least squares to create solutions when given singular matrix

MarcoForte commented 7 years ago

Cheers, seems like a good step. Please do and I'll merge it.

kardoszc commented 7 years ago

meet the same problem, and I try use it in python2.7, scipy-0.13.0b1, and it never happen again in my dataset(PNG), maybe you can try it, some code need to update.

in new version, scipy.sparse.diags has default value of offsets, so I make this change just to run it with scipy-0.13.0b1

D_script = scipy.sparse.diags(np.ravel(A.sum(axis=1)), offsets=0)
D = scipy.sparse.diags(np.ravel(all_constraints[:,:]), offsets=0)

i add the offsets param

MarcoForte commented 7 years ago

The default value of offsets is 0, see https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.diags.html. So I don't think your code makes a difference.

kardoszc commented 7 years ago

I knew it , but in python2.7, scipy-0.13.0b1, there is no default value, so I add this. see diags(diagonals, offsets, shape=None, format=None, dtype=None) Construct a sparse matrix from diagonals.

kardoszc commented 7 years ago

I juse want to say, in python2.7, scipy-0.19.0, the problem seems dispeard, maybe the difference in different version of scipy causes this problem?

MarcoForte commented 7 years ago

I suggest you try to update your version of scipy maybe it's accidentally not 0.19. I just checked and the default value is offsets=0 for me in Python 2.7, scipy-0.19

kardoszc commented 7 years ago

sorry, I make a mistake, it's 0.13.0b1, and I am running it to handle about 50+ images, the problem didn't happen again