Пример #1
0
def affineHomographyBlocks(coordinate_list):
    """Generate affine homography blocks which can be used to solve for homography coordinates."""
    # Store dtype and backend
    dtype = yp.getDatatype(coordinate_list)
    backend = yp.getBackend(coordinate_list)

    # Convert coordinates to numpy array
    coordinate_list = yp.asarray(yp.real(coordinate_list),
                                 dtype='float32',
                                 backend='numpy')

    # Ensure coordinate_list is a list of lists
    if yp.ndim(coordinate_list) == 1:
        coordinate_list = np.asarray([coordinate_list])

    # Determine the number of elements in a coordinate
    axis_count = yp.shape(coordinate_list)[1]

    # Loop over positions and concatenate to array
    coordinate_blocks = []
    for coordinate in coordinate_list:
        block = np.append(coordinate, 1)
        coordinate_blocks.append(np.kron(np.eye(len(coordinate)), block))

    # Convert to initial datatype and backend
    coordinate_blocks = yp.asarray(np.concatenate(coordinate_blocks), dtype,
                                   backend)

    return coordinate_blocks
Пример #2
0
def L2Sequential(A_list, y_list, reg=None):
    """ L2 objective function (sequential solver) """

    objective_function_list = []
    for index in range(len(A_list)):

        # Assign local operator and measurement
        A, y = A_list[index], y_list[index]

        # Check backend and datatype
        assert A.backend == getBackend(y)
        assert A.dtype == getDatatype(y)

        # Form local objective function and append
        objective_function_list.append(L2(A, y, reg))

    # Return stacked list
    return Vstack(objective_function_list)
Пример #3
0
def VecStack(vector_list, axis=0):
    """ This is a helper function to stack vectors """

    # Determine output size
    single_vector_shape = [
        max([shape(vector)[0] for vector in vector_list]),
        max([shape(vector)[1] for vector in vector_list])
    ]
    vector_shape = dcopy(single_vector_shape)
    vector_shape[axis] *= len(vector_list)

    # Allocate memory
    vector_full = zeros(vector_shape, getDatatype(vector_list[0]),
                        getBackend(vector_list[0]))

    # Assign vector elements to the output
    for index, vector in enumerate(vector_list):
        vector_full[index * single_vector_shape[0]:(index + 1) *
                    single_vector_shape[0], :] = pad(vector,
                                                     single_vector_shape)

    # Return
    return vector_full
Пример #4
0
def L2(A, y, reg=None):
    """ L2 objective function (global solver)"""

    #  assert A.M == shape(y), "Operator first dimension %d is not operator shape %s" % (A.shape[0], shape(y))
    assert A.backend == getBackend(y)
    assert A.dtype == getDatatype(y)

    # Define objective function
    L2_op = L2Norm(A.M, A.dtype, A.backend)
    objective_data_term = L2_op * (A - y)

    # Add L2 regularization if desired
    if reg is not None:
        # Create full objective (for gradient descent)
        objective = objective_data_term + reg * L2Norm(A.shape[1], A.dtype,
                                                       A.backend)

        # Add regularization to data term (only used for inverse)
        objective_data_term.inverse_regularizer = reg
    else:
        objective = objective_data_term

    # Simply return this operator
    return _addInvertFunction(objective)
