11.1图像的腐蚀和膨胀

news2024/11/15 19:36:55

基本概念-图像腐蚀

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

图像腐蚀(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

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

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

相关文章

Word中引用参考文献和公式编号的方法

文章目录 应用参考文献对于单个文献引用多于多个文献同时引用 公式编号手动编号自动编号 参考&#xff1a; 应用参考文献 对于单个文献引用 word中的参考文献用交叉应用实现。 首先&#xff0c;将参考文献编号&#xff1a; 然后&#xff0c;在需要引用的地方用交叉引用插入…

VM虚拟机使用的镜像文件下载

文章目录 Windows系统进入微软官网下载工具以Windows10为例下载镜像文件 Windows系统 进入微软官网下载工具 微软中国官网&#xff1a;https://www.microsoft.com/zh-cn/ 以Windows10为例下载镜像文件 选择下载的路径 开始下载 安装windows10操作系统出现Time out问题及解决办…

【AI视频】Runway:Gen-2 运镜详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI视频 | Runway 文章目录 &#x1f4af;前言&#x1f4af;Camera Control&#xff08;运镜&#xff09;&#x1f4af;Camera Control功能测试Horizonta&#xff08;左右平移&#xff09;Vertical&#xff08;上下平移&#xff0…

Python 中的 Kombu 类库

Kombu 是一个用于 Python 的消息队列库&#xff0c;提供了高效、灵活的消息传递机制。它是 Celery 的核心组件之一&#xff0c;但也可以单独使用。Kombu 支持多种消息代理&#xff08;如 RabbitMQ、Redis、Amazon SQS 等&#xff09;&#xff0c;并提供了消息生产者和消费者的功…

ByteTrack多目标跟踪流程图

ByteTrack多目标跟踪流程图 点个赞吧&#xff0c;谢谢。

用 Pygame 实现一个乒乓球游戏

用 Pygame 实现一个乒乓球游戏 伸手需要一瞬间&#xff0c;牵手却要很多年&#xff0c;无论你遇见谁&#xff0c;他都是你生命该出现的人&#xff0c;绝非偶然。若无相欠&#xff0c;怎会相见。 引言 在这篇文章中&#xff0c;我将带领大家使用 Pygame 库开发一个简单的乒乓球…

python文字转wav音频

借鉴博客 一.前期准备 1. pip install baidu-aip 2. pip install pydub 3. sudo apt-get install ffmpeg 二.代码 from aip import AipSpeech from pydub import AudioSegment import time#input your own APP_ID/API_KEY/SECRET_KEY APP_ID 14891501 API_KEY EIm2iXtvD…

【可变模板参数】

文章目录 可变参数模板的概念可变参数模板的定义方式参数包的展开方式递归展开参数包逗号表达式展开参数包 STL容器中的emplace相关接口函数 可变参数模板的概念 可变参数模板是C11新增的最强大的特性之一&#xff0c;它对参数高度泛化&#xff0c;能够让我们创建可以接受可变…

linux入门——“linux基本指令”下

1.mv指令 mv指令用于移动文件或者目录。语法是mv 源文件 目标文件。它的用法需要注意&#xff1a; 当目标文件不存在的时候&#xff0c;默认是将源文件进行重命名操作&#xff0c;名字就是目标文件的名字&#xff0c;当目标文件存在的时候才会把源文件移动到目标文件。 目标文…

centos 7.9安装k8s

前言 Kubernetes单词来自于希腊语&#xff0c;含义是领航员&#xff0c;生产环境级别的容器编排技术&#xff0c;可实现容器的自动部署扩容以及管理。Kubernetes也称为K8S&#xff0c;其中8代表中间8个字符&#xff0c;是Google在2014年的开源的一个容器编排引擎技术&#xff…

WebLogic 后台弱⼝令GetShell

漏洞描述 通过弱⼝令进⼊后台界⾯ , 上传部署war包 , getshell 影响范围 全版本&#xff08;前提后台存在弱⼝令&#xff09; 环境搭建 cd vulhub-master/weblogic/weak_password docker-compose up -d 漏洞复现 默认账号密码&#xff1a;weblogic/Oracle123 weblogic…

SQL编程题复习(24/9/19)

练习题 x25 10-145 查询S001学生选修而S003学生未选修的课程&#xff08;MSSQL&#xff09;10-146 检索出 sc表中至少选修了’C001’与’C002’课程的学生学号10-147 查询平均分高于60分的课程&#xff08;MSSQL&#xff09;10-148 检索C002号课程的成绩最高的二人学号&#xf…

34. 模型材质父类Material

学习到现在大家对threejs的材质都有简单的了解&#xff0c;本节课主要结合文档&#xff0c;从JavaScript语法角度&#xff0c;给大家总结一下材质API的语法。 材质父类Material 查询threejs文档&#xff0c;你可以看到基础网格材质MeshBasicMaterial、漫反射网格材质MeshLamb…

-bash: apt-get: command not found -bash: yum: command not found

1. 现象&#xff1a; 1.1. 容器内使用apt-get, yum 提示命令未找到 1.2. dockerfile制作镜像时候&#xff0c;使用apt-get, yum同样报此错误。 2.原因&#xff1a; 2.1. linux 分为&#xff1a; 1. RedHat系列&#xff1a; Redhat、Centos、Fedora等 2. Debian系列&#xff1a…

4G 网络下资源加载失败?一次运营商封禁 IP 的案例分享

在工作中&#xff0c;网络问题是不可避免的挑战之一。最近&#xff0c;我们在项目中遇到了一起网络资源加载异常的问题&#xff1a;某同事在使用 4G 网络连接公司 VPN 时&#xff0c;云服务的前端资源居然无法加载&#xff01;通过一系列的排查和分析&#xff0c;我们发现问题的…

alias 后门从入门到应急响应

目录 1. alias 后门介绍 2. alias 后门注入方式 2.1 方式一(以函数的方式执行) 2.2 方式二(执行python脚本) 3.应急响应 3.1 查看所有连接 3.2 通过PID查看异常连接的进程&#xff0c;以及该进程正在执行的命令行命令 3.3 查看别名 3.4 其他情况 3.5 那么检查这些…

Arthas jvm(查看当前JVM的信息)

文章目录 二、命令列表2.1 jvm相关命令2.1.3 jvm&#xff08;查看当前JVM的信息&#xff09; 二、命令列表 2.1 jvm相关命令 2.1.3 jvm&#xff08;查看当前JVM的信息&#xff09; 基础语法&#xff1a; jvm [arthas18139]$ jvmRUNTIME …

C++_21_模板

模板 简介&#xff1a; 一种用于实现通用编程的机制。 通过使用模板我们可以编写可复用的代码&#xff0c;可以适用于多种数据类型。 C模板的语法使用角括号 < > 来表示泛型类型&#xff0c;并使用关键字 template 来定义和声明模板 概念&#xff1a; c范式编程 特点&…

OSPFv3协议几类LSA介绍

OSPFv3协议介绍 与OSPFv2相比&#xff0c;OSPFv3在工作机制上与OSPFv2基本相同&#xff1b;但为了支持IPv6地址格式&#xff0c;OSPFv3对OSPFv2做了一些改动。OSPFv3基于OSPFv2基本原理增强&#xff0c;是一个独立的路由协议&#xff08;v3不兼容v2&#xff09;协议号仍然是89…

java -versionbash:/usr/lib/jvm/jdk1.8.0_162/bin/java:无法执行二进制文件:可执行文件格式错误

实验环境&#xff1a;Apple M1在VMwareFusion使用Utubun Jdk文件错误 &#xfffc; 尝试&#xff1a; 1、重新在网盘下载java1.8 2、在终端通过命令下载 3、确保 JDK 正确安装在系统中&#xff0c;可以通过 echo $JAVA_HOME 检查 JAVA_HOME 环境变量是否设置正确。 &#xfff…