Exemple #1
0
    def crop_cardboard(self, model):

        # Performs the crop
        mat = np.array(self.raw_scan.resize((1024, 688)))
        mat = mat.reshape(1, 688, 1024, 3)
        mat = mat.astype(np.uint8)

        prediction = model.gen_prediction(mat)[0]

        full_size_image = np.asarray(self.raw_scan.resize((2048, 1376)))

        self.p, self.prediction, self.angle, self.center_x, self.center_y = unwarp.get_uwrap(
            prediction)

        self.prediction = map_coordinates(self.prediction,
                                          warp_coords(self.transform,
                                                      self.prediction.shape),
                                          order=1,
                                          prefilter=False)
        # rotate it here
        full_size_image = unwarp.rorate_image(full_size_image, self.angle)
        self.warped_image = map_coordinates(full_size_image,
                                            warp_coords(
                                                self.transform,
                                                full_size_image.shape),
                                            order=1,
                                            prefilter=False)

        rect = cv2.minAreaRect(np.argwhere(self.prediction > 0))
        self.cropped_cardboard = self.crop_minAreaRect(self.warped_image, rect)
Exemple #2
0
def test_fast_homography():
    img = rgb2gray(data.lena()).astype(np.uint8)
    img = img[:, :100]

    theta = np.deg2rad(30)
    scale = 0.5
    tx, ty = 50, 50

    H = np.eye(3)
    S = scale * np.sin(theta)
    C = scale * np.cos(theta)

    H[:2, :2] = [[C, -S], [S, C]]
    H[:2, 2] = [tx, ty]

    tform = ProjectiveTransform(H)
    coords = warp_coords(tform.inverse, (img.shape[0], img.shape[1]))

    for order in range(4):
        for mode in ('constant', 'reflect', 'wrap', 'nearest'):
            p0 = map_coordinates(img, coords, mode=mode, order=order)
            p1 = warp(img, tform, mode=mode, order=order)

            # import matplotlib.pyplot as plt
            # f, (ax0, ax1, ax2, ax3) = plt.subplots(1, 4)
            # ax0.imshow(img)
            # ax1.imshow(p0, cmap=plt.cm.gray)
            # ax2.imshow(p1, cmap=plt.cm.gray)
            # ax3.imshow(np.abs(p0 - p1), cmap=plt.cm.gray)
            # plt.show()

            d = np.mean(np.abs(p0 - p1))
            assert d < 0.001
Exemple #3
0
def get_rot_coordinates(R, shape):
    """
    image rotation coordinates calculation with affine matrix R
    
    Parameters
    ----------
    R : affine matrix 3x3        
    shape : image_shape
        

    Returns
    -------
    coords_index : coordinate_index with order = 'C'       
    idx_valid : valid index

    """
    inverse_map = ProjectiveTransform(matrix=R)
    coords = warp_coords(inverse_map, shape)
    xs = coords[0].flatten().astype('int')
    ys = coords[1].flatten().astype('int')

    a = np.all(np.vstack((xs >= 0, xs < shape[1], ys >= 0, ys < shape[0])),
               axis=0)
    idx_valid = np.where(a)[0]

    coords_index = np.nan * np.ones((np.prod(shape), ))
    coords_index[idx_valid] = 1

    coords_index[idx_valid] = np.ravel_multi_index(
        (xs[idx_valid], ys[idx_valid]), shape)
    coords_index = np.reshape(coords_index, shape)
    return coords_index, idx_valid
Exemple #4
0
def _get_warped_image(is_left, single_photo, depth_map, distortion_rate):
    image = np.array(single_photo)
    shifted = _get_shifted_coords2(depth_map, is_left, distortion_rate)
    def shift_function(xy):
        return shifted
    coords = warp_coords(shift_function, image.shape)
    warped_image = map_coordinates(image, coords, prefilter=False)
    return warped_image