Пример #5
0
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
Пример #6
0
def ConvolutionOld(kernel,
                   dtype=None,
                   backend=None,
                   normalize=False,
                   mode='circular',
                   label='C',
                   pad_value='mean',
                   pad_size=None,
                   fft_backend=None,
                   inverse_regularizer=0,
                   center=False,
                   inner_operator=None,
                   force_full_convolution=False):
    """Convolution linear operator"""

    # Get temporary kernel to account for inner_operator size
    _kernel = kernel if inner_operator is None else inner_operator * kernel

    # Check number of dimensions
    N = _kernel.shape
    dim_count = len(N)
    assert dim_count == ndim(_kernel)

    # Get kernel backend
    if backend is None:
        backend = getBackend(kernel)
    else:
        # Convert kernel to provided backend
        kernel = asbackend(kernel, backend)

    # Get kernel dtype
    if dtype is None:
        dtype = getDatatype(kernel)
    else:
        kernel = astype(kernel, dtype)

    # Determine if the kernel is a shifted delta function - if so, return a
    # shift operator masked as a convolution
    position_list = tuple([
        tuple(np.asarray(pos) - np.asarray(shape(_kernel)) // 2)
        for pos in where(_kernel != 0.0)
    ])
    mode = 'discrete' if len(
        position_list) == 1 and not force_full_convolution else mode

    # Discrete convolution
    if mode == 'discrete':
        # Create shift operator, or identity operator if there is no shift.
        if all([pos == 0.0 for pos in position_list[0]]):
            op = Identity(N)
        else:
            op = Shift(N, position_list[0])

        loc = where(_kernel != 0)[0]

        # If the kernel is not binary, normalize to the correct value
        if scalar(_kernel[loc[0], loc[1]]) != 1.0:
            op *= scalar(_kernel[loc[0], loc[1]])

        # Update label to indicate this is a shift-based convolution
        label += '_{shift}'

        # Normalize if desired
        if normalize:
            op *= 1 / np.sqrt(np.size(kernel))

    elif mode in ['windowed', 'circular']:
        # The only difference between circular and non-circular convolution is
        # the pad size. We'll define this first, then define the convolution in
        # a common framework.

        if mode == 'circular':

            # Pad kernel to effecient size
            N_pad = list(N)
            for ind, d in enumerate(N):
                if next_fast_len(d) != d:
                    N_pad[ind] = next_fast_len(d)

            crop_start = [0] * len(N_pad)

        elif mode == 'windowed':
            if pad_size is None:
                # Determine support of kernel
                kernel_support_roi = boundingBox(kernel, return_roi=True)
                N_pad_raw = (np.asarray(N) +
                             np.asarray(kernel_support_roi.size).tolist())
                N_pad = [next_fast_len(sz) for sz in N_pad_raw]

                # Create pad and crop operator
                crop_start = [(N_pad[dim] - N[dim]) // 2
                              for dim in range(len(N))]
            else:
                if type(pad_size) not in (list, tuple, np.ndarray):
                    pad_size = (pad_size, pad_size)
                N_pad = (pad_size[0] + N[0], pad_size[1] + N[1])

                crop_start = None

        # Create pad operator
        P = Pad(N,
                N_pad,
                pad_value=pad_value,
                pad_start=crop_start,
                backend=backend,
                dtype=dtype)

        # Create F.T. operator
        F = FourierTransform(N_pad,
                             dtype=dtype,
                             backend=backend,
                             normalize=normalize,
                             fft_backend=fft_backend,
                             pad=False,
                             center=center)

        # Optionally create FFTShift operator
        if not center:
            FFTS = FFTShift(N_pad, dtype=dtype, backend=backend)
        else:
            FFTS = Identity(N_pad, dtype=dtype, backend=backend)

        # Diagonalize kernel
        K = Diagonalize(kernel,
                        inner_operator=F * FFTS * P,
                        inverse_regularizer=inverse_regularizer,
                        label=label)

        # Generate composite op
        op = P.H * F.H * K * F * P

        # Define inversion function
        def _inverse(self, x, y):
            # Get current kernel
            kernel_f = F * FFTS * P * kernel

            # Invert and create operator
            kernel_f_inv = conj(kernel_f) / (abs(kernel_f)**2 +
                                             self.inverse_regularizer)
            K_inverse = Diagonalize(kernel_f_inv,
                                    backend=backend,
                                    dtype=dtype,
                                    label=label)

            # Set output
            y[:] = P.H * F.H * K_inverse * F * P * x

        # Set inverse function
        op._inverse = types.MethodType(_inverse, op)

    else:
        raise ValueError(
            'Convolution mode %s is not defined! Valid options are "circular" and "windowed"'
            % mode)

    # Append type to label
    if '_' not in label:
        label += '_{' + mode + '}'

    # Set label
    op.label = label

    # Set inverse_regularizer
    op.inverse_regularizer = inverse_regularizer

    # Set latex to be just label
    def repr_latex(latex_input=None):
        if latex_input is None:
            return op.label
        else:
            return op.label + ' \\times ' + latex_input

    op.repr_latex = repr_latex

    return op