Question

I have created a script in Python which takes an image as input and produces a new image where each pixel corresponds to a feature calculated from the windowed group of pixels in the input image. The following picture will highlight this idea:

enter image description here

In the border cases we can either insert NaN into the output image or just use the pixels we have available inside the window. What would be an optimized way to do achieve this functionality in Python or some other programming language? At the moment, my script is simply using a bunch of for-loops to get the job done. Here you can see the code:

# This function will return the statistical features
# 
#
# INPUTS: 
# 'data' the data from which statistical features are to be calculated
# "winSize" specifying the window size, must be odd and > 1
#
# OUTPUT: 
# 'meanData, stdData' statistical feature matrices (numpy ndarrays)

def get_stat_feats(data, winSize):

    rows = data.shape[0]
    cols = data.shape[1]
    dist = int(math.floor(float(winSize)/2.0))
    neigh = range(-dist, dist+1)
    temp = np.zeros((int(winSize)**2, 1))
    meanData = np.zeros(data.shape)
    stdData = np.zeros(data.shape)
    for row in range(0, rows):
        for col in range(0, cols):
            index = 0
            makeNaN = 0
            for y in neigh:
                for x in neigh: 
                    indY = row + y
                    indX = col + x
                    # Check that we are inside the image
                    if indY >= 0 and indY <= rows-1 and indX >= 0 and indX <= cols-1:
                        temp[index] = data[indY, indX]
                        index += 1
                    else: 
                        makeNaN = 1
            if makeNaN == 1:
                meanData[row, col] = np.NAN
                stdData[row, col] = np.NAN

            else:
                meanData[row, col] = np.mean(temp)
                stdData[row, col] = np.std(temp)       
    return meanData, stdData

Thnx for any help! =) If there any more information needed, please ask =)

Was it helpful?

Solution

generic_filter from scipy.ndimage should be a decent solution for this. Probably faster solution, but this is the simplest i think.

It can take a mode parameter to define how to handle the edges. For example you could set it to treat elements outside the border to constant and equal NaN like this:

generic_filter(a, f, size=winSize, mode='constant', cval=np.nan)

def get_stat_feats(data, winSize):
    from scipy.ndimage import generic_filter
    import numpy as np
    mean = lambda x: x.mean()
    std = lambda x: x.std()

    meanData = generic_filter(data, mean, size=winSize)
    stdData = generic_filter(data, std, size=winSize)

    return meanData, stdData

force float and round return value:

import numpy as np

def get_stat_feats(data, winSize):
    from scipy.ndimage import generic_filter
    import numpy as np
    data = data.astype(float)
    mean = lambda x: x.mean()
    std = lambda x: x.std()

    meanData = generic_filter(data, mean, size=winSize)
    stdData = generic_filter(data, std, size=winSize)

    return np.round(meanData,2), np.round(stdData, 2)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top