0

I am making a code that partially normalizes intensity of an input image. Since I could not find corresponding function of Numpy library, I made a code like following:

def arealNorm(img,kernel_size = 7): #Img should me gray
    img_norm = np.zeros(img.shape)
    for v in range(kernel_size,img.shape[0]-kernel_size):
        for u in range(kernel_size,img.shape[1]-kernel_size):
            MaxV = np.max(img[v-kernel_size:v+kernel_size,u-kernel_size:u+kernel_size])
            minV = np.min(img[v-kernel_size:v+kernel_size,u-kernel_size:u+kernel_size])
            newval = (img[v,u]-minV)/(MaxV-minV)
            img_norm[v,u] = newval
    return img_norm

Since it should access every pixel of the image this code works very slowly.

Is there any numpy-like way to convert my code to work faster ?

MooNChilD Song
  • 225
  • 1
  • 9
  • List comprehension may be faster. [Good resource](https://stackoverflow.com/questions/22108488/are-list-comprehensions-and-functional-functions-faster-than-for-loops) – Blue Robin Feb 16 '23 at 04:15
  • 1
    The looping is an insignificant part of the processing time here. Comprehensions won't help. So, the output should be the relative brightness of each pixel within its 15x15 square? – Tim Roberts Feb 16 '23 at 04:27
  • 1
    https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.maximum_filter.html#scipy.ndimage.maximum_filter may help (and corresponding minimum filter). – Michael Butscher Feb 16 '23 at 04:31
  • @TimRoberts Yes it is – MooNChilD Song Feb 16 '23 at 04:37

2 Answers2

1

One approach to speed up this code is to use the built-in function scipy.ndimage.filters.generic_filter. This function applies a user-defined function to each neighborhood in the input image.

Here is an example implementation using generic_filter:

from scipy.ndimage.filters import generic_filter

def arealNorm(img, kernel_size=7):
  def local_norm(patch):
    max_val = np.max(patch)
    min_val = np.min(patch)
    return (img - min_val) / (max_val - min_val)

  img_norm = generic_filter(img, local_norm, size=kernel_size)
  return img_norm
AKG
  • 598
  • 6
  • 18
  • Thank you for your advice very much. However It seems that your code shows error ```Process finished with exit code -1073741571 (0xC00000FD)```. Can you please give me what I did wrong ? – MooNChilD Song Feb 16 '23 at 04:51
1

Thanks to @Michael Butscher , I finalized my code as :

def arealNorm(img,kernel_size = 7): #Img should me gray
    #img_norm = np.zeros(img.shape)
    img_max = ndi.filters.maximum_filter(img,size = kernel_size)
    img_min = ndi.filters.minimum_filter(img,size = kernel_size)
    img_norm = (img - img_min)/(img_max-img_min)

    return img_norm
MooNChilD Song
  • 225
  • 1
  • 9