OpenCV的周期性噪声去除滤波器(70)

2024-05-05 10:44

本文主要是介绍OpenCV的周期性噪声去除滤波器(70),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

返回:OpenCV系列文章目录(持续更新中......)
上一篇:OpenCV如何通过梯度结构张量进行各向异性图像分割(69)
下一篇 :OpenCV如何为我们的应用程序添加跟踪栏(71)

目录

目标

理论

如何消除傅里叶域中的周期性噪声?

源代码

解释

结果

目标

在本教程中,您将学习:

  • 如何消除傅里叶域中的周期性噪声

理论

注意

解释基于该书[108]。此页面上的图像是真实世界的图像。

周期性噪声在傅里叶域中产生尖峰,通常可以通过视觉分析检测到。

如何消除傅里叶域中的周期性噪声?

通过频域滤波可以显著降低周期性噪声。在此页面上,我们使用具有适当半径的陷波抑制滤波器来完全封闭傅里叶域中的噪声尖峰。陷波滤波器抑制中心频率附近预定义邻域中的频率。陷波滤波器的数量是任意的。缺口区域的形状也可以是任意的(例如矩形或圆形)。在此页面上,我们使用三个圆形陷波抑制滤光片。图像的功率谱致密化用于噪声尖峰的视觉检测。

源代码

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

#include <iostream>
#include "opencv2/highgui.hpp"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>using namespace cv;
using namespace std;void fftshift(const Mat& inputImg, Mat& outputImg);
void filter2DFreq(const Mat& inputImg, Mat& outputImg, const Mat& H);
void synthesizeFilterH(Mat& inputOutput_H, Point center, int radius);
void calcPSD(const Mat& inputImg, Mat& outputImg, int flag = 0);const String keys =
"{help h usage ? | | print this message }"
"{@image |period_input.jpg | input image name }"
;int main(int argc, char* argv[])
{CommandLineParser parser(argc, argv, keys);string strInFileName = parser.get<String>("@image");samples::addSamplesDataSearchSubDirectory("doc/tutorials/imgproc/periodic_noise_removing_filter/images");Mat imgIn = imread(samples::findFile(strInFileName), IMREAD_GRAYSCALE);if (imgIn.empty()) //check whether the image is loaded or not{cout << "ERROR : Image cannot be loaded..!!" << endl;return -1;}imshow("Image corrupted", imgIn);imgIn.convertTo(imgIn, CV_32F);// it needs to process even image onlyRect roi = Rect(0, 0, imgIn.cols & -2, imgIn.rows & -2);imgIn = imgIn(roi);// PSD calculation (start)Mat imgPSD;calcPSD(imgIn, imgPSD);fftshift(imgPSD, imgPSD);normalize(imgPSD, imgPSD, 0, 255, NORM_MINMAX);// PSD calculation (stop)//H calculation (start)Mat H = Mat(roi.size(), CV_32F, Scalar(1));const int r = 21;synthesizeFilterH(H, Point(705, 458), r);synthesizeFilterH(H, Point(850, 391), r);synthesizeFilterH(H, Point(993, 325), r);//H calculation (stop)// filtering (start)Mat imgOut;fftshift(H, H);filter2DFreq(imgIn, imgOut, H);// filtering (stop)imgOut.convertTo(imgOut, CV_8U);normalize(imgOut, imgOut, 0, 255, NORM_MINMAX);imwrite("result.jpg", imgOut);imwrite("PSD.jpg", imgPSD);fftshift(H, H);normalize(H, H, 0, 255, NORM_MINMAX);imshow("Debluring", imgOut);imwrite("filter.jpg", H);waitKey(0);return 0;
}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);
}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];
}void synthesizeFilterH(Mat& inputOutput_H, Point center, int radius)
{Point c2 = center, c3 = center, c4 = center;c2.y = inputOutput_H.rows - center.y;c3.x = inputOutput_H.cols - center.x;c4 = Point(c3.x,c2.y);circle(inputOutput_H, center, radius, 0, -1, 8);circle(inputOutput_H, c2, radius, 0, -1, 8);circle(inputOutput_H, c3, radius, 0, -1, 8);circle(inputOutput_H, c4, radius, 0, -1, 8);
}// Function calculates PSD(Power spectrum density) by fft with two flags
// flag = 0 means to return PSD
// flag = 1 means to return log(PSD)
void calcPSD(const Mat& inputImg, Mat& outputImg, int flag)
{Mat planes[2] = { Mat_<float>(inputImg.clone()), Mat::zeros(inputImg.size(), CV_32F) };Mat complexI;merge(planes, 2, complexI);dft(complexI, complexI);split(complexI, planes); // planes[0] = Re(DFT(I)), planes[1] = Im(DFT(I))planes[0].at<float>(0) = 0;planes[1].at<float>(0) = 0;// compute the PSD = sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)^2Mat imgPSD;magnitude(planes[0], planes[1], imgPSD); //imgPSD = sqrt(Power spectrum density)pow(imgPSD, 2, imgPSD); //it needs ^2 in order to get PSDoutputImg = imgPSD;// logPSD = log(1 + PSD)if (flag){Mat imglogPSD;imglogPSD = imgPSD + Scalar::all(1);log(imglogPSD, imglogPSD);outputImg = imglogPSD;}
}

解释

