opencv#37 形态学操作——腐蚀

图像腐蚀目的

·去除图像中微小物体

·分离较近的两个物体

我们对图像中所有米粒进行二值化处理,之后进行连通域分割以求去整个图像中共用多少米粒,处理结果在可以发现,在上图中有一小块区域上有个小点(非米粒),也被视为有数值的情况 。通过图像腐蚀操作就可以将这个微笑区域腐蚀掉,从而得到正确结果。

若图像中有两个非常近的圆,这两个圆在像素中并没有连接在一起,但是由于像素离得近,有可能会误认为两个区域为一个区域,那么通过图像腐蚀,就可以将这两个物体尽可能拉大距离,从而较为明显的去分割出两个物体。

图像腐蚀原理

首先给出一个结构元素,结构元素可以任意指定,这里以十字型结构为例,图像的腐蚀常用于对二值化的图像进行处理, 将此结构元素放置在原图像中像素值为1的区域,我们将结构元素的中心像素放在A区域,得到如下形式:

我们可以看到有部分元素被结构元素覆盖,还有部分元素没有被覆盖,这种情况我们就将像素A删除,之后将结构元素平移,如下:

同样还有没有被结构元素覆盖的情况,因此也许要将此像素1删除,依次进行此操作,可以看到当把结构元素放置到B时,能够把所有像素进行覆盖,那么此时就保留B,将像素B 放置在腐蚀结果中 。

依次移动结构元素,将结构元素的中心依次覆盖在原图像中所有非0像素中,那么最终可得到右图所示腐蚀后结果。整个图像腐蚀操作是一个并行运算的程序。

结构元素生成函数

getStructuringElement() 

void cv::getStructuringElement(Int   shape,Size  ksize,Point anchor = Point(-1,-1))

·shape:结构元素的种类。

·ksize:结构元素的尺寸大小。

·anchor:中心点的位置,默认参数为结构元素的几何中心。

图像腐蚀操作函数

erode() 

void cv::erode(InputArray    src,OutputArray   dst,InputArray    kernel,Point         anchor = Point(-1,-1),int           iterations = 1,int           borderType = BORDER_CONSTANT,const Scalar & borderValue = morphologyDefaultBorderValue())

·src:输入的待腐蚀图像,图像的通道数可以是任意的,但是图像的数据类型必须是CV_8U,CV_16U,CV_16S,CV_32F,CV_64F之一。

·dst:腐蚀后的输出图像,与输入图像src具有相同的尺寸和数据类型。

·kernel:用于腐蚀操作的结构元素,可以自己输入,也可以用getStructuringElement()函数生成。

·anchor:中心点在结构元素中的位置,默认参数为结构元素的几何中心点。

·iterations:腐蚀的次数。默认情况是腐蚀1次。

·borderType:像素外推法选择标志。

·borderValue:边界不变的边界值。若图像尺寸较小,要额外注意最后两个参数的选择。

