【OpenCV】8邻域种子填充法剔除短连通域的高效算法

//本文档参考种子填充算法描述及C++代码实现(https://www.bbsmax.com/A/amd0AVWzge/)讲解的原理,实现快速种子填充算法,运行效果高。
//具体功能如下:依次扫描每个像素,检测8领域,寻找连通域,删掉面积小于阈值的。
#include <opencv2/opencv.hpp>
#include <cv.h>

using namespace cv;
using namespace std;

#define IMG_MARGIN_GAP_SIZE			3
#define IMG_MINIMUM_ALGO_AREA		30   //保留连通域的面积下限
#define POSITION_OFFSET_SIZE	    8    //8邻域
#define MAX_STK_BIRD_SIZE           4000
#define INIMG_WIDTH                 300
#define INIMG_HEIGHT                720
int position_offset[POSITION_OFFSET_SIZE] = {-INIMG_WIDTH, -INIMG_WIDTH-1,-1, INIMG_WIDTH-1, INIMG_WIDTH, INIMG_WIDTH+1, 1, -INIMG_WIDTH+1};

int init_stk[MAX_STK_BIRD_SIZE];

void SeedFillAlgorithm(Mat &inImg, Mat &outImg) {
	int i, j, k, p, pp;
	uchar *bdata, *bdata_tmp, *cdata; 
	int *stk, stkN; 

	bdata = inImg.data; 
	bdata_tmp = inImg.data + INIMG_WIDTH * (INIMG_HEIGHT-IMG_MARGIN_GAP_SIZE); 
	for (i = 0; i < IMG_MARGIN_GAP_SIZE; i++) 
	{
		for (j = 0; j < INIMG_WIDTH; j++) 
		{
			*bdata++ = *bdata_tmp++ = 0;   //把图像上下边界3像素宽度范围内像素置为0
		}
	}
	bdata_tmp = inImg.data + (INIMG_WIDTH -1)*IMG_MARGIN_GAP_SIZE; 
	for (i = INIMG_HEIGHT-2*IMG_MARGIN_GAP_SIZE; i > 0; i--) 
	{
		for (j = 0; j < (IMG_MARGIN_GAP_SIZE*2); j++) 
		{
			bdata_tmp[j] = 0;              //把图像左右边界3像素宽度范围内的像素置为0
		}
		bdata_tmp += INIMG_WIDTH; 
	}

	cdata = outImg.data; 
	memset(cdata, 0, sizeof(uchar)*INIMG_HEIGHT*INIMG_WIDTH);

	//需要为stk分配空间!
	stk = init_stk;   //memset(stk, 0, sizeof(int)*MAX_STK_BIRD_SIZE);
	

	bdata = inImg.data; 
	for (i = INIMG_WIDTH*IMG_MARGIN_GAP_SIZE; i < INIMG_WIDTH*(INIMG_HEIGHT-IMG_MARGIN_GAP_SIZE); i++)  
	{
		if (bdata[i] == 0) continue; 
		bdata[i] = 0; 
		stk[0] = i; 
		k = 0; 
		stkN = 1; 
		while (1) 
		{
			p = stk[k++]; 
			for (j = POSITION_OFFSET_SIZE-1; j >= 0; j--) 
			{
				pp = p + position_offset[j]; 
				if (bdata[pp] == 0) continue; 
				bdata[pp] = 0; 
				stk[stkN++] = pp; 
			}
			if (k >= stkN) break; 
			if (stkN >= (MAX_STK_BIRD_SIZE-POSITION_OFFSET_SIZE)) break; 
		}
		if (stkN <= IMG_MINIMUM_ALGO_AREA) continue;   //如果8邻域联通总数小于设置的最小面积阈值,不保留。
		for (k = stkN - 1; k >= 0; k--) 
		{
			p = stk[k]; cdata[p] = 1; 
		}
	}
}

//把只有0/1取值的二值图转为0/255取值的二值图
static void binary2To255(Mat &img)
{
	for (int i=0;i<img.rows;i++)	
	{
		for (int j=0;j<img.cols;j++)	
		{
			if (img.data[i*img.cols + j] > 0)	
				img.data[i*img.cols + j] = 255;
		}
	}	
}

int main()
{
	Mat srcImg = imread("G:\\binaryImg\\image1.bmp", 0);
	imshow("in", srcImg);

	Mat dstImg(srcImg.rows, srcImg.cols, CV_8UC1, Scalar(0));;
	SeedFillAlgorithm(srcImg, dstImg);
	binary2To255(dstImg);

	imshow("out", dstImg);
	waitKey(0);

	return 0;
}

处理结果如下: 

 

 

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值