예제 #1
0
def feature_filter(arr, feature_id, threshold, knn):
    """
    Filters a point cloud based on a given feature threshold. Only points
    with selected feature values higher than threshold are kept as valid.

    Parameters
    ----------
    arr : array
        Three-dimensional (m x n) array of a point cloud, where the
        coordinates are represented in the columns (n) and the points are
        represented in the rows (m).
    feature_id : int
        Column index of feature selected as criteria to filter. Column
        indices follow Python notation [0 - (n_columns - 1)].
    threshold : float
        Minimum feature value for valid points.
    knn : int
        Number of neighbors to select around each point. Used to describe
        local point arrangement.

    Returns
    -------
    mask_feature : numpy.ndarray
        Boolean mask with valid points entries set as True.

    """

    # Running NearestNeighborhood search and calculating geometric features
    # for each point's neighborhood.
    nbrs_idx = set_nbrs_knn(arr, arr, knn, False)
    features = knn_features(arr, nbrs_idx)
    # Masking valid points.
    return features[:, feature_id] >= threshold
예제 #2
0
def apply_nn_value(base, arr, attr):

    """
    Upscales a set of attributes from a base array to another denser array.

    Args:
        base (array): Base array to which the attributes to upscale were
            originaly matched.
        arr (array): Target array to which the attributes will be upscaled.
        attr (array): Attributes to upscale.

    Returns:
        new_attr (array): Upscales attributes.

    Raises:
        AssertionError: length (number of samples) of "base" and "attr" must
            be equal.

    """

    assert base.shape[0] == attr.shape[0], '"base" and "attr" must have the\
 same number of samples.'

    # Obtaining the closest in base for each point in arr.
    idx = set_nbrs_knn(base, arr, 1, return_dist=False)

    # Making sure idx has the right type, int, for indexing.
    idx = idx.astype(int)

    # Applying base's attribute (attr) to points in arr.
    newattr = attr[idx]

    return np.reshape(newattr, newattr.shape[0])
예제 #3
0
def upper_quantile_min_cc(point_cloud):

    mask = point_cloud[:, 2] >= np.quantile(point_cloud[:, 2], 0.95)
    lower_points = point_cloud[mask]

    dist, ids = set_nbrs_knn(lower_points, lower_points, 2)

    return np.median(dist[:, 1:])
예제 #4
0
def lower_quantile_max_cc(point_cloud):

    mask = point_cloud[:, 2] <= np.quantile(point_cloud[:, 2], 0.1)
    lower_points = point_cloud[mask]

    dist, ids = set_nbrs_knn(lower_points, lower_points, 3)

    return np.max(dist[:, 1:])
예제 #5
0
def detect_nn_dist(arr, knn, sigma=1):
    """
    Calcuates the optimum distance among neighboring points.

    Args:
        arr (array): N-dimensional array (m x n) containing a set of
            parameters (n) over a set of observations (m).
        knn (int): Number of nearest neighbors to search to constitue the
            local subset of points around each point in 'arr'.

    Returns:
        dist (float): Optimal distance among neighboring points.

    """

    dist, indices = set_nbrs_knn(arr, arr, knn)

    return np.mean(dist[:, 1:]) + (np.std(dist[:, 1:]) * sigma)
