OpenCV 笔记(39):频域中的拉普拉斯算子

1. 拉普拉斯算子

在该系列的第八篇文章中,我们曾经介绍过在二维空间拉普拉斯算子的定义为:

这是对函数   的二阶偏导数之和。

2. 拉普拉斯算子的傅里叶变换及其推导

在该系列的第三十二篇文章中,我们曾给介绍过下面的公式

二维连续傅里叶变换:

二维连续傅里叶逆变换:

下面,我们尝试推导一下拉普拉斯算子在频域中的表示。首先考虑傅里叶变换的性质,特别是微分运算的傅里叶变换性质:

  • 一阶微分:在空间域中对 x 方向的微分变换为:

  • 二阶微分:在空间域中对 x 方向的二阶微分变换:

同理,

现在,可以直接将拉普拉斯算子作用在   上的结果进行傅里叶变换:

在频域中,由之前介绍过的公式可知   的傅里叶变换是  ,即 

拉普拉斯算子的作用等价于对   乘以一个因子:

π

这个乘积意味着:频率越高(u 或 v 越大),乘的因子绝对值越大,也就是高频成分被放大。因此频域中的拉普拉斯算子常用于边缘检测、锐化等图像处理任务。

3. 使用 OpenCV C++ 实现频域的拉普拉斯算子

下面的例子,实现频域拉普拉斯算子,并且对原图进行锐化。

在频域中,锐化操作相当于将原图频谱与拉普拉斯响应叠加。具体公式为:

其中 k 是一个控制锐化强度的正数。从空间域视角,这等价于:

#include <opencv2/opencv.hpp>
#include <iostream>usingnamespace cv;
usingnamespacestd;// 创建频域拉普拉斯滤波器
Mat createLaplacianFilter(Size size) {Mat laplacianFilter = Mat::zeros(size, CV_32FC2);int center_row = laplacianFilter.rows / 2;int center_col = laplacianFilter.cols / 2;float factor = (2 * CV_PI) * (2 * CV_PI); // 计算 (2*PI)^2for (int i = 0; i < laplacianFilter.rows; i++) {for (int j = 0; j < laplacianFilter.cols; j++) {float u = (float)(i - center_row);float v = (float)(j - center_col);float d_squared = u * u + v * v;laplacianFilter.at<Vec2f>(i, j)[0] = -factor * d_squared; // −(2π)^2(u^2+v^2)laplacianFilter.at<Vec2f>(i, j)[1] = 0;}}return laplacianFilter;
}// 对单个通道应用频域拉普拉斯锐化并返回处理后频域图像的幅度谱
Mat processChannelAndGetProcessedMag(const Mat& src, Mat& dst, double alpha) {int m = getOptimalDFTSize(src.rows);int n = getOptimalDFTSize(src.cols);Mat padded;copyMakeBorder(src, padded, 0, m - src.rows, 0, n - src.cols, BORDER_CONSTANT, Scalar::all(0));// 创建频域图像容器 (复数)Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};Mat complexImg;merge(planes, 2, complexImg);// 进行傅里叶变换 (DFT)dft(complexImg, complexImg);// 创建拉普拉斯滤波器Mat laplacianFilter = createLaplacianFilter(complexImg.size());// 应用拉普拉斯滤波器Mat resultFreq;mulSpectrums(complexImg, laplacianFilter, resultFreq, 0);// 计算处理后频域图像的幅度谱 (用于可视化)Mat magProcessed;Mat processedPlanes[2];split(resultFreq, processedPlanes);magnitude(processedPlanes[0], processedPlanes[1], magProcessed);magProcessed += Scalar::all(1); // 避免 log(0)log(magProcessed, magProcessed);normalize(magProcessed, magProcessed, 0, 1, NORM_MINMAX);int cx_processed = magProcessed.cols / 2;int cy_processed = magProcessed.rows / 2;Mat q0_processed(magProcessed, Rect(0, 0, cx_processed, cy_processed));Mat q1_processed(magProcessed, Rect(cx_processed, 0, cx_processed, cy_processed));Mat q2_processed(magProcessed, Rect(0, cy_processed, cx_processed, cy_processed));Mat q3_processed(magProcessed, Rect(cx_processed, cy_processed, cx_processed, cy_processed));Mat tmp_processed;q0_processed.copyTo(tmp_processed);q3_processed.copyTo(q0_processed);tmp_processed.copyTo(q3_processed);q1_processed.copyTo(tmp_processed);q2_processed.copyTo(q1_processed);tmp_processed.copyTo(q2_processed);// 进行傅里叶逆变换Mat resultImg;idft(resultFreq, resultImg, DFT_REAL_OUTPUT);// 裁剪回原始图像大小resultImg = resultImg(Rect(0, 0, src.cols, src.rows));// 归一化到 0-255 并转换为 CV_8UMat resultImg_normalized;normalize(resultImg, resultImg_normalized, 0, 255, NORM_MINMAX, CV_8U);// 锐化addWeighted(src, alpha, resultImg_normalized, (1 - alpha), 0, dst);return magProcessed;
}int main() {Mat src = imread(".../girl.jpg");if (src.empty()) {cout << "无法加载图像" << endl;return-1;}// 通道分离vector<Mat> channels;split(src, channels);// 对每个通道应用频域拉普拉斯锐化并获取处理后频域图像的幅度谱double alpha = 1.5; // 锐化强度因子Mat sharpenedB, sharpenedG, sharpenedR;Mat processedMagB = processChannelAndGetProcessedMag(channels[0], sharpenedB, alpha);Mat processedMagG = processChannelAndGetProcessedMag(channels[1], sharpenedG, alpha);Mat processedMagR = processChannelAndGetProcessedMag(channels[2], sharpenedR, alpha);// 合并锐化后的通道vector<Mat> sharpenedChannels = {sharpenedB, sharpenedG, sharpenedR};Mat sharpenedImg;merge(sharpenedChannels, sharpenedImg);imshow("src", src);imshow("Processed Magnitude Spectrum (Blue Channel)", processedMagB);imshow("Processed Magnitude Spectrum (Green Channel)", processedMagG);imshow("Processed Magnitude Spectrum (Red Channel)", processedMagR);imshow("Sharpened Color Image", sharpenedImg);waitKey(0);return0;
}
原图和锐化后的图.png
原图和锐化后的图.png

