def setUpClass(cls):
        img = imread(get_path('AS15-M-0298_SML.png'), flatten=True)
        img_coord = (482.09783936, 652.40679932)

        cls.template = sp.clip_roi(img, img_coord, 5)
        cls.template = rotate(cls.template, 90)
        cls.template = imresize(cls.template, 1.)

        cls.search = sp.clip_roi(img, img_coord, 21)
        cls.search = rotate(cls.search, 0)
        cls.search = imresize(cls.search, 1.)

        cls.offset = (1, 1)

        cls.offset_template = sp.clip_roi(img, np.add(img_coord, cls.offset), 5)
        cls.offset_template = rotate(cls.offset_template, 0)
        cls.offset_template = imresize(cls.offset_template, 1.)

        cls.search_center = [math.floor(cls.search.shape[0]/2),
                             math.floor(cls.search.shape[1]/2)]

        cls.upsampling = 10
        cls.alpha = math.pi/2
        cls.cifi_thresh = 90
        cls.rafi_thresh = 90
        cls.tefi_thresh = 100
        cls.use_percentile = True
        cls.radii = list(range(1, 3))

        cls.cifi_number_of_warnings = 2
        cls.rafi_number_of_warnings = 2
Beispiel #2
0
    def setUpClass(cls):
        img = imread(get_path('AS15-M-0298_SML.png'), flatten=True)
        img_coord = (482.09783936, 652.40679932)

        cls.template = sp.clip_roi(img, img_coord, 5)
        cls.template = rotate(cls.template, 90)
        cls.template = imresize(cls.template, 1.)

        cls.search = sp.clip_roi(img, img_coord, 21)
        cls.search = rotate(cls.search, 0)
        cls.search = imresize(cls.search, 1.)

        cls.offset = (1, 1)

        cls.offset_template = sp.clip_roi(img, np.add(img_coord, cls.offset),
                                          5)
        cls.offset_template = rotate(cls.offset_template, 0)
        cls.offset_template = imresize(cls.offset_template, 1.)

        cls.search_center = [
            math.floor(cls.search.shape[0] / 2),
            math.floor(cls.search.shape[1] / 2)
        ]

        cls.upsampling = 10
        cls.alpha = math.pi / 2
        cls.cifi_thresh = 90
        cls.rafi_thresh = 90
        cls.tefi_thresh = 100
        cls.use_percentile = True
        cls.radii = list(range(1, 3))

        cls.cifi_number_of_warnings = 2
        cls.rafi_number_of_warnings = 2
Beispiel #3
0
def offset_template(img, img_coord):
    coord_x, coord_y = img_coord
    coord_x += 1
    coord_y += 1
    offset_template, _, _ = sp.clip_roi(img, coord_x, coord_y, 5, 5)
    offset_template = rotate(offset_template, 0)
    offset_template = imresize(offset_template, 1.)

    return offset_template
Beispiel #4
0
def search(img, img_coord):
    coord_x, coord_y = img_coord
    search, _, _ = sp.clip_roi(img, coord_x, coord_y, 21, 21)
    search = rotate(search, 0)
    search = imresize(search, 1.)
    return search
Beispiel #5
0
def template(img, img_coord):
    coord_x, coord_y = img_coord
    template, _, _ = sp.clip_roi(img, coord_x, coord_y, 5, 5)
    template = rotate(template, 90)
    template = imresize(template, 1.)
    return template
Beispiel #6
0
    def subpixel_register(self, clean_keys=[], threshold=0.8, upsampling=16,
                          template_size=19, search_size=53, max_x_shift=1.0,
                          max_y_shift=1.0, tiled=False):
        """
        For the entire graph, compute the subpixel offsets using pattern-matching and add the result
        as an attribute to each edge of the graph.

        Parameters
        ----------
        clean_keys : list
             of string keys to masking arrays
             (created by calling outlier detection)

        threshold : float
                    On the range [-1, 1].  Values less than or equal to
                    this threshold are masked and can be considered
                    outliers

        upsampling : int
                     The multiplier to the template and search shapes to upsample
                     for subpixel accuracy

        template_size : int
                        The size of the template in pixels, must be odd

        search_size : int
                      The size of the search

        max_x_shift : float
                      The maximum (positive) value that a pixel can shift in the x direction
                      without being considered an outlier

        max_y_shift : float
                      The maximum (positive) value that a pixel can shift in the y direction
                      without being considered an outlier
        """

        matches = self.matches
        self.subpixel_offsets = pd.DataFrame(0, index=matches.index, columns=['x_offset',
                                                                              'y_offset',
                                                                              'correlation',
                                                                              's_idx', 'd_idx'])

        # Build up a composite mask from all of the user specified masks
        if clean_keys:
            matches, mask = self._clean(clean_keys)

        if tiled is True:
            s_img = self.source.handle
            d_img = self.destination.handle
        else:
            s_img = self.source.handle.read_array()
            d_img = self.destination.handle.read_array()

        # for each edge, calculate this for each keypoint pair
        for i, (idx, row) in enumerate(matches.iterrows()):
            s_idx = int(row['source_idx'])
            d_idx = int(row['destination_idx'])

            s_keypoint = self.source.keypoints.iloc[s_idx][['x', 'y']].values
            d_keypoint = self.destination.keypoints.iloc[d_idx][['x', 'y']].values

            # Get the template and search window
            s_template = sp.clip_roi(s_img, s_keypoint, template_size)
            d_search = sp.clip_roi(d_img, d_keypoint, search_size)

            try:
                x_off, y_off, strength = sp.subpixel_offset(s_template, d_search, upsampling=upsampling)
                self.subpixel_offsets.loc[idx] = [x_off, y_off, strength,s_idx, d_idx]
            except:
                warnings.warn('Template-Search size mismatch, failing for this correspondence point.')
                continue

        self.subpixel_offsets.to_sparse(fill_value=0.0)

        # Compute the mask for correlations less than the threshold
        threshold_mask = self.subpixel_offsets['correlation'] >= threshold

        # Compute the mask for the point shifts that are too large
        subp= self.subpixel_offsets
        query_string = 'x_offset <= -{0} or x_offset >= {0} or y_offset <= -{1} or y_offset >= {1}'.format(max_x_shift,
                                                                                                           max_y_shift)
        sp_shift_outliers = subp.query(query_string)
        shift_mask = pd.Series(True, index=self.subpixel_offsets.index)
        shift_mask[sp_shift_outliers.index] = False

        # Generate the composite mask and write the masks to the mask data structure
        mask = threshold_mask & shift_mask
        self.masks = ('shift', shift_mask)
        self.masks = ('threshold', threshold_mask)
        self.masks = ('subpixel', mask)
Beispiel #7
0
def test_clip_roi(center_x, center_y, size, expected):
    img = np.arange(10000).reshape(100, 100)

    clip, axr, ayr = sp.clip_roi(img, center_x, center_y, size)

    assert clip.mean() == expected
Beispiel #8
0
def offset_template(img, img_coord):
    coord_x, coord_y = img_coord
    coord_x += 1
    coord_y += 1
    offset_template, _, _ = sp.clip_roi(img, coord_x, coord_y, 5, 5)
    return offset_template