Exemple #5
0
def align_by_offset(Image,
                    shift_x,
                    shift_y,
                    splitstyle="hsplit",
                    shift_channel=1):
    """
    This function shifts one channel of the array based supplied
    offset values. Retains the single image structure.

    :param Image: 2D image array
    :param shift_x: float, offset in x
    :param shift_y: float, offset in y
    :param splitstyle: string, passed to ``im_split``; accepts
        "hsplit", "vsplit". Default is "hsplit"
    :param shift_channel: int, which channel to shift by offsets,
        default is channel 1.

    :return: 2D image array of aligned image

    :Example:
        >>> from smtools.alignment import find_global_offset,
        align_by_offset
        >>> import smtools.testdata as test
        >>> import matplotlib.pyplot as plt
        >>> im = test.image_stack()
        >>> dx, dy = find_global_offset(im)
        >>> new_image = align_by_offset(im[0], dx, dy)
        >>> plt.imshow(new_image), plt.show()
    """

    ch1, ch2 = im_split(Image, splitstyle)
    if shift_channel == 1:
        new_coords = warp_coords(lambda xy: xy - np.array([shift_x, shift_y]),
                                 ch2.shape)
        warped_channel = map_coordinates(ch2, new_coords)
        aligned_image = np.concatenate((ch1, warped_channel), axis=1)
    else:
        new_coords = warp_coords(lambda xy: xy + np.array([shift_x, shift_y]),
                                 ch1.shape)
        warped_channel = map_coordinates(ch1, new_coords)
        aligned_image = np.concatenate((warped_channel, ch2), axis=1)
    return aligned_image
Exemple #6
0
def face_warp_coord(src_face,
                    src_face_lm,
                    dst_face_lm,
                    tri,
                    bg,
                    warp_only=False,
                    use_bg=True):
    """
    Function takes two faces and landmarks and warp one face around another
    according to the face landmarks.

    script modified from
    https://github.com/marsbroshok/face-replace/blob/master/faceWarp.py


    :param src_face: grayscale (?) image (np.array of int) of face
        which will warped around second face
    :param src_face_lm: landmarks for the src_face
    :param dst_face: predicted image landmarks (np.array of int) which will
        be replaced by src_face.
    :param bg: image background
    :return: image with warped face
    """
    src_face_coord = src_face_lm
    dst_face_coord = dst_face_lm

    affines = []
    # find affine mapping from source positions to destination
    for k in tri:
        affine = AffineTransform()
        affine.estimate(src_face_coord[k, :], dst_face_coord[k, :])
        affines.append(affine)

    inverse_affines = []
    # find the inverse affine mapping
    for k in tri:
        affine = AffineTransform()
        affine.estimate(dst_face_coord[k, :], src_face_coord[k, :])
        inverse_affines.append(affine)

    coords = warp_coords(coord_map, src_face.shape)
    warped_face = map_coordinates(src_face, coords)
    if not warp_only:
        if use_bg:
            warped_face = _merge_images(warped_face, bg)
        else:
            warped_face = _merge_images(warped_face, src_face)
    return warped_face
Exemple #7
0
    def __init__(self, input_shape, angles, radial_positions, radii, n_steps=5, min_blur=.5):
        """
        :param input_shape: (height, width) of input images
        :param angles: list of angles of receptive field centres
        :param radial_positions: list of radial positions of receptive field centres (pixels from
            image centre)
        :param radii: list of radii of receptive fields; same length as radial_positions, as radius
            is mainly a function of eccentricity
        :param n_steps: receptive fields of various sizes are approximated in discrete steps by
            sampling from copies of the image with different degrees of blur; this is the number of
            different blurred images created; a larger number will result in less quantization error
            in the RF size, and longer run time
        :param min_blur: sigma of Gaussian blur of the sharpest image; some blur is needed to avoid
            moire due to aliasing
        """

        self.radial_positions = radial_positions
        self.radii = radii

        blurs = np.linspace(np.min(radii), np.max(radii), n_steps)
        blurs = np.maximum(min_blur, blurs)
        self.blurs = list(set(blurs))
        self.blurs.sort()

        self.sigmas = [blurs[0]]
        for i in range(1,len(blurs)):
            self.sigmas.append(np.sqrt(blurs[i]**2 - blurs[i-1]**2))

        # find index of blur stage closest to blur wanted at each radius
        self.blur_indices = np.interp(radii, self.blurs, range(len(self.blurs)))
        self.blur_indices = np.round(self.blur_indices).astype('int')

        self.coords = []
        for i in range(len(blurs)):
            rp = [radial_positions[j] for j in range(len(radial_positions)) if self.blur_indices[j] == i]
            map = AngleEccentricityMap(input_shape, angles, rp)
            if len(rp) > 0:
                wc = warp_coords(map, (len(angles), len(rp), 3))
            else:
                wc = None
            self.coords.append(wc)