频域拉普拉斯响应(即拉普拉斯滤波器作用后的图像)

频域拉普拉斯响应通常不适合直接显示:

1. 拉普拉斯响应具有正负值对称性(不是图像强度)

  • 拉普拉斯是一种二阶微分算子,其结果表示图像的边缘变化强度和方向(凸或凹)。

  • 拉普拉斯响应值可能是正的或负的,而标准图像通道(如CV_8U)不能表达负值

  • 直接显示会丢失符号信息:正负边缘变得无法分辨。

2. 值域动态范围极大,不适合线性可视化

频域中经过拉普拉斯滤波后,结果的值可能在很大的范围内波动(甚至数万级别),远远超出 [0, 255]。直接转换为 8 位图像会导致:

  • 要么强烈压缩 → 对比度丧失(画面几乎全灰或全白)

  • 要么饱和溢出 → 出现大片“过曝”或“过暗”现象

3. 响应是中间量,本身不代表直观图像内容。

所以,例子中展示了幅度谱,它是对频域响应的一种可视化方式。

各个通道处理后的幅度谱.png
各个通道处理后的幅度谱.png

4. 总结

在频域中,拉普拉斯算子通过傅里叶变换将空间域的微分操作转换为频域的乘法操作。主要用于增强图像高频成分以突出边缘和细节,典型应用包括图像锐化(通过逆变换叠加原图与拉普拉斯响应)、边缘检测(抑制低频保留高频突变信号)、频域滤波器设计(结合高低通滤波实现带通或带阻效果)以及图像恢复中的正则化约束(抑制噪声)。它是图像增强与分析的非常有用的工具。

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

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

相关文章

入职软件开发与实施工程师了后........

