OpenCV清除小面积连通域的实现方法

场景需求

使用OpenCV,往往遇到这类场景:需要清除目标图像中比较小的噪声区,保留主要区域信息。

特此分享自己写的一个简单的清除小面积连通域函数,逻辑比较简单,给大家留出了足够的发展空间,根据自身场景需求进行调整。

原理可以简单归结为:搜索图像的连通区轮廓->遍历各个连通区->基于阈值删除面积较小的连通区

运行速度方面,我没单独测试过这个单元,大家如果试过之后太慢可以评论告诉我哦~

反正平常我工作跑那种2000*2000的图像,这个函数的耗时几乎忽略不计。。。

C++实现代码

/**
* @brief  Clear_MicroConnected_Areas         清除微小面积连通区函数
* @param  src                                输入图像矩阵
* @param  dst                                输出结果
* @return min_area                           设定的最小面积清除阈值
*/
void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area)
{
	// 备份复制
	dst = src.clone();
	std::vector<std::vector<cv::Point> > contours;  // 创建轮廓容器
	std::vector<cv::Vec4i> 	hierarchy;  

	// 寻找轮廓的函数
	// 第四个参数CV_RETR_EXTERNAL,表示寻找最外围轮廓
	// 第五个参数CV_CHAIN_APPROX_NONE,表示保存物体边界上所有连续的轮廓点到contours向量内
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point());

	if (!contours.empty() && !hierarchy.empty())
	{
		std::vector<std::vector<cv::Point> >::const_iterator itc = contours.begin();
		// 遍历所有轮廓
		while (itc != contours.end())
		{
			// 定位当前轮廓所在位置
			cv::Rect rect = cv::boundingRect(cv::Mat(*itc));
			// contourArea函数计算连通区面积
			double area = contourArea(*itc);
			// 若面积小于设置的阈值
			if (area < min_area)
			{
				// 遍历轮廓所在位置所有像素点
				for (int i = rect.y; i < rect.y + rect.height; i++)
				{
					uchar *output_data = dst.ptr<uchar>(i);
					for (int j = rect.x; j < rect.x + rect.width; j++)
					{
						// 将连通区的值置0
						if (output_data[j] == 255)
						{
							output_data[j] = 0;
						}
					}
				}
			}
			itc++;
		}
	}
}

测试代码

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area);

int main(void)
{
	Mat A = Mat::zeros(500, 500, CV_8UC1);
	circle(A, Point2i(100, 100), 50, 255, -1);
	circle(A, Point2i(300, 400), 15, 255, -1);
	Mat B;
	Clear_MicroConnected_Areas(A, B, 1000);

	imshow("before:A", A);
	imshow("after:B", B);
	waitKey(0);

	system("pause");
	return 0;
}

void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area)
{
	// 备份复制
	dst = src.clone();
	std::vector<std::vector<cv::Point> > contours;  // 创建轮廓容器
	std::vector<cv::Vec4i> 	hierarchy;  

	// 寻找轮廓的函数
	// 第四个参数CV_RETR_EXTERNAL,表示寻找最外围轮廓
	// 第五个参数CV_CHAIN_APPROX_NONE,表示保存物体边界上所有连续的轮廓点到contours向量内
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point());

	if (!contours.empty() && !hierarchy.empty())
	{
		std::vector<std::vector<cv::Point> >::const_iterator itc = contours.begin();
		// 遍历所有轮廓
		while (itc != contours.end())
		{
			// 定位当前轮廓所在位置
			cv::Rect rect = cv::boundingRect(cv::Mat(*itc));
			// contourArea函数计算连通区面积
			double area = contourArea(*itc);
			// 若面积小于设置的阈值
			if (area < min_area)
			{
				// 遍历轮廓所在位置所有像素点
				for (int i = rect.y; i < rect.y + rect.height; i++)
				{
					uchar *output_data = dst.ptr<uchar>(i);
					for (int j = rect.x; j < rect.x + rect.width; j++)
					{
						// 将连通区的值置0
						if (output_data[j] == 255)
						{
							output_data[j] = 0;
						}
					}
				}
			}
			itc++;
		}
	}
}

测试效果

图1 处理前后图

