Пример #1
0
    def test_operator_crop_non_centered(self):
        ''' Non-centered Crop Operator '''
        # Generate Crop Operator
        crop_size = (image_size[0] // 2, image_size[1] // 2)
        crop_start = (6, 6)
        CR = ops.Crop(image_size, crop_size, pad_value=0,  dtype=global_dtype, backend=global_backend, crop_start=crop_start)

        # Check forward operator
        y_1 = yp.changeBackend(CR * self.x, 'numpy')
        y_2 = yp.changeBackend(yp.crop(self.x, crop_size, crop_start), 'numpy')
        assert yp.sumb(yp.abs(y_1 - y_2)) < eps

        # Check Adjoint Operator
        pad_size = [int((image_size[i] - crop_size[i]) / 2) for i in range(len(image_size))]
        y_3 = yp.pad(yp.crop(self.x, crop_size, crop_start), image_size, crop_start, pad_value=0)
        y_4 = yp.reshape(CR.H * CR * self.x, image_size)
        assert yp.sumb(yp.abs(y_3 - y_4)) < eps

        # Check gradient
        CR.gradient_check()
Пример #2
0
    def test_operator_crop(self):
        ''' Crop Operator '''
        # Generate Crop Operator
        crop_size = (image_size[0] // 2, image_size[1] // 2)
        CR = ops.Crop(image_size, crop_size, pad_value=0,  dtype=global_dtype, backend=global_backend)

        # Check forward operator
        crop_start = tuple(np.asarray(image_size) // 2 - np.asarray(crop_size) // 2)
        y_1 = yp.changeBackend(CR * self.x, 'numpy')
        y_2 = yp.changeBackend(yp.crop(self.x, crop_size, crop_start), 'numpy')
        assert yp.sumb(yp.abs(y_1 - y_2)) < eps

        # Check Adjoint Operator
        pad_size = [int((image_size[i] - crop_size[i]) / 2) for i in range(len(image_size))]
        y_3 = yp.pad(yp.crop(self.x, crop_size, crop_start), image_size, crop_start, pad_value=0)
        y_4 = CR.H * CR * self.x
        assert yp.sumb(yp.abs(y_3 - y_4)) < eps

        # Check gradient
        CR.gradient_check()
Пример #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 test_pad(self):
     pad_size = [self.x_np_randn.shape[i] + 10 for i in range(len(shape))]
     assert np.sum(
         np.abs(
             bops.pad(self.x_np_randn, pad_size, crop_start=(0, 0)) - np.
             asarray(bops.pad(self.x_ocl_randn, pad_size, crop_start=(
                 0, 0))))) < 1e-4
     assert np.sum(
         np.abs(
             bops.pad(self.x_np_randn, pad_size, crop_start=(5, 2)) - np.
             asarray(bops.pad(self.x_ocl_randn, pad_size, crop_start=(
                 5, 2))))) < 1e-4
     assert np.sum(
         np.abs(
             bops.pad(
                 self.x_np_randn, pad_size, crop_start=(
                     1, 3), pad_value=4) - np.asarray(
                         bops.pad(self.x_ocl_randn,
                                  pad_size,
                                  crop_start=(1, 3),
                                  pad_value=4)))) < 1e-4
Пример #5
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
Пример #6
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