topological sorting of definitions by caller hierarchy
This commit is contained in:
parent
3b18fc6158
commit
6e7645e319
@ -5,11 +5,6 @@ from funcy import compose, second
|
||||
from image_prediction.stitching.utils import make_coord_getter
|
||||
|
||||
|
||||
def group_by_coordinate(pairs, coord_getter):
|
||||
pairs = sorted(pairs, key=coord_getter)
|
||||
return map(compose(list, second), groupby(pairs, coord_getter))
|
||||
|
||||
|
||||
class CoordGrouper:
|
||||
def __init__(self, axis):
|
||||
self.c1_getter = make_coord_getter(f"{other_axis(axis)}1")
|
||||
@ -24,3 +19,8 @@ class CoordGrouper:
|
||||
|
||||
def other_axis(axis):
|
||||
return "y" if axis == "x" else "x"
|
||||
|
||||
|
||||
def group_by_coordinate(pairs, coord_getter):
|
||||
pairs = sorted(pairs, key=coord_getter)
|
||||
return map(compose(list, second), groupby(pairs, coord_getter))
|
||||
|
||||
@ -13,71 +13,51 @@ from image_prediction.utils.generic import until
|
||||
from test.utils.stitching import HorizontalKeyMapper, VerticalKeyMapper
|
||||
|
||||
|
||||
def make_pair_merger(axis):
|
||||
return {"y": merge_pair_vertically, "x": merge_pair_horizontally}[axis]
|
||||
def no_new_merges(pairs1, pairs2):
|
||||
return len(pairs1) == len(pairs2)
|
||||
|
||||
|
||||
def merge_along_both_axes(pairs: Iterable[ImageMetadataPair]):
|
||||
pairs = merge_along_axis(pairs, "x")
|
||||
pairs = list(merge_along_axis(pairs, "y"))
|
||||
|
||||
return pairs
|
||||
|
||||
|
||||
def merge_along_axis(pairs: Iterable[ImageMetadataPair], axis):
|
||||
def group_pairs_within_groups_by_greater_coordinate(groups):
|
||||
return map(CoordGrouper(axis).group_pairs_by_greater_coordinate, groups)
|
||||
|
||||
def merge_groups_along_orthogonal_axis(groups):
|
||||
return map(make_group_merger(axis), groups)
|
||||
|
||||
def group_pairs_by_lesser_coordinate(pairs):
|
||||
return CoordGrouper(axis).group_pairs_by_lesser_coordinate(pairs)
|
||||
|
||||
return rcompose(
|
||||
group_pairs_by_lesser_coordinate, # pairs -> groups of pairs aligned on one edge
|
||||
group_pairs_within_groups_by_greater_coordinate, # -> groups of pairs fully aligned on orthogonal axis
|
||||
flatten_groups_once, # groups of groups of pairs -> groups of pairs
|
||||
merge_groups_along_orthogonal_axis,
|
||||
flatten_groups_once, # groups of pairs -> pairs
|
||||
)(pairs)
|
||||
|
||||
|
||||
def make_group_merger(axis):
|
||||
return {"y": merge_group_vertically, "x": merge_group_horizontally}[axis]
|
||||
|
||||
|
||||
def merge_metadata_horizontally(m1: dict, m2: dict):
|
||||
m1, m2 = map(HorizontalKeyMapper, [m1, m2])
|
||||
return merge_metadata(m1, m2)
|
||||
def merge_group_vertically(group: Iterable[ImageMetadataPair]):
|
||||
return merge_group(group, "y")
|
||||
|
||||
|
||||
def merge_metadata_vertically(m1: dict, m2: dict):
|
||||
m1, m2 = map(VerticalKeyMapper, [m1, m2])
|
||||
return merge_metadata(m1, m2)
|
||||
def merge_group_horizontally(group: Iterable[ImageMetadataPair]):
|
||||
return merge_group(group, "x")
|
||||
|
||||
|
||||
def merge_metadata(m1: dict, m2: dict):
|
||||
|
||||
c1 = min(m1.c1, m2.c1)
|
||||
c2 = max(m1.c2, m2.c2)
|
||||
dim = m1.dim + m2.dim
|
||||
|
||||
merged = deepcopy(m1)
|
||||
merged.dim = dim
|
||||
merged.c1 = c1
|
||||
merged.c2 = c2
|
||||
|
||||
return merged.wrapped
|
||||
|
||||
|
||||
def merge_pair_horizontally(p1: ImageMetadataPair, p2: ImageMetadataPair):
|
||||
metadata_merged = merge_metadata_horizontally(p1.metadata, p2.metadata)
|
||||
image_concatenated = concat_images_horizontally(p1.image, p2.image, metadata_merged)
|
||||
return ImageMetadataPair(image_concatenated, metadata_merged)
|
||||
|
||||
|
||||
def merge_pair_vertically(p1: ImageMetadataPair, p2: ImageMetadataPair):
|
||||
metadata_merged = merge_metadata_vertically(p1.metadata, p2.metadata)
|
||||
image_concatenated = concat_images_vertically(p1.image, p2.image, metadata_merged)
|
||||
return ImageMetadataPair(image_concatenated, metadata_merged)
|
||||
|
||||
|
||||
def concat_images_horizontally(im1: Image, im2: Image, metadata: dict):
|
||||
return concat_images(im1, im2, metadata, 0)
|
||||
|
||||
|
||||
def concat_images_vertically(im1: Image, im2: Image, metadata: dict):
|
||||
return concat_images(im1, im2, metadata, 1)
|
||||
|
||||
|
||||
def concat_images(im1: Image, im2: Image, metadata: dict, axis):
|
||||
|
||||
im_aggr = Image.new(im1.mode, (metadata[Info.WIDTH], metadata[Info.HEIGHT]))
|
||||
|
||||
images = [im1, im2]
|
||||
|
||||
offsets = [0, *[im.size[axis] for im in images]]
|
||||
|
||||
for im, offset in zip(images, offsets):
|
||||
box = (offset, 0) if not axis else (0, offset)
|
||||
im_aggr.paste(im, box=box)
|
||||
|
||||
return im_aggr
|
||||
def merge_group(group: Iterable[ImageMetadataPair], direction):
|
||||
reduce_group = make_merger_aggregator(direction)
|
||||
return until(no_new_merges, reduce_group, group)
|
||||
|
||||
|
||||
def make_merger_aggregator(direction) -> Callable[[Iterable[ImageMetadataPair]], Iterable[ImageMetadataPair]]:
|
||||
@ -108,44 +88,64 @@ def make_merger_aggregator(direction) -> Callable[[Iterable[ImageMetadataPair]],
|
||||
return merger_aggregator
|
||||
|
||||
|
||||
def merge_group(group: Iterable[ImageMetadataPair], direction):
|
||||
reduce_group = make_merger_aggregator(direction)
|
||||
return until(no_new_merges, reduce_group, group)
|
||||
def make_pair_merger(axis):
|
||||
return {"y": merge_pair_vertically, "x": merge_pair_horizontally}[axis]
|
||||
|
||||
|
||||
def merge_group_horizontally(group: Iterable[ImageMetadataPair]):
|
||||
return merge_group(group, "x")
|
||||
def merge_pair_vertically(p1: ImageMetadataPair, p2: ImageMetadataPair):
|
||||
metadata_merged = merge_metadata_vertically(p1.metadata, p2.metadata)
|
||||
image_concatenated = concat_images_vertically(p1.image, p2.image, metadata_merged)
|
||||
return ImageMetadataPair(image_concatenated, metadata_merged)
|
||||
|
||||
|
||||
def merge_group_vertically(group: Iterable[ImageMetadataPair]):
|
||||
return merge_group(group, "y")
|
||||
def merge_pair_horizontally(p1: ImageMetadataPair, p2: ImageMetadataPair):
|
||||
metadata_merged = merge_metadata_horizontally(p1.metadata, p2.metadata)
|
||||
image_concatenated = concat_images_horizontally(p1.image, p2.image, metadata_merged)
|
||||
return ImageMetadataPair(image_concatenated, metadata_merged)
|
||||
|
||||
|
||||
def merge_along_axis(pairs: Iterable[ImageMetadataPair], axis):
|
||||
def group_pairs_within_groups_by_greater_coordinate(groups):
|
||||
return map(CoordGrouper(axis).group_pairs_by_greater_coordinate, groups)
|
||||
|
||||
def merge_groups_along_orthogonal_axis(groups):
|
||||
return map(make_group_merger(axis), groups)
|
||||
|
||||
def group_pairs_by_lesser_coordinate(pairs):
|
||||
return CoordGrouper(axis).group_pairs_by_lesser_coordinate(pairs)
|
||||
|
||||
return rcompose(
|
||||
group_pairs_by_lesser_coordinate, # pairs -> groups of pairs aligned on one edge
|
||||
group_pairs_within_groups_by_greater_coordinate, # -> groups of pairs fully aligned on orthogonal axis
|
||||
flatten_groups_once, # groups of groups of pairs -> groups of pairs
|
||||
merge_groups_along_orthogonal_axis,
|
||||
flatten_groups_once, # groups of pairs -> pairs
|
||||
)(pairs)
|
||||
def merge_metadata_vertically(m1: dict, m2: dict):
|
||||
m1, m2 = map(VerticalKeyMapper, [m1, m2])
|
||||
return merge_metadata(m1, m2)
|
||||
|
||||
|
||||
def merge_along_both_axes(pairs: Iterable[ImageMetadataPair]):
|
||||
pairs = merge_along_axis(pairs, "x")
|
||||
pairs = list(merge_along_axis(pairs, "y"))
|
||||
|
||||
return pairs
|
||||
def merge_metadata_horizontally(m1: dict, m2: dict):
|
||||
m1, m2 = map(HorizontalKeyMapper, [m1, m2])
|
||||
return merge_metadata(m1, m2)
|
||||
|
||||
|
||||
def no_new_merges(pairs1, pairs2):
|
||||
return len(pairs1) == len(pairs2)
|
||||
def merge_metadata(m1: dict, m2: dict):
|
||||
|
||||
c1 = min(m1.c1, m2.c1)
|
||||
c2 = max(m1.c2, m2.c2)
|
||||
dim = m1.dim + m2.dim
|
||||
|
||||
merged = deepcopy(m1)
|
||||
merged.dim = dim
|
||||
merged.c1 = c1
|
||||
merged.c2 = c2
|
||||
|
||||
return merged.wrapped
|
||||
|
||||
|
||||
def concat_images_vertically(im1: Image, im2: Image, metadata: dict):
|
||||
return concat_images(im1, im2, metadata, 1)
|
||||
|
||||
|
||||
def concat_images_horizontally(im1: Image, im2: Image, metadata: dict):
|
||||
return concat_images(im1, im2, metadata, 0)
|
||||
|
||||
|
||||
def concat_images(im1: Image, im2: Image, metadata: dict, axis):
|
||||
|
||||
im_aggr = Image.new(im1.mode, (metadata[Info.WIDTH], metadata[Info.HEIGHT]))
|
||||
|
||||
images = [im1, im2]
|
||||
|
||||
offsets = [0, *[im.size[axis] for im in images]]
|
||||
|
||||
for im, offset in zip(images, offsets):
|
||||
box = (offset, 0) if not axis else (0, offset)
|
||||
im_aggr.paste(im, box=box)
|
||||
|
||||
return im_aggr
|
||||
|
||||
@ -3,11 +3,8 @@ from itertools import chain
|
||||
from image_prediction.info import Info
|
||||
|
||||
|
||||
def make_getter(key):
|
||||
def getter(pair):
|
||||
return pair.metadata[key]
|
||||
|
||||
return getter
|
||||
def flatten_groups_once(groups):
|
||||
return chain.from_iterable(groups)
|
||||
|
||||
|
||||
def make_coord_getter(c):
|
||||
@ -19,12 +16,15 @@ def make_coord_getter(c):
|
||||
}[c]
|
||||
|
||||
|
||||
def make_getter(key):
|
||||
def getter(pair):
|
||||
return pair.metadata[key]
|
||||
|
||||
return getter
|
||||
|
||||
|
||||
def make_length_getter(dim):
|
||||
return {
|
||||
"width": make_getter(Info.WIDTH),
|
||||
"height": make_getter(Info.HEIGHT),
|
||||
}[dim]
|
||||
|
||||
|
||||
def flatten_groups_once(groups):
|
||||
return chain.from_iterable(groups)
|
||||
Loading…
x
Reference in New Issue
Block a user