diff --git a/docs/notebooks/blob_detection.ipynb b/docs/notebooks/blob_detection.ipynb
index d5490b4bac824fcd66be93af99815a94a1ed482e..86f6d94691fed612a44439db08d3382fa2d47c6b 100644
--- a/docs/notebooks/blob_detection.ipynb
+++ b/docs/notebooks/blob_detection.ipynb
@@ -4,15 +4,7 @@
    "cell_type": "code",
    "execution_count": 1,
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "WARNING:root:Could not load CuPy: No module named 'cupy'\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "import qim3d"
    ]
@@ -30,7 +22,9 @@
    "source": [
     "This notebook shows how to do **blob detection** in a 3D volume using the `qim3d` library. \n",
     "\n",
-    "Blob detection is done by initializing a `qim3d.processing.Blob` object, and then calling the `qim3d.processing.Blob.detect` method. The `qim3d.processing.Blob.detect` method detects blobs by using the Difference of Gaussian (DoG) blob detection method, and returns an array `blobs` with the blobs found in the volume stored as `(p, r, c, radius)`. Subsequently, a binary mask of the volume can be retrieved with the `qim3d.processing.get_mask` method, in which the found blobs are marked as `True`."
+    "Blob detection is done by using the `qim3d.processing.blob_detection` method, which detects blobs by using the Difference of Gaussian (DoG) blob detection method, and returns two arrays:\n",
+    "- `blobs`: The blobs found in the volume stored as `(p, r, c, radius)`\n",
+    "- `binary_volume`: A binary mask of the volume with the blobs marked as `True`"
    ]
   },
   {
@@ -49,7 +43,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [
     {
@@ -69,7 +63,7 @@
        "<Figure size 1000x200 with 5 Axes>"
       ]
      },
-     "execution_count": 4,
+     "execution_count": 2,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -97,9 +91,16 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 3,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "Bright background selected, volume will be inverted.\n"
+     ]
+    },
     {
      "name": "stdout",
      "output_type": "stream",
@@ -109,31 +110,29 @@
     }
    ],
    "source": [
-    "# Initialize blob detector\n",
-    "blob_detector = qim3d.processing.Blob(\n",
-    "    background = \"bright\", \n",
-    "    min_sigma = 1, \n",
-    "    max_sigma = 8, \n",
-    "    threshold = 0.001, \n",
-    "    overlap = 0.1\n",
+    "# Detect blobs, and get binary mask\n",
+    "blobs, mask = qim3d.processing.blob_detection(\n",
+    "    cement_filtered,\n",
+    "    min_sigma=1,\n",
+    "    max_sigma=8,\n",
+    "    threshold=0.001,\n",
+    "    overlap=0.1,\n",
+    "    background=\"bright\"\n",
     "    )\n",
     "\n",
-    "# Detect blobs in filtered volume\n",
-    "blobs = blob_detector.detect(vol = cement_filtered)\n",
-    "\n",
     "# Number of blobs found\n",
     "print(f'Number of blobs found in the volume: {len(blobs)} blobs')"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 6,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "4d128089a7e545d7a3fd8a4607c02085",
+       "model_id": "54d5e4864544453695c7d87287aa7cf9",
        "version_major": 2,
        "version_minor": 0
       },
@@ -141,32 +140,32 @@
        "interactive(children=(IntSlider(value=64, description='Slice', max=127), Output()), layout=Layout(align_items=…"
       ]
      },
-     "execution_count": 13,
+     "execution_count": 6,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
     "# Visualize blobs on slices of cement volume\n",
-    "qim3d.viz.detection.circles(blobs, cement, show = True)"
+    "qim3d.viz.detection.circles(blobs, cement, alpha = 0.8, show = True, color = 'red')"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "**Get binary mask of detected blobs**"
+    "**Binary mask of detected blobs**"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 14,
+   "execution_count": 5,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "2d8e5b955da948de8f2bea5bb19000b9",
+       "model_id": "11fd726e79a246c98948ec54b3c752e2",
        "version_major": 2,
        "version_minor": 0
       },
@@ -174,16 +173,13 @@
        "interactive(children=(IntSlider(value=64, description='Slice', max=127), Output()), layout=Layout(align_items=…"
       ]
      },
