# Copyright (C) 2003-2005 Peter J. Verveer
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# 3. The name of the author may not be used to endorse or promote
# products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import types
import math
import numarray
import _ni_support
import _nd_image
import morphology
from numarray.generic import _broadcast
def label(input, structure = None, output = None):
"""Label an array of objects.
The structure that defines the object connections must be
symmetric. If no structuring element is provided an element is
generated with a squared connectivity equal to one. This function
returns a tuple consisting of the array of labels and the number
of objects found. If an output array is provided only the number of
objects found is returned.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if structure == None:
structure = morphology.generate_binary_structure(input.rank, 1)
structure = numarray.asarray(structure, type = numarray.Bool)
if structure.rank != input.rank:
raise RuntimeError, 'structure and input must have equal rank'
for ii in structure.shape:
if ii != 3:
raise RuntimeError, 'structure dimensions must be equal to 3'
if not structure.iscontiguous():
structure = structure.copy()
if isinstance(output, numarray.NumArray):
if output.type() != numarray.Int32:
raise RuntimeError, 'output type must be Int32'
else:
output = numarray.Int32
output, return_value = _ni_support._get_output(output, input)
max_label = _nd_image.label(input, structure, output)
if return_value == None:
return max_label
else:
return return_value, max_label
def find_objects(input, max_label = 0):
"""Find objects in a labeled array.
The input must be an array with labeled objects. A list of slices
into the array is returned that contain the objects. The list
represents a sequence of the numbered objects. If a number is
missing, None is returned instead of a slice. If max_label > 0, it
gives the largest object number that is searched for, otherwise
all are returned.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if max_label < 1:
max_label = input.max()
return _nd_image.find_objects(input, max_label)
def sum(input, labels = None, index = None):
"""Calculate the sum of the values of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
return _nd_image.statistics(input, labels, index, 0)
def mean(input, labels = None, index = None):
"""Calculate the mean of the values of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
return _nd_image.statistics(input, labels, index, 1)
def variance(input, labels = None, index = None):
"""Calculate the variance of the values of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
return _nd_image.statistics(input, labels, index, 2)
def standard_deviation(input, labels = None, index = None):
"""Calculate the standard deviation of the values of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
var = variance(input, labels, index)
if (isinstance(var, types.ListType)):
return [math.sqrt(x) for x in var]
else:
return math.sqrt(var)
def minimum(input, labels = None, index = None):
"""Calculate the minimum of the values of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
return _nd_image.statistics(input, labels, index, 3)
def maximum(input, labels = None, index = None):
"""Calculate the maximum of the values of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
return _nd_image.statistics(input, labels, index, 4)
def _index_to_position(index, shape):
"""Convert a linear index to a position"""
if len(shape) > 0:
pos = []
stride = numarray.multiply.reduce(shape)
for size in shape:
stride = stride // size
pos.append(index // stride)
index -= pos[-1] * stride
return tuple(pos)
else:
return 0
def minimum_position(input, labels = None, index = None):
"""Find the position of the minimum of the values of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
pos = _nd_image.statistics(input, labels, index, 5)
if (isinstance(pos, types.ListType)):
return [_index_to_position(x, input.shape) for x in pos]
else:
return _index_to_position(pos, input.shape)
def maximum_position(input, labels = None, index = None):
"""Find the position of the maximum of the values of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
pos = _nd_image.statistics(input, labels, index, 6)
if (isinstance(pos, types.ListType)):
return [_index_to_position(x, input.shape) for x in pos]
else:
return _index_to_position(pos, input.shape)
def extrema(input, labels = None, index = None):
"""Calculate the minimum, the maximum and their positions of the
values of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
min, max, minp, maxp = _nd_image.statistics(input, labels, index, 7)
if (isinstance(minp, types.ListType)):
minp = [_index_to_position(x, input.shape) for x in minp]
maxp = [_index_to_position(x, input.shape) for x in maxp]
else:
minp = _index_to_position(minp, input.shape)
maxp = _index_to_position(maxp, input.shape)
return min, max, minp, maxp
def center_of_mass(input, labels = None, index = None):
"""Calculate the center of mass of of the array.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
return _nd_image.center_of_mass(input, labels, index)
def histogram(input, min, max, bins, labels = None, index = None):
"""Calculate a histogram of of the array.
The histogram is defined by its minimum and maximum value and the
number of bins.
The index parameter is a single label number or a sequence of
label numbers of the objects to be measured. If index is None, all
values are used where labels is larger than zero.
"""
input = numarray.asarray(input)
if isinstance(input.type(), numarray.ComplexType):
raise TypeError, 'Complex type not supported'
if labels != None:
labels = numarray.asarray(labels)
labels = _broadcast(labels, input.shape)
if labels.shape != input.shape:
raise RuntimeError, 'input and labels shape are not equal'
if bins < 1:
raise RuntimeError, 'number of bins must be >= 1'
if min >= max:
raise RuntimeError, 'min must be < max'
return _nd_image.histogram(input, min, max, bins, labels, index)
def watershed_ift(input, markers, structure = None, output = None):
"""Apply watershed from markers using a iterative forest transform
algorithm.
Negative markers are considered background markers which are
processed after the other markers. A structuring element defining
the connectivity of the object can be provided. If none is
provided an element is generated iwth a squared connecitiviy equal
to one. An output array can optionally be provided.
"""
input = numarray.asarray(input)
if input.type() not in [numarray.UInt8, numarray.UInt16]:
raise TypeError, 'only 8 and 16 unsigned inputs are supported'
if structure == None:
structure = morphology.generate_binary_structure(input.rank, 1)
structure = numarray.asarray(structure, type = numarray.Bool)
if structure.rank != input.rank:
raise RuntimeError, 'structure and input must have equal rank'
for ii in structure.shape:
if ii != 3:
raise RuntimeError, 'structure dimensions must be equal to 3'
if not structure.iscontiguous():
structure = structure.copy()
markers = numarray.asarray(markers)
if input.shape != markers.shape:
raise RuntimeError, 'input and markers must have equal shape'
if not isinstance(markers.type(), numarray.IntegralType):
raise RuntimeError, 'marker should be of integer type'
if isinstance(output, numarray.NumArray):
if not isinstance(output.type(), numarray.IntegralType):
raise RuntimeError, 'output should be of integer type'
else:
output = markers.type()
output, return_value = _ni_support._get_output(output, input)
_nd_image.watershed_ift(input, markers, structure, output)
return return_value
syntax highlighted by Code2HTML, v. 0.9.1