到此这篇关于OpenCV-清除小面积连通域的文章就介绍到这了,更多相关OpenCV-清除小面积连通域内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 使用OpenCV去除面积较小的连通域

    这是后期补充的部分,和前期的代码不太一样 效果图 源代码 //测试 void CCutImageVS2013Dlg::OnBnClickedTestButton1() { vector<vector<Point> > contours; //轮廓数组 vector<Point2d> centers; //轮廓质心坐标 vector<vector<Point> >::iterator itr; //轮廓迭代器 vector<Point2d&g

  • OpenCV实现图像连通域

    图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,连通域分析是指在图像中寻找出彼此互相独立的连通域并将其标记出来. 一般情况下,一个连通域内只包含一个像素值,因此为了防止像素值波动对提取不同连通域的影响,连通域分析常处理的是二值化后的图像. 4-邻域和8-邻域: 常用的图像邻域分析法有两遍扫描法和种子填充法.两遍扫描法会遍历两次图像,第一次遍历图像时会给每一个非0像素赋予一个数字标签,当某个像素的上方和左侧邻域内的像素已经有数字标签时,取两者中的最小值作为当前像素的标签,否则赋予

  • 使用OpenCV获取图片连通域数量,并用不同颜色标记函

    一,原图和效果图 二,代码 //#########################产生随机颜色######################### cv::Scalar icvprGetRandomColor() { uchar r = 255 * (rand() / (1.0 + RAND_MAX)); uchar g = 255 * (rand() / (1.0 + RAND_MAX)); uchar b = 255 * (rand() / (1.0 + RAND_MAX)); return

  • OpenCV清除小面积连通域的实现方法

    场景需求 使用OpenCV,往往遇到这类场景:需要清除目标图像中比较小的噪声区,保留主要区域信息. 特此分享自己写的一个简单的清除小面积连通域函数,逻辑比较简单,给大家留出了足够的发展空间,根据自身场景需求进行调整. 原理可以简单归结为:搜索图像的连通区轮廓->遍历各个连通区->基于阈值删除面积较小的连通区 运行速度方面,我没单独测试过这个单元,大家如果试过之后太慢可以评论告诉我哦~ 反正平常我工作跑那种2000*2000的图像,这个函数的耗时几乎忽略不计... C++实现代码 /** * @

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

    一.对于二值图,0代表黑色,255代表白色.去除小连通区域与孔洞,小连通区域用8邻域,孔洞用4邻域. 函数名字为:void RemoveSmallRegion(Mat &Src, Mat &Dst,int AreaLimit, int CheckMode, int NeihborMode) CheckMode: 0代表去除黑区域,1代表去除白区域; NeihborMode:0代表4邻域,1代表8邻域; 如果去除小连通区域CheckMode=1,NeihborMode=1去除孔洞CheckM

  • Python OpenCV招商银行信用卡卡号识别的方法

    学在前面 从本篇博客起,我们将实际完成几个小案例,第一个就是银行卡号识别,预计本案例将写 5 篇左右的博客才可以完成,一起加油吧. 本文的目标是最终获取一套招商银行卡,0~9 数字的图,对于下图的数字,我们需要提取出来,便于后续模板匹配使用.不过下图中找到的数字不完整,需要找到尽量多的卡片,然后补齐这些数字. 提取卡片相关数字 先对上文中卡片中的数字进行相关提取操作,加载图片的灰度图,获取目标区域.在画板中模拟一下坐标区域,为了便于进行后续的操作. 具体代码如下: import cv2 as c

  • opencv实现机器视觉检测和计数的方法

    引言 在机器视觉中,有时需要对产品进行检测和计数.其难点无非是对于产品的图像分割. 由于之前网购的维生素片,有时候忘了今天有没有吃过,就想对瓶子里的药片计数...在学习opencv以后,希望实现对于维生素片分割计数算法.本次实战在基于形态学的基础上又衍生出基于距离变换的分水岭算法,使其实现的效果更具普遍性. 基于形态学的维生素片检测和计数 整体思路: 读取图片 形态学处理(在二值化前进行适度形态学处理,效果俱佳) 二值化 提取轮廓(进行药片分割) 获取轮廓索引,并筛选所需要的轮廓 画出轮廓,显示

  • 清除浏览器缓存的几种方法总结(必看)

    关于浏览器缓存 浏览器缓存,有时候我们需要他,因为他可以提高网站性能和浏览器速度,提高网站性能.但是有时候我们又不得不清除缓存,因为缓存可能误事,出现一些错误的数据.像股票类网站实时更新等,这样的网站是不要缓存的,像有的网站很少更新,有缓存还是比较好的.今天主要介绍清除缓存的几种方法. 清理网站缓存的几种方法 meta方法 //不缓存 <META HTTP-EQUIV="pragma" CONTENT="no-cache"> <META HTTP-

  • Java 语言实现清除带 html 标签的内容方法

    实例如下: public String stripHtml(String content) { // <p>段落替换为换行 content = content.replaceAll("<p .*?>", "\r\n"); // <br><br/>替换为换行 content = content.replaceAll("<br\\s*/?>", "\r\n"); // 去

  • python OpenCV学习笔记之绘制直方图的方法

    本篇文章主要介绍了python OpenCV学习笔记之绘制直方图的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 官方文档 – https://docs.opencv.org/3.4.0/d1/db7/tutorial_py_histogram_begins.html 直方图会让你对图像的强度分布有一个全面的认识.它是一个在x轴上带有像素值(从0到255,但不总是),在y轴上的图像中对应的像素数量的图. 这只是理解图像的另一种方式.通过观察图像的直方图,你可以直

  • opencv改变imshow窗口大小,窗口位置的方法

    如下所示: cv2.HoughLinesP cv2.namedWindow("enhanced",0); cv2.resizeWindow("enhanced", 640, 480); cv2.imshow("enhanced",lines) cv2.waitKey(0) 创建窗口时候改变下参数就可以鼠标随意拖动窗口改变大小啦 cv::namedWindow("camera", CV_WINDOW_NORMAL);//CV_W

  • python下的opencv画矩形和文字注释的实现方法

    画矩形 函数调用:cv2.rectangle(img,pt1,pt2,color,thickness,line_type,shift) img: 图像. pt1: 矩形的一个顶点. pt2: 矩形对角线上的另一个顶点 color: 线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image). thickness: 组成矩形的线条的粗细程度.取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形. line_type: 线条的类型.见cvLine的描述 shift: 坐标点的

随机推荐