-     "execution_count": 14,
+     "execution_count": 5,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "# Get binary mask of detected blobs\n",
-    "mask = blob_detector.get_mask()\n",
-    "\n",
-    "# Visualize mask\n",
+    "# Visualize binary mask\n",
     "qim3d.viz.slicer(mask)"
    ]
   }
diff --git a/docs/processing.md b/docs/processing.md
index ab737cb3ff984210f03ee249f18b87622a7a9495..558f857e94aa01cbc128a3d3245b668ca82c1998 100644
--- a/docs/processing.md
+++ b/docs/processing.md
@@ -5,11 +5,16 @@ Here, we provide functionalities designed specifically for 3D image analysis and
 ::: qim3d.processing
     options:
         members:
+            - test_blob_detection
+            - blob_detection
             - structure_tensor
             - local_thickness
             - get_3d_cc
-            - Pipeline
-            - Blob
+            - gaussian
+            - median
+            - maximum
+            - minimum
+            - tophat
 
 ::: qim3d.processing.operations
     options:
@@ -18,3 +23,7 @@ Here, we provide functionalities designed specifically for 3D image analysis and
             - watershed
             - edge_fade
             - fade_mask
+::: qim3d.processing
+    options:
+        members:
+        - Pipeline
\ No newline at end of file
diff --git a/qim3d/processing/__init__.py b/qim3d/processing/__init__.py
index 34dea0c4f0c556184277de549acf22dc9ad3f59e..79d9acf5f85d48c285d04424380ac455069330c6 100644
--- a/qim3d/processing/__init__.py
+++ b/qim3d/processing/__init__.py
@@ -1,6 +1,8 @@
+"Testing docstring"
+
 from .local_thickness_ import local_thickness
 from .structure_tensor_ import structure_tensor
+from .detection import blob_detection
 from .filters import *
-from .detection import *
 from .operations import *
 from .cc import get_3d_cc
diff --git a/qim3d/processing/detection.py b/qim3d/processing/detection.py
index b1397e4e36f7f5c4f49f67b9dc3f1e80fb0b6592..c5743a1501f8d2e20edda9f22c06b1eee76a48ad 100644
--- a/qim3d/processing/detection.py
+++ b/qim3d/processing/detection.py
@@ -1,60 +1,40 @@
+""" Blob detection using Difference of Gaussian (DoG) method """
+
 import numpy as np
 from qim3d.io.logger import log
 from skimage.feature import blob_dog
 
-__all__ = ["Blob"]
-
 
