Skip to content

Commit

Permalink
Adding and refactoring tests for functions on binarization.py (#84)
Browse files Browse the repository at this point in the history
* References to bfly -> lepid

* Fixing typos

* test_return_largest_region will use fake_lepid_layout

* Adding test to return_bbox_largest_region

* Deleting previous binarization test images

* Improving name for test_missing_tags

* Starting to add test_binarization

* Adding pics necessary for testing

* Trying to fix the label_func issue

* Fixing label_func bug with a dirty trick :)

* test_binarization will test tags, ruler, leopd

* Adding documentation to test_binarization
  • Loading branch information
Alexandre de Siqueira authored Oct 5, 2021
1 parent 03de0cf commit 1026f92
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 66 deletions.
191 changes: 125 additions & 66 deletions mothra/tests/test_binarization.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,37 @@

from mothra import binarization
from skimage import draw
from skimage.io import imread
from skimage.util import img_as_bool


# required by fastai while predicting:
def label_func(image):
"""Function used to label images while training. Required by fastai."""
return path/"labels"/f"{image.stem}{LABEL_EXT}"

# a dirty trick, so pytorch sees label_func
import __main__; __main__.label_func = label_func


# defining labels for classes in the processed images.
TAGS_LABEL = 1

# defining RGB test image.
IMAGE_RGB = './mothra/tests/test_files/test_input/BMNHE_500607.JPG'

# binarized images.
LEPID_SEG = './mothra/tests/test_files/test_input/BMNHE_500607-lepid.png.seg'
RULER_SEG = './mothra/tests/test_files/test_input/BMNHE_500607-ruler.png.seg'
TAGS_SEG = './mothra/tests/test_files/test_input/BMNHE_500607-tags.png.seg'

# prediction weights.
WEIGHTS_BIN = './models/segmentation_test-4classes.pkl'


@pytest.fixture(scope="module")
def fake_bfly_layout():
"""Implements a "fake butterfly" input image containing ruler and
def fake_lepid_layout():
"""Implements a "fake lepidopteran" input image containing ruler and
identification tags, that mimics the others on the actual lepidopteran
datasets.
Expand All @@ -31,24 +54,24 @@ def fake_bfly_layout():
# creating ruler.
img_classes[230:] = 2

# creating "butterfly".
bfly_upper, bfly_lower = 50, 180
bfly_left, bfly_right = 50, 220
bfly_height = bfly_lower - bfly_upper
bfly_width = bfly_right - bfly_left
# creating "lepidopteran".
lepid_upper, lepid_lower = 50, 180
lepid_left, lepid_right = 50, 220
lepid_height = lepid_lower - lepid_upper
lepid_width = lepid_right - lepid_left

rr, cc = draw.polygon(
[bfly_upper, bfly_upper, bfly_lower],
[bfly_left, bfly_right, (bfly_left + bfly_right) / 2]
[lepid_upper, lepid_upper, lepid_lower],
[lepid_left, lepid_right, (lepid_left + lepid_right) / 2]
)
img_classes[rr, cc] = 3

return img_classes, (bfly_height, bfly_width)
return img_classes, (lepid_height, lepid_width)


@pytest.fixture(scope="module")
def fake_bfly_no_tags():
"""Implements a "fake butterfly" input image containing ruler, but no
def fake_lepid_no_tags():
"""Implements a "fake lepidopteran" input image containing ruler, but no
tags, that mimics the others on the actual lepidopteran datasets.
Notes
Expand All @@ -64,44 +87,44 @@ def fake_bfly_no_tags():
# creating ruler.
img_classes[230:] = 2

# creating "butterfly".
bfly_upper, bfly_lower = 50, 180
bfly_left, bfly_right = 50, 220
bfly_height = bfly_lower - bfly_upper
bfly_width = bfly_right - bfly_left
# creating "lepidopteran".
lepid_upper, lepid_lower = 50, 180
lepid_left, lepid_right = 50, 220
lepid_height = lepid_lower - lepid_upper
lepid_width = lepid_right - lepid_left

rr, cc = draw.polygon(
[bfly_upper, bfly_upper, bfly_lower],
[bfly_left, bfly_right, (bfly_left + bfly_right) / 2]
[lepid_upper, lepid_upper, lepid_lower],
[lepid_left, lepid_right, (lepid_left + lepid_right) / 2]
)
img_classes[rr, cc] = 3

return img_classes, (bfly_height, bfly_width)
return img_classes, (lepid_height, lepid_width)