Beispiel #9
0
    def compute_subpixel_offset(self,
                                clean_keys=[],
                                threshold=0.8,
                                upsampling=16,
                                template_size=19,
                                search_size=53):
        """
        For the entire graph, compute the subpixel offsets using pattern-matching and add the result
        as an attribute to each edge of the graph.

        Parameters
        ----------
        clean_keys : list
             of string keys to masking arrays
             (created by calling outlier detection)

        threshold : float
                    On the range [-1, 1].  Values less than or equal to
                    this threshold are masked and can be considered
                    outliers

        upsampling : int
                     The multiplier to the template and search shapes to upsample
                     for subpixel accuracy

        template_size : int
                        The size of the template in pixels, must be odd

        search_size : int
                      The size of the search
        """

        matches = self.matches

        full_offsets = np.zeros((len(matches), 3))

        # Build up a composite mask from all of the user specified masks
        if clean_keys:
            mask = np.prod([self._mask_arrays[i] for i in clean_keys],
                           axis=0,
                           dtype=np.bool)
            matches = matches[mask]
            full_mask = np.where(mask == True)

        # Preallocate the numpy array to avoid appending and type conversion
        edge_offsets = np.empty((len(matches), 3))

        # for each edge, calculate this for each keypoint pair
        for i, (idx, row) in enumerate(matches.iterrows()):

            s_idx = int(row['source_idx'])
            d_idx = int(row['destination_idx'])

            s_keypoint = self.source.keypoints.iloc[s_idx][['x', 'y']].values
            d_keypoint = self.destination.keypoints.iloc[d_idx][['x',
                                                                 'y']].values

            # Get the template and search windows
            s_template = sp.clip_roi(self.source.handle, s_keypoint,
                                     template_size)
            d_search = sp.clip_roi(self.destination.handle, d_keypoint,
                                   search_size)

            try:
                edge_offsets[i] = sp.subpixel_offset(s_template,
                                                     d_search,
                                                     upsampling=upsampling)
            except:
                warnings.warn(
                    'Template-Search size mismatch, failing for this correspondence point.'
                )
                continue

        # Compute the mask for correlations less than the threshold
        threshold_mask = edge_offsets[edge_offsets[:, -1] >= threshold]

        # Convert the truncated mask back into a full length mask
        if clean_keys:
            mask[full_mask] = threshold_mask
            full_offsets[full_mask] = edge_offsets
        else:
            mask = threshold_mask

        self.subpixel_offsets = pd.DataFrame(
            full_offsets, columns=['x_offset', 'y_offset', 'correlation'])
        self.masks = ('subpixel', mask)
Beispiel #10
0
def template(img, img_coord):
    coord_x, coord_y = img_coord
    template, _, _ = sp.clip_roi(img, coord_x, coord_y, 5, 5)
    template = rotate(template, 90)
    return template
Beispiel #11
0
def search():
    coord_x, coord_y = (482.09783936, 652.40679932)
    img = imread(get_path('AS15-M-0298_SML.png'), as_gray=True)
    search, _, _ = sp.clip_roi(img, coord_x, coord_y, 21, 21)
    return search
Beispiel #12
0
    def subpixel_register(self,
                          clean_keys=[],
                          threshold=0.8,
                          template_size=19,
                          search_size=53,
                          max_x_shift=1.0,
                          max_y_shift=1.0,
                          tiled=False,
                          **kwargs):
        """
        For the entire graph, compute the subpixel offsets using pattern-matching and add the result
        as an attribute to each edge of the graph.

        Parameters
        ----------
        clean_keys : list
             of string keys to masking arrays
             (created by calling outlier detection)

        threshold : float
                    On the range [-1, 1].  Values less than or equal to
                    this threshold are masked and can be considered
                    outliers

        upsampling : int
                     The multiplier to the template and search shapes to upsample
                     for subpixel accuracy

        template_size : int
                        The size of the template in pixels, must be odd

        search_size : int
                      The size of the search

        max_x_shift : float
                      The maximum (positive) value that a pixel can shift in the x direction
                      without being considered an outlier

        max_y_shift : float
                      The maximum (positive) value that a pixel can shift in the y direction
                      without being considered an outlier
        """
        matches = self.matches
        for column, default in {
                'x_offset': 0,
                'y_offset': 0,
                'correlation': 0,
                'reference': -1
        }.items():
            if column not in self.matches.columns:
                self.matches[column] = default

        # Build up a composite mask from all of the user specified masks
        matches, mask = self._clean(clean_keys)

        # Grab the full images, or handles
        if tiled is True:
            s_img = self.source.geodata
            d_img = self.destination.geodata
        else:
            s_img = self.source.geodata.read_array()
            d_img = self.destination.geodata.read_array()

        source_image = (matches.iloc[0]['source_image'])

        # for each edge, calculate this for each keypoint pair
        for i, (idx, row) in enumerate(matches.iterrows()):
            s_idx = int(row['source_idx'])
            d_idx = int(row['destination_idx'])

            s_keypoint = self.source.get_keypoint_coordinates(s_idx)
            d_keypoint = self.destination.get_keypoint_coordinates(d_idx)

            # Get the template and search window
            s_template = sp.clip_roi(s_img, s_keypoint, template_size)
            d_search = sp.clip_roi(d_img, d_keypoint, search_size)
            try:
                x_offset, y_offset, strength = sp.subpixel_offset(
                    s_template, d_search, **kwargs)
                self.matches.loc[idx, ('x_offset', 'y_offset', 'correlation',
                                       'reference')] = [
                                           x_offset, y_offset, strength,
                                           source_image
                                       ]
            except:
                warnings.warn(
                    'Template-Search size mismatch, failing for this correspondence point.'
                )
                continue

        # Compute the mask for correlations less than the threshold
        threshold_mask = self.matches['correlation'] >= threshold

        # Compute the mask for the point shifts that are too large
        query_string = 'x_offset <= -{0} or x_offset >= {0} or y_offset <= -{1} or y_offset >= {1}'.format(
            max_x_shift, max_y_shift)
        sp_shift_outliers = self.matches.query(query_string)
        shift_mask = pd.Series(True, index=self.matches.index)
        shift_mask.loc[sp_shift_outliers.index] = False

        # Generate the composite mask and write the masks to the mask data structure
        mask = threshold_mask & shift_mask
        self.masks = ('shift', shift_mask)
        self.masks = ('threshold', threshold_mask)
        self.masks = ('subpixel', mask)
