Generating feature stacks#

Machine learning algorithms such as Random Forest Classifiers, e.g. as implemented in APOC use feature stacks for pixel classification. Feature stacks are lists of images of the same size (2D or 3D). APOC brings a utility function for generating feature stacks. It takes an image and a feature specification string as input to produce a feature stack.

Let’s start with loading an example image and making a convenience function for visualization:

from skimage.io import imread, imshow
import numpy as np
import apoc
import matplotlib.pyplot as plt

We start again with the blobs example image.

image = imread('../../data/blobs.tif')
imshow(image)
<matplotlib.image.AxesImage at 0x7f9ba9333580>
../_images/05dbb9e7395c2944b360ead71bdaae0c366bad17ce7958c6cbb8002d921ca585.png

We furthermore define a utility function for visualizing feature stacks.

def visualize(feature_stack):
    """
    Shows lists of images in rows of three
    """
    if len(feature_stack) == 0:
        return
    
    # show feature images
    width = 3
    height = int(len(feature_stack) / 3)
    if height * width < len(feature_stack):
        height = height + 1    
    
    fig, axes = plt.subplots(height, width, figsize=(10,10))

    for i, f in enumerate(feature_stack):
        if height > 1:
            axes[int(i / 3)][i % 3].imshow(f, cmap=plt.cm.gray)
        else:
            axes[i].imshow(f, cmap=plt.cm.gray)

    w = len(feature_stack) % width
    if w > 0:
        w = width - w
        while (w > 0):
            if height > 1:
                axes[-1][width - w].set_visible(False)
            else:
                axes[width - w].set_visible(False)
            w = w - 1

    plt.show()        

Feature stacks#

A feature stack is a list of 2D or 3D images, typically derived from an original image. If you don’t specify any feature specfication, a stack will be generated with the original image, a blurred version and an edge image:

feature_stack = apoc.generate_feature_stack(image)

visualize(feature_stack)
../_images/d368282df2e14f5d52e4b9898770d58a62b547688916932fa7daa25c67448862.png

There are also some pre-defined Feature sets:

for f in apoc.PredefinedFeatureSet:
    print(f)
    visualize(apoc.generate_feature_stack(image, f))
PredefinedFeatureSet.custom
PredefinedFeatureSet.small_quick
../_images/456a6f3bcde240b3625667ba87bc324d9ec8c9a3c48deb15cf25e8595dd0ef2e.png
PredefinedFeatureSet.medium_quick
../_images/4d00598310029864edc59bc8bd72227a92f37641a7e2a55f9a2e208435116ee5.png
PredefinedFeatureSet.large_quick
../_images/f860120a5d08d2c235423b75ebada775ae1964211b51e08a3781fede34102ad3.png
PredefinedFeatureSet.small_dog_log
../_images/a34d206a7fe5588fa06a264a8be12cede2b08979de18caa24cf0c6426fda3a7b.png
PredefinedFeatureSet.medium_dog_log
../_images/986167d7cef40cf1538e2af422fd41cd693222b60e7c7fe7f408b489f0d0ee8d.png
PredefinedFeatureSet.large_dog_log
../_images/73af9287ed49aabcc7cf7cb62d3308b1bb9e432f95dc1d679272082e1d077bb8.png
PredefinedFeatureSet.object_size_1_to_2_px
../_images/30a8f6db05b82bc3629469bbeb2cc6bc652bd1dcb02ae74240b9c83e1049a424.png
PredefinedFeatureSet.object_size_1_to_5_px
../_images/07949a492843d1c3670dde1969f94f1236cf25b2af11a058eede40c9c2c50cb0.png
PredefinedFeatureSet.object_size_3_to_8_px
../_images/6a90b53f45e70b7e49f393fe292096d21a65617843e5b59b5c5156d13f72720b.png
PredefinedFeatureSet.object_size_5_to_10_px
../_images/b5c94dbe67081f1d4ecb7cf518bc4ce67e31f59a8bb4d8e58cc25df1ae41323b.png
PredefinedFeatureSet.object_size_10_to_15_px
../_images/2361605ec7c06893f6aa8db467403a211d58fc3a6e536106f223ad122a15b18c.png
PredefinedFeatureSet.object_size_15_to_20_px
../_images/37430e213351c372d3917c12b2ce5cd2c34dcc883287a2167d5789b4045f910e.png
PredefinedFeatureSet.object_size_20_to_25_px
../_images/f4689e47f5e839dd2d0f08201629d6881fe6a785856247588075b3a4f8616e13.png
PredefinedFeatureSet.object_size_25_to_50_px
../_images/b7cf8cfcb5198f5e48c8f0b42668627062e39eb68ed72be06a5e640abb2e30d3.png
PredefinedFeatureSet.object_size_50_to_100_px
../_images/7351ceb791bbe30c5cfaf9625614784a50d4e3d3b7a84c366666407bda81b0e9.png

Custom feature definitions#

You can furthermore, define specific features corresponding to clesperanto filters:

feature_stack = apoc.generate_feature_stack(image, "gaussian_blur=3 mean_box=3 top_hat_box=3")

visualize(feature_stack)
../_images/e92523b12cff3e18cd5b9186ccaf1a74e854c406e8216bc527dd7de0f0738c73.png
feature_stack = apoc.generate_feature_stack(image, "maximum_box=3 difference_of_gaussian=5 sobel=0")

visualize(feature_stack)
../_images/eb62c618f59a738cf4fb469d4d200066a990bd0ba9c9da0543d733c1abf53adf.png

You can also vary radii / sigmas of the fetures:

feature_stack = apoc.generate_feature_stack(image, "gaussian_blur=1 gaussian_blur=5 gaussian_blur=10 gaussian_blur=20")

visualize(feature_stack)
../_images/af0a1c3cfa9ad9885142e184a28c562edac37de8d2d1e057c2321c5bdb2e2c77.png

Furthermore, some features can be combined, for example you can compute the sobel of a Gaussian or a Laplacian of a Gaussian

feature_stack = apoc.generate_feature_stack(image, "sobel_of_gaussian_blur=1 sobel_of_gaussian_blur=5 sobel_of_gaussian_blur=10")

visualize(feature_stack)
../_images/29118e08c3cf53a4a5ce3e222882ddeef431c0d3e37e819e46f1ec71b6893983.png
feature_stack = apoc.generate_feature_stack(image, "laplace_box_of_gaussian_blur=1 laplace_box_of_gaussian_blur=5 laplace_box_of_gaussian_blur=10")

visualize(feature_stack)
../_images/257f4338ef05c87a57b7987393dae73ab13d54c2c455692872b0c981ca77f68e.png