11- OpenCV:自定义线性滤波(卷积,卷积边缘)

news2024/11/22 10:59:18

目录

一、卷积

1、卷积概念

2、卷积如何工作

3、常见算子(卷积核 Kenel)

4、自定义卷积模糊

二、卷积边缘

1、卷积边缘问题

2、处理边缘


一、卷积

1、卷积概念

(1)在OpenCV中,卷积是一种常用的图像处理操作,用于图像滤波、特征提取等任务。它基于滑动窗口的概念,通过将一个小的核Kenel(也称为滤波器)与图像进行逐像素的乘法和求和运算来实现。

— 卷积是图像处理中一个操作,是kernel在图像的每个像素上的操作。

— Kernel本质上一个固定大小的矩阵数组,其中心点称为锚点(anchor point)

(2)卷积操作可以理解为在图像上滑动一个小的核,并将核的每个元素与对应位置的图像像素值相乘,然后将所有乘积结果相加得到输出图像的对应像素值。这个过程可以简单地表示为:

output(x, y) = sum(kernel(i, j) * input(x+i, y+j))

其中,output(x, y)是输出图像的像素值,kernel(i, j)是核的元素值,input(x+i, y+j)是输入图像的像素值。

(3)卷积操作在图像处理中有多种应用,其中最常见的是图像滤波。通过选择不同的核,可以实现不同的滤波效果,例如平滑滤波、边缘检测等。卷积操作还可以用于图像特征提取,例如使用卷积神经网络(CNN)进行图像分类、目标检测等任务。

在OpenCV中,可以使用cv::filter2D函数来进行卷积操作。该函数接受输入图像、核以及输出图像作为参数,并将卷积结果存储在输出图像中。

2、卷积如何工作

把kernel放到像素数组之上,求锚点周围覆盖的像素乘积之和(包括锚点),用来替换锚点覆盖下像素点值称为卷积处理。数学表达如下

公式讲解:

K(i,j):卷积核的大小

I里面的参数就是窗口的半径

两个方向X、Y方向上的求和

例子:从左到右,从上到下进行计算

Sum = 8x1+6x1+6x1+2x1+8x1+6x1+2x1+2x1+8x1

New pixel = sum / (m*n)

3、常见算子(卷积核 Kenel)

(1)Robert算子:又称“梯度算子”

(2)Sobel算子:中间2*2,更大,比Robert算子的差异更大,效果可能更明显了

(3)拉普拉斯算子

4、自定义卷积模糊

(1)filter2D方法