示例
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>using namespace cv; //opencv的命名空间
using namespace std;//绘制包含区域函数
void drawState(Mat &img, int number, Mat centroids, Mat stats, String str) 
{RNG rng(10086); //RNG用来生成随机数,这里用了10086进行初始化。vector<Vec3b> colors; //vector是一个能够存放任意类型的动态数组,Vec3b可以看成vector<uchar,3>,即一个uchar类型,长度为3的vector向量(简单地说,就是一个uchar类型的数组,长度为3).for (int i = 0; i < number; i++);{//使用均匀分布的随机数确定颜色;rng.uniform(),可以生成指定范围的均匀分布的随机数Vec3b vec3 = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));colors.push_back(vec3);}//以不同的颜色标记出不同的连通域for (int i = 1; i < number; i++){//中心位置int center_x = centroids.at<double>(i, 0);int center_y = centroids.at<double>(i, 1);//矩形边框int x = stats.at<int>(i, CC_STAT_LEFT);int y = stats.at<int>(i, CC_STAT_TOP);int w = stats.at<int>(i, CC_STAT_WIDTH);int h = stats.at<int>(i, CC_STAT_HEIGHT);//中心位置绘制circle(img, Point(center_x, center_y), 2, Scalar(0, 255, 0), 2, 8, 0);//外接矩形Rect rect(x, y, w, h);rectangle(img, rect, colors[i], 1, 8, 0);putText(img, format("%d", i), Point(center_x, center_y), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 1);}imshow(str, img);
}//主函数
int main()
{//生成用于腐蚀的原图像Mat src = (Mat_<uchar>(6, 6) << 0, 0, 0, 0, 255, 0,0, 255, 255, 255, 255, 255,0, 255, 255, 255, 255, 0,0, 255, 255, 255, 255, 0,0, 255, 255, 255, 255, 0,0, 0, 0, 0, 0, 0);Mat struct1, struct2;struct1 = getStructuringElement(0, Size(3, 3));//矩形结构元素struct2 = getStructuringElement(1, Size(3, 3));//十字型结构元素Mat erodeSrc; //存放腐蚀后的图像erode(src, erodeSrc, struct2);namedWindow("src", WINDOW_GUI_NORMAL);namedWindow("erodeSrc", WINDOW_GUI_NORMAL);imshow("src", src);imshow("erodeSrc", erodeSrc);cout << "文字腐蚀验证" << endl;waitKey(0);//等待函数用于显示图像,按下键盘任意键后退出Mat LearnCV_black = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/LearnCV_black.png");Mat erode_black1, erode_black2;//黑背景图像腐蚀erode(LearnCV_black, erode_black1, struct1);erode(LearnCV_black, erode_black2, struct2);imshow("LearnCV_black", LearnCV_black);imshow("erode_balck1", erode_black1);imshow("erode_black2", erode_black2);cout << "验证腐蚀对小连通域的去除" << endl;waitKey(0);//等待函数用于显示图像,按下键盘任意键后退出Mat img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/hua.jpeg");if (img.empty()){cout << "请检查图像文件名称是否正确" << endl;return -1;}Mat img2;copyTo(img, img2, img); //克隆一个单独的图像,用于后期图像检测Mat hua, huaBW;//把图像转为二值图像,用于统计连通域cvtColor(img, hua, COLOR_BGR2GRAY);threshold(hua, huaBW, 50, 255, THRESH_BINARY);Mat out, stats, centroids;//统计图像中连通域的个数int number = connectedComponentsWithStats(huaBW, out, stats, centroids, 8, CV_16U);drawState(img, number, centroids, stats, "未腐蚀时统计连通域");//绘制图像erode(huaBW, huaBW, struct1);//对图像矩形腐蚀number = connectedComponentsWithStats(huaBW, out, stats, centroids, 8, CV_16U);drawState(img2, number, centroids, stats, "腐蚀后统计连通域"); //绘制图像waitKey(0);//等待函数用于显示图像,按下键盘任意键后退出return 0;}
结果

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/655129.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kotlin快速入门系列7

Kotlin的数据类、密封类、枚举类 数据类 与Java等语言不同&#xff0c;kotlin创建只包含数据的类时&#xff0c;需要在类名前声明关键字&#xff1a;data。 data class KotlinBean (val brand : String) 在kotlin中&#xff0c;编译器会自动的从主构造函数中根据所有声明的…

GMS测试Checklistfail---M37+M56+M58+无负一屏

问题&#xff1a; 1.M37 测试Fail ,"Nearby Share" 在edit菜单中,("Nearby Share" 需要on the first or second page)&#xff1b; 2.M56 测试Fail, 无"monochrome icons”&#xff1b; 3.M58 测试Fail, "Scan QR Code"置灰(已更新所以apk…

RabbitMQ-如何保证消息不丢失

RabbitMQ常用于 异步发送&#xff0c;mysql&#xff0c;redis&#xff0c;es之间的数据同步 &#xff0c;分布式事务&#xff0c;削峰填谷等..... 在微服务中&#xff0c;rabbitmq是我们经常用到的消息中间件。它能够异步的在各个业务之中进行消息的接受和发送&#xff0c;那么…

档案数字化转型面临问题

档案数字化转型面临以下问题&#xff1a; 1. 技术问题&#xff1a;档案数字化需要借助先进的技术手段和设备&#xff0c;包括扫描仪、存储设备和数据管理软件等。这些技术的成本高、操作复杂&#xff0c;需要专业的人员进行操作和维护。 2. 安全问题&#xff1a;档案数字化后的…

【Java程序设计】【C00176】基于SSM的图书管理系统(论文+PPT)

基于SSM的图书管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的图书管理系统 本系统分为前台系统、后台管理员以及后台学员3个功能模块。 前台系统&#xff1a;当游客打开系统的网址后&#xff0c;首先看到的就…

gmsh 01 对多个面,及体进行剖分

#include <set> #include <cmath> #include <gmsh.h>#include <iostream>int main(int argc, char** argv) {gmsh::initialize(argc, argv); // 初始化gmsh::model::add("t2"); // 创建 t2 modeldouble lc 0.05; gmsh::model::geo::add…

二手交易|校园二手交易小程序|基于微信小程序的闲置物品交易平台设计与实现(源码+数据库+文档)

校园二手交易小程序目录 目录 基于微信小程序的闲置物品交易平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、商品信息管理 3、公告信息管理 4、论坛信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕…

斜率优化dp模型整理

300. 任务安排1&#xff08;300. 任务安排1 - AcWing题库&#xff09; 思路&#xff1a;很明显这些任务是按顺序排好的&#xff0c;我们能执行的操作只是对它们进行分批&#xff0c;我们可以发现每一批之前的开始时间s&#xff0c;影响的不仅仅是当前这一批的结束时间&#xff…

JavaScript变量-注意事项-for循环

变量 1.目标 掌握变量的概念以及基本使用 ​ 变量&#xff1a;就是一个容器, 可以存放数据 2.实现思路 使用var关键字 声明一个变量使用 给变量赋值 3.代码实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"&…

8.6跳跃游戏②(LC45-M)

算法&#xff1a; 与上一题一样&#xff0c;还是看最大覆盖范围 要从覆盖范围出发&#xff0c;不管怎么跳&#xff0c;覆盖范围内一定是可以跳到的&#xff0c;以最小的步数增加覆盖范围&#xff0c;覆盖范围一旦覆盖了终点&#xff0c;得到的就是最少步数&#xff01; 这里…

Java和JavaScript区别与联系

Java 和 JavaScript 是两种不同的编程语言&#xff0c;尽管它们的名称相似&#xff0c;但它们在语法、用途和运行环境等方面有很大的区别。下面是 Java 和 JavaScript 的对比&#xff1a; 语法和类型系统&#xff1a; Java 是一种静态类型的面向对象编程语言&#xff0c;它使…

Python进阶--装饰器

装饰器简介 每个Python开发者早晚都会遇到装饰器&#xff0c;装饰器通常用于增强函数功能。 例如&#xff0c;在Django中用装饰器为视图添加权限&#xff1a; permission_required(edit_publisher) def publisher_edit(request, pkNone):...注册标签 register.simple_tag de…

C++大学教程(第九版)7.30 打印array对象 7.31 逆序打印字符串(递归练习题)

文章目录 题目代码运行截图题目代码运行截图 题目 (打印array对象)编写一个递归函数printArray它以一个array对象一个开始下标和一个结束下标作为实参&#xff0c;不返回任何值并打印这个array对象。当开始下标和结束下标相等时&#xff0c;这个函数应该停止处理并返回。 代码…

跨镜网络解决方案:SD-WAN专线,实现企业全球互联

在全球化的背景下&#xff0c;越来越多的企业需要在海外社媒平台推广、研发访问海外平台、实现海外分部和国内互联互通等需求。然而&#xff0c;面对不同地区之间网络连接不稳定、高延迟、高成本等问题&#xff0c;如何实现企业的全球互联成为了一个亟待解决的难题。 幸运的是&…

laravel学习笔记

这两天公司活不多&#xff0c;学习了一下laravel框架。经过几天的学习&#xff0c;也对它有一些大概的了解。现在我就把我所学的到在这儿做下笔记吧。 一、laravel集合 其实&#xff0c;这里所说的集合&#xff0c;跟前端es6中的集合概念还是有那一点的不太一样。前端es6的集合…

小世界网络 | 小世界网络(Python)

概述 小世界网络是一种网络模型,用于描述网络中节点之间的连接方式。它是基于"六度分隔理论"提出的,该理论认为任意两个人之间的联系最多通过六个中间人来实现。小世界网络模型试图解释人际关系网络、社交网络以及其他一些网络结构的特点。 在小世界网络中,节点…

C++ 数论相关题目:卡特兰数应用、快速幂求组合数。满足条件的01序列

给定 n 个 0 和 n 个 1 &#xff0c;它们将按照某种顺序排成长度为 2n 的序列&#xff0c;求它们能排列成的所有序列中&#xff0c;能够满足任意前缀序列中 0 的个数都不少于 1 的个数的序列有多少个。 输出的答案对 1097 取模。 输入格式 共一行&#xff0c;包含整数 n 。 …

Java 集合 02 综合练习+基本数据类型对应的包装类

练习1、 自己写的代码&#xff1a; import java.util.ArrayList; public class practice {public static void main(String[] args) {//定义一个集合ArrayList<String> list new ArrayList<>();list.add("aaa");list.add("bbb");list.add(…

理解C++中类内静态函数在类外定义时为何不需再加static关键字

理解C中类内静态函数在类外定义时为何不需再加static关键字 在C中&#xff0c;静态成员函数是类的成员函数&#xff0c;它们与类的实例无关&#xff0c;而是与整个类相关联的。当我们在类内部声明静态成员函数时&#xff0c;我们使用关键字 static 来标识它们。然而&#xff0…

Dockerr开发环境搭建

Docker安装 sudo apt install docker.ioDocker运行权限 #添加docker group sudo groupadd docker# 将当前用户添加到docker组 sudo gpasswd -a ${USER} docker# 重启docker服务&#xff1a; sudo service docker restart# 查看用户组及成员&#xff1a; cat /etc/group | gr…