-class Blob:
+def blob_detection(
+    vol: np.ndarray,
+    background: str = "dark",
+    min_sigma: float = 1,
+    max_sigma: float = 50,
+    sigma_ratio: float = 1.6,
+    threshold: float = 0.5,
+    overlap: float = 0.5,
+    threshold_rel: float = None,
+    exclude_border: bool = False,
+) -> np.ndarray:
     """
-    Extract blobs from a volume using Difference of Gaussian (DoG) method
-    """
-    def __init__(
-        self,
-        background="dark",
-        min_sigma=1,
-        max_sigma=50,
-        sigma_ratio=1.6,
-        threshold=0.5,
-        overlap=0.5,
-        threshold_rel=None,
-        exclude_border=False,
-    ):
-        """
-        Initialize the blob detection object
-
-        Args:
-            background: 'dark' if background is darker than the blobs, 'bright' if background is lighter than the blobs
-            min_sigma: The minimum standard deviation for Gaussian kernel
-            max_sigma: The maximum standard deviation for Gaussian kernel
-            sigma_ratio: The ratio between the standard deviation of Gaussian Kernels
-            threshold: The absolute lower bound for scale space maxima. Reduce this to detect blobs with lower intensities.
-            overlap: The fraction of area of two blobs that overlap
-            threshold_rel: The relative lower bound for scale space maxima
-            exclude_border: If True, exclude blobs that are too close to the border of the image
-        """
-        self.background = background
-        self.min_sigma = min_sigma
-        self.max_sigma = max_sigma
-        self.sigma_ratio = sigma_ratio
-        self.threshold = threshold
-        self.overlap = overlap
-        self.threshold_rel = threshold_rel
-        self.exclude_border = exclude_border
-        self.vol_shape = None
-        self.blobs = None
-
-    def detect(self, vol):
-        """
-        Detect blobs in the volume
-
-        Args:
-            vol: The volume to detect blobs in
-
-        Returns:
-            blobs: The blobs found in the volume as (p, r, c, radius)
-
-        Example:
+    Extract blobs from a volume using Difference of Gaussian (DoG) method, and retrieve a binary volume with the blobs marked as True
+
+    Args:
+        vol: The volume to detect blobs in
+        background: 'dark' if background is darker than the blobs, 'bright' if background is lighter than the blobs
+        min_sigma: The minimum standard deviation for Gaussian kernel
+        max_sigma: The maximum standard deviation for Gaussian kernel
+        sigma_ratio: The ratio between the standard deviation of Gaussian Kernels
+        threshold: The absolute lower bound for scale space maxima. Reduce this to detect blobs with lower intensities
+        overlap: The fraction of area of two blobs that overlap
+        threshold_rel: The relative lower bound for scale space maxima
+        exclude_border: If True, exclude blobs that are too close to the border of the image
+
+    Returns:
+        blobs: The blobs found in the volume as (p, r, c, radius)
+        binary_volume: A binary volume with the blobs marked as True
+
+    Example:
             ```python
             import qim3d
 
@@ -62,8 +42,9 @@ class Blob:
             vol = qim3d.examples.cement_128x128x128
             vol_blurred = qim3d.processing.gaussian(vol, sigma=2)
 
-            # Initialize Blob detector
-            blob_detector = qim3d.processing.Blob(
+            # Detect blobs, and get binary mask
+            blobs, mask = qim3d.processing.blob_detection(
+                vol_blurred,
                 min_sigma=1,
                 max_sigma=8,
                 threshold=0.001,
@@ -71,88 +52,63 @@ class Blob:
                 background="bright"
                 )
 
-            # Detect blobs
-            blobs = blob_detector.detect(vol_blurred)
-
-            # Visualize results
-            qim3d.viz.circles(blobs,vol,alpha=0.8,color='blue')
+            # Visualize detected blobs
+            qim3d.viz.circles(blobs, vol, alpha=0.8, color='blue')
             ```
             ![blob detection](assets/screenshots/blob_detection.gif)
-        """
-        self.vol_shape = vol.shape
-        if self.background == "bright":
-            log.info("Bright background selected, volume will be inverted.")
-            vol = np.invert(vol)
-
-        blobs = blob_dog(
-            vol,
-            min_sigma=self.min_sigma,
-            max_sigma=self.max_sigma,
-            sigma_ratio=self.sigma_ratio,
-            threshold=self.threshold,
-            overlap=self.overlap,
-            threshold_rel=self.threshold_rel,
-            exclude_border=self.exclude_border,
-        )
-        blobs[:, 3] = blobs[:, 3] * np.sqrt(3)  # Change sigma to radius
-        self.blobs = blobs
-        return self.blobs
-    
-    def get_mask(self):
-        '''
-        Retrieve a binary volume with the blobs marked as True
-
-        Returns:
-            binary_volume: A binary volume with the blobs marked as True
-
-        Example:
-            ```python
-            import qim3d
-
-            # Get data
-            vol = qim3d.examples.cement_128x128x128
-            vol_blurred = qim3d.processing.gaussian(vol, sigma=2)
-
-            # Initialize Blob detector
-            blob_detector = qim3d.processing.Blob(
-                min_sigma=1,
-                max_sigma=8,
-                threshold=0.001,
-                overlap=0.1,
-                background="bright"
-                )
-
-                
-            # Detect blobs
-            blobs = blob_detector.detect(vol_blurred)
 
-            # Get mask and visualize
-            mask = blob_detector.get_mask()
+            ```python
+            # Visualize binary mask
             qim3d.viz.slicer(mask)
             ```
             ![blob detection](assets/screenshots/blob_get_mask.gif)
-        '''
-        binary_volume = np.zeros(self.vol_shape, dtype=bool)
-
-        for z, y, x, radius in self.blobs:
-            # Calculate the bounding box around the blob
-            z_start = max(0, int(z - radius))
-            z_end = min(self.vol_shape[0], int(z + radius) + 1)
-            y_start = max(0, int(y - radius))
-            y_end = min(self.vol_shape[1], int(y + radius) + 1)
-            x_start = max(0, int(x - radius))
-            x_end = min(self.vol_shape[2], int(x + radius) + 1)
-
-            z_indices, y_indices, x_indices = np.indices((z_end - z_start, y_end - y_start, x_end - x_start))
-            z_indices += z_start
-            y_indices += y_start
-            x_indices += x_start
-
-            # Calculate distances from the center of the blob to voxels within the bounding box
-            dist = np.sqrt((x_indices - x)**2 + (y_indices - y)**2 + (z_indices - z)**2)
+    """
 
-            binary_volume[z_start:z_end, y_start:y_end, x_start:x_end][dist <= radius] = True
+    if background == "bright":
+        log.info("Bright background selected, volume will be inverted.")
+        vol = np.invert(vol)
+
+    blobs = blob_dog(
+        vol,
+        min_sigma=min_sigma,
+        max_sigma=max_sigma,
+        sigma_ratio=sigma_ratio,
+        threshold=threshold,
+        overlap=overlap,
+        threshold_rel=threshold_rel,
+        exclude_border=exclude_border,
+    )
+
+    # Change sigma to radius
+    blobs[:, 3] = blobs[:, 3] * np.sqrt(3)
+
+    # Create binary mask of detected blobs
+    vol_shape = vol.shape
+    binary_volume = np.zeros(vol_shape, dtype=bool)
+
+    for z, y, x, radius in blobs:
+        # Calculate the bounding box around the blob
+        z_start = max(0, int(z - radius))
+        z_end = min(vol_shape[0], int(z + radius) + 1)
+        y_start = max(0, int(y - radius))
+        y_end = min(vol_shape[1], int(y + radius) + 1)
+        x_start = max(0, int(x - radius))
+        x_end = min(vol_shape[2], int(x + radius) + 1)
+
+        z_indices, y_indices, x_indices = np.indices(
+            (z_end - z_start, y_end - y_start, x_end - x_start)
+        )
+        z_indices += z_start
+        y_indices += y_start
+        x_indices += x_start
 
-        return binary_volume
+        # Calculate distances from the center of the blob to voxels within the bounding box
+        dist = np.sqrt(
+            (x_indices - x) ** 2 + (y_indices - y) ** 2 + (z_indices - z) ** 2
+        )
 
+        binary_volume[z_start:z_end, y_start:y_end, x_start:x_end][
+            dist <= radius
+        ] = True
 
+    return blobs, binary_volume
diff --git a/qim3d/processing/filters.py b/qim3d/processing/filters.py
index 354214c4d7e699de2c934cfbfed0710dd51e1c23..fc2d89134ded623e2e478f24f75a4e3735224169 100644
--- a/qim3d/processing/filters.py
+++ b/qim3d/processing/filters.py
@@ -265,11 +265,13 @@ def minimum(vol, **kwargs):
 
 def tophat(vol, **kwargs):
     """
