当前位置: 首页 > news >正文

11.1图像的腐蚀和膨胀

基本概念-图像腐蚀

图像腐蚀是一种用于去除图像中小的对象或者突出物体边缘的形态学操作。

图像腐蚀(erosion)的基本概念
图像腐蚀通常用于二值图像,其基本原理是从图像中“侵蚀”掉一些像素点,这些像素点通常是边界上的或者是孤立的小点。在二值图像中,通常用白色表示前景,黑色表示背景。腐蚀操作会使得前景区域缩小。

腐蚀操作可以用一个称为结构元素(或核)的小矩阵来定义。这个结构元素通常是对称的,并且中心像素是结构元素的位置。腐蚀过程检查结构元素覆盖下的每个像素是否都为前景像素(通常是白色),只有当所有像素都是前景像素时,中心像素才会保留为前景;否则,中心像素将被标记为背景(通常是黑色)。

图像腐蚀(Erosion)是形态学操作的一种基本形式,主要用于消除小对象、分离相邻物体以及平滑边界。腐蚀操作通常用于图像预处理阶段,如去噪、连接组件的分离等。

形态学腐蚀原理

腐蚀操作的基本思想是从图像中去除突出的小部分或“凸起”的部分。具体来说,腐蚀会从每个前景像素(通常为白色或非零值)中减去一个结构元素(Structuring Element)的尺寸,如果结构元素在该像素周围的所有位置都能完全包含在前景区域内,则该像素被认为是腐蚀操作的结果的一部分。

结构元素

结构元素(Structuring Element)是一个定义了如何进行腐蚀操作的小型网格。最常见的结构元素是一个3x3或更大的方形网格,其中心像素代表当前正在处理的图像中的像素。结构元素可以有不同的形状,如圆形、十字形、椭圆形等。

腐蚀操作

在OpenCV中,可以使用erode函数来执行图像的腐蚀操作。

函数原型

void erode(InputArray src,OutputArray dst,InputArray kernel,Point anchor = Point(-1,-1),int iterations = 1,double borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue()
);参数说明
•src:输入图像。
•dst:输出图像,与输入图像具有相同的大小和类型。
•kernel:结构元素,可以使用getStructuringElement函数生成。
•anchor:结构元素相对于原点的位置,默认为中心位置。
•iterations:迭代次数,默认为1次。
•borderType:边界处理类型,默认为BORDER_CONSTANT。
•borderValue:边界值,默认为morphologyDefaultBorderValue()。

示例代码1

下面是一个使用OpenCV C++实现图像腐蚀的示例代码:

#include "pch.h"#include <iostream>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;void erodeImage(const Mat &src, Mat &dst, const Mat &kernel, int iterations)
{erode(src, dst, kernel, Point(-1, -1), iterations);
}int main(int argc, char** argv)
{/*if (argc != 2){cout << "Usage: ./ErodeImage <Image Path>" << endl;return -1;}*/// 加载图像Mat img = imread("897.png", IMREAD_GRAYSCALE);if (!img.data) {cout << "Error opening image" << endl;return -1;}// 定义结构元素Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));// 初始化输出矩阵Mat eroded;// 执行腐蚀操作erodeImage(img, eroded, kernel, 1);// 显示结果namedWindow("Origal Imagine", WINDOW_NORMAL);imshow("Origal Imagine", img);namedWindow("Eroded Image", WINDOW_NORMAL);imshow("Eroded Image", eroded);waitKey(0);destroyAllWindows();return 0;
}代码解释
1. 加载图像:使用 imread 函数以灰度模式加载图像。
2. 定义结构元素:使用 getStructuringElement 函数生成一个3x3大小的矩形结构元素。
3. 初始化输出矩阵:创建一个新的矩阵来存储腐蚀后的图像。
4. 执行腐蚀操作:使用 erode 函数对图像进行腐蚀操作。
5. 显示结果:使用 imshow 函数显示原始图像和腐蚀后的图像。注意事项
•结构元素的形状:不同的结构元素形状会导致不同的腐蚀效果。矩形结构元素通常用于去除孤立的噪声点,而十字形结构元素则可能更适合于特定的应用场景。
•迭代次数:增加迭代次数会使腐蚀效果更加明显,但过度的腐蚀可能会导致有用的细节丢失。
•边界处理:腐蚀操作默认会处理图像的边界,可以选择不同的边界处理方式来影响腐蚀的效果。
•数据类型:确保输出图像的数据类型与输入图像相同。

