【opencv】教程代码 —ImgProc (7)使用维纳滤波器来恢复失焦的图像

04685e62051fd3667a54341fec7c9434.png

7. out_of_focus_deblur_filter.cpp使用维纳滤波器来恢复失焦的图像

21863a4baa2e221814c0795a8bda9798.png

b5f468a450b26f52cfb18c791bc1a134.png

代码的主要功能是通过使用维纳滤波器来恢复失焦的图像,它读取一个灰度图像文件,对其进行滤波操作,并将结果保存为新文件。这个过程包括计算点扩散函数(PSF),执行FFT变换,应用滤波器,然后完成逆FFT变换。这些步骤都在main函数中进行,并在帮助函数中分别解决。

/**
* @brief 你将了解如何通过维纳滤波器恢复失焦的图像
* @author Karpushin Vladislav, karpushin@ngs.ru, https://github.com/VladKarpushin
*/
// 导入所需的库和模块
#include <iostream>
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"// 声明使用的命名空间
using namespace cv;
using namespace std;// 声明函数原型
void help();
void calcPSF(Mat& outputImg, Size filterSize, int R);
void fftshift(const Mat& inputImg, Mat& outputImg);
void filter2DFreq(const Mat& inputImg, Mat& outputImg, const Mat& H);
void calcWnrFilter(const Mat& input_h_PSF, Mat& output_G, double nsr);// 定义命令行参数
const String keys =
"{help h usage ? |             | print this message   }"
"{image          |original.jpg | input image name     }"
"{R              |5           | radius               }"
"{SNR            |100         | signal to noise ratio}"
;int main(int argc, char *argv[])
{help();    //调用帮助函数CommandLineParser parser(argc, argv, keys);  //创建命令行参数解析器if (parser.has("help"))    //如果含有"help"参数{parser.printMessage();    //打印消息return 0;    //返回0,结束程序}int R = parser.get<int>("R");  //获取参数R的值int snr = parser.get<int>("SNR");   //获取参数SNR的值string strInFileName = parser.get<String>("image");    //获取参数image的值samples::addSamplesDataSearchSubDirectory("doc/tutorials/imgproc/out_of_focus_deblur_filter/images");    //添加样本数据搜索子目录if (!parser.check())   //如果参数解析器检查失败{parser.printErrors();   //打印错误return 0;   //返回0,结束程序}Mat imgIn;imgIn = imread(samples::findFile( strInFileName ), IMREAD_GRAYSCALE);   //以灰度模式读取图片文件if (imgIn.empty())  //检查是否图片已成功加载{cout << "ERROR : Image cannot be loaded..!!" << endl;   //输出错误消息return -1;}Mat imgOut;  //创建输出图像//只处理偶数大小的图像Rect roi = Rect(0, 0, imgIn.cols & -2, imgIn.rows & -2);//开始计算HwMat Hw, h;calcPSF(h, roi.size(), R);  //计算点扩散函数calcWnrFilter(h, Hw, 1.0 / double(snr));   //计算维纳滤波器//结束计算Hw//开始滤波处理filter2DFreq(imgIn(roi), imgOut, Hw);//结束滤波处理imgOut.convertTo(imgOut, CV_8U);   //将输出图像转换为8位无符号整形normalize(imgOut, imgOut, 0, 255, NORM_MINMAX);   //将输出图像正规化到0-255imshow("Original", imgIn);   //显示原始图像imshow("Debluring", imgOut);  //显示滤波后的图像imwrite("result.jpg", imgOut);   //将滤波后的图像写入文件waitKey(0); //等待窗口关闭return 0;
}// 显示帮助信息的函数
void help()
{cout << "2018-07-12" << endl;cout << "DeBlur_v8" << endl;cout << "You will learn how to recover an out-of-focus image by Wiener filter" << endl;
}//! [calcPSF]
// 计算PSF的函数
void calcPSF(Mat& outputImg, Size filterSize, int R)
{Mat h(filterSize, CV_32F, Scalar(0)); // 创建一个滤波器大小的黑色图像Point point(filterSize.width / 2, filterSize.height / 2); // 圆心位于图像中心circle(h, point, R, 255, -1, 8); // 画一个填充圆,半径为RScalar summa = sum(h); // 计算圆内的像素和,为了进行归一化outputImg = h / summa[0]; // 归一化,使得PSF的总和为1
}
//! [calcPSF]//! [fftshift]
// 在数学上进行fftshift操作的函数 该函数实现对图像的快速傅里叶变换后的频率平面进行移位,将直流分量移至频率平面的中心。
//! [fftshift]
void fftshift(const Mat& inputImg, Mat& outputImg)
{outputImg = inputImg.clone(); //克隆输入图像int cx = outputImg.cols / 2;  //计算图像中心点的x坐标int cy = outputImg.rows / 2;  //计算图像中心点的y坐标Mat q0(outputImg, Rect(0, 0, cx, cy));    //创建四个子图像矩阵,分别表示图像的四个象限q0, q1, q2, q3Mat q1(outputImg, Rect(cx, 0, cx, cy));Mat q2(outputImg, Rect(0, cy, cx, cy));Mat q3(outputImg, Rect(cx, cy, cx, cy));Mat tmp;    //创建临时Mat变量//进行频率域的中心变换q0.copyTo(tmp); q3.copyTo(q0);tmp.copyTo(q3);q1.copyTo(tmp);q2.copyTo(q1);tmp.copyTo(q2);
}
//! [fftshift]//! [filter2DFreq]
// 实现2D频域滤波的函数 该函数实现了频率域滤波,先将图像和滤波器都变换到频率域,然后进行频谱相乘,最后反变换回空间域。
//! [filter2DFreq]
void filter2DFreq(const Mat& inputImg, Mat& outputImg, const Mat& H)
{Mat planes[2] = { Mat_<float>(inputImg.clone()), Mat::zeros(inputImg.size(), CV_32F) };Mat complexI;merge(planes, 2, complexI);  //将图像与频率平面合并成复数形式dft(complexI, complexI, DFT_SCALE);   //对复数形式的图像进行离散傅里叶变换Mat planesH[2] = { Mat_<float>(H.clone()), Mat::zeros(H.size(), CV_32F) };Mat complexH;merge(planesH, 2, complexH);  //同样将h与频率平面合并成复数形式Mat complexIH;   mulSpectrums(complexI, complexH, complexIH, 0);  //将两个频谱相乘idft(complexIH, complexIH);  //进行逆傅里叶变换split(complexIH, planes);  //拆分出图像部分和频率部分outputImg = planes[0];  //提取图像部分
}
//! [filter2DFreq]//! [calcWnrFilter]
// 计算维纳滤波器的函数
//函数实现了维纳滤波器在频率域的计算过程,确定了对模糊图像进行复原的滤波器。
//! [calcWnrFilter]
void calcWnrFilter(const Mat& input_h_PSF, Mat& output_G, double nsr)
{Mat h_PSF_shifted;fftshift(input_h_PSF, h_PSF_shifted);  //将PSF进行中心化Mat planes[2] = { Mat_<float>(h_PSF_shifted.clone()), Mat::zeros(h_PSF_shifted.size(), CV_32F) };Mat complexI;merge(planes, 2, complexI);  //形成复数图像 dft(complexI, complexI);   //进行傅里叶变换split(complexI, planes);  //进行图像分离,分别是实部和虚部Mat denom;pow(abs(planes[0]), 2, denom);  //求模之后取平方denom += nsr;  //加上噪声功率divide(planes[0], denom, output_G);  //复原图像与噪声功率的比值即为维纳滤波器的频响
}
//! [calcWnrFilter]

