Skip to content
Snippets Groups Projects
functions.py 7.79 KiB
Newer Older
Alexis David's avatar
Alexis David committed

import numpy as np


# interpolation kernels
w1 = np.array([[0,0,-1,0,0], [0,0,2,0,0], [-1,2,4,2,-1], [0,0,2,0,0], [0,0,-1,0,0]])/8 # G at R location
w2 = w1 #G at B location
w3 = np.array([[0,0,0.5,0,0], [0,-1,0,-1,0], [-1,4,5,4,-1], [0,-1,0,-1,0], [0,0,0.5,0,0]])/8 # R at G location (Brow, Rcol)
w4 = np.array([[0,0,-1,0,0], [0,-1,4,-1,0], [0.5,0,5,0,0.5], [0,-1,4,-1,0], [0,0,-1,0,0]])/8 # R at G location (Rrow, Bcol)
w5 = np.array([[0,0,-3/2,0,0], [0,2,0,2,0], [-3/2,0,6,0,-1], [0,2,0,2,0], [0,0,-3/2,0,0]])/8 # R at B location (Brow, Bcol)
w6 = w3 #R at G location (Brow, Rcol)
w7 = w4 #B at G location (Rrow, Bcol)
w8 = w5 #B at R location (Rrow, Rcol)
w_s = [w1, w2, w3, w4, w5, w6, w7, w8]

def conv(A,B):
    return np.sum(A*B)

def bayer_gradient_interpolation(y, op, w=w_s):
    """
    Second interpolation method: convolution with a 2D kernels (5x5) using multi-channel interpolations
    y: input image
    w: interpolation kernels
    """
    y_padded = np.pad(y, ((2,2),(2,2)), 'constant', constant_values=0)
    size_padded = y_padded.shape

    #separate channels
    y_0 = y*op.mask[:, :, 0]
    y_1 = y*op.mask[:, :, 1]
    y_2 = y*op.mask[:, :, 2]

    for i in range(2,size_padded[0]-2):
        for j in range(2,size_padded[1]-2):

            # determine the location of the pixel
            if op.mask[i-2,j-2,1] == 1: # at G
                if op.mask[i-2,j-3,0] == 1: #R row
                    y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w3)
                    y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w7)
                else: #B row
                    y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w4)
                    y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w6)

            elif op.mask[i-2,j-2,0] == 1: # at R
                y_1[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w1)
                y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w8)

            else: # at B
                y_1[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w2)
                y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w5)

    y_res = np.zeros((y.shape[0], y.shape[1], 3))
    y_res[:, :, 0] = y_0
    y_res[:, :, 1] = y_1
    y_res[:, :, 2] = y_2

    return y_res



import numpy as np
def conv(A,B):
    return np.sum(A*B)
