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

相关文章

opencv实现像素统计的示例代码

《opencv实现像素统计的示例代码》本文介绍了OpenCV中统计图像像素信息的常用方法和函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 统计像素值的基本信息2. 统计像素值的直方图3. 统计像素值的总和4. 统计非零像素的数量

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

opencv 滚动条

参数介绍:createTrackbar( trackbarname , "hello" , &alpha_slider ,alpha_max ,  on_trackbar )  ;在标签中显示的文字(提示滑动条的用途) TrackbarName创建的滑动条要放置窗体的名字 “hello”滑动条的取值范围从 0 到 alpha_max (最小值只能为 zero).滑动后的值存放在

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

树莓派5_opencv笔记27:Opencv录制视频(无声音)

今日继续学习树莓派5 8G:(Raspberry Pi,简称RPi或RasPi)  本人所用树莓派5 装载的系统与版本如下:  版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下: 今天就水一篇文章,用树莓派摄像头,Opencv录制一段视频保存在指定目录... 文章提供测试代码讲解,整体代码贴出、测试效果图 目录 阶段一:录制一段

Verybot之OpenCV应用三:色标跟踪

下面的这个应用主要完成的是Verybot跟踪色标的功能,识别部分还是居于OpenCV编写,色标跟踪一般需要将图像的颜色模式进行转换,将RGB转换为HSV,因为对HSV格式下的图像进行识别时受光线的影响比较小,但是也有采用RGB模式来进行识别的情况,这种情况一般光线条件比较固定,背景跟识别物在颜色上很容易区分出来。         下面这个程序的流程大致是这样的:

Verybot之OpenCV应用二:霍夫变换查找圆

其实我是想通过这个程序来测试一下,OpenCV在Verybot上跑得怎么样,霍夫变换的原理就不多说了,下面是程序: #include "cv.h"#include "highgui.h"#include "stdio.h"int main(int argc, char** argv){cvNamedWindow("vedio",0);CvCapture* capture;i

Verybot之OpenCV应用一:安装与图像采集测试

在Verybot上安装OpenCV是很简单的,只需要执行:         sudo apt-get update         sudo apt-get install libopencv-dev         sudo apt-get install python-opencv         下面就对安装好的OpenCV进行一下测试,编写一个通过USB摄像头采

虚拟机ubuntu配置opencv和opencv_contrib

前期准备  1.下载opencv和opencv_contrib源码 opencv-4.6.0:https://opencv.org/releases/ opencv_contrib-4.6.0:https://github.com/opencv/opencv_contrib 在ubuntu直接下载或者在window上下好传到虚拟机里都可以 自己找个地方把他们解压,个人习惯在home下新建一