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()
示例#2
0
    def test_invalid_feature_names(self):
        """
        The Rag should refuse to compute features it doesn't 
        support, not silently omit them.
        """
        superpixels = generate_random_voronoi((100,200), 200)
        rag = Rag( superpixels )

        # For simplicity, just make values identical to superpixels
        values = superpixels.astype(np.float32)

        def try_bad_features(feature_names):
            try:
                _ = rag.compute_features(values, feature_names)
            except:
                pass
            else:
                assert False, "Rag should raise an error if the user gives bad feature names!"

        try_bad_features(['standard_edddddge_count'])
        try_bad_features(['standard_sssp_count'])
        try_bad_features(['ssssstandard_sp_count'])
        try_bad_features(['ssssstandard_edge_count'])
        try_bad_features(['standard_edge_countttt'])
        try_bad_features(['standard_sp_countttt'])
    def test_invalid_feature_names(self):
        """
        The Rag should refuse to compute features it doesn't 
        support, not silently omit them.
        """
        superpixels = generate_random_voronoi((100,200), 200)
        rag = Rag( superpixels )

        # For simplicity, just make values identical to superpixels
        values = superpixels.astype(np.float32)

        def try_bad_features(feature_names):
            try:
                _ = rag.compute_features(values, feature_names)
            except:
                pass
            else:
                assert False, "Rag should raise an error if the user gives bad feature names!"

        # These aren't supported for a 2D rag
        try_bad_features(['edgeregion_edge_regionradii_2'])
        try_bad_features(['edgeregion_edge_regionaxes_0z'])
        try_bad_features(['edgeregion_edge_regionaxes_1z'])
        try_bad_features(['edgeregion_edge_regionaxes_2x'])
        try_bad_features(['edgeregion_edge_regionaxes_2y'])
        try_bad_features(['edgeregion_edge_regionaxes_2z'])
示例#4
0
def test_features_df_serialization():
    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)

    tmpdir = tempfile.mkdtemp()
    try:
        with h5py.File( tmpdir + '/' + 'test_dataframe.h5', 'w' ) as f:
            group = f.create_group('test_dataframe')
            dataframe_to_hdf5( group, features_df )
        
        with h5py.File( tmpdir + '/' + 'test_dataframe.h5', 'r' ) as f:
            group = f['test_dataframe']
            readback_features_df = dataframe_from_hdf5( group )
        
        assert (readback_features_df.columns.values == features_df.columns.values).all()
        assert (readback_features_df.values.shape == features_df.values.shape)
        assert (readback_features_df.values == features_df.values).all()

    finally:
        shutil.rmtree(tmpdir)
    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_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()
示例#8
0
    def testBasic(self):
        superpixels = generate_random_voronoi((100, 100, 100), 100)
        superpixels = superpixels.insertChannelAxis()

        voxel_data = superpixels.astype(np.float32)

        graph = Graph()
        multilane_op = OpEdgeTraining(graph=graph)
        multilane_op.VoxelData.resize(1)  # resizes all level-1 slots.
        op_view = multilane_op.getLane(0)

        op_view.VoxelData.setValue(voxel_data,
                                   extra_meta={'channel_names': ['Grayscale']})
        op_view.Superpixels.setValue(superpixels)

        multilane_op.FeatureNames.setValue(
            {"Grayscale": ['standard_edge_mean', 'standard_edge_count']})

        assert op_view.Rag.ready()

        # Pick some edges to label
        rag = op_view.Rag.value
        edge_A = tuple(rag.edge_ids[0])
        edge_B = tuple(rag.edge_ids[1])
        edge_C = tuple(rag.edge_ids[2])
        edge_D = tuple(rag.edge_ids[3])

        labels = {
            edge_A: 1,  # OFF
            edge_B: 1,
            edge_C: 2,  # ON
            edge_D: 2
        }

        op_view.EdgeLabelsDict.setValue(labels)
        op_view.FreezeClassifier.setValue(False)

        assert op_view.EdgeProbabilities.ready()
        assert op_view.EdgeProbabilitiesDict.ready()
        assert op_view.NaiveSegmentation.ready()

        edge_prob_dict = op_view.EdgeProbabilitiesDict.value

        # OFF
        assert edge_prob_dict[edge_A] < 0.5, "Expected < 0.5, got {}".format(
            edge_prob_dict[edge_A])
        assert edge_prob_dict[edge_B] < 0.5, "Expected < 0.5, got {}".format(
            edge_prob_dict[edge_B])

        # ON
        assert edge_prob_dict[edge_C] > 0.5, "Expected > 0.5, got {}".format(
            edge_prob_dict[edge_C])
        assert edge_prob_dict[edge_D] > 0.5, "Expected > 0.5, got {}".format(
            edge_prob_dict[edge_D])
    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()
示例#10
0
    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 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 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_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)
