import numpy as np import math import time import utility from scipy import signal # ============================================================= # function: dbayer_mhc # demosaicing using Malvar-He-Cutler algorithm # http://www.ipol.im/pub/art/2011/g_mhcd/ # ============================================================= def debayer_mhc(raw, bayer_pattern="rggb", clip_range=[0, 65535], timeshow=False): # convert to float32 in case it was not raw = np.float32(raw) # dimensions width, height = utility.helpers(raw).get_width_height() # number of pixels to pad no_of_pixel_pad = 2 raw = np.pad(raw, \ (no_of_pixel_pad, no_of_pixel_pad),\ 'reflect') # reflect would not repeat the border value # allocate space for the R, G, B planes R = np.empty( (height + no_of_pixel_pad * 2, width + no_of_pixel_pad * 2), dtype = np.float32 ) G = np.empty( (height + no_of_pixel_pad * 2, width + no_of_pixel_pad * 2), dtype = np.float32 ) B = np.empty( (height + no_of_pixel_pad * 2, width + no_of_pixel_pad * 2), dtype = np.float32 ) # create a RGB output demosaic_out = np.empty( (height, width, 3), dtype = np.float32 ) # fill up the directly available values according to the Bayer pattern if (bayer_pattern == "rggb"): G[::2, 1::2] = raw[::2, 1::2] G[1::2, ::2] = raw[1::2, ::2] R[::2, ::2] = raw[::2, ::2] B[1::2, 1::2] = raw[1::2, 1::2] # Green channel for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # to display progress t0 = time.process_time() for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # G at Red location if (((i % 2) == 0) and ((j % 2) == 0)): G[i, j] = 0.125 * np.sum([-1. * R[i-2, j], \ 2. * G[i-1, j], \ -1. * R[i, j-2], 2. * G[i, j-1], 4. * R[i,j], 2. * G[i, j+1], -1. * R[i, j+2],\ 2. * G[i+1, j], \ -1. * R[i+2, j]]) # G at Blue location elif (((i % 2) != 0) and ((j % 2) != 0)): G[i, j] = 0.125 * np.sum([-1. * B[i-2, j], \ 2. * G[i-1, j], \ -1. * B[i, j-2], 2. * G[i, j-1], 4. * B[i,j], 2. * G[i, j+1], -1. * B[i, j+2], \ 2. * G[i+1, j],\ -1. * B[i+2, j]]) if (timeshow): elapsed_time = time.process_time() - t0 print("Green: row index: " + str(i-1) + " of " + str(height) + \ " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # Red and Blue channel for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # to display progress t0 = time.process_time() for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # Green locations in Red rows if (((i % 2) == 0) and ((j % 2) != 0)): # R at Green locations in Red rows R[i, j] = 0.125 * np.sum([.5 * G[i-2, j],\ -1. * G[i-1, j-1], -1. * G[i-1, j+1], \ -1. * G[i, j-2], 4. * R[i, j-1], 5. * G[i,j], 4. * R[i, j+1], -1. * G[i, j+2], \ -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ .5 * G[i+2, j]]) # B at Green locations in Red rows B[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ -1. * G[i-1, j-1], 4. * B[i-1, j], -1. * G[i-1, j+1], \ .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ -1. * G[i+1, j-1], 4. * B[i+1,j], -1. * G[i+1, j+1], \ -1. * G[i+2, j]]) # Green locations in Blue rows elif (((i % 2) != 0) and ((j % 2) == 0)): # R at Green locations in Blue rows R[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ -1. * G[i-1, j-1], 4. * R[i-1, j], -1. * G[i-1, j+1], \ .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ -1. * G[i+1, j-1], 4. * R[i+1, j], -1. * G[i+1, j+1], \ -1. * G[i+2, j]]) # B at Green locations in Blue rows B[i, j] = 0.125 * np.sum([.5 * G[i-2, j], \ -1. * G [i-1, j-1], -1. * G[i-1, j+1], \ -1. * G[i, j-2], 4. * B[i, j-1], 5. * G[i,j], 4. * B[i, j+1], -1. * G[i, j+2], \ -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ .5 * G[i+2, j]]) # R at Blue locations elif (((i % 2) != 0) and ((j % 2) != 0)): R[i, j] = 0.125 * np.sum([-1.5 * B[i-2, j], \ 2. * R[i-1, j-1], 2. * R[i-1, j+1], \ -1.5 * B[i, j-2], 6. * B[i,j], -1.5 * B[i, j+2], \ 2. * R[i+1, j-1], 2. * R[i+1, j+1], \ -1.5 * B[i+2, j]]) # B at Red locations elif (((i % 2) == 0) and ((j % 2) == 0)): B[i, j] = 0.125 * np.sum([-1.5 * R[i-2, j], \ 2. * B[i-1, j-1], 2. * B[i-1, j+1], \ -1.5 * R[i, j-2], 6. * R[i,j], -1.5 * R[i, j+2], \ 2. * B[i+1, j-1], 2. * B[i+1, j+1], \ -1.5 * R[i+2, j]]) if (timeshow): elapsed_time = time.process_time() - t0 print("Red/Blue: row index: " + str(i-1) + " of " + str(height) + \ " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") elif (bayer_pattern == "gbrg"): G[::2, ::2] = raw[::2, ::2] G[1::2, 1::2] = raw[1::2, 1::2] R[1::2, ::2] = raw[1::2, ::2] B[::2, 1::2] = raw[::2, 1::2] # Green channel for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # to display progress t0 = time.process_time() for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # G at Red location if (((i % 2) != 0) and ((j % 2) == 0)): G[i, j] = 0.125 * np.sum([-1. * R[i-2, j], \ 2. * G[i-1, j], \ -1. * R[i, j-2], 2. * G[i, j-1], 4. * R[i,j], 2. * G[i, j+1], -1. * R[i, j+2],\ 2. * G[i+1, j], \ -1. * R[i+2, j]]) # G at Blue location elif (((i % 2) == 0) and ((j % 2) != 0)): G[i, j] = 0.125 * np.sum([-1. * B[i-2, j], \ 2. * G[i-1, j], \ -1. * B[i, j-2], 2. * G[i, j-1], 4. * B[i,j], 2. * G[i, j+1], -1. * B[i, j+2], \ 2. * G[i+1, j],\ -1. * B[i+2, j]]) if (timeshow): elapsed_time = time.process_time() - t0 print("Green: row index: " + str(i-1) + " of " + str(height) + \ " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # Red and Blue channel for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # to display progress t0 = time.process_time() for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # Green locations in Red rows if (((i % 2) != 0) and ((j % 2) != 0)): # R at Green locations in Red rows R[i, j] = 0.125 * np.sum([.5 * G[i-2, j],\ -1. * G[i-1, j-1], -1. * G[i-1, j+1], \ -1. * G[i, j-2], 4. * R[i, j-1], 5. * G[i,j], 4. * R[i, j+1], -1. * G[i, j+2], \ -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ .5 * G[i+2, j]]) # B at Green locations in Red rows B[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ -1. * G[i-1, j-1], 4. * B[i-1, j], -1. * G[i-1, j+1], \ .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ -1. * G[i+1, j-1], 4. * B[i+1,j], -1. * G[i+1, j+1], \ -1. * G[i+2, j]]) # Green locations in Blue rows elif (((i % 2) == 0) and ((j % 2) == 0)): # R at Green locations in Blue rows R[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ -1. * G[i-1, j-1], 4. * R[i-1, j], -1. * G[i-1, j+1], \ .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ -1. * G[i+1, j-1], 4. * R[i+1, j], -1. * G[i+1, j+1], \ -1. * G[i+2, j]]) # B at Green locations in Blue rows B[i, j] = 0.125 * np.sum([.5 * G[i-2, j], \ -1. * G [i-1, j-1], -1. * G[i-1, j+1], \ -1. * G[i, j-2], 4. * B[i, j-1], 5. * G[i,j], 4. * B[i, j+1], -1. * G[i, j+2], \ -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ .5 * G[i+2, j]]) # R at Blue locations elif (((i % 2) == 0) and ((j % 2) != 0)): R[i, j] = 0.125 * np.sum([-1.5 * B[i-2, j], \ 2. * R[i-1, j-1], 2. * R[i-1, j+1], \ -1.5 * B[i, j-2], 6. * B[i,j], -1.5 * B[i, j+2], \ 2. * R[i+1, j-1], 2. * R[i+1, j+1], \ -1.5 * B[i+2, j]]) # B at Red locations elif (((i % 2) != 0) and ((j % 2) == 0)): B[i, j] = 0.125 * np.sum([-1.5 * R[i-2, j], \ 2. * B[i-1, j-1], 2. * B[i-1, j+1], \ -1.5 * R[i, j-2], 6. * R[i,j], -1.5 * R[i, j+2], \ 2. * B[i+1, j-1], 2. * B[i+1, j+1], \ -1.5 * R[i+2, j]]) if (timeshow): elapsed_time = time.process_time() - t0 print("Red/Blue: row index: " + str(i-1) + " of " + str(height) + \ " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") elif (bayer_pattern == "grbg"): G[::2, ::2] = raw[::2, ::2] G[1::2, 1::2] = raw[1::2, 1::2] R[::2, 1::2] = raw[::2, 1::2] B[1::2, ::2] = raw[1::2, ::2] # Green channel for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # to display progress t0 = time.process_time() for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # G at Red location if (((i % 2) == 0) and ((j % 2) != 0)): G[i, j] = 0.125 * np.sum([-1. * R[i-2, j], \ 2. * G[i-1, j], \ -1. * R[i, j-2], 2. * G[i, j-1], 4. * R[i,j], 2. * G[i, j+1], -1. * R[i, j+2],\ 2. * G[i+1, j], \ -1. * R[i+2, j]]) # G at Blue location elif (((i % 2) != 0) and ((j % 2) == 0)): G[i, j] = 0.125 * np.sum([-1. * B[i-2, j], \ 2. * G[i-1, j], \ -1. * B[i, j-2], 2. * G[i, j-1], 4. * B[i,j], 2. * G[i, j+1], -1. * B[i, j+2], \ 2. * G[i+1, j],\ -1. * B[i+2, j]]) if (timeshow): elapsed_time = time.process_time() - t0 print("Green: row index: " + str(i-1) + " of " + str(height) + \ " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # Red and Blue channel for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # to display progress t0 = time.process_time() for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # Green locations in Red rows if (((i % 2) == 0) and ((j % 2) == 0)): # R at Green locations in Red rows R[i, j] = 0.125 * np.sum([.5 * G[i-2, j],\ -1. * G[i-1, j-1], -1. * G[i-1, j+1], \ -1. * G[i, j-2], 4. * R[i, j-1], 5. * G[i,j], 4. * R[i, j+1], -1. * G[i, j+2], \ -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ .5 * G[i+2, j]]) # B at Green locations in Red rows B[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ -1. * G[i-1, j-1], 4. * B[i-1, j], -1. * G[i-1, j+1], \ .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ -1. * G[i+1, j-1], 4. * B[i+1,j], -1. * G[i+1, j+1], \ -1. * G[i+2, j]]) # Green locations in Blue rows elif (((i % 2) != 0) and ((j % 2) != 0)): # R at Green locations in Blue rows R[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ -1. * G[i-1, j-1], 4. * R[i-1, j], -1. * G[i-1, j+1], \ .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ -1. * G[i+1, j-1], 4. * R[i+1, j], -1. * G[i+1, j+1], \ -1. * G[i+2, j]]) # B at Green locations in Blue rows B[i, j] = 0.125 * np.sum([.5 * G[i-2, j], \ -1. * G [i-1, j-1], -1. * G[i-1, j+1], \ -1. * G[i, j-2], 4. * B[i, j-1], 5. * G[i,j], 4. * B[i, j+1], -1. * G[i, j+2], \ -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ .5 * G[i+2, j]]) # R at Blue locations elif (((i % 2) != 0) and ((j % 2) == 0)): R[i, j] = 0.125 * np.sum([-1.5 * B[i-2, j], \ 2. * R[i-1, j-1], 2. * R[i-1, j+1], \ -1.5 * B[i, j-2], 6. * B[i,j], -1.5 * B[i, j+2], \ 2. * R[i+1, j-1], 2. * R[i+1, j+1], \ -1.5 * B[i+2, j]]) # B at Red locations elif (((i % 2) == 0) and ((j % 2) != 0)): B[i, j] = 0.125 * np.sum([-1.5 * R[i-2, j], \ 2. * B[i-1, j-1], 2. * B[i-1, j+1], \ -1.5 * R[i, j-2], 6. * R[i,j], -1.5 * R[i, j+2], \ 2. * B[i+1, j-1], 2. * B[i+1, j+1], \ -1.5 * R[i+2, j]]) if (timeshow): elapsed_time = time.process_time() - t0 print("Red/Blue: row index: " + str(i-1) + " of " + str(height) + \ " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") elif (bayer_pattern == "bggr"): G[::2, 1::2] = raw[::2, 1::2] G[1::2, ::2] = raw[1::2, ::2] R[1::2, 1::2] = raw[1::2, 1::2] B[::2, ::2] = raw[::2, ::2] # Green channel for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # to display progress t0 = time.process_time() for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # G at Red location if (((i % 2) != 0) and ((j % 2) != 0)): G[i, j] = 0.125 * np.sum([-1. * R[i-2, j], \ 2. * G[i-1, j], \ -1. * R[i, j-2], 2. * G[i, j-1], 4. * R[i,j], 2. * G[i, j+1], -1. * R[i, j+2],\ 2. * G[i+1, j], \ -1. * R[i+2, j]]) # G at Blue location elif (((i % 2) == 0) and ((j % 2) == 0)): G[i, j] = 0.125 * np.sum([-1. * B[i-2, j], \ 2. * G[i-1, j], \ -1. * B[i, j-2], 2. * G[i, j-1], 4. * B[i,j], 2. * G[i, j+1], -1. * B[i, j+2], \ 2. * G[i+1, j],\ -1. * B[i+2, j]]) if (timeshow): elapsed_time = time.process_time() - t0 print("Green: row index: " + str(i-1) + " of " + str(height) + \ " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # Red and Blue channel for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # to display progress t0 = time.process_time() for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # Green locations in Red rows if (((i % 2) != 0) and ((j % 2) == 0)): # R at Green locations in Red rows R[i, j] = 0.125 * np.sum([.5 * G[i-2, j],\ -1. * G[i-1, j-1], -1. * G[i-1, j+1], \ -1. * G[i, j-2], 4. * R[i, j-1], 5. * G[i,j], 4. * R[i, j+1], -1. * G[i, j+2], \ -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ .5 * G[i+2, j]]) # B at Green locations in Red rows B[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ -1. * G[i-1, j-1], 4. * B[i-1, j], -1. * G[i-1, j+1], \ .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ -1. * G[i+1, j-1], 4. * B[i+1,j], -1. * G[i+1, j+1], \ -1. * G[i+2, j]]) # Green locations in Blue rows elif (((i % 2) == 0) and ((j % 2) != 0)): # R at Green locations in Blue rows R[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ -1. * G[i-1, j-1], 4. * R[i-1, j], -1. * G[i-1, j+1], \ .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ -1. * G[i+1, j-1], 4. * R[i+1, j], -1. * G[i+1, j+1], \ -1. * G[i+2, j]]) # B at Green locations in Blue rows B[i, j] = 0.125 * np.sum([.5 * G[i-2, j], \ -1. * G [i-1, j-1], -1. * G[i-1, j+1], \ -1. * G[i, j-2], 4. * B[i, j-1], 5. * G[i,j], 4. * B[i, j+1], -1. * G[i, j+2], \ -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ .5 * G[i+2, j]]) # R at Blue locations elif (((i % 2) == 0) and ((j % 2) == 0)): R[i, j] = 0.125 * np.sum([-1.5 * B[i-2, j], \ 2. * R[i-1, j-1], 2. * R[i-1, j+1], \ -1.5 * B[i, j-2], 6. * B[i,j], -1.5 * B[i, j+2], \ 2. * R[i+1, j-1], 2. * R[i+1, j+1], \ -1.5 * B[i+2, j]]) # B at Red locations elif (((i % 2) != 0) and ((j % 2) != 0)): B[i, j] = 0.125 * np.sum([-1.5 * R[i-2, j], \ 2. * B[i-1, j-1], 2. * B[i-1, j+1], \ -1.5 * R[i, j-2], 6. * R[i,j], -1.5 * R[i, j+2], \ 2. * B[i+1, j-1], 2. * B[i+1, j+1], \ -1.5 * R[i+2, j]]) if (timeshow): elapsed_time = time.process_time() - t0 print("Red/Blue: row index: " + str(i-1) + " of " + str(height) + \ " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") else: print("Invalid bayer pattern. Valid pattern can be rggb, gbrg, grbg, bggr") return demosaic_out # This will be all zeros # Fill up the RGB output with interpolated values demosaic_out[0:height, 0:width, 0] = R[no_of_pixel_pad : height + no_of_pixel_pad, \ no_of_pixel_pad : width + no_of_pixel_pad] demosaic_out[0:height, 0:width, 1] = G[no_of_pixel_pad : height + no_of_pixel_pad, \ no_of_pixel_pad : width + no_of_pixel_pad] demosaic_out[0:height, 0:width, 2] = B[no_of_pixel_pad : height + no_of_pixel_pad, \ no_of_pixel_pad : width + no_of_pixel_pad] demosaic_out = np.clip(demosaic_out, clip_range[0], clip_range[1]) return demosaic_out def fill_channel_directional_weight(data, bayer_pattern): #== Calculate the directional weights (weight_N, weight_E, weight_S, weight_W. # where N, E, S, W stand for north, east, south, and west.) data = np.asarray(data) v = np.asarray(signal.convolve2d(data, [[1],[0],[-1]], mode="same", boundary="symm")) h = np.asarray(signal.convolve2d(data, [[1, 0, -1]], mode="same", boundary="symm")) weight_N = np.zeros(np.shape(data), dtype=np.float32) weight_E = np.zeros(np.shape(data), dtype=np.float32) weight_S = np.zeros(np.shape(data), dtype=np.float32) weight_W = np.zeros(np.shape(data), dtype=np.float32) value_N = np.zeros(np.shape(data), dtype=np.float32) value_E = np.zeros(np.shape(data), dtype=np.float32) value_S = np.zeros(np.shape(data), dtype=np.float32) value_W = np.zeros(np.shape(data), dtype=np.float32) if ((bayer_pattern == "rggb") or (bayer_pattern == "bggr")): # note that in the following the locations in the comments are given # assuming the bayer_pattern rggb #== CALCULATE WEIGHTS IN B LOCATIONS weight_N[1::2, 1::2] = np.abs(v[1::2, 1::2]) + np.abs(v[::2, 1::2]) # repeating the column before the last to the right so that sampling # does not cause any dimension mismatch temp_h_b = np.hstack((h, np.atleast_2d(h[:, -2]).T)) weight_E[1::2, 1::2] = np.abs(h[1::2, 1::2]) + np.abs(temp_h_b[1::2, 2::2]) # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch temp_v_b = np.vstack((v, v[-1])) weight_S[1::2, 1::2] = np.abs(v[1::2, 1::2]) + np.abs(temp_v_b[2::2, 1::2]) weight_W[1::2, 1::2] = np.abs(h[1::2, 1::2]) + np.abs(h[1::2, ::2]) #== CALCULATE WEIGHTS IN R LOCATIONS # repeating the second row at the top of matrix so that sampling does # not cause any dimension mismatch, also remove the bottom row temp_v_r = np.delete(np.vstack((v[1], v)), -1, 0) weight_N[::2, ::2] = np.abs(v[::2, ::2]) + np.abs(temp_v_r[::2, ::2]) weight_E[::2, ::2] = np.abs(h[::2, ::2]) + np.abs(h[::2, 1::2]) weight_S[::2, ::2] = np.abs(v[::2, ::2]) + np.abs(v[1::2, ::2]) # repeating the second column at the left of matrix so that sampling # does not cause any dimension mismatch, also remove the rightmost # column temp_h_r = np.delete(np.hstack((np.atleast_2d(h[:, 1]).T, h)), -1, 1) weight_W[::2, ::2] = np.abs(h[::2, ::2]) + np.abs(temp_h_r[::2, ::2]) weight_N = np.divide(1., 1. + weight_N) weight_E = np.divide(1., 1. + weight_E) weight_S = np.divide(1., 1. + weight_S) weight_W = np.divide(1., 1. + weight_W) #== CALCULATE DIRECTIONAL ESTIMATES IN B LOCATIONS value_N[1::2, 1::2] = data[::2, 1::2] + v[::2, 1::2] / 2. # repeating the column before the last to the right so that sampling # does not cause any dimension mismatch temp = np.hstack((data, np.atleast_2d(data[:, -2]).T)) value_E[1::2, 1::2] = temp[1::2, 2::2] - temp_h_b[1::2, 2::2] / 2. # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch temp = np.vstack((data, data[-1])) value_S[1::2, 1::2] = temp[2::2, 1::2] - temp_v_b[2::2, 1::2] / 2. value_W[1::2, 1::2] = data[1::2, ::2] + h[1::2, ::2] / 2. #== CALCULATE DIRECTIONAL ESTIMATES IN R LOCATIONS # repeating the second row at the top of matrix so that sampling does # not cause any dimension mismatch, also remove the bottom row temp = np.delete(np.vstack((data[1], data)), -1, 0) value_N[::2, ::2] = temp[::2, ::2] + temp_v_r[::2, ::2] / 2. value_E[::2, ::2] = data[::2, 1::2] - h[::2, 1::2] / 2. value_S[::2, ::2] = data[1::2, ::2] - v[1::2, ::2] / 2. # repeating the second column at the left of matrix so that sampling # does not cause any dimension mismatch, also remove the rightmost # column temp = np.delete(np.hstack((np.atleast_2d(data[:, 1]).T, data)), -1, 1) value_W[::2, ::2] = temp[::2, ::2] + temp_h_r[::2, ::2] / 2. output = np.zeros(np.shape(data), dtype=np.float32) output = np.divide((np.multiply(value_N, weight_N) + \ np.multiply(value_E, weight_E) + \ np.multiply(value_S, weight_S) + \ np.multiply(value_W, weight_W)),\ (weight_N + weight_E + weight_S + weight_W)) output[::2, 1::2] = data[::2, 1::2] output[1::2, ::2] = data[1::2, ::2] return output elif ((bayer_pattern == "gbrg") or (bayer_pattern == "grbg")): # note that in the following the locations in the comments are given # assuming the bayer_pattern gbrg #== CALCULATE WEIGHTS IN B LOCATIONS # repeating the second row at the top of matrix so that sampling does # not cause any dimension mismatch, also remove the bottom row temp_v_b = np.delete(np.vstack((v[1], v)), -1, 0) weight_N[::2, 1::2] = np.abs(v[::2, 1::2]) + np.abs(temp_v_b[::2, 1::2]) # repeating the column before the last to the right so that sampling # does not cause any dimension mismatch temp_h_b = np.hstack((h, np.atleast_2d(h[:, -2]).T)) weight_E[::2, 1::2] = np.abs(h[::2, 1::2]) + np.abs(temp_h_b[::2, 2::2]) # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch weight_S[::2, 1::2] = np.abs(v[::2, 1::2]) + np.abs(v[1::2, 1::2]) weight_W[::2, 1::2] = np.abs(h[::2, 1::2]) + np.abs(h[::2, ::2]) #== CALCULATE WEIGHTS IN R LOCATIONS weight_N[1::2, ::2] = np.abs(v[1::2, ::2]) + np.abs(v[::2, ::2]) weight_E[1::2, ::2] = np.abs(h[1::2, ::2]) + np.abs(h[1::2, 1::2]) # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch temp_v_r = np.vstack((v, v[-1])) weight_S[1::2, ::2] = np.abs(v[1::2, ::2]) + np.abs(temp_v_r[2::2, ::2]) # repeating the second column at the left of matrix so that sampling # does not cause any dimension mismatch, also remove the rightmost # column temp_h_r = np.delete(np.hstack((np.atleast_2d(h[:, 1]).T, h)), -1, 1) weight_W[1::2, ::2] = np.abs(h[1::2, ::2]) + np.abs(temp_h_r[1::2, ::2]) weight_N = np.divide(1., 1. + weight_N) weight_E = np.divide(1., 1. + weight_E) weight_S = np.divide(1., 1. + weight_S) weight_W = np.divide(1., 1. + weight_W) #== CALCULATE DIRECTIONAL ESTIMATES IN B LOCATIONS # repeating the second row at the top of matrix so that sampling does # not cause any dimension mismatch, also remove the bottom row temp = np.delete(np.vstack((data[1], data)), -1, 0) value_N[::2, 1::2] = temp[::2, 1::2] + temp_v_b[::2, 1::2] / 2. # repeating the column before the last to the right so that sampling # does not cause any dimension mismatch temp = np.hstack((data, np.atleast_2d(data[:, -2]).T)) value_E[::2, 1::2] = temp[::2, 2::2] - temp_h_b[::2, 2::2] / 2. # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch value_S[::2, 1::2] = data[1::2, 1::2] - v[1::2, 1::2] / 2. value_W[::2, 1::2] = data[::2, ::2] + h[::2, ::2] / 2. #== CALCULATE DIRECTIONAL ESTIMATES IN R LOCATIONS # repeating the second row at the top of matrix so that sampling does # not cause any dimension mismatch, also remove the bottom row value_N[1::2, ::2] = data[::2, ::2] + v[::2, ::2] / 2. value_E[1::2, ::2] = data[1::2, 1::2] - h[1::2, 1::2] / 2. # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch temp = np.vstack((data, data[-1])) value_S[1::2, ::2] = temp[2::2, ::2] - temp_v_r[2::2, ::2] / 2. # repeating the second column at the left of matrix so that sampling # does not cause any dimension mismatch, also remove the rightmost # column temp = np.delete(np.hstack((np.atleast_2d(data[:, 1]).T, data)), -1, 1) value_W[1::2, ::2] = temp[1::2, ::2] + temp_h_r[1::2, ::2] / 2. output = np.zeros(np.shape(data), dtype=np.float32) output = np.divide((np.multiply(value_N, weight_N) + \ np.multiply(value_E, weight_E) + \ np.multiply(value_S, weight_S) + \ np.multiply(value_W, weight_W)),\ (weight_N + weight_E + weight_S + weight_W)) output[::2, ::2] = data[::2, ::2] output[1::2, 1::2] = data[1::2, 1::2] return output def fill_br_locations(data, G, bayer_pattern): # Fill up the B/R values interpolated at R/B locations B = np.zeros(np.shape(data), dtype=np.float32) R = np.zeros(np.shape(data), dtype=np.float32) data = np.asarray(data) G = np.asarray(G) d1 = np.asarray(signal.convolve2d(data, [[-1, 0, 0],[0, 0, 0], [0, 0, 1]], mode="same", boundary="symm")) d2 = np.asarray(signal.convolve2d(data, [[0, 0, 1], [0, 0, 0], [-1, 0, 0]], mode="same", boundary="symm")) df_NE = np.asarray(signal.convolve2d(G, [[0, 0, 0], [0, 1, 0], [-1, 0, 0]], mode="same", boundary="symm")) df_SE = np.asarray(signal.convolve2d(G, [[-1, 0, 0], [0, 1, 0], [0, 0, 0]], mode="same", boundary="symm")) df_SW = np.asarray(signal.convolve2d(G, [[0, 0, -1], [0, 1, 0], [0, 0, 0]], mode="same", boundary="symm")) df_NW = np.asarray(signal.convolve2d(G, [[0, 0, 0], [0, 1, 0], [0, 0, -1]], mode="same", boundary="symm")) weight_NE = np.zeros(np.shape(data), dtype=np.float32) weight_SE = np.zeros(np.shape(data), dtype=np.float32) weight_SW = np.zeros(np.shape(data), dtype=np.float32) weight_NW = np.zeros(np.shape(data), dtype=np.float32) value_NE = np.zeros(np.shape(data), dtype=np.float32) value_SE = np.zeros(np.shape(data), dtype=np.float32) value_SW = np.zeros(np.shape(data), dtype=np.float32) value_NW = np.zeros(np.shape(data), dtype=np.float32) if ((bayer_pattern == "rggb") or (bayer_pattern == "bggr")): #== weights for B in R locations weight_NE[::2, ::2] = np.abs(d2[::2, ::2]) + np.abs(df_NE[::2, ::2]) weight_SE[::2, ::2] = np.abs(d1[::2, ::2]) + np.abs(df_SE[::2, ::2]) weight_SW[::2, ::2] = np.abs(d2[::2, ::2]) + np.abs(df_SW[::2, ::2]) weight_NW[::2, ::2] = np.abs(d1[::2, ::2]) + np.abs(df_NW[::2, ::2]) #== weights for R in B locations weight_NE[1::2, 1::2] = np.abs(d2[1::2, 1::2]) + np.abs(df_NE[1::2, 1::2]) weight_SE[1::2, 1::2] = np.abs(d1[1::2, 1::2]) + np.abs(df_SE[1::2, 1::2]) weight_SW[1::2, 1::2] = np.abs(d2[1::2, 1::2]) + np.abs(df_SW[1::2, 1::2]) weight_NW[1::2, 1::2] = np.abs(d1[1::2, 1::2]) + np.abs(df_NW[1::2, 1::2]) weight_NE = np.divide(1., 1. + weight_NE) weight_SE = np.divide(1., 1. + weight_SE) weight_SW = np.divide(1., 1. + weight_SW) weight_NW = np.divide(1., 1. + weight_NW) #== directional estimates of B in R locations # repeating the second row at the top of matrix so that sampling does # not cause any dimension mismatch, also remove the bottom row temp = np.delete(np.vstack((data[1], data)), -1, 0) value_NE[::2, ::2] = temp[::2, 1::2] + df_NE[::2, ::2] / 2. value_SE[::2, ::2] = data[1::2, 1::2] + df_SE[::2, ::2] / 2. # repeating the second column at the left of matrix so that sampling # does not cause any dimension mismatch, also remove the rightmost # column temp = np.delete(np.hstack((np.atleast_2d(data[:, 1]).T, data)), -1, 1) value_SW[::2, ::2] = temp[1::2, ::2] + df_SW[::2, ::2] / 2. # repeating the second row at the top of matrix so that sampling does # not cause any dimension mismatch, also remove the bottom row temp = np.delete(np.vstack((data[1], data)), -1, 0) # repeating the second column at the left of matrix so that sampling # does not cause any dimension mismatch, also remove the rightmost # column temp = np.delete(np.hstack((np.atleast_2d(temp[:, 1]).T, temp)), -1, 1) value_NW[::2, ::2] = temp[::2, ::2] + df_NW[::2, ::2] #== directional estimates of R in B locations # repeating the column before the last to the right so that sampling # does not cause any dimension mismatch temp = np.hstack((data, np.atleast_2d(data[:, -2]).T)) value_NE[1::2, 1::2] = temp[::2, 2::2] + df_NE[1::2, 1::2] / 2. # repeating the column before the last to the right so that sampling # does not cause any dimension mismatch temp = np.hstack((data, np.atleast_2d(data[:, -2]).T)) # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch temp = np.vstack((temp, temp[-1])) value_SE[1::2, 1::2] = temp[2::2, 2::2] + df_SE[1::2, 1::2] / 2. # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch temp = np.vstack((data, data[-1])) value_SW[1::2, 1::2] = temp[2::2, ::2] + df_SW[1::2, 1::2] / 2. value_NW[1::2, 1::2] = data[::2, ::2] + df_NW[1::2, 1::2] / 2. RB = np.divide(np.multiply(weight_NE, value_NE) + \ np.multiply(weight_SE, value_SE) + \ np.multiply(weight_SW, value_SW) + \ np.multiply(weight_NW, value_NW),\ (weight_NE + weight_SE + weight_SW + weight_NW)) if (bayer_pattern == "rggb"): R[1::2, 1::2] = RB[1::2, 1::2] R[::2, ::2] = data[::2, ::2] B[::2, ::2] = RB[::2, ::2] B[1::2, 1::2] = data[1::2, 1::2] elif (bayer_pattern == "bggr"): R[::2, ::2] = RB[::2, ::2] R[1::2, 1::2] = data[1::2, 1::2] B[1::2, 1::2] = RB[1::2, 1::2] B[::2, ::2] = data[::2, ::2] R[1::2, ::2] = G[1::2, ::2] R[::2, 1::2] = G[::2, 1::2] R = fill_channel_directional_weight(R, "gbrg") B[1::2, ::2] = G[1::2, ::2] B[::2, 1::2] = G[::2, 1::2] B = fill_channel_directional_weight(B, "gbrg") elif ((bayer_pattern == "grbg") or (bayer_pattern == "gbrg")): #== weights for B in R locations weight_NE[::2, 1::2] = np.abs(d2[::2, 1::2]) + np.abs(df_NE[::2, 1::2]) weight_SE[::2, 1::2] = np.abs(d1[::2, 1::2]) + np.abs(df_SE[::2, 1::2]) weight_SW[::2, 1::2] = np.abs(d2[::2, 1::2]) + np.abs(df_SW[::2, 1::2]) weight_NW[::2, 1::2] = np.abs(d1[::2, 1::2]) + np.abs(df_NW[::2, 1::2]) #== weights for R in B locations weight_NE[1::2, ::2] = np.abs(d2[1::2, ::2]) + np.abs(df_NE[1::2, ::2]) weight_SE[1::2, ::2] = np.abs(d1[1::2, ::2]) + np.abs(df_SE[1::2, ::2]) weight_SW[1::2, ::2] = np.abs(d2[1::2, ::2]) + np.abs(df_SW[1::2, ::2]) weight_NW[1::2, ::2] = np.abs(d1[1::2, ::2]) + np.abs(df_NW[1::2, ::2]) weight_NE = np.divide(1., 1. + weight_NE) weight_SE = np.divide(1., 1. + weight_SE) weight_SW = np.divide(1., 1. + weight_SW) weight_NW = np.divide(1., 1. + weight_NW) #== directional estimates of B in R locations # repeating the second row at the top of matrix so that sampling does # not cause any dimension mismatch, also remove the bottom row temp = np.delete(np.vstack((data[1], data)), -1, 0) # repeating the column before the last to the right so that sampling # does not cause any dimension mismatch temp = np.hstack((temp, np.atleast_2d(temp[:, -2]).T)) value_NE[::2, 1::2] = temp[::2, 2::2] + df_NE[::2, 1::2] / 2. # repeating the column before the last to the right so that sampling # does not cause any dimension mismatch temp = np.hstack((data, np.atleast_2d(data[:, -2]).T)) value_SE[::2, 1::2] = temp[1::2, 2::2] + df_SE[::2, 1::2] / 2. value_SW[::2, 1::2] = data[1::2, ::2] + df_SW[::2, 1::2] / 2. # repeating the second row at the top of matrix so that sampling does # not cause any dimension mismatch, also remove the bottom row temp = np.delete(np.vstack((data[1], data)), -1, 0) value_NW[::2, 1::2] = temp[::2, ::2] + df_NW[::2, 1::2] #== directional estimates of R in B locations value_NE[1::2, ::2] = data[::2, 1::2] + df_NE[1::2, ::2] / 2. # repeating the column before the last to the right so that sampling # does not cause any dimension mismatch temp = np.hstack((data, np.atleast_2d(data[:, -2]).T)) # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch temp = np.vstack((temp, temp[-1])) value_SE[1::2, ::2] = temp[2::2, 1::2] + df_SE[1::2, ::2] / 2. # repeating the row before the last row to the bottom so that sampling # does not cause any dimension mismatch temp = np.vstack((data, data[-1])) # repeating the second column at the left of matrix so that sampling # does not cause any dimension mismatch, also remove the rightmost # column temp = np.delete(np.hstack((np.atleast_2d(temp[:, 1]).T, temp)), -1, 1) value_SW[1::2, ::2] = temp[2::2, ::2] + df_SW[1::2, ::2] / 2. # repeating the second column at the left of matrix so that sampling # does not cause any dimension mismatch, also remove the rightmost # column temp = np.delete(np.hstack((np.atleast_2d(data[:, 1]).T, data)), -1, 1) value_NW[1::2, ::2] = temp[::2, ::2] + df_NW[1::2, ::2] / 2. RB = np.divide(np.multiply(weight_NE, value_NE) + \ np.multiply(weight_SE, value_SE) + \ np.multiply(weight_SW, value_SW) + \ np.multiply(weight_NW, value_NW),\ (weight_NE + weight_SE + weight_SW + weight_NW)) if (bayer_pattern == "grbg"): R[1::2, ::2] = RB[1::2, ::2] R[::2, 1::2] = data[::2, 1::2] B[::2, 1::2] = RB[::2, 1::2] B[1::2, ::2] = data[1::2, ::2] elif (bayer_pattern == "gbrg"): R[::2, 1::2] = RB[::2, 1::2] R[1::2, ::2] = data[1::2, ::2] B[1::2, ::2] = RB[1::2, ::2] B[::2, 1::2] = data[::2, 1::2] R[::2, ::2] = G[::2, ::2] R[1::2, 1::2] = G[1::2, 1::2] R = fill_channel_directional_weight(R, "rggb") B[1::2, 1::2] = G[1::2, 1::2] B[::2, ::2] = G[::2, ::2] B = fill_channel_directional_weight(B, "rggb") return B, R # # ============================================================= # # function: dbayer_mhc_fast # # demosaicing using Malvar-He-Cutler algorithm # # http://www.ipol.im/pub/art/2011/g_mhcd/ # # ============================================================= # def debayer_mhc_fast(raw, bayer_pattern="rggb", clip_range=[0, 65535], timeshow=False): # # # convert to float32 in case it was not # raw = np.float32(raw) # # # dimensions # width, height = utility.helpers(raw).get_width_height() # # # allocate space for the R, G, B planes # R = np.empty((height, width), dtype = np.float32) # G = np.empty((height, width), dtype = np.float32) # B = np.empty((height, width), dtype = np.float32) # # # create a RGB output # demosaic_out = np.empty( (height, width, 3), dtype = np.float32 ) # # # define the convolution kernels # kernel_g_at_rb = [[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.]] * .125 # # kernel_r_at_gr = [[0., 0., .5, 0., 0.],\ # [0., -1., 0., -1., 0.],\ # [-1., 4., 5., 4., -1.],\ # [0., -1., 0., -1., 0.],\ # [0., 0., .5, 0., 0.]] * .125 # # kernel_b_at_gr = [[0., 0., -1., 0., 0.],\ # [0., -1., 4., -1., 0.],\ # [.5., 0., 5., 0., .5],\ # [0., -1., 4., -1., 0],\ # [0., 0., -1., 0., 0.]] * .125 # # kernel_r_at_gb = [[0., 0., -1., 0., 0.],\ # [0., -1., 4., -1., 0.],\ # [.5, 0., 5., 0., .5],\ # [0., -1., 4., -1., 0.],\ # [0., 0., -1., 0., 0.]] * .125 # # kernel_b_at_gb = [[0., 0., .5, 0., 0.],\ # [0., -1., 0., -1., 0.],\ # [-1., 4., 5., 4., -1.],\ # [0., -1., 0., -1., 0.],\ # [0., 0., .5, 0., 0.]] * .125 # # kernel_r_at_b = [[0., 0., -1.5, 0., 0.],\ # [0., 2., 0., 2., 0.],\ # [-1.5, 0., 6., 0., -1.5],\ # [0., 2., 0., 2., 0.],\ # [0., 0., -1.5, 0., 0.]] * .125 # # kernel_b_at_r = [[0., 0., -1.5, 0., 0.],\ # [0., 2., 0., 2., 0.],\ # [-1.5, 0., 6., 0., -1.5],\ # [0., 2., 0., 2., 0.],\ # [0., 0., -1.5, 0., 0.]] * .125 # # # # # fill up the directly available values according to the Bayer pattern # if (bayer_pattern == "rggb"): # # G[::2, 1::2] = raw[::2, 1::2] # G[1::2, ::2] = raw[1::2, ::2] # R[::2, ::2] = raw[::2, ::2] # B[1::2, 1::2] = raw[1::2, 1::2] # # # Green channel # for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # # # to display progress # t0 = time.process_time() # # for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # # # G at Red location # if (((i % 2) == 0) and ((j % 2) == 0)): # G[i, j] = 0.125 * np.sum([-1. * R[i-2, j], \ # 2. * G[i-1, j], \ # -1. * R[i, j-2], 2. * G[i, j-1], 4. * R[i,j], 2. * G[i, j+1], -1. * R[i, j+2],\ # 2. * G[i+1, j], \ # -1. * R[i+2, j]]) # # G at Blue location # elif (((i % 2) != 0) and ((j % 2) != 0)): # G[i, j] = 0.125 * np.sum([-1. * B[i-2, j], \ # 2. * G[i-1, j], \ # -1. * B[i, j-2], 2. * G[i, j-1], 4. * B[i,j], 2. * G[i, j+1], -1. * B[i, j+2], \ # 2. * G[i+1, j],\ # -1. * B[i+2, j]]) # if (timeshow): # elapsed_time = time.process_time() - t0 # print("Green: row index: " + str(i-1) + " of " + str(height) + \ # " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # # # Red and Blue channel # for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # # # to display progress # t0 = time.process_time() # # for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # # # Green locations in Red rows # if (((i % 2) == 0) and ((j % 2) != 0)): # # R at Green locations in Red rows # R[i, j] = 0.125 * np.sum([.5 * G[i-2, j],\ # -1. * G[i-1, j-1], -1. * G[i-1, j+1], \ # -1. * G[i, j-2], 4. * R[i, j-1], 5. * G[i,j], 4. * R[i, j+1], -1. * G[i, j+2], \ # -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ # .5 * G[i+2, j]]) # # # B at Green locations in Red rows # B[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ # -1. * G[i-1, j-1], 4. * B[i-1, j], -1. * G[i-1, j+1], \ # .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ # -1. * G[i+1, j-1], 4. * B[i+1,j], -1. * G[i+1, j+1], \ # -1. * G[i+2, j]]) # # # Green locations in Blue rows # elif (((i % 2) != 0) and ((j % 2) == 0)): # # # R at Green locations in Blue rows # R[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ # -1. * G[i-1, j-1], 4. * R[i-1, j], -1. * G[i-1, j+1], \ # .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ # -1. * G[i+1, j-1], 4. * R[i+1, j], -1. * G[i+1, j+1], \ # -1. * G[i+2, j]]) # # # B at Green locations in Blue rows # B[i, j] = 0.125 * np.sum([.5 * G[i-2, j], \ # -1. * G [i-1, j-1], -1. * G[i-1, j+1], \ # -1. * G[i, j-2], 4. * B[i, j-1], 5. * G[i,j], 4. * B[i, j+1], -1. * G[i, j+2], \ # -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ # .5 * G[i+2, j]]) # # # R at Blue locations # elif (((i % 2) != 0) and ((j % 2) != 0)): # R[i, j] = 0.125 * np.sum([-1.5 * B[i-2, j], \ # 2. * R[i-1, j-1], 2. * R[i-1, j+1], \ # -1.5 * B[i, j-2], 6. * B[i,j], -1.5 * B[i, j+2], \ # 2. * R[i+1, j-1], 2. * R[i+1, j+1], \ # -1.5 * B[i+2, j]]) # # # B at Red locations # elif (((i % 2) == 0) and ((j % 2) == 0)): # B[i, j] = 0.125 * np.sum([-1.5 * R[i-2, j], \ # 2. * B[i-1, j-1], 2. * B[i-1, j+1], \ # -1.5 * R[i, j-2], 6. * R[i,j], -1.5 * R[i, j+2], \ # 2. * B[i+1, j-1], 2. * B[i+1, j+1], \ # -1.5 * R[i+2, j]]) # # if (timeshow): # elapsed_time = time.process_time() - t0 # print("Red/Blue: row index: " + str(i-1) + " of " + str(height) + \ # " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # # # elif (bayer_pattern == "gbrg"): # # G[::2, ::2] = raw[::2, ::2] # G[1::2, 1::2] = raw[1::2, 1::2] # R[1::2, ::2] = raw[1::2, ::2] # B[::2, 1::2] = raw[::2, 1::2] # # # Green channel # for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # # # to display progress # t0 = time.process_time() # # for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # # # G at Red location # if (((i % 2) != 0) and ((j % 2) == 0)): # G[i, j] = 0.125 * np.sum([-1. * R[i-2, j], \ # 2. * G[i-1, j], \ # -1. * R[i, j-2], 2. * G[i, j-1], 4. * R[i,j], 2. * G[i, j+1], -1. * R[i, j+2],\ # 2. * G[i+1, j], \ # -1. * R[i+2, j]]) # # G at Blue location # elif (((i % 2) == 0) and ((j % 2) != 0)): # G[i, j] = 0.125 * np.sum([-1. * B[i-2, j], \ # 2. * G[i-1, j], \ # -1. * B[i, j-2], 2. * G[i, j-1], 4. * B[i,j], 2. * G[i, j+1], -1. * B[i, j+2], \ # 2. * G[i+1, j],\ # -1. * B[i+2, j]]) # if (timeshow): # elapsed_time = time.process_time() - t0 # print("Green: row index: " + str(i-1) + " of " + str(height) + \ # " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # # # Red and Blue channel # for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # # # to display progress # t0 = time.process_time() # # for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # # # Green locations in Red rows # if (((i % 2) != 0) and ((j % 2) != 0)): # # R at Green locations in Red rows # R[i, j] = 0.125 * np.sum([.5 * G[i-2, j],\ # -1. * G[i-1, j-1], -1. * G[i-1, j+1], \ # -1. * G[i, j-2], 4. * R[i, j-1], 5. * G[i,j], 4. * R[i, j+1], -1. * G[i, j+2], \ # -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ # .5 * G[i+2, j]]) # # # B at Green locations in Red rows # B[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ # -1. * G[i-1, j-1], 4. * B[i-1, j], -1. * G[i-1, j+1], \ # .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ # -1. * G[i+1, j-1], 4. * B[i+1,j], -1. * G[i+1, j+1], \ # -1. * G[i+2, j]]) # # # Green locations in Blue rows # elif (((i % 2) == 0) and ((j % 2) == 0)): # # # R at Green locations in Blue rows # R[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ # -1. * G[i-1, j-1], 4. * R[i-1, j], -1. * G[i-1, j+1], \ # .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ # -1. * G[i+1, j-1], 4. * R[i+1, j], -1. * G[i+1, j+1], \ # -1. * G[i+2, j]]) # # # B at Green locations in Blue rows # B[i, j] = 0.125 * np.sum([.5 * G[i-2, j], \ # -1. * G [i-1, j-1], -1. * G[i-1, j+1], \ # -1. * G[i, j-2], 4. * B[i, j-1], 5. * G[i,j], 4. * B[i, j+1], -1. * G[i, j+2], \ # -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ # .5 * G[i+2, j]]) # # # R at Blue locations # elif (((i % 2) == 0) and ((j % 2) != 0)): # R[i, j] = 0.125 * np.sum([-1.5 * B[i-2, j], \ # 2. * R[i-1, j-1], 2. * R[i-1, j+1], \ # -1.5 * B[i, j-2], 6. * B[i,j], -1.5 * B[i, j+2], \ # 2. * R[i+1, j-1], 2. * R[i+1, j+1], \ # -1.5 * B[i+2, j]]) # # # B at Red locations # elif (((i % 2) != 0) and ((j % 2) == 0)): # B[i, j] = 0.125 * np.sum([-1.5 * R[i-2, j], \ # 2. * B[i-1, j-1], 2. * B[i-1, j+1], \ # -1.5 * R[i, j-2], 6. * R[i,j], -1.5 * R[i, j+2], \ # 2. * B[i+1, j-1], 2. * B[i+1, j+1], \ # -1.5 * R[i+2, j]]) # # if (timeshow): # elapsed_time = time.process_time() - t0 # print("Red/Blue: row index: " + str(i-1) + " of " + str(height) + \ # " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # # elif (bayer_pattern == "grbg"): # # G[::2, ::2] = raw[::2, ::2] # G[1::2, 1::2] = raw[1::2, 1::2] # R[::2, 1::2] = raw[::2, 1::2] # B[1::2, ::2] = raw[1::2, ::2] # # # Green channel # for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # # # to display progress # t0 = time.process_time() # # for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # # # G at Red location # if (((i % 2) == 0) and ((j % 2) != 0)): # G[i, j] = 0.125 * np.sum([-1. * R[i-2, j], \ # 2. * G[i-1, j], \ # -1. * R[i, j-2], 2. * G[i, j-1], 4. * R[i,j], 2. * G[i, j+1], -1. * R[i, j+2],\ # 2. * G[i+1, j], \ # -1. * R[i+2, j]]) # # G at Blue location # elif (((i % 2) != 0) and ((j % 2) == 0)): # G[i, j] = 0.125 * np.sum([-1. * B[i-2, j], \ # 2. * G[i-1, j], \ # -1. * B[i, j-2], 2. * G[i, j-1], 4. * B[i,j], 2. * G[i, j+1], -1. * B[i, j+2], \ # 2. * G[i+1, j],\ # -1. * B[i+2, j]]) # if (timeshow): # elapsed_time = time.process_time() - t0 # print("Green: row index: " + str(i-1) + " of " + str(height) + \ # " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # # # Red and Blue channel # for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # # # to display progress # t0 = time.process_time() # # for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # # # Green locations in Red rows # if (((i % 2) == 0) and ((j % 2) == 0)): # # R at Green locations in Red rows # R[i, j] = 0.125 * np.sum([.5 * G[i-2, j],\ # -1. * G[i-1, j-1], -1. * G[i-1, j+1], \ # -1. * G[i, j-2], 4. * R[i, j-1], 5. * G[i,j], 4. * R[i, j+1], -1. * G[i, j+2], \ # -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ # .5 * G[i+2, j]]) # # # B at Green locations in Red rows # B[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ # -1. * G[i-1, j-1], 4. * B[i-1, j], -1. * G[i-1, j+1], \ # .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ # -1. * G[i+1, j-1], 4. * B[i+1,j], -1. * G[i+1, j+1], \ # -1. * G[i+2, j]]) # # # Green locations in Blue rows # elif (((i % 2) != 0) and ((j % 2) != 0)): # # # R at Green locations in Blue rows # R[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ # -1. * G[i-1, j-1], 4. * R[i-1, j], -1. * G[i-1, j+1], \ # .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ # -1. * G[i+1, j-1], 4. * R[i+1, j], -1. * G[i+1, j+1], \ # -1. * G[i+2, j]]) # # # B at Green locations in Blue rows # B[i, j] = 0.125 * np.sum([.5 * G[i-2, j], \ # -1. * G [i-1, j-1], -1. * G[i-1, j+1], \ # -1. * G[i, j-2], 4. * B[i, j-1], 5. * G[i,j], 4. * B[i, j+1], -1. * G[i, j+2], \ # -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ # .5 * G[i+2, j]]) # # # R at Blue locations # elif (((i % 2) != 0) and ((j % 2) == 0)): # R[i, j] = 0.125 * np.sum([-1.5 * B[i-2, j], \ # 2. * R[i-1, j-1], 2. * R[i-1, j+1], \ # -1.5 * B[i, j-2], 6. * B[i,j], -1.5 * B[i, j+2], \ # 2. * R[i+1, j-1], 2. * R[i+1, j+1], \ # -1.5 * B[i+2, j]]) # # # B at Red locations # elif (((i % 2) == 0) and ((j % 2) != 0)): # B[i, j] = 0.125 * np.sum([-1.5 * R[i-2, j], \ # 2. * B[i-1, j-1], 2. * B[i-1, j+1], \ # -1.5 * R[i, j-2], 6. * R[i,j], -1.5 * R[i, j+2], \ # 2. * B[i+1, j-1], 2. * B[i+1, j+1], \ # -1.5 * R[i+2, j]]) # # if (timeshow): # elapsed_time = time.process_time() - t0 # print("Red/Blue: row index: " + str(i-1) + " of " + str(height) + \ # " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # # elif (bayer_pattern == "bggr"): # # G[::2, 1::2] = raw[::2, 1::2] # G[1::2, ::2] = raw[1::2, ::2] # R[1::2, 1::2] = raw[1::2, 1::2] # B[::2, ::2] = raw[::2, ::2] # # # Green channel # for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # # # to display progress # t0 = time.process_time() # # for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # # # G at Red location # if (((i % 2) != 0) and ((j % 2) != 0)): # G[i, j] = 0.125 * np.sum([-1. * R[i-2, j], \ # 2. * G[i-1, j], \ # -1. * R[i, j-2], 2. * G[i, j-1], 4. * R[i,j], 2. * G[i, j+1], -1. * R[i, j+2],\ # 2. * G[i+1, j], \ # -1. * R[i+2, j]]) # # G at Blue location # elif (((i % 2) == 0) and ((j % 2) == 0)): # G[i, j] = 0.125 * np.sum([-1. * B[i-2, j], \ # 2. * G[i-1, j], \ # -1. * B[i, j-2], 2. * G[i, j-1], 4. * B[i,j], 2. * G[i, j+1], -1. * B[i, j+2], \ # 2. * G[i+1, j],\ # -1. * B[i+2, j]]) # if (timeshow): # elapsed_time = time.process_time() - t0 # print("Green: row index: " + str(i-1) + " of " + str(height) + \ # " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # # # Red and Blue channel # for i in range(no_of_pixel_pad, height + no_of_pixel_pad): # # # to display progress # t0 = time.process_time() # # for j in range(no_of_pixel_pad, width + no_of_pixel_pad): # # # Green locations in Red rows # if (((i % 2) != 0) and ((j % 2) == 0)): # # R at Green locations in Red rows # R[i, j] = 0.125 * np.sum([.5 * G[i-2, j],\ # -1. * G[i-1, j-1], -1. * G[i-1, j+1], \ # -1. * G[i, j-2], 4. * R[i, j-1], 5. * G[i,j], 4. * R[i, j+1], -1. * G[i, j+2], \ # -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ # .5 * G[i+2, j]]) # # # B at Green locations in Red rows # B[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ # -1. * G[i-1, j-1], 4. * B[i-1, j], -1. * G[i-1, j+1], \ # .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ # -1. * G[i+1, j-1], 4. * B[i+1,j], -1. * G[i+1, j+1], \ # -1. * G[i+2, j]]) # # # Green locations in Blue rows # elif (((i % 2) == 0) and ((j % 2) != 0)): # # # R at Green locations in Blue rows # R[i, j] = 0.125 * np.sum([-1. * G[i-2, j], \ # -1. * G[i-1, j-1], 4. * R[i-1, j], -1. * G[i-1, j+1], \ # .5 * G[i, j-2], 5. * G[i,j], .5 * G[i, j+2], \ # -1. * G[i+1, j-1], 4. * R[i+1, j], -1. * G[i+1, j+1], \ # -1. * G[i+2, j]]) # # # B at Green locations in Blue rows # B[i, j] = 0.125 * np.sum([.5 * G[i-2, j], \ # -1. * G [i-1, j-1], -1. * G[i-1, j+1], \ # -1. * G[i, j-2], 4. * B[i, j-1], 5. * G[i,j], 4. * B[i, j+1], -1. * G[i, j+2], \ # -1. * G[i+1, j-1], -1. * G[i+1, j+1], \ # .5 * G[i+2, j]]) # # # R at Blue locations # elif (((i % 2) == 0) and ((j % 2) == 0)): # R[i, j] = 0.125 * np.sum([-1.5 * B[i-2, j], \ # 2. * R[i-1, j-1], 2. * R[i-1, j+1], \ # -1.5 * B[i, j-2], 6. * B[i,j], -1.5 * B[i, j+2], \ # 2. * R[i+1, j-1], 2. * R[i+1, j+1], \ # -1.5 * B[i+2, j]]) # # # B at Red locations # elif (((i % 2) != 0) and ((j % 2) != 0)): # B[i, j] = 0.125 * np.sum([-1.5 * R[i-2, j], \ # 2. * B[i-1, j-1], 2. * B[i-1, j+1], \ # -1.5 * R[i, j-2], 6. * R[i,j], -1.5 * R[i, j+2], \ # 2. * B[i+1, j-1], 2. * B[i+1, j+1], \ # -1.5 * R[i+2, j]]) # # if (timeshow): # elapsed_time = time.process_time() - t0 # print("Red/Blue: row index: " + str(i-1) + " of " + str(height) + \ # " | elapsed time: " + "{:.3f}".format(elapsed_time) + " seconds") # # else: # print("Invalid bayer pattern. Valid pattern can be rggb, gbrg, grbg, bggr") # return demosaic_out # This will be all zeros # # # Fill up the RGB output with interpolated values # demosaic_out[0:height, 0:width, 0] = R[no_of_pixel_pad : height + no_of_pixel_pad, \ # no_of_pixel_pad : width + no_of_pixel_pad] # demosaic_out[0:height, 0:width, 1] = G[no_of_pixel_pad : height + no_of_pixel_pad, \ # no_of_pixel_pad : width + no_of_pixel_pad] # demosaic_out[0:height, 0:width, 2] = B[no_of_pixel_pad : height + no_of_pixel_pad, \ # no_of_pixel_pad : width + no_of_pixel_pad] # # demosaic_out = np.clip(demosaic_out, clip_range[0], clip_range[1]) # return demosaic_out