时隔几个月没有创作的我又回来了&#xff0c;这几个月很忙&#xff0c;我一直在找工作&#xff0c;在自考&#xff08;顺便还处理了一下分手的事&#xff09;&#xff0c;到处奔波&#xff0c;心力交瘁。可能我骨子里比较傲吧。我不愿意着急谋生&#xff0c;做我不愿意做的普通…

多卡跑ollama run deepseek-r1

# 设置环境变量并启动模型 export CUDA_VISIBLE_DEVICES0,1,2,3 export OLLAMA_SCHED_SPREAD1 # 启用多卡负载均衡 ollama run deepseek-r1:32b 若 deepseek-r1:32b 的显存需求未超过单卡容量&#xff08;如单卡 24GB&#xff09;&#xff0c;Ollama 不会自动启用多卡 在run…

09、底层注解-@Import导入组件

09、底层注解-Import导入组件 Import是Spring框架中的一个注解&#xff0c;用于将组件导入到Spring的应用上下文中。以下是Import注解的详细介绍&#xff1a; #### 基本用法 - **导入配置类** java Configuration public class MainConfig { // 配置内容 } Configuration Impo…

题解:P12207 [蓝桥杯 2023 国 Python B] 划分

链接 题目描述 给定 40 个数&#xff0c;请将其任意划分成两组&#xff0c;每组至少一个元素。每组的权值为组内所有元素的和。划分的权值为两组权值的乘积。请问对于以下 40 个数&#xff0c;划分的权值最大为多少。 5160 9191 6410 4657 7492 1531 8854 1253 4520 9231126…

配置ssh服务-ubuntu到Windows拷贝文件方法

背景&#xff1a; 在工作中&#xff0c;需要频繁从ubuntu到Windows拷贝文件&#xff0c;但有时间总是无法拷出&#xff0c;每次重启虚拟机又比较麻烦并且效率较低。可以使用scp服务进行拷贝&#xff0c;不仅稳定而且高效&#xff0c;现将配置过程进行梳理&#xff0c;以供大家参…

线程池模式与C#中用法

一、线程池模式解析 1. 核心概念 线程池是一种 管理线程生命周期的技术&#xff0c;主要解决以下问题&#xff1a; 减少线程创建/销毁开销&#xff1a;复用已存在的线程 控制并发度&#xff1a;避免无限制创建线程导致资源耗尽 任务队列&#xff1a;有序处理异步请求 2. …

设置IDEA打开新项目使用JDK17

由于最近在学习Spring-AI&#xff0c;所以JDK8已经不适用了&#xff0c;但是每次创建新项目都还是JDK8&#xff0c;每次调来调去很麻烦 把Projects和SDKs都调整为JDK17即可 同时&#xff0c;Maven也要做些更改&#xff0c;主要是添加build标签 <build><plugins>&…

初识MySQL · 索引

目录 前言&#xff1a; 重温磁盘 认识索引 为什么这么做&#xff0c;怎么做 重谈page 聚簇索引VS非聚簇索引 回表查询 索引分类 前言&#xff1a; 前文我们主要是介绍了MySQL的一些基本操作&#xff0c;增删查改一类的操作都介绍了&#xff0c;并且因为大多数情况下&am…

MySQL——7、复合查询和表的内外连接

复合查询和表的内外连接 1、基本查询回顾2、多表查询3、自连接4、子查询4.1、单行子查询4.2、多行子查询4.3、多列子查询4.4、在from子句中使用子查询4.5、合并查询 5、表的内连和外连5.1、内连接5.2、外连接5.2.1、左外连接5.2.2、右外连接 1、基本查询回顾 1.1、查询工资高于…

MYSQL故障排查和环境优化

一、MySQL故障排查 1. 单实例常见故障 &#xff08;1&#xff09;连接失败类问题 ERROR 2002 (HY000): Cant connect to MySQL server 原因&#xff1a;MySQL未启动或端口被防火墙拦截。 解决&#xff1a;启动MySQL服务&#xff08;systemctl start mysqld&#xff09;或开放…

7GB显存如何部署bf16精度的DeepSeek-R1 70B大模型?