示例#14
0
    def testBasic(self):
        superpixels = generate_random_voronoi( (100,100,100), 100 )
        superpixels = superpixels.insertChannelAxis()
        
        voxel_data = superpixels.astype(np.float32)
                
        graph = Graph()
        multilane_op = OpEdgeTraining(graph=graph)
        multilane_op.VoxelData.resize(1) # resizes all level-1 slots.
        op_view = multilane_op.getLane(0)
        
        op_view.VoxelData.setValue( voxel_data, extra_meta={'channel_names': ['Grayscale']} )
        op_view.Superpixels.setValue( superpixels )
        
        multilane_op.FeatureNames.setValue( { "Grayscale": ['standard_edge_mean', 'standard_edge_count'] } )
        
        assert op_view.Rag.ready()

        # Pick some edges to label
        rag = op_view.Rag.value
        edge_A = tuple(rag.edge_ids[0])
        edge_B = tuple(rag.edge_ids[1])
        edge_C = tuple(rag.edge_ids[2])
        edge_D = tuple(rag.edge_ids[3])

        labels = { edge_A : 1, # OFF
                   edge_B : 1,
                   edge_C : 2, # ON
                   edge_D : 2 }

        op_view.EdgeLabelsDict.setValue( labels )
        op_view.FreezeClassifier.setValue(False)
        
        assert op_view.EdgeProbabilities.ready()
        assert op_view.EdgeProbabilitiesDict.ready()
        assert op_view.NaiveSegmentation.ready()

        edge_prob_dict = op_view.EdgeProbabilitiesDict.value
        
        # OFF
        assert edge_prob_dict[edge_A] < 0.5, "Expected < 0.5, got {}".format(edge_prob_dict[edge_A])
        assert edge_prob_dict[edge_B] < 0.5, "Expected < 0.5, got {}".format(edge_prob_dict[edge_B])
        
        # ON
        assert edge_prob_dict[edge_C] > 0.5, "Expected > 0.5, got {}".format(edge_prob_dict[edge_C])
        assert edge_prob_dict[edge_D] > 0.5, "Expected > 0.5, got {}".format(edge_prob_dict[edge_D])
示例#15
0
    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
示例#17
0
    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)
示例#19
0
    def test_naive_segmentation_from_edge_decisions(self):
        superpixels = generate_random_voronoi((100,200), 200)
        rag = Rag( superpixels )
        
        # The 'groundtruth' is just divided into quadrants
        groundtruth = np.zeros_like(superpixels)
        groundtruth[0:50,   0:100] = 1
        groundtruth[50:100, 0:100] = 2
        groundtruth[0:50,   100:200] = 3
        groundtruth[50:100, 100:200] = 4

        decisions = rag.edge_decisions_from_groundtruth(groundtruth)
        segmentation = rag.naive_segmentation_from_edge_decisions(decisions)
        
        # We don't know where the exact boundary is, but pixels 
        # near the corners should definitely be homogenous
        assert (segmentation[:20,   :20] == segmentation[0,  0]).all()
        assert (segmentation[:20,  -20:] == segmentation[0, -1]).all()
        assert (segmentation[-20:,  :20] == segmentation[-1, 0]).all()
        assert (segmentation[-20:, -20:] == segmentation[-1,-1]).all()
    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_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_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.
示例#23
0
    def test_construction(self):
        superpixels = generate_random_voronoi((100,200), 200)
        
        rag = Rag( superpixels )
        assert rag.num_sp == 200, "num_sp was: {}".format(rag.num_sp)
        assert rag.max_sp == 200
        assert (rag.sp_ids == np.arange(1,201)).all()
        assert rag.sp_ids.dtype == np.uint32
        assert isinstance(rag.max_sp, np.uint32)
        assert rag.edge_ids.dtype == np.uint32
        assert (rag.unique_edge_tables['yx'][['sp1', 'sp2', 'edge_label']].dtypes == np.uint32).all()
        for _axiskey, df in rag.dense_edge_tables.items():
            assert df['sp1'].dtype == df['sp2'].dtype == np.uint32
            assert df['forwardness'].dtype == bool
            assert df['edge_label'].dtype == np.uint32
            
            # The coordinate dtype can be uint16 or uint32,
            # depending on the size of the size of the image 
            assert df['y'].dtype == df['x'].dtype == np.uint16

        # Just check some basic invariants of the edge_ids
        assert rag.edge_ids.shape == (rag.num_edges, 2)

        # For all edges (u,v): u < v
        edge_ids_copy = rag.edge_ids.copy()
        edge_ids_copy.sort(axis=1)
        assert (rag.edge_ids == edge_ids_copy).all()

        # edge_ids should be sorted by u, then v.
        edge_df = pd.DataFrame(edge_ids_copy, columns=['sp1', 'sp2'])
        edge_df.sort(columns=['sp1', 'sp2'], inplace=True)
        assert (rag.edge_ids == edge_df.values).all()

        # We're just using default features, so the supported features should match.
        default_features = [acc_cls.supported_features(rag) for acc_cls in Rag.DEFAULT_ACCUMULATOR_CLASSES.values()]
        default_features = itertools.chain(*default_features)
        assert set(rag.supported_features()) == set( default_features )