Beispiel #13
0
def refine_subpixel(sx,
                    sy,
                    dx,
                    dy,
                    s_img,
                    d_img,
                    size=100,
                    reduction=25,
                    convergence_threshold=.5):
    """
    Iteratively apply a subpixel phase matcher to source (s_img) amd destination (d_img)
    images. The size parameter is used to set the initial search space. The algorithm
    is recursively applied to reduce the total search space by reduction until the convergence criteria
    are met. Convergence is defined as the point at which the computed shifts (x_shift,y_shift) are
    less than the convergence_threshold. In instances where the size is reducted to 1 pixel the
    algorithm terminates and returns None.

    Parameters
    ----------
    sx : numeric
         The x position of the center of the template to be matched to
    sy : numeric
         The y position of the center of the template to be matched to
    dx : numeric
         The x position of the center of the search to be matched from
    dy : numeric
         The y position of the center of the search to be matched to

    s_img : object
            A plio geodata object from which the template is extracted
    d_img : object
            A plio geodata object from which the search is extracted
    size : int
           One half of the total size of the template, so a 251 default results in a 502 pixel search space
    reduction : int
                With each recursive call to this func, the size is reduced by this amount
    convergence_threshold : float
                            The value under which the result can shift in the x and y directions to force a break

    Returns
    -------
    dx : float
         The new x value for the match in the destination (d) image
    dy : float
         The new y value for the match in the destination (d) image
    metrics : tuple
              A tuple of metrics. In the case of the phase matcher this are difference
              and RMSE in the phase dimension.
    """
    s_template, _, _ = clip_roi(s_img, sx, sy, size_x=size, size_y=size)
    d_search, dxr, dyr = clip_roi(d_img, dx, dy, size_x=size, size_y=size)
    if s_template.shape != d_search.shape:
        s_size = s_template.shape
        d_size = d_search.shape
        updated_size = int(min(s_size + d_size) / 2)
        s_template, _, _ = clip_roi(s_img,
                                    sx,
                                    sy,
                                    size_x=updated_size,
                                    size_y=updated_size)
        d_search, dxr, dyr = clip_roi(d_img,
                                      dx,
                                      dy,
                                      size_x=updated_size,
                                      size_y=updated_size)

    # Apply the phase matcher
    shift_x, shift_y, metrics = subpixel_phase(s_template,
                                               d_search,
                                               upsample_factor=100)
    # Apply the shift to d_search and compute the new correspondence location
    dx += (shift_x + dxr)
    dy += (shift_y + dyr)
    # Break if the solution has converged
    if abs(shift_x) < convergence_threshold and abs(
            shift_y) < convergence_threshold:
        return dx, dy, metrics
    else:
        size -= reduction
        if size < 1:
            return
        return refine_subpixel(sx, sy, dx, dy, s_img, d_img, size)
