Sampling

              
# point sampling
def point(g, step):
    if g is None:
        return g
    g_samp = g[int(step/2)::step, int(step/2)::step]
    return g_samp


# average sampling
def average(g, step):
    if g is None:
        return g
    # averaging the image with convolution
    kernel = np.ones((step, step)) / (step ** 2)
    g_conv = fftconvolve(g / 255.0, kernel[:, :, np.newaxis], mode='same')
    g_samp = g_conv[int(step / 2)::step, int(step / 2)::step]
    return g_samp

              
            

Histogram equalization

              
# Compute Histogram function
def compute_histogram(g):
    # Compute histogram
    H = np.zeros(256)
    for k in range(0, 256):
        H[k] = np.sum(g == k)
    return H

# Histogram function
def histogram(g):
    plt.close()
    H = compute_histogram(g)
    plt.plot(H)
    return plt.gcf()

# Equalize Histogram
def eq_histogram(g):
    M, N = g.shape
    H = compute_histogram(g)
    # Cumulative histogram
    G = np.cumsum(H)
    # Make intensity mapping
    g_eq = np.zeros_like(g)
    for k in range(0, 256):
        g_eq[g == k] = round(G[k] / (M * N) * 255)
    H_eq = compute_histogram(g_eq)
    plt.plot(H_eq)
    return plt.gcf(), g_eq
              
            

Border handling

              
# Zero
def zero(im):
    size = im.shape
    return np.pad(im,
                  ((int(size[0] / 2), int(size[0] / 2)),
                   (int(size[1] / 2), int(size[1] / 2)),
                   (0, 0)),
                  mode="constant")


def periodic(im):
    size = im.shape
    return np.pad(im,
                  ((int(size[0] / 2), int(size[0] / 2)),
                   (int(size[1] / 2), int(size[1] / 2)),
                   (0, 0)),
                  mode="wrap")


def constant(im):
    size = im.shape
    return np.pad(im,
                  ((int(size[0] / 2), int(size[0] / 2)),
                   (int(size[1] / 2), int(size[1] / 2)),
                   (0, 0)),
                  mode="edge")


def symmetric(im):
    size = im.shape
    return np.pad(im,
                  ((int(size[0] / 2), int(size[0] / 2)),
                   (int(size[1] / 2), int(size[1] / 2)),
                   (0, 0)),
                  mode="symmetric")
              
            

Linear filters

              
def gaussian(g):
    if g is None:
        return g
    ks = 31
    y, x = np.mgrid[-ks:ks, -ks:ks]
    h = np.exp(-(x ** 2 + y ** 2) / (2. * (ks / 2) ** 2))
    h = h / h.sum()
    g_conv = fftconvolve(g/255.0, h[:, :, np.newaxis], mode='same')
    return g_conv

def duto(g, lamb):
    if g is None:
        return g
    ks = 31
    y, x = np.mgrid[-ks:ks, -ks:ks]
    h = np.exp(-(x ** 2 + y ** 2) / (2. * (ks / 2) ** 2))
    h = h / h.sum()
    g_conv = fftconvolve(g/255.0, h[:, :, np.newaxis], mode='same')
    # lamb = 0.5
    g_duto = lamb * g/255.0 + (1 - lamb) * g_conv
    return g_duto

def laplace(g):
    if g is None:
        return g
    kernel = np.array([[0, 1, 0],
                       [1, -4, 1],
                       [0, 1, 0]])
    g_conv = fftconvolve(g/255.0, kernel, mode='same')
    # normalisation using clamping for better displaying
    g_conv = (g_conv - g_conv.min()) / (g_conv.max() - g_conv.min())
    return g_conv

def sharpening(g, lamb):
    if g is None:
        return g
    kernel = np.array([[0, 1, 0],
                       [1, -4, 1],
                       [0, 1, 0]])
    g_conv = fftconvolve(g / 255.0, kernel[:, :, np.newaxis], mode='same')
    # normalize
    g_sharp = g/255.0 - lamb * g_conv
    g_sharp = np.clip(g_sharp, 0.0, 1.0)
    return g_sharp

def sobel(g, opts):
    if g is None:
        return g
    kernel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    kernel_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
    kernel_x = kernel_x / (np.sum(np.abs(kernel_x)) * 1.0)
    kernel_y = kernel_y / (np.sum(np.abs(kernel_y)) * 1.0)

    if opts == "x-axis":
        g_conv_x = fftconvolve(g / 255.0, kernel_x[:, :, np.newaxis], mode='same')
        g_conv_x = (g_conv_x - g_conv_x.min()) / (g_conv_x.max() - g_conv_x.min())
        return g_conv_x
    if opts == "y-axis":
        g_conv_y = fftconvolve(g / 255.0, kernel_y[:, :, np.newaxis], mode='same')
        g_conv_y = (g_conv_y - g_conv_y.min()) / (g_conv_y.max() - g_conv_y.min())
        return g_conv_y

    g_conv_x = fftconvolve(g / 255.0, kernel_x[:, :, np.newaxis], mode='same')
    g_conv_y = fftconvolve(g / 255.0, kernel_y[:, :, np.newaxis], mode='same')
    g_conv = np.sqrt(g_conv_x ** 2 + g_conv_y ** 2)
    g_conv = (g_conv - g_conv.min()) / (g_conv.max() - g_conv.min())

    if opts == "edge detection binary":
        g_conv = np.where(g_conv > 0.2, 1.0, 0.0)
    # else normal edge detection
    return g_conv