Skip to content

Commit

Permalink
Merge pull request #337 from clEsperanto/stitching
Browse files Browse the repository at this point in the history
Stitching
  • Loading branch information
haesleinhuepf authored May 12, 2024
2 parents bb4c659 + 4f479b7 commit ae15f44
Show file tree
Hide file tree
Showing 5 changed files with 281 additions and 2 deletions.
5 changes: 3 additions & 2 deletions pyclesperanto_prototype/_tier3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
from ._standard_deviation_of_touching_neighbors_map import standard_deviation_of_touching_neighbors_map
from ._standard_deviation_of_proximal_neighbors_map import standard_deviation_of_proximal_neighbors_map
from ._standard_deviation_of_proximal_neighbors_map import standard_deviation_of_proximal_neighbors_map as standard_deviation_of_distal_neighbors_map

from ._stitch_horizontally_linear_blending import stitch_horizontally_linear_blending
from ._stitch_vertically_linear_blending import stitch_vertically_linear_blending
from ._subtract_gaussian_background import subtract_gaussian_background
from ._z_position_range_projection import z_position_range_projection
from ._z_position_range_projection import z_position_range_projection
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from .._tier0 import plugin_function
from .._tier0 import create
from .._tier0 import create_none
from .._tier0 import Image
from .._tier1 import paste

@plugin_function(output_creator=create_none, categories=['combine', 'transform', 'in assistant'])
def stitch_horizontally_linear_blending(image1 : Image, image2 : Image, destination : Image = None, num_pixels_overlap:int=0) -> Image:
"""Combines two images in X by linearly blending them in an overlapping region.
Parameters
----------
image1 : Image
image2 : Image
destination : Image, optional
num_pixels_overlap : int, optional
Returns
-------
destination
"""
from .._tier0 import create, asarray
from .._tier1 import set_ramp_x, crop
from .._tier1 import subtract_image_from_scalar
from .._tier2 import combine_horizontally

num_pixels_overlap = int(num_pixels_overlap)
image1_width = image1.shape[-1]
image2_width = image2.shape[-1]
image1_height = image1.shape[-2]
image2_height = image2.shape[-2]
image1_depth = 1 if len(image1.shape) == 2 else image1.shape[-3]
image2_depth = 1 if len(image2.shape) == 2 else image2.shape[-3]

# crop out left, right and the two overlapping parts
left_part = crop(image1, width=image1_width - num_pixels_overlap, height=image1_height, depth=image1_depth)
center_part1 = crop(image1, start_x=image1_width - num_pixels_overlap, width=num_pixels_overlap, height=image1_height, depth=image1_depth)
center_part2 = crop(image2, width=num_pixels_overlap, height=image2_height, depth=image2_depth)
right_part = crop(image2, start_x=num_pixels_overlap, width=image2_width - num_pixels_overlap, height=image2_height, depth=image2_depth)

# setup a gradient for the blending
gradient = create(center_part1.shape)
set_ramp_x(gradient)
gradient_right_left = (gradient + 1) / (gradient.shape[-1]+1)
gradient_left_right = subtract_image_from_scalar(gradient_right_left, scalar=1)

# compute the overlapping image by multiplying both images with the gradient
center_part = asarray(center_part1) * gradient_left_right + asarray(center_part2) * gradient_right_left

# combine images vertically
return combine_horizontally(combine_horizontally(left_part, center_part), right_part, destination)
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from .._tier0 import plugin_function
from .._tier0 import create
from .._tier0 import create_none
from .._tier0 import Image
from .._tier1 import paste

@plugin_function(output_creator=create_none, categories=['combine', 'transform', 'in assistant'])
def stitch_vertically_linear_blending(image1 : Image, image2 : Image, destination : Image = None, num_pixels_overlap:int=0) -> Image:
"""Combines two images in Y by linearly blending them in an overlapping region.
Parameters
----------
image1 : Image
image2 : Image
destination : Image, optional
num_pixels_overlap : int, optional
Returns
-------
destination
"""
from .._tier0 import create, asarray
from .._tier1 import set_ramp_y, crop
from .._tier1 import subtract_image_from_scalar
from .._tier2 import combine_vertically

num_pixels_overlap = int(num_pixels_overlap)
image1_width = image1.shape[-1]
image2_width = image2.shape[-1]
image1_height = image1.shape[-2]
image2_height = image2.shape[-2]
image1_depth = 1 if len(image1.shape) == 2 else image1.shape[-3]
image2_depth = 1 if len(image2.shape) == 2 else image2.shape[-3]

