OPENCV去除小连通区域,去除孔洞的实例讲解


Posted in Python onJune 21, 2018

一、对于二值图,0代表黑色,255代表白色。去除小连通区域与孔洞,小连通区域用8邻域,孔洞用4邻域。

OPENCV去除小连通区域,去除孔洞的实例讲解

函数名字为:void RemoveSmallRegion(Mat &Src, Mat &Dst,int AreaLimit, int CheckMode, int NeihborMode)

CheckMode: 0代表去除黑区域,1代表去除白区域; NeihborMode:0代表4邻域,1代表8邻域;

如果去除小连通区域CheckMode=1,NeihborMode=1去除孔洞CheckMode=0,NeihborMode=0

记录每个像素点检验状态的标签,0代表未检查,1代表正在检查,2代表检查不合格(需要反转颜色),3代表检查合格或不需检查 。

1.先对整个图像扫描,如果是去除小连通区域,则将黑色的背景图作为合格,像素值标记为3,如果是去除孔洞,则将白色的色素点作为合格,像素值标记为3。

2.扫面整个图像,对图像进行处理。

void RemoveSmallRegion(Mat &Src, Mat &Dst,int AreaLimit, int CheckMode, int NeihborMode)
{
	int RemoveCount = 0;
	//新建一幅标签图像初始化为0像素点,为了记录每个像素点检验状态的标签,0代表未检查,1代表正在检查,2代表检查不合格(需要反转颜色),3代表检查合格或不需检查 
	//初始化的图像全部为0,未检查
	Mat PointLabel = Mat::zeros(Src.size(), CV_8UC1);
	if (CheckMode == 1)//去除小连通区域的白色点
	{
		cout << "去除小连通域.";
		for (int i = 0; i < Src.rows; i++)
		{
			for (int j = 0; j < Src.cols; j++)
			{
				if (Src.at<uchar>(i, j) < 10)
				{
					PointLabel.at<uchar>(i, j) = 3;//将背景黑色点标记为合格,像素为3
				}
			}
		}
	}
	else//去除孔洞,黑色点像素
	{
		cout << "去除孔洞";
		for (int i = 0; i < Src.rows; i++)
		{
			for (int j = 0; j < Src.cols; j++)
			{
				if (Src.at<uchar>(i, j) > 10)
				{
					PointLabel.at<uchar>(i, j) = 3;//如果原图是白色区域,标记为合格,像素为3
				}
			}
		}
	}


	vector<Point2i>NeihborPos;//将邻域压进容器
	NeihborPos.push_back(Point2i(-1, 0));
	NeihborPos.push_back(Point2i(1, 0));
	NeihborPos.push_back(Point2i(0, -1));
	NeihborPos.push_back(Point2i(0, 1));
	if (NeihborMode == 1)
	{
		cout << "Neighbor mode: 8邻域." << endl;
		NeihborPos.push_back(Point2i(-1, -1));
		NeihborPos.push_back(Point2i(-1, 1));
		NeihborPos.push_back(Point2i(1, -1));
		NeihborPos.push_back(Point2i(1, 1));
	}
	else cout << "Neighbor mode: 4邻域." << endl;
	int NeihborCount = 4 + 4 * NeihborMode;
	int CurrX = 0, CurrY = 0;
	//开始检测
	for (int i = 0; i < Src.rows; i++)
	{
		for (int j = 0; j < Src.cols; j++)
		{
			if (PointLabel.at<uchar>(i, j) == 0)//标签图像像素点为0,表示还未检查的不合格点
			{ //开始检查
				vector<Point2i>GrowBuffer;//记录检查像素点的个数
				GrowBuffer.push_back(Point2i(j, i));
				PointLabel.at<uchar>(i, j) = 1;//标记为正在检查
				int CheckResult = 0;


				for (int z = 0; z < GrowBuffer.size(); z++)
				{
					for (int q = 0; q < NeihborCount; q++)
					{
						CurrX = GrowBuffer.at(z).x + NeihborPos.at(q).x;
						CurrY = GrowBuffer.at(z).y + NeihborPos.at(q).y;
						if (CurrX >= 0 && CurrX<Src.cols&&CurrY >= 0 && CurrY<Src.rows) //防止越界 
						{
							if (PointLabel.at<uchar>(CurrY, CurrX) == 0)
							{
								GrowBuffer.push_back(Point2i(CurrX, CurrY)); //邻域点加入buffer 
								PointLabel.at<uchar>(CurrY, CurrX) = 1;   //更新邻域点的检查标签,避免重复检查 
							}
						}
					}
				}
				if (GrowBuffer.size()>AreaLimit) //判断结果(是否超出限定的大小),1为未超出,2为超出 
					CheckResult = 2;
				else
				{
					CheckResult = 1;
					RemoveCount++;//记录有多少区域被去除
				}


				for (int z = 0; z < GrowBuffer.size(); z++)
				{
					CurrX = GrowBuffer.at(z).x;
					CurrY = GrowBuffer.at(z).y;
					PointLabel.at<uchar>(CurrY,CurrX)+=CheckResult;//标记不合格的像素点,像素值为2
				}
				//********结束该点处的检查********** 


			}
		}


	}


	CheckMode = 255 * (1 - CheckMode);
	//开始反转面积过小的区域 
	for (int i = 0; i < Src.rows; ++i)
	{
		for (int j = 0; j < Src.cols; ++j)
		{
			if (PointLabel.at<uchar>(i,j)==2)
			{
				Dst.at<uchar>(i, j) = CheckMode;
			}
			else if (PointLabel.at<uchar>(i, j) == 3)
			{
				Dst.at<uchar>(i, j) = Src.at<uchar>(i, j);
				
			}
		}
	}
	cout << RemoveCount << " objects removed." << endl;
}

