Goal

在本教程中,您将学习:

什么是退化图像(degradation image model)模型

失焦图像的 PSF (PSF of an out-of-focus image)是多少

如何恢复模糊的图像(restore a blurred image)

什么是维纳滤波器(Wiener filter)

Theory

笔记

解释基于书籍[95]和[303]。 另外,您可以参考 Matlab 的教程 Image Deblurring in Matlab Image Deblurring - MATLAB & Simulink (mathworks.com) 和文章 SmartDeblurRestoration of defocused and blurred images. Yuzhikov.com 。

此页面上的失焦图像是真实世界的图像。 失焦是通过相机光学系统手动实现的。

What is a degradation image model?

什么是退化图像模型

这是频域表示(frequency domain representation)中图像退化的数学模型:

S=HU+N

其中 S 是模糊(退化)图像的频谱,U 是原始真实(未退化)图像的频谱,H 是点扩散函数(point spread function) (PSF) 的频率响应,N 是额外噪声的频谱

圆形 PSF离焦失真的良好近似。 这样的 PSF 仅由一个参数指定 - 半径 R。在这项工作中使用圆形 PSF

Circular point spread function

How to restore a blurred image?

如何恢复模糊的图像

恢复(去模糊)的目的是获得对原始图像的估计频域恢复公式为:

其中U'是原始图像U的估计谱,Hw是恢复滤波器,例如Wiener filter.维纳滤波器

Opencv 实现图像的离散傅里叶变换(DFT)、卷积运算(相关滤波) - gavanwanggw - 博客园 (cnblogs.com)

What is the Wiener filter?

维纳滤波器是一种恢复模糊图像的方法。 假设PSF是a real and symmetric signal一个真实的对称信号,原始真实图像的功率谱噪声是未知的,那么简化的维纳公式为:

其中 SNR 是信噪比

因此,为了通过维纳滤波器恢复失焦图像,需要知道圆形 PSF 的 SNR 和 R

其中SNR表示信噪比,因此可以基于维纳滤波恢复离焦图像,实现图像反模糊。这个过程最终重要的两个参数,分别是半径R与信噪比SNR,在反模糊图像时候,要先尝试调整R,然后再尝试调整SNR。

Source code

您可以在 OpenCV 源代码库的 samples/cpp/tutorial_code/ImgProc/out_of_focus_deblur_filter/out_of_focus_deblur_filter.cpp 中找到源代码。

/**
* @brief You will learn how to recover an out-of-focus image by Wiener filter
* 您将学习如何通过维纳滤波器恢复失焦图像
* @author Karpushin Vladislav, karpushin@ngs.ru, https://github.com/VladKarpushin
*/
#include <iostream>
#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              |53           | radius               }"
"{SNR            |5200         | signal to noise ratio}"
;int main(int argc, char *argv[])
{help();CommandLineParser parser(argc, argv, keys);if (parser.has("help")){parser.printMessage();return 0;}//圆形 PSF 是离焦失真的良好近似int R = parser.get<int>("R");//计算圆形点扩散函数point spread function 的半径 Rint snr = parser.get<int>("SNR");//SNR 是信噪比string strInFileName = parser.get<String>("image");//输入图像路径if (!parser.check()){parser.printErrors();return 0;}Mat imgIn;imgIn = imread(strInFileName, IMREAD_GRAYSCALE);//加载灰度图if (imgIn.empty()) //check whether the image is loaded or not{cout << "ERROR : Image cannot be loaded..!!" << endl;return -1;}Mat imgOut;//! [main]// 它只需要处理偶数行列图像it needs to process even image onlyRect roi = Rect(0, 0, imgIn.cols & -2, imgIn.rows & -2);//Hw calculation (start)Mat Hw, h;calcPSF(h, roi.size(), R);//圆形的PSF因为只有一个半径参数R,是一个非常好的失焦畸变近似,所以算法采用圆形的PSF。  生成PSF calcWnrFilter(h, Hw, 1.0 / double(snr));//计算Hw 维纳滤波器  nsr=1/snr//Hw calculation (stop)// filtering (start)   // 去模糊filter2DFreq(imgIn(roi), imgOut, Hw);// filtering (stop)
//! [main]// 归一化显示imgOut.convertTo(imgOut, CV_8U);normalize(imgOut, imgOut, 0, 255, NORM_MINMAX);imwrite("result.jpg", imgOut);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] 点扩散函数图
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);//白色的圆Scalar summa = sum(h);outputImg = h / summa[0];
}
//! [calcPSF]//! [fftshift]快速傅里叶变换   频率对齐函数(fftshift)
//fftshift的作用正是让正半轴部分和负半轴部分的图像分别关于各自的中心对称,
//因为直接用fft得出的数据与频率不是对应的,fftshift可以纠正过来。
//具体实现,每一行后半部分移到前半部分,每一列后半部分移到前半部分。
void fftshift(const Mat& inputImg, Mat& outputImg)
{outputImg = inputImg.clone();int cx = outputImg.cols / 2;int cy = outputImg.rows / 2;Mat q0(outputImg, Rect(0, 0, cx, cy));Mat 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;q0.copyTo(tmp);q3.copyTo(q0);tmp.copyTo(q3);q1.copyTo(tmp);q2.copyTo(q1);tmp.copyTo(q2);
}
//! [fftshift]//! [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);//计算频域图complexIMat planesH[2] = { Mat_<float>(H.clone()), Mat::zeros(H.size(), CV_32F) };Mat complexH;merge(planesH, 2, complexH);Mat complexIH;mulSpectrums(complexI, complexH, complexIH, 0);//对于两张频谱图中每个元素的乘法   U′=Hw⋅S   U'是原始图像U的估计谱,Hw是恢复滤波器idft(complexIH, complexIH);//逆向傅里叶变换split(complexIH, planes);//outputImg = planes[0];//去模糊滤波后时域图
}
//! [filter2DFreq]//! [calcWnrFilter] 计算维纳滤波器
void calcWnrFilter(const Mat& input_h_PSF, Mat& output_G, double nsr)
{Mat h_PSF_shifted;//点扩散函数图的 频率域fftshift(input_h_PSF, h_PSF_shifted);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;//|H|^2+1/nsrdivide(planes[0], denom, output_G);//计算维纳滤波器Hw -> output_G    H/(|H|^2+1/nsr)
}
//! [calcWnrFilter]