# crop out left, right and the two overlapping parts
top_part = crop(image1, width=image1_width, height=image1_height - num_pixels_overlap, depth=image1_depth)
center_part1 = crop(image1, start_y=image1_height-num_pixels_overlap, width=image1_width, height=num_pixels_overlap, depth=image1_depth)
center_part2 = crop(image2, width=image2_width, height=num_pixels_overlap, depth=image2_depth)
bottom_part = crop(image2, start_y=num_pixels_overlap, width=image2_width, height=image2_height-num_pixels_overlap, depth=image2_depth)

# setup a gradient for the blending
gradient = create(center_part1.shape)
set_ramp_y(gradient)
gradient_right_left = (gradient + 1) / (gradient.shape[-2]+1)
gradient_left_right = subtract_image_from_scalar(gradient_right_left, scalar=1)

# compute the overlapping image by multiplying both images with the gradient
center_part = asarray(center_part1) * gradient_left_right + asarray(center_part2) * gradient_right_left

# combine images vertically
return combine_vertically(combine_vertically(top_part, center_part), bottom_part, destination)
80 changes: 80 additions & 0 deletions tests/test_stitch_horizontally_linear_blending.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import pyclesperanto_prototype as cle
import numpy as np


def test_stitch_horizontally_linear_blending_overlap0():
test1 = cle.push(np.asarray([
[1, 1],
[1, 1]
]))
test2 = cle.push(np.asarray([
[2, 2, 2],
[2, 2, 2]
]))

reference = cle.push(np.asarray([
[1, 1, 2, 2, 2],
[1, 1, 2, 2, 2]
]))

result = cle.stitch_horizontally_linear_blending(test1, test2)

a = cle.pull(result)
b = cle.pull(reference)

print(a)
print(b)

assert (np.allclose(a, b, 0.01))

def test_stitch_horizontally_linear_blending_overlap1():
test1 = cle.push(np.asarray([
[1, 1],
[1, 1]
]))
test2 = cle.push(np.asarray([
[2, 2, 2],
[2, 2, 2]
]))

reference = cle.push(np.asarray([
[1, 1.5, 2, 2],
[1, 1.5, 2, 2]
]))

result = cle.stitch_horizontally_linear_blending(test1, test2, num_pixels_overlap=1)

a = cle.pull(result)
b = cle.pull(reference)

print(a)
print(b)

assert (np.allclose(a, b, 0.01))


def test_stitch_horizontally_linear_blending_overlap2():
test1 = cle.push(np.asarray([
[1, 1, 1],
[1, 1, 1]
]))
test2 = cle.push(np.asarray([
[2, 2, 2],
[2, 2, 2]
]))

reference = cle.push(np.asarray([
[1, 1.33, 1.67, 2],
[1, 1.33, 1.67, 2]
]))

result = cle.stitch_horizontally_linear_blending(test1, test2, num_pixels_overlap=2)

a = cle.pull(result)
b = cle.pull(reference)

print(a)
print(b)

assert (np.allclose(a, b, 0.01))

96 changes: 96 additions & 0 deletions tests/test_stitch_vertically_linear_blending.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import pyclesperanto_prototype as cle
import numpy as np


def test_stitch_vertically_linear_blending_overlap0():
test1 = cle.push(np.asarray([
[1, 1],
[1, 1],
[1, 1]
]))
test2 = cle.push(np.asarray([
[2, 2],
[2, 2],
[2, 2]
]))

reference = cle.push(np.asarray([
[1, 1],
[1, 1],
[1, 1],
[2, 2],
[2, 2],
[2, 2],
]))

result = cle.stitch_vertically_linear_blending(test1, test2)

a = cle.pull(result)
b = cle.pull(reference)

print(a)
print(b)

assert (np.allclose(a, b, 0.01))


def test_stitch_vertically_linear_blending_overlap1():
test1 = cle.push(np.asarray([
[1, 1],
[1, 1],
[1, 1]
]))
test2 = cle.push(np.asarray([
[2, 2],
[2, 2],
[2, 2]
]))

reference = cle.push(np.asarray([
[1, 1],
[1, 1],
[1.5, 1.5],
[2, 2],
[2, 2],
]))

result = cle.stitch_vertically_linear_blending(test1, test2, num_pixels_overlap=1)

a = cle.pull(result)
b = cle.pull(reference)

print(a)
print(b)

assert (np.allclose(a, b, 0.01))


def test_stitch_vertically_linear_blending_overlap2():
test1 = cle.push(np.asarray([
[1, 1],
[1, 1],
[1, 1]
]))
test2 = cle.push(np.asarray([
[2, 2],
[2, 2],
[2, 2]
]))

reference = cle.push(np.asarray([
[1, 1],
[1.33, 1.33],
[1.67, 1.67],
[2, 2],
]))

result = cle.stitch_vertically_linear_blending(test1, test2, num_pixels_overlap=2)

a = cle.pull(result)
b = cle.pull(reference)

print(a)
print(b)

assert (np.allclose(a, b, 0.01))

0 comments on commit ae15f44

Please sign in to comment.