C/C++的OpenCV的锐化
图像锐化技术:使用 C/C++的OpenCV 增强图像细节 ✨
图像锐化是一种常见的图像处理技术,其目的是增强图像的边缘和细节,使图像看起来更清晰、更鲜明。这在很多应用中都非常有用,例如医学成像、卫星图像分析以及提升普通照片的视觉质量。本文将介绍几种在 C++/C的OpenCV 中实现图像锐化的方法。
图像锐化的基本原理
图像锐化的核心思想是增强图像中像素值变化剧烈的区域,即边缘和细节。这通常可以通过以下几种方式实现:
- 反锐化掩模 (Unsharp Masking):这是最经典和广泛使用的方法之一。
- 拉普拉斯算子 (Laplacian Operator):利用二阶导数来检测边缘和细节。
- 自定义卷积核 (Custom Kernel Convolution):直接使用一个设计好的锐化卷积核。
方法一:反锐化掩模 (Unsharp Masking)
反锐化掩模的步骤如下:
- 模糊图像:首先,对原始图像进行模糊处理(通常使用高斯模糊)。
blurred = GaussianBlur(original, ...)
- 计算掩模 (Mask):从原始图像中减去模糊后的图像,得到“掩模”。这个掩模包含了图像中的高频细节。
mask = original - blurred
- 锐化:将这个掩模按一定权重(强度因子)加回到原始图像中。
sharpened = original + amount * mask
这可以改写为:
sharpened = original * (1 + amount) - blurred * amount
在 OpenCV 中,可以使用 cv::GaussianBlur()
进行模糊,然后使用 cv::addWeighted()
或 cv::subtract()
和 cv::add()
来实现。
方法二:使用拉普拉斯算子
拉普拉斯算子是一种二阶微分算子,它可以有效地检测图像中的快速强度变化,即边缘。通过将拉普拉斯算子应用到图像上,并将结果与原始图像叠加,可以实现锐化效果。
一个常见的拉普拉斯核是:
K 1 = [ 0 1 0 1 − 4 1 0 1 0 ] K_1 = \begin{bmatrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \end{bmatrix} K1= 0101−41010 或者 K 2 = [ 1 1 1 1 − 8 1 1 1 1 ] K_2 = \begin{bmatrix} 1 & 1 & 1 \\ 1 & -8 & 1 \\ 1 & 1 & 1 \end{bmatrix} K2= 1111−81111
锐化后的图像 Sharpened
可以通过从原始图像 Original
中减去(或加上,取决于核的符号定义和期望效果)拉普拉斯滤波后的图像 LaplacianImage
得到:
Sharpened = Original - c * LaplacianImage
(如果核中心为负,如 K 1 , K 2 K_1, K_2 K1,K2)
其中 c
是一个缩放因子。
OpenCV 提供了 cv::Laplacian()
函数来应用拉普拉斯算子。
方法三:使用自定义锐化卷积核
这是最直接的方法之一,通过定义一个特定的 3 × 3 3 \times 3 3×3 卷积核并将其应用于图像。一个常见的锐化核是将单位矩阵(中心为1,其余为0)与一个拉普拉斯核(例如中心为-4或-8,周围为1)的某种组合。
例如,一个常用的锐化核是:
K s h a r p e n 1 = [ 0 − 1 0 − 1 5 − 1 0 − 1 0 ] K_{sharpen1} = \begin{bmatrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1 & 0 \end{bmatrix} Ksharpen1= 0−10−15−10−10
这个核可以看作是:Identity - K1
(其中 Identity 是中心为1的核,K1是中心为-4的拉普拉斯核,并且对K1取反并调整中心值,最终得到中心为5)。当这个核与图像卷积时,中心像素的权重被增强,而其邻近像素的权重被减弱,从而突出了中心像素与周围像素的差异,达到锐化效果。
另一个例子:
K s h a r p e n 2 = [ − 1 − 1 − 1 − 1 9 − 1 − 1 − 1 − 1 ] K_{sharpen2} = \begin{bmatrix} -1 & -1 & -1 \\ -1 & 9 & -1 \\ -1 & -1 & -1 \end{bmatrix} Ksharpen2= −1−1−1−19−1−1−1−1
这个核可以看作是:Identity - K2
(其中K2是中心为-8的拉普拉斯核,同样调整后得到)。
在 OpenCV 中,可以使用 cv::filter2D()
函数应用自定义卷积核。
C++ OpenCV 代码示例
下面的代码演示了如何使用自定义锐化卷积核 (cv::filter2D
) 和 反锐化掩模 来锐化图像。
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>// 方法1:使用自定义卷积核进行锐化
cv::Mat sharpenWithKernel(const cv::Mat& src) {cv::Mat sharpened_img;cv::Mat kernel = (cv::Mat_<float>(3, 3) <<0, -1, 0,-1, 5, -1,0, -1, 0);// 或者使用更强的锐化核:// cv::Mat kernel = (cv::Mat_<float>(3,3) <<// -1, -1, -1,// -1, 9, -1,// -1, -1, -1);// cv::filter2D 函数应用卷积核// src.depth() 表示输出图像与输入图像有相同的深度cv::filter2D(src, sharpened_img, src.depth(), kernel);return sharpened_img;
}// 方法2:使用反锐化掩模进行锐化
cv::Mat unsharpMask(const cv::Mat& src, double sigma = 1.0, double amount = 1.0) {cv::Mat blurred_img, mask, sharpened_img;// 1. 高斯模糊cv::GaussianBlur(src, blurred_img, cv::Size(0, 0), sigma, sigma);// 2. 计算掩模: mask = original - blurred// 锐化: sharpened = original + amount * mask// 合并为: sharpened = original * (1 + amount) + blurred * (-amount)// cv::addWeighted(src1, alpha, src2, beta, gamma, dst);// dst = src1*alpha + src2*beta + gamma;cv::addWeighted(src, 1.0 + amount, blurred_img, -amount, 0, sharpened_img);return sharpened_img;
}int main(int argc, char** argv) {if (argc != 2) {std::cout << "用法: " << argv[0] << " <图片路径>" << std::endl;return -1;}cv::Mat src = cv::imread(argv[1], cv::IMREAD_COLOR);if (src.empty()) {std::cerr << "错误: 无法加载图像 " << argv[1] << std::endl;return -1;}// 应用锐化方法1:自定义卷积核cv::Mat sharpened_kernel = sharpenWithKernel(src);// 应用锐化方法2:反锐化掩模// sigma 控制模糊程度,amount 控制锐化强度cv::Mat sharpened_unsharp = unsharpMask(src, 1.0, 1.5);cv::imshow("原始图像", src);cv::imshow("锐化图像 (卷积核)", sharpened_kernel);cv::imshow("锐化图像 (反锐化掩模)", sharpened_unsharp);cv::waitKey(0);cv::destroyAllWindows();// 可选: 保存锐化后的图像// cv::imwrite("sharpened_kernel_output.jpg", sharpened_kernel);// cv::imwrite("sharpened_unsharp_output.jpg", sharpened_unsharp);return 0;
}
代码解释
-
sharpenWithKernel(const cv::Mat& src)
函数:- 定义了一个 3 × 3 3 \times 3 3×3 的锐化卷积核
kernel
。这个核的中心值为5,周围直接相邻的像素值为-1。这意味着它会增强中心像素的亮度,同时减弱周围像素的亮度,从而突出细节。 cv::filter2D(src, sharpened_img, src.depth(), kernel)
: 这个函数用我们定义的kernel
对源图像src
进行2D卷积。src.depth()
指定输出图像sharpened_img
具有与输入图像相同的位深度。
- 定义了一个 3 × 3 3 \times 3 3×3 的锐化卷积核
-
unsharpMask(const cv::Mat& src, double sigma, double amount)
函数:cv::GaussianBlur(src, blurred_img, cv::Size(0, 0), sigma, sigma)
: 对源图像进行高斯模糊。cv::Size(0,0)
表示核的大小会根据sigma
(标准差) 自动计算。sigma
值越大,模糊程度越高。cv::addWeighted(src, 1.0 + amount, blurred_img, -amount, 0, sharpened_img)
: 这个函数实现了sharpened = src * (1.0 + amount) + blurred_img * (-amount) + 0
。src
: 第一个输入数组(原始图像)。1.0 + amount
: 第一个数组的权重。amount
是锐化强度因子。blurred_img
: 第二个输入数组(模糊图像)。-amount
: 第二个数组的权重。0
: 加到加权和上的标量(伽马校正值)。sharpened_img
: 输出数组。
-
main
函数:- 加载图像。
- 分别调用
sharpenWithKernel
和unsharpMask
函数进行锐化。 - 使用
cv::imshow()
显示原始图像和锐化后的图像。 cv::waitKey(0)
等待用户按键后关闭窗口。
编译
要编译此 C++ 代码,你需要 g++ (或任何兼容 C++11 的编译器) 和已安装的 OpenCV。
g++ -o sharpen_app image_sharpening.cpp `pkg-config --cflags --libs opencv4` -std=c++11
(如果你的 OpenCV 版本较旧,或者 pkg-config
的设置不同,请使用 opencv
替换 opencv4
)。
运行:
./sharpen_app <你的图片路径.jpg>
重要注意事项
- 噪声放大:锐化操作会增强图像中的高频成分,这也包括噪声。如果原始图像噪声较多,锐化后噪声会更加明显。通常建议在锐化前先进行适当的降噪处理,或者使用对噪声不那么敏感的锐化算法。
- 锐化程度:过度锐化会导致图像边缘出现“光晕”效应 (halos) 或伪影,使图像看起来不自然。需要仔细调整锐化参数(如反锐化掩模中的
amount
和sigma
,或卷积核的系数)。 - 图像类型:对于彩色图像,锐化通常分别应用于每个颜色通道,或者先转换到亮度-色度空间(如 YCrCb、HSV),仅对亮度(Y 或 V)通道进行锐化,然后再转换回 BGR/RGB 空间,这样可以避免颜色失真。本文中的示例直接在 BGR 图像上操作,
cv::filter2D
和cv::GaussianBlur
默认会分别处理每个通道。
总结
图像锐化是提升图像视觉效果的有效手段。OpenCV 提供了多种实现图像锐化的工具,从简单的卷积核滤波到更复杂的反锐化掩模技术。理解这些方法的原理并合理选择参数,可以显著改善图像的清晰度和细节表现。
相关文章:
C/C++的OpenCV的锐化
图像锐化技术:使用 C/C的OpenCV 增强图像细节 ✨ 图像锐化是一种常见的图像处理技术,其目的是增强图像的边缘和细节,使图像看起来更清晰、更鲜明。这在很多应用中都非常有用,例如医学成像、卫星图像分析以及提升普通照片的视觉质…...

Eigen矩阵存储顺序以及转换
一、Eigen矩阵存储顺序 在矩阵运算和线性代数中,"行优先"(Row-major)和"列优先"(Column-major)是两种不同的存储方式,它们决定了多维数组(如矩阵)在内存中的布局顺序。 1. 行优先(Row-major) 定义:矩阵按行顺序存储在内存中,即第一行的所有元…...
OpenLayers 加载ArcGIS瓦片数据
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 随着GIS应用的不断发展,Web地图也越来越丰富,除了像ESRI、超图、中地数码这样GIS厂商有各自的数据源格式,也有Google…...

2025蓝桥杯WP
引言 在2025年蓝桥杯网络安全赛道中,我们面对涵盖Web安全、逆向工程、PWN、取证分析以及加密解密等多领域的挑战,要求选手具备扎实且全面的安全技术与实战能力。本文将以实战记录的形式,逐题详细还原解题思路与操作步骤,并配以相…...

数字人教师:开启教育智慧革新之旅
在科技浪潮的推动下,教育领域正经历一场由数字人教师引领的深刻变革,这不仅是技术与教育融合的创新实践,更是教育模式重塑的关键路径。 一、数字人教师的崛起:教育变革的必然选择 随着互联网、大数据、人工智能等前沿技术的飞速…...
Linux中Java开发、部署和运维常用命令
在Java开发、部署和运维过程中,Linux操作系统常用的一些命令可以帮助开发人员、运维人员管理系统、查看日志、控制进程等。以下是一些常见的Linux命令: 1. 文件和目录操作 ls:列出当前目录下的文件和文件夹。 ls -l:显示详细信息…...

详解srs流媒体服务器的集群
前言: 什么是集群 集群就是多台计算机或服务器等资源,联在一起像一台大机器一样工作。比如一群蚂蚁一起搬东西,这些蚂蚁就类似集群里的各个部分。 为什么要集群 性能更强:能把任务分到多个机器上做,一起处理更快&…...

ubuntu22.04 安装 SecureCRT8.7.3
用到的全部软件,都放在这个网盘里面了,自取。 链接: https://pan.baidu.com/s/1AR6Lj8FS7bokMR5IrLmsIw?pwd3dzv 提取码: 3dzv 如果链接失效了,关注公号:每日早参,回复:资源,即可免费获取&…...
Day 37
继续之前的学习 过拟合的判断 import torch import torch.nn as nn import torch.optim as optim from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler import time import matpl…...

libvirt设置虚拟机mtu实现原理
背景 云计算场景下,可以动态调整虚拟机mtu,提高虚拟机网络性能。设置虚拟机(VM)virtio网卡的MTU(Maximum Transmission Unit)涉及 宿主机(Host)、QEMU/KVM、vhost-net后端 和 虚拟机内部的virtio驱动之间的协作。 原理分析 1.libvirt设置mtu分析 libv…...

AstroNex空间任务智能控制研究与训练数据集
数据集概述 AstroNex空间任务智能控制研究与训练数据集是朗迪锋科技基于Multiverse平台精心打造的首个全面覆盖航天器智能控制全周期的综合数据集产品。该数据集汇集了轨道动力学、姿态控制、机器视觉、环境感知等多维度数据,为航天器智能算法研发提供丰富的训练与…...

汽车副水箱液位传感器介绍
汽车副水箱液位传感器是现代车辆冷却系统中不可或缺的关键部件,其核心功能在于实时监测冷却液存量,确保发动机在最佳温度范围内稳定运行。随着汽车电子化程度不断提升,这一看似简单的传感器已发展成为集机械、电子、材料技术于一体的精密装置,其工作原理与技术演进值得深入…...
Docker+MobaXterm+x11实现容器UI界面转发本地
本文记录了搭建一个可直接ssh访问的container,并可通过x11转发界面的实现过程 0.1 实验环境 PC:windows 11 Server:Ubuntu 18.04 Docker image:Ubuntu 18.04 1. 获取Ubuntu 18.04的镜像 使用Dockerfile获取镜像,对…...

IEEE出版|2025年智能制造、机器人与自动化国际学术会议 (IMRA2025)
【重要信息】 会议官网:www.icimra.com 会议时间: 2025年11月14日-16日 会议地点: 中国湛江 截稿日期:2025年09月16日(一轮截稿) 接收或拒收通知:文章投递后5-7个工作日 会议提交检索:EI Compendex, Scopus IEEE出版|2025年…...

EasyRTC嵌入式SDK音视频实时通话助力WebRTC技术与智能硬件协同发展
一、概述 在万物互联的数字化浪潮下,智能硬件已广泛渗透生活与工业领域,实时音视频通信成为智能硬件实现高效交互的核心需求。WebRTC作为开源实时通信技术,为浏览器与移动应用提供免插件的音视频通信能力,而EasyRTC通过深度优化音…...

Higress MCP Server 安全再升级:API 认证为 AI 连接保驾护航
Higress MCP Server 安全再升级:API 认证为 AI 连接保驾护航 Higress 作为一款强大的 AI 原生 API 网关,致力于铺设 AI 与现实世界之间最短、最安全、最具成本效益的连接路径。其核心能力之一便是支持将现有的 OpenAPI 规范无缝转换为 MCP Server&#…...
多个vue2工程共享node_modules
手头有多个vue2项目,它们每个都需要一个node_modules,拷贝起来超级麻烦。于是想到能否共享一个node_modules呢?? 方法其实挺多,我选择了一个较简单的:符号连接法(win11平台) 创建方法很简单:比…...
蓝桥杯178 全球变暖
题目描述 你有一张某海域 NxN 像素的照片,"."表示海洋、"#"表示陆地,如下所示: ....... .##.... .##.... ....##. ..####. ...###. ....... 其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上…...

多模态理解大模型高性能优化丨前沿多模态模型开发与应用实战第七期
一、引言 在前序课程中,我们系统剖析了多模态理解大模型(Qwen2.5-VL、DeepSeek-VL2)的架构设计。鉴于此类模型训练需消耗千卡级算力与TB级数据,实际应用中绝大多数的用户场景均围绕推理部署展开,模型推理的效率影响着…...
mysql 合集
mysql 日志主要分为三个日志:redo log、binlog、undo log; redo log 主要是用来mysql 奔溃恢复 redo log 主要是有一个机制是 设置刷盘机制: 通过innodb_flush_log_at_trx_commit控制刷盘策略: 1:每次事务提交都刷盘(…...
Zustand V5教程:Vanilla Store 与 useStore 使用详解 + 实战 Demo
Zustand 是一个轻量、灵活的状态管理库。自从 Zustand v4 推出 Vanilla Store 后,我们可以更优雅地在组件外(如 API 拦截器、工具函数)访问状态,同时在组件内继续享受响应式的状态订阅。 本教程将通过一个“登录状态管理”示例&a…...
docker 搭建php 开发环境 添加扩展redis、swoole、xdebug(1)
docker-compose搭建lnmp 先决条件 首先需要安装docker 安装docker-compost 1、创建lnmp工作目录 #创建三个目录 mkdir lnmp && cd lnmp mkdir -p nginx/conf php mysql/data lnmp/www#编写nginx 配置文件 nginx/conf/default.conf vim nginx/conf/default.confserv…...

人脸识别技术合规备案最新政策详解
《人脸识别技术应用安全管理办法》将于2025年6月1日正式实施,该办法从技术应用、个人信息保护、技术替代、监管体系四方面构建了人脸识别技术的治理框架,旨在平衡技术发展与安全风险。 一、明确技术应用的边界 公共场所使用限制:仅在“维护公…...
(16)高性能风控系统设计
文章目录 🚀 高性能风控系统设计:千万级QPS实时风控解决方案TL;DR🏗️ 系统整体架构💻 Java技术栈选型详解1️⃣ 接入层技术选型🔥 接入层代码示例 2️⃣ 规则引擎层技术选型🧠 规则引擎优化技巧 3️⃣ 数据…...

AStar低代码平台-脚本调用C#方法
修改报工表表单,右键定义弹出菜单,新增一个菜单项,并在点击事件脚本中编写调用脚本。 编译脚本,然后在模块代码里面定义这个方法: public async Task<int> on_call_import(DataRow curRow) {PrintDataRow(cur…...

企业级RAG技术实战指南:从理论到落地的全景解析
前言 在大模型技术日新月异的今天,检索增强生成(RAG)技术正成为企业突破AI应用瓶颈的关键利器。当传统AI系统还在处理结构化数据的泥潭中挣扎时,RAG技术已经打开了通向非结构化知识海洋的大门。这本《RAG技术实战指南》以独特的工…...
getline()跳过输入
std::getline(cin, s) 第一个参数传递的是输入流:istream(输入流的基类), ifstream, istrstream 的引用; 第二个参数传递的是本地字符串引用,即从输入流读出来的东西要存放的位置。 会跳过getline()的输入 cin >> ch; getline(cin, s…...

【八股战神篇】RabbitMQ高频面试题
简述RabbitMQ五种模式 ? 延伸 请介绍一下RabbitMQ的特点 延伸 简述RabbitMQ的发布与订阅模式 延伸 RabbitMQ 如何保证消息不丢失? 延伸 RabbitMQ 如何保证消息有序? 延伸 专栏简介 八股战神篇专栏是基于各平台共上千篇面经…...

高阶数据结构——红黑树实现
目录 1.红黑树的概念 1.1 红黑树的规则: 1.2 红黑树的效率 2.红黑树的实现 2.1 红黑树的结构 2.2 红黑树的插入 2.2.1 不旋转只变色(无论c是p的左还是右,p是g的左还是右,都是一样的变色处理方式) 2.2.2 单旋变色…...
互联网大厂Java求职面试:AI与大模型应用集成中的架构难题与解决方案
互联网大厂Java求职面试:AI与大模型应用集成中的架构难题与解决方案 面试场景:AI与大模型应用集成的架构设计 面试官:技术总监 候选人:郑薪苦(搞笑但有技术潜力的程序员) 第一轮提问:系统架…...