def test_operator_norm_l2(self): L2 = ops.L2Norm(image_size[0] * image_size[1], dtype=global_dtype, backend=global_backend) # Check forward operator assert np.sum(np.abs(L2 * yp.vec(self.x) - 0.5 * yp.norm(yp.vec(self.x)) ** 2)) < eps, '%f' % np.sum(np.abs(L2 * yp.vec(self.x) - 0.5 * yp.norm(yp.vec(self.x)) ** 2)) # Check gradient L2.gradient_check()
def test_mechanical_operator_vector_sum(self): ''' Mechanical test of an operator-vector sum ''' # Test sum operations here A_s = self.A + self.y # Forward operator assert np.sum(np.abs(A_s * yp.vec(self.x) - (self.A * yp.vec(self.x) + self.y))) < eps # Adjoint assert np.sum(np.abs(A_s.H(yp.vec(self.x)) - self.A.H(yp.vec(self.x)))) < eps # Gradient Numerical Check self.A.gradient_check()
def test_operator_matrix_multiply(self): matrix_size = (10,10) m = yp.rand(matrix_size, global_dtype, global_backend) xm = yp.rand(matrix_size[1], global_dtype, global_backend) M = ops.MatrixMultiply(m) # Check Forward operator assert yp.sumb(yp.abs(yp.vec(yp.changeBackend(M * xm, 'numpy')) - yp.vec(yp.changeBackend(m, 'numpy').dot(yp.changeBackend(xm, 'numpy'))))) < eps, "%f" % yp.sumb(yp.abs(yp.changeBackend(M * xm, 'numpy') - yp.changeBackend(m, 'numpy').dot(yp.changeBackend(xm, 'numpy'))[:, np.newaxis])) # Check Adjoint assert yp.sumb(yp.abs(yp.vec(yp.changeBackend(M.H * xm, 'numpy')) - yp.vec(np.conj(yp.changeBackend(m, 'numpy').T).dot(yp.changeBackend(xm, 'numpy'))))) < eps, "%f" % yp.sumb(yp.abs(yp.changeBackend(M.H * xm, 'numpy') - np.conj(yp.changeBackend(m, 'numpy').T).dot(yp.changeBackend(xm, 'numpy'))[:, np.newaxis])) # Check gradient M.gradient_check()
def test_mechanical_gradient_3(self): ''' Mechanical test for an inner linear operator with outer non-linear operator ''' L2 = ops.L2Norm(image_size[0] * image_size[1], dtype=global_dtype, backend=global_backend) # Data difference function Delta = (self.A - self.y) # Objective Function O = L2 * Delta # Check forward operator assert np.all(np.abs(O(yp.vec(self.x)) - 0.5 * np.sum(np.abs(Delta * yp.vec(self.x)) ** 2)) < eps) # Check gradient operator (adjoint form) O.gradient_check()
def test_operator_convolution_circular(self): ''' Circular Convolution Operator ''' # Generate circular convolution operator C = ops.Convolution(self.h) # Test forward operator conv2 = lambda x, h: yp.changeBackend(np.fft.ifftshift((np.fft.ifft2(np.fft.fft2(x, axes=(0,1), norm='ortho') * np.fft.fft2(h, axes=(0,1), norm='ortho'), axes=(0,1), norm='ortho')), axes=(0,1)).astype(yp.getNativeDatatype(global_dtype, 'numpy')), global_backend) x_np = yp.changeBackend(self.x, 'numpy') h_np = yp.changeBackend(self.h, 'numpy') assert np.sum(np.abs(yp.reshape(C * yp.vec(self.x), image_size) - conv2(x_np, h_np)) ** 2) < 1e-3, \ 'SSE (%.4e) is greater than tolerance (%.4e)' % ((np.sum(np.abs((C * yp.vec(self.x)).reshape(image_size)-conv2(x,h)))), eps) # Check gradient C.gradient_check()
def test_operator_wavelet(self): ''' Wavelet Transform Operator ''' import pywt wavelet_list = ['db1', 'haar', 'rbio1.1', 'bior1.1', 'bior4.4', 'sym12'] for wavelet_test in wavelet_list: # Wavelet Transform W = ops.WaveletTransform(image_size, wavelet_type=wavelet_test, use_cycle_spinning=False) # Check forward operation coeffs = pywt.wavedecn(self.x, wavelet=wavelet_test) x_wavelet, coeff_slices = pywt.coeffs_to_array(coeffs) assert yp.sumb(yp.abs(yp.changeBackend(W * self.x, 'numpy') - x_wavelet)) < eps, "Difference %.6e" # Check inverse operation coeffs_from_arr = pywt.array_to_coeffs(x_wavelet, coeff_slices) cam_recon = pywt.waverecn(coeffs_from_arr, wavelet=wavelet_test) assert yp.sumb(yp.abs(W.H * W * self.x - self.x)) < 1e-2 # Ensure that the wavelet transform isn't just identity (weird bug) if W.shape[1] is yp.size(self.x): assert yp.sumb(yp.abs(W * yp.vec(self.x) - yp.vec(self.x))) > 1e-2, "%s" % wavelet_test
def test_operator_stacking_nonlinear(self): # Create list of operators op_list_nonlinear = [ ops.FourierTransform(image_size), ops.Identity(image_size), ops.Exponential(image_size) ] # Horizontally stacked operators H_nl = ops.Hstack(op_list_nonlinear) # Vertically stack x for forward operator x3 = yp.changeBackend(np.vstack((self.x, self.x, self.x)), global_backend) # Check forward operation y2 = yp.zeros(op_list_nonlinear[0].shape[0], op_list_nonlinear[0].dtype, op_list_nonlinear[0].backend) for op in op_list_nonlinear: y2 = y2 + yp.vec(op * self.x) assert yp.sumb(yp.abs(yp.vec(H_nl(x3)) - y2)) < eps, "%.4e" % yp.sumb(yp.abs(yp.vec(H_nl(x3)) - y2)) # Check gradient H_nl.gradient_check() # Create vertically stacked operator V_nl = ops.Vstack(op_list_nonlinear) # Check forward operator y3 = np.empty((0,image_size[1]), dtype=yp.getNativeDatatype(global_dtype, 'numpy')) for index, op in enumerate(op_list_nonlinear): y3 = np.append(y3, (op * self.x), axis=0) y3 = yp.changeBackend(y3, global_backend) assert yp.sumb(yp.abs(V_nl * self.x - y3)) < eps, "%.4e" % yp.sumb(yp.abs(V_nl * self.x - y3)) # Check gradient V_nl.gradient_check()
def test_mechanical_gradient_4(self): ''' Mechanical test for an outer non-linear operator with outer non-linear operator and a linear operator in-between''' shift_true = np.asarray((-5,3)).astype(yp.getNativeDatatype(global_dtype, 'numpy')) # Inner non-linear operator, linear operator in middle, and norm on outside F = ops.FourierTransform(image_size, dtype=global_dtype, backend=global_backend) D_object = ops.Diagonalize((F * yp.vec(self.x)).reshape(image_size), label='D_{object}', dtype=global_dtype, backend=global_backend) R = ops.PhaseRamp(image_size, dtype=global_dtype, backend=global_backend) A_shift = F.H * D_object * R y = A_shift(shift_true) L2 = ops.L2Norm(image_size[0] * image_size[1], dtype=global_dtype, backend=global_backend) objective = L2 * (A_shift - self.y) # Check gradient objective.gradient_check()
def test_operator_norm_l1(self): L1 = ops.L1Norm(image_size[0] * image_size[1], dtype=global_dtype) # Forward operator assert np.sum(np.abs(L1 * yp.vec(self.x) - np.sum(np.abs(yp.vec(self.x))))) < eps
def demosaic(frame, order='grbg', bayer_coupling_matrix=None, debug=False, white_balance=False): # bayer_coupling_matrix = None # bgrg: cells very green # rggb: slight gteen tint """Demosaic a frame""" frame_out = yp.zeros((int(yp.shape(frame)[0] / 2), int(yp.shape(frame)[1] / 2), 3), yp.getDatatype(frame), yp.getBackend(frame)) if bayer_coupling_matrix is not None: frame_vec = yp.zeros((4, int(yp.shape(frame)[0] * yp.shape(frame)[1] / 4)), yp.getDatatype(frame), yp.getBackend(frame)) # Cast bayer coupling matrix bayer_coupling_matrix = yp.cast(bayer_coupling_matrix, yp.getDatatype(frame), yp.getBackend(frame)) # Define frame vector for bayer_pattern_index in range(4): pixel_offsets = (0, 0) if bayer_pattern_index == 3: img_sub = frame[pixel_offsets[0]::2, pixel_offsets[1]::2] elif bayer_pattern_index == 1: img_sub = frame[pixel_offsets[0]::2, pixel_offsets[1] + 1::2] elif bayer_pattern_index == 2: img_sub = frame[pixel_offsets[0] + 1::2, pixel_offsets[1]::2] elif bayer_pattern_index == 0: img_sub = frame[pixel_offsets[0] + 1::2, pixel_offsets[1] + 1::2] frame_vec[bayer_pattern_index, :] = yp.dcopy(yp.vec(img_sub)) if debug: print("Channel %d mean is %g" % (bayer_pattern_index, yp.scalar(yp.real(yp.sum(img_sub))))) # Perform demosaic using least squares result = yp.linalg.lstsq(bayer_coupling_matrix, frame_vec) result -= yp.amin(result) result /= yp.amax(result) for channel in range(3): values = result[channel] frame_out[:, :, channel] = yp.reshape(values, ((yp.shape(frame_out)[0], yp.shape(frame_out)[1]))) if white_balance: frame_out[:, :, channel] -= yp.amin(frame_out[:, :, channel]) frame_out[:, :, channel] /= yp.amax(frame_out[:, :, channel]) return frame_out else: frame_out = yp.zeros((int(yp.shape(frame)[0] / 2), int(yp.shape(frame)[1] / 2), 3), dtype=yp.getDatatype(frame), backend=yp.getBackend(frame)) # Get color order from order variable b_index = order.find('b') r_index = order.find('r') g1_index = order.find('g') # Get g2 from intersection of sets g2_index = set(list(range(4))).difference({b_index, r_index, g1_index}).pop() # +-----+-----+ # | 0 | 1 | # +-----+-----| # | 2 | 3 | # +-----+-----| if debug: import matplotlib.pyplot as plt plt.figure() plt.imshow(frame[:12, :12]) r_start = (int(r_index in [2, 3]), int(r_index in [1, 3])) g1_start = (int(g1_index in [2, 3]), int(g1_index in [1, 3])) g2_start = (int(g2_index in [2, 3]), int(g2_index in [1, 3])) b_start = (int(b_index in [2, 3]), int(b_index in [1, 3])) frame_out[:, :, 0] = frame[r_start[0]::2, r_start[1]::2] frame_out[:, :, 1] = (frame[g1_start[0]::2, g1_start[1]::2] + frame[g2_start[0]::2, g2_start[1]::2]) / 2.0 frame_out[:, :, 2] = frame[b_start[0]::2, b_start[1]::2] # normalize frame_out /= yp.max(frame_out) # Perform white balancing if desired if white_balance: clims = [] for channel in range(3): clims.append(yp.max(frame_out[:, :, channel])) frame_out[:, :, channel] /= yp.max(frame_out[:, :, channel]) # Return frame return frame_out