Beispiel #14
0
    def compute_subpixel_offsets(self, clean_keys=[], threshold=0.8, upsampling=10,
                                 template_size=9, search_size=27):
        """
        For the entire graph, compute the subpixel offsets using pattern-matching and add the result
        as an attribute to each edge of the graph.

        Parameters
        ----------
        clean_keys : list
             of string keys to masking arrays
             (created by calling outlier detection)

        threshold : float
                    On the range [-1, 1].  Values less than or equal to
                    this threshold are masked and can be considered
                    outliers

        upsampling : int
                     The multiplier to the template and search shapes to upsample
                     for subpixel accuracy

        template_size : int
                        The size of the template in pixels, must be odd

        search_size : int
                      The size of the search
        """

        for source, destination, attributes in self.edges_iter(data=True):
            matches = attributes['matches']

            full_offsets = np.zeros((len(matches), 3))

            # Build up a composite mask from all of the user specified masks
            if clean_keys:
                mask = np.prod([attributes[i] for i in clean_keys], axis=0, dtype=np.bool)
                matches = matches[mask]
                full_mask = np.where(mask == True)

            src_image = self.node[source]['image']
            dest_image = self.node[destination]['image']

            # Preallocate the numpy array to avoid appending and type conversion
            edge_offsets = np.empty((len(matches),3))

            # for each edge, calculate this for each keypoint pair
            for i, (idx, row) in enumerate(matches.iterrows()):
                s_idx = int(row['source_idx'])
                d_idx = int(row['destination_idx'])

                s_node = self.node[source]
                d_node = self.node[destination]

                s_keypoint = s_node['keypoints'][s_idx].pt
                d_keypoint = d_node['keypoints'][d_idx].pt

                # Get the template and search windows
                s_template = sp.clip_roi(src_image, s_keypoint, template_size)
                d_search = sp.clip_roi(dest_image, d_keypoint, search_size)

                edge_offsets[i] = sp.subpixel_offset(s_template, d_search, upsampling=upsampling)

            # Compute the mask for correlations less than the threshold
            threshold_mask = edge_offsets[edge_offsets[:,-1] >= threshold]

            # Convert the truncated mask back into a full length mask
            if clean_keys:
                mask[full_mask] = threshold_mask
                full_offsets[full_mask] = edge_offsets
            else:
                mask = threshold_mask

            attributes['subpixel_offsets'] = pd.DataFrame(full_offsets, columns=['x_offset',
                                                                                 'y_offset',
                                                                                 'correlation'])
            attributes['subpixel'] = mask
Beispiel #15
0
def test_clip_roi(center_x, center_y, size, expected):
    img = np.arange(10000).reshape(100, 100)

    clip, axr, ayr = sp.clip_roi(img, center_x, center_y, size)

    assert clip.mean() == expected