filter2D (

Mat src, //输入图像

Mat dst, // 模糊图像

int depth, // 图像深度32/8,不知道的就默认-1,系统也默认和src的深度一样

Mat kernel, // 卷积核/模板

Point anchor = Point(-1,-1) , // 锚点位置,3、5、7、9,或者默认自动寻找中心位置

double delta = 0 // 计算出来的像素+delta

其中 kernel是可以自定义的卷积核

5、代码演示

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
int main(int argc, char** argv)
{
	Mat src, dst;
	int ksize = 0;

	src = imread("test.jpg");
	if (!src.data)
	{
		printf("could not load image...\n");
		return -1;
	}

	char INPUT_WIN[] = "input image";
	char OUTPUT_WIN[] = "Custom Blur Filter Result";
	namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);

	imshow(INPUT_WIN, src);

	// Robert 算子 X 方向
	//Mat Robert_x = (Mat_<int>(2, 2) << 1, 0, 0, -1);
	//Mat mat_Robert_x;
	//filter2D(src, mat_Robert_x, -1, Robert_x);
	//imshow("Robert x", mat_Robert_x);

	 Robert 算子 Y 方向
	//Mat Robert_y = (Mat_<int>(2, 2) << 0, 1, -1, 0);
	//Mat mat_Robert_y;
	//filter2D(src, mat_Robert_y, -1, Robert_y);
	//imshow("Robert y", mat_Robert_y);

	// Sobel X 方向
	Mat kernel_x = (Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
	filter2D(src, dst, -1, kernel_x, Point(-1, -1), 0.0);
	imshow("Sobel X", dst);

	// Sobel Y 方向
	Mat yimg;
	Mat kernel_y = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
	filter2D(src, yimg, -1, kernel_y, Point(-1, -1), 0.0);
	imshow("Sobel Y", yimg);


	// 拉普拉斯算子
	//Mat kernel_y = (Mat_<int>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
	//filter2D(src, dst, -1, kernel_y, Point(-1, -1), 0.0);
	//imshow("拉普拉斯", dst);
	
	waitKey(0);

    // 自定义卷积模糊
	//int c = 0;
	//int index = 0;
	//while (true)null
	//{
	//	c = waitKey(500);
	//	if ((char)c == 27) // ESC
	//	{ 
	//		break;
	//	}
	//	ksize = 5 + (index % 8) * 2;
	//	Mat kernel = Mat::ones(Size(ksize, ksize), CV_32F) / (float)(ksize * ksize);
	//	filter2D(src, dst, -1, kernel, Point(-1, -1));
	//	index++;
	//	imshow(OUTPUT_WIN, dst);
	//}

	return 0;
}

效果展示:

(1)Robert算子,在X与Y方向上呈现出差异性

(2)Sobel算子:相对与Robert算子,差异会明显一些

(3)拉普拉斯算子:碎发也没看到了

二、卷积边缘

1、卷积边缘问题

卷积边缘问题:图像卷积的时候边界像素,不能被卷积操作。

原因:在于边界像素没有完全跟kernel重叠,所以当3x3滤波时候有1个像素的边缘没有被处理,5x5滤波的时候有2个像素的边缘没有被处理。

2、处理边缘

在卷积开始之前增加边缘像素,填充的像素值为0或者RGB黑色,比如3x3在 四周各填充1个像素的边缘,这样就确保图像的边缘被处理,在卷积处理之 后再去掉这些边缘。

openCV中默认的处理方法是: BORDER_DEFAULT,此外 常用的还有如下几种:

- BORDER_CONSTANT – 填充边缘用指定像素值  

- BORDER_REPLICATE – 填充边缘像素用已知的边缘像素值

- BORDER_WRAP – 用另外一边的像素来补偿填充

3、相关的API说明

给图像添加边缘API:copyMakeBorder

copyMakeBorder(  

- Mat src, // 输入图像  

- Mat dst, // 添加边缘图像  

- int top, // 边缘长度,一般上下左右都取相同值,

 - int bottom,  

- int left,  

- int right,  

- int borderType // 边缘类型  

- Scalar value

4、代码演示

增加边缘的四种策略,都适用于什么场景,如何处理卷积的边缘。

先认识下:GaussianBlur()

GaussianBlur函数用于对图像进行高斯模糊操作。它可以有效地去除图像中的噪声,并平滑图像的细节。

void GaussianBlur (

InputArray src, // 输入图像,可以是单通道或多通道图像

OutputArray dst, // 输出图像,与输入图像具有相同的尺寸和类型

Size ksize, // 高斯核的大小,用Size(w, h)表示。它必须是正奇数,例如(3, 3)、(5, 5)等。

double sigmaX, // 高斯核在X方向上的标准差

double sigmaY = 0, // 高斯核在Y方向上的标准差。如果为0,则默认使用sigmaX的值

int borderType = BORDER_DEFAULT // 边界处理方式,默认为BORDER_DEFAULT

);

int main(int argc, char** argv) 
{
	Mat src, dst;
	src = imread("test.jpg");
	if (!src.data) 
	{
		printf("could not load image...\n");
		return -1;
	}
	char INPUT_WIN[] = "input image";
	char OUTPUT_WIN[] = "Border Demo";
	namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_WIN, src);
	/*
	int top = (int)(0.05*src.rows);
	int bottom = (int)(0.05*src.rows);
	int left = (int)(0.05*src.cols);
	int right = (int)(0.05*src.cols);
	RNG rng(12345);
	int borderType = BORDER_DEFAULT;

	int c = 0;
	while (true) 
	{
		c = waitKey(500);
		// ESC
		if ((char)c == 27) 
			break;

		if ((char)c == 'r') 
			borderType = BORDER_REPLICATE;
		else if((char)c == 'w') 
			borderType = BORDER_WRAP;
		else if((char)c == 'c') 
			borderType = BORDER_CONSTANT;

		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		copyMakeBorder(src, dst, top, bottom, left, right, borderType, color);
		imshow(OUTPUT_WIN, dst);
	}
	*/


    // 上面的代码可以直接用下面接口替换
	GaussianBlur(src, dst, Size(5, 5), 0, 0);
	imshow(OUTPUT_WIN, dst);

	waitKey(0);
	return 0;
}

效果展示:

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

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

相关文章

Python+Selenium+Unittest 之selenium13--WebDriver操作方法3-鼠标操作2

这篇说下ActionChains里常用的几种鼠标操作的方法。 ActionChains常用的鼠标操作方法 click()鼠标左键单击double_click()鼠标左键双击context_click()鼠标右键单击move_to_element()鼠标移动到某个元素上&#xff08;鼠标悬浮操作&#xff09;click_and_hold()点击鼠标左键&am…

合并K个升序链表(LeetCode 23)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路方法一&#xff1a;顺序合并方法二&#xff1a;分治合并方法三&#xff1a;使用优先队列合并 参考文献 1.问题描述 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff…

Flink的KeyedProcessFunction基于Event Time和Process Time的定时器用法实例分析

FLink处理函数简介 在Flink底层&#xff0c;我们可以不定义任何具体的算子&#xff08;比如 map&#xff0c;filter&#xff0c;或者 window&#xff09;&#xff0c;而只是提炼出一个统一的【处理】&#xff08;process&#xff09;操作——它是所有转换算子的一个概括性的表…

动手学深度学习5 矩阵计算

矩阵计算--矩阵怎么求导数 1. 导数和微分2. 偏导数3. 梯度1. 向量-标量求导2. 向量-向量求导3. 拓展到矩阵 4. 链式法则5. 小结QA练习 课程安排&#xff1a; 视频&#xff1a;https://www.bilibili.com/video/BV1eZ4y1w7PY/?spm_id_fromautoNext&vd_sourceeb04c9a33e87ce…

【复现】SpringBlade SQL 注入漏洞_22

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 SpringBlade 是由一个商业级项目升级优化而来的SpringCloud微服务架构&#xff0c;采用Java8 API重构了业务代码&#xff0c;完全…

具有中国特色的普及工厂数字化转型的新路子

工业互联网浪潮来袭&#xff0c;你准备好了吗&#xff1f; 国家智能制造专委会委员、浙江省智能制造专家委员会毛光烈主任在“第七届中国工业大数据大会”上的演讲&#xff0c;《具有中国特色的普及工厂数字化转型的新路子》&#xff0c;阐述了关于工厂订单全流程业务数据体系运…

C++核心编程之通过类和对象的思想对文件进行操作

目录 ​​​​​​​一、文件操作 1. 文件类型分类&#xff1a; 2. 操作文件的三大类 二、文本文件 1.写文件 2.读文件 三、二进制文件 1.写二进制文件 2.读二进制文件 一、文件操作 程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放 通过文件可以将…

GPT APP的开发步骤

开发一个GPT&#xff08;Generative Pre-trained Transformer&#xff09; Store&#xff08;存储&#xff09;涉及到使用预训练的语言模型&#xff08;例如GPT-3&#xff09;来生成和管理内容。以下是一般的步骤&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&…

2024年美国大学生数学建模思路 - 案例:异常检测

文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…

适合进阶学习的 机器学习 开源项目(可快速下载)

目录 开源项目合集[>> 开源的机器学习平台&#xff1a;mlflow/mlflow](https://gitcode.com/mlflow/mlflow)[>> 机器学习路线图&#xff1a;mrdbourke/machine-learning-roadmap](https://gitcode.com/mrdbourke/machine-learning-roadmap)[>> 机器学习理论和…

VsCode 常见的配置

转载&#xff1a;Visual Studio Code 常见的配置、常用好用插件以及【vsCode 开发相应项目推荐安装的插件】 - 知乎 (zhihu.com) 一、VsCode 常见的配置 1、取消更新 把插件的更新也一起取消了 2、设置编码为utf-8&#xff1a;默认就是了&#xff0c;不用设置了 3、设置常用的…

阿里云云原生弹性方案:用弹性解决集群资源利用率难题

作者&#xff1a;赫曦 随着上云的认知更加普遍&#xff0c;我们发现除了以往占大部分的互联网类型的客户&#xff0c;一些传统的企业&#xff0c;一些制造类的和工业型企业客户也都开始使用云原生的方式去做 IT 架构的转型&#xff0c;提高集群资源使用率也成为企业上云的一致…

【51单片机】数码管的静态与动态显示(含消影)

数码管在现实生活里是非常常见的设备&#xff0c;例如 这些数字的显示都是数码管的应用。 目录 静态数码管&#xff1a;器件介绍&#xff1a;数码管的使用&#xff1a;译码器的使用&#xff1a;缓冲器&#xff1a; 实现原理&#xff1a;完整代码&#xff1a; 动态数码管&#…

Linux Shell脚本入门

目录 介绍 编写格式与执行方式 Shell脚本文件编写规范 脚本文件后缀名规范 首行格式规范 注释格式 shell脚本HelloWord入门案例 需求 效果 实现步骤 脚本文件的常用执行三种方式 介绍 3种方式的区别 小结 多命令处理 Shell变量 环境变量 目标 Shell变量的介绍 变量类型 系统环境…

Java 方法中参数类型后写了三个点?什么意思?

1、...代表什么意思&#xff1f; 2、如何使用 3、注意事项 4、两个list&#xff0c;一个新的&#xff0c;一个旧的&#xff0c;旧列表中可能有新列表中存在的数据&#xff0c;也可能存在新列表中不存在的数据&#xff08;注&#xff1a;新旧列表中都不存在重复元素&#xff09;…

【数据结构】堆:堆的构建,堆的向上调整算法,堆的向下调整算法、堆排序

目录 一、堆的定义 1、堆的定义&#xff1a; 2、根节点与其左、右孩子间的联系 二、堆的创建 1、堆的向下调整算法 2、堆的向上调整算法 三、堆排序 一、堆的定义 1、堆的定义&#xff1a; 堆可以被看作是一棵完全二叉树的数组对象。即在存储结构上是数组&#xff0c…

2024 年 10 款最佳 Windows 免费分区管理器软件

买了一台现成的全新电脑&#xff0c;出于多种原因希望对硬盘进行分区&#xff0c;例如&#xff0c;为了更好地组织文件。我们整理了一份最佳分区软件列表&#xff0c;可以帮助您轻松完成这项任务。 适用于 Windows 11/10/8.1/8/7 的最佳 10 个磁盘分区工具 1.奇客分区大师 兼容…

vue3自定义按钮点击变颜色(切换)

实现效果图&#xff1a; 默认选中第一个按钮&#xff0c;未选中按钮为粉色&#xff0c;点击时颜色变为红色 利用动态类名&#xff0c;当定义isChange数值和下标index相同时&#xff0c;赋予act类名&#xff0c;实现变色效果 <template><view class"page"&g…

FPGA 多路分频器实验

1 概述 在 FPGA 中&#xff0c;时钟分频是经常用到的。本节课讲解 2 分频、3 分频、4 分频和 8 分频的 Verilog 实现并且学习 generate 语法功能的应。 2 程序设计思路 1&#xff09;整数倍分频&#xff0c;为 2、4、8&#xff0c;这种 2^n 次方倍数倍数关系的…

Spring Security 中 Authentication和Authorization的区别

Authentication Spring Security提供了全面的认证支持。认证是用来验证试图访问特定资源的用户身份的方式。验证用户的常见方式是要求用户输入用户名和密码。一旦认证完成&#xff0c;我们就知道了用户的身份并且可以进行授权。 Spring Security内置支持对用户进行认证。 简…