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使用rabbitmq实现网络爬虫示例
Feb 20 Python
使用Django的模版来配合字符串翻译工作
Jul 27 Python
用Python将结果保存为xlsx的方法
Jan 28 Python
python 实现提取某个索引中某个时间段的数据方法
Feb 01 Python
Python提取支付宝和微信支付二维码的示例代码
Feb 15 Python
python命令行工具Click快速掌握
Jul 04 Python
基于Python中的yield表达式介绍
Nov 19 Python
关于pandas的离散化,面元划分详解
Nov 22 Python
Python3打包exe代码2种方法实例解析
Feb 17 Python
Python3标准库glob文件名模式匹配的问题
Mar 13 Python
django执行数据库查询之后实现返回的结果集转json
Mar 31 Python
python 对象真假值的实例(哪些视为False)
Dec 11 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
windows下PHP APACHE MYSQ完整配置
2007/01/02 PHP
逆序二维数组插入一元素的php代码
2012/06/08 PHP
浅析PHP微信支付通知的处理方式
2014/05/25 PHP
PHP5多态性与动态绑定介绍
2015/04/03 PHP
详解PHP 7.4 中数组延展操作符语法知识点
2019/07/19 PHP
Zero Clipboard js+swf实现的复制功能使用方法
2010/03/07 Javascript
Jquery网页内滑动缓冲导航的实现代码
2015/04/05 Javascript
JavaScript实现基于十进制的四舍五入实例
2015/07/17 Javascript
谈谈JSON对象和字符串之间的相互转换JSON.stringify(obj)和JSON.parse(string)
2015/10/01 Javascript
Javascript数组Array方法解读
2016/03/13 Javascript
微信小程序 开发工具快捷键整理
2016/10/31 Javascript
理解AngularJs篇:30分钟快速掌握AngularJs
2016/12/23 Javascript
一个例子轻松学会Vue.js
2017/01/02 Javascript
react学习笔记之state以及setState的使用
2017/12/07 Javascript
手挽手带你学React之React-router4.x的使用
2019/02/14 Javascript
vue-mugen-scroll组件实现pc端滚动刷新
2019/08/16 Javascript
Python中捕捉详细异常信息的代码示例
2014/09/18 Python
跟老齐学Python之玩转字符串(2)更新篇
2014/09/28 Python
Python的设计模式编程入门指南
2015/04/02 Python
Python编程中实现迭代器的一些技巧小结
2016/06/21 Python
python写日志文件操作类与应用示例
2019/07/01 Python
Python 中list ,set,dict的大规模查找效率对比详解
2019/10/11 Python
opencv3/C++图像像素操作详解
2019/12/10 Python
html5应用缓存_动力节点Java学院整理
2017/07/13 HTML / CSS
澳大利亚领先的武术用品和健身器材供应商:SMAI
2019/03/24 全球购物
介绍JAVA 中的Collection FrameWork(及如何写自己的数据结构)
2014/10/31 面试题
办公室副主任职责范本
2014/03/08 职场文书
《诚实与信任》教学反思
2014/04/10 职场文书
运动会口号16字
2014/06/07 职场文书
助学感谢信范文
2015/01/21 职场文书
幼师大班个人总结
2015/02/13 职场文书
物业前台接待岗位职责
2015/04/03 职场文书
幼儿园园务工作总结2015
2015/05/18 职场文书
Python办公自动化之教你如何用Python将任意文件转为PDF格式
2021/06/28 Python
浅谈克隆 JavaScript
2021/11/02 Javascript
游戏《我的世界》澄清Xbox版暂无计划加入光追
2022/04/03 其他游戏