def test_volume(self): superpixels = generate_random_voronoi((100,200), 200) feature_names = ['edgeregion_edge_regionradii', 'edgeregion_edge_volume'] rag = Rag( superpixels ) try: rag.compute_features(None, feature_names) except AssertionError: pass except: raise else: assert False, "EdgeRegion accumulator should refuse to compute 'volume' for 2D images." superpixels = generate_random_voronoi((25,50,100), 200) feature_names = ['edgeregion_edge_regionradii', 'edgeregion_edge_area', 'edgeregion_edge_volume'] rag = Rag( superpixels ) features_df = rag.compute_features(None, feature_names) radii = features_df[['edgeregion_edge_regionradii_0', 'edgeregion_edge_regionradii_1', 'edgeregion_edge_regionradii_2']].values assert (radii[:,0] >= radii[:,1]).all() and (radii[:,1] >= radii[:,2]).all() volumes = features_df[['edgeregion_edge_volume']].values assert ((radii[:,0] * radii[:,1] * radii[:,2]) == volumes[:,0]).all() areas = features_df[['edgeregion_edge_area']].values assert ((radii[:,0] * radii[:,1]) == areas[:,0]).all()
def test_regionradii(self): # Create a volume of flat superpixels, where every slice # is the same (except for the actual sp ids) num_sp_per_slice = 200 slice_superpixels = generate_random_voronoi((100,200), num_sp_per_slice) superpixels = np.zeros( shape=((10,) + slice_superpixels.shape), dtype=np.uint32 ) for z in range(10): superpixels[z] = slice_superpixels + z*num_sp_per_slice superpixels = vigra.taggedView(superpixels, 'zyx') rag_flat = Rag( superpixels, flat_superpixels=True ) values = np.random.random(size=(superpixels.shape)).astype(np.float32) values = vigra.taggedView(values, 'zyx') flat_features_df = rag_flat.compute_features(values, ['standard_flatedge_regionradii'], edge_group='z') # Now compute the radii using a normal 'dense' rag rag_dense = Rag( superpixels ) dense_features_df = rag_dense.compute_features(values, ['edgeregion_edge_regionradii']) # Both methods should be reasonably close. combined_features_df = pd.merge(flat_features_df, dense_features_df, how='left', on=['sp1', 'sp2']) assert np.isclose(combined_features_df['standard_flatedge_regionradii_0'], combined_features_df['edgeregion_edge_regionradii_0'], atol=0.001).all() assert np.isclose(combined_features_df['standard_flatedge_regionradii_1'], combined_features_df['edgeregion_edge_regionradii_1'], atol=0.001).all()
def test_quantiles(self): # Create a volume of flat superpixels, where every slice # is the same (except for the actual sp ids) num_sp_per_slice = 200 slice_superpixels = generate_random_voronoi((100,200), num_sp_per_slice) superpixels = np.zeros( shape=((10,) + slice_superpixels.shape), dtype=np.uint32 ) for z in range(10): superpixels[z] = slice_superpixels + z*num_sp_per_slice superpixels = vigra.taggedView(superpixels, 'zyx') rag_flat = Rag( superpixels, flat_superpixels=True ) values = np.random.random(size=(superpixels.shape)).astype(np.float32) values = vigra.taggedView(values, 'zyx') flat_features_df = rag_flat.compute_features(values, ['standard_flatedge_quantiles'], edge_group='z') flat_features_df2 = rag_flat.compute_features(values, ['standard_edge_quantiles'], edge_group='yx') # Rename columns flat_features_df2.columns = flat_features_df.columns.values flat_features_df = pd.concat( (flat_features_df, flat_features_df2), axis=0 ) # Now compute the quantiles using a normal 'dense' rag rag_dense = Rag( superpixels ) dense_features_df = rag_dense.compute_features(values, ['standard_edge_quantiles']) all_features_df = pd.merge(dense_features_df, flat_features_df, how='left', on=['sp1', 'sp2']) assert (all_features_df['standard_edge_quantiles_0'] == all_features_df['standard_flatedge_quantiles_0']).all() assert (all_features_df['standard_edge_quantiles_100'] == all_features_df['standard_flatedge_quantiles_100']).all() # Due to the way histogram ranges are computed, we can't expect quantiles_10 to match closely # ... but quantiles_50 seems to be good. assert np.isclose(all_features_df['standard_edge_quantiles_50'], all_features_df['standard_edge_quantiles_50']).all()
def test1(self): superpixels = generate_random_voronoi((100,200), 200) superpixels.axistags = vigra.defaultAxistags('yx') feature_names = ['edgeregion_edge_regionradii'] rag = Rag( superpixels ) acc = EdgeRegionEdgeAccumulator(rag, feature_names) features_df = rag.compute_features(None, feature_names, accumulator_set=[acc]) radii = features_df[features_df.columns.values[2:]].values assert (radii[:,0] >= radii[:,1]).all() # Transpose superpixels and check again # Should match (radii are sorted by magnitude). superpixels.axistags = vigra.defaultAxistags('xy') rag = Rag( superpixels ) acc = EdgeRegionEdgeAccumulator(rag, feature_names) transposed_features_df = rag.compute_features(None, feature_names, accumulator_set=[acc]) transposed_radii = transposed_features_df[transposed_features_df.columns.values[2:]].values assert (transposed_features_df[['sp1', 'sp1']].values == features_df[['sp1', 'sp1']].values).all() DEBUG = False if DEBUG: count_features = rag.compute_features(None, ['standard_edge_count', 'standard_sp_count']) import pandas as pd combined_features_df = pd.merge(features_df, transposed_features_df, how='left', on=['sp1', 'sp2'], suffixes=('_orig', '_transposed')) combined_features_df = pd.merge(combined_features_df, count_features, how='left', on=['sp1', 'sp2']) problem_rows = np.logical_or(np.isclose(radii[:, 0], transposed_radii[:, 0]) != 1, np.isclose(radii[:, 1], transposed_radii[:, 1]) != 1) problem_df = combined_features_df.loc[problem_rows][sorted(list(combined_features_df.columns))] print(problem_df.transpose()) debug_sp = np.zeros_like(superpixels, dtype=np.uint8) for sp1 in problem_df['sp1'].values: debug_sp[superpixels == sp1] = 128 for sp2 in problem_df['sp2'].values: debug_sp[superpixels == sp2] = 255 vigra.impex.writeImage(debug_sp, '/tmp/debug_sp.png', dtype='NATIVE') # The first axes should all be close. # The second axes may differ somewhat in the case of purely linear edges, # so we allow a higher tolerance. assert np.isclose(radii[:,0], transposed_radii[:,0]).all() assert np.isclose(radii[:,1], transposed_radii[:,1], atol=0.001).all()
def test2(self): superpixels = np.zeros((10, 10), dtype=np.uint32) superpixels[1:2] = 1 superpixels = vigra.taggedView(superpixels, 'yx') rag = Rag( superpixels ) feature_names = ['edgeregion_edge_regionradii', 'edgeregion_edge_regionaxes'] acc = EdgeRegionEdgeAccumulator(rag, feature_names) features_df = rag.compute_features(None, feature_names, accumulator_set=[acc]) # Just 1 edge in this rag (0 -> 1) assert len(features_df) == 1 assert (features_df[['sp1', 'sp2']].values == [0,1]).all() # Manually compute the radius x_coords = np.arange(0, 10) x_coord_mean = x_coords.mean() centralized_x_coords = x_coords - x_coord_mean x_coord_variance = centralized_x_coords.dot(centralized_x_coords)/len(x_coords) x_radius = np.sqrt(x_coord_variance).astype(np.float32) assert features_df['edgeregion_edge_regionradii_0'].values[0] == x_radius # Eigenvectors are just parallel to the axes assert features_df['edgeregion_edge_regionaxes_0x'].values[0] == 1.0 assert features_df['edgeregion_edge_regionaxes_0y'].values[0] == 0.0 assert features_df['edgeregion_edge_regionaxes_1x'].values[0] == 0.0 assert features_df['edgeregion_edge_regionaxes_1y'].values[0] == 1.0
def test_edge_features_no_histogram(self): """ Make sure vigra edge filters still work even if no histogram features are selected. """ superpixels = generate_random_voronoi((100,200), 200) rag = Rag( superpixels ) # For simplicity, just make values identical to superpixels values = superpixels.astype(np.float32) feature_names = ['standard_edge_mean', 'standard_edge_minimum', 'standard_edge_maximum'] features_df = rag.compute_features(values, feature_names) assert len(features_df) == len(rag.edge_ids) assert list(features_df.columns.values) == ['sp1', 'sp2'] + list(feature_names), \ "Wrong output feature names: {}".format( features_df.columns.values ) assert (features_df[['sp1', 'sp2']].values == rag.edge_ids).all() for row_tuple in features_df.itertuples(): row = OrderedDict( zip(['index', 'sp1', 'sp2'] + list(feature_names), row_tuple) ) sp1 = row['sp1'] sp2 = row['sp2'] # Values were identical to the superpixels, so this is boring... assert row['standard_edge_mean'] == (sp1+sp2)/2. assert row['standard_edge_minimum'] == (sp1+sp2)/2. assert row['standard_edge_maximum'] == (sp1+sp2)/2.
def test_sp_features_no_histogram(self): superpixels = generate_random_voronoi((100,200), 200) rag = Rag( superpixels ) # For simplicity, just make values identical to superpixels values = superpixels.astype(np.float32) # Manually compute the sp counts sp_counts = np.bincount(superpixels.flat[:]) # COUNT features_df = rag.compute_features(values, ['standard_sp_count']) assert len(features_df) == len(rag.edge_ids) assert (features_df.columns.values == ['sp1', 'sp2', 'standard_sp_count_sum', 'standard_sp_count_difference']).all() assert (features_df[['sp1', 'sp2']].values == rag.edge_ids).all() dtypes = { colname: series.dtype for colname, series in features_df.iterkv() } assert all(dtype != np.float64 for dtype in dtypes.values()), \ "An accumulator returned float64 features. That's a waste of ram.\n"\ "dtypes were: {}".format(dtypes) # sp count features are normalized, consistent with the multicut paper. for _index, sp1, sp2, sp_count_sum, sp_count_difference in features_df.itertuples(): assert sp_count_sum == np.power(sp_counts[sp1] + sp_counts[sp2], 1./superpixels.ndim).astype(np.float32) assert sp_count_difference == np.power(np.abs(sp_counts[sp1] - sp_counts[sp2]), 1./superpixels.ndim).astype(np.float32) # SUM features_df = rag.compute_features(values, ['standard_sp_sum']) assert len(features_df) == len(rag.edge_ids) assert (features_df.columns.values == ['sp1', 'sp2', 'standard_sp_sum_sum', 'standard_sp_sum_difference']).all() assert (features_df[['sp1', 'sp2']].values == rag.edge_ids).all() # sp sum features ought to be normalized, too... for _index, sp1, sp2, sp_sum_sum, sp_sum_difference in features_df.itertuples(): assert sp_sum_sum == np.power(sp1*sp_counts[sp1] + sp2*sp_counts[sp2], 1./superpixels.ndim).astype(np.float32) assert sp_sum_difference == np.power(np.abs(sp1*sp_counts[sp1] - sp2*sp_counts[sp2]), 1./superpixels.ndim).astype(np.float32) # MEAN features_df = rag.compute_features(values, ['standard_sp_mean']) assert len(features_df) == len(rag.edge_ids) assert (features_df.columns.values == ['sp1', 'sp2', 'standard_sp_mean_sum', 'standard_sp_mean_difference']).all() assert (features_df[['sp1', 'sp2']].values == rag.edge_ids).all() # No normalization for other features... # Should there be? for _index, sp1, sp2, sp_mean_sum, sp_mean_difference in features_df.itertuples(): assert sp_mean_sum == sp1 + sp2 assert sp_mean_difference == np.abs(np.float32(sp1) - sp2)
def test_area(self): superpixels = generate_random_voronoi((100,200), 200) feature_names = ['edgeregion_edge_regionradii', 'edgeregion_edge_area'] rag = Rag( superpixels ) features_df = rag.compute_features(None, feature_names) radii = features_df[['edgeregion_edge_regionradii_0', 'edgeregion_edge_regionradii_1']].values assert (radii[:,0] >= radii[:,1]).all() areas = features_df[['edgeregion_edge_area']].values assert ((radii[:,0] * radii[:,1]) == areas[:,0]).all()
def test_correlation(self): # Create a volume of flat superpixels, where every slice # is the same (except for the actual sp ids) num_sp_per_slice = 200 slice_superpixels = generate_random_voronoi((100,200), num_sp_per_slice) superpixels = np.zeros( shape=((10,) + slice_superpixels.shape), dtype=np.uint32 ) for z in range(10): superpixels[z] = slice_superpixels + z*num_sp_per_slice superpixels = vigra.taggedView(superpixels, 'zyx') rag = Rag( superpixels, flat_superpixels=True ) # For simplicity, just make values identical to the first slice values = np.zeros_like(superpixels, dtype=np.float32) values[:] = slice_superpixels[None] features_df = rag.compute_features(values, ['similarity_flatedge_correlation'], edge_group='z') assert (features_df['similarity_flatedge_correlation'].values == 1.0).all() # Now add a little noise from one slice to the next. for z in range(10): if z == 0: continue if z == 1: values[z] += 0.001*np.random.random(size=(values[z].shape)) else: values[z] += 1.0001*np.abs(values[z-1] - values[z-2]) features_df = rag.compute_features(values, ['similarity_flatedge_correlation'], edge_group='z') assert (features_df['similarity_flatedge_correlation'].values >= 0.7).all() assert (features_df['similarity_flatedge_correlation'].values <= 1.0).all() # Now use just noise values = np.random.random(size=values.shape).astype(np.float32) values = vigra.taggedView(values, 'zyx') features_df = rag.compute_features(values, ['similarity_flatedge_correlation'], edge_group='z') assert (features_df['similarity_flatedge_correlation'].values <= 1.0).all() assert (features_df['similarity_flatedge_correlation'].values >= -1.0).all()
def test_serialization_without_labels(self): """ Users can opt to serialize the Rag without serializing the labels, but then they can't use superpixel features on the deserialized Rag. """ import h5py superpixels = generate_random_voronoi((100,200), 200) original_rag = Rag( superpixels ) tmp_dir = tempfile.mkdtemp() filepath = os.path.join(tmp_dir, 'test_rag.h5') rag_groupname = 'saved_rag' # Serialize with labels with h5py.File(filepath, 'w') as f: rag_group = f.create_group(rag_groupname) original_rag.serialize_hdf5(rag_group, store_labels=False) # Don't store # Deserialize with h5py.File(filepath, 'r') as f: rag_group = f[rag_groupname] deserialized_rag = Rag.deserialize_hdf5(rag_group) assert deserialized_rag.label_img.dtype == original_rag.label_img.dtype assert deserialized_rag.label_img.shape == original_rag.label_img.shape assert deserialized_rag.label_img.axistags == original_rag.label_img.axistags #assert (deserialized_rag.label_img == original_rag.label_img).all() # not stored assert (deserialized_rag.sp_ids == original_rag.sp_ids).all() assert deserialized_rag.max_sp == original_rag.max_sp assert deserialized_rag.num_sp == original_rag.num_sp assert deserialized_rag.num_edges == original_rag.num_edges assert (deserialized_rag.edge_ids == original_rag.edge_ids).all() # Check some features # For simplicity, just make values identical to superpixels values = superpixels.astype(np.float32) feature_names = ['standard_edge_mean', 'standard_edge_count'] features_df_original = original_rag.compute_features(values, feature_names) features_df_deserialized = deserialized_rag.compute_features(values, feature_names) assert (features_df_original.values == features_df_deserialized.values).all() try: deserialized_rag.compute_features(values, ['standard_sp_count']) except NotImplementedError: pass except: raise else: assert False, "Shouldn't be able to use superpixels if labels weren't serialized/deserialized!"
def test_sp_features_with_histogram(self): superpixels = generate_random_voronoi((100,200), 200) rag = Rag( superpixels ) # For simplicity, just make values identical to superpixels values = superpixels.astype(np.float32) # Manually compute the sp counts sp_counts = np.bincount(superpixels.flat[:]) # COUNT features_df = rag.compute_features(values, ['standard_sp_count', 'standard_sp_quantiles_25', 'standard_sp_quantiles_75']) assert len(features_df) == len(rag.edge_ids) assert (features_df.columns.values == ['sp1', 'sp2', 'standard_sp_count_sum', 'standard_sp_count_difference', 'standard_sp_quantiles_25_sum', 'standard_sp_quantiles_25_difference', 'standard_sp_quantiles_75_sum', 'standard_sp_quantiles_75_difference']).all() assert (features_df[['sp1', 'sp2']].values == rag.edge_ids).all() # Check dtypes (pandas makes it too easy to get this wrong). dtypes = { colname: series.dtype for colname, series in features_df.iterkv() } assert all(dtype != np.float64 for dtype in dtypes.values()), \ "An accumulator returned float64 features. That's a waste of ram.\n"\ "dtypes were: {}".format(dtypes) # sp count features are normalized, consistent with the multicut paper. for _index, sp1, sp2, \ sp_count_sum, sp_count_difference, \ sp_quantiles_25_sum, sp_quantiles_25_difference, \ sp_quantiles_75_sum, sp_quantiles_75_difference in features_df.itertuples(): assert type(sp_quantiles_25_sum) == np.float32 assert type(sp_quantiles_75_sum) == np.float32 assert type(sp_quantiles_25_difference) == np.float32 assert type(sp_quantiles_75_difference) == np.float32 assert sp_count_sum == np.power(sp_counts[sp1] + sp_counts[sp2], 1./superpixels.ndim).astype(np.float32) assert sp_count_difference == np.power(np.abs(sp_counts[sp1] - sp_counts[sp2]), 1./superpixels.ndim).astype(np.float32) assert sp_quantiles_25_sum == float(sp1 + sp2), \ "{} != {}".format( sp_quantiles_25_sum, float(sp1 + sp2) ) assert sp_quantiles_75_sum == float(sp1 + sp2) assert sp_quantiles_25_difference == abs(float(sp1) - sp2) assert sp_quantiles_75_difference == abs(float(sp1) - sp2)
def test_serialization_with_external_labels(self): """ Users can opt to serialize the Rag without serializing the labels, but then they can't use superpixel features on the deserialized Rag. When deserializing, they can provide the labels from an external source, as tested here. """ import h5py superpixels = generate_random_voronoi((100,200), 200) original_rag = Rag( superpixels ) tmp_dir = tempfile.mkdtemp() filepath = os.path.join(tmp_dir, 'test_rag.h5') rag_groupname = 'saved_rag' # Serialize with labels with h5py.File(filepath, 'w') as f: rag_group = f.create_group(rag_groupname) original_rag.serialize_hdf5(rag_group, store_labels=False) # Deserialize with h5py.File(filepath, 'r') as f: rag_group = f[rag_groupname] deserialized_rag = Rag.deserialize_hdf5(rag_group, label_img=superpixels) # Provide labels explicitly assert deserialized_rag.label_img.dtype == original_rag.label_img.dtype assert deserialized_rag.label_img.shape == original_rag.label_img.shape assert deserialized_rag.label_img.axistags == original_rag.label_img.axistags assert (deserialized_rag.label_img == original_rag.label_img).all() assert (deserialized_rag.sp_ids == original_rag.sp_ids).all() assert deserialized_rag.max_sp == original_rag.max_sp assert deserialized_rag.num_sp == original_rag.num_sp assert deserialized_rag.num_edges == original_rag.num_edges assert (deserialized_rag.edge_ids == original_rag.edge_ids).all() # Check some features # For simplicity, just make values identical to superpixels values = superpixels.astype(np.float32) feature_names = ['standard_edge_mean', 'standard_sp_count'] features_df_original = original_rag.compute_features(values, feature_names) features_df_deserialized = deserialized_rag.compute_features(values, feature_names) assert (features_df_original.values == features_df_deserialized.values).all()
def test_shorthand_names(self): superpixels = generate_random_voronoi((100,200), 200) rag = Rag( superpixels ) # For simplicity, just make values identical to superpixels values = superpixels.astype(np.float32) features_df = rag.compute_features(values, ['standard_edge_quantiles', 'standard_sp_quantiles']) quantile_names = ['quantiles_0', 'quantiles_10', 'quantiles_25', 'quantiles_50', 'quantiles_75', 'quantiles_90', 'quantiles_100'] edge_feature_names = map( lambda name: 'standard_edge_' + name, quantile_names ) sp_features_names = map( lambda name: 'standard_sp_' + name, quantile_names ) sp_output_columns = [] for name in sp_features_names: sp_output_columns.append( name + '_sum' ) sp_output_columns.append( name + '_difference' ) assert list(features_df.columns.values) == ['sp1', 'sp2'] + edge_feature_names + sp_output_columns
def test_serialization_with_labels(self): """ Serialize the rag and labels to hdf5, then deserialize it and make sure nothing was lost. """ import h5py superpixels = generate_random_voronoi((100,200), 200) original_rag = Rag( superpixels ) tmp_dir = tempfile.mkdtemp() filepath = os.path.join(tmp_dir, 'test_rag.h5') rag_groupname = 'saved_rag' # Serialize with labels with h5py.File(filepath, 'w') as f: rag_group = f.create_group(rag_groupname) original_rag.serialize_hdf5(rag_group, store_labels=True) # Deserialize with h5py.File(filepath, 'r') as f: rag_group = f[rag_groupname] deserialized_rag = Rag.deserialize_hdf5(rag_group) assert deserialized_rag.label_img.dtype == original_rag.label_img.dtype assert deserialized_rag.label_img.shape == original_rag.label_img.shape assert deserialized_rag.label_img.axistags == original_rag.label_img.axistags assert (deserialized_rag.label_img == original_rag.label_img).all() assert (deserialized_rag.sp_ids == original_rag.sp_ids).all() assert deserialized_rag.max_sp == original_rag.max_sp assert deserialized_rag.num_sp == original_rag.num_sp assert deserialized_rag.num_edges == original_rag.num_edges assert (deserialized_rag.edge_ids == original_rag.edge_ids).all() # Check some features # For simplicity, just make values identical to superpixels values = superpixels.astype(np.float32) feature_names = ['standard_edge_mean', 'standard_sp_count'] features_df_original = original_rag.compute_features(values, feature_names) features_df_deserialized = deserialized_rag.compute_features(values, feature_names) assert (features_df_original.values == features_df_deserialized.values).all()
def test_count(self): # Create a volume of flat superpixels, where every slice # is the same (except for the actual sp ids) num_sp_per_slice = 200 slice_superpixels = generate_random_voronoi((100,200), num_sp_per_slice) superpixels = np.zeros( shape=((10,) + slice_superpixels.shape), dtype=np.uint32 ) for z in range(10): superpixels[z] = slice_superpixels + z*num_sp_per_slice superpixels = vigra.taggedView(superpixels, 'zyx') rag = Rag( superpixels, flat_superpixels=True ) # Manually compute the sp counts for the first N-1 slices, # which happens to be the same as the edge counts (since superpixels are identical on all slices) sp_counts = np.bincount(superpixels[:-1].flat[:]) sp_counts = sp_counts[1:] # Drop zero sp (it doesn't exist) features_df = rag.compute_features(None, ['standard_flatedge_count'], edge_group='z') assert sorted(features_df['standard_flatedge_count'].values) == sorted(sp_counts)
def test_edge_features_with_histogram_blank_data(self): """ There was a bug related to histogram min/max if all edge pixels had the exact same value. In that case, min and max were identical and vigra complained. For example, if you give vigra histogramRange=(0.0, 0.0), that's a problem. This test verifies that no crashes occur in such cases. """ superpixels = generate_random_voronoi((100,200), 200) rag = Rag( superpixels ) values = np.zeros_like(superpixels, dtype=np.float32) feature_names = ['standard_edge_mean', 'standard_edge_minimum', 'standard_edge_maximum', 'standard_edge_variance', 'standard_edge_quantiles_25', 'standard_edge_quantiles_50', 'standard_edge_quantiles_75', 'standard_edge_count', 'standard_edge_sum'] features_df = rag.compute_features(values, feature_names) assert len(features_df) == len(rag.edge_ids) assert list(features_df.columns.values) == ['sp1', 'sp2'] + list(feature_names), \ "Wrong output feature names: {}".format( features_df.columns.values ) assert (features_df[['sp1', 'sp2']].values == rag.edge_ids).all() # Check dtypes (pandas makes it too easy to get this wrong). dtypes = { colname: series.dtype for colname, series in features_df.iteritems() } assert all(dtype != np.float64 for dtype in list(dtypes.values())), \ "An accumulator returned float64 features. That's a waste of ram.\n"\ "dtypes were: {}".format(dtypes) for row_tuple in features_df.itertuples(): row = OrderedDict( list(zip(['index', 'sp1', 'sp2'] + list(feature_names), row_tuple)) ) assert row['standard_edge_mean'] == 0.0 assert row['standard_edge_minimum'] == 0.0 assert row['standard_edge_maximum'] == 0.0 assert row['standard_edge_variance'] == 0.0 assert row['standard_edge_quantiles_25'] == 0.0 assert row['standard_edge_quantiles_75'] == 0.0 assert row['standard_edge_count'] > 0 assert row['standard_edge_sum'] == 0.0
def test_edge_features_with_histogram(self): superpixels = generate_random_voronoi((100,200), 200) rag = Rag( superpixels ) # For simplicity, just make values identical to superpixels values = superpixels.astype(np.float32) feature_names = ['standard_edge_mean', 'standard_edge_minimum', 'standard_edge_maximum', 'standard_edge_variance', 'standard_edge_quantiles_25', 'standard_edge_quantiles_50', 'standard_edge_quantiles_75', 'standard_edge_count', 'standard_edge_sum'] features_df = rag.compute_features(values, feature_names) assert len(features_df) == len(rag.edge_ids) assert list(features_df.columns.values) == ['sp1', 'sp2'] + list(feature_names), \ "Wrong output feature names: {}".format( features_df.columns.values ) assert (features_df[['sp1', 'sp2']].values == rag.edge_ids).all() # Check dtypes (pandas makes it too easy to get this wrong). dtypes = { colname: series.dtype for colname, series in features_df.iterkv() } assert all(dtype != np.float64 for dtype in dtypes.values()), \ "An accumulator returned float64 features. That's a waste of ram.\n"\ "dtypes were: {}".format(dtypes) for row_tuple in features_df.itertuples(): row = OrderedDict( zip(['index', 'sp1', 'sp2'] + list(feature_names), row_tuple) ) sp1 = row['sp1'] sp2 = row['sp2'] # Values were identical to the superpixels, so this is boring... assert row['standard_edge_mean'] == (sp1+sp2)/2. assert row['standard_edge_minimum'] == (sp1+sp2)/2. assert row['standard_edge_maximum'] == (sp1+sp2)/2. assert row['standard_edge_variance'] == 0.0 assert row['standard_edge_quantiles_25'] == (sp1+sp2)/2. assert row['standard_edge_quantiles_75'] == (sp1+sp2)/2. assert row['standard_edge_count'] > 0 assert row['standard_edge_sum'] == row['standard_edge_count'] * (sp1+sp2)/2.
def test_sp_region_features(self): # Create a superpixel for each y-column superpixels = np.zeros( (100, 200), dtype=np.uint32 ) superpixels[:] = np.arange(200)[None, :] superpixels = vigra.taggedView(superpixels, 'yx') rag = Rag( superpixels ) # For simplicity, just make values identical to superpixels values = superpixels.astype(np.float32) feature_names = ['standard_sp_regionradii_0', 'standard_sp_regionradii_1', 'standard_sp_regionaxes_0x', 'standard_sp_regionaxes_0y', 'standard_sp_regionaxes_1x', 'standard_sp_regionaxes_1y', ] output_columns = ['sp1', 'sp2', 'standard_sp_regionradii_0_sum', 'standard_sp_regionradii_0_difference', 'standard_sp_regionradii_1_sum', 'standard_sp_regionradii_1_difference', 'standard_sp_regionaxes_0x_sum', 'standard_sp_regionaxes_0x_difference', 'standard_sp_regionaxes_0y_sum', 'standard_sp_regionaxes_0y_difference', 'standard_sp_regionaxes_1x_sum', 'standard_sp_regionaxes_1x_difference', 'standard_sp_regionaxes_1y_sum', 'standard_sp_regionaxes_1y_difference' ] features_df = rag.compute_features(values, feature_names) assert len(features_df) == len(rag.edge_ids) assert list(features_df.columns.values) == output_columns, \ "Wrong output feature names: {}".format( features_df.columns.values ) # Using shorthand names should result in the same columns features_df = rag.compute_features(values, ['standard_sp_regionradii', 'standard_sp_regionaxes']) assert len(features_df) == len(rag.edge_ids) assert list(features_df.columns.values) == output_columns, \ "Wrong output feature names: {}".format( features_df.columns.values ) assert (features_df[['sp1', 'sp2']].values == rag.edge_ids).all() # Check dtypes (pandas makes it too easy to get this wrong). dtypes = { colname: series.dtype for colname, series in features_df.iterkv() } assert all(dtype != np.float64 for dtype in dtypes.values()), \ "An accumulator returned float64 features. That's a waste of ram.\n"\ "dtypes were: {}".format(dtypes) # Manually compute the 'radius' of each superpixel # This is easy because each superpixel is just 1 column wide. col_coord_mean = np.arange(100).mean() centralized_col_coords = np.arange(100) - col_coord_mean col_coord_variance = centralized_col_coords.dot(centralized_col_coords)/100. col_radius = np.sqrt(col_coord_variance).astype(np.float32) for row_tuple in features_df.itertuples(): row = OrderedDict( zip(['index'] + list(features_df.columns.values), row_tuple) ) # The superpixels were just vertical columns assert row['standard_sp_regionradii_0_sum'] == 2*col_radius assert row['standard_sp_regionradii_0_difference'] == 0.0 assert row['standard_sp_regionradii_1_sum'] == 0.0 assert row['standard_sp_regionradii_1_difference'] == 0.0 # Axes are just parallel to the coordinate axes, so this is boring. # The x_sum is 0.0 because all superpixels are only 1 pixel wide in that direction. assert row['standard_sp_regionaxes_0x_sum'] == 0.0 assert row['standard_sp_regionaxes_0x_difference'] == 0.0 assert row['standard_sp_regionaxes_0y_sum'] == 2.0 assert row['standard_sp_regionaxes_0y_difference'] == 0.0 # The second axis is the smaller one, so here the y_sum axes are non-zero assert row['standard_sp_regionaxes_1x_sum'] == 2.0 assert row['standard_sp_regionaxes_1x_difference'] == 0.0 assert row['standard_sp_regionaxes_1y_sum'] == 0.0 assert row['standard_sp_regionaxes_1y_difference'] == 0.0