广度优先的连通域计算
来源:互联网 发布:移动有网络机顶盒吗 编辑:程序博客网 时间:2024/06/03 21:11
广度优先的连通域求取算法,参考了http://blog.csdn.net/cui134/article/details/39610819文章。与我们平时用到的深度优先连通域算法的区别在于后者一般包含迭代求解过程,在数据量很大时可能出现栈溢出的情况;前者基于广度搜索,不存在迭代过程。
把代码和效果图贴出来,以后可能会用到。
#include <opencv2/opencv.hpp> #include "highgui.h" #include <math.h>using namespace std;using namespace cv;typedef unsigned long uint32;typedef unsigned int uint16;typedef unsigned char uint8;#define WHITE 1#define GRAY 2#define BLACK 3#define NIL 0#define INFINITE 255typedef Point ElemType;typedef struct Queue { ElemType* data; int front; int rear; int Qsize; }Queue; bool initQueue(Queue* q,int size) { q->front = 0; q->rear = 0; q->Qsize = size; q->data = (ElemType*)malloc(q->Qsize*sizeof(ElemType)); if( NULL == q->data) return false; return true; } //销毁队列,释放内存 void destroyQueue(Queue* q) { q->front = 0; q->rear = 0; q->Qsize = 0 ; free((q->data)); q->data = NULL; } //清空队列 void clearQueue(Queue* q) { q->front = 0; q->rear = 0; } //判断队列是否为空 bool isQueueEmpty(Queue *q) { if(q->front == q->rear) { printf("the queue is empty! \n"); return true; } else { return false; } } //返回队首元素 bool getHead(Queue *q,ElemType *e) { if(isQueueEmpty(q)) { printf("can not get the head element! \n"); return false; } else { *e = q->data[q->front]; return true; } } //返回队列长度:在循环队列中 int Qlength(Queue *q) { return (q->rear-q->front+q->Qsize)%q->Qsize; } //入队 bool enQueue(Queue *q,ElemType e) { //如果队列已满,重新分配内存 if(q->rear == q->Qsize-1) { q->data = (ElemType*)realloc(q->data,2*q->Qsize*sizeof(ElemType)); if(q->data == NULL) return false; else q->Qsize *= 2; } //先赋值,然后队尾循环加1 q->data[q->rear] = e; q->rear = (q->rear+1)%q->Qsize; return true; } //出队bool deQueue(Queue *q,ElemType *e) { if(isQueueEmpty(q)) return false; else { *e = q->data[q->front]; //队首标记循环加1 q->front = (q->front+1+q->Qsize) % q->Qsize; } return true; }void BFS( Mat& G,Mat& Label_Image, int x, int y ,uint8 num){Mat Color_src(G.size(), CV_8UC1);//白色表示未被搜索过,黑色表示搜索完毕,灰色表示正在搜索Point *u=&Point(0,0);int i,j,m,n;Queue Q; initQueue(&Q,10);//给所有点标记为白色Color_src.setTo(Scalar(WHITE));Color_src.at<unsigned char>(y,x) = GRAY;enQueue( &Q, Point( x, y));while( !isQueueEmpty(&Q) ){if( deQueue( &Q, u ) ){Label_Image.at<unsigned char>(u->y,u->x) = num;if( u->x==0|| u->x==G.cols||u->y==0|| u->y==G.rows )//不处理边界点continue;else{for( n=u->y - 1;n<=u->y+1; n++ )//八邻域{for( m=u->x - 1;m<=u->x+1; m++ ){if( m==u->x && n==u->y ){}else if(G.at<unsigned char>(n,m)==0 ){}else{if(WHITE==Color_src.at<unsigned char>(n,m)){Label_Image.at<unsigned char>(n,m) = num;Color_src.at<unsigned char>(n,m) = GRAY;enQueue( &Q, Point( m, n ));}}}}Color_src.at<unsigned char>(u->y, u->x) = BLACK;}}else break;}clearQueue(&Q);}void bwLabel(Mat img, Mat L_src ,Mat dst){int i,j;char s[5];uint8 Label_value=0;for( j=0; j<img.rows; j++ ){for( i=0; i<img.cols; i++ ){uint8 Label=L_src.at<unsigned char>(j,i);uint8 value=img.at<unsigned char>(j,i);if(Label==0&&value!=0){Label_value++;itoa( Label_value,s,10);putText(dst, s, Point(i,j), FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255)); BFS(img, L_src, i,j,Label_value);//以i,j为种子点标记同一目标}}}}int main(){Mat src, src_gray, L_src;int i,j,w,h;src = imread( "1.bmp" );//读取原图L_src.create(src.size(), CV_8UC1);L_src.setTo(0);w = src.cols;h = src.rows;cvtColor( src, src_gray, CV_BGR2GRAY );long long t = getTickCount();bwLabel(src_gray,L_src,src);//对图像进行标记cout<<"time: "<<(getTickCount()-t)/getTickFrequency();namedWindow("1",CV_WINDOW_AUTOSIZE);imshow("1",src);//标记后的图像namedWindow("2",CV_WINDOW_AUTOSIZE);imshow("2",src_gray);//原图cvWaitKey(0); return 0;}算法效果如下图所示:
阅读全文
0 0
- 广度优先的连通域计算
- 连通图里的深度优先和广度优先遍历
- 无向连通图的广度优先遍历算法
- 广度优先搜索写的连通区域标记算法
- [算法]广度优先求迷宫是否有出口,可用于求连通区域的数目
- 【Java】利用单链表遍历、队列通过广度优先搜索算法来求各个的连通分量
- 图的广度优先
- 广度优先搜索算法-计算最短距离
- C语言非连通图广度优先遍历
- 图的深度优先,广度优先
- 数的广度优先和深度优先
- 图的遍历-(深度优先&广度优先)
- 深度优先和广度优先的理解
- 图的深度优先和广度优先
- 图的遍历:深度优先、广度优先
- 广度优先搜索的思想
- 图的广度优先遍历
- 图的广度优先遍历
- 利用静态变量计算n的阶乘
- tomcat基本原理
- HDU
- 软件工程(C语言实践篇)学习心得总结
- 11-13 struts学习
- 广度优先的连通域计算
- SIM卡不识或者掉卡简单分析
- XGboost有关参数及其使用(PYTHON)
- 10个最佳的大数据处理编程语言
- 6.12
- 交叉编译(3)——交叉编译工具
- shell参数判断
- 使用maven将项目中的test代码打包进jar中
- 字符串函数模拟实现