예제 #6
0
def dist_majority(arr_1, arr_2, **kwargs):
    """
    Applies majority filter on two arrays.

    Args:
        arr_1 (array): n-dimensional array of points to filter.
        arr_2 (array): n-dimensional array of points to filter.
        **kwargs: knn, rad.
        knn (int or float): Number neighbors to select around each point in
            arr in order to apply the majority criteria.
        rad (int or float): Search radius arount each point in arr to select
            neighbors in order to apply the majority criteria.

    Returns:
        c_maj_1 (array): Boolean mask of filtered entries of same class as
            input 'arr_1'.
        c_maj_2 (array): Boolean mask of filtered entries of same class as
            input 'arr_2'.

    Raises:
        AssertionError: Raised if neither 'knn' or 'rad' arguments are passed
            with valid values (int or float).

    """

    # Asserting input arguments are valid.
    assert ('knn' in kwargs.keys()) or ('rad' in kwargs.keys()), 'Please\
 input a value for either "knn" or "rad".'

    if 'knn' in kwargs.keys():
        assert (type(kwargs['knn']) == int) or (type(kwargs['knn']) ==
                                                float), \
            '"knn" variable must be of type int or float.'
    elif 'rad' in kwargs.keys():
        assert (type(kwargs['rad']) == int) or (type(kwargs['rad']) ==
                                                float), \
            '"rad" variable must be of type int or float.'

    # Stacking the arrays from both classes to generate a combined array.
    arr = np.vstack((arr_1, arr_2))

    # Generating the indices for the local subsets of points around all points
    # in the combined array. Function used is based upon the argument passed.
    if 'knn' in kwargs.keys():
        dist, indices = set_nbrs_knn(arr, arr, kwargs['knn'])
    elif 'rad' in kwargs.keys():
        dist, indices = set_nbrs_rad(arr, arr, kwargs['rad'])

    # Making sure indices has type int.
    indices = indices.astype(int)

    # Generating the class arrays from both classified arrays and combining
    # them into a single classes array (classes).
    class_1 = np.full(arr_1.shape[0], 1, dtype=np.int)
    class_2 = np.full(arr_2.shape[0], 2, dtype=np.int)
    classes = np.hstack((class_1, class_2)).T

    # Allocating output variable.
    c_maj = np.zeros(classes.shape)

    # Selecting subset of classes based on the neighborhood expressed by
    # indices.
    class_ = classes[indices]

    # Looping over all points in indices.
    for i in range(len(indices)):

        # Obtaining classe from indices i.
        c = class_[i, :]
        # Caculating accummulated distance for each class.
        d1 = np.sum(dist[i][c == 1])
        d2 = np.sum(dist[i][c == 2])
        # Checking which class has the highest distance and assigning it
        # to current index in c_maj.
        if d1 >= d2:
            c_maj[i] = 1
        elif d1 < d2:
            c_maj[i] = 2

    return c_maj == 1, c_maj == 2
예제 #7
0
def class_filter(arr_1, arr_2, target, **kwargs):
    """
    Function to apply class filter on an array based on the combination of
    classed from both arrays (arr_1 and arr_2). Which array gets filtered
    is defined by ''target''.

    Args:
        arr_1 (array): n-dimensional array of points to filter.
        arr_2 (array): n-dimensional array of points to filter.
        target (int or float): number of the input array to filter. Valid
            values are 0 or 1.
        **kwargs: knn, rad.
        knn (int or float): Number neighbors to select around each point in
            arr in order to apply the majority criteria.
        rad (int or float): Search radius arount each point in arr to select
            neighbors in order to apply the majority criteria.

    Returns:
        c_maj_1 (array): Boolean mask of filtered entries of same class as
            input 'arr_1'.
        c_maj_2 (array): Boolean mask of filtered entries of same class as
            input 'arr_2'.

    Raises:
        AssertionError: Raised if neither 'knn' or 'rad' arguments are passed
            with valid values (int or float).
        AssertionError: Raised if 'target' variable is not an int or float with
            value 0 or 1.

    """

    # Asserting input arguments are valid.
    assert ('knn' in kwargs.keys()) or ('rad' in kwargs.keys()), 'Please\
 input a value for either "knn" or "rad".'

    if 'knn' in kwargs.keys():
        assert (type(kwargs['knn']) == int) or (type(kwargs['knn']) ==
                                                float), \
            '"knn" variable must be of type int or float.'
    elif 'rad' in kwargs.keys():
        assert (type(kwargs['rad']) == int) or (type(kwargs['rad']) ==
                                                float), \
            '"rad" variable must be of type int or float.'

    assert (type(target) == int) or (type(target) == float), '"target"\
 variable must be of type int or float.'

    assert (target == 0) or (target == 1), '"target" variable must be either\
 0 or 1.'

    # Stacking the arrays from both classes to generate a combined array.
    arr = np.vstack((arr_1, arr_2))

    # Generating the class arrays from both classified arrays and combining
    # them into a single classes array (classes).
    class_1 = np.full(arr_1.shape[0], 1, dtype=np.int)
    class_2 = np.full(arr_2.shape[0], 2, dtype=np.int)
    classes = np.hstack((class_1, class_2)).T

    # Generating the indices for the local subsets of points around all points
    # in the combined array. Function used is based upon the argument passed.
    if 'knn' in kwargs.keys():
        indices = set_nbrs_knn(arr, arr, kwargs['knn'], return_dist=False)
    elif 'rad' in kwargs.keys():
        indices = set_nbrs_rad(arr, arr, kwargs['rad'], return_dist=False)

    # Making sure indices has type int.
    indices = indices.astype(int)

    # Allocating output variable.
    c_maj = classes.copy()

    # Selecting subset of classes based on the neighborhood expressed by
    # indices.
    class_ = classes[indices]

    # Checking for the target class.
    target_idx = np.where(classes == target)[0]

    # Looping over the target points to filter.
    for i in target_idx:

        # Counting the number of occurrences of each value in the ith instance
        # of class_.
        count = np.bincount(class_[i, :])
        # Appending the majority class into the output variable.
        c_maj[i] = count.argmax()

    return c_maj == 1, c_maj == 2
