def test_euler_number(): en = regionprops(SAMPLE)[0].euler_number assert en == 0 SAMPLE_mod = SAMPLE.copy() SAMPLE_mod[7, -3] = 0 en = regionprops(SAMPLE_mod)[0].euler_number assert en == -1 en = euler_number(SAMPLE, 1) assert en == 2 en = euler_number(SAMPLE_mod, 1) assert en == 1 en = euler_number(SAMPLE_3D, 1) assert en == 1 en = euler_number(SAMPLE_3D, 3) assert en == 1 # for convex body, Euler number is 1 SAMPLE_3D_2 = cp.zeros((100, 100, 100)) SAMPLE_3D_2[40:60, 40:60, 40:60] = 1 en = euler_number(SAMPLE_3D_2, 3) assert en == 1 SAMPLE_3D_2[45:55, 45:55, 45:55] = 0 en = euler_number(SAMPLE_3D_2, 3) assert en == 2
def test_extra_properties_nr_args(): with pytest.raises(AttributeError): region = regionprops(SAMPLE, extra_properties=(too_few_args, ))[0] _ = region.too_few_args with pytest.raises(AttributeError): region = regionprops(SAMPLE, extra_properties=(too_many_args, ))[0] _ = region.too_many_args
def test_multichannel(): """Test that computing multichannel properties works.""" astro = data.astronaut()[::4, ::4] labels = slic(astro.astype(float), start_label=1) astro = cp.asarray(astro) astro_green = astro[..., 1] labels = cp.asarray(labels) segment_idx = int(cp.max(labels) // 2) region = regionprops(labels, astro_green)[segment_idx] region_multi = regionprops(labels, astro)[segment_idx] for prop in PROPS: p = region[prop] p_multi = region_multi[prop] if isinstance(p, (list, tuple)): p = tuple([cp.asnumpy(p_) for p_ in p]) p = np.stack(p) if isinstance(p_multi, (list, tuple)): p_multi = tuple([cp.asnumpy(p_) for p_ in p_multi]) p_multi = np.stack(p_multi) if np.shape(p) == np.shape(p_multi): # property does not depend on multiple channels assert_array_equal(p, p_multi) else: # property uses multiple channels, returns props stacked along # final axis assert_array_equal(p, p_multi[..., 1])
def test_euler_number(): en = regionprops(SAMPLE)[0].euler_number assert en == 1 SAMPLE_mod = SAMPLE.copy() SAMPLE_mod[7, -3] = 0 en = regionprops(SAMPLE_mod)[0].euler_number assert en == 0
def test_filled_area(): area = regionprops(SAMPLE)[0].filled_area assert area == cp.sum(SAMPLE) SAMPLE_mod = SAMPLE.copy() SAMPLE_mod[7, -3] = 0 area = regionprops(SAMPLE_mod)[0].filled_area assert area == cp.sum(SAMPLE)
def test_eccentricity(): eps = regionprops(SAMPLE)[0].eccentricity assert_almost_equal(eps, 0.814629313427) img = cp.zeros((5, 5), dtype=cp.int) img[2, 2] = 1 eps = regionprops(img)[0].eccentricity assert_almost_equal(eps, 0)
def test_iterate_all_props(): region = regionprops(SAMPLE)[0] p0 = {p: region[p] for p in region} region = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE)[0] p1 = {p: region[p] for p in region} assert len(p0) < len(p1)
def test_dtype(): regionprops(cp.zeros((10, 10), dtype=cp.int)) regionprops(cp.zeros((10, 10), dtype=cp.uint)) with pytest.raises(TypeError): regionprops(cp.zeros((10, 10), dtype=cp.float)) with pytest.raises(TypeError): regionprops(cp.zeros((10, 10), dtype=cp.double)) with pytest.raises(TypeError): regionprops(cp.zeros((10, 10), dtype=np.bool_))
def test_coordinates(): sample = cp.zeros((10, 10), dtype=cp.int8) coords = cp.array([[3, 2], [3, 3], [3, 4]]) sample[coords[:, 0], coords[:, 1]] = 1 prop_coords = regionprops(sample)[0].coords assert_array_equal(prop_coords, coords) sample = cp.zeros((6, 6, 6), dtype=cp.int8) coords = cp.array([[1, 1, 1], [1, 2, 1], [1, 3, 1]]) sample[coords[:, 0], coords[:, 1], coords[:, 2]] = 1 prop_coords = regionprops(sample)[0].coords assert_array_equal(prop_coords, coords)
def test_bbox(): bbox = regionprops(SAMPLE)[0].bbox assert_array_almost_equal(bbox, (0, 0, SAMPLE.shape[0], SAMPLE.shape[1])) SAMPLE_mod = SAMPLE.copy() SAMPLE_mod[:, -1] = 0 bbox = regionprops(SAMPLE_mod)[0].bbox assert_array_almost_equal(bbox, (0, 0, SAMPLE.shape[0], SAMPLE.shape[1] - 1)) bbox = regionprops(SAMPLE_3D)[0].bbox assert_array_almost_equal(bbox, (1, 1, 1, 4, 3, 3))
def test_equals(): arr = cp.zeros((100, 100), dtype=cp.int) arr[0:25, 0:25] = 1 arr[50:99, 50:99] = 2 regions = regionprops(arr) r1 = regions[0] regions = regionprops(arr) r2 = regions[0] r3 = regions[1] assert_equal(r1 == r2, True, "Same regionprops are not equal") assert_equal(r1 != r3, True, "Different regionprops are equal")
def test_orientation(): orient = regionprops(SAMPLE)[0].orientation # determined with MATLAB assert_almost_equal(orient, -1.4663278802756865) # test diagonal regions diag = cp.eye(10, dtype=int) orient_diag = regionprops(diag)[0].orientation assert_almost_equal(orient_diag, -math.pi / 4) orient_diag = regionprops(cp.flipud(diag))[0].orientation assert_almost_equal(orient_diag, math.pi / 4) orient_diag = regionprops(cp.fliplr(diag))[0].orientation assert_almost_equal(orient_diag, math.pi / 4) orient_diag = regionprops(cp.fliplr(cp.flipud(diag)))[0].orientation assert_almost_equal(orient_diag, -math.pi / 4)
def test_column_dtypes_correct(): msg = "mismatch with expected type," region = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE)[0] for col in COL_DTYPES: r = region[col] if col in OBJECT_COLUMNS: assert COL_DTYPES[col] == object continue # TODO: grlee77: check desired types for returned. # e.g. currently inertia_tensor_eigvals returns a list of 0-dim # arrays if isinstance(r, (tuple, list)): r0 = r[0] if isinstance(r0, cp.ndarray) and r0.ndim == 0: r0 = r0.item() t = type(r0) elif cp.isscalar(r): t = type(r) else: t = type(r.ravel()[0].item()) if cp.issubdtype(t, cp.floating): assert (COL_DTYPES[col] == float ), f"{col} dtype {t} {msg} {COL_DTYPES[col]}" elif cp.issubdtype(t, cp.integer): assert (COL_DTYPES[col] == int ), f"{col} dtype {t} {msg} {COL_DTYPES[col]}" else: assert False, f"{col} dtype {t} {msg} {COL_DTYPES[col]}"
def test_extra_properties_intensity(): region = regionprops( SAMPLE, intensity_image=INTENSITY_SAMPLE, extra_properties=(median_intensity, ), )[0] assert region.median_intensity == cp.median(INTENSITY_SAMPLE[SAMPLE == 1])
def test_all_props(): region = regionprops(SAMPLE, INTENSITY_SAMPLE)[0] for prop in PROPS: try: assert_array_almost_equal(region[prop], getattr(region, PROPS[prop])) except TypeError: # the `slice` property causes this pass
def test_invalid(): ps = regionprops(SAMPLE) def get_intensity_image(): ps[0].intensity_image with pytest.raises(AttributeError): get_intensity_image()
def test_all_props_3d(): region = regionprops(SAMPLE_3D, INTENSITY_SAMPLE_3D)[0] for prop in PROPS: try: assert_array_almost_equal(region[prop], getattr(region, PROPS[prop])) except (NotImplementedError, TypeError): pass
def test_extra_properties_mixed(): # mixed properties, with and without intensity region = regionprops( SAMPLE, intensity_image=INTENSITY_SAMPLE, extra_properties=(median_intensity, pixelcount), )[0] assert region.median_intensity == cp.median(INTENSITY_SAMPLE[SAMPLE == 1]) assert region.pixelcount == cp.sum(SAMPLE == 1)
def test_weighted_moments(): wm = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE)[0].weighted_moments ref = cp.asarray([ [7.4000000e01, 6.9900000e02, 7.8630000e03, 9.7317000e04], [4.1000000e02, 3.7850000e03, 4.4063000e04, 5.7256700e05], [2.7500000e03, 2.4855000e04, 2.9347700e05, 3.9007170e06], [1.9778000e04, 1.7500100e05, 2.0810510e06, 2.8078871e07], ]) assert_array_almost_equal(wm, ref)
def test_moments_normalized(): nu = regionprops(SAMPLE)[0].moments_normalized # determined with OpenCV assert_almost_equal(nu[0, 2], 0.24301268861454037) assert_almost_equal(nu[0, 3], -0.017278118992041805) assert_almost_equal(nu[1, 1], -0.016846707818929982) assert_almost_equal(nu[1, 2], 0.045473992910668816) assert_almost_equal(nu[2, 0], 0.08410493827160502) assert_almost_equal(nu[2, 1], -0.002899800614433943)
def test_moments_central(): mu = regionprops(SAMPLE)[0].moments_central # determined with OpenCV assert_almost_equal(mu[2, 0], 436.00000000000045) # different from OpenCV results, bug in OpenCV assert_almost_equal(mu[3, 0], -737.333333333333) assert_almost_equal(mu[1, 1], -87.33333333333303) assert_almost_equal(mu[2, 1], -127.5555555555593) assert_almost_equal(mu[0, 2], 1259.7777777777774) assert_almost_equal(mu[1, 2], 2000.296296296291) assert_almost_equal(mu[0, 3], -760.0246913580195)
def test_weighted_moments_normalized(): wnu = regionprops( SAMPLE, intensity_image=INTENSITY_SAMPLE)[0].weighted_moments_normalized ref = cp.asarray([ [cp.nan, cp.nan, 0.2301467830, -0.0162529732], [cp.nan, -0.0160405109, 0.0457932622, -0.0104598869], [0.0873590903, -0.0031421072, 0.0165315478, -0.0028544152], [-0.0161217406, -0.0031376984, 0.0043903193, -0.0011057191], ]) assert_array_almost_equal(wnu, ref)
def test_moments_hu(): hu = regionprops(SAMPLE)[0].moments_hu ref = cp.asarray([ 3.27117627e-01, 2.63869194e-02, 2.35390060e-02, 1.23151193e-03, 1.38882330e-06, -2.72586158e-05, -6.48350653e-06, ]) # bug in OpenCV caused in Central Moments calculation? assert_array_almost_equal(hu, ref)
def test_moments(): m = regionprops(SAMPLE)[0].moments # determined with OpenCV assert_almost_equal(m[0, 0], 72.0) assert_almost_equal(m[0, 1], 680.0) assert_almost_equal(m[0, 2], 7682.0) assert_almost_equal(m[0, 3], 95588.0) assert_almost_equal(m[1, 0], 408.0) assert_almost_equal(m[1, 1], 3766.0) assert_almost_equal(m[1, 2], 43882.0) assert_almost_equal(m[2, 0], 2748.0) assert_almost_equal(m[2, 1], 24836.0) assert_almost_equal(m[3, 0], 19776.0)
def test_weighted_moments_hu(): whu = regionprops(SAMPLE, intensity_image=INTENSITY_SAMPLE)[0].weighted_moments_hu ref = cp.asarray([ 3.1750587329e-01, 2.1417517159e-02, 2.3609322038e-02, 1.2565683360e-03, 8.3014209421e-07, -3.5073773473e-05, -6.7936409056e-06, ]) assert_array_almost_equal(whu, ref)
def test_props_to_dict(): regions = regionprops(SAMPLE) out = _props_to_dict(regions) assert out == { "label": cp.asarray([1]), "bbox-0": cp.asarray([0]), "bbox-1": cp.asarray([0]), "bbox-2": cp.asarray([10]), "bbox-3": cp.asarray([18]), } regions = regionprops(SAMPLE) out = _props_to_dict(regions, properties=("label", "area", "bbox"), separator="+") assert out == { "label": cp.asarray([1]), "area": cp.asarray([72]), "bbox+0": cp.asarray([0]), "bbox+1": cp.asarray([0]), "bbox+2": cp.asarray([10]), "bbox+3": cp.asarray([18]), }
def test_convex_image(): img = regionprops(SAMPLE)[0].convex_image ref = cp.asarray([ [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], ], ) assert_array_equal(img, ref)
def test_cache(): SAMPLE_mod = SAMPLE.copy() region = regionprops(SAMPLE_mod)[0] f0 = region.filled_image region._label_image[:10] = 1 f1 = region.filled_image # Changed underlying image, but cache keeps result the same assert_array_equal(f0, f1) # Now invalidate cache region._cache_active = False f1 = region.filled_image assert cp.any(f0 != f1)
def test_convex_image(): img = regionprops(SAMPLE)[0].convex_image # determined with MATLAB ref = cp.asarray([ [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], ]) assert_array_equal(img, ref)
def test_docstrings_and_props(): def foo(): """foo""" has_docstrings = bool(foo.__doc__) region = regionprops(SAMPLE)[0] docs = _parse_docs() props = [m for m in dir(region) if not m.startswith("_")] nr_docs_parsed = len(docs) nr_props = len(props) if has_docstrings: assert_equal(nr_docs_parsed, nr_props) ds = docs["weighted_moments_normalized"] assert "iteration" not in ds assert len(ds.split("\n")) > 3 else: assert_equal(nr_docs_parsed, 0)