>>> a = array([[1,2,2,1,1,0], ... [0,2,3,1,2,0], ... [1,1,1,3,3,2], ... [1,1,1,1,2,1]]) >>> print where(a > 1, 1, 0) [[0 1 1 0 0 0] [0 1 1 0 1 0] [0 0 0 1 1 1] [0 0 0 0 1 0]]
The result is a binary image, in which the individual objects still need to be identified and labeled. The function label generates an array where each object is assigned a unique number:
input, structure=None, output=None) |
>>> a = array([[0,1,1,0,0,0],[0,1,1,0,1,0],[0,0,0,1,1,1],[0,0,0,0,1,0]]) >>> s = [[0, 1, 0], [1,1,1], [0,1,0]] >>> print label(a, s) (array([[0, 1, 1, 0, 0, 0], [0, 1, 1, 0, 2, 0], [0, 0, 0, 2, 2, 2], [0, 0, 0, 0, 2, 0]]), 2)
>>> a = array([[0,1,1,0,0,0],[0,1,1,0,1,0],[0,0,0,1,1,1],[0,0,0,0,1,0]]) >>> s = [[1,1,1], [1,1,1], [1,1,1]] >>> print label(a, s)[0] [[0 1 1 0 0 0] [0 1 1 0 1 0] [0 0 0 1 1 1] [0 0 0 0 1 0]]
>>> l, n = label([1, 0, 1, 0, 1]) >>> print l [1 0 2 0 3] >>> l = where(l != 2, l, 0) >>> print l [1 0 0 0 3] >>> print label(l)[0] [1 0 0 0 2]
Note: The structuring element used by label is assumed to be symmetric.
There is a large number of other approaches for segmentation, for instance from an estimation of the borders of the objects that can be obtained for instance by derivative filters. One such an approach is watershed segmentation. The function watershed_ift generates an array where each object is assigned a unique label, from an array that localizes the object borders, generated for instance by a gradient magnitude filter. It uses an array containing initial markers for the objects:
input, markers, structure=None, output=None) |
The inputs of this function are the array to which the transform is applied, and an array of markers that designate the objects by a unique label, where any non-zero value is a marker. For instance:
>>> input = array([[0, 0, 0, 0, 0, 0, 0], ... [0, 1, 1, 1, 1, 1, 0], ... [0, 1, 0, 0, 0, 1, 0], ... [0, 1, 0, 0, 0, 1, 0], ... [0, 1, 0, 0, 0, 1, 0], ... [0, 1, 1, 1, 1, 1, 0], ... [0, 0, 0, 0, 0, 0, 0]], numarray.UInt8) >>> markers = array([[1, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 2, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0]], numarray.Int8) >>> print watershed_ift(input, markers) [[1 1 1 1 1 1 1] [1 1 2 2 2 1 1] [1 2 2 2 2 2 1] [1 2 2 2 2 2 1] [1 2 2 2 2 2 1] [1 1 2 2 2 1 1] [1 1 1 1 1 1 1]]
Here two markers were used to designate an object (marker=2) and the background (marker=1). The order in which these are processed is arbitrary: moving the marker for the background to the lower right corner of the array yields a different result:
>>> markers = array([[0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 2, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 1]], numarray.Int8) >>> print watershed_ift(input, markers) [[1 1 1 1 1 1 1] [1 1 1 1 1 1 1] [1 1 2 2 2 1 1] [1 1 2 2 2 1 1] [1 1 2 2 2 1 1] [1 1 1 1 1 1 1] [1 1 1 1 1 1 1]]
>>> markers = array([[0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 2, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0, 0, -1]], numarray.Int8) >>> print watershed_ift(input, markers) [[-1 -1 -1 -1 -1 -1 -1] [-1 -1 2 2 2 -1 -1] [-1 2 2 2 2 2 -1] [-1 2 2 2 2 2 -1] [-1 2 2 2 2 2 -1] [-1 -1 2 2 2 -1 -1] [-1 -1 -1 -1 -1 -1 -1]]
The connectivity of the objects is defined by a structuring element. If
no structuring element is provided, one is generated by calling
generate_binary_structure (see section
>>> print watershed_ift(input, markers, ... structure = [[1,1,1], [1,1,1], [1,1,1]]) [[-1 -1 -1 -1 -1 -1 -1] [-1 2 2 2 2 2 -1] [-1 2 2 2 2 2 -1] [-1 2 2 2 2 2 -1] [-1 2 2 2 2 2 -1] [-1 2 2 2 2 2 -1] [-1 -1 -1 -1 -1 -1 -1]]
Note: The implementation of watershed_ift limits the data types of the input to UInt8 and UInt16.
Send comments to the NumArray community.