OpenCV学习:CvGraph相关函数

 OpenCV提供了CvGraph相关函数,借助这些函数可以实现图算法。下面介绍OpenCV中CvGraph相关函数,并基于这些函数完成图像的宽度优先遍历算法,最后附上CvGraph相关的所有函数的用法介绍。

CvGraph、CvGraphVtx、CvGraphEdge结构

结构如下(源码中宏以作处理):

typedef struct CvGraphVtx
{
    int flags; //图算法中一些标记位,比如深度遍历、宽度遍历中对已访问节点的标记
    struct CvGraphEdge* first; //该点辐射的所有边中的第一条边
}CvGraphVtx;

typedef struct CvGraphEdge
{
    int flags; //图算法中一些标记位
    float weight; //边的权重
    struct CvGraphEdge* next[2];//该边起始点连接的下一条边[0],该边终止点连接的下一条边[1]
    struct CvGraphVtx* vtx[2];//该边的起始节点和终止节点
}CvGraphEdge;

typedef struct CvGraph
{
    CV_SET_FIELDS() /* set of vertices */   \
    CvSet* edges;   /* set of edges */
}
CvGraph;

图的宽度遍历

主要数据结构介绍完毕,下面程序使用这些数据结构完成图的宽度遍历。OpenCV中提供了了CvGraphScanner完成图像的遍历,但是算法确实很难用,有兴趣的可以读一下cvNextGraphItem函数。程序基于下图:


#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
#include "iostream"
#include "math.h"
#include "time.h"
#include <set>
#include <queue>
using namespace std;
#define  PI  3.1415926
clock_t start,finish;

#define VtxNum 6
#define EdgeNum 9
int main(int argc, char* argv[])
{
	CvGraph *graph;
	CvMemStorage * storage;
	int i;
	storage = cvCreateMemStorage(0);
	graph=cvCreateGraph(CV_SEQ_KIND_GRAPH,sizeof(CvGraph),sizeof(CvGraphVtx),sizeof(CvGraphEdge),storage);
	CvGraphEdge *Edges = new CvGraphEdge[EdgeNum];
	int *VId = new int[VtxNum];//记录插入节点的索引
	for (i=0;i<VtxNum;i++)
	{
		VId[i]=0;
	}
	int Flags[VtxNum]={0,1,2,3,4,5};
	int Weights[EdgeNum]={15,25,19,12,18,35,5,15,45};

	for (i=0;i<VtxNum;i++)
	{
		VId[i]=cvGraphAddVtx(graph);
	}
	int edge_start[EdgeNum]={VId[0],VId[0],VId[0],VId[0],VId[1],VId[2],VId[3],VId[3],VId[4]};
	int edge_end[EdgeNum]  ={VId[1],VId[2],VId[3],VId[4],VId[2],VId[3],VId[4],VId[5],VId[5]};
 
	for (i=0;i<EdgeNum;i++)
	{
		Edges[i].weight = Weights[i];
		cvGraphAddEdge(graph,edge_start[i],edge_end[i],&Edges[i],&Edges_addr[i]);//根据索引插入边
	}
	//图构建完毕。
	//开始进行宽度遍历
	queue<CvGraphVtx *> VtxQueue;
	CvGraphVtx *CurVtxOri;
	CvGraphVtx *CurVtxDst;
	CvGraphEdge *CurEdge;
	CurVtxOri=cvGetGraphVtx(graph,VId[0]);
	CurVtxOri->flags|=CV_GRAPH_ITEM_VISITED_FLAG;
	VtxQueue.push(cvGetGraphVtx(graph,VId[0]));
	while (!VtxQueue.empty())
	{
		CurVtxOri=VtxQueue.front();
		VtxQueue.pop();
		CurEdge=CurVtxOri->first;
		cout<<cvGraphVtxIdx(graph,CurVtxOri)<<" : " ;

		while (CurEdge)//如果是有边的
		{
			if (!CV_IS_GRAPH_EDGE_VISITED(CurEdge))
			{
				CurEdge->flags|=CV_GRAPH_ITEM_VISITED_FLAG;
				CurVtxDst=CurEdge->vtx[CurVtxOri==CurEdge->vtx[0]];//找到另一个点
				if (!CV_IS_GRAPH_VERTEX_VISITED(CurVtxDst))
				{
					VtxQueue.push(CurVtxDst);
					CurVtxDst->flags|=CV_GRAPH_ITEM_VISITED_FLAG;
					cout<<cvGraphVtxIdx(graph,CurVtxDst)<<" ";
				}
				
			}
			//好好处理CurEdge变量,区分当前点与边的关系,参考本博客第一部分对CvGraphEdge解释
			if (CurVtxOri==CurEdge->vtx[0])
			{
				CurEdge=CurEdge->next[0];
			}
			else
			{
				CurEdge=CurEdge->next[1];
			}
			
		 
		}
		cout<<endl;	
	}
	return 0;
}
CvGraph主要函数说明