Explanation

失焦图像恢复算法包括 PSF 生成Wiener 滤波器生成在频域中过滤模糊图像

//它只需要处理偶数图像 it needs to process even image only

Rect roi = Rect(0, 0, imgIn.cols & -2, imgIn.rows & -2);

//Hw calculation (start)

Mat Hw, h;

calcPSF(h, roi.size(), R);

calcWnrFilter(h, Hw, 1.0 / double(snr));

//Hw calculation (stop)

// filtering (start)

filter2DFreq(imgIn(roi), imgOut, Hw);

// filtering (stop)

函数 calcPSF() 根据输入参数半径 R 形成一个圆形 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);

Scalar summa = sum(h);

outputImg = h / summa[0];

}

函数 calcWnrFilter() 根据上述公式合成简化的维纳滤波器 Hw

void calcWnrFilter(const Mat& input_h_PSF, Mat& output_G, double nsr)

{

Mat h_PSF_shifted;

fftshift(input_h_PSF, h_PSF_shifted);

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);

}

函数 fftshift() 重新排列 PSF。 此代码刚刚从教程离散傅里叶变换中复制:

void fftshift(const Mat& inputImg, Mat& outputImg)

{

outputImg = inputImg.clone();

int cx = outputImg.cols / 2;

int cy = outputImg.rows / 2;

Mat q0(outputImg, Rect(0, 0, cx, cy));

Mat 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;

q0.copyTo(tmp);

q3.copyTo(q0);

tmp.copyTo(q3);

q1.copyTo(tmp);

q2.copyTo(q1);

tmp.copyTo(q2);

}

函数 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);

Mat complexIH;

mulSpectrums(complexI, complexH, complexIH, 0);

idft(complexIH, complexIH);

split(complexIH, planes);

outputImg = planes[0];

}

Result

下面你可以看到真正的失焦图像:

并且使用 R = 53SNR = 5200 参数计算了以下结果:

使用了 Wiener 滤波器,并且手动选择了 R 和 SNR 的值以提供最佳的视觉效果。 我们可以看到结果并不完美,但它为我们提供了图像内容的提示。 有一些困难,文本是可读的。

笔记

参数 R 是最重要的。 所以你应该先调整R,然后再调整SNR

有时您可以在恢复的图像中观察到振铃效应。 可以通过几种方法来减少这种影响。 例如,您可以使输入图像边缘变细

References

  • Image Deblurring in Matlab - Image Deblurring in Matlab
  • SmartDeblur - SmartDeblur site

OpenCV 频域-时域的傅里叶变换及逆变换 C++_Dwyane05的博客-CSDN博客_c++ opencv 傅里叶变换

opencv的频域滤波 - 凤凰_1 - 博客园 (cnblogs.com)

快速傅里叶变换C++完整实现(包括FFT、IFFT & FFTShift) - SegmentFault 思否

您还可以在 YouTube 上找到一个快速演示视频。

https://youtu.be/0bEcE4B0XP4

