Skip to content

Commit

Permalink
Merge e900426 into 4a3d153
Browse files Browse the repository at this point in the history
  • Loading branch information
ngreenwald committed Jun 3, 2020
2 parents 4a3d153 + e900426 commit 0b23f75
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 25 deletions.
48 changes: 30 additions & 18 deletions caliban_toolbox/reshape_data.py
Expand Up @@ -33,15 +33,18 @@
import xarray as xr

from caliban_toolbox.utils import crop_utils, slice_utils, io_utils
from caliban_toolbox.utils.crop_utils import compute_crop_indices, crop_helper


def crop_multichannel_data(X_data, y_data, crop_size, overlap_frac, test_parameters=False):
def crop_multichannel_data(X_data, y_data, crop_size=None, crop_num=None, overlap_frac=0.1,
test_parameters=False):
"""Reads in a stack of images and crops them into small pieces for easier annotation
Args:
X_data: xarray containing raw images to be cropped
y_data: xarray containing labeled images to be chopped
crop_size: (row_crop, col_crop) tuple specifying shape of the crop
crop_size: (row_crop, col_crop) tuple specifying the length of the crop, including overlap
crop_num: (row_num, col_num) tuple specifying number of crops
overlap_frac: fraction that crops will overlap each other on each edge
test_parameters: boolean to determine whether to run all fovs, or only the first
Expand Down Expand Up @@ -72,24 +75,33 @@ def crop_multichannel_data(X_data, y_data, crop_size, overlap_frac, test_paramet
X_data, y_data = X_data[:1, ...], y_data[:1, ...]

# compute the start and end coordinates for the row and column crops
row_starts, row_ends, row_padding = crop_utils.compute_crop_indices(img_len=X_data.shape[4],
crop_size=crop_size[0],
overlap_frac=overlap_frac)

col_starts, col_ends, col_padding = crop_utils.compute_crop_indices(img_len=X_data.shape[5],
crop_size=crop_size[1],
overlap_frac=overlap_frac)
if crop_size is not None:
row_starts, row_ends, row_padding = compute_crop_indices(img_len=X_data.shape[4],
crop_size=crop_size[0],
overlap_frac=overlap_frac)

col_starts, col_ends, col_padding = compute_crop_indices(img_len=X_data.shape[5],
crop_size=crop_size[1],
overlap_frac=overlap_frac)
else:
row_starts, row_ends, row_padding = compute_crop_indices(img_len=X_data.shape[4],
crop_num=crop_num[0],
overlap_frac=overlap_frac)

col_starts, col_ends, col_padding = compute_crop_indices(img_len=X_data.shape[5],
crop_num=crop_num[1],
overlap_frac=overlap_frac)

# crop images
X_data_cropped, padded_shape = crop_utils.crop_helper(X_data, row_starts=row_starts,
row_ends=row_ends,
col_starts=col_starts, col_ends=col_ends,
padding=(row_padding, col_padding))

y_data_cropped, padded_shape = crop_utils.crop_helper(y_data, row_starts=row_starts,
row_ends=row_ends,
col_starts=col_starts, col_ends=col_ends,
padding=(row_padding, col_padding))
X_data_cropped, padded_shape = crop_helper(X_data, row_starts=row_starts,
row_ends=row_ends,
col_starts=col_starts, col_ends=col_ends,
padding=(row_padding, col_padding))

y_data_cropped, padded_shape = crop_helper(y_data, row_starts=row_starts,
row_ends=row_ends,
col_starts=col_starts, col_ends=col_ends,
padding=(row_padding, col_padding))

# save relevant parameters for reconstructing image
log_data = {}
Expand Down
5 changes: 3 additions & 2 deletions caliban_toolbox/reshape_data_test.py
Expand Up @@ -57,8 +57,9 @@ def test_crop_multichannel_data():
overlap_frac=overlap_frac,
test_parameters=False)

expected_crop_num = len(crop_utils.compute_crop_indices(row_len, crop_size[0],
overlap_frac)[0]) ** 2
expected_crop_num = len(crop_utils.compute_crop_indices(img_len=row_len,
crop_size=crop_size[0],
overlap_frac=overlap_frac)[0]) ** 2
assert (X_data_cropped.shape == (fov_len, stack_len, expected_crop_num, slice_num,
crop_size[0], crop_size[1], channel_len))

Expand Down
26 changes: 22 additions & 4 deletions caliban_toolbox/utils/crop_utils.py
Expand Up @@ -35,12 +35,15 @@
import xarray as xr


def compute_crop_indices(img_len, crop_size, overlap_frac):
def compute_crop_indices(img_len, crop_size=None, crop_num=None, overlap_frac=0):
"""Determine how to crop the image across one dimension.
Args:
img_len: length of the image for given dimension
crop_size: size in pixels of the crop in given dimension
crop_size: size in pixels of the crop in given dimension; must be specified if
crop_num not provided
crop_num: number of crops in the given dimension; must be specified if
crop_size not provided
overlap_frac: fraction that adjacent crops will overlap each other on each side
Returns:
Expand All @@ -49,8 +52,23 @@ def compute_crop_indices(img_len, crop_size, overlap_frac):
int: number of pixels of padding at start and end of image in given dimension
"""

# compute overlap fraction in pixels
overlap_pix = math.floor(crop_size * overlap_frac)
# compute indices based on fixed number of pixels per crop
if crop_size is not None:

# compute overlap fraction in pixels
overlap_pix = math.floor(crop_size * overlap_frac)

# compute indices based on fixed number of crops
elif crop_num is not None:
# number of pixels in non-overlapping portion of crop
non_overlap_crop_size = np.ceil(img_len / crop_num)

# Technically this is the fraction the non-overlap, rather than fraction of the whole,
# but we're going to visually crop overlays anyway to make sure value is appropriate
overlap_pix = math.floor(non_overlap_crop_size * overlap_frac)

# total crop size
crop_size = non_overlap_crop_size + overlap_pix

# the crops start at pixel 0, and are spaced crop_size - overlap_pix away from each other
start_indices = np.arange(0, img_len - overlap_pix, crop_size - overlap_pix)
Expand Down
26 changes: 25 additions & 1 deletion caliban_toolbox/utils/crop_utils_test.py
Expand Up @@ -61,7 +61,7 @@ def _blank_data_xr(fov_len, stack_len, crop_num, slice_num, row_len, col_len, ch
return test_stack_xr


def test_compute_crop_indices():
def test_compute_crop_indices_crop_size():
# test corner case of only one crop
img_len, crop_size, overlap_frac = 100, 100, 0.2
starts, ends, padding = crop_utils.compute_crop_indices(img_len=img_len, crop_size=crop_size,
Expand Down Expand Up @@ -89,6 +89,30 @@ def test_compute_crop_indices():
assert (padding == 0)


def test_compute_crop_indices_num_crops():
# test corner case of only one crop
img_len, crop_num, overlap_frac = 100, 1, 0.2
starts, ends, padding = crop_utils.compute_crop_indices(img_len=img_len, crop_num=crop_num,
overlap_frac=overlap_frac)
assert (len(starts) == 1)
assert (len(ends) == 1)

# test num crops that don't divide evenly into image size
img_len, crop_num, overlap_frac = 105, 3, 0.2
starts, ends, padding = crop_utils.compute_crop_indices(img_len=img_len, crop_num=crop_num,
overlap_frac=overlap_frac)
assert len(starts) == crop_num
assert ends[-1] == img_len + padding

# test overlap of 0 between crops
img_len, crop_num, overlap_frac = 200, 10, 0
starts, ends, padding = crop_utils.compute_crop_indices(img_len=img_len, crop_num=crop_num,
overlap_frac=overlap_frac)
assert (np.all(starts == range(0, 200, 20)))
assert (np.all(ends == range(20, 201, 20)))
assert (padding == 0)


def test_crop_helper():
# img params
fov_len, stack_len, crop_num, slice_num, row_len, col_len, chan_len = 2, 1, 1, 1, 200, 200, 1
Expand Down

0 comments on commit 0b23f75

Please sign in to comment.