函数:int cvGraphAddVtx( CvGraph* graph, const CvGraphVtx* vtx=NULL,CvGraphVtx** inserted_vtx=NULL );
功能:插入一个顶点到图中,并返回顶点的索引
参数:graph----要操作的图
      vtx------可选输入参数,用来初始化新加入的顶点,
      inserted_vtx----可选的输出参数。如果不为NULL,则传回新加入顶点的地址
函数:int cvGraphRemoveVtx( CvGraph* graph, int index );
功能:通过索引从图中删除一个顶点,连同删除含有此顶点的边。如果输入的顶点不属于该图的话,将报告删除出错,返回值为被删除的边数,如果顶点不属于该图的话,返回-1。
函数:int cvGraphRemoveVtxByPtr( CvGraph* graph, CvGraphVtx* vtx );
功能:从图中删除一个顶点,连同删除含有此顶点的边。如果输入的顶点不属于该图的话,将报告出错。返回值为被删除的边数,如果顶点不属于该图的话,返回-1.
函数:CvGraphVtx *cvGetGraphVtx(CvGraph*graph,int vtx_idx);
功能:返回索引值是vtx_idx的顶点的指针,如果不存在则返回NULL。
函数:int cvGraphVtxIdx(CvGraph * graph,CvGraphVtx *vtx);
功能:返回与vtx相对应的顶点的索引值
函数:int cvGraphAddEdge(CvGraph *graph,int start_idx,int end_idx,const CvGraphEdge *edge=NULL,CvGraphEdge **insert_edge=NULL);
参数:start_idx,end_idx 起始顶点和终止顶点的索引值
      edge 要插入的边,其中包含初始化数据
      insert_edge 被插入边的地址
功能:该函数连接两条特定的顶点。如果成功插入,返回1,如果这条边已经存在,返回0,如果顶点没有发现或者起始顶点和终止顶点是同一个点,那么返回-1.
      如果两个图的首尾是一样报错。
函数:int cvGraphAddEdgeByPtr(CvGraph * graph,CvGraphVtx *start_vtx,CvGraphVtx *end_vtx,const CvGraphEdge *edge=NULL,CvGraphEdge**inserted_edge=NULL);
功能:同上
函数:void cvGraphRemoveEdge(CvGraph *graph,int start_idx,int end_idx);
功能:删除连接两特定顶点的边,若没有连接,那么函数什么都不做
函数:void cvGraphRemoveEdgeByPtr(CvGraph *graph,CvGraphVtx *start_vtx,CvGraphVex *end_vtx);
功能:同上
函数:CvGraphEdge* cvFindGraphEdge(CvGraph*graph,int start_idx,int end_idx);
功能:查找与两特定顶点相对应的边,并返回指向该边的指针。
函数:CvGraphEdge *cvFindGraphEdgeByPtr(CvGraph*graph,const CvGraphVtx *start_vtx,const CvGraphVtx *end_vtx);
功能:同上
函数:int cvGraphEdgeIdx(CvGraph* graph,CvGraphEdge *edge);
功能:函数返回与边对应的索引值
函数:int cvGraghVtxDegree(const CvGraph* graph,int vtx_idx);
功能:统计与顶点相关联的边数,包括以该顶点为起始点和以该顶点以终止节点的。
宏:CV_NEXT_GRAPH_EDGE(CvGraphEdge* ,CvGraphVtx *);
功能:返回依附于该顶点的下一条边
函数: int cvGraphVtxDegreeByPtr(const CvGraph *graph,const CvGraphVtx *vtx);
功能:同上
函数:void cvClearGraph(CvGraph *graph);
功能:删除该图所有的顶点和所有的边,时间复杂度是O(1)
函数:CvGraph* cvCloneGraph(const CvGraph *graph,CvMemStorate * storage);
参数:storage:容器,存放拷贝
功能:函数cvCloneGraph创建图像的完全拷贝,如果顶点和边含有指向外部变量的指针,那么图和它的拷贝共享这些指针。
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值