使用定义的类作为图形增强库中无向图的边权重

时间:2018-02-07 15:34:49

标签: c++ algorithm boost graph

我是 Boost Graph Library 的新手,并且对无向图有疑问。

我的问题是,一个2D空间,其中放置了几个地标。在开始时,定义了一个Master-landmark,目标是计算从Master-landmark到所有其他地标的相对姿势。由于网格很大,一次看到它,我只得到本地信息,意味着两个或多个地标之间的相对连接/姿势(Master-landmark不必在每个图像中)。鉴于这些本地信息,我需要构建一个树,以便获得从Master-landmark到其他地标的路径。到现在为止还挺好。 由于地标观测由另一个程序完成,我构建了一个矩阵,其中有关地标关系的信息被编码(两个地标一起看?如果是,相对姿势,如果不是0)。该矩阵是大小为tag_relation_mat的所谓N×N矩阵。 N定义地标的数量,矩阵的行和列代表所有N地标以编码它们的关系。每个元素(如果两个标记之间存在连接,否则为0)是rel_marker_pose,包括:2D姿势(x和y值)和错误值(高值很差) 。换句话说,tag_relation_mat是一个矩阵,它对地标之间的所有有效连接进行编码。 基于该矩阵,我想生成无向图并计算从Master-landmark到所有其他给定最佳误差值的相对姿势。

所以我现在基本上做的(在this link的帮助下)是

  • 建立无向图和
  • 使用dijkstra_shortest_paths算法
  • 解决它

结果是组合权重(从主要地标到地标)和地标的父级。

根据这些信息,我通过组合N×N矩阵给出的变换,递归地生成从每个地标到主地标的路径:

.h文件:

// Edge weight.
typedef boost::property<boost::edge_weight_t, double> EdgeWeightProperty;

typedef adjacency_list < boost::setS, boost::vecS, boost::undirectedS,
    boost::no_property, EdgeWeightProperty > Graph; //graph type

typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex; //vertex descriptor
typedef typename boost::graph_traits<Graph>::edge_descriptor Edge; //edge descriptor
typedef std::pair<int, int> _edge;

class GraphTree {

public:
    GraphTree(int no_of_tags) {
        this->num_vertices = no_of_tags;

        //generate vertices
        for(int i = 0; i < no_of_tags; i++) {
            Vertex v  = boost::add_vertex(this->undirected_graph);
            idx_to_vertex.insert({i, v});
        }
    }

    /**
     * @brief generateTree generates tree graph with tags as edges and 
     */
    void generateTree();

    /**
     * @brief solveTree thin tree based on chosen solver
     */
    std::vector<rel_marker_pose> solveTree(tree_solver solver, int master_vertex_idx);

    /**
     * @brief getRelPosesToMaster given a master tag (either defined or automatically chosen) rel. poses to the other existing tags are computed
     */
    void getRelPosesToMaster(int master_node, std::vector<Vertex> parent_vec, int start_node, rel_marker_pose* rel_m_pose);

private:
    // declare a graph object
    Graph undirected_graph;

    std::map<int, Vertex> idx_to_vertex;

    int num_vertices;//    const int num_vertices = N;
    int num_edges;//int num_edges = sizeof(edge_array)/sizeof(edge_array[0]);

    std::vector<Edge> edge_vec;

};

.cpp文件:

void GraphTree::generateTree() {

for(int i = 0; i < this->num_vertices; ++i) { //iterate over rows (landmark_from)
    for(int j = 0; j < this->num_vertices; ++j) { //iterate over columns (landmark_to)
        double weight = this->tag_relation_mat.at(i).at(j).rel_pose.quality;

        //check if tags have been seen together -> add only relevant edges
        if(this->tag_relation_mat.at(i).at(j).landmark_from != 0 && this->tag_relation_mat.at(i).at(j).landmark_to != 0) {

            boost::add_edge(this->idx_to_vertex[i], this->idx_to_vertex[j], EdgeWeightProperty(weight), this->undirected_graph);

            }
        }
    }
}

std::vector<rel_marker_pose> GraphTree::solveTree(tree_solver solver, int master_vertex_idx) {

    std::vector<rel_marker_pose> master_to_vertex_vec;

    if(solver == tree_solver::Dijkstra) { //http://www.boost.org/doc/libs/1_46_1/libs/graph/example/dijkstra-example.cpp

        //create vectors to store the predecessors (p) and the distances from the root (d)
        std::vector<Vertex> p(boost::num_vertices(this->undirected_graph));
        std::vector<double> d(boost::num_vertices(this->undirected_graph));
        //create a descriptor for the source node
        Vertex master_vertex = vertex(master_vertex_idx, this->undirected_graph);

        //evaluate dijkstra on graph g with source s, predecessor_map p and distance_map d
        boost::dijkstra_shortest_paths(this->undirected_graph, master_vertex, boost::predecessor_map(&p[0]).distance_map(&d[0]));

        boost::graph_traits < Graph >::vertex_iterator vi, vend;
        for (boost::tie(vi, vend) = boost::vertices(this->undirected_graph); vi != vend; ++vi) {

            rel_marker_pose r_m_p;

            this->getRelPosesToMaster(master_vertex_idx, p, *vi, &r_m_p);

            master_to_vertex_vec.push_back(r_m_p);
        }
    }
    return master_to_vertex_vec;
}

void GraphTree::getRelPosesToMaster(int master_node, std::vector<Vertex> parent_vec, int start_node, rel_marker_pose* rel_m_pose ) {
    rel_m_pose->rel_pose.quality += this->tag_relation_mat.at(start_node).at(parent_vec[start_node]).rel_pose.quality;

    // ...
    // combine the transformations
    // ...

    rel_m_pose->landmark_from = parent_vec[start_node];

    if(parent_vec[start_node] == master_node) {
        return;
    }
    else {
        this->getRelPosesToMaster(master_node, parent_vec, parent_vec[start_node], rel_m_pose);
    }
}

嗯,它有效,但绝对不是最优雅的方式!我在想:

  1. 如果有可能将所有相关信息直接添加到无向图中(顶点的地标名称;边缘的姿势和质量)。到目前为止,它只是质量,然后用于解决图表。因此,在生成图形之后,我只需要图形而不是在求解图形之后合并图形和矩阵之间的信息?
  2. 是否有一种实现方式(在boost lib中)获取从master-landmark到landmark的所有访问过的边缘?
  3. 非常感谢你的帮助!

0 个答案:

没有答案