Beispiel #16
0
    def subpixel_register(self,
                          method='phase',
                          clean_keys=[],
                          template_size=251,
                          search_size=251,
                          **kwargs):
        """
        For the entire graph, compute the subpixel offsets using pattern-matching and add the result
        as an attribute to each edge of the graph.

        Parameters
        ----------
        clean_keys : list
                     of string keys to masking arrays
                     (created by calling outlier detection)

        threshold : float
                    On the range [-1, 1].  Values less than or equal to
                    this threshold are masked and can be considered
                    outliers

        upsampling : int
                     The multiplier to the template and search shapes to upsample
                     for subpixel accuracy

        template_size : int
                        The size of the template in pixels, must be odd

        search_size : int
                      The size of the search

        max_x_shift : float
                      The maximum (positive) value that a pixel can shift in the x direction
                      without being considered an outlier

        max_y_shift : float
                      The maximum (positive) value that a pixel can shift in the y direction
                      without being considered an outlier
        """
        # Build up a composite mask from all of the user specified masks
        matches, mask = self.clean(clean_keys)

        # Get the img handles
        s_img = self.source.geodata
        d_img = self.destination.geodata

        # Determine which algorithm is going ot be used.
        if method == 'phase':
            func = sp.subpixel_phase
            shifts_x, shifts_y, strengths, new_x, new_y = sp._prep_subpixel(
                len(matches), 2)
        elif method == 'template':
            func = sp.subpixel_template
            shifts_x, shifts_y, strengths, new_x, new_y = sp._prep_subpixel(
                len(matches), 1)

        # for each edge, calculate this for each keypoint pair
        for i, (idx, row) in enumerate(matches.iterrows()):
            s_idx = int(row['source_idx'])
            d_idx = int(row['destination_idx'])

            if 'source_x' in row.index:
                sx = row.source_x
                sy = row.source_y
            else:
                s_keypoint = self.source.get_keypoint_coordinates([s_idx])
                sx = s_keypoint.x
                sy = s_keypoint.y

            if 'destination_x' in row.index:
                dx = row.destination_x
                dy = row.destination_y
            else:
                d_keypoint = self.destination.get_keypoint_coordinates([d_idx])
                dx = d_keypoint.x
                dy = d_keypoint.y

            s_template, _, _ = sp.clip_roi(s_img,
                                           sx,
                                           sy,
                                           size_x=template_size,
                                           size_y=template_size)
            d_search, dxr, dyr = sp.clip_roi(d_img,
                                             dx,
                                             dy,
                                             size_x=search_size,
                                             size_y=search_size)

            # Now check to see if these are the same size.
            if method == 'phase' and (s_template.shape != d_search.shape):
                s_size = s_template.shape
                d_size = d_search.shape
                updated_size = int(min(s_size + d_size) / 2)
                s_template, _, _ = sp.clip_roi(s_img,
                                               sx,
                                               sy,
                                               size_x=updated_size,
                                               size_y=updated_size)
                d_search, dxr, dyr = sp.clip_roi(d_img,
                                                 dx,
                                                 dy,
                                                 size_x=updated_size,
                                                 size_y=updated_size)
            shift_x, shift_y, metrics = func(s_template, d_search, **kwargs)

            # ROIs and clipping all work using whole pixels. The clip_roi func returns
            # the subpixel components that are lost when converting to whole pixels
            # reapply those here.
            shifts_x[i] = shift_x + dxr
            shifts_y[i] = shift_y + dyr

            new_x[i] = dx - shift_x
            new_y[i] = dy - shift_y
            strengths[i] = metrics

        self.matches.loc[mask, 'shift_x'] = shifts_x
        self.matches.loc[mask, 'shift_y'] = shifts_y
        self.matches.loc[mask, 'destination_x'] = new_x
        self.matches.loc[mask, 'destination_y'] = new_y

        if method == 'phase':
            self.costs.loc[mask, 'phase_diff'] = strengths[:, 0]
            self.costs.loc[mask, 'rmse'] = strengths[:, 1]
        elif method == 'template':
            self.costs.loc[mask, 'correlation'] = strengths[:, 0]