def test_rescale_image(fake_bfly_layout):
"""Testing function binarization.binarization.
def test_rescale_image(fake_lepid_layout):
"""Testing function binarization._rescale_image.
Summary
-------
We decimate an input image, rescale it using binarization.binarization
We decimate an input image, rescale it using binarization._rescale_image
and compare their sizes.
Expected
--------
The input image and its decimated/rescaled version should have the same
size.
"""
bfly, _ = fake_bfly_layout
bfly_dec = bfly[::4]
bfly_dec_rescaled = binarization._rescale_image(image_refer=bfly,
image_to_rescale=bfly_dec)
lepid, _ = fake_lepid_layout
lepid_dec = lepid[::4]
lepid_dec_rescaled = binarization._rescale_image(image_refer=lepid,
image_to_rescale=lepid_dec)

assert (bfly_dec_rescaled.shape == bfly.shape)
assert (lepid_dec_rescaled.shape == lepid.shape)


def test_find_tags_edge(fake_bfly_layout):
"""Testing function binarization.binarization.
def test_find_tags_edge(fake_lepid_layout):
"""Testing function binarization.find_tags_edge.
Summary
-------
Expand All @@ -113,16 +136,16 @@ def test_find_tags_edge(fake_bfly_layout):
--------
Edge of the tags, returned as an X coordinate, is in a proper place.
"""
bfly, _ = fake_bfly_layout
lepid, _ = fake_lepid_layout
# returning a binary image containing only tags.
bfly_tags = bfly * (bfly == TAGS_LABEL)
lepid_tags = lepid * (lepid == TAGS_LABEL)

result = binarization.find_tags_edge(tags_bin=bfly_tags, top_ruler=230)
result = binarization.find_tags_edge(tags_bin=lepid_tags, top_ruler=230)
assert (250 <= result <= 260)


def test_missing_tags(fake_bfly_no_tags):
"""Testing function binarization.binarization.
def test_find_tags_edge_missing_tags(fake_lepid_no_tags):
"""Testing function binarization.find_tags_edge.
Summary
-------
Expand All @@ -134,51 +157,87 @@ def test_missing_tags(fake_bfly_no_tags):
image. That could probably impair the measurement process, but the
pipeline won't crash.
"""
bfly, _ = fake_bfly_no_tags
lepid, _ = fake_lepid_no_tags
# returning a binary image containing no tags.
bfly_no_tags = bfly * (bfly == TAGS_LABEL)
print(bfly_no_tags, bfly_no_tags.shape)
lepid_no_tags = lepid * (lepid == TAGS_LABEL)
print(lepid_no_tags, lepid_no_tags.shape)

result = binarization.find_tags_edge(tags_bin=bfly_no_tags, top_ruler=230)
result = binarization.find_tags_edge(tags_bin=lepid_no_tags, top_ruler=230)

assert (result >= 399)


def test_return_largest_region():
def test_binarization():
"""Testing function binarization.binarization.
Summary
-------
We pass a test image to binarization.binarization and check if its results
are equal to the expected.
Expected
--------
Expected tags, ruler and lepidopteran are equal to the ones returned by
binarization.binarization.
"""
lepid_rgb = imread(IMAGE_RGB)
tags_result, ruler_result, lepid_result = binarization.binarization(
image_rgb=lepid_rgb,
weights=WEIGHTS_BIN)

tags_expected = img_as_bool(imread(TAGS_SEG))

assert (tags_expected.all() == tags_result.all())

ruler_expected = img_as_bool(imread(RULER_SEG))

assert (ruler_expected.all() == ruler_result.all())

lepid_expected = img_as_bool(imread(LEPID_SEG))

assert (lepid_expected.all() == lepid_result.all())


def test_return_bbox_largest_region(fake_lepid_layout):
"""Testing function binarization.return_bbox_largest_region.
Summary
-------
We pass a binary input image with a region and compare the resulting
bounding box from binarization.return_bbox_largest_region with the expected
result.
Expected
--------
Resulting and expected bounding boxes are equal.
"""
lepid, _ = fake_lepid_layout
lepid = (lepid == 3) # getting only the lepidopteran

bbox_result = binarization.return_bbox_largest_region(lepid)

bbox_expected = (50, 50, 181, 221)

assert bbox_result == bbox_expected


def test_return_largest_region(fake_lepid_layout):
"""Testing function binarization.return_largest_region.
Summary
-------
We pass a binary input image with three regions and check if the result
We pass a binary input image with three regions and check if the resulting
image from binarization.return_largest_region contains only the largest
one.
Expected
--------
Resulting image has only the largest region.
"""
img_test = np.asarray([[0, 0, 1, 1, 0, 0, 0, 0, 1, 0],
[0, 1, 1, 1, 1, 0, 0, 0, 1, 1],
[1, 1, 1, 1, 1, 1, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 0, 0, 1, 0],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 1, 1, 0],
[0, 1, 1, 1, 1, 0, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 0, 0, 1, 1, 1],
[0, 1, 1, 1, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype='bool')

img_expect = np.asarray([[0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype='bool')

img_result = binarization.return_largest_region(img_test)

assert (img_expect.all() == img_result.all())
lepid, _ = fake_lepid_layout
img_result = binarization.return_largest_region(lepid)

img_expect = (lepid == 3) # getting only the lepidopteran

assert (img_expect.all() == img_result.all())
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 1026f92

Please sign in to comment.