Exemple #8
0
def test_warp_coords_example():
    image = data.astronaut().astype(np.float32)
    assert 3 == image.shape[2]
    tform = SimilarityTransform(translation=(0, -10))
    coords = warp_coords(tform, (30, 30, 3))
    map_coordinates(image[:, :, 0], coords[:2])
Exemple #9
0
def shift_stack(stack, popt, n_cols, n_rows, ndx, ndy, limit=None,
                save=False, savedir=None, name=None):
    """Shift a stack

    Shifts the input stack, using the second and third elements in popt, and makes a new stack of the shifted images.

    Parameters
    ----------
    stack : hyperspy.api.signals.Signal2D
        A stack of e.g. Precession Electron Diffraction patterns to be shifted. Assumed to have shape (Nx, Ny, nx, ny)
    popt : numpy.ndarray
        A numpy array of shape (Nx*Ny, 7), where the second and third elements are used as shifts in row and column directions, respectively
    n_cols : int, float or str
        Number of columns in the stack (equal to Ny)
    n_rows : int, float or str
        Number of rows in the stack (equal to Nx)
    ndx : int, float or str
        Number of vertical (?) pixels in the diffraction pattern
    ndy : int, float or str
        Number of horizontal (?) pixels in the diffraction pattern
    limit : int, float, str or None, optional
        Number of frames to shift before breaking, useful for debugging (the default is `None` indicating that all frames will be shifted)
    save : {False, True}, optional
        Whether or not the shifted stack should be saved
    savedir : int, float or str, optional
        Used to specify a directory to store the shifted stack if `save=True` (default is `''` indicating that the signal will be stored in the cwd)
    name : int, float or str, optional
        Used to specify the name of the signal if `save=True` (default is `'shifted_stack'`

    Returns
    -------
    shifted_signal : hyperspy.api.signals.Signal2D
        The shifted stack as a hyperspy signal
    times : list of floats
        The time spent since the start of the for loop, sampled at every 1% of total frames.

    Raises
    ------

    Notes
    -----

    Examples
    --------

    Load a premade `popt` file and a signal to shift, then shift the signal

    >>> s = hs.load('C:\\Users\\emilc\\Desktop\\SPED_align_laptop\\2017_01_11_6060-20-1-C-4_001.blo')
    >>> n_cols = s.axes_manager['x'].get('size')['size']
    >>> n_rows = s.axes_manager['y'].get('size')['size']
    >>> ndx = s.axes_manager['dx'].get('size')['size']
    >>> ndy = s.axes_manager['dy'].get('size')['size']
    >>> Popts = np.load(savedir+'Popts_1.npy')
    >>> shifted_signal = sa.shift_stack(s, Popts, n_cols=n_cols, n_rows=n_rows, ndx=ndx, ndy=ndy, save=True, savedir='C:\\Users\\emilc\\Desktop\\SPED_align_laptop\\2017_01_11_6060-20-1-C-4_001_shifted')

    """
    assert isinstance(stack,
                      hs.signals.Signal2D), '`stack` is type {}, must be a `hyperspy.api.signals.Signal2D` object'.format(
        type(stack))
    assert isinstance(popt,
                      np.ndarray), '`popt` is type {}, must be a `numpy.ndarray`'.format(
        type(popt))
    assert len(np.shape(
        stack)) == 4, '`stack` has shape {}, must have a 4D shape'.format(
        np.shape(stack))
    assert len(np.shape(
        popt)) == 2, '`popt` has shape {}, must have a 2D shape (flattened array)'.format(
        np.shape(popt))
    assert np.shape(popt)[0] == np.shape(stack)[0] * np.shape(stack)[1] and \
           np.shape(popt)[
               1] == 7, 'First dimension of `popt` ({}) must equal the product of the first ({}) and second ({}) dimension of `stack`.'.format(
        np.shape(popt)[0], np.shape(stack)[0], np.shape(stack)[1])
    try:
        n_cols, n_rows, ndx, ndy = int(n_cols), int(n_rows), int(ndx), int(
            ndy)
        if limit is None:
            limit = n_rows * n_cols
        else:
            limit = int(limit)

        save = bool(save)

        if save:
            if savedir is None:
                savedir = ''
            else:
                savedir = str(savedir)

            if name is None:
                name = 'shifted_stack'
            else:
                name = str(name)
    except ValueError as e:
        print(e)
        return None
    except TypeError as e:
        print(e)
        return None

    # Define function for shifting image (called by skimage.transform.warp_coords)
    def shift(xy):
        """Shift image coordinates somehow

        Parameters
        ----------
        xy : numpy.ndarray
            Coordinate array

        Returns
        -------
        numpy.ndarray
            I think this function returns a numpy.ndarray... But I am not sure yet: On Todo!

        """
        return xy - np.array(
            [72 - popt[frameno, 2], 72 - popt[frameno, 1]])[None, :]

    # Total number of frames in the stack
    n_tot = n_cols * n_rows

    # Allocate memory and define the new (shifted) stack
    shifted_stack = np.zeros((n_rows, n_cols, ndx, ndy), dtype=np.uint8)

    # Define row and column counters
    rowno = 0
    colno = 0
    # Make a list over rumtime times.
    times = [time.time()]

    # loop over all the frames in the stack, and for each frame, use a corresponding image shift found by e.g.
    # `align_stack_fast()` to shift the frame
    for frameno, frame in enumerate(stack):
        if colno == n_cols:
            colno = 0
            rowno += 1
        # Print some output for every 1/100 th frame
        if not frameno % (int(limit / 100)):
            curr_t_diff = time.time() - times[0]
            times.append(curr_t_diff)

            print(
                '{}% done (now on Frame {} of {}: row {}, col {})\n\tTime passed since start: {} seconds.'.format(
                    int(frameno / limit * 100), frameno,
                    limit, rowno, colno, curr_t_diff))

        coords = warp_coords(shift, frame.data.shape)
        shifted_stack[rowno, colno, :, :] = map_coordinates(frame.data,
                                                            coords).astype(
            np.uint8)

        colno += 1

        # Check if the limit is reached or if the loop is finished.
        if frameno == limit or frameno == n_tot - 1:
            shifted_signal = hs.signals.Signal2D(shifted_stack)
            shifted_signal.metadata = stack.metadata.deepcopy()
            new_metadata = {'Postprocessing': {
                'date': dt.datetime.now().strftime('%c%'),
                'version': 'latest',
                'type': 'Shifted stack', 'limit': limit, 'save': save,
                'savedirectory': savedir, 'name': name,
                'time elapsed': times[-1]}}
            shifted_signal.metadata.add_dictionary(new_metadata)
            shifted_signal.axes_manager = stack.axes_manager.copy()

            # If the user wants to save the shifted signal, save it as `.hdf5` file
            if save:
                shifted_signal.save(savedir + name + '.hdf5')
            return shifted_signal, times

    # Just in case the if statement above bugs, return the signal anyways
    shifted_signal = hs.signals.Signal2D(shifted_stack)
    shifted_signal.metadata = shifted_signal.metadata = stack.metadata.deepcopy()
    new_metadata = {
        'Postprocessing': {'date': dt.datetime.now().strftime('%c%'),
                           'version': 'latest',
                           'type': 'Shifted stack', 'limit': limit,
                           'save': save,
                           'savedirectory': savedir, 'name': name,
                           'time elapsed': times[-1]}}
    shifted_signal.metadata.add_dictionary(new_metadata)
    shifted_signal.axes_manager = stack.axes_manager.copy()
    return shifted_signal, times
