opencv bfs测试程序

不记得代码是从哪里来的了,代码功能:使用BFS标记连通域个数
想了一下bfs和dfs实现时的区别在于使用的数据结构不一样,BFS使用Queue,先入先出(FIFO)便于广度优先遍历,DFS使用stack,后入先出(LIFO)便于深度优先遍历。

#include <opencv2/opencv.hpp>  
#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 255

typedef 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;
}

参考输入图片如下:
opencv bfs测试程序
程序执行输出:
opencv bfs测试程序

上一篇:【ybtoj高效进阶 21272】生命游戏(bfs)(二分)


下一篇:求细胞数量