4acb41f06fe25e496101efaf0a0d5afb.png

9cf02fbd4618484e381b5a9a5d059955.png

dc61dc2d70d18a8458bacb03a58bb63c.png

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

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

相关文章

机器学习模型——KNN

KNN的基本概念&#xff1a; KNN(K-Nearest Neighbor)就是k个最近的邻居的意思&#xff0c;即每个样本都可以用它最接近的k个邻居来代表。KNN常用来处理分类问题&#xff0c;但也可以用来处理回归问题。 核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某…

python实现在线 ChatGLM调用

python实现在线 ChatGLM调用 1. 申请调用权限&#xff1a; 收钱进入到质谱AI开放平台&#xff0c;点击“开始使用”或者“开发者工具台”进行注册&#xff1a; 对于需要使用 API key 来搭建应用的话&#xff0c;需要点击右边红框中的查看 API key&#xff0c;就会进入到我们…

yolov8 pose keypoint解读

yolov8进行关键点检测的代码如下&#xff1a; from ultralytics import YOLO# Load a model model YOLO(yolov8n.pt) # pretrained YOLOv8n model# Run batched inference on a list of images results model([im1.jpg, im2.jpg]) # return a list of Results objects# Pr…

读所罗门的密码笔记04_社会信用

1. 人工智能 1.1. 人工智能可以帮助人们处理复杂的大气问题&#xff0c;完善现有的气候变化模拟&#xff0c;帮助我们更好地了解人类活动对环境造成的危害&#xff0c;以及如何减少这种危害 1.2. 人工智能也有助于减少森林退化和非法砍伐 1.3. 人工智能甚至可以将我们从枯燥…