Exemple #10
0
def align_stack_fast(stack, limit=None, bounds=10,
                     save=False, savedir=None, name=None):
    """Find 000 position of each frame in stack and align the stack to these positions

    Parameters
    ----------
    stack : hyperspy.api.signals.Signal2D
        The stack containing the diffraction patterns to be aligned.
    limit : int, float or str, optional
        The total number of frames to consider before ending, useful for debugging (default is None which implies treating the whole stack).
    bounds : int, float or str, optional
        Defines the region where a 2D gaussian is fitted to the dataset (the default is 10). The region is defined as `frame[center[0]-bounds:center[0]+bounds+1, center[1]-bounds:center[1]+bounds+1`. The region should be chosen large enough to (preferably) only contain the 000 reflection.
    save : {False, True}, optional
        Whether or not to save the aligned stack and the gaussian fits as hdf5 files.
    savedir : str, optional
        The directory to store the results, if `save=True` (defaults to `''` which implies storing results in the cwd).
    name : str, optional
        The name to give the aligned stack (defaults to `aligned_stack`).

    Returns
    -------
    Popt : numpy.ndarray
        The fit results containing all the data to produce the fitted gaussian. The array has shape (N*M, 7) where N and M are the scan dimensions of the stack (total number of frames), and 7 is the number of parameters to describe the gaussian.
    g : hyperspy.api.signals.Signal2D
        A stack of the intensities of the fitted gaussians.
    aligned_stack : hyperspy.api.signals.Signal2D
        A stack containing the aligned diffraction patterns of the input stack.

    See Also
    --------
    gaussian_2d_fast : Compute 2D gaussian
    fit_gaussian_2d_to_imagesubset_fast : Fit a 2D gaussian to a subset of image

    Examples
    --------

    Load a blockfile containing Scanning Precession Electron Diffraction data and align them.

    >>> s = hs.load('data.blo')
    >>> Popts, g, s_aligned = sa.align_stack_fast(s, limit=None, save=True)

    """

    assert isinstance(stack,
                      hs.signals.Signal2D), '`stack` is type {}, must be a `hyperspy.api.signals.Signal2D` object'.format(
        type(stack))
    assert len(np.shape(
        stack)) == 4, '`stack` has shape {}, must have a 4D shape'.format(
        np.shape(stack))
    try:
        n_cols = stack.axes_manager['x'].get('size')['size']
        n_rows = stack.axes_manager['y'].get('size')['size']
        n_tot = n_cols * n_rows
        if limit is None:
            limit = n_tot
        else:
            limit = int(limit)

        ndx = stack.axes_manager['dx'].get('size')['size']
        ndy = stack.axes_manager['dy'].get('size')['size']

        bounds = int(bounds)
        assert bounds < ndx / 2 and bounds < ndy / 2, 'The bounds ({}) cannot be larger than half the diffraction pattern width (whole widths: {}, {}).'.format(
            bounds, ndx, ndy)

        save = bool(save)

        if save:
            if savedir is None:
                savedir = ''
            else:
                savedir = str(savedir)

            if name is None:
                name = 'aligned_stack'
            else:
                name = str(name)
    except ValueError as e:
        print(e)
        return None
    except TypeError as e:
        print(e)
        return None

    def shift(xy):
        return xy - np.array([72 - fit_popt[2], 72 - fit_popt[1]])[None, :]

    dx, dy = np.mgrid[0:ndx, 0:ndy]

    Popt = np.zeros((n_tot, 7))
    G = np.zeros((n_rows, n_cols, ndx, ndy), dtype=np.uint8)
    shifted_stack = np.zeros((n_rows, n_cols, ndx, ndy), dtype=np.uint8)

    rowno = 0
    colno = 0

    times = [time.time()]
    for frameno, frame in enumerate(stack):
        if colno == n_cols:
            colno = 0
            rowno += 1
        if not frameno % (int(limit / 100)):
            times.append(time.time() - times[0])
            print(
                '{}% done (now on Frame {} of {}: row {}, col {})'.format(
                    int(frameno / limit * 100), frameno,
                    limit, rowno, colno))

        try:
            fit_popt = fit_gaussian_2d_to_imagesubset_fast(frame.data,
                                                           bounds)

        except RuntimeError as e:
            g = hs.signals.Signal2D(G)
            g.metadata = stack.metadata.deepcopy()
            g.axes_manager = stack.axes_manager.copy()
            new_metadata = {'Postprocessing': {
                'date': dt.datetime.now().strftime('%c'),
                'version': 'latest',
                'type': 'Gaussian fit', 'limit': limit, 'save': save,
                'savedirectory': savedir, 'name': name,
                'time elapsed': times[-1]}}
            g.metadata.add_dictionary(new_metadata)
            # g.axes_manager = stack.axes_manager.copy()

            aligned_stack = hs.signals.Signal2D(shifted_stack)
            aligned_stack.metadata = stack.metadata.deepcopy()
            aligned_stack.axes_manager = stack.axes_manager.copy()
            new_metadata = {'Postprocessing': {
                'date': dt.datetime.now().strftime('%c'),
                'version': 'latest',
                'type': 'aligned stack', 'limit': limit, 'save': save,
                'savedirectory': savedir, 'name': name,
                'time elapsed': times[-1]}}
            aligned_stack.metadata.add_dictionary(new_metadata)

            if save:
                np.save(savedir + 'Popts_1', Popt)
                g.save(savedir + 'G.hdf5')
                aligned_stack.save(savedir + name + '.hdf5')
            print(e)
            return Popt, g, aligned_stack

        Popt[frameno, :] = fit_popt
        G[rowno, colno, :, :] = gaussian_2d_fast((dx, dy),
                                                 *fit_popt).reshape(
            np.shape(dx)).astype(np.uint8)
        coords = warp_coords(shift, frame.data.shape)
        shifted_stack[rowno, colno, :, :] = map_coordinates(frame.data,
                                                            coords).astype(
            np.uint8)

        colno += 1

        if frameno == limit or frameno == n_tot - 1:
            g = hs.signals.Signal2D(G)
            g.metadata = stack.metadata.deepcopy()
            #print('Stack metadata:\n', stack.metadata)
            #print('G metadata (deepcopied):\n', g.metadata)
            g.axes_manager = stack.axes_manager.copy()
            new_metadata = {'Postprocessing': {
                'date': dt.datetime.now().strftime('%c'),
                'version': 'latest',
                'type': 'Gaussian fit',
                'limit': limit,
                'save': save,
                'savedirectory': savedir,
                'name': name,
                'time elapsed': times[-1]}}
            g.metadata.add_dictionary(new_metadata)
            #print('G metadata (added dict):\n',g.metadata)

            aligned_stack = hs.signals.Signal2D(shifted_stack)
            aligned_stack.metadata = stack.metadata.deepcopy()
            aligned_stack.axes_manager = stack.axes_manager.copy()
            new_metadata = {'Postprocessing': {
                'date': dt.datetime.now().strftime('%c'),
                'version': 'latest',
                'type': 'aligned stack', 'limit': limit, 'save': save,
                'savedirectory': savedir, 'name': name,
                'time elapsed': times[-1]}}
            aligned_stack.metadata.add_dictionary(new_metadata)

            if save:
                np.save(savedir + 'Popts_1', Popt)
                g.save(savedir + 'G.hdf5')
                aligned_stack.save(savedir + name + '.hdf5')
            return Popt, g, aligned_stack
Exemple #11
0
def test_warp_coords_example():
    image = data.lena().astype(np.float32)
    assert 3 == image.shape[2]
    tform = SimilarityTransform(translation=(0, -10))
    coords = warp_coords(tform, (30, 30, 3))
    map_coordinates(image[:, :, 0], coords[:2])