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脚本实现统计日志文件中的ip访问次数代码分享
Aug 06 Python
实现python版本的按任意键继续/退出
Sep 26 Python
利用Python循环(包括while&amp;for)各种打印九九乘法表的实例
Nov 06 Python
python引入不同文件夹下的自定义模块方法
Oct 27 Python
Python实现FM算法解析
Jun 18 Python
django框架model orM使用字典作为参数,保存数据的方法分析
Jun 24 Python
Python 内置函数globals()和locals()对比详解
Dec 23 Python
Python基础之函数基本用法与进阶详解
Jan 02 Python
Python基础之字符串常见操作经典实例详解
Feb 26 Python
django form和field具体方法和属性说明
Jul 09 Python
python调用摄像头的示例代码
Sep 28 Python
Python合并多张图片成PDF
Jun 09 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把数字转成人民币大写的函数分享
2014/06/30 PHP
php基于mcrypt的加密解密实例
2014/10/27 PHP
jQuery对象和DOM对象使用说明
2010/06/25 Javascript
Javascript控制页面链接在新窗口打开具体方法
2013/08/16 Javascript
将JavaScript的jQuery库中表单转化为JSON对象的方法
2015/11/17 Javascript
基于html5和nodejs相结合实现websocket即使通讯
2015/11/19 NodeJs
Treegrid的动态加载实例代码
2016/04/29 Javascript
NodeJS连接MongoDB数据库时报错的快速解决方法
2016/05/13 NodeJs
基于JavaScript实现熔岩灯效果导航菜单
2017/01/04 Javascript
微信小程序 数据封装,参数传值等经验分享
2017/01/09 Javascript
原生JS京东轮播图代码
2017/03/22 Javascript
jquery图片放大镜效果
2017/06/23 jQuery
js图片轮播插件的封装
2017/07/21 Javascript
基于jQuery实现定位导航位置效果
2017/11/15 jQuery
node 命令方式启动修改端口的方法
2018/05/12 Javascript
vue动画效果实现方法示例
2019/03/18 Javascript
vue如何搭建多页面多系统应用
2020/06/17 Javascript
Python中的XML库4Suite Server的介绍
2015/04/14 Python
python列出目录下指定文件与子目录的方法
2015/07/03 Python
Python实现截屏的函数
2015/07/25 Python
Python IDE PyCharm的基本快捷键和配置简介
2015/11/04 Python
利用python如何处理百万条数据(适用java新手)
2018/06/06 Python
利用pyinstaller打包exe文件的基本教程
2019/05/02 Python
python日期相关操作实例小结
2019/06/24 Python
简单分析python的类变量、实例变量
2019/08/23 Python
python应用文件读取与登录注册功能
2019/09/23 Python
python itsdangerous模块的具体使用方法
2020/02/17 Python
Python读取yaml文件的详细教程
2020/07/21 Python
恒华伟业笔试面试题
2015/02/26 面试题
基层党建工作宣传标语
2014/06/24 职场文书
医德医风自我评价
2014/09/19 职场文书
夫妻吵架保证书
2015/05/08 职场文书
2016新春团拜会致辞
2015/08/01 职场文书
法制主题班会教案
2015/08/13 职场文书
公司岗位说明书
2015/10/08 职场文书
Redis实现短信验证码登录的示例代码
2022/06/14 Redis