Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: rename up-down to top-bottom, use tblr consistently #42

Merged
merged 1 commit into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions camtools/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pathlib import Path


class ArtifactManager:
class _ArtifactManager:
BASE_URL = "https://github.com/yxlao/camtools-artifacts/releases/download"

def __init__(self):
Expand Down Expand Up @@ -44,5 +44,5 @@ def get_artifact_path(artifact_key: str):
"""
Checks if the artifact is locally available, and if not, attempts to download it.
"""
artifact_manager = ArtifactManager()
artifact_manager = _ArtifactManager()
return artifact_manager.get_path(artifact_key)
104 changes: 52 additions & 52 deletions camtools/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ def crop_white_boarders(im: np.array, padding: Tuple[int] = (0, 0, 0, 0)) -> np.
Return:
im_dst: (H', W', 3) image, float32.
"""
udlr = compute_cropping(im)
im_dst = apply_cropping_padding(im, udlr, padding)
tblr = compute_cropping(im)
im_dst = apply_cropping_padding(im, tblr, padding)
return im_dst


def compute_cropping(im: np.array) -> Tuple[int]:
"""
Compute top, down, left, right white boarder in pixels.
Compute top, bottom, left, right white boarder in pixels.

This function can handle (H, W, N) images, e.g.,
- 3-channel image: (H, W, 3)
Expand All @@ -32,8 +32,8 @@ def compute_cropping(im: np.array) -> Tuple[int]:
im: (H, W, N) image, float32.

Return: tuple of 4 elements
crop_u: int, number of white pixels on the top edge.
crop_d: int, number of white pixels on the down edge.
crop_t: int, number of white pixels on the top edge.
crop_b: int, number of white pixels on the bottom edge.
crop_l: int, number of white pixels on the left edge.
crop_r: int, number of white pixels on the right edge.
"""
Expand All @@ -47,19 +47,19 @@ def compute_cropping(im: np.array) -> Tuple[int]:
h, w, _ = im.shape

# Find the number of white pixels on each edge.
crop_u = 0
crop_d = 0
crop_t = 0
crop_b = 0
crop_l = 0
crop_r = 0

for u in range(h):
if np.allclose(im[u, :, :], 1.0):
crop_u += 1
for t in range(h):
if np.allclose(im[t, :, :], 1.0):
crop_t += 1
else:
break
for d in range(h):
if np.allclose(im[h - d - 1, :, :], 1.0):
crop_d += 1
for b in range(h):
if np.allclose(im[h - b - 1, :, :], 1.0):
crop_b += 1
else:
break
for l in range(w):
Expand All @@ -73,79 +73,79 @@ def compute_cropping(im: np.array) -> Tuple[int]:
else:
break

return crop_u, crop_d, crop_l, crop_r
return crop_t, crop_b, crop_l, crop_r


def apply_cropping_padding(
src_im: np.ndarray,
im_src: np.ndarray,
cropping: Tuple[int],
padding: Tuple[int],
) -> np.ndarray:
"""
Apply cropping and padding to an image.

Args:
src_im: (H, W, 3) image, float32.
cropping: 4-tuple (crop_u, crop_d, crop_l, crop_r)
padding: 4-tuple (pad_u, pad_d, pad_l, pad_r)
im_src: (H, W, 3) image, float32.
cropping: 4-tuple (crop_t, crop_b, crop_l, crop_r)
padding: 4-tuple (pad_t, pad_b, pad_l, pad_r)

Return:
dst_im: (H, W, 3) image, float32.
im_dst: (H, W, 3) image, float32.
"""
if not src_im.dtype == np.float32:
raise ValueError(f"src_im.dtype == {src_im.dtype} != np.float32")
if not src_im.ndim == 3:
raise ValueError(f"src_im must be (H, W, 3), but got {src_im.shape}")
if not im_src.dtype == np.float32:
raise ValueError(f"im_src.dtype == {im_src.dtype} != np.float32")
if not im_src.ndim == 3:
raise ValueError(f"im_src must be (H, W, 3), but got {im_src.shape}")

(
h,
w,
_,
) = src_im.shape
crop_u, crop_d, crop_l, crop_r = cropping
dst_im = src_im[crop_u : h - crop_d, crop_l : w - crop_r, :]
pad_u, pad_d, pad_l, pad_r = padding
dst_im = np.pad(
dst_im,
((pad_u, pad_d), (pad_l, pad_r), (0, 0)),
) = im_src.shape
crop_t, crop_b, crop_l, crop_r = cropping
im_dst = im_src[crop_t : h - crop_b, crop_l : w - crop_r, :]
pad_t, pad_b, pad_l, pad_r = padding
im_dst = np.pad(
im_dst,
((pad_t, pad_b), (pad_l, pad_r), (0, 0)),
mode="constant",
constant_values=1.0,
)
return dst_im
return im_dst


def apply_croppings_paddings(src_ims, croppings, paddings):
def apply_croppings_paddings(im_srcs, croppings, paddings):
"""
Apply cropping and padding to a list of images.

