Skip to content

Example 1 : single workflow

Romain Mormont edited this page Nov 29, 2017 · 4 revisions

The objective for this example is to detect in the following image whether the objects are squares or circles and to detect their color.

First toy example's image

Code

For solving this problem, we will use a SLDCWorkflow:

Defining components:
[1] Defining the segmentation procedure (simple thresholding)
[2] Defining a dispatching rule (detecting whether the shape of the object is a circle or a square)
[3] Defining a classifier (predicting the color of the object)

Building the workflow:
[4] Using a builder, building the workflow using the defined components
[5] Instanciating the image

Executing the workflow on the image:
[6] Running the workflow

Exploring the results and metadata:
[7] Displaying running times
[8] Showing detected objects

Script:

import os
import numpy as np
from sldc import Segmenter, DispatchingRule, PolygonClassifier, report_timing, StandardOutputLogger, Logger
from sldc.builder import SLDCWorkflowBuilder
from test import NumpyImage, draw_circle, draw_square


""" (1) Define a segmenting procedure for locating the objects """
class BasicSegmenter(Segmenter):
    def __init__(self):
        super(BasicSegmenter, self).__init__()

    def segment(self, image):
        """Assume grayscale image"""
        mask = (image > 0).astype(np.uint8)
        mask[mask == 1] = 255
        return mask


""" (2) Define a dispatching rule for identifying circle and squares"""
class ShapeRule(DispatchingRule):
    CIRCLE = "circle"
    SQUARE = "square"

    def __init__(self, which=CIRCLE):
        self._which = which

    def evaluate(self, image, polygon):
        circularity = 4 * np.pi * polygon.area / (polygon.length * polygon.length)
        if self._which == self.CIRCLE:
            return circularity > 0.85
        else:
            return circularity <= 0.85


""" (3) Define a classifier that classify the object according to its color"""
class ColorClassifier(PolygonClassifier):
    def predict(self, image, polygon):
        windows = image.np_image
        x, y = int(polygon.centroid.x), int(polygon.centroid.y)
        return windows[y, x], 1.0


def main():
    """ (4) build the workflow """
    logger = StandardOutputLogger(Logger.INFO)
    builder = SLDCWorkflowBuilder()
    builder.set_n_jobs(4)
    builder.set_logger(logger)
    builder.set_default_tile_builder()
    builder.set_tile_size(256, 256)
    builder.set_segmenter(BasicSegmenter())
    builder.add_classifier(ShapeRule(ShapeRule.CIRCLE), ColorClassifier(), "circle")
    builder.add_classifier(ShapeRule(ShapeRule.SQUARE), ColorClassifier(), "square")

    workflow = builder.get()

    """ (5) build a (fake) image """
    np_image = np.zeros([2000, 2000], dtype=np.uint8)
    np_image = draw_circle(np_image, 100, (500, 1500), 255)
    np_image = draw_circle(np_image, 100, (1500, 600), 127)
    np_image = draw_square(np_image, 200, (500, 500), 255)
    np_image = draw_square(np_image, 200, (1500, 1500), 127)
    np_image = draw_square(np_image, 300, (1000, 1000), 255)
    image = NumpyImage(np_image)

    """ (6) process the image """
    results = workflow.process(image)

    """ (7) report execution times """
    report_timing(results.timing, logger)

    """ (8) explore the results """
    for i, object_info in enumerate(results):
        print(
            "Object {}:".format(i + 1) + os.linesep +
            "> area    : {}".format(object_info.polygon.area) + os.linesep +
            "> label   : '{}'".format(object_info.label) + os.linesep +
            "> proba   : {}".format(object_info.proba) + os.linesep +
            "> dispatch: '{}'".format(object_info.dispatch)
        )


if __name__ == "__main__":
    main()

Output of the script:

[pid:012048][2017-11-29T16:19:31.794986][INFO ] SLDCWorkflow : start segment/locate.
[pid:012048][2017-11-29T16:19:32.641947][INFO ] SLDCWorkflow : end segment/locate.
[pid:012048][2017-11-29T16:19:32.641947][INFO ] SLDCWorkflow : 81 tile(s) processed in 0.8470055087450934 s.
[pid:012048][2017-11-29T16:19:32.641947][INFO ] SLDCWorkflow : 18 polygon(s) found on those tiles.
[pid:012048][2017-11-29T16:19:32.641947][INFO ] SLDCWorkflow : start merging
[pid:012048][2017-11-29T16:19:32.658946][INFO ] SLDCWorkflow : end merging.
[pid:012048][2017-11-29T16:19:32.658946][INFO ] SLDCWorkflow : 5 polygon(s) found.
[pid:012048][2017-11-29T16:19:32.658946][INFO ] SLDCWorkflow : executed in 0.016348062299703536 s.
[pid:012048][2017-11-29T16:19:32.658946][INFO ] SLDCWorkflow : start dispatch/classify.
[pid:012048][2017-11-29T16:19:32.658946][INFO ] Dispatcher: start dispatching.
[pid:012048][2017-11-29T16:19:32.659946][INFO ] Dispatcher: end dispatching.
[pid:012048][2017-11-29T16:19:32.659946][INFO ] Dispatcher: 2/5 polygons dispatched to 'circle'.
[pid:012048][2017-11-29T16:19:32.659946][INFO ] Dispatcher: 3/5 polygons dispatched to 'square'.
[pid:012048][2017-11-29T16:19:32.659946][WARN ] Dispatcher: 0/5 polygons not dispatched.
[pid:012048][2017-11-29T16:19:32.659946][INFO ] DispatcherClassifier: start classification.
[pid:012048][2017-11-29T16:19:32.660947][INFO ] DispatcherClassifier: end classification.
[pid:012048][2017-11-29T16:19:32.660947][INFO ] SLDCWorkflow : end dispatch/classify.
[pid:012048][2017-11-29T16:19:32.660947][INFO ] SLDCWorkflow : executed in 0.002233285715188771 s.
[pid:012048][2017-11-29T16:19:32.661947][INFO ] Timing report:
[pid:012048][2017-11-29T16:19:32.662947][INFO ] * merge: 0.01635s (mean:0.01635s std:0.0s min:0.01635s max:0.01635s, count:1)
[pid:012048][2017-11-29T16:19:32.662947][INFO ] * dispatch_classify: 0.00223s (mean:0.00223s std:0.0s min:0.00223s max:0.00223s, count:1)
[pid:012048][2017-11-29T16:19:32.662947][INFO ]   * classify: 0.00074s (mean:0.00037s std:1e-05s min:0.00036s max:0.00038s, count:2)
[pid:012048][2017-11-29T16:19:32.663947][INFO ]   * dispatch: 0.00088s (mean:0.00088s std:0.0s min:0.00088s max:0.00088s, count:1)
[pid:012048][2017-11-29T16:19:32.663947][INFO ] * detect: 0.84701s (mean:0.84701s std:0.0s min:0.84701s max:0.84701s, count:1)
[pid:012048][2017-11-29T16:19:32.663947][INFO ]   * load: 0.00157s (mean:2e-05s std:0.0s min:1e-05s max:3e-05s, count:81)
[pid:012048][2017-11-29T16:19:32.663947][INFO ]   * segment: 0.01467s (mean:0.00018s std:8e-05s min:2e-05s max:0.00042s, count:81)
[pid:012048][2017-11-29T16:19:32.663947][INFO ]   * locate: 0.51553s (mean:0.00636s std:0.00302s min:0.00043s max:0.01349s, count:81)
Object 1:
> area    : 40000.0
> label   : '255'
> proba   : 1.0
> dispatch: 'square'
Object 2:
> area    : 31463.00000000025
> label   : '127'
> proba   : 1.0
> dispatch: 'circle'
Object 3:
> area    : 90000.0
> label   : '255'
> proba   : 1.0
> dispatch: 'square'
Object 4:
> area    : 31463.000000000007
> label   : '255'
> proba   : 1.0
> dispatch: 'circle'
Object 5:
> area    : 40000.0
> label   : '127'
> proba   : 1.0
> dispatch: 'square'
Clone this wiki locally