【opencv 450 Image Processing】Out-of-focus Deblur Filter失焦去模糊滤镜相关推荐

  1. 【opencv 450 Image Processing】Periodic Noise Removing Filter周期性去噪滤波器

    Periodic Noise Removing Filter 周期性去噪滤波器 OpenCV: Periodic Noise Removing Filter Goal 在本教程中,您将学习:    如 ...

  2. 【opencv 450 Image Processing】Image Moments 图像矩

    Goal 在本教程中,您将学习如何: 使用 OpenCV 函数 cv::moments 使用 OpenCV 函数 cv::contourArea 使用 OpenCV 函数 cv::arcLength ...

  3. 【opencv 450 Image Processing】Hit-or-Miss

    Goal 在本教程中,您将学习如何使用 Hit-or-Miss 变换(也称为 Hit-and-Miss 变换)在二进制图像中找到给定的配置或模式(-1对应背景,1对应前景.找到邻域与内核模式一样的像素 ...

  4. 【opencv 450 Image Processing】Anisotropic image segmentation by a gradient structure tensor

    Anisotropic image segmentation by a gradient structure tensor 梯度结构张量的各向异性图像分割 Goal 在本教程中,您将学习: 梯度结构张 ...

  5. OpenCV离焦去模糊滤镜

    OpenCV离焦去模糊滤镜 离焦去模糊滤镜 目标 理论 什么是降级图像模型? 如何恢复模糊的图像? 什么是维纳过滤器? 源代码 解释 结果 离焦去模糊滤镜 目标 在本教程中,您将学习: 什么是退化图像 ...

  6. 【opencv 450 core】使用统一向量指令(Universal Intrinsics)对代码进行矢量化

    Vectorizing your code using Universal Intrinsics 使用 Universal Intrinsics 对代码进行矢量化 Goal 本教程的目标是提供使用通用 ...

  7. OpenCV图像处理学习九,双边滤波器 (Bilateral Filter)和中位数滤波器 (Median Filter)

    均值模糊无法克服边缘像素信息丢失缺陷,原因是均值滤波是基于平均权重,赋予图像内的像素与图像边缘像素一样的比值权重,图像处理是会使得边缘部分图像部分像素信息丢失: 高斯模糊部分克服了该缺陷,但是无法完全 ...

  8. 【Deblur SF-Net】去模糊 超细网络【嵌入式、移动端可部署,超小型高精度网络】

    开发原因: 在做显微镜呈现的时候,经常会遇到对焦不准导致图像模糊的情况 暂时不便开源,仅记录. 我制作了一个数据集,包含了大量的病理图像[模糊-清晰]对,用于网络训练. 本算法的目的是通过卷积神经网络 ...

  9. OpenCV 保边滤波器 各向异性扩散滤波(Anisotropic Filter)

    各向异性扩散滤波(Anisotropic filter),是双边滤波的一种简化,具有双边滤波的保留图像边缘同时减少噪声的作用,又加快了算法的实现速度. 首先,我们来了解一下各向异性扩散. 各向异性扩散 ...

  10. Windows 远程桌面连接使用教程

    做为一个对 vps 不太了解的新手站长,首先要学会的就是怎么用远程桌面软件登陆 vps,我们一般都使用 Windows7 系统自带的"远程桌面连接".位置在桌面的开始-程序-附件- ...

最新文章

  1. iOS UI 12 block传值
  2. ABP 拦截器不工作
  3. 大学生试用期辞退之没有工钱
  4. flutter进行自动编译操作步骤
  5. 云计算与SaaS的关系 :新计算时代将来临
  6. 华菱重卡仪表指示说明_新一代创虎重卡登场!LNG车型将配玉柴燃气发动机
  7. 【渝粤题库】广东开放大学 商务合同 形成性考核
  8. cad多线段长度计算总和_没想到啊,我平时用的CAD多段线有这么多学问
  9. php7数据库备份还原,基于thinkphp的数据库在线备份还原
  10. 作为一个php程序员要学会的技能
  11. linux切换英文界面,linux英文界面下使用中文输入法
  12. Atitit prj 项目管理与行政管理(1)------项目环境的概览与建立
  13. Windows系统使用数据监视器收集软件运行数据
  14. 《哈佛大学幸福课》笔记
  15. 第47讲 Android Camera2 API AWB自动白平衡实战
  16. CAN波特率与负载率
  17. 数据分析报告怎么写?
  18. 微信小程序之----页面之间相互传递数据
  19. matlab 鼠标画图,在matlab中使用鼠标在GUI上绘图
  20. 高等教育心理学:学生的认知发展

热门文章

  1. 华为网络设备-生成树协议配置
  2. myeclipseCI2018.12.0新建web项目目录结构没有webroot
  3. 残差、方差、偏差、MSE均方误差、Bagging、Boosting、过拟合欠拟合和交叉验证
  4. 一个在线文字转语音工具
  5. 金融壹账通第一季营收10亿 沈崇锋:推进双重主要上市
  6. 猫加路由加服务器加交换机怎么配置文件,光猫接交换机和路由器,怎么设置?...
  7. 【多图长文】古希腊式、巴洛克式、哥特式.....图说西方建筑简史
  8. 一起自学SLAM算法:写在前面
  9. cad没有命令输入框_CAD命令,教您CAD命令栏不见了怎么调出来
  10. 丢失数据文件和控制文件的恢复案例(zt)