Repository: scikit-image/scikit-image

Issue:
Question: Why is default structuring element of 1-connectivity used by ndimage.label for getting the default markers(labeled local minima) for watershed segmentation?
## Description

In the implemented watershed.py segmentation, one can pass a connectivity argument, when `local_minima` is called by watershed (when `markers=none`) it passes the same connectivity value onto the local minima function, this generates the `markers_bool`, which then is used by `ndimage.label()` to generate the labeled markers. `ndimage.label` can take a structure argument and it defaults to 1-connectivity structure if none are given. IMO it is more intuitive to have `ndimage.label` also use the same connectivity which is passed by the user to the watershed function instead of always using the default 1-connectivity.
Below is the line in the source I am referring to:
https://github.com/scikit-image/scikit-image/blob/663e9e4b0f2ba88249bfef45bc65700555a3f24b/skimage/segmentation/_watershed.py#L76

Instead of the above would it not be better to have?
```python
if connectivity==2:
   markers = ndi.label(markers_bool,
                       structure = [[1,1,1],
                                   [1,1,1],
                                   [1,1,1]])[0]
```



Discussion:
@nbCloud91 you're right, we should definitely match the connectivity. Rather than an if statement, though, I would replace

```python
markers = ndi.label(markers_bool)[0]
```

with

```python
footprint = ndi.generate_binary_structure(markers_bool.ndim, connectivity)
markers = ndi.label(markers_bool, structure=footprint)[0]
```
@jni could you make a PR for the above changes? I have not agreed to any CoC for this project and this seems like a small edit.
@nbCloud91 you're right, it's a small fix, but we have lots of them! (See list of open issues/PRs 😫) If you have time to make a PR with the change + test, we would much appreciate it! If not, no worries, I definitely hope that we can get to it before the next release. 🤞
I can  raise this PR . :) 

Resolving patch:
diff --git a/skimage/segmentation/_watershed.py b/skimage/segmentation/_watershed.py
--- a/skimage/segmentation/_watershed.py
+++ b/skimage/segmentation/_watershed.py
@@ -73,7 +73,8 @@ def _validate_inputs(image, markers, mask, connectivity):
             raise ValueError(message)
     if markers is None:
         markers_bool = local_minima(image, connectivity=connectivity) * mask
-        markers = ndi.label(markers_bool)[0]
+        footprint = ndi.generate_binary_structure(markers_bool.ndim, connectivity)
+        markers = ndi.label(markers_bool, structure=footprint)[0]
     elif not isinstance(markers, (np.ndarray, list, tuple)):
         # not array-like, assume int
         # given int, assume that number of markers *within mask*.


Test patch:
diff --git a/skimage/segmentation/tests/test_watershed.py b/skimage/segmentation/tests/test_watershed.py
--- a/skimage/segmentation/tests/test_watershed.py
+++ b/skimage/segmentation/tests/test_watershed.py
@@ -494,5 +494,48 @@ def test_no_markers():
     assert np.max(out) == 2
 
 
+def test_connectivity():
+    """
+    Watershed segmentation should output different result for 
+    different connectivity
+    when markers are calculated where None is supplied.
+    Issue = 5084
+    """
+    # Generate a dummy BrightnessTemperature image
+    x, y = np.indices((406, 270))
+    x1, y1, x2, y2, x3, y3, x4, y4 = 200, 208, 300, 120, 100, 100, 340, 208
+    r1, r2, r3, r4 = 100, 50, 40, 80
+    mask_circle1 = (x - x1)**2 + (y - y1)**2 < r1**2
+    mask_circle2 = (x - x2)**2 + (y - y2)**2 < r2**2
+    mask_circle3 = (x - x3)**2 + (y - y3)**2 < r3**2
+    mask_circle4 = (x - x4)**2 + (y - y4)**2 < r4**2
+    image = np.logical_or(mask_circle1, mask_circle2)
+    image = np.logical_or(image, mask_circle3)
+    image = np.logical_or(image, mask_circle4)
+
+    # calcuate distance in discrete increase
+    DummyBT = ndi.distance_transform_edt(image)
+    DummyBT_dis = np.around(DummyBT / 12, decimals = 0)*12
+    # calculate the mask
+    Img_mask = np.where(DummyBT_dis == 0, 0, 1)
+
+    # segments for connectivity 1 and 2
+    labels_c1 = watershed(200 - DummyBT_dis, mask=Img_mask, connectivity=1,
+                          compactness=0.01)
+    labels_c2 = watershed(200 - DummyBT_dis, mask=Img_mask, connectivity=2,
+                          compactness=0.01)
+
+    # assertions
+    assert np.unique(labels_c1).shape[0] == 6
+    assert np.unique(labels_c2).shape[0] == 5
+
+    # checking via area of each individual segment.
+    for lab, area in zip(range(6), [61824, 3653, 20467, 11097, 1301, 11278]):
+        assert np.sum(labels_c1 == lab) == area
+
+    for lab, area in zip(range(5), [61824, 3653, 20466, 12386, 11291]):
+        assert np.sum(labels_c2 == lab) == area
+
+
 if __name__ == "__main__":
     np.testing.run_module_suite()