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中模拟enum枚举类型的5种方法分享
Nov 22 Python
python获取外网ip地址的方法总结
Jul 02 Python
python 换位密码算法的实例详解
Jul 19 Python
Pythony运维入门之Socket网络编程详解
Apr 15 Python
python 单线程和异步协程工作方式解析
Sep 28 Python
django使用xadmin的全局配置详解
Nov 15 Python
tensorflow 只恢复部分模型参数的实例
Jan 06 Python
Keras 实现加载预训练模型并冻结网络的层
Jun 15 Python
详解Python高阶函数
Aug 15 Python
搭建pypi私有仓库实现过程详解
Nov 25 Python
详解pandas赋值失败问题解决
Nov 29 Python
python飞机大战游戏实例讲解
Dec 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
总集篇&特番节目先行播出!《SAO Alicization War of Underworld》第2季度TV动画4月25日放送!
2020/03/06 日漫
php mssql 日期出现中文字符的解决方法
2009/03/10 PHP
php中mysql模块部分功能的简单封装
2011/09/30 PHP
zf框架的校验器使用使用示例(自定义校验器和校验器链)
2014/03/13 PHP
如何解决phpmyadmin导入数据库文件最大限制2048KB
2015/10/09 PHP
学习php设计模式 php实现门面模式(Facade)
2015/12/07 PHP
PHP基于imagick扩展实现合成图片的两种方法【附imagick扩展下载】
2017/11/14 PHP
PHP有序表查找之插值查找算法示例
2018/02/10 PHP
laravel 实现向公共模板中传值 (view composer)
2019/10/22 PHP
Javascript生成json的函数代码(可以用php的json_decode解码)
2012/06/11 Javascript
JS多物体 任意值 链式 缓冲运动
2012/08/10 Javascript
jQuery实现流动虚线框的方法
2015/01/29 Javascript
js中this用法实例详解
2015/05/05 Javascript
Javascript如何判断数据类型和数组类型
2016/06/22 Javascript
js方法数据验证的简单实例
2016/09/17 Javascript
jQuery插件jqGrid动态获取列和列字段的方法
2017/03/03 Javascript
微信小程序实现随机验证码功能
2018/12/20 Javascript
pm2启动ssr失败的解决方法
2019/06/29 Javascript
js针对图片加载失败的处理方法分析
2019/08/24 Javascript
vue 组件基础知识总结
2021/01/26 Vue.js
JS实现百度搜索框
2021/02/25 Javascript
Python 闭包的使用方法
2017/09/07 Python
Python实现的读取电脑硬件信息功能示例
2018/05/30 Python
python suds访问webservice服务实现
2020/06/26 Python
Python3爬虫中pyspider的安装步骤
2020/07/29 Python
CAT鞋英国官网:坚固耐用的靴子和鞋
2016/10/21 全球购物
欧舒丹澳洲版:L’OCCITANE
2017/07/17 全球购物
大学应届毕业生个人求职信
2013/09/23 职场文书
社区网格化管理实施方案
2014/03/21 职场文书
毕业评语大全
2014/05/04 职场文书
毕业生工作求职信
2014/06/30 职场文书
2015年农村党员干部主题教育活动总结
2015/03/25 职场文书
项目合作意向书
2015/05/08 职场文书
体育部部长竞选稿
2015/11/21 职场文书
python3实现Dijkstra算法最短路径的实现
2021/05/12 Python
python在package下继续嵌套一个package
2022/04/14 Python