通过频域滤波进行周期性降噪,包括功率谱密度计算(用于噪声尖峰视觉检测)、陷波抑制滤波器合成和频率滤波:

 // it needs to process even image onlyRect roi = Rect(0, 0, imgIn.cols & -2, imgIn.rows & -2);imgIn = imgIn(roi);// PSD calculation (start)Mat imgPSD;calcPSD(imgIn, imgPSD);fftshift(imgPSD, imgPSD);normalize(imgPSD, imgPSD, 0, 255, NORM_MINMAX);// PSD calculation (stop)//H calculation (start)Mat H = Mat(roi.size(), CV_32F, Scalar(1));const int r = 21;synthesizeFilterH(H, Point(705, 458), r);synthesizeFilterH(H, Point(850, 391), r);synthesizeFilterH(H, Point(993, 325), r);//H calculation (stop)// filtering (start)Mat imgOut;fftshift(H, H);filter2DFreq(imgIn, imgOut, H);// filtering (stop)

函数 calcPSD()计算图像的功率谱密度:

void calcPSD(const Mat& inputImg, Mat& outputImg, int flag)
{Mat planes[2] = { Mat_<float>(inputImg.clone()), Mat::zeros(inputImg.size(), CV_32F) };Mat complexI;merge(planes, 2, complexI);dft(complexI, complexI);split(complexI, planes); // planes[0] = Re(DFT(I)), planes[1] = Im(DFT(I))planes[0].at<float>(0) = 0;planes[1].at<float>(0) = 0;// compute the PSD = sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)^2Mat imgPSD;magnitude(planes[0], planes[1], imgPSD); //imgPSD = sqrt(Power spectrum density)pow(imgPSD, 2, imgPSD); //it needs ^2 in order to get PSDoutputImg = imgPSD;// logPSD = log(1 + PSD)if (flag){Mat imglogPSD;imglogPSD = imgPSD + Scalar::all(1);log(imglogPSD, imglogPSD);outputImg = imglogPSD;}
}

函数 synthesizeFilterH()根据中心频率和半径形成理想圆形陷波抑制滤波器的传递函数:

void synthesizeFilterH(Mat& inputOutput_H, Point center, int radius)
{Point c2 = center, c3 = center, c4 = center;c2.y = inputOutput_H.rows - center.y;c3.x = inputOutput_H.cols - center.x;c4 = Point(c3.x,c2.y);circle(inputOutput_H, center, radius, 0, -1, 8);circle(inputOutput_H, c2, radius, 0, -1, 8);circle(inputOutput_H, c3, radius, 0, -1, 8);circle(inputOutput_H, c4, radius, 0, -1, 8);
}

函数 filter2DFreq()过滤频域中的图像。函数 fftshift()和 filter2DFreq()是从教程 Out-of-focus Deblur Filter 中复制的。

结果

下图显示了被各种频率的周期性噪声严重损坏的图像。

噪声分量很容易被看作是下图所示的功率谱密度中的亮点(尖峰)。

下图显示了具有适当半径的陷波抑制滤波器,以完全封闭噪声尖峰。

使用陷波抑制滤波器处理图像的结果如下所示。

这种改进是显而易见的。与原始图像相比,此图像包含的可见周期性噪声要少得多。

您还可以在 YouTube 上找到此过滤理念的快速视频演示。

这篇关于OpenCV的周期性噪声去除滤波器(70)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/961516

相关文章

Python如何将OpenCV摄像头视频流通过浏览器播放

《Python如何将OpenCV摄像头视频流通过浏览器播放》:本文主要介绍Python如何将OpenCV摄像头视频流通过浏览器播放的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完... 目录方法1:使用Flask + MJPEG流实现代码使用方法优点缺点方法2:使用WebSocket传输视

Python如何去除图片干扰代码示例

《Python如何去除图片干扰代码示例》图片降噪是一个广泛应用于图像处理的技术,可以提高图像质量和相关应用的效果,:本文主要介绍Python如何去除图片干扰的相关资料,文中通过代码介绍的非常详细,... 目录一、噪声去除1. 高斯噪声(像素值正态分布扰动)2. 椒盐噪声(随机黑白像素点)3. 复杂噪声(如伪

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

C/C++中OpenCV 矩阵运算的实现

《C/C++中OpenCV矩阵运算的实现》本文主要介绍了C/C++中OpenCV矩阵运算的实现,包括基本算术运算(标量与矩阵)、矩阵乘法、转置、逆矩阵、行列式、迹、范数等操作,感兴趣的可以了解一下... 目录矩阵的创建与初始化创建矩阵访问矩阵元素基本的算术运算 ➕➖✖️➗矩阵与标量运算矩阵与矩阵运算 (逐元

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

C/C++和OpenCV实现调用摄像头

《C/C++和OpenCV实现调用摄像头》本文主要介绍了C/C++和OpenCV实现调用摄像头,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录准备工作1. 打开摄像头2. 读取视频帧3. 显示视频帧4. 释放资源5. 获取和设置摄像头属性

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

c/c++的opencv实现图片膨胀

《c/c++的opencv实现图片膨胀》图像膨胀是形态学操作,通过结构元素扩张亮区填充孔洞、连接断开部分、加粗物体,OpenCV的cv::dilate函数实现该操作,本文就来介绍一下opencv图片... 目录什么是图像膨胀?结构元素 (KerChina编程nel)OpenCV 中的 cv::dilate() 函