Boost logo

Boost Users :

From: Jef Driesen (jefdriesen_at_[hidden])
Date: 2006-01-25 09:02:01


Johan Oudinet wrote:
> On 1/24/06, Jef Driesen <jefdriesen_at_[hidden]> wrote:
>> I'm trying to create a graph from an image, where pixel values are
>> regions labels. I have defined my graph to use lists instead of the
>> vectors (because I need to add/remove vertices and edges) and one extra
>> property for the vertex (the region label):
>>
>> typedef boost::adjacency_list<
>> boost::listS, // Adjacency list
>> boost::listS, // Vertex list
>> boost::undirectedS, // Undirected graph
>> unsigned int, // Vertex property (=label)
>> boost::no_property, // Edge property
>> boost::no_property, // Graph property
>> boost::listS // Edge list
>> > graph;
>> typedef boost::graph_traits<graph>::vertex_descriptor vertex_t;
>> typedef boost::graph_traits<graph>::edge_descriptor edge_t;
>>
>> I have the following pseudo code to populate the graph:
>>
>> graph g;
>> for each pixel (i,j) {
>> unsigned int u_label = image[i][j];
>> for each neighbourhood pixel (k,l) {
>> unsigned int v_label = image[k][l];
>> if (u_label != v_label) {
>> // Find/add both vertices
>> vertex_t u = boost::add_vertex(u_label,g);
>> vertex_t v = boost::add_vertex(v_label, g);
>> // Find/add edge
>> boost::add_edge(u, v, g);
>> }
>> }
>> }
>>
>> But this creates many duplicates (with regard to the label) for both
>> vertices and edges. How can i prevent this? Would using a set for the
>> edges solves my problem?
>
> Yes, and a set for your vertices too.

Doesn't this contradict with your statement below? How can a set prevent
duplicates if there is no way to add vertex only if that vertex does not
exist in the graph already? I tried using a set for the vertex list, but
it makes no difference.

When using a list for both the adjacency and vertex list, i get these
numbers:
    Maximum #labels: 2453
    #vertices: 603844 <-- This should be equal to (or smaller than 2453)
    #edges: 301922
And using a set for both lists results in exactly the same output (and
is also much slower)!

>> And how can I add a vertex only if it does not
>> exist already?
>
> You can't, unless using a map from vertex_label to vertex_descriptor and
> ensure the vertex_label doesn't exist in this map before inserting a vertex.
>

Using your idea of using a map seemed a very nice solution. But I can't
get it work properly. I wrote a special "add_unique_vertex" function to
replace the "boost::add_vertex" function in the code above. The program
compiles, but crashes during the first call of "boost::add_edge". Even
if replace the body of my function with "return boost::add_vertex(label,
g);". What is going wrong?

template <class G>
typename boost::graph_traits<G>::vertex_descriptor
add_unique_vertex(
       unsigned int label,
       std::map<unsigned int, typename
boost::graph_traits<G>::vertex_descriptor > map,
       G g)
{
    typedef boost::graph_traits<G>::vertex_descriptor vertex_descriptor;
    typedef std::map<unsigned int, vertex_descriptor> vertex_map;
    typedef std::pair<vertex_map::iterator, bool> pair;

    // Search the vertex_map for the label. If
    // no vertex is found, a new entry is created.
    pair p = map.insert(vertex_map::value_type(label, vertex_descriptor()));
    if (p.second) {
       return (p.first->second = boost::add_vertex(label,g));
    } else {
       // Return existing vertex.
       return p.first->second;
    }
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net