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实现得到一个给定类的虚函数
Sep 28 Python
Python编程中的for循环语句学习教程
Oct 14 Python
Python内置数据结构与操作符的练习题集锦
Jul 01 Python
python绘制简单折线图代码示例
Dec 19 Python
python中的set实现不重复的排序原理
Jan 24 Python
Python定义二叉树及4种遍历方法实例详解
Jul 05 Python
python快排算法详解
Mar 04 Python
python删除列表元素的三种方法(remove,pop,del)
Jul 22 Python
python lambda表达式(匿名函数)写法解析
Sep 16 Python
pytorch 准备、训练和测试自己的图片数据的方法
Jan 10 Python
Python+Xlwings 删除Excel的行和列
Dec 19 Python
Python pandas求方差和标准差的方法实例
Aug 04 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简单封装了一些常用JS操作
2007/02/25 PHP
PHP写UltraEdit插件脚本实现方法
2011/12/26 PHP
php中判断文件空目录是否有读写权限的函数代码
2012/08/07 PHP
PHP输出XML到页面的3种方法详解
2013/06/06 PHP
smarty模板中拼接字符串的方法
2014/02/14 PHP
PHP PDOStatement对象bindpram()、bindvalue()和bindcolumn之间的区别
2014/11/20 PHP
PHP使用ffmpeg给视频增加字幕显示的方法
2015/03/12 PHP
JS获取scrollHeight问题想到的标准问题
2007/05/27 Javascript
JS Range HTML文档/文字内容选中、库及应用介绍
2011/05/12 Javascript
P3P Header解决Cookie跨域的问题
2013/03/12 Javascript
JavaScript中合并数组的N种方法
2014/09/16 Javascript
Javascript核心读书有感之语言核心
2015/02/01 Javascript
JS实现图片放大镜效果的方法
2015/02/27 Javascript
轻松实现javascript数据双向绑定
2015/11/11 Javascript
AngularJS自定义指令之复制指令实现方法
2017/05/18 Javascript
JS点击缩略图整屏居中放大图片效果
2017/07/04 Javascript
5分钟打造简易高效的webpack常用配置
2017/07/04 Javascript
Node.JS使用Sequelize操作MySQL的示例代码
2017/10/09 Javascript
详解NodeJs开发微信公众号
2018/05/25 NodeJs
Node.js学习教程之Module模块
2019/09/03 Javascript
Vue实现多页签组件
2021/01/14 Vue.js
[03:11]不朽宝藏三外观展示
2020/09/18 DOTA
Python中__init__和__new__的区别详解
2014/07/09 Python
Numpy数组转置的两种实现方法
2018/04/17 Python
opencv之为图像添加边界的方法示例
2019/12/26 Python
打包PyQt5应用时的注意事项
2020/02/14 Python
Python基于pandas爬取网页表格数据
2020/05/11 Python
Python collections模块的使用方法
2020/10/09 Python
森林防火宣传标语
2014/06/27 职场文书
珍惜资源的建议书
2014/08/26 职场文书
普通话演讲稿
2014/09/03 职场文书
2014年勤工助学工作总结
2014/11/24 职场文书
呼兰河传读书笔记
2015/06/30 职场文书
干货:企业内部人才推荐奖励方案!
2019/07/09 职场文书
Django模型层实现多表关系创建和多表操作
2021/07/21 Python
sql时间段切分实现每隔x分钟出一份高速门架车流量
2022/02/28 SQL Server