def quad_gradient_interpolation(y, op):
    """
    Second interpolation method: convolution with a 2D kernels (5x5) using multi-channel interpolations
    y: input image
    w: interpolation kernels
    """
    y_padded = np.pad(y, ((2,2),(2,2)), 'constant', constant_values=0)
    size_padded = y_padded.shape

    mask_padded = np.pad(op.mask, ((2,2),(2,2),(0,0)), 'constant', constant_values=-1)

    #separate channels
    y_0 = y*op.mask[:, :, 0]
    y_1 = y*op.mask[:, :, 1]
    y_2 = y*op.mask[:, :, 2]

    #interpolation kernels
    # green quad kernels
    wg11 = np.zeros((5,5))
    wg11[0,2] = -3
    wg11[1,2] = 13
    wg11[2,4] = 2
    wg11 += wg11.T
    wg11 = wg11/24

    # rotate the kernel
    wg12 = np.rot90(wg11,3)
    wg22 = np.rot90(wg11,2)
    wg21 = np.rot90(wg11,1)

    #red/blue quad kernels
        # center part 
    w_c11 = np.zeros((5,5))
    w_c11[0:2,0:2] = np.array([[-1,-1],[-1,9]])/6
    w_c21 = np.rot90(w_c11,1)
    w_c22 = np.rot90(w_c11,2)
    w_c12 = np.rot90(w_c11,3)
        # left part
    w_l11 = np.zeros((5,5))
    w_l11[0:2, 2] = np.array([-3,13])
    w_l11[4,2] = 2
    w_l11 = w_l11/12
    w_l22 = np.rot90(w_l11,2)
        # top part
    w_t11 = np.rot90(w_l11,1)
    w_t22 = np.rot90(w_t11,2)


    for i in range(2,size_padded[0]-2):
        for j in range(2,size_padded[1]-2):

            # determine the location of the pixel
            if mask_padded[i,j,1] == 1: # at G
                if mask_padded[i-1,j,0] + mask_padded[i+1,j,0] == 1: # at R column
                    if mask_padded[i,j-1,2] == 1:
                        y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_t11)
                    elif mask_padded[i,j+1,2] == 1:
                        y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_t22)
                    if mask_padded[i-1,j,0] == 1:
                        y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_l11)
                    elif mask_padded[i+1,j,0] == 1:
                        y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_l22)

                else:
                    if mask_padded[i,j-1,0] == 1:
                        y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_t11)
                    elif mask_padded[i,j+1,0] == 1:
                        y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_t22)
                    if mask_padded[i-1,j,2] == 1:
                        y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_l11)
                    elif mask_padded[i+1,j,2] == 1:
                        y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_l22)


            elif mask_padded[i,j,1] == 0: # at R or B
                if mask_padded[i-1,j,1] ==1:
                    if mask_padded[i,j-1,1] ==1:
                        y_1[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],wg11)
                    else:
                        y_1[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],wg12)
                else:
                    if mask_padded[i,j-1,1] ==1:
                        y_1[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],wg21)
                    else:
                        y_1[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],wg22)
                
                if mask_padded[i,j,0] == 1: #at R
                    if mask_padded[i-1,j-1,2] ==1: #center (1,1)
                        y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_c11)
                    elif mask_padded[i-1,j+1,2] ==1: #center (1,2)
                        y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_c12)
                    elif mask_padded[i+1,j-1,2] ==1: #center (2,1)
                        y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_c21)
                    elif mask_padded[i+1,j+1,2] ==1: #center (2,2)
                        y_2[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_c22)
                    
                elif mask_padded[i,j,2] == 1: #at B
                    if mask_padded[i-1,j-1,0] ==1: #center (1,1)
                        y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_c11)   
                    elif mask_padded[i-1,j+1,0] ==1: #center (1,2)
                        y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_c12)
                    elif mask_padded[i+1,j-1,0] ==1: #center (2,1)
                        y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_c21)
                    elif mask_padded[i+1,j+1,0] ==1: #center (2,2)
                        y_0[i-2,j-2] = conv(y_padded[i-2:i+3, j-2:j+3],w_c22)

    y_res = np.zeros((y.shape[0], y.shape[1], 3))
    y_res[:, :, 0] = y_0
    y_res[:, :, 1] = y_1
    y_res[:, :, 2] = y_2

    return y_res

from scipy import signal
def interpolate(y, op, mode = 'bayer'):
    """
    First interpolation method: convolution with a 2D kernel
    y: input image
    op: object of class CFA
    """
    #separate channels
    y_0 = y*op.mask[:, :, 0]
    y_1 = y*op.mask[:, :, 1]
    y_2 = y*op.mask[:, :, 2]

    #convolution 2D
    
    if mode == 'bayer':
        a = np.array([1,2,1])
    elif mode == 'quad_bayer':
        a = np.array([1,2,3,2,1])
    else:
        raise Exception('Mode not supported')
    
    # create the 2D kernel
    w = a[:, None] * a[None, :]
    w = w / np.sum(w)

    #interpolate green
    y_1_interpolated = signal.convolve2d(y_1, w, mode='same', boundary='fill', fillvalue=0)

    #interpolate red
    y_0_interpolated = signal.convolve2d(y_0, w, mode='same', boundary='fill', fillvalue=0)

    # interpolate blue
    y_2_interpolated = signal.convolve2d(y_2, w, mode='same', boundary='fill', fillvalue=0)

    y_res = np.zeros((y.shape[0], y.shape[1], 3))   
    y_res[:,:,0] = y_0_interpolated*4
    y_res[:,:,1] = y_1_interpolated*2
    y_res[:,:,2] = y_2_interpolated*4

    return y_res