构建RAG混合开发---PythonAIJavaEEVue.js前端的实践-CSDN博客 服务容错治理框架resilience4j&sentinel基础应用---微服务的限流/熔断/降级解决方案-CSDN博客 conda管理python环境-CSDN博客 快速搭建对象存储服务 - Minio&#xff0c;并解决临时地址暴露ip、短链接请求改…

数字图像处理——图像压缩

背景 图像压缩是一种减少图像文件大小的技术&#xff0c;旨在在保持视觉质量的同时降低存储和传输成本。随着数字图像的广泛应用&#xff0c;图像压缩在多个领域如互联网、移动通信、医学影像和卫星图像处理中变得至关重要。 技术总览 当下图像压缩JPEG几乎一统天下&#xff…

抖音视频怎么去掉抖音号水印

你是不是经常遇到这样的烦恼&#xff1f;看到喜欢的抖音视频&#xff0c;想保存下来分享给朋友或二次创作&#xff0c;却被抖音号水印挡住了画面&#xff1f;别着急&#xff0c;今天教你几种超简单的方法&#xff0c;轻松去除水印&#xff0c;高清无水印视频一键保存&#xff0…

RISC-V 开发板 MUSE Pi Pro PCIE 测试以及 fio 崩溃问题解决

视频讲解&#xff1a; RISC-V 开发板 MUSE Pi Pro PCIE 测试以及 fio 崩溃问题解决 板子上有一个m.2的pcie插槽&#xff0c;k1有三个pcie控制器&#xff0c;pcie0和usb3复用一个phy&#xff0c;所以实际开发板就两个&#xff0c;测试的话&#xff0c;上一个nvme硬盘&#xff0c…

超级管理员租户资源初始化与授权管理设计方案

背景说明 在多租户系统中&#xff0c;资源&#xff08;如功能模块、系统菜单、服务能力等&#xff09;需按租户维度进行授权管理。超级管理员在创建新租户时&#xff0c;需要初始化该租户的资源授权信息。 两种可选方案 方案描述方案 A&#xff1a;前端传入选中的资源列表创…

stm32week16

stm32学习 十一.中断 4.使用中断 EXTI的配置步骤&#xff1a; 使能GPIO时钟设置GPIO输入模式使能AFIO/SYSCFG时钟设置EXTI和IO对应关系设置EXTI屏蔽&#xff0c;上/下沿设置NVIC设计中断服务函数 HAL库的使用&#xff1a; 使能GPIO时钟&#xff1a;__HAL_RCC_GPIOx_CLK_EN…

什么是RDMA?

什么是RDMA&#xff1f; RDMA(RemoteDirect Memory Access)技术全称远程直接内存访问&#xff0c;就是为了解决网络传输中服务器端数据处理的延迟而产生的。它将数据直接从一台计算机的内存传输到另一台计算机&#xff0c;无需双方操作系统的介入。这允许高吞吐、低延迟的网络…

golang 安装gin包、创建路由基本总结

文章目录 一、安装gin包和热加载包二、路由简单场景总结 一、安装gin包和热加载包 首先终端新建一个main.go然后go mod init ‘项目名称’执行以下命令 安装gin包 go get -u github.com/gin-gonic/gin终端安装热加载包 go get github.com/pilu/fresh终端输入fresh 运行 &…

【数据结构篇】链式结构二叉树

目录&#xff1a; 一 二叉链的概念与结构&#xff1a; 1.1 概念&#xff1a; 1.2 结构&#xff1a; 二 二叉链的实现&#xff1a; 2.1 二叉树的构建&#xff1a; 2.2 二叉树的遍历&#xff1a; 2.2.1 前序遍历&#xff1a; 2.2.2 中序遍历&#xff1a; 2.2.3 后序遍历…

【MySQL】02.数据库基础

1. 数据库的引入 之前存储数据用文件就可以了&#xff0c;为什么还要弄个数据库? 文件存储存在安全性问题&#xff0c;文件不利于数据查询和管理&#xff0c;文件不利于存储海量数据&#xff0c;文件在程序中控制不方便。而为了解决上述问题&#xff0c;专家们设计出更加利于…