运行结果1

应用场景

•去噪:在二值化图像或边缘检测之后,可以使用腐蚀操作去除小的孤立噪声点。

•分离连通组件:在处理连通组件时,可以使用腐蚀操作来分离紧密相连的对象。

•平滑边界:可以使用腐蚀操作来平滑图像的边界,使其更加光滑。

通过这些示例和详细解释,你应该能够理解如何在OpenCV中使用C++实现图像的腐蚀操作。

示例代码2

在OpenCV中,使用erode函数可以很方便地对图像进行腐蚀操作。下面是一个简单的例子,展示了如何使用C++来实现图像腐蚀:

#include "pch.h"#include <iostream>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;int main(int argc, char** argv)
{// 加载图像cv::Mat src = cv::imread("888.png", cv::IMREAD_GRAYSCALE);if (src.empty()){std::cout << "Error: Image cannot be loaded!" << std::endl;return -1;}// 定义结构元素cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));// 腐蚀图像cv::Mat dst;cv::erode(src, dst, element);// 显示结果cv::namedWindow("Original Image", cv::WINDOW_NORMAL);cv::imshow("Original Image", src);cv::namedWindow("Eroded Image", cv::WINDOW_NORMAL);cv::imshow("Eroded Image", dst);// 等待按键并退出cv::waitKey(0);return 0;
}在这个例子中:使用cv::imread读取图片。
使用cv::getStructuringElement创建一个3x3大小的矩形结构元素。
使用cv::erode函数对原图像进行腐蚀。
使用cv::imshow显示原始图像和腐蚀后的图像。腐蚀的程度取决于结构元素的形状和大小。不同的形状(如圆形、十字形等)以及更大的尺寸都会影响腐蚀的效果。如果需要更精细的控制,可以调整结构元素的大小和形状。

运行结果2

基本概念-图像膨胀

图像膨胀(dilation)是另一种常用的形态学操作,它与图像腐蚀相对。膨胀主要用于扩展图像中的对象边界,填补前景物体中的小孔洞,或者连接靠近的物体。在二值图像处理中,膨胀通常会使得前景区域扩大。

图像膨胀(Dilation)是形态学操作的一种基本形式,主要用于扩大前景区域(通常为白色或非零值),填补孔洞,连接接近的物体,并扩展边界。膨胀操作通常用于图像处理和分析中,如去噪、连接组件的合并等。

形态学膨胀原理

膨胀操作的基本思想是在每个前景像素周围加上一个结构元素(Structuring Element),如果结构元素中的任何部分落在前景区域内,则该像素被认为是膨胀操作的结果的一部分。

图像膨胀的基本概念
与腐蚀相反,膨胀操作同样需要一个结构元素。对于每个像素位置,如果结构元素覆盖下的任何像素是前景像素(通常是白色),那么中心像素也会被标记为前景。因此,膨胀可以增加前景区域的大小,使得边界向外扩张。

结构元素

结构元素是一个定义了如何进行膨胀操作的小型网格。最常见的结构元素是一个3x3或更大的方形网格,其中心像素代表当前正在处理的图像中的像素。结构元素可以有不同的形状,如圆形、十字形、椭圆形等。

膨胀操作

在OpenCV中,可以使用dilate函数来执行图像的膨胀操作。这个函数接受几个参数,包括输入图像、输出图像、结构元素、锚点位置、迭代次数等。

函数原型

void dilate(InputArray src,OutputArray dst,InputArray kernel,Point anchor = Point(-1,-1),int iterations = 1,double borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue()
);参数说明
•src:输入图像。
•dst:输出图像,与输入图像具有相同的大小和类型。
•kernel:结构元素,可以使用getStructuringElement函数生成。
•anchor:结构元素相对于原点的位置,默认为中心位置。
•iterations:迭代次数,默认为1次。
•borderType:边界处理类型,默认为BORDER_CONSTANT。•borderValue:边界值,默认为morphologyDefaultBorderValue()。

示例代码3

