您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
小编给大家分享一下OpenCV如何清除小面积连通域,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
使用OpenCV,往往遇到这类场景:需要清除目标图像中比较小的噪声区,保留主要区域信息。
特此分享自己写的一个简单的清除小面积连通域函数,逻辑比较简单,给大家留出了足够的发展空间,根据自身场景需求进行调整。
原理可以简单归结为:搜索图像的连通区轮廓->遍历各个连通区->基于阈值删除面积较小的连通区
运行速度方面,我没单独测试过这个单元,大家如果试过之后太慢可以评论告诉我哦~
反正平常我工作跑那种2000*2000的图像,这个函数的耗时几乎忽略不计。。。
/** * @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++; } } }
测试效果
以上是“OpenCV如何清除小面积连通域”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。