예제 #8
0
def array_majority(arr_1, arr_2, **kwargs):
    """
    Applies majority filter on two arrays.

    Args:
        arr_1 (array): n-dimensional array of points to filter.
        arr_2 (array): n-dimensional array of points to filter.
        **kwargs: knn, rad.
        knn (int or float): Number neighbors to select around each point in
            arr in order to apply the majority criteria.
        rad (int or float): Search radius arount each point in arr to select
            neighbors in order to apply the majority criteria.

    Returns:
        c_maj_1 (array): Boolean mask of filtered entries of same class as
            input 'arr_1'.
        c_maj_2 (array): Boolean mask of filtered entries of same class as
            input 'arr_2'.

    Raises:
        AssertionError: Raised if neither 'knn' or 'rad' arguments are passed
            with valid values (int or float).

    """

    # Asserting input arguments are valid.
    assert ('knn' in kwargs.keys()) or ('rad' in kwargs.keys()), 'Please\
 input a value for either "knn" or "rad".'

    if 'knn' in kwargs.keys():
        assert (type(kwargs['knn']) == int) or (type(kwargs['knn']) ==
                                                float), \
            '"knn" variable must be of type int or float.'
    elif 'rad' in kwargs.keys():
        assert (type(kwargs['rad']) == int) or (type(kwargs['rad']) ==
                                                float), \
            '"rad" variable must be of type int or float.'

    # Stacking the arrays from both classes to generate a combined array.
    arr = np.vstack((arr_1, arr_2))

    # Generating the indices for the local subsets of points around all points
    # in the combined array. Function used is based upon the argument passed.
    if 'knn' in kwargs.keys():
        indices = set_nbrs_knn(arr, arr, kwargs['knn'], return_dist=False)
    elif 'rad' in kwargs.keys():
        indices = set_nbrs_rad(arr, arr, kwargs['rad'], return_dist=False)

    # Making sure indices has type int.
    indices = indices.astype(int)

    # Generating the class arrays from both classified arrays and combining
    # them into a single classes array (classes).
    class_1 = np.full(arr_1.shape[0], 1, dtype=np.int)
    class_2 = np.full(arr_2.shape[0], 2, dtype=np.int)
    classes = np.hstack((class_1, class_2)).T

    # Allocating output variable.
    c_maj = np.zeros(classes.shape)

    # Selecting subset of classes based on the neighborhood expressed by
    # indices.
    class_ = classes[indices]

    # Looping over all points in indices.
    for i in range(len(indices)):

        # Counting the number of occurrences of each value in the ith instance
        # of class_.
        unique, count = np.unique(class_[i, :], return_counts=True)
        # Appending the majority class into the output variable.
        c_maj[i] = unique[np.argmax(count)]

    return c_maj == 1, c_maj == 2