-    Remove background from the volume
+    Remove background from the volume.
+
     Args:
         vol: The volume to remove background from
         radius: The radius of the structuring element (default: 3)
         background: color of the background, 'dark' or 'bright' (default: 'dark'). If 'bright', volume will be inverted.
+    
     Returns:
         vol: The volume with background removed
     """
diff --git a/qim3d/viz/detection.py b/qim3d/viz/detection.py
index 8f792f95a6ebd84ffa3c0e357aef4789975e3c94..f6ff1bf102c44106696b2eda97b868e83d4dff67 100644
--- a/qim3d/viz/detection.py
+++ b/qim3d/viz/detection.py
@@ -15,7 +15,7 @@ def circles(blobs, vol, alpha=0.5, color="#ff9900", **kwargs):
 
     Args:
         blobs (array-like): An array-like object of blobs, where each blob is represented
-            as a 4-tuple (p, r, c, radius). Usally the result of `qim3d.processing.Blob().detect()`
+            as a 4-tuple (p, r, c, radius). Usually the result of `qim3d.processing.blob_detection(vol)`
         vol (array-like): The 3D volume on which to plot the blobs.
         alpha (float, optional): The transparency of the blobs. Defaults to 0.5.
         color (str, optional): The color of the blobs. Defaults to "#ff9900".