Source code for magali._detection
# Copyright (c) 2024 The Magali Developers.
# Distributed under the terms of the BSD 3-Clause License.
# SPDX-License-Identifier: BSD-3-Clause
#
# This code is part of the Fatiando a Terra project (https://www.fatiando.org)
#
import numpy as np
import skimage.exposure
from ._utils import _estimate_grid_spacing
def _calculate_blob_sizes(detected_scales, grid_spacing, size_multiplier):
"""
Calculate the sizes of the blobs in μm.
Parameters
----------
detected_scales : array-like
Detected blob scales (sigma values).
grid_spacing : float
Grid spacing between data points.
size_multiplier : int
Scaling factor for the detected blob sizes.
Returns
-------
array-like
Calculated sizes of the blobs in data units.
"""
return detected_scales * np.sqrt(2) * grid_spacing * size_multiplier
def _generate_bounding_boxes(blob_sizes, blob_x_coords, blob_y_coords):
"""
Generate bounding boxes around detected blobs.
Parameters
----------
blob_sizes : array-like
Sizes of the detected blobs.
blob_x_coords : array-like
X coordinates of the detected blobs.
blob_y_coords : array-like
Y coordinates of the detected blobs.
Returns
-------
list of lists
Bounding boxes in data coordinates for each detected blob.
"""
return [
[x - size, x + size, y - size, y + size]
for size, x, y in zip(blob_sizes, blob_x_coords, blob_y_coords)
]
[docs]
def detect_anomalies(
data,
size_range,
size_multiplier=2,
num_scales=10,
detection_threshold=0.5,
overlap_ratio=0.5,
border_exclusion=0,
):
"""
Detect anomalies using blob detection.
Parameters
----------
data : xr.DataArray
Input data array with coordinates "x" and "y".
size_range : tuple
Minimum and maximum size of detected anomalies in µm.
size_multiplier : int, optional
Scaling factor for the detected blob sizes (default is 2).
num_scales : int, optional
Number of sigma values for the blob detection (default is 10). A sigma
value represents the scale or size of the blobs that the algorithm
will detect. Smaller sigma values correspond to smaller blobs, while
larger sigma values correspond to larger blobs.
detection_threshold : float, optional
Detection threshold for the blob detection (default is 0.5). This
parameter determines the sensitivity of the detection. A higher value
means fewer blobs will be detected, and a lower value means more blobs
will be detected.
overlap_ratio : float, optional
Overlap fraction for merging blobs (default is 0.5).
border_exclusion : int, optional
Border exclusion size in data units (default is 0). This parameter
excludes blobs close to the border of the data array.
Returns
-------
bounding_boxes : list of lists
Bounding boxes of detected anomalies in data coordinates. Each
bounding box corresponds to a detected blob, defined by the
coordinates and size of the blob.
"""
grid_spacing = _estimate_grid_spacing(data)
min_sigma, max_sigma = [0.5 * size for size in size_range]
y_indices, x_indices, detected_scales = skimage.feature.blob_log(
data,
min_sigma=min_sigma,
max_sigma=max_sigma,
threshold=detection_threshold,
num_sigma=num_scales,
overlap=overlap_ratio,
exclude_border=border_exclusion,
).T # Transpose the output to separate y, x, and scale values
blob_x_coords = data.x.values[x_indices.astype(int)]
blob_y_coords = data.y.values[y_indices.astype(int)]
blob_sizes = _calculate_blob_sizes(detected_scales, grid_spacing, size_multiplier)
bounding_boxes = _generate_bounding_boxes(blob_sizes, blob_x_coords, blob_y_coords)
return bounding_boxes