OpenCV清除小面积连通域的实现方法
作者:翟天保Steven 时间:2023-11-16 03:58:25
场景需求
使用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 处理前后图
来源:https://zhaitianbao.blog.csdn.net/article/details/116152311
标签:OpenCV,清除,小面积,连通域
0
投稿
猜你喜欢
vue.js中toast用法及使用toast弹框的实例代码
2024-05-08 09:33:02
Web 前端优化最佳实践之 Cookie 篇
2008-06-25 13:00:00
Golang 函数执行时间统计装饰器的一个实现详解
2024-05-09 09:46:22
opencv-python基本图像处理详解
2021-07-07 04:37:02
Python matplotlib绘制图形实例(包括点,曲线,注释和箭头)
2021-08-31 22:57:06
Python中的变量赋值
2023-07-23 06:00:10
python脚本实现统计日志文件中的ip访问次数代码分享
2021-03-17 08:40:08
MySQL利用索引优化ORDER BY排序语句的方法
2024-01-24 00:19:34
详解python实现可视化的MD5、sha256哈希加密小工具
2021-05-31 15:02:34
Go语言使用Etcd实现分布式锁
2024-04-23 09:37:33
Oracle 管道 解决Exp/Imp大量数据处理问题
2024-01-21 22:15:16
OBJECTPROPERTY与sp_rename更改对象名称的介绍
2012-01-29 18:04:39
Python获取本机所有网卡ip,掩码和广播地址实例代码
2021-06-26 20:32:17
PyQt5 QThread倒计时功能的实现代码
2021-08-02 06:00:28
Python使用 Beanstalkd 做异步任务处理的方法
2021-01-06 18:18:19
带你了解Python妙开根号的三种方式
2021-10-18 08:27:56
Python爬虫之Spider类用法简单介绍
2023-04-23 15:03:27
python入门基础之用户输入与模块初认识
2022-08-13 01:10:21
Python3 Random模块代码详解
2023-04-11 01:36:20
jQuery 1.3.3 新功能[译]
2009-06-04 12:23:00