Пример #1
0
    def setup_method(self, test_method):
        # Initialize arrays

        self.eps = bops.precision(dtype) * np.prod(shape)
        self.x_np_ones = bops.ones(shape, dtype, 'numpy')
        self.x_ocl_ones = bops.ones(shape, dtype, 'arrayfire')

        self.x_ocl_randn = bops.randn(shape, dtype, 'arrayfire')
        self.x_np_randn = np.asarray(self.x_ocl_randn)

        self.x_ocl_randu = bops.randu(shape, dtype, 'arrayfire')
        self.x_np_randu = np.asarray(self.x_ocl_randu)

        # Create random matricies
        self.A_ocl = bops.randn((10, 10), backend='arrayfire')
        self.A_np = np.asarray(self.A_ocl)

        self.sz = (10, 20)
        self.x_np_rect = bops.randn(self.sz, backend='numpy')
        assert bops.shape(self.x_np_rect) == self.sz

        self.x_ocl_rect = bops.randn(self.sz, backend='arrayfire')
        assert bops.shape(self.x_ocl_rect) == self.sz

        # Load object and crop to size
        brain = imageio.imread(object_file_name)
        x_0 = sp.misc.imresize(
            brain, size=image_size)[:, :, object_color_channel].astype(
                bops.getNativeDatatype(dtype, 'numpy')) / 255.

        # Convert object to desired backend
        self.x = bops.changeBackend(x_0, 'arrayfire')
Пример #2
0
    def test_shape(self):
        # Check that shape function is correct

        assert bops.shape(bops.changeBackend(self.x_ocl_rect,
                                             'numpy')) == self.sz
        assert bops.shape(bops.changeBackend(self.x_np_rect,
                                             'arrayfire')) == self.sz
Пример #3
0
    def _inverse(x, y):
        """Inverse using phase correlation."""
        # Extract two arrays to correlate
        xf_1 = array_to_register_to_f
        xf_2 = x

        # Compute normalized cross-correlation
        phasor = (conj(xf_1) * xf_2) / abs(conj(xf_1) * xf_2)
        phasor[isnan(phasor)] = 0

        # Convert phasor to delta function
        delta = F.H * phasor

        # If axes is defined, return only one axis
        if len(axes) != ndim(x) or any(
            [ax != index for (ax, index) in zip(axes, range(len(axes)))]):
            axes_not_used = [
                index for index in range(ndim(x)) if index not in axes
            ]

            delta = squeeze(sum(delta, axes=axes_not_used))

        if debug:
            import matplotlib.pyplot as plt
            plt.figure(figsize=(12, 3))
            plt.subplot(131)
            plt.imshow(abs(F.H * xf_1))
            plt.subplot(132)
            plt.imshow(abs(F.H * xf_2))
            plt.subplot(133)
            if ndim(delta) > 1:
                plt.imshow(abs(delta))
            else:
                plt.plot(abs(delta))

        # Calculate maximum and return
        if not center:
            y[:] = reshape(asarray(argmax(delta)), shape(y))
        else:
            y[:] = reshape(
                asarray(argmax(delta)) - asarray(delta.shape) / 2, shape(y))

        # Deal with negative values
        sizes = reshape(asarray([_shape[ax] for ax in axes]), shape(y))
        mask = y[:] > sizes / 2
        y[:] -= mask * sizes

        if debug:
            plt.title(
                str(np.real(np.asarray(argmax(delta))).tolist()) + ' ' +
                str(np.abs(np.asarray(y).ravel())))
Пример #4
0
    def _forward_func(self, x, y, m=False):

        # Create iterator
        iterator = lambda i: reshape(
            self.stack_operators[i] * reshape(x[:], self.N)[self.idx[
                i]:self.idx[i + 1], :], shape(y))

        # Use the map command to expose parallel nature of this problem
        if self.parallelize:

            # Make the Pool of workers
            pool = ThreadPool(self.thread_count)

            # Run parallal map
            result_parallel = pool.map(iterator, range(self.stack_op_count))

            # Unpack result
            y[:] = sum(result_parallel)

            # Close and join workers
            pool.close()
            pool.join()

        else:
            # Run serial map
            result_serial = map(iterator, range(self.stack_op_count))

            # Unpack result
            y[:] = sum(result_serial)

        if self.normalize:
            y[:] /= self.stack_op_count
