Source code for node_conversions

# This file is part of Sympathy for Data.
# Copyright (c) 2017, Combine Control Systems AB
#
# SYMPATHY FOR DATA COMMERCIAL LICENSE
# You should have received a link to the License with Sympathy for Data.

"""
Some of the docstrings for this module have been
extracted from the `scikit-image <http://scikit-image.org/>`_ library
and are covered by their respective licenses.
"""
import numpy as np

from sympathy.api import node
from sympathy.api.nodeconfig import Ports
from sympathy.api.exceptions import SyDataError

from sylib.imageprocessing.image import ImagePort
from sylib.imageprocessing.algorithm_selector import ImageFiltering_abstract
from sylib.imageprocessing.generic_filtering import GenericImageFiltering


def alg_cartesian_to_complex(im, par):
    if len(im.shape) < 3:
        raise SyDataError(
            'Wrong number of channels for conversion to complex number')
    if (im.shape[2] % 2) == 1:
        raise SyDataError(
            'Conversion to complex number requires an even number of channels')
    res = np.zeros(im.shape[:2] + (int(im.shape[2]/2),)).astype(complex)
    for ch in range(int(im.shape[2]/2)):
        res[:, :, ch] = im[:, :, 2 * ch] + im[:, :, 2 * ch + 1] * 1j
    return res


def alg_polar_to_complex(im, par):
    if len(im.shape) < 3:
        raise SyDataError(
            'Wrong number of channels for conversion to complex number')
    if (im.shape[2] % 2) == 1:
        raise SyDataError(
            'Conversion to complex number requires an even number of channels')
    res = np.zeros(im.shape[:2] + (int(im.shape[2]/2),)).astype(complex)
    for ch in range(int(im.shape[2]/2)):
        res[:, :, ch] = im[:, :, 2 * ch] * np.exp(im[:, :, 2 * ch + 1] * 1j)
    return res


def alg_cartesian_from_complex(im, par):
    if len(im.shape) < 3:
        im = im.reshape(im.shape+(1,))
    res = np.zeros(im.shape[:2] + (im.shape[2]*2,))
    for ch in range(im.shape[2]):
        res[:, :, 2 * ch] = np.real(im[:, :, ch])
        res[:, :, 2 * ch + 1] = np.imag(im[:, :, ch])
    return res


def alg_polar_from_complex(im, par):
    if len(im.shape) < 3:
        im = im.reshape(im.shape+(1,))
    res = np.zeros(im.shape[:2] + (im.shape[2]*2,))
    for ch in range(im.shape[2]):
        res[:, :, 2 * ch] = np.abs(im[:, :, ch])
        res[:, :, 2 * ch + 1] = np.angle(im[:, :, ch])
    return res


CONVERSION_ALGS = {
    'to integer': {
        'description': 'Converts all channels into integer data',
        'multi_chromatic': True,
        'algorithm': lambda im, par: im.astype('int64')
    },
    'to float': {
        'description': 'Converts all channels into float data',
        'multi_chromatic': True,
        'algorithm': lambda im, par: im.astype('float64')
    },
    'cartesian to complex': {
        'description': (
            'Converts pairs of real/imaginary channels into complex '
            'valued channels'),
        'multi_chromatic': True,
        'algorithm': alg_cartesian_to_complex
    },
    'polar to complex': {
        'description': (
            'Converts pairs of magnitude/phase channels into complex '
            'valued channels'),
        'multi_chromatic': True,
        'algorithm': alg_polar_to_complex
    },
    'cartesian from complex': {
        'description': (
            'Converts complex valued channels into pairs of real/imaginary '
            'channels'),
        'multi_chromatic': True,
        'algorithm': alg_cartesian_from_complex
    },
    'polar from complex': {
        'description': (
            'Converts complex valued channels into pairs of magnitude/phase '
            'channels'),
        'multi_chromatic': True,
        'algorithm': alg_polar_from_complex
    },
}


CONVERSION_PARAMETERS = []
CONVERSION_TYPES = {}
CONVERSION_DEFAULTS = {}


[docs] class ConversionImageFiltering(ImageFiltering_abstract, GenericImageFiltering, node.Node): name = 'Convert Image Data' icon = 'image_convert.svg' description = ( 'Applies simple filtering or scaling algorithms on an image. For more ' 'complex operations see the more specialized image manipulation nodes') nodeid = 'com.sympathyfordata.imageanalysis.conversion_filters' algorithms = CONVERSION_ALGS options_list = CONVERSION_PARAMETERS options_types = CONVERSION_TYPES options_default = CONVERSION_DEFAULTS parameters = node.parameters() parameters.set_string('algorithm', value=next(iter(algorithms)), description='', label='Algorithm') ImageFiltering_abstract.generate_parameters(parameters, options_types, options_default) inputs = Ports([ ImagePort('source image to filter', name='source'), ]) outputs = Ports([ ImagePort('result after filtering', name='result'), ]) __doc__ = ImageFiltering_abstract.generate_docstring( description, algorithms, options_list, inputs, outputs)