Example #1
0
def radius_filter(arr, radius, min_points):
    """
    Applies a radius search filter, which remove isolated points/clusters of
    points.

    Args:
        arr (array): Point cloud of shape n points x m dimensions to be
            filtered.
        radius (float): Search radius around each point to form a neighborhood.
        min_point (int): Minimum number of points in a neighborhood for it
            to be considered valid, i.e not filtered out.

    Returns:
        mask (array): Array of bools masking valid points as True and
            "noise" points as False.

    """

    # Setting up neighborhood indices.
    indices = set_nbrs_rad(arr, arr, radius, return_dist=False)

    # Allocating array of neighborhood's sizes (one entry for each point in
    # arr).
    n_points = np.zeros(arr.shape[0], dtype=int)

    # Iterating over each entry in indices and calculating total number of
    # points.
    for i, id_ in enumerate(indices):
        n_points[i] = id_.shape[0]

    return n_points >= min_points
Example #2
0
def detect_rad_nn(arr, rad):
    """
    Calculates an average of number of neighbors based on a fixed radius
    around each point in a point cloud.

    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).
    rad : float
        Radius distance to select neighboring points.

    Returns
    -------
    mean_knn : int
        Average number of points inside a radius 'rad' around each point in
        'arr'.

    """

    # Performin Nearest Neighbors search for the whole point cloud.
    indices = set_nbrs_rad(arr, arr, rad, return_dist=False)

    # Counting number of points around each point in 'arr'.
    indices_len = [len(i) for i in indices]

    # Calculates a mean of all neighboring point counts.
    mean_knn = np.mean(indices_len).astype(int)

    return mean_knn
Example #3
0
def plane_filter(arr, rad, threshold):
    """
    Filters a point cloud based on its points planicity. Removes points that
    are part of a neighbohood with planar spatial arrangement (low curvature).

    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).
    rad : float
        Search radius distance around each point. Used to describe
        local point arrangement.
    threshold : float
        Minimum curvature value for valid points.

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

    """

    # Running NearestNeighborhood search around each point in arr.
    nbrs_idx = set_nbrs_rad(arr, arr, rad, False)
    # Calculating curvature for each point's neighborhood.
    c = curvature(arr, nbrs_idx)

    return c >= threshold
Example #4
0
def detect_optimal_knn(arr, rad_lst=[0.1, 0.2, 0.3], sample_size=10000):
    """
    Detects optimal values for knn in order to facilitate material separation.

    Parameters
    ----------
    arr: array
        Set of 3D points.
    rad_lst: list
        Set of radius values to generate samples of neighborhoods. This is
        used to select points to calculate a number of neighboring points
        distribution from the point cloud.
    sample_size: int
        Number of points in arr to process in order to genrate a distribution.

    Returns
    -------
    knn_lst: list
        Set of k-nearest neighbors values.

    """

    # Generating sample indices.
    sids = np.random.choice(np.arange(arr.shape[0]),
                            sample_size,
                            replace=False)

    # Obtaining nearest neighbors' indices and distance for sampled points.
    # This process is done just once, with the largest value of radius in
    # rad_lst. Later on, it is possible to subsample indices by limiting
    # their distances for a smaller radius.
    dist, ids = set_nbrs_rad(arr, arr[sids], np.max(rad_lst), True)

    # Initializing empty list to store knn values.
    knn_lst = []

    # Looping over each radius value.
    for r in rad_lst:
        # Counting number of points inside radius r.
        n_pts = [len(i[d <= r]) for i, d in zip(ids, dist)]

        # Binning n_pts into a histogram.
        y, x = np.histogram(n_pts)

        # Detecting peaks of accumulated points from n_pts.
        maxtab, mintab = peakdet(y, 100)
        maxtab = np.array(maxtab)

        # Appending knn values relative to peaks detected in n_pts.
        knn_lst.append(x[maxtab[:, 0]])

    # Flattening nested lists into a final list of knn values.
    knn_lst = [i for j in knn_lst for i in j]

    return knn_lst
Example #5
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
Example #6
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
Example #7
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