Commit b6394ccb authored by Manuel Günther's avatar Manuel Günther

Merge branch 'block_gen' into 'master'

Add a block_generator function. Fixes #11

Closes #11

See merge request !16
parents 8b84d8c6 18132e74
Pipeline #19851 passed with stages
in 35 minutes and 36 seconds
......@@ -175,3 +175,54 @@ def shift(src, offset, dst = None, src_mask = None, dst_mask = None, fill_patter
# shift image by cropping
return crop(src, offset, dst=dst, src_mask=src_mask, dst_mask=dst_mask, fill_pattern=fill_pattern)
def block_generator(input, block_size, block_overlap=(0, 0)):
"""Performs a block decomposition of a 2D or 3D array/image
It works exactly as :any:`bob.ip.base.block` except that it yields the blocks
one by one instead of concatenating them. It also works with color images.
Parameters
----------
input : :any:`numpy.ndarray`
A 2D array (Height, Width) or a color image (Bob format: Channels,
Height, Width).
block_size : (:obj:`int`, :obj:`int`)
The size of the blocks in which the image is decomposed.
block_overlap : (:obj:`int`, :obj:`int`), optional
The overlap of the blocks.
Yields
------
array_like
A block view of the image. Modifying the blocks will change the original
image as well. This is different from :any:`bob.ip.base.block`.
Raises
------
ValueError
If the block_overlap is not smaller than block_size.
If the block_size is bigger than the image size.
"""
block_h, block_w = block_size
overlap_h, overlap_w = block_overlap
img_h, img_w = input.shape[-2:]
if overlap_h >= block_h or overlap_w >= block_w:
raise ValueError(
"block_overlap: {} must be smaller than block_size: {}.".format(
block_overlap, block_size))
if img_h < block_h or img_w < block_w:
raise ValueError(
"block_size: {} must be smaller than the image size: {}.".format(
block_size, input.shape[-2:]))
# Determine the number of block per row and column
size_ov_h = block_h - overlap_h
size_ov_w = block_w - overlap_w
# Perform the block decomposition
for h in range(0, img_h - block_h + 1, size_ov_h):
for w in range(0, img_w - block_w + 1, size_ov_w):
yield input[..., h: h + block_h, w: w + block_w]
......@@ -24,6 +24,8 @@ def test_block():
B = numpy.ndarray(shape_4D, 'float64')
bob.ip.base.block(A_org, (2, 2), (0, 0), output = B)
assert (B == A_ans_0_4D).all()
C = bob.ip.base.block(A_org, (2, 2), (0, 0), flat = False)
assert (C == A_ans_0_4D).all()
......@@ -36,3 +38,17 @@ def test_block():
assert (B == A_ans_0_3D).all()
def test_block_generator():
# test the block generator
patches = bob.ip.base.block_generator(A_org, (2, 2))
for patch in A_ans_0_3D:
assert numpy.all(patch == next(patches))
# test on a color image
patches = bob.ip.base.block_generator(
numpy.asarray([A_org, A_org + 17, A_org - 17]), (2, 2))
for patch in A_ans_0_3D:
gen_patch = next(patches)
assert numpy.all(patch == gen_patch[0])
assert numpy.all(patch + 17 == gen_patch[1])
assert numpy.all(patch - 17 == gen_patch[2])
......@@ -57,6 +57,7 @@ Functions
bob.ip.base.angle_to_horizontal
bob.ip.base.block
bob.ip.base.block_output_shape
bob.ip.base.block_generator
bob.ip.base.crop
bob.ip.base.shift
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment