def test_2D_indices_col(self):
     """
     The returned 2D index should be the same as control.
     """
     control = numpy.where(self.array_2D == 66)
     wh = numpy.where(self.array_1D_1 == 66)
     ind2D = array_indices(array=self.array_2D, index=wh[0])
     n = len(control[1])
     self.assertEqual((control[1] == ind2D[1]).sum(), n)
 def test_2D_indices_col(self):
     """
     The returned 2D index should be the same as control.
     """
     control = numpy.where(self.array_2D == 66)
     wh      = numpy.where(self.array_1D_1 == 66)
     ind2D   = array_indices(array=self.array_2D, index=wh[0])
     n       = len(control[1])
     self.assertEqual((control[1] == ind2D[1]).sum(), n)
 def test_dimensions(self):
     """
     Test that the dimensions keyword works and yields the same result as the control.
     """
     control     = numpy.where(self.array_3D == 66)
     control_sum = numpy.sum(self.array_3D[control])
     wh          = numpy.where(self.array_1D_2 == 66)
     ind3D       = array_indices(array=self.array_3D.shape, index=wh[0], dimensions=True)
     test_sum    = numpy.sum(self.array_3D[ind3D])
     self.assertEqual(control_sum, test_sum)
 def test_dimensions(self):
     """
     Test that the dimensions keyword works and yields the same result as the control.
     """
     control = numpy.where(self.array_3D == 66)
     control_sum = numpy.sum(self.array_3D[control])
     wh = numpy.where(self.array_1D_2 == 66)
     ind3D = array_indices(array=self.array_3D.shape,
                           index=wh[0],
                           dimensions=True)
     test_sum = numpy.sum(self.array_3D[ind3D])
     self.assertEqual(control_sum, test_sum)
示例#5
0
    def getSegmentLocations(self, segmentID=1):
        """
        Retrieve the pixel locations corresponding to a segmentID.
        """

        ri = self.ri
        i  = segmentID

        if ri[i+1] > ri[i]:
            idx = ri[ri[i]:ri[i+1]]
            idx = array_indices(self.dims, idx, dimensions=True)
        else:
            idx = (numpy.array([]), numpy.array([]))


        return idx
示例#6
0
def obj_centroid(array):
    """
    Calculates centroids per object.
    """

    dims = array.shape
    h    = histogram(array.flatten(), Min=1, reverse_indices='ri')
    hist = h['histogram']
    ri   = h['ri']
    cent = []
    for i in numpy.arange(hist.shape[0]):
        if (hist[i] == 0):
            continue
        idx = numpy.array(array_indices(dims, ri[ri[i]:ri[i+1]], dimensions=True))
        cent_i = numpy.mean(idx, axis=1)
        cent.append(cent_i)

    return cent
示例#7
0
def obj_rectangularity(array):
    """
    Calculates rectangularity per object.
    """

    dims = array.shape
    h    = histogram(array.flatten(), Min=1, reverse_indices='ri')
    hist = h['histogram']
    ri   = h['ri']
    rect = []
    for i in numpy.arange(hist.shape[0]):
        if (hist[i] == 0):
            continue
        idx = numpy.array(array_indices(dims, ri[ri[i]:ri[i+1]], dimensions=True))
        min_yx = numpy.min(idx, axis=1)
        max_yx = numpy.max(idx, axis=1)
        diff = max_yx - min_yx + 1 # Add one to account for zero based index
        bbox_area = numpy.prod(diff)
        rect.append(hist[i] / bbox_area)

    return rect
示例#8
0
    # Create the mask via the thresholds
    mask = (array >= lower) & (array <= upper)

    # The label function segments the image into contiguous blobs
    label_array, num_labels = ndimage.label(mask, structure=s)

    # Find the labels associated with the ROI
    labels = label_array[ROIPixels]
    mx_lab = numpy.max(labels)
    # Find unique labels, excluding zero (background)
    ulabels = (numpy.unique(labels[labels > 0])
               ).tolist()  # Convert to list; Makes for neater indexing

    # Generate a histogram to find the label locations
    h = histogram(label_array.flatten(),
                  min=0,
                  max=mx_lab,
                  reverse_indices='ri')
    hist = h['histogram']
    ri = h['ri']

    for lab in ulabels:
        if hist[lab] == 0:
            continue
        idx.extend(ri[ri[lab]:ri[lab + 1]])

    idx = numpy.array(idx)
    idx = array_indices(dims, idx, dimensions=True)

    return idx
示例#9
0
def obj_get_boundary_method1(labelled_array, fill_holes=True):
    """
    Get the pixels that mark the object boundary/perimeter.
    Method 1.
    
    8 neighbourhood chain code

         5 6 7
         4 . 0
         3 2 1

    4 neighbourhood chain code

         . 3 .
         2 . 0
         . 1 .

    """

    dims = labelled_array.shape
    rows = dims[0]
    cols = dims[1]

    if fill_holes:
        orig_binary = (labelled_array > 0).astype('uint8')
        fill = obj_fill_holes(labelled_array)
        s = [[1,1,1],[1,1,1],[1,1,1]]
        labelled_array, nlabels = ndimage.label(fill, structure=s)

    # We'll opt for the perimeter co-ordinates to be ordered in a clockwise fashion. GIS convention???
    pix_directions = numpy.array([[ 0, 1],
                                  [ 1, 1],
                                  [ 1, 0],
                                  [ 1,-1],
                                  [ 0,-1],
                                  [-1,-1],
                                  [-1, 0],
                                  [-1, 1]])

    # Set up the distances as we traverse across a pixel
    diag           = numpy.sqrt(2.0) # NumPy will return a float64, but just in case future versions change....
    pix_distances  = {0 : 1.0,
                      1 : diag,
                      2 : 1.0,
                      3 : diag,
                      4 : 1.0,
                      5 : diag,
                      6 : 1.0,
                      7, diag
                     }

    # Determine the co-ordinates (indices) of each segement
    # The first index of each segment will be used to define the start and end of a boundary/perimeter
    h = histogram(labelled_array.flatten(), Min=1, reverse_indices='ri')
    hist = h['histogram']
    ri = h['ri']
    nlabels = hist.shape[0]
    seg_start_idxs = numpy.zeros(nlabels, dtype='int')

    # Boundary or perimeter ?? Will go with perimeter, akin to a method implement earlier which uses a
    # convolution operator to determine perimeter length.

    # Obtain the start indices of each segment/object
    for i in numpy.arange(nlabels):
        #if (hist[i] == 0): # The labeled array should be consecutive
        #    continue
        seg_start_idxs[i] = ri[ri[i]:ri[i+1]][0] # Return the first index

    # Convert the 1D indices to 2D indices used by NumPy
    seg_start_idxs = array_indices(dims, seg_start_idxs, dimensions=True)

    # Lots to figure out here. Dealing with 'from' and 'too' directions can make things confusing
    # Keep track of the direction we last travelled, that way we can start at the next clockwise direction
    # For single pixel objects or 'islands' use the histogram value to skip the follow boundary/search routine

    """
    The memory of the order of the array should be 'C-Style': column, column, column, then next row.

    eg a 2x5 array

        0, 1, 2, 3, 4
        5, 6, 7, 8, 9

    Therefore the first index will only have labels to the right and below (below left, below right).

    eg an object with a label ID of 6

       0, 0, 6, 6, 6
       6, 6, 6, 6, 6

    As such, the first direction travelled will be to the right '0' in the freeman chain, and the first index will be the
    first boundary co-ordinate and will be the final co-ordinate to close the boundary thereby creating a polygon.
    As for linear features...
    """

    # Probably deal with these inside the boundary tracking routine
    # Let the tracking routine handle to/from and just return the final result
    to_   = 0
    from_ = 4

    perimeter_info = {}

    for i in range(hist.shape[0]):
        if hist[i] == 0:
            continue
        if hist[i] == 1:
            # What is the perimeter of a single pixel, 0.0, 4.0???
            #perimeter_co_ords[i] = seg_start_idxs[i[0],i[1]] # Still need to design the function and how to return the result
            continue
        idx   = (seg_start_idxs[0][i], seg_start_idxs[1][i])
        label = i + 1
        perimeter_info[i] = track_object_boundary(labelled_array, start_index=idx, label_id=label)

    # Might need to format the perimeter_info dictionary before returning, ie turn the co-ords into numpy arrays.
    # Or even into a polygon object using the shapely library???
    # Using shapely might be easier to report geometrical attributes

    # Still need to deal with holes within an object as ENVI does. They will increase an objects perimeter length.
    # SciPy have a binary_fill_holes function. label the filled array, then get the indices, and then retrive only those indices
    # for each object that are 0 in the original array.
    # That might be one way to do it, which means re-writing the above function....ughhh :)

    #!!!!This isn't the correct place for the handling of object holes, but just get the rough structure out!!!
    if fill_holes:
        for i in range(hist.shape[0]):
            if hist[i] == 0:
                continue
            if hist[i] == 1:
                # What is the perimeter of a single pixel, 0.0, 4.0???
                continue
            idx   = (seg_start_idxs[0][i], seg_start_idxs[1][i])
            label = i + 1
            perimeter_info[i] = track_object_boundary(labelled_array, start_index=idx, label_id=label)
            # Can we trust that the labelling of the filled and unfilled arrays will give the same object index??
            # If we can we could use the area differences to determine if there are holes and only go through the 
            # hole perimeter tracking if needed.
            single_object = numpy.zeros((rows*cols), dtype='uint8')
            single_object[ri[ri[i]:ri[i+1]]] = 1
            holes = numexpr.evaluate("(single_object - orig_binary) == 1")
            labs, nlabs = ndimage.label(holes, s)
            h_holes = histogram(labs, Min=1, reverse_indices='ri')
            hist_holes = h_holes['histogram']
            ri_h = h_holes['ri']
            seg_holes_start_idxs = numpy.zeros(nlabs, dtype='int')
            for j in numpy.arange(nlabels):
                #if (hist[i] == 0): # The labeled array should be consecutive
                #    continue
                seg_holes_start_idxs[j] = ri_h[ri_h[j]:ri_h[j+1]][0] # Return the first index

            # Convert the 1D indices to 2D indices used by NumPy
            seg_holes_start_idxs = array_indices(dims, seg_holes_start_idxs, dimensions=True)
            for k in range(hist_holes.shape):
                if hist_holes[k] == 0:
                    continue
                if hist[i] == 1:
                    # What is the perimeter of a single pixel, 0.0, 4.0???
                    continue
                idx = (seg_holes_start_idxs[0][k], seg_holes_start_idxs[1][k])
                holes_label = k + 1
                holes_result = track_object_boundary(labs, start_index=idx, label_id=holes_label)
                perimeter_info[i]['Holes'] = holes_result['Vertices']
                perimeter_info[i]['Perimeter_Length'] += perimeter_info['Perimeter_Length']

    return perimeter_info