1

I am trying to create a custom filter to run it with the generic filter from SciPy package.

scipy.ndimage.filters.generic_filter

The problem is that I don't know how to get the returned value to be a scalar, as it needs for the generic function to work. I read through these threads (bottom), but I can't find a way for my function to perform.

The code is this:

import scipy.ndimage as sc

def minimum(window):    
    list = []
    for i in range(window.shape[0]):
        window[i] -= min(window)
        list.append(window[i])        
    return list

test =  np.ones((10, 10)) * np.arange(10)

result = sc.generic_filter(test, minimum, size=3)

It gives the error:

cval, origins, extra_arguments, extra_keywords)
TypeError: a float is required

Scipy filter with multi-dimensional (or non-scalar) output

How to apply ndimage.generic_filter()

http://ilovesymposia.com/2014/06/24/a-clever-use-of-scipys-ndimage-generic_filter-for-n-dimensional-image-processing/

Community
  • 1
  • 1
Litwos
  • 1,278
  • 4
  • 19
  • 44

2 Answers2

2

If I understand, you want to substract each pixel the min of its 3-horizontal neighbourhood. It's not a good practice to do that with lists, because numpy is for efficiency( ~100 times faster ). The simplest way to do that is just :

test-sc.generic_filter(test, np.min, size=3)

Then the substraction is vectorized on the whole array. You can also do:

test-np.min([np.roll(test,1),np.roll(test,-1),test],axis=0)

10 times faster, if you accept the artefact at the border.

B. M.
  • 18,243
  • 2
  • 35
  • 54
  • What do you mean by the 'a' value? – Litwos Oct 30 '15 at 19:05
  • Thx for the help. I tested both lines of code. Does the first one substract the values corresponding to the filter position? I got a very different result compared to agold's answer. Testing the second line of code resulted in no difference between the input and output. – Litwos Oct 31 '15 at 20:27
  • I think so. filters seems to be centerered on the current pixel in this case. I forgot a `axis=0` in the second line. – B. M. Nov 01 '15 at 08:57
1

Using the example in Scipy filter with multi-dimensional (or non-scalar) output I converted your code to:

def minimum(window,out):
    list = []
    for i in range(window.shape[0]):
        window[i] -= min(window)
        list.append(window[i])        
    out.append(list)
    return 0

test =  np.ones((10, 10)) * np.arange(10)

result = []
sc.generic_filter(test, minimum, size=3, extra_arguments=(result,))

Now your function minimum outputs its result to the parameter out, and the return value is not used anymore. So the final result matrix contains all the results concatenated, not the output of generic_filter.

Edit 1: Using the generic_filter with a function that returns a scalar, a matrix of the same dimensions is returned. In this case however the lists are appended of each call by the filter which results in a larger matrix (100x9 in this case).

Community
  • 1
  • 1
agold
  • 6,140
  • 9
  • 38
  • 54
  • There seems to be a problem with the output. I tested it on different matrices and returns only 0 values. – Litwos Oct 30 '15 at 09:42
  • Yes but you should use the matrix `result`, not the output of the function. – agold Oct 30 '15 at 09:44
  • I see, but my intention is to keep the input shape of the matrix, in this example being (10L,10L). I transformed the 'result' into an array, and it's shape is (100L, 9L). – Litwos Oct 30 '15 at 09:50