RISC-V特权架构 - 中断定义

RISC-V特权架构 - 中断定义 1 中断类型1.1 外部中断1.2 计时器中断1.3 软件中断1.4 调试中断 2 中断屏蔽3 中断等待4 中断优先级与仲裁5 中断嵌套6 异常相关寄存器 本文属于《 RISC-V指令集基础系列教程》之一&#xff0c;欢迎查看其它文章。 1 中断类型 RISC-V 架构定义的中…

idea打开文件乱码,设置编码

idea整个项目都设置了utf-8了&#xff0c;但是还是有一个文件是其他编码_(ཀ」 ∠)__ 。 配置项目编码 在设置中设置编码 配置具体目录的编码 上面的设置之后&#xff0c;还是有几个文件一直是乱码&#xff0c;需要单独配置。 偶尔引入的依赖中的文件也会乱码&#xff0c;需…

题目:摆花(蓝桥OJ 0389)

问题描述&#xff1a; 题解&#xff1a; #include <bits/stdc.h> using namespace std; using ll long long; const int N 105; const ll p 1e6 7; ll a[N], dp[N][N];int main() {int n, m; cin >> n >> m;for(int i 1; i < n; i)cin >> a[i…

【科研基础】VAE: Auto-encoding Variational Bayes

[1]Kingma, Diederik P., and Max Welling. “Auto-encoding variational bayes.” arXiv preprint arXiv:1312.6114 (2013). [2] [论文简析]VAE: Auto-encoding Variational Bayes[1312.6114] [3] The Reparameterization Trick [4] 变分法的基本原理是什么? 文章目录 1-…

我的编程之路:从非计算机专业到Java开发工程师的成长之路 | 学习路线 | Java | 零基础 | 学习资源 | 自学

小伙伴们好&#xff0c;我是「 行走的程序喵」&#xff0c;感谢您阅读本文&#xff0c;欢迎三连~ &#x1f63b; 【Java基础】专栏&#xff0c;Java基础知识全面详解&#xff1a;&#x1f449;点击直达 &#x1f431; 【Mybatis框架】专栏&#xff0c;入门到基于XML的配置、以…

负荷频率控制LFC,自抗扰ADRC控制,麻雀SSA算法优化自抗扰参数,两区域二次调频simulink/matlab

