Repository: scikit-image/scikit-image

Issue:
measure.regionprops_table missing num_pixels as a property in stable
### Description:

Reading the stable documentation here: https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops

We have:
```
num_pixels: int
Number of foreground pixels.
```
But whe trying to use that property I get errors.

### Way to reproduce:

Example code:

```python
import math
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from skimage.draw import ellipse
from skimage.measure import label, regionprops, regionprops_table
from skimage.transform import rotate


image = np.zeros((600, 600))

rr, cc = ellipse(300, 350, 100, 220)
image[rr, cc] = 1

image = rotate(image, angle=15, order=0)

rr, cc = ellipse(100, 100, 60, 50)
image[rr, cc] = 1

label_img = label(image)
regions = regionprops(label_img)

props = regionprops_table(label_img, properties=('area', 'num_pixels', 'slice'))
```

And the generated error:
```
  Cell In[47], line 14
    props = regionprops_table(label_img, properties=('area', 'num_pixels', 'slice'))

  File ~\anaconda3\envs\ai\lib\site-packages\skimage\measure\_regionprops.py:1045 in regionprops_table
    return _props_to_dict(

  File ~\anaconda3\envs\ai\lib\site-packages\skimage\measure\_regionprops.py:841 in _props_to_dict
    func = r._extra_properties[prop]

KeyError: 'num_pixels'
```

### Version information:

```Shell
3.9.16 (main, Mar  8 2023, 10:39:24) [MSC v.1916 64 bit (AMD64)]
Windows-10-10.0.19045-SP0
scikit-image version: 0.20.0
numpy version: 1.24.3
```

### Related issues
There's an older related issue here, but it was not valid since in that time num_pixels were only in the unstable scikit https://github.com/scikit-image/scikit-image/issues/6337


Discussion:

Resolving patch:
diff --git a/skimage/measure/_regionprops.py b/skimage/measure/_regionprops.py
--- a/skimage/measure/_regionprops.py
+++ b/skimage/measure/_regionprops.py
@@ -102,6 +102,7 @@
     'centroid_weighted': float,
     'centroid_weighted_local': float,
     'coords': object,
+    'coords_scaled': object,
     'eccentricity': float,
     'equivalent_diameter_area': float,
     'euler_number': int,
@@ -125,6 +126,7 @@
     'moments_weighted_central': float,
     'moments_weighted_hu': float,
     'moments_weighted_normalized': float,
+    'num_pixels': int,
     'orientation': float,
     'perimeter': float,
     'perimeter_crofton': float,
@@ -1096,8 +1098,6 @@ def regionprops(label_image, intensity_image=None, cache=True,
     -----
     The following properties can be accessed as attributes or keys:
 
-    **num_pixels** : int
-        Number of foreground pixels.
     **area** : float
         Area of the region i.e. number of pixels of the region scaled by pixel-area.
     **area_bbox** : float
@@ -1219,6 +1219,8 @@ def regionprops(label_image, intensity_image=None, cache=True,
             wnu_ij = wmu_ij / wm_00^[(i+j)/2 + 1]
 
         where ``wm_00`` is the zeroth spatial moment (intensity-weighted area).
+    **num_pixels** : int
+        Number of foreground pixels.
     **orientation** : float
         Angle between the 0th axis (rows) and the major
         axis of the ellipse that has the same second moments as the region,


Test patch:
diff --git a/requirements/test.txt b/requirements/test.txt
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -1,5 +1,6 @@
 asv
 matplotlib>=3.5
+numpydoc>=1.5
 pooch>=1.6.0
 pytest>=7.0
 pytest-cov>=2.11.0
diff --git a/skimage/measure/tests/test_regionprops.py b/skimage/measure/tests/test_regionprops.py
--- a/skimage/measure/tests/test_regionprops.py
+++ b/skimage/measure/tests/test_regionprops.py
@@ -1,8 +1,10 @@
 import math
 
+import re
 import numpy as np
 import pytest
 import scipy.ndimage as ndi
+import numpydoc
 from numpy.testing import (assert_allclose, assert_almost_equal,
                            assert_array_almost_equal, assert_array_equal,
                            assert_equal)
@@ -1232,10 +1234,6 @@ def test_regionprops_table_no_regions():
     assert len(out['bbox+3']) == 0
 
 
-def test_column_dtypes_complete():
-    assert set(COL_DTYPES.keys()).union(OBJECT_COLUMNS) == set(PROPS.values())
-
-
 def test_column_dtypes_correct():
     msg = 'mismatch with expected type,'
     region = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE)[0]
@@ -1262,6 +1260,17 @@ def test_column_dtypes_correct():
             )
 
 
+def test_all_documented_items_in_col_dtypes():
+    docstring = numpydoc.docscrape.FunctionDoc(regionprops)
+    notes_lines = docstring['Notes']
+    property_lines = filter(lambda line: line.startswith('**'), notes_lines)
+    pattern = r'\*\*(?P<property_name>[a-z_]+)\*\*.*'
+    property_names = {re.search(pattern, property_line).group('property_name')
+                      for property_line in property_lines}
+    column_keys = set(COL_DTYPES.keys())
+    assert column_keys == property_names
+
+
 def pixelcount(regionmask):
     """a short test for an extra property"""
     return np.sum(regionmask)