diff --git a/qim3d/__init__.py b/qim3d/__init__.py
index 07782e4e1a6ec54d7f3f605268d707ceeab557a7..ecbfe255266c3a164ec42cd6e09b3d182f9ba724 100644
--- a/qim3d/__init__.py
+++ b/qim3d/__init__.py
@@ -33,18 +33,20 @@ class _LazyLoader:
 
 # List of submodules
 _submodules = [
-    "examples",
-    "generate",
-    "gui",
-    "io",
-    "models",
-    "processing",
-    "tests",
-    "utils",
-    "viz",
-    "cli",
+    'examples',
+    'generate',
+    'gui',
+    'io',
+    'models',
+    'processing',
+    'tests',
+    'utils',
+    'viz',
+    'cli',
+    'filters',
+    'segmentation'
 ]
 
 # Creating lazy loaders for each submodule
 for submodule in _submodules:
-    globals()[submodule] = _LazyLoader(f"qim3d.{submodule}")
+    globals()[submodule] = _LazyLoader(f'qim3d.{submodule}')
diff --git a/qim3d/processing/filters.py b/qim3d/filters.py
similarity index 100%
rename from qim3d/processing/filters.py
rename to qim3d/filters.py
diff --git a/qim3d/processing/__init__.py b/qim3d/processing/__init__.py
index 8f6edf04173e5781339f0ca33ff304a29851f0f9..056804d123bbd9152a362dbd4cc1fe21a1aeeb91 100644
--- a/qim3d/processing/__init__.py
+++ b/qim3d/processing/__init__.py
@@ -1,7 +1,6 @@
 from .local_thickness_ import local_thickness
 from .structure_tensor_ import structure_tensor
 from .detection import blob_detection
-from .filters import *
 from .operations import *
 from .cc import get_3d_cc
 from .layers2d import segment_layers, get_lines
diff --git a/qim3d/processing/operations.py b/qim3d/processing/operations.py
index e559a16d0100186e36ba96b597b6bdfa58f286fb..bf6f16f4b33c2d7b9606f0ba57bff2aa35732f9f 100644
--- a/qim3d/processing/operations.py
+++ b/qim3d/processing/operations.py
@@ -1,5 +1,5 @@
 import numpy as np
-import qim3d.processing.filters as filters
+import qim3d.filters as filters
 from qim3d.utils.logger import log
 
 