Пример #5
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
Пример #6
0
    def _adjoint_func(self, x, y):
        y[:] = sum([
            reshape(
                self.stack_operators[i].H * x[self.idx[i]:self.idx[i + 1], :],
                shape(y)) for i in range(self.stack_op_count)
        ])

        if self.normalize:
            y[:] /= self.stack_op_count
Пример #7
0
    def _inverse_func(self, x, y):
        """Inverse (Used on y for non-linear operators)."""
        y[:] = sum([
            reshape(
                self.stack_operators[i].inv *
                x[self.idx[i]:self.idx[i + 1], :], shape(y))
            for i in range(self.stack_op_count)
        ])

        if self.normalize:
            y[:] /= self.stack_op_count
Пример #8
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
Пример #9
0
def VecSplit(vector, count, axis=0):
    _shape = shape(vector)
    _step = _shape[axis] // count

    if axis == 0:
        return [
            vector[index * _step:(index + 1) * _step, :]
            for index in range(count)
        ]
    elif axis == 1:
        return [
            vector[:, index * _step:(index + 1) * _step]
            for index in range(count)
        ]
Пример #10
0
    def test_crop(self):
        crop_size = [self.x_np_randn.shape[i] - 2 for i in range(len(shape))]
        assert np.sum(
            np.abs(
                bops.crop(self.x_np_randn, crop_size, crop_start=(0, 0)) -
                np.asarray(
                    bops.crop(self.x_ocl_randn, crop_size, crop_start=(
                        0, 0))))) < 1e-4

        x_full_np = bops.rand((20, 20), dtype=dtype, backend='numpy')
        x_full_ocl = bops.changeBackend(x_full_np, 'arrayfire')
        crop_size = tuple(np.asarray(bops.shape(x_full_np)) // 2)
        crop_start = (2, 2)

        x_crop_np = bops.crop(x_full_np, crop_size, crop_start=crop_start)
        x_crop_ocl = bops.crop(x_full_ocl, crop_size, crop_start=crop_start)

        assert np.sum(
            np.abs(bops.changeBackend(x_crop_ocl, 'numpy') - x_crop_np)) < 1e-4
Пример #11
0
def add(signal, type='gaussian', **kwargs):
    """ Add noise to a measurement"""
    if type == 'gaussian':
        snr = kwargs.get('snr', 1.0)
        signal_mean = yp.abs(yp.mean(signal))
        noise_gaussian = np.random.normal(0, signal_mean / snr,
                                          yp.shape(signal))
        return signal + noise_gaussian

    elif type == 'poisson':
        noise_poisson = np.random.poisson(np.real(signal))
        return signal + noise_poisson

    elif type == 'saltpepper' or type == 'saltandpepper':
        salt_pepper_ratio = kwargs.get('ratio', 0.5)
        salt_pepper_saturation = kwargs.get('saturation', 0.004)
        output = yp.changeBackend(signal, 'numpy')

        # Salt mode
        num_salt = np.ceil(salt_pepper_saturation * signal.size *
                           salt_pepper_ratio)
        coords = [
            np.random.randint(0, i - 1, int(num_salt)) for i in signal.shape
        ]
        output[tuple(coords)] = 1

        # Pepper mode
        num_pepper = np.ceil(salt_pepper_saturation * signal.size *
                             (1. - salt_pepper_ratio))
        coords = [
            np.random.randint(0, i - 1, int(num_pepper)) for i in signal.shape
        ]
        output[tuple(coords)] = 0
        return yp.cast_like(output, signal)

    elif type == 'speckle':
        noise_speckle = yp.randn(signal.shape)
        return signal + signal * noise_speckle
Пример #12
0
def registerImage(image0,
                  image1,
                  method='xc',
                  axis=None,
                  preprocess_methods=['reflect'],
                  debug=False,
                  **kwargs):

    # Perform preprocessing
    if len(preprocess_methods) > 0:
        image0, image1 = _preprocessForRegistration(image0, image1,
                                                    preprocess_methods,
                                                    **kwargs)

    # Parameter on whether we can trust our registration
    trust_ratio = 1.0

    if method in ['xc' or 'cross_correlation']:

        # Get energy ratio threshold
        trust_threshold = kwargs.get('energy_ratio_threshold', 1.5)

        # Pad arrays for optimal speed
        pad_size = tuple(
            [sp.fftpack.next_fast_len(s) for s in yp.shape(image0)])

        # Perform padding
        if pad_size is not yp.shape(image0):
            image0 = yp.pad(image0, pad_size, pad_value='edge', center=True)
            image1 = yp.pad(image1, pad_size, pad_value='edge', center=True)

        # Take F.T. of measurements
        src_freq, target_freq = yp.Ft(image0, axes=axis), yp.Ft(image1,
                                                                axes=axis)

        # Whole-pixel shift - Compute cross-correlation by an IFFT
        image_product = src_freq * yp.conj(target_freq)
        # image_product /= abs(src_freq * yp.conj(target_freq))
        cross_correlation = yp.iFt(image_product, center=False, axes=axis)

        # Take sum along axis if we're doing 1D
        if axis is not None:
            axis_to_sum = list(range(yp.ndim(image1)))
            del axis_to_sum[axis]
            cross_correlation = yp.sum(cross_correlation, axis=axis_to_sum)

        # Locate maximum
        shape = yp.shape(src_freq)
        maxima = yp.argmax(yp.abs(cross_correlation))
        midpoints = np.array([np.fix(axis_size / 2) for axis_size in shape])

        shifts = np.array(maxima, dtype=np.float64)
        shifts[shifts > midpoints] -= np.array(shape)[shifts > midpoints]

        # If its only one row or column the shift along that dimension has no
        # effect. We set to zero.
        for dim in range(yp.ndim(src_freq)):
            if shape[dim] == 1:
                shifts[dim] = 0

        # If energy ratio is too small, set all shifts to zero
        trust_metric = yp.scalar(
            yp.max(yp.abs(cross_correlation)**2) /
            yp.mean(yp.abs(cross_correlation)**2))

        # Determine if this registraition can be trusted
        trust_ratio = trust_metric / trust_threshold

    elif method == 'orb':

        # Get user-defined mean_residual_threshold if given
        trust_threshold = kwargs.get('mean_residual_threshold', 40.0)

        # Get user-defined mean_residual_threshold if given
        orb_feature_threshold = kwargs.get('orb_feature_threshold', 25)

        match_count = 0
        fast_threshold = 0.05
        while match_count < orb_feature_threshold:
            descriptor_extractor = ORB(n_keypoints=500,
                                       fast_n=9,
                                       harris_k=0.1,
                                       fast_threshold=fast_threshold)

            # Extract keypoints from first frame
            descriptor_extractor.detect_and_extract(
                np.asarray(image0).astype(np.double))
            keypoints0 = descriptor_extractor.keypoints
            descriptors0 = descriptor_extractor.descriptors

            # Extract keypoints from second frame
            descriptor_extractor.detect_and_extract(
                np.asarray(image1).astype(np.double))
            keypoints1 = descriptor_extractor.keypoints
            descriptors1 = descriptor_extractor.descriptors

            # Set match count
            match_count = min(len(keypoints0), len(keypoints1))
            fast_threshold -= 0.01

            if fast_threshold == 0:
                raise RuntimeError(
                    'Could not find any keypoints (even after shrinking fast threshold).'
                )

        # Match descriptors
        matches = match_descriptors(descriptors0,
                                    descriptors1,
                                    cross_check=True)

        # Filter descriptors to axes (if provided)
        if axis is not None:
            matches_filtered = []
            for (index_0, index_1) in matches:
                point_0 = keypoints0[index_0, :]
                point_1 = keypoints1[index_1, :]
                unit_vec = point_0 - point_1
                unit_vec /= np.linalg.norm(unit_vec)

                if yp.abs(unit_vec[axis]) > 0.99:
                    matches_filtered.append((index_0, index_1))

            matches_filtered = np.asarray(matches_filtered)
        else:
            matches_filtered = matches

        # Robustly estimate affine transform model with RANSAC
        model_robust, inliers = ransac((keypoints0[matches_filtered[:, 0]],
                                        keypoints1[matches_filtered[:, 1]]),
                                       EuclideanTransform,
                                       min_samples=3,
                                       residual_threshold=2,
                                       max_trials=100)

        # Note that model_robust has a translation property, but this doesn't
        # seem to be as numerically stable as simply averaging the difference
        # between the coordinates along the desired axis.

        # Apply match filter
        matches_filtered = matches_filtered[inliers, :]

        # Process keypoints
        if yp.shape(matches_filtered)[0] > 0:

            # Compute shifts
            difference = keypoints0[matches_filtered[:, 0]] - keypoints1[
                matches_filtered[:, 1]]
            shifts = (yp.sum(difference, axis=0) / yp.shape(difference)[0])
            shifts = np.round(shifts[0])

            # Filter to axis mask
            if axis is not None:
                _shifts = [0, 0]
                _shifts[axis] = shifts[axis]
                shifts = _shifts

            # Calculate residuals
            residuals = yp.sqrt(
                yp.sum(
                    yp.abs(keypoints0[matches_filtered[:, 0]] +
                           np.asarray(shifts) -
                           keypoints1[matches_filtered[:, 1]])**2))

            # Define a trust metric
            trust_metric = residuals / yp.shape(
                keypoints0[matches_filtered[:, 0]])[0]

            # Determine if this registration can be trusted
            trust_ratio = 1 / (trust_metric / trust_threshold)
            print('===')
            print(trust_ratio)
            print(trust_threshold)
            print(trust_metric)
            print(shifts)
        else:
            trust_metric = 1e10
            trust_ratio = 0.0
            shifts = np.asarray([0, 0])

    elif method == 'optimize':

        # Create Operators
        L2 = ops.L2Norm(yp.shape(image0), dtype='complex64')
        R = ops.PhaseRamp(yp.shape(image0), dtype='complex64')
        REAL = ops.RealFilter((2, 1), dtype='complex64')

        # Take Fourier Transforms of images
        image0_f, image1_f = yp.astype(yp.Ft(image0), 'complex64'), yp.astype(
            yp.Ft(image1), 'complex64')

        # Diagonalize one of the images
        D = ops.Diagonalize(image0_f)

        # Form objective
        objective = L2 * (D * R * REAL - image1_f)

        # Solve objective
        solver = ops.solvers.GradientDescent(objective)
        shifts = solver.solve(iteration_count=1000, step_size=1e-8)

        # Convert to numpy array, take real part, and round.
        shifts = yp.round(yp.real(yp.asbackend(shifts, 'numpy')))

        # Flip shift axes (x,y to y, x)
        shifts = np.fliplr(shifts)

        # TODO: Trust metric and trust_threshold
        trust_threshold = 1
        trust_ratio = 1.0

    else:
        raise ValueError('Invalid Registration Method %s' % method)

    # Mark whether or not this measurement is of good quality
    if not trust_ratio > 1:
        if debug:
            print('Ignoring shift with trust metric %g (threshold is %g)' %
                  (trust_metric, trust_threshold))
        shifts = yp.zeros_like(np.asarray(shifts)).tolist()

    # Show debugging figures if requested
    if debug:
        import matplotlib.pyplot as plt
        plt.figure(figsize=(6, 5))
        plt.subplot(131)
        plt.imshow(yp.abs(image0))
        plt.axis('off')
        plt.subplot(132)
        plt.imshow(yp.abs(image1))
        plt.title('Trust ratio: %g' % (trust_ratio))
        plt.axis('off')
        plt.subplot(133)
        if method in ['xc' or 'cross_correlation']:
            if axis is not None:
                plt.plot(yp.abs(yp.squeeze(cross_correlation)))
            else:
                plt.imshow(yp.abs(yp.fftshift(cross_correlation)))
        else:
            plot_matches(plt.gca(), yp.real(image0), yp.real(image1),
                         keypoints0, keypoints1, matches_filtered)
        plt.title(str(shifts))
        plt.axis('off')

    # Return
    return shifts, trust_ratio
Пример #13
0
def register_translation(src_image,
                         target_image,
                         upsample_factor=1,
                         energy_ratio_threshold=2,
                         space="real"):
    """
    Efficient subpixel image translation registration by cross-correlation.
    This code gives the same precision as the FFT upsampled cross-correlation
    in a fraction of the computation time and with reduced memory requirements.
    It obtains an initial estimate of the cross-correlation peak by an FFT and
    then refines the shift estimation by upsampling the DFT only in a small
    neighborhood of that estimate by means of a matrix-multiply DFT.
    Parameters
    ----------
    src_image : ndarray
        Reference image.
    target_image : ndarray
        Image to register.  Must be same dimensionality as ``src_image``.
    upsample_factor : int, optional
        Upsampling factor. Images will be registered to within
        ``1 / upsample_factor`` of a pixel. For example
        ``upsample_factor == 20`` means the images will be registered
        within 1/20th of a pixel.  Default is 1 (no upsampling)
    space : string, one of "real" or "fourier", optional
        Defines how the algorithm interprets input data.  "real" means data
        will be FFT'd to compute the correlation, while "fourier" data will
        bypass FFT of input data.  Case insensitive.
    return_error : bool, optional
        Returns error and phase difference if on,
        otherwise only shifts are returned
    Returns
    -------
    shifts : ndarray
        Shift vector (in pixels) required to register ``target_image`` with
        ``src_image``.  Axis ordering is consistent with numpy (e.g. Z, Y, X)
    error : float
        Translation invariant normalized RMS error between ``src_image`` and
        ``target_image``.
    phasediff : float
        Global phase difference between the two images (should be
        zero if images are non-negative).
    References
    ----------
    .. [1] Manuel Guizar-Sicairos, Samuel T. Thurman, and James R. Fienup,
           "Efficient subpixel image registration algorithms,"
           Optics Letters 33, 156-158 (2008). :DOI:`10.1364/OL.33.000156`
    .. [2] James R. Fienup, "Invariant error metrics for image reconstruction"
           Optics Letters 36, 8352-8357 (1997). :DOI:`10.1364/AO.36.008352`
    """
    # images must be the same shape
    if yp.shape(src_image) != yp.shape(target_image):
        raise ValueError("Error: images must be same size for "
                         "register_translation")

    # only 2D data makes sense right now
    if yp.ndim(src_image) > 3 and upsample_factor > 1:
        raise NotImplementedError("Error: register_translation only supports "
                                  "subpixel registration for 2D and 3D images")

    # assume complex data is already in Fourier space
    if space.lower() == 'fourier':
        src_freq = src_image
        target_freq = target_image
    # real data needs to be fft'd.
    elif space.lower() == 'real':
        src_freq = yp.Ft(src_image)
        target_freq = yp.Ft(target_image)
    else:
        raise ValueError("Error: register_translation only knows the \"real\" "
                         "and \"fourier\" values for the ``space`` argument.")

    # Whole-pixel shift - Compute cross-correlation by an IFFT
    shape = yp.shape(src_freq)
    image_product = src_freq * yp.conj(target_freq)
    cross_correlation = yp.iFt(image_product, center=False)

    # Locate maximum
    maxima = yp.argmax(yp.abs(cross_correlation))
    midpoints = np.array([np.fix(axis_size / 2) for axis_size in shape])

    shifts = np.array(maxima, dtype=np.float64)
    shifts[shifts > midpoints] -= np.array(shape)[shifts > midpoints]

    # if upsample_factor > 1:
    #     # Initial shift estimate in upsampled grid
    #     shifts = np.round(shifts * upsample_factor) / upsample_factor
    #     upsampled_region_size = np.ceil(upsample_factor * 1.5)
    #     # Center of output array at dftshift + 1
    #     dftshift = np.fix(upsampled_region_size / 2.0)
    #     upsample_factor = np.array(upsample_factor, dtype=np.float64)
    #     normalization = (src_freq.size * upsample_factor ** 2)
    #     # Matrix multiply DFT around the current shift estimate
    #     sample_region_offset = dftshift - shifts*upsample_factor
    #     cross_correlation = _upsampled_dft(image_product.conj(),
    #                                        upsampled_region_size,
    #                                        upsample_factor,
    #                                        sample_region_offset).conj()
    #     cross_correlation /= normalization
    #     # Locate maximum and map back to original pixel grid
    #     maxima = np.array(np.unravel_index(
    #                           np.argmax(np.abs(cross_correlation)),
    #                           cross_correlation.shape),
    #                       dtype=np.float64)
    #     maxima -= dftshift
    #
    #     shifts = shifts + maxima / upsample_factor

    # If its only one row or column the shift along that dimension has no
    # effect. We set to zero.
    for dim in range(yp.ndim(src_freq)):
        if shape[dim] == 1:
            shifts[dim] = 0

    # If energy ratio is too small, set all shifts to zero
    energy_ratio = yp.max(yp.abs(cross_correlation)**2) / yp.sum(
        yp.abs(cross_correlation)**2) * yp.prod(yp.shape(cross_correlation))
    if energy_ratio < energy_ratio_threshold:
        print('Ignoring shift with energy ratio %g (threshold is %g)' %
              (energy_ratio, energy_ratio_threshold))
        shifts = yp.zeros_like(shifts)

    return shifts
Пример #14
0
def _preprocessForRegistration(image0, image1, methods=['pad'], **kwargs):

    # Ensure methods argument is a list
    if type(methods) not in (list, tuple):
        methods = [methods]

    # Perform 'reflection', which pads an object with antisymmetric copies of itself
    if 'pad' in methods:

        # Get pad factor
        pad_factor = kwargs.get('pad_factor', 2)

        # Get pad value
        pad_type = kwargs.get('pad_type', 'reflect')

        # Generate pad operator which pads the object to 2x it's size
        pad_size = [
            sp.fftpack.next_fast_len(int(pad_factor * s))
            for s in yp.shape(image0)
        ]

        # Perform padding
        image0 = yp.pad(image0, pad_size, pad_value=pad_type, center=True)
        image1 = yp.pad(image1, pad_size, pad_value=pad_type, center=True)

    # Normalize to the range [0,1] (Always do if we're filtering)
    if 'normalize' in methods:
        image0 = filters._normalize(image0)
        image1 = filters._normalize(image1)

    # Sobel filtering
    if 'sobel' in methods:
        image0 = filters.sobel(image0)
        image1 = filters.sobel(image1)

    # Gaussian filtering
    if 'gaussian' in methods:
        image0 = filters.gaussian(image0, sigma=1)
        image1 = filters.gaussian(image1, sigma=1)

    # High-pass filtering (using gaussian)
    if 'highpass' in methods:
        image0 = filters.gaussian(image0, sigma=2) - filters.gaussian(image0,
                                                                      sigma=4)
        image1 = filters.gaussian(image1, sigma=2) - filters.gaussian(image1,
                                                                      sigma=4)

    # Roberts filtering
    if 'roberts' in methods:
        image0 = filters.roberts(image0)
        image1 = filters.roberts(image1)

    # Scharr filtering
    if 'scharr' in methods:
        image0 = filters.scharr(image0)
        image1 = filters.scharr(image1)

    # Prewitt filtering
    if 'prewitt' in methods:
        image0 = filters.prewitt(image0)
        image1 = filters.prewitt(image1)

    # Canny filtering
    if 'canny' in methods:
        image0 = filters.canny(image0,
                               sigma=kwargs.get('sigma', 1),
                               low_threshold=kwargs.get('low_threshold', 0.01),
                               high_threshold=kwargs.get(
                                   'high_threshold', 0.05))
        image1 = filters.canny(image1,
                               sigma=kwargs.get('sigma', 1),
                               low_threshold=kwargs.get('low_threshold', 0.01),
                               high_threshold=kwargs.get(
                                   'high_threshold', 0.05))

    return image0, image1
Пример #15
0
def Registration(array_to_register_to,
                 dtype=None,
                 backend=None,
                 label='R',
                 inner_operator=None,
                 center=False,
                 axes=None,
                 debug=False):
    """Registeration operator for input x and operator input."""
    # Configure backend and datatype
    backend = backend if backend is not None else config.default_backend
    dtype = dtype if dtype is not None else config.default_dtype
    _shape = shape(
        array_to_register_to) if inner_operator is None else inner_operator.M
    axes = axes if axes is not None else tuple(
        range(ndim(array_to_register_to)))

    # Create sub-operators
    PR = PhaseRamp(_shape, dtype, backend, center=center, axes=axes)
    F = FourierTransform(_shape, dtype, backend, center=center, axes=axes)
    X = Diagonalize(-1 * array_to_register_to,
                    dtype,
                    backend,
                    inner_operator=F * inner_operator,
                    label='x')
    _R = X * PR

    # Compute Fourier Transform of array to register to
    array_to_register_to_f = F * array_to_register_to

    # Define inverse
    def _inverse(x, y):
        """Inverse using phase correlation."""
        # Extract two arrays to correlate
        xf_1 = array_to_register_to_f
        xf_2 = x

        # Compute normalized cross-correlation
        phasor = (conj(xf_1) * xf_2) / abs(conj(xf_1) * xf_2)
        phasor[isnan(phasor)] = 0

        # Convert phasor to delta function
        delta = F.H * phasor

        # If axes is defined, return only one axis
        if len(axes) != ndim(x) or any(
            [ax != index for (ax, index) in zip(axes, range(len(axes)))]):
            axes_not_used = [
                index for index in range(ndim(x)) if index not in axes
            ]

            delta = squeeze(sum(delta, axes=axes_not_used))

        if debug:
            import matplotlib.pyplot as plt
            plt.figure(figsize=(12, 3))
            plt.subplot(131)
            plt.imshow(abs(F.H * xf_1))
            plt.subplot(132)
            plt.imshow(abs(F.H * xf_2))
            plt.subplot(133)
            if ndim(delta) > 1:
                plt.imshow(abs(delta))
            else:
                plt.plot(abs(delta))

        # Calculate maximum and return
        if not center:
            y[:] = reshape(asarray(argmax(delta)), shape(y))
        else:
            y[:] = reshape(
                asarray(argmax(delta)) - asarray(delta.shape) / 2, shape(y))

        # Deal with negative values
        sizes = reshape(asarray([_shape[ax] for ax in axes]), shape(y))
        mask = y[:] > sizes / 2
        y[:] -= mask * sizes

        if debug:
            plt.title(
                str(np.real(np.asarray(argmax(delta))).tolist()) + ' ' +
                str(np.abs(np.asarray(y).ravel())))

    # Define operator name
    repr_str = 'Registration'

    # Create a new operator from phase ramp
    R = Operator(
        _R.shape,
        _R.dtype,
        _R.backend,
        repr_str=repr_str,
        label=label,
        forward=_R.forward,  # Don't provide adjoint, implies nonlinear
        gradient=_R._gradient,
        inverse=_inverse,
        cost=_R.cost,
        convex=_R.convex,
        smooth=True,
        set_arguments_function=X._set_argument_function,
        get_arguments_function=X._get_argument_function,
        inverse_regularizer=_R.inverse_regularizer,
        repr_latex=_R.repr_latex)

    def show_xc(x, figsize=(11, 3)):
        xf_1 = F * _R.arguments[0]
        xf_2 = F * x

        # Compute normalized cross-correlation
        phasor = (conj(xf_1) * xf_2) / abs(conj(xf_1) * xf_2)

        import matplotlib.pyplot as plt
        import llops as yp

        plt.figure(figsize=figsize)
        plt.subplot(121)
        plt.imshow(yp.angle(phasor))
        plt.title('Phase of Frequency domain')
        plt.subplot(122)
        plt.imshow(yp.abs(yp.iFt(phasor)))
        plt.title('Amplitude of Object domain')

    # Return operator with prepended inverse Fourier Transform
    op = F.H * R

    # Set the show_xc in this operator, since it is removed by multiplication
    op.show_xc = show_xc

    # Set the set and get argument functions
    op._setArgumentsFunction = R._set_argument_function
    op._getArgumentsFunction = R._get_argument_function

    # Return result
    return op
Пример #16
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
Пример #17
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