下面是一个使用OpenCV C++实现图像膨胀的示例代码:

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;void dilateImage(const Mat &src, Mat &dst, const Mat &kernel, int iterations)
{dilate(src, dst, kernel, Point(-1, -1), iterations);
}int main(int argc, char** argv) 
{/*if (argc != 2) {cout << "Usage: ./DilateImage <Image Path>" << endl;return -1;}*/// 加载图像Mat img = imread("999.png", IMREAD_GRAYSCALE);if (!img.data){cout << "Error opening image" << endl;return -1;}// 定义结构元素Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));// 初始化输出矩阵Mat dilated;// 执行膨胀操作dilateImage(img, dilated, kernel, 1);// 显示结果namedWindow("Original Image", cv::WINDOW_NORMAL);imshow("Original Image", img);namedWindow("Dilated Image", cv::WINDOW_NORMAL);imshow("Dilated Image", dilated);waitKey(0);destroyAllWindows();return 0;
}代码解释
1. 加载图像:使用 imread 函数以灰度模式加载图像。
2. 定义结构元素:使用 getStructuringElement 函数生成一个3x3大小的矩形结构元素。
3. 初始化输出矩阵:创建一个新的矩阵来存储膨胀后的图像。
4. 执行膨胀操作:使用 dilate 函数对图像进行膨胀操作。
5. 显示结果:使用 imshow 函数显示原始图像和膨胀后的图像。注意事项
•结构元素的形状:不同的结构元素形状会导致不同的膨胀效果。矩形结构元素通常用于扩大前景区域,而十字形结构元素则可能适合特定的应用场景。
•迭代次数:增加迭代次数会使膨胀效果更加明显,但过度的膨胀可能会导致前景区域过大,甚至连接本来应该分离的物体。
•边界处理:膨胀操作默认会处理图像的边界,可以选择不同的边界处理方式来影响膨胀的效果。
•数据类型:确保输出图像的数据类型与输入图像相同。应用场景
•去噪:在二值化图像或边缘检测之后,可以使用膨胀操作去除小的孔洞或连接分离的物体。
•连接连通组件:在处理连通组件时,可以使用膨胀操作来连接紧密相连的对象。
•平滑边界:可以使用膨胀操作来平滑图像的边界,使其更加光滑。

运行结果3

示例代码4

在OpenCV中,使用dilate函数可以实现图像的膨胀操作。下面是一个简单的示例代码,展示了如何使用C++来实现图像膨胀:

#include "pch.h"#include <opencv2/opencv.hpp>
#include <iostream>using namespace std;
using namespace cv;int main(int argc, char** argv)
{// 加载图像cv::Mat src = cv::imread("875.jpeg", cv::IMREAD_GRAYSCALE);if (src.empty()){std::cout << "Error: Image cannot be loaded!" << std::endl;return -1;}// 定义结构元素cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));// 膨胀图像cv::Mat dst;cv::dilate(src, dst, element);// 显示结果cv::namedWindow("Original Image", cv::WINDOW_NORMAL);cv::imshow("Original Image", src);cv::namedWindow("Dilated Image", cv::WINDOW_NORMAL);cv::imshow("Dilated Image", dst);// 等待按键并退出cv::waitKey(0);return 0;
}在这个例子中:cv::imread用于读取图片。
cv::getStructuringElement用于创建一个3x3大小的矩形结构元素。
cv::dilate函数用来执行膨胀操作。
cv::imshow用于显示原始图像和膨胀后的图像。结构元素的选择
结构元素的选择会影响膨胀的结果。常见的结构元素形状有矩形、椭圆和十字形等。结构元素的大小也会影响最终的效果。较大的结构元素会导致更大的膨胀效果,可能会合并原本分离的物体。迭代次数
在调用cv::dilate函数时,还可以指定迭代次数,这决定了膨胀操作被执行的次数。每次迭代都会根据结构元素再次扩展前景区域。更多的迭代次数意味着更大的膨胀效果。注意事项
膨胀和腐蚀都是针对二值图像的操作,因此在进行这些操作之前,通常需要先将图像转换为灰度图,并可能需要进行阈值化处理。
结构元素的选择和迭代次数应该根据具体的应用场景来调整,以达到最佳效果。

运行结果4

综合实验代码5

// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include "pch.h"
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
using namespace std;
Mat src, erosion_dst, dilation_dst;
int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;
void Erosion(int, void*);
void Dilation(int, void*);
//#pragma comment(lib, "opencv_world450d.lib")  //引用引入库
int main(int argc, char** argv)
{src = imread("93.jpeg",IMREAD_COLOR);if (src.empty()){cout << "Could not open or find the image!\n" << endl;return -1;}namedWindow("Erosion Demo", WINDOW_NORMAL);namedWindow("Dilation Demo", WINDOW_NORMAL);moveWindow("Dilation Demo", src.cols, 0);createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",&erosion_elem, max_elem,Erosion);createTrackbar("Kernel size:\n 2n +1", "Erosion Demo",&erosion_size, max_kernel_size,Erosion);createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",&dilation_elem, max_elem,Dilation);createTrackbar("Kernel size:\n 2n +1", "Dilation Demo",&dilation_size, max_kernel_size,Dilation);Erosion(0, 0);Dilation(0, 0);waitKey(0);return 0;
}
void Erosion(int, void*)
{int erosion_type = 0;if (erosion_elem == 0) { erosion_type = MORPH_RECT; }else if (erosion_elem == 1) { erosion_type = MORPH_CROSS; }else if (erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }Mat element = getStructuringElement(erosion_type,Size(2 * erosion_size + 1, 2 * erosion_size + 1),Point(erosion_size, erosion_size));erode(src, erosion_dst, element);imshow("Erosion Demo", erosion_dst);
}
void Dilation(int, void*)
{int dilation_type = 0;if (dilation_elem == 0) { dilation_type = MORPH_RECT; }else if (dilation_elem == 1) { dilation_type = MORPH_CROSS; }else if (dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }Mat element = getStructuringElement(dilation_type,Size(2 * dilation_size + 1, 2 * dilation_size + 1),Point(dilation_size, dilation_size));dilate(src, dilation_dst, element);imshow("Dilation Demo", dilation_dst);
}

运行结果5

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【隐私计算】Cheetah安全多方计算协议-阿里安全双子座实验室
  • ls 命令:列出目录
  • 探索自闭症寄宿学校的专属教育模式
  • 相图数据对于纳米材料研究的积极作用
  • 【Redis入门到精通三】Redis核心数据类型(List,Set)详解
  • 解决selenium爬虫被浏览器检测问题
  • [第一章]java快速入门
  • 6.C_数据结构_查询_哈希表
  • 【深度学习 Transformer VIT】Transformer VIT:拆解“视觉变形金刚”,笑谈技术细节
  • 十种果冻的做法
  • 生信初学者教程(四):软件
  • 一起对话式学习-机器学习03——模型评估与模型选择
  • 中电信翼康基于Apache Dolphinscheduler重构“星海·济世医疗数据中台”实践经验分享
  • 【网络通信基础与实践第四讲】用户数据报协议UDP和传输控制协议TCP
  • JavaWeb纯小白笔记02:Tomcat的使用:发布项目的三种方式、配置虚拟主机、配置用户名和密码
  • 【comparator, comparable】小总结
  • bootstrap创建登录注册页面
  • C++入门教程(10):for 语句
  • docker python 配置
  • express + mock 让前后台并行开发
  • k8s如何管理Pod
  • leetcode讲解--894. All Possible Full Binary Trees
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • PAT A1120
  • vue 个人积累(使用工具,组件)
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 对超线程几个不同角度的解释
  • 官方解决所有 npm 全局安装权限问题
  • 面试遇到的一些题
  • 微信小程序实战练习(仿五洲到家微信版)
  • 协程
  • 阿里云ACE认证之理解CDN技术
  • ​Linux·i2c驱动架构​
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • # 详解 JS 中的事件循环、宏/微任务、Primise对象、定时器函数,以及其在工作中的应用和注意事项
  • #include<初见C语言之指针(5)>
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (C语言)fgets与fputs函数详解
  • (面试必看!)锁策略
  • (算法)N皇后问题
  • (转)Android学习笔记 --- android任务栈和启动模式
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .gitignore文件—git忽略文件
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .net core 控制台应用程序读取配置文件app.config
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET Framework 服务实现监控可观测性最佳实践
  • .Net FrameWork总结
  • .Net IOC框架入门之一 Unity
  • .net SqlSugarHelper