| |
- builtins.object
-
- constitch.alignment.Aligner
-
- constitch.alignment.FFTAligner
- constitch.alignment.FeatureAligner
- constitch.alignment.PCCAligner
- constitch.composite.BBox
- constitch.composite.BBoxList
- constitch.composite.CompositeImage
- constitch.constraints.Constraint
- constitch.constraints.ConstraintFilter
- constitch.constraints.ConstraintSet
- constitch.merging.Merger
-
- constitch.merging.EfficientMeanMerger
- constitch.merging.EfficientNearestMerger
- constitch.merging.LastMerger
- constitch.merging.MeanMerger
- constitch.merging.NearestMerger
-
- constitch.merging.MaskMerger
- constitch.solving.Solver
-
- constitch.solving.LinearSolver
-
- constitch.solving.LPSolver
- constitch.solving.MAESolver
- constitch.solving.OptimalSolver
- constitch.solving.OutlierSolver
- constitch.solving.SpanningTreeSolver
- constitch.stage_model.ConversionStageModel(sklearn.base.BaseEstimator)
-
- constitch.stage_model.GlobalStageModel
- constitch.stage_model.SimpleOffsetModel
class Aligner(builtins.object) |
|
Abstract class that defines an algorithm for aligning two images onto each other. |
|
Methods defined here:
- align(self, constraint, precalc1=None, precalc2=None)
- Performs the alignment of two images, finding the pixel offset that best aligns the
two images. The offset should be from image1 to image2. The return value should be a Constraint
object, with at least the dx, dy fields filled in to represent the offset of image2 needed
to align the two images. If the function finds the images don't overlap, None should be returned.
If a constraint is specified, this method should only return a constraint that fits within the error
of given constraint, meaning within constraint.error pixels from the (constraint.dx, constraint.dy)
offset.
- precalculate(self, image, box)
- Performs an arbitrary precalculation step specific to the alignment algorithm.
This would be a step in the algorithm that only has to be run once per image,
and can be cached for each calculation done with the same image. The result of
this function will be passed to the align function as the precalc1 or precalc2 argument
- precalculate_if_needed(self, constraint, precalc1, precalc2)
- resize_if_needed(self, image, box=None, downscale_factor=None, padding=None)
- # Helper functions for subclasses:
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class BBox(builtins.object) |
|
BBox(position=None, size=None, point1=None, point2=None)
Represents the bounding box of an image in a CompositeImage. Contains two
representations of the box, as a position and a size and as two points point1 and point2
which define the bounding box. Both representations can be retrieved from and assigned to
at BBox.position, BBox.size, BBox.point1, BBox.point2, and a BBox can be constructed
from either. |
|
Methods defined here:
- __init__(self, position=None, size=None, point1=None, point2=None)
- Initialize self. See help(type(self)) for accurate signature.
- __repr__(self)
- Return repr(self).
- __str__(self)
- Return str(self).
- area(self)
- Returns the area of the box, basically self.size.prod()
However if the size of the rectangle is negative in either or both
dimentions the result will be negative, indicating an invalid rectangle
- as2d(self)
- Creates a copy of this box that only has two dimensions,
dropping extra values.
- collides(self, otherbox)
- Whether this box collides with the other box. This is defined as either
overlapping or sharing an edge
- contains(self, otherbox)
- Whether this box fully contains the other box, meaning every pixel in the other
box is also contained in this box
- copy(self)
- intersection(self, other)
- Returns the overlapping area between this box and the BBox other passed in
This may return boxes with negative size, which would indicate there is no overlap
- overlaps(self, otherbox)
- Whether this box overlaps with the other box. This does not consider
sharing an edge as overlapping, to count as overlapping there must be at least
one pixel that is contained in both images
Readonly properties defined here:
- center
- The center pixel of the image, rounded to the nearest pixel. Equivalent
to np.round(self.position + self.size / 2)
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
- point1
- The first position that defines the bounding box of the image.
When retrieved is identical to self.position.
Can be assigned to, however this is not the same as assigning to self.position.
When assigning self.point2 is maintained, meaning self.size will be changed.
The new size is calculated as self.position + self.size - value
Because of this difference in assignment behavior it cannot be updated
by indexing, ie box.point1[0] = 5 will fail.
- point2
- The second position that defines the bounding box of the image.
Calculated as self.position + self.size.
This can be assigned to, which will change the size of the image, keeping
self.point1 and self.position the same. The new size is calculated as
value - self._position
However it cannot be updated by indexing, ie box.point1[0] = 5 will fail.
- position
- The position of the image bounding box, measured from the
origin of the image, ie the (0, 0) pixel in the top left of
the image.
Setting the position will move the box to the new position, maintaning
the previous size. Additionally the position can be indexed and modified
in place, such as box.position[0] = 5. However care should be made sure to
not make a copy when indexing, as then changes will not take effect.
- size
- The size of the image bounding box, the (width, height) of the image
This can be assigned to, modifying the box size. As with BBox.position,
it can be indexed and assigned to as well.
|
class BBoxList(builtins.object) |
|
BBoxList(positions=None, sizes=None)
A list of image bounding boxes, countained in a ConstraintImage.
Supports normal list operations such as indexing, len, index, as well
as bulk operations on all boxes with the numpy array properties
BBoxList.positions, BBoxList.sizes, and similar |
|
Methods defined here:
- __contains__(self, box)
- __getitem__(self, index)
- __init__(self, positions=None, sizes=None)
- Initialize self. See help(type(self)) for accurate signature.
- __iter__(self)
- __len__(self)
- __repr__(self)
- Return repr(self).
- __str__(self)
- Return str(self).
- append(self, box)
- Add a new BBox to this list. Typically users should not need to use
this, instead add images through the CompositeImage.add_images and similar
methods
- copy(self)
- index(self, box)
- resize(self, n_dims)
- Changes the number of dimensions all boxes in the list have. It is enforced
that all boxes in the list have the same number of dimensions. When adding a dimension
it is filled with zeros
- setpositions(self, positions)
- Applies new positions to all boxes
Args:
positions (sequence of positions, dict of positions, callable):
Specifies a change in positions for boxes, depending on the type:
If a numpy array, the new positions are set as self.positions, maintaining sizes of boxes.
If a dict of positions, each entry will be set as the position of the box at the key.
If a callable, it is invoked for each box. If it returns a new position it is applied to the box
Readonly properties defined here:
- centers
- The center pixel of all image boxes, rounded to the nearest pixel.
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
- points1
- The lower point of all bounding boxes in the list as a 2d array. See BBox.point1.
- points2
- The higher point of all bounding boxes in the list as a 2d array. See BBox.point2.
Setting this will update all sizes, same as assigning to BBox.point2
- positions
- The positions of all boxes in the list, as a 2d numpy array. See BBox.position
for specifics about the positions of the boxes.
Setting this will update all positions, as well as modifying slices, such
as self.positions[:,0] += 100 would increase all x positions by 100.
- sizes
- The sizes of all boxes in the list as a 2d array. See BBox.size.
Setting this will update all sizes, same as assigning to BBox.size
|
class CompositeImage(builtins.object) |
|
CompositeImage(images=None, positions=None, boxes=None, scale='pixel', channel_axis=None, grid_size=None, tile_shape=None, overlap=0.1, aligner=None, precalculate=False, debug=True, progress=False, executor=None)
This class encapsulates the whole stitching process, the smallest example of stitching is
shown below:
composite = constitch.CompositeImage()
composite.add_images(images)
composite.calc_constraints()
composite.filter_constraints()
composite.solve_constraints(filter_outliers=True)
full_image = composite.stitch_images()
This class is meant to be adaptable to many different stitching use cases, and each step
can be customized and configured. The general steps for the stitching of a group images are as follows:
Creating the composite
To begin we have to instantiate the CompositeImage class.
The full method signature can be found at
__init__() but some important parameters are described below:
The executor is what the composite uses to perform intensive computation
tasks, namely calculating the alignment of all the images. If provided
it should be a concurrent.futures.Executor object, for example
concurrent.futures.ThreadPoolExecutor. Importantly, concurrent.futures.ProcessPoolExecutor
does not work very well as the images need to be passed to the executor
and in the case of ProcessPoolExecutor this means they need to be pickled
and unpickled to get to the other process. ThreadPoolExecutor doesn't need
this as the threads can share memory, but it doesn't take full advantage of
multithreading as the python GIL prevents python code from running in parallel.
Luckily most of the intensive computation happens in numpy functions which don't
hold the GIL, so ThreadPoolExecutor is usually the best choice.
The arguments debug and process define how logging should happen with the composite.
If debug is True logging messages summarizing the results of different operations
will be printed out to stderr. Setting it to False will disable these messages.
If process is True a progress bar will be printed out during long running steps.
The default progress bar is a simple ascii bar that works whether the output is
a tty or a file, but if you want you can pass a replacement in instead of setting
it to True, such as tqdm.
An example of setting up the composite would be something similar to this:
import constitch
import concurrent.futures
import tqdm
with concurrent.futures.ThreadPoolExecutor(max_workers=32) as executor:
composite = constitch.CompositeImage(executor=executor, debug=True, progress=tqdm.tqdm)
Adding the images
Once the composite is set up we can add the images, and this is done through the add_images()
method. There are a couple ways of adding images, depending on how much information you have on the images:
First of all, you can just add the images with no positions, meaning they will all default to being at 0,0.
This will work out, as when you calculate constraints between images it will calculate constraints for all
possible images and filter out constraints that have no overlap. However the number of constraints that have
to be calculated grows exponentially with the number of images, and if you have positional information on your
images it is best to pass that in to help with the alignment. If you would like to use this method but are running
into computational limits, the section on pruning constraints below can be helpful.
composite.add_images(images)
If your images are taken on a grid you can pass in their positions as grid positions, by setting the scale
parameter to 'tile'. For example:
positions=[(0,0), (0,1), (1,0), (1,1)]
composite.add_images(images, positions=positions, scale='tile')
Now when constraints are calculated only nearby images will be checked, speeding up computation greatly.
If your images are not on a grid or you have the exact position they were taken in, you can also specify
positions in pixels instead of grid positions, to do this simply set the scale parameter to 'pixel'
and the positions passed in will be interpreted as pixel coordinates. When specifying pixel specific
positions another parameter that is available is the uncertainty of the provided positions. If you know
to the pixel where each image is you probably don't have a need for this library, but there is still a
wide range of possibilities, from being precise to a couple pixels to only providing the general locations.
The error on positions can be provided to add_images with the keyword argument positional_error or by directly
setting CompositeImage.positional_error. This will be a pixel value that acts as error bars, meaning the
image positions are plus or minus that value.
When specifying positions, you can also specify more than two dimensions. The first two are the x and y
dimensions of the images, but a z dimension can be added if you are doing 3 dimensional stitching or in our case
if you are doing fisseq and want to make sure all the cycles line up perfectly. In the case of fisseq,
you can add the cycle index as the z coordinate for the image.
Calculating constraints
Once images have been added we need to calculate the constraints between overlapping images.
Creating, calculating, filtering, and solving constraints is an integral part of the stitching
algorithm, and a subpackage is dedicated to them, constitch.constraints. This module contains the
Constraint class, as well as the ConstraintSet and ConstraintFilter classes. Here we will go over the
typical usage of them but for more information consult constitch.constraints.
The core idea of constraints is that each constraint stores a positional offset between two images, "constraining"
them to have that difference in positions. Constraints are useful for stitching because most alignment algorithms
only work with a pair of images, meaning they take as input and provide as output constraints.
We can always create new constraints using the attribute CompositeImage.constraints, which generates
constraints using the image positions specified in the composite. To retrieve constraints between all touching
images we can do:
overlapping = composite.constraints(touching=True)
The constraints here are considered "implicit" constraints as they were created from the provided image positions,
which are not precise. The variable overlapping is a ConstraintSet class, which acts similar to a dictionary, holding
a set of constraints. Specific constraints can be retrieved by indexing into the set with the indices of the two images
the constraint is between, eg overlapping[1,2] will return the constraint between image 1 and image 2 in composite.
As mentioned before these constraints are not precise, and the next step in stitching is passing
them to an alignment algorithm to refine them. This is done with the ConstraintSet.calculate()
method, like so:
constraints = overlapping.calculate()
This creates a new ConstraintSet constraints, which holds all our new constraints generated by the Aligner class
passed to calculate. By default constitch.FFTAligner() is used, which runs the phase correlation algorithm to
find the offset with the maximum correlation.
Filtering constraints
With the constraints calculated we can filter out any erroneous constraints using the constraint scores:
constraints = constraints.filter(min_score=0.5)
This will only keep constraints with a score >= 0.5, which should eliminate almost all of the constraints
that are not accurate. To futher filter the constraints we can fit a linear model to the constraints that remain:
stage_model = constraints.fit_model(outliers=True)
constraints = stage_model.inliers
When fitting a linear model to the constraints, we can use an outlier resistant model by specifying outliers=True,
which uses RANSAC to classify some constraints as outliers. We can additionally use the stage model to estimate
constrains that were filtered out before:
model_constraints = overlapping.calculate(stage_model)
As you can see here, the stage_model is an Aligner class that can be used to calculate new constraints,
with the same interface as the FFTAligner. We can merge these two constraint sets together to replace any
constraints that were filtered out with the modeled constraints:
constraints = constraints.merge(model_constraints)
Solving constraints
The final step is to solve the constraints that have been calculated, which we can do with the ConstraintSet.solve()
method. This converts each constraint into two linear equations, and solves the system of equations to find the
image positions that minimize alignment error. We can then apply these positions to the composite with CompositeImage.setpositions():
solution = constraints.solve()
composite.setpositions(solution)
Creating the final image
To get the final merged composite image we can call the CompositeImage.stitch() function, which combines all individual images
based on the current image positions:
final_image = composite.stitch()
The method that this function merges the images together can be configured by passing a Merger instance,
by default it will use MeanMerger. More information on mergers can be found in the docs of the constitch.Merger class
and the constitch.merging module.
For each of these steps there are many different parameters to configure the behaviour, make sure to check out the documentation
for each method to see the details on how they work. |
|
Methods defined here:
- __init__(self, images=None, positions=None, boxes=None, scale='pixel', channel_axis=None, grid_size=None, tile_shape=None, overlap=0.1, aligner=None, precalculate=False, debug=True, progress=False, executor=None)
- Initialize self. See help(type(self)) for accurate signature.
- add_image(self, image, position=None, box=None, scale='pixel', imagescale=1)
- add_images(self, images, positions=None, boxes=None, scale='pixel', channel_axis=None, imagescale=1)
- Adds images to the composite
Args:
images (np.ndarray shape (N, W, H) or list of N np.ndarrays shape (W, H) or list of strings):
The images that will be stitched together. Can pass a list of
paths that will be opened by imageio.v3.imread when needed.
Passing paths will require less memory as images are not stored,
but will increase computation time.
positions (np.ndarray shape (N, D) ):
Specifies the extimated positions of each image. The approx values are
used to decide which images are overlapping. These values are interpreted
using the scale argument, default they are pixel values.
boxes (sequence of BBox):
An alternative to specifying the positions, the full bounding boxes of every image can also
be passed in. The units of the boxes are interpreted the same as image positions,
with the scale argument deciding their relation to the scale of pixels.
scale ('pixel', 'tile', float, or sequence):
The scale argument is used to interpret the position values given.
'pixel' means the values are pixel values, equivalent to putting 1.
'tile' means the values are indices in a tile grid, eg a unit of 1 is
the width of an image.
a float value means the position values are a units where one unit is
the given number of pixels.
If a sequence is given, each element can be any of the previous values,
which are applied to each axis.
- add_split_image(self, image, grid_size=None, tile_shape=None, overlap=0.1, channel_axis=None)
- Adds an image split into a number of tiles. This can be used to divide up
a large image into smaller pieces for efficient processing. The resulting
images are guaranteed to all be the same size.
A common pattern would be:
composite.add_split_image(image, 10)
for i in range(len(composite.images)):
composite.images[i] = process(composite.images[i])
result = composite.stitch_images()
image: ndarray
the image that will be split into tiles
grid_size: int or (int, int)
the number of tiles to split the image into. Either this or tile_shape
should be specified.
tile_shape: (int, int)
The shape of the resulting tiles, if grid_size isn't specified the maximum
number of tiles that fit in the image are extracted. Whether specified or not,
the size of all tiles created is guaranteed to be uniform.
overlap: float, int or (float or int, float or int)
The amount of overlap between neighboring tiles. Zero will result in no overlap,
a floating point number represents a percentage of the size of the tile, and an
integer number represents a flat pixel overlap. The overlap is treated as a lower bound,
as it is not always possible to get the exact overlap requested due to rounding issues,
and in some cases more overlap will exist between some tiles
- align_disconnected_regions(self, num_test_points=0.05, expand_range=5)
- Looks at the current constraints in this composite and sees if there are any images or
groups of images that are fully disconnected from the rest of the images. If any are found,
they are attempted to be joined back together by calculating select constraints between the
two groups
- calc_score_threshold(self, num_samples=None, random_state=12345)
- Estimates a threshold for selecting constraints with good overlap.
Done by calculating random constraints and using a gaussian mixture model
to distinguish random constraints from real constraints
Args:
num_samples (float): optional
The number of fake constraints to be generated, defaults to 0.25*len(images).
In general the more samples the better the estimate, at the expense of speed
random_state (int): Used as a seed to get reproducible results
Returns (float):
threshold for score where all scores lower are likely to be bad constraints
- constraint_error(self, i, j, constraint)
- copy(self, **kwargs)
- Creates a full copy of this composite. The only thing shared between this composite
and the new copy is the raw image data.
- html_summary(self, path, score_func=None)
- layer(self, index)
- Returns a SubComposite with only images that are on the specified layer, that is
all images where box.position[2] == index.
Layers can be created when calling merge() with new_layer=True
or manually by specifying a third dimension when adding images
- merge(self, other_composite, *other_constraint_sets, new_layer=False, align_coords=False)
- Adds all images and constraints from another montage into this one.
other_composite: CompositeImage
Another composite instance that will be added to this one. All images from
it are added to this instance. All image positions are added, mantaining
the scale_factors of both composites.
Returns: list of indices
returns the list of indices of the images added from the other composite.
- pair_func(self)
- plot_scores(self, path, constraints=None, score_func=None, axis_size=12, constraint_multiplier=1)
- print_mem_usage(self)
- random_pair_func(self)
- resized_image(self, index, scale_x, scale_y)
- Returns the image at self.images[index] but upscaled or downscaled
by scale_x and scale_y.
Args:
index (int): index of image
scale_x (int, float, fractions.Fraction): The scale multiplier across the x axis
scale_x (int, float, fractions.Fraction): The scale multiplier across the y axis
- score_heatmap(self, path, score_func=None)
- set_aligner(self, aligner, rescore_constraints=False)
- set_executor(self, executor)
- set_logging(self, debug=True, progress=False)
- set_scale(self, scale_factor)
- Sets the scale factor of the composite. Normally this doesn't need to be changed,
however if you are trying to stich together images taken at different magnifications you
may need to modify the scale factor.
scale_factor: float or int
Scale of images in this composite, as a multiplier. Eg a scale_factor of
10 will result in each pixel in images corresponding to 10 pixels in the
output of functions like `CompositeImage.stitch_images()` or when merging composites together.
- setimages(self, images)
- Updates the images of this composite.
images (sequence or dict): The new images to be set
If a sequence, it must be the current length of self.images. Each
image is updated with the corresponding new image in the sequence.
If a dict, it must map from indices within the range [0, len(self.images))
to new images, that are set at said indices.
All images must be numpy arrays of shape either (W, H) or (W, H, C).
- setpositions(self, positions)
- Applies new positions to images in this composite. positions is either a dict
mapping image indices to new positions, a sequence of new positions, or a constitch.Solver
class that has had solve() run on it, usually from ConstraintSet.solve
- stitch(self, merger='mean', indices=None, real_images=None, out=None, bg_value=None, return_bg_mask=False, mins=None, maxes=None, keep_zero=False)
- Combines images in the composite into a single image
merger: str or merging.Merger instance
The merger used to combine overlapping regions of images. If a string it is mapped to a Merger
class as follows:
"mean": merging.MeanMerger,
"efficient_mean": merging.EfficientMeanMerger,
"last": merging.LastMerger,
"nearest": merging.NearestMerger,
"efficient_nearest": merging.EfficientNearestMerger,
indices: sequence of int
Indices of images in the composite to be stitched together
real_images: sequence of np.ndarray
An alternative image list to be used in the stitching, instead of
the stored images. Must be same length and each image must have the
first two dimensions the same size as self.images
bg_value: scalar or array
Value to fill empty areas of the image.
return_bg_mask: bool
If True a boolean mask of the background, pixels with no images
in them, is returned.
keep_zero: bool
Whether or not to keep the origin in the result. If true this could
result in extra blank space, which might be necessary when lining up
multiple images.
Returns: np.ndarray
image stitched together
- subcomposite(self, indices, **kwargs)
- Returns a new composite with a subset of the images and constraints in this one.
The images and positions are shared, so modifing them on the new composite will
change them on the original.
indices: sequence of ints, sequence of bools, function
A way to select the images to be included in the new composite. Can be:
a sequence of indices, a sequence of boolean values the same length as images,
kwargs: arguments passed to the constructor of the subcomposite
- to_obj(self)
Class methods defined here:
- from_obj(obj, **kwargs) from builtins.type
Readonly properties defined here:
- positions
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class Constraint(builtins.object) |
|
Constraint(composite, index1=None, index2=None, dx=None, dy=None, score=None, error=None, type=<ConstraintType.NORMAL: 'normal'>)
A class to represent the pixel offset between two images in a composite.
The Constraint is an important component of the ConStitch algorithm, and converting
from global positions of images to a set of constraints between images and back
is the main algorithm used to stitch image sets.
It is not normally necessary to instantiate Constraint objects directly, instead
they are created from the existing image positions with CompositeImage.constraints
or by calculating new constraints with the Constraint.calculate or ConstraintSet.calculate
functions.
The class ConstraintSet is used as a container to manipulate and filter large collections
of constraints
Fields:
composite (Composite): A reference to the composite that holds the images of this constraint
index1 (int): The index in the composite to the first image.
This index will always be less than index2, if index1 > index2 then
the constraint should have been created swapping index1 and index2
index2 (int): The index in the composite to the second image
dx (int): X coordinate offset from image1 to image2
This offset is measured from the pixel at 0,0 of image1
to the pixel at 0,0 of image2, or put another way the
offset is measured from the position of the box of the first image
to the position of the box of the second image
dy (int): Y coordinate offset from image1 to image2
Measured the same way as dx, from the 0,0 pixel in image1
to the 0,0 pixel in image2, or from box1.position to box2.position
score (float): A value that relatively scores how well the alignment is
This score is generated by the alignment algorithm, to allow for filtering
and weighting of constraints based on it. Constraints calculated
from existing image positions will have a score of None
error (int): The uncertanty of the specified alignment
This error value is treated as an uncertanty, saying the true alignment
is equal to (dx ± error, dy ± error). This is typically zero
unless the images were downscaled, and the uncertanty of original
image positions can be specified by the user. When calculating new constraints
only offsets that fall within these bounds are considered, see section1 and section2
for more information on how |
|
Methods defined here:
- __init__(self, composite, index1=None, index2=None, dx=None, dy=None, score=None, error=None, type=<ConstraintType.NORMAL: 'normal'>)
- Initialize self. See help(type(self)) for accurate signature.
- __repr__(self)
- Return repr(self).
- __str__(self)
- Return str(self).
- calculate(self, aligner=None, executor=None)
- Calculates a new constraint using the specified alignment algorithm.
More information on how alignment is performed can be found at constitch.alignment
- new(self, dx=None, dy=None, score=None, error=None, type=None)
- Creates a new constraint between the images of this one. Normally used
by alignment algorithms when they calculate a
new constraint
Params:
dx, dy, score, error, type: See docs for Constraint.__init__()
- new_rescaled(self, dx=None, dy=None, score=None, error=None, type=None)
- Creates a new constraint, similar to Constraint.new. This method is used when
the new constraint was calculated using Constraint.resized_image1 and Constraint.resized_image2,
normally when aligning in an Aligner. This means that dx and dy are expected to be
the offsets in these resized images, and they are converted into an offset in the original image,
taking into account the amount each image has been resized. The error is also adjusted, eg
if the alignment in the rescaled images is accurate to 8 pixels but the images were upscaled by
4 pixels, the true error would be 2
- new_section(self, dx=None, dy=None, score=None, error=None, type=None)
- Creates a new constraint, similar to Constraint.new. This method is used when
the new constraint was calculated using Constraint.section1 and Constraint.section2,
normally when aligning in an Aligner. This means that dx, dy, and error are expected to be
relative to the coordinate space of the sections, and are converted into an offset and error for the whole image,
taking into account the bounds of the sections and the amount each image has been
resized
- to_obj(self)
Readonly properties defined here:
- box1
- Retrieves the box of image1 from the composite,
equivalent to self.composite.boxes[self.index1]
- box2
- Retrieves the box of image2 from the composite,
equivalent to self.composite.boxes[self.index2]
- difference
- The difference between the offset specified in this constraint and the
difference in positions of the images currently, from self.box1 and self.box2.
If this constraint was calculated using an alignment algorithm this is the
correction the alignment algorithm applied, and if this is after the global
positions of the images have been solved then this is the error present when
solving for the positions
- image1
- Retrieves the image1 from the composite,
equivalent to self.composite.images[self.index1]
- image2
- Retrieves the image2 from the composite,
equivalent to self.composite.images[self.index2]
- implicit
- Whether or not this constraint is implicit, meaning it was calculated
from existing image positions and was not calculated using an alignment
algorithm
- length
- The length of the offset between images, sqrt(dx^2 + dy^2)
- modeled
- overlap
- The overlap of the two images, in total number of pixels. If the images
don't overlap, it will be negative
- overlap_ratio
- The overlap of the two images, as a ratio of the number of pixels overlapping
over the maximum possible number of pixels overlapping
- overlap_ratio_x
- The overlap of the two images across the x axis, as a ratio of the image size.
If the images are different sizes it is a ratio with the smaller images size.
- overlap_ratio_y
- The overlap of the two images across the y axis, as a ratio of the image size.
If the images are different sizes it is a ratio with the smaller images size.
- overlap_x
- The overlap of the two images across the x axis, in pixels
- overlap_y
- The overlap of the two images across the y axis, in pixels
- pair
- The two indices of the images in the composite as a tuple
- pixel_scale_ratio
- The difference in pixel scale between image1 and image2. For example
if image2 was taken with 2x the magnification and thus each pixel is
half the size of each pixel in image1, the scale ratio would be 2 / 1
as image2 would need to be scaled up by 2 to have the same pixel size.
The ratio is returned as a fractions.Fraction for the x and y axes.
- resized_image1
- Retrieves the first image of the constraint, resizing it so that
the scale of pixels between image1 and image2 is the same.
This may require computing the resized image, but it will be cached
in the composite and any subsequent calls will not require any calculation
- resized_image2
- Retrieves the first image of the constraint, resizing it so that
the scale of pixels between image1 and image2 is the same.
This may require computing the resized image, but it will be cached
in the composite and any subsequent calls will not require any calculation
- section1
- Returns the section of image1 relevant for alignment, that is the
section of image1 that overlaps with image2, expanded to include self.error,
and resized so that both sections have the same pixel scale.
If error is infinite or None this will be the same as self.resized_image1.
Usually used by the alignment algorithm when calculating new constraints,
see the docs for Aligner for more info
- section1_bounds
- section2
- Returns the section of image2 relevant for alignment, that is the
section of image2 that overlaps with image1, expanded to include self.error,
and resized so that both sections have the same pixel scale.
If error is infinite or None this will be the same as self.resized_image1.
- section2_bounds
- touching
- True if the images are either overlapping (self.overlap > 0) or touching
along the x or y axis (self.overlap_x > 0 or self.overlap_y > 0)
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class ConstraintFilter(builtins.object) |
|
ConstraintFilter(obj=None, **kwargs)
A class that represents a filter on constraints. Can be a threshold
on a attribute of constraints, eg ConstraintFilter(min_score=0.5),
a required value or constraint type, eg ConstraintFilter(touching=True, implicit=True),
or a custom function that returns a bool, eg ConstraintFilter(lambda const: const.box1.position[0] < 5000)
Filters can be created and combined with & or | and passed to ConstraintSet.filter() to select for
specific constraints. |
|
Methods defined here:
- __and__(self, other)
- Combines two filters, creating a new filter that evaluates
to True when both others evaluate to True
- __call__(self, constraint)
- Evaluates the filter on a constraint.
Returns whether or not the constraint should be kept.
- __init__(self, obj=None, **kwargs)
- A filter can be constructed in multiple ways:
ConstraintFilter(params)
ConstraintFilter(**kwargs)
Constructing with a dictionary of parameters. Each entry in the
dictionary or keyword parameter must be an attribute of a Constraint
instance, optionally prepended with min_ or max_.
When filtering, the specified attribute will be retrieved from each constraint
and compared to the value passed here. If prepended with min_ values greater or equal
will be kept and if prepended with max_ values less than or equal will be kept,
otherwise only values that are equal are kept.
For example, the filter ConstraintFilter(min_score=0.5) will keep constrains where
constraint.score >= 0.5 is True.
When multiple parameters are specified, only constraints that match all parameters
will be kept. If you want to match either parameter, create multiple filters and combine
them, eg ConstraintFilter(touching=True) | ConstraintFilter(min_score=0.5)
ConstraintFilter(func)
Constructing from a function. The passed function is evaluated for each constraint,
if True the constraint is kept. This has the same behaviour as the builtin filter()
- __or__(self, other)
- Combines two filters, creating a new filter that evaluates
to True when either other filters evaluate to True
- __str__(self)
- Return str(self).
- alwaystrue(self)
- fromdict(self, params)
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class ConstraintSet(builtins.object) |
|
ConstraintSet(constraints=None)
A class that stores a set of constraints
Many important algorithms when stitching revolve around manipulating
sets of constraints, thus we have the class ConstraintSet to represent
collections of Constraints and filter/manipulate them. A ConstraintSet
behaves mostly like a dictionary mapping pairs of images to Constraints.
ConstraintSets are normally created from CompositeImage.constraints
or ConstraintSet.calculate, but they can be instantiated with any
sequence of Constraints |
|
Methods defined here:
- __contains__(self, obj)
- Tests if a Constraint or a pair is contained
- __getattr__(self, name)
- Some attributes of Constraint can be accessed from a ConstraintSet, returned as a numpy
array of the values for all constraints, in the order of self.keys()
- __getitem__(self, pair)
- __init__(self, constraints=None)
- Initialize self. See help(type(self)) for accurate signature.
- __iter__(self)
- Iterates through all constraints in this set
- __len__(self)
- add(self, other)
- Add constraints to this set
If a constraint between the same images is already present, the constraint
with the lower error is kept and the other is removed.
In the case of equal errors the new constraint is kept
Args:
other (Constraint or sequence of Constraints): Constraint or Constraints to add
Raises:
ValueError: The constraint(s) to be added are from a different CompositeImage
- calculate(self, aligner=None, executor=None)
- Calculates new constraints using an alignment algorithm
For every constraint the provided aligner is invoked to calculate
a new constraint. See constitch.alignment for more information on
alignment.
Args:
aligner (constitch.Aligner): default self.composite.aligner
The aligner that is used to calculate the new constraints
executor (concurrent.futures.Executor): default self.composite.executor
A thread or process pool instance to parallelize the computation,
as some aligners can be quite slow
- debug(self, *args, **kwargs)
- A shorthand for self.composite.debug
- filter(self, obj=None, limit=None, random=False, sorted_by=None, **kwargs)
- Returns a new ConstraintSet with only constraints that are
matching the specified filter.
Either a ConstraintFilter instance can be passed in or an object that
can be converted into a filter, ie a dictionary or a set of keyword arguments.
See ConstraintFilter for the full documentation on creating a filter.
Args:
obj: The filter or object to be converted into a filter. Can be many types:
If it is a ConstraintFilter or a callable it is applied as the filter
If it is a numpy bool array, it is used to filter constraint, mapping with
the order of self.constraints
If it is a set or list of pairs of indices, only constraints for those pairs are kept
limit (int): The maximum number of constraints returned
random (bool): If true the constraints are shuffled
Normally used in conjunction with the limit argument to select a random
sample of the constraints
sorted_by (function or str): key to sort constraints on
Either a function that can be passed as a key to sorted() or a string
that is an attribute of a constraint. Used to sort the constraints, normally
used with the limit argument
kwargs: Any keyword arguments are passed to a new ConstraintFilter() constructor
and applied as a filter
Returns:
A new ConstraintSet with the filtered Constraints
- find(self, obj=None, **kwargs)
- Returns the first constraint to match a filter
Uses the same interface as self.filter but returns the first
constraint that matches the filter
- fit_model(self, model=None, outliers=False, random_state=12345)
- Fits a linear model to the constraints in this set
This learns the motion of the microscope stage, which can be used to fill in
constraints in areas where there are not enough features to align.
The model is trained on the relation between the offset in image positions,
that is box2.position - bos1.position, and the offset specified in dx and dy.
Args:
model (sklearn base model): default constitch.SimpleOffsetModel()
The linear model to train, it should be a sklearn model class, meaning
it has a fit and predict method. The fit method is called
with X as a 4 column matrix containing the x and y positions of image1 and image2
for all constraints, and y as a 2 column matrix with dx and dy for all constraints
outliers (bool): Whether to use an outlier resistant model
If set to True the provided model is wrapped in sklearn.linear_model.RANSACRegressor,
and the inlier and outlier classifications are added onto the returned
result as result.inliers and result.outliers. These are new ConstraintSets
containing only the inliers and outliers that the model classified
random_state: the random state passed to RANSACRegressor when outliers=True
Returns:
An Aligner class that can be used to calculate new constraints, using
the linear model fit here.
- items(self)
- keys(self)
- merge(self, other, *others)
- Returns a new ConstaintSet with combined constraints from this and other sets
As with add(), if constraints between the same image pair are present in both sets
then the constraint with the lowest error is kept, with ties defaulting to constraints in the
last passed in set
Args:
other (Constraint or sequence of Constraints): Constraint or Constraints to
merge with new set
Raises:
ValueError: The constraints to be merged are from a different ConstraintImage
- neighborhood_difference(self, constraint)
- A metric that measures how well this constraint matches the image
positions, taking into account neighboring constraints.
- neighboring(self, constraint, depth=1)
- Returns a new ConstraintSet containing only constraints that
are connected to an initial constraint or image
The starting location is specified by passing either a constraint, a
image index, or a sequence of either. Constraints are added by BFS to
the requested depth. Any constraints provided as a starting location
are not included in the resulting set
- progress(self, iter, **kwargs)
- A shorthand for self.composite.progress
- remove(self, other)
- Remove constraints from this set
Args:
other (Constraint, (int, int) or sequence of either):
The constraints or pairs to be removed
Raises:
KeyError: The specified constraint does not exist
- solve(self, solver='mae', **kwargs)
- Solve the constraints to get a global position for each image
Args:
solver (constitch.Solver or str): default constitch.LinearSolver()
The solver method that is used to combine the overconstrainted
system of constraints and optimize for the best global positions.
Options include 'mse' for standard least squares solving, 'mae'
for solving while minimizing mean absolute error, 'huber' for
minimizing the huber loss, or any subclass of constitch.Solver.
More info can be found in constitch.solving
**kwargs: Arguments passed to the constructor of the solver.
Any arguments specified here are passed to the constructor
of the solver, for example if solver='huber' epsilon=5 could
be included to change the default epsilon parameter for huber loss.
Cannot be specified if solver is an already instantiated constitch.Solver
instance.
Returns:
The solver instance, with an attribute positions containing a dict
mapping image indices to their global positions
- values(self)
Readonly properties defined here:
- composite
- The composite that contains all the images of the constraints of this
set. If constraints from a different constraint are added, an error will be
raised. If this instance contains no constraints this will return None
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
Data and other attributes defined here:
- ATTRS = ['dx', 'dy', 'score', 'error', 'overlap', 'overlap_x', 'overlap_y', 'overlap_ratio', 'overlap_ratio_x', 'overlap_ratio_y', 'size', 'difference']
|
class EfficientMeanMerger(Merger) |
|
A version of MeanMerger that does not require double the memory, however there is a small loss of
precision as calculation errors can add up as images are merged. It is recommended to start with
MeanMerger and if memory becomes an issue switch to this one. |
|
- Method resolution order:
- EfficientMeanMerger
- Merger
- builtins.object
Methods defined here:
- add_image(self, image, location)
- Called to add an image. location is a tuple of slices used
to select the area for the image, it is guaranteed to be the
same size as image.
- create_image(self, image_shape, image_dtype)
- Init is called with the shape of the final image (may be
more than 2d) and the dtype. Normally a merger would create
an image using this information.
- final_image(self)
- Called once to get the final image. It will only be called
once when stitching, so final processing can take place and modify
the stored image. Returns the final image and a mask for pixels that
had no images.
Data descriptors inherited from Merger:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class EfficientNearestMerger(Merger) |
|
This merger does the same as the NearestMerger but it does it with only an extra array of
uint8, halfing the extra memory requirements. The downside is that it will only trim up to 255
pixels away from the edge of images, so if the overlap between your images is much larger than
this, this merger will not give the same results. |
|
- Method resolution order:
- EfficientNearestMerger
- Merger
- builtins.object
Methods defined here:
- add_image(self, image, location)
- Called to add an image. location is a tuple of slices used
to select the area for the image, it is guaranteed to be the
same size as image.
- create_image(self, image_shape, image_dtype)
- Init is called with the shape of the final image (may be
more than 2d) and the dtype. Normally a merger would create
an image using this information.
- final_image(self)
- Called once to get the final image. It will only be called
once when stitching, so final processing can take place and modify
the stored image. Returns the final image and a mask for pixels that
had no images.
Data descriptors inherited from Merger:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class FFTAligner(Aligner) |
|
FFTAligner(num_peaks=2, precalculate_fft=True, downscale_factor=None, upscale_factor=1)
An aligner that uses the phase cross correlation algorithm to estimate the proper alignment of two images.
The algorithm is the same as described in Kuglin, Charles D. "The phase correlation image alignment method."
http://boutigny.free.fr/Astronomie/AstroSources/Kuglin-Hines.pdf |
|
- Method resolution order:
- FFTAligner
- Aligner
- builtins.object
Methods defined here:
- __init__(self, num_peaks=2, precalculate_fft=True, downscale_factor=None, upscale_factor=1)
- num_peaks: int default 2
Sets the number of peaks in the resulting phase cross correlation image to be checked. Sometimes the highest
peak is not actually the best offset for alignment so checking multiple peaks can help find the one that
has the highest ncc score. Increasing this will also increase processing time, possibly dramatically.
precalculate_fft: bool default True
Whether or not the FFT of the images should be precalculated and cached or be calculated every time.
The FFT is able to be precalculated however it does take up a large amount of memory, so if memory
is a limiting factor setting this to False can help
downscale_factor: int, optional
This algorithm is rather slow when calculating large numbers of constraints, and one way to improve
speed is by downscaling the images before running the algorithm. This will improve runtime at the expense
of precision, the constraints calculated will have a nonzero error value. Also, if the downscale factor
is large enough the algorithm can begin to fail and not find any overlap, in general the largest recommended
value is around 32, but it depends on how large the features in your images are.
- align(self, constraint, precalc1=None, precalc2=None)
- Performs the alignment of two images, finding the pixel offset that best aligns the
two images. The offset should be from image1 to image2. The return value should be a Constraint
object, with at least the dx, dy fields filled in to represent the offset of image2 needed
to align the two images. If the function finds the images don't overlap, None should be returned.
If a constraint is specified, this method should only return a constraint that fits within the error
of given constraint, meaning within constraint.error pixels from the (constraint.dx, constraint.dy)
offset.
- align_full(self, constraint, precalc1=None, precalc2=None)
- precalculate(self, image, box=None)
- Performs an arbitrary precalculation step specific to the alignment algorithm.
This would be a step in the algorithm that only has to be run once per image,
and can be cached for each calculation done with the same image. The result of
this function will be passed to the align function as the precalc1 or precalc2 argument
Methods inherited from Aligner:
- precalculate_if_needed(self, constraint, precalc1, precalc2)
- resize_if_needed(self, image, box=None, downscale_factor=None, padding=None)
- # Helper functions for subclasses:
Data descriptors inherited from Aligner:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class FeatureAligner(Aligner) |
|
FeatureAligner(num_features=2000)
|
|
- Method resolution order:
- FeatureAligner
- Aligner
- builtins.object
Methods defined here:
- __init__(self, num_features=2000)
- Initialize self. See help(type(self)) for accurate signature.
- align(self, constraint, precalc1=None, precalc2=None)
- Performs the alignment of two images, finding the pixel offset that best aligns the
two images. The offset should be from image1 to image2. The return value should be a Constraint
object, with at least the dx, dy fields filled in to represent the offset of image2 needed
to align the two images. If the function finds the images don't overlap, None should be returned.
If a constraint is specified, this method should only return a constraint that fits within the error
of given constraint, meaning within constraint.error pixels from the (constraint.dx, constraint.dy)
offset.
- precalculate(self, image, box=None)
- Performs an arbitrary precalculation step specific to the alignment algorithm.
This would be a step in the algorithm that only has to be run once per image,
and can be cached for each calculation done with the same image. The result of
this function will be passed to the align function as the precalc1 or precalc2 argument
Methods inherited from Aligner:
- precalculate_if_needed(self, constraint, precalc1, precalc2)
- resize_if_needed(self, image, box=None, downscale_factor=None, padding=None)
- # Helper functions for subclasses:
Data descriptors inherited from Aligner:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class GlobalStageModel(ConversionStageModel) |
|
GlobalStageModel(model=None)
Stage model that takes into account the global positions of the
two images, by passing both image positions to the model unchanged.
This is equivalent to just using the internal model directly, this is
just a separate class for documentation and consistency. |
|
- Method resolution order:
- GlobalStageModel
- ConversionStageModel
- sklearn.base.BaseEstimator
- builtins.object
Methods defined here:
- __init__(self, model=None)
- Initialize self. See help(type(self)) for accurate signature.
- conversion_func(self, poses1, poses2)
Methods inherited from ConversionStageModel:
- __repr__(self)
- Return repr(self).
- __str__(self)
- Return str(self).
- fit(self, X, y)
- fit_predict(self, X, y)
- predict(self, X)
- score(self, X, y)
- split_X(self, X)
Methods inherited from sklearn.base.BaseEstimator:
- __getstate__(self)
- __setstate__(self, state)
- get_params(self, deep=True)
- Get parameters for this estimator.
Parameters
----------
deep : bool, default=True
If True, will return the parameters for this estimator and
contained subobjects that are estimators.
Returns
-------
params : dict
Parameter names mapped to their values.
- set_params(self, **params)
- Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects
(such as :class:`~sklearn.pipeline.Pipeline`). The latter have
parameters of the form ``<component>__<parameter>`` so that it's
possible to update each component of a nested object.
Parameters
----------
**params : dict
Estimator parameters.
Returns
-------
self : estimator instance
Estimator instance.
Data descriptors inherited from sklearn.base.BaseEstimator:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class LPSolver(LinearSolver) |
|
LPSolver(integral=True)
Solver that uses (integer) linear programming to find a solution minimizing the mean
absolute error of the system of equations specified by the constraints. This
differs from MAESolver as by using integer linear programming we can constrain
the resulting values to be integers, which removes any errors that might come from
rounding the solution values. |
|
- Method resolution order:
- LPSolver
- LinearSolver
- Solver
- builtins.object
Methods defined here:
- __init__(self, integral=True)
- Initialize self. See help(type(self)) for accurate signature.
- solve_matrix(self, solution_mat, solution_vals, initial_values)
Methods inherited from LinearSolver:
- make_constraint_matrix(self, constraints, initial_poses)
- make_positions(self, initial_poses, poses)
- score_func(self, constraint)
- solve(self, constraints, initial_poses)
- Solve the global positions for images given the constraints and estimated positions.
returns the xy position for each image, mapping the image index to the position
with a dictionary.
Additionally the constraints dictionary can be returned as the second return value, which
will replace the constraints in the composite with the ones returned, filtering outliers.
Data descriptors inherited from Solver:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class LastMerger(Merger) |
|
This is the simplest merger, overlap is decided just by which image was added last.
This also means it has no extra memory requirements, if your images have no overlap or
you don't need any merging this is the best choice. |
|
- Method resolution order:
- LastMerger
- Merger
- builtins.object
Methods defined here:
- add_image(self, image, location)
- Called to add an image. location is a tuple of slices used
to select the area for the image, it is guaranteed to be the
same size as image.
- create_image(self, image_shape, image_dtype)
- Init is called with the shape of the final image (may be
more than 2d) and the dtype. Normally a merger would create
an image using this information.
- final_image(self)
- Called once to get the final image. It will only be called
once when stitching, so final processing can take place and modify
the stored image. Returns the final image and a mask for pixels that
had no images.
Data descriptors inherited from Merger:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class LinearSolver(Solver) |
|
LinearSolver(model=None)
Solver that represents the constraints as an overconstrained system of equations, and
solves it using least squares. |
|
- Method resolution order:
- LinearSolver
- Solver
- builtins.object
Methods defined here:
- __init__(self, model=None)
- Initialize self. See help(type(self)) for accurate signature.
- make_constraint_matrix(self, constraints, initial_poses)
- make_positions(self, initial_poses, poses)
- score_func(self, constraint)
- solve(self, constraints, initial_poses)
- Solve the global positions for images given the constraints and estimated positions.
returns the xy position for each image, mapping the image index to the position
with a dictionary.
Additionally the constraints dictionary can be returned as the second return value, which
will replace the constraints in the composite with the ones returned, filtering outliers.
- solve_matrix(self, solution_mat, solution_vals, initial_values)
Data descriptors inherited from Solver:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class MAESolver(LinearSolver) |
|
MAESolver(**kwargs)
Solver that performs quantile regression instead of ordinary least squares
to solve the system of equations described by constraints. Equivalent to minimizing
the mean absolute error, this is much more outlier resistant that minimizing MSE
and should provide better results when there are erroneous constraints present.
This is identical to LinearSolver except that the linear model used is QuantileRegressor.
Any parameters passed to the constructor are forwared to the constructor of
sklearn.linear_model.QuantileRegressor. By default the L1 regularization constant
alpha=0 and fit_intercept=False, unless specified in the constructor. |
|
- Method resolution order:
- MAESolver
- LinearSolver
- Solver
- builtins.object
Methods defined here:
- __init__(self, **kwargs)
- Initialize self. See help(type(self)) for accurate signature.
- score_func(self, constraint)
Methods inherited from LinearSolver:
- make_constraint_matrix(self, constraints, initial_poses)
- make_positions(self, initial_poses, poses)
- solve(self, constraints, initial_poses)
- Solve the global positions for images given the constraints and estimated positions.
returns the xy position for each image, mapping the image index to the position
with a dictionary.
Additionally the constraints dictionary can be returned as the second return value, which
will replace the constraints in the composite with the ones returned, filtering outliers.
- solve_matrix(self, solution_mat, solution_vals, initial_values)
Data descriptors inherited from Solver:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class MaskMerger(NearestMerger) |
|
MaskMerger(overlap_threshold=0.75, dtype=<class 'numpy.uint32'>)
This merger is specifically for merging an image mask, where each integer represents
an independent class, for example cell segmentation masks. Other merging techniques won't
work on these image masks. This merger first makes sure that every mask in each image
has a unique integer value, then merges overlapping sections by going through the
masks and combining masks that are mostly overlapping in both images. The amount
of overlap needed to combine masks is the overlap_threshold. |
|
- Method resolution order:
- MaskMerger
- NearestMerger
- Merger
- builtins.object
Methods defined here:
- __init__(self, overlap_threshold=0.75, dtype=<class 'numpy.uint32'>)
- Initialize self. See help(type(self)) for accurate signature.
- add_image(self, image, location)
- Called to add an image. location is a tuple of slices used
to select the area for the image, it is guaranteed to be the
same size as image.
- create_image(self, image_shape, image_dtype)
- Init is called with the shape of the final image (may be
more than 2d) and the dtype. Normally a merger would create
an image using this information.
Methods inherited from NearestMerger:
- final_image(self)
- Called once to get the final image. It will only be called
once when stitching, so final processing can take place and modify
the stored image. Returns the final image and a mask for pixels that
had no images.
Data descriptors inherited from Merger:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class MeanMerger(Merger) |
|
A merger that calculates the mean of any overlapping areas. This requires
storing the whole image using a larger dtype, eg when merging uint16 images
the whole image will be stored as a uint32 image to account for possible overflow.
This will double the memory requirements compared to other mergers such as LastMerger
or EfficientMeanMerger. |
|
- Method resolution order:
- MeanMerger
- Merger
- builtins.object
Methods defined here:
- add_image(self, image, location)
- Called to add an image. location is a tuple of slices used
to select the area for the image, it is guaranteed to be the
same size as image.
- create_image(self, image_shape, image_dtype)
- Init is called with the shape of the final image (may be
more than 2d) and the dtype. Normally a merger would create
an image using this information.
- final_image(self)
- Called once to get the final image. It will only be called
once when stitching, so final processing can take place and modify
the stored image. Returns the final image and a mask for pixels that
had no images.
- promote_dtype(self, dtype)
Data descriptors inherited from Merger:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class Merger(builtins.object) |
|
Abstract class that specifies the methods required for an image merger.
At its heart an image merger is a method for handling multiple values at one
pixel location, either taking one, combining them all, or some other method.
Using this the merger is able to combine many images at different locations
into one final image.
The simplest merger is LastMerger, which doesn't do any extra processing, it
simply places each image on top of each other, meaning overlapping areas will
be the last image added. Other mergers attempt to combine images better but
this requires using more memory and processing. |
|
Methods defined here:
- add_image(self, image, location)
- Called to add an image. location is a tuple of slices used
to select the area for the image, it is guaranteed to be the
same size as image.
- create_image(self, image_shape, image_dtype)
- Init is called with the shape of the final image (may be
more than 2d) and the dtype. Normally a merger would create
an image using this information.
- final_image(self)
- Called once to get the final image. It will only be called
once when stitching, so final processing can take place and modify
the stored image. Returns the final image and a mask for pixels that
had no images.
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class NearestMerger(Merger) |
|
This merger keeps the pixel that is closer to the center of its image when there is overlap.
This normally means that the edges of images are removed and central pixels are prioritized.
This does require more memory, an extra array of uint16 the size of the final image. If memory
is an issue EfficientNearestMerger uses a similar algorithm but only needs an array of uint8. |
|
- Method resolution order:
- NearestMerger
- Merger
- builtins.object
Methods defined here:
- add_image(self, image, location)
- Called to add an image. location is a tuple of slices used
to select the area for the image, it is guaranteed to be the
same size as image.
- create_image(self, image_shape, image_dtype)
- Init is called with the shape of the final image (may be
more than 2d) and the dtype. Normally a merger would create
an image using this information.
- final_image(self)
- Called once to get the final image. It will only be called
once when stitching, so final processing can take place and modify
the stored image. Returns the final image and a mask for pixels that
had no images.
Data descriptors inherited from Merger:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class OptimalSolver(LinearSolver) |
|
OptimalSolver(model=None, loss_func=None)
Solver that solves the system of equations generated by LinearSolver by
minimizing an arbitrary loss function.
This solver uses the provided linear model, default LinearRegression,
to get initial positions then uses scipy.optimize.minimize to find the final
solution that minimizes the loss function.
By default the loss function used is mean absolute error, however if you are
looking to minimize on MAE you should use MAESolver as it is equivalent
and more efficient. Only use this model when there is not a dedicated
sklearn.linear_model or similar regressor that can be utilized with LinearSolver
for your loss function |
|
- Method resolution order:
- OptimalSolver
- LinearSolver
- Solver
- builtins.object
Methods defined here:
- __init__(self, model=None, loss_func=None)
- Initialize self. See help(type(self)) for accurate signature.
- loss(self, values, solution_mat, solution_vals)
- solve_matrix(self, solution_mat, solution_vals, initial_values)
Methods inherited from LinearSolver:
- make_constraint_matrix(self, constraints, initial_poses)
- make_positions(self, initial_poses, poses)
- score_func(self, constraint)
- solve(self, constraints, initial_poses)
- Solve the global positions for images given the constraints and estimated positions.
returns the xy position for each image, mapping the image index to the position
with a dictionary.
Additionally the constraints dictionary can be returned as the second return value, which
will replace the constraints in the composite with the ones returned, filtering outliers.
Data descriptors inherited from Solver:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class OutlierSolver(Solver) |
|
OutlierSolver(solver=None, outlier_threshold=1.5)
|
|
- Method resolution order:
- OutlierSolver
- Solver
- builtins.object
Methods defined here:
- __init__(self, solver=None, outlier_threshold=1.5)
- Initialize self. See help(type(self)) for accurate signature.
- solve(self, constraints, initial_poses)
- Solve the global positions for images given the constraints and estimated positions.
returns the xy position for each image, mapping the image index to the position
with a dictionary.
Additionally the constraints dictionary can be returned as the second return value, which
will replace the constraints in the composite with the ones returned, filtering outliers.
Data descriptors inherited from Solver:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class PCCAligner(Aligner) |
|
PCCAligner(**kwargs)
An aligner that invokes the skimage.registration.phase_cross_correlation method
An alternative to the FFTAligner which implements the same algorithm |
|
- Method resolution order:
- PCCAligner
- Aligner
- builtins.object
Methods defined here:
- __init__(self, **kwargs)
- Initialize self. See help(type(self)) for accurate signature.
- align(self, constraint, precalc1=None, precalc2=None)
- Performs the alignment of two images, finding the pixel offset that best aligns the
two images. The offset should be from image1 to image2. The return value should be a Constraint
object, with at least the dx, dy fields filled in to represent the offset of image2 needed
to align the two images. If the function finds the images don't overlap, None should be returned.
If a constraint is specified, this method should only return a constraint that fits within the error
of given constraint, meaning within constraint.error pixels from the (constraint.dx, constraint.dy)
offset.
Methods inherited from Aligner:
- precalculate(self, image, box)
- Performs an arbitrary precalculation step specific to the alignment algorithm.
This would be a step in the algorithm that only has to be run once per image,
and can be cached for each calculation done with the same image. The result of
this function will be passed to the align function as the precalc1 or precalc2 argument
- precalculate_if_needed(self, constraint, precalc1, precalc2)
- resize_if_needed(self, image, box=None, downscale_factor=None, padding=None)
- # Helper functions for subclasses:
Data descriptors inherited from Aligner:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class SimpleOffsetModel(ConversionStageModel) |
|
SimpleOffsetModel(model=None)
Simple stage model that calculates the offsets of the two
images and gives them to the internal model (default LinearRegression)
for estimation.
This model is the most simple, it only considers the relative positions of
the two images |
|
- Method resolution order:
- SimpleOffsetModel
- ConversionStageModel
- sklearn.base.BaseEstimator
- builtins.object
Methods defined here:
- conversion_func(self, poses1, poses2)
Methods inherited from ConversionStageModel:
- __init__(self, model=None)
- Initialize self. See help(type(self)) for accurate signature.
- __repr__(self)
- Return repr(self).
- __str__(self)
- Return str(self).
- fit(self, X, y)
- fit_predict(self, X, y)
- predict(self, X)
- score(self, X, y)
- split_X(self, X)
Methods inherited from sklearn.base.BaseEstimator:
- __getstate__(self)
- __setstate__(self, state)
- get_params(self, deep=True)
- Get parameters for this estimator.
Parameters
----------
deep : bool, default=True
If True, will return the parameters for this estimator and
contained subobjects that are estimators.
Returns
-------
params : dict
Parameter names mapped to their values.
- set_params(self, **params)
- Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects
(such as :class:`~sklearn.pipeline.Pipeline`). The latter have
parameters of the form ``<component>__<parameter>`` so that it's
possible to update each component of a nested object.
Parameters
----------
**params : dict
Estimator parameters.
Returns
-------
self : estimator instance
Estimator instance.
Data descriptors inherited from sklearn.base.BaseEstimator:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class Solver(builtins.object) |
|
Base class that takes in all the constraints of a composite
and solves them into global positions |
|
Methods defined here:
- solve(self, constraints, initial_poses)
- Solve the global positions for images given the constraints and estimated positions.
returns the xy position for each image, mapping the image index to the position
with a dictionary.
Additionally the constraints dictionary can be returned as the second return value, which
will replace the constraints in the composite with the ones returned, filtering outliers.
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|
class SpanningTreeSolver(Solver) |
|
Solver that finds the maximum spanning tree, and uses it to solve for
global positions of all images |
|
- Method resolution order:
- SpanningTreeSolver
- Solver
- builtins.object
Methods defined here:
- __init__(self)
- Initialize self. See help(type(self)) for accurate signature.
- solve(self, constraints, initial_poses)
- Constructs a maximum spanning tree with Kruskals algorithm
Data descriptors inherited from Solver:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
| |