geowatch.utils.util_kwarray module¶
Functions that may eventually be moved to kwarray
- geowatch.utils.util_kwarray.cartesian_product(*arrays)[source]¶
Fast numpy version of itertools.product
TODO: Move to kwarray
- geowatch.utils.util_kwarray.tukey_biweight_loss(r, c=4.685)[source]¶
Beaton Tukey Biweight
- Computes the function :
- L(r) = (
(c ** 2) / 6 * (1 - 1 * (r / c) ** 2) ** 3) if abs(r) <= c else (c ** 2)
)
- Parameters:
r (float | ndarray) – residual parameter
c (float) – tuning constant (defaults to 4.685 which is 95% efficient for normal distributions of residuals)
Todo
[ ] Move elsewhere or find a package that provides it
[ ] Move elsewhere (kwarray?) or find a package that provides it
- Returns:
float | ndarray
References
https://en.wikipedia.org/wiki/Robust_statistics https://mathworld.wolfram.com/TukeysBiweight.html https://statisticaloddsandends.wordpress.com/2021/04/23/what-is-the-tukey-loss-function/ https://arxiv.org/pdf/1505.06606.pdf
Example
>>> from geowatch.utils.util_kwarray import * # NOQA >>> import ubelt as ub >>> r = np.linspace(-20, 20, 1000) >>> data = {'r': r} >>> grid = ub.named_product({ >>> 'c': [4.685, 2, 6], >>> }) >>> for kwargs in grid: >>> key = ub.urepr(kwargs, compact=1) >>> loss = tukey_biweight_loss(r, **kwargs) >>> data[key] = loss >>> import pandas as pd >>> melted = pd.DataFrame(data).melt(['r']) >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> sns = kwplot.autosns() >>> kwplot.figure(fnum=1, doclf=True) >>> ax = sns.lineplot(data=melted, x='r', y='value', hue='variable', style='variable') >>> #ax.set_ylim(*robust_limits(melted.value))
- geowatch.utils.util_kwarray.asymptotic(x, offset=1, gamma=1, degree=0, horizontal=1)[source]¶
A function with a horizontal asymptote at
horizontal- Parameters:
x (ndarray) – input parameter
offset (float) – shifts function to the left or the right
gamma (float) – higher values approach the asymptote more slowly
horizontal (float) – location of the horiztonal asymptote
Todo
[ ] Move elsewhere (kwarray?) or find a package that provides it
Example
>>> from geowatch.utils.util_kwarray import * # NOQA >>> import ubelt as ub >>> x = np.linspace(0, 27, 1000) >>> data = {'x': x} >>> grid = ub.named_product({ >>> #'gamma': [0.5, 1.0, 2.0, 3.0], >>> 'gamma': [1.0, 3.0], >>> 'degree': [0, 1, 2, 3], >>> 'offset': [0, 2], >>> 'horizontal': [1], >>> }) >>> for kwargs in grid: >>> key = ub.urepr(kwargs, compact=1) >>> data[key] = asymptotic(x, **kwargs) >>> import pandas as pd >>> melted = pd.DataFrame(data).melt(['x']) >>> print(melted) >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> sns = kwplot.autosns() >>> kwplot.figure(fnum=1, doclf=True) >>> ax = sns.lineplot(data=melted, x='x', y='value', hue='variable', style='variable') >>> ax.set_ylim(0, 2)
- geowatch.utils.util_kwarray.robust_limits(values)[source]¶
# TODO: Proper Robust estimator for matplotlib ylim and general use
values = np.array([-1000, -4, -3, -2, 0, 2.7, 3.1415, 1, 2, 3, 4, 100000]) robust_limits(values)
- geowatch.utils.util_kwarray.unique_rows(arr, ordered=False)[source]¶
Note: function also added to kwarray and will be available in >0.5.20
Example
>>> import kwarray >>> from kwarray.util_numpy import * # NOQA >>> rng = kwarray.ensure_rng(0) >>> arr = rng.randint(0, 2, size=(12, 3)) >>> arr_unique = unique_rows(arr) >>> print('arr_unique = {!r}'.format(arr_unique))
- geowatch.utils.util_kwarray.find_robust_normalizers(data, params='auto')[source]¶
Finds robust normalization statistics for a single observation
- Parameters:
data (ndarray) – a 1D numpy array where invalid data has already been removed
params (str | dict) – normalization params
- Returns:
normalization parameters
- Return type:
Todo
[ ] No Magic Numbers! Use first principles to deterimine defaults.
[ ] Probably a lot of literature on the subject.
[ ] Is this a kwarray function in general?
[ ] https://www.tandfonline.com/doi/full/10.1080/02664763.2019.1671961
Example
>>> data = np.random.rand(100) >>> norm_params1 = find_robust_normalizers(data, params='auto') >>> norm_params2 = find_robust_normalizers(data, params={'low': 0, 'high': 1.0}) >>> norm_params3 = find_robust_normalizers(np.empty(0), params='auto') >>> print('norm_params1 = {}'.format(ub.urepr(norm_params1, nl=1))) >>> print('norm_params2 = {}'.format(ub.urepr(norm_params2, nl=1))) >>> print('norm_params3 = {}'.format(ub.urepr(norm_params3, nl=1)))
- geowatch.utils.util_kwarray.apply_normalizer(data, normalizer, mask=None, set_value_at_mask=nan)[source]¶
- geowatch.utils.util_kwarray.normalize(arr, mode='linear', alpha=None, beta=None, out=None, min_val=None, max_val=None)[source]¶
Rebalance signal values via contrast stretching.
By default linearly stretches array values to minimum and maximum values.
- Parameters:
arr (ndarray) – array to normalize, usually an image
out (ndarray | None) – output array. Note, that we will create an internal floating point copy for integer computations.
mode (str) – either linear or sigmoid.
alpha (float) – Only used if mode=sigmoid. Division factor (pre-sigmoid). If unspecified computed as:
max(abs(old_min - beta), abs(old_max - beta)) / 6.212606. Note this parameter is sensitive to if the input is a float or uint8 image.beta (float) – subtractive factor (pre-sigmoid). This should be the intensity of the most interesting bits of the image, i.e. bring them to the center (0) of the distribution. Defaults to
(max - min) / 2. Note this parameter is sensitive to if the input is a float or uint8 image.min_val – override minimum value
max_val – override maximum value
References
https://en.wikipedia.org/wiki/Normalization_(image_processing)
Example
>>> raw_f = np.random.rand(8, 8) >>> norm_f = normalize(raw_f) >>> raw_f = np.random.rand(8, 8) * 100 >>> norm_f = normalize(raw_f) >>> assert isclose(norm_f.min(), 0) >>> assert isclose(norm_f.max(), 1) >>> raw_u = (np.random.rand(8, 8) * 255).astype(np.uint8) >>> norm_u = normalize(raw_u) >>> raw_m = (np.zeros((8, 8)) + 10) >>> norm_m = normalize(raw_m, min_val=0, max_val=20) >>> assert isclose(norm_m.min(), 0.5) >>> assert isclose(norm_m.max(), 0.5) >>> # Ensure that we're clamping if explicit min or max values >>> # are provided >>> raw_m = (np.zeros((8, 8)) + 10) >>> norm_m = normalize(raw_m, min_val=0, max_val=5) >>> assert isclose(norm_m.min(), 1.0) >>> assert isclose(norm_m.max(), 1.0)
Example
>>> # xdoctest: +REQUIRES(module:kwimage) >>> import kwimage >>> arr = kwimage.grab_test_image('lowcontrast') >>> arr = kwimage.ensure_float01(arr) >>> norms = {} >>> norms['arr'] = arr.copy() >>> norms['linear'] = normalize(arr, mode='linear') >>> norms['sigmoid'] = normalize(arr, mode='sigmoid') >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> kwplot.figure(fnum=1, doclf=True) >>> pnum_ = kwplot.PlotNums(nSubplots=len(norms)) >>> for key, img in norms.items(): >>> kwplot.imshow(img, pnum=pnum_(), title=key)
- geowatch.utils.util_kwarray.balanced_number_partitioning(items, num_parts)[source]¶
Greedy approximation to multiway number partitioning
Uses Greedy number partitioning method to minimize the size of the largest partition.
- Parameters:
items (np.ndarray) – list of numbers (i.e. weights) to split between paritions.
num_parts (int) – number of partitions
- Returns:
A list for each parition that contains the index of the items assigned to it.
- Return type:
List[np.ndarray]
References
https://en.wikipedia.org/wiki/Multiway_number_partitioning https://en.wikipedia.org/wiki/Balanced_number_partitioning
Example
>>> from geowatch.utils.util_kwarray import * # NOQA >>> items = np.array([1, 3, 29, 22, 4, 5, 9]) >>> num_parts = 3 >>> bin_assignments = balanced_number_partitioning(items, num_parts) >>> import kwarray >>> groups = kwarray.apply_grouping(items, bin_assignments) >>> bin_weights = [g.sum() for g in groups]
- geowatch.utils.util_kwarray.torch_array_equal(data1, data2, equal_nan=False) bool[source]¶
Example
>>> # xdoctest: +REQUIRES(module:torch) >>> import torch >>> data1 = torch.rand(5, 5) >>> data2 = data1 + 1 >>> result1 = torch_array_equal(data1, data2) >>> result3 = torch_array_equal(data1, data1) >>> assert result1 is False >>> assert result3 is True
Example
>>> # xdoctest: +REQUIRES(module:torch) >>> import torch >>> data1 = torch.rand(5, 5) >>> data1[0] = np.nan >>> data2 = data1 >>> result1 = torch_array_equal(data1, data2) >>> result3 = torch_array_equal(data1, data2, equal_nan=True) >>> assert result1 is False >>> assert result3 is True
- geowatch.utils.util_kwarray.combine_mean_stds(means, stds, nums=None, axis=None, keepdims=False, bessel=True)[source]¶
- Parameters:
means (array) – means[i] is the mean of the ith entry to combine
stds (array) – stds[i] is the std of the ith entry to combine
nums (array | None) – nums[i] is the number of samples in the ith entry to combine. if None, assumes sample sizes are infinite.
axis (int | Tuple[int] | None) – axis to combine the statistics over
keepdims (bool) – if True return arrays with the same number of dimensions they were given in.
bessel (int) – Set to 1 to enables bessel correction to unbias the combined std estimate. Only disable if you have the true population means, or you think you know what you are doing.
References
- SeeAlso:
development kwarray has a similar hidden function in util_averages. Might expose later.
Example
>>> means = np.stack([np.array([1.2, 3.2, 4.1])] * 100, axis=0) >>> stds = np.stack([np.array([4.2, 0.2, 2.1])] * 100, axis=0) >>> nums = np.stack([np.array([10, 100, 10])] * 100, axis=0) >>> cm1, cs1, _ = combine_mean_stds(means, stds, nums, axis=None) >>> print('combo_mean = {}'.format(ub.urepr(cm1, nl=1))) >>> print('combo_std = {}'.format(ub.urepr(cs1, nl=1))) >>> means = np.stack([np.array([1.2, 3.2, 4.1])] * 1, axis=0) >>> stds = np.stack([np.array([4.2, 0.2, 2.1])] * 1, axis=0) >>> nums = np.stack([np.array([10, 100, 10])] * 1, axis=0) >>> cm2, cs2, _ = combine_mean_stds(means, stds, nums, axis=None) >>> print('combo_mean = {}'.format(ub.urepr(cm2, nl=1))) >>> print('combo_std = {}'.format(ub.urepr(cs2, nl=1))) >>> means = np.stack([np.array([1.2, 3.2, 4.1])] * 5, axis=0) >>> stds = np.stack([np.array([4.2, 0.2, 2.1])] * 5, axis=0) >>> nums = np.stack([np.array([10, 100, 10])] * 5, axis=0) >>> cm3, cs3, combo_num = combine_mean_stds(means, stds, nums, axis=1) >>> print('combo_mean = {}'.format(ub.urepr(cm3, nl=1))) >>> print('combo_std = {}'.format(ub.urepr(cs3, nl=1))) >>> assert np.allclose(cm1, cm2) and np.allclose(cm2, cm3) >>> assert not np.allclose(cs1, cs2) >>> assert np.allclose(cs2, cs3)
Example
>>> from geowatch.utils.util_kwarray import * # NOQA >>> means = np.random.rand(2, 3, 5, 7) >>> stds = np.random.rand(2, 3, 5, 7) >>> nums = (np.random.rand(2, 3, 5, 7) * 10) + 1 >>> cm, cs, cn = combine_mean_stds(means, stds, nums, axis=1, keepdims=1) >>> print('cs = {}'.format(ub.urepr(cs, nl=1))) >>> assert cm.shape == cs.shape == cn.shape ... >>> print(f'cm.shape={cm.shape}') >>> cm, cs, cn = combine_mean_stds(means, stds, nums, axis=(0, 2), keepdims=1) >>> assert cm.shape == cs.shape == cn.shape >>> print(f'cm.shape={cm.shape}') >>> cm, cs, cn = combine_mean_stds(means, stds, nums, axis=(1, 3), keepdims=1) >>> assert cm.shape == cs.shape == cn.shape >>> print(f'cm.shape={cm.shape}') >>> cm, cs, cn = combine_mean_stds(means, stds, nums, axis=None) >>> assert cm.shape == cs.shape == cn.shape >>> print(f'cm.shape={cm.shape}') cm.shape=(2, 1, 5, 7) cm.shape=(1, 3, 1, 7) cm.shape=(2, 1, 5, 1) cm.shape=()
- geowatch.utils.util_kwarray.apply_robust_normalizer(normalizer, imdata, imdata_valid, mask, dtype, copy=True)[source]¶
data = [self.dataset[idx] for idx in possibly_batched_index]
- File “/home/joncrall/code/watch/geowatch/tasks/fusion/datamodules/kwcoco_dataset.py”, line 1004, in __getitem__
return self.getitem(index)
- File “/home/joncrall/code/watch/geowatch/tasks/fusion/datamodules/kwcoco_dataset.py”, line 1375, in getitem
imdata_normalized = apply_robust_normalizer(
- File “/home/joncrall/code/watch/geowatch/tasks/fusion/datamodules/kwcoco_dataset.py”, line 2513, in apply_robust_normalizer
imdata_valid_normalized = kwarray.normalize(
- File “/home/joncrall/code/kwarray/kwarray/util_numpy.py”, line 760, in normalize
old_min = np.nanmin(float_out)
File “<__array_function__ internals>”, line 5, in nanmin File “/home/joncrall/.pyenv/versions/3.10.5/envs/pyenv3.10.5/lib/python3.10/site-packages/numpy/lib/nanfunctions.py”, line 319, in nanmin
res = np.fmin.reduce(a, axis=axis, out=out, **kwargs)
- geowatch.utils.util_kwarray.biased_1d_weights(upweight_time, num_frames)[source]¶
import kwplot plt = kwplot.autoplt()
kwplot.figure() import sys, ubelt sys.path.append(ubelt.expandpath(‘~/code/watch’)) from geowatch.tasks.fusion.datamodules.kwcoco_dataset import * # NOQA
kwplot.figure(fnum=1, doclf=1) num_frames = 5 values = biased_1d_weights(0.5, num_frames) plt.plot(values) values = biased_1d_weights(0.1, num_frames) plt.plot(values) values = biased_1d_weights(0.0, num_frames) plt.plot(values) values = biased_1d_weights(0.9, num_frames) plt.plot(values) values = biased_1d_weights(1.0, num_frames) plt.plot(values)
- geowatch.utils.util_kwarray.argsort_threshold(arr, threshold=None, num_top=None, objective='maximize')[source]¶
Find all indexes over a threshold, but always return at least the num_top, and potentially more.
- Parameters:
arr (ndarray) – array of scores
threshold (float) – return indexes that are better than this threshold.
num_top (int) – always return at least this number of “best” indexes.
objective (str) – if maximize, filters things above the threshold, otherwise filters below the threshold.
- Returns:
top indexes
- Return type:
ndarray
Example
>>> from geowatch.utils.util_kwarray import * # NOQA >>> arr = np.array([0.3, .2, 0.1, 0.15, 0.11, 0.15, 0.2, 0.6, 0.32]) >>> argsort_threshold(arr, threshold=0.5, num_top=0) array([7]) >>> argsort_threshold(arr, threshold=0.5, num_top=3) array([7, 8, 0]) >>> argsort_threshold(arr, threshold=0.0, num_top=3)
- class geowatch.utils.util_kwarray.SlidingWindow(shape, window, overlap=None, stride=None, keepbound=False, allow_overshoot=False)[source]¶
Bases:
NiceReprSlide a window of a certain shape over an array with a larger shape.
This can be used for iterating over a grid of sub-regions of 2d-images, 3d-volumes, or any n-dimensional array.
Yields slices of shape window that can be used to index into an array with shape shape via numpy / torch fancy indexing. This allows for fast fast iteration over subregions of a larger image. Because we generate a grid-basis using only shapes, the larger image does not need to be in memory as long as its width/height/depth/etc…
- Parameters:
shape (Tuple[int, …]) – shape of source array to slide across.
window (Tuple[int, …]) – shape of window that will be slid over the larger image.
overlap (float, default=0) – a number between 0 and 1 indicating the fraction of overlap that parts will have. Specifying this is mutually exclusive with stride. Must be 0 <= overlap < 1.
stride (int, default=None) – the number of cells (pixels) moved on each step of the window. Mutually exclusive with overlap.
keepbound (bool, default=False) – if True, a non-uniform stride will be taken to ensure that the right / bottom of the image is returned as a slice if needed. Such a slice will not obey the overlap constraints. (Defaults to False)
allow_overshoot (bool, default=False) – if False, we will raise an error if the window doesn’t slide perfectly over the input shape.
- Variables:
strides (basis_shape - shape of the grid corresponding to the number of) – the sliding window will take.
dimension (basis_slices - slices that will be taken in every)
- Yields:
Tuple[slice, …] –
- slices used for numpy indexing, the number of slices
in the tuple
Note
For each dimension, we generate a basis (which defines a grid), and we slide over that basis.
Todo
- [ ] have an option that is allowed to go outside of the window bounds
on the right and bottom when the slider overshoots.
Example
>>> shape = (10, 10) >>> window = (5, 5) >>> self = SlidingWindow(shape, window) >>> for i, index in enumerate(self): >>> print('i={}, index={}'.format(i, index)) i=0, index=(slice(0, 5, None), slice(0, 5, None)) i=1, index=(slice(0, 5, None), slice(5, 10, None)) i=2, index=(slice(5, 10, None), slice(0, 5, None)) i=3, index=(slice(5, 10, None), slice(5, 10, None))
Example
>>> shape = (16, 16) >>> window = (4, 4) >>> self = SlidingWindow(shape, window, overlap=(.5, .25)) >>> print('self.stride = {!r}'.format(self.stride)) self.stride = [2, 3] >>> list(ub.chunks(self.grid, 5)) [[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4)], [(1, 0), (1, 1), (1, 2), (1, 3), (1, 4)], [(2, 0), (2, 1), (2, 2), (2, 3), (2, 4)], [(3, 0), (3, 1), (3, 2), (3, 3), (3, 4)], [(4, 0), (4, 1), (4, 2), (4, 3), (4, 4)], [(5, 0), (5, 1), (5, 2), (5, 3), (5, 4)], [(6, 0), (6, 1), (6, 2), (6, 3), (6, 4)]]
Example
>>> # Test shapes that dont fit >>> # When the window is bigger than the shape, the left-aligned slices >>> # are returend. >>> self = SlidingWindow((3, 3), (12, 12), allow_overshoot=True, keepbound=True) >>> print(list(self)) [(slice(0, 12, None), slice(0, 12, None))] >>> print(list(SlidingWindow((3, 3), None, allow_overshoot=True, keepbound=True))) [(slice(0, 3, None), slice(0, 3, None))] >>> print(list(SlidingWindow((3, 3), (None, 2), allow_overshoot=True, keepbound=True))) [(slice(0, 3, None), slice(0, 2, None)), (slice(0, 3, None), slice(1, 3, None))]
- property grid¶
Generate indices into the “basis” slice for each dimension. This enumerates the nd indices of the grid.
- Yields:
Tuple[int, …]
- property slices¶
Generate slices for each window (equivalent to iter(self))
Example
>>> shape = (220, 220) >>> window = (10, 10) >>> self = SlidingWindow(shape, window, stride=5) >>> list(self)[41:45] [(slice(0, 10, None), slice(205, 215, None)), (slice(0, 10, None), slice(210, 220, None)), (slice(5, 15, None), slice(0, 10, None)), (slice(5, 15, None), slice(5, 15, None))] >>> print('self.overlap = {!r}'.format(self.overlap)) self.overlap = [0.5, 0.5]
- property centers¶
Generate centers of each window
- Yields:
Tuple[float, …] – the center coordinate of the slice
Example
>>> shape = (4, 4) >>> window = (3, 3) >>> self = SlidingWindow(shape, window, stride=1) >>> list(zip(self.centers, self.slices)) [((1.0, 1.0), (slice(0, 3, None), slice(0, 3, None))), ((1.0, 2.0), (slice(0, 3, None), slice(1, 4, None))), ((2.0, 1.0), (slice(1, 4, None), slice(0, 3, None))), ((2.0, 2.0), (slice(1, 4, None), slice(1, 4, None)))] >>> shape = (3, 3) >>> window = (2, 2) >>> self = SlidingWindow(shape, window, stride=1) >>> list(zip(self.centers, self.slices)) [((0.5, 0.5), (slice(0, 2, None), slice(0, 2, None))), ((0.5, 1.5), (slice(0, 2, None), slice(1, 3, None))), ((1.5, 0.5), (slice(1, 3, None), slice(0, 2, None))), ((1.5, 1.5), (slice(1, 3, None), slice(1, 3, None)))]
- class geowatch.utils.util_kwarray.Stitcher(shape, device='numpy', dtype='float32', nan_policy='propogate', memmap=False)[source]¶
Bases:
NiceReprFrom kwarray: v0.6.19
Stitches multiple possibly overlapping slices into a larger array.
This is used to invert the SlidingWindow. For semenatic segmentation the patches are probability chips. Overlapping chips are averaged together.
- SeeAlso:
kwarray.RunningStats- similarly performs running means, butcan also track other statistics.
Example
>>> # Build a high resolution image and slice it into chips >>> highres = np.random.rand(5, 200, 200).astype(np.float32) >>> target_shape = (1, 50, 50) >>> slider = SlidingWindow(highres.shape, target_shape, overlap=(0, .5, .5)) >>> # Show how Sticher can be used to reconstruct the original image >>> stitcher = Stitcher(slider.input_shape) >>> for sl in list(slider): ... chip = highres[sl] ... stitcher.add(sl, chip) >>> assert stitcher.weights.max() == 4, 'some parts should be processed 4 times' >>> recon = stitcher.finalize()
Example
>>> # Demo stitching 3 patterns where one has nans >>> pat1 = np.full((32, 32), fill_value=0.2) >>> pat2 = np.full((32, 32), fill_value=0.4) >>> pat3 = np.full((32, 32), fill_value=0.8) >>> pat1[:, 16:] = 0.6 >>> pat2[16:, :] = np.nan >>> # Test with nan_policy=omit >>> stitcher = Stitcher(shape=(32, 64), nan_policy='omit') >>> stitcher[0:32, 0:32](pat1) >>> stitcher[0:32, 16:48](pat2) >>> stitcher[0:32, 33:64](pat3[:, 1:]) >>> final1 = stitcher.finalize() >>> # Test without nan_policy=propogate >>> stitcher = Stitcher(shape=(32, 64), nan_policy='propogate') >>> stitcher[0:32, 0:32](pat1) >>> stitcher[0:32, 16:48](pat2) >>> stitcher[0:32, 33:64](pat3[:, 1:]) >>> final2 = stitcher.finalize() >>> # Checks >>> assert np.isnan(final1).sum() == 16, 'only should contain nan where no data was stiched' >>> assert np.isnan(final2).sum() == 512, 'should contain nan wherever a nan was stitched' >>> # xdoctest: +REQUIRES(--show) >>> # xdoctest: +REQUIRES(module:kwplot) >>> import kwplot >>> import kwimage >>> kwplot.autompl() >>> kwplot.imshow(pat1, title='pat1', pnum=(3, 3, 1)) >>> kwplot.imshow(kwimage.nodata_checkerboard(pat2, square_shape=1), title='pat2 (has nans)', pnum=(3, 3, 2)) >>> kwplot.imshow(pat3, title='pat3', pnum=(3, 3, 3)) >>> kwplot.imshow(kwimage.nodata_checkerboard(final1, square_shape=1), title='stitched (nan_policy=omit)', pnum=(3, 1, 2)) >>> kwplot.imshow(kwimage.nodata_checkerboard(final2, square_shape=1), title='stitched (nan_policy=propogate)', pnum=(3, 1, 3))
- Parameters:
shape (tuple) – dimensions of the large image that will be created from the smaller pixels or patches.
device (str | int | torch.device) – default is ‘numpy’, but if given as a torch device, then underlying operations will be done with torch tensors instead.
dtype (str) – the datatype to use in the underlying accumulator.
nan_policy (str) – if omit, check for nans and convert any to zero weight items in stitching.
memmap (bool | PathLike) – if truthy, the stitcher will use a memory map. If this pathlike, then we use this as the directory for the memmap. If True, a temp directory is used.
- add(indices, patch, weight=None)[source]¶
Incorporate a new (possibly overlapping) patch or pixel using a weighted sum.
- Parameters:
indices (slice | tuple | None) – typically a Tuple[slice] of pixels or a single pixel, but this can be any numpy fancy index.
patch (ndarray) – data to patch into the bigger image.
weight (float | ndarray) – weight of this patch (default to 1.0)