红色曲线为优化结果&#xff0c;蓝色曲线为没有自抗扰和没有优化的结果&#xff01;

基于springboot实现蜗牛兼职网平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现蜗牛兼职网平台系统演示 摘要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;蜗牛兼职网当然也不能排除在外。蜗牛兼职网是以实际运用为开发背景&#xff…

【C语言】多文件编程以及static关键字

1、多文件编程 把函数声明放在头文件xxx.h中&#xff0c;在主函数中包含相应头文件在头文件对应的xxx.c中实现xxx.h声明的函数 a、主文件 #include<stdio.h> #include "MyMain.h"//需要包含头文件&#xff0c;头文件包含我们自定义的函数int main(){int num…

6、鸿蒙学习-Stage模型应用程序包结构

基于Stage模型开发的应用&#xff0c;经编译打包后&#xff0c;其应用程序的结构如下图应用程序包结构&#xff08;Stage模型&#xff09;所示。开发者需要熟悉应用程序包结构相关的基本概念。 一、在开发态&#xff0c;一个应用包含一个或者多个Module&#xff0c;可以在DevE…

【管理咨询宝藏60】顶级咨询公司对医药行业的研究报告

【管理咨询宝藏60】顶级咨询公司对医药行业的研究报告 【格式】PDF 【关键词】医疗行业、战略咨询、行业洞察 【核心观点】 - 195页精品内容&#xff0c;让你彻底透视医疗行业的发展现状和未来趋势 - 前20大交易约占医疗交易总额的65%&#xff1b;医疗行业大部分为制药业投资交…

c++的学习之路:5、类和对象(1)

一、面向对象和面向过程 在说这个定义时&#xff0c;我就拿c语言举例&#xff0c;在c语言写程序的时候&#xff0c;基本上就是缺什么函数&#xff0c;就去手搓一个函数&#xff0c;写的程序也只是调用函数的&#xff0c;而c就是基于面向对象的开发&#xff0c;他关注的不再是单…

DFS算法(C/C++)(内含立例题)

DFS&#xff1a; DFS又称深度优先搜索&#xff0c;是一种图运算方法&#xff0c;它从第一个节点走起&#xff0c;一直往下走&#xff0c;一直走到不能继续再走&#xff0c;就返回上一个节点&#xff0c;继续搜索其他地方&#xff0c;直到找到目标节点为止。 DFS可以解决迷宫问…

每日一题 --- 有效的字母异位词[力扣][Go]

有效的字母异位词 题目&#xff1a;242. 有效的字母异位词 给定两个字符串 *s* 和 *t* &#xff0c;编写一个函数来判断 *t* 是否是 *s* 的字母异位词。 **注意&#xff1a;**若 *s* 和 *t* 中每个字符出现的次数都相同&#xff0c;则称 *s* 和 *t* 互为字母异位词。 示例 …

基于单片机多功能智能台灯设计

**单片机设计介绍&#xff0c;基于单片机多功能智能台灯设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的多功能智能台灯设计是一个集硬件与软件于一体的综合性项目&#xff0c;旨在为用户提供更加便捷、舒适和节…

安静:内向性格的竞争力 - 三余书屋 3ysw.net

精读文稿 这期我们介绍的这本书叫做《安静》&#xff0c;副标题是《内向性格的竞争力》。本书共有267页&#xff0c;我会用大约25分钟的时间为你讲述书中的精髓。内向性格具备什么样的竞争力&#xff1f;内向性格的人在人际交往和日常生活中似乎总是吃亏&#xff0c;因为他们不…

[AutoSar]BSW_ECUC模块介绍

目录 关键词平台说明一、ECUC 的定义二、Definition of Partitions三、Variant Resolver Description四、Definition of PDUs 关键词 嵌入式、C语言、autosar、OS、BSW 平台说明 项目ValueOSautosar OSautosar厂商vector &#xff0c; EB芯片厂商TI 英飞凌编程语言C&#xf…