调用函数:dst是原来的二值图。

Mat erzhi1 = Mat::zeros(srcImage.rows, srcImage.cols, CV_8UC1);
RemoveSmallRegion(dst, erzhi,100, 1, 1);
RemoveSmallRegion(erzhi, erzhi,100, 0, 0);
imshow("erzhi1", erzhi);

OPENCV去除小连通区域,去除孔洞的实例讲解

和之前的图像相比

OPENCV去除小连通区域,去除孔洞的实例讲解

以上这篇OPENCV去除小连通区域,去除孔洞的实例讲解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中实现对Timestamp和Datetime及UTC时间之间的转换
Apr 08 Python
Python用list或dict字段模式读取文件的方法
Jan 10 Python
Scrapy的简单使用教程
Oct 24 Python
python利用smtplib实现QQ邮箱发送邮件
May 20 Python
Django后台admin的使用详解
Jul 08 Python
python读写csv文件并增加行列的实例代码
Aug 01 Python
python os.fork() 循环输出方法
Aug 08 Python
Tensorflow tf.nn.depthwise_conv2d如何实现深度卷积的
Apr 20 Python
Python爬虫谷歌Chrome F12抓包过程原理解析
Jun 04 Python
Python调用.net动态库实现过程解析
Jun 05 Python
django models里数据表插入数据id自增操作
Jul 15 Python
Python pickle模块常用方法代码实例
Oct 10 Python
python读取文本绘制动态速度曲线
Jun 21 #Python
python实现可视化动态CPU性能监控
Jun 21 #Python
python实时监控cpu小工具
Jun 21 #Python
python实现监控某个服务 服务崩溃即发送邮件报告
Jun 21 #Python
python实现简易内存监控
Jun 21 #Python
Python实现的微信好友数据分析功能示例
Jun 21 #Python
python skimage 连通性区域检测方法
Jun 21 #Python
You might like
聊天室php&amp;mysql(一)
2006/10/09 PHP
php开启安全模式后禁用的函数集合
2011/06/26 PHP
thinkPHP查询方式小结
2016/01/09 PHP
php-7.3.6 编译安装过程
2020/02/11 PHP
Javascript 网页水印(非图片水印)实现代码
2010/03/01 Javascript
js调用打印机打印网页字体总是缩小一号的解决方法
2014/01/24 Javascript
原生js获取宽高与jquery获取宽高的方法关系对比
2014/04/04 Javascript
jQuery学习笔记之 Ajax操作篇(一) - 数据加载
2014/06/23 Javascript
Windows8下搭建Node.js开发环境教程
2014/09/03 Javascript
JavaScript检测实例属性, 原型属性
2015/02/04 Javascript
nodejs中实现阻塞实例
2015/03/24 NodeJs
解析javascript瀑布流原理实现图片滚动加载
2016/03/10 Javascript
jQuery+Ajax实现限制查询间隔的方法
2016/06/07 Javascript
bootstrap实现点击删除按钮弹出确认框的实例代码
2018/08/16 Javascript
利用JS动态生成隔行换色HTML表格的两种方法
2018/10/09 Javascript
微信开发之微信jssdk录音功能开发示例
2018/10/22 Javascript
详解vantUI框架在vue项目中的应用踩坑
2018/12/06 Javascript
详解vue高级特性
2020/06/09 Javascript
[04:53]DOTA2英雄基础教程 祈求者
2014/01/03 DOTA
[01:21]DOTA2 新英雄 森海飞霞
2020/12/18 DOTA
python查找第k小元素代码分享
2013/12/18 Python
详解Python的Django框架中的中间件
2015/07/24 Python
用Python解决计数原理问题的方法
2016/08/04 Python
python读取文件名称生成list的方法
2018/04/27 Python
对python requests的content和text方法的区别详解
2018/10/11 Python
使用coverage统计python web项目代码覆盖率的方法详解
2019/08/05 Python
浅谈Python_Openpyxl使用(最全总结)
2019/09/05 Python
python装饰器练习题及答案
2019/11/01 Python
Python tkinter三种布局实例详解
2020/01/06 Python
什么是数据库锁?Oracle中都有哪些类型的锁?
2015/08/21 面试题
学校爱国卫生月活动总结
2014/06/25 职场文书
植树节标语
2014/06/27 职场文书
护士医德医风自我评价
2014/09/15 职场文书
试用期辞职信范文
2015/03/02 职场文书
SpringBoot中获取profile的方法详解
2022/04/08 Java/Android
postgreSQL数据库基础知识介绍
2022/04/12 PostgreSQL