Args:
src_ims: list of (H, W, 3) images, float32.
im_srcs: list of (H, W, 3) images, float32.
croppings: list of 4-tuples
[
(crop_u, crop_d, crop_l, crop_r),
(crop_u, crop_d, crop_l, crop_r),
(crop_t, crop_b, crop_l, crop_r),
(crop_t, crop_b, crop_l, crop_r),
...
]
paddings: list of 4-tuples
[
(pad_u, pad_d, pad_l, pad_r),
(pad_u, pad_d, pad_l, pad_r),
(pad_t, pad_b, pad_l, pad_r),
(pad_t, pad_b, pad_l, pad_r),
...
]
"""
num_images = len(src_ims)
if not len(croppings) == num_images:
raise ValueError(f"len(croppings) == {len(croppings)} != {num_images}")
if not len(paddings) == num_images:
raise ValueError(f"len(paddings) == {len(paddings)} != {num_images}")
num_ims = len(im_srcs)
if not len(croppings) == num_ims:
raise ValueError(f"len(croppings) == {len(croppings)} != {num_ims}")
if not len(paddings) == num_ims:
raise ValueError(f"len(paddings) == {len(paddings)} != {num_ims}")
for cropping in croppings:
if not len(cropping) == 4:
raise ValueError(f"len(cropping) == {len(cropping)} != 4")

dst_ims = []
for src_im, cropping, padding in zip(src_ims, croppings, paddings):
dst_im = apply_cropping_padding(src_im, cropping, padding)
dst_ims.append(dst_im)
for im_src, cropping, padding in zip(im_srcs, croppings, paddings):
im_dst = apply_cropping_padding(im_src, cropping, padding)
dst_ims.append(im_dst)

return dst_ims

Expand All @@ -158,23 +158,23 @@ def get_post_croppings_paddings_shapes(src_shapes, croppings, paddings):
src_shapes: list of source image shapes.
croppings: list of 4-tuples
[
(crop_u, crop_d, crop_l, crop_r),
(crop_u, crop_d, crop_l, crop_r),
(crop_t, crop_b, crop_l, crop_r),
(crop_t, crop_b, crop_l, crop_r),
...
]
paddings: list of 4-tuples
[
(pad_u, pad_d, pad_l, pad_r),
(pad_u, pad_d, pad_l, pad_r),
(pad_t, pad_b, pad_l, pad_r),
(pad_t, pad_b, pad_l, pad_r),
...
]
"""
dst_shapes = []
for src_shape, cropping, padding in zip(src_shapes, croppings, paddings):
crop_u, crop_d, crop_l, crop_r = cropping
pad_u, pad_d, pad_l, pad_r = padding
crop_t, crop_b, crop_l, crop_r = cropping
pad_t, pad_b, pad_l, pad_r = padding
dst_shape = (
src_shape[0] - crop_u - crop_d + pad_u + pad_d,
src_shape[0] - crop_t - crop_b + pad_t + pad_b,
src_shape[1] - crop_l - crop_r + pad_l + pad_r,
src_shape[2],
)
Expand Down
2 changes: 1 addition & 1 deletion camtools/tools/crop_boarders.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def entry_point(parser, args):
paddings.append((padding, padding, padding, padding))

# If same_shape is specified, pad all images to the same shape.
# Distribute the padding evenly among top/down, left/right.
# Distribute the padding evenly among top/bottom, left/right.
if args.same_shape:
dst_shapes = ct.image.get_post_croppings_paddings_shapes(
src_shapes=[im.shape for im in src_ims],
Expand Down
Loading