@@ -52,74 +52,6 @@ def remove_background(
     return pipeline(vol)
 
 
-def watershed(bin_vol: np.ndarray, min_distance: int = 5) -> tuple[np.ndarray, int]:
-    """
-    Apply watershed segmentation to a binary volume.
-
-    Args:
-        bin_vol (np.ndarray): Binary volume to segment. The input should be a 3D binary image where non-zero elements 
-                              represent the objects to be segmented.
-        min_distance (int): Minimum number of pixels separating peaks in the distance transform. Peaks that are 
-                            too close will be merged, affecting the number of segmented objects. Default is 5.
-
-    Returns:
-        tuple[np.ndarray, int]: 
-            - Labeled volume (np.ndarray): A 3D array of the same shape as the input `bin_vol`, where each segmented object
-              is assigned a unique integer label.
-            - num_labels (int): The total number of unique objects found in the labeled volume.
-
-    Example:
-        ```python
-        import qim3d
-
-        vol = qim3d.examples.cement_128x128x128
-        binary = qim3d.processing.filters.gaussian(vol, sigma = 2)<60
-
-        qim3d.viz.slices(binary, axis=1)
-        ```
-        ![operations-watershed_before](assets/screenshots/operations-watershed_before.png)
-
-        ```python
-        labeled_volume, num_labels = qim3d.processing.operations.watershed(binary)
-
-        cmap = qim3d.viz.colormaps.objects(num_labels)
-        qim3d.viz.slices(labeled_volume, axis = 1, cmap = cmap)
-        ```
-        ![operations-watershed_after](assets/screenshots/operations-watershed_after.png)
-
-    """
-    import skimage
-    import scipy
-
-    if len(np.unique(bin_vol)) > 2:
-        raise ValueError("bin_vol has to be binary volume - it must contain max 2 unique values.")
-
-    # Compute distance transform of binary volume
-    distance = scipy.ndimage.distance_transform_edt(bin_vol)
-
-    # Find peak coordinates in distance transform
-    coords = skimage.feature.peak_local_max(
-        distance, min_distance=min_distance, labels=bin_vol
-    )
-
-    # Create a mask with peak coordinates
-    mask = np.zeros(distance.shape, dtype=bool)
-    mask[tuple(coords.T)] = True
-
-    # Label peaks
-    markers, _ = scipy.ndimage.label(mask)
-
-    # Apply watershed segmentation
-    labeled_volume = skimage.segmentation.watershed(
-        -distance, markers=markers, mask=bin_vol
-    )
-
-    # Extract number of objects found
-    num_labels = len(np.unique(labeled_volume)) - 1
-    log.info(f"Total number of objects found: {num_labels}")
-
-    return labeled_volume, num_labels
-
 
 def fade_mask(
     vol: np.ndarray,
diff --git a/qim3d/segmentation/__init__.py b/qim3d/segmentation/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..a2b743b795bd2af1765cf7d365ce63e6c2c5c7ba
--- /dev/null
+++ b/qim3d/segmentation/__init__.py
@@ -0,0 +1 @@
+from .standard import *
\ No newline at end of file
diff --git a/qim3d/segmentation/standard.py b/qim3d/segmentation/standard.py
new file mode 100644
index 0000000000000000000000000000000000000000..333b2da0ad6009f0f6851299e49fcef9c81d9679
--- /dev/null
+++ b/qim3d/segmentation/standard.py
@@ -0,0 +1,72 @@
+import numpy as np
+from qim3d.utils.logger import log
+
+__all__ = ["watershed"]
+
+def watershed(bin_vol: np.ndarray, min_distance: int = 5) -> tuple[np.ndarray, int]:
+    """
+    Apply watershed segmentation to a binary volume.
+
+    Args:
+        bin_vol (np.ndarray): Binary volume to segment. The input should be a 3D binary image where non-zero elements 
+                              represent the objects to be segmented.
+        min_distance (int): Minimum number of pixels separating peaks in the distance transform. Peaks that are 
+                            too close will be merged, affecting the number of segmented objects. Default is 5.
+
+    Returns:
+        tuple[np.ndarray, int]: 
+            - Labeled volume (np.ndarray): A 3D array of the same shape as the input `bin_vol`, where each segmented object
+              is assigned a unique integer label.
+            - num_labels (int): The total number of unique objects found in the labeled volume.
+
+    Example:
+        ```python
+        import qim3d
+
+        vol = qim3d.examples.cement_128x128x128
+        binary = qim3d.processing.filters.gaussian(vol, sigma = 2)<60
+
+        qim3d.viz.slices(binary, axis=1)
+        ```
+        ![operations-watershed_before](assets/screenshots/operations-watershed_before.png)
+
+        ```python
+        labeled_volume, num_labels = qim3d.processing.operations.watershed(binary)
+
+        cmap = qim3d.viz.colormaps.objects(num_labels)
+        qim3d.viz.slices(labeled_volume, axis = 1, cmap = cmap)
+        ```
+        ![operations-watershed_after](assets/screenshots/operations-watershed_after.png)
+
+    """
+    import skimage
+    import scipy
+
+    if len(np.unique(bin_vol)) > 2:
+        raise ValueError("bin_vol has to be binary volume - it must contain max 2 unique values.")
+
+    # Compute distance transform of binary volume
+    distance = scipy.ndimage.distance_transform_edt(bin_vol)
+
+    # Find peak coordinates in distance transform
+    coords = skimage.feature.peak_local_max(
+        distance, min_distance=min_distance, labels=bin_vol
+    )
+
+    # Create a mask with peak coordinates
+    mask = np.zeros(distance.shape, dtype=bool)
+    mask[tuple(coords.T)] = True
+
+    # Label peaks
+    markers, _ = scipy.ndimage.label(mask)
+
+    # Apply watershed segmentation
+    labeled_volume = skimage.segmentation.watershed(
+        -distance, markers=markers, mask=bin_vol
+    )
+
+    # Extract number of objects found
+    num_labels = len(np.unique(labeled_volume)) - 1
+    log.info(f"Total number of objects found: {num_labels}")
+
+    return labeled_volume, num_labels
\ No newline at end of file
diff --git a/qim3d/tests/processing/test_filters.py b/qim3d/tests/processing/test_filters.py
index e63628118775b34d2c98f897d303d89e4c18b60a..5a6d0993fb4ac6cecaf9c26d06b450eeb2a9f893 100644
--- a/qim3d/tests/processing/test_filters.py
+++ b/qim3d/tests/processing/test_filters.py
@@ -1,5 +1,5 @@
 import qim3d
-from qim3d.processing.filters import *
+from qim3d.filters import *
 import numpy as np
 import pytest
 import re