Beispiel #17
0
    def subpixel_register(self, clean_keys=[], threshold=0.8,
                          template_size=19, search_size=53, max_x_shift=1.0,
                          max_y_shift=1.0, tiled=False, **kwargs):
        """
        For the entire graph, compute the subpixel offsets using pattern-matching and add the result
        as an attribute to each edge of the graph.

        Parameters
        ----------
        clean_keys : list
             of string keys to masking arrays
             (created by calling outlier detection)

        threshold : float
                    On the range [-1, 1].  Values less than or equal to
                    this threshold are masked and can be considered
                    outliers

        upsampling : int
                     The multiplier to the template and search shapes to upsample
                     for subpixel accuracy

        template_size : int
                        The size of the template in pixels, must be odd

        search_size : int
                      The size of the search

        max_x_shift : float
                      The maximum (positive) value that a pixel can shift in the x direction
                      without being considered an outlier

        max_y_shift : float
                      The maximum (positive) value that a pixel can shift in the y direction
                      without being considered an outlier
        """
        matches = self.matches
        for column, default in {'x_offset': 0, 'y_offset': 0, 'correlation': 0, 'reference': -1}.items():
            if column not in self.matches.columns:
                self.matches[column] = default

        # Build up a composite mask from all of the user specified masks
        matches, mask = self._clean(clean_keys)

        # Grab the full images, or handles
        if tiled is True:
            s_img = self.source.geodata
            d_img = self.destination.geodata
        else:
            s_img = self.source.geodata.read_array()
            d_img = self.destination.geodata.read_array()

        source_image = (matches.iloc[0]['source_image'])

        # for each edge, calculate this for each keypoint pair
        for i, (idx, row) in enumerate(matches.iterrows()):
            s_idx = int(row['source_idx'])
            d_idx = int(row['destination_idx'])

            s_keypoint = self.source.get_keypoint_coordinates(s_idx)
            d_keypoint = self.destination.get_keypoint_coordinates(d_idx)

            # Get the template and search window
            s_template = sp.clip_roi(s_img, s_keypoint, template_size)
            d_search = sp.clip_roi(d_img, d_keypoint, search_size)
            try:
                x_offset, y_offset, strength = sp.subpixel_offset(s_template, d_search, **kwargs)
                self.matches.loc[idx, ('x_offset', 'y_offset',
                                       'correlation', 'reference')] = [x_offset, y_offset, strength, source_image]
            except:
                warnings.warn('Template-Search size mismatch, failing for this correspondence point.')
                continue

        # Compute the mask for correlations less than the threshold
        threshold_mask = self.matches['correlation'] >= threshold

        # Compute the mask for the point shifts that are too large
        query_string = 'x_offset <= -{0} or x_offset >= {0} or y_offset <= -{1} or y_offset >= {1}'.format(max_x_shift,
                                                                                                           max_y_shift)
        sp_shift_outliers = self.matches.query(query_string)
        shift_mask = pd.Series(True, index=self.matches.index)
        shift_mask.loc[sp_shift_outliers.index] = False

        # Generate the composite mask and write the masks to the mask data structure
        mask = threshold_mask & shift_mask
        self.masks = ('shift', shift_mask)
        self.masks = ('threshold', threshold_mask)
        self.masks = ('subpixel', mask)
Beispiel #18
0
    def compute_subpixel_offset(self, clean_keys=[], threshold=0.8, upsampling=16,
                                 template_size=19, search_size=53):
        """
        For the entire graph, compute the subpixel offsets using pattern-matching and add the result
        as an attribute to each edge of the graph.

        Parameters
        ----------
        clean_keys : list
             of string keys to masking arrays
             (created by calling outlier detection)

        threshold : float
                    On the range [-1, 1].  Values less than or equal to
                    this threshold are masked and can be considered
                    outliers

        upsampling : int
                     The multiplier to the template and search shapes to upsample
                     for subpixel accuracy

        template_size : int
                        The size of the template in pixels, must be odd

        search_size : int
                      The size of the search
        """

        matches = self.matches

        full_offsets = np.zeros((len(matches), 3))

        # Build up a composite mask from all of the user specified masks
        if clean_keys:
            mask = np.prod([self._mask_arrays[i] for i in clean_keys], axis=0, dtype=np.bool)
            matches = matches[mask]
            full_mask = np.where(mask == True)

        # Preallocate the numpy array to avoid appending and type conversion
        edge_offsets = np.empty((len(matches),3))

        # for each edge, calculate this for each keypoint pair
        for i, (idx, row) in enumerate(matches.iterrows()):

            s_idx = int(row['source_idx'])
            d_idx = int(row['destination_idx'])

            s_keypoint = self.source.keypoints.iloc[s_idx][['x', 'y']].values
            d_keypoint = self.destination.keypoints.iloc[d_idx][['x', 'y']].values

            # Get the template and search windows
            s_template = sp.clip_roi(self.source.handle, s_keypoint, template_size)
            d_search = sp.clip_roi(self.destination.handle, d_keypoint, search_size)

            try:
                edge_offsets[i] = sp.subpixel_offset(s_template, d_search, upsampling=upsampling)
            except:
                warnings.warn('Template-Search size mismatch, failing for this correspondence point.')
                continue

        # Compute the mask for correlations less than the threshold
        threshold_mask = edge_offsets[edge_offsets[:, -1] >= threshold]

        # Convert the truncated mask back into a full length mask
        if clean_keys:
            mask[full_mask] = threshold_mask
            full_offsets[full_mask] = edge_offsets
        else:
            mask = threshold_mask

        self.subpixel_offsets = pd.DataFrame(full_offsets, columns=['x_offset',
                                                                    'y_offset',
                                                                    'correlation'])
        self.masks = ('subpixel', mask)